@webiny/api-event-handler-aws 0.0.0-unstable.0d717d18dd → 6.6.0-alpha.1

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 (36) hide show
  1. package/composition/index.d.ts +4 -0
  2. package/composition/index.js +4 -0
  3. package/composition/registerInboundEventTypes.d.ts +16 -0
  4. package/composition/registerInboundEventTypes.js +16 -0
  5. package/composition/registerInboundEventTypes.js.map +1 -0
  6. package/composition/registerWebinyApiChild.d.ts +10 -0
  7. package/composition/registerWebinyApiChild.js +24 -0
  8. package/composition/registerWebinyApiChild.js.map +1 -0
  9. package/composition/registerWebinyApiRoot.d.ts +8 -0
  10. package/composition/registerWebinyApiRoot.js +14 -0
  11. package/composition/registerWebinyApiRoot.js.map +1 -0
  12. package/composition/types.d.ts +35 -0
  13. package/composition/types.js +0 -0
  14. package/createWebinyApiHandler.d.ts +3 -40
  15. package/createWebinyApiHandler.js +6 -40
  16. package/createWebinyApiHandler.js.map +1 -1
  17. package/createWebinyStreamApiHandler.d.ts +3 -0
  18. package/createWebinyStreamApiHandler.js +23 -0
  19. package/createWebinyStreamApiHandler.js.map +1 -0
  20. package/handlers/ApiGatewayIdentityLoaderDecorator.d.ts +3 -4
  21. package/handlers/ApiGatewayIdentityLoaderDecorator.js +4 -16
  22. package/handlers/ApiGatewayIdentityLoaderDecorator.js.map +1 -1
  23. package/handlers/FunctionUrlStreamIdentityLoaderDecorator.d.ts +22 -0
  24. package/handlers/FunctionUrlStreamIdentityLoaderDecorator.js +27 -0
  25. package/handlers/FunctionUrlStreamIdentityLoaderDecorator.js.map +1 -0
  26. package/handlers/FunctionUrlStreamTenantLoaderDecorator.d.ts +22 -0
  27. package/handlers/FunctionUrlStreamTenantLoaderDecorator.js +27 -0
  28. package/handlers/FunctionUrlStreamTenantLoaderDecorator.js.map +1 -0
  29. package/handlers/extractRequestAuth.d.ts +21 -0
  30. package/handlers/extractRequestAuth.js +34 -0
  31. package/handlers/extractRequestAuth.js.map +1 -0
  32. package/handlers/index.d.ts +3 -0
  33. package/handlers/index.js +3 -0
  34. package/index.d.ts +3 -0
  35. package/index.js +1 -0
  36. package/package.json +18 -18
@@ -0,0 +1,4 @@
1
+ export * from "./types.js";
2
+ export * from "./registerInboundEventTypes.js";
3
+ export * from "./registerWebinyApiRoot.js";
4
+ export * from "./registerWebinyApiChild.js";
@@ -0,0 +1,4 @@
1
+ export * from "./types.js";
2
+ export * from "./registerInboundEventTypes.js";
3
+ export * from "./registerWebinyApiRoot.js";
4
+ export * from "./registerWebinyApiChild.js";
@@ -0,0 +1,16 @@
1
+ import type { Container } from "@webiny/di";
2
+ /**
3
+ * Registers every NON-HTTP way this Lambda can be invoked: the event type that recognises the
4
+ * payload shape, plus the handler the dispatcher resolves once it matches. (The HTTP transport is
5
+ * registered by `ApiGatewayFeature`, which also brings the router.)
6
+ *
7
+ * Both halves are required. An event type with no handler resolves to an empty handler chain and
8
+ * the invocation silently does nothing; a handler with no event type fails the dispatch outright
9
+ * with "No event type matched the incoming event".
10
+ *
11
+ * This lives in one function so the set is testable, and so an inbound transport cannot be
12
+ * half-wired. Two bugs of exactly that shape have already shipped: WebSockets ($connect never
13
+ * dispatched, so server→client push was dead) and EventBridge Scheduler (schedules were created
14
+ * and fired, but the invocation was rejected, so scheduled publishing silently never happened).
15
+ */
16
+ export declare function registerInboundEventTypes(container: Container): void;
@@ -0,0 +1,16 @@
1
+ import { BackgroundTaskEventType, EventBridgeEventType, ScheduledActionEventType, WebSocketEventType } from "@webiny/event-handler-aws";
2
+ import { BackgroundTasksAwsFeature } from "@webiny/background-tasks-aws";
3
+ import { BulkActionsEventBridgeLambdaHandlerFeature } from "@webiny/api-headless-cms-bulk-actions-aws";
4
+ import { ScheduledActionLambdaHandler } from "@webiny/api-scheduler";
5
+ function registerInboundEventTypes(container) {
6
+ container.register(BackgroundTaskEventType);
7
+ BackgroundTasksAwsFeature.register(container);
8
+ container.register(EventBridgeEventType);
9
+ BulkActionsEventBridgeLambdaHandlerFeature.register(container);
10
+ container.register(ScheduledActionEventType);
11
+ container.register(ScheduledActionLambdaHandler);
12
+ container.register(WebSocketEventType);
13
+ }
14
+ export { registerInboundEventTypes };
15
+
16
+ //# sourceMappingURL=registerInboundEventTypes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"composition/registerInboundEventTypes.js","sources":["../../src/composition/registerInboundEventTypes.ts"],"sourcesContent":["import type { Container } from \"@webiny/di\";\nimport {\n BackgroundTaskEventType,\n EventBridgeEventType,\n ScheduledActionEventType,\n WebSocketEventType\n} from \"@webiny/event-handler-aws\";\nimport { BackgroundTasksAwsFeature } from \"@webiny/background-tasks-aws\";\nimport { BulkActionsEventBridgeLambdaHandlerFeature } from \"@webiny/api-headless-cms-bulk-actions-aws\";\nimport { ScheduledActionLambdaHandler } from \"@webiny/api-scheduler\";\n\n/**\n * Registers every NON-HTTP way this Lambda can be invoked: the event type that recognises the\n * payload shape, plus the handler the dispatcher resolves once it matches. (The HTTP transport is\n * registered by `ApiGatewayFeature`, which also brings the router.)\n *\n * Both halves are required. An event type with no handler resolves to an empty handler chain and\n * the invocation silently does nothing; a handler with no event type fails the dispatch outright\n * with \"No event type matched the incoming event\".\n *\n * This lives in one function so the set is testable, and so an inbound transport cannot be\n * half-wired. Two bugs of exactly that shape have already shipped: WebSockets ($connect never\n * dispatched, so server→client push was dead) and EventBridge Scheduler (schedules were created\n * and fired, but the invocation was rejected, so scheduled publishing silently never happened).\n */\nexport function registerInboundEventTypes(container: Container): void {\n // Background task invocations (Step Functions → Lambda directly). BackgroundTasksAwsFeature\n // registers the Lambda handler + StepFunctionService (the AWS dispatch transport).\n container.register(BackgroundTaskEventType);\n BackgroundTasksAwsFeature.register(container);\n\n // EventBridge invocations (e.g. scheduled empty-trash-bin).\n container.register(EventBridgeEventType);\n BulkActionsEventBridgeLambdaHandlerFeature.register(container);\n\n // EventBridge Scheduler invocations (a scheduled publish/unpublish firing). SchedulerAwsFeature\n // wires only the OUTBOUND side (creating the schedule), so the inbound half belongs here.\n container.register(ScheduledActionEventType);\n container.register(ScheduledActionLambdaHandler);\n\n // API Gateway WebSocket invocations ($connect/$disconnect/$default). The connection handlers\n // come from WebsocketsFeature in the per-request stack.\n container.register(WebSocketEventType);\n}\n"],"names":["registerInboundEventTypes","container","BackgroundTaskEventType","BackgroundTasksAwsFeature","EventBridgeEventType","BulkActionsEventBridgeLambdaHandlerFeature","ScheduledActionEventType","ScheduledActionLambdaHandler","WebSocketEventType"],"mappings":";;;;AAyBO,SAASA,0BAA0BC,SAAoB;IAG1DA,UAAU,QAAQ,CAACC;IACnBC,0BAA0B,QAAQ,CAACF;IAGnCA,UAAU,QAAQ,CAACG;IACnBC,2CAA2C,QAAQ,CAACJ;IAIpDA,UAAU,QAAQ,CAACK;IACnBL,UAAU,QAAQ,CAACM;IAInBN,UAAU,QAAQ,CAACO;AACvB"}
@@ -0,0 +1,10 @@
1
+ import type { Container } from "@webiny/di";
2
+ import type { WebinyApiCompositionConfig } from "./types.js";
3
+ /**
4
+ * Sets up the per-request CHILD container: the transport-agnostic feature stack (shared with the
5
+ * server transport), with the AWS-specific interleave points supplied as the `transports` adapters.
6
+ *
7
+ * Named for the `child` lifecycle step of `HandlerConfig`, not "request", so it matches the contract
8
+ * it implements.
9
+ */
10
+ export declare function registerWebinyApiChild(container: Container, config: WebinyApiCompositionConfig): Promise<void>;
@@ -0,0 +1,24 @@
1
+ import { registerApiRequestStack } from "@webiny/api-event-handler-core";
2
+ import { WebsocketsAwsFeature } from "@webiny/api-websockets-aws";
3
+ import { SchedulerAwsFeature } from "@webiny/api-scheduler-aws";
4
+ import { FileManagerS3Feature } from "@webiny/api-file-manager-s3";
5
+ async function registerWebinyApiChild(container, config) {
6
+ await registerApiRequestStack(container, {
7
+ extensions: config.extensions,
8
+ registerRequestStorage: config.registerRequestStorage,
9
+ transports: {
10
+ realtime: (c)=>{
11
+ WebsocketsAwsFeature.register(c);
12
+ },
13
+ scheduler: (c)=>{
14
+ SchedulerAwsFeature.register(c);
15
+ },
16
+ fileManager: (c)=>{
17
+ FileManagerS3Feature.register(c, {});
18
+ }
19
+ }
20
+ });
21
+ }
22
+ export { registerWebinyApiChild };
23
+
24
+ //# sourceMappingURL=registerWebinyApiChild.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"composition/registerWebinyApiChild.js","sources":["../../src/composition/registerWebinyApiChild.ts"],"sourcesContent":["import type { Container } from \"@webiny/di\";\nimport { registerApiRequestStack } from \"@webiny/api-event-handler-core\";\nimport { WebsocketsAwsFeature } from \"@webiny/api-websockets-aws\";\nimport { SchedulerAwsFeature } from \"@webiny/api-scheduler-aws\";\nimport { FileManagerS3Feature } from \"@webiny/api-file-manager-s3\";\nimport type { WebinyApiCompositionConfig } from \"./types.js\";\n\n/**\n * Sets up the per-request CHILD container: the transport-agnostic feature stack (shared with the\n * server transport), with the AWS-specific interleave points supplied as the `transports` adapters.\n *\n * Named for the `child` lifecycle step of `HandlerConfig`, not \"request\", so it matches the contract\n * it implements.\n */\nexport async function registerWebinyApiChild(\n container: Container,\n config: WebinyApiCompositionConfig\n): Promise<void> {\n await registerApiRequestStack(container, {\n extensions: config.extensions,\n registerRequestStorage: config.registerRequestStorage,\n transports: {\n // Real AWS WebSocket transport (API Gateway Management API), registered right after\n // WebsocketsFeature so it overrides the NullWebsocketsTransport.\n realtime: c => {\n WebsocketsAwsFeature.register(c);\n },\n // Scheduler transport: the scheduler-aws extension (EventBridge Scheduler).\n scheduler: c => {\n SchedulerAwsFeature.register(c);\n },\n // File-manager storage transport: S3 (asset delivery + S3 file operations + schema).\n fileManager: c => {\n FileManagerS3Feature.register(c, {});\n }\n }\n });\n}\n"],"names":["registerWebinyApiChild","container","config","registerApiRequestStack","c","WebsocketsAwsFeature","SchedulerAwsFeature","FileManagerS3Feature"],"mappings":";;;;AAcO,eAAeA,uBAClBC,SAAoB,EACpBC,MAAkC;IAElC,MAAMC,wBAAwBF,WAAW;QACrC,YAAYC,OAAO,UAAU;QAC7B,wBAAwBA,OAAO,sBAAsB;QACrD,YAAY;YAGR,UAAUE,CAAAA;gBACNC,qBAAqB,QAAQ,CAACD;YAClC;YAEA,WAAWA,CAAAA;gBACPE,oBAAoB,QAAQ,CAACF;YACjC;YAEA,aAAaA,CAAAA;gBACTG,qBAAqB,QAAQ,CAACH,GAAG,CAAC;YACtC;QACJ;IACJ;AACJ"}
@@ -0,0 +1,8 @@
1
+ import type { Container } from "@webiny/di";
2
+ import type { getDocumentClient } from "@webiny/aws-sdk/client-dynamodb/index.js";
3
+ import type { WebinyApiCompositionConfig } from "./types.js";
4
+ /**
5
+ * ROOT container registration that is not transport-specific: database, identity providers, and the
6
+ * storage variant. Shared by both AWS Lambda composition roots.
7
+ */
8
+ export declare function registerWebinyApiRoot(container: Container, config: WebinyApiCompositionConfig, documentClient: ReturnType<typeof getDocumentClient>): Promise<void>;
@@ -0,0 +1,14 @@
1
+ import { DynamoDBCoreFeature } from "@webiny/db-dynamodb";
2
+ import { CognitoIdpFeature } from "@webiny/cognito/api/features/CognitoIdp/feature.js";
3
+ async function registerWebinyApiRoot(container, config, documentClient) {
4
+ DynamoDBCoreFeature.register(container, {
5
+ documentClient
6
+ });
7
+ CognitoIdpFeature.register(container);
8
+ await config.registerRootStorage(container, {
9
+ documentClient
10
+ });
11
+ }
12
+ export { registerWebinyApiRoot };
13
+
14
+ //# sourceMappingURL=registerWebinyApiRoot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"composition/registerWebinyApiRoot.js","sources":["../../src/composition/registerWebinyApiRoot.ts"],"sourcesContent":["import type { Container } from \"@webiny/di\";\nimport type { getDocumentClient } from \"@webiny/aws-sdk/client-dynamodb/index.js\";\nimport { DynamoDBCoreFeature } from \"@webiny/db-dynamodb\";\n// CognitoIdpFeature must be in the root container so the request auth step\n// (identity loader decorator → RequestIdentityLoader) sees CognitoIdentityProvider when it is first\n// instantiated. Extensions register in the child/request container — too late.\nimport { CognitoIdpFeature } from \"@webiny/cognito/api/features/CognitoIdp/feature.js\";\nimport type { WebinyApiCompositionConfig } from \"./types.js\";\n\n/**\n * ROOT container registration that is not transport-specific: database, identity providers, and the\n * storage variant. Shared by both AWS Lambda composition roots.\n */\nexport async function registerWebinyApiRoot(\n container: Container,\n config: WebinyApiCompositionConfig,\n documentClient: ReturnType<typeof getDocumentClient>\n): Promise<void> {\n // ── Database ───────────────────────────────────────────────\n DynamoDBCoreFeature.register(container, { documentClient });\n\n // ── Identity providers ─────────────────────────────────────\n // Must be in root so the request auth step can authenticate requests before the GraphQL engine\n // runs.\n CognitoIdpFeature.register(container);\n\n // ── Storage (variant-specific: CMS storage ops, DDB registries, OpenSearch core) ──\n await config.registerRootStorage(container, { documentClient });\n}\n"],"names":["registerWebinyApiRoot","container","config","documentClient","DynamoDBCoreFeature","CognitoIdpFeature"],"mappings":";;AAaO,eAAeA,sBAClBC,SAAoB,EACpBC,MAAkC,EAClCC,cAAoD;IAGpDC,oBAAoB,QAAQ,CAACH,WAAW;QAAEE;IAAe;IAKzDE,kBAAkB,QAAQ,CAACJ;IAG3B,MAAMC,OAAO,mBAAmB,CAACD,WAAW;QAAEE;IAAe;AACjE"}
@@ -0,0 +1,35 @@
1
+ import type { Container } from "@webiny/di";
2
+ import type { getDocumentClient } from "@webiny/aws-sdk/client-dynamodb/index.js";
3
+ import type { registerExtensions } from "@webiny/handler";
4
+ export interface RegisterRootStorageContext {
5
+ documentClient: ReturnType<typeof getDocumentClient>;
6
+ }
7
+ /**
8
+ * The transport-agnostic half of a Webiny AWS Lambda composition root, shared by the buffered API
9
+ * Gateway handler (`createWebinyApiHandler`) and the response-streaming Function URL handler
10
+ * (`createWebinyStreamApiHandler`) so the two cannot drift on storage, identity providers, or the
11
+ * per-request feature stack.
12
+ */
13
+ export interface WebinyApiCompositionConfig {
14
+ /**
15
+ * Project-defined extensions, applied at register() time. This is the one project-specific
16
+ * input; everything else is standard AWS/env wiring owned by this package.
17
+ */
18
+ extensions: () => Parameters<typeof registerExtensions>[1];
19
+ /**
20
+ * DynamoDB document client. Defaults to the standard AWS client (`getDocumentClient()`).
21
+ * Injectable so integration tests can point the handler at a local (dynalite) DynamoDB.
22
+ */
23
+ documentClient?: ReturnType<typeof getDocumentClient>;
24
+ /**
25
+ * Register the storage-variant features in the ROOT container: the CMS storage operations, the
26
+ * DDB storage registries, and (for the OpenSearch variant) the OpenSearch core. Supplied by the
27
+ * variant package.
28
+ */
29
+ registerRootStorage: (container: Container, ctx: RegisterRootStorageContext) => void | Promise<void>;
30
+ /**
31
+ * Register any request-phase storage features that must run BEFORE `HeadlessCmsFeature` builds
32
+ * its storage — e.g. `DbRegistryFeature` for the DDB+ES variant. Optional (DDB-only needs none).
33
+ */
34
+ registerRequestStorage?: (container: Container) => void | Promise<void>;
35
+ }
File without changes
@@ -1,41 +1,4 @@
1
- /**
2
- * DI-native Webiny API handler for the AWS Lambda transport — storage-agnostic BASE.
3
- *
4
- * The ROOT container wires the AWS transport (API Gateway HTTP + auth/tenant loaders, background-task
5
- * and WebSocket Lambda invocations, DynamoDB, Cognito, storage). The per-request feature stack is the
6
- * transport-AGNOSTIC `registerApiRequestStack` from `@webiny/api-event-handler-core`, with the two
7
- * AWS-specific interleave points supplied as hooks (real-time WebSockets transport + scheduler
8
- * transport). The storage variant is injected via `registerRootStorage` / `registerRequestStorage`
9
- * by a thin variant package (`@webiny/api-event-handler-aws-ddb`, `-aws-ddb-os`). Keeping the wiring
10
- * in real packages (not an app template) is what makes it unit/integration testable.
11
- */
12
- import type { Container } from "@webiny/di";
13
- import { getDocumentClient } from "@webiny/aws-sdk/client-dynamodb/index.js";
14
- import { registerExtensions } from "@webiny/handler";
15
- export interface RegisterRootStorageContext {
16
- documentClient: ReturnType<typeof getDocumentClient>;
17
- }
18
- export interface CreateWebinyApiHandlerConfig {
19
- /**
20
- * Project-defined extensions, applied at register() time. This is the one project-specific
21
- * input; everything else is standard AWS/env wiring owned by this package.
22
- */
23
- extensions: () => Parameters<typeof registerExtensions>[1];
24
- /**
25
- * DynamoDB document client. Defaults to the standard AWS client (`getDocumentClient()`).
26
- * Injectable so integration tests can point the handler at a local (dynalite) DynamoDB.
27
- */
28
- documentClient?: ReturnType<typeof getDocumentClient>;
29
- /**
30
- * Register the storage-variant features in the ROOT container: the CMS storage operations, the
31
- * DDB storage registries, and (for the OpenSearch variant) the OpenSearch core. Supplied by the
32
- * variant package.
33
- */
34
- registerRootStorage: (container: Container, ctx: RegisterRootStorageContext) => void | Promise<void>;
35
- /**
36
- * Register any request-phase storage features that must run BEFORE `HeadlessCmsFeature` builds
37
- * its storage — e.g. `DbRegistryFeature` for the DDB+ES variant. Optional (DDB-only needs none).
38
- */
39
- registerRequestStorage?: (container: Container) => void | Promise<void>;
40
- }
1
+ import type { WebinyApiCompositionConfig } from "./composition/index.js";
2
+ export type { RegisterRootStorageContext } from "./composition/index.js";
3
+ export type CreateWebinyApiHandlerConfig = WebinyApiCompositionConfig;
41
4
  export declare function createWebinyApiHandler(config: CreateWebinyApiHandlerConfig): (event: any, context?: import("aws-lambda").Context) => Promise<any>;
@@ -1,53 +1,19 @@
1
1
  import { getDocumentClient } from "@webiny/aws-sdk/client-dynamodb/index.js";
2
- import { ApiGatewayFeature, BackgroundTaskEventType, EventBridgeEventType, WebSocketEventType, createLambdaHandler } from "@webiny/event-handler-aws";
3
- import { BackgroundTasksAwsFeature } from "@webiny/background-tasks-aws";
4
- import { DynamoDBCoreFeature } from "@webiny/db-dynamodb";
5
- import { registerApiRequestStack } from "@webiny/api-event-handler-core";
6
- import { WebsocketsAwsFeature } from "@webiny/api-websockets-aws";
7
- import { SchedulerAwsFeature } from "@webiny/api-scheduler-aws";
8
- import { FileManagerS3Feature } from "@webiny/api-file-manager-s3";
9
- import { WebSocketLambdaHandler } from "@webiny/api-websockets";
10
- import { CognitoIdpFeature } from "@webiny/cognito/api/features/CognitoIdp/feature.js";
11
- import { BulkActionsEventBridgeLambdaHandlerFeature } from "@webiny/api-headless-cms-bulk-actions-aws";
2
+ import { ApiGatewayFeature, createLambdaHandler } from "@webiny/event-handler-aws";
12
3
  import { ApiGatewayIdentityLoaderDecorator } from "./handlers/ApiGatewayIdentityLoaderDecorator.js";
13
4
  import { ApiGatewayTenantLoaderDecorator } from "./handlers/ApiGatewayTenantLoaderDecorator.js";
5
+ import { registerInboundEventTypes, registerWebinyApiChild, registerWebinyApiRoot } from "./composition/index.js";
14
6
  function createWebinyApiHandler(config) {
15
- const documentClient = config.documentClient ?? getDocumentClient();
16
7
  return createLambdaHandler({
17
8
  root: async (container)=>{
18
9
  ApiGatewayFeature.register(container);
19
10
  container.registerDecorator(ApiGatewayIdentityLoaderDecorator);
20
11
  container.registerDecorator(ApiGatewayTenantLoaderDecorator);
21
- container.register(BackgroundTaskEventType);
22
- BackgroundTasksAwsFeature.register(container);
23
- container.register(EventBridgeEventType);
24
- BulkActionsEventBridgeLambdaHandlerFeature.register(container);
25
- container.register(WebSocketEventType);
26
- container.register(WebSocketLambdaHandler);
27
- DynamoDBCoreFeature.register(container, {
28
- documentClient
29
- });
30
- CognitoIdpFeature.register(container);
31
- await config.registerRootStorage(container, {
32
- documentClient
33
- });
12
+ registerInboundEventTypes(container);
13
+ await registerWebinyApiRoot(container, config, config.documentClient ?? getDocumentClient());
34
14
  },
35
- request: async (container)=>{
36
- await registerApiRequestStack(container, {
37
- extensions: config.extensions,
38
- registerRequestStorage: config.registerRequestStorage,
39
- transports: {
40
- realtime: (c)=>{
41
- WebsocketsAwsFeature.register(c);
42
- },
43
- scheduler: (c)=>{
44
- SchedulerAwsFeature.register(c);
45
- },
46
- fileManager: (c)=>{
47
- FileManagerS3Feature.register(c, {});
48
- }
49
- }
50
- });
15
+ child: async (container)=>{
16
+ await registerWebinyApiChild(container, config);
51
17
  }
52
18
  });
53
19
  }
@@ -1 +1 @@
1
- {"version":3,"file":"createWebinyApiHandler.js","sources":["../src/createWebinyApiHandler.ts"],"sourcesContent":["/**\n * DI-native Webiny API handler for the AWS Lambda transport — storage-agnostic BASE.\n *\n * The ROOT container wires the AWS transport (API Gateway HTTP + auth/tenant loaders, background-task\n * and WebSocket Lambda invocations, DynamoDB, Cognito, storage). The per-request feature stack is the\n * transport-AGNOSTIC `registerApiRequestStack` from `@webiny/api-event-handler-core`, with the two\n * AWS-specific interleave points supplied as hooks (real-time WebSockets transport + scheduler\n * transport). The storage variant is injected via `registerRootStorage` / `registerRequestStorage`\n * by a thin variant package (`@webiny/api-event-handler-aws-ddb`, `-aws-ddb-os`). Keeping the wiring\n * in real packages (not an app template) is what makes it unit/integration testable.\n */\nimport type { Container } from \"@webiny/di\";\nimport { getDocumentClient } from \"@webiny/aws-sdk/client-dynamodb/index.js\";\nimport {\n createLambdaHandler,\n ApiGatewayFeature,\n BackgroundTaskEventType,\n EventBridgeEventType,\n WebSocketEventType\n} from \"@webiny/event-handler-aws\";\nimport { BackgroundTasksAwsFeature } from \"@webiny/background-tasks-aws\";\nimport { registerExtensions } from \"@webiny/handler\";\nimport { DynamoDBCoreFeature } from \"@webiny/db-dynamodb\";\nimport { registerApiRequestStack } from \"@webiny/api-event-handler-core\";\nimport { WebsocketsAwsFeature } from \"@webiny/api-websockets-aws\";\nimport { SchedulerAwsFeature } from \"@webiny/api-scheduler-aws\";\nimport { FileManagerS3Feature } from \"@webiny/api-file-manager-s3\";\nimport { WebSocketLambdaHandler } from \"@webiny/api-websockets\";\n// CognitoIdpFeature must be in the root container so the request auth step\n// (ApiGatewayIdentityLoaderDecorator → RequestIdentityLoader) sees CognitoIdentityProvider\n// when it is first instantiated. Extensions register in the child/request container — too late.\nimport { CognitoIdpFeature } from \"@webiny/cognito/api/features/CognitoIdp/feature.js\";\nimport { BulkActionsEventBridgeLambdaHandlerFeature } from \"@webiny/api-headless-cms-bulk-actions-aws\";\nimport { ApiGatewayIdentityLoaderDecorator } from \"~/handlers/ApiGatewayIdentityLoaderDecorator.js\";\nimport { ApiGatewayTenantLoaderDecorator } from \"~/handlers/ApiGatewayTenantLoaderDecorator.js\";\n\nexport interface RegisterRootStorageContext {\n documentClient: ReturnType<typeof getDocumentClient>;\n}\n\nexport interface CreateWebinyApiHandlerConfig {\n /**\n * Project-defined extensions, applied at register() time. This is the one project-specific\n * input; everything else is standard AWS/env wiring owned by this package.\n */\n extensions: () => Parameters<typeof registerExtensions>[1];\n /**\n * DynamoDB document client. Defaults to the standard AWS client (`getDocumentClient()`).\n * Injectable so integration tests can point the handler at a local (dynalite) DynamoDB.\n */\n documentClient?: ReturnType<typeof getDocumentClient>;\n /**\n * Register the storage-variant features in the ROOT container: the CMS storage operations, the\n * DDB storage registries, and (for the OpenSearch variant) the OpenSearch core. Supplied by the\n * variant package.\n */\n registerRootStorage: (\n container: Container,\n ctx: RegisterRootStorageContext\n ) => void | Promise<void>;\n /**\n * Register any request-phase storage features that must run BEFORE `HeadlessCmsFeature` builds\n * its storage — e.g. `DbRegistryFeature` for the DDB+ES variant. Optional (DDB-only needs none).\n */\n registerRequestStorage?: (container: Container) => void | Promise<void>;\n}\n\nexport function createWebinyApiHandler(config: CreateWebinyApiHandlerConfig) {\n const documentClient = config.documentClient ?? getDocumentClient();\n\n return createLambdaHandler({\n root: async container => {\n // ── Transport ──────────────────────────────────────────────\n // ApiGatewayFeature registers the HTTP transport (event type + router + HttpFeature).\n ApiGatewayFeature.register(container);\n\n // ── Tenant + auth (extract → shared load) ──────────────────\n // These decorators depend on api-core (RequestTenantLoader/RequestIdentityLoader), so\n // they live in this composition layer, not event-handler-aws. registerDecorator applies\n // LATER registrations as the OUTER wrapper (whose execute() runs first). TENANT must be\n // established before IDENTITY: API-key authentication resolves the key by tenant partition\n // (ApiKeysRepository reads TenantContext.getTenant()), so identity establishment depends on\n // the tenant. The reverse is not true — RequestTenantLoader has no identity dependency. So\n // register identity first (inner) and tenant last (outer) → tenant runs, then identity,\n // then the router.\n container.registerDecorator(ApiGatewayIdentityLoaderDecorator);\n container.registerDecorator(ApiGatewayTenantLoaderDecorator);\n\n // Background task invocations (Step Functions → Lambda directly). BackgroundTasksAwsFeature\n // registers the Lambda handler + StepFunctionService (the AWS dispatch transport).\n container.register(BackgroundTaskEventType);\n BackgroundTasksAwsFeature.register(container);\n\n // EventBridge invocations (e.g. scheduled empty-trash-bin). Without the event type the\n // dispatcher can't match an EventBridge-shaped event; without the handler the container\n // can't resolve EventBridgeEventHandler.\n container.register(EventBridgeEventType);\n BulkActionsEventBridgeLambdaHandlerFeature.register(container);\n\n // WebSocket invocations (API Gateway WebSocket → this Lambda: $connect/$disconnect/$default).\n // Without the event type + handler, the DI dispatcher can't match a WS event (\"No event type\n // matched\") so $connect fails and no connection is ever registered → no server→client push.\n container.register(WebSocketEventType);\n container.register(WebSocketLambdaHandler);\n\n // ── Database ───────────────────────────────────────────────\n DynamoDBCoreFeature.register(container, {\n documentClient\n });\n\n // ── Identity providers ─────────────────────────────────────\n // Must be in root so the request auth step can authenticate\n // requests before the GraphQL engine runs.\n CognitoIdpFeature.register(container);\n\n // ── Storage (variant-specific: CMS storage ops, DDB registries, OpenSearch core) ──\n await config.registerRootStorage(container, { documentClient });\n },\n\n request: async container => {\n // The per-request feature stack is transport-agnostic (shared with the server transport).\n // The AWS-specific interleave points are supplied as the `transports` adapters.\n await registerApiRequestStack(container, {\n extensions: config.extensions,\n registerRequestStorage: config.registerRequestStorage,\n transports: {\n // Real AWS WebSocket transport (API Gateway Management API), registered right after\n // WebsocketsFeature so it overrides the NullWebsocketsTransport.\n realtime: c => {\n WebsocketsAwsFeature.register(c);\n },\n // Scheduler transport: the scheduler-aws extension (EventBridge Scheduler).\n scheduler: c => {\n SchedulerAwsFeature.register(c);\n },\n // File-manager storage transport: S3 (asset delivery + S3 file operations + schema).\n fileManager: c => {\n FileManagerS3Feature.register(c, {});\n }\n }\n });\n }\n });\n}\n"],"names":["createWebinyApiHandler","config","documentClient","getDocumentClient","createLambdaHandler","container","ApiGatewayFeature","ApiGatewayIdentityLoaderDecorator","ApiGatewayTenantLoaderDecorator","BackgroundTaskEventType","BackgroundTasksAwsFeature","EventBridgeEventType","BulkActionsEventBridgeLambdaHandlerFeature","WebSocketEventType","WebSocketLambdaHandler","DynamoDBCoreFeature","CognitoIdpFeature","registerApiRequestStack","c","WebsocketsAwsFeature","SchedulerAwsFeature","FileManagerS3Feature"],"mappings":";;;;;;;;;;;;;AAmEO,SAASA,uBAAuBC,MAAoC;IACvE,MAAMC,iBAAiBD,OAAO,cAAc,IAAIE;IAEhD,OAAOC,oBAAoB;QACvB,MAAM,OAAMC;YAGRC,kBAAkB,QAAQ,CAACD;YAW3BA,UAAU,iBAAiB,CAACE;YAC5BF,UAAU,iBAAiB,CAACG;YAI5BH,UAAU,QAAQ,CAACI;YACnBC,0BAA0B,QAAQ,CAACL;YAKnCA,UAAU,QAAQ,CAACM;YACnBC,2CAA2C,QAAQ,CAACP;YAKpDA,UAAU,QAAQ,CAACQ;YACnBR,UAAU,QAAQ,CAACS;YAGnBC,oBAAoB,QAAQ,CAACV,WAAW;gBACpCH;YACJ;YAKAc,kBAAkB,QAAQ,CAACX;YAG3B,MAAMJ,OAAO,mBAAmB,CAACI,WAAW;gBAAEH;YAAe;QACjE;QAEA,SAAS,OAAMG;YAGX,MAAMY,wBAAwBZ,WAAW;gBACrC,YAAYJ,OAAO,UAAU;gBAC7B,wBAAwBA,OAAO,sBAAsB;gBACrD,YAAY;oBAGR,UAAUiB,CAAAA;wBACNC,qBAAqB,QAAQ,CAACD;oBAClC;oBAEA,WAAWA,CAAAA;wBACPE,oBAAoB,QAAQ,CAACF;oBACjC;oBAEA,aAAaA,CAAAA;wBACTG,qBAAqB,QAAQ,CAACH,GAAG,CAAC;oBACtC;gBACJ;YACJ;QACJ;IACJ;AACJ"}
1
+ {"version":3,"file":"createWebinyApiHandler.js","sources":["../src/createWebinyApiHandler.ts"],"sourcesContent":["/**\n * DI-native Webiny API handler for the AWS Lambda transport — storage-agnostic BASE.\n *\n * The ROOT container wires the AWS transport (API Gateway HTTP + auth/tenant loaders, background-task\n * and WebSocket Lambda invocations, DynamoDB, Cognito, storage). Everything that is not\n * transport-specific — database, identity providers, storage, and the transport-AGNOSTIC per-request\n * feature stack — lives in `composition/`, shared with the response-streaming handler\n * (`createWebinyStreamApiHandler`) so the two roots cannot drift. The storage variant is injected via\n * `registerRootStorage` / `registerRequestStorage` by a thin variant package\n * (`@webiny/api-event-handler-aws-ddb`, `-aws-ddb-os`). Keeping the wiring in real packages (not an app\n * template) is what makes it unit/integration testable.\n */\nimport { getDocumentClient } from \"@webiny/aws-sdk/client-dynamodb/index.js\";\nimport { createLambdaHandler, ApiGatewayFeature } from \"@webiny/event-handler-aws\";\nimport { ApiGatewayIdentityLoaderDecorator } from \"~/handlers/ApiGatewayIdentityLoaderDecorator.js\";\nimport { ApiGatewayTenantLoaderDecorator } from \"~/handlers/ApiGatewayTenantLoaderDecorator.js\";\nimport {\n registerInboundEventTypes,\n registerWebinyApiChild,\n registerWebinyApiRoot\n} from \"~/composition/index.js\";\nimport type { WebinyApiCompositionConfig } from \"~/composition/index.js\";\n\nexport type { RegisterRootStorageContext } from \"~/composition/index.js\";\n\nexport type CreateWebinyApiHandlerConfig = WebinyApiCompositionConfig;\n\nexport function createWebinyApiHandler(config: CreateWebinyApiHandlerConfig) {\n return createLambdaHandler({\n root: async container => {\n // ── Transport ──────────────────────────────────────────────\n // ApiGatewayFeature registers the HTTP transport (event type + router + HttpFeature).\n ApiGatewayFeature.register(container);\n\n // ── Tenant + auth (extract → shared load) ──────────────────\n // These decorators depend on api-core (RequestTenantLoader/RequestIdentityLoader), so\n // they live in this composition layer, not event-handler-aws. registerDecorator applies\n // LATER registrations as the OUTER wrapper (whose execute() runs first). TENANT must be\n // established before IDENTITY: API-key authentication resolves the key by tenant partition\n // (ApiKeysRepository reads TenantContext.getTenant()), so identity establishment depends on\n // the tenant. The reverse is not true — RequestTenantLoader has no identity dependency. So\n // register identity first (inner) and tenant last (outer) → tenant runs, then identity,\n // then the router.\n container.registerDecorator(ApiGatewayIdentityLoaderDecorator);\n container.registerDecorator(ApiGatewayTenantLoaderDecorator);\n\n // Every non-HTTP invocation shape (background tasks, EventBridge, scheduled actions,\n // WebSockets) with its handler. Kept in one function so the set is testable and an\n // inbound transport can't be half-wired.\n registerInboundEventTypes(container);\n\n // Resolved here rather than at factory time: one bundle exports BOTH this handler and the\n // streaming one, so building the client eagerly would open a second DynamoDB client on\n // every cold start. `root` runs once, lazily.\n await registerWebinyApiRoot(\n container,\n config,\n config.documentClient ?? getDocumentClient()\n );\n },\n\n child: async container => {\n await registerWebinyApiChild(container, config);\n }\n });\n}\n"],"names":["createWebinyApiHandler","config","createLambdaHandler","container","ApiGatewayFeature","ApiGatewayIdentityLoaderDecorator","ApiGatewayTenantLoaderDecorator","registerInboundEventTypes","registerWebinyApiRoot","getDocumentClient","registerWebinyApiChild"],"mappings":";;;;;AA2BO,SAASA,uBAAuBC,MAAoC;IACvE,OAAOC,oBAAoB;QACvB,MAAM,OAAMC;YAGRC,kBAAkB,QAAQ,CAACD;YAW3BA,UAAU,iBAAiB,CAACE;YAC5BF,UAAU,iBAAiB,CAACG;YAK5BC,0BAA0BJ;YAK1B,MAAMK,sBACFL,WACAF,QACAA,OAAO,cAAc,IAAIQ;QAEjC;QAEA,OAAO,OAAMN;YACT,MAAMO,uBAAuBP,WAAWF;QAC5C;IACJ;AACJ"}
@@ -0,0 +1,3 @@
1
+ import type { WebinyApiCompositionConfig } from "./composition/index.js";
2
+ export type CreateWebinyStreamApiHandlerConfig = WebinyApiCompositionConfig;
3
+ export declare function createWebinyStreamApiHandler(config: CreateWebinyStreamApiHandlerConfig): import("@webiny/event-handler-aws").StreamLambdaHandler;
@@ -0,0 +1,23 @@
1
+ import { getDocumentClient } from "@webiny/aws-sdk/client-dynamodb/index.js";
2
+ import { FunctionUrlStreamFeature, createStreamLambdaHandler } from "@webiny/event-handler-aws";
3
+ import { BackgroundTasksAwsFeature } from "@webiny/background-tasks-aws";
4
+ import { FunctionUrlStreamIdentityLoaderDecorator } from "./handlers/FunctionUrlStreamIdentityLoaderDecorator.js";
5
+ import { FunctionUrlStreamTenantLoaderDecorator } from "./handlers/FunctionUrlStreamTenantLoaderDecorator.js";
6
+ import { registerWebinyApiChild, registerWebinyApiRoot } from "./composition/index.js";
7
+ function createWebinyStreamApiHandler(config) {
8
+ return createStreamLambdaHandler({
9
+ root: async (container)=>{
10
+ FunctionUrlStreamFeature.register(container);
11
+ container.registerDecorator(FunctionUrlStreamIdentityLoaderDecorator);
12
+ container.registerDecorator(FunctionUrlStreamTenantLoaderDecorator);
13
+ BackgroundTasksAwsFeature.register(container);
14
+ await registerWebinyApiRoot(container, config, config.documentClient ?? getDocumentClient());
15
+ },
16
+ child: async (container)=>{
17
+ await registerWebinyApiChild(container, config);
18
+ }
19
+ });
20
+ }
21
+ export { createWebinyStreamApiHandler };
22
+
23
+ //# sourceMappingURL=createWebinyStreamApiHandler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createWebinyStreamApiHandler.js","sources":["../src/createWebinyStreamApiHandler.ts"],"sourcesContent":["/**\n * DI-native Webiny API handler for AWS Lambda **response streaming** — storage-agnostic BASE.\n *\n * This is a SECOND Lambda function sharing the buffered function's code bundle, not a second entry on\n * the same function: a Lambda's handler entry is fixed per function, and a `streamifyResponse` handler\n * is only meaningful under `InvokeMode: RESPONSE_STREAM`. It is reached through a Lambda Function URL\n * (fronted by CloudFront), because API Gateway buffers the entire Lambda response and therefore cannot\n * stream at all.\n *\n * Root/request registration is shared with `createWebinyApiHandler` via `composition/`; only\n * the transport differs. Notably NOT registered here: the background-task and WebSocket **event\n * types**. Those match inbound invocations that only ever target the buffered function, so\n * registering them would add cold-start cost for events this function never receives.\n *\n * Outbound transports are a different matter, and both ARE present: websockets push completion\n * messages from the shared per-request stack, and `BackgroundTasksAwsFeature` supplies the Step\n * Functions dispatcher that `TaskService.trigger()` needs. Omitting the latter does not disable\n * task triggering — it breaks it silently, because the shared root registers `TaskService` either\n * way and its callers treat a failed trigger as a no-op (ACO's FLP handlers, for one, swallow it),\n * so writes land while their projections never update.\n */\nimport { getDocumentClient } from \"@webiny/aws-sdk/client-dynamodb/index.js\";\nimport { createStreamLambdaHandler, FunctionUrlStreamFeature } from \"@webiny/event-handler-aws\";\nimport { BackgroundTasksAwsFeature } from \"@webiny/background-tasks-aws\";\nimport { FunctionUrlStreamIdentityLoaderDecorator } from \"~/handlers/FunctionUrlStreamIdentityLoaderDecorator.js\";\nimport { FunctionUrlStreamTenantLoaderDecorator } from \"~/handlers/FunctionUrlStreamTenantLoaderDecorator.js\";\nimport { registerWebinyApiChild, registerWebinyApiRoot } from \"~/composition/index.js\";\nimport type { WebinyApiCompositionConfig } from \"~/composition/index.js\";\n\nexport type CreateWebinyStreamApiHandlerConfig = WebinyApiCompositionConfig;\n\nexport function createWebinyStreamApiHandler(config: CreateWebinyStreamApiHandlerConfig) {\n return createStreamLambdaHandler({\n root: async container => {\n // ── Transport ──────────────────────────────────────────────\n // Registers the Function URL event type + router + the streaming terminal handler.\n // Deliberately NOT alongside ApiGatewayFeature: both event types match the same payload\n // shape, so they must never share a container.\n FunctionUrlStreamFeature.register(container);\n\n // ── Tenant + auth (extract → shared load) ──────────────────\n // registerDecorator applies LATER registrations as the OUTER wrapper (whose execute() runs\n // first). TENANT must be established before IDENTITY: API-key authentication resolves the\n // key by tenant partition (ApiKeysRepository reads TenantContext.getTenant()), so identity\n // establishment depends on the tenant. The reverse is not true. So register identity first\n // (inner) and tenant last (outer) → tenant runs, then identity, then the router. Mirrors\n // the buffered handler.\n container.registerDecorator(FunctionUrlStreamIdentityLoaderDecorator);\n container.registerDecorator(FunctionUrlStreamTenantLoaderDecorator);\n\n // ── Background tasks: outbound dispatch only ───────────────\n // Registers StepFunctionService, which is what a `TaskService.trigger()` resolves to\n // actually start an execution. Without it the trigger throws deep inside the container\n // and every caller that ignores the failure just carries on. `BackgroundTaskEventType`\n // is deliberately left out, so the handler this also registers stays unreachable here:\n // Step Functions invokes the buffered function, never this one.\n BackgroundTasksAwsFeature.register(container);\n\n // Resolved here rather than at factory time: one bundle exports BOTH this handler and the\n // buffered one, so building the client eagerly would open a second DynamoDB client on every\n // cold start of whichever function isn't streaming. `root` runs once, lazily.\n await registerWebinyApiRoot(\n container,\n config,\n config.documentClient ?? getDocumentClient()\n );\n },\n\n child: async container => {\n await registerWebinyApiChild(container, config);\n }\n });\n}\n"],"names":["createWebinyStreamApiHandler","config","createStreamLambdaHandler","container","FunctionUrlStreamFeature","FunctionUrlStreamIdentityLoaderDecorator","FunctionUrlStreamTenantLoaderDecorator","BackgroundTasksAwsFeature","registerWebinyApiRoot","getDocumentClient","registerWebinyApiChild"],"mappings":";;;;;;AA+BO,SAASA,6BAA6BC,MAA0C;IACnF,OAAOC,0BAA0B;QAC7B,MAAM,OAAMC;YAKRC,yBAAyB,QAAQ,CAACD;YASlCA,UAAU,iBAAiB,CAACE;YAC5BF,UAAU,iBAAiB,CAACG;YAQ5BC,0BAA0B,QAAQ,CAACJ;YAKnC,MAAMK,sBACFL,WACAF,QACAA,OAAO,cAAc,IAAIQ;QAEjC;QAEA,OAAO,OAAMN;YACT,MAAMO,uBAAuBP,WAAWF;QAC5C;IACJ;AACJ"}
@@ -4,9 +4,9 @@ import { RawAuthToken } from "@webiny/api-core/features/requestContext/index.js"
4
4
  import type { IRequestIdentityLoader } from "@webiny/api-core/features/requestContext/abstractions.js";
5
5
  import type { EventContext, NextFunction } from "@webiny/event-handler-core";
6
6
  /**
7
- * EXTRACT (transport-specific): reads the auth token from an API Gateway event — bearer
8
- * `Authorization` header preferred, then the `wby-id-token` cookie — into RawAuthToken, then invokes
9
- * the shared LOAD step (RequestIdentityLoader) which authenticates it and sets IdentityContext.
7
+ * EXTRACT (transport-specific): reads the auth token from an API Gateway event — see
8
+ * {@link extractAuthToken} for the header precedence — into RawAuthToken, then invokes the shared LOAD
9
+ * step (RequestIdentityLoader) which authenticates it and sets IdentityContext.
10
10
  *
11
11
  * A missing token leaves RawAuthToken null → the loader authenticates as anonymous.
12
12
  * Registered BEFORE ApiGatewayTenantLoaderDecorator so identity is established before tenant
@@ -18,7 +18,6 @@ declare class ApiGatewayIdentityLoaderDecoratorImpl implements ApiGatewayEventHa
18
18
  private decoratee;
19
19
  constructor(rawAuthToken: RawAuthToken.Interface, identityLoader: IRequestIdentityLoader, decoratee: ApiGatewayEventHandler.Interface);
20
20
  execute(ctx: EventContext<APIGatewayProxyEvent>, next: NextFunction): Promise<any>;
21
- private extractToken;
22
21
  }
23
22
  export declare const ApiGatewayIdentityLoaderDecorator: typeof ApiGatewayIdentityLoaderDecoratorImpl & {
24
23
  __abstraction: import("@webiny/di").Abstraction<import("@webiny/event-handler-aws").IApiGatewayEventHandler>;
@@ -1,12 +1,6 @@
1
1
  import { ApiGatewayEventHandler } from "@webiny/event-handler-aws";
2
2
  import { RawAuthToken, RequestIdentityLoader } from "@webiny/api-core/features/requestContext/index.js";
3
- function parseCookieHeader(cookieHeader) {
4
- return cookieHeader.split(";").reduce((acc, pair)=>{
5
- const idx = pair.indexOf("=");
6
- if (idx > 0) acc[pair.slice(0, idx).trim()] = decodeURIComponent(pair.slice(idx + 1).trim());
7
- return acc;
8
- }, {});
9
- }
3
+ import { extractAuthToken } from "./extractRequestAuth.js";
10
4
  class ApiGatewayIdentityLoaderDecoratorImpl {
11
5
  constructor(rawAuthToken, identityLoader, decoratee){
12
6
  this.rawAuthToken = rawAuthToken;
@@ -14,18 +8,12 @@ class ApiGatewayIdentityLoaderDecoratorImpl {
14
8
  this.decoratee = decoratee;
15
9
  }
16
10
  async execute(ctx, next) {
17
- this.rawAuthToken.set(this.extractToken(ctx.event));
11
+ const headers = ctx.event?.headers;
12
+ const authToken = extractAuthToken(headers);
13
+ this.rawAuthToken.set(authToken);
18
14
  await this.identityLoader.establish();
19
15
  return this.decoratee.execute(ctx, next);
20
16
  }
21
- extractToken(event) {
22
- const headers = event?.headers;
23
- if (!headers) return null;
24
- const bearer = (headers["authorization"] ?? headers["Authorization"] ?? "").replace(/^Bearer\s+/i, "");
25
- if (bearer) return bearer;
26
- const cookieHeader = headers["cookie"] ?? headers["Cookie"] ?? "";
27
- return parseCookieHeader(cookieHeader)["wby-id-token"] ?? null;
28
- }
29
17
  }
30
18
  const ApiGatewayIdentityLoaderDecorator = ApiGatewayEventHandler.createDecorator({
31
19
  decorator: ApiGatewayIdentityLoaderDecoratorImpl,
@@ -1 +1 @@
1
- {"version":3,"file":"handlers/ApiGatewayIdentityLoaderDecorator.js","sources":["../../src/handlers/ApiGatewayIdentityLoaderDecorator.ts"],"sourcesContent":["import type { APIGatewayProxyEvent } from \"@webiny/aws-sdk/types/index.js\";\nimport { ApiGatewayEventHandler } from \"@webiny/event-handler-aws\";\nimport {\n RawAuthToken,\n RequestIdentityLoader\n} from \"@webiny/api-core/features/requestContext/index.js\";\nimport type { IRequestIdentityLoader } from \"@webiny/api-core/features/requestContext/abstractions.js\";\nimport type { EventContext, NextFunction } from \"@webiny/event-handler-core\";\n\nfunction parseCookieHeader(cookieHeader: string): Record<string, string> {\n return cookieHeader.split(\";\").reduce<Record<string, string>>((acc, pair) => {\n const idx = pair.indexOf(\"=\");\n if (idx > 0) {\n acc[pair.slice(0, idx).trim()] = decodeURIComponent(pair.slice(idx + 1).trim());\n }\n return acc;\n }, {});\n}\n\n/**\n * EXTRACT (transport-specific): reads the auth token from an API Gateway event — bearer\n * `Authorization` header preferred, then the `wby-id-token` cookie — into RawAuthToken, then invokes\n * the shared LOAD step (RequestIdentityLoader) which authenticates it and sets IdentityContext.\n *\n * A missing token leaves RawAuthToken null → the loader authenticates as anonymous.\n * Registered BEFORE ApiGatewayTenantLoaderDecorator so identity is established before tenant\n * (see ApiGatewayFeature).\n */\nclass ApiGatewayIdentityLoaderDecoratorImpl implements ApiGatewayEventHandler.Interface {\n constructor(\n private rawAuthToken: RawAuthToken.Interface,\n private identityLoader: IRequestIdentityLoader,\n private decoratee: ApiGatewayEventHandler.Interface\n ) {}\n\n async execute(ctx: EventContext<APIGatewayProxyEvent>, next: NextFunction): Promise<any> {\n this.rawAuthToken.set(this.extractToken(ctx.event));\n await this.identityLoader.establish();\n return this.decoratee.execute(ctx, next);\n }\n\n private extractToken(event: APIGatewayProxyEvent): string | null {\n const headers = event?.headers;\n if (!headers) {\n return null;\n }\n const bearer = (headers[\"authorization\"] ?? headers[\"Authorization\"] ?? \"\").replace(\n /^Bearer\\s+/i,\n \"\"\n );\n if (bearer) {\n return bearer;\n }\n const cookieHeader = headers[\"cookie\"] ?? headers[\"Cookie\"] ?? \"\";\n return parseCookieHeader(cookieHeader)[\"wby-id-token\"] ?? null;\n }\n}\n\nexport const ApiGatewayIdentityLoaderDecorator = ApiGatewayEventHandler.createDecorator({\n decorator: ApiGatewayIdentityLoaderDecoratorImpl,\n dependencies: [RawAuthToken, RequestIdentityLoader]\n});\n"],"names":["parseCookieHeader","cookieHeader","acc","pair","idx","decodeURIComponent","ApiGatewayIdentityLoaderDecoratorImpl","rawAuthToken","identityLoader","decoratee","ctx","next","event","headers","bearer","ApiGatewayIdentityLoaderDecorator","ApiGatewayEventHandler","RawAuthToken","RequestIdentityLoader"],"mappings":";;AASA,SAASA,kBAAkBC,YAAoB;IAC3C,OAAOA,aAAa,KAAK,CAAC,KAAK,MAAM,CAAyB,CAACC,KAAKC;QAChE,MAAMC,MAAMD,KAAK,OAAO,CAAC;QACzB,IAAIC,MAAM,GACNF,GAAG,CAACC,KAAK,KAAK,CAAC,GAAGC,KAAK,IAAI,GAAG,GAAGC,mBAAmBF,KAAK,KAAK,CAACC,MAAM,GAAG,IAAI;QAEhF,OAAOF;IACX,GAAG,CAAC;AACR;AAWA,MAAMI;IACF,YACYC,YAAoC,EACpCC,cAAsC,EACtCC,SAA2C,CACrD;aAHUF,YAAY,GAAZA;aACAC,cAAc,GAAdA;aACAC,SAAS,GAATA;IACT;IAEH,MAAM,QAAQC,GAAuC,EAAEC,IAAkB,EAAgB;QACrF,IAAI,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,YAAY,CAACD,IAAI,KAAK;QACjD,MAAM,IAAI,CAAC,cAAc,CAAC,SAAS;QACnC,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,CAACA,KAAKC;IACvC;IAEQ,aAAaC,KAA2B,EAAiB;QAC7D,MAAMC,UAAUD,OAAO;QACvB,IAAI,CAACC,SACD,OAAO;QAEX,MAAMC,SAAUD,AAAAA,CAAAA,OAAO,CAAC,gBAAgB,IAAIA,OAAO,CAAC,gBAAgB,IAAI,EAAC,EAAG,OAAO,CAC/E,eACA;QAEJ,IAAIC,QACA,OAAOA;QAEX,MAAMb,eAAeY,OAAO,CAAC,SAAS,IAAIA,OAAO,CAAC,SAAS,IAAI;QAC/D,OAAOb,kBAAkBC,aAAa,CAAC,eAAe,IAAI;IAC9D;AACJ;AAEO,MAAMc,oCAAoCC,uBAAuB,eAAe,CAAC;IACpF,WAAWV;IACX,cAAc;QAACW;QAAcC;KAAsB;AACvD"}
1
+ {"version":3,"file":"handlers/ApiGatewayIdentityLoaderDecorator.js","sources":["../../src/handlers/ApiGatewayIdentityLoaderDecorator.ts"],"sourcesContent":["import type { APIGatewayProxyEvent } from \"@webiny/aws-sdk/types/index.js\";\nimport { ApiGatewayEventHandler } from \"@webiny/event-handler-aws\";\nimport {\n RawAuthToken,\n RequestIdentityLoader\n} from \"@webiny/api-core/features/requestContext/index.js\";\nimport type { IRequestIdentityLoader } from \"@webiny/api-core/features/requestContext/abstractions.js\";\nimport type { EventContext, NextFunction } from \"@webiny/event-handler-core\";\nimport { extractAuthToken } from \"./extractRequestAuth.js\";\n\n/**\n * EXTRACT (transport-specific): reads the auth token from an API Gateway event — see\n * {@link extractAuthToken} for the header precedence — into RawAuthToken, then invokes the shared LOAD\n * step (RequestIdentityLoader) which authenticates it and sets IdentityContext.\n *\n * A missing token leaves RawAuthToken null → the loader authenticates as anonymous.\n * Registered BEFORE ApiGatewayTenantLoaderDecorator so identity is established before tenant\n * (see ApiGatewayFeature).\n */\nclass ApiGatewayIdentityLoaderDecoratorImpl implements ApiGatewayEventHandler.Interface {\n constructor(\n private rawAuthToken: RawAuthToken.Interface,\n private identityLoader: IRequestIdentityLoader,\n private decoratee: ApiGatewayEventHandler.Interface\n ) {}\n\n async execute(ctx: EventContext<APIGatewayProxyEvent>, next: NextFunction): Promise<any> {\n const headers = ctx.event?.headers as Record<string, string>;\n const authToken = extractAuthToken(headers);\n\n this.rawAuthToken.set(authToken);\n\n await this.identityLoader.establish();\n return this.decoratee.execute(ctx, next);\n }\n}\n\nexport const ApiGatewayIdentityLoaderDecorator = ApiGatewayEventHandler.createDecorator({\n decorator: ApiGatewayIdentityLoaderDecoratorImpl,\n dependencies: [RawAuthToken, RequestIdentityLoader]\n});\n"],"names":["ApiGatewayIdentityLoaderDecoratorImpl","rawAuthToken","identityLoader","decoratee","ctx","next","headers","authToken","extractAuthToken","ApiGatewayIdentityLoaderDecorator","ApiGatewayEventHandler","RawAuthToken","RequestIdentityLoader"],"mappings":";;;AAmBA,MAAMA;IACF,YACYC,YAAoC,EACpCC,cAAsC,EACtCC,SAA2C,CACrD;aAHUF,YAAY,GAAZA;aACAC,cAAc,GAAdA;aACAC,SAAS,GAATA;IACT;IAEH,MAAM,QAAQC,GAAuC,EAAEC,IAAkB,EAAgB;QACrF,MAAMC,UAAUF,IAAI,KAAK,EAAE;QAC3B,MAAMG,YAAYC,iBAAiBF;QAEnC,IAAI,CAAC,YAAY,CAAC,GAAG,CAACC;QAEtB,MAAM,IAAI,CAAC,cAAc,CAAC,SAAS;QACnC,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,CAACH,KAAKC;IACvC;AACJ;AAEO,MAAMI,oCAAoCC,uBAAuB,eAAe,CAAC;IACpF,WAAWV;IACX,cAAc;QAACW;QAAcC;KAAsB;AACvD"}
@@ -0,0 +1,22 @@
1
+ import { FunctionUrlStreamEventHandler } from "@webiny/event-handler-aws";
2
+ import { RawAuthToken } from "@webiny/api-core/features/requestContext/index.js";
3
+ import type { IRequestIdentityLoader } from "@webiny/api-core/features/requestContext/abstractions.js";
4
+ import type { EventContext, NextFunction } from "@webiny/event-handler-core";
5
+ /**
6
+ * EXTRACT (transport-specific): the Function URL streaming counterpart of
7
+ * `ApiGatewayIdentityLoaderDecorator`. Same shared LOAD step; the only difference is that Function URL
8
+ * events carry cookies as an array, so the headers are normalised first.
9
+ *
10
+ * Registered BEFORE FunctionUrlStreamTenantLoaderDecorator so identity is established before tenant.
11
+ */
12
+ declare class FunctionUrlStreamIdentityLoaderDecoratorImpl implements FunctionUrlStreamEventHandler.Interface {
13
+ private rawAuthToken;
14
+ private identityLoader;
15
+ private decoratee;
16
+ constructor(rawAuthToken: RawAuthToken.Interface, identityLoader: IRequestIdentityLoader, decoratee: FunctionUrlStreamEventHandler.Interface);
17
+ execute(ctx: EventContext<any>, next: NextFunction): Promise<void>;
18
+ }
19
+ export declare const FunctionUrlStreamIdentityLoaderDecorator: typeof FunctionUrlStreamIdentityLoaderDecoratorImpl & {
20
+ __abstraction: import("@webiny/di").Abstraction<import("@webiny/event-handler-aws").IFunctionUrlStreamEventHandler>;
21
+ };
22
+ export {};
@@ -0,0 +1,27 @@
1
+ import { FunctionUrlStreamEventHandler } from "@webiny/event-handler-aws";
2
+ import { RawAuthToken, RequestIdentityLoader } from "@webiny/api-core/features/requestContext/index.js";
3
+ import { extractAuthToken, headersFromFunctionUrlEvent } from "./extractRequestAuth.js";
4
+ class FunctionUrlStreamIdentityLoaderDecoratorImpl {
5
+ constructor(rawAuthToken, identityLoader, decoratee){
6
+ this.rawAuthToken = rawAuthToken;
7
+ this.identityLoader = identityLoader;
8
+ this.decoratee = decoratee;
9
+ }
10
+ async execute(ctx, next) {
11
+ const headers = headersFromFunctionUrlEvent(ctx.event);
12
+ const authToken = extractAuthToken(headers);
13
+ this.rawAuthToken.set(authToken);
14
+ await this.identityLoader.establish();
15
+ return this.decoratee.execute(ctx, next);
16
+ }
17
+ }
18
+ const FunctionUrlStreamIdentityLoaderDecorator = FunctionUrlStreamEventHandler.createDecorator({
19
+ decorator: FunctionUrlStreamIdentityLoaderDecoratorImpl,
20
+ dependencies: [
21
+ RawAuthToken,
22
+ RequestIdentityLoader
23
+ ]
24
+ });
25
+ export { FunctionUrlStreamIdentityLoaderDecorator };
26
+
27
+ //# sourceMappingURL=FunctionUrlStreamIdentityLoaderDecorator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handlers/FunctionUrlStreamIdentityLoaderDecorator.js","sources":["../../src/handlers/FunctionUrlStreamIdentityLoaderDecorator.ts"],"sourcesContent":["import { FunctionUrlStreamEventHandler } from \"@webiny/event-handler-aws\";\nimport {\n RawAuthToken,\n RequestIdentityLoader\n} from \"@webiny/api-core/features/requestContext/index.js\";\nimport type { IRequestIdentityLoader } from \"@webiny/api-core/features/requestContext/abstractions.js\";\nimport type { EventContext, NextFunction } from \"@webiny/event-handler-core\";\nimport { extractAuthToken, headersFromFunctionUrlEvent } from \"./extractRequestAuth.js\";\n\n/**\n * EXTRACT (transport-specific): the Function URL streaming counterpart of\n * `ApiGatewayIdentityLoaderDecorator`. Same shared LOAD step; the only difference is that Function URL\n * events carry cookies as an array, so the headers are normalised first.\n *\n * Registered BEFORE FunctionUrlStreamTenantLoaderDecorator so identity is established before tenant.\n */\nclass FunctionUrlStreamIdentityLoaderDecoratorImpl\n implements FunctionUrlStreamEventHandler.Interface\n{\n constructor(\n private rawAuthToken: RawAuthToken.Interface,\n private identityLoader: IRequestIdentityLoader,\n private decoratee: FunctionUrlStreamEventHandler.Interface\n ) {}\n\n async execute(ctx: EventContext<any>, next: NextFunction): Promise<void> {\n const headers = headersFromFunctionUrlEvent(ctx.event);\n const authToken = extractAuthToken(headers);\n\n this.rawAuthToken.set(authToken);\n\n await this.identityLoader.establish();\n return this.decoratee.execute(ctx, next);\n }\n}\n\nexport const FunctionUrlStreamIdentityLoaderDecorator =\n FunctionUrlStreamEventHandler.createDecorator({\n decorator: FunctionUrlStreamIdentityLoaderDecoratorImpl,\n dependencies: [RawAuthToken, RequestIdentityLoader]\n });\n"],"names":["FunctionUrlStreamIdentityLoaderDecoratorImpl","rawAuthToken","identityLoader","decoratee","ctx","next","headers","headersFromFunctionUrlEvent","authToken","extractAuthToken","FunctionUrlStreamIdentityLoaderDecorator","FunctionUrlStreamEventHandler","RawAuthToken","RequestIdentityLoader"],"mappings":";;;AAgBA,MAAMA;IAGF,YACYC,YAAoC,EACpCC,cAAsC,EACtCC,SAAkD,CAC5D;aAHUF,YAAY,GAAZA;aACAC,cAAc,GAAdA;aACAC,SAAS,GAATA;IACT;IAEH,MAAM,QAAQC,GAAsB,EAAEC,IAAkB,EAAiB;QACrE,MAAMC,UAAUC,4BAA4BH,IAAI,KAAK;QACrD,MAAMI,YAAYC,iBAAiBH;QAEnC,IAAI,CAAC,YAAY,CAAC,GAAG,CAACE;QAEtB,MAAM,IAAI,CAAC,cAAc,CAAC,SAAS;QACnC,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,CAACJ,KAAKC;IACvC;AACJ;AAEO,MAAMK,2CACTC,8BAA8B,eAAe,CAAC;IAC1C,WAAWX;IACX,cAAc;QAACY;QAAcC;KAAsB;AACvD"}
@@ -0,0 +1,22 @@
1
+ import { FunctionUrlStreamEventHandler } from "@webiny/event-handler-aws";
2
+ import { RawTenantId } from "@webiny/api-core/features/requestContext/index.js";
3
+ import type { IRequestTenantLoader } from "@webiny/api-core/features/requestContext/abstractions.js";
4
+ import type { EventContext, NextFunction } from "@webiny/event-handler-core";
5
+ /**
6
+ * EXTRACT (transport-specific): reads the tenant id from the `x-tenant` header of a Function URL event
7
+ * into RawTenantId, then invokes the shared LOAD step (RequestTenantLoader). A missing header leaves
8
+ * RawTenantId null → the loader defaults to the "root" tenant.
9
+ *
10
+ * Registered AFTER FunctionUrlStreamIdentityLoaderDecorator.
11
+ */
12
+ declare class FunctionUrlStreamTenantLoaderDecoratorImpl implements FunctionUrlStreamEventHandler.Interface {
13
+ private rawTenantId;
14
+ private tenantLoader;
15
+ private decoratee;
16
+ constructor(rawTenantId: RawTenantId.Interface, tenantLoader: IRequestTenantLoader, decoratee: FunctionUrlStreamEventHandler.Interface);
17
+ execute(ctx: EventContext<any>, next: NextFunction): Promise<void>;
18
+ }
19
+ export declare const FunctionUrlStreamTenantLoaderDecorator: typeof FunctionUrlStreamTenantLoaderDecoratorImpl & {
20
+ __abstraction: import("@webiny/di").Abstraction<import("@webiny/event-handler-aws").IFunctionUrlStreamEventHandler>;
21
+ };
22
+ export {};
@@ -0,0 +1,27 @@
1
+ import { FunctionUrlStreamEventHandler } from "@webiny/event-handler-aws";
2
+ import { RawTenantId, RequestTenantLoader } from "@webiny/api-core/features/requestContext/index.js";
3
+ import { extractTenantId, headersFromFunctionUrlEvent } from "./extractRequestAuth.js";
4
+ class FunctionUrlStreamTenantLoaderDecoratorImpl {
5
+ constructor(rawTenantId, tenantLoader, decoratee){
6
+ this.rawTenantId = rawTenantId;
7
+ this.tenantLoader = tenantLoader;
8
+ this.decoratee = decoratee;
9
+ }
10
+ async execute(ctx, next) {
11
+ const headers = headersFromFunctionUrlEvent(ctx.event);
12
+ const tenantId = extractTenantId(headers);
13
+ this.rawTenantId.set(tenantId);
14
+ await this.tenantLoader.establish();
15
+ return this.decoratee.execute(ctx, next);
16
+ }
17
+ }
18
+ const FunctionUrlStreamTenantLoaderDecorator = FunctionUrlStreamEventHandler.createDecorator({
19
+ decorator: FunctionUrlStreamTenantLoaderDecoratorImpl,
20
+ dependencies: [
21
+ RawTenantId,
22
+ RequestTenantLoader
23
+ ]
24
+ });
25
+ export { FunctionUrlStreamTenantLoaderDecorator };
26
+
27
+ //# sourceMappingURL=FunctionUrlStreamTenantLoaderDecorator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handlers/FunctionUrlStreamTenantLoaderDecorator.js","sources":["../../src/handlers/FunctionUrlStreamTenantLoaderDecorator.ts"],"sourcesContent":["import { FunctionUrlStreamEventHandler } from \"@webiny/event-handler-aws\";\nimport {\n RawTenantId,\n RequestTenantLoader\n} from \"@webiny/api-core/features/requestContext/index.js\";\nimport type { IRequestTenantLoader } from \"@webiny/api-core/features/requestContext/abstractions.js\";\nimport type { EventContext, NextFunction } from \"@webiny/event-handler-core\";\nimport { extractTenantId, headersFromFunctionUrlEvent } from \"./extractRequestAuth.js\";\n\n/**\n * EXTRACT (transport-specific): reads the tenant id from the `x-tenant` header of a Function URL event\n * into RawTenantId, then invokes the shared LOAD step (RequestTenantLoader). A missing header leaves\n * RawTenantId null → the loader defaults to the \"root\" tenant.\n *\n * Registered AFTER FunctionUrlStreamIdentityLoaderDecorator.\n */\nclass FunctionUrlStreamTenantLoaderDecoratorImpl\n implements FunctionUrlStreamEventHandler.Interface\n{\n constructor(\n private rawTenantId: RawTenantId.Interface,\n private tenantLoader: IRequestTenantLoader,\n private decoratee: FunctionUrlStreamEventHandler.Interface\n ) {}\n\n async execute(ctx: EventContext<any>, next: NextFunction): Promise<void> {\n const headers = headersFromFunctionUrlEvent(ctx.event);\n const tenantId = extractTenantId(headers);\n\n this.rawTenantId.set(tenantId);\n\n await this.tenantLoader.establish();\n return this.decoratee.execute(ctx, next);\n }\n}\n\nexport const FunctionUrlStreamTenantLoaderDecorator = FunctionUrlStreamEventHandler.createDecorator(\n {\n decorator: FunctionUrlStreamTenantLoaderDecoratorImpl,\n dependencies: [RawTenantId, RequestTenantLoader]\n }\n);\n"],"names":["FunctionUrlStreamTenantLoaderDecoratorImpl","rawTenantId","tenantLoader","decoratee","ctx","next","headers","headersFromFunctionUrlEvent","tenantId","extractTenantId","FunctionUrlStreamTenantLoaderDecorator","FunctionUrlStreamEventHandler","RawTenantId","RequestTenantLoader"],"mappings":";;;AAgBA,MAAMA;IAGF,YACYC,WAAkC,EAClCC,YAAkC,EAClCC,SAAkD,CAC5D;aAHUF,WAAW,GAAXA;aACAC,YAAY,GAAZA;aACAC,SAAS,GAATA;IACT;IAEH,MAAM,QAAQC,GAAsB,EAAEC,IAAkB,EAAiB;QACrE,MAAMC,UAAUC,4BAA4BH,IAAI,KAAK;QACrD,MAAMI,WAAWC,gBAAgBH;QAEjC,IAAI,CAAC,WAAW,CAAC,GAAG,CAACE;QAErB,MAAM,IAAI,CAAC,YAAY,CAAC,SAAS;QACjC,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,CAACJ,KAAKC;IACvC;AACJ;AAEO,MAAMK,yCAAyCC,8BAA8B,eAAe,CAC/F;IACI,WAAWX;IACX,cAAc;QAACY;QAAaC;KAAoB;AACpD"}
@@ -0,0 +1,21 @@
1
+ /**
2
+ * Header parsing shared by the API Gateway and Function URL auth/tenant decorators, so the two
3
+ * transports can't drift on how a caller authenticates.
4
+ */
5
+ export declare const WEBINY_AUTHORIZATION_HEADER = "x-webiny-authorization";
6
+ /**
7
+ * Reads the auth token, preferring `x-webiny-authorization` over `Authorization`.
8
+ *
9
+ * That order exists for CloudFront → Lambda Function URL with Origin Access Control: OAC signs the
10
+ * request with SigV4, which occupies the `Authorization` header, so a viewer's bearer token cannot
11
+ * survive to the origin. Clients that may traverse an OAC-signed origin send the token in the
12
+ * `x-webiny-authorization` header instead. Plain `Authorization` stays supported for every other
13
+ * caller, and the `wby-id-token` cookie remains the last resort.
14
+ */
15
+ export declare function extractAuthToken(headers: Record<string, string> | undefined): string | null;
16
+ export declare function extractTenantId(headers: Record<string, string> | undefined): string | null;
17
+ /**
18
+ * Function URL events (payload format 2.0) deliver cookies as a `cookies` ARRAY rather than a `cookie`
19
+ * header. Fold them back so the extractors above see a normal header map.
20
+ */
21
+ export declare function headersFromFunctionUrlEvent(event: any): Record<string, string>;
@@ -0,0 +1,34 @@
1
+ const WEBINY_AUTHORIZATION_HEADER = "x-webiny-authorization";
2
+ function parseCookieHeader(cookieHeader) {
3
+ return cookieHeader.split(";").reduce((acc, pair)=>{
4
+ const idx = pair.indexOf("=");
5
+ if (idx > 0) acc[pair.slice(0, idx).trim()] = decodeURIComponent(pair.slice(idx + 1).trim());
6
+ return acc;
7
+ }, {});
8
+ }
9
+ function getHeader(headers, name) {
10
+ if (!headers) return "";
11
+ for (const key of Object.keys(headers))if (key.toLowerCase() === name) return headers[key] ?? "";
12
+ return "";
13
+ }
14
+ function extractAuthToken(headers) {
15
+ const webinyAuth = getHeader(headers, WEBINY_AUTHORIZATION_HEADER).replace(/^Bearer\s+/i, "");
16
+ if (webinyAuth) return webinyAuth;
17
+ const bearer = getHeader(headers, "authorization").replace(/^Bearer\s+/i, "");
18
+ if (bearer) return bearer;
19
+ const cookieHeader = getHeader(headers, "cookie");
20
+ return parseCookieHeader(cookieHeader)["wby-id-token"] ?? null;
21
+ }
22
+ function extractTenantId(headers) {
23
+ return getHeader(headers, "x-tenant") || null;
24
+ }
25
+ function headersFromFunctionUrlEvent(event) {
26
+ const headers = {
27
+ ...event?.headers || {}
28
+ };
29
+ if (Array.isArray(event?.cookies) && event.cookies.length > 0) headers.cookie = event.cookies.join("; ");
30
+ return headers;
31
+ }
32
+ export { WEBINY_AUTHORIZATION_HEADER, extractAuthToken, extractTenantId, headersFromFunctionUrlEvent };
33
+
34
+ //# sourceMappingURL=extractRequestAuth.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handlers/extractRequestAuth.js","sources":["../../src/handlers/extractRequestAuth.ts"],"sourcesContent":["/**\n * Header parsing shared by the API Gateway and Function URL auth/tenant decorators, so the two\n * transports can't drift on how a caller authenticates.\n */\n\nexport const WEBINY_AUTHORIZATION_HEADER = \"x-webiny-authorization\";\n\nfunction parseCookieHeader(cookieHeader: string): Record<string, string> {\n return cookieHeader.split(\";\").reduce<Record<string, string>>((acc, pair) => {\n const idx = pair.indexOf(\"=\");\n if (idx > 0) {\n acc[pair.slice(0, idx).trim()] = decodeURIComponent(pair.slice(idx + 1).trim());\n }\n return acc;\n }, {});\n}\n\nfunction getHeader(headers: Record<string, string> | undefined, name: string): string {\n if (!headers) {\n return \"\";\n }\n // Header names are case-insensitive, and the casing that reaches us depends on the transport and\n // on the client, so match on the lowercased key rather than guessing a spelling.\n for (const key of Object.keys(headers)) {\n if (key.toLowerCase() === name) {\n return headers[key] ?? \"\";\n }\n }\n return \"\";\n}\n\n/**\n * Reads the auth token, preferring `x-webiny-authorization` over `Authorization`.\n *\n * That order exists for CloudFront → Lambda Function URL with Origin Access Control: OAC signs the\n * request with SigV4, which occupies the `Authorization` header, so a viewer's bearer token cannot\n * survive to the origin. Clients that may traverse an OAC-signed origin send the token in the\n * `x-webiny-authorization` header instead. Plain `Authorization` stays supported for every other\n * caller, and the `wby-id-token` cookie remains the last resort.\n */\nexport function extractAuthToken(headers: Record<string, string> | undefined): string | null {\n const webinyAuth = getHeader(headers, WEBINY_AUTHORIZATION_HEADER).replace(/^Bearer\\s+/i, \"\");\n if (webinyAuth) {\n return webinyAuth;\n }\n\n const bearer = getHeader(headers, \"authorization\").replace(/^Bearer\\s+/i, \"\");\n if (bearer) {\n return bearer;\n }\n\n const cookieHeader = getHeader(headers, \"cookie\");\n return parseCookieHeader(cookieHeader)[\"wby-id-token\"] ?? null;\n}\n\nexport function extractTenantId(headers: Record<string, string> | undefined): string | null {\n return getHeader(headers, \"x-tenant\") || null;\n}\n\n/**\n * Function URL events (payload format 2.0) deliver cookies as a `cookies` ARRAY rather than a `cookie`\n * header. Fold them back so the extractors above see a normal header map.\n */\nexport function headersFromFunctionUrlEvent(event: any): Record<string, string> {\n const headers: Record<string, string> = {\n ...((event?.headers as Record<string, string>) || {})\n };\n\n if (Array.isArray(event?.cookies) && event.cookies.length > 0) {\n headers.cookie = event.cookies.join(\"; \");\n }\n\n return headers;\n}\n"],"names":["WEBINY_AUTHORIZATION_HEADER","parseCookieHeader","cookieHeader","acc","pair","idx","decodeURIComponent","getHeader","headers","name","key","Object","extractAuthToken","webinyAuth","bearer","extractTenantId","headersFromFunctionUrlEvent","event","Array"],"mappings":"AAKO,MAAMA,8BAA8B;AAE3C,SAASC,kBAAkBC,YAAoB;IAC3C,OAAOA,aAAa,KAAK,CAAC,KAAK,MAAM,CAAyB,CAACC,KAAKC;QAChE,MAAMC,MAAMD,KAAK,OAAO,CAAC;QACzB,IAAIC,MAAM,GACNF,GAAG,CAACC,KAAK,KAAK,CAAC,GAAGC,KAAK,IAAI,GAAG,GAAGC,mBAAmBF,KAAK,KAAK,CAACC,MAAM,GAAG,IAAI;QAEhF,OAAOF;IACX,GAAG,CAAC;AACR;AAEA,SAASI,UAAUC,OAA2C,EAAEC,IAAY;IACxE,IAAI,CAACD,SACD,OAAO;IAIX,KAAK,MAAME,OAAOC,OAAO,IAAI,CAACH,SAC1B,IAAIE,IAAI,WAAW,OAAOD,MACtB,OAAOD,OAAO,CAACE,IAAI,IAAI;IAG/B,OAAO;AACX;AAWO,SAASE,iBAAiBJ,OAA2C;IACxE,MAAMK,aAAaN,UAAUC,SAASR,6BAA6B,OAAO,CAAC,eAAe;IAC1F,IAAIa,YACA,OAAOA;IAGX,MAAMC,SAASP,UAAUC,SAAS,iBAAiB,OAAO,CAAC,eAAe;IAC1E,IAAIM,QACA,OAAOA;IAGX,MAAMZ,eAAeK,UAAUC,SAAS;IACxC,OAAOP,kBAAkBC,aAAa,CAAC,eAAe,IAAI;AAC9D;AAEO,SAASa,gBAAgBP,OAA2C;IACvE,OAAOD,UAAUC,SAAS,eAAe;AAC7C;AAMO,SAASQ,4BAA4BC,KAAU;IAClD,MAAMT,UAAkC;QACpC,GAAKS,OAAO,WAAsC,CAAC,CAAC;IACxD;IAEA,IAAIC,MAAM,OAAO,CAACD,OAAO,YAAYA,MAAM,OAAO,CAAC,MAAM,GAAG,GACxDT,QAAQ,MAAM,GAAGS,MAAM,OAAO,CAAC,IAAI,CAAC;IAGxC,OAAOT;AACX"}
@@ -1,3 +1,6 @@
1
1
  export * from "./ApiGatewayIdentityLoaderDecorator.js";
2
+ export * from "./FunctionUrlStreamIdentityLoaderDecorator.js";
3
+ export * from "./FunctionUrlStreamTenantLoaderDecorator.js";
4
+ export * from "./extractRequestAuth.js";
2
5
  export * from "./ApiGatewayTenantLoaderDecorator.js";
3
6
  export * from "./S3TenantLoaderDecorator.js";
package/handlers/index.js CHANGED
@@ -1,3 +1,6 @@
1
1
  export * from "./ApiGatewayIdentityLoaderDecorator.js";
2
+ export * from "./FunctionUrlStreamIdentityLoaderDecorator.js";
3
+ export * from "./FunctionUrlStreamTenantLoaderDecorator.js";
4
+ export * from "./extractRequestAuth.js";
2
5
  export * from "./ApiGatewayTenantLoaderDecorator.js";
3
6
  export * from "./S3TenantLoaderDecorator.js";
package/index.d.ts CHANGED
@@ -1,3 +1,6 @@
1
1
  export { createWebinyApiHandler } from "./createWebinyApiHandler.js";
2
2
  export type { CreateWebinyApiHandlerConfig, RegisterRootStorageContext } from "./createWebinyApiHandler.js";
3
+ export { createWebinyStreamApiHandler } from "./createWebinyStreamApiHandler.js";
4
+ export type { CreateWebinyStreamApiHandlerConfig } from "./createWebinyStreamApiHandler.js";
5
+ export type { WebinyApiCompositionConfig } from "./composition/index.js";
3
6
  export * from "./handlers/index.js";
package/index.js CHANGED
@@ -1,2 +1,3 @@
1
1
  export * from "./handlers/index.js";
2
2
  export { createWebinyApiHandler } from "./createWebinyApiHandler.js";
3
+ export { createWebinyStreamApiHandler } from "./createWebinyStreamApiHandler.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webiny/api-event-handler-aws",
3
- "version": "0.0.0-unstable.0d717d18dd",
3
+ "version": "6.6.0-alpha.1",
4
4
  "type": "module",
5
5
  "main": "index.js",
6
6
  "exports": {
@@ -18,30 +18,30 @@
18
18
  ],
19
19
  "license": "MIT",
20
20
  "dependencies": {
21
- "@webiny/api-core": "0.0.0-unstable.0d717d18dd",
22
- "@webiny/api-event-handler-core": "0.0.0-unstable.0d717d18dd",
23
- "@webiny/api-file-manager-s3": "0.0.0-unstable.0d717d18dd",
24
- "@webiny/api-headless-cms-bulk-actions-aws": "0.0.0-unstable.0d717d18dd",
25
- "@webiny/api-scheduler-aws": "0.0.0-unstable.0d717d18dd",
26
- "@webiny/api-websockets": "0.0.0-unstable.0d717d18dd",
27
- "@webiny/api-websockets-aws": "0.0.0-unstable.0d717d18dd",
28
- "@webiny/aws-sdk": "0.0.0-unstable.0d717d18dd",
29
- "@webiny/background-tasks-aws": "0.0.0-unstable.0d717d18dd",
30
- "@webiny/cognito": "0.0.0-unstable.0d717d18dd",
31
- "@webiny/db-dynamodb": "0.0.0-unstable.0d717d18dd",
32
- "@webiny/event-handler-aws": "0.0.0-unstable.0d717d18dd",
33
- "@webiny/event-handler-core": "0.0.0-unstable.0d717d18dd",
34
- "@webiny/handler": "0.0.0-unstable.0d717d18dd"
21
+ "@webiny/api-core": "6.6.0-alpha.1",
22
+ "@webiny/api-event-handler-core": "6.6.0-alpha.1",
23
+ "@webiny/api-file-manager-s3": "6.6.0-alpha.1",
24
+ "@webiny/api-headless-cms-bulk-actions-aws": "6.6.0-alpha.1",
25
+ "@webiny/api-scheduler": "6.6.0-alpha.1",
26
+ "@webiny/api-scheduler-aws": "6.6.0-alpha.1",
27
+ "@webiny/api-websockets-aws": "6.6.0-alpha.1",
28
+ "@webiny/aws-sdk": "6.6.0-alpha.1",
29
+ "@webiny/background-tasks-aws": "6.6.0-alpha.1",
30
+ "@webiny/cognito": "6.6.0-alpha.1",
31
+ "@webiny/db-dynamodb": "6.6.0-alpha.1",
32
+ "@webiny/event-handler-aws": "6.6.0-alpha.1",
33
+ "@webiny/event-handler-core": "6.6.0-alpha.1",
34
+ "@webiny/handler": "6.6.0-alpha.1"
35
35
  },
36
36
  "peerDependencies": {
37
37
  "@webiny/di": ">=0.2.3"
38
38
  },
39
39
  "devDependencies": {
40
- "@webiny/build-tools": "0.0.0-unstable.0d717d18dd",
41
- "@webiny/di": "1.0.2",
40
+ "@webiny/build-tools": "6.6.0-alpha.1",
41
+ "@webiny/di": "1.1.0",
42
42
  "rimraf": "6.1.3",
43
43
  "typescript": "7.0.2",
44
- "vitest": "4.1.10"
44
+ "vitest": "4.1.11"
45
45
  },
46
46
  "publishConfig": {
47
47
  "access": "public"