@geekmidas/constructs 10.0.0-alpha.70 → 10.0.0-alpha.72
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/dist/{Construct-BO1X-kt9.mjs → Construct-B1vGBPme.mjs} +2 -2
- package/dist/{Construct-BO1X-kt9.mjs.map → Construct-B1vGBPme.mjs.map} +1 -1
- package/dist/{Construct-DmvXceVY.cjs → Construct-DUSXuTHP.cjs} +2 -2
- package/dist/{Construct-DmvXceVY.cjs.map → Construct-DUSXuTHP.cjs.map} +1 -1
- package/dist/{CronBuilder-BoHzlWU_.cjs → CronBuilder-C0Ek1-RA.cjs} +3 -3
- package/dist/{CronBuilder-BoHzlWU_.cjs.map → CronBuilder-C0Ek1-RA.cjs.map} +1 -1
- package/dist/{CronBuilder-CCgt0wCE.mjs → CronBuilder-Dmix_Pen.mjs} +3 -3
- package/dist/{CronBuilder-CCgt0wCE.mjs.map → CronBuilder-Dmix_Pen.mjs.map} +1 -1
- package/dist/{Endpoint-DfiXTm_v.cjs → Endpoint-Ba1PiyuJ.cjs} +3 -3
- package/dist/{Endpoint-DfiXTm_v.cjs.map → Endpoint-Ba1PiyuJ.cjs.map} +1 -1
- package/dist/{Endpoint-DV3jK5sP.d.cts → Endpoint-DJZkADYh.d.cts} +2 -2
- package/dist/{Endpoint-BJDBZBZu.d.mts.map → Endpoint-DJZkADYh.d.cts.map} +1 -1
- package/dist/{Endpoint-CMWWrQ7u.mjs → Endpoint-ZJhv68qq.mjs} +3 -3
- package/dist/{Endpoint-CMWWrQ7u.mjs.map → Endpoint-ZJhv68qq.mjs.map} +1 -1
- package/dist/{Endpoint-BJDBZBZu.d.mts → Endpoint-hcHSFhda.d.mts} +3 -3
- package/dist/{Endpoint-DV3jK5sP.d.cts.map → Endpoint-hcHSFhda.d.mts.map} +1 -1
- package/dist/{EndpointFactory-gaF4yRpP.d.mts → EndpointFactory-B5siFRcO.d.mts} +3 -3
- package/dist/{EndpointFactory-gaF4yRpP.d.mts.map → EndpointFactory-B5siFRcO.d.mts.map} +1 -1
- package/dist/{EndpointFactory-CLxrcS0O.cjs → EndpointFactory-B_x2fXWQ.cjs} +4 -4
- package/dist/{EndpointFactory-CLxrcS0O.cjs.map → EndpointFactory-B_x2fXWQ.cjs.map} +1 -1
- package/dist/{EndpointFactory-CLzCLkLt.d.cts → EndpointFactory-BkYuVg8W.d.cts} +2 -2
- package/dist/{EndpointFactory-CLzCLkLt.d.cts.map → EndpointFactory-BkYuVg8W.d.cts.map} +1 -1
- package/dist/{EndpointFactory-7g4Dg6cW.mjs → EndpointFactory-C3QvXMk6.mjs} +4 -4
- package/dist/{EndpointFactory-7g4Dg6cW.mjs.map → EndpointFactory-C3QvXMk6.mjs.map} +1 -1
- package/dist/{HonoEndpointAdaptor-Df5-cIJU.cjs → HonoEndpointAdaptor-0yLvYunI.cjs} +39 -16
- package/dist/HonoEndpointAdaptor-0yLvYunI.cjs.map +1 -0
- package/dist/{HonoEndpointAdaptor-9Byxn0TX.mjs → HonoEndpointAdaptor-chgcjPmg.mjs} +39 -16
- package/dist/HonoEndpointAdaptor-chgcjPmg.mjs.map +1 -0
- package/dist/{Queue-hwPN-t31.mjs → Queue-CLRT_j5a.mjs} +2 -2
- package/dist/{Queue-hwPN-t31.mjs.map → Queue-CLRT_j5a.mjs.map} +1 -1
- package/dist/{Queue-D5jcw0mu.cjs → Queue-umpX3683.cjs} +2 -2
- package/dist/{Queue-D5jcw0mu.cjs.map → Queue-umpX3683.cjs.map} +1 -1
- package/dist/{QueueBuilder-DCuYdjMw.mjs → QueueBuilder-B0mCqq74.mjs} +2 -2
- package/dist/{QueueBuilder-DCuYdjMw.mjs.map → QueueBuilder-B0mCqq74.mjs.map} +1 -1
- package/dist/{QueueBuilder-BFQn3OzZ.cjs → QueueBuilder-B9ClmXjX.cjs} +2 -2
- package/dist/{QueueBuilder-BFQn3OzZ.cjs.map → QueueBuilder-B9ClmXjX.cjs.map} +1 -1
- package/dist/{SubscriberBuilder-DMFk_Ap1.mjs → SubscriberBuilder-CDy4nHCz.mjs} +2 -2
- package/dist/{SubscriberBuilder-DMFk_Ap1.mjs.map → SubscriberBuilder-CDy4nHCz.mjs.map} +1 -1
- package/dist/{SubscriberBuilder-C2PwqwIl.cjs → SubscriberBuilder-D_owVoHo.cjs} +2 -2
- package/dist/{SubscriberBuilder-C2PwqwIl.cjs.map → SubscriberBuilder-D_owVoHo.cjs.map} +1 -1
- package/dist/{Topic-CkxOTrMv.cjs → Topic-BliAKi5r.cjs} +2 -2
- package/dist/{Topic-CkxOTrMv.cjs.map → Topic-BliAKi5r.cjs.map} +1 -1
- package/dist/{Topic-hPffOsot.mjs → Topic-DCxIstf9.mjs} +2 -2
- package/dist/{Topic-hPffOsot.mjs.map → Topic-DCxIstf9.mjs.map} +1 -1
- package/dist/adaptors/aws.cjs +8 -8
- package/dist/adaptors/aws.cjs.map +1 -1
- package/dist/adaptors/aws.d.cts +1 -1
- package/dist/adaptors/aws.d.mts +2 -2
- package/dist/adaptors/aws.mjs +9 -9
- package/dist/adaptors/aws.mjs.map +1 -1
- package/dist/adaptors/hono.cjs +1 -1
- package/dist/adaptors/hono.d.cts +1 -1
- package/dist/adaptors/hono.d.cts.map +1 -1
- package/dist/adaptors/hono.d.mts +1 -1
- package/dist/adaptors/hono.d.mts.map +1 -1
- package/dist/adaptors/hono.mjs +1 -1
- package/dist/adaptors/testing.cjs +7 -7
- package/dist/adaptors/testing.d.cts +1 -1
- package/dist/adaptors/testing.d.mts +1 -1
- package/dist/adaptors/testing.mjs +7 -7
- package/dist/{auth-CIFXNuDk.d.cts → auth-CuCozjsh.d.cts} +62 -7
- package/dist/auth-CuCozjsh.d.cts.map +1 -0
- package/dist/{auth-CJ9Ff6Lu.d.mts → auth-XtDcvQxV.d.mts} +63 -8
- package/dist/auth-XtDcvQxV.d.mts.map +1 -0
- package/dist/auth.cjs +78 -11
- package/dist/auth.cjs.map +1 -1
- package/dist/auth.d.cts +2 -2
- package/dist/auth.d.mts +2 -2
- package/dist/auth.mjs +77 -11
- package/dist/auth.mjs.map +1 -1
- package/dist/crons/index.cjs +2 -2
- package/dist/crons/index.mjs +2 -2
- package/dist/database/kysely.cjs +1 -1
- package/dist/database/kysely.mjs +1 -1
- package/dist/endpoints/index.cjs +3 -3
- package/dist/endpoints/index.d.cts +2 -2
- package/dist/endpoints/index.d.mts +2 -2
- package/dist/endpoints/index.mjs +3 -3
- package/dist/functions/index.cjs +1 -1
- package/dist/functions/index.mjs +1 -1
- package/dist/{functions-Di6n5ltG.mjs → functions-BFizikJU.mjs} +2 -2
- package/dist/{functions-Di6n5ltG.mjs.map → functions-BFizikJU.mjs.map} +1 -1
- package/dist/{functions-CbP5ZKma.cjs → functions-CfzJG9hK.cjs} +2 -2
- package/dist/{functions-CbP5ZKma.cjs.map → functions-CfzJG9hK.cjs.map} +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.mjs +1 -1
- package/dist/{kysely-BRzzawr2.cjs → kysely-B-xWOGmn.cjs} +2 -2
- package/dist/kysely-B-xWOGmn.cjs.map +1 -0
- package/dist/{kysely-BYfM6Zby.mjs → kysely-BhJ3lLdE.mjs} +2 -2
- package/dist/kysely-BhJ3lLdE.mjs.map +1 -0
- package/dist/{processAudits-BpRlPQMW.mjs → processAudits-BRRVVHUB.mjs} +57 -3
- package/dist/processAudits-BRRVVHUB.mjs.map +1 -0
- package/dist/{processAudits-D_2W5x8k.cjs → processAudits-DasOZjPl.cjs} +69 -3
- package/dist/processAudits-DasOZjPl.cjs.map +1 -0
- package/dist/queue/index.cjs +2 -2
- package/dist/queue/index.mjs +2 -2
- package/dist/rest-api.cjs +1 -1
- package/dist/rest-api.d.cts +2 -2
- package/dist/rest-api.d.mts +2 -2
- package/dist/rest-api.mjs +1 -1
- package/dist/{runSubscriber-BYEY_bfA.mjs → runSubscriber-BHvJ8POr.mjs} +2 -2
- package/dist/runSubscriber-BHvJ8POr.mjs.map +1 -0
- package/dist/{runSubscriber-BRp9a_qi.cjs → runSubscriber-D8nLXIv1.cjs} +2 -2
- package/dist/runSubscriber-D8nLXIv1.cjs.map +1 -0
- package/dist/subscribers/index.cjs +3 -3
- package/dist/subscribers/index.cjs.map +1 -1
- package/dist/subscribers/index.mjs +3 -3
- package/dist/subscribers/index.mjs.map +1 -1
- package/dist/topic/index.cjs +1 -1
- package/dist/topic/index.mjs +1 -1
- package/dist/worker.cjs +4 -4
- package/dist/worker.mjs +4 -4
- package/package.json +31 -31
- package/dist/HonoEndpointAdaptor-9Byxn0TX.mjs.map +0 -1
- package/dist/HonoEndpointAdaptor-Df5-cIJU.cjs.map +0 -1
- package/dist/auth-CIFXNuDk.d.cts.map +0 -1
- package/dist/auth-CJ9Ff6Lu.d.mts.map +0 -1
- package/dist/kysely-BRzzawr2.cjs.map +0 -1
- package/dist/kysely-BYfM6Zby.mjs.map +0 -1
- package/dist/processAudits-BpRlPQMW.mjs.map +0 -1
- package/dist/processAudits-D_2W5x8k.cjs.map +0 -1
- package/dist/runSubscriber-BRp9a_qi.cjs.map +0 -1
- package/dist/runSubscriber-BYEY_bfA.mjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SubscriberBuilder-C2PwqwIl.cjs","names":["Construct","DEFAULT_LOGGER","DEFAULT_LOGGER","cloneWith","servicesOf","idsOf","serviceOf","databaseEdges"],"sources":["../src/subscribers/Subscriber.ts","../src/subscribers/SubscriberBuilder.ts"],"sourcesContent":["import type {\n\tEventPublisher,\n\tExtractPublisherMessage,\n} from '@geekmidas/events';\nimport type { Logger } from '@geekmidas/logger';\nimport { DEFAULT_LOGGER } from '@geekmidas/logger/console';\nimport type { InferStandardSchema } from '@geekmidas/schema';\nimport type { Service, ServiceRecord } from '@geekmidas/services';\nimport type { StandardSchemaV1 } from '@standard-schema/spec';\nimport { Construct, ConstructType } from '../Construct';\nimport type { DatabaseContext } from '../functions/Function';\n\n// Helper type to extract payload types for subscribed events\ntype ExtractEventPayloads<\n\tTPublisher extends EventPublisher<any> | undefined,\n\tTEventTypes extends any[],\n> = TPublisher extends EventPublisher<any>\n\t? Extract<ExtractPublisherMessage<TPublisher>, { type: TEventTypes[number] }>\n\t: never;\n\n/**\n * A runnable that consumes a topic. Its handler gets `db` when it has a\n * database: the worker's, declared once with `worker.database(db)`, or its own\n * with `.database(other)`.\n */\nexport class Subscriber<\n\tTServices extends Service[] = [],\n\tTLogger extends Logger = Logger,\n\tOutSchema extends StandardSchemaV1 | undefined = undefined,\n\t/** The topic's message union — what types the events this subscriber receives. */\n\tTEventPublisher extends EventPublisher<any> | undefined = undefined,\n\tTSubscribedEvents extends\n\t\tExtractPublisherMessage<TEventPublisher>['type'][] = ExtractPublisherMessage<TEventPublisher>['type'][],\n\tTDatabase = undefined,\n\tTDatabaseServiceName extends string = string,\n> extends Construct<\n\tTLogger,\n\tOutSchema,\n\tTServices,\n\tstring,\n\tundefined,\n\tTDatabaseServiceName,\n\tTDatabase\n> {\n\t__IS_SUBSCRIBER__ = true;\n\n\tstatic isSubscriber(\n\t\tobj: any,\n\t): obj is Subscriber<any, any, any, any, any, any> {\n\t\treturn Boolean(\n\t\t\tobj &&\n\t\t\t\tobj.__IS_SUBSCRIBER__ === true &&\n\t\t\t\tobj.type === ConstructType.Subscriber,\n\t\t);\n\t}\n\n\tconstructor(\n\t\tpublic readonly handler: SubscriberHandler<\n\t\t\tTEventPublisher,\n\t\t\tTSubscribedEvents,\n\t\t\tTServices,\n\t\t\tTLogger,\n\t\t\tOutSchema,\n\t\t\tTDatabase\n\t\t>,\n\t\tpublic override readonly timeout: number = 30000,\n\t\tprotected _subscribedEvents?: TSubscribedEvents,\n\t\tpublic override readonly outputSchema?: OutSchema,\n\t\tpublic override readonly services: TServices = [] as unknown as TServices,\n\t\tpublic override readonly logger: TLogger = DEFAULT_LOGGER as TLogger,\n\t\t/**\n\t\t * The name of the {@link Topic} this subscriber binds to (via\n\t\t * `worker.topic(topic)`), recorded for the manifest so infra wires the\n\t\t * SNS subscription.\n\t\t */\n\t\tpublic readonly topicName?: string,\n\t\t/**\n\t\t * The construct ids `.dependsOn()` named — last, so no existing positional\n\t\t * argument moves.\n\t\t */\n\t\tconstructs: string[] = [],\n\t\t/**\n\t\t * What the handler's `db` is registered from — after `constructs`, for\n\t\t * the same reason.\n\t\t */\n\t\tdatabaseService?: Service<TDatabaseServiceName, TDatabase>,\n\t) {\n\t\tsuper(\n\t\t\tConstructType.Subscriber,\n\t\t\tlogger,\n\t\t\tservices,\n\t\t\t[],\n\t\t\toutputSchema,\n\t\t\ttimeout,\n\t\t\tundefined, // memorySize\n\t\t\tundefined, // auditorStorageService\n\t\t\tconstructs,\n\t\t);\n\n\t\tthis.databaseService = databaseService;\n\t}\n\n\tget subscribedEvents(): TSubscribedEvents | undefined {\n\t\treturn this._subscribedEvents;\n\t}\n}\n\n// Handler type for subscribers that receives an array of events\nexport type SubscriberHandler<\n\tTEventPublisher extends EventPublisher<any> | undefined,\n\tTSubscribedEvents extends ExtractPublisherMessage<TEventPublisher>['type'][],\n\tTServices extends Service[] = [],\n\tTLogger extends Logger = Logger,\n\tOutSchema extends StandardSchemaV1 | undefined = undefined,\n\tTDatabase = undefined,\n> = (\n\tctx: SubscriberContext<\n\t\tTEventPublisher,\n\t\tTSubscribedEvents,\n\t\tTServices,\n\t\tTLogger,\n\t\tTDatabase\n\t>,\n) => OutSchema extends StandardSchemaV1\n\t? InferStandardSchema<OutSchema> | Promise<InferStandardSchema<OutSchema>>\n\t: any | Promise<any>;\n\n// Context type for subscriber handlers — `db` only when a database is set.\nexport type SubscriberContext<\n\tTEventPublisher extends EventPublisher<any> | undefined,\n\tTSubscribedEvents extends ExtractPublisherMessage<TEventPublisher>['type'][],\n\tTServices extends Service[] = [],\n\tTLogger extends Logger = Logger,\n\tTDatabase = undefined,\n> = {\n\tevents: ExtractEventPayloads<TEventPublisher, TSubscribedEvents>[];\n\tservices: ServiceRecord<TServices>;\n\tlogger: TLogger;\n} & DatabaseContext<TDatabase>;\n","import type {\n\tEventPublisher,\n\tExtractPublisherMessage,\n} from '@geekmidas/events';\nimport type { Logger } from '@geekmidas/logger';\nimport { DEFAULT_LOGGER } from '@geekmidas/logger/console';\nimport type { Service } from '@geekmidas/services';\nimport type { StandardSchemaV1 } from '@standard-schema/spec';\nimport { cloneWith } from '../clone';\nimport {\n\ttype Consumable,\n\tdatabaseEdges,\n\tidsOf,\n\ttype ServicesOf,\n\tserviceOf,\n\tservicesOf,\n} from '../construct-interface';\nimport type { Topic, TopicEvents, TopicMessage } from '../topic/Topic';\nimport { Subscriber, type SubscriberHandler } from './Subscriber';\n\nexport class SubscriberBuilder<\n\tTServices extends Service[] = [],\n\tTLogger extends Logger = Logger,\n\tOutSchema extends StandardSchemaV1 | undefined = undefined,\n\tTEventPublisher extends EventPublisher<any> | undefined = undefined,\n\tTSubscribedEvents extends any[] = [],\n\tTDatabase = undefined,\n\tTDatabaseServiceName extends string = string,\n> {\n\tprivate _subscribedEvents: TSubscribedEvents = [] as any;\n\tprivate _timeout?: number;\n\tprivate outputSchema?: OutSchema;\n\tprivate _services: TServices = [] as Service[] as TServices;\n\t/** The construct ids `.dependsOn()` named — what the manifest records. */\n\tpublic _constructs: string[] = [];\n\tprivate _logger: TLogger = DEFAULT_LOGGER;\n\t/**\n\t * The deploy unit that runs this, by construct id. Seeded by the factory a\n\t * `Worker` hands out, so a subscriber is not owned by its directory.\n\t */\n\tpublic _owner?: string;\n\tprivate _topicName?: string;\n\t/** What the handler's `db` comes from — the worker's, unless overridden. */\n\tprivate _databaseService?: Service<TDatabaseServiceName, TDatabase>;\n\t/** The edge `.database()` added, so the next one can replace it. */\n\tprivate _databaseEdge?: string;\n\n\tconstructor() {\n\t\tthis._timeout = 30000; // Default timeout\n\t}\n\n\t/**\n\t * Bind this subscriber to a {@link Topic}: the subscribable event types (and\n\t * their payloads) come from the topic's contract, and the binding is recorded\n\t * for the manifest, so infra wires the SNS subscription.\n\t *\n\t * A consumer does not publish, so binding a topic does *not* hand it the\n\t * topic's publisher connection string (least privilege). One that publishes\n\t * follow-up events depends on the topic it publishes to: `.dependsOn([orders])`.\n\t */\n\ttopic<TName extends string, TEvents extends TopicEvents>(\n\t\ttopic: Topic<TName, TEvents>,\n\t): SubscriberBuilder<\n\t\tTServices,\n\t\tTLogger,\n\t\tOutSchema,\n\t\tEventPublisher<TopicMessage<TEvents>>,\n\t\tTSubscribedEvents,\n\t\tTDatabase,\n\t\tTDatabaseServiceName\n\t> {\n\t\treturn cloneWith(this, {\n\t\t\t_topicName: topic.name,\n\t\t}) as unknown as SubscriberBuilder<\n\t\t\tTServices,\n\t\t\tTLogger,\n\t\t\tOutSchema,\n\t\t\tEventPublisher<TopicMessage<TEvents>>,\n\t\t\tTSubscribedEvents,\n\t\t\tTDatabase,\n\t\t\tTDatabaseServiceName\n\t\t>;\n\t}\n\n\ttimeout(timeout: number): this {\n\t\treturn cloneWith(this, { _timeout: timeout });\n\t}\n\n\toutput<T extends StandardSchemaV1>(\n\t\tschema: T,\n\t): SubscriberBuilder<\n\t\tTServices,\n\t\tTLogger,\n\t\tT,\n\t\tTEventPublisher,\n\t\tTSubscribedEvents,\n\t\tTDatabase,\n\t\tTDatabaseServiceName\n\t> {\n\t\treturn cloneWith(this, {\n\t\t\toutputSchema: schema as unknown as OutSchema,\n\t\t}) as any;\n\t}\n\n\t/**\n\t * Depend on constructs — a database, a bucket, a mail sender, a queue, a\n\t * topic.\n\t *\n\t * It records the edge and dissolves each construct's client into the\n\t * handler's service record under the construct's own id, so\n\t * `.dependsOn([uploads])` is what makes `services.uploads` exist and type.\n\t *\n\t * Constructs only. A `Service` does not match the shape, which is what keeps\n\t * env sniffing confined to `.services()` and the explicit lift.\n\t */\n\tdependsOn<const T extends readonly Consumable[]>(\n\t\tconstructs: T,\n\t): SubscriberBuilder<\n\t\t[...TServices, ...ServicesOf<T>],\n\t\tTLogger,\n\t\tOutSchema,\n\t\tTEventPublisher,\n\t\tTSubscribedEvents,\n\t\tTDatabase,\n\t\tTDatabaseServiceName\n\t> {\n\t\t// Both halves of the edge, from one call and one clone: the services the\n\t\t// handler runs with, and the ids the manifest records. Recording them\n\t\t// separately is what let them drift apart.\n\t\t//\n\t\t// `servicesOf` is the half that validates, so it runs first — recording\n\t\t// ids ahead of it left a caught `NotAConstruct` with `undefined` already\n\t\t// on a `string[]`.\n\t\tconst services = servicesOf(constructs) as unknown as Service[];\n\n\t\treturn cloneWith(this, {\n\t\t\t_services: [...this._services, ...services],\n\t\t\t_constructs: idsOf(constructs, this._constructs),\n\t\t}) as unknown as SubscriberBuilder<\n\t\t\t[...TServices, ...ServicesOf<T>],\n\t\t\tTLogger,\n\t\t\tOutSchema,\n\t\t\tTEventPublisher,\n\t\t\tTSubscribedEvents,\n\t\t\tTDatabase,\n\t\t\tTDatabaseServiceName\n\t\t>;\n\t}\n\n\tservices<T extends Service[]>(\n\t\tservices: T,\n\t): SubscriberBuilder<\n\t\t[...TServices, ...T],\n\t\tTLogger,\n\t\tOutSchema,\n\t\tTEventPublisher,\n\t\tTSubscribedEvents,\n\t\tTDatabase,\n\t\tTDatabaseServiceName\n\t> {\n\t\treturn cloneWith(this, {\n\t\t\t_services: [...this._services, ...services] as any,\n\t\t}) as any;\n\t}\n\n\tlogger<T extends Logger>(\n\t\tlogger: T,\n\t): SubscriberBuilder<\n\t\tTServices,\n\t\tT,\n\t\tOutSchema,\n\t\tTEventPublisher,\n\t\tTSubscribedEvents,\n\t\tTDatabase,\n\t\tTDatabaseServiceName\n\t> {\n\t\treturn cloneWith(this, { _logger: logger as unknown as TLogger }) as any;\n\t}\n\n\t/**\n\t * The database the handler receives as `db`.\n\t *\n\t * A subscriber built from a worker already has the worker's, when the\n\t * worker named one with `.database(db)`; this replaces it — the edge as well\n\t * as the client — for a consumer that works against a different database.\n\t */\n\tdatabase<T, TDbName extends string>(\n\t\tsource: Consumable<TDbName, T> | Service<TDbName, T>,\n\t): SubscriberBuilder<\n\t\tTServices,\n\t\tTLogger,\n\t\tOutSchema,\n\t\tTEventPublisher,\n\t\tTSubscribedEvents,\n\t\tT,\n\t\tTDbName\n\t> {\n\t\treturn cloneWith(this, {\n\t\t\t_databaseService: serviceOf(source),\n\t\t\t...databaseEdges(\n\t\t\t\t{\n\t\t\t\t\tconstructs: this._constructs,\n\t\t\t\t\tedge: this._databaseEdge,\n\t\t\t\t\tservice: this._databaseService as Service | undefined,\n\t\t\t\t\tservices: this._services,\n\t\t\t\t},\n\t\t\t\tsource,\n\t\t\t),\n\t\t}) as unknown as SubscriberBuilder<\n\t\t\tTServices,\n\t\t\tTLogger,\n\t\t\tOutSchema,\n\t\t\tTEventPublisher,\n\t\t\tTSubscribedEvents,\n\t\t\tT,\n\t\t\tTDbName\n\t\t>;\n\t}\n\n\tsubscribe<\n\t\tTEvent extends TEventPublisher extends EventPublisher<any>\n\t\t\t?\n\t\t\t\t\t| ExtractPublisherMessage<TEventPublisher>['type']\n\t\t\t\t\t| ExtractPublisherMessage<TEventPublisher>['type'][]\n\t\t\t: never,\n\t>(\n\t\tevent: TEvent,\n\t): SubscriberBuilder<\n\t\tTServices,\n\t\tTLogger,\n\t\tOutSchema,\n\t\tTEventPublisher,\n\t\tTEvent extends any[]\n\t\t\t? [...TSubscribedEvents, ...TEvent]\n\t\t\t: [...TSubscribedEvents, TEvent],\n\t\tTDatabase,\n\t\tTDatabaseServiceName\n\t> {\n\t\tconst eventsToAdd = Array.isArray(event) ? event : [event];\n\t\treturn cloneWith(this, {\n\t\t\t_subscribedEvents: [...this._subscribedEvents, ...eventsToAdd] as any,\n\t\t}) as any;\n\t}\n\n\thandle(\n\t\tfn: SubscriberHandler<\n\t\t\tTEventPublisher,\n\t\t\tTSubscribedEvents,\n\t\t\tTServices,\n\t\t\tTLogger,\n\t\t\tOutSchema,\n\t\t\tTDatabase\n\t\t>,\n\t): Subscriber<\n\t\tTServices,\n\t\tTLogger,\n\t\tOutSchema,\n\t\tTEventPublisher,\n\t\tTSubscribedEvents,\n\t\tTDatabase,\n\t\tTDatabaseServiceName\n\t> {\n\t\tconst subscriber = new Subscriber(\n\t\t\tfn,\n\t\t\tthis._timeout,\n\t\t\tthis._subscribedEvents,\n\t\t\tthis.outputSchema,\n\t\t\tthis._services,\n\t\t\tthis._logger,\n\t\t\tthis._topicName,\n\t\t\tthis._constructs,\n\t\t\tthis._databaseService,\n\t\t);\n\n\t\t// Which process runs it. Carried from the factory rather than inferred\n\t\t// from the directory the file happens to sit in.\n\t\tsubscriber.owner = this._owner;\n\n\t\t// No reset: `.handle()` reads this builder and leaves it alone, so a\n\t\t// configured base stays usable for the next subscriber.\n\t\treturn subscriber;\n\t}\n}\n"],"mappings":";;;;;;;;;;AAyBA,IAAa,aAAb,cAUUA,kBAAAA,UAQR;CAcgB;CAQS;CACf;CACe;CACA;CACA;CAMT;CA/BjB,oBAAoB;CAEpB,OAAO,aACN,KACkD;EAClD,OAAO,QACN,OACC,IAAI,sBAAsB,QAC1B,IAAI,SAAA,mCACN;CACD;CAEA,YACC,SAQA,UAA2C,KAC3C,mBACA,cACA,WAA+C,CAAC,GAChD,SAA2CC,0BAAAA,gBAM3C,WAKA,aAAuB,CAAC,GAKxB,iBACC;EACD,MAAA,qCAEC,QACA,UACA,CAAC,GACD,cACA,SACA,KAAA,GACA,KAAA,GACA,UACD;EAxCgB,KAAA,UAAA;EAQS,KAAA,UAAA;EACf,KAAA,oBAAA;EACe,KAAA,eAAA;EACA,KAAA,WAAA;EACA,KAAA,SAAA;EAMT,KAAA,YAAA;EAwBhB,KAAK,kBAAkB;CACxB;CAEA,IAAI,mBAAkD;EACrD,OAAO,KAAK;CACb;AACD;;;ACrFA,IAAa,oBAAb,MAQE;CACD,oBAA+C,CAAC;CAChD;CACA;CACA,YAA+B,CAAC;;CAEhC,cAA+B,CAAC;CAChC,UAA2BC,0BAAAA;;;;;CAK3B;CACA;;CAEA;;CAEA;CAEA,cAAc;EACb,KAAK,WAAW;CACjB;;;;;;;;;;CAWA,MACC,OASC;EACD,OAAOC,cAAAA,UAAU,MAAM,EACtB,YAAY,MAAM,KACnB,CAAC;CASF;CAEA,QAAQ,SAAuB;EAC9B,OAAOA,cAAAA,UAAU,MAAM,EAAE,UAAU,QAAQ,CAAC;CAC7C;CAEA,OACC,QASC;EACD,OAAOA,cAAAA,UAAU,MAAM,EACtB,cAAc,OACf,CAAC;CACF;;;;;;;;;;;;CAaA,UACC,YASC;EAQD,MAAM,WAAWC,4BAAAA,WAAW,UAAU;EAEtC,OAAOD,cAAAA,UAAU,MAAM;GACtB,WAAW,CAAC,GAAG,KAAK,WAAW,GAAG,QAAQ;GAC1C,aAAaE,4BAAAA,MAAM,YAAY,KAAK,WAAW;EAChD,CAAC;CASF;CAEA,SACC,UASC;EACD,OAAOF,cAAAA,UAAU,MAAM,EACtB,WAAW,CAAC,GAAG,KAAK,WAAW,GAAG,QAAQ,EAC3C,CAAC;CACF;CAEA,OACC,QASC;EACD,OAAOA,cAAAA,UAAU,MAAM,EAAE,SAAS,OAA6B,CAAC;CACjE;;;;;;;;CASA,SACC,QASC;EACD,OAAOA,cAAAA,UAAU,MAAM;GACtB,kBAAkBG,4BAAAA,UAAU,MAAM;GAClC,GAAGC,4BAAAA,cACF;IACC,YAAY,KAAK;IACjB,MAAM,KAAK;IACX,SAAS,KAAK;IACd,UAAU,KAAK;GAChB,GACA,MACD;EACD,CAAC;CASF;CAEA,UAOC,OAWC;EACD,MAAM,cAAc,MAAM,QAAQ,KAAK,IAAI,QAAQ,CAAC,KAAK;EACzD,OAAOJ,cAAAA,UAAU,MAAM,EACtB,mBAAmB,CAAC,GAAG,KAAK,mBAAmB,GAAG,WAAW,EAC9D,CAAC;CACF;CAEA,OACC,IAgBC;EACD,MAAM,aAAa,IAAI,WACtB,IACA,KAAK,UACL,KAAK,mBACL,KAAK,cACL,KAAK,WACL,KAAK,SACL,KAAK,YACL,KAAK,aACL,KAAK,gBACN;EAIA,WAAW,QAAQ,KAAK;EAIxB,OAAO;CACR;AACD"}
|
|
1
|
+
{"version":3,"file":"SubscriberBuilder-D_owVoHo.cjs","names":["Construct","DEFAULT_LOGGER","DEFAULT_LOGGER","cloneWith","servicesOf","idsOf","serviceOf","databaseEdges"],"sources":["../src/subscribers/Subscriber.ts","../src/subscribers/SubscriberBuilder.ts"],"sourcesContent":["import type {\n\tEventPublisher,\n\tExtractPublisherMessage,\n} from '@geekmidas/events';\nimport type { Logger } from '@geekmidas/logger';\nimport { DEFAULT_LOGGER } from '@geekmidas/logger/console';\nimport type { InferStandardSchema } from '@geekmidas/schema';\nimport type { Service, ServiceRecord } from '@geekmidas/services';\nimport type { StandardSchemaV1 } from '@standard-schema/spec';\nimport { Construct, ConstructType } from '../Construct';\nimport type { DatabaseContext } from '../functions/Function';\n\n// Helper type to extract payload types for subscribed events\ntype ExtractEventPayloads<\n\tTPublisher extends EventPublisher<any> | undefined,\n\tTEventTypes extends any[],\n> = TPublisher extends EventPublisher<any>\n\t? Extract<ExtractPublisherMessage<TPublisher>, { type: TEventTypes[number] }>\n\t: never;\n\n/**\n * A runnable that consumes a topic. Its handler gets `db` when it has a\n * database: the worker's, declared once with `worker.database(db)`, or its own\n * with `.database(other)`.\n */\nexport class Subscriber<\n\tTServices extends Service[] = [],\n\tTLogger extends Logger = Logger,\n\tOutSchema extends StandardSchemaV1 | undefined = undefined,\n\t/** The topic's message union — what types the events this subscriber receives. */\n\tTEventPublisher extends EventPublisher<any> | undefined = undefined,\n\tTSubscribedEvents extends\n\t\tExtractPublisherMessage<TEventPublisher>['type'][] = ExtractPublisherMessage<TEventPublisher>['type'][],\n\tTDatabase = undefined,\n\tTDatabaseServiceName extends string = string,\n> extends Construct<\n\tTLogger,\n\tOutSchema,\n\tTServices,\n\tstring,\n\tundefined,\n\tTDatabaseServiceName,\n\tTDatabase\n> {\n\t__IS_SUBSCRIBER__ = true;\n\n\tstatic isSubscriber(\n\t\tobj: any,\n\t): obj is Subscriber<any, any, any, any, any, any> {\n\t\treturn Boolean(\n\t\t\tobj &&\n\t\t\t\tobj.__IS_SUBSCRIBER__ === true &&\n\t\t\t\tobj.type === ConstructType.Subscriber,\n\t\t);\n\t}\n\n\tconstructor(\n\t\tpublic readonly handler: SubscriberHandler<\n\t\t\tTEventPublisher,\n\t\t\tTSubscribedEvents,\n\t\t\tTServices,\n\t\t\tTLogger,\n\t\t\tOutSchema,\n\t\t\tTDatabase\n\t\t>,\n\t\tpublic override readonly timeout: number = 30000,\n\t\tprotected _subscribedEvents?: TSubscribedEvents,\n\t\tpublic override readonly outputSchema?: OutSchema,\n\t\tpublic override readonly services: TServices = [] as unknown as TServices,\n\t\tpublic override readonly logger: TLogger = DEFAULT_LOGGER as TLogger,\n\t\t/**\n\t\t * The name of the {@link Topic} this subscriber binds to (via\n\t\t * `worker.topic(topic)`), recorded for the manifest so infra wires the\n\t\t * SNS subscription.\n\t\t */\n\t\tpublic readonly topicName?: string,\n\t\t/**\n\t\t * The construct ids `.dependsOn()` named — last, so no existing positional\n\t\t * argument moves.\n\t\t */\n\t\tconstructs: string[] = [],\n\t\t/**\n\t\t * What the handler's `db` is registered from — after `constructs`, for\n\t\t * the same reason.\n\t\t */\n\t\tdatabaseService?: Service<TDatabaseServiceName, TDatabase>,\n\t) {\n\t\tsuper(\n\t\t\tConstructType.Subscriber,\n\t\t\tlogger,\n\t\t\tservices,\n\t\t\t[],\n\t\t\toutputSchema,\n\t\t\ttimeout,\n\t\t\tundefined, // memorySize\n\t\t\tundefined, // auditorStorageService\n\t\t\tconstructs,\n\t\t);\n\n\t\tthis.databaseService = databaseService;\n\t}\n\n\tget subscribedEvents(): TSubscribedEvents | undefined {\n\t\treturn this._subscribedEvents;\n\t}\n}\n\n// Handler type for subscribers that receives an array of events\nexport type SubscriberHandler<\n\tTEventPublisher extends EventPublisher<any> | undefined,\n\tTSubscribedEvents extends ExtractPublisherMessage<TEventPublisher>['type'][],\n\tTServices extends Service[] = [],\n\tTLogger extends Logger = Logger,\n\tOutSchema extends StandardSchemaV1 | undefined = undefined,\n\tTDatabase = undefined,\n> = (\n\tctx: SubscriberContext<\n\t\tTEventPublisher,\n\t\tTSubscribedEvents,\n\t\tTServices,\n\t\tTLogger,\n\t\tTDatabase\n\t>,\n) => OutSchema extends StandardSchemaV1\n\t? InferStandardSchema<OutSchema> | Promise<InferStandardSchema<OutSchema>>\n\t: any | Promise<any>;\n\n// Context type for subscriber handlers — `db` only when a database is set.\nexport type SubscriberContext<\n\tTEventPublisher extends EventPublisher<any> | undefined,\n\tTSubscribedEvents extends ExtractPublisherMessage<TEventPublisher>['type'][],\n\tTServices extends Service[] = [],\n\tTLogger extends Logger = Logger,\n\tTDatabase = undefined,\n> = {\n\tevents: ExtractEventPayloads<TEventPublisher, TSubscribedEvents>[];\n\tservices: ServiceRecord<TServices>;\n\tlogger: TLogger;\n} & DatabaseContext<TDatabase>;\n","import type {\n\tEventPublisher,\n\tExtractPublisherMessage,\n} from '@geekmidas/events';\nimport type { Logger } from '@geekmidas/logger';\nimport { DEFAULT_LOGGER } from '@geekmidas/logger/console';\nimport type { Service } from '@geekmidas/services';\nimport type { StandardSchemaV1 } from '@standard-schema/spec';\nimport { cloneWith } from '../clone';\nimport {\n\ttype Consumable,\n\tdatabaseEdges,\n\tidsOf,\n\ttype ServicesOf,\n\tserviceOf,\n\tservicesOf,\n} from '../construct-interface';\nimport type { Topic, TopicEvents, TopicMessage } from '../topic/Topic';\nimport { Subscriber, type SubscriberHandler } from './Subscriber';\n\nexport class SubscriberBuilder<\n\tTServices extends Service[] = [],\n\tTLogger extends Logger = Logger,\n\tOutSchema extends StandardSchemaV1 | undefined = undefined,\n\tTEventPublisher extends EventPublisher<any> | undefined = undefined,\n\tTSubscribedEvents extends any[] = [],\n\tTDatabase = undefined,\n\tTDatabaseServiceName extends string = string,\n> {\n\tprivate _subscribedEvents: TSubscribedEvents = [] as any;\n\tprivate _timeout?: number;\n\tprivate outputSchema?: OutSchema;\n\tprivate _services: TServices = [] as Service[] as TServices;\n\t/** The construct ids `.dependsOn()` named — what the manifest records. */\n\tpublic _constructs: string[] = [];\n\tprivate _logger: TLogger = DEFAULT_LOGGER;\n\t/**\n\t * The deploy unit that runs this, by construct id. Seeded by the factory a\n\t * `Worker` hands out, so a subscriber is not owned by its directory.\n\t */\n\tpublic _owner?: string;\n\tprivate _topicName?: string;\n\t/** What the handler's `db` comes from — the worker's, unless overridden. */\n\tprivate _databaseService?: Service<TDatabaseServiceName, TDatabase>;\n\t/** The edge `.database()` added, so the next one can replace it. */\n\tprivate _databaseEdge?: string;\n\n\tconstructor() {\n\t\tthis._timeout = 30000; // Default timeout\n\t}\n\n\t/**\n\t * Bind this subscriber to a {@link Topic}: the subscribable event types (and\n\t * their payloads) come from the topic's contract, and the binding is recorded\n\t * for the manifest, so infra wires the SNS subscription.\n\t *\n\t * A consumer does not publish, so binding a topic does *not* hand it the\n\t * topic's publisher connection string (least privilege). One that publishes\n\t * follow-up events depends on the topic it publishes to: `.dependsOn([orders])`.\n\t */\n\ttopic<TName extends string, TEvents extends TopicEvents>(\n\t\ttopic: Topic<TName, TEvents>,\n\t): SubscriberBuilder<\n\t\tTServices,\n\t\tTLogger,\n\t\tOutSchema,\n\t\tEventPublisher<TopicMessage<TEvents>>,\n\t\tTSubscribedEvents,\n\t\tTDatabase,\n\t\tTDatabaseServiceName\n\t> {\n\t\treturn cloneWith(this, {\n\t\t\t_topicName: topic.name,\n\t\t}) as unknown as SubscriberBuilder<\n\t\t\tTServices,\n\t\t\tTLogger,\n\t\t\tOutSchema,\n\t\t\tEventPublisher<TopicMessage<TEvents>>,\n\t\t\tTSubscribedEvents,\n\t\t\tTDatabase,\n\t\t\tTDatabaseServiceName\n\t\t>;\n\t}\n\n\ttimeout(timeout: number): this {\n\t\treturn cloneWith(this, { _timeout: timeout });\n\t}\n\n\toutput<T extends StandardSchemaV1>(\n\t\tschema: T,\n\t): SubscriberBuilder<\n\t\tTServices,\n\t\tTLogger,\n\t\tT,\n\t\tTEventPublisher,\n\t\tTSubscribedEvents,\n\t\tTDatabase,\n\t\tTDatabaseServiceName\n\t> {\n\t\treturn cloneWith(this, {\n\t\t\toutputSchema: schema as unknown as OutSchema,\n\t\t}) as any;\n\t}\n\n\t/**\n\t * Depend on constructs — a database, a bucket, a mail sender, a queue, a\n\t * topic.\n\t *\n\t * It records the edge and dissolves each construct's client into the\n\t * handler's service record under the construct's own id, so\n\t * `.dependsOn([uploads])` is what makes `services.uploads` exist and type.\n\t *\n\t * Constructs only. A `Service` does not match the shape, which is what keeps\n\t * env sniffing confined to `.services()` and the explicit lift.\n\t */\n\tdependsOn<const T extends readonly Consumable[]>(\n\t\tconstructs: T,\n\t): SubscriberBuilder<\n\t\t[...TServices, ...ServicesOf<T>],\n\t\tTLogger,\n\t\tOutSchema,\n\t\tTEventPublisher,\n\t\tTSubscribedEvents,\n\t\tTDatabase,\n\t\tTDatabaseServiceName\n\t> {\n\t\t// Both halves of the edge, from one call and one clone: the services the\n\t\t// handler runs with, and the ids the manifest records. Recording them\n\t\t// separately is what let them drift apart.\n\t\t//\n\t\t// `servicesOf` is the half that validates, so it runs first — recording\n\t\t// ids ahead of it left a caught `NotAConstruct` with `undefined` already\n\t\t// on a `string[]`.\n\t\tconst services = servicesOf(constructs) as unknown as Service[];\n\n\t\treturn cloneWith(this, {\n\t\t\t_services: [...this._services, ...services],\n\t\t\t_constructs: idsOf(constructs, this._constructs),\n\t\t}) as unknown as SubscriberBuilder<\n\t\t\t[...TServices, ...ServicesOf<T>],\n\t\t\tTLogger,\n\t\t\tOutSchema,\n\t\t\tTEventPublisher,\n\t\t\tTSubscribedEvents,\n\t\t\tTDatabase,\n\t\t\tTDatabaseServiceName\n\t\t>;\n\t}\n\n\tservices<T extends Service[]>(\n\t\tservices: T,\n\t): SubscriberBuilder<\n\t\t[...TServices, ...T],\n\t\tTLogger,\n\t\tOutSchema,\n\t\tTEventPublisher,\n\t\tTSubscribedEvents,\n\t\tTDatabase,\n\t\tTDatabaseServiceName\n\t> {\n\t\treturn cloneWith(this, {\n\t\t\t_services: [...this._services, ...services] as any,\n\t\t}) as any;\n\t}\n\n\tlogger<T extends Logger>(\n\t\tlogger: T,\n\t): SubscriberBuilder<\n\t\tTServices,\n\t\tT,\n\t\tOutSchema,\n\t\tTEventPublisher,\n\t\tTSubscribedEvents,\n\t\tTDatabase,\n\t\tTDatabaseServiceName\n\t> {\n\t\treturn cloneWith(this, { _logger: logger as unknown as TLogger }) as any;\n\t}\n\n\t/**\n\t * The database the handler receives as `db`.\n\t *\n\t * A subscriber built from a worker already has the worker's, when the\n\t * worker named one with `.database(db)`; this replaces it — the edge as well\n\t * as the client — for a consumer that works against a different database.\n\t */\n\tdatabase<T, TDbName extends string>(\n\t\tsource: Consumable<TDbName, T> | Service<TDbName, T>,\n\t): SubscriberBuilder<\n\t\tTServices,\n\t\tTLogger,\n\t\tOutSchema,\n\t\tTEventPublisher,\n\t\tTSubscribedEvents,\n\t\tT,\n\t\tTDbName\n\t> {\n\t\treturn cloneWith(this, {\n\t\t\t_databaseService: serviceOf(source),\n\t\t\t...databaseEdges(\n\t\t\t\t{\n\t\t\t\t\tconstructs: this._constructs,\n\t\t\t\t\tedge: this._databaseEdge,\n\t\t\t\t\tservice: this._databaseService as Service | undefined,\n\t\t\t\t\tservices: this._services,\n\t\t\t\t},\n\t\t\t\tsource,\n\t\t\t),\n\t\t}) as unknown as SubscriberBuilder<\n\t\t\tTServices,\n\t\t\tTLogger,\n\t\t\tOutSchema,\n\t\t\tTEventPublisher,\n\t\t\tTSubscribedEvents,\n\t\t\tT,\n\t\t\tTDbName\n\t\t>;\n\t}\n\n\tsubscribe<\n\t\tTEvent extends TEventPublisher extends EventPublisher<any>\n\t\t\t?\n\t\t\t\t\t| ExtractPublisherMessage<TEventPublisher>['type']\n\t\t\t\t\t| ExtractPublisherMessage<TEventPublisher>['type'][]\n\t\t\t: never,\n\t>(\n\t\tevent: TEvent,\n\t): SubscriberBuilder<\n\t\tTServices,\n\t\tTLogger,\n\t\tOutSchema,\n\t\tTEventPublisher,\n\t\tTEvent extends any[]\n\t\t\t? [...TSubscribedEvents, ...TEvent]\n\t\t\t: [...TSubscribedEvents, TEvent],\n\t\tTDatabase,\n\t\tTDatabaseServiceName\n\t> {\n\t\tconst eventsToAdd = Array.isArray(event) ? event : [event];\n\t\treturn cloneWith(this, {\n\t\t\t_subscribedEvents: [...this._subscribedEvents, ...eventsToAdd] as any,\n\t\t}) as any;\n\t}\n\n\thandle(\n\t\tfn: SubscriberHandler<\n\t\t\tTEventPublisher,\n\t\t\tTSubscribedEvents,\n\t\t\tTServices,\n\t\t\tTLogger,\n\t\t\tOutSchema,\n\t\t\tTDatabase\n\t\t>,\n\t): Subscriber<\n\t\tTServices,\n\t\tTLogger,\n\t\tOutSchema,\n\t\tTEventPublisher,\n\t\tTSubscribedEvents,\n\t\tTDatabase,\n\t\tTDatabaseServiceName\n\t> {\n\t\tconst subscriber = new Subscriber(\n\t\t\tfn,\n\t\t\tthis._timeout,\n\t\t\tthis._subscribedEvents,\n\t\t\tthis.outputSchema,\n\t\t\tthis._services,\n\t\t\tthis._logger,\n\t\t\tthis._topicName,\n\t\t\tthis._constructs,\n\t\t\tthis._databaseService,\n\t\t);\n\n\t\t// Which process runs it. Carried from the factory rather than inferred\n\t\t// from the directory the file happens to sit in.\n\t\tsubscriber.owner = this._owner;\n\n\t\t// No reset: `.handle()` reads this builder and leaves it alone, so a\n\t\t// configured base stays usable for the next subscriber.\n\t\treturn subscriber;\n\t}\n}\n"],"mappings":";;;;;;;;;;AAyBA,IAAa,aAAb,cAUUA,kBAAAA,UAQR;CAcgB;CAQS;CACf;CACe;CACA;CACA;CAMT;CA/BjB,oBAAoB;CAEpB,OAAO,aACN,KACkD;EAClD,OAAO,QACN,OACC,IAAI,sBAAsB,QAC1B,IAAI,SAAA,mCACN;CACD;CAEA,YACC,SAQA,UAA2C,KAC3C,mBACA,cACA,WAA+C,CAAC,GAChD,SAA2CC,0BAAAA,gBAM3C,WAKA,aAAuB,CAAC,GAKxB,iBACC;EACD,MAAA,qCAEC,QACA,UACA,CAAC,GACD,cACA,SACA,KAAA,GACA,KAAA,GACA,UACD;EAxCgB,KAAA,UAAA;EAQS,KAAA,UAAA;EACf,KAAA,oBAAA;EACe,KAAA,eAAA;EACA,KAAA,WAAA;EACA,KAAA,SAAA;EAMT,KAAA,YAAA;EAwBhB,KAAK,kBAAkB;CACxB;CAEA,IAAI,mBAAkD;EACrD,OAAO,KAAK;CACb;AACD;;;ACrFA,IAAa,oBAAb,MAQE;CACD,oBAA+C,CAAC;CAChD;CACA;CACA,YAA+B,CAAC;;CAEhC,cAA+B,CAAC;CAChC,UAA2BC,0BAAAA;;;;;CAK3B;CACA;;CAEA;;CAEA;CAEA,cAAc;EACb,KAAK,WAAW;CACjB;;;;;;;;;;CAWA,MACC,OASC;EACD,OAAOC,cAAAA,UAAU,MAAM,EACtB,YAAY,MAAM,KACnB,CAAC;CASF;CAEA,QAAQ,SAAuB;EAC9B,OAAOA,cAAAA,UAAU,MAAM,EAAE,UAAU,QAAQ,CAAC;CAC7C;CAEA,OACC,QASC;EACD,OAAOA,cAAAA,UAAU,MAAM,EACtB,cAAc,OACf,CAAC;CACF;;;;;;;;;;;;CAaA,UACC,YASC;EAQD,MAAM,WAAWC,4BAAAA,WAAW,UAAU;EAEtC,OAAOD,cAAAA,UAAU,MAAM;GACtB,WAAW,CAAC,GAAG,KAAK,WAAW,GAAG,QAAQ;GAC1C,aAAaE,4BAAAA,MAAM,YAAY,KAAK,WAAW;EAChD,CAAC;CASF;CAEA,SACC,UASC;EACD,OAAOF,cAAAA,UAAU,MAAM,EACtB,WAAW,CAAC,GAAG,KAAK,WAAW,GAAG,QAAQ,EAC3C,CAAC;CACF;CAEA,OACC,QASC;EACD,OAAOA,cAAAA,UAAU,MAAM,EAAE,SAAS,OAA6B,CAAC;CACjE;;;;;;;;CASA,SACC,QASC;EACD,OAAOA,cAAAA,UAAU,MAAM;GACtB,kBAAkBG,4BAAAA,UAAU,MAAM;GAClC,GAAGC,4BAAAA,cACF;IACC,YAAY,KAAK;IACjB,MAAM,KAAK;IACX,SAAS,KAAK;IACd,UAAU,KAAK;GAChB,GACA,MACD;EACD,CAAC;CASF;CAEA,UAOC,OAWC;EACD,MAAM,cAAc,MAAM,QAAQ,KAAK,IAAI,QAAQ,CAAC,KAAK;EACzD,OAAOJ,cAAAA,UAAU,MAAM,EACtB,mBAAmB,CAAC,GAAG,KAAK,mBAAmB,GAAG,WAAW,EAC9D,CAAC;CACF;CAEA,OACC,IAgBC;EACD,MAAM,aAAa,IAAI,WACtB,IACA,KAAK,UACL,KAAK,mBACL,KAAK,cACL,KAAK,WACL,KAAK,SACL,KAAK,YACL,KAAK,aACL,KAAK,gBACN;EAIA,WAAW,QAAQ,KAAK;EAIxB,OAAO;CACR;AACD"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const require_Construct = require("./Construct-
|
|
1
|
+
const require_Construct = require("./Construct-DUSXuTHP.cjs");
|
|
2
2
|
let _geekmidas_manifest = require("@geekmidas/manifest");
|
|
3
3
|
let _geekmidas_logger_console = require("@geekmidas/logger/console");
|
|
4
4
|
let _geekmidas_events = require("@geekmidas/events");
|
|
@@ -101,4 +101,4 @@ Object.defineProperty(exports, "Topic", {
|
|
|
101
101
|
}
|
|
102
102
|
});
|
|
103
103
|
|
|
104
|
-
//# sourceMappingURL=Topic-
|
|
104
|
+
//# sourceMappingURL=Topic-BliAKi5r.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Topic-
|
|
1
|
+
{"version":3,"file":"Topic-BliAKi5r.cjs","names":["Construct","DEFAULT_LOGGER","canonicalId","provideKey","serviceKey","Publisher"],"sources":["../src/topic/Topic.ts"],"sourcesContent":["import {\n\ttype EventPublisher,\n\ttype EventPublisherConnectionString,\n\ttype PublishableMessage,\n\tPublisher,\n} from '@geekmidas/events';\nimport { DEFAULT_LOGGER } from '@geekmidas/logger/console';\nimport {\n\ttype ConstructName,\n\tcanonicalId,\n\ttype Declaration,\n\tprovideKey,\n\tserviceKey,\n} from '@geekmidas/manifest';\nimport type { InferStandardSchema } from '@geekmidas/schema';\nimport type { Service } from '@geekmidas/services';\nimport type { StandardSchemaV1 } from '@standard-schema/spec';\nimport { Construct, ConstructType } from '../Construct';\n\n/** A topic's event contract — a map of event type → payload schema. */\nexport type TopicEvents = Record<string, StandardSchemaV1>;\n\n/**\n * The union of wire messages a topic carries, derived from its event map:\n * `{ type: 'user.created'; payload: … } | { type: 'user.updated'; payload: … }`.\n */\nexport type TopicMessage<TEvents extends TopicEvents> = {\n\t[K in keyof TEvents & string]: PublishableMessage<\n\t\tK,\n\t\tInferStandardSchema<TEvents[K]>\n\t>;\n}[keyof TEvents & string];\n\n/**\n * A topic — pub/sub fan-out. Unlike a `Queue` (point-to-point, one consumer), a\n * topic is a *resource* owned by no single handler: it declares the event\n * contract, and any number of subscribers (`worker.topic(topic)`) bind to it.\n * `gkm build` discovers it into the manifest's `topics` field; infra provisions\n * an SNS topic.\n *\n * A construct publishes with `.event(topic, { type, payload })`, repeatable\n * across topics, each event going through its own topic's publisher. That also\n * puts `services.<topic>` in the handler, as `.dependsOn([topic])` does, for an\n * event the handler decides on itself.\n *\n * ```ts\n * export const users = new Topic('Users', {\n * events: { 'user.created': z.object({ userId: z.string() }) },\n * });\n * ```\n */\nexport class Topic<\n\tTName extends string = string,\n\tTEvents extends TopicEvents = TopicEvents,\n> extends Construct {\n\t__IS_TOPIC__ = true;\n\n\tstatic isTopic(obj: unknown): obj is Topic<string, TopicEvents> {\n\t\treturn Boolean(\n\t\t\tobj &&\n\t\t\t\t(obj as { __IS_TOPIC__?: boolean }).__IS_TOPIC__ === true &&\n\t\t\t\t(obj as Construct).type === ConstructType.Topic,\n\t\t);\n\t}\n\n\t/**\n\t * The canonical id this topic is declared under.\n\t *\n\t * Derived from the name, so `users` and `Users` are one topic. The name is\n\t * left alone: subscribers bind to it and it is what the broker routes on.\n\t */\n\treadonly id: string;\n\n\t/** The name it was declared with — what the broker routes on. */\n\treadonly name: TName;\n\n\t/**\n\t * The event contract — a map of event type → payload schema. Named\n\t * `eventSchemas` (not `events`) to avoid clashing with `Construct.events`,\n\t * which is the array of `MappedEvent`s a construct *publishes*.\n\t */\n\treadonly eventSchemas: TEvents;\n\n\t/**\n\t * The topic as a dependency — what `.dependsOn([users])` and\n\t * `.event(users, …)` dissolve into, reachable as `services.users`.\n\t *\n\t * The producer, because publishing is the only thing depending on a topic\n\t * can mean: a subscriber binds to the topic instead, and is never handed\n\t * this. It reads `<NAME>_PUBLISHER_CONNECTION_STRING` and picks the\n\t * transport from its protocol — `pgboss://` locally, `sns://` deployed.\n\t *\n\t * A field assigned once, not a getter: services are cached by object\n\t * identity, and a fresh literal on every access never hit that cache.\n\t */\n\treadonly service: Service<\n\t\tUncapitalize<TName>,\n\t\tEventPublisher<TopicMessage<TEvents>>\n\t>;\n\n\t/** The producer's env key, read by both {@link declare} and the service. */\n\tprivate readonly connectionKey: string;\n\n\tconstructor(name: ConstructName<TName>, options: TopicOptions<TEvents>) {\n\t\tsuper(ConstructType.Topic, DEFAULT_LOGGER, [], []);\n\n\t\tthis.name = name as TName;\n\t\tthis.id = canonicalId(name as string);\n\t\tthis.eventSchemas = options.events;\n\t\tthis.connectionKey = provideKey(this.id, 'publisherConnectionString');\n\n\t\tconst envVar = this.connectionKey;\n\t\tconst topic = this.name as string;\n\t\tthis.service = {\n\t\t\tserviceName: serviceKey(this.id) as Uncapitalize<TName>,\n\t\t\tasync register({ envParser }) {\n\t\t\t\tconst { connectionString } = envParser\n\t\t\t\t\t.create((get) => ({ connectionString: get(envVar).string() }))\n\t\t\t\t\t.parse();\n\n\t\t\t\t// Named as a topic, so a broker with one address for everything\n\t\t\t\t// (pg-boss) fans each message out to every subscriber.\n\t\t\t\treturn Publisher.fromConnectionString<TopicMessage<TEvents>>(\n\t\t\t\t\tconnectionString as EventPublisherConnectionString,\n\t\t\t\t\t{ topic },\n\t\t\t\t);\n\t\t\t},\n\t\t};\n\t}\n\n\t/**\n\t * What this topic is in the manifest.\n\t *\n\t * Only the producer's key: a subscriber is *bound* to a topic rather than\n\t * depending on it, so the binding is an edge the deploy target reads and not\n\t * an env key anyone can hold. Locally both sides meet on the same broker.\n\t */\n\tdeclare(): Declaration[] {\n\t\treturn [\n\t\t\t{\n\t\t\t\tkind: 'topic',\n\t\t\t\tid: this.id,\n\t\t\t\tprovides: [this.connectionKey],\n\t\t\t\t// The contract this topic carries. Structural: which events exist\n\t\t\t\t// is a fact about the application, and a subscriber binding to one\n\t\t\t\t// that does not is a mistake worth catching at build.\n\t\t\t\tevents: this.eventTypes,\n\t\t\t\t// Bound rather than declared here — a subscriber names the topic,\n\t\t\t\t// not the other way round — so the build fills these from what it\n\t\t\t\t// found. Nested when it does, because position is the trigger.\n\t\t\t\tsubscribers: [],\n\t\t\t},\n\t\t];\n\t}\n\n\t/** The event type names this topic carries. */\n\tget eventTypes(): (keyof TEvents & string)[] {\n\t\treturn Object.keys(this.eventSchemas) as (keyof TEvents & string)[];\n\t}\n}\n\nexport interface TopicOptions<TEvents extends TopicEvents> {\n\t/** Each event this topic carries — its type, and its payload's schema. */\n\tevents: TEvents;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAmDA,IAAa,QAAb,cAGUA,kBAAAA,UAAU;CACnB,eAAe;CAEf,OAAO,QAAQ,KAAiD;EAC/D,OAAO,QACN,OACE,IAAmC,iBAAiB,QACpD,IAAkB,SAAA,8BACrB;CACD;;;;;;;CAQA;;CAGA;;;;;;CAOA;;;;;;;;;;;;;CAcA;;CAMA;CAEA,YAAY,MAA4B,SAAgC;EACvE,MAAA,gCAA2BC,0BAAAA,gBAAgB,CAAC,GAAG,CAAC,CAAC;EAEjD,KAAK,OAAO;EACZ,KAAK,MAAA,GAAKC,oBAAAA,YAAAA,CAAY,IAAc;EACpC,KAAK,eAAe,QAAQ;EAC5B,KAAK,iBAAA,GAAgBC,oBAAAA,WAAAA,CAAW,KAAK,IAAI,2BAA2B;EAEpE,MAAM,SAAS,KAAK;EACpB,MAAM,QAAQ,KAAK;EACnB,KAAK,UAAU;GACd,cAAA,GAAaC,oBAAAA,WAAAA,CAAW,KAAK,EAAE;GAC/B,MAAM,SAAS,EAAE,aAAa;IAC7B,MAAM,EAAE,qBAAqB,UAC3B,QAAQ,SAAS,EAAE,kBAAkB,IAAI,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAC7D,MAAM;IAIR,OAAOC,kBAAAA,UAAU,qBAChB,kBACA,EAAE,MAAM,CACT;GACD;EACD;CACD;;;;;;;;CASA,UAAyB;EACxB,OAAO,CACN;GACC,MAAM;GACN,IAAI,KAAK;GACT,UAAU,CAAC,KAAK,aAAa;GAI7B,QAAQ,KAAK;GAIb,aAAa,CAAC;EACf,CACD;CACD;;CAGA,IAAI,aAAyC;EAC5C,OAAO,OAAO,KAAK,KAAK,YAAY;CACrC;AACD"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { t as Construct } from "./Construct-
|
|
1
|
+
import { t as Construct } from "./Construct-B1vGBPme.mjs";
|
|
2
2
|
import { canonicalId, provideKey, serviceKey } from "@geekmidas/manifest";
|
|
3
3
|
import { DEFAULT_LOGGER } from "@geekmidas/logger/console";
|
|
4
4
|
import { Publisher } from "@geekmidas/events";
|
|
@@ -96,4 +96,4 @@ var Topic = class extends Construct {
|
|
|
96
96
|
//#endregion
|
|
97
97
|
export { Topic as t };
|
|
98
98
|
|
|
99
|
-
//# sourceMappingURL=Topic-
|
|
99
|
+
//# sourceMappingURL=Topic-DCxIstf9.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Topic-
|
|
1
|
+
{"version":3,"file":"Topic-DCxIstf9.mjs","names":[],"sources":["../src/topic/Topic.ts"],"sourcesContent":["import {\n\ttype EventPublisher,\n\ttype EventPublisherConnectionString,\n\ttype PublishableMessage,\n\tPublisher,\n} from '@geekmidas/events';\nimport { DEFAULT_LOGGER } from '@geekmidas/logger/console';\nimport {\n\ttype ConstructName,\n\tcanonicalId,\n\ttype Declaration,\n\tprovideKey,\n\tserviceKey,\n} from '@geekmidas/manifest';\nimport type { InferStandardSchema } from '@geekmidas/schema';\nimport type { Service } from '@geekmidas/services';\nimport type { StandardSchemaV1 } from '@standard-schema/spec';\nimport { Construct, ConstructType } from '../Construct';\n\n/** A topic's event contract — a map of event type → payload schema. */\nexport type TopicEvents = Record<string, StandardSchemaV1>;\n\n/**\n * The union of wire messages a topic carries, derived from its event map:\n * `{ type: 'user.created'; payload: … } | { type: 'user.updated'; payload: … }`.\n */\nexport type TopicMessage<TEvents extends TopicEvents> = {\n\t[K in keyof TEvents & string]: PublishableMessage<\n\t\tK,\n\t\tInferStandardSchema<TEvents[K]>\n\t>;\n}[keyof TEvents & string];\n\n/**\n * A topic — pub/sub fan-out. Unlike a `Queue` (point-to-point, one consumer), a\n * topic is a *resource* owned by no single handler: it declares the event\n * contract, and any number of subscribers (`worker.topic(topic)`) bind to it.\n * `gkm build` discovers it into the manifest's `topics` field; infra provisions\n * an SNS topic.\n *\n * A construct publishes with `.event(topic, { type, payload })`, repeatable\n * across topics, each event going through its own topic's publisher. That also\n * puts `services.<topic>` in the handler, as `.dependsOn([topic])` does, for an\n * event the handler decides on itself.\n *\n * ```ts\n * export const users = new Topic('Users', {\n * events: { 'user.created': z.object({ userId: z.string() }) },\n * });\n * ```\n */\nexport class Topic<\n\tTName extends string = string,\n\tTEvents extends TopicEvents = TopicEvents,\n> extends Construct {\n\t__IS_TOPIC__ = true;\n\n\tstatic isTopic(obj: unknown): obj is Topic<string, TopicEvents> {\n\t\treturn Boolean(\n\t\t\tobj &&\n\t\t\t\t(obj as { __IS_TOPIC__?: boolean }).__IS_TOPIC__ === true &&\n\t\t\t\t(obj as Construct).type === ConstructType.Topic,\n\t\t);\n\t}\n\n\t/**\n\t * The canonical id this topic is declared under.\n\t *\n\t * Derived from the name, so `users` and `Users` are one topic. The name is\n\t * left alone: subscribers bind to it and it is what the broker routes on.\n\t */\n\treadonly id: string;\n\n\t/** The name it was declared with — what the broker routes on. */\n\treadonly name: TName;\n\n\t/**\n\t * The event contract — a map of event type → payload schema. Named\n\t * `eventSchemas` (not `events`) to avoid clashing with `Construct.events`,\n\t * which is the array of `MappedEvent`s a construct *publishes*.\n\t */\n\treadonly eventSchemas: TEvents;\n\n\t/**\n\t * The topic as a dependency — what `.dependsOn([users])` and\n\t * `.event(users, …)` dissolve into, reachable as `services.users`.\n\t *\n\t * The producer, because publishing is the only thing depending on a topic\n\t * can mean: a subscriber binds to the topic instead, and is never handed\n\t * this. It reads `<NAME>_PUBLISHER_CONNECTION_STRING` and picks the\n\t * transport from its protocol — `pgboss://` locally, `sns://` deployed.\n\t *\n\t * A field assigned once, not a getter: services are cached by object\n\t * identity, and a fresh literal on every access never hit that cache.\n\t */\n\treadonly service: Service<\n\t\tUncapitalize<TName>,\n\t\tEventPublisher<TopicMessage<TEvents>>\n\t>;\n\n\t/** The producer's env key, read by both {@link declare} and the service. */\n\tprivate readonly connectionKey: string;\n\n\tconstructor(name: ConstructName<TName>, options: TopicOptions<TEvents>) {\n\t\tsuper(ConstructType.Topic, DEFAULT_LOGGER, [], []);\n\n\t\tthis.name = name as TName;\n\t\tthis.id = canonicalId(name as string);\n\t\tthis.eventSchemas = options.events;\n\t\tthis.connectionKey = provideKey(this.id, 'publisherConnectionString');\n\n\t\tconst envVar = this.connectionKey;\n\t\tconst topic = this.name as string;\n\t\tthis.service = {\n\t\t\tserviceName: serviceKey(this.id) as Uncapitalize<TName>,\n\t\t\tasync register({ envParser }) {\n\t\t\t\tconst { connectionString } = envParser\n\t\t\t\t\t.create((get) => ({ connectionString: get(envVar).string() }))\n\t\t\t\t\t.parse();\n\n\t\t\t\t// Named as a topic, so a broker with one address for everything\n\t\t\t\t// (pg-boss) fans each message out to every subscriber.\n\t\t\t\treturn Publisher.fromConnectionString<TopicMessage<TEvents>>(\n\t\t\t\t\tconnectionString as EventPublisherConnectionString,\n\t\t\t\t\t{ topic },\n\t\t\t\t);\n\t\t\t},\n\t\t};\n\t}\n\n\t/**\n\t * What this topic is in the manifest.\n\t *\n\t * Only the producer's key: a subscriber is *bound* to a topic rather than\n\t * depending on it, so the binding is an edge the deploy target reads and not\n\t * an env key anyone can hold. Locally both sides meet on the same broker.\n\t */\n\tdeclare(): Declaration[] {\n\t\treturn [\n\t\t\t{\n\t\t\t\tkind: 'topic',\n\t\t\t\tid: this.id,\n\t\t\t\tprovides: [this.connectionKey],\n\t\t\t\t// The contract this topic carries. Structural: which events exist\n\t\t\t\t// is a fact about the application, and a subscriber binding to one\n\t\t\t\t// that does not is a mistake worth catching at build.\n\t\t\t\tevents: this.eventTypes,\n\t\t\t\t// Bound rather than declared here — a subscriber names the topic,\n\t\t\t\t// not the other way round — so the build fills these from what it\n\t\t\t\t// found. Nested when it does, because position is the trigger.\n\t\t\t\tsubscribers: [],\n\t\t\t},\n\t\t];\n\t}\n\n\t/** The event type names this topic carries. */\n\tget eventTypes(): (keyof TEvents & string)[] {\n\t\treturn Object.keys(this.eventSchemas) as (keyof TEvents & string)[];\n\t}\n}\n\nexport interface TopicOptions<TEvents extends TopicEvents> {\n\t/** Each event this topic carries — its type, and its payload's schema. */\n\tevents: TEvents;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAmDA,IAAa,QAAb,cAGU,UAAU;CACnB,eAAe;CAEf,OAAO,QAAQ,KAAiD;EAC/D,OAAO,QACN,OACE,IAAmC,iBAAiB,QACpD,IAAkB,SAAA,8BACrB;CACD;;;;;;;CAQA;;CAGA;;;;;;CAOA;;;;;;;;;;;;;CAcA;;CAMA;CAEA,YAAY,MAA4B,SAAgC;EACvE,MAAA,gCAA2B,gBAAgB,CAAC,GAAG,CAAC,CAAC;EAEjD,KAAK,OAAO;EACZ,KAAK,KAAK,YAAY,IAAc;EACpC,KAAK,eAAe,QAAQ;EAC5B,KAAK,gBAAgB,WAAW,KAAK,IAAI,2BAA2B;EAEpE,MAAM,SAAS,KAAK;EACpB,MAAM,QAAQ,KAAK;EACnB,KAAK,UAAU;GACd,aAAa,WAAW,KAAK,EAAE;GAC/B,MAAM,SAAS,EAAE,aAAa;IAC7B,MAAM,EAAE,qBAAqB,UAC3B,QAAQ,SAAS,EAAE,kBAAkB,IAAI,MAAM,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAC7D,MAAM;IAIR,OAAO,UAAU,qBAChB,kBACA,EAAE,MAAM,CACT;GACD;EACD;CACD;;;;;;;;CASA,UAAyB;EACxB,OAAO,CACN;GACC,MAAM;GACN,IAAI,KAAK;GACT,UAAU,CAAC,KAAK,aAAa;GAI7B,QAAQ,KAAK;GAIb,aAAa,CAAC;EACf,CACD;CACD;;CAGA,IAAI,aAAyC;EAC5C,OAAO,OAAO,KAAK,KAAK,YAAY;CACrC;AACD"}
|
package/dist/adaptors/aws.cjs
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
2
|
const require_rolldown_runtime = require("../rolldown-runtime-y5ARvAq5.cjs");
|
|
3
|
-
const require_functions = require("../functions-
|
|
4
|
-
const require_Endpoint = require("../Endpoint-
|
|
3
|
+
const require_functions = require("../functions-CfzJG9hK.cjs");
|
|
4
|
+
const require_Endpoint = require("../Endpoint-Ba1PiyuJ.cjs");
|
|
5
5
|
const require_surfaceEnv = require("../surfaceEnv-CNimK76p.cjs");
|
|
6
6
|
const require_lazyAccessors = require("../lazyAccessors-hJKGv8Ay.cjs");
|
|
7
|
-
const require_runSubscriber = require("../runSubscriber-
|
|
8
|
-
const require_processAudits = require("../processAudits-
|
|
7
|
+
const require_runSubscriber = require("../runSubscriber-D8nLXIv1.cjs");
|
|
8
|
+
const require_processAudits = require("../processAudits-DasOZjPl.cjs");
|
|
9
9
|
let _geekmidas_errors = require("@geekmidas/errors");
|
|
10
10
|
let _geekmidas_services = require("@geekmidas/services");
|
|
11
|
-
let _geekmidas_db_rls = require("@geekmidas/db/rls");
|
|
12
11
|
let qs = require("qs");
|
|
13
12
|
qs = require_rolldown_runtime.__toESM(qs, 1);
|
|
14
|
-
let _geekmidas_audit = require("@geekmidas/audit");
|
|
15
13
|
let _middy_core = require("@middy/core");
|
|
16
14
|
_middy_core = require_rolldown_runtime.__toESM(_middy_core, 1);
|
|
15
|
+
let _geekmidas_audit = require("@geekmidas/audit");
|
|
17
16
|
let _geekmidas_audit_kysely = require("@geekmidas/audit/kysely");
|
|
17
|
+
let _geekmidas_db_rls = require("@geekmidas/db/rls");
|
|
18
18
|
//#region src/functions/FunctionExecutionWrapper.ts
|
|
19
19
|
var FunctionExecutionWrapper = class {
|
|
20
20
|
envParser;
|
|
@@ -125,7 +125,7 @@ var AWSLambdaFunction = class extends FunctionExecutionWrapper {
|
|
|
125
125
|
} else req.event.parsedInput = req.event;
|
|
126
126
|
} catch (error) {
|
|
127
127
|
this.logger.error({
|
|
128
|
-
error,
|
|
128
|
+
err: error,
|
|
129
129
|
event: req.event
|
|
130
130
|
}, "Failed to parse input");
|
|
131
131
|
throw error;
|
|
@@ -677,7 +677,7 @@ var AWSLambdaQueue = class {
|
|
|
677
677
|
messages.push(validation.value);
|
|
678
678
|
} catch (error) {
|
|
679
679
|
logger.error({
|
|
680
|
-
error,
|
|
680
|
+
err: error,
|
|
681
681
|
messageId: record.messageId
|
|
682
682
|
}, "Failed to parse SQS record");
|
|
683
683
|
batchItemFailures.push({ itemIdentifier: record.messageId });
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"aws.cjs","names":["ServiceDiscovery","DefaultAuditor","withAuditableTransaction","FunctionBuilder","publishEvents","wrapError","FunctionBuilder","middy","runWithRequestContext","envParserFor","wrapError","Endpoint","UnprocessableEntityError","ServiceDiscovery","ForbiddenError","publishConstructEvents","createAuditContext","executeWithAuditTransaction","ResponseBuilder","withRlsContext","middy","runWithRequestContext","createApiGatewayCookies","ServiceDiscovery","wrapError","runWithRequestContext","wrapError","subscriberContext","subscribedEvents","runSubscriber","middy","runWithRequestContext"],"sources":["../../src/functions/FunctionExecutionWrapper.ts","../../src/functions/AWSLambdaFunction.ts","../../src/crons/AWSScheduledFunction.ts","../../src/endpoints/AmazonApiGatewayEndpointAdaptor.ts","../../src/endpoints/parseQueryParams.ts","../../src/endpoints/AmazonApiGatewayV1EndpointAdaptor.ts","../../src/endpoints/AmazonApiGatewayV2EndpointAdaptor.ts","../../src/queue/AWSLambdaQueueAdaptor.ts","../../src/subscribers/AWSLambdaSubscriberAdaptor.ts"],"sourcesContent":["import type { AuditableAction, Auditor, AuditStorage } from '@geekmidas/audit';\nimport { DefaultAuditor } from '@geekmidas/audit';\nimport { withAuditableTransaction } from '@geekmidas/audit/kysely';\nimport type { EnvironmentParser } from '@geekmidas/envkit';\nimport type { EventPublisher } from '@geekmidas/events';\nimport type { Logger } from '@geekmidas/logger';\nimport type {\n\tComposableStandardSchema,\n\tInferComposableStandardSchema,\n\tInferStandardSchema,\n} from '@geekmidas/schema';\nimport {\n\ttype Service,\n\tServiceDiscovery,\n\ttype ServiceRecord,\n} from '@geekmidas/services';\nimport type { StandardSchemaV1 } from '@standard-schema/spec';\nimport { publishEvents } from '../publisher';\nimport type { Function, FunctionHandler } from './Function';\nimport { FunctionBuilder } from './FunctionBuilder';\n\nexport abstract class FunctionExecutionWrapper<\n\tTInput extends ComposableStandardSchema | undefined = undefined,\n\tTOutSchema extends StandardSchemaV1 | undefined = undefined,\n\tTServices extends Service[] = [],\n\tTLogger extends Logger = Logger,\n\tTAuditStorage extends AuditStorage | undefined = undefined,\n\tTAuditStorageServiceName extends string = string,\n\tTDatabase = undefined,\n\tTDatabaseServiceName extends string = string,\n\tTAuditAction extends AuditableAction<string, unknown> = AuditableAction<\n\t\tstring,\n\t\tunknown\n\t>,\n> {\n\tconstructor(\n\t\tprotected envParser: EnvironmentParser<{}>,\n\t\tprotected readonly fn: Function<\n\t\t\tTInput,\n\t\t\tTServices,\n\t\t\tTLogger,\n\t\t\tTOutSchema,\n\t\t\tTAuditStorage,\n\t\t\tTAuditStorageServiceName,\n\t\t\tTDatabase,\n\t\t\tTDatabaseServiceName,\n\t\t\tTAuditAction,\n\t\t\tFunctionHandler<\n\t\t\t\tTInput,\n\t\t\t\tTServices,\n\t\t\t\tTLogger,\n\t\t\t\tTOutSchema,\n\t\t\t\tTDatabase,\n\t\t\t\tTAuditStorage,\n\t\t\t\tTAuditAction\n\t\t\t>\n\t\t>,\n\t) {}\n\n\tprotected _logger?: TLogger;\n\n\tget logger(): TLogger {\n\t\treturn this._logger || this.fn.logger;\n\t}\n\n\tget serviceDiscovery(): ServiceDiscovery<ServiceRecord<TServices>> {\n\t\tconst serviceDiscovery = ServiceDiscovery.getInstance<\n\t\t\tServiceRecord<TServices>\n\t\t>(this.envParser);\n\n\t\treturn serviceDiscovery;\n\t}\n\n\tgetServices(): Promise<ServiceRecord<TServices>> {\n\t\treturn this.serviceDiscovery.register(this.fn.services);\n\t}\n\n\tasync getDatabase(): Promise<TDatabase | undefined> {\n\t\tif (!this.fn.databaseService) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst services = await this.serviceDiscovery.register([\n\t\t\tthis.fn.databaseService,\n\t\t]);\n\n\t\treturn services[\n\t\t\tthis.fn.databaseService.serviceName as keyof typeof services\n\t\t] as TDatabase;\n\t}\n\n\t/**\n\t * Get the audit storage service if configured.\n\t * Returns undefined if no auditor storage is configured.\n\t */\n\tasync getAuditStorage(): Promise<TAuditStorage | undefined> {\n\t\tif (!this.fn.auditorStorageService) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst services = await this.serviceDiscovery.register([\n\t\t\tthis.fn.auditorStorageService,\n\t\t]);\n\n\t\treturn services[\n\t\t\tthis.fn.auditorStorageService.serviceName as keyof typeof services\n\t\t] as TAuditStorage;\n\t}\n\n\t/**\n\t * Create an auditor instance for the function.\n\t * Returns undefined if no auditor storage is configured.\n\t */\n\tasync createAuditor(): Promise<Auditor<TAuditAction> | undefined> {\n\t\tconst storage = await this.getAuditStorage();\n\t\tif (!storage) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn new DefaultAuditor<TAuditAction>({\n\t\t\tactor: { id: 'system', type: 'system' },\n\t\t\tstorage: storage as AuditStorage,\n\t\t\tmetadata: {\n\t\t\t\tfunction: this.fn.type,\n\t\t\t},\n\t\t});\n\t}\n\n\t/**\n\t * Execute handler with audit transaction support.\n\t * If the audit storage has a database (via getDatabase()), wraps execution\n\t * in a transaction so audits are atomic with handler's database operations.\n\t *\n\t * @param handler - The handler function to execute (receives auditor and db)\n\t * @returns The handler result\n\t */\n\tasync executeWithAudit<T>(\n\t\thandler: (ctx: {\n\t\t\tauditor?: Auditor<TAuditAction>;\n\t\t\tdb?: TDatabase;\n\t\t}) => Promise<T>,\n\t): Promise<T> {\n\t\tconst auditor = await this.createAuditor();\n\t\tconst storage = await this.getAuditStorage();\n\n\t\t// No audit context - just run handler with regular db\n\t\tif (!auditor || !storage) {\n\t\t\tconst db = await this.getDatabase();\n\t\t\treturn handler({ db });\n\t\t}\n\n\t\t// Check if storage has a database and db service names match\n\t\tconst storageDb = (storage as AuditStorage).getDatabase?.();\n\t\tconst databaseServiceName = this.fn.databaseService?.serviceName;\n\t\tconst auditDbServiceName = this.fn.auditorStorageService?.serviceName;\n\n\t\t// If the audit storage has a database and we're using the same database service\n\t\t// (or the audit storage provides the database), use transactional execution\n\t\tif (storageDb && databaseServiceName && auditDbServiceName) {\n\t\t\treturn withAuditableTransaction(\n\t\t\t\tstorageDb as any,\n\t\t\t\tauditor as any,\n\t\t\t\tasync (trx) => {\n\t\t\t\t\t// Use transaction as db\n\t\t\t\t\tconst response = await handler({\n\t\t\t\t\t\tauditor,\n\t\t\t\t\t\tdb: trx as TDatabase,\n\t\t\t\t\t});\n\t\t\t\t\t// Audits are flushed by withAuditableTransaction before commit\n\t\t\t\t\treturn response;\n\t\t\t\t},\n\t\t\t);\n\t\t}\n\n\t\t// No database on storage or service names don't match - run handler and flush audits after\n\t\tconst db = await this.getDatabase();\n\t\tconst response = await handler({ auditor, db });\n\n\t\t// Flush audits (no transaction)\n\t\tawait auditor.flush();\n\n\t\treturn response;\n\t}\n\n\tasync getFunctionInput<TEvent>(\n\t\tevent: TEvent,\n\t): Promise<InferComposableStandardSchema<TInput>> {\n\t\tconst parsedInput = await FunctionBuilder.parseComposableStandardSchema(\n\t\t\tevent,\n\t\t\tthis.fn.input,\n\t\t);\n\n\t\treturn parsedInput as InferComposableStandardSchema<TInput>;\n\t}\n\n\tasync publishEvents(response: InferStandardSchema<TOutSchema>) {\n\t\tawait publishEvents(\n\t\t\tthis.logger,\n\t\t\tthis.serviceDiscovery,\n\t\t\tthis.fn.events,\n\t\t\tresponse,\n\t\t);\n\t}\n\n\tasync parseComposableStandardSchema<T extends ComposableStandardSchema>(\n\t\tdata: unknown,\n\t\tschema: T,\n\t): Promise<InferComposableStandardSchema<T>> {\n\t\treturn FunctionBuilder.parseComposableStandardSchema(data, schema);\n\t}\n}\n","import type { AuditableAction, Auditor, AuditStorage } from '@geekmidas/audit';\nimport type { EnvironmentParser } from '@geekmidas/envkit';\nimport { wrapError } from '@geekmidas/errors';\nimport type { EventPublisher } from '@geekmidas/events';\nimport type { Logger } from '@geekmidas/logger';\nimport type {\n\tComposableStandardSchema,\n\tInferComposableStandardSchema,\n\tInferStandardSchema,\n} from '@geekmidas/schema';\nimport type { Service, ServiceRecord } from '@geekmidas/services';\nimport { runWithRequestContext } from '@geekmidas/services';\nimport middy, { type MiddlewareObj } from '@middy/core';\nimport type { StandardSchemaV1 } from '@standard-schema/spec';\nimport type { Context, Handler } from 'aws-lambda';\nimport type { Function, FunctionHandler } from './Function';\nimport { FunctionBuilder } from './FunctionBuilder';\nimport { FunctionExecutionWrapper } from './FunctionExecutionWrapper';\n\nexport type AWSLambdaHandler<TEvent = any, TResult = any> = Handler<\n\tTEvent,\n\tTResult\n>;\n\ntype FunctionEvent<\n\tTEvent,\n\tTInput extends ComposableStandardSchema | undefined,\n\tTServices extends Service[],\n\tTLogger extends Logger,\n\tTDatabase = undefined,\n\tTAuditAction extends AuditableAction<string, unknown> = AuditableAction<\n\t\tstring,\n\t\tunknown\n\t>,\n> = TEvent & {\n\tparsedInput: InferComposableStandardSchema<TInput>;\n\tservices: ServiceRecord<TServices>;\n\tlogger: TLogger;\n\tdb: TDatabase | undefined;\n\tauditor: Auditor<TAuditAction> | undefined;\n};\n\ntype Middleware<\n\tTEvent,\n\tTInput extends ComposableStandardSchema | undefined,\n\tTServices extends Service[],\n\tTLogger extends Logger,\n\tTOutSchema extends StandardSchemaV1 | undefined,\n\tTDatabase = undefined,\n\tTAuditAction extends AuditableAction<string, unknown> = AuditableAction<\n\t\tstring,\n\t\tunknown\n\t>,\n> = MiddlewareObj<\n\tFunctionEvent<TEvent, TInput, TServices, TLogger, TDatabase, TAuditAction>,\n\tInferComposableStandardSchema<TOutSchema>,\n\tError,\n\tContext\n>;\n\nexport class AWSLambdaFunction<\n\tTInput extends ComposableStandardSchema | undefined = undefined,\n\tTOutSchema extends StandardSchemaV1 | undefined = undefined,\n\tTServices extends Service[] = [],\n\tTLogger extends Logger = Logger,\n\tTAuditStorage extends AuditStorage | undefined = undefined,\n\tTAuditStorageServiceName extends string = string,\n\tTDatabase = undefined,\n\tTDatabaseServiceName extends string = string,\n\tTAuditAction extends AuditableAction<string, unknown> = AuditableAction<\n\t\tstring,\n\t\tunknown\n\t>,\n> extends FunctionExecutionWrapper<\n\tTInput,\n\tTOutSchema,\n\tTServices,\n\tTLogger,\n\tTAuditStorage,\n\tTAuditStorageServiceName,\n\tTDatabase,\n\tTDatabaseServiceName,\n\tTAuditAction\n> {\n\tconstructor(\n\t\tenvParser: EnvironmentParser<{}>,\n\t\toverride readonly fn: Function<\n\t\t\tTInput,\n\t\t\tTServices,\n\t\t\tTLogger,\n\t\t\tTOutSchema,\n\t\t\tTAuditStorage,\n\t\t\tTAuditStorageServiceName,\n\t\t\tTDatabase,\n\t\t\tTDatabaseServiceName,\n\t\t\tTAuditAction,\n\t\t\tFunctionHandler<\n\t\t\t\tTInput,\n\t\t\t\tTServices,\n\t\t\t\tTLogger,\n\t\t\t\tTOutSchema,\n\t\t\t\tTDatabase,\n\t\t\t\tTAuditStorage,\n\t\t\t\tTAuditAction\n\t\t\t>\n\t\t>,\n\t) {\n\t\tsuper(envParser, fn);\n\t}\n\n\tprivate error<TEvent>(): Middleware<\n\t\tTEvent,\n\t\tTInput,\n\t\tTServices,\n\t\tTLogger,\n\t\tTOutSchema,\n\t\tTDatabase,\n\t\tTAuditAction\n\t> {\n\t\treturn {\n\t\t\tonError: (req) => {\n\t\t\t\tconst logger = req.event?.logger || this.fn.logger;\n\t\t\t\tlogger.error(req.error || {}, 'Error processing function');\n\n\t\t\t\t// Re-throw the wrapped error to let Lambda handle it\n\t\t\t\tthrow wrapError(req.error);\n\t\t\t},\n\t\t};\n\t}\n\n\tprivate baseInput<TEvent>(): Middleware<\n\t\tTEvent,\n\t\tTInput,\n\t\tTServices,\n\t\tTLogger,\n\t\tTOutSchema,\n\t\tTDatabase,\n\t\tTAuditAction\n\t> {\n\t\treturn {\n\t\t\tbefore: (_req) => {},\n\t\t};\n\t}\n\n\tprivate input<\n\t\tTEvent extends { input: InferComposableStandardSchema<TInput> },\n\t>(): Middleware<\n\t\tTEvent,\n\t\tTInput,\n\t\tTServices,\n\t\tTLogger,\n\t\tTOutSchema,\n\t\tTDatabase,\n\t\tTAuditAction\n\t> {\n\t\treturn {\n\t\t\tbefore: async (req) => {\n\t\t\t\ttry {\n\t\t\t\t\t// Parse input if schema is provided\n\t\t\t\t\tif (this.fn.input) {\n\t\t\t\t\t\tconst parsedInput =\n\t\t\t\t\t\t\tawait FunctionBuilder.parseComposableStandardSchema(\n\t\t\t\t\t\t\t\treq.event,\n\t\t\t\t\t\t\t\tthis.fn.input,\n\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\treq.event.parsedInput =\n\t\t\t\t\t\t\tparsedInput as InferComposableStandardSchema<TInput>;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// If no schema, pass the event as-is\n\t\t\t\t\t\treq.event.parsedInput = req.event as any;\n\t\t\t\t\t}\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthis.logger.error(\n\t\t\t\t\t\t{ error, event: req.event },\n\t\t\t\t\t\t'Failed to parse input',\n\t\t\t\t\t);\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t},\n\t\t};\n\t}\n\n\tprivate loggerMiddleware<TEvent>(): Middleware<\n\t\tTEvent,\n\t\tTInput,\n\t\tTServices,\n\t\tTLogger,\n\t\tTOutSchema,\n\t\tTDatabase,\n\t\tTAuditAction\n\t> {\n\t\treturn {\n\t\t\tbefore: (req) => {\n\t\t\t\tthis._logger = this.fn.logger.child({\n\t\t\t\t\tfn: {\n\t\t\t\t\t\tname: req.context.functionName,\n\t\t\t\t\t\tversion: req.context.functionVersion,\n\t\t\t\t\t\tmemory: req.context.memoryLimitInMB,\n\t\t\t\t\t},\n\t\t\t\t\treq: {\n\t\t\t\t\t\tid: req.context.awsRequestId,\n\t\t\t\t\t},\n\t\t\t\t}) as TLogger;\n\n\t\t\t\treq.event.logger = this._logger;\n\t\t\t},\n\t\t};\n\t}\n\n\tprivate services<TEvent>(): Middleware<\n\t\tTEvent,\n\t\tTInput,\n\t\tTServices,\n\t\tTLogger,\n\t\tTOutSchema,\n\t\tTDatabase,\n\t\tTAuditAction\n\t> {\n\t\treturn {\n\t\t\tbefore: async (req) => {\n\t\t\t\treq.event.services = await this.getServices();\n\t\t\t},\n\t\t};\n\t}\n\n\tprivate database<TEvent>(): Middleware<\n\t\tTEvent,\n\t\tTInput,\n\t\tTServices,\n\t\tTLogger,\n\t\tTOutSchema,\n\t\tTDatabase,\n\t\tTAuditAction\n\t> {\n\t\treturn {\n\t\t\tbefore: async (req) => {\n\t\t\t\treq.event.db = await this.getDatabase();\n\t\t\t},\n\t\t};\n\t}\n\n\tprivate auditor<TEvent>(): Middleware<\n\t\tTEvent,\n\t\tTInput,\n\t\tTServices,\n\t\tTLogger,\n\t\tTOutSchema,\n\t\tTDatabase,\n\t\tTAuditAction\n\t> {\n\t\treturn {\n\t\t\tbefore: async (req) => {\n\t\t\t\treq.event.auditor = await this.createAuditor();\n\t\t\t},\n\t\t\tafter: async (req) => {\n\t\t\t\t// Flush any pending audits after successful execution\n\t\t\t\tif (req.event.auditor) {\n\t\t\t\t\tconst records = req.event.auditor.getRecords();\n\t\t\t\t\tif (records.length > 0) {\n\t\t\t\t\t\tthis.logger.debug(\n\t\t\t\t\t\t\t{ auditCount: records.length },\n\t\t\t\t\t\t\t'Flushing function audits',\n\t\t\t\t\t\t);\n\t\t\t\t\t\tawait req.event.auditor.flush();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t};\n\t}\n\n\tprivate events<TEvent>(): Middleware<\n\t\tTEvent,\n\t\tTInput,\n\t\tTServices,\n\t\tTLogger,\n\t\tTOutSchema,\n\t\tTDatabase,\n\t\tTAuditAction\n\t> {\n\t\treturn {\n\t\t\tafter: async (req) => {\n\t\t\t\tconst response = (req.response ||\n\t\t\t\t\tundefined) as InferStandardSchema<TOutSchema>;\n\t\t\t\tawait this.publishEvents(response);\n\t\t\t},\n\t\t};\n\t}\n\n\tprivate async _handler<TEvent>(\n\t\tevent: FunctionEvent<\n\t\t\tTEvent,\n\t\t\tTInput,\n\t\t\tTServices,\n\t\t\tTLogger,\n\t\t\tTDatabase,\n\t\t\tTAuditAction\n\t\t>,\n\t) {\n\t\t// Execute the function with the parsed context\n\t\tconst result = await this.fn.fn({\n\t\t\tinput: event.parsedInput,\n\t\t\tservices: event.services,\n\t\t\tlogger: event.logger,\n\t\t\tdb: event.db,\n\t\t\tauditor: event.auditor,\n\t\t} as any);\n\n\t\t// Parse output if schema is provided\n\t\tconst output = await this.fn.parseOutput(result);\n\n\t\treturn output;\n\t}\n\n\tget handler(): AWSLambdaHandler {\n\t\tconst handler = this._handler.bind(this);\n\n\t\t// Apply middleware in order\n\t\tconst chain = middy(handler)\n\t\t\t.use(this.loggerMiddleware())\n\t\t\t.use(this.baseInput())\n\t\t\t.use(this.error())\n\t\t\t.use(this.services())\n\t\t\t.use(this.database())\n\t\t\t.use(this.auditor())\n\t\t\t.use(this.input())\n\t\t\t.use(this.events());\n\n\t\t// Wrap entire Middy chain in request context for service access\n\t\tconst wrappedHandler = async (event: unknown, context: Context) => {\n\t\t\tconst startTime = Date.now();\n\t\t\tconst requestId = context.awsRequestId;\n\t\t\tconst logger = this.fn.logger.child({ requestId }) as TLogger;\n\n\t\t\treturn runWithRequestContext(\n\t\t\t\t{ logger, requestId, startTime, operation: context.functionName },\n\t\t\t\t() => chain(event as Parameters<typeof chain>[0], context),\n\t\t\t);\n\t\t};\n\n\t\treturn wrappedHandler as unknown as AWSLambdaHandler;\n\t}\n}\n","import type { EnvironmentParser } from '@geekmidas/envkit';\nimport type { EventPublisher } from '@geekmidas/events';\nimport type { Logger } from '@geekmidas/logger';\nimport type { ComposableStandardSchema } from '@geekmidas/schema';\nimport type { Service } from '@geekmidas/services';\nimport type { StandardSchemaV1 } from '@standard-schema/spec';\nimport { AWSLambdaFunction } from '../functions/AWSLambdaFunction';\nimport type { Cron } from './Cron';\n\n/**\n * AWS Lambda adaptor for {@link Cron} constructs.\n *\n * A `Cron` is a {@link import('../functions').Function} that is invoked on a\n * schedule (an EventBridge rule) rather than by an API request. Because of\n * that, the runtime execution pipeline is identical to a regular Lambda\n * function: input parsing, service/database/auditor wiring, event publishing,\n * error handling, and the `runWithRequestContext` wrapper that powers\n * request-scoped logging via `serviceContext.getLogger()`.\n *\n * This adaptor therefore reuses {@link AWSLambdaFunction} wholesale and only\n * narrows the constructor to accept a `Cron`. The schedule expression itself\n * (`cron.schedule`) is **deploy-time** infrastructure consumed by the CLI to\n * provision the EventBridge rule — it is not needed at runtime.\n *\n * @example\n * ```typescript\n * import { AWSScheduledFunction } from '@geekmidas/constructs/crons';\n * import { cancelPastBookings } from '../../../src/crons/cancelPastBookings.js';\n * import { envParser } from '../../../src/env';\n *\n * const adapter = new AWSScheduledFunction(envParser, cancelPastBookings);\n *\n * export const handler = adapter.handler;\n * ```\n */\nexport class AWSScheduledFunction<\n\tTInput extends ComposableStandardSchema | undefined = undefined,\n\tTServices extends Service[] = [],\n\tTLogger extends Logger = Logger,\n\tTOutSchema extends StandardSchemaV1 | undefined = undefined,\n\tTDatabase = undefined,\n\tTDatabaseServiceName extends string = string,\n> extends AWSLambdaFunction<\n\tTInput,\n\tTOutSchema,\n\tTServices,\n\tTLogger,\n\tundefined,\n\tstring,\n\tTDatabase,\n\tTDatabaseServiceName\n> {\n\t// biome-ignore lint/complexity/noUselessConstructor: narrows the inherited `Function` parameter to `Cron` for a clearer public API\n\tconstructor(\n\t\tenvParser: EnvironmentParser<{}>,\n\t\tcron: Cron<\n\t\t\tTInput,\n\t\t\tTServices,\n\t\t\tTLogger,\n\t\t\tTOutSchema,\n\t\t\tTDatabase,\n\t\t\tTDatabaseServiceName\n\t\t>,\n\t) {\n\t\tsuper(envParser, cron);\n\t}\n}\n","import type { AuditableAction, AuditStorage } from '@geekmidas/audit';\nimport { withRlsContext } from '@geekmidas/db/rls';\nimport type { EnvironmentParser } from '@geekmidas/envkit';\nimport type { Logger } from '@geekmidas/logger';\nimport middy, { type MiddlewareObj } from '@middy/core';\nimport type { StandardSchemaV1 } from '@standard-schema/spec';\nimport type {\n\tAPIGatewayProxyEvent,\n\tAPIGatewayProxyEventV2,\n\tContext,\n} from 'aws-lambda';\nimport set from 'lodash.set';\nimport type { Telemetry } from '../telemetry';\nimport type { HttpMethod } from '../types';\nimport { Endpoint, type EndpointSchemas, ResponseBuilder } from './Endpoint';\nimport { envParserFor } from './surfaceEnv';\n\n/**\n * Telescope integration for request recording.\n * Uses Middy middleware pattern for compatibility with existing telescope package.\n */\nexport interface TelescopeIntegration {\n\tmiddleware: MiddlewareObj<any, any, Error, Context>;\n}\n\nimport {\n\tForbiddenError,\n\tUnprocessableEntityError,\n\twrapError,\n} from '@geekmidas/errors';\nimport type { EventPublisher } from '@geekmidas/events';\nimport type {\n\tInferComposableStandardSchema,\n\tInferStandardSchema,\n} from '@geekmidas/schema';\nimport {\n\trunWithRequestContext,\n\ttype Service,\n\tServiceDiscovery,\n\ttype ServiceRecord,\n} from '@geekmidas/services';\nimport { publishConstructEvents } from '../publisher';\nimport type { MappedAudit } from './audit';\nimport type { CookieFn, HeaderFn } from './Endpoint';\nimport {\n\tcreateAuditContext,\n\texecuteWithAuditTransaction,\n} from './processAudits';\n\n// Helper function to publish events\n\n/**\n * Options for Amazon API Gateway endpoint adaptors\n */\nexport interface AmazonApiGatewayEndpointOptions {\n\t/**\n\t * Telescope integration for request recording and monitoring.\n\t *\n\t * @example\n\t * ```typescript\n\t * import { telescopeMiddleware } from '@geekmidas/telescope/lambda';\n\t *\n\t * const adaptor = new AmazonApiGatewayV2Endpoint(endpoint, {\n\t * telescope: { middleware: telescopeMiddleware(telescope) },\n\t * });\n\t * ```\n\t */\n\ttelescope?: TelescopeIntegration;\n\n\t/**\n\t * Telemetry integration for distributed tracing.\n\t * Works with any OpenTelemetry-compatible backend.\n\t *\n\t * @example\n\t * ```typescript\n\t * import { OTelTelemetry } from '@geekmidas/telescope/instrumentation';\n\t *\n\t * const adaptor = new AmazonApiGatewayV2Endpoint(endpoint, {\n\t * telemetry: new OTelTelemetry(),\n\t * });\n\t * ```\n\t */\n\ttelemetry?: Telemetry;\n}\n\nexport abstract class AmazonApiGatewayEndpoint<\n\tTHandler extends\n\t\t| AmazonApiGatewayV1EndpointHandler\n\t\t| AmazonApiGatewayV2EndpointHandler,\n\tTEvent extends HandlerEvent<THandler>,\n\tTRoute extends string,\n\tTMethod extends HttpMethod,\n\tTInput extends EndpointSchemas = {},\n\tTOutSchema extends StandardSchemaV1 | undefined = undefined,\n\tTServices extends Service[] = [],\n\tTLogger extends Logger = Logger,\n\tTSession = unknown,\n\tTAuditStorage extends AuditStorage | undefined = undefined,\n\tTAuditStorageServiceName extends string = string,\n\tTAuditAction extends AuditableAction<string, unknown> = AuditableAction<\n\t\tstring,\n\t\tunknown\n\t>,\n> {\n\tprotected options: AmazonApiGatewayEndpointOptions;\n\n\t/**\n\t * The parser this adaptor discovers services with.\n\t *\n\t * Taken from the endpoint's surface rather than handed in. An endpoint built\n\t * with `api.get()` carries its API, and the API carries the parser — so a\n\t * generated handler is `new AmazonApiGatewayV2Endpoint(endpoint)` with no\n\t * import written for it, which is the whole reason the surface is the\n\t * factory.\n\t */\n\tprotected envParser: EnvironmentParser<{}>;\n\n\tconstructor(\n\t\tprotected readonly endpoint: Endpoint<\n\t\t\tTRoute,\n\t\t\tTMethod,\n\t\t\tTInput,\n\t\t\tTOutSchema,\n\t\t\tTServices,\n\t\t\tTLogger,\n\t\t\tTSession,\n\t\t\tTAuditStorage,\n\t\t\tTAuditStorageServiceName,\n\t\t\tTAuditAction\n\t\t>,\n\t\toptions: AmazonApiGatewayEndpointOptions = {},\n\t) {\n\t\tthis.options = options;\n\t\tthis.envParser = envParserFor(endpoint.surface);\n\t}\n\n\tprivate error(): Middleware<TEvent, TInput, TServices, TLogger> {\n\t\treturn {\n\t\t\tonError: (req) => {\n\t\t\t\t(req.event.logger || this.endpoint.logger).error(\n\t\t\t\t\treq.error || {},\n\t\t\t\t\t'Error processing request',\n\t\t\t\t);\n\t\t\t\tconst wrappedError = wrapError(req.error);\n\n\t\t\t\t// Set the response with the proper status code from the HttpError\n\t\t\t\treq.response = {\n\t\t\t\t\tstatusCode: wrappedError.statusCode,\n\t\t\t\t\tbody: wrappedError.body,\n\t\t\t\t};\n\t\t\t},\n\t\t};\n\t}\n\tabstract getInput(e: TEvent): GetInputResponse;\n\n\t/**\n\t * Decodes the raw body from an API Gateway event.\n\t * Uses Content-Type to decide parsing strategy (like Express/Fastify/Hono):\n\t * - `application/json` (or missing) → JSON.parse the decoded string\n\t * - Anything else → return decoded string as-is, let the schema handle it\n\t *\n\t * Defaults to JSON when no Content-Type is provided for backwards compatibility.\n\t */\n\tstatic decodeBody(\n\t\tbody: string | undefined | null,\n\t\tisBase64Encoded: boolean | undefined,\n\t\tcontentType: string | undefined,\n\t): any {\n\t\tif (!body) return undefined;\n\n\t\tconst raw = isBase64Encoded\n\t\t\t? Buffer.from(body, 'base64').toString('utf-8')\n\t\t\t: body;\n\n\t\tconst isJson =\n\t\t\t!contentType || contentType.toLowerCase().includes('application/json');\n\t\tif (isJson) {\n\t\t\treturn JSON.parse(raw);\n\t\t}\n\n\t\treturn raw;\n\t}\n\n\tprotected getCookies(e: TEvent): CookieFn {\n\t\tconst headers = e.headers as Record<string, string>;\n\t\treturn Endpoint.createCookies(headers?.cookie);\n\t}\n\n\tprivate input(): Middleware<TEvent, TInput, TServices, TLogger> {\n\t\treturn {\n\t\t\tbefore: async (req) => {\n\t\t\t\ttry {\n\t\t\t\t\tconst { body, query, params } = this.getInput(req.event);\n\t\t\t\t\tconst headers = req.event.headers as Record<string, string>;\n\t\t\t\t\tconst header = Endpoint.createHeaders(headers);\n\t\t\t\t\tconst cookie = this.getCookies(req.event);\n\n\t\t\t\t\tset(req.event, 'body', await this.endpoint.parseInput(body, 'body'));\n\n\t\t\t\t\tset(\n\t\t\t\t\t\treq.event,\n\t\t\t\t\t\t'query',\n\t\t\t\t\t\tawait this.endpoint.parseInput(query, 'query'),\n\t\t\t\t\t);\n\t\t\t\t\tset(\n\t\t\t\t\t\treq.event,\n\t\t\t\t\t\t'params',\n\t\t\t\t\t\tawait this.endpoint.parseInput(params, 'params'),\n\t\t\t\t\t);\n\t\t\t\t\tset(req.event, 'header', header);\n\t\t\t\t\tset(req.event, 'cookie', cookie);\n\t\t\t\t} catch (error) {\n\t\t\t\t\t// Convert validation errors to 422 Unprocessable Entity\n\t\t\t\t\tif (error && typeof error === 'object' && Array.isArray(error)) {\n\t\t\t\t\t\tthrow new UnprocessableEntityError('Validation failed', error);\n\t\t\t\t\t}\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t},\n\t\t};\n\t}\n\n\tabstract getLoggerContext(data: TEvent, context: Context): LoggerContext;\n\n\tprivate logger(): Middleware<TEvent, TInput, TServices, TLogger> {\n\t\treturn {\n\t\t\tbefore: (req) => {\n\t\t\t\treq.event.logger = this.endpoint.logger.child({\n\t\t\t\t\troute: this.endpoint.route,\n\t\t\t\t\thost: req.event.headers?.host,\n\t\t\t\t\tmethod: this.endpoint.method,\n\t\t\t\t\t...this.getLoggerContext(req.event, req.context),\n\t\t\t\t}) as TLogger;\n\t\t\t},\n\t\t};\n\t}\n\tprivate services(): Middleware<TEvent, TInput, TServices, TLogger> {\n\t\treturn {\n\t\t\tbefore: async (req) => {\n\t\t\t\tconst _logger = req.event.logger as TLogger;\n\t\t\t\tconst serviceDiscovery = ServiceDiscovery.getInstance<\n\t\t\t\t\tServiceRecord<TServices>\n\t\t\t\t>(this.envParser);\n\n\t\t\t\tconst services = await serviceDiscovery.register(\n\t\t\t\t\tthis.endpoint.services,\n\t\t\t\t);\n\n\t\t\t\treq.event.services = services;\n\t\t\t},\n\t\t};\n\t}\n\n\tprivate authorize(): Middleware<TEvent, TInput, TServices, TLogger> {\n\t\treturn {\n\t\t\tbefore: async (req) => {\n\t\t\t\tconst logger = req.event.logger as TLogger;\n\t\t\t\tconst services = req.event.services;\n\t\t\t\tconst header = req.event.header;\n\t\t\t\tconst cookie = req.event.cookie;\n\t\t\t\tconst session = req.event.session as TSession;\n\n\t\t\t\tconst isAuthorized = await this.endpoint.authorize({\n\t\t\t\t\theader,\n\t\t\t\t\tcookie,\n\t\t\t\t\tservices,\n\t\t\t\t\tlogger,\n\t\t\t\t\tsession,\n\t\t\t\t\t...((req.event as any).db !== undefined && {\n\t\t\t\t\t\tdb: (req.event as any).db,\n\t\t\t\t\t}),\n\t\t\t\t\tbody: (req.event as any).body,\n\t\t\t\t\tquery: (req.event as any).query,\n\t\t\t\t\tparams: (req.event as any).params,\n\t\t\t\t} as any);\n\n\t\t\t\tif (!isAuthorized) {\n\t\t\t\t\tlogger.warn('Forbidden access attempt');\n\t\t\t\t\tthrow new ForbiddenError(\n\t\t\t\t\t\t'Forbidden access to the endpoint',\n\t\t\t\t\t\t'You do not have permission to access this resource.',\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t},\n\t\t};\n\t}\n\n\tprivate database(): Middleware<TEvent, TInput, TServices, TLogger> {\n\t\treturn {\n\t\t\tbefore: async (req) => {\n\t\t\t\tif (!this.endpoint.databaseService) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst _logger = req.event.logger as TLogger;\n\t\t\t\tconst serviceDiscovery = ServiceDiscovery.getInstance<\n\t\t\t\t\tServiceRecord<TServices>\n\t\t\t\t>(this.envParser);\n\n\t\t\t\tconst db = await serviceDiscovery\n\t\t\t\t\t.register([this.endpoint.databaseService])\n\t\t\t\t\t.then(\n\t\t\t\t\t\t(s) =>\n\t\t\t\t\t\t\ts[this.endpoint.databaseService?.serviceName as keyof typeof s],\n\t\t\t\t\t);\n\n\t\t\t\t(req.event as any).db = db;\n\t\t\t},\n\t\t};\n\t}\n\n\tprivate session(): Middleware<TEvent, TInput, TServices, TLogger> {\n\t\treturn {\n\t\t\tbefore: async (req) => {\n\t\t\t\tconst logger = req.event.logger as TLogger;\n\t\t\t\tconst services = req.event.services;\n\t\t\t\tconst db = (req.event as any).db;\n\t\t\t\treq.event.session = (await this.endpoint.getSession({\n\t\t\t\t\tlogger,\n\t\t\t\t\tservices,\n\t\t\t\t\theader: req.event.header,\n\t\t\t\t\tcookie: req.event.cookie,\n\t\t\t\t\t...(db !== undefined && { db }),\n\t\t\t\t} as any)) as TSession;\n\t\t\t},\n\t\t};\n\t}\n\n\tprivate events(): Middleware<TEvent, TInput, TServices, TLogger> {\n\t\treturn {\n\t\t\tafter: async (req) => {\n\t\t\t\tconst event = req.event;\n\t\t\t\tconst response = (event as any)\n\t\t\t\t\t.__response as InferStandardSchema<TOutSchema>;\n\t\t\t\tconst statusCode = req.response?.statusCode ?? this.endpoint.status;\n\n\t\t\t\t// Only publish events on successful responses (2xx status codes)\n\t\t\t\t// Note: Audits are processed inside the handler's transaction\n\t\t\t\tif (Endpoint.isSuccessStatus(statusCode)) {\n\t\t\t\t\tconst logger = event.logger as TLogger;\n\t\t\t\t\tconst serviceDiscovery = ServiceDiscovery.getInstance<\n\t\t\t\t\t\tServiceRecord<TServices>\n\t\t\t\t\t>(this.envParser);\n\n\t\t\t\t\t// Publish events\n\t\t\t\t\tawait publishConstructEvents(\n\t\t\t\t\t\tthis.endpoint,\n\t\t\t\t\t\tresponse,\n\t\t\t\t\t\tserviceDiscovery,\n\t\t\t\t\t\tlogger,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t},\n\t\t};\n\t}\n\n\tprivate async _handler(\n\t\tevent: Event<TEvent, TInput, TServices, TLogger, TSession>,\n\t) {\n\t\tconst input = this.endpoint.refineInput(event);\n\t\tconst logger = event.logger as TLogger;\n\t\tconst serviceDiscovery = ServiceDiscovery.getInstance<\n\t\t\tServiceRecord<TServices>\n\t\t>(this.envParser);\n\n\t\t// Create audit context if audit storage is configured\n\t\tconst auditContext = await createAuditContext(\n\t\t\tthis.endpoint,\n\t\t\tserviceDiscovery,\n\t\t\tlogger,\n\t\t\t{\n\t\t\t\tsession: event.session,\n\t\t\t\theader: event.header,\n\t\t\t\tcookie: event.cookie,\n\t\t\t\tservices: event.services as Record<string, unknown>,\n\t\t\t},\n\t\t);\n\n\t\t// Warn if declarative audits are configured but no audit storage\n\t\tconst audits = this.endpoint.audits as MappedAudit<\n\t\t\tTAuditAction,\n\t\t\tTOutSchema\n\t\t>[];\n\t\tif (!auditContext && audits?.length) {\n\t\t\tlogger.warn('No auditor storage service available');\n\t\t}\n\n\t\t// Get pre-resolved database from middleware\n\t\tconst rawDb = (event as any).db;\n\n\t\t// Extract RLS context if configured and not bypassed\n\t\tconst rlsActive =\n\t\t\tthis.endpoint.rlsConfig &&\n\t\t\t!this.endpoint.rlsBypass &&\n\t\t\trawDb !== undefined;\n\t\tconst rlsContext = rlsActive\n\t\t\t? await this.endpoint.rlsConfig?.extractor({\n\t\t\t\t\tservices: event.services as ServiceRecord<TServices>,\n\t\t\t\t\tsession: event.session,\n\t\t\t\t\theader: event.header,\n\t\t\t\t\tcookie: event.cookie,\n\t\t\t\t\tlogger,\n\t\t\t\t})\n\t\t\t: undefined;\n\n\t\t// Execute handler with automatic audit transaction support\n\t\tconst result = await executeWithAuditTransaction(\n\t\t\tauditContext,\n\t\t\tasync (auditor) => {\n\t\t\t\t// Use audit transaction as db only if the storage uses the same database service\n\t\t\t\tconst sameDatabase =\n\t\t\t\t\tauditContext?.storage?.databaseServiceName &&\n\t\t\t\t\tauditContext.storage.databaseServiceName ===\n\t\t\t\t\t\tthis.endpoint.databaseService?.serviceName;\n\t\t\t\tconst baseDb = sameDatabase\n\t\t\t\t\t? (auditor?.getTransaction?.() ?? rawDb)\n\t\t\t\t\t: rawDb;\n\n\t\t\t\t// Helper to execute handler with given db\n\t\t\t\tconst executeHandler = async (db: any) => {\n\t\t\t\t\tconst responseBuilder = new ResponseBuilder();\n\t\t\t\t\tconst response = await this.endpoint.handler(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\theader: event.header,\n\t\t\t\t\t\t\tcookie: event.cookie,\n\t\t\t\t\t\t\tlogger: event.logger,\n\t\t\t\t\t\t\tservices: event.services,\n\t\t\t\t\t\t\tsession: event.session,\n\t\t\t\t\t\t\tauditor,\n\t\t\t\t\t\t\tdb,\n\t\t\t\t\t\t\t...input,\n\t\t\t\t\t\t} as any,\n\t\t\t\t\t\tresponseBuilder,\n\t\t\t\t\t);\n\n\t\t\t\t\t// Check if response has metadata\n\t\t\t\t\tlet data = response;\n\t\t\t\t\tlet metadata = responseBuilder.getMetadata();\n\n\t\t\t\t\tif (Endpoint.hasMetadata(response)) {\n\t\t\t\t\t\tdata = response.data;\n\t\t\t\t\t\tmetadata = response.metadata;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst output = this.endpoint.outputSchema\n\t\t\t\t\t\t? await this.endpoint.parseOutput(data)\n\t\t\t\t\t\t: undefined;\n\n\t\t\t\t\treturn { output, metadata, responseBuilder };\n\t\t\t\t};\n\n\t\t\t\t// If RLS is active, wrap handler with RLS context\n\t\t\t\tif (rlsActive && rlsContext && baseDb) {\n\t\t\t\t\treturn withRlsContext(\n\t\t\t\t\t\tbaseDb,\n\t\t\t\t\t\trlsContext,\n\t\t\t\t\t\tasync (trx: any) => executeHandler(trx),\n\t\t\t\t\t\t{ prefix: this.endpoint.rlsConfig?.prefix },\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\treturn executeHandler(baseDb);\n\t\t\t},\n\t\t\t// Process declarative audits after handler (inside transaction)\n\t\t\tasync (result, auditor) => {\n\t\t\t\tif (!audits?.length) return;\n\n\t\t\t\tfor (const audit of audits) {\n\t\t\t\t\tif (audit.when && !audit.when(result.output as any)) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tconst payload = audit.payload(result.output as any);\n\t\t\t\t\tconst entityId = audit.entityId?.(result.output as any);\n\t\t\t\t\tauditor.audit(audit.type as any, payload as any, {\n\t\t\t\t\t\ttable: audit.table,\n\t\t\t\t\t\tentityId,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t},\n\t\t\t// Pass rawDb so storage can reuse existing transactions\n\t\t\t{ db: rawDb },\n\t\t);\n\n\t\tconst { output, metadata } = result;\n\t\tconst isJsonResponse = this.endpoint.responseType === 'application/json';\n\t\tconst body =\n\t\t\toutput === undefined\n\t\t\t\t? undefined\n\t\t\t\t: isJsonResponse\n\t\t\t\t\t? JSON.stringify(output)\n\t\t\t\t\t: typeof output === 'string'\n\t\t\t\t\t\t? output\n\t\t\t\t\t\t: String(output);\n\n\t\t// Store response for middleware access\n\t\t(event as any).__response = output;\n\n\t\t// Build response with metadata\n\t\tconst lambdaResponse: AmazonApiGatewayEndpointHandlerResponse = {\n\t\t\tstatusCode: metadata.status ?? this.endpoint.status,\n\t\t\tbody,\n\t\t};\n\n\t\t// Compose headers. For non-JSON responseType, emit a default\n\t\t// Content-Type header which metadata.headers (r.header()) can override.\n\t\tconst baseHeaders: Record<string, string> | undefined = isJsonResponse\n\t\t\t? undefined\n\t\t\t: { 'content-type': this.endpoint.responseType };\n\n\t\tif (\n\t\t\tbaseHeaders ||\n\t\t\t(metadata.headers && Object.keys(metadata.headers).length > 0)\n\t\t) {\n\t\t\tlambdaResponse.headers = {\n\t\t\t\t...(baseHeaders ?? {}),\n\t\t\t\t...(metadata.headers ?? {}),\n\t\t\t};\n\t\t}\n\n\t\t// Format cookies as Set-Cookie headers\n\t\tif (metadata.cookies && metadata.cookies.size > 0) {\n\t\t\tconst setCookieHeaders: string[] = [];\n\t\t\tfor (const [name, { value, options }] of metadata.cookies) {\n\t\t\t\tsetCookieHeaders.push(\n\t\t\t\t\tEndpoint.formatCookieHeader(name, value, options),\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif (setCookieHeaders.length > 0) {\n\t\t\t\tlambdaResponse.multiValueHeaders = {\n\t\t\t\t\t...lambdaResponse.multiValueHeaders,\n\t\t\t\t\t'Set-Cookie': setCookieHeaders,\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\treturn lambdaResponse;\n\t}\n\n\t/**\n\t * Convert Telemetry interface to Middy middleware\n\t */\n\tprivate telemetry(): Middleware<TEvent, TInput, TServices, TLogger> | null {\n\t\tif (!this.options.telemetry) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst telemetry = this.options.telemetry;\n\t\tlet ctx: any;\n\n\t\treturn {\n\t\t\tbefore: (request) => {\n\t\t\t\tctx = telemetry.onRequestStart({\n\t\t\t\t\tevent: request.event,\n\t\t\t\t\tcontext: request.context,\n\t\t\t\t});\n\t\t\t},\n\t\t\tafter: (request) => {\n\t\t\t\tif (ctx) {\n\t\t\t\t\ttelemetry.onRequestEnd(ctx, {\n\t\t\t\t\t\tstatusCode: request.response?.statusCode ?? 200,\n\t\t\t\t\t\tbody: request.response?.body,\n\t\t\t\t\t\theaders: request.response?.headers,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t},\n\t\t\tonError: (request) => {\n\t\t\t\tif (ctx && request.error) {\n\t\t\t\t\ttelemetry.onRequestError(\n\t\t\t\t\t\tctx,\n\t\t\t\t\t\trequest.error instanceof Error\n\t\t\t\t\t\t\t? request.error\n\t\t\t\t\t\t\t: new Error(String(request.error)),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t},\n\t\t};\n\t}\n\n\tget handler() {\n\t\tconst handler = this._handler.bind(this);\n\t\tlet chain = middy(handler)\n\t\t\t.use(this.logger())\n\t\t\t.use(this.error())\n\t\t\t.use(this.services())\n\t\t\t.use(this.input())\n\t\t\t.use(this.database())\n\t\t\t.use(this.session())\n\t\t\t.use(this.authorize())\n\t\t\t.use(this.events());\n\n\t\t// Add telemetry middleware if configured (runs early for span creation)\n\t\tconst telemetryMiddleware = this.telemetry();\n\t\tif (telemetryMiddleware) {\n\t\t\tchain = chain.use(telemetryMiddleware);\n\t\t}\n\n\t\t// Add Telescope middleware if configured (runs first/last in chain)\n\t\tif (this.options.telescope?.middleware) {\n\t\t\tchain = chain.use(this.options.telescope.middleware);\n\t\t}\n\n\t\t// Wrap entire Middy chain in request context for service access\n\t\tconst wrappedHandler = async (event: TEvent, context: Context) => {\n\t\t\tconst startTime = Date.now();\n\t\t\tconst requestId = context.awsRequestId;\n\t\t\tconst logger = this.endpoint.logger.child({ requestId }) as TLogger;\n\n\t\t\t// Cast event to any since Middy middlewares enrich the event with\n\t\t\t// services, logger, session, etc. during the middleware chain execution\n\t\t\tconst operation = `${this.endpoint.method} ${this.endpoint.route}`;\n\t\t\treturn runWithRequestContext(\n\t\t\t\t{ logger, requestId, startTime, operation },\n\t\t\t\t() => chain(event as unknown as Parameters<typeof chain>[0], context),\n\t\t\t);\n\t\t};\n\n\t\treturn wrappedHandler as unknown as THandler;\n\t}\n}\n\nexport type Event<\n\tTEvent extends APIGatewayProxyEvent | APIGatewayProxyEventV2,\n\tTInput extends EndpointSchemas = {},\n\tTServices extends Service[] = [],\n\tTLogger extends Logger = Logger,\n\tTSession = unknown,\n> = {\n\tservices: ServiceRecord<TServices>;\n\tlogger: TLogger;\n\theader: HeaderFn;\n\tcookie: CookieFn;\n\tsession: TSession;\n} & TEvent &\n\tInferComposableStandardSchema<TInput>;\n\ntype Middleware<\n\tTEvent extends APIGatewayProxyEvent | APIGatewayProxyEventV2,\n\tTInput extends EndpointSchemas = {},\n\tTServices extends Service[] = [],\n\tTLogger extends Logger = Logger,\n\tTSession = unknown,\n> = MiddlewareObj<Event<TEvent, TInput, TServices, TLogger, TSession>>;\n\nexport type AmazonApiGatewayEndpointHandlerResponse = {\n\tstatusCode: number;\n\tbody: string | undefined;\n\theaders?: Record<string, string>;\n\tmultiValueHeaders?: Record<string, string[]>;\n};\n\nexport type LoggerContext = {\n\tfn: {\n\t\tname: string;\n\t\tversion: string;\n\t};\n\treq: {\n\t\tid: string | undefined;\n\t\tawsRequestId: string;\n\t\tpath: string;\n\t\tip: string | undefined;\n\t\tuserAgent: string | undefined;\n\t};\n};\n\nexport type GetInputResponse = {\n\tbody: any;\n\tquery: any;\n\tparams: any;\n};\n\nexport type AmazonApiGatewayV1EndpointHandler = (\n\tevent: APIGatewayProxyEvent,\n\tcontext: Context,\n) => Promise<AmazonApiGatewayEndpointHandlerResponse>;\n\nexport type AmazonApiGatewayV2EndpointHandler = (\n\tevent: APIGatewayProxyEventV2,\n\tcontext: Context,\n) => Promise<AmazonApiGatewayEndpointHandlerResponse>;\n\nexport type HandlerEvent<T extends Function> = T extends (\n\tevent: infer E,\n\tcontext: Context,\n) => any\n\t? E\n\t: never;\n","import qs from 'qs';\n\n/**\n * Parse query parameters from a flat object into a nested structure\n * Uses qs bracket notation for standard interoperability\n *\n * @example\n * parseQueryParams({ 'tags[]': ['a', 'b'], 'filter[name]': 'john' })\n * // Returns: { tags: ['a', 'b'], filter: { name: 'john' } }\n */\nexport function parseQueryParams(\n\tqueryParams: Record<string, string | string[] | undefined> | null,\n): Record<string, any> {\n\tif (!queryParams) {\n\t\treturn {};\n\t}\n\n\t// Reconstruct a query string from the flat object so qs can parse bracket notation\n\tconst parts: string[] = [];\n\tfor (const [key, value] of Object.entries(queryParams)) {\n\t\tif (value === undefined) continue;\n\t\tif (Array.isArray(value)) {\n\t\t\tfor (const v of value) {\n\t\t\t\tparts.push(`${encodeURIComponent(key)}=${encodeURIComponent(v)}`);\n\t\t\t}\n\t\t} else {\n\t\t\tparts.push(`${encodeURIComponent(key)}=${encodeURIComponent(value)}`);\n\t\t}\n\t}\n\n\treturn qs.parse(parts.join('&')) as Record<string, any>;\n}\n","import type { EventPublisher } from '@geekmidas/events';\nimport type { Logger } from '@geekmidas/logger';\nimport type { Service } from '@geekmidas/services';\nimport type { StandardSchemaV1 } from '@standard-schema/spec';\nimport type { APIGatewayProxyEvent, Context } from 'aws-lambda';\nimport type { HttpMethod } from '../types';\nimport {\n\tAmazonApiGatewayEndpoint,\n\ttype AmazonApiGatewayEndpointOptions,\n\ttype AmazonApiGatewayV1EndpointHandler,\n\ttype GetInputResponse,\n\ttype LoggerContext,\n} from './AmazonApiGatewayEndpointAdaptor';\nimport type { Endpoint, EndpointSchemas } from './Endpoint';\nimport { parseQueryParams } from './parseQueryParams';\n\nexport class AmazonApiGatewayV1Endpoint<\n\tTRoute extends string,\n\tTMethod extends HttpMethod,\n\tTInput extends EndpointSchemas = {},\n\tTOutSchema extends StandardSchemaV1 | undefined = undefined,\n\tTServices extends Service[] = [],\n\tTLogger extends Logger = Logger,\n\tTSession = unknown,\n> extends AmazonApiGatewayEndpoint<\n\tAmazonApiGatewayV1EndpointHandler,\n\tAPIGatewayProxyEvent,\n\tTRoute,\n\tTMethod,\n\tTInput,\n\tTOutSchema,\n\tTServices,\n\tTLogger,\n\tTSession\n> {\n\toverride getInput(e: APIGatewayProxyEvent): GetInputResponse {\n\t\t// For arrays, AWS API Gateway V1 provides multiValueQueryStringParameters\n\t\tconst multiValueParams = e.multiValueQueryStringParameters || {};\n\t\tconst singleValueParams = e.queryStringParameters || {};\n\n\t\t// Merge single and multi-value parameters\n\t\tconst mergedParams: Record<string, string | string[]> = {};\n\n\t\t// Add single value parameters\n\t\tfor (const [key, value] of Object.entries(singleValueParams)) {\n\t\t\tif (value !== undefined) {\n\t\t\t\tmergedParams[key] = value;\n\t\t\t}\n\t\t}\n\n\t\t// Override with multi-value parameters where applicable\n\t\tfor (const [key, values] of Object.entries(multiValueParams)) {\n\t\t\tif (values && values.length > 1) {\n\t\t\t\tmergedParams[key] = values;\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\tbody: AmazonApiGatewayEndpoint.decodeBody(\n\t\t\t\te.body,\n\t\t\t\te.isBase64Encoded,\n\t\t\t\te.headers?.['Content-Type'] ?? e.headers?.['content-type'],\n\t\t\t),\n\t\t\tquery: parseQueryParams(mergedParams),\n\t\t\tparams: e.pathParameters || {},\n\t\t};\n\t}\n\toverride getLoggerContext(\n\t\tdata: APIGatewayProxyEvent,\n\t\tcontext: Context,\n\t): LoggerContext {\n\t\treturn {\n\t\t\tfn: {\n\t\t\t\tname: context.functionName,\n\t\t\t\tversion: context.functionVersion,\n\t\t\t},\n\t\t\treq: {\n\t\t\t\tid: data.requestContext.requestId,\n\t\t\t\tawsRequestId: context.awsRequestId,\n\t\t\t\tip: data.requestContext.identity.sourceIp,\n\t\t\t\tuserAgent: data.requestContext.identity.userAgent || undefined,\n\t\t\t\tpath: data.requestContext.path,\n\t\t\t},\n\t\t};\n\t}\n\tconstructor(\n\t\tprotected override readonly endpoint: Endpoint<\n\t\t\tTRoute,\n\t\t\tTMethod,\n\t\t\tTInput,\n\t\t\tTOutSchema,\n\t\t\tTServices,\n\t\t\tTLogger,\n\t\t\tTSession\n\t\t>,\n\t\toptions: AmazonApiGatewayEndpointOptions = {},\n\t) {\n\t\tsuper(endpoint, options);\n\t}\n}\n","import type { EventPublisher } from '@geekmidas/events';\nimport type { Logger } from '@geekmidas/logger';\nimport type { Service } from '@geekmidas/services';\nimport type { StandardSchemaV1 } from '@standard-schema/spec';\nimport type { APIGatewayProxyEventV2, Context } from 'aws-lambda';\nimport qs from 'qs';\nimport type { HttpMethod } from '../types';\nimport {\n\tAmazonApiGatewayEndpoint,\n\ttype AmazonApiGatewayEndpointOptions,\n\ttype AmazonApiGatewayV2EndpointHandler,\n\ttype GetInputResponse,\n\ttype LoggerContext,\n} from './AmazonApiGatewayEndpointAdaptor';\nimport type { CookieFn, Endpoint, EndpointSchemas } from './Endpoint';\nimport { createApiGatewayCookies } from './lazyAccessors';\n\nexport class AmazonApiGatewayV2Endpoint<\n\tTRoute extends string,\n\tTMethod extends HttpMethod,\n\tTInput extends EndpointSchemas = {},\n\tTOutSchema extends StandardSchemaV1 | undefined = undefined,\n\tTServices extends Service[] = [],\n\tTLogger extends Logger = Logger,\n\tTSession = unknown,\n> extends AmazonApiGatewayEndpoint<\n\tAmazonApiGatewayV2EndpointHandler,\n\tAPIGatewayProxyEventV2,\n\tTRoute,\n\tTMethod,\n\tTInput,\n\tTOutSchema,\n\tTServices,\n\tTLogger,\n\tTSession\n> {\n\toverride getCookies(e: APIGatewayProxyEventV2): CookieFn {\n\t\treturn createApiGatewayCookies(\n\t\t\te.cookies,\n\t\t\t(e.headers as Record<string, string>)?.cookie,\n\t\t);\n\t}\n\n\toverride getInput(e: APIGatewayProxyEventV2): GetInputResponse {\n\t\tconst raw = AmazonApiGatewayEndpoint.decodeBody(\n\t\t\te.body,\n\t\t\te.isBase64Encoded,\n\t\t\te.headers?.['content-type'],\n\t\t);\n\n\t\treturn {\n\t\t\tbody: raw,\n\t\t\tquery: qs.parse(e.rawQueryString) as Record<string, any>,\n\t\t\tparams: e.pathParameters || {},\n\t\t};\n\t}\n\toverride getLoggerContext(\n\t\tevent: APIGatewayProxyEventV2,\n\t\tcontext: Context,\n\t): LoggerContext {\n\t\treturn {\n\t\t\tfn: {\n\t\t\t\tname: context.functionName,\n\t\t\t\tversion: context.functionVersion,\n\t\t\t},\n\t\t\treq: {\n\t\t\t\tid: event.requestContext.requestId,\n\t\t\t\tawsRequestId: context.awsRequestId,\n\t\t\t\tip: event.requestContext.http.sourceIp,\n\t\t\t\tuserAgent: event.requestContext.http.userAgent || undefined,\n\t\t\t\tpath: event.requestContext.http.path,\n\t\t\t},\n\t\t};\n\t}\n\tconstructor(\n\t\tprotected override readonly endpoint: Endpoint<\n\t\t\tTRoute,\n\t\t\tTMethod,\n\t\t\tTInput,\n\t\t\tTOutSchema,\n\t\t\tTServices,\n\t\t\tTLogger,\n\t\t\tTSession\n\t\t>,\n\t\toptions: AmazonApiGatewayEndpointOptions = {},\n\t) {\n\t\tsuper(endpoint, options);\n\t}\n}\n\n// Re-export options type for convenience\nexport type { AmazonApiGatewayEndpointOptions };\n","import type { EnvironmentParser } from '@geekmidas/envkit';\nimport { wrapError } from '@geekmidas/errors';\nimport type { Logger } from '@geekmidas/logger';\nimport type { InferStandardSchema } from '@geekmidas/schema';\nimport type { Service, ServiceRecord } from '@geekmidas/services';\nimport { runWithRequestContext, ServiceDiscovery } from '@geekmidas/services';\nimport type { StandardSchemaV1 } from '@standard-schema/spec';\nimport type {\n\tContext,\n\tHandler,\n\tSQSBatchResponse,\n\tSQSEvent,\n\tSQSRecord,\n} from 'aws-lambda';\nimport type { Queue, QueueContext } from './Queue';\n\nexport type AWSLambdaHandler<TEvent = any, TResult = any> = Handler<\n\tTEvent,\n\tTResult\n>;\n\n/**\n * Runs a {@link Queue} worker as an AWS Lambda backed by an SQS event-source\n * mapping. Unlike a subscriber, a queue drains *every* record (no type filter):\n * each record body (`{ type, payload }`, as written by the SQS publisher) is\n * unwrapped to its `payload`, validated against the queue's `messageSchema`, and\n * the whole batch is handed to the handler as `messages`.\n *\n * Uses SQS partial-batch responses: a record that fails to parse, validate, or\n * (when the handler throws) process is returned in `batchItemFailures` so SQS\n * retries only those records.\n */\nexport class AWSLambdaQueue<\n\tTName extends string = string,\n\tTMessage extends StandardSchemaV1 = StandardSchemaV1,\n\tTServices extends Service[] = [],\n\tTLogger extends Logger = Logger,\n\tTDatabase = undefined,\n\tTDatabaseServiceName extends string = string,\n> {\n\tprivate _services?: ServiceRecord<TServices>;\n\n\tconstructor(\n\t\tprivate readonly envParser: EnvironmentParser<{}>,\n\t\treadonly queue: Queue<\n\t\t\tTName,\n\t\t\tTMessage,\n\t\t\tTServices,\n\t\t\tTLogger,\n\t\t\tTDatabase,\n\t\t\tTDatabaseServiceName\n\t\t>,\n\t) {}\n\n\tget logger(): TLogger {\n\t\treturn this.queue.logger;\n\t}\n\n\tprivate async getServices(): Promise<ServiceRecord<TServices>> {\n\t\tif (this._services) {\n\t\t\treturn this._services;\n\t\t}\n\n\t\tconst serviceDiscovery = ServiceDiscovery.getInstance(this.envParser);\n\n\t\tthis._services =\n\t\t\tthis.queue.services.length > 0\n\t\t\t\t? ((await serviceDiscovery.register(\n\t\t\t\t\t\tthis.queue.services,\n\t\t\t\t\t)) as ServiceRecord<TServices>)\n\t\t\t\t: ({} as ServiceRecord<TServices>);\n\n\t\treturn this._services;\n\t}\n\n\t/** The queue's database, registered as functions register theirs. */\n\tprivate async getDatabase(): Promise<TDatabase | undefined> {\n\t\tconst service = this.queue.databaseService;\n\t\tif (!service) return undefined;\n\n\t\tconst registered = await ServiceDiscovery.getInstance(\n\t\t\tthis.envParser,\n\t\t).register([service]);\n\n\t\treturn registered[service.serviceName as keyof typeof registered] as\n\t\t\t| TDatabase\n\t\t\t| undefined;\n\t}\n\n\tprivate safeJsonParse(value: string): unknown {\n\t\ttry {\n\t\t\treturn JSON.parse(value);\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Unwrap the queue payload from an SQS record. The SQS publisher writes\n\t * `{ type, payload }`; a payload-only body is also accepted as-is.\n\t */\n\tprivate extractPayload(record: SQSRecord): unknown {\n\t\tconst body = this.safeJsonParse(record.body);\n\t\tif (body && typeof body === 'object' && 'payload' in body) {\n\t\t\treturn (body as { payload: unknown }).payload;\n\t\t}\n\t\treturn body ?? record.body;\n\t}\n\n\tprivate async _handler(\n\t\tevent: SQSEvent,\n\t\tcontext: Context,\n\t): Promise<SQSBatchResponse> {\n\t\tconst logger = this.queue.logger.child({\n\t\t\tqueue: {\n\t\t\t\tname: this.queue.name,\n\t\t\t\tfn: context.functionName,\n\t\t\t},\n\t\t\treq: { id: context.awsRequestId },\n\t\t}) as TLogger;\n\n\t\tconst services = await this.getServices();\n\t\tconst db = await this.getDatabase();\n\t\tconst schema = this.queue.messageSchema;\n\n\t\tconst batchItemFailures: { itemIdentifier: string }[] = [];\n\t\tconst messages: InferStandardSchema<TMessage>[] = [];\n\n\t\tfor (const record of event.Records) {\n\t\t\ttry {\n\t\t\t\tconst payload = this.extractPayload(record);\n\t\t\t\tconst validation = await schema['~standard'].validate(payload);\n\t\t\t\tif (validation.issues) {\n\t\t\t\t\tlogger.error(\n\t\t\t\t\t\t{ issues: validation.issues, messageId: record.messageId },\n\t\t\t\t\t\t'Queue message failed validation',\n\t\t\t\t\t);\n\t\t\t\t\tbatchItemFailures.push({ itemIdentifier: record.messageId });\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tmessages.push(validation.value as InferStandardSchema<TMessage>);\n\t\t\t} catch (error) {\n\t\t\t\tlogger.error(\n\t\t\t\t\t{ error, messageId: record.messageId },\n\t\t\t\t\t'Failed to parse SQS record',\n\t\t\t\t);\n\t\t\t\tbatchItemFailures.push({ itemIdentifier: record.messageId });\n\t\t\t}\n\t\t}\n\n\t\tif (messages.length === 0) {\n\t\t\treturn { batchItemFailures };\n\t\t}\n\n\t\ttry {\n\t\t\t// Cast because `db` is in the context only when TDatabase is set, a\n\t\t\t// condition a generic cannot resolve; `undefined` when it is not.\n\t\t\tawait this.queue.handler({\n\t\t\t\tmessages,\n\t\t\t\tservices,\n\t\t\t\tlogger,\n\t\t\t\tdb,\n\t\t\t} as unknown as QueueContext<TMessage, TServices, TLogger, TDatabase>);\n\t\t} catch (error) {\n\t\t\tlogger.error(wrapError(error), 'Queue handler failed; retrying batch');\n\t\t\t// Handler processes the batch atomically — fail the whole batch so SQS\n\t\t\t// retries every (valid) record.\n\t\t\tfor (const record of event.Records) {\n\t\t\t\tif (\n\t\t\t\t\t!batchItemFailures.some((f) => f.itemIdentifier === record.messageId)\n\t\t\t\t) {\n\t\t\t\t\tbatchItemFailures.push({ itemIdentifier: record.messageId });\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn { batchItemFailures };\n\t}\n\n\tget handler(): AWSLambdaHandler<SQSEvent, SQSBatchResponse> {\n\t\tconst handler = this._handler.bind(this);\n\n\t\treturn (async (event: SQSEvent, context: Context) => {\n\t\t\tconst startTime = Date.now();\n\t\t\tconst requestId = context.awsRequestId;\n\t\t\tconst logger = this.queue.logger.child({ requestId }) as TLogger;\n\n\t\t\treturn runWithRequestContext(\n\t\t\t\t{ logger, requestId, startTime, operation: `queue ${this.queue.name}` },\n\t\t\t\t() => handler(event, context),\n\t\t\t);\n\t\t}) as unknown as AWSLambdaHandler<SQSEvent, SQSBatchResponse>;\n\t}\n}\n","import type { EnvironmentParser } from '@geekmidas/envkit';\nimport { wrapError } from '@geekmidas/errors';\nimport type { EventPublisher } from '@geekmidas/events';\nimport type { Logger } from '@geekmidas/logger';\nimport type { InferStandardSchema } from '@geekmidas/schema';\nimport type { Service, ServiceRecord } from '@geekmidas/services';\nimport { runWithRequestContext } from '@geekmidas/services';\nimport middy, { type MiddlewareObj } from '@middy/core';\nimport type { StandardSchemaV1 } from '@standard-schema/spec';\nimport type { Context, Handler, SNSEvent, SQSEvent } from 'aws-lambda';\nimport {\n\trunSubscriber,\n\tsubscribedEvents,\n\tsubscriberContext,\n} from './runSubscriber';\nimport type { Subscriber } from './Subscriber';\n\nexport type AWSLambdaHandler<TEvent = any, TResult = any> = Handler<\n\tTEvent,\n\tTResult\n>;\n\ntype SubscriberEvent<TServices extends Service[], TLogger extends Logger> = {\n\tevents: any[];\n\tservices: ServiceRecord<TServices>;\n\tlogger: TLogger;\n\t/** The subscriber's database, when it has one. */\n\tdb?: unknown;\n};\n\ntype Middleware<\n\tTServices extends Service[],\n\tTLogger extends Logger,\n\tTOutSchema extends StandardSchemaV1 | undefined,\n> = MiddlewareObj<\n\tSubscriberEvent<TServices, TLogger>,\n\tInferStandardSchema<TOutSchema>,\n\tError,\n\tContext\n>;\n\nexport class AWSLambdaSubscriber<\n\tTServices extends Service[] = [],\n\tTLogger extends Logger = Logger,\n\tOutSchema extends StandardSchemaV1 | undefined = undefined,\n\tTEventPublisher extends EventPublisher<any> | undefined = undefined,\n\tTSubscribedEvents extends any[] = [],\n\tTDatabase = undefined,\n\tTDatabaseServiceName extends string = string,\n> {\n\tprivate _logger!: TLogger;\n\n\tconstructor(\n\t\tprivate envParser: EnvironmentParser<{}>,\n\t\treadonly subscriber: Subscriber<\n\t\t\tTServices,\n\t\t\tTLogger,\n\t\t\tOutSchema,\n\t\t\tTEventPublisher,\n\t\t\tTSubscribedEvents,\n\t\t\tTDatabase,\n\t\t\tTDatabaseServiceName\n\t\t>,\n\t) {\n\t\tthis._logger = subscriber.logger;\n\t}\n\n\tget logger(): TLogger {\n\t\treturn this._logger;\n\t}\n\n\tprivate error(): Middleware<TServices, TLogger, OutSchema> {\n\t\treturn {\n\t\t\tonError: (req) => {\n\t\t\t\tconst logger = req.event?.logger || this.subscriber.logger;\n\t\t\t\tlogger.error(req.error || {}, 'Error processing subscriber');\n\n\t\t\t\t// Re-throw the wrapped error to let Lambda handle it\n\t\t\t\tthrow wrapError(req.error);\n\t\t\t},\n\t\t};\n\t}\n\n\tprivate loggerMiddleware(): Middleware<TServices, TLogger, OutSchema> {\n\t\treturn {\n\t\t\tbefore: (req) => {\n\t\t\t\tthis._logger = this.subscriber.logger.child({\n\t\t\t\t\tsubscriber: {\n\t\t\t\t\t\tname: req.context.functionName,\n\t\t\t\t\t\tversion: req.context.functionVersion,\n\t\t\t\t\t\tmemory: req.context.memoryLimitInMB,\n\t\t\t\t\t},\n\t\t\t\t\treq: {\n\t\t\t\t\t\tid: req.context.awsRequestId,\n\t\t\t\t\t},\n\t\t\t\t}) as TLogger;\n\n\t\t\t\treq.event.logger = this._logger;\n\t\t\t},\n\t\t};\n\t}\n\n\tprivate services(): Middleware<TServices, TLogger, OutSchema> {\n\t\treturn {\n\t\t\tbefore: async (req) => {\n\t\t\t\tconst { services, db } = await subscriberContext(\n\t\t\t\t\tthis.subscriber,\n\t\t\t\t\tthis.envParser,\n\t\t\t\t);\n\t\t\t\treq.event.services = services as ServiceRecord<TServices>;\n\t\t\t\treq.event.db = db;\n\t\t\t},\n\t\t};\n\t}\n\n\tprivate parseEvents(): Middleware<TServices, TLogger, OutSchema> {\n\t\treturn {\n\t\t\tbefore: async (req) => {\n\t\t\t\tconst { logger, ...rawEvent } = req.event;\n\n\t\t\t\tlogger.info({\n\t\t\t\t\trawEvent,\n\t\t\t\t});\n\n\t\t\t\treq.event.events = subscribedEvents(\n\t\t\t\t\tthis.subscriber,\n\t\t\t\t\trawEvent as unknown as SQSEvent | SNSEvent,\n\t\t\t\t\tthis.logger,\n\t\t\t\t);\n\t\t\t},\n\t\t};\n\t}\n\n\tprivate async _handler(event: SubscriberEvent<TServices, TLogger>) {\n\t\t// Only these four: the raw Lambda event stays out of the handler.\n\t\tconst { events, services, logger, db } = event;\n\t\treturn runSubscriber(this.subscriber, {\n\t\t\tevents,\n\t\t\tservices,\n\t\t\tlogger,\n\t\t\tdb,\n\t\t}) as Promise<InferStandardSchema<OutSchema>>;\n\t}\n\n\tget handler(): AWSLambdaHandler {\n\t\tconst handler = this._handler.bind(this);\n\n\t\t// Apply middleware in order\n\t\tconst chain = middy(handler)\n\t\t\t.use(this.loggerMiddleware())\n\t\t\t.use(this.parseEvents())\n\t\t\t.use(this.error())\n\t\t\t.use(this.services());\n\n\t\t// Wrap entire Middy chain in request context for service access\n\t\tconst wrappedHandler = async (event: unknown, context: Context) => {\n\t\t\tconst startTime = Date.now();\n\t\t\tconst requestId = context.awsRequestId;\n\t\t\tconst logger = this.subscriber.logger.child({\n\t\t\t\trequestId,\n\t\t\t}) as TLogger;\n\n\t\t\tconst operation = `subscriber ${this.subscriber.topicName ?? context.functionName}`;\n\t\t\treturn runWithRequestContext(\n\t\t\t\t{ logger, requestId, startTime, operation },\n\t\t\t\t() => chain(event as Parameters<typeof chain>[0], context),\n\t\t\t);\n\t\t};\n\n\t\treturn wrappedHandler as unknown as AWSLambdaHandler;\n\t}\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"aws.cjs","names":["ServiceDiscovery","DefaultAuditor","withAuditableTransaction","FunctionBuilder","publishEvents","wrapError","FunctionBuilder","middy","runWithRequestContext","envParserFor","wrapError","Endpoint","UnprocessableEntityError","ServiceDiscovery","ForbiddenError","publishConstructEvents","createAuditContext","executeWithAuditTransaction","ResponseBuilder","withRlsContext","middy","runWithRequestContext","createApiGatewayCookies","ServiceDiscovery","wrapError","runWithRequestContext","wrapError","subscriberContext","subscribedEvents","runSubscriber","middy","runWithRequestContext"],"sources":["../../src/functions/FunctionExecutionWrapper.ts","../../src/functions/AWSLambdaFunction.ts","../../src/crons/AWSScheduledFunction.ts","../../src/endpoints/AmazonApiGatewayEndpointAdaptor.ts","../../src/endpoints/parseQueryParams.ts","../../src/endpoints/AmazonApiGatewayV1EndpointAdaptor.ts","../../src/endpoints/AmazonApiGatewayV2EndpointAdaptor.ts","../../src/queue/AWSLambdaQueueAdaptor.ts","../../src/subscribers/AWSLambdaSubscriberAdaptor.ts"],"sourcesContent":["import type { AuditableAction, Auditor, AuditStorage } from '@geekmidas/audit';\nimport { DefaultAuditor } from '@geekmidas/audit';\nimport { withAuditableTransaction } from '@geekmidas/audit/kysely';\nimport type { EnvironmentParser } from '@geekmidas/envkit';\nimport type { EventPublisher } from '@geekmidas/events';\nimport type { Logger } from '@geekmidas/logger';\nimport type {\n\tComposableStandardSchema,\n\tInferComposableStandardSchema,\n\tInferStandardSchema,\n} from '@geekmidas/schema';\nimport {\n\ttype Service,\n\tServiceDiscovery,\n\ttype ServiceRecord,\n} from '@geekmidas/services';\nimport type { StandardSchemaV1 } from '@standard-schema/spec';\nimport { publishEvents } from '../publisher';\nimport type { Function, FunctionHandler } from './Function';\nimport { FunctionBuilder } from './FunctionBuilder';\n\nexport abstract class FunctionExecutionWrapper<\n\tTInput extends ComposableStandardSchema | undefined = undefined,\n\tTOutSchema extends StandardSchemaV1 | undefined = undefined,\n\tTServices extends Service[] = [],\n\tTLogger extends Logger = Logger,\n\tTAuditStorage extends AuditStorage | undefined = undefined,\n\tTAuditStorageServiceName extends string = string,\n\tTDatabase = undefined,\n\tTDatabaseServiceName extends string = string,\n\tTAuditAction extends AuditableAction<string, unknown> = AuditableAction<\n\t\tstring,\n\t\tunknown\n\t>,\n> {\n\tconstructor(\n\t\tprotected envParser: EnvironmentParser<{}>,\n\t\tprotected readonly fn: Function<\n\t\t\tTInput,\n\t\t\tTServices,\n\t\t\tTLogger,\n\t\t\tTOutSchema,\n\t\t\tTAuditStorage,\n\t\t\tTAuditStorageServiceName,\n\t\t\tTDatabase,\n\t\t\tTDatabaseServiceName,\n\t\t\tTAuditAction,\n\t\t\tFunctionHandler<\n\t\t\t\tTInput,\n\t\t\t\tTServices,\n\t\t\t\tTLogger,\n\t\t\t\tTOutSchema,\n\t\t\t\tTDatabase,\n\t\t\t\tTAuditStorage,\n\t\t\t\tTAuditAction\n\t\t\t>\n\t\t>,\n\t) {}\n\n\tprotected _logger?: TLogger;\n\n\tget logger(): TLogger {\n\t\treturn this._logger || this.fn.logger;\n\t}\n\n\tget serviceDiscovery(): ServiceDiscovery<ServiceRecord<TServices>> {\n\t\tconst serviceDiscovery = ServiceDiscovery.getInstance<\n\t\t\tServiceRecord<TServices>\n\t\t>(this.envParser);\n\n\t\treturn serviceDiscovery;\n\t}\n\n\tgetServices(): Promise<ServiceRecord<TServices>> {\n\t\treturn this.serviceDiscovery.register(this.fn.services);\n\t}\n\n\tasync getDatabase(): Promise<TDatabase | undefined> {\n\t\tif (!this.fn.databaseService) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst services = await this.serviceDiscovery.register([\n\t\t\tthis.fn.databaseService,\n\t\t]);\n\n\t\treturn services[\n\t\t\tthis.fn.databaseService.serviceName as keyof typeof services\n\t\t] as TDatabase;\n\t}\n\n\t/**\n\t * Get the audit storage service if configured.\n\t * Returns undefined if no auditor storage is configured.\n\t */\n\tasync getAuditStorage(): Promise<TAuditStorage | undefined> {\n\t\tif (!this.fn.auditorStorageService) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tconst services = await this.serviceDiscovery.register([\n\t\t\tthis.fn.auditorStorageService,\n\t\t]);\n\n\t\treturn services[\n\t\t\tthis.fn.auditorStorageService.serviceName as keyof typeof services\n\t\t] as TAuditStorage;\n\t}\n\n\t/**\n\t * Create an auditor instance for the function.\n\t * Returns undefined if no auditor storage is configured.\n\t */\n\tasync createAuditor(): Promise<Auditor<TAuditAction> | undefined> {\n\t\tconst storage = await this.getAuditStorage();\n\t\tif (!storage) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn new DefaultAuditor<TAuditAction>({\n\t\t\tactor: { id: 'system', type: 'system' },\n\t\t\tstorage: storage as AuditStorage,\n\t\t\tmetadata: {\n\t\t\t\tfunction: this.fn.type,\n\t\t\t},\n\t\t});\n\t}\n\n\t/**\n\t * Execute handler with audit transaction support.\n\t * If the audit storage has a database (via getDatabase()), wraps execution\n\t * in a transaction so audits are atomic with handler's database operations.\n\t *\n\t * @param handler - The handler function to execute (receives auditor and db)\n\t * @returns The handler result\n\t */\n\tasync executeWithAudit<T>(\n\t\thandler: (ctx: {\n\t\t\tauditor?: Auditor<TAuditAction>;\n\t\t\tdb?: TDatabase;\n\t\t}) => Promise<T>,\n\t): Promise<T> {\n\t\tconst auditor = await this.createAuditor();\n\t\tconst storage = await this.getAuditStorage();\n\n\t\t// No audit context - just run handler with regular db\n\t\tif (!auditor || !storage) {\n\t\t\tconst db = await this.getDatabase();\n\t\t\treturn handler({ db });\n\t\t}\n\n\t\t// Check if storage has a database and db service names match\n\t\tconst storageDb = (storage as AuditStorage).getDatabase?.();\n\t\tconst databaseServiceName = this.fn.databaseService?.serviceName;\n\t\tconst auditDbServiceName = this.fn.auditorStorageService?.serviceName;\n\n\t\t// If the audit storage has a database and we're using the same database service\n\t\t// (or the audit storage provides the database), use transactional execution\n\t\tif (storageDb && databaseServiceName && auditDbServiceName) {\n\t\t\treturn withAuditableTransaction(\n\t\t\t\tstorageDb as any,\n\t\t\t\tauditor as any,\n\t\t\t\tasync (trx) => {\n\t\t\t\t\t// Use transaction as db\n\t\t\t\t\tconst response = await handler({\n\t\t\t\t\t\tauditor,\n\t\t\t\t\t\tdb: trx as TDatabase,\n\t\t\t\t\t});\n\t\t\t\t\t// Audits are flushed by withAuditableTransaction before commit\n\t\t\t\t\treturn response;\n\t\t\t\t},\n\t\t\t);\n\t\t}\n\n\t\t// No database on storage or service names don't match - run handler and flush audits after\n\t\tconst db = await this.getDatabase();\n\t\tconst response = await handler({ auditor, db });\n\n\t\t// Flush audits (no transaction)\n\t\tawait auditor.flush();\n\n\t\treturn response;\n\t}\n\n\tasync getFunctionInput<TEvent>(\n\t\tevent: TEvent,\n\t): Promise<InferComposableStandardSchema<TInput>> {\n\t\tconst parsedInput = await FunctionBuilder.parseComposableStandardSchema(\n\t\t\tevent,\n\t\t\tthis.fn.input,\n\t\t);\n\n\t\treturn parsedInput as InferComposableStandardSchema<TInput>;\n\t}\n\n\tasync publishEvents(response: InferStandardSchema<TOutSchema>) {\n\t\tawait publishEvents(\n\t\t\tthis.logger,\n\t\t\tthis.serviceDiscovery,\n\t\t\tthis.fn.events,\n\t\t\tresponse,\n\t\t);\n\t}\n\n\tasync parseComposableStandardSchema<T extends ComposableStandardSchema>(\n\t\tdata: unknown,\n\t\tschema: T,\n\t): Promise<InferComposableStandardSchema<T>> {\n\t\treturn FunctionBuilder.parseComposableStandardSchema(data, schema);\n\t}\n}\n","import type { AuditableAction, Auditor, AuditStorage } from '@geekmidas/audit';\nimport type { EnvironmentParser } from '@geekmidas/envkit';\nimport { wrapError } from '@geekmidas/errors';\nimport type { EventPublisher } from '@geekmidas/events';\nimport type { Logger } from '@geekmidas/logger';\nimport type {\n\tComposableStandardSchema,\n\tInferComposableStandardSchema,\n\tInferStandardSchema,\n} from '@geekmidas/schema';\nimport type { Service, ServiceRecord } from '@geekmidas/services';\nimport { runWithRequestContext } from '@geekmidas/services';\nimport middy, { type MiddlewareObj } from '@middy/core';\nimport type { StandardSchemaV1 } from '@standard-schema/spec';\nimport type { Context, Handler } from 'aws-lambda';\nimport type { Function, FunctionHandler } from './Function';\nimport { FunctionBuilder } from './FunctionBuilder';\nimport { FunctionExecutionWrapper } from './FunctionExecutionWrapper';\n\nexport type AWSLambdaHandler<TEvent = any, TResult = any> = Handler<\n\tTEvent,\n\tTResult\n>;\n\ntype FunctionEvent<\n\tTEvent,\n\tTInput extends ComposableStandardSchema | undefined,\n\tTServices extends Service[],\n\tTLogger extends Logger,\n\tTDatabase = undefined,\n\tTAuditAction extends AuditableAction<string, unknown> = AuditableAction<\n\t\tstring,\n\t\tunknown\n\t>,\n> = TEvent & {\n\tparsedInput: InferComposableStandardSchema<TInput>;\n\tservices: ServiceRecord<TServices>;\n\tlogger: TLogger;\n\tdb: TDatabase | undefined;\n\tauditor: Auditor<TAuditAction> | undefined;\n};\n\ntype Middleware<\n\tTEvent,\n\tTInput extends ComposableStandardSchema | undefined,\n\tTServices extends Service[],\n\tTLogger extends Logger,\n\tTOutSchema extends StandardSchemaV1 | undefined,\n\tTDatabase = undefined,\n\tTAuditAction extends AuditableAction<string, unknown> = AuditableAction<\n\t\tstring,\n\t\tunknown\n\t>,\n> = MiddlewareObj<\n\tFunctionEvent<TEvent, TInput, TServices, TLogger, TDatabase, TAuditAction>,\n\tInferComposableStandardSchema<TOutSchema>,\n\tError,\n\tContext\n>;\n\nexport class AWSLambdaFunction<\n\tTInput extends ComposableStandardSchema | undefined = undefined,\n\tTOutSchema extends StandardSchemaV1 | undefined = undefined,\n\tTServices extends Service[] = [],\n\tTLogger extends Logger = Logger,\n\tTAuditStorage extends AuditStorage | undefined = undefined,\n\tTAuditStorageServiceName extends string = string,\n\tTDatabase = undefined,\n\tTDatabaseServiceName extends string = string,\n\tTAuditAction extends AuditableAction<string, unknown> = AuditableAction<\n\t\tstring,\n\t\tunknown\n\t>,\n> extends FunctionExecutionWrapper<\n\tTInput,\n\tTOutSchema,\n\tTServices,\n\tTLogger,\n\tTAuditStorage,\n\tTAuditStorageServiceName,\n\tTDatabase,\n\tTDatabaseServiceName,\n\tTAuditAction\n> {\n\tconstructor(\n\t\tenvParser: EnvironmentParser<{}>,\n\t\toverride readonly fn: Function<\n\t\t\tTInput,\n\t\t\tTServices,\n\t\t\tTLogger,\n\t\t\tTOutSchema,\n\t\t\tTAuditStorage,\n\t\t\tTAuditStorageServiceName,\n\t\t\tTDatabase,\n\t\t\tTDatabaseServiceName,\n\t\t\tTAuditAction,\n\t\t\tFunctionHandler<\n\t\t\t\tTInput,\n\t\t\t\tTServices,\n\t\t\t\tTLogger,\n\t\t\t\tTOutSchema,\n\t\t\t\tTDatabase,\n\t\t\t\tTAuditStorage,\n\t\t\t\tTAuditAction\n\t\t\t>\n\t\t>,\n\t) {\n\t\tsuper(envParser, fn);\n\t}\n\n\tprivate error<TEvent>(): Middleware<\n\t\tTEvent,\n\t\tTInput,\n\t\tTServices,\n\t\tTLogger,\n\t\tTOutSchema,\n\t\tTDatabase,\n\t\tTAuditAction\n\t> {\n\t\treturn {\n\t\t\tonError: (req) => {\n\t\t\t\tconst logger = req.event?.logger || this.fn.logger;\n\t\t\t\tlogger.error(req.error || {}, 'Error processing function');\n\n\t\t\t\t// Re-throw the wrapped error to let Lambda handle it\n\t\t\t\tthrow wrapError(req.error);\n\t\t\t},\n\t\t};\n\t}\n\n\tprivate baseInput<TEvent>(): Middleware<\n\t\tTEvent,\n\t\tTInput,\n\t\tTServices,\n\t\tTLogger,\n\t\tTOutSchema,\n\t\tTDatabase,\n\t\tTAuditAction\n\t> {\n\t\treturn {\n\t\t\tbefore: (_req) => {},\n\t\t};\n\t}\n\n\tprivate input<\n\t\tTEvent extends { input: InferComposableStandardSchema<TInput> },\n\t>(): Middleware<\n\t\tTEvent,\n\t\tTInput,\n\t\tTServices,\n\t\tTLogger,\n\t\tTOutSchema,\n\t\tTDatabase,\n\t\tTAuditAction\n\t> {\n\t\treturn {\n\t\t\tbefore: async (req) => {\n\t\t\t\ttry {\n\t\t\t\t\t// Parse input if schema is provided\n\t\t\t\t\tif (this.fn.input) {\n\t\t\t\t\t\tconst parsedInput =\n\t\t\t\t\t\t\tawait FunctionBuilder.parseComposableStandardSchema(\n\t\t\t\t\t\t\t\treq.event,\n\t\t\t\t\t\t\t\tthis.fn.input,\n\t\t\t\t\t\t\t);\n\n\t\t\t\t\t\treq.event.parsedInput =\n\t\t\t\t\t\t\tparsedInput as InferComposableStandardSchema<TInput>;\n\t\t\t\t\t} else {\n\t\t\t\t\t\t// If no schema, pass the event as-is\n\t\t\t\t\t\treq.event.parsedInput = req.event as any;\n\t\t\t\t\t}\n\t\t\t\t} catch (error) {\n\t\t\t\t\tthis.logger.error(\n\t\t\t\t\t\t{ err: error, event: req.event },\n\t\t\t\t\t\t'Failed to parse input',\n\t\t\t\t\t);\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t},\n\t\t};\n\t}\n\n\tprivate loggerMiddleware<TEvent>(): Middleware<\n\t\tTEvent,\n\t\tTInput,\n\t\tTServices,\n\t\tTLogger,\n\t\tTOutSchema,\n\t\tTDatabase,\n\t\tTAuditAction\n\t> {\n\t\treturn {\n\t\t\tbefore: (req) => {\n\t\t\t\tthis._logger = this.fn.logger.child({\n\t\t\t\t\tfn: {\n\t\t\t\t\t\tname: req.context.functionName,\n\t\t\t\t\t\tversion: req.context.functionVersion,\n\t\t\t\t\t\tmemory: req.context.memoryLimitInMB,\n\t\t\t\t\t},\n\t\t\t\t\treq: {\n\t\t\t\t\t\tid: req.context.awsRequestId,\n\t\t\t\t\t},\n\t\t\t\t}) as TLogger;\n\n\t\t\t\treq.event.logger = this._logger;\n\t\t\t},\n\t\t};\n\t}\n\n\tprivate services<TEvent>(): Middleware<\n\t\tTEvent,\n\t\tTInput,\n\t\tTServices,\n\t\tTLogger,\n\t\tTOutSchema,\n\t\tTDatabase,\n\t\tTAuditAction\n\t> {\n\t\treturn {\n\t\t\tbefore: async (req) => {\n\t\t\t\treq.event.services = await this.getServices();\n\t\t\t},\n\t\t};\n\t}\n\n\tprivate database<TEvent>(): Middleware<\n\t\tTEvent,\n\t\tTInput,\n\t\tTServices,\n\t\tTLogger,\n\t\tTOutSchema,\n\t\tTDatabase,\n\t\tTAuditAction\n\t> {\n\t\treturn {\n\t\t\tbefore: async (req) => {\n\t\t\t\treq.event.db = await this.getDatabase();\n\t\t\t},\n\t\t};\n\t}\n\n\tprivate auditor<TEvent>(): Middleware<\n\t\tTEvent,\n\t\tTInput,\n\t\tTServices,\n\t\tTLogger,\n\t\tTOutSchema,\n\t\tTDatabase,\n\t\tTAuditAction\n\t> {\n\t\treturn {\n\t\t\tbefore: async (req) => {\n\t\t\t\treq.event.auditor = await this.createAuditor();\n\t\t\t},\n\t\t\tafter: async (req) => {\n\t\t\t\t// Flush any pending audits after successful execution\n\t\t\t\tif (req.event.auditor) {\n\t\t\t\t\tconst records = req.event.auditor.getRecords();\n\t\t\t\t\tif (records.length > 0) {\n\t\t\t\t\t\tthis.logger.debug(\n\t\t\t\t\t\t\t{ auditCount: records.length },\n\t\t\t\t\t\t\t'Flushing function audits',\n\t\t\t\t\t\t);\n\t\t\t\t\t\tawait req.event.auditor.flush();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t};\n\t}\n\n\tprivate events<TEvent>(): Middleware<\n\t\tTEvent,\n\t\tTInput,\n\t\tTServices,\n\t\tTLogger,\n\t\tTOutSchema,\n\t\tTDatabase,\n\t\tTAuditAction\n\t> {\n\t\treturn {\n\t\t\tafter: async (req) => {\n\t\t\t\tconst response = (req.response ||\n\t\t\t\t\tundefined) as InferStandardSchema<TOutSchema>;\n\t\t\t\tawait this.publishEvents(response);\n\t\t\t},\n\t\t};\n\t}\n\n\tprivate async _handler<TEvent>(\n\t\tevent: FunctionEvent<\n\t\t\tTEvent,\n\t\t\tTInput,\n\t\t\tTServices,\n\t\t\tTLogger,\n\t\t\tTDatabase,\n\t\t\tTAuditAction\n\t\t>,\n\t) {\n\t\t// Execute the function with the parsed context\n\t\tconst result = await this.fn.fn({\n\t\t\tinput: event.parsedInput,\n\t\t\tservices: event.services,\n\t\t\tlogger: event.logger,\n\t\t\tdb: event.db,\n\t\t\tauditor: event.auditor,\n\t\t} as any);\n\n\t\t// Parse output if schema is provided\n\t\tconst output = await this.fn.parseOutput(result);\n\n\t\treturn output;\n\t}\n\n\tget handler(): AWSLambdaHandler {\n\t\tconst handler = this._handler.bind(this);\n\n\t\t// Apply middleware in order\n\t\tconst chain = middy(handler)\n\t\t\t.use(this.loggerMiddleware())\n\t\t\t.use(this.baseInput())\n\t\t\t.use(this.error())\n\t\t\t.use(this.services())\n\t\t\t.use(this.database())\n\t\t\t.use(this.auditor())\n\t\t\t.use(this.input())\n\t\t\t.use(this.events());\n\n\t\t// Wrap entire Middy chain in request context for service access\n\t\tconst wrappedHandler = async (event: unknown, context: Context) => {\n\t\t\tconst startTime = Date.now();\n\t\t\tconst requestId = context.awsRequestId;\n\t\t\tconst logger = this.fn.logger.child({ requestId }) as TLogger;\n\n\t\t\treturn runWithRequestContext(\n\t\t\t\t{ logger, requestId, startTime, operation: context.functionName },\n\t\t\t\t() => chain(event as Parameters<typeof chain>[0], context),\n\t\t\t);\n\t\t};\n\n\t\treturn wrappedHandler as unknown as AWSLambdaHandler;\n\t}\n}\n","import type { EnvironmentParser } from '@geekmidas/envkit';\nimport type { EventPublisher } from '@geekmidas/events';\nimport type { Logger } from '@geekmidas/logger';\nimport type { ComposableStandardSchema } from '@geekmidas/schema';\nimport type { Service } from '@geekmidas/services';\nimport type { StandardSchemaV1 } from '@standard-schema/spec';\nimport { AWSLambdaFunction } from '../functions/AWSLambdaFunction';\nimport type { Cron } from './Cron';\n\n/**\n * AWS Lambda adaptor for {@link Cron} constructs.\n *\n * A `Cron` is a {@link import('../functions').Function} that is invoked on a\n * schedule (an EventBridge rule) rather than by an API request. Because of\n * that, the runtime execution pipeline is identical to a regular Lambda\n * function: input parsing, service/database/auditor wiring, event publishing,\n * error handling, and the `runWithRequestContext` wrapper that powers\n * request-scoped logging via `serviceContext.getLogger()`.\n *\n * This adaptor therefore reuses {@link AWSLambdaFunction} wholesale and only\n * narrows the constructor to accept a `Cron`. The schedule expression itself\n * (`cron.schedule`) is **deploy-time** infrastructure consumed by the CLI to\n * provision the EventBridge rule — it is not needed at runtime.\n *\n * @example\n * ```typescript\n * import { AWSScheduledFunction } from '@geekmidas/constructs/crons';\n * import { cancelPastBookings } from '../../../src/crons/cancelPastBookings.js';\n * import { envParser } from '../../../src/env';\n *\n * const adapter = new AWSScheduledFunction(envParser, cancelPastBookings);\n *\n * export const handler = adapter.handler;\n * ```\n */\nexport class AWSScheduledFunction<\n\tTInput extends ComposableStandardSchema | undefined = undefined,\n\tTServices extends Service[] = [],\n\tTLogger extends Logger = Logger,\n\tTOutSchema extends StandardSchemaV1 | undefined = undefined,\n\tTDatabase = undefined,\n\tTDatabaseServiceName extends string = string,\n> extends AWSLambdaFunction<\n\tTInput,\n\tTOutSchema,\n\tTServices,\n\tTLogger,\n\tundefined,\n\tstring,\n\tTDatabase,\n\tTDatabaseServiceName\n> {\n\t// biome-ignore lint/complexity/noUselessConstructor: narrows the inherited `Function` parameter to `Cron` for a clearer public API\n\tconstructor(\n\t\tenvParser: EnvironmentParser<{}>,\n\t\tcron: Cron<\n\t\t\tTInput,\n\t\t\tTServices,\n\t\t\tTLogger,\n\t\t\tTOutSchema,\n\t\t\tTDatabase,\n\t\t\tTDatabaseServiceName\n\t\t>,\n\t) {\n\t\tsuper(envParser, cron);\n\t}\n}\n","import type { AuditableAction, AuditStorage } from '@geekmidas/audit';\nimport { withRlsContext } from '@geekmidas/db/rls';\nimport type { EnvironmentParser } from '@geekmidas/envkit';\nimport type { Logger } from '@geekmidas/logger';\nimport middy, { type MiddlewareObj } from '@middy/core';\nimport type { StandardSchemaV1 } from '@standard-schema/spec';\nimport type {\n\tAPIGatewayProxyEvent,\n\tAPIGatewayProxyEventV2,\n\tContext,\n} from 'aws-lambda';\nimport set from 'lodash.set';\nimport type { Telemetry } from '../telemetry';\nimport type { HttpMethod } from '../types';\nimport { Endpoint, type EndpointSchemas, ResponseBuilder } from './Endpoint';\nimport { envParserFor } from './surfaceEnv';\n\n/**\n * Telescope integration for request recording.\n * Uses Middy middleware pattern for compatibility with existing telescope package.\n */\nexport interface TelescopeIntegration {\n\tmiddleware: MiddlewareObj<any, any, Error, Context>;\n}\n\nimport {\n\tForbiddenError,\n\tUnprocessableEntityError,\n\twrapError,\n} from '@geekmidas/errors';\nimport type { EventPublisher } from '@geekmidas/events';\nimport type {\n\tInferComposableStandardSchema,\n\tInferStandardSchema,\n} from '@geekmidas/schema';\nimport {\n\trunWithRequestContext,\n\ttype Service,\n\tServiceDiscovery,\n\ttype ServiceRecord,\n} from '@geekmidas/services';\nimport { publishConstructEvents } from '../publisher';\nimport type { MappedAudit } from './audit';\nimport type { CookieFn, HeaderFn } from './Endpoint';\nimport {\n\tcreateAuditContext,\n\texecuteWithAuditTransaction,\n} from './processAudits';\n\n// Helper function to publish events\n\n/**\n * Options for Amazon API Gateway endpoint adaptors\n */\nexport interface AmazonApiGatewayEndpointOptions {\n\t/**\n\t * Telescope integration for request recording and monitoring.\n\t *\n\t * @example\n\t * ```typescript\n\t * import { telescopeMiddleware } from '@geekmidas/telescope/lambda';\n\t *\n\t * const adaptor = new AmazonApiGatewayV2Endpoint(endpoint, {\n\t * telescope: { middleware: telescopeMiddleware(telescope) },\n\t * });\n\t * ```\n\t */\n\ttelescope?: TelescopeIntegration;\n\n\t/**\n\t * Telemetry integration for distributed tracing.\n\t * Works with any OpenTelemetry-compatible backend.\n\t *\n\t * @example\n\t * ```typescript\n\t * import { OTelTelemetry } from '@geekmidas/telescope/instrumentation';\n\t *\n\t * const adaptor = new AmazonApiGatewayV2Endpoint(endpoint, {\n\t * telemetry: new OTelTelemetry(),\n\t * });\n\t * ```\n\t */\n\ttelemetry?: Telemetry;\n}\n\nexport abstract class AmazonApiGatewayEndpoint<\n\tTHandler extends\n\t\t| AmazonApiGatewayV1EndpointHandler\n\t\t| AmazonApiGatewayV2EndpointHandler,\n\tTEvent extends HandlerEvent<THandler>,\n\tTRoute extends string,\n\tTMethod extends HttpMethod,\n\tTInput extends EndpointSchemas = {},\n\tTOutSchema extends StandardSchemaV1 | undefined = undefined,\n\tTServices extends Service[] = [],\n\tTLogger extends Logger = Logger,\n\tTSession = unknown,\n\tTAuditStorage extends AuditStorage | undefined = undefined,\n\tTAuditStorageServiceName extends string = string,\n\tTAuditAction extends AuditableAction<string, unknown> = AuditableAction<\n\t\tstring,\n\t\tunknown\n\t>,\n> {\n\tprotected options: AmazonApiGatewayEndpointOptions;\n\n\t/**\n\t * The parser this adaptor discovers services with.\n\t *\n\t * Taken from the endpoint's surface rather than handed in. An endpoint built\n\t * with `api.get()` carries its API, and the API carries the parser — so a\n\t * generated handler is `new AmazonApiGatewayV2Endpoint(endpoint)` with no\n\t * import written for it, which is the whole reason the surface is the\n\t * factory.\n\t */\n\tprotected envParser: EnvironmentParser<{}>;\n\n\tconstructor(\n\t\tprotected readonly endpoint: Endpoint<\n\t\t\tTRoute,\n\t\t\tTMethod,\n\t\t\tTInput,\n\t\t\tTOutSchema,\n\t\t\tTServices,\n\t\t\tTLogger,\n\t\t\tTSession,\n\t\t\tTAuditStorage,\n\t\t\tTAuditStorageServiceName,\n\t\t\tTAuditAction\n\t\t>,\n\t\toptions: AmazonApiGatewayEndpointOptions = {},\n\t) {\n\t\tthis.options = options;\n\t\tthis.envParser = envParserFor(endpoint.surface);\n\t}\n\n\tprivate error(): Middleware<TEvent, TInput, TServices, TLogger> {\n\t\treturn {\n\t\t\tonError: (req) => {\n\t\t\t\t(req.event.logger || this.endpoint.logger).error(\n\t\t\t\t\treq.error || {},\n\t\t\t\t\t'Error processing request',\n\t\t\t\t);\n\t\t\t\tconst wrappedError = wrapError(req.error);\n\n\t\t\t\t// Set the response with the proper status code from the HttpError\n\t\t\t\treq.response = {\n\t\t\t\t\tstatusCode: wrappedError.statusCode,\n\t\t\t\t\tbody: wrappedError.body,\n\t\t\t\t};\n\t\t\t},\n\t\t};\n\t}\n\tabstract getInput(e: TEvent): GetInputResponse;\n\n\t/**\n\t * Decodes the raw body from an API Gateway event.\n\t * Uses Content-Type to decide parsing strategy (like Express/Fastify/Hono):\n\t * - `application/json` (or missing) → JSON.parse the decoded string\n\t * - Anything else → return decoded string as-is, let the schema handle it\n\t *\n\t * Defaults to JSON when no Content-Type is provided for backwards compatibility.\n\t */\n\tstatic decodeBody(\n\t\tbody: string | undefined | null,\n\t\tisBase64Encoded: boolean | undefined,\n\t\tcontentType: string | undefined,\n\t): any {\n\t\tif (!body) return undefined;\n\n\t\tconst raw = isBase64Encoded\n\t\t\t? Buffer.from(body, 'base64').toString('utf-8')\n\t\t\t: body;\n\n\t\tconst isJson =\n\t\t\t!contentType || contentType.toLowerCase().includes('application/json');\n\t\tif (isJson) {\n\t\t\treturn JSON.parse(raw);\n\t\t}\n\n\t\treturn raw;\n\t}\n\n\tprotected getCookies(e: TEvent): CookieFn {\n\t\tconst headers = e.headers as Record<string, string>;\n\t\treturn Endpoint.createCookies(headers?.cookie);\n\t}\n\n\tprivate input(): Middleware<TEvent, TInput, TServices, TLogger> {\n\t\treturn {\n\t\t\tbefore: async (req) => {\n\t\t\t\ttry {\n\t\t\t\t\tconst { body, query, params } = this.getInput(req.event);\n\t\t\t\t\tconst headers = req.event.headers as Record<string, string>;\n\t\t\t\t\tconst header = Endpoint.createHeaders(headers);\n\t\t\t\t\tconst cookie = this.getCookies(req.event);\n\n\t\t\t\t\tset(req.event, 'body', await this.endpoint.parseInput(body, 'body'));\n\n\t\t\t\t\tset(\n\t\t\t\t\t\treq.event,\n\t\t\t\t\t\t'query',\n\t\t\t\t\t\tawait this.endpoint.parseInput(query, 'query'),\n\t\t\t\t\t);\n\t\t\t\t\tset(\n\t\t\t\t\t\treq.event,\n\t\t\t\t\t\t'params',\n\t\t\t\t\t\tawait this.endpoint.parseInput(params, 'params'),\n\t\t\t\t\t);\n\t\t\t\t\tset(req.event, 'header', header);\n\t\t\t\t\tset(req.event, 'cookie', cookie);\n\t\t\t\t} catch (error) {\n\t\t\t\t\t// Convert validation errors to 422 Unprocessable Entity\n\t\t\t\t\tif (error && typeof error === 'object' && Array.isArray(error)) {\n\t\t\t\t\t\tthrow new UnprocessableEntityError('Validation failed', error);\n\t\t\t\t\t}\n\t\t\t\t\tthrow error;\n\t\t\t\t}\n\t\t\t},\n\t\t};\n\t}\n\n\tabstract getLoggerContext(data: TEvent, context: Context): LoggerContext;\n\n\tprivate logger(): Middleware<TEvent, TInput, TServices, TLogger> {\n\t\treturn {\n\t\t\tbefore: (req) => {\n\t\t\t\treq.event.logger = this.endpoint.logger.child({\n\t\t\t\t\troute: this.endpoint.route,\n\t\t\t\t\thost: req.event.headers?.host,\n\t\t\t\t\tmethod: this.endpoint.method,\n\t\t\t\t\t...this.getLoggerContext(req.event, req.context),\n\t\t\t\t}) as TLogger;\n\t\t\t},\n\t\t};\n\t}\n\tprivate services(): Middleware<TEvent, TInput, TServices, TLogger> {\n\t\treturn {\n\t\t\tbefore: async (req) => {\n\t\t\t\tconst _logger = req.event.logger as TLogger;\n\t\t\t\tconst serviceDiscovery = ServiceDiscovery.getInstance<\n\t\t\t\t\tServiceRecord<TServices>\n\t\t\t\t>(this.envParser);\n\n\t\t\t\tconst services = await serviceDiscovery.register(\n\t\t\t\t\tthis.endpoint.services,\n\t\t\t\t);\n\n\t\t\t\treq.event.services = services;\n\t\t\t},\n\t\t};\n\t}\n\n\tprivate authorize(): Middleware<TEvent, TInput, TServices, TLogger> {\n\t\treturn {\n\t\t\tbefore: async (req) => {\n\t\t\t\tconst logger = req.event.logger as TLogger;\n\t\t\t\tconst services = req.event.services;\n\t\t\t\tconst header = req.event.header;\n\t\t\t\tconst cookie = req.event.cookie;\n\t\t\t\tconst session = req.event.session as TSession;\n\n\t\t\t\tconst isAuthorized = await this.endpoint.authorize({\n\t\t\t\t\theader,\n\t\t\t\t\tcookie,\n\t\t\t\t\tservices,\n\t\t\t\t\tlogger,\n\t\t\t\t\tsession,\n\t\t\t\t\t...((req.event as any).db !== undefined && {\n\t\t\t\t\t\tdb: (req.event as any).db,\n\t\t\t\t\t}),\n\t\t\t\t\tbody: (req.event as any).body,\n\t\t\t\t\tquery: (req.event as any).query,\n\t\t\t\t\tparams: (req.event as any).params,\n\t\t\t\t} as any);\n\n\t\t\t\tif (!isAuthorized) {\n\t\t\t\t\tlogger.warn('Forbidden access attempt');\n\t\t\t\t\tthrow new ForbiddenError(\n\t\t\t\t\t\t'Forbidden access to the endpoint',\n\t\t\t\t\t\t'You do not have permission to access this resource.',\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t},\n\t\t};\n\t}\n\n\tprivate database(): Middleware<TEvent, TInput, TServices, TLogger> {\n\t\treturn {\n\t\t\tbefore: async (req) => {\n\t\t\t\tif (!this.endpoint.databaseService) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tconst _logger = req.event.logger as TLogger;\n\t\t\t\tconst serviceDiscovery = ServiceDiscovery.getInstance<\n\t\t\t\t\tServiceRecord<TServices>\n\t\t\t\t>(this.envParser);\n\n\t\t\t\tconst db = await serviceDiscovery\n\t\t\t\t\t.register([this.endpoint.databaseService])\n\t\t\t\t\t.then(\n\t\t\t\t\t\t(s) =>\n\t\t\t\t\t\t\ts[this.endpoint.databaseService?.serviceName as keyof typeof s],\n\t\t\t\t\t);\n\n\t\t\t\t(req.event as any).db = db;\n\t\t\t},\n\t\t};\n\t}\n\n\tprivate session(): Middleware<TEvent, TInput, TServices, TLogger> {\n\t\treturn {\n\t\t\tbefore: async (req) => {\n\t\t\t\tconst logger = req.event.logger as TLogger;\n\t\t\t\tconst services = req.event.services;\n\t\t\t\tconst db = (req.event as any).db;\n\t\t\t\treq.event.session = (await this.endpoint.getSession({\n\t\t\t\t\tlogger,\n\t\t\t\t\tservices,\n\t\t\t\t\theader: req.event.header,\n\t\t\t\t\tcookie: req.event.cookie,\n\t\t\t\t\t...(db !== undefined && { db }),\n\t\t\t\t} as any)) as TSession;\n\t\t\t},\n\t\t};\n\t}\n\n\tprivate events(): Middleware<TEvent, TInput, TServices, TLogger> {\n\t\treturn {\n\t\t\tafter: async (req) => {\n\t\t\t\tconst event = req.event;\n\t\t\t\tconst response = (event as any)\n\t\t\t\t\t.__response as InferStandardSchema<TOutSchema>;\n\t\t\t\tconst statusCode = req.response?.statusCode ?? this.endpoint.status;\n\n\t\t\t\t// Only publish events on successful responses (2xx status codes)\n\t\t\t\t// Note: Audits are processed inside the handler's transaction\n\t\t\t\tif (Endpoint.isSuccessStatus(statusCode)) {\n\t\t\t\t\tconst logger = event.logger as TLogger;\n\t\t\t\t\tconst serviceDiscovery = ServiceDiscovery.getInstance<\n\t\t\t\t\t\tServiceRecord<TServices>\n\t\t\t\t\t>(this.envParser);\n\n\t\t\t\t\t// Publish events\n\t\t\t\t\tawait publishConstructEvents(\n\t\t\t\t\t\tthis.endpoint,\n\t\t\t\t\t\tresponse,\n\t\t\t\t\t\tserviceDiscovery,\n\t\t\t\t\t\tlogger,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t},\n\t\t};\n\t}\n\n\tprivate async _handler(\n\t\tevent: Event<TEvent, TInput, TServices, TLogger, TSession>,\n\t) {\n\t\tconst input = this.endpoint.refineInput(event);\n\t\tconst logger = event.logger as TLogger;\n\t\tconst serviceDiscovery = ServiceDiscovery.getInstance<\n\t\t\tServiceRecord<TServices>\n\t\t>(this.envParser);\n\n\t\t// Create audit context if audit storage is configured\n\t\tconst auditContext = await createAuditContext(\n\t\t\tthis.endpoint,\n\t\t\tserviceDiscovery,\n\t\t\tlogger,\n\t\t\t{\n\t\t\t\tsession: event.session,\n\t\t\t\theader: event.header,\n\t\t\t\tcookie: event.cookie,\n\t\t\t\tservices: event.services as Record<string, unknown>,\n\t\t\t},\n\t\t);\n\n\t\t// Warn if declarative audits are configured but no audit storage\n\t\tconst audits = this.endpoint.audits as MappedAudit<\n\t\t\tTAuditAction,\n\t\t\tTOutSchema\n\t\t>[];\n\t\tif (!auditContext && audits?.length) {\n\t\t\tlogger.warn('No auditor storage service available');\n\t\t}\n\n\t\t// Get pre-resolved database from middleware\n\t\tconst rawDb = (event as any).db;\n\n\t\t// Extract RLS context if configured and not bypassed\n\t\tconst rlsActive =\n\t\t\tthis.endpoint.rlsConfig &&\n\t\t\t!this.endpoint.rlsBypass &&\n\t\t\trawDb !== undefined;\n\t\tconst rlsContext = rlsActive\n\t\t\t? await this.endpoint.rlsConfig?.extractor({\n\t\t\t\t\tservices: event.services as ServiceRecord<TServices>,\n\t\t\t\t\tsession: event.session,\n\t\t\t\t\theader: event.header,\n\t\t\t\t\tcookie: event.cookie,\n\t\t\t\t\tlogger,\n\t\t\t\t})\n\t\t\t: undefined;\n\n\t\t// Execute handler with automatic audit transaction support\n\t\tconst result = await executeWithAuditTransaction(\n\t\t\tauditContext,\n\t\t\tasync (auditor) => {\n\t\t\t\t// Use audit transaction as db only if the storage uses the same database service\n\t\t\t\tconst sameDatabase =\n\t\t\t\t\tauditContext?.storage?.databaseServiceName &&\n\t\t\t\t\tauditContext.storage.databaseServiceName ===\n\t\t\t\t\t\tthis.endpoint.databaseService?.serviceName;\n\t\t\t\tconst baseDb = sameDatabase\n\t\t\t\t\t? (auditor?.getTransaction?.() ?? rawDb)\n\t\t\t\t\t: rawDb;\n\n\t\t\t\t// Helper to execute handler with given db\n\t\t\t\tconst executeHandler = async (db: any) => {\n\t\t\t\t\tconst responseBuilder = new ResponseBuilder();\n\t\t\t\t\tconst response = await this.endpoint.handler(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\theader: event.header,\n\t\t\t\t\t\t\tcookie: event.cookie,\n\t\t\t\t\t\t\tlogger: event.logger,\n\t\t\t\t\t\t\tservices: event.services,\n\t\t\t\t\t\t\tsession: event.session,\n\t\t\t\t\t\t\tauditor,\n\t\t\t\t\t\t\tdb,\n\t\t\t\t\t\t\t...input,\n\t\t\t\t\t\t} as any,\n\t\t\t\t\t\tresponseBuilder,\n\t\t\t\t\t);\n\n\t\t\t\t\t// Check if response has metadata\n\t\t\t\t\tlet data = response;\n\t\t\t\t\tlet metadata = responseBuilder.getMetadata();\n\n\t\t\t\t\tif (Endpoint.hasMetadata(response)) {\n\t\t\t\t\t\tdata = response.data;\n\t\t\t\t\t\tmetadata = response.metadata;\n\t\t\t\t\t}\n\n\t\t\t\t\tconst output = this.endpoint.outputSchema\n\t\t\t\t\t\t? await this.endpoint.parseOutput(data)\n\t\t\t\t\t\t: undefined;\n\n\t\t\t\t\treturn { output, metadata, responseBuilder };\n\t\t\t\t};\n\n\t\t\t\t// If RLS is active, wrap handler with RLS context\n\t\t\t\tif (rlsActive && rlsContext && baseDb) {\n\t\t\t\t\treturn withRlsContext(\n\t\t\t\t\t\tbaseDb,\n\t\t\t\t\t\trlsContext,\n\t\t\t\t\t\tasync (trx: any) => executeHandler(trx),\n\t\t\t\t\t\t{ prefix: this.endpoint.rlsConfig?.prefix },\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\treturn executeHandler(baseDb);\n\t\t\t},\n\t\t\t// Process declarative audits after handler (inside transaction)\n\t\t\tasync (result, auditor) => {\n\t\t\t\tif (!audits?.length) return;\n\n\t\t\t\tfor (const audit of audits) {\n\t\t\t\t\tif (audit.when && !audit.when(result.output as any)) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tconst payload = audit.payload(result.output as any);\n\t\t\t\t\tconst entityId = audit.entityId?.(result.output as any);\n\t\t\t\t\tauditor.audit(audit.type as any, payload as any, {\n\t\t\t\t\t\ttable: audit.table,\n\t\t\t\t\t\tentityId,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t},\n\t\t\t// Pass rawDb so storage can reuse existing transactions\n\t\t\t{ db: rawDb },\n\t\t);\n\n\t\tconst { output, metadata } = result;\n\t\tconst isJsonResponse = this.endpoint.responseType === 'application/json';\n\t\tconst body =\n\t\t\toutput === undefined\n\t\t\t\t? undefined\n\t\t\t\t: isJsonResponse\n\t\t\t\t\t? JSON.stringify(output)\n\t\t\t\t\t: typeof output === 'string'\n\t\t\t\t\t\t? output\n\t\t\t\t\t\t: String(output);\n\n\t\t// Store response for middleware access\n\t\t(event as any).__response = output;\n\n\t\t// Build response with metadata\n\t\tconst lambdaResponse: AmazonApiGatewayEndpointHandlerResponse = {\n\t\t\tstatusCode: metadata.status ?? this.endpoint.status,\n\t\t\tbody,\n\t\t};\n\n\t\t// Compose headers. For non-JSON responseType, emit a default\n\t\t// Content-Type header which metadata.headers (r.header()) can override.\n\t\tconst baseHeaders: Record<string, string> | undefined = isJsonResponse\n\t\t\t? undefined\n\t\t\t: { 'content-type': this.endpoint.responseType };\n\n\t\tif (\n\t\t\tbaseHeaders ||\n\t\t\t(metadata.headers && Object.keys(metadata.headers).length > 0)\n\t\t) {\n\t\t\tlambdaResponse.headers = {\n\t\t\t\t...(baseHeaders ?? {}),\n\t\t\t\t...(metadata.headers ?? {}),\n\t\t\t};\n\t\t}\n\n\t\t// Format cookies as Set-Cookie headers\n\t\tif (metadata.cookies && metadata.cookies.size > 0) {\n\t\t\tconst setCookieHeaders: string[] = [];\n\t\t\tfor (const [name, { value, options }] of metadata.cookies) {\n\t\t\t\tsetCookieHeaders.push(\n\t\t\t\t\tEndpoint.formatCookieHeader(name, value, options),\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif (setCookieHeaders.length > 0) {\n\t\t\t\tlambdaResponse.multiValueHeaders = {\n\t\t\t\t\t...lambdaResponse.multiValueHeaders,\n\t\t\t\t\t'Set-Cookie': setCookieHeaders,\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\treturn lambdaResponse;\n\t}\n\n\t/**\n\t * Convert Telemetry interface to Middy middleware\n\t */\n\tprivate telemetry(): Middleware<TEvent, TInput, TServices, TLogger> | null {\n\t\tif (!this.options.telemetry) {\n\t\t\treturn null;\n\t\t}\n\n\t\tconst telemetry = this.options.telemetry;\n\t\tlet ctx: any;\n\n\t\treturn {\n\t\t\tbefore: (request) => {\n\t\t\t\tctx = telemetry.onRequestStart({\n\t\t\t\t\tevent: request.event,\n\t\t\t\t\tcontext: request.context,\n\t\t\t\t});\n\t\t\t},\n\t\t\tafter: (request) => {\n\t\t\t\tif (ctx) {\n\t\t\t\t\ttelemetry.onRequestEnd(ctx, {\n\t\t\t\t\t\tstatusCode: request.response?.statusCode ?? 200,\n\t\t\t\t\t\tbody: request.response?.body,\n\t\t\t\t\t\theaders: request.response?.headers,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t},\n\t\t\tonError: (request) => {\n\t\t\t\tif (ctx && request.error) {\n\t\t\t\t\ttelemetry.onRequestError(\n\t\t\t\t\t\tctx,\n\t\t\t\t\t\trequest.error instanceof Error\n\t\t\t\t\t\t\t? request.error\n\t\t\t\t\t\t\t: new Error(String(request.error)),\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t},\n\t\t};\n\t}\n\n\tget handler() {\n\t\tconst handler = this._handler.bind(this);\n\t\tlet chain = middy(handler)\n\t\t\t.use(this.logger())\n\t\t\t.use(this.error())\n\t\t\t.use(this.services())\n\t\t\t.use(this.input())\n\t\t\t.use(this.database())\n\t\t\t.use(this.session())\n\t\t\t.use(this.authorize())\n\t\t\t.use(this.events());\n\n\t\t// Add telemetry middleware if configured (runs early for span creation)\n\t\tconst telemetryMiddleware = this.telemetry();\n\t\tif (telemetryMiddleware) {\n\t\t\tchain = chain.use(telemetryMiddleware);\n\t\t}\n\n\t\t// Add Telescope middleware if configured (runs first/last in chain)\n\t\tif (this.options.telescope?.middleware) {\n\t\t\tchain = chain.use(this.options.telescope.middleware);\n\t\t}\n\n\t\t// Wrap entire Middy chain in request context for service access\n\t\tconst wrappedHandler = async (event: TEvent, context: Context) => {\n\t\t\tconst startTime = Date.now();\n\t\t\tconst requestId = context.awsRequestId;\n\t\t\tconst logger = this.endpoint.logger.child({ requestId }) as TLogger;\n\n\t\t\t// Cast event to any since Middy middlewares enrich the event with\n\t\t\t// services, logger, session, etc. during the middleware chain execution\n\t\t\tconst operation = `${this.endpoint.method} ${this.endpoint.route}`;\n\t\t\treturn runWithRequestContext(\n\t\t\t\t{ logger, requestId, startTime, operation },\n\t\t\t\t() => chain(event as unknown as Parameters<typeof chain>[0], context),\n\t\t\t);\n\t\t};\n\n\t\treturn wrappedHandler as unknown as THandler;\n\t}\n}\n\nexport type Event<\n\tTEvent extends APIGatewayProxyEvent | APIGatewayProxyEventV2,\n\tTInput extends EndpointSchemas = {},\n\tTServices extends Service[] = [],\n\tTLogger extends Logger = Logger,\n\tTSession = unknown,\n> = {\n\tservices: ServiceRecord<TServices>;\n\tlogger: TLogger;\n\theader: HeaderFn;\n\tcookie: CookieFn;\n\tsession: TSession;\n} & TEvent &\n\tInferComposableStandardSchema<TInput>;\n\ntype Middleware<\n\tTEvent extends APIGatewayProxyEvent | APIGatewayProxyEventV2,\n\tTInput extends EndpointSchemas = {},\n\tTServices extends Service[] = [],\n\tTLogger extends Logger = Logger,\n\tTSession = unknown,\n> = MiddlewareObj<Event<TEvent, TInput, TServices, TLogger, TSession>>;\n\nexport type AmazonApiGatewayEndpointHandlerResponse = {\n\tstatusCode: number;\n\tbody: string | undefined;\n\theaders?: Record<string, string>;\n\tmultiValueHeaders?: Record<string, string[]>;\n};\n\nexport type LoggerContext = {\n\tfn: {\n\t\tname: string;\n\t\tversion: string;\n\t};\n\treq: {\n\t\tid: string | undefined;\n\t\tawsRequestId: string;\n\t\tpath: string;\n\t\tip: string | undefined;\n\t\tuserAgent: string | undefined;\n\t};\n};\n\nexport type GetInputResponse = {\n\tbody: any;\n\tquery: any;\n\tparams: any;\n};\n\nexport type AmazonApiGatewayV1EndpointHandler = (\n\tevent: APIGatewayProxyEvent,\n\tcontext: Context,\n) => Promise<AmazonApiGatewayEndpointHandlerResponse>;\n\nexport type AmazonApiGatewayV2EndpointHandler = (\n\tevent: APIGatewayProxyEventV2,\n\tcontext: Context,\n) => Promise<AmazonApiGatewayEndpointHandlerResponse>;\n\nexport type HandlerEvent<T extends Function> = T extends (\n\tevent: infer E,\n\tcontext: Context,\n) => any\n\t? E\n\t: never;\n","import qs from 'qs';\n\n/**\n * Parse query parameters from a flat object into a nested structure\n * Uses qs bracket notation for standard interoperability\n *\n * @example\n * parseQueryParams({ 'tags[]': ['a', 'b'], 'filter[name]': 'john' })\n * // Returns: { tags: ['a', 'b'], filter: { name: 'john' } }\n */\nexport function parseQueryParams(\n\tqueryParams: Record<string, string | string[] | undefined> | null,\n): Record<string, any> {\n\tif (!queryParams) {\n\t\treturn {};\n\t}\n\n\t// Reconstruct a query string from the flat object so qs can parse bracket notation\n\tconst parts: string[] = [];\n\tfor (const [key, value] of Object.entries(queryParams)) {\n\t\tif (value === undefined) continue;\n\t\tif (Array.isArray(value)) {\n\t\t\tfor (const v of value) {\n\t\t\t\tparts.push(`${encodeURIComponent(key)}=${encodeURIComponent(v)}`);\n\t\t\t}\n\t\t} else {\n\t\t\tparts.push(`${encodeURIComponent(key)}=${encodeURIComponent(value)}`);\n\t\t}\n\t}\n\n\treturn qs.parse(parts.join('&')) as Record<string, any>;\n}\n","import type { EventPublisher } from '@geekmidas/events';\nimport type { Logger } from '@geekmidas/logger';\nimport type { Service } from '@geekmidas/services';\nimport type { StandardSchemaV1 } from '@standard-schema/spec';\nimport type { APIGatewayProxyEvent, Context } from 'aws-lambda';\nimport type { HttpMethod } from '../types';\nimport {\n\tAmazonApiGatewayEndpoint,\n\ttype AmazonApiGatewayEndpointOptions,\n\ttype AmazonApiGatewayV1EndpointHandler,\n\ttype GetInputResponse,\n\ttype LoggerContext,\n} from './AmazonApiGatewayEndpointAdaptor';\nimport type { Endpoint, EndpointSchemas } from './Endpoint';\nimport { parseQueryParams } from './parseQueryParams';\n\nexport class AmazonApiGatewayV1Endpoint<\n\tTRoute extends string,\n\tTMethod extends HttpMethod,\n\tTInput extends EndpointSchemas = {},\n\tTOutSchema extends StandardSchemaV1 | undefined = undefined,\n\tTServices extends Service[] = [],\n\tTLogger extends Logger = Logger,\n\tTSession = unknown,\n> extends AmazonApiGatewayEndpoint<\n\tAmazonApiGatewayV1EndpointHandler,\n\tAPIGatewayProxyEvent,\n\tTRoute,\n\tTMethod,\n\tTInput,\n\tTOutSchema,\n\tTServices,\n\tTLogger,\n\tTSession\n> {\n\toverride getInput(e: APIGatewayProxyEvent): GetInputResponse {\n\t\t// For arrays, AWS API Gateway V1 provides multiValueQueryStringParameters\n\t\tconst multiValueParams = e.multiValueQueryStringParameters || {};\n\t\tconst singleValueParams = e.queryStringParameters || {};\n\n\t\t// Merge single and multi-value parameters\n\t\tconst mergedParams: Record<string, string | string[]> = {};\n\n\t\t// Add single value parameters\n\t\tfor (const [key, value] of Object.entries(singleValueParams)) {\n\t\t\tif (value !== undefined) {\n\t\t\t\tmergedParams[key] = value;\n\t\t\t}\n\t\t}\n\n\t\t// Override with multi-value parameters where applicable\n\t\tfor (const [key, values] of Object.entries(multiValueParams)) {\n\t\t\tif (values && values.length > 1) {\n\t\t\t\tmergedParams[key] = values;\n\t\t\t}\n\t\t}\n\n\t\treturn {\n\t\t\tbody: AmazonApiGatewayEndpoint.decodeBody(\n\t\t\t\te.body,\n\t\t\t\te.isBase64Encoded,\n\t\t\t\te.headers?.['Content-Type'] ?? e.headers?.['content-type'],\n\t\t\t),\n\t\t\tquery: parseQueryParams(mergedParams),\n\t\t\tparams: e.pathParameters || {},\n\t\t};\n\t}\n\toverride getLoggerContext(\n\t\tdata: APIGatewayProxyEvent,\n\t\tcontext: Context,\n\t): LoggerContext {\n\t\treturn {\n\t\t\tfn: {\n\t\t\t\tname: context.functionName,\n\t\t\t\tversion: context.functionVersion,\n\t\t\t},\n\t\t\treq: {\n\t\t\t\tid: data.requestContext.requestId,\n\t\t\t\tawsRequestId: context.awsRequestId,\n\t\t\t\tip: data.requestContext.identity.sourceIp,\n\t\t\t\tuserAgent: data.requestContext.identity.userAgent || undefined,\n\t\t\t\tpath: data.requestContext.path,\n\t\t\t},\n\t\t};\n\t}\n\tconstructor(\n\t\tprotected override readonly endpoint: Endpoint<\n\t\t\tTRoute,\n\t\t\tTMethod,\n\t\t\tTInput,\n\t\t\tTOutSchema,\n\t\t\tTServices,\n\t\t\tTLogger,\n\t\t\tTSession\n\t\t>,\n\t\toptions: AmazonApiGatewayEndpointOptions = {},\n\t) {\n\t\tsuper(endpoint, options);\n\t}\n}\n","import type { EventPublisher } from '@geekmidas/events';\nimport type { Logger } from '@geekmidas/logger';\nimport type { Service } from '@geekmidas/services';\nimport type { StandardSchemaV1 } from '@standard-schema/spec';\nimport type { APIGatewayProxyEventV2, Context } from 'aws-lambda';\nimport qs from 'qs';\nimport type { HttpMethod } from '../types';\nimport {\n\tAmazonApiGatewayEndpoint,\n\ttype AmazonApiGatewayEndpointOptions,\n\ttype AmazonApiGatewayV2EndpointHandler,\n\ttype GetInputResponse,\n\ttype LoggerContext,\n} from './AmazonApiGatewayEndpointAdaptor';\nimport type { CookieFn, Endpoint, EndpointSchemas } from './Endpoint';\nimport { createApiGatewayCookies } from './lazyAccessors';\n\nexport class AmazonApiGatewayV2Endpoint<\n\tTRoute extends string,\n\tTMethod extends HttpMethod,\n\tTInput extends EndpointSchemas = {},\n\tTOutSchema extends StandardSchemaV1 | undefined = undefined,\n\tTServices extends Service[] = [],\n\tTLogger extends Logger = Logger,\n\tTSession = unknown,\n> extends AmazonApiGatewayEndpoint<\n\tAmazonApiGatewayV2EndpointHandler,\n\tAPIGatewayProxyEventV2,\n\tTRoute,\n\tTMethod,\n\tTInput,\n\tTOutSchema,\n\tTServices,\n\tTLogger,\n\tTSession\n> {\n\toverride getCookies(e: APIGatewayProxyEventV2): CookieFn {\n\t\treturn createApiGatewayCookies(\n\t\t\te.cookies,\n\t\t\t(e.headers as Record<string, string>)?.cookie,\n\t\t);\n\t}\n\n\toverride getInput(e: APIGatewayProxyEventV2): GetInputResponse {\n\t\tconst raw = AmazonApiGatewayEndpoint.decodeBody(\n\t\t\te.body,\n\t\t\te.isBase64Encoded,\n\t\t\te.headers?.['content-type'],\n\t\t);\n\n\t\treturn {\n\t\t\tbody: raw,\n\t\t\tquery: qs.parse(e.rawQueryString) as Record<string, any>,\n\t\t\tparams: e.pathParameters || {},\n\t\t};\n\t}\n\toverride getLoggerContext(\n\t\tevent: APIGatewayProxyEventV2,\n\t\tcontext: Context,\n\t): LoggerContext {\n\t\treturn {\n\t\t\tfn: {\n\t\t\t\tname: context.functionName,\n\t\t\t\tversion: context.functionVersion,\n\t\t\t},\n\t\t\treq: {\n\t\t\t\tid: event.requestContext.requestId,\n\t\t\t\tawsRequestId: context.awsRequestId,\n\t\t\t\tip: event.requestContext.http.sourceIp,\n\t\t\t\tuserAgent: event.requestContext.http.userAgent || undefined,\n\t\t\t\tpath: event.requestContext.http.path,\n\t\t\t},\n\t\t};\n\t}\n\tconstructor(\n\t\tprotected override readonly endpoint: Endpoint<\n\t\t\tTRoute,\n\t\t\tTMethod,\n\t\t\tTInput,\n\t\t\tTOutSchema,\n\t\t\tTServices,\n\t\t\tTLogger,\n\t\t\tTSession\n\t\t>,\n\t\toptions: AmazonApiGatewayEndpointOptions = {},\n\t) {\n\t\tsuper(endpoint, options);\n\t}\n}\n\n// Re-export options type for convenience\nexport type { AmazonApiGatewayEndpointOptions };\n","import type { EnvironmentParser } from '@geekmidas/envkit';\nimport { wrapError } from '@geekmidas/errors';\nimport type { Logger } from '@geekmidas/logger';\nimport type { InferStandardSchema } from '@geekmidas/schema';\nimport type { Service, ServiceRecord } from '@geekmidas/services';\nimport { runWithRequestContext, ServiceDiscovery } from '@geekmidas/services';\nimport type { StandardSchemaV1 } from '@standard-schema/spec';\nimport type {\n\tContext,\n\tHandler,\n\tSQSBatchResponse,\n\tSQSEvent,\n\tSQSRecord,\n} from 'aws-lambda';\nimport type { Queue, QueueContext } from './Queue';\n\nexport type AWSLambdaHandler<TEvent = any, TResult = any> = Handler<\n\tTEvent,\n\tTResult\n>;\n\n/**\n * Runs a {@link Queue} worker as an AWS Lambda backed by an SQS event-source\n * mapping. Unlike a subscriber, a queue drains *every* record (no type filter):\n * each record body (`{ type, payload }`, as written by the SQS publisher) is\n * unwrapped to its `payload`, validated against the queue's `messageSchema`, and\n * the whole batch is handed to the handler as `messages`.\n *\n * Uses SQS partial-batch responses: a record that fails to parse, validate, or\n * (when the handler throws) process is returned in `batchItemFailures` so SQS\n * retries only those records.\n */\nexport class AWSLambdaQueue<\n\tTName extends string = string,\n\tTMessage extends StandardSchemaV1 = StandardSchemaV1,\n\tTServices extends Service[] = [],\n\tTLogger extends Logger = Logger,\n\tTDatabase = undefined,\n\tTDatabaseServiceName extends string = string,\n> {\n\tprivate _services?: ServiceRecord<TServices>;\n\n\tconstructor(\n\t\tprivate readonly envParser: EnvironmentParser<{}>,\n\t\treadonly queue: Queue<\n\t\t\tTName,\n\t\t\tTMessage,\n\t\t\tTServices,\n\t\t\tTLogger,\n\t\t\tTDatabase,\n\t\t\tTDatabaseServiceName\n\t\t>,\n\t) {}\n\n\tget logger(): TLogger {\n\t\treturn this.queue.logger;\n\t}\n\n\tprivate async getServices(): Promise<ServiceRecord<TServices>> {\n\t\tif (this._services) {\n\t\t\treturn this._services;\n\t\t}\n\n\t\tconst serviceDiscovery = ServiceDiscovery.getInstance(this.envParser);\n\n\t\tthis._services =\n\t\t\tthis.queue.services.length > 0\n\t\t\t\t? ((await serviceDiscovery.register(\n\t\t\t\t\t\tthis.queue.services,\n\t\t\t\t\t)) as ServiceRecord<TServices>)\n\t\t\t\t: ({} as ServiceRecord<TServices>);\n\n\t\treturn this._services;\n\t}\n\n\t/** The queue's database, registered as functions register theirs. */\n\tprivate async getDatabase(): Promise<TDatabase | undefined> {\n\t\tconst service = this.queue.databaseService;\n\t\tif (!service) return undefined;\n\n\t\tconst registered = await ServiceDiscovery.getInstance(\n\t\t\tthis.envParser,\n\t\t).register([service]);\n\n\t\treturn registered[service.serviceName as keyof typeof registered] as\n\t\t\t| TDatabase\n\t\t\t| undefined;\n\t}\n\n\tprivate safeJsonParse(value: string): unknown {\n\t\ttry {\n\t\t\treturn JSON.parse(value);\n\t\t} catch {\n\t\t\treturn null;\n\t\t}\n\t}\n\n\t/**\n\t * Unwrap the queue payload from an SQS record. The SQS publisher writes\n\t * `{ type, payload }`; a payload-only body is also accepted as-is.\n\t */\n\tprivate extractPayload(record: SQSRecord): unknown {\n\t\tconst body = this.safeJsonParse(record.body);\n\t\tif (body && typeof body === 'object' && 'payload' in body) {\n\t\t\treturn (body as { payload: unknown }).payload;\n\t\t}\n\t\treturn body ?? record.body;\n\t}\n\n\tprivate async _handler(\n\t\tevent: SQSEvent,\n\t\tcontext: Context,\n\t): Promise<SQSBatchResponse> {\n\t\tconst logger = this.queue.logger.child({\n\t\t\tqueue: {\n\t\t\t\tname: this.queue.name,\n\t\t\t\tfn: context.functionName,\n\t\t\t},\n\t\t\treq: { id: context.awsRequestId },\n\t\t}) as TLogger;\n\n\t\tconst services = await this.getServices();\n\t\tconst db = await this.getDatabase();\n\t\tconst schema = this.queue.messageSchema;\n\n\t\tconst batchItemFailures: { itemIdentifier: string }[] = [];\n\t\tconst messages: InferStandardSchema<TMessage>[] = [];\n\n\t\tfor (const record of event.Records) {\n\t\t\ttry {\n\t\t\t\tconst payload = this.extractPayload(record);\n\t\t\t\tconst validation = await schema['~standard'].validate(payload);\n\t\t\t\tif (validation.issues) {\n\t\t\t\t\tlogger.error(\n\t\t\t\t\t\t{ issues: validation.issues, messageId: record.messageId },\n\t\t\t\t\t\t'Queue message failed validation',\n\t\t\t\t\t);\n\t\t\t\t\tbatchItemFailures.push({ itemIdentifier: record.messageId });\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tmessages.push(validation.value as InferStandardSchema<TMessage>);\n\t\t\t} catch (error) {\n\t\t\t\tlogger.error(\n\t\t\t\t\t{ err: error, messageId: record.messageId },\n\t\t\t\t\t'Failed to parse SQS record',\n\t\t\t\t);\n\t\t\t\tbatchItemFailures.push({ itemIdentifier: record.messageId });\n\t\t\t}\n\t\t}\n\n\t\tif (messages.length === 0) {\n\t\t\treturn { batchItemFailures };\n\t\t}\n\n\t\ttry {\n\t\t\t// Cast because `db` is in the context only when TDatabase is set, a\n\t\t\t// condition a generic cannot resolve; `undefined` when it is not.\n\t\t\tawait this.queue.handler({\n\t\t\t\tmessages,\n\t\t\t\tservices,\n\t\t\t\tlogger,\n\t\t\t\tdb,\n\t\t\t} as unknown as QueueContext<TMessage, TServices, TLogger, TDatabase>);\n\t\t} catch (error) {\n\t\t\tlogger.error(wrapError(error), 'Queue handler failed; retrying batch');\n\t\t\t// Handler processes the batch atomically — fail the whole batch so SQS\n\t\t\t// retries every (valid) record.\n\t\t\tfor (const record of event.Records) {\n\t\t\t\tif (\n\t\t\t\t\t!batchItemFailures.some((f) => f.itemIdentifier === record.messageId)\n\t\t\t\t) {\n\t\t\t\t\tbatchItemFailures.push({ itemIdentifier: record.messageId });\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn { batchItemFailures };\n\t}\n\n\tget handler(): AWSLambdaHandler<SQSEvent, SQSBatchResponse> {\n\t\tconst handler = this._handler.bind(this);\n\n\t\treturn (async (event: SQSEvent, context: Context) => {\n\t\t\tconst startTime = Date.now();\n\t\t\tconst requestId = context.awsRequestId;\n\t\t\tconst logger = this.queue.logger.child({ requestId }) as TLogger;\n\n\t\t\treturn runWithRequestContext(\n\t\t\t\t{ logger, requestId, startTime, operation: `queue ${this.queue.name}` },\n\t\t\t\t() => handler(event, context),\n\t\t\t);\n\t\t}) as unknown as AWSLambdaHandler<SQSEvent, SQSBatchResponse>;\n\t}\n}\n","import type { EnvironmentParser } from '@geekmidas/envkit';\nimport { wrapError } from '@geekmidas/errors';\nimport type { EventPublisher } from '@geekmidas/events';\nimport type { Logger } from '@geekmidas/logger';\nimport type { InferStandardSchema } from '@geekmidas/schema';\nimport type { Service, ServiceRecord } from '@geekmidas/services';\nimport { runWithRequestContext } from '@geekmidas/services';\nimport middy, { type MiddlewareObj } from '@middy/core';\nimport type { StandardSchemaV1 } from '@standard-schema/spec';\nimport type { Context, Handler, SNSEvent, SQSEvent } from 'aws-lambda';\nimport {\n\trunSubscriber,\n\tsubscribedEvents,\n\tsubscriberContext,\n} from './runSubscriber';\nimport type { Subscriber } from './Subscriber';\n\nexport type AWSLambdaHandler<TEvent = any, TResult = any> = Handler<\n\tTEvent,\n\tTResult\n>;\n\ntype SubscriberEvent<TServices extends Service[], TLogger extends Logger> = {\n\tevents: any[];\n\tservices: ServiceRecord<TServices>;\n\tlogger: TLogger;\n\t/** The subscriber's database, when it has one. */\n\tdb?: unknown;\n};\n\ntype Middleware<\n\tTServices extends Service[],\n\tTLogger extends Logger,\n\tTOutSchema extends StandardSchemaV1 | undefined,\n> = MiddlewareObj<\n\tSubscriberEvent<TServices, TLogger>,\n\tInferStandardSchema<TOutSchema>,\n\tError,\n\tContext\n>;\n\nexport class AWSLambdaSubscriber<\n\tTServices extends Service[] = [],\n\tTLogger extends Logger = Logger,\n\tOutSchema extends StandardSchemaV1 | undefined = undefined,\n\tTEventPublisher extends EventPublisher<any> | undefined = undefined,\n\tTSubscribedEvents extends any[] = [],\n\tTDatabase = undefined,\n\tTDatabaseServiceName extends string = string,\n> {\n\tprivate _logger!: TLogger;\n\n\tconstructor(\n\t\tprivate envParser: EnvironmentParser<{}>,\n\t\treadonly subscriber: Subscriber<\n\t\t\tTServices,\n\t\t\tTLogger,\n\t\t\tOutSchema,\n\t\t\tTEventPublisher,\n\t\t\tTSubscribedEvents,\n\t\t\tTDatabase,\n\t\t\tTDatabaseServiceName\n\t\t>,\n\t) {\n\t\tthis._logger = subscriber.logger;\n\t}\n\n\tget logger(): TLogger {\n\t\treturn this._logger;\n\t}\n\n\tprivate error(): Middleware<TServices, TLogger, OutSchema> {\n\t\treturn {\n\t\t\tonError: (req) => {\n\t\t\t\tconst logger = req.event?.logger || this.subscriber.logger;\n\t\t\t\tlogger.error(req.error || {}, 'Error processing subscriber');\n\n\t\t\t\t// Re-throw the wrapped error to let Lambda handle it\n\t\t\t\tthrow wrapError(req.error);\n\t\t\t},\n\t\t};\n\t}\n\n\tprivate loggerMiddleware(): Middleware<TServices, TLogger, OutSchema> {\n\t\treturn {\n\t\t\tbefore: (req) => {\n\t\t\t\tthis._logger = this.subscriber.logger.child({\n\t\t\t\t\tsubscriber: {\n\t\t\t\t\t\tname: req.context.functionName,\n\t\t\t\t\t\tversion: req.context.functionVersion,\n\t\t\t\t\t\tmemory: req.context.memoryLimitInMB,\n\t\t\t\t\t},\n\t\t\t\t\treq: {\n\t\t\t\t\t\tid: req.context.awsRequestId,\n\t\t\t\t\t},\n\t\t\t\t}) as TLogger;\n\n\t\t\t\treq.event.logger = this._logger;\n\t\t\t},\n\t\t};\n\t}\n\n\tprivate services(): Middleware<TServices, TLogger, OutSchema> {\n\t\treturn {\n\t\t\tbefore: async (req) => {\n\t\t\t\tconst { services, db } = await subscriberContext(\n\t\t\t\t\tthis.subscriber,\n\t\t\t\t\tthis.envParser,\n\t\t\t\t);\n\t\t\t\treq.event.services = services as ServiceRecord<TServices>;\n\t\t\t\treq.event.db = db;\n\t\t\t},\n\t\t};\n\t}\n\n\tprivate parseEvents(): Middleware<TServices, TLogger, OutSchema> {\n\t\treturn {\n\t\t\tbefore: async (req) => {\n\t\t\t\tconst { logger, ...rawEvent } = req.event;\n\n\t\t\t\tlogger.info({\n\t\t\t\t\trawEvent,\n\t\t\t\t});\n\n\t\t\t\treq.event.events = subscribedEvents(\n\t\t\t\t\tthis.subscriber,\n\t\t\t\t\trawEvent as unknown as SQSEvent | SNSEvent,\n\t\t\t\t\tthis.logger,\n\t\t\t\t);\n\t\t\t},\n\t\t};\n\t}\n\n\tprivate async _handler(event: SubscriberEvent<TServices, TLogger>) {\n\t\t// Only these four: the raw Lambda event stays out of the handler.\n\t\tconst { events, services, logger, db } = event;\n\t\treturn runSubscriber(this.subscriber, {\n\t\t\tevents,\n\t\t\tservices,\n\t\t\tlogger,\n\t\t\tdb,\n\t\t}) as Promise<InferStandardSchema<OutSchema>>;\n\t}\n\n\tget handler(): AWSLambdaHandler {\n\t\tconst handler = this._handler.bind(this);\n\n\t\t// Apply middleware in order\n\t\tconst chain = middy(handler)\n\t\t\t.use(this.loggerMiddleware())\n\t\t\t.use(this.parseEvents())\n\t\t\t.use(this.error())\n\t\t\t.use(this.services());\n\n\t\t// Wrap entire Middy chain in request context for service access\n\t\tconst wrappedHandler = async (event: unknown, context: Context) => {\n\t\t\tconst startTime = Date.now();\n\t\t\tconst requestId = context.awsRequestId;\n\t\t\tconst logger = this.subscriber.logger.child({\n\t\t\t\trequestId,\n\t\t\t}) as TLogger;\n\n\t\t\tconst operation = `subscriber ${this.subscriber.topicName ?? context.functionName}`;\n\t\t\treturn runWithRequestContext(\n\t\t\t\t{ logger, requestId, startTime, operation },\n\t\t\t\t() => chain(event as Parameters<typeof chain>[0], context),\n\t\t\t);\n\t\t};\n\n\t\treturn wrappedHandler as unknown as AWSLambdaHandler;\n\t}\n}\n"],"mappings":"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"}
|