@geekmidas/constructs 10.0.0-alpha.41 → 10.0.0-alpha.43

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (196) hide show
  1. package/dist/{Cron-CMEGfRs8.d.cts → Cron-DI3nKoic.d.cts} +3 -2
  2. package/dist/Cron-DI3nKoic.d.cts.map +1 -0
  3. package/dist/{Cron-D6X4-xjB.d.mts → Cron-uYAHPnp7.d.mts} +3 -2
  4. package/dist/Cron-uYAHPnp7.d.mts.map +1 -0
  5. package/dist/{CronBuilder-DB35T5dL.cjs → CronBuilder-BoHzlWU_.cjs} +8 -3
  6. package/dist/CronBuilder-BoHzlWU_.cjs.map +1 -0
  7. package/dist/{CronBuilder-Dv0IlZs0.mjs → CronBuilder-CCgt0wCE.mjs} +9 -4
  8. package/dist/CronBuilder-CCgt0wCE.mjs.map +1 -0
  9. package/dist/{CronBuilder-O_gvButp.d.mts → CronBuilder-DaSUm2Na.d.mts} +5 -4
  10. package/dist/CronBuilder-DaSUm2Na.d.mts.map +1 -0
  11. package/dist/{CronBuilder-CEK7aOqD.d.cts → CronBuilder-g1lZLWyG.d.cts} +5 -4
  12. package/dist/CronBuilder-g1lZLWyG.d.cts.map +1 -0
  13. package/dist/{Endpoint-CQAeh1Rh.mjs → Endpoint-BDgmfml0.mjs} +2 -2
  14. package/dist/{Endpoint-CQAeh1Rh.mjs.map → Endpoint-BDgmfml0.mjs.map} +1 -1
  15. package/dist/{Endpoint-Dp5AKIXl.d.cts → Endpoint-BkzU6nn1.d.cts} +5 -4
  16. package/dist/Endpoint-BkzU6nn1.d.cts.map +1 -0
  17. package/dist/{Endpoint-DtI7heFm.d.mts → Endpoint-BpboleFh.d.mts} +5 -4
  18. package/dist/Endpoint-BpboleFh.d.mts.map +1 -0
  19. package/dist/{Endpoint-D1L9qu5C.cjs → Endpoint-wSCHSnqb.cjs} +2 -2
  20. package/dist/{Endpoint-D1L9qu5C.cjs.map → Endpoint-wSCHSnqb.cjs.map} +1 -1
  21. package/dist/{EndpointFactory-FeFRmlDZ.d.cts → EndpointFactory-BZZOleQT.d.cts} +4 -4
  22. package/dist/{EndpointFactory-CgMDvERK.d.mts.map → EndpointFactory-BZZOleQT.d.cts.map} +1 -1
  23. package/dist/{EndpointFactory-BBdNeaGJ.mjs → EndpointFactory-C9G2pz86.mjs} +3 -3
  24. package/dist/{EndpointFactory-BBdNeaGJ.mjs.map → EndpointFactory-C9G2pz86.mjs.map} +1 -1
  25. package/dist/{EndpointFactory-CgMDvERK.d.mts → EndpointFactory-DnNlYflU.d.mts} +4 -4
  26. package/dist/{EndpointFactory-FeFRmlDZ.d.cts.map → EndpointFactory-DnNlYflU.d.mts.map} +1 -1
  27. package/dist/{EndpointFactory-BZOCOaK6.cjs → EndpointFactory-G1g1kiqC.cjs} +3 -3
  28. package/dist/{EndpointFactory-BZOCOaK6.cjs.map → EndpointFactory-G1g1kiqC.cjs.map} +1 -1
  29. package/dist/Function-DuqGcbOI.d.mts +76 -0
  30. package/dist/Function-DuqGcbOI.d.mts.map +1 -0
  31. package/dist/Function-Pu-1kKZz.d.cts +76 -0
  32. package/dist/Function-Pu-1kKZz.d.cts.map +1 -0
  33. package/dist/{HonoEndpointAdaptor-Cq99r9H7.cjs → HonoEndpointAdaptor-CBoSm3TM.cjs} +3 -3
  34. package/dist/{HonoEndpointAdaptor-Cq99r9H7.cjs.map → HonoEndpointAdaptor-CBoSm3TM.cjs.map} +1 -1
  35. package/dist/{HonoEndpointAdaptor-Aui-x9Lg.mjs → HonoEndpointAdaptor-DL_fCB9O.mjs} +3 -3
  36. package/dist/{HonoEndpointAdaptor-Aui-x9Lg.mjs.map → HonoEndpointAdaptor-DL_fCB9O.mjs.map} +1 -1
  37. package/dist/{Queue-Ckmudcm8.cjs → Queue-D5jcw0mu.cjs} +6 -2
  38. package/dist/Queue-D5jcw0mu.cjs.map +1 -0
  39. package/dist/{Queue-YmvN2vEP.d.mts → Queue-DlsHRzUp.d.mts} +22 -10
  40. package/dist/Queue-DlsHRzUp.d.mts.map +1 -0
  41. package/dist/{Queue-CpQIGB_2.d.cts → Queue-HPyi0e1i.d.cts} +22 -10
  42. package/dist/Queue-HPyi0e1i.d.cts.map +1 -0
  43. package/dist/{Queue-C1uDgjxt.mjs → Queue-hwPN-t31.mjs} +6 -2
  44. package/dist/Queue-hwPN-t31.mjs.map +1 -0
  45. package/dist/{QueueBuilder-CJNcv4dy.cjs → QueueBuilder-BFQn3OzZ.cjs} +27 -4
  46. package/dist/QueueBuilder-BFQn3OzZ.cjs.map +1 -0
  47. package/dist/{QueueBuilder-XuPKZwKH.mjs → QueueBuilder-DCuYdjMw.mjs} +28 -5
  48. package/dist/QueueBuilder-DCuYdjMw.mjs.map +1 -0
  49. package/dist/{QueueBuilder-XEnnOWGe.d.cts → QueueBuilder-OSi6LkV9.d.cts} +24 -11
  50. package/dist/QueueBuilder-OSi6LkV9.d.cts.map +1 -0
  51. package/dist/{QueueBuilder-CM0WUxfw.d.mts → QueueBuilder-QHsnVt1P.d.mts} +24 -11
  52. package/dist/QueueBuilder-QHsnVt1P.d.mts.map +1 -0
  53. package/dist/{Subscriber-B91YSkZt.d.cts → Subscriber-Bpp02cGr.d.cts} +20 -9
  54. package/dist/Subscriber-Bpp02cGr.d.cts.map +1 -0
  55. package/dist/{Subscriber-BjHYe5hK.d.mts → Subscriber-CtN9R48-.d.mts} +20 -9
  56. package/dist/Subscriber-CtN9R48-.d.mts.map +1 -0
  57. package/dist/{SubscriberBuilder-Duk028pD.cjs → SubscriberBuilder-C2PwqwIl.cjs} +31 -3
  58. package/dist/SubscriberBuilder-C2PwqwIl.cjs.map +1 -0
  59. package/dist/{SubscriberBuilder-BhMphk4z.d.mts → SubscriberBuilder-CuCMFpYW.d.mts} +23 -11
  60. package/dist/SubscriberBuilder-CuCMFpYW.d.mts.map +1 -0
  61. package/dist/{SubscriberBuilder-DzQUWE08.mjs → SubscriberBuilder-DMFk_Ap1.mjs} +32 -4
  62. package/dist/SubscriberBuilder-DMFk_Ap1.mjs.map +1 -0
  63. package/dist/{SubscriberBuilder-BSpQX1JT.d.cts → SubscriberBuilder-g3fAVWgs.d.cts} +23 -11
  64. package/dist/SubscriberBuilder-g3fAVWgs.d.cts.map +1 -0
  65. package/dist/adaptors/aws.cjs +20 -4
  66. package/dist/adaptors/aws.cjs.map +1 -1
  67. package/dist/adaptors/aws.d.cts +17 -13
  68. package/dist/adaptors/aws.d.cts.map +1 -1
  69. package/dist/adaptors/aws.d.mts +17 -13
  70. package/dist/adaptors/aws.d.mts.map +1 -1
  71. package/dist/adaptors/aws.mjs +20 -4
  72. package/dist/adaptors/aws.mjs.map +1 -1
  73. package/dist/adaptors/hono.cjs +1 -1
  74. package/dist/adaptors/hono.d.cts +1 -1
  75. package/dist/adaptors/hono.d.mts +1 -1
  76. package/dist/adaptors/hono.mjs +1 -1
  77. package/dist/adaptors/testing.cjs +170 -13
  78. package/dist/adaptors/testing.cjs.map +1 -1
  79. package/dist/adaptors/testing.d.cts +38 -21
  80. package/dist/adaptors/testing.d.cts.map +1 -1
  81. package/dist/adaptors/testing.d.mts +38 -21
  82. package/dist/adaptors/testing.d.mts.map +1 -1
  83. package/dist/adaptors/testing.mjs +170 -13
  84. package/dist/adaptors/testing.mjs.map +1 -1
  85. package/dist/{auth-CMwml9QN.d.mts → auth-3OAmK42n.d.cts} +4 -4
  86. package/dist/{auth-CMwml9QN.d.mts.map → auth-3OAmK42n.d.cts.map} +1 -1
  87. package/dist/{auth-rVRDjIw_.d.cts → auth-BWbiewHa.d.mts} +4 -4
  88. package/dist/{auth-rVRDjIw_.d.cts.map → auth-BWbiewHa.d.mts.map} +1 -1
  89. package/dist/auth.d.cts +1 -1
  90. package/dist/auth.d.mts +1 -1
  91. package/dist/{cache-C9a_hVCc.d.cts → cache-CXh6GIgb.d.mts} +3 -3
  92. package/dist/{cache-C9a_hVCc.d.cts.map → cache-CXh6GIgb.d.mts.map} +1 -1
  93. package/dist/{cache-CeTMI8LR.d.mts → cache-DnGDGly3.d.cts} +3 -3
  94. package/dist/{cache-CeTMI8LR.d.mts.map → cache-DnGDGly3.d.cts.map} +1 -1
  95. package/dist/cache.d.cts +1 -1
  96. package/dist/cache.d.mts +1 -1
  97. package/dist/{construct-interface-_3zgxzXl.d.mts → construct-interface-B1AfqRl4.d.cts} +25 -3
  98. package/dist/{construct-interface-_3zgxzXl.d.mts.map → construct-interface-B1AfqRl4.d.cts.map} +1 -1
  99. package/dist/{construct-interface-_xi4BPN8.d.cts → construct-interface-DluK3_da.d.mts} +25 -3
  100. package/dist/{construct-interface-_xi4BPN8.d.cts.map → construct-interface-DluK3_da.d.mts.map} +1 -1
  101. package/dist/construct-interface.cjs +26 -0
  102. package/dist/construct-interface.cjs.map +1 -1
  103. package/dist/construct-interface.d.cts +2 -2
  104. package/dist/construct-interface.d.mts +2 -2
  105. package/dist/construct-interface.mjs +26 -1
  106. package/dist/construct-interface.mjs.map +1 -1
  107. package/dist/credential.d.cts +1 -1
  108. package/dist/credential.d.mts +1 -1
  109. package/dist/crons/index.cjs +1 -1
  110. package/dist/crons/index.d.cts +2 -2
  111. package/dist/crons/index.d.mts +2 -2
  112. package/dist/crons/index.mjs +1 -1
  113. package/dist/database/kysely.d.cts +1 -1
  114. package/dist/database/kysely.d.mts +1 -1
  115. package/dist/email.d.cts +1 -1
  116. package/dist/email.d.mts +1 -1
  117. package/dist/endpoints/index.cjs +3 -3
  118. package/dist/endpoints/index.d.cts +2 -2
  119. package/dist/endpoints/index.d.mts +2 -2
  120. package/dist/endpoints/index.mjs +3 -3
  121. package/dist/{external-api-DS3mujT5.d.mts → external-api-CWY9orcO.d.mts} +2 -2
  122. package/dist/{external-api-DS3mujT5.d.mts.map → external-api-CWY9orcO.d.mts.map} +1 -1
  123. package/dist/{external-api-LBfE-q3g.d.cts → external-api-D-5WB-sr.d.cts} +2 -2
  124. package/dist/{external-api-LBfE-q3g.d.cts.map → external-api-D-5WB-sr.d.cts.map} +1 -1
  125. package/dist/external-api.d.cts +1 -1
  126. package/dist/external-api.d.mts +1 -1
  127. package/dist/file-server.d.cts +1 -1
  128. package/dist/file-server.d.mts +1 -1
  129. package/dist/functions/index.cjs +1 -1
  130. package/dist/functions/index.d.cts +2 -1
  131. package/dist/functions/index.d.mts +2 -1
  132. package/dist/functions/index.mjs +1 -1
  133. package/dist/{functions-ZH60FE7H.cjs → functions-CbP5ZKma.cjs} +15 -3
  134. package/dist/functions-CbP5ZKma.cjs.map +1 -0
  135. package/dist/{functions-DCIfCRR-.mjs → functions-Di6n5ltG.mjs} +16 -4
  136. package/dist/{functions-DCIfCRR-.mjs.map → functions-Di6n5ltG.mjs.map} +1 -1
  137. package/dist/{index-B0kxstwf.d.cts → index-BuzRvKOQ.d.cts} +9 -71
  138. package/dist/index-BuzRvKOQ.d.cts.map +1 -0
  139. package/dist/{index-CjVEjOw0.d.mts → index-CTkKOer4.d.mts} +9 -71
  140. package/dist/index-CTkKOer4.d.mts.map +1 -0
  141. package/dist/{kysely-BJ8IQ_1P.d.mts → kysely-Bqov3fwv.d.mts} +3 -3
  142. package/dist/{kysely-BJ8IQ_1P.d.mts.map → kysely-Bqov3fwv.d.mts.map} +1 -1
  143. package/dist/{kysely-DVF8wOT4.d.cts → kysely-DTnkZsub.d.cts} +3 -3
  144. package/dist/{kysely-DVF8wOT4.d.cts.map → kysely-DTnkZsub.d.cts.map} +1 -1
  145. package/dist/mobile-app.d.cts +1 -1
  146. package/dist/mobile-app.d.mts +1 -1
  147. package/dist/object-storage.d.cts +1 -1
  148. package/dist/object-storage.d.mts +1 -1
  149. package/dist/queue/index.cjs +2 -2
  150. package/dist/queue/index.d.cts +2 -2
  151. package/dist/queue/index.d.mts +2 -2
  152. package/dist/queue/index.mjs +2 -2
  153. package/dist/rest-api.cjs +1 -1
  154. package/dist/rest-api.d.cts +3 -3
  155. package/dist/rest-api.d.mts +3 -3
  156. package/dist/rest-api.mjs +1 -1
  157. package/dist/site.d.cts +1 -1
  158. package/dist/site.d.mts +1 -1
  159. package/dist/subscribers/index.cjs +1 -1
  160. package/dist/subscribers/index.d.cts +2 -2
  161. package/dist/subscribers/index.d.mts +2 -2
  162. package/dist/subscribers/index.mjs +1 -1
  163. package/dist/worker.cjs +26 -10
  164. package/dist/worker.cjs.map +1 -1
  165. package/dist/worker.d.cts +38 -22
  166. package/dist/worker.d.cts.map +1 -1
  167. package/dist/worker.d.mts +38 -22
  168. package/dist/worker.d.mts.map +1 -1
  169. package/dist/worker.mjs +26 -10
  170. package/dist/worker.mjs.map +1 -1
  171. package/package.json +31 -31
  172. package/dist/Cron-CMEGfRs8.d.cts.map +0 -1
  173. package/dist/Cron-D6X4-xjB.d.mts.map +0 -1
  174. package/dist/CronBuilder-CEK7aOqD.d.cts.map +0 -1
  175. package/dist/CronBuilder-DB35T5dL.cjs.map +0 -1
  176. package/dist/CronBuilder-Dv0IlZs0.mjs.map +0 -1
  177. package/dist/CronBuilder-O_gvButp.d.mts.map +0 -1
  178. package/dist/Endpoint-Dp5AKIXl.d.cts.map +0 -1
  179. package/dist/Endpoint-DtI7heFm.d.mts.map +0 -1
  180. package/dist/Queue-C1uDgjxt.mjs.map +0 -1
  181. package/dist/Queue-Ckmudcm8.cjs.map +0 -1
  182. package/dist/Queue-CpQIGB_2.d.cts.map +0 -1
  183. package/dist/Queue-YmvN2vEP.d.mts.map +0 -1
  184. package/dist/QueueBuilder-CJNcv4dy.cjs.map +0 -1
  185. package/dist/QueueBuilder-CM0WUxfw.d.mts.map +0 -1
  186. package/dist/QueueBuilder-XEnnOWGe.d.cts.map +0 -1
  187. package/dist/QueueBuilder-XuPKZwKH.mjs.map +0 -1
  188. package/dist/Subscriber-B91YSkZt.d.cts.map +0 -1
  189. package/dist/Subscriber-BjHYe5hK.d.mts.map +0 -1
  190. package/dist/SubscriberBuilder-BSpQX1JT.d.cts.map +0 -1
  191. package/dist/SubscriberBuilder-BhMphk4z.d.mts.map +0 -1
  192. package/dist/SubscriberBuilder-Duk028pD.cjs.map +0 -1
  193. package/dist/SubscriberBuilder-DzQUWE08.mjs.map +0 -1
  194. package/dist/functions-ZH60FE7H.cjs.map +0 -1
  195. package/dist/index-B0kxstwf.d.cts.map +0 -1
  196. package/dist/index-CjVEjOw0.d.mts.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Queue-hwPN-t31.mjs","names":[],"sources":["../src/queue/Queue.ts"],"sourcesContent":["import {\n\ttype EventPublisher,\n\ttype EventPublisherConnectionString,\n\ttype PublishableMessage,\n\tPublisher,\n} from '@geekmidas/events';\nimport type { Logger } from '@geekmidas/logger';\nimport { DEFAULT_LOGGER } from '@geekmidas/logger/console';\nimport {\n\tcanonicalId,\n\ttype Declaration,\n\tprovideKey,\n\tserviceKey,\n} from '@geekmidas/manifest';\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/**\n * The wire message a queue carries: `{ type: <queue name>, payload: <message> }`.\n * The producer publishes this shape and the worker receives the `payload`s as\n * its `messages`. Typing `type` to the queue name keeps the publisher fully\n * typed and lets pg-boss (local) / SQS (deployed) route by name.\n */\nexport type QueueMessage<\n\tTName extends string,\n\tTMessage extends StandardSchemaV1,\n> = PublishableMessage<TName, InferStandardSchema<TMessage>>;\n\n/**\n * A queue worker — a point-to-point SQS-style queue and its single consumer.\n * Unlike a `Subscriber` (topic fan-out, filtered by `subscribedEvents`), a queue\n * drains every message of its one `message` type. Build one from the worker\n * that runs it — `worker.queue('Emails').message(schema).handle(…)` — and\n * `gkm build` discovers it into the manifest's `queues` field.\n *\n * Producers send to it by depending on it: `.dependsOn([emails])` makes\n * `services.emails` the publisher.\n *\n * Its handler gets `db` when it has a database: the worker's, declared once\n * with `worker.database(db)`, or its own with `.database(other)`.\n */\nexport class Queue<\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> extends Construct<\n\tTLogger,\n\tundefined,\n\tTServices,\n\tstring,\n\tundefined,\n\tTDatabaseServiceName,\n\tTDatabase\n> {\n\t__IS_QUEUE__ = true;\n\n\tstatic isQueue(\n\t\tobj: unknown,\n\t): obj is Queue<string, StandardSchemaV1, Service[], Logger, any> {\n\t\treturn Boolean(\n\t\t\tobj &&\n\t\t\t\t(obj as { __IS_QUEUE__?: boolean }).__IS_QUEUE__ === true &&\n\t\t\t\t(obj as Construct).type === ConstructType.Queue,\n\t\t);\n\t}\n\n\t/**\n\t * The canonical id this queue is declared under.\n\t *\n\t * Derived from the name rather than given separately, so `emails` and\n\t * `Emails` are one queue. The name stays what it was: it is the wire `type`\n\t * a producer sends and the worker subscribes to, and changing that would\n\t * silently orphan in-flight messages.\n\t */\n\treadonly id: string;\n\n\t/**\n\t * The queue as a dependency — what `.dependsOn([emails])` dissolves into,\n\t * reachable as `services.emails`.\n\t *\n\t * The producer: the queue's one consumer is the handler it was built with,\n\t * so the only thing another construct can want from a queue is to send to\n\t * it. It reads `<NAME>_PUBLISHER_CONNECTION_STRING` and picks the transport\n\t * from its protocol — `pgboss://` locally, `sqs://` deployed. A field\n\t * assigned once, not a getter: services are cached by object identity.\n\t */\n\treadonly service: Service<\n\t\tUncapitalize<TName>,\n\t\tEventPublisher<QueueMessage<TName, TMessage>>\n\t>;\n\n\t/**\n\t * The producer's env key. Read by both {@link declare} and the service, so\n\t * what the target publishes and what the producer looks up cannot drift.\n\t */\n\tprivate readonly connectionKey: string;\n\n\tconstructor(\n\t\tpublic readonly name: TName,\n\t\tpublic readonly handler: QueueHandler<\n\t\t\tTMessage,\n\t\t\tTServices,\n\t\t\tTLogger,\n\t\t\tTDatabase\n\t\t>,\n\t\tpublic readonly messageSchema: TMessage,\n\t\tpublic override readonly timeout: number = 30000,\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/** SQS event-source batch size (deployed). */\n\t\tpublic readonly batchSize?: number,\n\t\t/** Whether the queue is FIFO (deployed). */\n\t\tpublic readonly fifo?: boolean,\n\t\t/**\n\t\t * The construct ids the *worker* `.dependsOn()` named — last, so no\n\t\t * existing positional 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.Queue,\n\t\t\tlogger,\n\t\t\tservices,\n\t\t\t[],\n\t\t\tundefined,\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\tthis.id = canonicalId(name);\n\t\tthis.connectionKey = provideKey(this.id, 'publisherConnectionString');\n\n\t\tconst envVar = this.connectionKey;\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\treturn Publisher.fromConnectionString<QueueMessage<TName, TMessage>>(\n\t\t\t\t\tconnectionString as EventPublisherConnectionString,\n\t\t\t\t);\n\t\t\t},\n\t\t};\n\t}\n\n\t/**\n\t * What this queue is in the manifest.\n\t *\n\t * A queue is a resource, not a handler: the worker is reached *through* it,\n\t * so the declaration carries the producer's key and nothing about the code\n\t * that drains it. The local target reads this to know which broker has to be\n\t * running and what connection string to inject.\n\t */\n\tdeclare(): Declaration[] {\n\t\treturn [\n\t\t\t{\n\t\t\t\tkind: 'queue',\n\t\t\t\tid: this.id,\n\t\t\t\tprovides: [this.connectionKey],\n\t\t\t\t...(this.fifo ? { fifo: true } : {}),\n\t\t\t\t// Nested rather than a sibling node, because position carries the\n\t\t\t\t// trigger: this handler is reached by messages on this queue and\n\t\t\t\t// by nothing else, so there is no `trigger` field to keep in step.\n\t\t\t\t//\n\t\t\t\t// `handler` is the export name; which directory the build wrote it\n\t\t\t\t// to is the target's business, and a path with a cloud in it does\n\t\t\t\t// not belong in a neutral declaration.\n\t\t\t\tworker: {\n\t\t\t\t\tid: `${this.id}Worker`,\n\t\t\t\t\thandler: `${this.id}.handler`,\n\t\t\t\t\t// Filled by the build from what the worker declared. Empty is a\n\t\t\t\t\t// stated gap, not a claim that it reaches nothing.\n\t\t\t\t\tdependencies: [],\n\t\t\t\t},\n\t\t\t},\n\t\t];\n\t}\n}\n\n/**\n * The context a queue handler receives — a batch of typed messages, and `db`\n * when the queue has a database.\n */\nexport type QueueContext<\n\tTMessage extends StandardSchemaV1,\n\tTServices extends Service[] = [],\n\tTLogger extends Logger = Logger,\n\tTDatabase = undefined,\n> = {\n\tmessages: InferStandardSchema<TMessage>[];\n\tservices: ServiceRecord<TServices>;\n\tlogger: TLogger;\n} & DatabaseContext<TDatabase>;\n\nexport type QueueHandler<\n\tTMessage extends StandardSchemaV1,\n\tTServices extends Service[] = [],\n\tTLogger extends Logger = Logger,\n\tTDatabase = undefined,\n> = (\n\tctx: QueueContext<TMessage, TServices, TLogger, TDatabase>,\n) => unknown | Promise<unknown>;\n"],"mappings":";;;;;;;;;;;;;;;;;;AA4CA,IAAa,QAAb,cAOU,UAQR;CA6CgB;CACA;CAMA;CACS;CACA;CACA;CAET;CAEA;CA1DjB,eAAe;CAEf,OAAO,QACN,KACiE;EACjE,OAAO,QACN,OACE,IAAmC,iBAAiB,QACpD,IAAkB,SAAA,8BACrB;CACD;;;;;;;;;CAUA;;;;;;;;;;;CAYA;;;;;CASA;CAEA,YACC,MACA,SAMA,eACA,UAA2C,KAC3C,WAA+C,CAAC,GAChD,SAA2C,gBAE3C,WAEA,MAKA,aAAuB,CAAC,GAKxB,iBACC;EACD,MAAA,gCAEC,QACA,UACA,CAAC,GACD,KAAA,GACA,SACA,KAAA,GACA,KAAA,GACA,UACD;EApCgB,KAAA,OAAA;EACA,KAAA,UAAA;EAMA,KAAA,gBAAA;EACS,KAAA,UAAA;EACA,KAAA,WAAA;EACA,KAAA,SAAA;EAET,KAAA,YAAA;EAEA,KAAA,OAAA;EAwBhB,KAAK,kBAAkB;EACvB,KAAK,KAAK,YAAY,IAAI;EAC1B,KAAK,gBAAgB,WAAW,KAAK,IAAI,2BAA2B;EAEpE,MAAM,SAAS,KAAK;EACpB,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;IAER,OAAO,UAAU,qBAChB,gBACD;GACD;EACD;CACD;;;;;;;;;CAUA,UAAyB;EACxB,OAAO,CACN;GACC,MAAM;GACN,IAAI,KAAK;GACT,UAAU,CAAC,KAAK,aAAa;GAC7B,GAAI,KAAK,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;GAQlC,QAAQ;IACP,IAAI,GAAG,KAAK,GAAG;IACf,SAAS,GAAG,KAAK,GAAG;IAGpB,cAAc,CAAC;GAChB;EACD,CACD;CACD;AACD"}
@@ -1,6 +1,6 @@
1
1
  const require_construct_interface = require("./construct-interface.cjs");
2
2
  const require_clone = require("./clone-UGJpvQnL.cjs");
3
- const require_Queue = require("./Queue-Ckmudcm8.cjs");
3
+ const require_Queue = require("./Queue-D5jcw0mu.cjs");
4
4
  let _geekmidas_logger_console = require("@geekmidas/logger/console");
5
5
  //#region src/queue/QueueBuilder.ts
6
6
  /**
@@ -8,7 +8,8 @@ let _geekmidas_logger_console = require("@geekmidas/logger/console");
8
8
  * `worker.queue('orders')`, never constructed by hand: the worker stamps itself
9
9
  * as the owner. `message` is the typed job payload and `handle` the consumer.
10
10
  * The queue name is captured as a literal so `queue.service` publishes
11
- * `{ type: '<name>', payload }`.
11
+ * `{ type: '<name>', payload }`. The handler's `db` is the worker's database
12
+ * unless `.database(other)` names another.
12
13
  */
13
14
  var QueueBuilder = class {
14
15
  _name;
@@ -22,6 +23,10 @@ var QueueBuilder = class {
22
23
  _logger = _geekmidas_logger_console.DEFAULT_LOGGER;
23
24
  /** The worker that runs this queue's consumer — stamped by `worker.queue()`. */
24
25
  _owner;
26
+ /** What the handler's `db` comes from — the worker's, unless overridden. */
27
+ _databaseService;
28
+ /** The edge `.database()` added, so the next one can replace it. */
29
+ _databaseEdge;
25
30
  /** The queue name — drives the infra queue and its `<NAME>_*` env vars. */
26
31
  queue(name) {
27
32
  return require_clone.cloneWith(this, { _name: name });
@@ -61,6 +66,24 @@ var QueueBuilder = class {
61
66
  logger(logger) {
62
67
  return require_clone.cloneWith(this, { _logger: logger });
63
68
  }
69
+ /**
70
+ * The database the handler receives as `db`.
71
+ *
72
+ * A queue built from a worker already has the worker's, when the worker
73
+ * named one with `.database(db)`; this replaces it — the edge as well as
74
+ * the client — for a consumer that works against a different database.
75
+ */
76
+ database(source) {
77
+ return require_clone.cloneWith(this, {
78
+ _databaseService: require_construct_interface.serviceOf(source),
79
+ ...require_construct_interface.databaseEdges({
80
+ constructs: this._constructs,
81
+ edge: this._databaseEdge,
82
+ service: this._databaseService,
83
+ services: this._services
84
+ }, source)
85
+ });
86
+ }
64
87
  /** The typed message (job) payload the queue carries. */
65
88
  message(schema) {
66
89
  return require_clone.cloneWith(this, { _messageSchema: schema });
@@ -68,7 +91,7 @@ var QueueBuilder = class {
68
91
  handle(fn) {
69
92
  if (!this._name) throw new QueueNeedsName();
70
93
  if (!this._messageSchema) throw new QueueNeedsMessage(this._name);
71
- const queue = new require_Queue.Queue(this._name, fn, this._messageSchema, this._timeout, this._services, this._logger, this._batchSize, this._fifo, this._constructs);
94
+ const queue = new require_Queue.Queue(this._name, fn, this._messageSchema, this._timeout, this._services, this._logger, this._batchSize, this._fifo, this._constructs, this._databaseService);
72
95
  queue.owner = this._owner;
73
96
  return queue;
74
97
  }
@@ -109,4 +132,4 @@ Object.defineProperty(exports, "QueueNeedsName", {
109
132
  }
110
133
  });
111
134
 
112
- //# sourceMappingURL=QueueBuilder-CJNcv4dy.cjs.map
135
+ //# sourceMappingURL=QueueBuilder-BFQn3OzZ.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"QueueBuilder-BFQn3OzZ.cjs","names":["DEFAULT_LOGGER","cloneWith","servicesOf","idsOf","serviceOf","databaseEdges","Queue"],"sources":["../src/queue/QueueBuilder.ts"],"sourcesContent":["import 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 { Queue, type QueueHandler } from './Queue';\n\n/**\n * Builds a {@link Queue} and its one consumer. Reached through\n * `worker.queue('orders')`, never constructed by hand: the worker stamps itself\n * as the owner. `message` is the typed job payload and `handle` the consumer.\n * The queue name is captured as a literal so `queue.service` publishes\n * `{ type: '<name>', payload }`. The handler's `db` is the worker's database\n * unless `.database(other)` names another.\n */\nexport class QueueBuilder<\n\tTName extends string = string,\n\tTMessage extends StandardSchemaV1 | undefined = undefined,\n\tTServices extends Service[] = [],\n\tTLogger extends Logger = Logger,\n\tTDatabase = undefined,\n\tTDatabaseServiceName extends string = string,\n> {\n\tprivate _name?: string;\n\tprivate _messageSchema?: TMessage;\n\tprivate _timeout = 30000;\n\tprivate _batchSize?: number;\n\tprivate _fifo?: boolean;\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 as TLogger;\n\t/** The worker that runs this queue's consumer — stamped by `worker.queue()`. */\n\tpublic _owner?: 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\t/** The queue name — drives the infra queue and its `<NAME>_*` env vars. */\n\tqueue<T extends string>(\n\t\tname: T,\n\t): QueueBuilder<\n\t\tT,\n\t\tTMessage,\n\t\tTServices,\n\t\tTLogger,\n\t\tTDatabase,\n\t\tTDatabaseServiceName\n\t> {\n\t\treturn cloneWith(this, { _name: name }) as unknown as QueueBuilder<\n\t\t\tT,\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\ttimeout(timeout: number): this {\n\t\treturn cloneWith(this, { _timeout: timeout });\n\t}\n\n\t/** SQS event-source batch size (deployed). */\n\tbatchSize(batchSize: number): this {\n\t\treturn cloneWith(this, { _batchSize: batchSize });\n\t}\n\n\t/** Mark the queue as FIFO (deployed). */\n\tfifo(fifo = true): this {\n\t\treturn cloneWith(this, { _fifo: fifo });\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): QueueBuilder<\n\t\tTName,\n\t\tTMessage,\n\t\t[...TServices, ...ServicesOf<T>],\n\t\tTLogger,\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 QueueBuilder<\n\t\t\tTName,\n\t\t\tTMessage,\n\t\t\t[...TServices, ...ServicesOf<T>],\n\t\t\tTLogger,\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): QueueBuilder<\n\t\tTName,\n\t\tTMessage,\n\t\t[...TServices, ...T],\n\t\tTLogger,\n\t\tTDatabase,\n\t\tTDatabaseServiceName\n\t> {\n\t\treturn cloneWith(this, {\n\t\t\t_services: [...this._services, ...services] as unknown as TServices,\n\t\t}) as unknown as QueueBuilder<\n\t\t\tTName,\n\t\t\tTMessage,\n\t\t\t[...TServices, ...T],\n\t\t\tTLogger,\n\t\t\tTDatabase,\n\t\t\tTDatabaseServiceName\n\t\t>;\n\t}\n\n\tlogger<T extends Logger>(\n\t\tlogger: T,\n\t): QueueBuilder<\n\t\tTName,\n\t\tTMessage,\n\t\tTServices,\n\t\tT,\n\t\tTDatabase,\n\t\tTDatabaseServiceName\n\t> {\n\t\treturn cloneWith(this, {\n\t\t\t_logger: logger as unknown as TLogger,\n\t\t}) as unknown as QueueBuilder<\n\t\t\tTName,\n\t\t\tTMessage,\n\t\t\tTServices,\n\t\t\tT,\n\t\t\tTDatabase,\n\t\t\tTDatabaseServiceName\n\t\t>;\n\t}\n\n\t/**\n\t * The database the handler receives as `db`.\n\t *\n\t * A queue built from a worker already has the worker's, when the worker\n\t * named one with `.database(db)`; this replaces it — the edge as well as\n\t * 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): QueueBuilder<TName, TMessage, TServices, TLogger, T, TDbName> {\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 QueueBuilder<\n\t\t\tTName,\n\t\t\tTMessage,\n\t\t\tTServices,\n\t\t\tTLogger,\n\t\t\tT,\n\t\t\tTDbName\n\t\t>;\n\t}\n\n\t/** The typed message (job) payload the queue carries. */\n\tmessage<T extends StandardSchemaV1>(\n\t\tschema: T,\n\t): QueueBuilder<\n\t\tTName,\n\t\tT,\n\t\tTServices,\n\t\tTLogger,\n\t\tTDatabase,\n\t\tTDatabaseServiceName\n\t> {\n\t\treturn cloneWith(this, {\n\t\t\t_messageSchema: schema as unknown as TMessage,\n\t\t}) as unknown as QueueBuilder<\n\t\t\tTName,\n\t\t\tT,\n\t\t\tTServices,\n\t\t\tTLogger,\n\t\t\tTDatabase,\n\t\t\tTDatabaseServiceName\n\t\t>;\n\t}\n\n\thandle(\n\t\tfn: QueueHandler<NonNullable<TMessage>, TServices, TLogger, TDatabase>,\n\t): Queue<\n\t\tTName,\n\t\tNonNullable<TMessage>,\n\t\tTServices,\n\t\tTLogger,\n\t\tTDatabase,\n\t\tTDatabaseServiceName\n\t> {\n\t\tif (!this._name) throw new QueueNeedsName();\n\t\tif (!this._messageSchema) throw new QueueNeedsMessage(this._name);\n\n\t\tconst queue = new Queue<\n\t\t\tTName,\n\t\t\tNonNullable<TMessage>,\n\t\t\tTServices,\n\t\t\tTLogger,\n\t\t\tTDatabase,\n\t\t\tTDatabaseServiceName\n\t\t>(\n\t\t\tthis._name as TName,\n\t\t\tfn,\n\t\t\tthis._messageSchema as NonNullable<TMessage>,\n\t\t\tthis._timeout,\n\t\t\tthis._services,\n\t\t\tthis._logger,\n\t\t\tthis._batchSize,\n\t\t\tthis._fifo,\n\t\t\tthis._constructs,\n\t\t\tthis._databaseService,\n\t\t);\n\t\t// Which process runs the consumer: the worker it was built from.\n\t\tqueue.owner = this._owner;\n\n\t\t// No reset. `.handle()` reads this builder and leaves it alone, so a\n\t\t// configured base — `const fn = f.logger(log).timeout(60_000)` — keeps\n\t\t// its configuration for every construct built from it. The reset that\n\t\t// used to be here wiped the base on first use, which made a base usable\n\t\t// exactly once, and quietly reverted the logger to the default.\n\n\t\treturn queue;\n\t}\n}\n\n/** A queue built without a name — only reachable by building one by hand. */\nexport class QueueNeedsName extends Error {\n\tconstructor() {\n\t\tsuper(\n\t\t\t\"A queue needs a name: build it from a worker, worker.queue('Emails').\",\n\t\t);\n\t\tthis.name = 'QueueNeedsName';\n\t}\n}\n\n/** A queue whose message was never described. */\nexport class QueueNeedsMessage extends Error {\n\tconstructor(readonly queue: string) {\n\t\tsuper(\n\t\t\t`Queue '${queue}' has no message: call .message(schema) before .handle(), ` +\n\t\t\t\t'so its producers and its consumer agree on what it carries.',\n\t\t);\n\t\tthis.name = 'QueueNeedsMessage';\n\t}\n}\n"],"mappings":";;;;;;;;;;;;;AAuBA,IAAa,eAAb,MAOE;CACD;CACA;CACA,WAAmB;CACnB;CACA;CACA,YAA+B,CAAC;;CAEhC,cAA+B,CAAC;CAChC,UAA2BA,0BAAAA;;CAE3B;;CAEA;;CAEA;;CAGA,MACC,MAQC;EACD,OAAOC,cAAAA,UAAU,MAAM,EAAE,OAAO,KAAK,CAAC;CAQvC;CAEA,QAAQ,SAAuB;EAC9B,OAAOA,cAAAA,UAAU,MAAM,EAAE,UAAU,QAAQ,CAAC;CAC7C;;CAGA,UAAU,WAAyB;EAClC,OAAOA,cAAAA,UAAU,MAAM,EAAE,YAAY,UAAU,CAAC;CACjD;;CAGA,KAAK,OAAO,MAAY;EACvB,OAAOA,cAAAA,UAAU,MAAM,EAAE,OAAO,KAAK,CAAC;CACvC;;;;;;;;;;;;CAaA,UACC,YAQC;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;CAQF;CAEA,SACC,UAQC;EACD,OAAOF,cAAAA,UAAU,MAAM,EACtB,WAAW,CAAC,GAAG,KAAK,WAAW,GAAG,QAAQ,EAC3C,CAAC;CAQF;CAEA,OACC,QAQC;EACD,OAAOA,cAAAA,UAAU,MAAM,EACtB,SAAS,OACV,CAAC;CAQF;;;;;;;;CASA,SACC,QACgE;EAChE,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;CAQF;;CAGA,QACC,QAQC;EACD,OAAOJ,cAAAA,UAAU,MAAM,EACtB,gBAAgB,OACjB,CAAC;CAQF;CAEA,OACC,IAQC;EACD,IAAI,CAAC,KAAK,OAAO,MAAM,IAAI,eAAe;EAC1C,IAAI,CAAC,KAAK,gBAAgB,MAAM,IAAI,kBAAkB,KAAK,KAAK;EAEhE,MAAM,QAAQ,IAAIK,cAAAA,MAQjB,KAAK,OACL,IACA,KAAK,gBACL,KAAK,UACL,KAAK,WACL,KAAK,SACL,KAAK,YACL,KAAK,OACL,KAAK,aACL,KAAK,gBACN;EAEA,MAAM,QAAQ,KAAK;EAQnB,OAAO;CACR;AACD;;AAGA,IAAa,iBAAb,cAAoC,MAAM;CACzC,cAAc;EACb,MACC,uEACD;EACA,KAAK,OAAO;CACb;AACD;;AAGA,IAAa,oBAAb,cAAuC,MAAM;CACvB;CAArB,YAAY,OAAwB;EACnC,MACC,UAAU,MAAM,sHAEjB;EAJoB,KAAA,QAAA;EAKpB,KAAK,OAAO;CACb;AACD"}
@@ -1,6 +1,6 @@
1
- import { idsOf, servicesOf } from "./construct-interface.mjs";
1
+ import { databaseEdges, idsOf, serviceOf, servicesOf } from "./construct-interface.mjs";
2
2
  import { t as cloneWith } from "./clone-EKNovYHu.mjs";
3
- import { t as Queue } from "./Queue-C1uDgjxt.mjs";
3
+ import { t as Queue } from "./Queue-hwPN-t31.mjs";
4
4
  import { DEFAULT_LOGGER } from "@geekmidas/logger/console";
5
5
  //#region src/queue/QueueBuilder.ts
6
6
  /**
@@ -8,7 +8,8 @@ import { DEFAULT_LOGGER } from "@geekmidas/logger/console";
8
8
  * `worker.queue('orders')`, never constructed by hand: the worker stamps itself
9
9
  * as the owner. `message` is the typed job payload and `handle` the consumer.
10
10
  * The queue name is captured as a literal so `queue.service` publishes
11
- * `{ type: '<name>', payload }`.
11
+ * `{ type: '<name>', payload }`. The handler's `db` is the worker's database
12
+ * unless `.database(other)` names another.
12
13
  */
13
14
  var QueueBuilder = class {
14
15
  _name;
@@ -22,6 +23,10 @@ var QueueBuilder = class {
22
23
  _logger = DEFAULT_LOGGER;
23
24
  /** The worker that runs this queue's consumer — stamped by `worker.queue()`. */
24
25
  _owner;
26
+ /** What the handler's `db` comes from — the worker's, unless overridden. */
27
+ _databaseService;
28
+ /** The edge `.database()` added, so the next one can replace it. */
29
+ _databaseEdge;
25
30
  /** The queue name — drives the infra queue and its `<NAME>_*` env vars. */
26
31
  queue(name) {
27
32
  return cloneWith(this, { _name: name });
@@ -61,6 +66,24 @@ var QueueBuilder = class {
61
66
  logger(logger) {
62
67
  return cloneWith(this, { _logger: logger });
63
68
  }
69
+ /**
70
+ * The database the handler receives as `db`.
71
+ *
72
+ * A queue built from a worker already has the worker's, when the worker
73
+ * named one with `.database(db)`; this replaces it — the edge as well as
74
+ * the client — for a consumer that works against a different database.
75
+ */
76
+ database(source) {
77
+ return cloneWith(this, {
78
+ _databaseService: serviceOf(source),
79
+ ...databaseEdges({
80
+ constructs: this._constructs,
81
+ edge: this._databaseEdge,
82
+ service: this._databaseService,
83
+ services: this._services
84
+ }, source)
85
+ });
86
+ }
64
87
  /** The typed message (job) payload the queue carries. */
65
88
  message(schema) {
66
89
  return cloneWith(this, { _messageSchema: schema });
@@ -68,7 +91,7 @@ var QueueBuilder = class {
68
91
  handle(fn) {
69
92
  if (!this._name) throw new QueueNeedsName();
70
93
  if (!this._messageSchema) throw new QueueNeedsMessage(this._name);
71
- const queue = new Queue(this._name, fn, this._messageSchema, this._timeout, this._services, this._logger, this._batchSize, this._fifo, this._constructs);
94
+ const queue = new Queue(this._name, fn, this._messageSchema, this._timeout, this._services, this._logger, this._batchSize, this._fifo, this._constructs, this._databaseService);
72
95
  queue.owner = this._owner;
73
96
  return queue;
74
97
  }
@@ -92,4 +115,4 @@ var QueueNeedsMessage = class extends Error {
92
115
  //#endregion
93
116
  export { QueueNeedsMessage as n, QueueNeedsName as r, QueueBuilder as t };
94
117
 
95
- //# sourceMappingURL=QueueBuilder-XuPKZwKH.mjs.map
118
+ //# sourceMappingURL=QueueBuilder-DCuYdjMw.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"QueueBuilder-DCuYdjMw.mjs","names":[],"sources":["../src/queue/QueueBuilder.ts"],"sourcesContent":["import 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 { Queue, type QueueHandler } from './Queue';\n\n/**\n * Builds a {@link Queue} and its one consumer. Reached through\n * `worker.queue('orders')`, never constructed by hand: the worker stamps itself\n * as the owner. `message` is the typed job payload and `handle` the consumer.\n * The queue name is captured as a literal so `queue.service` publishes\n * `{ type: '<name>', payload }`. The handler's `db` is the worker's database\n * unless `.database(other)` names another.\n */\nexport class QueueBuilder<\n\tTName extends string = string,\n\tTMessage extends StandardSchemaV1 | undefined = undefined,\n\tTServices extends Service[] = [],\n\tTLogger extends Logger = Logger,\n\tTDatabase = undefined,\n\tTDatabaseServiceName extends string = string,\n> {\n\tprivate _name?: string;\n\tprivate _messageSchema?: TMessage;\n\tprivate _timeout = 30000;\n\tprivate _batchSize?: number;\n\tprivate _fifo?: boolean;\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 as TLogger;\n\t/** The worker that runs this queue's consumer — stamped by `worker.queue()`. */\n\tpublic _owner?: 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\t/** The queue name — drives the infra queue and its `<NAME>_*` env vars. */\n\tqueue<T extends string>(\n\t\tname: T,\n\t): QueueBuilder<\n\t\tT,\n\t\tTMessage,\n\t\tTServices,\n\t\tTLogger,\n\t\tTDatabase,\n\t\tTDatabaseServiceName\n\t> {\n\t\treturn cloneWith(this, { _name: name }) as unknown as QueueBuilder<\n\t\t\tT,\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\ttimeout(timeout: number): this {\n\t\treturn cloneWith(this, { _timeout: timeout });\n\t}\n\n\t/** SQS event-source batch size (deployed). */\n\tbatchSize(batchSize: number): this {\n\t\treturn cloneWith(this, { _batchSize: batchSize });\n\t}\n\n\t/** Mark the queue as FIFO (deployed). */\n\tfifo(fifo = true): this {\n\t\treturn cloneWith(this, { _fifo: fifo });\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): QueueBuilder<\n\t\tTName,\n\t\tTMessage,\n\t\t[...TServices, ...ServicesOf<T>],\n\t\tTLogger,\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 QueueBuilder<\n\t\t\tTName,\n\t\t\tTMessage,\n\t\t\t[...TServices, ...ServicesOf<T>],\n\t\t\tTLogger,\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): QueueBuilder<\n\t\tTName,\n\t\tTMessage,\n\t\t[...TServices, ...T],\n\t\tTLogger,\n\t\tTDatabase,\n\t\tTDatabaseServiceName\n\t> {\n\t\treturn cloneWith(this, {\n\t\t\t_services: [...this._services, ...services] as unknown as TServices,\n\t\t}) as unknown as QueueBuilder<\n\t\t\tTName,\n\t\t\tTMessage,\n\t\t\t[...TServices, ...T],\n\t\t\tTLogger,\n\t\t\tTDatabase,\n\t\t\tTDatabaseServiceName\n\t\t>;\n\t}\n\n\tlogger<T extends Logger>(\n\t\tlogger: T,\n\t): QueueBuilder<\n\t\tTName,\n\t\tTMessage,\n\t\tTServices,\n\t\tT,\n\t\tTDatabase,\n\t\tTDatabaseServiceName\n\t> {\n\t\treturn cloneWith(this, {\n\t\t\t_logger: logger as unknown as TLogger,\n\t\t}) as unknown as QueueBuilder<\n\t\t\tTName,\n\t\t\tTMessage,\n\t\t\tTServices,\n\t\t\tT,\n\t\t\tTDatabase,\n\t\t\tTDatabaseServiceName\n\t\t>;\n\t}\n\n\t/**\n\t * The database the handler receives as `db`.\n\t *\n\t * A queue built from a worker already has the worker's, when the worker\n\t * named one with `.database(db)`; this replaces it — the edge as well as\n\t * 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): QueueBuilder<TName, TMessage, TServices, TLogger, T, TDbName> {\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 QueueBuilder<\n\t\t\tTName,\n\t\t\tTMessage,\n\t\t\tTServices,\n\t\t\tTLogger,\n\t\t\tT,\n\t\t\tTDbName\n\t\t>;\n\t}\n\n\t/** The typed message (job) payload the queue carries. */\n\tmessage<T extends StandardSchemaV1>(\n\t\tschema: T,\n\t): QueueBuilder<\n\t\tTName,\n\t\tT,\n\t\tTServices,\n\t\tTLogger,\n\t\tTDatabase,\n\t\tTDatabaseServiceName\n\t> {\n\t\treturn cloneWith(this, {\n\t\t\t_messageSchema: schema as unknown as TMessage,\n\t\t}) as unknown as QueueBuilder<\n\t\t\tTName,\n\t\t\tT,\n\t\t\tTServices,\n\t\t\tTLogger,\n\t\t\tTDatabase,\n\t\t\tTDatabaseServiceName\n\t\t>;\n\t}\n\n\thandle(\n\t\tfn: QueueHandler<NonNullable<TMessage>, TServices, TLogger, TDatabase>,\n\t): Queue<\n\t\tTName,\n\t\tNonNullable<TMessage>,\n\t\tTServices,\n\t\tTLogger,\n\t\tTDatabase,\n\t\tTDatabaseServiceName\n\t> {\n\t\tif (!this._name) throw new QueueNeedsName();\n\t\tif (!this._messageSchema) throw new QueueNeedsMessage(this._name);\n\n\t\tconst queue = new Queue<\n\t\t\tTName,\n\t\t\tNonNullable<TMessage>,\n\t\t\tTServices,\n\t\t\tTLogger,\n\t\t\tTDatabase,\n\t\t\tTDatabaseServiceName\n\t\t>(\n\t\t\tthis._name as TName,\n\t\t\tfn,\n\t\t\tthis._messageSchema as NonNullable<TMessage>,\n\t\t\tthis._timeout,\n\t\t\tthis._services,\n\t\t\tthis._logger,\n\t\t\tthis._batchSize,\n\t\t\tthis._fifo,\n\t\t\tthis._constructs,\n\t\t\tthis._databaseService,\n\t\t);\n\t\t// Which process runs the consumer: the worker it was built from.\n\t\tqueue.owner = this._owner;\n\n\t\t// No reset. `.handle()` reads this builder and leaves it alone, so a\n\t\t// configured base — `const fn = f.logger(log).timeout(60_000)` — keeps\n\t\t// its configuration for every construct built from it. The reset that\n\t\t// used to be here wiped the base on first use, which made a base usable\n\t\t// exactly once, and quietly reverted the logger to the default.\n\n\t\treturn queue;\n\t}\n}\n\n/** A queue built without a name — only reachable by building one by hand. */\nexport class QueueNeedsName extends Error {\n\tconstructor() {\n\t\tsuper(\n\t\t\t\"A queue needs a name: build it from a worker, worker.queue('Emails').\",\n\t\t);\n\t\tthis.name = 'QueueNeedsName';\n\t}\n}\n\n/** A queue whose message was never described. */\nexport class QueueNeedsMessage extends Error {\n\tconstructor(readonly queue: string) {\n\t\tsuper(\n\t\t\t`Queue '${queue}' has no message: call .message(schema) before .handle(), ` +\n\t\t\t\t'so its producers and its consumer agree on what it carries.',\n\t\t);\n\t\tthis.name = 'QueueNeedsMessage';\n\t}\n}\n"],"mappings":";;;;;;;;;;;;;AAuBA,IAAa,eAAb,MAOE;CACD;CACA;CACA,WAAmB;CACnB;CACA;CACA,YAA+B,CAAC;;CAEhC,cAA+B,CAAC;CAChC,UAA2B;;CAE3B;;CAEA;;CAEA;;CAGA,MACC,MAQC;EACD,OAAO,UAAU,MAAM,EAAE,OAAO,KAAK,CAAC;CAQvC;CAEA,QAAQ,SAAuB;EAC9B,OAAO,UAAU,MAAM,EAAE,UAAU,QAAQ,CAAC;CAC7C;;CAGA,UAAU,WAAyB;EAClC,OAAO,UAAU,MAAM,EAAE,YAAY,UAAU,CAAC;CACjD;;CAGA,KAAK,OAAO,MAAY;EACvB,OAAO,UAAU,MAAM,EAAE,OAAO,KAAK,CAAC;CACvC;;;;;;;;;;;;CAaA,UACC,YAQC;EAQD,MAAM,WAAW,WAAW,UAAU;EAEtC,OAAO,UAAU,MAAM;GACtB,WAAW,CAAC,GAAG,KAAK,WAAW,GAAG,QAAQ;GAC1C,aAAa,MAAM,YAAY,KAAK,WAAW;EAChD,CAAC;CAQF;CAEA,SACC,UAQC;EACD,OAAO,UAAU,MAAM,EACtB,WAAW,CAAC,GAAG,KAAK,WAAW,GAAG,QAAQ,EAC3C,CAAC;CAQF;CAEA,OACC,QAQC;EACD,OAAO,UAAU,MAAM,EACtB,SAAS,OACV,CAAC;CAQF;;;;;;;;CASA,SACC,QACgE;EAChE,OAAO,UAAU,MAAM;GACtB,kBAAkB,UAAU,MAAM;GAClC,GAAG,cACF;IACC,YAAY,KAAK;IACjB,MAAM,KAAK;IACX,SAAS,KAAK;IACd,UAAU,KAAK;GAChB,GACA,MACD;EACD,CAAC;CAQF;;CAGA,QACC,QAQC;EACD,OAAO,UAAU,MAAM,EACtB,gBAAgB,OACjB,CAAC;CAQF;CAEA,OACC,IAQC;EACD,IAAI,CAAC,KAAK,OAAO,MAAM,IAAI,eAAe;EAC1C,IAAI,CAAC,KAAK,gBAAgB,MAAM,IAAI,kBAAkB,KAAK,KAAK;EAEhE,MAAM,QAAQ,IAAI,MAQjB,KAAK,OACL,IACA,KAAK,gBACL,KAAK,UACL,KAAK,WACL,KAAK,SACL,KAAK,YACL,KAAK,OACL,KAAK,aACL,KAAK,gBACN;EAEA,MAAM,QAAQ,KAAK;EAQnB,OAAO;CACR;AACD;;AAGA,IAAa,iBAAb,cAAoC,MAAM;CACzC,cAAc;EACb,MACC,uEACD;EACA,KAAK,OAAO;CACb;AACD;;AAGA,IAAa,oBAAb,cAAuC,MAAM;CACvB;CAArB,YAAY,OAAwB;EACnC,MACC,UAAU,MAAM,sHAEjB;EAJoB,KAAA,QAAA;EAKpB,KAAK,OAAO;CACb;AACD"}
@@ -1,6 +1,6 @@
1
1
  import { t as StandardSchemaV1 } from "./index-CeEtxDmK.cjs";
2
- import { c as ServicesOf, r as Consumable } from "./construct-interface-_xi4BPN8.cjs";
3
- import { r as QueueHandler, t as Queue } from "./Queue-CpQIGB_2.cjs";
2
+ import { c as ServicesOf, r as Consumable } from "./construct-interface-B1AfqRl4.cjs";
3
+ import { r as QueueHandler, t as Queue } from "./Queue-HPyi0e1i.cjs";
4
4
  import { Logger } from "@geekmidas/logger";
5
5
  import { Service } from "@geekmidas/services";
6
6
  //#region src/queue/QueueBuilder.d.ts
@@ -9,9 +9,10 @@ import { Service } from "@geekmidas/services";
9
9
  * `worker.queue('orders')`, never constructed by hand: the worker stamps itself
10
10
  * as the owner. `message` is the typed job payload and `handle` the consumer.
11
11
  * The queue name is captured as a literal so `queue.service` publishes
12
- * `{ type: '<name>', payload }`.
12
+ * `{ type: '<name>', payload }`. The handler's `db` is the worker's database
13
+ * unless `.database(other)` names another.
13
14
  */
14
- declare class QueueBuilder<TName extends string = string, TMessage extends StandardSchemaV1 | undefined = undefined, TServices extends Service[] = [], TLogger extends Logger = Logger> {
15
+ declare class QueueBuilder<TName extends string = string, TMessage extends StandardSchemaV1 | undefined = undefined, TServices extends Service[] = [], TLogger extends Logger = Logger, TDatabase = undefined, TDatabaseServiceName extends string = string> {
15
16
  private _name?;
16
17
  private _messageSchema?;
17
18
  private _timeout;
@@ -23,8 +24,12 @@ declare class QueueBuilder<TName extends string = string, TMessage extends Stand
23
24
  private _logger;
24
25
  /** The worker that runs this queue's consumer — stamped by `worker.queue()`. */
25
26
  _owner?: string;
27
+ /** What the handler's `db` comes from — the worker's, unless overridden. */
28
+ private _databaseService?;
29
+ /** The edge `.database()` added, so the next one can replace it. */
30
+ private _databaseEdge?;
26
31
  /** The queue name — drives the infra queue and its `<NAME>_*` env vars. */
27
- queue<T extends string>(name: T): QueueBuilder<T, TMessage, TServices, TLogger>;
32
+ queue<T extends string>(name: T): QueueBuilder<T, TMessage, TServices, TLogger, TDatabase, TDatabaseServiceName>;
28
33
  timeout(timeout: number): this;
29
34
  /** SQS event-source batch size (deployed). */
30
35
  batchSize(batchSize: number): this;
@@ -41,12 +46,20 @@ declare class QueueBuilder<TName extends string = string, TMessage extends Stand
41
46
  * Constructs only. A `Service` does not match the shape, which is what keeps
42
47
  * env sniffing confined to `.services()` and the explicit lift.
43
48
  */
44
- dependsOn<const T extends readonly Consumable[]>(constructs: T): QueueBuilder<TName, TMessage, [...TServices, ...ServicesOf<T>], TLogger>;
45
- services<T extends Service[]>(services: T): QueueBuilder<TName, TMessage, [...TServices, ...T], TLogger>;
46
- logger<T extends Logger>(logger: T): QueueBuilder<TName, TMessage, TServices, T>;
49
+ dependsOn<const T extends readonly Consumable[]>(constructs: T): QueueBuilder<TName, TMessage, [...TServices, ...ServicesOf<T>], TLogger, TDatabase, TDatabaseServiceName>;
50
+ services<T extends Service[]>(services: T): QueueBuilder<TName, TMessage, [...TServices, ...T], TLogger, TDatabase, TDatabaseServiceName>;
51
+ logger<T extends Logger>(logger: T): QueueBuilder<TName, TMessage, TServices, T, TDatabase, TDatabaseServiceName>;
52
+ /**
53
+ * The database the handler receives as `db`.
54
+ *
55
+ * A queue built from a worker already has the worker's, when the worker
56
+ * named one with `.database(db)`; this replaces it — the edge as well as
57
+ * the client — for a consumer that works against a different database.
58
+ */
59
+ database<T, TDbName extends string>(source: Consumable<TDbName, T> | Service<TDbName, T>): QueueBuilder<TName, TMessage, TServices, TLogger, T, TDbName>;
47
60
  /** The typed message (job) payload the queue carries. */
48
- message<T extends StandardSchemaV1>(schema: T): QueueBuilder<TName, T, TServices, TLogger>;
49
- handle(fn: QueueHandler<NonNullable<TMessage>, TServices, TLogger>): Queue<TName, NonNullable<TMessage>, TServices, TLogger>;
61
+ message<T extends StandardSchemaV1>(schema: T): QueueBuilder<TName, T, TServices, TLogger, TDatabase, TDatabaseServiceName>;
62
+ handle(fn: QueueHandler<NonNullable<TMessage>, TServices, TLogger, TDatabase>): Queue<TName, NonNullable<TMessage>, TServices, TLogger, TDatabase, TDatabaseServiceName>;
50
63
  }
51
64
  /** A queue built without a name — only reachable by building one by hand. */
52
65
  declare class QueueNeedsName extends Error {
@@ -59,4 +72,4 @@ declare class QueueNeedsMessage extends Error {
59
72
  }
60
73
  //#endregion
61
74
  export { QueueNeedsMessage as n, QueueNeedsName as r, QueueBuilder as t };
62
- //# sourceMappingURL=QueueBuilder-XEnnOWGe.d.cts.map
75
+ //# sourceMappingURL=QueueBuilder-OSi6LkV9.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"QueueBuilder-OSi6LkV9.d.cts","names":[],"sources":["../src/queue/QueueBuilder.ts"],"mappings":";;;;;;;;;;;;;;cAuBa,aACZ,+BACA,iBAAiB,0CACjB,kBAAkB,gBAClB,gBAAgB,SAAS,QACzB,uBACA;UAEQ;UACA;UACA;UACA;UACA;UACA;;EAED;UACC;;EAED;;UAEC;;UAEA;;EAGR,MAAM,kBACL,MAAM,IACJ,aACF,GACA,UACA,WACA,SACA,WACA;EAYD,QAAQ;;EAKR,UAAU;;EAKV,KAAK;;;;;;;;;;;;EAeL,gBAAgB,mBAAmB,cAClC,YAAY,IACV,aACF,OACA,cACI,cAAc,WAAW,KAC7B,SACA,WACA;EAwBD,SAAS,UAAU,WAClB,UAAU,IACR,aACF,OACA,cACI,cAAc,IAClB,SACA,WACA;EAcD,OAAO,UAAU,QAChB,QAAQ,IACN,aACF,OACA,UACA,WACA,GACA,WACA;;;;;;;;EAqBD,SAAS,GAAG,wBACX,QAAQ,WAAW,SAAS,KAAK,QAAQ,SAAS,KAChD,aAAa,OAAO,UAAU,WAAW,SAAS,GAAG;;EAuBxD,QAAQ,UAAU,kBACjB,QAAQ,IACN,aACF,OACA,GACA,WACA,SACA,WACA;EAcD,OACC,IAAI,aAAa,YAAY,WAAW,WAAW,SAAS,aAC1D,MACF,OACA,YAAY,WACZ,WACA,SACA,WACA;;;cAsCW,uBAAuB;EACnC;;;cASY,0BAA0B;WACjB;EAArB,YAAqB"}
@@ -1,6 +1,6 @@
1
1
  import { t as StandardSchemaV1 } from "./index-CeEtxDmK.mjs";
2
- import { c as ServicesOf, r as Consumable } from "./construct-interface-_3zgxzXl.mjs";
3
- import { r as QueueHandler, t as Queue } from "./Queue-YmvN2vEP.mjs";
2
+ import { c as ServicesOf, r as Consumable } from "./construct-interface-DluK3_da.mjs";
3
+ import { r as QueueHandler, t as Queue } from "./Queue-DlsHRzUp.mjs";
4
4
  import { Service } from "@geekmidas/services";
5
5
  import { Logger } from "@geekmidas/logger";
6
6
  //#region src/queue/QueueBuilder.d.ts
@@ -9,9 +9,10 @@ import { Logger } from "@geekmidas/logger";
9
9
  * `worker.queue('orders')`, never constructed by hand: the worker stamps itself
10
10
  * as the owner. `message` is the typed job payload and `handle` the consumer.
11
11
  * The queue name is captured as a literal so `queue.service` publishes
12
- * `{ type: '<name>', payload }`.
12
+ * `{ type: '<name>', payload }`. The handler's `db` is the worker's database
13
+ * unless `.database(other)` names another.
13
14
  */
14
- declare class QueueBuilder<TName extends string = string, TMessage extends StandardSchemaV1 | undefined = undefined, TServices extends Service[] = [], TLogger extends Logger = Logger> {
15
+ declare class QueueBuilder<TName extends string = string, TMessage extends StandardSchemaV1 | undefined = undefined, TServices extends Service[] = [], TLogger extends Logger = Logger, TDatabase = undefined, TDatabaseServiceName extends string = string> {
15
16
  private _name?;
16
17
  private _messageSchema?;
17
18
  private _timeout;
@@ -23,8 +24,12 @@ declare class QueueBuilder<TName extends string = string, TMessage extends Stand
23
24
  private _logger;
24
25
  /** The worker that runs this queue's consumer — stamped by `worker.queue()`. */
25
26
  _owner?: string;
27
+ /** What the handler's `db` comes from — the worker's, unless overridden. */
28
+ private _databaseService?;
29
+ /** The edge `.database()` added, so the next one can replace it. */
30
+ private _databaseEdge?;
26
31
  /** The queue name — drives the infra queue and its `<NAME>_*` env vars. */
27
- queue<T extends string>(name: T): QueueBuilder<T, TMessage, TServices, TLogger>;
32
+ queue<T extends string>(name: T): QueueBuilder<T, TMessage, TServices, TLogger, TDatabase, TDatabaseServiceName>;
28
33
  timeout(timeout: number): this;
29
34
  /** SQS event-source batch size (deployed). */
30
35
  batchSize(batchSize: number): this;
@@ -41,12 +46,20 @@ declare class QueueBuilder<TName extends string = string, TMessage extends Stand
41
46
  * Constructs only. A `Service` does not match the shape, which is what keeps
42
47
  * env sniffing confined to `.services()` and the explicit lift.
43
48
  */
44
- dependsOn<const T extends readonly Consumable[]>(constructs: T): QueueBuilder<TName, TMessage, [...TServices, ...ServicesOf<T>], TLogger>;
45
- services<T extends Service[]>(services: T): QueueBuilder<TName, TMessage, [...TServices, ...T], TLogger>;
46
- logger<T extends Logger>(logger: T): QueueBuilder<TName, TMessage, TServices, T>;
49
+ dependsOn<const T extends readonly Consumable[]>(constructs: T): QueueBuilder<TName, TMessage, [...TServices, ...ServicesOf<T>], TLogger, TDatabase, TDatabaseServiceName>;
50
+ services<T extends Service[]>(services: T): QueueBuilder<TName, TMessage, [...TServices, ...T], TLogger, TDatabase, TDatabaseServiceName>;
51
+ logger<T extends Logger>(logger: T): QueueBuilder<TName, TMessage, TServices, T, TDatabase, TDatabaseServiceName>;
52
+ /**
53
+ * The database the handler receives as `db`.
54
+ *
55
+ * A queue built from a worker already has the worker's, when the worker
56
+ * named one with `.database(db)`; this replaces it — the edge as well as
57
+ * the client — for a consumer that works against a different database.
58
+ */
59
+ database<T, TDbName extends string>(source: Consumable<TDbName, T> | Service<TDbName, T>): QueueBuilder<TName, TMessage, TServices, TLogger, T, TDbName>;
47
60
  /** The typed message (job) payload the queue carries. */
48
- message<T extends StandardSchemaV1>(schema: T): QueueBuilder<TName, T, TServices, TLogger>;
49
- handle(fn: QueueHandler<NonNullable<TMessage>, TServices, TLogger>): Queue<TName, NonNullable<TMessage>, TServices, TLogger>;
61
+ message<T extends StandardSchemaV1>(schema: T): QueueBuilder<TName, T, TServices, TLogger, TDatabase, TDatabaseServiceName>;
62
+ handle(fn: QueueHandler<NonNullable<TMessage>, TServices, TLogger, TDatabase>): Queue<TName, NonNullable<TMessage>, TServices, TLogger, TDatabase, TDatabaseServiceName>;
50
63
  }
51
64
  /** A queue built without a name — only reachable by building one by hand. */
52
65
  declare class QueueNeedsName extends Error {
@@ -59,4 +72,4 @@ declare class QueueNeedsMessage extends Error {
59
72
  }
60
73
  //#endregion
61
74
  export { QueueNeedsMessage as n, QueueNeedsName as r, QueueBuilder as t };
62
- //# sourceMappingURL=QueueBuilder-CM0WUxfw.d.mts.map
75
+ //# sourceMappingURL=QueueBuilder-QHsnVt1P.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"QueueBuilder-QHsnVt1P.d.mts","names":[],"sources":["../src/queue/QueueBuilder.ts"],"mappings":";;;;;;;;;;;;;;cAuBa,aACZ,+BACA,iBAAiB,0CACjB,kBAAkB,gBAClB,gBAAgB,SAAS,QACzB,uBACA;UAEQ;UACA;UACA;UACA;UACA;UACA;;EAED;UACC;;EAED;;UAEC;;UAEA;;EAGR,MAAM,kBACL,MAAM,IACJ,aACF,GACA,UACA,WACA,SACA,WACA;EAYD,QAAQ;;EAKR,UAAU;;EAKV,KAAK;;;;;;;;;;;;EAeL,gBAAgB,mBAAmB,cAClC,YAAY,IACV,aACF,OACA,cACI,cAAc,WAAW,KAC7B,SACA,WACA;EAwBD,SAAS,UAAU,WAClB,UAAU,IACR,aACF,OACA,cACI,cAAc,IAClB,SACA,WACA;EAcD,OAAO,UAAU,QAChB,QAAQ,IACN,aACF,OACA,UACA,WACA,GACA,WACA;;;;;;;;EAqBD,SAAS,GAAG,wBACX,QAAQ,WAAW,SAAS,KAAK,QAAQ,SAAS,KAChD,aAAa,OAAO,UAAU,WAAW,SAAS,GAAG;;EAuBxD,QAAQ,UAAU,kBACjB,QAAQ,IACN,aACF,OACA,GACA,WACA,SACA,WACA;EAcD,OACC,IAAI,aAAa,YAAY,WAAW,WAAW,SAAS,aAC1D,MACF,OACA,YAAY,WACZ,WACA,SACA,WACA;;;cAsCW,uBAAuB;EACnC;;;cASY,0BAA0B;WACjB;EAArB,YAAqB"}
@@ -1,5 +1,6 @@
1
1
  import { t as StandardSchemaV1 } from "./index-CeEtxDmK.cjs";
2
2
  import { t as Construct } from "./Construct-BQALFCh2.cjs";
3
+ import { t as DatabaseContext } from "./Function-Pu-1kKZz.cjs";
3
4
  import { Logger } from "@geekmidas/logger";
4
5
  import { InferStandardSchema } from "@geekmidas/schema";
5
6
  import { Service, ServiceRecord } from "@geekmidas/services";
@@ -8,10 +9,15 @@ import { EventPublisher, ExtractPublisherMessage } from "@geekmidas/events";
8
9
  type ExtractEventPayloads<TPublisher extends EventPublisher<any> | undefined, TEventTypes extends any[]> = TPublisher extends EventPublisher<any> ? Extract<ExtractPublisherMessage<TPublisher>, {
9
10
  type: TEventTypes[number];
10
11
  }> : never;
12
+ /**
13
+ * A runnable that consumes a topic. Its handler gets `db` when it has a
14
+ * database: the worker's, declared once with `worker.database(db)`, or its own
15
+ * with `.database(other)`.
16
+ */
11
17
  declare class Subscriber<TServices extends Service[] = [], TLogger extends Logger = Logger, OutSchema extends StandardSchemaV1 | undefined = undefined,
12
18
  /** The topic's message union — what types the events this subscriber receives. */
13
- TEventPublisher extends EventPublisher<any> | undefined = undefined, TSubscribedEvents extends ExtractPublisherMessage<TEventPublisher>['type'][] = ExtractPublisherMessage<TEventPublisher>['type'][]> extends Construct<TLogger, OutSchema, TServices> {
14
- readonly handler: SubscriberHandler<TEventPublisher, TSubscribedEvents, TServices, TLogger, OutSchema>;
19
+ TEventPublisher extends EventPublisher<any> | undefined = undefined, TSubscribedEvents extends ExtractPublisherMessage<TEventPublisher>['type'][] = ExtractPublisherMessage<TEventPublisher>['type'][], TDatabase = undefined, TDatabaseServiceName extends string = string> extends Construct<TLogger, OutSchema, TServices, string, undefined, TDatabaseServiceName, TDatabase> {
20
+ readonly handler: SubscriberHandler<TEventPublisher, TSubscribedEvents, TServices, TLogger, OutSchema, TDatabase>;
15
21
  readonly timeout: number;
16
22
  protected _subscribedEvents?: TSubscribedEvents | undefined;
17
23
  readonly outputSchema?: OutSchema | undefined;
@@ -24,8 +30,8 @@ TEventPublisher extends EventPublisher<any> | undefined = undefined, TSubscribed
24
30
  */
25
31
  readonly topicName?: string | undefined;
26
32
  __IS_SUBSCRIBER__: boolean;
27
- static isSubscriber(obj: any): obj is Subscriber<any, any, any, any, any>;
28
- constructor(handler: SubscriberHandler<TEventPublisher, TSubscribedEvents, TServices, TLogger, OutSchema>, timeout?: number, _subscribedEvents?: TSubscribedEvents | undefined, outputSchema?: OutSchema | undefined, services?: TServices, logger?: TLogger,
33
+ static isSubscriber(obj: any): obj is Subscriber<any, any, any, any, any, any>;
34
+ constructor(handler: SubscriberHandler<TEventPublisher, TSubscribedEvents, TServices, TLogger, OutSchema, TDatabase>, timeout?: number, _subscribedEvents?: TSubscribedEvents | undefined, outputSchema?: OutSchema | undefined, services?: TServices, logger?: TLogger,
29
35
  /**
30
36
  * The name of the {@link Topic} this subscriber binds to (via
31
37
  * `worker.topic(topic)`), recorded for the manifest so infra wires the
@@ -36,15 +42,20 @@ TEventPublisher extends EventPublisher<any> | undefined = undefined, TSubscribed
36
42
  * The construct ids `.dependsOn()` named — last, so no existing positional
37
43
  * argument moves.
38
44
  */
39
- constructs?: string[]);
45
+ constructs?: string[],
46
+ /**
47
+ * What the handler's `db` is registered from — after `constructs`, for
48
+ * the same reason.
49
+ */
50
+ databaseService?: Service<TDatabaseServiceName, TDatabase>);
40
51
  get subscribedEvents(): TSubscribedEvents | undefined;
41
52
  }
42
- type SubscriberHandler<TEventPublisher extends EventPublisher<any> | undefined, TSubscribedEvents extends ExtractPublisherMessage<TEventPublisher>['type'][], TServices extends Service[] = [], TLogger extends Logger = Logger, OutSchema extends StandardSchemaV1 | undefined = undefined> = (ctx: SubscriberContext<TEventPublisher, TSubscribedEvents, TServices, TLogger>) => OutSchema extends StandardSchemaV1 ? InferStandardSchema<OutSchema> | Promise<InferStandardSchema<OutSchema>> : any | Promise<any>;
43
- type SubscriberContext<TEventPublisher extends EventPublisher<any> | undefined, TSubscribedEvents extends ExtractPublisherMessage<TEventPublisher>['type'][], TServices extends Service[] = [], TLogger extends Logger = Logger> = {
53
+ type SubscriberHandler<TEventPublisher extends EventPublisher<any> | undefined, TSubscribedEvents extends ExtractPublisherMessage<TEventPublisher>['type'][], TServices extends Service[] = [], TLogger extends Logger = Logger, OutSchema extends StandardSchemaV1 | undefined = undefined, TDatabase = undefined> = (ctx: SubscriberContext<TEventPublisher, TSubscribedEvents, TServices, TLogger, TDatabase>) => OutSchema extends StandardSchemaV1 ? InferStandardSchema<OutSchema> | Promise<InferStandardSchema<OutSchema>> : any | Promise<any>;
54
+ type SubscriberContext<TEventPublisher extends EventPublisher<any> | undefined, TSubscribedEvents extends ExtractPublisherMessage<TEventPublisher>['type'][], TServices extends Service[] = [], TLogger extends Logger = Logger, TDatabase = undefined> = {
44
55
  events: ExtractEventPayloads<TEventPublisher, TSubscribedEvents>[];
45
56
  services: ServiceRecord<TServices>;
46
57
  logger: TLogger;
47
- };
58
+ } & DatabaseContext<TDatabase>;
48
59
  //#endregion
49
60
  export { SubscriberHandler as n, Subscriber as t };
50
- //# sourceMappingURL=Subscriber-B91YSkZt.d.cts.map
61
+ //# sourceMappingURL=Subscriber-Bpp02cGr.d.cts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Subscriber-Bpp02cGr.d.cts","names":[],"sources":["../src/subscribers/Subscriber.ts"],"mappings":";;;;;;;;KAaK,qBACJ,mBAAmB,iCACnB,6BACG,mBAAmB,sBACpB,QAAQ,wBAAwB;EAAe,MAAM;;;;;;;cAQ3C,WACZ,kBAAkB,gBAClB,gBAAgB,SAAS,QACzB,kBAAkB;;AAElB,wBAAwB,6CACxB,0BACC,wBAAwB,6BAA6B,wBAAwB,4BAC9E,uBACA,sDACS,UACT,SACA,WACA,8BAGA,sBACA;WAeiB,SAAS,kBACxB,iBACA,mBACA,WACA,SACA,WACA;WAEwB;YACf,oBAAoB;WACL,eAAe;WACf,UAAU;WACV,QAAQ;;;;;;WAMjB;EA/BjB;SAEO,aACN,WACE,OAAO;EAQV,YACiB,SAAS,kBACxB,iBACA,mBACA,WACA,SACA,WACA,YAEwB,kBACf,oBAAoB,+BACL,eAAe,uBACf,WAAU,WACV,SAAQ,SAMjB;;;;;;EAAA,gCAKhB;;;;;EAAA,uBAKA;;;;;EAAA,kBAAkB,QAAQ,sBAAsB;MAiB7C,oBAAoB;;KAMb,kBACX,wBAAwB,iCACxB,0BAA0B,wBAAwB,4BAClD,kBAAkB,gBAClB,gBAAgB,SAAS,QACzB,kBAAkB,0CAClB,0BAEA,KAAK,kBACJ,iBACA,mBACA,WACA,SACA,eAEG,kBAAkB,mBACpB,oBAAoB,aAAa,QAAQ,oBAAoB,oBACvD;KAGG,kBACX,wBAAwB,iCACxB,0BAA0B,wBAAwB,4BAClD,kBAAkB,gBAClB,gBAAgB,SAAS,QACzB;EAEA,QAAQ,qBAAqB,iBAAiB;EAC9C,UAAU,cAAc;EACxB,QAAQ;IACL,gBAAgB"}
@@ -1,5 +1,6 @@
1
1
  import { t as StandardSchemaV1 } from "./index-CeEtxDmK.mjs";
2
2
  import { t as Construct } from "./Construct-QXnl3VqT.mjs";
3
+ import { t as DatabaseContext } from "./Function-DuqGcbOI.mjs";
3
4
  import { EventPublisher, ExtractPublisherMessage } from "@geekmidas/events";
4
5
  import { Service, ServiceRecord } from "@geekmidas/services";
5
6
  import { Logger } from "@geekmidas/logger";
@@ -8,10 +9,15 @@ import { InferStandardSchema } from "@geekmidas/schema";
8
9
  type ExtractEventPayloads<TPublisher extends EventPublisher<any> | undefined, TEventTypes extends any[]> = TPublisher extends EventPublisher<any> ? Extract<ExtractPublisherMessage<TPublisher>, {
9
10
  type: TEventTypes[number];
10
11
  }> : never;
12
+ /**
13
+ * A runnable that consumes a topic. Its handler gets `db` when it has a
14
+ * database: the worker's, declared once with `worker.database(db)`, or its own
15
+ * with `.database(other)`.
16
+ */
11
17
  declare class Subscriber<TServices extends Service[] = [], TLogger extends Logger = Logger, OutSchema extends StandardSchemaV1 | undefined = undefined,
12
18
  /** The topic's message union — what types the events this subscriber receives. */
13
- TEventPublisher extends EventPublisher<any> | undefined = undefined, TSubscribedEvents extends ExtractPublisherMessage<TEventPublisher>['type'][] = ExtractPublisherMessage<TEventPublisher>['type'][]> extends Construct<TLogger, OutSchema, TServices> {
14
- readonly handler: SubscriberHandler<TEventPublisher, TSubscribedEvents, TServices, TLogger, OutSchema>;
19
+ TEventPublisher extends EventPublisher<any> | undefined = undefined, TSubscribedEvents extends ExtractPublisherMessage<TEventPublisher>['type'][] = ExtractPublisherMessage<TEventPublisher>['type'][], TDatabase = undefined, TDatabaseServiceName extends string = string> extends Construct<TLogger, OutSchema, TServices, string, undefined, TDatabaseServiceName, TDatabase> {
20
+ readonly handler: SubscriberHandler<TEventPublisher, TSubscribedEvents, TServices, TLogger, OutSchema, TDatabase>;
15
21
  readonly timeout: number;
16
22
  protected _subscribedEvents?: TSubscribedEvents | undefined;
17
23
  readonly outputSchema?: OutSchema | undefined;
@@ -24,8 +30,8 @@ TEventPublisher extends EventPublisher<any> | undefined = undefined, TSubscribed
24
30
  */
25
31
  readonly topicName?: string | undefined;
26
32
  __IS_SUBSCRIBER__: boolean;
27
- static isSubscriber(obj: any): obj is Subscriber<any, any, any, any, any>;
28
- constructor(handler: SubscriberHandler<TEventPublisher, TSubscribedEvents, TServices, TLogger, OutSchema>, timeout?: number, _subscribedEvents?: TSubscribedEvents | undefined, outputSchema?: OutSchema | undefined, services?: TServices, logger?: TLogger,
33
+ static isSubscriber(obj: any): obj is Subscriber<any, any, any, any, any, any>;
34
+ constructor(handler: SubscriberHandler<TEventPublisher, TSubscribedEvents, TServices, TLogger, OutSchema, TDatabase>, timeout?: number, _subscribedEvents?: TSubscribedEvents | undefined, outputSchema?: OutSchema | undefined, services?: TServices, logger?: TLogger,
29
35
  /**
30
36
  * The name of the {@link Topic} this subscriber binds to (via
31
37
  * `worker.topic(topic)`), recorded for the manifest so infra wires the
@@ -36,15 +42,20 @@ TEventPublisher extends EventPublisher<any> | undefined = undefined, TSubscribed
36
42
  * The construct ids `.dependsOn()` named — last, so no existing positional
37
43
  * argument moves.
38
44
  */
39
- constructs?: string[]);
45
+ constructs?: string[],
46
+ /**
47
+ * What the handler's `db` is registered from — after `constructs`, for
48
+ * the same reason.
49
+ */
50
+ databaseService?: Service<TDatabaseServiceName, TDatabase>);
40
51
  get subscribedEvents(): TSubscribedEvents | undefined;
41
52
  }
42
- type SubscriberHandler<TEventPublisher extends EventPublisher<any> | undefined, TSubscribedEvents extends ExtractPublisherMessage<TEventPublisher>['type'][], TServices extends Service[] = [], TLogger extends Logger = Logger, OutSchema extends StandardSchemaV1 | undefined = undefined> = (ctx: SubscriberContext<TEventPublisher, TSubscribedEvents, TServices, TLogger>) => OutSchema extends StandardSchemaV1 ? InferStandardSchema<OutSchema> | Promise<InferStandardSchema<OutSchema>> : any | Promise<any>;
43
- type SubscriberContext<TEventPublisher extends EventPublisher<any> | undefined, TSubscribedEvents extends ExtractPublisherMessage<TEventPublisher>['type'][], TServices extends Service[] = [], TLogger extends Logger = Logger> = {
53
+ type SubscriberHandler<TEventPublisher extends EventPublisher<any> | undefined, TSubscribedEvents extends ExtractPublisherMessage<TEventPublisher>['type'][], TServices extends Service[] = [], TLogger extends Logger = Logger, OutSchema extends StandardSchemaV1 | undefined = undefined, TDatabase = undefined> = (ctx: SubscriberContext<TEventPublisher, TSubscribedEvents, TServices, TLogger, TDatabase>) => OutSchema extends StandardSchemaV1 ? InferStandardSchema<OutSchema> | Promise<InferStandardSchema<OutSchema>> : any | Promise<any>;
54
+ type SubscriberContext<TEventPublisher extends EventPublisher<any> | undefined, TSubscribedEvents extends ExtractPublisherMessage<TEventPublisher>['type'][], TServices extends Service[] = [], TLogger extends Logger = Logger, TDatabase = undefined> = {
44
55
  events: ExtractEventPayloads<TEventPublisher, TSubscribedEvents>[];
45
56
  services: ServiceRecord<TServices>;
46
57
  logger: TLogger;
47
- };
58
+ } & DatabaseContext<TDatabase>;
48
59
  //#endregion
49
60
  export { SubscriberHandler as n, Subscriber as t };
50
- //# sourceMappingURL=Subscriber-BjHYe5hK.d.mts.map
61
+ //# sourceMappingURL=Subscriber-CtN9R48-.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Subscriber-CtN9R48-.d.mts","names":[],"sources":["../src/subscribers/Subscriber.ts"],"mappings":";;;;;;;;KAaK,qBACJ,mBAAmB,iCACnB,6BACG,mBAAmB,sBACpB,QAAQ,wBAAwB;EAAe,MAAM;;;;;;;cAQ3C,WACZ,kBAAkB,gBAClB,gBAAgB,SAAS,QACzB,kBAAkB;;AAElB,wBAAwB,6CACxB,0BACC,wBAAwB,6BAA6B,wBAAwB,4BAC9E,uBACA,sDACS,UACT,SACA,WACA,8BAGA,sBACA;WAeiB,SAAS,kBACxB,iBACA,mBACA,WACA,SACA,WACA;WAEwB;YACf,oBAAoB;WACL,eAAe;WACf,UAAU;WACV,QAAQ;;;;;;WAMjB;EA/BjB;SAEO,aACN,WACE,OAAO;EAQV,YACiB,SAAS,kBACxB,iBACA,mBACA,WACA,SACA,WACA,YAEwB,kBACf,oBAAoB,+BACL,eAAe,uBACf,WAAU,WACV,SAAQ,SAMjB;;;;;;EAAA,gCAKhB;;;;;EAAA,uBAKA;;;;;EAAA,kBAAkB,QAAQ,sBAAsB;MAiB7C,oBAAoB;;KAMb,kBACX,wBAAwB,iCACxB,0BAA0B,wBAAwB,4BAClD,kBAAkB,gBAClB,gBAAgB,SAAS,QACzB,kBAAkB,0CAClB,0BAEA,KAAK,kBACJ,iBACA,mBACA,WACA,SACA,eAEG,kBAAkB,mBACpB,oBAAoB,aAAa,QAAQ,oBAAoB,oBACvD;KAGG,kBACX,wBAAwB,iCACxB,0BAA0B,wBAAwB,4BAClD,kBAAkB,gBAClB,gBAAgB,SAAS,QACzB;EAEA,QAAQ,qBAAqB,iBAAiB;EAC9C,UAAU,cAAc;EACxB,QAAQ;IACL,gBAAgB"}
@@ -3,6 +3,11 @@ const require_construct_interface = require("./construct-interface.cjs");
3
3
  const require_clone = require("./clone-UGJpvQnL.cjs");
4
4
  let _geekmidas_logger_console = require("@geekmidas/logger/console");
5
5
  //#region src/subscribers/Subscriber.ts
6
+ /**
7
+ * A runnable that consumes a topic. Its handler gets `db` when it has a
8
+ * database: the worker's, declared once with `worker.database(db)`, or its own
9
+ * with `.database(other)`.
10
+ */
6
11
  var Subscriber = class extends require_Construct.Construct {
7
12
  handler;
8
13
  timeout;
@@ -15,7 +20,7 @@ var Subscriber = class extends require_Construct.Construct {
15
20
  static isSubscriber(obj) {
16
21
  return Boolean(obj && obj.__IS_SUBSCRIBER__ === true && obj.type === "dev.geekmidas.function.subscriber");
17
22
  }
18
- constructor(handler, timeout = 3e4, _subscribedEvents, outputSchema, services = [], logger = _geekmidas_logger_console.DEFAULT_LOGGER, topicName, constructs = []) {
23
+ constructor(handler, timeout = 3e4, _subscribedEvents, outputSchema, services = [], logger = _geekmidas_logger_console.DEFAULT_LOGGER, topicName, constructs = [], databaseService) {
19
24
  super("dev.geekmidas.function.subscriber", logger, services, [], outputSchema, timeout, void 0, void 0, constructs);
20
25
  this.handler = handler;
21
26
  this.timeout = timeout;
@@ -24,6 +29,7 @@ var Subscriber = class extends require_Construct.Construct {
24
29
  this.services = services;
25
30
  this.logger = logger;
26
31
  this.topicName = topicName;
32
+ this.databaseService = databaseService;
27
33
  }
28
34
  get subscribedEvents() {
29
35
  return this._subscribedEvents;
@@ -45,6 +51,10 @@ var SubscriberBuilder = class {
45
51
  */
46
52
  _owner;
47
53
  _topicName;
54
+ /** What the handler's `db` comes from — the worker's, unless overridden. */
55
+ _databaseService;
56
+ /** The edge `.database()` added, so the next one can replace it. */
57
+ _databaseEdge;
48
58
  constructor() {
49
59
  this._timeout = 3e4;
50
60
  }
@@ -90,12 +100,30 @@ var SubscriberBuilder = class {
90
100
  logger(logger) {
91
101
  return require_clone.cloneWith(this, { _logger: logger });
92
102
  }
103
+ /**
104
+ * The database the handler receives as `db`.
105
+ *
106
+ * A subscriber built from a worker already has the worker's, when the
107
+ * worker named one with `.database(db)`; this replaces it — the edge as well
108
+ * as the client — for a consumer that works against a different database.
109
+ */
110
+ database(source) {
111
+ return require_clone.cloneWith(this, {
112
+ _databaseService: require_construct_interface.serviceOf(source),
113
+ ...require_construct_interface.databaseEdges({
114
+ constructs: this._constructs,
115
+ edge: this._databaseEdge,
116
+ service: this._databaseService,
117
+ services: this._services
118
+ }, source)
119
+ });
120
+ }
93
121
  subscribe(event) {
94
122
  const eventsToAdd = Array.isArray(event) ? event : [event];
95
123
  return require_clone.cloneWith(this, { _subscribedEvents: [...this._subscribedEvents, ...eventsToAdd] });
96
124
  }
97
125
  handle(fn) {
98
- const subscriber = new Subscriber(fn, this._timeout, this._subscribedEvents, this.outputSchema, this._services, this._logger, this._topicName, this._constructs);
126
+ const subscriber = new Subscriber(fn, this._timeout, this._subscribedEvents, this.outputSchema, this._services, this._logger, this._topicName, this._constructs, this._databaseService);
99
127
  subscriber.owner = this._owner;
100
128
  return subscriber;
101
129
  }
@@ -114,4 +142,4 @@ Object.defineProperty(exports, "SubscriberBuilder", {
114
142
  }
115
143
  });
116
144
 
117
- //# sourceMappingURL=SubscriberBuilder-Duk028pD.cjs.map
145
+ //# sourceMappingURL=SubscriberBuilder-C2PwqwIl.cjs.map
@@ -0,0 +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"}