elysia-lambda-handler 0.1.0
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.
- package/README.md +91 -0
- package/dist/index.cjs +90 -0
- package/dist/index.d.cts +74 -0
- package/dist/index.d.mts +74 -0
- package/dist/index.mjs +87 -0
- package/package.json +57 -0
package/README.md
ADDED
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# elysia-lambda-handler
|
|
2
|
+
|
|
3
|
+
Run [Elysia](https://elysiajs.com/) apps on AWS Lambda with the **Node.js runtime**.
|
|
4
|
+
|
|
5
|
+
This handler converts an API Gateway REST API (payload v1) proxy event into a Web
|
|
6
|
+
standard `Request`, passes it to `app.handle()`, and converts the returned
|
|
7
|
+
`Response` back into the Lambda proxy result format. No HTTP server is started
|
|
8
|
+
and no Bun-specific APIs are used — only the Web APIs built into Node.js 18+.
|
|
9
|
+
|
|
10
|
+
- Zero runtime dependencies (`elysia` is a peer dependency)
|
|
11
|
+
- Works with `NodejsFunction` / esbuild bundling out of the box
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```sh
|
|
16
|
+
npm install elysia-lambda-handler
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Usage
|
|
20
|
+
|
|
21
|
+
Keep your Elysia app runtime-agnostic:
|
|
22
|
+
|
|
23
|
+
```ts
|
|
24
|
+
// app.ts
|
|
25
|
+
import { Elysia } from "elysia";
|
|
26
|
+
|
|
27
|
+
export const app = new Elysia().get("/", () => ({ hello: "lambda" }));
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Then wrap it once at module scope in your Lambda entry:
|
|
31
|
+
|
|
32
|
+
```ts
|
|
33
|
+
// lambda.ts
|
|
34
|
+
import { handle } from "elysia-lambda-handler";
|
|
35
|
+
import { app } from "./app.js";
|
|
36
|
+
|
|
37
|
+
export const handler = handle(app);
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Deploy `lambda.ts` behind an API Gateway REST API with Lambda proxy
|
|
41
|
+
integration (for example CDK's `LambdaRestApi`).
|
|
42
|
+
|
|
43
|
+
## Supported event types
|
|
44
|
+
|
|
45
|
+
| Event source | Status |
|
|
46
|
+
| --- | --- |
|
|
47
|
+
| API Gateway REST API (payload v1), proxy integration | ✅ Supported |
|
|
48
|
+
| API Gateway HTTP API (payload v2) | Planned |
|
|
49
|
+
| Lambda Function URL | Planned |
|
|
50
|
+
|
|
51
|
+
## Binary responses
|
|
52
|
+
|
|
53
|
+
When the `Response` has a non-text `content-type` (anything other than
|
|
54
|
+
`text/*`, `application/json`, `+json` / `+xml` suffixes, or a type with an
|
|
55
|
+
explicit `charset`), the body is returned base64-encoded with
|
|
56
|
+
`isBase64Encoded: true`. Note that a REST API only decodes it back to bytes
|
|
57
|
+
when the API's `binaryMediaTypes` matches the request — configure it (for
|
|
58
|
+
example `*/*`) if you serve images or other binary content.
|
|
59
|
+
|
|
60
|
+
Multiple `Set-Cookie` headers are returned via `multiValueHeaders`, which the
|
|
61
|
+
REST API supports natively.
|
|
62
|
+
|
|
63
|
+
## Cold starts
|
|
64
|
+
|
|
65
|
+
On Lambda, cold-start time usually dominates. Two tips:
|
|
66
|
+
|
|
67
|
+
- Call `handle(app)` at module scope (as in the example above) so the app and
|
|
68
|
+
its route compilation are initialized once per execution environment, not per
|
|
69
|
+
invocation.
|
|
70
|
+
- Elysia's ahead-of-time route compilation (`aot`, enabled by default) makes
|
|
71
|
+
the *first* request in each execution environment more expensive when the app
|
|
72
|
+
has many routes. If cold-start latency matters more than steady-state
|
|
73
|
+
throughput — the common case for Lambda — try `new Elysia({ aot: false })`
|
|
74
|
+
and measure both variants for your workload.
|
|
75
|
+
|
|
76
|
+
## API
|
|
77
|
+
|
|
78
|
+
### `handle(app)`
|
|
79
|
+
|
|
80
|
+
Takes anything with a fetch-style `handle(request: Request)` method (an Elysia
|
|
81
|
+
instance) and returns an async Lambda handler
|
|
82
|
+
`(event, context?) => Promise<APIGatewayProxyResult>`.
|
|
83
|
+
|
|
84
|
+
The lower-level conversion helpers `eventToRequest(event)` and
|
|
85
|
+
`responseToResult(response)` are also exported, along with the structural
|
|
86
|
+
types `APIGatewayProxyEvent` / `APIGatewayProxyResult` (compatible with
|
|
87
|
+
`@types/aws-lambda`, which is not required at runtime or compile time).
|
|
88
|
+
|
|
89
|
+
## License
|
|
90
|
+
|
|
91
|
+
MIT
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
//#region src/request.ts
|
|
3
|
+
const findHeader = (event, name) => {
|
|
4
|
+
for (const [key, value] of Object.entries(event.headers ?? {})) if (key.toLowerCase() === name && value !== void 0) return value;
|
|
5
|
+
for (const [key, values] of Object.entries(event.multiValueHeaders ?? {})) if (key.toLowerCase() === name && values?.length) return values[0];
|
|
6
|
+
};
|
|
7
|
+
const buildSearch = (event) => {
|
|
8
|
+
const params = new URLSearchParams();
|
|
9
|
+
if (event.multiValueQueryStringParameters) for (const [key, values] of Object.entries(event.multiValueQueryStringParameters)) for (const value of values ?? []) params.append(key, value);
|
|
10
|
+
else if (event.queryStringParameters) {
|
|
11
|
+
for (const [key, value] of Object.entries(event.queryStringParameters)) if (value !== void 0) params.append(key, value);
|
|
12
|
+
}
|
|
13
|
+
const search = params.toString();
|
|
14
|
+
return search ? `?${search}` : "";
|
|
15
|
+
};
|
|
16
|
+
const buildHeaders = (event) => {
|
|
17
|
+
const headers = new Headers();
|
|
18
|
+
if (event.multiValueHeaders) for (const [key, values] of Object.entries(event.multiValueHeaders)) for (const value of values ?? []) headers.append(key, value);
|
|
19
|
+
else if (event.headers) {
|
|
20
|
+
for (const [key, value] of Object.entries(event.headers)) if (value !== void 0) headers.append(key, value);
|
|
21
|
+
}
|
|
22
|
+
return headers;
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Convert an API Gateway REST API (payload v1) proxy event into a Web
|
|
26
|
+
* standard `Request` that can be passed to `app.handle()`.
|
|
27
|
+
*/
|
|
28
|
+
const eventToRequest = (event) => {
|
|
29
|
+
const host = findHeader(event, "host") ?? event.requestContext?.domainName ?? "localhost";
|
|
30
|
+
const method = event.httpMethod.toUpperCase();
|
|
31
|
+
const url = `https://${host}${event.path}${buildSearch(event)}`;
|
|
32
|
+
let body;
|
|
33
|
+
if (event.body !== null && method !== "GET" && method !== "HEAD") body = Buffer.from(event.body, event.isBase64Encoded ? "base64" : "utf8");
|
|
34
|
+
return new Request(url, {
|
|
35
|
+
method,
|
|
36
|
+
headers: buildHeaders(event),
|
|
37
|
+
body
|
|
38
|
+
});
|
|
39
|
+
};
|
|
40
|
+
//#endregion
|
|
41
|
+
//#region src/response.ts
|
|
42
|
+
const TEXT_TYPE_PATTERN = /^text\/|^application\/(json|javascript|xml|x-www-form-urlencoded)\b|[+](json|xml)\b|charset=/i;
|
|
43
|
+
const isTextContentType = (contentType) => contentType === null || TEXT_TYPE_PATTERN.test(contentType);
|
|
44
|
+
/**
|
|
45
|
+
* Convert a Web standard `Response` returned by `app.handle()` into an API
|
|
46
|
+
* Gateway REST API (payload v1) proxy result. Text bodies are passed through
|
|
47
|
+
* as UTF-8; anything else is base64-encoded with `isBase64Encoded: true`
|
|
48
|
+
* (the REST API additionally requires matching `binaryMediaTypes` to decode
|
|
49
|
+
* it on the way out).
|
|
50
|
+
*/
|
|
51
|
+
const responseToResult = async (response) => {
|
|
52
|
+
const multiValueHeaders = {};
|
|
53
|
+
for (const [key, value] of response.headers) {
|
|
54
|
+
if (key === "set-cookie") continue;
|
|
55
|
+
multiValueHeaders[key] = [value];
|
|
56
|
+
}
|
|
57
|
+
const setCookie = response.headers.getSetCookie();
|
|
58
|
+
if (setCookie.length > 0) multiValueHeaders["set-cookie"] = setCookie;
|
|
59
|
+
const buffer = Buffer.from(await response.arrayBuffer());
|
|
60
|
+
const isText = isTextContentType(response.headers.get("content-type"));
|
|
61
|
+
return {
|
|
62
|
+
statusCode: response.status,
|
|
63
|
+
multiValueHeaders,
|
|
64
|
+
body: buffer.toString(isText ? "utf8" : "base64"),
|
|
65
|
+
isBase64Encoded: !isText
|
|
66
|
+
};
|
|
67
|
+
};
|
|
68
|
+
//#endregion
|
|
69
|
+
//#region src/index.ts
|
|
70
|
+
/**
|
|
71
|
+
* Wrap an Elysia app as an AWS Lambda handler for API Gateway REST API
|
|
72
|
+
* (payload v1) proxy integration events.
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```ts
|
|
76
|
+
* import { handle } from "elysia-lambda-handler";
|
|
77
|
+
* import { app } from "./app.js";
|
|
78
|
+
*
|
|
79
|
+
* export const handler = handle(app);
|
|
80
|
+
* ```
|
|
81
|
+
*/
|
|
82
|
+
const handle = (app) => {
|
|
83
|
+
return async (event) => {
|
|
84
|
+
return responseToResult(await app.handle(eventToRequest(event)));
|
|
85
|
+
};
|
|
86
|
+
};
|
|
87
|
+
//#endregion
|
|
88
|
+
exports.eventToRequest = eventToRequest;
|
|
89
|
+
exports.handle = handle;
|
|
90
|
+
exports.responseToResult = responseToResult;
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
//#region src/types.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Structurally-compatible subset of the API Gateway REST API (payload v1)
|
|
4
|
+
* proxy event. Kept local so this package has no runtime or type
|
|
5
|
+
* dependencies — an `APIGatewayProxyEvent` from `@types/aws-lambda` is
|
|
6
|
+
* assignable to this type.
|
|
7
|
+
*/
|
|
8
|
+
interface APIGatewayProxyEvent {
|
|
9
|
+
httpMethod: string;
|
|
10
|
+
path: string;
|
|
11
|
+
headers: Record<string, string | undefined> | null;
|
|
12
|
+
multiValueHeaders: Record<string, string[] | undefined> | null;
|
|
13
|
+
queryStringParameters: Record<string, string | undefined> | null;
|
|
14
|
+
multiValueQueryStringParameters: Record<string, string[] | undefined> | null;
|
|
15
|
+
body: string | null;
|
|
16
|
+
isBase64Encoded: boolean;
|
|
17
|
+
requestContext: {
|
|
18
|
+
domainName?: string;
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* API Gateway REST API (payload v1) proxy result. Structurally compatible
|
|
23
|
+
* with `APIGatewayProxyResult` from `@types/aws-lambda`.
|
|
24
|
+
*/
|
|
25
|
+
interface APIGatewayProxyResult {
|
|
26
|
+
statusCode: number;
|
|
27
|
+
multiValueHeaders: Record<string, string[]>;
|
|
28
|
+
body: string;
|
|
29
|
+
isBase64Encoded: boolean;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* The subset of an Elysia instance the handler relies on. Any object with a
|
|
33
|
+
* fetch-style `handle` method works, which keeps `elysia` a peer dependency
|
|
34
|
+
* used only at the type level by consumers.
|
|
35
|
+
*/
|
|
36
|
+
interface HandleTarget {
|
|
37
|
+
handle: (request: Request) => Response | Promise<Response>;
|
|
38
|
+
}
|
|
39
|
+
/** Lambda handler signature returned by {@link handle}. */
|
|
40
|
+
type LambdaHandler = (event: APIGatewayProxyEvent, context?: unknown) => Promise<APIGatewayProxyResult>;
|
|
41
|
+
//#endregion
|
|
42
|
+
//#region src/request.d.ts
|
|
43
|
+
/**
|
|
44
|
+
* Convert an API Gateway REST API (payload v1) proxy event into a Web
|
|
45
|
+
* standard `Request` that can be passed to `app.handle()`.
|
|
46
|
+
*/
|
|
47
|
+
declare const eventToRequest: (event: APIGatewayProxyEvent) => Request;
|
|
48
|
+
//#endregion
|
|
49
|
+
//#region src/response.d.ts
|
|
50
|
+
/**
|
|
51
|
+
* Convert a Web standard `Response` returned by `app.handle()` into an API
|
|
52
|
+
* Gateway REST API (payload v1) proxy result. Text bodies are passed through
|
|
53
|
+
* as UTF-8; anything else is base64-encoded with `isBase64Encoded: true`
|
|
54
|
+
* (the REST API additionally requires matching `binaryMediaTypes` to decode
|
|
55
|
+
* it on the way out).
|
|
56
|
+
*/
|
|
57
|
+
declare const responseToResult: (response: Response) => Promise<APIGatewayProxyResult>;
|
|
58
|
+
//#endregion
|
|
59
|
+
//#region src/index.d.ts
|
|
60
|
+
/**
|
|
61
|
+
* Wrap an Elysia app as an AWS Lambda handler for API Gateway REST API
|
|
62
|
+
* (payload v1) proxy integration events.
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* ```ts
|
|
66
|
+
* import { handle } from "elysia-lambda-handler";
|
|
67
|
+
* import { app } from "./app.js";
|
|
68
|
+
*
|
|
69
|
+
* export const handler = handle(app);
|
|
70
|
+
* ```
|
|
71
|
+
*/
|
|
72
|
+
declare const handle: (app: HandleTarget) => LambdaHandler;
|
|
73
|
+
//#endregion
|
|
74
|
+
export { type APIGatewayProxyEvent, type APIGatewayProxyResult, type HandleTarget, type LambdaHandler, eventToRequest, handle, responseToResult };
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
//#region src/types.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Structurally-compatible subset of the API Gateway REST API (payload v1)
|
|
4
|
+
* proxy event. Kept local so this package has no runtime or type
|
|
5
|
+
* dependencies — an `APIGatewayProxyEvent` from `@types/aws-lambda` is
|
|
6
|
+
* assignable to this type.
|
|
7
|
+
*/
|
|
8
|
+
interface APIGatewayProxyEvent {
|
|
9
|
+
httpMethod: string;
|
|
10
|
+
path: string;
|
|
11
|
+
headers: Record<string, string | undefined> | null;
|
|
12
|
+
multiValueHeaders: Record<string, string[] | undefined> | null;
|
|
13
|
+
queryStringParameters: Record<string, string | undefined> | null;
|
|
14
|
+
multiValueQueryStringParameters: Record<string, string[] | undefined> | null;
|
|
15
|
+
body: string | null;
|
|
16
|
+
isBase64Encoded: boolean;
|
|
17
|
+
requestContext: {
|
|
18
|
+
domainName?: string;
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* API Gateway REST API (payload v1) proxy result. Structurally compatible
|
|
23
|
+
* with `APIGatewayProxyResult` from `@types/aws-lambda`.
|
|
24
|
+
*/
|
|
25
|
+
interface APIGatewayProxyResult {
|
|
26
|
+
statusCode: number;
|
|
27
|
+
multiValueHeaders: Record<string, string[]>;
|
|
28
|
+
body: string;
|
|
29
|
+
isBase64Encoded: boolean;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* The subset of an Elysia instance the handler relies on. Any object with a
|
|
33
|
+
* fetch-style `handle` method works, which keeps `elysia` a peer dependency
|
|
34
|
+
* used only at the type level by consumers.
|
|
35
|
+
*/
|
|
36
|
+
interface HandleTarget {
|
|
37
|
+
handle: (request: Request) => Response | Promise<Response>;
|
|
38
|
+
}
|
|
39
|
+
/** Lambda handler signature returned by {@link handle}. */
|
|
40
|
+
type LambdaHandler = (event: APIGatewayProxyEvent, context?: unknown) => Promise<APIGatewayProxyResult>;
|
|
41
|
+
//#endregion
|
|
42
|
+
//#region src/request.d.ts
|
|
43
|
+
/**
|
|
44
|
+
* Convert an API Gateway REST API (payload v1) proxy event into a Web
|
|
45
|
+
* standard `Request` that can be passed to `app.handle()`.
|
|
46
|
+
*/
|
|
47
|
+
declare const eventToRequest: (event: APIGatewayProxyEvent) => Request;
|
|
48
|
+
//#endregion
|
|
49
|
+
//#region src/response.d.ts
|
|
50
|
+
/**
|
|
51
|
+
* Convert a Web standard `Response` returned by `app.handle()` into an API
|
|
52
|
+
* Gateway REST API (payload v1) proxy result. Text bodies are passed through
|
|
53
|
+
* as UTF-8; anything else is base64-encoded with `isBase64Encoded: true`
|
|
54
|
+
* (the REST API additionally requires matching `binaryMediaTypes` to decode
|
|
55
|
+
* it on the way out).
|
|
56
|
+
*/
|
|
57
|
+
declare const responseToResult: (response: Response) => Promise<APIGatewayProxyResult>;
|
|
58
|
+
//#endregion
|
|
59
|
+
//#region src/index.d.ts
|
|
60
|
+
/**
|
|
61
|
+
* Wrap an Elysia app as an AWS Lambda handler for API Gateway REST API
|
|
62
|
+
* (payload v1) proxy integration events.
|
|
63
|
+
*
|
|
64
|
+
* @example
|
|
65
|
+
* ```ts
|
|
66
|
+
* import { handle } from "elysia-lambda-handler";
|
|
67
|
+
* import { app } from "./app.js";
|
|
68
|
+
*
|
|
69
|
+
* export const handler = handle(app);
|
|
70
|
+
* ```
|
|
71
|
+
*/
|
|
72
|
+
declare const handle: (app: HandleTarget) => LambdaHandler;
|
|
73
|
+
//#endregion
|
|
74
|
+
export { type APIGatewayProxyEvent, type APIGatewayProxyResult, type HandleTarget, type LambdaHandler, eventToRequest, handle, responseToResult };
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
//#region src/request.ts
|
|
2
|
+
const findHeader = (event, name) => {
|
|
3
|
+
for (const [key, value] of Object.entries(event.headers ?? {})) if (key.toLowerCase() === name && value !== void 0) return value;
|
|
4
|
+
for (const [key, values] of Object.entries(event.multiValueHeaders ?? {})) if (key.toLowerCase() === name && values?.length) return values[0];
|
|
5
|
+
};
|
|
6
|
+
const buildSearch = (event) => {
|
|
7
|
+
const params = new URLSearchParams();
|
|
8
|
+
if (event.multiValueQueryStringParameters) for (const [key, values] of Object.entries(event.multiValueQueryStringParameters)) for (const value of values ?? []) params.append(key, value);
|
|
9
|
+
else if (event.queryStringParameters) {
|
|
10
|
+
for (const [key, value] of Object.entries(event.queryStringParameters)) if (value !== void 0) params.append(key, value);
|
|
11
|
+
}
|
|
12
|
+
const search = params.toString();
|
|
13
|
+
return search ? `?${search}` : "";
|
|
14
|
+
};
|
|
15
|
+
const buildHeaders = (event) => {
|
|
16
|
+
const headers = new Headers();
|
|
17
|
+
if (event.multiValueHeaders) for (const [key, values] of Object.entries(event.multiValueHeaders)) for (const value of values ?? []) headers.append(key, value);
|
|
18
|
+
else if (event.headers) {
|
|
19
|
+
for (const [key, value] of Object.entries(event.headers)) if (value !== void 0) headers.append(key, value);
|
|
20
|
+
}
|
|
21
|
+
return headers;
|
|
22
|
+
};
|
|
23
|
+
/**
|
|
24
|
+
* Convert an API Gateway REST API (payload v1) proxy event into a Web
|
|
25
|
+
* standard `Request` that can be passed to `app.handle()`.
|
|
26
|
+
*/
|
|
27
|
+
const eventToRequest = (event) => {
|
|
28
|
+
const host = findHeader(event, "host") ?? event.requestContext?.domainName ?? "localhost";
|
|
29
|
+
const method = event.httpMethod.toUpperCase();
|
|
30
|
+
const url = `https://${host}${event.path}${buildSearch(event)}`;
|
|
31
|
+
let body;
|
|
32
|
+
if (event.body !== null && method !== "GET" && method !== "HEAD") body = Buffer.from(event.body, event.isBase64Encoded ? "base64" : "utf8");
|
|
33
|
+
return new Request(url, {
|
|
34
|
+
method,
|
|
35
|
+
headers: buildHeaders(event),
|
|
36
|
+
body
|
|
37
|
+
});
|
|
38
|
+
};
|
|
39
|
+
//#endregion
|
|
40
|
+
//#region src/response.ts
|
|
41
|
+
const TEXT_TYPE_PATTERN = /^text\/|^application\/(json|javascript|xml|x-www-form-urlencoded)\b|[+](json|xml)\b|charset=/i;
|
|
42
|
+
const isTextContentType = (contentType) => contentType === null || TEXT_TYPE_PATTERN.test(contentType);
|
|
43
|
+
/**
|
|
44
|
+
* Convert a Web standard `Response` returned by `app.handle()` into an API
|
|
45
|
+
* Gateway REST API (payload v1) proxy result. Text bodies are passed through
|
|
46
|
+
* as UTF-8; anything else is base64-encoded with `isBase64Encoded: true`
|
|
47
|
+
* (the REST API additionally requires matching `binaryMediaTypes` to decode
|
|
48
|
+
* it on the way out).
|
|
49
|
+
*/
|
|
50
|
+
const responseToResult = async (response) => {
|
|
51
|
+
const multiValueHeaders = {};
|
|
52
|
+
for (const [key, value] of response.headers) {
|
|
53
|
+
if (key === "set-cookie") continue;
|
|
54
|
+
multiValueHeaders[key] = [value];
|
|
55
|
+
}
|
|
56
|
+
const setCookie = response.headers.getSetCookie();
|
|
57
|
+
if (setCookie.length > 0) multiValueHeaders["set-cookie"] = setCookie;
|
|
58
|
+
const buffer = Buffer.from(await response.arrayBuffer());
|
|
59
|
+
const isText = isTextContentType(response.headers.get("content-type"));
|
|
60
|
+
return {
|
|
61
|
+
statusCode: response.status,
|
|
62
|
+
multiValueHeaders,
|
|
63
|
+
body: buffer.toString(isText ? "utf8" : "base64"),
|
|
64
|
+
isBase64Encoded: !isText
|
|
65
|
+
};
|
|
66
|
+
};
|
|
67
|
+
//#endregion
|
|
68
|
+
//#region src/index.ts
|
|
69
|
+
/**
|
|
70
|
+
* Wrap an Elysia app as an AWS Lambda handler for API Gateway REST API
|
|
71
|
+
* (payload v1) proxy integration events.
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* ```ts
|
|
75
|
+
* import { handle } from "elysia-lambda-handler";
|
|
76
|
+
* import { app } from "./app.js";
|
|
77
|
+
*
|
|
78
|
+
* export const handler = handle(app);
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
const handle = (app) => {
|
|
82
|
+
return async (event) => {
|
|
83
|
+
return responseToResult(await app.handle(eventToRequest(event)));
|
|
84
|
+
};
|
|
85
|
+
};
|
|
86
|
+
//#endregion
|
|
87
|
+
export { eventToRequest, handle, responseToResult };
|
package/package.json
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "elysia-lambda-handler",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Run Elysia apps on AWS Lambda with the Node.js runtime (API Gateway REST API events)",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/datakahashi/elysia-lambda-handler.git"
|
|
9
|
+
},
|
|
10
|
+
"homepage": "https://github.com/datakahashi/elysia-lambda-handler#readme",
|
|
11
|
+
"bugs": {
|
|
12
|
+
"url": "https://github.com/datakahashi/elysia-lambda-handler/issues"
|
|
13
|
+
},
|
|
14
|
+
"type": "module",
|
|
15
|
+
"main": "./dist/index.cjs",
|
|
16
|
+
"module": "./dist/index.mjs",
|
|
17
|
+
"types": "./dist/index.d.cts",
|
|
18
|
+
"exports": {
|
|
19
|
+
".": {
|
|
20
|
+
"import": {
|
|
21
|
+
"types": "./dist/index.d.mts",
|
|
22
|
+
"default": "./dist/index.mjs"
|
|
23
|
+
},
|
|
24
|
+
"require": {
|
|
25
|
+
"types": "./dist/index.d.cts",
|
|
26
|
+
"default": "./dist/index.cjs"
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
},
|
|
30
|
+
"files": [
|
|
31
|
+
"dist"
|
|
32
|
+
],
|
|
33
|
+
"keywords": [
|
|
34
|
+
"elysia",
|
|
35
|
+
"aws",
|
|
36
|
+
"lambda",
|
|
37
|
+
"api-gateway",
|
|
38
|
+
"handler",
|
|
39
|
+
"serverless"
|
|
40
|
+
],
|
|
41
|
+
"scripts": {
|
|
42
|
+
"build": "tsdown",
|
|
43
|
+
"test": "vitest run",
|
|
44
|
+
"typecheck": "tsc --noEmit"
|
|
45
|
+
},
|
|
46
|
+
"peerDependencies": {
|
|
47
|
+
"elysia": "^1.0.0"
|
|
48
|
+
},
|
|
49
|
+
"devDependencies": {
|
|
50
|
+
"@types/aws-lambda": "^8.10.162",
|
|
51
|
+
"@types/node": "^24.0.0",
|
|
52
|
+
"elysia": "1",
|
|
53
|
+
"tsdown": "^0.22.9",
|
|
54
|
+
"typescript": "5",
|
|
55
|
+
"vitest": "^4.1.10"
|
|
56
|
+
}
|
|
57
|
+
}
|