@webiny/api-event-handler-aws 0.0.0-unstable.0d717d18dd

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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) Webiny
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,11 @@
1
+ # @webiny/api-event-handler-aws
2
+
3
+ > [!NOTE]
4
+ > This package is part of the [Webiny](https://www.webiny.com) monorepo.
5
+ > It’s **included in every Webiny project by default** and is not meant to be used as a standalone package.
6
+
7
+ πŸ“˜ **Documentation:** [https://www.webiny.com/docs](https://www.webiny.com/docs)
8
+
9
+ ---
10
+
11
+ _This README file is automatically generated during the publish process._
@@ -0,0 +1,41 @@
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
+ }
41
+ export declare function createWebinyApiHandler(config: CreateWebinyApiHandlerConfig): (event: any, context?: import("aws-lambda").Context) => Promise<any>;
@@ -0,0 +1,56 @@
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";
12
+ import { ApiGatewayIdentityLoaderDecorator } from "./handlers/ApiGatewayIdentityLoaderDecorator.js";
13
+ import { ApiGatewayTenantLoaderDecorator } from "./handlers/ApiGatewayTenantLoaderDecorator.js";
14
+ function createWebinyApiHandler(config) {
15
+ const documentClient = config.documentClient ?? getDocumentClient();
16
+ return createLambdaHandler({
17
+ root: async (container)=>{
18
+ ApiGatewayFeature.register(container);
19
+ container.registerDecorator(ApiGatewayIdentityLoaderDecorator);
20
+ 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
+ });
34
+ },
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
+ });
51
+ }
52
+ });
53
+ }
54
+ export { createWebinyApiHandler };
55
+
56
+ //# sourceMappingURL=createWebinyApiHandler.js.map
@@ -0,0 +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"}
@@ -0,0 +1,26 @@
1
+ import type { APIGatewayProxyEvent } from "@webiny/aws-sdk/types/index.js";
2
+ import { ApiGatewayEventHandler } from "@webiny/event-handler-aws";
3
+ import { RawAuthToken } from "@webiny/api-core/features/requestContext/index.js";
4
+ import type { IRequestIdentityLoader } from "@webiny/api-core/features/requestContext/abstractions.js";
5
+ import type { EventContext, NextFunction } from "@webiny/event-handler-core";
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.
10
+ *
11
+ * A missing token leaves RawAuthToken null β†’ the loader authenticates as anonymous.
12
+ * Registered BEFORE ApiGatewayTenantLoaderDecorator so identity is established before tenant
13
+ * (see ApiGatewayFeature).
14
+ */
15
+ declare class ApiGatewayIdentityLoaderDecoratorImpl implements ApiGatewayEventHandler.Interface {
16
+ private rawAuthToken;
17
+ private identityLoader;
18
+ private decoratee;
19
+ constructor(rawAuthToken: RawAuthToken.Interface, identityLoader: IRequestIdentityLoader, decoratee: ApiGatewayEventHandler.Interface);
20
+ execute(ctx: EventContext<APIGatewayProxyEvent>, next: NextFunction): Promise<any>;
21
+ private extractToken;
22
+ }
23
+ export declare const ApiGatewayIdentityLoaderDecorator: typeof ApiGatewayIdentityLoaderDecoratorImpl & {
24
+ __abstraction: import("@webiny/di").Abstraction<import("@webiny/event-handler-aws").IApiGatewayEventHandler>;
25
+ };
26
+ export {};
@@ -0,0 +1,39 @@
1
+ import { ApiGatewayEventHandler } from "@webiny/event-handler-aws";
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
+ }
10
+ class ApiGatewayIdentityLoaderDecoratorImpl {
11
+ constructor(rawAuthToken, identityLoader, decoratee){
12
+ this.rawAuthToken = rawAuthToken;
13
+ this.identityLoader = identityLoader;
14
+ this.decoratee = decoratee;
15
+ }
16
+ async execute(ctx, next) {
17
+ this.rawAuthToken.set(this.extractToken(ctx.event));
18
+ await this.identityLoader.establish();
19
+ return this.decoratee.execute(ctx, next);
20
+ }
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
+ }
30
+ const ApiGatewayIdentityLoaderDecorator = ApiGatewayEventHandler.createDecorator({
31
+ decorator: ApiGatewayIdentityLoaderDecoratorImpl,
32
+ dependencies: [
33
+ RawAuthToken,
34
+ RequestIdentityLoader
35
+ ]
36
+ });
37
+ export { ApiGatewayIdentityLoaderDecorator };
38
+
39
+ //# sourceMappingURL=ApiGatewayIdentityLoaderDecorator.js.map
@@ -0,0 +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"}
@@ -0,0 +1,24 @@
1
+ import type { APIGatewayProxyEvent } from "@webiny/aws-sdk/types/index.js";
2
+ import { ApiGatewayEventHandler } from "@webiny/event-handler-aws";
3
+ import { RawTenantId } from "@webiny/api-core/features/requestContext/index.js";
4
+ import type { IRequestTenantLoader } from "@webiny/api-core/features/requestContext/abstractions.js";
5
+ import type { EventContext, NextFunction } from "@webiny/event-handler-core";
6
+ /**
7
+ * EXTRACT (transport-specific): reads the tenant id from the `x-tenant` header of an API Gateway
8
+ * event into RawTenantId, then invokes the shared LOAD step (RequestTenantLoader) which
9
+ * resolves the Tenant and sets TenantContext. A missing header leaves RawTenantId null β†’ the
10
+ * loader defaults to the "root" tenant.
11
+ *
12
+ * Registered AFTER ApiGatewayIdentityLoaderDecorator (see ApiGatewayFeature).
13
+ */
14
+ declare class ApiGatewayTenantLoaderDecoratorImpl implements ApiGatewayEventHandler.Interface {
15
+ private rawTenantId;
16
+ private tenantLoader;
17
+ private decoratee;
18
+ constructor(rawTenantId: RawTenantId.Interface, tenantLoader: IRequestTenantLoader, decoratee: ApiGatewayEventHandler.Interface);
19
+ execute(ctx: EventContext<APIGatewayProxyEvent>, next: NextFunction): Promise<any>;
20
+ }
21
+ export declare const ApiGatewayTenantLoaderDecorator: typeof ApiGatewayTenantLoaderDecoratorImpl & {
22
+ __abstraction: import("@webiny/di").Abstraction<import("@webiny/event-handler-aws").IApiGatewayEventHandler>;
23
+ };
24
+ export {};
@@ -0,0 +1,25 @@
1
+ import { ApiGatewayEventHandler } from "@webiny/event-handler-aws";
2
+ import { RawTenantId, RequestTenantLoader } from "@webiny/api-core/features/requestContext/index.js";
3
+ class ApiGatewayTenantLoaderDecoratorImpl {
4
+ constructor(rawTenantId, tenantLoader, decoratee){
5
+ this.rawTenantId = rawTenantId;
6
+ this.tenantLoader = tenantLoader;
7
+ this.decoratee = decoratee;
8
+ }
9
+ async execute(ctx, next) {
10
+ const headers = ctx.event?.headers;
11
+ this.rawTenantId.set(headers ? headers["x-tenant"] ?? headers["X-Tenant"] ?? null : null);
12
+ await this.tenantLoader.establish();
13
+ return this.decoratee.execute(ctx, next);
14
+ }
15
+ }
16
+ const ApiGatewayTenantLoaderDecorator = ApiGatewayEventHandler.createDecorator({
17
+ decorator: ApiGatewayTenantLoaderDecoratorImpl,
18
+ dependencies: [
19
+ RawTenantId,
20
+ RequestTenantLoader
21
+ ]
22
+ });
23
+ export { ApiGatewayTenantLoaderDecorator };
24
+
25
+ //# sourceMappingURL=ApiGatewayTenantLoaderDecorator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handlers/ApiGatewayTenantLoaderDecorator.js","sources":["../../src/handlers/ApiGatewayTenantLoaderDecorator.ts"],"sourcesContent":["import type { APIGatewayProxyEvent } from \"@webiny/aws-sdk/types/index.js\";\nimport { ApiGatewayEventHandler } 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\";\n\n/**\n * EXTRACT (transport-specific): reads the tenant id from the `x-tenant` header of an API Gateway\n * event into RawTenantId, then invokes the shared LOAD step (RequestTenantLoader) which\n * resolves the Tenant and sets TenantContext. A missing header leaves RawTenantId null β†’ the\n * loader defaults to the \"root\" tenant.\n *\n * Registered AFTER ApiGatewayIdentityLoaderDecorator (see ApiGatewayFeature).\n */\nclass ApiGatewayTenantLoaderDecoratorImpl implements ApiGatewayEventHandler.Interface {\n constructor(\n private rawTenantId: RawTenantId.Interface,\n private tenantLoader: IRequestTenantLoader,\n private decoratee: ApiGatewayEventHandler.Interface\n ) {}\n\n async execute(ctx: EventContext<APIGatewayProxyEvent>, next: NextFunction): Promise<any> {\n const headers = ctx.event?.headers;\n this.rawTenantId.set(headers ? (headers[\"x-tenant\"] ?? headers[\"X-Tenant\"] ?? null) : null);\n await this.tenantLoader.establish();\n return this.decoratee.execute(ctx, next);\n }\n}\n\nexport const ApiGatewayTenantLoaderDecorator = ApiGatewayEventHandler.createDecorator({\n decorator: ApiGatewayTenantLoaderDecoratorImpl,\n dependencies: [RawTenantId, RequestTenantLoader]\n});\n"],"names":["ApiGatewayTenantLoaderDecoratorImpl","rawTenantId","tenantLoader","decoratee","ctx","next","headers","ApiGatewayTenantLoaderDecorator","ApiGatewayEventHandler","RawTenantId","RequestTenantLoader"],"mappings":";;AAiBA,MAAMA;IACF,YACYC,WAAkC,EAClCC,YAAkC,EAClCC,SAA2C,CACrD;aAHUF,WAAW,GAAXA;aACAC,YAAY,GAAZA;aACAC,SAAS,GAATA;IACT;IAEH,MAAM,QAAQC,GAAuC,EAAEC,IAAkB,EAAgB;QACrF,MAAMC,UAAUF,IAAI,KAAK,EAAE;QAC3B,IAAI,CAAC,WAAW,CAAC,GAAG,CAACE,UAAWA,OAAO,CAAC,WAAW,IAAIA,OAAO,CAAC,WAAW,IAAI,OAAQ;QACtF,MAAM,IAAI,CAAC,YAAY,CAAC,SAAS;QACjC,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,CAACF,KAAKC;IACvC;AACJ;AAEO,MAAME,kCAAkCC,uBAAuB,eAAe,CAAC;IAClF,WAAWR;IACX,cAAc;QAACS;QAAaC;KAAoB;AACpD"}
@@ -0,0 +1,22 @@
1
+ import type { S3Event } from "@webiny/aws-sdk/types/index.js";
2
+ import { S3EventHandler } from "@webiny/event-handler-aws";
3
+ import { RawTenantId } from "@webiny/api-core/features/requestContext/index.js";
4
+ import type { IRequestTenantLoader } from "@webiny/api-core/features/requestContext/abstractions.js";
5
+ import type { EventContext, NextFunction } from "@webiny/event-handler-core";
6
+ /**
7
+ * EXTRACT (transport-specific): reads the tenant id from an S3 event's bucket name (convention
8
+ * "<tenant>-…" β†’ "<tenant>") into RawTenantId, then invokes the shared LOAD step
9
+ * (RequestTenantLoader). Mirrors the API Gateway tenant decorator β€” same shared load, different
10
+ * extract. S3 events carry no user identity, so no auth token is extracted.
11
+ */
12
+ declare class S3TenantLoaderDecoratorImpl implements S3EventHandler.Interface {
13
+ private rawTenantId;
14
+ private tenantLoader;
15
+ private decoratee;
16
+ constructor(rawTenantId: RawTenantId.Interface, tenantLoader: IRequestTenantLoader, decoratee: S3EventHandler.Interface);
17
+ execute(ctx: EventContext<S3Event>, next: NextFunction): Promise<any>;
18
+ }
19
+ export declare const S3TenantLoaderDecorator: typeof S3TenantLoaderDecoratorImpl & {
20
+ __abstraction: import("@webiny/di").Abstraction<import("@webiny/event-handler-aws").IS3EventHandler>;
21
+ };
22
+ export {};
@@ -0,0 +1,25 @@
1
+ import { S3EventHandler } from "@webiny/event-handler-aws";
2
+ import { RawTenantId, RequestTenantLoader } from "@webiny/api-core/features/requestContext/index.js";
3
+ class S3TenantLoaderDecoratorImpl {
4
+ constructor(rawTenantId, tenantLoader, decoratee){
5
+ this.rawTenantId = rawTenantId;
6
+ this.tenantLoader = tenantLoader;
7
+ this.decoratee = decoratee;
8
+ }
9
+ async execute(ctx, next) {
10
+ const bucket = ctx.event?.Records?.[0]?.s3?.bucket?.name;
11
+ this.rawTenantId.set(bucket ? bucket.split("-")[0] ?? null : null);
12
+ await this.tenantLoader.establish();
13
+ return this.decoratee.execute(ctx, next);
14
+ }
15
+ }
16
+ const S3TenantLoaderDecorator = S3EventHandler.createDecorator({
17
+ decorator: S3TenantLoaderDecoratorImpl,
18
+ dependencies: [
19
+ RawTenantId,
20
+ RequestTenantLoader
21
+ ]
22
+ });
23
+ export { S3TenantLoaderDecorator };
24
+
25
+ //# sourceMappingURL=S3TenantLoaderDecorator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"handlers/S3TenantLoaderDecorator.js","sources":["../../src/handlers/S3TenantLoaderDecorator.ts"],"sourcesContent":["import type { S3Event } from \"@webiny/aws-sdk/types/index.js\";\nimport { S3EventHandler } 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\";\n\n/**\n * EXTRACT (transport-specific): reads the tenant id from an S3 event's bucket name (convention\n * \"<tenant>-…\" β†’ \"<tenant>\") into RawTenantId, then invokes the shared LOAD step\n * (RequestTenantLoader). Mirrors the API Gateway tenant decorator β€” same shared load, different\n * extract. S3 events carry no user identity, so no auth token is extracted.\n */\nclass S3TenantLoaderDecoratorImpl implements S3EventHandler.Interface {\n constructor(\n private rawTenantId: RawTenantId.Interface,\n private tenantLoader: IRequestTenantLoader,\n private decoratee: S3EventHandler.Interface\n ) {}\n\n async execute(ctx: EventContext<S3Event>, next: NextFunction): Promise<any> {\n const bucket = ctx.event?.Records?.[0]?.s3?.bucket?.name;\n this.rawTenantId.set(bucket ? (bucket.split(\"-\")[0] ?? null) : null);\n await this.tenantLoader.establish();\n return this.decoratee.execute(ctx, next);\n }\n}\n\nexport const S3TenantLoaderDecorator = S3EventHandler.createDecorator({\n decorator: S3TenantLoaderDecoratorImpl,\n dependencies: [RawTenantId, RequestTenantLoader]\n});\n"],"names":["S3TenantLoaderDecoratorImpl","rawTenantId","tenantLoader","decoratee","ctx","next","bucket","S3TenantLoaderDecorator","S3EventHandler","RawTenantId","RequestTenantLoader"],"mappings":";;AAeA,MAAMA;IACF,YACYC,WAAkC,EAClCC,YAAkC,EAClCC,SAAmC,CAC7C;aAHUF,WAAW,GAAXA;aACAC,YAAY,GAAZA;aACAC,SAAS,GAATA;IACT;IAEH,MAAM,QAAQC,GAA0B,EAAEC,IAAkB,EAAgB;QACxE,MAAMC,SAASF,IAAI,KAAK,EAAE,SAAS,CAAC,EAAE,EAAE,IAAI,QAAQ;QACpD,IAAI,CAAC,WAAW,CAAC,GAAG,CAACE,SAAUA,OAAO,KAAK,CAAC,IAAI,CAAC,EAAE,IAAI,OAAQ;QAC/D,MAAM,IAAI,CAAC,YAAY,CAAC,SAAS;QACjC,OAAO,IAAI,CAAC,SAAS,CAAC,OAAO,CAACF,KAAKC;IACvC;AACJ;AAEO,MAAME,0BAA0BC,eAAe,eAAe,CAAC;IAClE,WAAWR;IACX,cAAc;QAACS;QAAaC;KAAoB;AACpD"}
@@ -0,0 +1,3 @@
1
+ export * from "./ApiGatewayIdentityLoaderDecorator.js";
2
+ export * from "./ApiGatewayTenantLoaderDecorator.js";
3
+ export * from "./S3TenantLoaderDecorator.js";
@@ -0,0 +1,3 @@
1
+ export * from "./ApiGatewayIdentityLoaderDecorator.js";
2
+ export * from "./ApiGatewayTenantLoaderDecorator.js";
3
+ export * from "./S3TenantLoaderDecorator.js";
package/index.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ export { createWebinyApiHandler } from "./createWebinyApiHandler.js";
2
+ export type { CreateWebinyApiHandlerConfig, RegisterRootStorageContext } from "./createWebinyApiHandler.js";
3
+ export * from "./handlers/index.js";
package/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export * from "./handlers/index.js";
2
+ export { createWebinyApiHandler } from "./createWebinyApiHandler.js";
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "@webiny/api-event-handler-aws",
3
+ "version": "0.0.0-unstable.0d717d18dd",
4
+ "type": "module",
5
+ "main": "index.js",
6
+ "exports": {
7
+ ".": "./index.js",
8
+ "./*": "./*"
9
+ },
10
+ "types": "index.d.ts",
11
+ "description": "Composition layer: assembles the Webiny API handler for the AWS Lambda transport.",
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "https://github.com/webiny/webiny-js.git"
15
+ },
16
+ "contributors": [
17
+ "Webiny Team"
18
+ ],
19
+ "license": "MIT",
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"
35
+ },
36
+ "peerDependencies": {
37
+ "@webiny/di": ">=0.2.3"
38
+ },
39
+ "devDependencies": {
40
+ "@webiny/build-tools": "0.0.0-unstable.0d717d18dd",
41
+ "@webiny/di": "1.0.2",
42
+ "rimraf": "6.1.3",
43
+ "typescript": "7.0.2",
44
+ "vitest": "4.1.10"
45
+ },
46
+ "publishConfig": {
47
+ "access": "public"
48
+ },
49
+ "webiny": {
50
+ "publishFrom": "dist"
51
+ }
52
+ }