@h4ad/serverless-adapter 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +204 -0
  3. package/lib/@types/binary-settings.d.ts +23 -0
  4. package/lib/@types/binary-settings.js +2 -0
  5. package/lib/@types/headers.d.ts +24 -0
  6. package/lib/@types/headers.js +2 -0
  7. package/lib/@types/helpers.d.ts +6 -0
  8. package/lib/@types/helpers.js +2 -0
  9. package/lib/@types/index.d.ts +3 -0
  10. package/lib/@types/index.js +15 -0
  11. package/lib/@types/proxy-params.d.ts +8 -0
  12. package/lib/@types/proxy-params.js +2 -0
  13. package/lib/adapters/aws/alb.adapter.d.ts +58 -0
  14. package/lib/adapters/aws/alb.adapter.js +119 -0
  15. package/lib/adapters/aws/api-gateway-v1.adapter.d.ts +63 -0
  16. package/lib/adapters/aws/api-gateway-v1.adapter.js +126 -0
  17. package/lib/adapters/aws/api-gateway-v2.adapter.d.ts +61 -0
  18. package/lib/adapters/aws/api-gateway-v2.adapter.js +123 -0
  19. package/lib/adapters/aws/dynamodb.adapter.d.ts +62 -0
  20. package/lib/adapters/aws/dynamodb.adapter.js +81 -0
  21. package/lib/adapters/aws/event-bridge.adapter.d.ts +66 -0
  22. package/lib/adapters/aws/event-bridge.adapter.js +91 -0
  23. package/lib/adapters/aws/index.d.ts +8 -0
  24. package/lib/adapters/aws/index.js +20 -0
  25. package/lib/adapters/aws/lambda-edge.adapter.d.ts +179 -0
  26. package/lib/adapters/aws/lambda-edge.adapter.js +248 -0
  27. package/lib/adapters/aws/sns.adapter.d.ts +62 -0
  28. package/lib/adapters/aws/sns.adapter.js +81 -0
  29. package/lib/adapters/aws/sqs.adapter.d.ts +62 -0
  30. package/lib/adapters/aws/sqs.adapter.js +81 -0
  31. package/lib/adapters/index.d.ts +1 -0
  32. package/lib/adapters/index.js +13 -0
  33. package/lib/contracts/adapter.contract.d.ts +152 -0
  34. package/lib/contracts/adapter.contract.js +2 -0
  35. package/lib/contracts/framework.contract.d.ts +15 -0
  36. package/lib/contracts/framework.contract.js +3 -0
  37. package/lib/contracts/handler.contract.d.ts +18 -0
  38. package/lib/contracts/handler.contract.js +3 -0
  39. package/lib/contracts/index.d.ts +4 -0
  40. package/lib/contracts/index.js +16 -0
  41. package/lib/contracts/resolver.contract.d.ts +70 -0
  42. package/lib/contracts/resolver.contract.js +3 -0
  43. package/lib/core/constants.d.ts +4 -0
  44. package/lib/core/constants.js +10 -0
  45. package/lib/core/current-invoke.d.ts +37 -0
  46. package/lib/core/current-invoke.js +34 -0
  47. package/lib/core/event-body.d.ts +16 -0
  48. package/lib/core/event-body.js +24 -0
  49. package/lib/core/headers.d.ts +27 -0
  50. package/lib/core/headers.js +53 -0
  51. package/lib/core/index.d.ts +10 -0
  52. package/lib/core/index.js +22 -0
  53. package/lib/core/is-binary.d.ts +55 -0
  54. package/lib/core/is-binary.js +91 -0
  55. package/lib/core/logger.d.ts +38 -0
  56. package/lib/core/logger.js +51 -0
  57. package/lib/core/no-op.d.ts +4 -0
  58. package/lib/core/no-op.js +8 -0
  59. package/lib/core/optional.d.ts +17 -0
  60. package/lib/core/optional.js +25 -0
  61. package/lib/core/path.d.ts +28 -0
  62. package/lib/core/path.js +56 -0
  63. package/lib/core/stream.d.ts +8 -0
  64. package/lib/core/stream.js +39 -0
  65. package/lib/frameworks/express.framework.d.ts +13 -0
  66. package/lib/frameworks/express.framework.js +17 -0
  67. package/lib/frameworks/fastify.framework.d.ts +13 -0
  68. package/lib/frameworks/fastify.framework.js +18 -0
  69. package/lib/frameworks/hapi.framework.d.ts +13 -0
  70. package/lib/frameworks/hapi.framework.js +18 -0
  71. package/lib/frameworks/index.d.ts +4 -0
  72. package/lib/frameworks/index.js +16 -0
  73. package/lib/frameworks/koa.framework.d.ts +13 -0
  74. package/lib/frameworks/koa.framework.js +17 -0
  75. package/lib/handlers/base/base.handler.d.ts +28 -0
  76. package/lib/handlers/base/base.handler.js +52 -0
  77. package/lib/handlers/base/index.d.ts +1 -0
  78. package/lib/handlers/base/index.js +13 -0
  79. package/lib/handlers/default.handler.d.ts +85 -0
  80. package/lib/handlers/default.handler.js +183 -0
  81. package/lib/handlers/index.d.ts +2 -0
  82. package/lib/handlers/index.js +14 -0
  83. package/lib/index.d.ts +9 -0
  84. package/lib/index.js +21 -0
  85. package/lib/network/index.d.ts +2 -0
  86. package/lib/network/index.js +14 -0
  87. package/lib/network/request.d.ts +15 -0
  88. package/lib/network/request.js +40 -0
  89. package/lib/network/response.d.ts +22 -0
  90. package/lib/network/response.js +104 -0
  91. package/lib/resolvers/aws-context.resolver.d.ts +21 -0
  92. package/lib/resolvers/aws-context.resolver.js +55 -0
  93. package/lib/resolvers/callback.resolver.d.ts +16 -0
  94. package/lib/resolvers/callback.resolver.js +40 -0
  95. package/lib/resolvers/index.d.ts +3 -0
  96. package/lib/resolvers/index.js +15 -0
  97. package/lib/resolvers/promise.resolver.d.ts +10 -0
  98. package/lib/resolvers/promise.resolver.js +38 -0
  99. package/lib/serverless-adapter.d.ts +114 -0
  100. package/lib/serverless-adapter.js +158 -0
  101. package/package.json +130 -0
@@ -0,0 +1,179 @@
1
+ import type { CloudFrontRequest, Context } from 'aws-lambda';
2
+ import type { CloudFrontEvent, CloudFrontHeaders } from 'aws-lambda/common/cloudfront';
3
+ import type { CloudFrontRequestEvent, CloudFrontRequestResult } from 'aws-lambda/trigger/cloudfront-request';
4
+ import { BothValueHeaders, SingleValueHeaders } from '../../@types';
5
+ import { Concrete } from '../../@types/helpers';
6
+ import { AdapterContract, AdapterRequest, GetResponseAdapterProps, OnErrorProps } from '../../contracts';
7
+ /**
8
+ * The type alias to indicate where we get the default value of query string to create the request.
9
+ */
10
+ export declare type DefaultQueryString = CloudFrontRequestEvent['Records'][number]['cf']['request']['querystring'];
11
+ /**
12
+ * The type alias to indicate where we get the default value of path to create the request.
13
+ */
14
+ export declare type DefaultForwardPath = CloudFrontRequestEvent['Records'][number]['cf']['request']['uri'];
15
+ /**
16
+ * Represents the body of the new version of Lambda@edge, which uses the `body` property inside `request` as the body (library) of the request.
17
+ */
18
+ export declare type NewLambdaEdgeBody = CloudFrontRequestEvent['Records'][number]['cf']['request']['body'];
19
+ /**
20
+ * Represents the body of the old version of Lambda@edge supported by @vendia/serverless-express which returns the `data` property within `body` for the body (library) of the request.
21
+ */
22
+ export declare type OldLambdaEdgeBody = Concrete<CloudFrontRequestEvent['Records'][number]['cf']['request']>['body']['data'];
23
+ /**
24
+ * The list was created based on {@link https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/edge-functions-restrictions.html these docs} in the "Disallowed Headers" section.
25
+ */
26
+ export declare const DEFAULT_LAMBDA_EDGE_DISALLOWED_HEADERS: (string | RegExp)[];
27
+ /**
28
+ * The default max response size in bytes of viewer request and viewer response.
29
+ *
30
+ * @default 1024 * 40 = 40960 = 40KB
31
+ *
32
+ * {@link https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/cloudfront-limits.html Reference}
33
+ */
34
+ export declare const DEFAULT_VIEWER_MAX_RESPONSE_SIZE_IN_BYTES: number;
35
+ /**
36
+ * The default max response size in bytes of origin request and origin response.
37
+ *
38
+ * @default 1024 * 1024 = 1048576 = 1MB
39
+ *
40
+ * {@link https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/cloudfront-limits.html Reference}
41
+ */
42
+ export declare const DEFAULT_ORIGIN_MAX_RESPONSE_SIZE_IN_BYTES: number;
43
+ /**
44
+ * The options to customize the {@link LambdaEdgeAdapter}.
45
+ */
46
+ export interface LambdaEdgeAdapterOptions {
47
+ /**
48
+ * The max response size in bytes of viewer request and viewer response.
49
+ *
50
+ * {@link https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/cloudfront-limits.html Reference}
51
+ *
52
+ * @default {@link DEFAULT_VIEWER_MAX_RESPONSE_SIZE_IN_BYTES}
53
+ */
54
+ viewerMaxResponseSizeInBytes?: number;
55
+ /**
56
+ * The max response size in bytes of origin request and origin response.
57
+ *
58
+ * {@link https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/cloudfront-limits.html Reference}
59
+ *
60
+ * @default {@link DEFAULT_ORIGIN_MAX_RESPONSE_SIZE_IN_BYTES}
61
+ */
62
+ originMaxResponseSizeInBytes?: number;
63
+ /**
64
+ * The function called when the response size exceed the max limits of the Lambda@edge
65
+ *
66
+ * @param response The response from framework that exceed the limit of Lambda@edge
67
+ * @default undefined
68
+ */
69
+ onResponseSizeExceedLimit?: (response: CloudFrontRequestResult) => CloudFrontRequestResult;
70
+ /**
71
+ * Return the path to be used to create a request to the framework
72
+ *
73
+ * @note You MUST append the query params from {@link DefaultQueryString}, you can use the helper {@link getPathWithQueryStringParams}.
74
+ *
75
+ * @param event The event sent by the serverless
76
+ * @default The value from {@link DefaultForwardPath}
77
+ */
78
+ getPathFromEvent?: (event: CloudFrontRequestEvent['Records'][number]) => string;
79
+ /**
80
+ * The headers that will be stripped from the headers object because Lambda@edge will fail if these headers are passed in the response.
81
+ *
82
+ * @note All headers will be compared with other headers using toLowerCase, but for the RegExp, if you modify this list, you must put the flag `/gmi` at the end of the RegExp (ex: `/(X-Amz-Cf-)(.*)/gim`)
83
+ *
84
+ * @default To get the full list, see {@link DEFAULT_LAMBDA_EDGE_DISALLOWED_HEADERS}.
85
+ */
86
+ disallowedHeaders?: (string | RegExp)[];
87
+ /**
88
+ * If you want to change how we check against the header if it should be stripped, you can pass a function to this property.
89
+ *
90
+ * @param header The header of the response
91
+ * @default The default method is implemented to test the header against the list {@link disallowedHeaders}.
92
+ */
93
+ shouldStripHeader?: (header: string) => boolean;
94
+ /**
95
+ * By default, the {@link CloudFrontRequestResult} has the `headers` property, but we also have the headers sent by the framework too.
96
+ * So this setting tells us how to handle this case, if you pass `true` to this property, we will use the framework headers.
97
+ * Otherwise, we will forward the body back to cloudfront without modifying or trying to set the `headers` property inside {@link CloudFrontRequestResult}.
98
+ *
99
+ * @default false
100
+ */
101
+ shouldUseHeadersFromFramework?: boolean;
102
+ }
103
+ /**
104
+ * The adapter to handle requests from AWS Lambda@Edge.
105
+ *
106
+ * This adapter is not fully compatible with Lambda@edge supported by @vendia/serverless-express, the request body was modified to return {@link NewLambdaEdgeBody} instead {@link OldLambdaEdgeBody}.
107
+ * Also, the response has been modified to return entire body sent by the framework, in this form you MUST return the body from the framework in the format of {@link CloudFrontRequestResult}.
108
+ * And when we get an error during the forwarding to the framework, we call `resolver.fail` instead of trying to return status 500 like the old implementation was.
109
+ *
110
+ * {@link https://docs.aws.amazon.com/lambda/latest/dg/lambda-edge.html Lambda edge docs}
111
+ * {@link https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/lambda-event-structure.html Event Reference}
112
+ *
113
+ * @example```typescript
114
+ * ```
115
+ */
116
+ export declare class LambdaEdgeAdapter implements AdapterContract<CloudFrontRequestEvent, Context, CloudFrontRequestResult> {
117
+ protected readonly options?: LambdaEdgeAdapterOptions | undefined;
118
+ /**
119
+ * Default constructor
120
+ *
121
+ * @param options The options to customize the {@link LambdaEdgeAdapter}
122
+ */
123
+ constructor(options?: LambdaEdgeAdapterOptions | undefined);
124
+ /**
125
+ * This property is used to cache the disallowed headers in `RegExp` version, even if you provide a string in `disallowedHeader`, we will cache it in an instance of `RegExp`.
126
+ */
127
+ protected readonly cachedDisallowedHeaders: RegExp[];
128
+ /**
129
+ * @inheritDoc
130
+ */
131
+ getAdapterName(): string;
132
+ /**
133
+ * @inheritDoc
134
+ */
135
+ canHandle(event: unknown): event is CloudFrontRequestEvent;
136
+ /**
137
+ * @inheritDoc
138
+ */
139
+ getRequest(event: CloudFrontRequestEvent): AdapterRequest;
140
+ /**
141
+ * @inheritDoc
142
+ */
143
+ getResponse(props: GetResponseAdapterProps<CloudFrontRequestEvent>): CloudFrontRequestResult;
144
+ /**
145
+ * @inheritDoc
146
+ */
147
+ onErrorWhileForwarding({ error, delegatedResolver, }: OnErrorProps<CloudFrontRequestEvent, CloudFrontRequestResult>): void;
148
+ /**
149
+ * Returns the headers with the flattened (non-list) values of the cloudfront request headers
150
+ *
151
+ * @param cloudFrontRequest The cloudfront request
152
+ */
153
+ protected getFlattenedHeadersFromCloudfrontRequest(cloudFrontRequest: CloudFrontRequest): SingleValueHeaders;
154
+ /**
155
+ * Returns the framework response in the format required by the Lambda@edge.
156
+ *
157
+ * @param body The body of the response
158
+ * @param frameworkHeaders The headers from the framework
159
+ */
160
+ protected getResponseToLambdaEdge({ body, headers: frameworkHeaders, }: GetResponseAdapterProps<CloudFrontRequestEvent>): CloudFrontRequestResult;
161
+ /**
162
+ * Returns headers in Cloudfront Response format.
163
+ *
164
+ * @param originalHeaders The original version of the request sent by the framework
165
+ */
166
+ protected getHeadersForCloudfrontResponse(originalHeaders: BothValueHeaders): CloudFrontHeaders;
167
+ /**
168
+ * Returns the information if we should remove the response header
169
+ *
170
+ * @param headerKey The header that will be tested
171
+ */
172
+ protected shouldStripHeader(headerKey: string): boolean;
173
+ /**
174
+ * Determines whether the event is from origin or is from viewer.
175
+ *
176
+ * @param content The event sent by AWS or the response sent by the framework
177
+ */
178
+ protected isEventTypeOrigin(content: CloudFrontEvent['config']): boolean;
179
+ }
@@ -0,0 +1,248 @@
1
+ "use strict";
2
+ //#region Imports
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.LambdaEdgeAdapter = exports.DEFAULT_ORIGIN_MAX_RESPONSE_SIZE_IN_BYTES = exports.DEFAULT_VIEWER_MAX_RESPONSE_SIZE_IN_BYTES = exports.DEFAULT_LAMBDA_EDGE_DISALLOWED_HEADERS = void 0;
5
+ const core_1 = require("../../core");
6
+ /**
7
+ * The list was created based on {@link https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/edge-functions-restrictions.html these docs} in the "Disallowed Headers" section.
8
+ */
9
+ exports.DEFAULT_LAMBDA_EDGE_DISALLOWED_HEADERS = [
10
+ 'Connection',
11
+ 'Expect',
12
+ 'Keep-Alive',
13
+ 'Proxy-Authenticate',
14
+ 'Proxy-Authorization',
15
+ 'Proxy-Connection',
16
+ 'Trailer',
17
+ 'Upgrade',
18
+ 'X-Accel-Buffering',
19
+ 'X-Accel-Charset',
20
+ 'X-Accel-Limit-Rate',
21
+ 'X-Accel-Redirect',
22
+ /(X-Amz-Cf-)(.*)/gim,
23
+ 'X-Cache',
24
+ /(X-Edge-)(.*)/gim,
25
+ 'X-Forwarded-Proto',
26
+ 'X-Real-IP',
27
+ ];
28
+ /**
29
+ * The default max response size in bytes of viewer request and viewer response.
30
+ *
31
+ * @default 1024 * 40 = 40960 = 40KB
32
+ *
33
+ * {@link https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/cloudfront-limits.html Reference}
34
+ */
35
+ exports.DEFAULT_VIEWER_MAX_RESPONSE_SIZE_IN_BYTES = 1024 * 40;
36
+ /**
37
+ * The default max response size in bytes of origin request and origin response.
38
+ *
39
+ * @default 1024 * 1024 = 1048576 = 1MB
40
+ *
41
+ * {@link https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/cloudfront-limits.html Reference}
42
+ */
43
+ exports.DEFAULT_ORIGIN_MAX_RESPONSE_SIZE_IN_BYTES = 1024 * 1024;
44
+ /**
45
+ * The adapter to handle requests from AWS Lambda@Edge.
46
+ *
47
+ * This adapter is not fully compatible with Lambda@edge supported by @vendia/serverless-express, the request body was modified to return {@link NewLambdaEdgeBody} instead {@link OldLambdaEdgeBody}.
48
+ * Also, the response has been modified to return entire body sent by the framework, in this form you MUST return the body from the framework in the format of {@link CloudFrontRequestResult}.
49
+ * And when we get an error during the forwarding to the framework, we call `resolver.fail` instead of trying to return status 500 like the old implementation was.
50
+ *
51
+ * {@link https://docs.aws.amazon.com/lambda/latest/dg/lambda-edge.html Lambda edge docs}
52
+ * {@link https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/lambda-event-structure.html Event Reference}
53
+ *
54
+ * @example```typescript
55
+ * ```
56
+ */
57
+ class LambdaEdgeAdapter {
58
+ //#region Constructor
59
+ /**
60
+ * Default constructor
61
+ *
62
+ * @param options The options to customize the {@link LambdaEdgeAdapter}
63
+ */
64
+ constructor(options) {
65
+ var _a;
66
+ this.options = options;
67
+ const disallowedHeaders = (0, core_1.getDefaultIfUndefined)((_a = this.options) === null || _a === void 0 ? void 0 : _a.disallowedHeaders, exports.DEFAULT_LAMBDA_EDGE_DISALLOWED_HEADERS);
68
+ this.cachedDisallowedHeaders = disallowedHeaders.map(disallowedHeader => {
69
+ if (disallowedHeader instanceof RegExp)
70
+ return disallowedHeader;
71
+ return new RegExp(`(${disallowedHeader})`, 'gim');
72
+ });
73
+ }
74
+ //#endregion
75
+ //#region Public Methods
76
+ /**
77
+ * @inheritDoc
78
+ */
79
+ getAdapterName() {
80
+ return LambdaEdgeAdapter.name;
81
+ }
82
+ /**
83
+ * @inheritDoc
84
+ */
85
+ canHandle(event) {
86
+ var _a, _b, _c;
87
+ const lambdaEdgeEvent = event;
88
+ if (!Array.isArray(lambdaEdgeEvent === null || lambdaEdgeEvent === void 0 ? void 0 : lambdaEdgeEvent.Records))
89
+ return false;
90
+ const eventType = (_c = (_b = (_a = lambdaEdgeEvent.Records[0]) === null || _a === void 0 ? void 0 : _a.cf) === null || _b === void 0 ? void 0 : _b.config) === null || _c === void 0 ? void 0 : _c.eventType;
91
+ const validEventTypes = [
92
+ 'origin-response',
93
+ 'origin-request',
94
+ 'viewer-response',
95
+ 'viewer-request',
96
+ ];
97
+ return validEventTypes.includes(eventType);
98
+ }
99
+ /**
100
+ * @inheritDoc
101
+ */
102
+ getRequest(event) {
103
+ var _a;
104
+ const request = event.Records[0];
105
+ const cloudFrontRequest = request.cf.request;
106
+ const method = cloudFrontRequest.method;
107
+ const pathFromOptions = ((_a = this.options) === null || _a === void 0 ? void 0 : _a.getPathFromEvent)
108
+ ? this.options.getPathFromEvent(request)
109
+ : undefined;
110
+ const defaultPath = (0, core_1.getPathWithQueryStringParams)(cloudFrontRequest.uri, cloudFrontRequest.querystring);
111
+ const path = (0, core_1.getDefaultIfUndefined)(pathFromOptions, defaultPath);
112
+ const remoteAddress = cloudFrontRequest.clientIp;
113
+ const headers = this.getFlattenedHeadersFromCloudfrontRequest(cloudFrontRequest);
114
+ let body;
115
+ if (cloudFrontRequest.body) {
116
+ const [buffer, contentLength] = (0, core_1.getEventBodyAsBuffer)(JSON.stringify(cloudFrontRequest.body), false);
117
+ body = buffer;
118
+ headers['content-length'] = contentLength.toString();
119
+ }
120
+ const { host } = headers;
121
+ return {
122
+ method,
123
+ path,
124
+ headers,
125
+ body,
126
+ remoteAddress,
127
+ host,
128
+ hostname: host,
129
+ };
130
+ }
131
+ /**
132
+ * @inheritDoc
133
+ */
134
+ getResponse(props) {
135
+ var _a, _b, _c;
136
+ const response = this.getResponseToLambdaEdge(props);
137
+ const responseToServiceBytes = new TextEncoder().encode(JSON.stringify(response)).length;
138
+ const isOriginRequestOrResponse = this.isEventTypeOrigin(props.event.Records[0].cf.config);
139
+ const maxSizeInBytes = isOriginRequestOrResponse
140
+ ? (0, core_1.getDefaultIfUndefined)((_a = this.options) === null || _a === void 0 ? void 0 : _a.originMaxResponseSizeInBytes, exports.DEFAULT_ORIGIN_MAX_RESPONSE_SIZE_IN_BYTES)
141
+ : (0, core_1.getDefaultIfUndefined)((_b = this.options) === null || _b === void 0 ? void 0 : _b.viewerMaxResponseSizeInBytes, exports.DEFAULT_VIEWER_MAX_RESPONSE_SIZE_IN_BYTES);
142
+ if (responseToServiceBytes <= maxSizeInBytes)
143
+ return response;
144
+ if ((_c = this.options) === null || _c === void 0 ? void 0 : _c.onResponseSizeExceedLimit)
145
+ this.options.onResponseSizeExceedLimit(response);
146
+ else {
147
+ props.log.error(`SERVERLESS_ADAPTER:LAMBDA_EDGE_ADAPTER: Max response size exceeded: ${responseToServiceBytes} of the max of ${maxSizeInBytes}.`);
148
+ }
149
+ return response;
150
+ }
151
+ /**
152
+ * @inheritDoc
153
+ */
154
+ onErrorWhileForwarding({ error, delegatedResolver, }) {
155
+ delegatedResolver.fail(error);
156
+ }
157
+ //#endregion
158
+ //#region Protected Methods
159
+ /**
160
+ * Returns the headers with the flattened (non-list) values of the cloudfront request headers
161
+ *
162
+ * @param cloudFrontRequest The cloudfront request
163
+ */
164
+ getFlattenedHeadersFromCloudfrontRequest(cloudFrontRequest) {
165
+ const headers = {};
166
+ const headerValuePairs = Object.entries(cloudFrontRequest.headers);
167
+ for (const [headerKey, headerValue] of headerValuePairs)
168
+ headers[headerKey] = headerValue.map(header => header.value).join(',');
169
+ return headers;
170
+ }
171
+ /**
172
+ * Returns the framework response in the format required by the Lambda@edge.
173
+ *
174
+ * @param body The body of the response
175
+ * @param frameworkHeaders The headers from the framework
176
+ */
177
+ getResponseToLambdaEdge({ body, headers: frameworkHeaders, }) {
178
+ var _a;
179
+ const shouldUseHeadersFromFramework = (0, core_1.getDefaultIfUndefined)((_a = this.options) === null || _a === void 0 ? void 0 : _a.shouldUseHeadersFromFramework, false);
180
+ const parsedBody = JSON.parse(body);
181
+ if (parsedBody.headers) {
182
+ parsedBody.headers = Object.keys(parsedBody.headers).reduce((acc, header) => {
183
+ if (this.shouldStripHeader(header))
184
+ return acc;
185
+ acc[header] = parsedBody.headers[header];
186
+ return acc;
187
+ }, {});
188
+ }
189
+ if (!shouldUseHeadersFromFramework)
190
+ return parsedBody;
191
+ parsedBody.headers = this.getHeadersForCloudfrontResponse(frameworkHeaders);
192
+ return parsedBody;
193
+ }
194
+ /**
195
+ * Returns headers in Cloudfront Response format.
196
+ *
197
+ * @param originalHeaders The original version of the request sent by the framework
198
+ */
199
+ getHeadersForCloudfrontResponse(originalHeaders) {
200
+ const originalHeadersEntries = Object.entries(originalHeaders);
201
+ const headers = {};
202
+ for (const [headerKey, headerValue] of originalHeadersEntries) {
203
+ if (this.shouldStripHeader(headerKey))
204
+ continue;
205
+ if (!headers[headerKey])
206
+ headers[headerKey] = [];
207
+ if (!Array.isArray(headerValue)) {
208
+ headers[headerKey].push({
209
+ key: headerKey,
210
+ value: headerValue || '',
211
+ });
212
+ continue;
213
+ }
214
+ const headersArray = headerValue.map(value => ({
215
+ key: headerKey,
216
+ value: value,
217
+ }));
218
+ headers[headerKey].push(...headersArray);
219
+ }
220
+ return headers;
221
+ }
222
+ /**
223
+ * Returns the information if we should remove the response header
224
+ *
225
+ * @param headerKey The header that will be tested
226
+ */
227
+ shouldStripHeader(headerKey) {
228
+ var _a;
229
+ if ((_a = this.options) === null || _a === void 0 ? void 0 : _a.shouldStripHeader)
230
+ return this.options.shouldStripHeader(headerKey);
231
+ const headerKeyLowerCase = headerKey.toLowerCase();
232
+ for (const stripHeaderIf of this.cachedDisallowedHeaders) {
233
+ if (!stripHeaderIf.test(headerKeyLowerCase))
234
+ continue;
235
+ return true;
236
+ }
237
+ return false;
238
+ }
239
+ /**
240
+ * Determines whether the event is from origin or is from viewer.
241
+ *
242
+ * @param content The event sent by AWS or the response sent by the framework
243
+ */
244
+ isEventTypeOrigin(content) {
245
+ return content.eventType.includes('origin');
246
+ }
247
+ }
248
+ exports.LambdaEdgeAdapter = LambdaEdgeAdapter;
@@ -0,0 +1,62 @@
1
+ import type { Context, SNSEvent } from 'aws-lambda';
2
+ import { AdapterContract, AdapterRequest, OnErrorProps } from '../../contracts';
3
+ import { IEmptyResponse } from '../../core';
4
+ /**
5
+ * The options to customize the {@link SNSAdapter}
6
+ */
7
+ export interface SNSAdapterOptions {
8
+ /**
9
+ * The path that will be used to create a request to be forwarded to the framework.
10
+ *
11
+ * @default /sns
12
+ */
13
+ snsForwardPath?: string;
14
+ /**
15
+ * The http method that will be used to create a request to be forwarded to the framework.
16
+ *
17
+ * @default POST
18
+ */
19
+ snsForwardMethod?: string;
20
+ }
21
+ /**
22
+ * The adapter to handle requests from AWS SNS.
23
+ *
24
+ * The option of `responseWithErrors` is ignored by this adapter and we always call `resolver.fail` with the error.
25
+ *
26
+ * {@link https://docs.aws.amazon.com/pt_br/lambda/latest/dg/with-sns.html Event Reference}
27
+ *
28
+ * @example```typescript
29
+ * const snsForwardPath = '/your/route/sns'; // default /sns
30
+ * const snsForwardMethod = 'POST'; // default POST
31
+ * const adapter = new SNSAdapter({ snsForwardPath, snsForwardMethod });
32
+ * ```
33
+ */
34
+ export declare class SNSAdapter implements AdapterContract<SNSEvent, Context, IEmptyResponse> {
35
+ protected readonly options?: SNSAdapterOptions | undefined;
36
+ /**
37
+ * Default constructor
38
+ *
39
+ * @param options The options to customize the {@link SNSAdapter}
40
+ */
41
+ constructor(options?: SNSAdapterOptions | undefined);
42
+ /**
43
+ * @inheritDoc
44
+ */
45
+ getAdapterName(): string;
46
+ /**
47
+ * @inheritDoc
48
+ */
49
+ canHandle(event: unknown): event is SNSEvent;
50
+ /**
51
+ * @inheritDoc
52
+ */
53
+ getRequest(event: SNSEvent): AdapterRequest;
54
+ /**
55
+ * @inheritDoc
56
+ */
57
+ getResponse(): IEmptyResponse;
58
+ /**
59
+ * @inheritDoc
60
+ */
61
+ onErrorWhileForwarding({ error, delegatedResolver, }: OnErrorProps<SNSEvent, IEmptyResponse>): void;
62
+ }
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+ //#region Imports
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.SNSAdapter = void 0;
5
+ const core_1 = require("../../core");
6
+ /**
7
+ * The adapter to handle requests from AWS SNS.
8
+ *
9
+ * The option of `responseWithErrors` is ignored by this adapter and we always call `resolver.fail` with the error.
10
+ *
11
+ * {@link https://docs.aws.amazon.com/pt_br/lambda/latest/dg/with-sns.html Event Reference}
12
+ *
13
+ * @example```typescript
14
+ * const snsForwardPath = '/your/route/sns'; // default /sns
15
+ * const snsForwardMethod = 'POST'; // default POST
16
+ * const adapter = new SNSAdapter({ snsForwardPath, snsForwardMethod });
17
+ * ```
18
+ */
19
+ class SNSAdapter {
20
+ //#region Constructor
21
+ /**
22
+ * Default constructor
23
+ *
24
+ * @param options The options to customize the {@link SNSAdapter}
25
+ */
26
+ constructor(options) {
27
+ this.options = options;
28
+ }
29
+ //#endregion
30
+ //#region Public Methods
31
+ /**
32
+ * @inheritDoc
33
+ */
34
+ getAdapterName() {
35
+ return SNSAdapter.name;
36
+ }
37
+ /**
38
+ * @inheritDoc
39
+ */
40
+ canHandle(event) {
41
+ var _a;
42
+ const snsEvent = event;
43
+ if (!Array.isArray(snsEvent === null || snsEvent === void 0 ? void 0 : snsEvent.Records))
44
+ return false;
45
+ const eventSource = (_a = snsEvent.Records[0]) === null || _a === void 0 ? void 0 : _a.EventSource;
46
+ return eventSource === 'aws:sns';
47
+ }
48
+ /**
49
+ * @inheritDoc
50
+ */
51
+ getRequest(event) {
52
+ var _a, _b;
53
+ const path = (0, core_1.getDefaultIfUndefined)((_a = this.options) === null || _a === void 0 ? void 0 : _a.snsForwardPath, '/sns');
54
+ const method = (0, core_1.getDefaultIfUndefined)((_b = this.options) === null || _b === void 0 ? void 0 : _b.snsForwardMethod, 'POST');
55
+ const [body, contentLength] = (0, core_1.getEventBodyAsBuffer)(JSON.stringify(event), false);
56
+ const headers = {
57
+ host: 'sns.amazonaws.com',
58
+ 'content-type': 'application/json',
59
+ 'content-length': String(contentLength),
60
+ };
61
+ return {
62
+ method,
63
+ headers,
64
+ body,
65
+ path,
66
+ };
67
+ }
68
+ /**
69
+ * @inheritDoc
70
+ */
71
+ getResponse() {
72
+ return core_1.EmptyResponse;
73
+ }
74
+ /**
75
+ * @inheritDoc
76
+ */
77
+ onErrorWhileForwarding({ error, delegatedResolver, }) {
78
+ delegatedResolver.fail(error);
79
+ }
80
+ }
81
+ exports.SNSAdapter = SNSAdapter;
@@ -0,0 +1,62 @@
1
+ import type { Context, SQSEvent } from 'aws-lambda';
2
+ import { AdapterContract, AdapterRequest, OnErrorProps } from '../../contracts';
3
+ import { IEmptyResponse } from '../../core';
4
+ /**
5
+ * The options to customize the {@link SQSAdapter}
6
+ */
7
+ export interface SQSAdapterOptions {
8
+ /**
9
+ * The path that will be used to create a request to be forwarded to the framework.
10
+ *
11
+ * @default /sqs
12
+ */
13
+ sqsForwardPath?: string;
14
+ /**
15
+ * The http method that will be used to create a request to be forwarded to the framework.
16
+ *
17
+ * @default POST
18
+ */
19
+ sqsForwardMethod?: string;
20
+ }
21
+ /**
22
+ * The adapter to handle requests from AWS SQS.
23
+ *
24
+ * The option of `responseWithErrors` is ignored by this adapter and we always call `resolver.fail` with the error.
25
+ *
26
+ * {@link https://docs.aws.amazon.com/pt_br/lambda/latest/dg/with-sqs.html Event Reference}
27
+ *
28
+ * @example```typescript
29
+ * const sqsForwardPath = '/your/route/sqs'; // default /sqs
30
+ * const sqsForwardMethod = 'POST'; // default POST
31
+ * const adapter = new SQSAdapter({ sqsForwardPath, sqsForwardMethod });
32
+ * ```
33
+ */
34
+ export declare class SQSAdapter implements AdapterContract<SQSEvent, Context, IEmptyResponse> {
35
+ protected readonly options?: SQSAdapterOptions | undefined;
36
+ /**
37
+ * Default constructor
38
+ *
39
+ * @param options The options to customize the {@link SQSAdapter}
40
+ */
41
+ constructor(options?: SQSAdapterOptions | undefined);
42
+ /**
43
+ * @inheritDoc
44
+ */
45
+ getAdapterName(): string;
46
+ /**
47
+ * @inheritDoc
48
+ */
49
+ canHandle(event: unknown): event is SQSEvent;
50
+ /**
51
+ * @inheritDoc
52
+ */
53
+ getRequest(event: SQSEvent): AdapterRequest;
54
+ /**
55
+ * @inheritDoc
56
+ */
57
+ getResponse(): IEmptyResponse;
58
+ /**
59
+ * @inheritDoc
60
+ */
61
+ onErrorWhileForwarding({ error, delegatedResolver, }: OnErrorProps<SQSEvent, IEmptyResponse>): void;
62
+ }