Skip to content

Commit b3bc1f0

Browse files
authored
feat(parser): enhance API Gateway schemas (#2665)
1 parent 5634566 commit b3bc1f0

29 files changed

+1958
-362
lines changed

Diff for: docs/utilities/parser.md

+3
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,10 @@ Parser comes with the following built-in schemas:
6464
| -------------------------------------------- | ------------------------------------------------------------------------------------- |
6565
| **AlbSchema** | Lambda Event Source payload for Amazon Application Load Balancer |
6666
| **APIGatewayProxyEventSchema** | Lambda Event Source payload for Amazon API Gateway |
67+
| **APIGatewayRequestAuthorizerEventSchema** | Lambda Event Source payload for Amazon API Gateway Request Authorizer |
68+
| **APIGatewayTokenAuthorizerEventSchema** | Lambda Event Source payload for Amazon API Gateway Token Authorizer |
6769
| **APIGatewayProxyEventV2Schema** | Lambda Event Source payload for Amazon API Gateway v2 payload |
70+
| **APIGatewayRequestAuthorizerEventV2Schema** | Lambda Event Source payload for Amazon API Gateway v2 Authorizer |
6871
| **CloudFormationCustomResourceCreateSchema** | Lambda Event Source payload for AWS CloudFormation `CREATE` operation |
6972
| **CloudFormationCustomResourceUpdateSchema** | Lambda Event Source payload for AWS CloudFormation `UPDATE` operation |
7073
| **CloudFormationCustomResourceDeleteSchema** | Lambda Event Source payload for AWS CloudFormation `DELETE` operation |

Diff for: packages/parser/jest.config.cjs

+1-2
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@ module.exports = {
99
'^(\\.{1,2}/.*)\\.js$': '$1',
1010
},
1111
transform: {
12-
'^.+\\.ts?$': ['ts-jest', {tsconfig: './tests/tsconfig.json'}],
13-
12+
'^.+\\.ts?$': ['ts-jest'],
1413
},
1514
moduleFileExtensions: ['js', 'ts'],
1615
collectCoverageFrom: ['**/src/**/*.ts', '!**/node_modules/**'],

Diff for: packages/parser/package.json

+16
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,14 @@
4343
"require": "./lib/cjs/schemas/index.js",
4444
"import": "./lib/esm/schemas/index.js"
4545
},
46+
"./schemas/api-gateway": {
47+
"require": "./lib/cjs/schemas/apigw.js",
48+
"import": "./lib/esm/schemas/apigw.js"
49+
},
50+
"./schemas/api-gatewayv2": {
51+
"require": "./lib/cjs/schemas/apigwv2.js",
52+
"import": "./lib/esm/schemas/apigwv2.js"
53+
},
4654
"./envelopes": {
4755
"require": "./lib/cjs/envelopes/index.js",
4856
"import": "./lib/esm/envelopes/index.js"
@@ -66,6 +74,14 @@
6674
"./lib/cjs/schemas/index.d.ts",
6775
"./lib/esm/schemas/index.d.ts"
6876
],
77+
"schemas/api-gateway": [
78+
"./lib/cjs/schemas/apigw.d.ts",
79+
"./lib/esm/schemas/apigw.d.ts"
80+
],
81+
"schemas/api-gatewayv2": [
82+
"./lib/cjs/schemas/apigwv2.d.ts",
83+
"./lib/esm/schemas/apigwv2.d.ts"
84+
],
6985
"envelopes": [
7086
"./lib/cjs/envelopes/index.d.ts",
7187
"./lib/esm/envelopes/index.d.ts"

Diff for: packages/parser/src/schemas/apigw-proxy.ts

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
import { z } from 'zod';
2+
3+
/**
4+
* A zod schema for an API Gateway Certificate
5+
*/
6+
const APIGatewayCert = z.object({
7+
clientCertPem: z.string(),
8+
subjectDN: z.string(),
9+
issuerDN: z.string(),
10+
serialNumber: z.string(),
11+
validity: z.object({
12+
notBefore: z.string(),
13+
notAfter: z.string(),
14+
}),
15+
});
16+
17+
/**
18+
* A zod schema for an object with string keys and string values
19+
*/
20+
const APIGatewayRecord = z.record(z.string());
21+
22+
/**
23+
* A zod schema for an array of strings
24+
*/
25+
const APIGatewayStringArray = z.array(z.string());
26+
27+
/**
28+
* A zod schema for API Gateway HTTP methods
29+
*/
30+
const APIGatewayHttpMethod = z.enum([
31+
'GET',
32+
'POST',
33+
'PUT',
34+
'PATCH',
35+
'DELETE',
36+
'HEAD',
37+
'OPTIONS',
38+
]);
39+
40+
export {
41+
APIGatewayCert,
42+
APIGatewayRecord,
43+
APIGatewayStringArray,
44+
APIGatewayHttpMethod,
45+
};

Diff for: packages/parser/src/schemas/apigw.ts

+182-37
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
11
import { z } from 'zod';
2+
import {
3+
APIGatewayCert,
4+
APIGatewayRecord,
5+
APIGatewayStringArray,
6+
APIGatewayHttpMethod,
7+
} from './apigw-proxy.js';
28

3-
const APIGatewayCert = z.object({
4-
clientCertPem: z.string(),
5-
subjectDN: z.string(),
6-
issuerDN: z.string(),
7-
serialNumber: z.string(),
8-
validity: z.object({
9-
notBefore: z.string(),
10-
notAfter: z.string(),
11-
}),
12-
});
13-
9+
/**
10+
* A zod schema for an API Gateway Event Identity
11+
*
12+
* @see {@link https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html}
13+
*/
1414
const APIGatewayEventIdentity = z.object({
1515
accessKey: z.string().nullish(),
1616
accountId: z.string().nullish(),
@@ -38,15 +38,27 @@ const APIGatewayEventIdentity = z.object({
3838
clientCert: APIGatewayCert.nullish(),
3939
});
4040

41+
/**
42+
* A zod schema for an API Gateway Event Request Context
43+
*
44+
* @see {@link https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-mapping-template-reference.html#context-variable-reference}
45+
*/
4146
const APIGatewayEventRequestContext = z
4247
.object({
4348
accountId: z.string(),
4449
apiId: z.string(),
50+
deploymentId: z.string().nullish(),
4551
authorizer: z
46-
.object({
47-
claims: z.record(z.string(), z.any()).nullish(),
48-
scopes: z.array(z.string()).nullish(),
49-
})
52+
.union([
53+
z.object({
54+
integrationLatency: z.number(),
55+
principalId: z.string(),
56+
}),
57+
z.object({
58+
claims: z.record(z.string(), z.any()),
59+
scopes: APIGatewayStringArray.optional(),
60+
}),
61+
])
5062
.nullish(),
5163
stage: z.string(),
5264
protocol: z.string(),
@@ -88,32 +100,165 @@ const APIGatewayEventRequestContext = z
88100
}
89101
);
90102

103+
/**
104+
* A zod schema for an API Gateway Proxy event
105+
*
106+
* @example
107+
* ```json
108+
* {
109+
* "type": "REQUEST",
110+
* "methodArn": "arn:aws:execute-api:us-east-1:123456789012:abcdef123/test/GET/request",
111+
* "resource": "/request",
112+
* "path": "/request",
113+
* "httpMethod": "GET",
114+
* "headers": {
115+
* "X-AMZ-Date": "20170718T062915Z",
116+
* "Accept": "application/json",
117+
* "HeaderAuth1": "headerValue1"
118+
* },
119+
* "queryStringParameters": {
120+
* "QueryString1": "queryValue1"
121+
* },
122+
* "pathParameters": {},
123+
* "stageVariables": null,
124+
* "requestContext": {
125+
* "path": "/request",
126+
* "accountId": "123456789012",
127+
* "resourceId": "05c7jb",
128+
* "stage": "test",
129+
* "requestId": "...",
130+
* "identity": {
131+
* "cognitoIdentityPoolId": null,
132+
* "accountId": null,
133+
* "cognitoIdentityId": null,
134+
* "caller": null,
135+
* "sourceIp": "192.168.1.1",
136+
* "principalOrgId": null,
137+
* "accessKey": null,
138+
* "cognitoAuthenticationType": null,
139+
* "cognitoAuthenticationProvider": null,
140+
* "userArn": null,
141+
* "userAgent": "HTTPie/3.2.2",
142+
* "user": null
143+
* }
144+
* },
145+
* "resourcePath": "/request",
146+
* "httpMethod": "GET",
147+
* "apiId": "abcdef123"
148+
* }
149+
* ```
150+
*
151+
* @see {@link https://docs.aws.amazon.com/apigateway/latest/developerguide/set-up-lambda-proxy-integrations.html}
152+
*/
91153
const APIGatewayProxyEventSchema = z.object({
92-
version: z.string().optional(),
93-
authorizationToken: z.string().optional(),
94-
identitySource: z.string().optional(),
95-
methodArn: z.string().optional(),
96-
type: z.enum(['TOKEN', 'REQUEST']).optional(),
97154
resource: z.string(),
98155
path: z.string(),
99-
httpMethod: z.enum([
100-
'GET',
101-
'POST',
102-
'PUT',
103-
'PATCH',
104-
'DELETE',
105-
'HEAD',
106-
'OPTIONS',
107-
]),
108-
headers: z.record(z.string()).optional(),
109-
queryStringParameters: z.record(z.string()).nullable(),
110-
multiValueHeaders: z.record(z.array(z.string())).optional(),
111-
multiValueQueryStringParameters: z.record(z.array(z.string())).nullable(),
156+
httpMethod: APIGatewayHttpMethod,
157+
headers: APIGatewayRecord.nullish(),
158+
multiValueHeaders: z.record(APIGatewayStringArray).nullish(),
159+
queryStringParameters: APIGatewayRecord.nullable(),
160+
multiValueQueryStringParameters: z.record(APIGatewayStringArray).nullable(),
161+
pathParameters: APIGatewayRecord.nullish(),
162+
stageVariables: APIGatewayRecord.nullish(),
112163
requestContext: APIGatewayEventRequestContext,
113-
pathParameters: z.record(z.string()).optional().nullish(),
114-
stageVariables: z.record(z.string()).optional().nullish(),
115-
isBase64Encoded: z.boolean().optional(),
116164
body: z.string().nullable(),
165+
isBase64Encoded: z.boolean(),
166+
});
167+
168+
/**
169+
* A zod schema for an API Gateway Request Authorizer event
170+
*
171+
* @example
172+
* ```json
173+
* {
174+
* "type": "REQUEST",
175+
* "methodArn": "arn:aws:execute-api:us-west-2:123456789012:ymy8tbxw7b/prod/GET/",
176+
* "resource": "/{proxy+}",
177+
* "path": "/hello/world",
178+
* "httpMethod": "GET",
179+
* "headers": {
180+
* "X-AMZ-Date": "20170718T062915Z",
181+
* "Accept": "application/json",
182+
* "HeaderAuth1": "headerValue1"
183+
* },
184+
* "multiValueHeaders": {
185+
* "X-AMZ-Date": ["20170718T062915Z"],
186+
* "Accept": ["application/json"],
187+
* "HeaderAuth1": ["headerValue1"]
188+
* },
189+
* "queryStringParameters": {},
190+
* "multiValueQueryStringParameters": {},
191+
* "pathParameters": {},
192+
* "stageVariables": {},
193+
* "requestContext": {
194+
* "path": "/request",
195+
* "accountId": "123456789012",
196+
* "resourceId": "05c7jb",
197+
* "stage": "test",
198+
* "requestId": "...",
199+
* "identity": {
200+
* "cognitoIdentityPoolId": null,
201+
* "accountId": null,
202+
* "cognitoIdentityId": null,
203+
* "caller": null,
204+
* "sourceIp": "192.168.1.1",
205+
* "principalOrgId": null,
206+
* "accessKey": null,
207+
* "cognitoAuthenticationType": null,
208+
* "cognitoAuthenticationProvider": null,
209+
* "userArn": null,
210+
* "userAgent": "HTTPie/3.2.2",
211+
* "user": null
212+
* }
213+
* },
214+
* "domainName": "id.execute-api.us-west-2.amazonaws.com",
215+
* "deploymentId": "lle82z",
216+
* "apiId": "ymy8tbxw7b"
217+
* }
218+
* ```
219+
*
220+
* @see {@link https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-lambda-authorizer-input.html#w76aac15b9c21c25c21b5}
221+
*/
222+
const APIGatewayRequestAuthorizerEventSchema = z.object({
223+
type: z.literal('REQUEST'),
224+
methodArn: z.string(),
225+
resource: z.string(),
226+
path: z.string(),
227+
httpMethod: APIGatewayHttpMethod,
228+
headers: APIGatewayRecord,
229+
multiValueHeaders: z.record(APIGatewayStringArray),
230+
queryStringParameters: APIGatewayRecord,
231+
multiValueQueryStringParameters: z.record(APIGatewayStringArray),
232+
pathParameters: APIGatewayRecord,
233+
stageVariables: APIGatewayRecord,
234+
requestContext: APIGatewayEventRequestContext,
235+
domainName: z.string().optional(),
236+
deploymentId: z.string().optional(),
237+
apiId: z.string().optional(),
238+
});
239+
240+
/**
241+
* A zod schema for an API Gateway Token Authorizer event
242+
*
243+
* @example
244+
* ```json
245+
* {
246+
* "type": "TOKEN",
247+
* "authorizationToken": "Bearer abcd1234",
248+
* "methodArn": "arn:aws:execute-api:us-west-2:123456789012:ymy8tbxw7b/prod/GET/"
249+
* }
250+
* ```
251+
*
252+
* @see {@link https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-lambda-authorizer-input.html#w76aac15b9c21c25c21b3}
253+
*/
254+
const APIGatewayTokenAuthorizerEventSchema = z.object({
255+
type: z.literal('TOKEN'),
256+
authorizationToken: z.string(),
257+
methodArn: z.string(),
117258
});
118259

119-
export { APIGatewayProxyEventSchema, APIGatewayCert };
260+
export {
261+
APIGatewayProxyEventSchema,
262+
APIGatewayRequestAuthorizerEventSchema,
263+
APIGatewayTokenAuthorizerEventSchema,
264+
};

0 commit comments

Comments
 (0)