serverless-event-orchestrator 2.2.0 → 2.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.
Files changed (45) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +489 -489
  3. package/dist/dispatcher.d.ts +6 -1
  4. package/dist/dispatcher.d.ts.map +1 -1
  5. package/dist/dispatcher.js +31 -7
  6. package/dist/dispatcher.js.map +1 -1
  7. package/dist/tenant/helpers.js +1 -1
  8. package/dist/tenant/helpers.js.map +1 -1
  9. package/jest.config.js +32 -32
  10. package/package.json +82 -81
  11. package/src/dispatcher.ts +586 -558
  12. package/src/http/body-parser.ts +60 -60
  13. package/src/http/cors.ts +76 -76
  14. package/src/http/index.ts +3 -3
  15. package/src/http/response.ts +209 -209
  16. package/src/identity/extractor.ts +207 -207
  17. package/src/identity/index.ts +2 -2
  18. package/src/identity/jwt-verifier.ts +41 -41
  19. package/src/index.ts +128 -128
  20. package/src/middleware/crm-guard.ts +51 -51
  21. package/src/middleware/index.ts +3 -3
  22. package/src/middleware/init-tenant-context.ts +59 -59
  23. package/src/middleware/tenant-guard.ts +54 -54
  24. package/src/tenant/TenantContext.ts +115 -115
  25. package/src/tenant/helpers.ts +112 -112
  26. package/src/tenant/index.ts +21 -21
  27. package/src/tenant/types.ts +101 -101
  28. package/src/types/event-type.enum.ts +21 -21
  29. package/src/types/index.ts +2 -2
  30. package/src/types/routes.ts +218 -218
  31. package/src/utils/headers.ts +72 -72
  32. package/src/utils/index.ts +2 -2
  33. package/src/utils/path-matcher.ts +84 -84
  34. package/tests/cors.test.ts +133 -133
  35. package/tests/dispatcher.test.ts +795 -715
  36. package/tests/headers.test.ts +99 -99
  37. package/tests/identity.test.ts +301 -301
  38. package/tests/middleware/crm-guard.test.ts +69 -69
  39. package/tests/middleware/init-tenant-context.test.ts +147 -147
  40. package/tests/middleware/tenant-guard.test.ts +100 -100
  41. package/tests/path-matcher.test.ts +102 -102
  42. package/tests/response.test.ts +155 -155
  43. package/tests/tenant/TenantContext.test.ts +134 -134
  44. package/tests/tenant/helpers.test.ts +187 -187
  45. package/tsconfig.json +24 -24
@@ -1,209 +1,209 @@
1
- /**
2
- * Response utilities for consistent HTTP responses
3
- * Agnostic to domain-specific error codes - allows injection of custom codes
4
- */
5
-
6
- /**
7
- * Standard HTTP status codes
8
- */
9
- export enum HttpStatus {
10
- OK = 200,
11
- CREATED = 201,
12
- NO_CONTENT = 204,
13
- BAD_REQUEST = 400,
14
- UNAUTHORIZED = 401,
15
- FORBIDDEN = 403,
16
- NOT_FOUND = 404,
17
- CONFLICT = 409,
18
- UNPROCESSABLE_ENTITY = 422,
19
- INTERNAL_SERVER_ERROR = 500,
20
- SERVICE_UNAVAILABLE = 503,
21
- }
22
-
23
- /**
24
- * Standard response structure
25
- */
26
- export interface StandardResponse<T = unknown, C = string> {
27
- status: number;
28
- code: C;
29
- data?: T;
30
- message?: string;
31
- }
32
-
33
- /**
34
- * Lambda HTTP response format
35
- */
36
- export interface HttpResponse {
37
- statusCode: number;
38
- body: string;
39
- headers?: Record<string, string>;
40
- }
41
-
42
- /**
43
- * Default response codes for standard HTTP statuses
44
- */
45
- export const DefaultResponseCode = {
46
- SUCCESS: 'SUCCESS',
47
- CREATED: 'CREATED',
48
- BAD_REQUEST: 'BAD_REQUEST',
49
- UNAUTHORIZED: 'UNAUTHORIZED',
50
- FORBIDDEN: 'FORBIDDEN',
51
- NOT_FOUND: 'NOT_FOUND',
52
- CONFLICT: 'CONFLICT',
53
- VALIDATION_ERROR: 'VALIDATION_ERROR',
54
- INTERNAL_ERROR: 'INTERNAL_ERROR',
55
- } as const;
56
-
57
- /**
58
- * Creates a standardized HTTP response.
59
- * Automatically handles data/message normalization to ensure consistent structure.
60
- *
61
- * @param statusCode - HTTP status code
62
- * @param data - Response payload (will be placed in 'data' field)
63
- * @param code - Custom response code (Domain-specific)
64
- * @param message - Optional message (if provided and data is null, message content will be put into 'data' for backward compatibility if needed, but the library now prefers explicit data)
65
- * @param headers - Optional headers
66
- */
67
- export function createStandardResponse<T, C = string>(
68
- statusCode: number,
69
- data?: T,
70
- code?: C,
71
- message?: string,
72
- headers?: Record<string, string>
73
- ): HttpResponse {
74
- const responseCode = code ?? (getDefaultCodeForStatus(statusCode) as unknown as C);
75
-
76
- // Normalización automática:
77
- // Si tenemos un mensaje pero no data, y el status es error,
78
- // podríamos querer que el mensaje sea la descripción en data.
79
- // Pero lo más limpio es seguir la estructura: { status, code, data, message }
80
-
81
- const body: StandardResponse<T, C> = {
82
- status: statusCode,
83
- code: responseCode,
84
- ...(data !== undefined && { data }),
85
- ...(message && { message }),
86
- };
87
-
88
- const corsOrigin = process.env.CORS_ALLOWED_ORIGINS || '*';
89
- const corsHeaders = process.env.CORS_ALLOWED_HEADERS ||
90
- 'Content-Type,Authorization,X-Amz-Date,X-Api-Key,X-Amz-Security-Token,appVersion,app-version,platform,geo,x-forwarded-for,x-real-ip';
91
- const corsMethods = process.env.CORS_ALLOWED_METHODS || 'GET,POST,PUT,PATCH,DELETE,OPTIONS';
92
-
93
- return {
94
- statusCode,
95
- body: JSON.stringify(body, null, 2),
96
- headers: {
97
- 'Content-Type': 'application/json',
98
- 'Access-Control-Allow-Origin': corsOrigin,
99
- 'Access-Control-Allow-Headers': corsHeaders,
100
- 'Access-Control-Allow-Methods': corsMethods,
101
- ...headers,
102
- },
103
- };
104
- }
105
-
106
- /**
107
- * Gets default response code for a status
108
- */
109
- function getDefaultCodeForStatus(status: number): string {
110
- switch (status) {
111
- case HttpStatus.OK:
112
- return DefaultResponseCode.SUCCESS;
113
- case HttpStatus.CREATED:
114
- return DefaultResponseCode.CREATED;
115
- case HttpStatus.BAD_REQUEST:
116
- return DefaultResponseCode.BAD_REQUEST;
117
- case HttpStatus.UNAUTHORIZED:
118
- return DefaultResponseCode.UNAUTHORIZED;
119
- case HttpStatus.FORBIDDEN:
120
- return DefaultResponseCode.FORBIDDEN;
121
- case HttpStatus.NOT_FOUND:
122
- return DefaultResponseCode.NOT_FOUND;
123
- case HttpStatus.CONFLICT:
124
- return DefaultResponseCode.CONFLICT;
125
- case HttpStatus.UNPROCESSABLE_ENTITY:
126
- return DefaultResponseCode.VALIDATION_ERROR;
127
- default:
128
- return DefaultResponseCode.INTERNAL_ERROR;
129
- }
130
- }
131
-
132
- /**
133
- * Success response (200 OK)
134
- */
135
- export function successResponse<T, C = string>(data?: T, code?: C, headers?: Record<string, string>): HttpResponse {
136
- return createStandardResponse(HttpStatus.OK, data, code, undefined, headers);
137
- }
138
-
139
- /**
140
- * Created response (201 Created)
141
- */
142
- export function createdResponse<T, C = string>(data?: T, code?: C, headers?: Record<string, string>): HttpResponse {
143
- return createStandardResponse(HttpStatus.CREATED, data, code, undefined, headers);
144
- }
145
-
146
- /**
147
- * Bad request response (400)
148
- */
149
- export function badRequestResponse<C = string>(message?: string, code?: C, headers?: Record<string, string>): HttpResponse {
150
- return createStandardResponse(HttpStatus.BAD_REQUEST, undefined, code, message, headers);
151
- }
152
-
153
- /**
154
- * Unauthorized response (401)
155
- */
156
- export function unauthorizedResponse<C = string>(message?: string, code?: C, headers?: Record<string, string>): HttpResponse {
157
- return createStandardResponse(HttpStatus.UNAUTHORIZED, undefined, code, message, headers);
158
- }
159
-
160
- /**
161
- * Forbidden response (403)
162
- */
163
- export function forbiddenResponse<C = string>(message?: string, code?: C, headers?: Record<string, string>): HttpResponse {
164
- return createStandardResponse(HttpStatus.FORBIDDEN, undefined, code, message, headers);
165
- }
166
-
167
- /**
168
- * Not found response (404)
169
- */
170
- export function notFoundResponse<C = string>(message?: string, code?: C, headers?: Record<string, string>): HttpResponse {
171
- return createStandardResponse(HttpStatus.NOT_FOUND, undefined, code, message, headers);
172
- }
173
-
174
- /**
175
- * Conflict response (409)
176
- */
177
- export function conflictResponse<C = string>(message?: string, code?: C, headers?: Record<string, string>): HttpResponse {
178
- return createStandardResponse(HttpStatus.CONFLICT, undefined, code, message, headers);
179
- }
180
-
181
- /**
182
- * Validation error response (422)
183
- */
184
- export function validationErrorResponse<C = string>(message?: string, code?: C, headers?: Record<string, string>): HttpResponse {
185
- return createStandardResponse(HttpStatus.UNPROCESSABLE_ENTITY, undefined, code, message, headers);
186
- }
187
-
188
- /**
189
- * Internal server error response (500)
190
- */
191
- export function internalErrorResponse<C = string>(message?: string, code?: C, headers?: Record<string, string>): HttpResponse {
192
- return createStandardResponse(HttpStatus.INTERNAL_SERVER_ERROR, undefined, code, message, headers);
193
- }
194
-
195
- /**
196
- * Custom error response with automatic status resolution
197
- * @param customCode - Your domain-specific error code
198
- * @param message - Error message
199
- * @param codeToStatusMap - Mapping of custom codes to HTTP statuses
200
- */
201
- export function customErrorResponse<C extends string>(
202
- customCode: C,
203
- message?: string,
204
- codeToStatusMap?: Record<C, HttpStatus>,
205
- headers?: Record<string, string>
206
- ): HttpResponse {
207
- const status = codeToStatusMap?.[customCode] ?? HttpStatus.INTERNAL_SERVER_ERROR;
208
- return createStandardResponse(status, undefined, customCode, message, headers);
209
- }
1
+ /**
2
+ * Response utilities for consistent HTTP responses
3
+ * Agnostic to domain-specific error codes - allows injection of custom codes
4
+ */
5
+
6
+ /**
7
+ * Standard HTTP status codes
8
+ */
9
+ export enum HttpStatus {
10
+ OK = 200,
11
+ CREATED = 201,
12
+ NO_CONTENT = 204,
13
+ BAD_REQUEST = 400,
14
+ UNAUTHORIZED = 401,
15
+ FORBIDDEN = 403,
16
+ NOT_FOUND = 404,
17
+ CONFLICT = 409,
18
+ UNPROCESSABLE_ENTITY = 422,
19
+ INTERNAL_SERVER_ERROR = 500,
20
+ SERVICE_UNAVAILABLE = 503,
21
+ }
22
+
23
+ /**
24
+ * Standard response structure
25
+ */
26
+ export interface StandardResponse<T = unknown, C = string> {
27
+ status: number;
28
+ code: C;
29
+ data?: T;
30
+ message?: string;
31
+ }
32
+
33
+ /**
34
+ * Lambda HTTP response format
35
+ */
36
+ export interface HttpResponse {
37
+ statusCode: number;
38
+ body: string;
39
+ headers?: Record<string, string>;
40
+ }
41
+
42
+ /**
43
+ * Default response codes for standard HTTP statuses
44
+ */
45
+ export const DefaultResponseCode = {
46
+ SUCCESS: 'SUCCESS',
47
+ CREATED: 'CREATED',
48
+ BAD_REQUEST: 'BAD_REQUEST',
49
+ UNAUTHORIZED: 'UNAUTHORIZED',
50
+ FORBIDDEN: 'FORBIDDEN',
51
+ NOT_FOUND: 'NOT_FOUND',
52
+ CONFLICT: 'CONFLICT',
53
+ VALIDATION_ERROR: 'VALIDATION_ERROR',
54
+ INTERNAL_ERROR: 'INTERNAL_ERROR',
55
+ } as const;
56
+
57
+ /**
58
+ * Creates a standardized HTTP response.
59
+ * Automatically handles data/message normalization to ensure consistent structure.
60
+ *
61
+ * @param statusCode - HTTP status code
62
+ * @param data - Response payload (will be placed in 'data' field)
63
+ * @param code - Custom response code (Domain-specific)
64
+ * @param message - Optional message (if provided and data is null, message content will be put into 'data' for backward compatibility if needed, but the library now prefers explicit data)
65
+ * @param headers - Optional headers
66
+ */
67
+ export function createStandardResponse<T, C = string>(
68
+ statusCode: number,
69
+ data?: T,
70
+ code?: C,
71
+ message?: string,
72
+ headers?: Record<string, string>
73
+ ): HttpResponse {
74
+ const responseCode = code ?? (getDefaultCodeForStatus(statusCode) as unknown as C);
75
+
76
+ // Normalización automática:
77
+ // Si tenemos un mensaje pero no data, y el status es error,
78
+ // podríamos querer que el mensaje sea la descripción en data.
79
+ // Pero lo más limpio es seguir la estructura: { status, code, data, message }
80
+
81
+ const body: StandardResponse<T, C> = {
82
+ status: statusCode,
83
+ code: responseCode,
84
+ ...(data !== undefined && { data }),
85
+ ...(message && { message }),
86
+ };
87
+
88
+ const corsOrigin = process.env.CORS_ALLOWED_ORIGINS || '*';
89
+ const corsHeaders = process.env.CORS_ALLOWED_HEADERS ||
90
+ 'Content-Type,Authorization,X-Amz-Date,X-Api-Key,X-Amz-Security-Token,appVersion,app-version,platform,geo,x-forwarded-for,x-real-ip';
91
+ const corsMethods = process.env.CORS_ALLOWED_METHODS || 'GET,POST,PUT,PATCH,DELETE,OPTIONS';
92
+
93
+ return {
94
+ statusCode,
95
+ body: JSON.stringify(body, null, 2),
96
+ headers: {
97
+ 'Content-Type': 'application/json',
98
+ 'Access-Control-Allow-Origin': corsOrigin,
99
+ 'Access-Control-Allow-Headers': corsHeaders,
100
+ 'Access-Control-Allow-Methods': corsMethods,
101
+ ...headers,
102
+ },
103
+ };
104
+ }
105
+
106
+ /**
107
+ * Gets default response code for a status
108
+ */
109
+ function getDefaultCodeForStatus(status: number): string {
110
+ switch (status) {
111
+ case HttpStatus.OK:
112
+ return DefaultResponseCode.SUCCESS;
113
+ case HttpStatus.CREATED:
114
+ return DefaultResponseCode.CREATED;
115
+ case HttpStatus.BAD_REQUEST:
116
+ return DefaultResponseCode.BAD_REQUEST;
117
+ case HttpStatus.UNAUTHORIZED:
118
+ return DefaultResponseCode.UNAUTHORIZED;
119
+ case HttpStatus.FORBIDDEN:
120
+ return DefaultResponseCode.FORBIDDEN;
121
+ case HttpStatus.NOT_FOUND:
122
+ return DefaultResponseCode.NOT_FOUND;
123
+ case HttpStatus.CONFLICT:
124
+ return DefaultResponseCode.CONFLICT;
125
+ case HttpStatus.UNPROCESSABLE_ENTITY:
126
+ return DefaultResponseCode.VALIDATION_ERROR;
127
+ default:
128
+ return DefaultResponseCode.INTERNAL_ERROR;
129
+ }
130
+ }
131
+
132
+ /**
133
+ * Success response (200 OK)
134
+ */
135
+ export function successResponse<T, C = string>(data?: T, code?: C, headers?: Record<string, string>): HttpResponse {
136
+ return createStandardResponse(HttpStatus.OK, data, code, undefined, headers);
137
+ }
138
+
139
+ /**
140
+ * Created response (201 Created)
141
+ */
142
+ export function createdResponse<T, C = string>(data?: T, code?: C, headers?: Record<string, string>): HttpResponse {
143
+ return createStandardResponse(HttpStatus.CREATED, data, code, undefined, headers);
144
+ }
145
+
146
+ /**
147
+ * Bad request response (400)
148
+ */
149
+ export function badRequestResponse<C = string>(message?: string, code?: C, headers?: Record<string, string>): HttpResponse {
150
+ return createStandardResponse(HttpStatus.BAD_REQUEST, undefined, code, message, headers);
151
+ }
152
+
153
+ /**
154
+ * Unauthorized response (401)
155
+ */
156
+ export function unauthorizedResponse<C = string>(message?: string, code?: C, headers?: Record<string, string>): HttpResponse {
157
+ return createStandardResponse(HttpStatus.UNAUTHORIZED, undefined, code, message, headers);
158
+ }
159
+
160
+ /**
161
+ * Forbidden response (403)
162
+ */
163
+ export function forbiddenResponse<C = string>(message?: string, code?: C, headers?: Record<string, string>): HttpResponse {
164
+ return createStandardResponse(HttpStatus.FORBIDDEN, undefined, code, message, headers);
165
+ }
166
+
167
+ /**
168
+ * Not found response (404)
169
+ */
170
+ export function notFoundResponse<C = string>(message?: string, code?: C, headers?: Record<string, string>): HttpResponse {
171
+ return createStandardResponse(HttpStatus.NOT_FOUND, undefined, code, message, headers);
172
+ }
173
+
174
+ /**
175
+ * Conflict response (409)
176
+ */
177
+ export function conflictResponse<C = string>(message?: string, code?: C, headers?: Record<string, string>): HttpResponse {
178
+ return createStandardResponse(HttpStatus.CONFLICT, undefined, code, message, headers);
179
+ }
180
+
181
+ /**
182
+ * Validation error response (422)
183
+ */
184
+ export function validationErrorResponse<C = string>(message?: string, code?: C, headers?: Record<string, string>): HttpResponse {
185
+ return createStandardResponse(HttpStatus.UNPROCESSABLE_ENTITY, undefined, code, message, headers);
186
+ }
187
+
188
+ /**
189
+ * Internal server error response (500)
190
+ */
191
+ export function internalErrorResponse<C = string>(message?: string, code?: C, headers?: Record<string, string>): HttpResponse {
192
+ return createStandardResponse(HttpStatus.INTERNAL_SERVER_ERROR, undefined, code, message, headers);
193
+ }
194
+
195
+ /**
196
+ * Custom error response with automatic status resolution
197
+ * @param customCode - Your domain-specific error code
198
+ * @param message - Error message
199
+ * @param codeToStatusMap - Mapping of custom codes to HTTP statuses
200
+ */
201
+ export function customErrorResponse<C extends string>(
202
+ customCode: C,
203
+ message?: string,
204
+ codeToStatusMap?: Record<C, HttpStatus>,
205
+ headers?: Record<string, string>
206
+ ): HttpResponse {
207
+ const status = codeToStatusMap?.[customCode] ?? HttpStatus.INTERNAL_SERVER_ERROR;
208
+ return createStandardResponse(status, undefined, customCode, message, headers);
209
+ }