@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
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2022 Vinícius Lourenço
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,204 @@
1
+ <h1 align="center">
2
+ 🚀 Serverless Adapter
3
+ </h1>
4
+
5
+ <p align="center">
6
+ <a href="#install">Install</a>&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;
7
+ <a href="#usage">Usage</a>&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;
8
+ <a href="#support">Support</a>&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;
9
+ <a href="#architecture">Architecture</a>&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;
10
+ <a href="#credits">Credits</a>
11
+ </p>
12
+
13
+ [![npm package][npm-img]][npm-url]
14
+ [![Build Status][build-img]][build-url]
15
+ [![Downloads][downloads-img]][downloads-url]
16
+ [![Issues][issues-img]][issues-url]
17
+ [![Code Coverage][codecov-img]][codecov-url]
18
+ [![Commitizen Friendly][commitizen-img]][commitizen-url]
19
+ [![Semantic Release][semantic-release-img]][semantic-release-url]
20
+
21
+ Run REST APIs and other web applications using your existing Node.js application framework (Express, Koa, Hapi and Fastify)
22
+ , on top of AWS Lambda, Amazon API Gateway and many other event sources.
23
+
24
+ This library was a refactored version of [@vendia/serverless-express](https://github.com/vendia/serverless-express), I created a new way to interact and extend event sources by creating contracts to abstract the integrations between each library layer.
25
+
26
+ Why you would use this libray instead of [@vendia/serverless-express](https://github.com/vendia/serverless-express)?
27
+
28
+ - Better APIs to extend library functionality.
29
+ - You don't need me to release a new version to integrate with the new event source, you can create an adapter and just call the `addAdapter` method when building your handler.
30
+ - All code can be extended, if you want to modify the current behavior you can.
31
+ - This is important because if you find a bug, you can quickly resolve it by extending the class, _and then you can submit a PR to fix the bug_.
32
+ - All code was written in Typescript.
33
+ - We have >99% coverage.
34
+
35
+ # Install
36
+
37
+ Using NPM:
38
+
39
+ ```bash
40
+ npm install --save @h4ad/serverless-adapter
41
+ ```
42
+
43
+ Using Yarn:
44
+
45
+ ```bash
46
+ yarn add @h4ad/serverless-adapter
47
+ ```
48
+
49
+ # Usage
50
+
51
+ You can quickly use this library as follows:
52
+
53
+ ```ts
54
+ import app from './app';
55
+
56
+ export const handler = ServerlessAdapter.new(app)
57
+ .setFramework(new ExpressFramework())
58
+ .setHandler(new DefaultHandler())
59
+ .setResolver(new PromiseResolver())
60
+ .addAdapter(new AlbAdapter())
61
+ .addAdapter(new SQSAdapter())
62
+ .addAdapter(new SNSAdapter())
63
+ .build();
64
+
65
+ export { handler };
66
+ ```
67
+
68
+ Too fast? Ok, I can explain.
69
+
70
+ First, you need to create an instance of the builder with `ServerlessAdapter.new(app)`.
71
+ The variable `app` is the instance of your framework (Express, Fastify, Koa, etc).
72
+
73
+ So you need to specify for this library which `framework` you will use to handle the `request` with `setFramework`, you can only use one.
74
+ If you use express in our backend, use [ExpressFramework](./src/frameworks/express.framework.ts), see more in [support](#support).
75
+
76
+ Then you specify which `handler` you will use to interact with the serverless cloud with `setHandler`, currently we only have one, the [DefaultHandler](./src/handlers/default.handler.ts).
77
+ In the next releases, maybe we will add support for Azure, Huawei and others, for now, you can use this default.
78
+
79
+ Then you specify with `setResolver` which `resolver` you will use to wait for the library to forward the request to your `framework`, and then get the `response` back to your cloud.
80
+ I recommend you use [PromiseResolver](./src/resolvers/promise.resolver.ts), it's the most cloud-agnostic `resolver`.
81
+
82
+ By now, you've already added the basic abstractions of this library, now, you can add the `adapters` that will add support for receiving and processing different sources of `addAdapter` events.
83
+ In the example I added [AlbAdapter](./src/adapters/aws/alb.adapter.ts), [SQSAdapter](./src/adapters/aws/sqs.adapter.ts) and [SNSAdapter](./src/adapters/aws/sns.adapter.ts).
84
+ With these adapters you can connect your lambda to three different event sources and you can add more if you wish.
85
+
86
+ Finally, we call `build` which will assemble your handler that you can expose directly to your cloud.
87
+
88
+ Final thoughts:
89
+
90
+ - You can set the `framework` only once.
91
+ - You can set the `handler` only once.
92
+ - You can set the `resolver` only once.
93
+ - You can have as many `adapters` as you like, use and extend as you wish.
94
+
95
+ # Support
96
+
97
+ > We are in beta, so some adapters may not work as expected, feel free to create an issue or provide feedback on current behavior.
98
+
99
+ By design we have these contracts that define the layers of the library: Frameworks, Adapters, Resolvers and Handlers.
100
+
101
+ > If you don't know what each thing means, see [Architecture](#architecture).
102
+
103
+ Currently, we support these frameworks:
104
+
105
+ - [Express](https://expressjs.com/) by using ([ExpressFramework](./src/frameworks/express.framework.ts))
106
+ - [Fastify](https://www.fastify.io/) by using ([FastifyFramework](./src/frameworks/fastify.framework.ts))
107
+ - [Hapi](https://hapi.dev/) by using ([HapiFramework](./src/frameworks/hapi.framework.ts))
108
+ - [Koa](https://koajs.com/) by using ([KoaFramework](./src/frameworks/koa.framework.ts))
109
+
110
+ We support these event sources:
111
+
112
+ - AWS
113
+ - [AWS Load Balancer](https://docs.aws.amazon.com/lambda/latest/dg/services-alb.html) by
114
+ using ([AlbAdapter](./src/adapters/aws/alb.adapter.ts))
115
+ - [AWS Api Gateway V1](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html)
116
+ by using ([ApiGatewayV1Adapter](./src/adapters/aws/api-gateway-v1.adapter.ts))
117
+ - [AWS Api Gateway V2](https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html)
118
+ by using ([ApiGatewayV2Adapter](./src/adapters/aws/api-gateway-v2.adapter.ts))
119
+ - [AWS DynamoDB](https://docs.aws.amazon.com/lambda/latest/dg/with-ddb.html) by
120
+ using ([DynamoDBAdapter](./src/adapters/aws/dynamodb.adapter.ts))
121
+ - [AWS Event Bridge / CloudWatch Events](https://docs.aws.amazon.com/lambda/latest/dg/services-cloudwatchevents.html)
122
+ by using ([EventBridgeAdapter](./src/adapters/aws/event-bridge.adapter.ts))
123
+ - [AWS Lambda Edge](https://docs.aws.amazon.com/lambda/latest/dg/lambda-edge.html) by
124
+ using ([LambdaEdgeAdapter](./src/adapters/aws/lambda-edge.adapter.ts))
125
+ - [AWS SNS](https://docs.aws.amazon.com/pt_br/lambda/latest/dg/with-sns.html) by
126
+ using ([SNSAdapter](./src/adapters/aws/sns.adapter.ts))
127
+ - [AWS SQS](https://docs.aws.amazon.com/pt_br/lambda/latest/dg/with-sqs.html) by
128
+ using ([SQSAdapter](./src/adapters/aws/sqs.adapter.ts))
129
+ - Azure
130
+ - The support is cooming soon.
131
+ - Huawei
132
+ - The support is cooming soon.
133
+
134
+ We support these resolvers:
135
+
136
+ - Promise by using ([PromiseResolver](./src/resolvers/promise.resolver.ts))
137
+ - Callback by using ([CallbackResolver](./src/resolvers/callback.resolver.ts))
138
+ - AWS Context by using ([AwsContextResolver](./src/resolvers/aws-context.resolver.ts))
139
+
140
+ We support these handlers:
141
+
142
+ - Default by using ([DefaultHandler](./src/handlers/default.handler.ts))
143
+
144
+ # Architecture
145
+
146
+ The main purpose of this library is to allow the developer to add support for any cloud and as many event sources as he wants, without having to create an issue to request the feature or copy the library code because the library doesn't expose good APIs for you to extend its functionality
147
+
148
+ So I refactored [@vendia/serverless-express](https://github.com/vendia/serverless-express) with 4 layers of abstraction: Framework, Handler, Resolver and Adapter.
149
+
150
+ The [FrameworkContract](./src/contracts/framework.contract.ts) is responsible for forwarding to [IncomingMessage](https://nodejs.org/api/http.html#class-httpincomingmessage) and [ServerResponse](https://nodejs.org/api/http.html#class-httpserverresponse) for your application instance.
151
+ With this abstraction you can implement any framework you want, they just need to accept both parameters and call [end](https://nodejs.org/api/http.html#class-httpserverresponse) in [ServerResponse](https://nodejs.org/api/http.html#class-httpserverresponse), so the library knows when to continue and return the response.
152
+
153
+ The [HandlerContract](./src/contracts/handler.contract.ts) is responsible to get the input from the serverless and then manage to call each layer of abstraction to return a response.
154
+ With this abstraction, you can implement different ways to receive input from your serverless environment.
155
+ They usually have the same structure, but if you need to deal with a very different cloud, you can use this abstraction to add support for that cloud.
156
+
157
+ > Handler is a good choice for implementing (~~monsters~~) ways to receive input.
158
+ > For example, we can create an http server as its handler to test our serverless code without having to launch the framework. Because? I don't know, but you can.
159
+
160
+ The [ResolverContract](./src/contracts/resolver.contract.ts) is responsible for waiting for the framework to handle the request and then returning the response to the cloud.
161
+ Using AWS for example, you have three ways to wait for the response: returning a promise, calling the callback, and ~~using in-context methods~~, each option has its own benefits, but generally the promise option will be the better because any good cloud provider will support promises.
162
+
163
+ Finally, the masterpiece of this library, the [AdapterContract](./src/contracts/adapter.contract.ts) is responsible for handling the received event, transforming the request in a way that your application can understand and then transforming the response in a way your cloud can understand.
164
+
165
+ Well, with these four contracts, you'll be able to add support to any cloud that exists (no more excuses not to use cloud X with NodeJS).
166
+
167
+ ## Why you create this library?
168
+
169
+ The real reason I created this library was because I wanted to add API Gateway and SQS support at the same time to save some money.
170
+ But, [@vendia/serverless-express](https://github.com/vendia/serverless-express) was not supported, so I [created a PR](https://github.com/vendia/serverless-express/pull/483), but until I finished this library, that PR was never accepted.
171
+
172
+ So I build my own library based on that library with better APIs so I never have to wait for the maintainer to accept my PR just to extend the library's functionality :)
173
+
174
+ # Credits
175
+
176
+ Honestly, I just refactored all the code that the @vendia team and many other contributors wrote, thanks so much to them for existing and giving us a brilliant library that is the core of my current company.
177
+
178
+ [build-img]:https://github.com/H4ad/serverless-adapter/actions/workflows/release.yml/badge.svg
179
+
180
+ [build-url]:https://github.com/H4ad/serverless-adapter/actions/workflows/release.yml
181
+
182
+ [downloads-img]:https://img.shields.io/npm/dt/serverless-adapter
183
+
184
+ [downloads-url]:https://www.npmtrends.com/serverless-adapter
185
+
186
+ [npm-img]:https://img.shields.io/npm/v/serverless-adapter
187
+
188
+ [npm-url]:https://www.npmjs.com/package/serverless-adapter
189
+
190
+ [issues-img]:https://img.shields.io/github/issues/H4ad/serverless-adapter
191
+
192
+ [issues-url]:https://github.com/H4ad/serverless-adapter/issues
193
+
194
+ [codecov-img]:https://codecov.io/gh/H4ad/serverless-adapter/branch/main/graph/badge.svg
195
+
196
+ [codecov-url]:https://codecov.io/gh/H4ad/serverless-adapter
197
+
198
+ [semantic-release-img]:https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg
199
+
200
+ [semantic-release-url]:https://github.com/semantic-release/semantic-release
201
+
202
+ [commitizen-img]:https://img.shields.io/badge/commitizen-friendly-brightgreen.svg
203
+
204
+ [commitizen-url]:http://commitizen.github.io/cz-cli/
@@ -0,0 +1,23 @@
1
+ /**
2
+ * The interface representing the settings for whether the response should be treated as binary or not
3
+ *
4
+ * @note Encoded as binary means the response body will be converted to base64
5
+ */
6
+ export declare type BinarySettings = {
7
+ /**
8
+ * This property can be a function that receives the response headers and returns whether that response should be encoded as binary.
9
+ * Otherwise, you can specify not to treat any response as binary by putting `false` in this property.
10
+ *
11
+ * @note Setting this property prevents the `contentTypes` and `contentEncodings` properties from being used.
12
+ */
13
+ isBinary: ((headers: Record<string, string | string[] | undefined>) => boolean) | false;
14
+ } | {
15
+ /**
16
+ * The list of content types that will be treated as binary
17
+ */
18
+ contentTypes: (string | RegExp)[];
19
+ /**
20
+ * The list of content encodings that will be treated as binary
21
+ */
22
+ contentEncodings: string[];
23
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,24 @@
1
+ /**
2
+ * The record that represents the headers that doesn't have multiple values in the value
3
+ *
4
+ * @example```typescript
5
+ * { 'Accept-Encoding': 'gzip, deflate, br' }
6
+ * ```
7
+ */
8
+ export declare type SingleValueHeaders = Record<string, string | undefined>;
9
+ /**
10
+ * The record that represents the headers that have multiple values in the value
11
+ *
12
+ * @example```typescript
13
+ * { 'Accept-Encoding': ['gzip', 'deflate', 'br'] }
14
+ * ```
15
+ */
16
+ export declare type MultiValueHeaders = Record<string, string[] | undefined>;
17
+ /**
18
+ * The record that represents the headers that can both single or multiple values in the value
19
+ *
20
+ * @example```typescript
21
+ * { 'Accept-Encoding': ['gzip', 'deflate', 'br'], 'Host': 'xyz.execute-api.us-east-1.amazonaws.com' }
22
+ * ```
23
+ */
24
+ export declare type BothValueHeaders = Record<string, string | string[] | undefined>;
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Removes 'optional' attributes from a type's properties
3
+ */
4
+ export declare type Concrete<Type> = {
5
+ [Property in keyof Type]-?: Type[Property];
6
+ };
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,3 @@
1
+ export * from './binary-settings';
2
+ export * from './headers';
3
+ export * from './proxy-params';
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
5
+ }) : (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ o[k2] = m[k];
8
+ }));
9
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
10
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
11
+ };
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ __exportStar(require("./binary-settings"), exports);
14
+ __exportStar(require("./headers"), exports);
15
+ __exportStar(require("./proxy-params"), exports);
@@ -0,0 +1,8 @@
1
+ /// <reference types="node" />
2
+ import { RequestListener } from 'http';
3
+ import { BinarySettings } from './binary-settings';
4
+ export interface ProxyParams {
5
+ app: RequestListener;
6
+ binaryMimeTypes?: string[];
7
+ binarySettings?: BinarySettings;
8
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,58 @@
1
+ import type { ALBEvent, ALBResult, Context } from 'aws-lambda';
2
+ import { AdapterContract, AdapterRequest, GetResponseAdapterProps, OnErrorProps } from '../../contracts';
3
+ /**
4
+ * The options to customize the {@link AlbAdapter}
5
+ */
6
+ export interface AlbAdapterOptions {
7
+ /**
8
+ * Strip base path for custom domains
9
+ *
10
+ * @default ''
11
+ */
12
+ stripBasePath?: string;
13
+ }
14
+ /**
15
+ * The adapter to handle requests from AWS ALB
16
+ *
17
+ * @example```typescript
18
+ * const stripBasePath = '/any/custom/base/path'; // default ''
19
+ * const adapter = new AlbAdapter({ stripBasePath });
20
+ * ```
21
+ *
22
+ * {@link https://docs.aws.amazon.com/lambda/latest/dg/services-alb.html Event Reference}
23
+ */
24
+ export declare class AlbAdapter implements AdapterContract<ALBEvent, Context, ALBResult> {
25
+ protected readonly options?: AlbAdapterOptions | undefined;
26
+ /**
27
+ * Default constructor
28
+ *
29
+ * @param options The options to customize the {@link AlbAdapter}
30
+ */
31
+ constructor(options?: AlbAdapterOptions | undefined);
32
+ /**
33
+ * @inheritDoc
34
+ */
35
+ getAdapterName(): string;
36
+ /**
37
+ * @inheritDoc
38
+ */
39
+ canHandle(event: unknown): event is ALBEvent;
40
+ /**
41
+ * @inheritDoc
42
+ */
43
+ getRequest(event: ALBEvent): AdapterRequest;
44
+ /**
45
+ * @inheritDoc
46
+ */
47
+ getResponse({ event, headers: responseHeaders, body, isBase64Encoded, statusCode, }: GetResponseAdapterProps<ALBEvent>): ALBResult;
48
+ /**
49
+ * @inheritDoc
50
+ */
51
+ onErrorWhileForwarding({ error, delegatedResolver, respondWithErrors, event, log, }: OnErrorProps<ALBEvent, ALBResult>): void;
52
+ /**
53
+ * Get path from event with query strings
54
+ *
55
+ * @param event The event sent by serverless
56
+ */
57
+ protected getPathFromEvent(event: ALBEvent): string;
58
+ }
@@ -0,0 +1,119 @@
1
+ "use strict";
2
+ //#region Imports
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.AlbAdapter = void 0;
5
+ const core_1 = require("../../core");
6
+ /**
7
+ * The adapter to handle requests from AWS ALB
8
+ *
9
+ * @example```typescript
10
+ * const stripBasePath = '/any/custom/base/path'; // default ''
11
+ * const adapter = new AlbAdapter({ stripBasePath });
12
+ * ```
13
+ *
14
+ * {@link https://docs.aws.amazon.com/lambda/latest/dg/services-alb.html Event Reference}
15
+ */
16
+ class AlbAdapter {
17
+ //#region Constructor
18
+ /**
19
+ * Default constructor
20
+ *
21
+ * @param options The options to customize the {@link AlbAdapter}
22
+ */
23
+ constructor(options) {
24
+ this.options = options;
25
+ }
26
+ //#endregion
27
+ //#region Public Methods
28
+ /**
29
+ * @inheritDoc
30
+ */
31
+ getAdapterName() {
32
+ return AlbAdapter.name;
33
+ }
34
+ /**
35
+ * @inheritDoc
36
+ */
37
+ canHandle(event) {
38
+ const albEvent = event;
39
+ return !!((albEvent === null || albEvent === void 0 ? void 0 : albEvent.requestContext) && albEvent.requestContext.elb);
40
+ }
41
+ /**
42
+ * @inheritDoc
43
+ */
44
+ getRequest(event) {
45
+ const method = event.httpMethod;
46
+ const path = this.getPathFromEvent(event);
47
+ const headers = event.multiValueHeaders
48
+ ? (0, core_1.getFlattenedHeadersMap)(event.multiValueHeaders, ',', true)
49
+ : event.headers;
50
+ let body;
51
+ if (event.body) {
52
+ const [bufferBody, contentLength] = (0, core_1.getEventBodyAsBuffer)(event.body, event.isBase64Encoded);
53
+ body = bufferBody;
54
+ headers['content-length'] = String(contentLength);
55
+ }
56
+ let remoteAddress = '';
57
+ // ref: https://docs.aws.amazon.com/elasticloadbalancing/latest/application/x-forwarded-headers.html#x-forwarded-for
58
+ if (headers['x-forwarded-for'])
59
+ remoteAddress = headers['x-forwarded-for'];
60
+ return {
61
+ method,
62
+ headers,
63
+ body,
64
+ remoteAddress,
65
+ path,
66
+ };
67
+ }
68
+ /**
69
+ * @inheritDoc
70
+ */
71
+ getResponse({ event, headers: responseHeaders, body, isBase64Encoded, statusCode, }) {
72
+ const multiValueHeaders = !event.headers
73
+ ? (0, core_1.getMultiValueHeadersMap)(responseHeaders)
74
+ : undefined;
75
+ const headers = event.headers
76
+ ? (0, core_1.getFlattenedHeadersMap)(responseHeaders)
77
+ : undefined;
78
+ return {
79
+ statusCode,
80
+ body,
81
+ headers,
82
+ multiValueHeaders,
83
+ isBase64Encoded,
84
+ };
85
+ }
86
+ /**
87
+ * @inheritDoc
88
+ */
89
+ onErrorWhileForwarding({ error, delegatedResolver, respondWithErrors, event, log, }) {
90
+ const body = respondWithErrors ? error.stack || '' : '';
91
+ const errorResponse = this.getResponse({
92
+ event,
93
+ statusCode: 500,
94
+ body,
95
+ headers: {},
96
+ isBase64Encoded: false,
97
+ log,
98
+ });
99
+ delegatedResolver.succeed(errorResponse);
100
+ }
101
+ //#endregion
102
+ //#region Protected Methods
103
+ /**
104
+ * Get path from event with query strings
105
+ *
106
+ * @param event The event sent by serverless
107
+ */
108
+ getPathFromEvent(event) {
109
+ var _a;
110
+ const stripBasePath = (0, core_1.getDefaultIfUndefined)((_a = this.options) === null || _a === void 0 ? void 0 : _a.stripBasePath, '');
111
+ const replaceRegex = new RegExp(`^${stripBasePath}`);
112
+ const path = event.path.replace(replaceRegex, '');
113
+ const queryParams = event.headers
114
+ ? event.queryStringParameters
115
+ : event.multiValueQueryStringParameters;
116
+ return (0, core_1.getPathWithQueryStringParams)(path, queryParams || {});
117
+ }
118
+ }
119
+ exports.AlbAdapter = AlbAdapter;
@@ -0,0 +1,63 @@
1
+ import type { APIGatewayProxyResult, Context } from 'aws-lambda';
2
+ import type { APIGatewayProxyEvent } from 'aws-lambda/trigger/api-gateway-proxy';
3
+ import { AdapterContract, AdapterRequest, GetResponseAdapterProps, OnErrorProps } from '../../contracts';
4
+ /**
5
+ * The options to customize the {@link ApiGatewayV1Adapter}
6
+ */
7
+ export interface ApiGatewayV1Options {
8
+ /**
9
+ * Strip base path for custom domains
10
+ *
11
+ * @default ''
12
+ */
13
+ stripBasePath?: string;
14
+ }
15
+ /**
16
+ * The adapter to handle requests from AWS Api Gateway V1
17
+ *
18
+ * As per {@link https://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-known-issues.html know issues}, we throw an exception when you send the `transfer-encoding=chunked`, currently, API Gateway doesn't support chunked transfer.
19
+ *
20
+ * @note This adapter is not fully compatible with @vendia/serverless-express, on @vendia they filter `transfer-encoding=chunked` but we throw an exception.
21
+ *
22
+ * @example```typescript
23
+ * const stripBasePath = '/any/custom/base/path'; // default ''
24
+ * const adapter = new ApiGatewayV1Adapter({ stripBasePath });
25
+ * ```
26
+ *
27
+ * {@link https://docs.aws.amazon.com/apigateway/latest/developerguide/http-api-develop-integrations-lambda.html Event Reference}
28
+ */
29
+ export declare class ApiGatewayV1Adapter implements AdapterContract<APIGatewayProxyEvent, Context, APIGatewayProxyResult> {
30
+ protected readonly options?: ApiGatewayV1Options | undefined;
31
+ /**
32
+ * Default constructor
33
+ *
34
+ * @param options The options to customize the {@link ApiGatewayV1Adapter}
35
+ */
36
+ constructor(options?: ApiGatewayV1Options | undefined);
37
+ /**
38
+ * @inheritDoc
39
+ */
40
+ getAdapterName(): string;
41
+ /**
42
+ * @inheritDoc
43
+ */
44
+ canHandle(event: unknown): event is APIGatewayProxyEvent;
45
+ /**
46
+ * @inheritDoc
47
+ */
48
+ getRequest(event: APIGatewayProxyEvent): AdapterRequest;
49
+ /**
50
+ * @inheritDoc
51
+ */
52
+ getResponse({ headers: responseHeaders, body, isBase64Encoded, statusCode, response, }: GetResponseAdapterProps<APIGatewayProxyEvent>): APIGatewayProxyResult;
53
+ /**
54
+ * @inheritDoc
55
+ */
56
+ onErrorWhileForwarding({ error, delegatedResolver, respondWithErrors, event, log, }: OnErrorProps<APIGatewayProxyEvent, APIGatewayProxyResult>): void;
57
+ /**
58
+ * Get path from event with query strings
59
+ *
60
+ * @param event The event sent by serverless
61
+ */
62
+ protected getPathFromEvent(event: APIGatewayProxyEvent): string;
63
+ }