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,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,21 +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
- 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
+ * 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';