hono-adapter-aws-lambda 1.3.5 → 1.4.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/dist/index.d.mts CHANGED
@@ -1,42 +1,83 @@
1
- import { LambdaEvent, LambdaTriggerEvent } from '@namesmt/utils-lambda';
2
- export { LambdaEvent, LambdaRequestEvent, LambdaTriggerEvent } from '@namesmt/utils-lambda';
3
- import { Env, Schema, Hono } from 'hono';
4
- import { Handler, APIGatewayProxyResult, APIGatewayProxyStructuredResultV2 } from 'aws-lambda';
5
- export { Context as LambdaContext } from 'aws-lambda';
6
- import * as hono_types from 'hono/types';
7
- import { H } from 'hono/types';
8
-
9
- type LambdaHandler<TEvent = any, TResult = any> = Handler<TEvent, TResult>;
10
- type LambdaHandlerResult = APIGatewayProxyResult | APIGatewayProxyStructuredResultV2;
11
-
1
+ import { Env, Hono, Schema } from "hono";
2
+ import { LambdaEvent, LambdaRequestEvent, LambdaTriggerEvent, LambdaTriggerEvent as LambdaTriggerEvent$1 } from "@namesmt/utils-lambda";
3
+ import { APIGatewayProxyResult, APIGatewayProxyStructuredResultV2, Context as LambdaContext, Handler } from "aws-lambda";
4
+ import { H } from "hono/types";
5
+ //#region src/types.d.ts
6
+ export type LambdaHandler<TEvent = any, TResult = any> = Handler<TEvent, TResult>;
7
+ export type LambdaHandlerResult = APIGatewayProxyResult | APIGatewayProxyStructuredResultV2;
8
+ /**
9
+ * Amazon VPC Lattice v2 event.
10
+ * Not yet available in `@types/aws-lambda`, so defined locally.
11
+ */
12
+ export interface LatticeRequestContextV2 {
13
+ serviceNetworkArn: string;
14
+ serviceArn: string;
15
+ targetGroupArn: string;
16
+ region: string;
17
+ timeEpoch: string;
18
+ identity: {
19
+ sourceVpcArn?: string;
20
+ type?: string;
21
+ principal?: string;
22
+ principalOrgID?: string;
23
+ sessionName?: string;
24
+ x509IssuerOu?: string;
25
+ x509SanDns?: string;
26
+ x509SanNameCn?: string;
27
+ x509SanUri?: string;
28
+ x509SubjectCn?: string;
29
+ };
30
+ }
31
+ export interface LatticeProxyEventV2 {
32
+ version: string;
33
+ path: string;
34
+ method: string;
35
+ headers: Record<string, string[] | undefined>;
36
+ queryStringParameters: Record<string, string[] | undefined>;
37
+ body: string | null;
38
+ isBase64Encoded: boolean;
39
+ requestContext: LatticeRequestContextV2;
40
+ }
41
+ /**
42
+ * All events the adapter handles: request, trigger, and VPC Lattice.
43
+ */
44
+ export type AdapterEvent = LambdaEvent | LatticeProxyEventV2;
45
+ //#endregion
46
+ //#region src/handler.d.ts
12
47
  interface HandleConfigOptions {
13
- /**
14
- * This allows you to easier invoke HTTP routes manually by parsing `event.routeKey` for method and path.
15
- */
16
- easyRouteKey?: boolean;
48
+ /**
49
+ * This allows you to easier invoke HTTP routes manually by parsing `event.routeKey` for method and path.
50
+ */
51
+ easyRouteKey?: boolean;
52
+ /**
53
+ * Overrides the default binary content-type detection.
54
+ * Defaults to `defaultIsContentTypeBinary`.
55
+ */
56
+ isContentTypeBinary?: (contentType: string) => boolean;
17
57
  }
18
- declare function streamHandle<E extends Env = Env, S extends Schema = {}, BasePath extends string = '/'>(app: Hono<E, S, BasePath>, handleConfig?: HandleConfigOptions): LambdaHandler<LambdaEvent>;
58
+ export declare function streamHandle<E extends Env = Env, S extends Schema = {}, BasePath extends string = '/'>(app: Hono<E, S, BasePath>, handleConfig?: HandleConfigOptions): LambdaHandler<AdapterEvent>;
19
59
  /**
20
60
  * Accepts events from API Gateway/ELB(`APIGatewayProxyEvent`) and directly through Function Url(`APIGatewayProxyEventV2`)
21
61
  */
22
- declare function handle<E extends Env = Env, S extends Schema = {}, BasePath extends string = '/'>(app: Hono<E, S, BasePath>, handleConfig?: HandleConfigOptions): LambdaHandler<LambdaEvent, LambdaHandlerResult>;
23
-
24
- declare class TriggerFactory<IE extends Env, HE extends Env> {
25
- private simpleRouter;
26
- honoApp: Hono<HE>;
27
- internalApp: Hono<IE, hono_types.BlankSchema, "/">;
28
- constructor(app: Hono<HE>);
29
- on: (eventSource: string, id: string, ...handlers: H<IE>[]) => this;
62
+ export declare function handle<E extends Env = Env, S extends Schema = {}, BasePath extends string = '/'>(app: Hono<E, S, BasePath>, handleConfig?: HandleConfigOptions): LambdaHandler<AdapterEvent, LambdaHandlerResult>;
63
+ //#endregion
64
+ //#region src/trigger.d.ts
65
+ export declare class TriggerFactory<IE extends Env, HE extends Env> {
66
+ private simpleRouter;
67
+ honoApp: Hono<HE>;
68
+ internalApp: Hono<IE, import("hono/types").BlankSchema, "/">;
69
+ constructor(app: Hono<HE>);
70
+ on: (eventSource: string, id: string, ...handlers: H<IE>[]) => this;
30
71
  }
31
72
  type ExtractHonoEnv<A extends Hono> = A extends Hono<infer E> ? E : never;
32
- declare function createTriggerFactory<E extends Env, A extends Hono<any, any, '/'>>(app: A): TriggerFactory<E extends unknown ? {
33
- Bindings: {
34
- event: LambdaTriggerEvent;
35
- };
36
- Variables: Record<string, unknown>;
73
+ export declare function createTriggerFactory<E extends Env, A extends Hono<any, any, '/'>>(app: A): TriggerFactory<E extends unknown ? {
74
+ Bindings: {
75
+ event: LambdaTriggerEvent$1;
76
+ };
77
+ Variables: Record<string, unknown>;
37
78
  } : E, ExtractHonoEnv<A>>;
38
- declare const triggerPathUUID: string;
39
- declare function getTriggerPath(path: string): string;
40
-
41
- export { TriggerFactory, createTriggerFactory, getTriggerPath, handle, streamHandle, triggerPathUUID };
42
- export type { LambdaHandler, LambdaHandlerResult };
79
+ export declare const triggerPathUUID: string;
80
+ export declare function getTriggerPath(path: string): string;
81
+ //#endregion
82
+ export type { LambdaContext, LambdaEvent, LambdaRequestEvent, LambdaTriggerEvent };
83
+ //# sourceMappingURL=index.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/types.ts","../src/handler.ts","../src/trigger.ts"],"mappings":";;;;;YAMY,cAAc,cAAc,iBAAiB,QAAQ,QAAQ;YAC7D,sBAAsB,wBAAwB;;;;;iBAMzC;EACf;EACA;EACA;EACA;EACA;EACA;IACE;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;;;iBAIa;EACf;EACA;EACA;EACA,SAAS;EACT,uBAAuB;EACvB;EACA;EACA,gBAAgB;;;;;YAMN,eAAe,cAAc;;;UCGxB;;;;EAIf;;;;;EAKA,uBAAuB;;wBAGT,aACd,UAAU,MAAM,KAChB,UAAU,aACV,+BACA,KAAK,KAAK,GAAG,GAAG,WAAW,eAAe,sBAAsB,cAAc;;;;wBAmDhE,OAAO,UAAU,MAAM,KAAK,UAAU,aAAa,+BAA+B,KAAK,KAAK,GAAG,GAAG,WAAW,eAAe,sBAAsB,cAAc,cAAc;;;qBCvGjL,eAAe,WAAW,KAAK,WAAW;UAC7C;EAER,SAAS,KAAK;EACd,aAAW,KAAA,yBAAA;EAEC,YAAA,KAAK,KAAK;EAItB,KAAM,qBAAqB,eAAe,UAAU,EAAE;;KAyCnD,eAAe,UAAU,QAAQ,UAAU,WAAW,KAAK;wBAEhD,qBAAqB,UAAU,KAAK,UAAU,qBAAqB,KAAK,IAAC,eAAA;EAGvE;IAAE,OAAO;;EACR,WAAA;IAGlB,GAAA,eAAA;qBAoCY;wBAEG,eAAe"}
package/dist/index.mjs CHANGED
@@ -1,412 +1,404 @@
1
- import { Readable } from 'stream';
2
- import { pipeline } from 'stream/promises';
3
- import { decodeBase64, encodeBase64 } from 'hono/utils/encode';
4
- import { Hono } from 'hono';
5
- import { mergePath } from 'hono/utils/url';
6
-
7
- class RequestEventProcessor {
8
- createRequest(event) {
9
- const queryString = this.getQueryString(event);
10
- const domainName = event.requestContext && "domainName" in event.requestContext ? event.requestContext.domainName : event.headers?.host ?? event.multiValueHeaders?.host?.[0];
11
- const path = this.getPath(event);
12
- const urlPath = `https://${domainName}${path}`;
13
- const url = queryString ? `${urlPath}?${queryString}` : urlPath;
14
- const headers = this.getHeaders(event);
15
- const method = this.getMethod(event);
16
- const requestInit = {
17
- headers,
18
- method
19
- };
20
- if (event.body) {
21
- requestInit.body = event.isBase64Encoded ? decodeBase64(event.body) : event.body;
22
- }
23
- return new Request(url, requestInit);
24
- }
25
- async createResult(event, res) {
26
- const contentType = res.headers.get("content-type");
27
- let isBase64Encoded = !!(contentType && isContentTypeBinary(contentType));
28
- if (!isBase64Encoded) {
29
- const contentEncoding = res.headers.get("content-encoding");
30
- isBase64Encoded = isContentEncodingBinary(contentEncoding);
31
- }
32
- const body = isBase64Encoded ? encodeBase64(await res.arrayBuffer()) : await res.text();
33
- const result = {
34
- body,
35
- headers: {},
36
- multiValueHeaders: void 0,
37
- statusCode: res.status,
38
- isBase64Encoded
39
- };
40
- if ("multiValueHeaders" in event) {
41
- result.multiValueHeaders = {};
42
- }
43
- this.setCookies(event, res, result);
44
- res.headers.forEach((value, key) => {
45
- result.headers[key] = value;
46
- if ("multiValueHeaders" in event) {
47
- result.multiValueHeaders[key] = [value];
48
- }
49
- });
50
- return result;
51
- }
52
- setCookies(event, res, result) {
53
- if (res.headers.has("set-cookie")) {
54
- const cookies = res.headers.getSetCookie ? res.headers.getSetCookie() : Array.from(res.headers.entries()).filter(([k]) => k === "set-cookie").map(([, v]) => v);
55
- if (Array.isArray(cookies)) {
56
- this.setCookiesToResult(event, result, cookies);
57
- res.headers.delete("set-cookie");
58
- }
59
- }
60
- }
61
- }
62
- class EventV2Processor extends RequestEventProcessor {
63
- getPath(event) {
64
- return event.rawPath;
65
- }
66
- getMethod(event) {
67
- return event.requestContext.http.method;
68
- }
69
- getQueryString(event) {
70
- return event.rawQueryString;
71
- }
72
- getCookies(event, headers) {
73
- if (Array.isArray(event.cookies)) {
74
- headers.set("Cookie", event.cookies.join("; "));
75
- }
76
- }
77
- setCookiesToResult(_, result, cookies) {
78
- result.cookies = cookies;
79
- }
80
- getHeaders(event) {
81
- const headers = new Headers();
82
- this.getCookies(event, headers);
83
- if (event.headers) {
84
- for (const [k, v] of Object.entries(event.headers)) {
85
- if (v) {
86
- headers.set(k, v);
87
- }
88
- }
89
- }
90
- return headers;
91
- }
1
+ import { Readable } from "stream";
2
+ import { pipeline } from "stream/promises";
3
+ import { decodeBase64, encodeBase64 } from "hono/utils/encode";
4
+ import { Hono } from "hono";
5
+ import { mergePath } from "hono/utils/url";
6
+ //#region src/request.ts
7
+ const NON_ASCII_REGEX = /[^\x00-\x7F]/;
8
+ function sanitizeHeaderValue(value) {
9
+ if (!NON_ASCII_REGEX.test(value)) return value;
10
+ return encodeURIComponent(value);
92
11
  }
12
+ var RequestEventProcessor = class {
13
+ createRequest(event) {
14
+ const queryString = this.getQueryString(event);
15
+ const urlPath = `https://${event.requestContext && "domainName" in event.requestContext ? event.requestContext.domainName : event.headers?.host ?? event.multiValueHeaders?.host?.[0]}${this.getPath(event)}`;
16
+ const url = queryString ? `${urlPath}?${queryString}` : urlPath;
17
+ const headers = this.getHeaders(event);
18
+ const requestInit = {
19
+ headers,
20
+ method: this.getMethod(event)
21
+ };
22
+ if (event.body) {
23
+ const body = event.isBase64Encoded ? decodeBase64(event.body) : new TextEncoder().encode(event.body);
24
+ requestInit.body = body;
25
+ headers.set("content-length", body.length.toString());
26
+ }
27
+ return new Request(url, requestInit);
28
+ }
29
+ async createResult(event, res, options) {
30
+ const contentType = res.headers.get("content-type");
31
+ const isContentTypeBinaryFn = options?.isContentTypeBinary ?? defaultIsContentTypeBinary;
32
+ let isBase64Encoded = !!(contentType && isContentTypeBinaryFn(contentType));
33
+ if (!isBase64Encoded) isBase64Encoded = isContentEncodingBinary(res.headers.get("content-encoding"));
34
+ const result = {
35
+ body: isBase64Encoded ? encodeBase64(await res.arrayBuffer()) : await res.text(),
36
+ headers: {},
37
+ multiValueHeaders: void 0,
38
+ statusCode: res.status,
39
+ isBase64Encoded
40
+ };
41
+ if ("multiValueHeaders" in event) result.multiValueHeaders = {};
42
+ this.setCookies(event, res, result);
43
+ res.headers.forEach((value, key) => {
44
+ result.headers[key] = value;
45
+ if ("multiValueHeaders" in event) result.multiValueHeaders[key] = [value];
46
+ });
47
+ return result;
48
+ }
49
+ setCookies(event, res, result) {
50
+ if (res.headers.has("set-cookie")) {
51
+ const cookies = res.headers.getSetCookie ? res.headers.getSetCookie() : Array.from(res.headers.entries()).filter(([k]) => k === "set-cookie").map(([, v]) => v);
52
+ if (Array.isArray(cookies)) {
53
+ this.setCookiesToResult(event, result, cookies);
54
+ res.headers.delete("set-cookie");
55
+ }
56
+ }
57
+ }
58
+ };
59
+ var EventV2Processor = class extends RequestEventProcessor {
60
+ getPath(event) {
61
+ return event.rawPath;
62
+ }
63
+ getMethod(event) {
64
+ return event.requestContext.http.method;
65
+ }
66
+ getQueryString(event) {
67
+ return event.rawQueryString;
68
+ }
69
+ getCookies(event, headers) {
70
+ if (Array.isArray(event.cookies)) headers.set("Cookie", event.cookies.join("; "));
71
+ }
72
+ setCookiesToResult(_, result, cookies) {
73
+ result.cookies = cookies;
74
+ }
75
+ getHeaders(event) {
76
+ const headers = new Headers();
77
+ this.getCookies(event, headers);
78
+ if (event.headers) {
79
+ for (const [k, v] of Object.entries(event.headers)) if (v) headers.set(k, v);
80
+ }
81
+ return headers;
82
+ }
83
+ };
93
84
  const v2Processor = new EventV2Processor();
94
- class EventV1Processor extends RequestEventProcessor {
95
- getPath(event) {
96
- return event.path;
97
- }
98
- getMethod(event) {
99
- return event.httpMethod;
100
- }
101
- getQueryString(event) {
102
- return Object.entries(event.queryStringParameters || {}).filter(([, value]) => value).map(([key, value]) => `${key}=${value}`).join("&");
103
- }
104
- getCookies(event, headers) {
105
- }
106
- getHeaders(event) {
107
- const headers = new Headers();
108
- this.getCookies(event, headers);
109
- if (event.headers) {
110
- for (const [k, v] of Object.entries(event.headers)) {
111
- if (v) {
112
- headers.set(k, v);
113
- }
114
- }
115
- }
116
- if (event.multiValueHeaders) {
117
- for (const [k, values] of Object.entries(event.multiValueHeaders)) {
118
- if (values) {
119
- const foundK = headers.get(k);
120
- values.forEach((v) => (!foundK || !foundK.includes(v)) && headers.append(k, v));
121
- }
122
- }
123
- }
124
- return headers;
125
- }
126
- setCookiesToResult(_, result, cookies) {
127
- result.multiValueHeaders = {
128
- "set-cookie": cookies
129
- };
130
- }
131
- }
85
+ var EventV1Processor = class extends RequestEventProcessor {
86
+ getPath(event) {
87
+ return event.path;
88
+ }
89
+ getMethod(event) {
90
+ return event.httpMethod;
91
+ }
92
+ getQueryString(event) {
93
+ if (event.multiValueQueryStringParameters) return Object.entries(event.multiValueQueryStringParameters || {}).filter(([, value]) => value).map(([key, values]) => values.map((value) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`).join("&")).join("&");
94
+ else return Object.entries(event.queryStringParameters || {}).filter(([, value]) => value).map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value || "")}`).join("&");
95
+ }
96
+ getCookies(event, headers) {}
97
+ getHeaders(event) {
98
+ const headers = new Headers();
99
+ this.getCookies(event, headers);
100
+ if (event.multiValueHeaders) {
101
+ for (const [k, values] of Object.entries(event.multiValueHeaders)) if (values) values.forEach((v) => headers.append(k, sanitizeHeaderValue(v)));
102
+ }
103
+ if (event.headers) {
104
+ for (const [k, v] of Object.entries(event.headers)) if (v && !headers.has(k)) headers.set(k, sanitizeHeaderValue(v));
105
+ }
106
+ return headers;
107
+ }
108
+ setCookiesToResult(_, result, cookies) {
109
+ result.multiValueHeaders = { "set-cookie": cookies };
110
+ }
111
+ };
132
112
  const v1Processor = new EventV1Processor();
133
- class ALBProcessor extends RequestEventProcessor {
134
- getHeaders(event) {
135
- const headers = new Headers();
136
- if (event.multiValueHeaders) {
137
- for (const [key, values] of Object.entries(event.multiValueHeaders)) {
138
- if (values && Array.isArray(values)) {
139
- headers.set(key, values.join("; "));
140
- }
141
- }
142
- } else {
143
- for (const [key, value] of Object.entries(event.headers ?? {})) {
144
- if (value) {
145
- headers.set(key, value);
146
- }
147
- }
148
- }
149
- return headers;
150
- }
151
- getPath(event) {
152
- return event.path;
153
- }
154
- getMethod(event) {
155
- return event.httpMethod;
156
- }
157
- getQueryString(event) {
158
- if (event.multiValueQueryStringParameters) {
159
- return Object.entries(event.multiValueQueryStringParameters || {}).filter(([, value]) => value).map(([key, value]) => `${key}=${value?.join(`&${key}=`)}`).join("&");
160
- } else {
161
- return Object.entries(event.queryStringParameters || {}).filter(([, value]) => value).map(([key, value]) => `${key}=${value}`).join("&");
162
- }
163
- }
164
- getCookies(event, headers) {
165
- let cookie;
166
- if (event.multiValueHeaders) {
167
- cookie = event.multiValueHeaders.cookie?.join("; ");
168
- } else {
169
- cookie = event.headers ? event.headers.cookie : void 0;
170
- }
171
- if (cookie) {
172
- headers.append("Cookie", cookie);
173
- }
174
- }
175
- setCookiesToResult(event, result, cookies) {
176
- if (event.multiValueHeaders && result.multiValueHeaders) {
177
- result.multiValueHeaders["set-cookie"] = cookies;
178
- } else {
179
- result.headers["set-cookie"] = cookies.join(", ");
180
- }
181
- }
182
- }
113
+ var ALBProcessor = class extends RequestEventProcessor {
114
+ getHeaders(event) {
115
+ const headers = new Headers();
116
+ if (event.multiValueHeaders) {
117
+ for (const [key, values] of Object.entries(event.multiValueHeaders)) if (values && Array.isArray(values)) headers.set(key, sanitizeHeaderValue(values.join("; ")));
118
+ } else for (const [key, value] of Object.entries(event.headers ?? {})) if (value) headers.set(key, sanitizeHeaderValue(value));
119
+ return headers;
120
+ }
121
+ getPath(event) {
122
+ return event.path;
123
+ }
124
+ getMethod(event) {
125
+ return event.httpMethod;
126
+ }
127
+ getQueryString(event) {
128
+ if (event.multiValueQueryStringParameters) return Object.entries(event.multiValueQueryStringParameters || {}).filter(([, value]) => value).map(([key, value]) => `${key}=${value?.join(`&${key}=`)}`).join("&");
129
+ else return Object.entries(event.queryStringParameters || {}).filter(([, value]) => value).map(([key, value]) => `${key}=${value}`).join("&");
130
+ }
131
+ getCookies(event, headers) {
132
+ let cookie;
133
+ if (event.multiValueHeaders) cookie = event.multiValueHeaders.cookie?.join("; ");
134
+ else cookie = event.headers ? event.headers.cookie : void 0;
135
+ if (cookie) headers.append("Cookie", cookie);
136
+ }
137
+ setCookiesToResult(event, result, cookies) {
138
+ if (event.multiValueHeaders && result.multiValueHeaders) result.multiValueHeaders["set-cookie"] = cookies;
139
+ else result.headers["set-cookie"] = cookies[0];
140
+ }
141
+ };
183
142
  const albProcessor = new ALBProcessor();
143
+ var LatticeV2Processor = class extends RequestEventProcessor {
144
+ getPath(event) {
145
+ return event.path;
146
+ }
147
+ getMethod(event) {
148
+ return event.method;
149
+ }
150
+ getQueryString() {
151
+ return "";
152
+ }
153
+ getHeaders(event) {
154
+ const headers = new Headers();
155
+ if (event.headers) {
156
+ for (const [k, values] of Object.entries(event.headers)) if (values) values.forEach((v) => headers.append(k, sanitizeHeaderValue(v)));
157
+ }
158
+ return headers;
159
+ }
160
+ getCookies() {}
161
+ setCookiesToResult(_, result, cookies) {
162
+ result.headers = {
163
+ ...result.headers,
164
+ "set-cookie": cookies[0]
165
+ };
166
+ }
167
+ };
168
+ const latticeV2Processor = new LatticeV2Processor();
184
169
  function isProxyEventALB(event) {
185
- return Object.hasOwn(event, "requestContext") && Object.hasOwn(event.requestContext, "elb");
170
+ return Object.hasOwn(event, "requestContext") && Object.hasOwn(event.requestContext, "elb");
186
171
  }
187
172
  function isProxyEventV2(event) {
188
- return Object.hasOwn(event, "rawPath");
173
+ return Object.hasOwn(event, "rawPath") && Object.hasOwn(event.requestContext ?? {}, "http");
189
174
  }
190
-
175
+ function isLatticeEventV2(event) {
176
+ return Object.hasOwn(event, "requestContext") && Object.hasOwn(event.requestContext ?? {}, "serviceArn");
177
+ }
178
+ //#endregion
179
+ //#region src/trigger.ts
191
180
  const METHOD = "TRIGGER";
192
181
  const JSON_CONTENT_TYPE_REGEX = /^application\/json/;
193
- class TriggerFactory {
194
- simpleRouter = {};
195
- honoApp;
196
- internalApp = new Hono();
197
- constructor(app) {
198
- this.honoApp = app;
199
- }
200
- on = (eventSource, id, ...handlers) => {
201
- let thisEventSource = this.simpleRouter[eventSource];
202
- if (!thisEventSource) {
203
- this.simpleRouter[eventSource] = thisEventSource = {};
204
- this.honoApp.on(METHOD, getTriggerPath(eventSource), async (c) => {
205
- if (thisEventSource["$!"]) {
206
- return this.internalApp.fetch(makeLocalRequest(METHOD, `/${eventSource}/$!`), c.env);
207
- }
208
- const resObj = {};
209
- for (const route in thisEventSource) {
210
- if (route[0] === "$")
211
- continue;
212
- const res = await this.internalApp.fetch(makeLocalRequest(METHOD, `/${eventSource}/${route}`), c.env);
213
- resObj[route] = JSON_CONTENT_TYPE_REGEX.test(res.headers.get("content-type") || "") ? await res.json() : await res.text();
214
- }
215
- if (thisEventSource["$="]) {
216
- return this.internalApp.fetch(makeLocalRequest(METHOD, `/${eventSource}/$=`), c.env);
217
- }
218
- return c.json(resObj);
219
- });
220
- }
221
- if (thisEventSource[id])
222
- throw new Error(`Route ID "${id}" already exists for event source "${eventSource}"`);
223
- this.internalApp.on(METHOD, `/${eventSource}/${id}`, ...handlers);
224
- thisEventSource[id] = true;
225
- return this;
226
- };
227
- }
182
+ var TriggerFactory = class {
183
+ simpleRouter = {};
184
+ honoApp;
185
+ internalApp = new Hono();
186
+ constructor(app) {
187
+ this.honoApp = app;
188
+ }
189
+ on = (eventSource, id, ...handlers) => {
190
+ let thisEventSource = this.simpleRouter[eventSource];
191
+ if (!thisEventSource) {
192
+ this.simpleRouter[eventSource] = thisEventSource = {};
193
+ this.honoApp.on(METHOD, getTriggerPath(eventSource), async (c) => {
194
+ if (thisEventSource["$!"]) return this.internalApp.fetch(makeLocalRequest(METHOD, `/${eventSource}/$!`), c.env);
195
+ const resObj = {};
196
+ for (const route in thisEventSource) {
197
+ if (route[0] === "$") continue;
198
+ const res = await this.internalApp.fetch(makeLocalRequest(METHOD, `/${eventSource}/${route}`), c.env);
199
+ resObj[route] = JSON_CONTENT_TYPE_REGEX.test(res.headers.get("content-type") || "") ? await res.json() : await res.text();
200
+ }
201
+ if (thisEventSource["$="]) return this.internalApp.fetch(makeLocalRequest(METHOD, `/${eventSource}/$=`), c.env);
202
+ return c.json(resObj);
203
+ });
204
+ }
205
+ if (thisEventSource[id]) throw new Error(`Route ID "${id}" already exists for event source "${eventSource}"`);
206
+ this.internalApp.on(METHOD, `/${eventSource}/${id}`, ...handlers);
207
+ thisEventSource[id] = true;
208
+ return this;
209
+ };
210
+ };
228
211
  function createTriggerFactory(app) {
229
- return new TriggerFactory(app);
230
- }
231
- class TriggerEventProcessor {
232
- createRequest(event) {
233
- const path = getTriggerPath(getEventSource(event));
234
- return makeLocalRequest(METHOD, path);
235
- }
236
- async createResult(event, res) {
237
- const contentType = res.headers.get("content-type");
238
- let isBase64Encoded = !!(contentType && isContentTypeBinary(contentType));
239
- if (!isBase64Encoded) {
240
- const contentEncoding = res.headers.get("content-encoding");
241
- isBase64Encoded = isContentEncodingBinary(contentEncoding);
242
- }
243
- const body = isBase64Encoded ? encodeBase64(await res.arrayBuffer()) : await res.text();
244
- const result = {
245
- body,
246
- headers: {},
247
- statusCode: res.status,
248
- isBase64Encoded
249
- };
250
- res.headers.forEach((value, key) => {
251
- result.headers[key] = value;
252
- });
253
- return result;
254
- }
212
+ return new TriggerFactory(app);
255
213
  }
214
+ var TriggerEventProcessor = class {
215
+ createRequest(event) {
216
+ const path = getTriggerPath(getEventSource(event));
217
+ return makeLocalRequest(METHOD, path);
218
+ }
219
+ async createResult(event, res) {
220
+ const contentType = res.headers.get("content-type");
221
+ let isBase64Encoded = !!(contentType && isContentTypeBinary(contentType));
222
+ if (!isBase64Encoded) isBase64Encoded = isContentEncodingBinary(res.headers.get("content-encoding"));
223
+ const result = {
224
+ body: isBase64Encoded ? encodeBase64(await res.arrayBuffer()) : await res.text(),
225
+ headers: {},
226
+ statusCode: res.status,
227
+ isBase64Encoded
228
+ };
229
+ res.headers.forEach((value, key) => {
230
+ result.headers[key] = value;
231
+ });
232
+ return result;
233
+ }
234
+ };
256
235
  const triggerProcessor = new TriggerEventProcessor();
257
236
  const triggerPathUUID = `${process.env.HONO_TRIGGER_SALT}-${Date.now()}-${Math.random()}`;
258
237
  function getTriggerPath(path) {
259
- return mergePath(triggerPathUUID, path);
238
+ return mergePath(triggerPathUUID, path);
260
239
  }
261
240
  function getEventSource(event) {
262
- const eventSource = event?.eventSource || event?.Name || event?.Records?.[0]?.eventSource || event?.Records?.[0]?.EventSource || event?.source || event?.triggerSource;
263
- if (!eventSource)
264
- throw new Error("Invalid `event`: not LambdaTriggerEvent");
265
- return eventSource;
241
+ const eventSource = event?.eventSource || event?.Name || event?.Records?.[0]?.eventSource || event?.Records?.[0]?.EventSource || event?.source || event?.triggerSource;
242
+ if (!eventSource) throw new Error("Invalid `event`: not LambdaTriggerEvent");
243
+ return eventSource;
266
244
  }
267
245
  function isTriggerEvent(event) {
268
- try {
269
- return Boolean(getEventSource(event));
270
- } catch {
271
- return false;
272
- }
246
+ try {
247
+ return Boolean(getEventSource(event));
248
+ } catch {
249
+ return false;
250
+ }
273
251
  }
274
252
  function makeLocalRequest(method, path) {
275
- return new Request(`http://127.0.0.1${path}`, { method });
253
+ return new Request(`http://127.0.0.1${path}`, { method });
254
+ }
255
+ //#endregion
256
+ //#region src/common.ts
257
+ const CONTENT_TYPE_TEXT_REGEX = /^text\/(?:plain|html|css|javascript|csv)|(?:\/|\+)(?:json|xml)\s*(?:;|$)/;
258
+ const CONTENT_ENCODING_IDENTITY_REGEX = /^identity$/i;
259
+ /**
260
+ * Check if the given content type is binary.
261
+ * This is the default used by `handle`/`streamHandle` and may be overridden via the
262
+ * `isContentTypeBinary` option.
263
+ */
264
+ function defaultIsContentTypeBinary(contentType) {
265
+ return !CONTENT_TYPE_TEXT_REGEX.test(contentType);
276
266
  }
277
-
278
- const CONTENT_TYPE_TEXT_REGEX = /^(?:text\/(?:plain|html|css|javascript|csv).*|application\/(?:.*json|.*xml).*|image\/svg\+xml.*)$/;
279
- const CONTENT_ENCODING_BINARY_REGEX = /^(?:gzip|deflate|compress|br)/;
280
267
  function isContentTypeBinary(contentType) {
281
- return !CONTENT_TYPE_TEXT_REGEX.test(contentType);
268
+ return defaultIsContentTypeBinary(contentType);
282
269
  }
283
270
  function isContentEncodingBinary(contentEncoding) {
284
- if (contentEncoding === null) {
285
- return false;
286
- }
287
- return CONTENT_ENCODING_BINARY_REGEX.test(contentEncoding);
271
+ return !!contentEncoding && !CONTENT_ENCODING_IDENTITY_REGEX.test(contentEncoding);
288
272
  }
289
273
  function getProcessor(event) {
290
- if (isTriggerEvent(event))
291
- return triggerProcessor;
292
- if (isProxyEventALB(event))
293
- return albProcessor;
294
- if (isProxyEventV2(event))
295
- return v2Processor;
296
- return v1Processor;
274
+ if (isTriggerEvent(event)) return triggerProcessor;
275
+ if (isProxyEventALB(event)) return albProcessor;
276
+ if (isProxyEventV2(event)) return v2Processor;
277
+ if (isLatticeEventV2(event)) return latticeV2Processor;
278
+ return v1Processor;
297
279
  }
298
-
280
+ //#endregion
281
+ //#region src/utils/event.ts
282
+ /**
283
+ * Creates/populates a minimal event with path & method for routing usage purpose.
284
+ *
285
+ * Will also set `Content-Type` header and stringify body if method is not GET/HEAD
286
+ */
299
287
  function minimalEvent(method, path, baseEvent) {
300
- const event = baseEvent ?? {};
301
- event.requestContext ??= {
302
- http: {
303
- method: "",
304
- path: ""
305
- },
306
- routeKey: ""
307
- };
308
- if (method !== "GET" && method !== "HEAD") {
309
- event.headers ??= {};
310
- event.headers["content-type"] ??= "application/json";
311
- if (typeof event.body !== "string")
312
- event.body = JSON.stringify(event.body);
313
- }
314
- event.routeKey = event.requestContext.routeKey = `${method} ${path}`;
315
- event.requestContext.http.method = method;
316
- event.rawPath = event.requestContext.http.path = path;
317
- return event;
288
+ const event = baseEvent ?? {};
289
+ event.requestContext ??= {
290
+ http: {
291
+ method: "",
292
+ path: ""
293
+ },
294
+ routeKey: ""
295
+ };
296
+ if (method !== "GET" && method !== "HEAD") {
297
+ event.headers ??= {};
298
+ event.headers["content-type"] ??= "application/json";
299
+ if (typeof event.body !== "string") event.body = JSON.stringify(event.body);
300
+ }
301
+ event.routeKey = event.requestContext.routeKey = `${method} ${path}`;
302
+ event.requestContext.http.method = method;
303
+ event.rawPath = event.requestContext.http.path = path;
304
+ return event;
318
305
  }
319
-
306
+ //#endregion
307
+ //#region src/handler.ts
320
308
  async function writableWriteReadable(writer, reader) {
321
- let readResult = await reader.read();
322
- while (!readResult.done) {
323
- writer.write(readResult.value);
324
- readResult = await reader.read();
325
- }
326
- writer.end();
309
+ let readResult = await reader.read();
310
+ while (!readResult.done) {
311
+ writer.write(readResult.value);
312
+ readResult = await reader.read();
313
+ }
314
+ writer.end();
327
315
  }
328
316
  function stringToReadable(str) {
329
- return Readable.from(Buffer.from(str));
317
+ return Readable.from(Buffer.from(str));
330
318
  }
331
319
  function resultToStreamMetadata(result) {
332
- return {
333
- statusCode: result.statusCode,
334
- headers: result.headers,
335
- cookies: result.cookies
336
- };
320
+ return {
321
+ statusCode: result.statusCode,
322
+ headers: result.headers,
323
+ cookies: result.cookies
324
+ };
337
325
  }
338
326
  function responseToStreamMetadata(res) {
339
- const headers = {};
340
- const cookies = [];
341
- res.headers.forEach((value, name) => {
342
- if (name === "set-cookie")
343
- cookies.push(value);
344
- else
345
- headers[name] = value;
346
- });
347
- return {
348
- statusCode: res.status,
349
- headers,
350
- cookies
351
- };
327
+ const headers = {};
328
+ const cookies = [];
329
+ res.headers.forEach((value, name) => {
330
+ if (name === "set-cookie") cookies.push(value);
331
+ else headers[name] = value;
332
+ });
333
+ return {
334
+ statusCode: res.status,
335
+ headers,
336
+ cookies
337
+ };
352
338
  }
353
339
  function streamHandle(app, handleConfig) {
354
- return awslambda.streamifyResponse(
355
- async (event, responseStream, context) => {
356
- await processConfig(event, context, handleConfig);
357
- const processor = getProcessor(event);
358
- try {
359
- const req = processor.createRequest(event);
360
- const res = await app.fetch(req, {
361
- event,
362
- context
363
- });
364
- if (res.headers.get("$HAAL-returnBody")) {
365
- const result = await res.json();
366
- responseStream = awslambda.HttpResponseStream.from(responseStream, resultToStreamMetadata(result));
367
- const bodyStream = stringToReadable(result.body || "");
368
- await pipeline(bodyStream, responseStream);
369
- } else {
370
- responseStream = awslambda.HttpResponseStream.from(responseStream, responseToStreamMetadata(res));
371
- if (res.body) {
372
- await writableWriteReadable(responseStream, res.body.getReader());
373
- } else {
374
- responseStream.write("");
375
- }
376
- }
377
- } catch (error) {
378
- console.error("Error processing request:", error);
379
- responseStream.write("Internal Server Error");
380
- } finally {
381
- responseStream.end();
382
- }
383
- }
384
- );
340
+ return awslambda.streamifyResponse(async (event, responseStream, context) => {
341
+ await processConfig(event, context, handleConfig);
342
+ const processor = getProcessor(event);
343
+ try {
344
+ const req = processor.createRequest(event);
345
+ const res = await app.fetch(req, {
346
+ event,
347
+ context
348
+ });
349
+ if (res.headers.get("$HAAL-returnBody")) {
350
+ const result = await res.json();
351
+ responseStream = awslambda.HttpResponseStream.from(responseStream, resultToStreamMetadata(result));
352
+ const bodyStream = stringToReadable(result.body || "");
353
+ await pipeline(bodyStream, responseStream);
354
+ } else {
355
+ responseStream = awslambda.HttpResponseStream.from(responseStream, responseToStreamMetadata(res));
356
+ if (res.body) await writableWriteReadable(responseStream, res.body.getReader());
357
+ else responseStream.write("");
358
+ }
359
+ } catch (error) {
360
+ console.error("Error processing request:", error);
361
+ responseStream.write("Internal Server Error");
362
+ } finally {
363
+ responseStream.end();
364
+ }
365
+ });
385
366
  }
367
+ /**
368
+ * Accepts events from API Gateway/ELB(`APIGatewayProxyEvent`) and directly through Function Url(`APIGatewayProxyEventV2`)
369
+ */
386
370
  function handle(app, handleConfig) {
387
- return async (event, context) => {
388
- await processConfig(event, context, handleConfig);
389
- const processor = getProcessor(event);
390
- const req = processor.createRequest(event);
391
- const res = await app.fetch(req, {
392
- event,
393
- context
394
- });
395
- if (res.headers.get("$HAAL-returnBody"))
396
- return await res.json();
397
- return processor.createResult(event, res);
398
- };
371
+ return async (event, context) => {
372
+ await processConfig(event, context, handleConfig);
373
+ const processor = getProcessor(event);
374
+ const resultOptions = handleConfig?.isContentTypeBinary ? { isContentTypeBinary: handleConfig.isContentTypeBinary } : void 0;
375
+ let req;
376
+ try {
377
+ req = processor.createRequest(event);
378
+ } catch (error) {
379
+ console.error("Error processing request:", error);
380
+ const errorResponse = error instanceof TypeError ? new Response("Invalid request", { status: 400 }) : new Response("Internal Server Error", { status: 500 });
381
+ return processor.createResult(event, errorResponse, resultOptions);
382
+ }
383
+ const res = await app.fetch(req, {
384
+ event,
385
+ context
386
+ });
387
+ if (res.headers.get("$HAAL-returnBody")) return await res.json();
388
+ return processor.createResult(event, res, resultOptions);
389
+ };
399
390
  }
400
391
  async function processConfig(event, context, handleConfig) {
401
- const _eventCastV2 = event;
402
- if (handleConfig?.easyRouteKey) {
403
- if (!_eventCastV2.routeKey)
404
- return;
405
- if (!_eventCastV2.requestContext?.http?.path && !_eventCastV2.requestContext?.http?.method) {
406
- const [method, path] = _eventCastV2.routeKey.split(" ");
407
- minimalEvent(method, path, _eventCastV2);
408
- }
409
- }
392
+ const _eventCastV2 = event;
393
+ if (handleConfig?.easyRouteKey) {
394
+ if (!_eventCastV2.routeKey) return;
395
+ if (!_eventCastV2.requestContext?.http?.path && !_eventCastV2.requestContext?.http?.method) {
396
+ const [method, path] = _eventCastV2.routeKey.split(" ");
397
+ minimalEvent(method, path, _eventCastV2);
398
+ }
399
+ }
410
400
  }
411
-
401
+ //#endregion
412
402
  export { TriggerFactory, createTriggerFactory, getTriggerPath, handle, streamHandle, triggerPathUUID };
403
+
404
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.mjs","names":[],"sources":["../src/request.ts","../src/trigger.ts","../src/common.ts","../src/utils/event.ts","../src/handler.ts"],"sourcesContent":["import type { LambdaRequestEvent } from '@namesmt/utils-lambda'\nimport type { ALBEvent, APIGatewayProxyEvent, APIGatewayProxyEventV2, APIGatewayProxyResult, APIGatewayProxyStructuredResultV2 } from 'aws-lambda'\nimport type { EventProcessor, ResultOptions } from './common'\n\nimport type { AdapterEvent, LambdaHandlerResult, LatticeProxyEventV2 } from './types'\nimport { decodeBase64, encodeBase64 } from 'hono/utils/encode'\nimport { defaultIsContentTypeBinary, isContentEncodingBinary } from './common'\n\n// eslint-disable-next-line no-control-regex\nconst NON_ASCII_REGEX = /[^\\x00-\\x7F]/\n\nfunction sanitizeHeaderValue(value: string): string {\n // Check if the value contains non-ASCII characters (char codes > 127)\n if (!NON_ASCII_REGEX.test(value))\n return value\n return encodeURIComponent(value)\n}\n\nabstract class RequestEventProcessor<E extends LambdaRequestEvent | LatticeProxyEventV2> implements EventProcessor<E> {\n protected abstract getPath(event: E): string\n\n protected abstract getMethod(event: E): string\n\n protected abstract getQueryString(event: E): string\n\n protected abstract getHeaders(event: E): Headers\n\n protected abstract getCookies(event: E, headers: Headers): void\n\n protected abstract setCookiesToResult(\n event: E,\n result: LambdaHandlerResult,\n cookies: string[]\n ): void\n\n createRequest(event: E): Request {\n const queryString = this.getQueryString(event)\n const domainName\n = event.requestContext && 'domainName' in event.requestContext\n ? event.requestContext.domainName\n : (event as unknown as APIGatewayProxyEventV2).headers?.host ?? (event as unknown as APIGatewayProxyEvent).multiValueHeaders?.host?.[0]\n const path = this.getPath(event)\n const urlPath = `https://${domainName}${path}`\n const url = queryString ? `${urlPath}?${queryString}` : urlPath\n\n const headers = this.getHeaders(event)\n\n const method = this.getMethod(event)\n const requestInit: RequestInit = {\n headers,\n method,\n }\n\n if (event.body) {\n const body = event.isBase64Encoded ? decodeBase64(event.body) : new TextEncoder().encode(event.body)\n requestInit.body = body\n headers.set('content-length', body.length.toString())\n }\n\n return new Request(url, requestInit)\n }\n\n async createResult(event: E, res: Response, options?: ResultOptions): Promise<LambdaHandlerResult> {\n const contentType = res.headers.get('content-type')\n const isContentTypeBinaryFn = options?.isContentTypeBinary ?? defaultIsContentTypeBinary\n let isBase64Encoded = !!(contentType && isContentTypeBinaryFn(contentType))\n\n if (!isBase64Encoded) {\n const contentEncoding = res.headers.get('content-encoding')\n isBase64Encoded = isContentEncodingBinary(contentEncoding)\n }\n\n const body = isBase64Encoded ? encodeBase64(await res.arrayBuffer()) : await res.text()\n\n const result = {\n body,\n headers: {} as NonNullable<APIGatewayProxyStructuredResultV2['headers']>,\n multiValueHeaders: undefined as APIGatewayProxyResult['multiValueHeaders'],\n statusCode: res.status,\n isBase64Encoded,\n } satisfies APIGatewayProxyResult & APIGatewayProxyStructuredResultV2\n\n if ('multiValueHeaders' in event) {\n result.multiValueHeaders = {}\n }\n\n this.setCookies(event, res, result)\n res.headers.forEach((value, key) => {\n result.headers[key] = value\n if ('multiValueHeaders' in event) {\n result.multiValueHeaders![key] = [value]\n }\n })\n\n return result\n }\n\n setCookies(event: E, res: Response, result: LambdaHandlerResult) {\n if (res.headers.has('set-cookie')) {\n const cookies = res.headers.getSetCookie\n ? res.headers.getSetCookie()\n : Array.from(res.headers.entries()).filter(([k]) => k === 'set-cookie').map(([, v]) => v)\n\n if (Array.isArray(cookies)) {\n this.setCookiesToResult(event, result, cookies)\n res.headers.delete('set-cookie')\n }\n }\n }\n}\n\nclass EventV2Processor extends RequestEventProcessor<APIGatewayProxyEventV2> {\n protected getPath(event: APIGatewayProxyEventV2): string {\n return event.rawPath\n }\n\n protected getMethod(event: APIGatewayProxyEventV2): string {\n return event.requestContext.http.method\n }\n\n protected getQueryString(event: APIGatewayProxyEventV2): string {\n return event.rawQueryString\n }\n\n protected getCookies(event: APIGatewayProxyEventV2, headers: Headers): void {\n if (Array.isArray(event.cookies)) {\n headers.set('Cookie', event.cookies.join('; '))\n }\n }\n\n protected setCookiesToResult(\n _: APIGatewayProxyEventV2,\n result: APIGatewayProxyStructuredResultV2,\n cookies: string[],\n ): void {\n result.cookies = cookies\n }\n\n protected getHeaders(event: APIGatewayProxyEventV2): Headers {\n const headers = new Headers()\n this.getCookies(event, headers)\n if (event.headers) {\n for (const [k, v] of Object.entries(event.headers)) {\n if (v) {\n headers.set(k, v)\n }\n }\n }\n return headers\n }\n}\n\nexport const v2Processor: EventV2Processor = new EventV2Processor()\n\nclass EventV1Processor extends RequestEventProcessor<Exclude<LambdaRequestEvent, APIGatewayProxyEventV2>> {\n protected getPath(event: Exclude<LambdaRequestEvent, APIGatewayProxyEventV2>): string {\n return event.path\n }\n\n protected getMethod(event: Exclude<LambdaRequestEvent, APIGatewayProxyEventV2>): string {\n return event.httpMethod\n }\n\n protected getQueryString(event: Exclude<LambdaRequestEvent, APIGatewayProxyEventV2>): string {\n // API Gateway passes decoded values, so we need to re-encode them to preserve the original URL\n if ((event as APIGatewayProxyEvent).multiValueQueryStringParameters) {\n return Object.entries((event as APIGatewayProxyEvent).multiValueQueryStringParameters || {})\n .filter(([, value]) => value)\n .map(([key, values]) => values!.map(value => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`).join('&'))\n .join('&')\n }\n else {\n return Object.entries(event.queryStringParameters || {})\n .filter(([, value]) => value)\n .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value || '')}`)\n .join('&')\n }\n }\n\n protected getCookies(\n // eslint-disable-next-line unused-imports/no-unused-vars\n event: Exclude<LambdaRequestEvent, APIGatewayProxyEventV2>,\n // eslint-disable-next-line unused-imports/no-unused-vars\n headers: Headers,\n ): void {\n // nop\n }\n\n protected getHeaders(event: APIGatewayProxyEvent): Headers {\n const headers = new Headers()\n this.getCookies(event, headers)\n if (event.multiValueHeaders) {\n for (const [k, values] of Object.entries(event.multiValueHeaders)) {\n if (values) {\n values.forEach(v => headers.append(k, sanitizeHeaderValue(v)))\n }\n }\n }\n if (event.headers) {\n for (const [k, v] of Object.entries(event.headers)) {\n if (v && !headers.has(k)) {\n headers.set(k, sanitizeHeaderValue(v))\n }\n }\n }\n return headers\n }\n\n protected setCookiesToResult(\n _: APIGatewayProxyEvent,\n result: APIGatewayProxyResult,\n cookies: string[],\n ): void {\n result.multiValueHeaders = {\n 'set-cookie': cookies,\n }\n }\n}\n\nexport const v1Processor: EventV1Processor = new EventV1Processor()\n\nclass ALBProcessor extends RequestEventProcessor<ALBEvent> {\n protected getHeaders(event: ALBEvent): Headers {\n const headers = new Headers()\n // if multiValueHeaders is present the ALB will use it instead of the headers field\n // https://docs.aws.amazon.com/elasticloadbalancing/latest/application/lambda-functions.html#multi-value-headers\n if (event.multiValueHeaders) {\n for (const [key, values] of Object.entries(event.multiValueHeaders)) {\n if (values && Array.isArray(values)) {\n // https://www.rfc-editor.org/rfc/rfc9110.html#name-common-rules-for-defining-f\n headers.set(key, sanitizeHeaderValue(values.join('; ')))\n }\n }\n }\n else {\n for (const [key, value] of Object.entries(event.headers ?? {})) {\n if (value) {\n headers.set(key, sanitizeHeaderValue(value))\n }\n }\n }\n return headers\n }\n\n protected getPath(event: ALBEvent): string {\n return event.path\n }\n\n protected getMethod(event: ALBEvent): string {\n return event.httpMethod\n }\n\n protected getQueryString(event: ALBEvent): string {\n // In the case of ALB Integration either queryStringParameters or multiValueQueryStringParameters can be present not both\n /* \n In other cases like when using the serverless framework, the event object does contain both queryStringParameters and multiValueQueryStringParameters:\n Below is an example event object for this URL: /payment/b8c55e69?select=amount&select=currency\n {\n ...\n queryStringParameters: { select: 'currency' },\n multiValueQueryStringParameters: { select: [ 'amount', 'currency' ] },\n }\n The expected results is for select to be an array with two items. However the pre-fix code is only returning one item ('currency') in the array.\n A simple fix would be to invert the if statement and check the multiValueQueryStringParameters first.\n */\n if (event.multiValueQueryStringParameters) {\n return Object.entries(event.multiValueQueryStringParameters || {})\n .filter(([, value]) => value)\n .map(([key, value]) => `${key}=${value?.join(`&${key}=`)}`)\n .join('&')\n }\n else {\n return Object.entries(event.queryStringParameters || {})\n .filter(([, value]) => value)\n .map(([key, value]) => `${key}=${value}`)\n .join('&')\n }\n }\n\n protected getCookies(event: ALBEvent, headers: Headers): void {\n let cookie\n if (event.multiValueHeaders) {\n cookie = event.multiValueHeaders.cookie?.join('; ')\n }\n else {\n cookie = event.headers ? event.headers.cookie : undefined\n }\n if (cookie) {\n headers.append('Cookie', cookie)\n }\n }\n\n protected setCookiesToResult(\n event: ALBEvent,\n result: APIGatewayProxyResult,\n cookies: string[],\n ): void {\n // when multi value headers is enabled\n if (event.multiValueHeaders && result.multiValueHeaders) {\n result.multiValueHeaders['set-cookie'] = cookies\n }\n else {\n // otherwise serialize the set-cookie\n result.headers!['set-cookie'] = cookies[0]\n }\n }\n}\n\nexport const albProcessor: ALBProcessor = new ALBProcessor()\n\nclass LatticeV2Processor extends RequestEventProcessor<LatticeProxyEventV2> {\n protected getPath(event: LatticeProxyEventV2): string {\n return event.path\n }\n\n protected getMethod(event: LatticeProxyEventV2): string {\n return event.method\n }\n\n protected getQueryString(): string {\n return ''\n }\n\n protected getHeaders(event: LatticeProxyEventV2): Headers {\n const headers = new Headers()\n if (event.headers) {\n for (const [k, values] of Object.entries(event.headers)) {\n if (values) {\n values.forEach(v => headers.append(k, sanitizeHeaderValue(v)))\n }\n }\n }\n return headers\n }\n\n protected getCookies(): void {\n // nop\n }\n\n protected setCookiesToResult(\n _: LatticeProxyEventV2,\n result: APIGatewayProxyResult,\n cookies: string[],\n ): void {\n result.headers = {\n ...result.headers,\n 'set-cookie': cookies[0],\n }\n }\n}\n\nexport const latticeV2Processor: LatticeV2Processor = new LatticeV2Processor()\n\nexport function isProxyEventALB(event: AdapterEvent): event is ALBEvent {\n return Object.hasOwn(event, 'requestContext') && Object.hasOwn((event as LambdaRequestEvent).requestContext, 'elb')\n}\n\nexport function isProxyEventV2(event: AdapterEvent): event is APIGatewayProxyEventV2 {\n // A V1 (REST API) event behind a custom domain base path mapping also carries a\n // `rawPath`, so `rawPath` alone is not enough to identify a V2 event. Every V2\n // (HTTP API / function URL) event has an `http` object on its request context.\n return Object.hasOwn(event, 'rawPath') && Object.hasOwn((event as LambdaRequestEvent).requestContext ?? {}, 'http')\n}\n\nexport function isLatticeEventV2(event: AdapterEvent): event is LatticeProxyEventV2 {\n return Object.hasOwn(event, 'requestContext') && Object.hasOwn((event as LatticeProxyEventV2).requestContext ?? {}, 'serviceArn')\n}\n","import type { CommonTriggerEventsMap, LambdaTriggerEvent } from '@namesmt/utils-lambda'\nimport type { APIGatewayProxyStructuredResultV2 } from 'aws-lambda'\nimport type { Env } from 'hono'\nimport type { H } from 'hono/types'\nimport type { EventProcessor } from './common'\nimport type { AdapterEvent } from './types'\nimport { Hono } from 'hono'\nimport { encodeBase64 } from 'hono/utils/encode'\nimport { mergePath } from 'hono/utils/url'\nimport { isContentEncodingBinary, isContentTypeBinary } from './common'\n\nconst METHOD = 'TRIGGER'\nconst JSON_CONTENT_TYPE_REGEX = /^application\\/json/\n\nexport class TriggerFactory<IE extends Env, HE extends Env> {\n private simpleRouter: Record<string, Record<string, true>> = {}\n\n honoApp: Hono<HE>\n internalApp = new Hono<IE>()\n\n constructor(app: Hono<HE>) {\n this.honoApp = app\n }\n\n on = (eventSource: string, id: string, ...handlers: H<IE>[]) => {\n let thisEventSource = this.simpleRouter[eventSource]\n if (!thisEventSource) {\n this.simpleRouter[eventSource] = thisEventSource = {}\n\n this.honoApp.on(METHOD, getTriggerPath(eventSource), async (c) => {\n // $!: rootTakeover, this is a special id that will return itself, bypass the execute of the rest of the ids\n if (thisEventSource['$!']) {\n return this.internalApp.fetch(makeLocalRequest(METHOD, `/${eventSource}/$!`), c.env)\n }\n\n const resObj: Record<string, any> = {}\n for (const route in thisEventSource) {\n // Bypass special ids in normal process loop\n if (route[0] === '$')\n continue\n\n const res = await this.internalApp.fetch(makeLocalRequest(METHOD, `/${eventSource}/${route}`), c.env)\n resObj[route] = JSON_CONTENT_TYPE_REGEX.test(res.headers.get('content-type') || '') ? await res.json() : await res.text()\n }\n\n // $: rootReturn, this is a special id that will always be processed last and return itself instead of an object of all ids result.\n if (thisEventSource['$=']) {\n return this.internalApp.fetch(makeLocalRequest(METHOD, `/${eventSource}/$=`), c.env)\n }\n\n return c.json(resObj)\n })\n }\n\n if (thisEventSource[id])\n throw new Error(`Route ID \"${id}\" already exists for event source \"${eventSource}\"`)\n\n // @ts-expect-error upstream Hono type bug\n this.internalApp.on(METHOD, `/${eventSource}/${id}`, ...handlers)\n thisEventSource[id] = true\n\n return this\n }\n}\n\ntype ExtractHonoEnv<A extends Hono> = A extends Hono<infer E> ? E : never\n\nexport function createTriggerFactory<E extends Env, A extends Hono<any, any, '/'>>(app: A) {\n return new TriggerFactory<E extends unknown\n ? {\n Bindings: { event: LambdaTriggerEvent }\n Variables: Record<string, unknown>\n }\n : E, ExtractHonoEnv<A>>(app)\n}\n\nclass TriggerEventProcessor implements EventProcessor<LambdaTriggerEvent> {\n createRequest(event: LambdaTriggerEvent): Request {\n const path = getTriggerPath(getEventSource(event))\n return makeLocalRequest(METHOD, path)\n }\n\n async createResult(event: LambdaTriggerEvent, res: Response): Promise<any> {\n const contentType = res.headers.get('content-type')\n let isBase64Encoded = !!(contentType && isContentTypeBinary(contentType))\n\n if (!isBase64Encoded) {\n const contentEncoding = res.headers.get('content-encoding')\n isBase64Encoded = isContentEncodingBinary(contentEncoding)\n }\n\n const body = isBase64Encoded ? encodeBase64(await res.arrayBuffer()) : await res.text()\n\n const result = {\n body,\n headers: {} as NonNullable<APIGatewayProxyStructuredResultV2['headers']>,\n statusCode: res.status,\n isBase64Encoded,\n } satisfies APIGatewayProxyStructuredResultV2\n\n res.headers.forEach((value, key) => {\n result.headers[key] = value\n })\n\n return result\n }\n}\nexport const triggerProcessor: TriggerEventProcessor = new TriggerEventProcessor()\n\n// eslint-disable-next-line node/prefer-global/process\nexport const triggerPathUUID = `${process.env.HONO_TRIGGER_SALT}-${Date.now()}-${Math.random()}`\n\nexport function getTriggerPath(path: string) {\n return mergePath(triggerPathUUID, path)\n}\n\nexport function getEventSource(event: LambdaTriggerEvent): string {\n const eventSource = (false\n || (event as CommonTriggerEventsMap['eventSource'])?.eventSource\n || (event as CommonTriggerEventsMap['Name'])?.Name\n || (event as CommonTriggerEventsMap['Records.eventSource'])?.Records?.[0]?.eventSource\n || (event as CommonTriggerEventsMap['Records.EventSource'])?.Records?.[0]?.EventSource\n || (event as CommonTriggerEventsMap['source'])?.source\n || (event as CommonTriggerEventsMap['triggerSource'])?.triggerSource\n )\n\n if (!eventSource)\n throw new Error('Invalid `event`: not LambdaTriggerEvent')\n\n return eventSource\n}\n\nexport function isTriggerEvent(event: AdapterEvent): event is LambdaTriggerEvent {\n try {\n return Boolean(getEventSource(event as LambdaTriggerEvent))\n }\n catch {\n return false\n }\n}\n\nexport function makeLocalRequest(method: string, path: string): Request {\n return new Request(`http://127.0.0.1${path}`, { method })\n}\n","import type { AdapterEvent } from './types'\n\nimport { albProcessor, isLatticeEventV2, isProxyEventALB, isProxyEventV2, latticeV2Processor, v1Processor, v2Processor } from './request'\nimport { isTriggerEvent, triggerProcessor } from './trigger'\n\nconst CONTENT_TYPE_TEXT_REGEX = /^text\\/(?:plain|html|css|javascript|csv)|(?:\\/|\\+)(?:json|xml)\\s*(?:;|$)/\nconst CONTENT_ENCODING_IDENTITY_REGEX = /^identity$/i\n\n/**\n * Check if the given content type is binary.\n * This is the default used by `handle`/`streamHandle` and may be overridden via the\n * `isContentTypeBinary` option.\n */\nexport function defaultIsContentTypeBinary(contentType: string): boolean {\n return !CONTENT_TYPE_TEXT_REGEX.test(contentType)\n}\n\nexport function isContentTypeBinary(contentType: string) {\n return defaultIsContentTypeBinary(contentType)\n}\n\nexport function isContentEncodingBinary(contentEncoding: string | null) {\n return !!contentEncoding && !CONTENT_ENCODING_IDENTITY_REGEX.test(contentEncoding)\n}\n\nexport interface ResultOptions {\n isContentTypeBinary?: (contentType: string) => boolean\n}\n\nexport abstract class EventProcessor<E extends AdapterEvent> {\n abstract createRequest(event: E): Request\n\n abstract createResult(event: E, res: Response, options?: ResultOptions): Promise<any>\n}\n\nexport function getProcessor(event: AdapterEvent): EventProcessor<AdapterEvent> {\n if (isTriggerEvent(event))\n return triggerProcessor\n if (isProxyEventALB(event))\n return albProcessor\n\n if (isProxyEventV2(event))\n return v2Processor\n\n if (isLatticeEventV2(event))\n return latticeV2Processor\n\n return v1Processor\n}\n","import type { APIGatewayProxyEventV2 } from 'aws-lambda'\n\n/**\n * Creates/populates a minimal event with path & method for routing usage purpose.\n * \n * Will also set `Content-Type` header and stringify body if method is not GET/HEAD \n */\nexport function minimalEvent(method: string, path: string, baseEvent?: APIGatewayProxyEventV2): APIGatewayProxyEventV2 {\n const event = baseEvent ?? {} as any\n\n event.requestContext ??= {\n http: {\n method: '',\n path: '',\n },\n routeKey: '',\n }\n\n if (method !== 'GET' && method !== 'HEAD') {\n event.headers ??= {}\n event.headers['content-type'] ??= 'application/json'\n\n if (typeof event.body !== 'string')\n event.body = JSON.stringify(event.body)\n }\n\n event.routeKey = event.requestContext.routeKey = `${method} ${path}`\n event.requestContext.http.method = method\n event.rawPath = event.requestContext.http.path = path\n\n return event as APIGatewayProxyEventV2\n}\n","import type { APIGatewayProxyEventV2, APIGatewayProxyStructuredResultV2 } from 'aws-lambda'\nimport type { Env, Hono, Schema } from 'hono'\nimport type { ReadableStreamDefaultReader } from 'stream/web'\nimport type { ResultOptions } from './common'\nimport type { AdapterEvent, LambdaContext, LambdaHandler, LambdaHandlerResult } from './types'\nimport { Readable } from 'stream'\nimport { pipeline } from 'stream/promises'\nimport { getProcessor } from './common'\nimport { minimalEvent } from './utils/event'\n\nasync function writableWriteReadable(writer: NodeJS.WritableStream, reader: ReadableStreamDefaultReader<Uint8Array>): Promise<void> {\n let readResult = await reader.read()\n while (!readResult.done) {\n writer.write(readResult.value)\n readResult = await reader.read()\n }\n writer.end()\n}\n\nfunction stringToReadable(str: string): Readable {\n // eslint-disable-next-line node/prefer-global/buffer\n return Readable.from(Buffer.from(str))\n}\n\nfunction resultToStreamMetadata(result: APIGatewayProxyStructuredResultV2) {\n return {\n statusCode: result.statusCode,\n headers: result.headers,\n cookies: result.cookies,\n }\n}\n\nfunction responseToStreamMetadata(res: Response) {\n const headers: Record<string, string> = {}\n const cookies: string[] = []\n\n res.headers.forEach((value, name) => {\n if (name === 'set-cookie')\n cookies.push(value)\n else\n headers[name] = value\n })\n\n return {\n statusCode: res.status,\n headers,\n cookies,\n }\n}\n\nexport interface HandleConfigOptions {\n /**\n * This allows you to easier invoke HTTP routes manually by parsing `event.routeKey` for method and path.\n */\n easyRouteKey?: boolean\n /**\n * Overrides the default binary content-type detection.\n * Defaults to `defaultIsContentTypeBinary`.\n */\n isContentTypeBinary?: (contentType: string) => boolean\n}\n\nexport function streamHandle<\n E extends Env = Env,\n S extends Schema = {},\n BasePath extends string = '/',\n>(app: Hono<E, S, BasePath>, handleConfig?: HandleConfigOptions): LambdaHandler<AdapterEvent> {\n // @ts-expect-error awslambda is not a standard API\n return awslambda.streamifyResponse(\n async (event, responseStream, context) => {\n await processConfig(event, context, handleConfig)\n\n const processor = getProcessor(event)\n try {\n const req = processor.createRequest(event)\n\n const res = await app.fetch(req, {\n event,\n context,\n })\n\n if (res.headers.get('$HAAL-returnBody')) {\n const result = (await res.json()) as APIGatewayProxyStructuredResultV2\n\n // Update response stream metadata\n responseStream = awslambda.HttpResponseStream.from(responseStream, resultToStreamMetadata(result))\n\n const bodyStream = stringToReadable(result.body || '')\n\n await pipeline(bodyStream, responseStream)\n }\n else {\n // Update response stream metadata\n responseStream = awslambda.HttpResponseStream.from(responseStream, responseToStreamMetadata(res))\n\n if (res.body) {\n await writableWriteReadable(responseStream, res.body.getReader())\n }\n else {\n responseStream.write('')\n }\n }\n }\n catch (error) {\n console.error('Error processing request:', error)\n responseStream.write('Internal Server Error')\n }\n finally {\n responseStream.end()\n }\n },\n )\n}\n\n/**\n * Accepts events from API Gateway/ELB(`APIGatewayProxyEvent`) and directly through Function Url(`APIGatewayProxyEventV2`)\n */\nexport function handle<E extends Env = Env, S extends Schema = {}, BasePath extends string = '/'>(app: Hono<E, S, BasePath>, handleConfig?: HandleConfigOptions): LambdaHandler<AdapterEvent, LambdaHandlerResult> {\n return async (event, context?) => {\n await processConfig(event, context, handleConfig)\n\n const processor = getProcessor(event)\n\n const resultOptions: ResultOptions | undefined = handleConfig?.isContentTypeBinary\n ? { isContentTypeBinary: handleConfig.isContentTypeBinary }\n : undefined\n\n let req: Request\n try {\n req = processor.createRequest(event)\n }\n catch (error) {\n console.error('Error processing request:', error)\n const errorResponse = error instanceof TypeError\n ? new Response('Invalid request', { status: 400 })\n : new Response('Internal Server Error', { status: 500 })\n return processor.createResult(event, errorResponse, resultOptions)\n }\n\n const res = await app.fetch(req, {\n event,\n context,\n })\n\n if (res.headers.get('$HAAL-returnBody'))\n return (await res.json()) as LambdaHandlerResult\n\n return processor.createResult(event, res, resultOptions)\n }\n}\n\nasync function processConfig(event: AdapterEvent, context?: LambdaContext, handleConfig?: HandleConfigOptions) {\n const _eventCastV2 = event as APIGatewayProxyEventV2\n if (handleConfig?.easyRouteKey) {\n if (!_eventCastV2.routeKey)\n return\n\n if (!_eventCastV2.requestContext?.http?.path && !_eventCastV2.requestContext?.http?.method) {\n const [method, path] = _eventCastV2.routeKey.split(' ')\n minimalEvent(method, path, _eventCastV2)\n }\n }\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "hono-adapter-aws-lambda",
3
3
  "type": "module",
4
- "version": "1.3.5",
4
+ "version": "1.4.0",
5
5
  "packageManager": "pnpm@12.4.1",
6
6
  "description": "",
7
7
  "author": "NamesMT <dangquoctrung123@gmail.com>",
@@ -20,6 +20,9 @@
20
20
  "lambda"
21
21
  ],
22
22
  "sideEffects": false,
23
+ "imports": {
24
+ "#src/*": "./src/*"
25
+ },
23
26
  "exports": {
24
27
  ".": {
25
28
  "types": "./dist/index.d.mts",
@@ -34,20 +37,17 @@
34
37
  "dist"
35
38
  ],
36
39
  "engines": {
37
- "node": ">=18.20.3"
40
+ "node": ">=22.0.0"
38
41
  },
39
42
  "scripts": {
40
43
  "start": "NODE_ENV=dev tsx src/index.ts",
41
44
  "watch": "NODE_ENV=dev tsx watch src/index.ts",
42
- "stub": "unbuild --stub",
43
45
  "dev": "pnpm run watch",
44
- "play": "pnpm run stub && pnpm run --filter playground dev",
45
- "play:useBuild": "pnpm run build && pnpm run --filter playground dev",
46
46
  "lint": "eslint .",
47
47
  "test": "vitest",
48
48
  "test:types": "tsc --noEmit --skipLibCheck",
49
49
  "check": "pnpm lint && pnpm test:types && vitest run --coverage",
50
- "build": "unbuild",
50
+ "build": "tsdown",
51
51
  "release": "pnpm dlx changelogen@latest --release --push --publish",
52
52
  "prepare": "simple-git-hooks",
53
53
  "prepublishOnly": "pnpm run build"
@@ -72,9 +72,9 @@
72
72
  "klona": "^2.0.6",
73
73
  "lint-staged": "^16.4.0",
74
74
  "simple-git-hooks": "^2.14.0",
75
+ "tsdown": "^0.23.0",
75
76
  "tsx": "^4.23.13",
76
77
  "typescript": "^5.9.3",
77
- "unbuild": "^3.6.1",
78
78
  "vitest": "^3.2.7"
79
79
  },
80
80
  "simple-git-hooks": {