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.
Files changed (52) hide show
  1. package/LICENSE +21 -21
  2. package/README.md +489 -434
  3. package/dist/dispatcher.d.ts +6 -1
  4. package/dist/dispatcher.d.ts.map +1 -1
  5. package/dist/dispatcher.js +66 -7
  6. package/dist/dispatcher.js.map +1 -1
  7. package/dist/index.d.ts +1 -1
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js.map +1 -1
  10. package/dist/types/event-type.enum.d.ts +1 -0
  11. package/dist/types/event-type.enum.d.ts.map +1 -1
  12. package/dist/types/event-type.enum.js +1 -0
  13. package/dist/types/event-type.enum.js.map +1 -1
  14. package/dist/types/routes.d.ts +6 -0
  15. package/dist/types/routes.d.ts.map +1 -1
  16. package/jest.config.js +32 -32
  17. package/package.json +82 -81
  18. package/src/dispatcher.ts +586 -519
  19. package/src/http/body-parser.ts +60 -60
  20. package/src/http/cors.ts +76 -76
  21. package/src/http/index.ts +3 -3
  22. package/src/http/response.ts +209 -209
  23. package/src/identity/extractor.ts +207 -207
  24. package/src/identity/index.ts +2 -2
  25. package/src/identity/jwt-verifier.ts +41 -41
  26. package/src/index.ts +128 -127
  27. package/src/middleware/crm-guard.ts +51 -51
  28. package/src/middleware/index.ts +3 -3
  29. package/src/middleware/init-tenant-context.ts +59 -59
  30. package/src/middleware/tenant-guard.ts +54 -54
  31. package/src/tenant/TenantContext.ts +115 -115
  32. package/src/tenant/helpers.ts +112 -112
  33. package/src/tenant/index.ts +21 -21
  34. package/src/tenant/types.ts +101 -101
  35. package/src/types/event-type.enum.ts +21 -20
  36. package/src/types/index.ts +2 -2
  37. package/src/types/routes.ts +218 -211
  38. package/src/utils/headers.ts +72 -72
  39. package/src/utils/index.ts +2 -2
  40. package/src/utils/path-matcher.ts +84 -84
  41. package/tests/cors.test.ts +133 -133
  42. package/tests/dispatcher.test.ts +795 -715
  43. package/tests/headers.test.ts +99 -99
  44. package/tests/identity.test.ts +301 -301
  45. package/tests/middleware/crm-guard.test.ts +69 -69
  46. package/tests/middleware/init-tenant-context.test.ts +147 -147
  47. package/tests/middleware/tenant-guard.test.ts +100 -100
  48. package/tests/path-matcher.test.ts +102 -102
  49. package/tests/response.test.ts +155 -155
  50. package/tests/tenant/TenantContext.test.ts +134 -134
  51. package/tests/tenant/helpers.test.ts +187 -187
  52. 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
+ }