serverless-event-orchestrator 1.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +377 -0
- package/dist/dispatcher.d.ts +18 -0
- package/dist/dispatcher.d.ts.map +1 -0
- package/dist/dispatcher.js +345 -0
- package/dist/dispatcher.js.map +1 -0
- package/dist/http/body-parser.d.ts +27 -0
- package/dist/http/body-parser.d.ts.map +1 -0
- package/dist/http/body-parser.js +56 -0
- package/dist/http/body-parser.js.map +1 -0
- package/dist/http/cors.d.ts +32 -0
- package/dist/http/cors.d.ts.map +1 -0
- package/dist/http/cors.js +69 -0
- package/dist/http/cors.js.map +1 -0
- package/dist/http/index.d.ts +4 -0
- package/dist/http/index.d.ts.map +1 -0
- package/dist/http/index.js +20 -0
- package/dist/http/index.js.map +1 -0
- package/dist/http/response.d.ts +104 -0
- package/dist/http/response.d.ts.map +1 -0
- package/dist/http/response.js +164 -0
- package/dist/http/response.js.map +1 -0
- package/dist/identity/extractor.d.ts +39 -0
- package/dist/identity/extractor.d.ts.map +1 -0
- package/dist/identity/extractor.js +88 -0
- package/dist/identity/extractor.js.map +1 -0
- package/dist/identity/index.d.ts +2 -0
- package/dist/identity/index.d.ts.map +1 -0
- package/dist/identity/index.js +18 -0
- package/dist/identity/index.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +62 -0
- package/dist/index.js.map +1 -0
- package/dist/types/event-type.enum.d.ts +20 -0
- package/dist/types/event-type.enum.d.ts.map +1 -0
- package/dist/types/event-type.enum.js +25 -0
- package/dist/types/event-type.enum.js.map +1 -0
- package/dist/types/index.d.ts +3 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +19 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/routes.d.ts +163 -0
- package/dist/types/routes.d.ts.map +1 -0
- package/dist/types/routes.js +3 -0
- package/dist/types/routes.js.map +1 -0
- package/dist/utils/headers.d.ts +28 -0
- package/dist/utils/headers.d.ts.map +1 -0
- package/dist/utils/headers.js +61 -0
- package/dist/utils/headers.js.map +1 -0
- package/dist/utils/index.d.ts +3 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +19 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/path-matcher.d.ts +33 -0
- package/dist/utils/path-matcher.d.ts.map +1 -0
- package/dist/utils/path-matcher.js +74 -0
- package/dist/utils/path-matcher.js.map +1 -0
- package/jest.config.js +32 -0
- package/package.json +68 -0
- package/src/dispatcher.ts +415 -0
- package/src/http/body-parser.ts +60 -0
- package/src/http/cors.ts +76 -0
- package/src/http/index.ts +3 -0
- package/src/http/response.ts +194 -0
- package/src/identity/extractor.ts +89 -0
- package/src/identity/index.ts +1 -0
- package/src/index.ts +92 -0
- package/src/types/event-type.enum.ts +20 -0
- package/src/types/index.ts +2 -0
- package/src/types/routes.ts +182 -0
- package/src/utils/headers.ts +72 -0
- package/src/utils/index.ts +2 -0
- package/src/utils/path-matcher.ts +79 -0
- package/tests/cors.test.ts +133 -0
- package/tests/dispatcher.test.ts +425 -0
- package/tests/headers.test.ts +99 -0
- package/tests/identity.test.ts +171 -0
- package/tests/path-matcher.test.ts +102 -0
- package/tests/response.test.ts +155 -0
- package/tsconfig.json +24 -0
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.detectEventType = detectEventType;
|
|
4
|
+
exports.dispatchEvent = dispatchEvent;
|
|
5
|
+
exports.createOrchestrator = createOrchestrator;
|
|
6
|
+
const event_type_enum_js_1 = require("./types/event-type.enum.js");
|
|
7
|
+
const path_matcher_js_1 = require("./utils/path-matcher.js");
|
|
8
|
+
const headers_js_1 = require("./utils/headers.js");
|
|
9
|
+
const body_parser_js_1 = require("./http/body-parser.js");
|
|
10
|
+
const extractor_js_1 = require("./identity/extractor.js");
|
|
11
|
+
const response_js_1 = require("./http/response.js");
|
|
12
|
+
/**
|
|
13
|
+
* Detects the type of AWS event
|
|
14
|
+
*/
|
|
15
|
+
function detectEventType(event) {
|
|
16
|
+
if (event.source === 'EVENT_BRIDGE')
|
|
17
|
+
return event_type_enum_js_1.EventType.EventBridge;
|
|
18
|
+
if (event.requestContext && event.httpMethod)
|
|
19
|
+
return event_type_enum_js_1.EventType.ApiGateway;
|
|
20
|
+
if (event.Records && Array.isArray(event.Records) && event.Records[0]?.eventSource === 'aws:sqs')
|
|
21
|
+
return event_type_enum_js_1.EventType.Sqs;
|
|
22
|
+
if (event.awsRequestId)
|
|
23
|
+
return event_type_enum_js_1.EventType.Lambda;
|
|
24
|
+
return event_type_enum_js_1.EventType.Unknown;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Checks if a router is segmented (has public/private/backoffice/internal keys)
|
|
28
|
+
*/
|
|
29
|
+
function isSegmentedRouter(router) {
|
|
30
|
+
if (!router || typeof router !== 'object')
|
|
31
|
+
return false;
|
|
32
|
+
const segmentKeys = ['public', 'private', 'backoffice', 'internal'];
|
|
33
|
+
const routerKeys = Object.keys(router);
|
|
34
|
+
return routerKeys.some(key => segmentKeys.includes(key));
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Checks if a segment config has middleware
|
|
38
|
+
*/
|
|
39
|
+
function isSegmentConfig(config) {
|
|
40
|
+
return config && typeof config === 'object' && 'routes' in config;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Gets the HttpRouter from a segment (handles both simple and advanced config)
|
|
44
|
+
*/
|
|
45
|
+
function getRouterFromSegment(segment) {
|
|
46
|
+
if (!segment)
|
|
47
|
+
return undefined;
|
|
48
|
+
if (isSegmentConfig(segment))
|
|
49
|
+
return segment.routes;
|
|
50
|
+
return segment;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Gets middleware from a segment config
|
|
54
|
+
*/
|
|
55
|
+
function getMiddlewareFromSegment(segment) {
|
|
56
|
+
if (!segment)
|
|
57
|
+
return [];
|
|
58
|
+
if (isSegmentConfig(segment))
|
|
59
|
+
return segment.middleware ?? [];
|
|
60
|
+
return [];
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Finds a matching route using pattern for lookup and actualPath for params extraction
|
|
64
|
+
*/
|
|
65
|
+
function findRouteInRouterWithActualPath(router, method, routePattern, actualPath) {
|
|
66
|
+
if (!router)
|
|
67
|
+
return null;
|
|
68
|
+
const methodRoutes = router[method];
|
|
69
|
+
if (!methodRoutes)
|
|
70
|
+
return null;
|
|
71
|
+
const normalizedPattern = (0, path_matcher_js_1.normalizePath)(routePattern);
|
|
72
|
+
const normalizedActualPath = (0, path_matcher_js_1.normalizePath)(actualPath);
|
|
73
|
+
// First, try exact match with the pattern
|
|
74
|
+
if (methodRoutes[normalizedPattern]) {
|
|
75
|
+
// Extract params from the actual path using the pattern
|
|
76
|
+
const params = (0, path_matcher_js_1.matchPath)(normalizedPattern, normalizedActualPath) ?? {};
|
|
77
|
+
return { config: methodRoutes[normalizedPattern], params };
|
|
78
|
+
}
|
|
79
|
+
// Then, try pattern matching
|
|
80
|
+
for (const [pattern, config] of Object.entries(methodRoutes)) {
|
|
81
|
+
const params = (0, path_matcher_js_1.matchPath)(pattern, normalizedActualPath);
|
|
82
|
+
if (params !== null) {
|
|
83
|
+
return { config, params };
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Finds a route across all segments with actual path for params
|
|
90
|
+
*/
|
|
91
|
+
function findRouteInSegmentsWithActualPath(router, method, routePattern, actualPath) {
|
|
92
|
+
const segments = [
|
|
93
|
+
event_type_enum_js_1.RouteSegment.Public,
|
|
94
|
+
event_type_enum_js_1.RouteSegment.Private,
|
|
95
|
+
event_type_enum_js_1.RouteSegment.Backoffice,
|
|
96
|
+
event_type_enum_js_1.RouteSegment.Internal,
|
|
97
|
+
];
|
|
98
|
+
for (const segment of segments) {
|
|
99
|
+
const segmentRouter = router[segment];
|
|
100
|
+
const httpRouter = getRouterFromSegment(segmentRouter);
|
|
101
|
+
const result = findRouteInRouterWithActualPath(httpRouter, method, routePattern, actualPath);
|
|
102
|
+
if (result) {
|
|
103
|
+
return {
|
|
104
|
+
handler: result.config.handler,
|
|
105
|
+
params: result.params,
|
|
106
|
+
segment,
|
|
107
|
+
middleware: getMiddlewareFromSegment(segmentRouter),
|
|
108
|
+
config: result.config,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Normalizes an API Gateway event into a standard format
|
|
116
|
+
*/
|
|
117
|
+
function normalizeApiGatewayEvent(event, segment, params) {
|
|
118
|
+
const identity = (0, extractor_js_1.extractIdentity)(event);
|
|
119
|
+
return {
|
|
120
|
+
eventRaw: event,
|
|
121
|
+
eventType: event_type_enum_js_1.EventType.ApiGateway,
|
|
122
|
+
payload: {
|
|
123
|
+
body: (0, body_parser_js_1.parseJsonBody)(event.body, event.isBase64Encoded),
|
|
124
|
+
pathParameters: { ...event.pathParameters, ...params },
|
|
125
|
+
queryStringParameters: (0, body_parser_js_1.parseQueryParams)(event.queryStringParameters),
|
|
126
|
+
headers: (0, headers_js_1.normalizeHeaders)(event.headers),
|
|
127
|
+
},
|
|
128
|
+
params,
|
|
129
|
+
context: {
|
|
130
|
+
segment,
|
|
131
|
+
identity,
|
|
132
|
+
requestId: event.requestContext?.requestId,
|
|
133
|
+
},
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Normalizes an EventBridge event
|
|
138
|
+
*/
|
|
139
|
+
function normalizeEventBridgeEvent(event) {
|
|
140
|
+
return {
|
|
141
|
+
eventRaw: event,
|
|
142
|
+
eventType: event_type_enum_js_1.EventType.EventBridge,
|
|
143
|
+
payload: {
|
|
144
|
+
body: event.detail,
|
|
145
|
+
},
|
|
146
|
+
params: {},
|
|
147
|
+
context: {
|
|
148
|
+
segment: event_type_enum_js_1.RouteSegment.Internal,
|
|
149
|
+
requestId: event.id,
|
|
150
|
+
},
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Normalizes an SQS event
|
|
155
|
+
*/
|
|
156
|
+
function normalizeSqsEvent(event) {
|
|
157
|
+
const record = event.Records[0];
|
|
158
|
+
let body = {};
|
|
159
|
+
try {
|
|
160
|
+
body = JSON.parse(record.body);
|
|
161
|
+
}
|
|
162
|
+
catch {
|
|
163
|
+
body = { rawBody: record.body };
|
|
164
|
+
}
|
|
165
|
+
return {
|
|
166
|
+
eventRaw: event,
|
|
167
|
+
eventType: event_type_enum_js_1.EventType.Sqs,
|
|
168
|
+
payload: {
|
|
169
|
+
body,
|
|
170
|
+
},
|
|
171
|
+
params: {},
|
|
172
|
+
context: {
|
|
173
|
+
segment: event_type_enum_js_1.RouteSegment.Internal,
|
|
174
|
+
requestId: record.messageId,
|
|
175
|
+
},
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Normalizes a Lambda invocation event
|
|
180
|
+
*/
|
|
181
|
+
function normalizeLambdaEvent(event) {
|
|
182
|
+
return {
|
|
183
|
+
eventRaw: event,
|
|
184
|
+
eventType: event_type_enum_js_1.EventType.Lambda,
|
|
185
|
+
payload: {
|
|
186
|
+
body: event,
|
|
187
|
+
},
|
|
188
|
+
params: {},
|
|
189
|
+
context: {
|
|
190
|
+
segment: event_type_enum_js_1.RouteSegment.Internal,
|
|
191
|
+
},
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Validates User Pool for a segment
|
|
196
|
+
*/
|
|
197
|
+
function validateSegmentUserPool(normalized, segment, config) {
|
|
198
|
+
// Public routes don't require validation
|
|
199
|
+
if (segment === event_type_enum_js_1.RouteSegment.Public)
|
|
200
|
+
return true;
|
|
201
|
+
// If no user pool config, skip validation
|
|
202
|
+
const expectedUserPoolId = config.userPools?.[segment];
|
|
203
|
+
if (!expectedUserPoolId)
|
|
204
|
+
return true;
|
|
205
|
+
// Validate issuer matches expected user pool
|
|
206
|
+
return (0, extractor_js_1.validateIssuer)(normalized.context.identity, expectedUserPoolId);
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Executes middleware chain
|
|
210
|
+
*/
|
|
211
|
+
async function executeMiddleware(middleware, event) {
|
|
212
|
+
let currentEvent = event;
|
|
213
|
+
for (const mw of middleware) {
|
|
214
|
+
const result = await mw(currentEvent);
|
|
215
|
+
if (result) {
|
|
216
|
+
currentEvent = result;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
return currentEvent;
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Main dispatch function with all improvements
|
|
223
|
+
*/
|
|
224
|
+
async function dispatchEvent(event, routes, config = {}) {
|
|
225
|
+
const debug = config.debug ?? false;
|
|
226
|
+
if (debug) {
|
|
227
|
+
console.log('[SEO] Event received:', JSON.stringify(event, null, 2));
|
|
228
|
+
}
|
|
229
|
+
const type = detectEventType(event);
|
|
230
|
+
if (debug) {
|
|
231
|
+
console.log('[SEO] Event type:', type);
|
|
232
|
+
}
|
|
233
|
+
// Handle API Gateway events
|
|
234
|
+
if (type === event_type_enum_js_1.EventType.ApiGateway) {
|
|
235
|
+
const method = event.httpMethod?.toLowerCase();
|
|
236
|
+
const routePattern = event.resource || event.path;
|
|
237
|
+
const actualPath = event.path || event.resource;
|
|
238
|
+
if (debug) {
|
|
239
|
+
console.log('[SEO] Method:', method, 'Path:', routePattern, 'Actual:', actualPath);
|
|
240
|
+
}
|
|
241
|
+
const apiRoutes = routes.apigateway;
|
|
242
|
+
if (!apiRoutes) {
|
|
243
|
+
return config.responses?.notFound?.() ?? (0, response_js_1.notFoundResponse)('No API routes configured');
|
|
244
|
+
}
|
|
245
|
+
let routeMatch = null;
|
|
246
|
+
// Use routePattern for finding routes, but extract params from actualPath
|
|
247
|
+
if (isSegmentedRouter(apiRoutes)) {
|
|
248
|
+
routeMatch = findRouteInSegmentsWithActualPath(apiRoutes, method, routePattern, actualPath);
|
|
249
|
+
}
|
|
250
|
+
else {
|
|
251
|
+
// Flat router - treat as public
|
|
252
|
+
const result = findRouteInRouterWithActualPath(apiRoutes, method, routePattern, actualPath);
|
|
253
|
+
if (result) {
|
|
254
|
+
routeMatch = {
|
|
255
|
+
handler: result.config.handler,
|
|
256
|
+
params: result.params,
|
|
257
|
+
segment: event_type_enum_js_1.RouteSegment.Public,
|
|
258
|
+
middleware: [],
|
|
259
|
+
config: result.config,
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
if (!routeMatch) {
|
|
264
|
+
if (debug) {
|
|
265
|
+
console.log('[SEO] No route found for:', method, routePattern);
|
|
266
|
+
}
|
|
267
|
+
return config.responses?.notFound?.() ?? (0, response_js_1.notFoundResponse)(`Route not found: ${method.toUpperCase()} ${routePattern}`);
|
|
268
|
+
}
|
|
269
|
+
if (debug) {
|
|
270
|
+
console.log('[SEO] Route matched:', routeMatch.segment, 'Params:', routeMatch.params);
|
|
271
|
+
}
|
|
272
|
+
// Normalize event
|
|
273
|
+
let normalized = normalizeApiGatewayEvent(event, routeMatch.segment, routeMatch.params);
|
|
274
|
+
// Validate User Pool
|
|
275
|
+
if (!validateSegmentUserPool(normalized, routeMatch.segment, config)) {
|
|
276
|
+
if (debug) {
|
|
277
|
+
console.log('[SEO] User Pool validation failed for segment:', routeMatch.segment);
|
|
278
|
+
}
|
|
279
|
+
return config.responses?.forbidden?.() ?? (0, response_js_1.forbiddenResponse)('Access denied: Invalid token issuer');
|
|
280
|
+
}
|
|
281
|
+
// Execute global middleware
|
|
282
|
+
if (config.globalMiddleware?.length) {
|
|
283
|
+
normalized = await executeMiddleware(config.globalMiddleware, normalized);
|
|
284
|
+
}
|
|
285
|
+
// Execute segment middleware
|
|
286
|
+
if (routeMatch.middleware?.length) {
|
|
287
|
+
normalized = await executeMiddleware(routeMatch.middleware, normalized);
|
|
288
|
+
}
|
|
289
|
+
// Execute handler
|
|
290
|
+
return routeMatch.handler(normalized);
|
|
291
|
+
}
|
|
292
|
+
// Handle EventBridge events
|
|
293
|
+
if (type === event_type_enum_js_1.EventType.EventBridge) {
|
|
294
|
+
const operationName = event.detail?.operationName;
|
|
295
|
+
const handler = operationName
|
|
296
|
+
? routes.eventbridge?.[operationName] ?? routes.eventbridge?.default
|
|
297
|
+
: routes.eventbridge?.default;
|
|
298
|
+
if (!handler) {
|
|
299
|
+
if (debug) {
|
|
300
|
+
console.log('[SEO] No EventBridge handler for:', operationName);
|
|
301
|
+
}
|
|
302
|
+
return { statusCode: 404, body: 'EventBridge handler not found' };
|
|
303
|
+
}
|
|
304
|
+
const normalized = normalizeEventBridgeEvent(event);
|
|
305
|
+
return handler(normalized);
|
|
306
|
+
}
|
|
307
|
+
// Handle SQS events
|
|
308
|
+
if (type === event_type_enum_js_1.EventType.Sqs) {
|
|
309
|
+
const queueArn = event.Records[0]?.eventSourceARN;
|
|
310
|
+
const queueName = queueArn?.split(':').pop();
|
|
311
|
+
const handler = routes.sqs?.[queueName] ?? routes.sqs?.default;
|
|
312
|
+
if (!handler) {
|
|
313
|
+
if (debug) {
|
|
314
|
+
console.log('[SEO] No SQS handler for queue:', queueName);
|
|
315
|
+
}
|
|
316
|
+
return { statusCode: 404, body: 'SQS handler not found' };
|
|
317
|
+
}
|
|
318
|
+
const normalized = normalizeSqsEvent(event);
|
|
319
|
+
return handler(normalized);
|
|
320
|
+
}
|
|
321
|
+
// Handle Lambda invocation
|
|
322
|
+
if (type === event_type_enum_js_1.EventType.Lambda) {
|
|
323
|
+
const handler = routes.lambda?.default;
|
|
324
|
+
if (!handler) {
|
|
325
|
+
return { statusCode: 404, body: 'Lambda handler not found' };
|
|
326
|
+
}
|
|
327
|
+
const normalized = normalizeLambdaEvent(event);
|
|
328
|
+
return handler(normalized);
|
|
329
|
+
}
|
|
330
|
+
// Unknown event type
|
|
331
|
+
if (debug) {
|
|
332
|
+
console.log('[SEO] Unknown event type');
|
|
333
|
+
}
|
|
334
|
+
return config.responses?.badRequest?.('Unknown event type') ?? (0, response_js_1.badRequestResponse)('Unknown event type');
|
|
335
|
+
}
|
|
336
|
+
/**
|
|
337
|
+
* Creates an orchestrator instance with pre-configured options
|
|
338
|
+
*/
|
|
339
|
+
function createOrchestrator(config = {}) {
|
|
340
|
+
return {
|
|
341
|
+
dispatch: (event, routes) => dispatchEvent(event, routes, config),
|
|
342
|
+
config,
|
|
343
|
+
};
|
|
344
|
+
}
|
|
345
|
+
//# sourceMappingURL=dispatcher.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dispatcher.js","sourceRoot":"","sources":["../src/dispatcher.ts"],"names":[],"mappings":";;AAuBA,0CAMC;AA4OD,sCA2IC;AAKD,gDAKC;AA9ZD,mEAAqE;AAcrE,6DAAmE;AACnE,mDAAsD;AACtD,0DAAwE;AACxE,0DAA0E;AAC1E,oDAA6F;AAE7F;;GAEG;AACH,SAAgB,eAAe,CAAC,KAAU;IACxC,IAAI,KAAK,CAAC,MAAM,KAAK,cAAc;QAAE,OAAO,8BAAS,CAAC,WAAW,CAAC;IAClE,IAAI,KAAK,CAAC,cAAc,IAAI,KAAK,CAAC,UAAU;QAAE,OAAO,8BAAS,CAAC,UAAU,CAAC;IAC1E,IAAI,KAAK,CAAC,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,WAAW,KAAK,SAAS;QAAE,OAAO,8BAAS,CAAC,GAAG,CAAC;IACvH,IAAI,KAAK,CAAC,YAAY;QAAE,OAAO,8BAAS,CAAC,MAAM,CAAC;IAChD,OAAO,8BAAS,CAAC,OAAO,CAAC;AAC3B,CAAC;AAED;;GAEG;AACH,SAAS,iBAAiB,CAAC,MAAW;IACpC,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IACxD,MAAM,WAAW,GAAG,CAAC,QAAQ,EAAE,SAAS,EAAE,YAAY,EAAE,UAAU,CAAC,CAAC;IACpE,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IACvC,OAAO,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,WAAW,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;AAC3D,CAAC;AAED;;GAEG;AACH,SAAS,eAAe,CAAC,MAAW;IAClC,OAAO,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,QAAQ,IAAI,MAAM,CAAC;AACpE,CAAC;AAED;;GAEG;AACH,SAAS,oBAAoB,CAAC,OAA+C;IAC3E,IAAI,CAAC,OAAO;QAAE,OAAO,SAAS,CAAC;IAC/B,IAAI,eAAe,CAAC,OAAO,CAAC;QAAE,OAAO,OAAO,CAAC,MAAM,CAAC;IACpD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;GAEG;AACH,SAAS,wBAAwB,CAAC,OAA+C;IAC/E,IAAI,CAAC,OAAO;QAAE,OAAO,EAAE,CAAC;IACxB,IAAI,eAAe,CAAC,OAAO,CAAC;QAAE,OAAO,OAAO,CAAC,UAAU,IAAI,EAAE,CAAC;IAC9D,OAAO,EAAE,CAAC;AACZ,CAAC;AAGD;;GAEG;AACH,SAAS,+BAA+B,CACtC,MAA8B,EAC9B,MAAkB,EAClB,YAAoB,EACpB,UAAkB;IAElB,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IAEzB,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;IACpC,IAAI,CAAC,YAAY;QAAE,OAAO,IAAI,CAAC;IAE/B,MAAM,iBAAiB,GAAG,IAAA,+BAAa,EAAC,YAAY,CAAC,CAAC;IACtD,MAAM,oBAAoB,GAAG,IAAA,+BAAa,EAAC,UAAU,CAAC,CAAC;IAEvD,0CAA0C;IAC1C,IAAI,YAAY,CAAC,iBAAiB,CAAC,EAAE,CAAC;QACpC,wDAAwD;QACxD,MAAM,MAAM,GAAG,IAAA,2BAAS,EAAC,iBAAiB,EAAE,oBAAoB,CAAC,IAAI,EAAE,CAAC;QACxE,OAAO,EAAE,MAAM,EAAE,YAAY,CAAC,iBAAiB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC7D,CAAC;IAED,6BAA6B;IAC7B,KAAK,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC;QAC7D,MAAM,MAAM,GAAG,IAAA,2BAAS,EAAC,OAAO,EAAE,oBAAoB,CAAC,CAAC;QACxD,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;YACpB,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC;QAC5B,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;GAEG;AACH,SAAS,iCAAiC,CACxC,MAAqD,EACrD,MAAkB,EAClB,YAAoB,EACpB,UAAkB;IAElB,MAAM,QAAQ,GAAmB;QAC/B,iCAAY,CAAC,MAAM;QACnB,iCAAY,CAAC,OAAO;QACpB,iCAAY,CAAC,UAAU;QACvB,iCAAY,CAAC,QAAQ;KACtB,CAAC;IAEF,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,MAAM,aAAa,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC;QACtC,MAAM,UAAU,GAAG,oBAAoB,CAAC,aAAa,CAAC,CAAC;QACvD,MAAM,MAAM,GAAG,+BAA+B,CAAC,UAAU,EAAE,MAAM,EAAE,YAAY,EAAE,UAAU,CAAC,CAAC;QAE7F,IAAI,MAAM,EAAE,CAAC;YACX,OAAO;gBACL,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO;gBAC9B,MAAM,EAAE,MAAM,CAAC,MAAM;gBACrB,OAAO;gBACP,UAAU,EAAE,wBAAwB,CAAC,aAAa,CAAC;gBACnD,MAAM,EAAE,MAAM,CAAC,MAAM;aACtB,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAGD;;GAEG;AACH,SAAS,wBAAwB,CAAC,KAAU,EAAE,OAAqB,EAAE,MAA8B;IACjG,MAAM,QAAQ,GAAG,IAAA,8BAAe,EAAC,KAAK,CAAC,CAAC;IAExC,OAAO;QACL,QAAQ,EAAE,KAAK;QACf,SAAS,EAAE,8BAAS,CAAC,UAAU;QAC/B,OAAO,EAAE;YACP,IAAI,EAAE,IAAA,8BAAa,EAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,eAAe,CAAC;YACtD,cAAc,EAAE,EAAE,GAAG,KAAK,CAAC,cAAc,EAAE,GAAG,MAAM,EAAE;YACtD,qBAAqB,EAAE,IAAA,iCAAgB,EAAC,KAAK,CAAC,qBAAqB,CAAC;YACpE,OAAO,EAAE,IAAA,6BAAgB,EAAC,KAAK,CAAC,OAAO,CAAC;SACzC;QACD,MAAM;QACN,OAAO,EAAE;YACP,OAAO;YACP,QAAQ;YACR,SAAS,EAAE,KAAK,CAAC,cAAc,EAAE,SAAS;SAC3C;KACF,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,yBAAyB,CAAC,KAAU;IAC3C,OAAO;QACL,QAAQ,EAAE,KAAK;QACf,SAAS,EAAE,8BAAS,CAAC,WAAW;QAChC,OAAO,EAAE;YACP,IAAI,EAAE,KAAK,CAAC,MAAM;SACnB;QACD,MAAM,EAAE,EAAE;QACV,OAAO,EAAE;YACP,OAAO,EAAE,iCAAY,CAAC,QAAQ;YAC9B,SAAS,EAAE,KAAK,CAAC,EAAE;SACpB;KACF,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,iBAAiB,CAAC,KAAU;IACnC,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IAChC,IAAI,IAAI,GAAwB,EAAE,CAAC;IAEnC,IAAI,CAAC;QACH,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAwB,CAAC;IACxD,CAAC;IAAC,MAAM,CAAC;QACP,IAAI,GAAG,EAAE,OAAO,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC;IAClC,CAAC;IAED,OAAO;QACL,QAAQ,EAAE,KAAK;QACf,SAAS,EAAE,8BAAS,CAAC,GAAG;QACxB,OAAO,EAAE;YACP,IAAI;SACL;QACD,MAAM,EAAE,EAAE;QACV,OAAO,EAAE;YACP,OAAO,EAAE,iCAAY,CAAC,QAAQ;YAC9B,SAAS,EAAE,MAAM,CAAC,SAAS;SAC5B;KACF,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,oBAAoB,CAAC,KAAU;IACtC,OAAO;QACL,QAAQ,EAAE,KAAK;QACf,SAAS,EAAE,8BAAS,CAAC,MAAM;QAC3B,OAAO,EAAE;YACP,IAAI,EAAE,KAAK;SACZ;QACD,MAAM,EAAE,EAAE;QACV,OAAO,EAAE;YACP,OAAO,EAAE,iCAAY,CAAC,QAAQ;SAC/B;KACF,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,SAAS,uBAAuB,CAC9B,UAA2B,EAC3B,OAAqB,EACrB,MAA0B;IAE1B,yCAAyC;IACzC,IAAI,OAAO,KAAK,iCAAY,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IAEjD,0CAA0C;IAC1C,MAAM,kBAAkB,GAAG,MAAM,CAAC,SAAS,EAAE,CAAC,OAAO,CAAC,CAAC;IACvD,IAAI,CAAC,kBAAkB;QAAE,OAAO,IAAI,CAAC;IAErC,6CAA6C;IAC7C,OAAO,IAAA,6BAAc,EAAC,UAAU,CAAC,OAAO,CAAC,QAAQ,EAAE,kBAAkB,CAAC,CAAC;AACzE,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,iBAAiB,CAC9B,UAA0B,EAC1B,KAAsB;IAEtB,IAAI,YAAY,GAAG,KAAK,CAAC;IAEzB,KAAK,MAAM,EAAE,IAAI,UAAU,EAAE,CAAC;QAC5B,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,YAAY,CAAC,CAAC;QACtC,IAAI,MAAM,EAAE,CAAC;YACX,YAAY,GAAG,MAAM,CAAC;QACxB,CAAC;IACH,CAAC;IAED,OAAO,YAAY,CAAC;AACtB,CAAC;AAED;;GAEG;AACI,KAAK,UAAU,aAAa,CACjC,KAAU,EACV,MAAsB,EACtB,SAA6B,EAAE;IAE/B,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI,KAAK,CAAC;IAEpC,IAAI,KAAK,EAAE,CAAC;QACV,OAAO,CAAC,GAAG,CAAC,uBAAuB,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IACvE,CAAC;IAED,MAAM,IAAI,GAAG,eAAe,CAAC,KAAK,CAAC,CAAC;IAEpC,IAAI,KAAK,EAAE,CAAC;QACV,OAAO,CAAC,GAAG,CAAC,mBAAmB,EAAE,IAAI,CAAC,CAAC;IACzC,CAAC;IAED,4BAA4B;IAC5B,IAAI,IAAI,KAAK,8BAAS,CAAC,UAAU,EAAE,CAAC;QAClC,MAAM,MAAM,GAAG,KAAK,CAAC,UAAU,EAAE,WAAW,EAAgB,CAAC;QAC7D,MAAM,YAAY,GAAG,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,IAAI,CAAC;QAClD,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,QAAQ,CAAC;QAEhD,IAAI,KAAK,EAAE,CAAC;YACV,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,UAAU,CAAC,CAAC;QACrF,CAAC;QAED,MAAM,SAAS,GAAG,MAAM,CAAC,UAAU,CAAC;QACpC,IAAI,CAAC,SAAS,EAAE,CAAC;YACf,OAAO,MAAM,CAAC,SAAS,EAAE,QAAQ,EAAE,EAAE,IAAI,IAAA,8BAAgB,EAAC,0BAA0B,CAAC,CAAC;QACxF,CAAC;QAED,IAAI,UAAU,GAAsB,IAAI,CAAC;QAEzC,0EAA0E;QAC1E,IAAI,iBAAiB,CAAC,SAAS,CAAC,EAAE,CAAC;YACjC,UAAU,GAAG,iCAAiC,CAAC,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,UAAU,CAAC,CAAC;QAC9F,CAAC;aAAM,CAAC;YACN,gCAAgC;YAChC,MAAM,MAAM,GAAG,+BAA+B,CAAC,SAAuB,EAAE,MAAM,EAAE,YAAY,EAAE,UAAU,CAAC,CAAC;YAC1G,IAAI,MAAM,EAAE,CAAC;gBACX,UAAU,GAAG;oBACX,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO;oBAC9B,MAAM,EAAE,MAAM,CAAC,MAAM;oBACrB,OAAO,EAAE,iCAAY,CAAC,MAAM;oBAC5B,UAAU,EAAE,EAAE;oBACd,MAAM,EAAE,MAAM,CAAC,MAAM;iBACtB,CAAC;YACJ,CAAC;QACH,CAAC;QAED,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,IAAI,KAAK,EAAE,CAAC;gBACV,OAAO,CAAC,GAAG,CAAC,2BAA2B,EAAE,MAAM,EAAE,YAAY,CAAC,CAAC;YACjE,CAAC;YACD,OAAO,MAAM,CAAC,SAAS,EAAE,QAAQ,EAAE,EAAE,IAAI,IAAA,8BAAgB,EAAC,oBAAoB,MAAM,CAAC,WAAW,EAAE,IAAI,YAAY,EAAE,CAAC,CAAC;QACxH,CAAC;QAED,IAAI,KAAK,EAAE,CAAC;YACV,OAAO,CAAC,GAAG,CAAC,sBAAsB,EAAE,UAAU,CAAC,OAAO,EAAE,SAAS,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC;QACxF,CAAC;QAED,kBAAkB;QAClB,IAAI,UAAU,GAAG,wBAAwB,CAAC,KAAK,EAAE,UAAU,CAAC,OAAO,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC;QAExF,qBAAqB;QACrB,IAAI,CAAC,uBAAuB,CAAC,UAAU,EAAE,UAAU,CAAC,OAAO,EAAE,MAAM,CAAC,EAAE,CAAC;YACrE,IAAI,KAAK,EAAE,CAAC;gBACV,OAAO,CAAC,GAAG,CAAC,gDAAgD,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC;YACpF,CAAC;YACD,OAAO,MAAM,CAAC,SAAS,EAAE,SAAS,EAAE,EAAE,IAAI,IAAA,+BAAiB,EAAC,qCAAqC,CAAC,CAAC;QACrG,CAAC;QAED,4BAA4B;QAC5B,IAAI,MAAM,CAAC,gBAAgB,EAAE,MAAM,EAAE,CAAC;YACpC,UAAU,GAAG,MAAM,iBAAiB,CAAC,MAAM,CAAC,gBAAgB,EAAE,UAAU,CAAC,CAAC;QAC5E,CAAC;QAED,6BAA6B;QAC7B,IAAI,UAAU,CAAC,UAAU,EAAE,MAAM,EAAE,CAAC;YAClC,UAAU,GAAG,MAAM,iBAAiB,CAAC,UAAU,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;QAC1E,CAAC;QAED,kBAAkB;QAClB,OAAO,UAAU,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IACxC,CAAC;IAED,4BAA4B;IAC5B,IAAI,IAAI,KAAK,8BAAS,CAAC,WAAW,EAAE,CAAC;QACnC,MAAM,aAAa,GAAG,KAAK,CAAC,MAAM,EAAE,aAAa,CAAC;QAClD,MAAM,OAAO,GAAG,aAAa;YAC3B,CAAC,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,aAAa,CAAC,IAAI,MAAM,CAAC,WAAW,EAAE,OAAO;YACpE,CAAC,CAAC,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC;QAEhC,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,IAAI,KAAK,EAAE,CAAC;gBACV,OAAO,CAAC,GAAG,CAAC,mCAAmC,EAAE,aAAa,CAAC,CAAC;YAClE,CAAC;YACD,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,IAAI,EAAE,+BAA+B,EAAE,CAAC;QACpE,CAAC;QAED,MAAM,UAAU,GAAG,yBAAyB,CAAC,KAAK,CAAC,CAAC;QACpD,OAAO,OAAO,CAAC,UAAU,CAAC,CAAC;IAC7B,CAAC;IAED,oBAAoB;IACpB,IAAI,IAAI,KAAK,8BAAS,CAAC,GAAG,EAAE,CAAC;QAC3B,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,cAAc,CAAC;QAClD,MAAM,SAAS,GAAG,QAAQ,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,CAAC;QAC7C,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,IAAI,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC;QAE/D,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,IAAI,KAAK,EAAE,CAAC;gBACV,OAAO,CAAC,GAAG,CAAC,iCAAiC,EAAE,SAAS,CAAC,CAAC;YAC5D,CAAC;YACD,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,IAAI,EAAE,uBAAuB,EAAE,CAAC;QAC5D,CAAC;QAED,MAAM,UAAU,GAAG,iBAAiB,CAAC,KAAK,CAAC,CAAC;QAC5C,OAAO,OAAO,CAAC,UAAU,CAAC,CAAC;IAC7B,CAAC;IAED,2BAA2B;IAC3B,IAAI,IAAI,KAAK,8BAAS,CAAC,MAAM,EAAE,CAAC;QAC9B,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;QAEvC,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,EAAE,UAAU,EAAE,GAAG,EAAE,IAAI,EAAE,0BAA0B,EAAE,CAAC;QAC/D,CAAC;QAED,MAAM,UAAU,GAAG,oBAAoB,CAAC,KAAK,CAAC,CAAC;QAC/C,OAAO,OAAO,CAAC,UAAU,CAAC,CAAC;IAC7B,CAAC;IAED,qBAAqB;IACrB,IAAI,KAAK,EAAE,CAAC;QACV,OAAO,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAC;IAC1C,CAAC;IACD,OAAO,MAAM,CAAC,SAAS,EAAE,UAAU,EAAE,CAAC,oBAAoB,CAAC,IAAI,IAAA,gCAAkB,EAAC,oBAAoB,CAAC,CAAC;AAC1G,CAAC;AAED;;GAEG;AACH,SAAgB,kBAAkB,CAAC,SAA6B,EAAE;IAChE,OAAO;QACL,QAAQ,EAAE,CAAC,KAAU,EAAE,MAAsB,EAAE,EAAE,CAAC,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC;QACtF,MAAM;KACP,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Safe JSON body parsing utilities
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Safely parses a JSON body string
|
|
6
|
+
* @param body - Raw body string from event
|
|
7
|
+
* @param isBase64Encoded - Whether the body is base64 encoded
|
|
8
|
+
* @returns Parsed object or empty object on error
|
|
9
|
+
*/
|
|
10
|
+
export declare function parseJsonBody(body: string | null | undefined, isBase64Encoded?: boolean): Record<string, any>;
|
|
11
|
+
/**
|
|
12
|
+
* Safely parses query string parameters
|
|
13
|
+
* Handles multi-value parameters
|
|
14
|
+
* @param params - Query string parameters object
|
|
15
|
+
* @returns Normalized parameters
|
|
16
|
+
*/
|
|
17
|
+
export declare function parseQueryParams(params: Record<string, string | undefined> | null | undefined): Record<string, string>;
|
|
18
|
+
/**
|
|
19
|
+
* Middleware-style body parser that can be applied to events
|
|
20
|
+
*/
|
|
21
|
+
export declare function withJsonBodyParser<T extends {
|
|
22
|
+
body?: string;
|
|
23
|
+
isBase64Encoded?: boolean;
|
|
24
|
+
}>(event: T): T & {
|
|
25
|
+
parsedBody: Record<string, any>;
|
|
26
|
+
};
|
|
27
|
+
//# sourceMappingURL=body-parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"body-parser.d.ts","sourceRoot":"","sources":["../../src/http/body-parser.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAAE,eAAe,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAe7G;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,GAAG,IAAI,GAAG,SAAS,GAC5D,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAYxB;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,CAAC,SAAS;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,eAAe,CAAC,EAAE,OAAO,CAAA;CAAE,EACvF,KAAK,EAAE,CAAC,GACP,CAAC,GAAG;IAAE,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;CAAE,CAKzC"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Safe JSON body parsing utilities
|
|
4
|
+
*/
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.parseJsonBody = parseJsonBody;
|
|
7
|
+
exports.parseQueryParams = parseQueryParams;
|
|
8
|
+
exports.withJsonBodyParser = withJsonBodyParser;
|
|
9
|
+
/**
|
|
10
|
+
* Safely parses a JSON body string
|
|
11
|
+
* @param body - Raw body string from event
|
|
12
|
+
* @param isBase64Encoded - Whether the body is base64 encoded
|
|
13
|
+
* @returns Parsed object or empty object on error
|
|
14
|
+
*/
|
|
15
|
+
function parseJsonBody(body, isBase64Encoded) {
|
|
16
|
+
if (!body)
|
|
17
|
+
return {};
|
|
18
|
+
try {
|
|
19
|
+
let decodedBody = body;
|
|
20
|
+
if (isBase64Encoded) {
|
|
21
|
+
decodedBody = Buffer.from(body, 'base64').toString('utf-8');
|
|
22
|
+
}
|
|
23
|
+
const parsed = JSON.parse(decodedBody);
|
|
24
|
+
return parsed ?? {};
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return {};
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Safely parses query string parameters
|
|
32
|
+
* Handles multi-value parameters
|
|
33
|
+
* @param params - Query string parameters object
|
|
34
|
+
* @returns Normalized parameters
|
|
35
|
+
*/
|
|
36
|
+
function parseQueryParams(params) {
|
|
37
|
+
if (!params)
|
|
38
|
+
return {};
|
|
39
|
+
const result = {};
|
|
40
|
+
for (const [key, value] of Object.entries(params)) {
|
|
41
|
+
if (value !== undefined) {
|
|
42
|
+
result[key] = value;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return result;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Middleware-style body parser that can be applied to events
|
|
49
|
+
*/
|
|
50
|
+
function withJsonBodyParser(event) {
|
|
51
|
+
return {
|
|
52
|
+
...event,
|
|
53
|
+
parsedBody: parseJsonBody(event.body, event.isBase64Encoded),
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=body-parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"body-parser.js","sourceRoot":"","sources":["../../src/http/body-parser.ts"],"names":[],"mappings":";AAAA;;GAEG;;AAQH,sCAeC;AAQD,4CAcC;AAKD,gDAOC;AAvDD;;;;;GAKG;AACH,SAAgB,aAAa,CAAC,IAA+B,EAAE,eAAyB;IACtF,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,CAAC;IAErB,IAAI,CAAC;QACH,IAAI,WAAW,GAAG,IAAI,CAAC;QAEvB,IAAI,eAAe,EAAE,CAAC;YACpB,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QAC9D,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAAwB,CAAC;QAC9D,OAAO,MAAM,IAAI,EAAE,CAAC;IACtB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;;;;GAKG;AACH,SAAgB,gBAAgB,CAC9B,MAA6D;IAE7D,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,CAAC;IAEvB,MAAM,MAAM,GAA2B,EAAE,CAAC;IAE1C,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAClD,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;QACtB,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;GAEG;AACH,SAAgB,kBAAkB,CAChC,KAAQ;IAER,OAAO;QACL,GAAG,KAAK;QACR,UAAU,EAAE,aAAa,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,eAAe,CAAC;KAC7D,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { CorsConfig } from '../types/routes.js';
|
|
2
|
+
import { HttpResponse } from './response.js';
|
|
3
|
+
/**
|
|
4
|
+
* CORS handling utilities
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Checks if a request is a CORS preflight request
|
|
8
|
+
* @param event - Raw API Gateway event
|
|
9
|
+
* @returns True if this is an OPTIONS preflight request
|
|
10
|
+
*/
|
|
11
|
+
export declare function isPreflightRequest(event: any): boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Creates a preflight response with CORS headers
|
|
14
|
+
* @param config - CORS configuration
|
|
15
|
+
* @returns HTTP response for preflight
|
|
16
|
+
*/
|
|
17
|
+
export declare function createPreflightResponse(config?: CorsConfig | boolean): HttpResponse;
|
|
18
|
+
/**
|
|
19
|
+
* Applies CORS headers to an existing response
|
|
20
|
+
* @param response - Original response
|
|
21
|
+
* @param config - CORS configuration
|
|
22
|
+
* @returns Response with CORS headers
|
|
23
|
+
*/
|
|
24
|
+
export declare function applyCorsHeaders(response: HttpResponse, config?: CorsConfig | boolean): HttpResponse;
|
|
25
|
+
/**
|
|
26
|
+
* Middleware that handles CORS for a handler
|
|
27
|
+
* @param handler - Original handler function
|
|
28
|
+
* @param config - CORS configuration
|
|
29
|
+
* @returns Wrapped handler with CORS support
|
|
30
|
+
*/
|
|
31
|
+
export declare function withCors<T extends (...args: any[]) => Promise<HttpResponse>>(handler: T, config?: CorsConfig | boolean): T;
|
|
32
|
+
//# sourceMappingURL=cors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cors.d.ts","sourceRoot":"","sources":["../../src/http/cors.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAEhD,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAE7C;;GAEG;AAEH;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO,CAEtD;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,CAAC,EAAE,UAAU,GAAG,OAAO,GAAG,YAAY,CAQnF;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,YAAY,EAAE,MAAM,CAAC,EAAE,UAAU,GAAG,OAAO,GAAG,YAAY,CAapG;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,OAAO,CAAC,YAAY,CAAC,EAC1E,OAAO,EAAE,CAAC,EACV,MAAM,CAAC,EAAE,UAAU,GAAG,OAAO,GAC5B,CAAC,CAaH"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isPreflightRequest = isPreflightRequest;
|
|
4
|
+
exports.createPreflightResponse = createPreflightResponse;
|
|
5
|
+
exports.applyCorsHeaders = applyCorsHeaders;
|
|
6
|
+
exports.withCors = withCors;
|
|
7
|
+
const headers_js_1 = require("../utils/headers.js");
|
|
8
|
+
/**
|
|
9
|
+
* CORS handling utilities
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Checks if a request is a CORS preflight request
|
|
13
|
+
* @param event - Raw API Gateway event
|
|
14
|
+
* @returns True if this is an OPTIONS preflight request
|
|
15
|
+
*/
|
|
16
|
+
function isPreflightRequest(event) {
|
|
17
|
+
return event.httpMethod?.toUpperCase() === 'OPTIONS';
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Creates a preflight response with CORS headers
|
|
21
|
+
* @param config - CORS configuration
|
|
22
|
+
* @returns HTTP response for preflight
|
|
23
|
+
*/
|
|
24
|
+
function createPreflightResponse(config) {
|
|
25
|
+
const corsConfig = config === true ? undefined : (config === false ? undefined : config);
|
|
26
|
+
return {
|
|
27
|
+
statusCode: 204,
|
|
28
|
+
body: '',
|
|
29
|
+
headers: (0, headers_js_1.getCorsHeaders)(corsConfig),
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Applies CORS headers to an existing response
|
|
34
|
+
* @param response - Original response
|
|
35
|
+
* @param config - CORS configuration
|
|
36
|
+
* @returns Response with CORS headers
|
|
37
|
+
*/
|
|
38
|
+
function applyCorsHeaders(response, config) {
|
|
39
|
+
if (config === false)
|
|
40
|
+
return response;
|
|
41
|
+
const corsConfig = config === true ? undefined : config;
|
|
42
|
+
const corsHeaders = (0, headers_js_1.getCorsHeaders)(corsConfig);
|
|
43
|
+
return {
|
|
44
|
+
...response,
|
|
45
|
+
headers: {
|
|
46
|
+
...corsHeaders,
|
|
47
|
+
...response.headers,
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Middleware that handles CORS for a handler
|
|
53
|
+
* @param handler - Original handler function
|
|
54
|
+
* @param config - CORS configuration
|
|
55
|
+
* @returns Wrapped handler with CORS support
|
|
56
|
+
*/
|
|
57
|
+
function withCors(handler, config) {
|
|
58
|
+
return (async (...args) => {
|
|
59
|
+
const event = args[0];
|
|
60
|
+
// Handle preflight requests
|
|
61
|
+
if (isPreflightRequest(event?.eventRaw ?? event)) {
|
|
62
|
+
return createPreflightResponse(config);
|
|
63
|
+
}
|
|
64
|
+
// Execute handler and apply CORS headers
|
|
65
|
+
const response = await handler(...args);
|
|
66
|
+
return applyCorsHeaders(response, config);
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=cors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cors.js","sourceRoot":"","sources":["../../src/http/cors.ts"],"names":[],"mappings":";;AAaA,gDAEC;AAOD,0DAQC;AAQD,4CAaC;AAQD,4BAgBC;AA1ED,oDAAqD;AAGrD;;GAEG;AAEH;;;;GAIG;AACH,SAAgB,kBAAkB,CAAC,KAAU;IAC3C,OAAO,KAAK,CAAC,UAAU,EAAE,WAAW,EAAE,KAAK,SAAS,CAAC;AACvD,CAAC;AAED;;;;GAIG;AACH,SAAgB,uBAAuB,CAAC,MAA6B;IACnE,MAAM,UAAU,GAAG,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IAEzF,OAAO;QACL,UAAU,EAAE,GAAG;QACf,IAAI,EAAE,EAAE;QACR,OAAO,EAAE,IAAA,2BAAc,EAAC,UAAU,CAAC;KACpC,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,SAAgB,gBAAgB,CAAC,QAAsB,EAAE,MAA6B;IACpF,IAAI,MAAM,KAAK,KAAK;QAAE,OAAO,QAAQ,CAAC;IAEtC,MAAM,UAAU,GAAG,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC;IACxD,MAAM,WAAW,GAAG,IAAA,2BAAc,EAAC,UAAU,CAAC,CAAC;IAE/C,OAAO;QACL,GAAG,QAAQ;QACX,OAAO,EAAE;YACP,GAAG,WAAW;YACd,GAAG,QAAQ,CAAC,OAAO;SACpB;KACF,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,SAAgB,QAAQ,CACtB,OAAU,EACV,MAA6B;IAE7B,OAAO,CAAC,KAAK,EAAE,GAAG,IAAmB,EAAyB,EAAE;QAC9D,MAAM,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;QAEtB,4BAA4B;QAC5B,IAAI,kBAAkB,CAAC,KAAK,EAAE,QAAQ,IAAI,KAAK,CAAC,EAAE,CAAC;YACjD,OAAO,uBAAuB,CAAC,MAAM,CAAC,CAAC;QACzC,CAAC;QAED,yCAAyC;QACzC,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,GAAG,IAAI,CAAC,CAAC;QACxC,OAAO,gBAAgB,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC5C,CAAC,CAAM,CAAC;AACV,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/http/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAC;AAC9B,cAAc,kBAAkB,CAAC;AACjC,cAAc,WAAW,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./response.js"), exports);
|
|
18
|
+
__exportStar(require("./body-parser.js"), exports);
|
|
19
|
+
__exportStar(require("./cors.js"), exports);
|
|
20
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/http/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,gDAA8B;AAC9B,mDAAiC;AACjC,4CAA0B"}
|