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,101 +1,101 @@
1
- /**
2
- * Tenant types for the multi-tenant system.
3
- * - ORG: Organization/Agency (tenantId = orgProfileId)
4
- * - PERSON: Independent agent (tenantId = personProfileId)
5
- */
6
- export type TenantType = 'ORG' | 'PERSON';
7
-
8
- /**
9
- * SaaS subscription plans.
10
- * Determine the features available for a tenant.
11
- * Stored in the Tenants table and injected into JWT via Pre Token Generation.
12
- */
13
- export type Plan = 'FREE' | 'BASIC' | 'PRO' | 'ENTERPRISE';
14
-
15
- /**
16
- * Features enabled per plan.
17
- * Stored in the Tenants table and queried from JWT claim or table directly.
18
- */
19
- export interface TenantFeatures {
20
- maxProperties: number;
21
- hasWhiteLabelWebsite: boolean;
22
- hasCRMAccess: boolean;
23
- hasAdvancedAnalytics: boolean;
24
- maxAgents: number;
25
- }
26
-
27
- /**
28
- * Tenant information that travels in the context of each request.
29
- * Propagated via AsyncLocalStorage and available throughout the async chain.
30
- *
31
- * Filled from JWT claims (private/backoffice routes) or from headers
32
- * X-Tenant-Id (internal routes, Lambda-to-Lambda).
33
- */
34
- export interface TenantInfo {
35
- /** Tenant ID: orgProfileId (ORG) or personProfileId (PERSON) */
36
- tenantId: string;
37
-
38
- /** Tenant type */
39
- tenantType: TenantType;
40
-
41
- /** Authenticated user ID (Cognito sub or custom:userId) */
42
- userId: string;
43
-
44
- /** PersonProfileId of the user (always present, it's their personal profile) */
45
- personProfileId?: string;
46
-
47
- /** OrgProfileId if belongs to an organization (only for TenantType = ORG) */
48
- orgProfileId?: string;
49
-
50
- /** User's country code (ISO 3166-1 alpha-2, e.g., 'CO', 'MX', 'US') */
51
- countryCode: string;
52
-
53
- /** Tenant's plan (optional, filled if present in JWT) */
54
- plan?: Plan;
55
-
56
- /** Whether the tenant has CRM access (shortcut for features.hasCRMAccess) */
57
- hasCRM?: boolean;
58
- }
59
-
60
- /**
61
- * Custom claims injected into the Cognito JWT via Pre Token Generation.
62
- * These claims are available in event.context.identity.claims
63
- * after the orchestrator extracts the identity.
64
- */
65
- export interface TenantClaims {
66
- 'custom:tenantId': string;
67
- 'custom:tenantType': TenantType;
68
- 'custom:userId': string;
69
- 'custom:personProfileId': string;
70
- 'custom:orgProfileId'?: string;
71
- 'custom:countryCode': string;
72
- 'custom:plan'?: Plan;
73
- 'custom:hasCRM'?: string; // 'true' | 'false' (Cognito only accepts strings)
74
- 'custom:hasWhiteLabel'?: string; // 'true' | 'false'
75
- }
76
-
77
- /**
78
- * Headers used to propagate tenant in Lambda-to-Lambda calls.
79
- */
80
- export const TENANT_HEADERS = {
81
- TENANT_ID: 'x-tenant-id',
82
- TENANT_TYPE: 'x-tenant-type',
83
- USER_ID: 'x-user-id',
84
- COUNTRY_CODE: 'x-country-code',
85
- PERSON_PROFILE_ID: 'x-person-profile-id',
86
- ORG_PROFILE_ID: 'x-org-profile-id',
87
- } as const;
88
-
89
- /**
90
- * Type guard: checks if a value is a valid TenantType.
91
- */
92
- export function isTenantType(value: unknown): value is TenantType {
93
- return value === 'ORG' || value === 'PERSON';
94
- }
95
-
96
- /**
97
- * Type guard: checks if a value is a valid Plan.
98
- */
99
- export function isPlan(value: unknown): value is Plan {
100
- return value === 'FREE' || value === 'BASIC' || value === 'PRO' || value === 'ENTERPRISE';
101
- }
1
+ /**
2
+ * Tenant types for the multi-tenant system.
3
+ * - ORG: Organization/Agency (tenantId = orgProfileId)
4
+ * - PERSON: Independent agent (tenantId = personProfileId)
5
+ */
6
+ export type TenantType = 'ORG' | 'PERSON';
7
+
8
+ /**
9
+ * SaaS subscription plans.
10
+ * Determine the features available for a tenant.
11
+ * Stored in the Tenants table and injected into JWT via Pre Token Generation.
12
+ */
13
+ export type Plan = 'FREE' | 'BASIC' | 'PRO' | 'ENTERPRISE';
14
+
15
+ /**
16
+ * Features enabled per plan.
17
+ * Stored in the Tenants table and queried from JWT claim or table directly.
18
+ */
19
+ export interface TenantFeatures {
20
+ maxProperties: number;
21
+ hasWhiteLabelWebsite: boolean;
22
+ hasCRMAccess: boolean;
23
+ hasAdvancedAnalytics: boolean;
24
+ maxAgents: number;
25
+ }
26
+
27
+ /**
28
+ * Tenant information that travels in the context of each request.
29
+ * Propagated via AsyncLocalStorage and available throughout the async chain.
30
+ *
31
+ * Filled from JWT claims (private/backoffice routes) or from headers
32
+ * X-Tenant-Id (internal routes, Lambda-to-Lambda).
33
+ */
34
+ export interface TenantInfo {
35
+ /** Tenant ID: orgProfileId (ORG) or personProfileId (PERSON) */
36
+ tenantId: string;
37
+
38
+ /** Tenant type */
39
+ tenantType: TenantType;
40
+
41
+ /** Authenticated user ID (Cognito sub or custom:userId) */
42
+ userId: string;
43
+
44
+ /** PersonProfileId of the user (always present, it's their personal profile) */
45
+ personProfileId?: string;
46
+
47
+ /** OrgProfileId if belongs to an organization (only for TenantType = ORG) */
48
+ orgProfileId?: string;
49
+
50
+ /** User's country code (ISO 3166-1 alpha-2, e.g., 'CO', 'MX', 'US') */
51
+ countryCode: string;
52
+
53
+ /** Tenant's plan (optional, filled if present in JWT) */
54
+ plan?: Plan;
55
+
56
+ /** Whether the tenant has CRM access (shortcut for features.hasCRMAccess) */
57
+ hasCRM?: boolean;
58
+ }
59
+
60
+ /**
61
+ * Custom claims injected into the Cognito JWT via Pre Token Generation.
62
+ * These claims are available in event.context.identity.claims
63
+ * after the orchestrator extracts the identity.
64
+ */
65
+ export interface TenantClaims {
66
+ 'custom:tenantId': string;
67
+ 'custom:tenantType': TenantType;
68
+ 'custom:userId': string;
69
+ 'custom:personProfileId': string;
70
+ 'custom:orgProfileId'?: string;
71
+ 'custom:countryCode': string;
72
+ 'custom:plan'?: Plan;
73
+ 'custom:hasCRM'?: string; // 'true' | 'false' (Cognito only accepts strings)
74
+ 'custom:hasWhiteLabel'?: string; // 'true' | 'false'
75
+ }
76
+
77
+ /**
78
+ * Headers used to propagate tenant in Lambda-to-Lambda calls.
79
+ */
80
+ export const TENANT_HEADERS = {
81
+ TENANT_ID: 'x-tenant-id',
82
+ TENANT_TYPE: 'x-tenant-type',
83
+ USER_ID: 'x-user-id',
84
+ COUNTRY_CODE: 'x-country-code',
85
+ PERSON_PROFILE_ID: 'x-person-profile-id',
86
+ ORG_PROFILE_ID: 'x-org-profile-id',
87
+ } as const;
88
+
89
+ /**
90
+ * Type guard: checks if a value is a valid TenantType.
91
+ */
92
+ export function isTenantType(value: unknown): value is TenantType {
93
+ return value === 'ORG' || value === 'PERSON';
94
+ }
95
+
96
+ /**
97
+ * Type guard: checks if a value is a valid Plan.
98
+ */
99
+ export function isPlan(value: unknown): value is Plan {
100
+ return value === 'FREE' || value === 'BASIC' || value === 'PRO' || value === 'ENTERPRISE';
101
+ }
@@ -1,20 +1,21 @@
1
- /**
2
- * Supported AWS event types for dispatching
3
- */
4
- export enum EventType {
5
- EventBridge = 'eventbridge',
6
- ApiGateway = 'apigateway',
7
- Lambda = 'lambda',
8
- Sqs = 'sqs',
9
- Unknown = 'unknown',
10
- }
11
-
12
- /**
13
- * Route segments for access control categorization
14
- */
15
- export enum RouteSegment {
16
- Public = 'public',
17
- Private = 'private',
18
- Backoffice = 'backoffice',
19
- Internal = 'internal',
20
- }
1
+ /**
2
+ * Supported AWS event types for dispatching
3
+ */
4
+ export enum EventType {
5
+ EventBridge = 'eventbridge',
6
+ ApiGateway = 'apigateway',
7
+ Lambda = 'lambda',
8
+ Sqs = 'sqs',
9
+ Scheduled = 'scheduled',
10
+ Unknown = 'unknown',
11
+ }
12
+
13
+ /**
14
+ * Route segments for access control categorization
15
+ */
16
+ export enum RouteSegment {
17
+ Public = 'public',
18
+ Private = 'private',
19
+ Backoffice = 'backoffice',
20
+ Internal = 'internal',
21
+ }
@@ -1,2 +1,2 @@
1
- export * from './event-type.enum.js';
2
- export * from './routes.js';
1
+ export * from './event-type.enum.js';
2
+ export * from './routes.js';