@geekmidas/constructs 10.0.0-alpha.123 → 10.0.0-alpha.125

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 (183) hide show
  1. package/dist/{Construct-CFW0zjdD.d.cts → Construct-127M7yrl.d.cts} +3 -2
  2. package/dist/{Construct-B7AXn0xH.d.mts.map → Construct-127M7yrl.d.cts.map} +1 -1
  3. package/dist/{Construct-CKUA-CTA.mjs → Construct-CGuc_Ijk.mjs} +2 -1
  4. package/dist/{Construct-CKUA-CTA.mjs.map → Construct-CGuc_Ijk.mjs.map} +1 -1
  5. package/dist/{Construct-DEOVauyA.cjs → Construct-DorKS0Ua.cjs} +2 -1
  6. package/dist/{Construct-DEOVauyA.cjs.map → Construct-DorKS0Ua.cjs.map} +1 -1
  7. package/dist/{Construct-B7AXn0xH.d.mts → Construct-DySlwh8o.d.mts} +3 -2
  8. package/dist/{Construct-CFW0zjdD.d.cts.map → Construct-DySlwh8o.d.mts.map} +1 -1
  9. package/dist/{Cron-bdGRSROY.d.cts → Cron-CFkpEys6.d.cts} +4 -4
  10. package/dist/{Cron-bdGRSROY.d.cts.map → Cron-CFkpEys6.d.cts.map} +1 -1
  11. package/dist/{Cron-i4Uetezh.d.mts → Cron-CQoDSu-n.d.mts} +4 -4
  12. package/dist/{Cron-i4Uetezh.d.mts.map → Cron-CQoDSu-n.d.mts.map} +1 -1
  13. package/dist/{CronBuilder-9H4BnD6W.d.mts → CronBuilder-1W-G_i15.d.mts} +5 -5
  14. package/dist/{CronBuilder-9H4BnD6W.d.mts.map → CronBuilder-1W-G_i15.d.mts.map} +1 -1
  15. package/dist/{CronBuilder-D3sF9tS_.mjs → CronBuilder-BJ5LoadF.mjs} +3 -3
  16. package/dist/{CronBuilder-D3sF9tS_.mjs.map → CronBuilder-BJ5LoadF.mjs.map} +1 -1
  17. package/dist/{CronBuilder-BXTG10u5.cjs → CronBuilder-B_NSP-Y5.cjs} +3 -3
  18. package/dist/{CronBuilder-BXTG10u5.cjs.map → CronBuilder-B_NSP-Y5.cjs.map} +1 -1
  19. package/dist/{CronBuilder-B_24LZpn.d.cts → CronBuilder-OaCRRFVk.d.cts} +5 -5
  20. package/dist/{CronBuilder-B_24LZpn.d.cts.map → CronBuilder-OaCRRFVk.d.cts.map} +1 -1
  21. package/dist/{Endpoint-DgrpG15P.d.cts → Endpoint-BEh-jW-f.d.cts} +4 -4
  22. package/dist/{Endpoint-CeFkSwh5.d.mts.map → Endpoint-BEh-jW-f.d.cts.map} +1 -1
  23. package/dist/{Endpoint-yhR2T2Wt.cjs → Endpoint-BuGFNFSB.cjs} +3 -3
  24. package/dist/{Endpoint-yhR2T2Wt.cjs.map → Endpoint-BuGFNFSB.cjs.map} +1 -1
  25. package/dist/{Endpoint-CeFkSwh5.d.mts → Endpoint-DTXDggNl.d.mts} +4 -4
  26. package/dist/{Endpoint-DgrpG15P.d.cts.map → Endpoint-DTXDggNl.d.mts.map} +1 -1
  27. package/dist/{Endpoint-gPXhHKhJ.mjs → Endpoint-VdaYKc2g.mjs} +3 -3
  28. package/dist/{Endpoint-gPXhHKhJ.mjs.map → Endpoint-VdaYKc2g.mjs.map} +1 -1
  29. package/dist/{EndpointFactory-Cc863XJS.d.cts → EndpointFactory-B2dCS9dy.d.cts} +4 -4
  30. package/dist/{EndpointFactory-Dbw9ugkX.d.mts.map → EndpointFactory-B2dCS9dy.d.cts.map} +1 -1
  31. package/dist/{EndpointFactory-CSrAyazj.cjs → EndpointFactory-C6pVda4y.cjs} +4 -4
  32. package/dist/{EndpointFactory-CSrAyazj.cjs.map → EndpointFactory-C6pVda4y.cjs.map} +1 -1
  33. package/dist/{EndpointFactory-c2ZugGig.mjs → EndpointFactory-CUpqgtaH.mjs} +4 -4
  34. package/dist/{EndpointFactory-c2ZugGig.mjs.map → EndpointFactory-CUpqgtaH.mjs.map} +1 -1
  35. package/dist/{EndpointFactory-Dbw9ugkX.d.mts → EndpointFactory-D2HXcUrJ.d.mts} +4 -4
  36. package/dist/{EndpointFactory-Cc863XJS.d.cts.map → EndpointFactory-D2HXcUrJ.d.mts.map} +1 -1
  37. package/dist/{Function-B0uZhZnU.d.cts → Function-BIEsY0Hm.d.cts} +2 -2
  38. package/dist/{Function-B0uZhZnU.d.cts.map → Function-BIEsY0Hm.d.cts.map} +1 -1
  39. package/dist/{Function-B_9R7Zy1.d.mts → Function-DfMzTGS4.d.mts} +2 -2
  40. package/dist/{Function-B_9R7Zy1.d.mts.map → Function-DfMzTGS4.d.mts.map} +1 -1
  41. package/dist/{HonoEndpointAdaptor-CN1jjUBJ.cjs → HonoEndpointAdaptor-BBTzbP38.cjs} +3 -3
  42. package/dist/{HonoEndpointAdaptor-CN1jjUBJ.cjs.map → HonoEndpointAdaptor-BBTzbP38.cjs.map} +1 -1
  43. package/dist/{HonoEndpointAdaptor-euH1oSdY.mjs → HonoEndpointAdaptor-BR_LyaFE.mjs} +3 -3
  44. package/dist/{HonoEndpointAdaptor-euH1oSdY.mjs.map → HonoEndpointAdaptor-BR_LyaFE.mjs.map} +1 -1
  45. package/dist/ObjectSubscriberBuilder-HmBwFn2o.d.mts +129 -0
  46. package/dist/ObjectSubscriberBuilder-HmBwFn2o.d.mts.map +1 -0
  47. package/dist/ObjectSubscriberBuilder-l-64yUiF.d.cts +129 -0
  48. package/dist/ObjectSubscriberBuilder-l-64yUiF.d.cts.map +1 -0
  49. package/dist/ProcessorBuilder-B2_stA8f.d.mts +216 -0
  50. package/dist/ProcessorBuilder-B2_stA8f.d.mts.map +1 -0
  51. package/dist/ProcessorBuilder-C62bIOwj.d.cts +216 -0
  52. package/dist/ProcessorBuilder-C62bIOwj.d.cts.map +1 -0
  53. package/dist/{Queue-B-dDXyjF.d.mts → Queue-BnK3UH8r.d.mts} +3 -3
  54. package/dist/{Queue-B-dDXyjF.d.mts.map → Queue-BnK3UH8r.d.mts.map} +1 -1
  55. package/dist/{Queue-JbIjVtTf.d.cts → Queue-C4rijiM7.d.cts} +3 -3
  56. package/dist/{Queue-JbIjVtTf.d.cts.map → Queue-C4rijiM7.d.cts.map} +1 -1
  57. package/dist/{Queue-BhuofM3k.cjs → Queue-D4Iaidrs.cjs} +3 -3
  58. package/dist/{Queue-BhuofM3k.cjs.map → Queue-D4Iaidrs.cjs.map} +1 -1
  59. package/dist/{Queue-cmhqEBOB.mjs → Queue-u8w8_HpE.mjs} +3 -3
  60. package/dist/{Queue-cmhqEBOB.mjs.map → Queue-u8w8_HpE.mjs.map} +1 -1
  61. package/dist/{QueueBuilder-DXu1qxT1.mjs → QueueBuilder-2wP5lEC8.mjs} +2 -2
  62. package/dist/{QueueBuilder-DXu1qxT1.mjs.map → QueueBuilder-2wP5lEC8.mjs.map} +1 -1
  63. package/dist/{QueueBuilder-48W-q8In.d.mts → QueueBuilder-B3vL1ED2.d.mts} +2 -2
  64. package/dist/{QueueBuilder-48W-q8In.d.mts.map → QueueBuilder-B3vL1ED2.d.mts.map} +1 -1
  65. package/dist/{QueueBuilder-MfpkJ3R9.d.cts → QueueBuilder-BcPBQSSX.d.cts} +2 -2
  66. package/dist/{QueueBuilder-MfpkJ3R9.d.cts.map → QueueBuilder-BcPBQSSX.d.cts.map} +1 -1
  67. package/dist/{QueueBuilder-DdU2klPu.cjs → QueueBuilder-BxsZ9o5z.cjs} +2 -2
  68. package/dist/{QueueBuilder-DdU2klPu.cjs.map → QueueBuilder-BxsZ9o5z.cjs.map} +1 -1
  69. package/dist/{Subscriber-CEt7kHkc.d.cts → Subscriber-BdCtfFXL.d.cts} +15 -3
  70. package/dist/{Subscriber-CEt7kHkc.d.cts.map → Subscriber-BdCtfFXL.d.cts.map} +1 -1
  71. package/dist/{Subscriber-dsxc5LKa.d.mts → Subscriber-DDo4HFNn.d.mts} +15 -3
  72. package/dist/{Subscriber-dsxc5LKa.d.mts.map → Subscriber-DDo4HFNn.d.mts.map} +1 -1
  73. package/dist/{SubscriberBuilder-DRXfxWn_.mjs → SubscriberBuilder-3msj1U2w.mjs} +99 -3
  74. package/dist/SubscriberBuilder-3msj1U2w.mjs.map +1 -0
  75. package/dist/{SubscriberBuilder-M2EAgQhC.cjs → SubscriberBuilder-CQst6Iz3.cjs} +110 -2
  76. package/dist/SubscriberBuilder-CQst6Iz3.cjs.map +1 -0
  77. package/dist/{Topic-D2R0r24C.mjs → Topic-DN2gYJ-p.mjs} +3 -3
  78. package/dist/{Topic-D2R0r24C.mjs.map → Topic-DN2gYJ-p.mjs.map} +1 -1
  79. package/dist/{Topic-DwS3QO0m.cjs → Topic-Dp9Q7Lj2.cjs} +3 -3
  80. package/dist/{Topic-DwS3QO0m.cjs.map → Topic-Dp9Q7Lj2.cjs.map} +1 -1
  81. package/dist/adaptors/aws.cjs +4 -4
  82. package/dist/adaptors/aws.cjs.map +1 -1
  83. package/dist/adaptors/aws.d.cts +5 -5
  84. package/dist/adaptors/aws.d.mts +5 -5
  85. package/dist/adaptors/aws.mjs +5 -5
  86. package/dist/adaptors/aws.mjs.map +1 -1
  87. package/dist/adaptors/hono.cjs +1 -1
  88. package/dist/adaptors/hono.d.cts +1 -1
  89. package/dist/adaptors/hono.d.mts +1 -1
  90. package/dist/adaptors/hono.mjs +1 -1
  91. package/dist/adaptors/testing.cjs +114 -7
  92. package/dist/adaptors/testing.cjs.map +1 -1
  93. package/dist/adaptors/testing.d.cts +25 -4
  94. package/dist/adaptors/testing.d.cts.map +1 -1
  95. package/dist/adaptors/testing.d.mts +25 -4
  96. package/dist/adaptors/testing.d.mts.map +1 -1
  97. package/dist/adaptors/testing.mjs +114 -7
  98. package/dist/adaptors/testing.mjs.map +1 -1
  99. package/dist/crons/index.cjs +2 -2
  100. package/dist/crons/index.d.cts +2 -2
  101. package/dist/crons/index.d.mts +2 -2
  102. package/dist/crons/index.mjs +2 -2
  103. package/dist/endpoints/index.cjs +3 -3
  104. package/dist/endpoints/index.d.cts +3 -3
  105. package/dist/endpoints/index.d.mts +3 -3
  106. package/dist/endpoints/index.mjs +3 -3
  107. package/dist/file-server.cjs +101 -31
  108. package/dist/file-server.cjs.map +1 -1
  109. package/dist/file-server.d.cts +95 -0
  110. package/dist/file-server.d.cts.map +1 -1
  111. package/dist/file-server.d.mts +95 -0
  112. package/dist/file-server.d.mts.map +1 -1
  113. package/dist/file-server.mjs +101 -33
  114. package/dist/file-server.mjs.map +1 -1
  115. package/dist/functions/index.cjs +1 -1
  116. package/dist/functions/index.d.cts +2 -2
  117. package/dist/functions/index.d.mts +2 -2
  118. package/dist/functions/index.mjs +1 -1
  119. package/dist/{functions-CTI-hDem.mjs → functions-BvIDQKAA.mjs} +3 -3
  120. package/dist/{functions-CTI-hDem.mjs.map → functions-BvIDQKAA.mjs.map} +1 -1
  121. package/dist/{functions-D7O5SGVc.cjs → functions-DLF6-IK8.cjs} +3 -3
  122. package/dist/{functions-D7O5SGVc.cjs.map → functions-DLF6-IK8.cjs.map} +1 -1
  123. package/dist/{index-Cd2w-DRL.d.cts → index-BtzMzhMA.d.cts} +3 -3
  124. package/dist/{index-Cd2w-DRL.d.cts.map → index-BtzMzhMA.d.cts.map} +1 -1
  125. package/dist/{index-aBIcAiH5.d.mts → index-DuriFjYD.d.mts} +3 -3
  126. package/dist/{index-aBIcAiH5.d.mts.map → index-DuriFjYD.d.mts.map} +1 -1
  127. package/dist/index.cjs +1 -1
  128. package/dist/index.d.cts +1 -1
  129. package/dist/index.d.mts +1 -1
  130. package/dist/index.mjs +1 -1
  131. package/dist/pattern-C1CEcglD.mjs +241 -0
  132. package/dist/pattern-C1CEcglD.mjs.map +1 -0
  133. package/dist/pattern-QFaUIr77.cjs +288 -0
  134. package/dist/pattern-QFaUIr77.cjs.map +1 -0
  135. package/dist/processors/index.cjs +214 -0
  136. package/dist/processors/index.cjs.map +1 -0
  137. package/dist/processors/index.d.cts +78 -0
  138. package/dist/processors/index.d.cts.map +1 -0
  139. package/dist/processors/index.d.mts +78 -0
  140. package/dist/processors/index.d.mts.map +1 -0
  141. package/dist/processors/index.mjs +193 -0
  142. package/dist/processors/index.mjs.map +1 -0
  143. package/dist/queue/index.cjs +2 -2
  144. package/dist/queue/index.d.cts +2 -2
  145. package/dist/queue/index.d.mts +2 -2
  146. package/dist/queue/index.mjs +2 -2
  147. package/dist/rest-api.cjs +1 -1
  148. package/dist/rest-api.d.cts +2 -2
  149. package/dist/rest-api.d.mts +2 -2
  150. package/dist/rest-api.mjs +1 -1
  151. package/dist/{runSubscriber-D8nLXIv1.cjs → runSubscriber-B1Yg4dID.cjs} +5 -3
  152. package/dist/runSubscriber-B1Yg4dID.cjs.map +1 -0
  153. package/dist/{runSubscriber-BHvJ8POr.mjs → runSubscriber-JCgkeYbE.mjs} +5 -3
  154. package/dist/runSubscriber-JCgkeYbE.mjs.map +1 -0
  155. package/dist/subscribers/index.cjs +31 -13
  156. package/dist/subscribers/index.cjs.map +1 -1
  157. package/dist/subscribers/index.d.cts +27 -4
  158. package/dist/subscribers/index.d.cts.map +1 -1
  159. package/dist/subscribers/index.d.mts +27 -4
  160. package/dist/subscribers/index.d.mts.map +1 -1
  161. package/dist/subscribers/index.mjs +30 -14
  162. package/dist/subscribers/index.mjs.map +1 -1
  163. package/dist/topic/index.cjs +1 -1
  164. package/dist/topic/index.d.cts +1 -1
  165. package/dist/topic/index.d.mts +1 -1
  166. package/dist/topic/index.mjs +1 -1
  167. package/dist/worker.cjs +25 -4
  168. package/dist/worker.cjs.map +1 -1
  169. package/dist/worker.d.cts +26 -7
  170. package/dist/worker.d.cts.map +1 -1
  171. package/dist/worker.d.mts +26 -7
  172. package/dist/worker.d.mts.map +1 -1
  173. package/dist/worker.mjs +25 -4
  174. package/dist/worker.mjs.map +1 -1
  175. package/package.json +41 -31
  176. package/dist/SubscriberBuilder-BRa_nrmH.d.cts +0 -67
  177. package/dist/SubscriberBuilder-BRa_nrmH.d.cts.map +0 -1
  178. package/dist/SubscriberBuilder-D9bkrYzH.d.mts +0 -67
  179. package/dist/SubscriberBuilder-D9bkrYzH.d.mts.map +0 -1
  180. package/dist/SubscriberBuilder-DRXfxWn_.mjs.map +0 -1
  181. package/dist/SubscriberBuilder-M2EAgQhC.cjs.map +0 -1
  182. package/dist/runSubscriber-BHvJ8POr.mjs.map +0 -1
  183. package/dist/runSubscriber-D8nLXIv1.cjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"Queue-BhuofM3k.cjs","names":["Construct","DEFAULT_LOGGER","canonicalId","provideKey","serviceKey","Publisher"],"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,cAOUA,kBAAAA,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,SAA2CC,0BAAAA,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,MAAA,GAAKC,oBAAAA,YAAAA,CAAY,IAAI;EAC1B,KAAK,iBAAA,GAAgBC,oBAAAA,WAAAA,CAAW,KAAK,IAAI,2BAA2B;EAEpE,MAAM,SAAS,KAAK;EACpB,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;IAER,OAAOC,kBAAAA,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
+ {"version":3,"file":"Queue-D4Iaidrs.cjs","names":["Construct","DEFAULT_LOGGER","canonicalId","provideKey","serviceKey","Publisher"],"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,cAOUA,kBAAAA,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,SAA2CC,0BAAAA,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,MAAA,GAAKC,oBAAAA,YAAAA,CAAY,IAAI;EAC1B,KAAK,iBAAA,GAAgBC,oBAAAA,WAAAA,CAAW,KAAK,IAAI,2BAA2B;EAEpE,MAAM,SAAS,KAAK;EACpB,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;IAER,OAAOC,kBAAAA,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,7 +1,7 @@
1
- import { t as Construct } from "./Construct-CKUA-CTA.mjs";
1
+ import { t as Construct } from "./Construct-CGuc_Ijk.mjs";
2
2
  import { canonicalId, provideKey, serviceKey } from "@geekmidas/manifest";
3
- import { Publisher } from "@geekmidas/events";
4
3
  import { DEFAULT_LOGGER } from "@geekmidas/logger/console";
4
+ import { Publisher } from "@geekmidas/events";
5
5
  //#region src/queue/Queue.ts
6
6
  /**
7
7
  * A queue worker — a point-to-point SQS-style queue and its single consumer.
@@ -101,4 +101,4 @@ var Queue = class extends Construct {
101
101
  //#endregion
102
102
  export { Queue as t };
103
103
 
104
- //# sourceMappingURL=Queue-cmhqEBOB.mjs.map
104
+ //# sourceMappingURL=Queue-u8w8_HpE.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"Queue-cmhqEBOB.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
+ {"version":3,"file":"Queue-u8w8_HpE.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
  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-cmhqEBOB.mjs";
3
+ import { t as Queue } from "./Queue-u8w8_HpE.mjs";
4
4
  import { DEFAULT_LOGGER } from "@geekmidas/logger/console";
5
5
  //#region src/queue/QueueBuilder.ts
6
6
  /**
@@ -115,4 +115,4 @@ var QueueNeedsMessage = class extends Error {
115
115
  //#endregion
116
116
  export { QueueNeedsMessage as n, QueueNeedsName as r, QueueBuilder as t };
117
117
 
118
- //# sourceMappingURL=QueueBuilder-DXu1qxT1.mjs.map
118
+ //# sourceMappingURL=QueueBuilder-2wP5lEC8.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"QueueBuilder-DXu1qxT1.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
+ {"version":3,"file":"QueueBuilder-2wP5lEC8.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 { n as StandardSchemaV1 } from "./index-DdRjYhiJ.mjs";
2
2
  import { c as ServicesOf, r as Consumable } from "./construct-interface-ZvYQbivO.mjs";
3
- import { r as QueueHandler, t as Queue } from "./Queue-B-dDXyjF.mjs";
3
+ import { r as QueueHandler, t as Queue } from "./Queue-BnK3UH8r.mjs";
4
4
  import { Service } from "@geekmidas/services";
5
5
  import { Logger } from "@geekmidas/logger";
6
6
  //#region src/queue/QueueBuilder.d.ts
@@ -72,4 +72,4 @@ declare class QueueNeedsMessage extends Error {
72
72
  }
73
73
  //#endregion
74
74
  export { QueueNeedsMessage as n, QueueNeedsName as r, QueueBuilder as t };
75
- //# sourceMappingURL=QueueBuilder-48W-q8In.d.mts.map
75
+ //# sourceMappingURL=QueueBuilder-B3vL1ED2.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"QueueBuilder-48W-q8In.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
+ {"version":3,"file":"QueueBuilder-B3vL1ED2.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,6 +1,6 @@
1
1
  import { n as StandardSchemaV1 } from "./index-DdRjYhiJ.cjs";
2
2
  import { c as ServicesOf, r as Consumable } from "./construct-interface-B1AfqRl4.cjs";
3
- import { r as QueueHandler, t as Queue } from "./Queue-JbIjVtTf.cjs";
3
+ import { r as QueueHandler, t as Queue } from "./Queue-C4rijiM7.cjs";
4
4
  import { Logger } from "@geekmidas/logger";
5
5
  import { Service } from "@geekmidas/services";
6
6
  //#region src/queue/QueueBuilder.d.ts
@@ -72,4 +72,4 @@ declare class QueueNeedsMessage extends Error {
72
72
  }
73
73
  //#endregion
74
74
  export { QueueNeedsMessage as n, QueueNeedsName as r, QueueBuilder as t };
75
- //# sourceMappingURL=QueueBuilder-MfpkJ3R9.d.cts.map
75
+ //# sourceMappingURL=QueueBuilder-BcPBQSSX.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"QueueBuilder-MfpkJ3R9.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
+ {"version":3,"file":"QueueBuilder-BcPBQSSX.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
  const require_construct_interface = require("./construct-interface.cjs");
2
2
  const require_clone = require("./clone-UGJpvQnL.cjs");
3
- const require_Queue = require("./Queue-BhuofM3k.cjs");
3
+ const require_Queue = require("./Queue-D4Iaidrs.cjs");
4
4
  let _geekmidas_logger_console = require("@geekmidas/logger/console");
5
5
  //#region src/queue/QueueBuilder.ts
6
6
  /**
@@ -132,4 +132,4 @@ Object.defineProperty(exports, "QueueNeedsName", {
132
132
  }
133
133
  });
134
134
 
135
- //# sourceMappingURL=QueueBuilder-DdU2klPu.cjs.map
135
+ //# sourceMappingURL=QueueBuilder-BxsZ9o5z.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"QueueBuilder-DdU2klPu.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
+ {"version":3,"file":"QueueBuilder-BxsZ9o5z.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
1
  import { n as StandardSchemaV1 } from "./index-DdRjYhiJ.cjs";
2
- import { t as Construct } from "./Construct-CFW0zjdD.cjs";
3
- import { t as DatabaseContext } from "./Function-B0uZhZnU.cjs";
2
+ import { t as Construct } from "./Construct-127M7yrl.cjs";
3
+ import { t as DatabaseContext } from "./Function-BIEsY0Hm.cjs";
4
4
  import { Logger } from "@geekmidas/logger";
5
5
  import { InferStandardSchema } from "@geekmidas/schema";
6
6
  import { Service, ServiceRecord } from "@geekmidas/services";
@@ -48,6 +48,18 @@ TEventPublisher extends EventPublisher<any> | undefined = undefined, TSubscribed
48
48
  * the same reason.
49
49
  */
50
50
  databaseService?: Service<TDatabaseServiceName, TDatabase>);
51
+ /**
52
+ * The id of the bucket this subscriber is bound to (via
53
+ * `worker.objects(bucket)`), when its topic is the storage itself — read
54
+ * by the build to bind it, and by the adaptors to read what the storage
55
+ * sends as object events.
56
+ */
57
+ bucketName?: string;
58
+ /** Which of the bucket's keys it watches — see `worker.objects()`. */
59
+ objectFilter?: {
60
+ prefix?: string;
61
+ suffix?: string;
62
+ };
51
63
  get subscribedEvents(): TSubscribedEvents | undefined;
52
64
  }
53
65
  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>;
@@ -58,4 +70,4 @@ type SubscriberContext<TEventPublisher extends EventPublisher<any> | undefined,
58
70
  } & DatabaseContext<TDatabase>;
59
71
  //#endregion
60
72
  export { SubscriberHandler as n, Subscriber as t };
61
- //# sourceMappingURL=Subscriber-CEt7kHkc.d.cts.map
73
+ //# sourceMappingURL=Subscriber-BdCtfFXL.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Subscriber-CEt7kHkc.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
+ {"version":3,"file":"Subscriber-BdCtfFXL.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;;;;;;;EAuBjD;;EAGA;IAAiB;IAAiB;;MAE9B,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,6 +1,6 @@
1
1
  import { n as StandardSchemaV1 } from "./index-DdRjYhiJ.mjs";
2
- import { t as Construct } from "./Construct-B7AXn0xH.mjs";
3
- import { t as DatabaseContext } from "./Function-B_9R7Zy1.mjs";
2
+ import { t as Construct } from "./Construct-DySlwh8o.mjs";
3
+ import { t as DatabaseContext } from "./Function-DfMzTGS4.mjs";
4
4
  import { EventPublisher, ExtractPublisherMessage } from "@geekmidas/events";
5
5
  import { Service, ServiceRecord } from "@geekmidas/services";
6
6
  import { Logger } from "@geekmidas/logger";
@@ -48,6 +48,18 @@ TEventPublisher extends EventPublisher<any> | undefined = undefined, TSubscribed
48
48
  * the same reason.
49
49
  */
50
50
  databaseService?: Service<TDatabaseServiceName, TDatabase>);
51
+ /**
52
+ * The id of the bucket this subscriber is bound to (via
53
+ * `worker.objects(bucket)`), when its topic is the storage itself — read
54
+ * by the build to bind it, and by the adaptors to read what the storage
55
+ * sends as object events.
56
+ */
57
+ bucketName?: string;
58
+ /** Which of the bucket's keys it watches — see `worker.objects()`. */
59
+ objectFilter?: {
60
+ prefix?: string;
61
+ suffix?: string;
62
+ };
51
63
  get subscribedEvents(): TSubscribedEvents | undefined;
52
64
  }
53
65
  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>;
@@ -58,4 +70,4 @@ type SubscriberContext<TEventPublisher extends EventPublisher<any> | undefined,
58
70
  } & DatabaseContext<TDatabase>;
59
71
  //#endregion
60
72
  export { SubscriberHandler as n, Subscriber as t };
61
- //# sourceMappingURL=Subscriber-dsxc5LKa.d.mts.map
73
+ //# sourceMappingURL=Subscriber-DDo4HFNn.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Subscriber-dsxc5LKa.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"}
1
+ {"version":3,"file":"Subscriber-DDo4HFNn.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;;;;;;;EAuBjD;;EAGA;IAAiB;IAAiB;;MAE9B,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,7 +1,94 @@
1
- import { t as Construct } from "./Construct-CKUA-CTA.mjs";
1
+ import { t as Construct } from "./Construct-CGuc_Ijk.mjs";
2
2
  import { databaseEdges, idsOf, serviceOf, servicesOf } from "./construct-interface.mjs";
3
3
  import { t as cloneWith } from "./clone-EKNovYHu.mjs";
4
4
  import { DEFAULT_LOGGER } from "@geekmidas/logger/console";
5
+ //#region src/subscribers/ObjectSubscriberBuilder.ts
6
+ /** `.on()` was given no event to react to. */
7
+ var ObjectSubscriberHasNoEvents = class extends Error {
8
+ bucket;
9
+ constructor(bucket) {
10
+ super(`A subscriber bound to '${bucket}' names no event. Name what it reacts to: .on(['object.created']), .on(['object.deleted']), or both.`);
11
+ this.bucket = bucket;
12
+ this.name = "ObjectSubscriberHasNoEvents";
13
+ }
14
+ };
15
+ /**
16
+ * A subscriber to a bucket's objects, from `worker.objects(bucket)`.
17
+ *
18
+ * Built on the topic subscriber's builder, which it wraps rather than
19
+ * extends: the services, database, owner and edges are configured exactly as
20
+ * a topic subscriber's, and only the trigger differs — the storage, filtered
21
+ * by event and key.
22
+ */
23
+ var ObjectSubscriberBuilder = class ObjectSubscriberBuilder {
24
+ inner;
25
+ bucket;
26
+ events;
27
+ filter;
28
+ constructor(inner, bucket, events = [], filter = {}) {
29
+ this.inner = inner;
30
+ this.bucket = bucket;
31
+ this.events = events;
32
+ this.filter = filter;
33
+ }
34
+ /**
35
+ * What it reacts to: the events, and — optionally — only keys under a
36
+ * prefix and ending in a suffix. Repeatable; the last filter wins.
37
+ */
38
+ on(events, filter = {}) {
39
+ return new ObjectSubscriberBuilder(this.inner, this.bucket, [.../* @__PURE__ */ new Set([...this.events, ...events])], {
40
+ ...filter.prefix ? { prefix: filter.prefix } : {},
41
+ ...filter.suffix ? { suffix: filter.suffix } : {}
42
+ });
43
+ }
44
+ /** See {@link SubscriberBuilder.dependsOn}. */
45
+ dependsOn(constructs) {
46
+ return this.with(this.inner.dependsOn(constructs));
47
+ }
48
+ services(services) {
49
+ return this.with(this.inner.services(services));
50
+ }
51
+ /** See {@link SubscriberBuilder.database}. */
52
+ database(source) {
53
+ return this.with(this.inner.database(source));
54
+ }
55
+ timeout(timeout) {
56
+ return this.with(this.inner.timeout(timeout));
57
+ }
58
+ output(schema) {
59
+ return this.with(this.inner.output(schema));
60
+ }
61
+ logger(logger) {
62
+ return this.with(this.inner.logger(logger));
63
+ }
64
+ handle(fn) {
65
+ if (this.events.length === 0) throw new ObjectSubscriberHasNoEvents(this.bucket);
66
+ const events = [...this.events];
67
+ const filter = this.filter;
68
+ const handler = async (ctx) => {
69
+ const { matchesObjectFilter } = await import("@geekmidas/storage/events");
70
+ const wanted = ctx.events.filter((event) => isObjectMessage(event) && events.includes(event.type) && matchesObjectFilter(event.payload, filter));
71
+ if (wanted.length === 0) return void 0;
72
+ return fn({
73
+ ...ctx,
74
+ events: wanted,
75
+ objects: wanted.map((event) => event.payload)
76
+ });
77
+ };
78
+ const subscriber = this.inner.subscribe(events).handle(handler);
79
+ subscriber.bucketName = this.bucket;
80
+ subscriber.objectFilter = filter;
81
+ return subscriber;
82
+ }
83
+ with(inner) {
84
+ return new ObjectSubscriberBuilder(inner, this.bucket, this.events, this.filter);
85
+ }
86
+ };
87
+ function isObjectMessage(value) {
88
+ const message = value;
89
+ return typeof message === "object" && message !== null && (message.type === "object.created" || message.type === "object.deleted") && typeof message.payload?.key === "string";
90
+ }
91
+ //#endregion
5
92
  //#region src/subscribers/Subscriber.ts
6
93
  /**
7
94
  * A runnable that consumes a topic. Its handler gets `db` when it has a
@@ -31,6 +118,15 @@ var Subscriber = class extends Construct {
31
118
  this.topicName = topicName;
32
119
  this.databaseService = databaseService;
33
120
  }
121
+ /**
122
+ * The id of the bucket this subscriber is bound to (via
123
+ * `worker.objects(bucket)`), when its topic is the storage itself — read
124
+ * by the build to bind it, and by the adaptors to read what the storage
125
+ * sends as object events.
126
+ */
127
+ bucketName;
128
+ /** Which of the bucket's keys it watches — see `worker.objects()`. */
129
+ objectFilter;
34
130
  get subscribedEvents() {
35
131
  return this._subscribedEvents;
36
132
  }
@@ -129,6 +225,6 @@ var SubscriberBuilder = class {
129
225
  }
130
226
  };
131
227
  //#endregion
132
- export { Subscriber as n, SubscriberBuilder as t };
228
+ export { ObjectSubscriberHasNoEvents as i, Subscriber as n, ObjectSubscriberBuilder as r, SubscriberBuilder as t };
133
229
 
134
- //# sourceMappingURL=SubscriberBuilder-DRXfxWn_.mjs.map
230
+ //# sourceMappingURL=SubscriberBuilder-3msj1U2w.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SubscriberBuilder-3msj1U2w.mjs","names":[],"sources":["../src/subscribers/ObjectSubscriberBuilder.ts","../src/subscribers/Subscriber.ts","../src/subscribers/SubscriberBuilder.ts"],"sourcesContent":["import 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 type {\n\tObjectEvent,\n\tObjectEventType,\n\tObjectFilter,\n\tObjectMessage,\n} from '@geekmidas/storage/events';\nimport type { StandardSchemaV1 } from '@standard-schema/spec';\nimport type { Consumable, ServicesOf } from '../construct-interface';\nimport type { DatabaseContext } from '../functions/Function';\nimport type { Subscriber } from './Subscriber';\nimport type { SubscriberBuilder } from './SubscriberBuilder';\n\n/**\n * A subscriber bound to a bucket: a topic subscriber whose topic is the\n * storage itself, so it runs through the same adaptors — Lambda, SNS push,\n * a polled broker, a feature test.\n */\nexport type ObjectSubscriber<\n\tTServices extends Service[] = [],\n\tTLogger extends Logger = Logger,\n\tOutSchema extends StandardSchemaV1 | undefined = undefined,\n\tTEvents extends ObjectEventType[] = ObjectEventType[],\n\tTDatabase = undefined,\n\tTDatabaseServiceName extends string = string,\n> = Subscriber<\n\tTServices,\n\tTLogger,\n\tOutSchema,\n\tEventPublisher<ObjectMessage>,\n\tTEvents,\n\tTDatabase,\n\tTDatabaseServiceName\n>;\n\n/** What a bucket's subscriber is handed: the objects, and how each changed. */\nexport type ObjectSubscriberContext<\n\tTEvents extends ObjectEventType[],\n\tTServices extends Service[] = [],\n\tTLogger extends Logger = Logger,\n\tTDatabase = undefined,\n> = {\n\t/** Each object that changed, in the order the storage reported them. */\n\tobjects: ObjectEvent[];\n\t/** The same objects with what happened to each — for a handler of both. */\n\tevents: ObjectMessage<TEvents[number]>[];\n\tservices: ServiceRecord<TServices>;\n\tlogger: TLogger;\n} & DatabaseContext<TDatabase>;\n\nexport type ObjectSubscriberHandler<\n\tTEvents extends ObjectEventType[],\n\tTServices extends Service[] = [],\n\tTLogger extends Logger = Logger,\n\tOutSchema extends StandardSchemaV1 | undefined = undefined,\n\tTDatabase = undefined,\n> = (\n\tctx: ObjectSubscriberContext<TEvents, TServices, TLogger, TDatabase>,\n) => OutSchema extends StandardSchemaV1\n\t? InferStandardSchema<OutSchema> | Promise<InferStandardSchema<OutSchema>>\n\t: any | Promise<any>;\n\n/** `.on()` was given no event to react to. */\nexport class ObjectSubscriberHasNoEvents extends Error {\n\tconstructor(readonly bucket: string) {\n\t\tsuper(\n\t\t\t`A subscriber bound to '${bucket}' names no event. Name what it reacts ` +\n\t\t\t\t`to: .on(['object.created']), .on(['object.deleted']), or both.`,\n\t\t);\n\t\tthis.name = 'ObjectSubscriberHasNoEvents';\n\t}\n}\n\n/**\n * A subscriber to a bucket's objects, from `worker.objects(bucket)`.\n *\n * Built on the topic subscriber's builder, which it wraps rather than\n * extends: the services, database, owner and edges are configured exactly as\n * a topic subscriber's, and only the trigger differs — the storage, filtered\n * by event and key.\n */\nexport class ObjectSubscriberBuilder<\n\tTServices extends Service[] = [],\n\tTLogger extends Logger = Logger,\n\tOutSchema extends StandardSchemaV1 | undefined = undefined,\n\tTEvents extends ObjectEventType[] = [],\n\tTDatabase = undefined,\n\tTDatabaseServiceName extends string = string,\n> {\n\tconstructor(\n\t\t/** The topic subscriber's builder, already owned by its worker. */\n\t\tprivate readonly inner: SubscriberBuilder<\n\t\t\tany,\n\t\t\tany,\n\t\t\tany,\n\t\t\tany,\n\t\t\tany,\n\t\t\tany,\n\t\t\tany\n\t\t>,\n\t\t/** The bucket's id — what the build binds the subscriber to. */\n\t\tprivate readonly bucket: string,\n\t\tprivate readonly events: readonly ObjectEventType[] = [],\n\t\tprivate readonly filter: ObjectFilter = {},\n\t) {}\n\n\t/**\n\t * What it reacts to: the events, and — optionally — only keys under a\n\t * prefix and ending in a suffix. Repeatable; the last filter wins.\n\t */\n\ton<const T extends ObjectEventType[]>(\n\t\tevents: T,\n\t\tfilter: ObjectFilter = {},\n\t): ObjectSubscriberBuilder<\n\t\tTServices,\n\t\tTLogger,\n\t\tOutSchema,\n\t\t[...TEvents, ...T],\n\t\tTDatabase,\n\t\tTDatabaseServiceName\n\t> {\n\t\treturn new ObjectSubscriberBuilder(\n\t\t\tthis.inner,\n\t\t\tthis.bucket,\n\t\t\t[...new Set([...this.events, ...events])],\n\t\t\t{\n\t\t\t\t...(filter.prefix ? { prefix: filter.prefix } : {}),\n\t\t\t\t...(filter.suffix ? { suffix: filter.suffix } : {}),\n\t\t\t},\n\t\t);\n\t}\n\n\t/** See {@link SubscriberBuilder.dependsOn}. */\n\tdependsOn<const T extends readonly Consumable[]>(\n\t\tconstructs: T,\n\t): ObjectSubscriberBuilder<\n\t\t[...TServices, ...ServicesOf<T>],\n\t\tTLogger,\n\t\tOutSchema,\n\t\tTEvents,\n\t\tTDatabase,\n\t\tTDatabaseServiceName\n\t> {\n\t\treturn this.with(this.inner.dependsOn(constructs));\n\t}\n\n\tservices<T extends Service[]>(\n\t\tservices: T,\n\t): ObjectSubscriberBuilder<\n\t\t[...TServices, ...T],\n\t\tTLogger,\n\t\tOutSchema,\n\t\tTEvents,\n\t\tTDatabase,\n\t\tTDatabaseServiceName\n\t> {\n\t\treturn this.with(this.inner.services(services));\n\t}\n\n\t/** See {@link SubscriberBuilder.database}. */\n\tdatabase<T, TDbName extends string>(\n\t\tsource: Consumable<TDbName, T> | Service<TDbName, T>,\n\t): ObjectSubscriberBuilder<\n\t\tTServices,\n\t\tTLogger,\n\t\tOutSchema,\n\t\tTEvents,\n\t\tT,\n\t\tTDbName\n\t> {\n\t\treturn this.with(this.inner.database(source));\n\t}\n\n\ttimeout(timeout: number): this {\n\t\treturn this.with(this.inner.timeout(timeout)) as this;\n\t}\n\n\toutput<T extends StandardSchemaV1>(\n\t\tschema: T,\n\t): ObjectSubscriberBuilder<\n\t\tTServices,\n\t\tTLogger,\n\t\tT,\n\t\tTEvents,\n\t\tTDatabase,\n\t\tTDatabaseServiceName\n\t> {\n\t\treturn this.with(this.inner.output(schema));\n\t}\n\n\tlogger<T extends Logger>(\n\t\tlogger: T,\n\t): ObjectSubscriberBuilder<\n\t\tTServices,\n\t\tT,\n\t\tOutSchema,\n\t\tTEvents,\n\t\tTDatabase,\n\t\tTDatabaseServiceName\n\t> {\n\t\treturn this.with(this.inner.logger(logger));\n\t}\n\n\thandle(\n\t\tfn: ObjectSubscriberHandler<\n\t\t\tTEvents,\n\t\t\tTServices,\n\t\t\tTLogger,\n\t\t\tOutSchema,\n\t\t\tTDatabase\n\t\t>,\n\t): ObjectSubscriber<\n\t\tTServices,\n\t\tTLogger,\n\t\tOutSchema,\n\t\tTEvents,\n\t\tTDatabase,\n\t\tTDatabaseServiceName\n\t> {\n\t\tif (this.events.length === 0) {\n\t\t\tthrow new ObjectSubscriberHasNoEvents(this.bucket);\n\t\t}\n\t\tconst events = [...this.events];\n\t\tconst filter = this.filter;\n\n\t\t// Every adaptor hands the handler `events` as `{ type, payload }`\n\t\t// messages; this narrows them to the ones this subscriber wants — the\n\t\t// adaptor's word is final on the key, whatever filtered at the source\n\t\t// — and hands over the objects.\n\t\tconst handler = async (ctx: Record<string, any>) => {\n\t\t\tconst { matchesObjectFilter } = await import('@geekmidas/storage/events');\n\t\t\tconst wanted = (ctx.events as unknown[]).filter(\n\t\t\t\t(event): event is ObjectMessage =>\n\t\t\t\t\tisObjectMessage(event) &&\n\t\t\t\t\tevents.includes(event.type) &&\n\t\t\t\t\tmatchesObjectFilter(event.payload, filter),\n\t\t\t);\n\t\t\tif (wanted.length === 0) return undefined;\n\t\t\treturn fn({\n\t\t\t\t...ctx,\n\t\t\t\tevents: wanted,\n\t\t\t\tobjects: wanted.map((event) => event.payload),\n\t\t\t} as unknown as ObjectSubscriberContext<\n\t\t\t\tTEvents,\n\t\t\t\tTServices,\n\t\t\t\tTLogger,\n\t\t\t\tTDatabase\n\t\t\t>);\n\t\t};\n\n\t\tconst subscriber = this.inner\n\t\t\t.subscribe(events as never)\n\t\t\t.handle(handler as never) as unknown as ObjectSubscriber<\n\t\t\tTServices,\n\t\t\tTLogger,\n\t\t\tOutSchema,\n\t\t\tTEvents,\n\t\t\tTDatabase,\n\t\t\tTDatabaseServiceName\n\t\t>;\n\t\tsubscriber.bucketName = this.bucket;\n\t\tsubscriber.objectFilter = filter;\n\t\treturn subscriber;\n\t}\n\n\tprivate with(inner: SubscriberBuilder<any, any, any, any, any, any, any>) {\n\t\treturn new ObjectSubscriberBuilder<any, any, any, any, any, any>(\n\t\t\tinner,\n\t\t\tthis.bucket,\n\t\t\tthis.events,\n\t\t\tthis.filter,\n\t\t);\n\t}\n}\n\nfunction isObjectMessage(value: unknown): value is ObjectMessage {\n\tconst message = value as ObjectMessage | undefined;\n\treturn (\n\t\ttypeof message === 'object' &&\n\t\tmessage !== null &&\n\t\t(message.type === 'object.created' || message.type === 'object.deleted') &&\n\t\ttypeof message.payload?.key === 'string'\n\t);\n}\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 { 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\t/**\n\t * The id of the bucket this subscriber is bound to (via\n\t * `worker.objects(bucket)`), when its topic is the storage itself — read\n\t * by the build to bind it, and by the adaptors to read what the storage\n\t * sends as object events.\n\t */\n\tbucketName?: string;\n\n\t/** Which of the bucket's keys it watches — see `worker.objects()`. */\n\tobjectFilter?: { prefix?: string; suffix?: string };\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":";;;;;;AAkEA,IAAa,8BAAb,cAAiD,MAAM;CACjC;CAArB,YAAY,QAAyB;EACpC,MACC,0BAA0B,OAAO,qGAElC;EAJoB,KAAA,SAAA;EAKpB,KAAK,OAAO;CACb;AACD;;;;;;;;;AAUA,IAAa,0BAAb,MAAa,wBAOX;CAGiB;CAUA;CACA;CACA;CAdlB,YAEC,OAUA,QACA,SAAsD,CAAC,GACvD,SAAwC,CAAC,GACxC;EAbgB,KAAA,QAAA;EAUA,KAAA,SAAA;EACA,KAAA,SAAA;EACA,KAAA,SAAA;CACf;;;;;CAMH,GACC,QACA,SAAuB,CAAC,GAQvB;EACD,OAAO,IAAI,wBACV,KAAK,OACL,KAAK,QACL,CAAC,mBAAG,IAAI,IAAI,CAAC,GAAG,KAAK,QAAQ,GAAG,MAAM,CAAC,CAAC,GACxC;GACC,GAAI,OAAO,SAAS,EAAE,QAAQ,OAAO,OAAO,IAAI,CAAC;GACjD,GAAI,OAAO,SAAS,EAAE,QAAQ,OAAO,OAAO,IAAI,CAAC;EAClD,CACD;CACD;;CAGA,UACC,YAQC;EACD,OAAO,KAAK,KAAK,KAAK,MAAM,UAAU,UAAU,CAAC;CAClD;CAEA,SACC,UAQC;EACD,OAAO,KAAK,KAAK,KAAK,MAAM,SAAS,QAAQ,CAAC;CAC/C;;CAGA,SACC,QAQC;EACD,OAAO,KAAK,KAAK,KAAK,MAAM,SAAS,MAAM,CAAC;CAC7C;CAEA,QAAQ,SAAuB;EAC9B,OAAO,KAAK,KAAK,KAAK,MAAM,QAAQ,OAAO,CAAC;CAC7C;CAEA,OACC,QAQC;EACD,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,MAAM,CAAC;CAC3C;CAEA,OACC,QAQC;EACD,OAAO,KAAK,KAAK,KAAK,MAAM,OAAO,MAAM,CAAC;CAC3C;CAEA,OACC,IAcC;EACD,IAAI,KAAK,OAAO,WAAW,GAC1B,MAAM,IAAI,4BAA4B,KAAK,MAAM;EAElD,MAAM,SAAS,CAAC,GAAG,KAAK,MAAM;EAC9B,MAAM,SAAS,KAAK;EAMpB,MAAM,UAAU,OAAO,QAA6B;GACnD,MAAM,EAAE,wBAAwB,MAAM,OAAO;GAC7C,MAAM,SAAU,IAAI,OAAqB,QACvC,UACA,gBAAgB,KAAK,KACrB,OAAO,SAAS,MAAM,IAAI,KAC1B,oBAAoB,MAAM,SAAS,MAAM,CAC3C;GACA,IAAI,OAAO,WAAW,GAAG,OAAO,KAAA;GAChC,OAAO,GAAG;IACT,GAAG;IACH,QAAQ;IACR,SAAS,OAAO,KAAK,UAAU,MAAM,OAAO;GAC7C,CAKC;EACF;EAEA,MAAM,aAAa,KAAK,MACtB,UAAU,MAAe,CAAC,CAC1B,OAAO,OAAgB;EAQzB,WAAW,aAAa,KAAK;EAC7B,WAAW,eAAe;EAC1B,OAAO;CACR;CAEA,KAAa,OAA6D;EACzE,OAAO,IAAI,wBACV,OACA,KAAK,QACL,KAAK,QACL,KAAK,MACN;CACD;AACD;AAEA,SAAS,gBAAgB,OAAwC;CAChE,MAAM,UAAU;CAChB,OACC,OAAO,YAAY,YACnB,YAAY,SACX,QAAQ,SAAS,oBAAoB,QAAQ,SAAS,qBACvD,OAAO,QAAQ,SAAS,QAAQ;AAElC;;;;;;;;ACrQA,IAAa,aAAb,cAUU,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,SAA2C,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;;;;;;;CAQA;;CAGA;CAEA,IAAI,mBAAkD;EACrD,OAAO,KAAK;CACb;AACD;;;AChGA,IAAa,oBAAb,MAQE;CACD,oBAA+C,CAAC;CAChD;CACA;CACA,YAA+B,CAAC;;CAEhC,cAA+B,CAAC;CAChC,UAA2B;;;;;CAK3B;CACA;;CAEA;;CAEA;CAEA,cAAc;EACb,KAAK,WAAW;CACjB;;;;;;;;;;CAWA,MACC,OASC;EACD,OAAO,UAAU,MAAM,EACtB,YAAY,MAAM,KACnB,CAAC;CASF;CAEA,QAAQ,SAAuB;EAC9B,OAAO,UAAU,MAAM,EAAE,UAAU,QAAQ,CAAC;CAC7C;CAEA,OACC,QASC;EACD,OAAO,UAAU,MAAM,EACtB,cAAc,OACf,CAAC;CACF;;;;;;;;;;;;CAaA,UACC,YASC;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;CASF;CAEA,SACC,UASC;EACD,OAAO,UAAU,MAAM,EACtB,WAAW,CAAC,GAAG,KAAK,WAAW,GAAG,QAAQ,EAC3C,CAAC;CACF;CAEA,OACC,QASC;EACD,OAAO,UAAU,MAAM,EAAE,SAAS,OAA6B,CAAC;CACjE;;;;;;;;CASA,SACC,QASC;EACD,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;CASF;CAEA,UAOC,OAWC;EACD,MAAM,cAAc,MAAM,QAAQ,KAAK,IAAI,QAAQ,CAAC,KAAK;EACzD,OAAO,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"}