Skip to content

Commit d00d31b

Browse files
author
Brendan McKee
committed
feat(api-gateway): support instantiating ApiIntegrations directly
1 parent 768c4e5 commit d00d31b

File tree

3 files changed

+57
-24
lines changed

3 files changed

+57
-24
lines changed

src/api.ts

Lines changed: 15 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -74,15 +74,24 @@ type IntegrationTarget<IntegrationRequest, IntegrationResponse> =
7474
| Function<IntegrationRequest, IntegrationResponse>
7575
| ExpressStepFunction<IntegrationRequest, IntegrationResponse>;
7676

77-
interface BaseApiIntegration {
77+
export abstract class BaseApiIntegration {
78+
/**
79+
* Identify subclasses as API integrations to the Functionless plugin
80+
*/
81+
public static readonly FunctionlessType = "ApiIntegration";
82+
protected readonly functionlessKind = BaseApiIntegration.FunctionlessType;
83+
7884
/**
7985
* Add this integration as a Method to an API Gateway resource.
8086
*
8187
* TODO: this mirrors the AppsyncResolver.addResolver method, but it
8288
* is on the chopping block: https://github.com/functionless/functionless/issues/137
8389
* The 2 classes are conceptually similar so we should keep the DX in sync.
8490
*/
85-
addMethod(httpMethod: HttpMethod, resource: aws_apigateway.Resource): void;
91+
public abstract addMethod(
92+
httpMethod: HttpMethod,
93+
resource: aws_apigateway.Resource
94+
): void;
8695
}
8796

8897
/**
@@ -158,17 +167,12 @@ export interface MockApiIntegrationProps<
158167
*/
159168
export class MockApiIntegration<
160169
Props extends MockApiIntegrationProps<any, any, any>
161-
> implements BaseApiIntegration
162-
{
163-
/**
164-
* This static property identifies this class as a MockApiIntegration to the Functionless plugin.
165-
*/
166-
public static readonly FunctionlessType = "MockApiIntegration";
167-
170+
> extends BaseApiIntegration {
168171
private readonly request: FunctionDecl;
169172
private readonly responses: { [K in keyof Props["responses"]]: FunctionDecl };
170173

171174
public constructor(props: Props) {
175+
super();
172176
this.request = validateFunctionDecl(props.request);
173177
this.responses = Object.fromEntries(
174178
Object.entries(props.responses).map(([k, v]) => [
@@ -251,18 +255,13 @@ export interface AwsApiIntegrationProps<
251255
*/
252256
export class AwsApiIntegration<
253257
Props extends AwsApiIntegrationProps<any, any, any, any>
254-
> implements BaseApiIntegration
255-
{
256-
/**
257-
* This static property identifies this class as an AwsApiIntegration to the Functionless plugin.
258-
*/
259-
public static readonly FunctionlessType = "AwsApiIntegration";
260-
258+
> extends BaseApiIntegration {
261259
private readonly request: FunctionDecl;
262260
private readonly response: FunctionDecl;
263261
private readonly integration: Props["integration"];
264262

265263
constructor(props: Props) {
264+
super();
266265
this.request = validateFunctionDecl(props.request);
267266
this.response = validateFunctionDecl(props.response);
268267
this.integration = props.integration;

src/checker.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import * as ts from "typescript";
22
import * as tsserver from "typescript/lib/tsserverlibrary";
3+
import { BaseApiIntegration } from "./api";
34
import { AppsyncResolver } from "./appsync";
45
import { EventBus, EventBusRule } from "./event-bridge";
56
import { EventBusTransform } from "./event-bridge/transform";
@@ -59,6 +60,10 @@ export type ApiIntegrationsStaticMethodInterface = ts.CallExpression & {
5960
arguments: [ts.ObjectLiteralExpression];
6061
};
6162

63+
export type ApiIntegrationInterface = ts.NewExpression & {
64+
arguments: [ts.ObjectLiteralExpression];
65+
};
66+
6267
export type FunctionlessChecker = ReturnType<typeof makeFunctionlessChecker>;
6368

6469
export function makeFunctionlessChecker(
@@ -77,6 +82,7 @@ export function makeFunctionlessChecker(
7782
isStepFunction,
7883
isNewFunctionlessFunction,
7984
isApiIntegrationsStaticMethod,
85+
isApiIntegration,
8086
isCDKConstruct,
8187
getFunctionlessTypeKind,
8288
};
@@ -231,6 +237,16 @@ export function makeFunctionlessChecker(
231237
return x;
232238
}
233239

240+
function isApiIntegration(node: ts.Node): node is ApiIntegrationInterface {
241+
return (
242+
ts.isNewExpression(node) &&
243+
isFunctionlessClassOfKind(
244+
node.expression,
245+
BaseApiIntegration.FunctionlessType
246+
)
247+
);
248+
}
249+
234250
/**
235251
* Heuristically evaluate the fqn of a symbol to be in a module and of a type name.
236252
*

src/compile.ts

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import type { PluginConfig, TransformerExtras } from "ts-patch";
44
import ts from "typescript";
55
import { assertDefined } from "./assert";
66
import {
7+
ApiIntegrationInterface,
78
ApiIntegrationsStaticMethodInterface,
89
EventBusMapInterface,
910
EventBusRuleInterface,
@@ -117,6 +118,8 @@ export function compile(
117118
return visitFunction(node, ctx);
118119
} else if (checker.isApiIntegrationsStaticMethod(node)) {
119120
return visitApiIntegrationsStaticMethod(node);
121+
} else if (checker.isApiIntegration(node)) {
122+
return visitApiIntegration(node);
120123
}
121124
return node;
122125
};
@@ -533,7 +536,29 @@ export function compile(
533536
): ts.CallExpression {
534537
const [props] = node.arguments;
535538

536-
const updatedProps = ts.factory.updateObjectLiteralExpression(
539+
return ts.factory.updateCallExpression(
540+
node,
541+
node.expression,
542+
node.typeArguments,
543+
[visitApiIntegrationProps(props)]
544+
);
545+
}
546+
547+
function visitApiIntegration(node: ApiIntegrationInterface): ts.Node {
548+
const [props] = node.arguments;
549+
550+
return ts.factory.updateNewExpression(
551+
node,
552+
node.expression,
553+
node.typeArguments,
554+
[visitApiIntegrationProps(props)]
555+
);
556+
}
557+
558+
function visitApiIntegrationProps(
559+
props: ts.ObjectLiteralExpression
560+
): ts.ObjectLiteralExpression {
561+
return ts.factory.updateObjectLiteralExpression(
537562
props,
538563
props.properties.map((prop) => {
539564
if (
@@ -552,13 +577,6 @@ export function compile(
552577
return prop;
553578
})
554579
);
555-
556-
return ts.factory.updateCallExpression(
557-
node,
558-
node.expression,
559-
node.typeArguments,
560-
[updatedProps]
561-
);
562580
}
563581

564582
function visitApiIntegrationMapperProp(

0 commit comments

Comments
 (0)