quantum-flow 1.3.7 → 1.3.10

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,13 +1,10 @@
1
- import { APIGatewayProxyEvent, APIGatewayProxyResult, Context, Handler } from 'aws-lambda';
2
- import { LambdaApp, LambdaRequest, LambdaResponse } from '../../types/index.js';
1
+ import { LambdaApp } from '../../types/index.js';
2
+ import { Handler } from 'aws-lambda';
3
3
  export declare class LambdaAdapter {
4
- private static getHeaderValue;
5
- static toRequest(event: APIGatewayProxyEvent, context: Context): LambdaRequest;
6
- static createResponseBody(response: any): any;
7
- static toLambdaResponse(response: any, request?: LambdaRequest): LambdaResponse;
8
- static createHandler(Contoller: new (...args: any[]) => LambdaApp): Handler<APIGatewayProxyEvent, APIGatewayProxyResult>;
9
- private static safeHeaders;
10
- private static safeParams;
4
+ static createHandler(Controller: new (...args: any[]) => LambdaApp): Handler;
5
+ private static getEventType;
6
+ private static toRequest;
7
+ private static toLambdaResponse;
8
+ private static handleError;
11
9
  private static getSourceIp;
12
- private static getUserAgent;
13
10
  }
@@ -1,244 +1,219 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.LambdaAdapter = void 0;
4
- const _constants_1 = require("../../constants.js");
5
4
  const _utils_1 = require("../../utils/index.js");
6
5
  class LambdaAdapter {
7
- static getHeaderValue(headers, headerName) {
8
- const value = headers?.[headerName] || headers?.[headerName.toLowerCase()];
9
- if (!value)
10
- return undefined;
11
- if (Array.isArray(value)) {
12
- return value[0];
6
+ static createHandler(Controller) {
7
+ return async (event, context) => {
8
+ const instance = new Controller();
9
+ if (Object.hasOwn(instance, 'beforeStart')) {
10
+ await instance.beforeStart?.();
11
+ }
12
+ try {
13
+ const eventType = this.getEventType(event);
14
+ const normalizedEvent = (0, _utils_1.normalizeEvent)(event, eventType);
15
+ const request = this.toRequest(normalizedEvent, context);
16
+ if (typeof instance.handleRequest !== 'function') {
17
+ throw new Error('Controller must have handleRequest method');
18
+ }
19
+ const response = await instance.handleRequest(request);
20
+ return this.toLambdaResponse(response, request, eventType);
21
+ }
22
+ catch (error) {
23
+ return this.handleError(error, event, context);
24
+ }
25
+ };
26
+ }
27
+ static getEventType(event) {
28
+ if (event.httpMethod && event.resource) {
29
+ return 'rest';
30
+ }
31
+ if (event.version === '2.0' || event.requestContext?.http) {
32
+ return 'http';
33
+ }
34
+ if (event.version && event.rawPath && !event.requestContext?.http) {
35
+ return 'url';
13
36
  }
14
- return value;
37
+ return 'rest';
15
38
  }
16
39
  static toRequest(event, context) {
17
40
  const query = {};
18
- if (event.queryStringParameters) {
41
+ if (event.multiValueQueryStringParameters) {
42
+ Object.entries(event.multiValueQueryStringParameters).forEach(([key, value]) => {
43
+ query[key] = value;
44
+ });
45
+ }
46
+ else {
19
47
  Object.entries(event.queryStringParameters).forEach(([key, value]) => {
20
- if (event.multiValueQueryStringParameters?.[key]) {
21
- query[key] = event.multiValueQueryStringParameters[key];
22
- }
23
- else {
24
- query[key] = value || '';
25
- }
48
+ query[key] = value;
26
49
  });
27
50
  }
28
51
  const cookies = {};
29
- const cookieHeader = event.headers?.Cookie || event.headers?.cookie;
52
+ const cookieHeader = event.headers?.Cookie || event.headers?.cookie || event.headers?.cookies;
30
53
  if (cookieHeader) {
31
- cookieHeader.split(';').forEach((cookie) => {
32
- const [name, value] = cookie.trim().split('=');
33
- if (name && value) {
34
- cookies[name] = decodeURIComponent(value);
35
- }
36
- });
37
- }
38
- let body = (0, _utils_1.ParseBody)(event);
39
- const protocol = event.headers?.['x-forwarded-proto'] || 'http';
40
- const host = event.headers?.host || 'localhost';
41
- const cleanPath = event.path.split('?')[0];
42
- const fullUrl = `${protocol}://${host}${cleanPath.startsWith('/') ? '' : '/'}${cleanPath}`;
43
- let url;
44
- try {
45
- url = new URL(fullUrl);
46
- if (event.queryStringParameters) {
47
- Object.entries(event.queryStringParameters).forEach(([key, value]) => {
48
- if (value)
49
- url.searchParams.append(key, value);
54
+ if (Array.isArray(cookieHeader)) {
55
+ cookieHeader.forEach((cookie) => {
56
+ const [name, value] = cookie.split('=');
57
+ if (name && value)
58
+ cookies[name] = decodeURIComponent(value);
59
+ });
60
+ }
61
+ else {
62
+ cookieHeader.split(';').forEach((cookie) => {
63
+ const [name, value] = cookie.trim().split('=');
64
+ if (name && value)
65
+ cookies[name] = decodeURIComponent(value);
50
66
  });
51
67
  }
52
68
  }
53
- catch (error) {
54
- console.error('❌ Failed to create URL:', fullUrl, error);
55
- url = new URL('http://localhost/');
69
+ let rawBody = Buffer.from(event.body ?? '', 'base64');
70
+ let body = event.body || {};
71
+ if (event.body && event.isBase64Encoded) {
72
+ body = rawBody.toString('utf-8');
73
+ }
74
+ if (typeof body === 'string' && body.trim().startsWith('{')) {
75
+ try {
76
+ body = JSON.parse(body);
77
+ }
78
+ catch (e) { }
56
79
  }
80
+ const xForvarded = Array.isArray(event.headers['x-forwarded-proto'])
81
+ ? event.headers['x-forwarded-proto']?.[0]
82
+ : event.headers['x-forwarded-proto'];
83
+ const xhost = Array.isArray(event.headers['host'])
84
+ ? event.headers['host']?.[0]
85
+ : event.headers['host'];
86
+ const protocol = xForvarded || 'https';
87
+ const host = xhost || 'localhost:3000';
88
+ const fullUrl = `${protocol}://${host}${event.path}`;
89
+ let url = new URL(fullUrl);
57
90
  return {
58
- method: event.httpMethod,
59
- path: cleanPath,
91
+ method: event.httpMethod.toUpperCase(),
60
92
  url,
61
- headers: this.safeHeaders(event.headers),
93
+ headers: event.headers,
62
94
  query,
63
95
  body,
64
- params: this.safeParams(event.pathParameters),
96
+ params: event.pathParameters,
65
97
  cookies,
66
98
  event,
67
99
  context,
68
- isBase64Encoded: event.isBase64Encoded || false,
100
+ rawBody,
101
+ path: event.path,
102
+ isBase64Encoded: event.isBase64Encoded,
69
103
  requestId: context.awsRequestId,
70
104
  stage: event.requestContext?.stage || '$default',
71
105
  sourceIp: this.getSourceIp(event),
72
- userAgent: this.getUserAgent(event),
106
+ _startTime: Date.now(),
107
+ userAgent: typeof event.headers['user-agent'] === 'string'
108
+ ? event.headers['user-agent']
109
+ : event.headers['user-agent']?.[0] || 'unknown',
73
110
  };
74
111
  }
75
- static createResponseBody(response) {
76
- let body = response;
77
- if (response && typeof response === 'object') {
78
- if ('data' in response) {
79
- body = {
80
- data: response.data,
81
- timestamp: new Date().toISOString(),
82
- };
83
- }
84
- else if (response.body) {
85
- return response;
86
- }
87
- else {
88
- body = {
89
- data: response,
90
- timestamp: new Date().toISOString(),
91
- };
92
- }
93
- }
94
- return body;
95
- }
96
- static toLambdaResponse(response, request) {
97
- let statusCode = response.status ?? 200;
98
- let body = this.createResponseBody(response);
99
- let headers = {
112
+ static toLambdaResponse(response, request, eventType) {
113
+ const statusCode = response.status || 200;
114
+ const headers = {
100
115
  'Content-Type': 'application/json',
101
- 'X-Request-Id': request?.requestId || 'unknown',
102
- 'X-Powered-By': 'Lambda Decorators',
116
+ 'X-Request-Id': request.requestId,
117
+ ...(response.headers || {}),
103
118
  };
104
- const cookies = [];
105
- if (response && typeof response === 'object') {
106
- if ('data' in response) {
107
- body = {
108
- success: _constants_1.OK_STATUSES.includes(statusCode),
109
- data: response.data,
110
- timestamp: new Date().toISOString(),
111
- requestId: request?.requestId,
112
- };
113
- }
114
- else if (response.body) {
115
- return response;
119
+ const originHeader = request.headers['origin'] || request.headers['Origin'];
120
+ let origin;
121
+ if (originHeader) {
122
+ if (Array.isArray(originHeader)) {
123
+ origin = originHeader[0];
116
124
  }
117
125
  else {
118
- body = {
119
- success: _constants_1.OK_STATUSES.includes(statusCode),
120
- data: response,
121
- timestamp: new Date().toISOString(),
122
- requestId: request?.requestId,
123
- };
126
+ origin = originHeader;
124
127
  }
125
128
  }
126
- let origin = LambdaAdapter.getHeaderValue(request?.headers, 'origin');
127
- const originHeader = Array.isArray(origin) ? origin[0] : origin;
128
- if (originHeader) {
129
- headers['Access-Control-Allow-Origin'] = originHeader;
129
+ if (origin) {
130
+ headers['Access-Control-Allow-Origin'] = origin;
130
131
  headers['Access-Control-Allow-Credentials'] = 'true';
131
132
  headers['Access-Control-Allow-Methods'] = 'GET,POST,PUT,DELETE,OPTIONS';
132
133
  headers['Access-Control-Allow-Headers'] =
133
134
  'Content-Type,Authorization,X-Amz-Date,X-Api-Key,X-Amz-Security-Token';
134
135
  }
135
- if (request?.cookies && Object.keys(request.cookies).length > 0) {
136
- Object.entries(request.cookies).forEach(([name, value]) => {
137
- cookies.push(`${name}=${encodeURIComponent(value)}; Path=/; HttpOnly`);
138
- });
139
- }
140
- const lambdaResponse = {
136
+ const body = JSON.stringify({
137
+ success: statusCode < 400,
138
+ data: response.data,
139
+ timestamp: new Date().toISOString(),
140
+ });
141
+ const commonResponse = {
141
142
  statusCode,
142
143
  headers,
143
- body: JSON.stringify(body),
144
- isBase64Encoded: false,
144
+ body: response.data,
145
+ timestamp: new Date().toISOString(),
145
146
  };
146
- if (cookies.length > 0) {
147
- lambdaResponse.cookies = cookies;
148
- }
149
- if (cookies.length > 0) {
150
- lambdaResponse.multiValueHeaders = {
151
- 'Set-Cookie': cookies,
152
- };
153
- }
154
- return lambdaResponse;
155
- }
156
- static createHandler(Contoller) {
157
- const handler = async (event, context) => {
158
- const instance = new Contoller();
159
- if (Object.hasOwn(instance, 'beforeStart')) {
160
- await instance.beforeStart?.();
161
- }
162
- try {
163
- const request = LambdaAdapter.toRequest(event, context);
164
- if (typeof instance.handleRequest === 'function') {
165
- const response = await instance.handleRequest(request);
166
- return LambdaAdapter.toLambdaResponse(response, request);
167
- }
168
- else {
169
- throw new Error('Controller must have handleRequest method');
170
- }
171
- }
172
- catch (error) {
173
- console.error('❌ Lambda error:', error);
174
- const errorResponse = {
175
- statusCode: error.status || 500,
176
- headers: {
177
- 'Content-Type': 'application/json',
178
- 'X-Request-Id': context.awsRequestId,
179
- 'Access-Control-Allow-Origin': event.headers?.origin || event.headers?.Origin || '*',
180
- 'Access-Control-Allow-Credentials': 'true',
181
- },
182
- body: JSON.stringify({
183
- success: false,
184
- message: error.message || 'Internal Server Error',
185
- requestId: context.awsRequestId,
186
- }),
147
+ switch (eventType) {
148
+ case 'rest':
149
+ return { ...commonResponse, isBase64Encoded: false };
150
+ case 'http':
151
+ return {
152
+ ...commonResponse,
153
+ cookies: request.cookies
154
+ ? Object.entries(request.cookies).map(([k, v]) => `${k}=${encodeURIComponent(v)}`)
155
+ : undefined,
187
156
  };
188
- if (error.cookies) {
189
- errorResponse.cookies = error.cookies;
190
- }
191
- return errorResponse;
192
- }
193
- };
194
- return handler;
195
- }
196
- static safeHeaders(headers) {
197
- const result = {};
198
- if (!headers)
199
- return result;
200
- Object.entries(headers).forEach(([key, value]) => {
201
- if (value !== undefined) {
202
- result[key] = value;
203
- }
204
- });
205
- return result;
157
+ case 'url':
158
+ return {
159
+ ...commonResponse,
160
+ cookies: request.cookies
161
+ ? Object.entries(request.cookies).map(([k, v]) => `${k}=${encodeURIComponent(v)}`)
162
+ : undefined,
163
+ };
164
+ default:
165
+ return {
166
+ statusCode,
167
+ headers,
168
+ body,
169
+ };
170
+ }
206
171
  }
207
- static safeParams(params) {
208
- const result = {};
209
- if (!params)
210
- return result;
211
- Object.entries(params).forEach(([key, value]) => {
212
- if (value !== undefined) {
213
- result[key] = value;
214
- }
172
+ static handleError(error, event, context) {
173
+ const eventType = this.getEventType(event);
174
+ const statusCode = error.status || 500;
175
+ const body = JSON.stringify({
176
+ success: false,
177
+ message: error.message || 'Internal Server Error',
178
+ requestId: context.awsRequestId,
215
179
  });
216
- return result;
180
+ const headers = {
181
+ 'Content-Type': 'application/json',
182
+ 'X-Request-Id': context.awsRequestId,
183
+ 'Access-Control-Allow-Origin': '*',
184
+ 'Access-Control-Allow-Credentials': 'true',
185
+ };
186
+ switch (eventType) {
187
+ case 'rest':
188
+ return {
189
+ statusCode,
190
+ headers,
191
+ body,
192
+ isBase64Encoded: false,
193
+ };
194
+ default:
195
+ return {
196
+ statusCode,
197
+ headers,
198
+ body,
199
+ };
200
+ }
217
201
  }
218
202
  static getSourceIp(event) {
219
- if (event.requestContext?.identity?.sourceIp) {
220
- return event.requestContext.identity.sourceIp;
221
- }
222
- const forwardedFor = event.headers?.['x-forwarded-for'];
203
+ const forwardedFor = event.headers['x-forwarded-for'];
223
204
  if (forwardedFor) {
224
- if (typeof forwardedFor === 'string') {
225
- return forwardedFor.split(',')[0].trim();
226
- }
227
- if (Array.isArray(forwardedFor) && forwardedFor.length > 0) {
205
+ if (Array.isArray(forwardedFor)) {
228
206
  return forwardedFor[0].split(',')[0].trim();
229
207
  }
208
+ return forwardedFor.split(',')[0].trim();
209
+ }
210
+ if (event.requestContext?.identity?.sourceIp) {
211
+ return event.requestContext.identity.sourceIp;
212
+ }
213
+ if (event.requestContext?.http?.sourceIp) {
214
+ return event.requestContext.http.sourceIp;
230
215
  }
231
216
  return '0.0.0.0';
232
217
  }
233
- static getUserAgent(event) {
234
- const ua = event.headers?.['user-agent'];
235
- if (!ua)
236
- return 'unknown';
237
- if (typeof ua === 'string')
238
- return ua;
239
- if (Array.isArray(ua) && ua.length > 0)
240
- return ua[0];
241
- return 'unknown';
242
- }
243
218
  }
244
219
  exports.LambdaAdapter = LambdaAdapter;
@@ -0,0 +1,5 @@
1
+ import 'reflect-metadata';
2
+ export declare class Root {
3
+ }
4
+ export declare class App {
5
+ }
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.App = exports.Root = void 0;
10
+ const core_1 = require("quantum-flow/core");
11
+ const http_1 = require("quantum-flow/http");
12
+ require("reflect-metadata");
13
+ const user_1 = require("./controllers/user");
14
+ let Root = class Root {
15
+ };
16
+ exports.Root = Root;
17
+ exports.Root = Root = __decorate([
18
+ (0, core_1.Controller)({ prefix: 'api', controllers: [user_1.User] })
19
+ ], Root);
20
+ let App = class App {
21
+ };
22
+ exports.App = App;
23
+ exports.App = App = __decorate([
24
+ (0, http_1.Server)({
25
+ controllers: [Root],
26
+ websocket: { enabled: true },
27
+ interceptor: (data) => data,
28
+ errorHandler: (err) => err,
29
+ }),
30
+ (0, http_1.Port)(3000),
31
+ (0, core_1.Use)((data) => data),
32
+ (0, core_1.Use)((data) => data),
33
+ (0, core_1.Catch)((err) => err)
34
+ ], App);
@@ -1,3 +1,7 @@
1
1
  export declare class UserMetadata {
2
2
  getUserMetadata(params: any): Promise<any>;
3
+ createMeta(body: any, params: any): Promise<{
4
+ body: any;
5
+ params: any;
6
+ }>;
3
7
  }
@@ -27,6 +27,9 @@ let UserMetadata = class UserMetadata {
27
27
  async getUserMetadata(params) {
28
28
  return params;
29
29
  }
30
+ async createMeta(body, params) {
31
+ return { body, params };
32
+ }
30
33
  };
31
34
  exports.UserMetadata = UserMetadata;
32
35
  __decorate([
@@ -36,6 +39,14 @@ __decorate([
36
39
  __metadata("design:paramtypes", [Object]),
37
40
  __metadata("design:returntype", Promise)
38
41
  ], UserMetadata.prototype, "getUserMetadata", null);
42
+ __decorate([
43
+ (0, core_1.POST)('/:meta'),
44
+ __param(0, (0, core_1.Body)()),
45
+ __param(1, (0, core_1.Params)(DTO, 'meta')),
46
+ __metadata("design:type", Function),
47
+ __metadata("design:paramtypes", [Object, Object]),
48
+ __metadata("design:returntype", Promise)
49
+ ], UserMetadata.prototype, "createMeta", null);
39
50
  exports.UserMetadata = UserMetadata = __decorate([
40
51
  (0, core_1.Controller)({ prefix: 'metadata' })
41
52
  ], UserMetadata);
@@ -0,0 +1 @@
1
+ export declare const handler: import("aws-lambda").Handler;
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.handler = void 0;
4
+ const app_1 = require("./app");
5
+ const aws_1 = require("quantum-flow/aws");
6
+ exports.handler = aws_1.LambdaAdapter.createHandler(app_1.Root);
@@ -0,0 +1,14 @@
1
+ export declare const mockContext: {
2
+ awsRequestId: string;
3
+ functionName: string;
4
+ functionVersion: string;
5
+ invokedFunctionArn: string;
6
+ memoryLimitInMB: string;
7
+ logGroupName: string;
8
+ logStreamName: string;
9
+ getRemainingTimeInMillis: () => number;
10
+ callbackWaitsForEmptyEventLoop: boolean;
11
+ done: () => void;
12
+ fail: () => void;
13
+ succeed: () => void;
14
+ };
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.mockContext = void 0;
4
+ exports.mockContext = {
5
+ awsRequestId: 'local-req-id-123456',
6
+ functionName: 'localFunction',
7
+ functionVersion: '$LATEST',
8
+ invokedFunctionArn: 'arn:aws:lambda:local:123456789012:function:localFunction',
9
+ memoryLimitInMB: '128',
10
+ logGroupName: '/aws/lambda/localFunction',
11
+ logStreamName: '2023/01/01/[$LATEST]abcdefghijk',
12
+ getRemainingTimeInMillis: () => 30000,
13
+ callbackWaitsForEmptyEventLoop: true,
14
+ done: () => { },
15
+ fail: () => { },
16
+ succeed: () => { },
17
+ };
@@ -1 +1 @@
1
- import 'reflect-metadata';
1
+ export {};
@@ -1,37 +1,6 @@
1
1
  "use strict";
2
- var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
- var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
- if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
- else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
- return c > 3 && r && Object.defineProperty(target, key, r), r;
7
- };
8
2
  Object.defineProperty(exports, "__esModule", { value: true });
9
- const core_1 = require("quantum-flow/core");
10
3
  const http_1 = require("quantum-flow/http");
11
- require("reflect-metadata");
12
- const user_1 = require("./controllers/user");
13
- let Root = class Root {
14
- };
15
- Root = __decorate([
16
- (0, core_1.Controller)({ prefix: 'api', controllers: [user_1.User] })
17
- ], Root);
18
- let App =
19
- // @Catch((error) => ({ status: 400, error }))
20
- class App {
21
- };
22
- App = __decorate([
23
- (0, http_1.Server)({
24
- controllers: [Root],
25
- websocket: { enabled: true },
26
- interceptor: (data) => data,
27
- errorHandler: (err) => {
28
- return err;
29
- },
30
- }),
31
- (0, http_1.Port)(3000),
32
- (0, core_1.Use)((data) => data),
33
- (0, core_1.Use)((data) => data)
34
- // @Catch((error) => ({ status: 400, error }))
35
- ], App);
36
- const server = new http_1.HttpServer(App);
4
+ const app_1 = require("./app");
5
+ const server = new http_1.HttpServer(app_1.App);
37
6
  server.listen().catch(console.error);
@@ -12,6 +12,7 @@ export interface HttpError extends Error {
12
12
  export type AppRequest<B = unknown, Q extends P_Q = unknown, P extends P_Q = unknown> = {
13
13
  method: HTTP_METHODS;
14
14
  url: URL;
15
+ path?: string;
15
16
  headers: IncomingHttpHeaders;
16
17
  query?: Q;
17
18
  params?: P;
@@ -20,6 +21,12 @@ export type AppRequest<B = unknown, Q extends P_Q = unknown, P extends P_Q = unk
20
21
  isBase64Encoded?: boolean;
21
22
  cookies: Record<string, string>;
22
23
  _startTime: number;
24
+ event?: any;
25
+ context?: any;
26
+ requestId?: string;
27
+ stage?: string;
28
+ sourceIp?: string;
29
+ userAgent?: string;
23
30
  };
24
31
  export type Router = (req: AppRequest, res?: ServerResponse) => Promise<{
25
32
  status: number;
@@ -1,4 +1,44 @@
1
- import { APIGatewayProxyEvent, Context } from 'aws-lambda';
1
+ import { APIGatewayProxyEvent, APIGatewayProxyEventV2, Context } from 'aws-lambda';
2
+ export interface LambdaFunctionUrlEvent {
3
+ version: string;
4
+ routeKey: string;
5
+ rawPath: string;
6
+ rawQueryString: string;
7
+ headers: Record<string, string>;
8
+ body?: string;
9
+ isBase64Encoded?: boolean;
10
+ requestContext: {
11
+ accountId: string;
12
+ apiId: string;
13
+ domainName: string;
14
+ domainPrefix: string;
15
+ http: {
16
+ method: string;
17
+ path: string;
18
+ protocol: string;
19
+ sourceIp: string;
20
+ userAgent: string;
21
+ };
22
+ requestId: string;
23
+ routeKey: string;
24
+ stage: string;
25
+ time: string;
26
+ timeEpoch: number;
27
+ };
28
+ }
29
+ export type LambdaEvent = APIGatewayProxyEvent | APIGatewayProxyEventV2 | LambdaFunctionUrlEvent;
30
+ export interface NormalizedEvent {
31
+ httpMethod: string;
32
+ path: string;
33
+ headers: Record<string, string | string[]>;
34
+ queryStringParameters: Record<string, string>;
35
+ multiValueQueryStringParameters?: Record<string, string[]>;
36
+ pathParameters: Record<string, string>;
37
+ body: string | null;
38
+ isBase64Encoded: boolean;
39
+ cookies?: string[];
40
+ requestContext: any;
41
+ }
2
42
  export interface LambdaRequest {
3
43
  method: string;
4
44
  path: string;
@@ -14,7 +54,8 @@ export interface LambdaRequest {
14
54
  sourceIp: string;
15
55
  userAgent: string;
16
56
  url: URL;
17
- event: APIGatewayProxyEvent;
57
+ event: NormalizedEvent;
58
+ _startTime: number;
18
59
  }
19
60
  export interface LambdaResponse {
20
61
  statusCode: number;
@@ -1,8 +1,9 @@
1
1
  export * from './controller';
2
+ export * from './endpoint';
2
3
  export * from './helper';
4
+ export * from './lambda';
3
5
  export * from './multipart';
4
6
  export * from './parsers';
5
7
  export * from './server';
6
8
  export * from './transform';
7
9
  export * from './validate';
8
- export * from './endpoint';
@@ -15,10 +15,11 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./controller"), exports);
18
+ __exportStar(require("./endpoint"), exports);
18
19
  __exportStar(require("./helper"), exports);
20
+ __exportStar(require("./lambda"), exports);
19
21
  __exportStar(require("./multipart"), exports);
20
22
  __exportStar(require("./parsers"), exports);
21
23
  __exportStar(require("./server"), exports);
22
24
  __exportStar(require("./transform"), exports);
23
25
  __exportStar(require("./validate"), exports);
24
- __exportStar(require("./endpoint"), exports);
@@ -0,0 +1,2 @@
1
+ import { NormalizedEvent } from '../types/index.js';
2
+ export declare const normalizeEvent: (event: any, type: string) => NormalizedEvent;
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.normalizeEvent = void 0;
4
+ const parseQueryString = (queryString) => {
5
+ const params = {};
6
+ if (!queryString)
7
+ return params;
8
+ new URLSearchParams(queryString).forEach((value, key) => {
9
+ params[key] = value;
10
+ });
11
+ return params;
12
+ };
13
+ const normalizeEvent = (event, type) => {
14
+ const base = {
15
+ headers: event.headers || {},
16
+ body: event.body || null,
17
+ isBase64Encoded: event.isBase64Encoded || false,
18
+ requestContext: event.requestContext,
19
+ };
20
+ switch (type) {
21
+ case 'rest':
22
+ return {
23
+ ...base,
24
+ httpMethod: event.httpMethod,
25
+ path: event.path,
26
+ queryStringParameters: event.queryStringParameters || {},
27
+ multiValueQueryStringParameters: event.multiValueQueryStringParameters,
28
+ pathParameters: event.pathParameters || {},
29
+ cookies: event.headers?.Cookie ? [event.headers.Cookie] : [],
30
+ };
31
+ case 'http':
32
+ return {
33
+ ...base,
34
+ httpMethod: event.requestContext?.http?.method || 'GET',
35
+ path: event.rawPath,
36
+ queryStringParameters: event.queryStringParameters || {},
37
+ pathParameters: event.pathParameters || {},
38
+ cookies: event.cookies || [],
39
+ };
40
+ case 'url':
41
+ return {
42
+ ...base,
43
+ httpMethod: event.requestContext?.http?.method || 'GET',
44
+ path: event.rawPath,
45
+ queryStringParameters: parseQueryString(event.rawQueryString),
46
+ pathParameters: {},
47
+ cookies: [],
48
+ };
49
+ default:
50
+ throw new Error(`Unsupported event type: ${type}`);
51
+ }
52
+ };
53
+ exports.normalizeEvent = normalizeEvent;
@@ -13,7 +13,7 @@ const resolveConfig = (configOrClass) => {
13
13
  port: 3000,
14
14
  host: 'localhost',
15
15
  ...decoratorConfig,
16
- errorHandler,
16
+ errorHandler: decoratorConfig.errorHandler ?? errorHandler,
17
17
  interceptors,
18
18
  controllers: [...controllers, ...(decoratorConfig.controllers || [])],
19
19
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "quantum-flow",
3
- "version": "1.3.7",
3
+ "version": "1.3.10",
4
4
  "description": "Decorator-based API framework",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",