@jaypie/express 1.2.4-rc0 → 1.2.4-rc2

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.
@@ -1,11 +1,11 @@
1
1
  import type { IncomingHttpHeaders } from "node:http";
2
2
  import { Readable } from "node:stream";
3
- import type { FunctionUrlEvent, LambdaContext } from "./types.js";
3
+ import type { LambdaContext, LambdaEvent } from "./types.js";
4
4
  interface LambdaRequestOptions {
5
5
  body?: Buffer | null;
6
6
  headers: Record<string, string>;
7
7
  lambdaContext: LambdaContext;
8
- lambdaEvent: FunctionUrlEvent;
8
+ lambdaEvent: LambdaEvent;
9
9
  method: string;
10
10
  protocol: string;
11
11
  remoteAddress: string;
@@ -37,7 +37,7 @@ export declare class LambdaRequest extends Readable {
37
37
  params: Record<string, string>;
38
38
  query: Record<string, unknown>;
39
39
  readonly _lambdaContext: LambdaContext;
40
- readonly _lambdaEvent: FunctionUrlEvent;
40
+ readonly _lambdaEvent: LambdaEvent;
41
41
  private bodyBuffer;
42
42
  private bodyPushed;
43
43
  constructor(options: LambdaRequestOptions);
@@ -47,7 +47,7 @@ export declare class LambdaRequest extends Readable {
47
47
  private normalizeHeaders;
48
48
  }
49
49
  /**
50
- * Create a LambdaRequest from a Function URL event.
50
+ * Create a LambdaRequest from a Lambda event (Function URL, HTTP API v2, or REST API v1).
51
51
  */
52
- export declare function createLambdaRequest(event: FunctionUrlEvent, context: LambdaContext): LambdaRequest;
52
+ export declare function createLambdaRequest(event: LambdaEvent, context: LambdaContext): LambdaRequest;
53
53
  export default LambdaRequest;
@@ -9,11 +9,7 @@ export declare class LambdaResponseBuffered extends Writable {
9
9
  statusCode: number;
10
10
  statusMessage: string;
11
11
  readonly socket: {
12
- cork: () => void;
13
- destroy: () => void;
14
12
  remoteAddress: string;
15
- uncork: () => void;
16
- writable: boolean;
17
13
  };
18
14
  private _chunks;
19
15
  private _headers;
@@ -9,11 +9,7 @@ export declare class LambdaResponseStreaming extends Writable {
9
9
  statusCode: number;
10
10
  statusMessage: string;
11
11
  readonly socket: {
12
- cork: () => void;
13
- destroy: () => void;
14
12
  remoteAddress: string;
15
- uncork: () => void;
16
- writable: boolean;
17
13
  };
18
14
  private _headers;
19
15
  private _headersSent;
@@ -1,12 +1,12 @@
1
1
  import type { Application } from "express";
2
- import type { CreateLambdaHandlerOptions, FunctionUrlEvent, LambdaContext, LambdaHandler, LambdaStreamHandler } from "./types.js";
2
+ import type { CreateLambdaHandlerOptions, LambdaContext, LambdaEvent, LambdaHandler, LambdaStreamHandler } from "./types.js";
3
3
  /**
4
4
  * Get the current Lambda invoke context.
5
5
  * Used by getCurrentInvokeUuid adapter to get the request ID.
6
6
  */
7
7
  export declare function getCurrentInvoke(): {
8
8
  context: LambdaContext;
9
- event: FunctionUrlEvent;
9
+ event: LambdaEvent;
10
10
  } | null;
11
11
  /**
12
12
  * Create a Lambda handler that buffers the Express response.
@@ -47,4 +47,4 @@ export declare function createLambdaStreamHandler(app: Application, _options?: C
47
47
  export { LambdaRequest, createLambdaRequest } from "./LambdaRequest.js";
48
48
  export { LambdaResponseBuffered } from "./LambdaResponseBuffered.js";
49
49
  export { LambdaResponseStreaming } from "./LambdaResponseStreaming.js";
50
- export type { AwsLambdaGlobal, CreateLambdaHandlerOptions, FunctionUrlEvent, HttpResponseStreamMetadata, LambdaContext, LambdaHandler, LambdaHandlerFactory, LambdaResponse, LambdaStreamHandler, LambdaStreamHandlerFactory, ResponseStream, } from "./types.js";
50
+ export type { ApiGatewayV1Event, AwsLambdaGlobal, CreateLambdaHandlerOptions, FunctionUrlEvent, HttpResponseStreamMetadata, LambdaContext, LambdaEvent, LambdaHandler, LambdaHandlerFactory, LambdaResponse, LambdaStreamHandler, LambdaStreamHandlerFactory, ResponseStream, } from "./types.js";
@@ -10,6 +10,37 @@ export interface LambdaContext {
10
10
  memoryLimitInMB?: string;
11
11
  [key: string]: unknown;
12
12
  }
13
+ export interface ApiGatewayV1Event {
14
+ body?: string | null;
15
+ headers: Record<string, string>;
16
+ httpMethod: string;
17
+ isBase64Encoded: boolean;
18
+ multiValueHeaders?: Record<string, string[]>;
19
+ multiValueQueryStringParameters?: Record<string, string[]> | null;
20
+ path: string;
21
+ pathParameters?: Record<string, string> | null;
22
+ queryStringParameters?: Record<string, string> | null;
23
+ requestContext: {
24
+ accountId: string;
25
+ apiId: string;
26
+ domainName?: string;
27
+ httpMethod: string;
28
+ identity: {
29
+ sourceIp: string;
30
+ userAgent?: string;
31
+ };
32
+ path: string;
33
+ protocol: string;
34
+ requestId: string;
35
+ requestTime?: string;
36
+ requestTimeEpoch?: number;
37
+ resourceId?: string;
38
+ resourcePath?: string;
39
+ stage: string;
40
+ };
41
+ resource?: string;
42
+ stageVariables?: Record<string, string> | null;
43
+ }
13
44
  export interface FunctionUrlEvent {
14
45
  body?: string;
15
46
  cookies?: string[];
@@ -38,6 +69,7 @@ export interface FunctionUrlEvent {
38
69
  routeKey: string;
39
70
  version: "2.0";
40
71
  }
72
+ export type LambdaEvent = ApiGatewayV1Event | FunctionUrlEvent;
41
73
  export interface LambdaResponse {
42
74
  body: string;
43
75
  cookies?: string[];
@@ -63,8 +95,8 @@ export interface AwsLambdaGlobal {
63
95
  };
64
96
  streamifyResponse<TEvent = unknown>(handler: (event: TEvent, responseStream: ResponseStream, context: LambdaContext) => Promise<void>): (event: TEvent, context: LambdaContext) => Promise<void>;
65
97
  }
66
- export type LambdaHandler = (event: FunctionUrlEvent, context: LambdaContext) => Promise<LambdaResponse>;
67
- export type LambdaStreamHandler = (event: FunctionUrlEvent, context: LambdaContext) => Promise<void>;
98
+ export type LambdaHandler = (event: LambdaEvent, context: LambdaContext) => Promise<LambdaResponse>;
99
+ export type LambdaStreamHandler = (event: LambdaEvent, context: LambdaContext) => Promise<void>;
68
100
  export type CreateLambdaHandlerOptions = {
69
101
  /**
70
102
  * Optional name for logging and debugging
@@ -81,16 +81,63 @@ class LambdaRequest extends node_stream.Readable {
81
81
  }
82
82
  //
83
83
  //
84
+ // Type Guards
85
+ //
86
+ /**
87
+ * Check if event is a Function URL / HTTP API v2 event.
88
+ */
89
+ function isFunctionUrlEvent(event) {
90
+ return "requestContext" in event && "http" in event.requestContext;
91
+ }
92
+ /**
93
+ * Check if event is an API Gateway REST API v1 event.
94
+ */
95
+ function isApiGatewayV1Event(event) {
96
+ return "httpMethod" in event;
97
+ }
98
+ //
99
+ //
84
100
  // Factory Function
85
101
  //
86
102
  /**
87
- * Create a LambdaRequest from a Function URL event.
103
+ * Create a LambdaRequest from a Lambda event (Function URL, HTTP API v2, or REST API v1).
88
104
  */
89
105
  function createLambdaRequest(event, context) {
90
- // Build URL with query string
91
- const url = event.rawQueryString
92
- ? `${event.rawPath}?${event.rawQueryString}`
93
- : event.rawPath;
106
+ let url;
107
+ let method;
108
+ let protocol;
109
+ let remoteAddress;
110
+ const headers = { ...event.headers };
111
+ if (isFunctionUrlEvent(event)) {
112
+ // Function URL / HTTP API v2 format
113
+ url = event.rawQueryString
114
+ ? `${event.rawPath}?${event.rawQueryString}`
115
+ : event.rawPath;
116
+ method = event.requestContext.http.method;
117
+ protocol = event.requestContext.http.protocol.split("/")[0].toLowerCase();
118
+ remoteAddress = event.requestContext.http.sourceIp;
119
+ // Normalize cookies into Cookie header if not already present
120
+ if (event.cookies && event.cookies.length > 0 && !headers.cookie) {
121
+ headers.cookie = event.cookies.join("; ");
122
+ }
123
+ }
124
+ else if (isApiGatewayV1Event(event)) {
125
+ // API Gateway REST API v1 format
126
+ const queryParams = event.queryStringParameters;
127
+ if (queryParams && Object.keys(queryParams).length > 0) {
128
+ const queryString = new URLSearchParams(queryParams).toString();
129
+ url = `${event.path}?${queryString}`;
130
+ }
131
+ else {
132
+ url = event.path;
133
+ }
134
+ method = event.httpMethod;
135
+ protocol = event.requestContext.protocol.split("/")[0].toLowerCase();
136
+ remoteAddress = event.requestContext.identity.sourceIp;
137
+ }
138
+ else {
139
+ throw new Error("Unsupported Lambda event format. Expected Function URL, HTTP API v2, or REST API v1 event.");
140
+ }
94
141
  // Decode body if present
95
142
  let body = null;
96
143
  if (event.body) {
@@ -98,19 +145,14 @@ function createLambdaRequest(event, context) {
98
145
  ? Buffer.from(event.body, "base64")
99
146
  : Buffer.from(event.body, "utf8");
100
147
  }
101
- // Normalize cookies into Cookie header if not already present
102
- const headers = { ...event.headers };
103
- if (event.cookies && event.cookies.length > 0 && !headers.cookie) {
104
- headers.cookie = event.cookies.join("; ");
105
- }
106
148
  return new LambdaRequest({
107
149
  body,
108
150
  headers,
109
151
  lambdaContext: context,
110
152
  lambdaEvent: event,
111
- method: event.requestContext.http.method,
112
- protocol: event.requestContext.http.protocol.split("/")[0].toLowerCase(),
113
- remoteAddress: event.requestContext.http.sourceIp,
153
+ method,
154
+ protocol,
155
+ remoteAddress,
114
156
  url,
115
157
  });
116
158
  }
@@ -143,11 +185,7 @@ class LambdaResponseBuffered extends node_stream.Writable {
143
185
  this.statusMessage = "OK";
144
186
  // Mock socket to satisfy Express/finalhandler checks
145
187
  this.socket = {
146
- cork: () => { },
147
- destroy: () => { },
148
188
  remoteAddress: "127.0.0.1",
149
- uncork: () => { },
150
- writable: true,
151
189
  };
152
190
  this._chunks = [];
153
191
  this._headers = new Map();
@@ -315,11 +353,7 @@ class LambdaResponseStreaming extends node_stream.Writable {
315
353
  this.statusMessage = "OK";
316
354
  // Mock socket to satisfy Express/finalhandler checks
317
355
  this.socket = {
318
- cork: () => { },
319
- destroy: () => { },
320
356
  remoteAddress: "127.0.0.1",
321
- uncork: () => { },
322
- writable: true,
323
357
  };
324
358
  this._headers = new Map();
325
359
  this._headersSent = false;