serverless-event-orchestrator 2.0.1 → 2.3.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/LICENSE +21 -21
- package/README.md +489 -434
- package/dist/dispatcher.d.ts +6 -1
- package/dist/dispatcher.d.ts.map +1 -1
- package/dist/dispatcher.js +66 -7
- package/dist/dispatcher.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/types/event-type.enum.d.ts +1 -0
- package/dist/types/event-type.enum.d.ts.map +1 -1
- package/dist/types/event-type.enum.js +1 -0
- package/dist/types/event-type.enum.js.map +1 -1
- package/dist/types/routes.d.ts +6 -0
- package/dist/types/routes.d.ts.map +1 -1
- package/jest.config.js +32 -32
- package/package.json +82 -81
- package/src/dispatcher.ts +586 -519
- package/src/http/body-parser.ts +60 -60
- package/src/http/cors.ts +76 -76
- package/src/http/index.ts +3 -3
- package/src/http/response.ts +209 -209
- package/src/identity/extractor.ts +207 -207
- package/src/identity/index.ts +2 -2
- package/src/identity/jwt-verifier.ts +41 -41
- package/src/index.ts +128 -127
- package/src/middleware/crm-guard.ts +51 -51
- package/src/middleware/index.ts +3 -3
- package/src/middleware/init-tenant-context.ts +59 -59
- package/src/middleware/tenant-guard.ts +54 -54
- package/src/tenant/TenantContext.ts +115 -115
- package/src/tenant/helpers.ts +112 -112
- package/src/tenant/index.ts +21 -21
- package/src/tenant/types.ts +101 -101
- package/src/types/event-type.enum.ts +21 -20
- package/src/types/index.ts +2 -2
- package/src/types/routes.ts +218 -211
- package/src/utils/headers.ts +72 -72
- package/src/utils/index.ts +2 -2
- package/src/utils/path-matcher.ts +84 -84
- package/tests/cors.test.ts +133 -133
- package/tests/dispatcher.test.ts +795 -715
- package/tests/headers.test.ts +99 -99
- package/tests/identity.test.ts +301 -301
- package/tests/middleware/crm-guard.test.ts +69 -69
- package/tests/middleware/init-tenant-context.test.ts +147 -147
- package/tests/middleware/tenant-guard.test.ts +100 -100
- package/tests/path-matcher.test.ts +102 -102
- package/tests/response.test.ts +155 -155
- package/tests/tenant/TenantContext.test.ts +134 -134
- package/tests/tenant/helpers.test.ts +187 -187
- package/tsconfig.json +24 -24
package/src/http/body-parser.ts
CHANGED
|
@@ -1,60 +1,60 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Safe JSON body parsing utilities
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Safely parses a JSON body string
|
|
7
|
-
* @param body - Raw body string from event
|
|
8
|
-
* @param isBase64Encoded - Whether the body is base64 encoded
|
|
9
|
-
* @returns Parsed object or empty object on error
|
|
10
|
-
*/
|
|
11
|
-
export function parseJsonBody(body: string | null | undefined, isBase64Encoded?: boolean): Record<string, any> {
|
|
12
|
-
if (!body) return {};
|
|
13
|
-
|
|
14
|
-
try {
|
|
15
|
-
let decodedBody = body;
|
|
16
|
-
|
|
17
|
-
if (isBase64Encoded) {
|
|
18
|
-
decodedBody = Buffer.from(body, 'base64').toString('utf-8');
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const parsed = JSON.parse(decodedBody) as Record<string, any>;
|
|
22
|
-
return parsed ?? {};
|
|
23
|
-
} catch {
|
|
24
|
-
return {};
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Safely parses query string parameters
|
|
30
|
-
* Handles multi-value parameters
|
|
31
|
-
* @param params - Query string parameters object
|
|
32
|
-
* @returns Normalized parameters
|
|
33
|
-
*/
|
|
34
|
-
export function parseQueryParams(
|
|
35
|
-
params: Record<string, string | undefined> | null | undefined
|
|
36
|
-
): Record<string, string> {
|
|
37
|
-
if (!params) return {};
|
|
38
|
-
|
|
39
|
-
const result: Record<string, string> = {};
|
|
40
|
-
|
|
41
|
-
for (const [key, value] of Object.entries(params)) {
|
|
42
|
-
if (value !== undefined) {
|
|
43
|
-
result[key] = value;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
return result;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
/**
|
|
51
|
-
* Middleware-style body parser that can be applied to events
|
|
52
|
-
*/
|
|
53
|
-
export function withJsonBodyParser<T extends { body?: string; isBase64Encoded?: boolean }>(
|
|
54
|
-
event: T
|
|
55
|
-
): T & { parsedBody: Record<string, any> } {
|
|
56
|
-
return {
|
|
57
|
-
...event,
|
|
58
|
-
parsedBody: parseJsonBody(event.body, event.isBase64Encoded),
|
|
59
|
-
};
|
|
60
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* Safe JSON body parsing utilities
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Safely parses a JSON body string
|
|
7
|
+
* @param body - Raw body string from event
|
|
8
|
+
* @param isBase64Encoded - Whether the body is base64 encoded
|
|
9
|
+
* @returns Parsed object or empty object on error
|
|
10
|
+
*/
|
|
11
|
+
export function parseJsonBody(body: string | null | undefined, isBase64Encoded?: boolean): Record<string, any> {
|
|
12
|
+
if (!body) return {};
|
|
13
|
+
|
|
14
|
+
try {
|
|
15
|
+
let decodedBody = body;
|
|
16
|
+
|
|
17
|
+
if (isBase64Encoded) {
|
|
18
|
+
decodedBody = Buffer.from(body, 'base64').toString('utf-8');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const parsed = JSON.parse(decodedBody) as Record<string, any>;
|
|
22
|
+
return parsed ?? {};
|
|
23
|
+
} catch {
|
|
24
|
+
return {};
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Safely parses query string parameters
|
|
30
|
+
* Handles multi-value parameters
|
|
31
|
+
* @param params - Query string parameters object
|
|
32
|
+
* @returns Normalized parameters
|
|
33
|
+
*/
|
|
34
|
+
export function parseQueryParams(
|
|
35
|
+
params: Record<string, string | undefined> | null | undefined
|
|
36
|
+
): Record<string, string> {
|
|
37
|
+
if (!params) return {};
|
|
38
|
+
|
|
39
|
+
const result: Record<string, string> = {};
|
|
40
|
+
|
|
41
|
+
for (const [key, value] of Object.entries(params)) {
|
|
42
|
+
if (value !== undefined) {
|
|
43
|
+
result[key] = value;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return result;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Middleware-style body parser that can be applied to events
|
|
52
|
+
*/
|
|
53
|
+
export function withJsonBodyParser<T extends { body?: string; isBase64Encoded?: boolean }>(
|
|
54
|
+
event: T
|
|
55
|
+
): T & { parsedBody: Record<string, any> } {
|
|
56
|
+
return {
|
|
57
|
+
...event,
|
|
58
|
+
parsedBody: parseJsonBody(event.body, event.isBase64Encoded),
|
|
59
|
+
};
|
|
60
|
+
}
|
package/src/http/cors.ts
CHANGED
|
@@ -1,76 +1,76 @@
|
|
|
1
|
-
import { CorsConfig } from '../types/routes.js';
|
|
2
|
-
import { getCorsHeaders } from '../utils/headers.js';
|
|
3
|
-
import { HttpResponse } from './response.js';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* CORS handling utilities
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
/**
|
|
10
|
-
* Checks if a request is a CORS preflight request
|
|
11
|
-
* @param event - Raw API Gateway event
|
|
12
|
-
* @returns True if this is an OPTIONS preflight request
|
|
13
|
-
*/
|
|
14
|
-
export function isPreflightRequest(event: any): boolean {
|
|
15
|
-
return event.httpMethod?.toUpperCase() === 'OPTIONS';
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* Creates a preflight response with CORS headers
|
|
20
|
-
* @param config - CORS configuration
|
|
21
|
-
* @returns HTTP response for preflight
|
|
22
|
-
*/
|
|
23
|
-
export function createPreflightResponse(config?: CorsConfig | boolean): HttpResponse {
|
|
24
|
-
const corsConfig = config === true ? undefined : (config === false ? undefined : config);
|
|
25
|
-
|
|
26
|
-
return {
|
|
27
|
-
statusCode: 204,
|
|
28
|
-
body: '',
|
|
29
|
-
headers: getCorsHeaders(corsConfig),
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Applies CORS headers to an existing response
|
|
35
|
-
* @param response - Original response
|
|
36
|
-
* @param config - CORS configuration
|
|
37
|
-
* @returns Response with CORS headers
|
|
38
|
-
*/
|
|
39
|
-
export function applyCorsHeaders(response: HttpResponse, config?: CorsConfig | boolean): HttpResponse {
|
|
40
|
-
if (config === false) return response;
|
|
41
|
-
|
|
42
|
-
const corsConfig = config === true ? undefined : config;
|
|
43
|
-
const corsHeaders = getCorsHeaders(corsConfig);
|
|
44
|
-
|
|
45
|
-
return {
|
|
46
|
-
...response,
|
|
47
|
-
headers: {
|
|
48
|
-
...corsHeaders,
|
|
49
|
-
...response.headers,
|
|
50
|
-
},
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Middleware that handles CORS for a handler
|
|
56
|
-
* @param handler - Original handler function
|
|
57
|
-
* @param config - CORS configuration
|
|
58
|
-
* @returns Wrapped handler with CORS support
|
|
59
|
-
*/
|
|
60
|
-
export function withCors<T extends (...args: any[]) => Promise<HttpResponse>>(
|
|
61
|
-
handler: T,
|
|
62
|
-
config?: CorsConfig | boolean
|
|
63
|
-
): T {
|
|
64
|
-
return (async (...args: Parameters<T>): Promise<HttpResponse> => {
|
|
65
|
-
const event = args[0];
|
|
66
|
-
|
|
67
|
-
// Handle preflight requests
|
|
68
|
-
if (isPreflightRequest(event?.eventRaw ?? event)) {
|
|
69
|
-
return createPreflightResponse(config);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
// Execute handler and apply CORS headers
|
|
73
|
-
const response = await handler(...args);
|
|
74
|
-
return applyCorsHeaders(response, config);
|
|
75
|
-
}) as T;
|
|
76
|
-
}
|
|
1
|
+
import { CorsConfig } from '../types/routes.js';
|
|
2
|
+
import { getCorsHeaders } from '../utils/headers.js';
|
|
3
|
+
import { HttpResponse } from './response.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* CORS handling utilities
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Checks if a request is a CORS preflight request
|
|
11
|
+
* @param event - Raw API Gateway event
|
|
12
|
+
* @returns True if this is an OPTIONS preflight request
|
|
13
|
+
*/
|
|
14
|
+
export function isPreflightRequest(event: any): boolean {
|
|
15
|
+
return event.httpMethod?.toUpperCase() === 'OPTIONS';
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Creates a preflight response with CORS headers
|
|
20
|
+
* @param config - CORS configuration
|
|
21
|
+
* @returns HTTP response for preflight
|
|
22
|
+
*/
|
|
23
|
+
export function createPreflightResponse(config?: CorsConfig | boolean): HttpResponse {
|
|
24
|
+
const corsConfig = config === true ? undefined : (config === false ? undefined : config);
|
|
25
|
+
|
|
26
|
+
return {
|
|
27
|
+
statusCode: 204,
|
|
28
|
+
body: '',
|
|
29
|
+
headers: getCorsHeaders(corsConfig),
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Applies CORS headers to an existing response
|
|
35
|
+
* @param response - Original response
|
|
36
|
+
* @param config - CORS configuration
|
|
37
|
+
* @returns Response with CORS headers
|
|
38
|
+
*/
|
|
39
|
+
export function applyCorsHeaders(response: HttpResponse, config?: CorsConfig | boolean): HttpResponse {
|
|
40
|
+
if (config === false) return response;
|
|
41
|
+
|
|
42
|
+
const corsConfig = config === true ? undefined : config;
|
|
43
|
+
const corsHeaders = getCorsHeaders(corsConfig);
|
|
44
|
+
|
|
45
|
+
return {
|
|
46
|
+
...response,
|
|
47
|
+
headers: {
|
|
48
|
+
...corsHeaders,
|
|
49
|
+
...response.headers,
|
|
50
|
+
},
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* Middleware that handles CORS for a handler
|
|
56
|
+
* @param handler - Original handler function
|
|
57
|
+
* @param config - CORS configuration
|
|
58
|
+
* @returns Wrapped handler with CORS support
|
|
59
|
+
*/
|
|
60
|
+
export function withCors<T extends (...args: any[]) => Promise<HttpResponse>>(
|
|
61
|
+
handler: T,
|
|
62
|
+
config?: CorsConfig | boolean
|
|
63
|
+
): T {
|
|
64
|
+
return (async (...args: Parameters<T>): Promise<HttpResponse> => {
|
|
65
|
+
const event = args[0];
|
|
66
|
+
|
|
67
|
+
// Handle preflight requests
|
|
68
|
+
if (isPreflightRequest(event?.eventRaw ?? event)) {
|
|
69
|
+
return createPreflightResponse(config);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// Execute handler and apply CORS headers
|
|
73
|
+
const response = await handler(...args);
|
|
74
|
+
return applyCorsHeaders(response, config);
|
|
75
|
+
}) as T;
|
|
76
|
+
}
|
package/src/http/index.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export * from './response.js';
|
|
2
|
-
export * from './body-parser.js';
|
|
3
|
-
export * from './cors.js';
|
|
1
|
+
export * from './response.js';
|
|
2
|
+
export * from './body-parser.js';
|
|
3
|
+
export * from './cors.js';
|