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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (196) hide show
  1. package/dist/{Cron-CMEGfRs8.d.cts → Cron-DI3nKoic.d.cts} +3 -2
  2. package/dist/Cron-DI3nKoic.d.cts.map +1 -0
  3. package/dist/{Cron-D6X4-xjB.d.mts → Cron-uYAHPnp7.d.mts} +3 -2
  4. package/dist/Cron-uYAHPnp7.d.mts.map +1 -0
  5. package/dist/{CronBuilder-DB35T5dL.cjs → CronBuilder-BoHzlWU_.cjs} +8 -3
  6. package/dist/CronBuilder-BoHzlWU_.cjs.map +1 -0
  7. package/dist/{CronBuilder-Dv0IlZs0.mjs → CronBuilder-CCgt0wCE.mjs} +9 -4
  8. package/dist/CronBuilder-CCgt0wCE.mjs.map +1 -0
  9. package/dist/{CronBuilder-O_gvButp.d.mts → CronBuilder-DaSUm2Na.d.mts} +5 -4
  10. package/dist/CronBuilder-DaSUm2Na.d.mts.map +1 -0
  11. package/dist/{CronBuilder-CEK7aOqD.d.cts → CronBuilder-g1lZLWyG.d.cts} +5 -4
  12. package/dist/CronBuilder-g1lZLWyG.d.cts.map +1 -0
  13. package/dist/{Endpoint-CQAeh1Rh.mjs → Endpoint-BDgmfml0.mjs} +2 -2
  14. package/dist/{Endpoint-CQAeh1Rh.mjs.map → Endpoint-BDgmfml0.mjs.map} +1 -1
  15. package/dist/{Endpoint-Dp5AKIXl.d.cts → Endpoint-BkzU6nn1.d.cts} +5 -4
  16. package/dist/Endpoint-BkzU6nn1.d.cts.map +1 -0
  17. package/dist/{Endpoint-DtI7heFm.d.mts → Endpoint-BpboleFh.d.mts} +5 -4
  18. package/dist/Endpoint-BpboleFh.d.mts.map +1 -0
  19. package/dist/{Endpoint-D1L9qu5C.cjs → Endpoint-wSCHSnqb.cjs} +2 -2
  20. package/dist/{Endpoint-D1L9qu5C.cjs.map → Endpoint-wSCHSnqb.cjs.map} +1 -1
  21. package/dist/{EndpointFactory-FeFRmlDZ.d.cts → EndpointFactory-BZZOleQT.d.cts} +4 -4
  22. package/dist/{EndpointFactory-CgMDvERK.d.mts.map → EndpointFactory-BZZOleQT.d.cts.map} +1 -1
  23. package/dist/{EndpointFactory-BBdNeaGJ.mjs → EndpointFactory-C9G2pz86.mjs} +3 -3
  24. package/dist/{EndpointFactory-BBdNeaGJ.mjs.map → EndpointFactory-C9G2pz86.mjs.map} +1 -1
  25. package/dist/{EndpointFactory-CgMDvERK.d.mts → EndpointFactory-DnNlYflU.d.mts} +4 -4
  26. package/dist/{EndpointFactory-FeFRmlDZ.d.cts.map → EndpointFactory-DnNlYflU.d.mts.map} +1 -1
  27. package/dist/{EndpointFactory-BZOCOaK6.cjs → EndpointFactory-G1g1kiqC.cjs} +3 -3
  28. package/dist/{EndpointFactory-BZOCOaK6.cjs.map → EndpointFactory-G1g1kiqC.cjs.map} +1 -1
  29. package/dist/Function-DuqGcbOI.d.mts +76 -0
  30. package/dist/Function-DuqGcbOI.d.mts.map +1 -0
  31. package/dist/Function-Pu-1kKZz.d.cts +76 -0
  32. package/dist/Function-Pu-1kKZz.d.cts.map +1 -0
  33. package/dist/{HonoEndpointAdaptor-Cq99r9H7.cjs → HonoEndpointAdaptor-CBoSm3TM.cjs} +3 -3
  34. package/dist/{HonoEndpointAdaptor-Cq99r9H7.cjs.map → HonoEndpointAdaptor-CBoSm3TM.cjs.map} +1 -1
  35. package/dist/{HonoEndpointAdaptor-Aui-x9Lg.mjs → HonoEndpointAdaptor-DL_fCB9O.mjs} +3 -3
  36. package/dist/{HonoEndpointAdaptor-Aui-x9Lg.mjs.map → HonoEndpointAdaptor-DL_fCB9O.mjs.map} +1 -1
  37. package/dist/{Queue-Ckmudcm8.cjs → Queue-D5jcw0mu.cjs} +6 -2
  38. package/dist/Queue-D5jcw0mu.cjs.map +1 -0
  39. package/dist/{Queue-YmvN2vEP.d.mts → Queue-DlsHRzUp.d.mts} +22 -10
  40. package/dist/Queue-DlsHRzUp.d.mts.map +1 -0
  41. package/dist/{Queue-CpQIGB_2.d.cts → Queue-HPyi0e1i.d.cts} +22 -10
  42. package/dist/Queue-HPyi0e1i.d.cts.map +1 -0
  43. package/dist/{Queue-C1uDgjxt.mjs → Queue-hwPN-t31.mjs} +6 -2
  44. package/dist/Queue-hwPN-t31.mjs.map +1 -0
  45. package/dist/{QueueBuilder-CJNcv4dy.cjs → QueueBuilder-BFQn3OzZ.cjs} +27 -4
  46. package/dist/QueueBuilder-BFQn3OzZ.cjs.map +1 -0
  47. package/dist/{QueueBuilder-XuPKZwKH.mjs → QueueBuilder-DCuYdjMw.mjs} +28 -5
  48. package/dist/QueueBuilder-DCuYdjMw.mjs.map +1 -0
  49. package/dist/{QueueBuilder-XEnnOWGe.d.cts → QueueBuilder-OSi6LkV9.d.cts} +24 -11
  50. package/dist/QueueBuilder-OSi6LkV9.d.cts.map +1 -0
  51. package/dist/{QueueBuilder-CM0WUxfw.d.mts → QueueBuilder-QHsnVt1P.d.mts} +24 -11
  52. package/dist/QueueBuilder-QHsnVt1P.d.mts.map +1 -0
  53. package/dist/{Subscriber-B91YSkZt.d.cts → Subscriber-Bpp02cGr.d.cts} +20 -9
  54. package/dist/Subscriber-Bpp02cGr.d.cts.map +1 -0
  55. package/dist/{Subscriber-BjHYe5hK.d.mts → Subscriber-CtN9R48-.d.mts} +20 -9
  56. package/dist/Subscriber-CtN9R48-.d.mts.map +1 -0
  57. package/dist/{SubscriberBuilder-Duk028pD.cjs → SubscriberBuilder-C2PwqwIl.cjs} +31 -3
  58. package/dist/SubscriberBuilder-C2PwqwIl.cjs.map +1 -0
  59. package/dist/{SubscriberBuilder-BhMphk4z.d.mts → SubscriberBuilder-CuCMFpYW.d.mts} +23 -11
  60. package/dist/SubscriberBuilder-CuCMFpYW.d.mts.map +1 -0
  61. package/dist/{SubscriberBuilder-DzQUWE08.mjs → SubscriberBuilder-DMFk_Ap1.mjs} +32 -4
  62. package/dist/SubscriberBuilder-DMFk_Ap1.mjs.map +1 -0
  63. package/dist/{SubscriberBuilder-BSpQX1JT.d.cts → SubscriberBuilder-g3fAVWgs.d.cts} +23 -11
  64. package/dist/SubscriberBuilder-g3fAVWgs.d.cts.map +1 -0
  65. package/dist/adaptors/aws.cjs +20 -4
  66. package/dist/adaptors/aws.cjs.map +1 -1
  67. package/dist/adaptors/aws.d.cts +17 -13
  68. package/dist/adaptors/aws.d.cts.map +1 -1
  69. package/dist/adaptors/aws.d.mts +17 -13
  70. package/dist/adaptors/aws.d.mts.map +1 -1
  71. package/dist/adaptors/aws.mjs +20 -4
  72. package/dist/adaptors/aws.mjs.map +1 -1
  73. package/dist/adaptors/hono.cjs +1 -1
  74. package/dist/adaptors/hono.d.cts +1 -1
  75. package/dist/adaptors/hono.d.mts +1 -1
  76. package/dist/adaptors/hono.mjs +1 -1
  77. package/dist/adaptors/testing.cjs +170 -13
  78. package/dist/adaptors/testing.cjs.map +1 -1
  79. package/dist/adaptors/testing.d.cts +38 -21
  80. package/dist/adaptors/testing.d.cts.map +1 -1
  81. package/dist/adaptors/testing.d.mts +38 -21
  82. package/dist/adaptors/testing.d.mts.map +1 -1
  83. package/dist/adaptors/testing.mjs +170 -13
  84. package/dist/adaptors/testing.mjs.map +1 -1
  85. package/dist/{auth-CMwml9QN.d.mts → auth-3OAmK42n.d.cts} +4 -4
  86. package/dist/{auth-CMwml9QN.d.mts.map → auth-3OAmK42n.d.cts.map} +1 -1
  87. package/dist/{auth-rVRDjIw_.d.cts → auth-BWbiewHa.d.mts} +4 -4
  88. package/dist/{auth-rVRDjIw_.d.cts.map → auth-BWbiewHa.d.mts.map} +1 -1
  89. package/dist/auth.d.cts +1 -1
  90. package/dist/auth.d.mts +1 -1
  91. package/dist/{cache-C9a_hVCc.d.cts → cache-CXh6GIgb.d.mts} +3 -3
  92. package/dist/{cache-C9a_hVCc.d.cts.map → cache-CXh6GIgb.d.mts.map} +1 -1
  93. package/dist/{cache-CeTMI8LR.d.mts → cache-DnGDGly3.d.cts} +3 -3
  94. package/dist/{cache-CeTMI8LR.d.mts.map → cache-DnGDGly3.d.cts.map} +1 -1
  95. package/dist/cache.d.cts +1 -1
  96. package/dist/cache.d.mts +1 -1
  97. package/dist/{construct-interface-_3zgxzXl.d.mts → construct-interface-B1AfqRl4.d.cts} +25 -3
  98. package/dist/{construct-interface-_3zgxzXl.d.mts.map → construct-interface-B1AfqRl4.d.cts.map} +1 -1
  99. package/dist/{construct-interface-_xi4BPN8.d.cts → construct-interface-DluK3_da.d.mts} +25 -3
  100. package/dist/{construct-interface-_xi4BPN8.d.cts.map → construct-interface-DluK3_da.d.mts.map} +1 -1
  101. package/dist/construct-interface.cjs +26 -0
  102. package/dist/construct-interface.cjs.map +1 -1
  103. package/dist/construct-interface.d.cts +2 -2
  104. package/dist/construct-interface.d.mts +2 -2
  105. package/dist/construct-interface.mjs +26 -1
  106. package/dist/construct-interface.mjs.map +1 -1
  107. package/dist/credential.d.cts +1 -1
  108. package/dist/credential.d.mts +1 -1
  109. package/dist/crons/index.cjs +1 -1
  110. package/dist/crons/index.d.cts +2 -2
  111. package/dist/crons/index.d.mts +2 -2
  112. package/dist/crons/index.mjs +1 -1
  113. package/dist/database/kysely.d.cts +1 -1
  114. package/dist/database/kysely.d.mts +1 -1
  115. package/dist/email.d.cts +1 -1
  116. package/dist/email.d.mts +1 -1
  117. package/dist/endpoints/index.cjs +3 -3
  118. package/dist/endpoints/index.d.cts +2 -2
  119. package/dist/endpoints/index.d.mts +2 -2
  120. package/dist/endpoints/index.mjs +3 -3
  121. package/dist/{external-api-DS3mujT5.d.mts → external-api-CWY9orcO.d.mts} +2 -2
  122. package/dist/{external-api-DS3mujT5.d.mts.map → external-api-CWY9orcO.d.mts.map} +1 -1
  123. package/dist/{external-api-LBfE-q3g.d.cts → external-api-D-5WB-sr.d.cts} +2 -2
  124. package/dist/{external-api-LBfE-q3g.d.cts.map → external-api-D-5WB-sr.d.cts.map} +1 -1
  125. package/dist/external-api.d.cts +1 -1
  126. package/dist/external-api.d.mts +1 -1
  127. package/dist/file-server.d.cts +1 -1
  128. package/dist/file-server.d.mts +1 -1
  129. package/dist/functions/index.cjs +1 -1
  130. package/dist/functions/index.d.cts +2 -1
  131. package/dist/functions/index.d.mts +2 -1
  132. package/dist/functions/index.mjs +1 -1
  133. package/dist/{functions-ZH60FE7H.cjs → functions-CbP5ZKma.cjs} +15 -3
  134. package/dist/functions-CbP5ZKma.cjs.map +1 -0
  135. package/dist/{functions-DCIfCRR-.mjs → functions-Di6n5ltG.mjs} +16 -4
  136. package/dist/{functions-DCIfCRR-.mjs.map → functions-Di6n5ltG.mjs.map} +1 -1
  137. package/dist/{index-B0kxstwf.d.cts → index-BuzRvKOQ.d.cts} +9 -71
  138. package/dist/index-BuzRvKOQ.d.cts.map +1 -0
  139. package/dist/{index-CjVEjOw0.d.mts → index-CTkKOer4.d.mts} +9 -71
  140. package/dist/index-CTkKOer4.d.mts.map +1 -0
  141. package/dist/{kysely-BJ8IQ_1P.d.mts → kysely-Bqov3fwv.d.mts} +3 -3
  142. package/dist/{kysely-BJ8IQ_1P.d.mts.map → kysely-Bqov3fwv.d.mts.map} +1 -1
  143. package/dist/{kysely-DVF8wOT4.d.cts → kysely-DTnkZsub.d.cts} +3 -3
  144. package/dist/{kysely-DVF8wOT4.d.cts.map → kysely-DTnkZsub.d.cts.map} +1 -1
  145. package/dist/mobile-app.d.cts +1 -1
  146. package/dist/mobile-app.d.mts +1 -1
  147. package/dist/object-storage.d.cts +1 -1
  148. package/dist/object-storage.d.mts +1 -1
  149. package/dist/queue/index.cjs +2 -2
  150. package/dist/queue/index.d.cts +2 -2
  151. package/dist/queue/index.d.mts +2 -2
  152. package/dist/queue/index.mjs +2 -2
  153. package/dist/rest-api.cjs +1 -1
  154. package/dist/rest-api.d.cts +3 -3
  155. package/dist/rest-api.d.mts +3 -3
  156. package/dist/rest-api.mjs +1 -1
  157. package/dist/site.d.cts +1 -1
  158. package/dist/site.d.mts +1 -1
  159. package/dist/subscribers/index.cjs +1 -1
  160. package/dist/subscribers/index.d.cts +2 -2
  161. package/dist/subscribers/index.d.mts +2 -2
  162. package/dist/subscribers/index.mjs +1 -1
  163. package/dist/worker.cjs +26 -10
  164. package/dist/worker.cjs.map +1 -1
  165. package/dist/worker.d.cts +38 -22
  166. package/dist/worker.d.cts.map +1 -1
  167. package/dist/worker.d.mts +38 -22
  168. package/dist/worker.d.mts.map +1 -1
  169. package/dist/worker.mjs +26 -10
  170. package/dist/worker.mjs.map +1 -1
  171. package/package.json +31 -31
  172. package/dist/Cron-CMEGfRs8.d.cts.map +0 -1
  173. package/dist/Cron-D6X4-xjB.d.mts.map +0 -1
  174. package/dist/CronBuilder-CEK7aOqD.d.cts.map +0 -1
  175. package/dist/CronBuilder-DB35T5dL.cjs.map +0 -1
  176. package/dist/CronBuilder-Dv0IlZs0.mjs.map +0 -1
  177. package/dist/CronBuilder-O_gvButp.d.mts.map +0 -1
  178. package/dist/Endpoint-Dp5AKIXl.d.cts.map +0 -1
  179. package/dist/Endpoint-DtI7heFm.d.mts.map +0 -1
  180. package/dist/Queue-C1uDgjxt.mjs.map +0 -1
  181. package/dist/Queue-Ckmudcm8.cjs.map +0 -1
  182. package/dist/Queue-CpQIGB_2.d.cts.map +0 -1
  183. package/dist/Queue-YmvN2vEP.d.mts.map +0 -1
  184. package/dist/QueueBuilder-CJNcv4dy.cjs.map +0 -1
  185. package/dist/QueueBuilder-CM0WUxfw.d.mts.map +0 -1
  186. package/dist/QueueBuilder-XEnnOWGe.d.cts.map +0 -1
  187. package/dist/QueueBuilder-XuPKZwKH.mjs.map +0 -1
  188. package/dist/Subscriber-B91YSkZt.d.cts.map +0 -1
  189. package/dist/Subscriber-BjHYe5hK.d.mts.map +0 -1
  190. package/dist/SubscriberBuilder-BSpQX1JT.d.cts.map +0 -1
  191. package/dist/SubscriberBuilder-BhMphk4z.d.mts.map +0 -1
  192. package/dist/SubscriberBuilder-Duk028pD.cjs.map +0 -1
  193. package/dist/SubscriberBuilder-DzQUWE08.mjs.map +0 -1
  194. package/dist/functions-ZH60FE7H.cjs.map +0 -1
  195. package/dist/index-B0kxstwf.d.cts.map +0 -1
  196. package/dist/index-CjVEjOw0.d.mts.map +0 -1
@@ -1,11 +1,11 @@
1
1
  import { t as StandardSchemaV1 } from "../index-CeEtxDmK.mjs";
2
- import { r as Function } from "../index-CjVEjOw0.mjs";
2
+ import { n as Function } from "../Function-DuqGcbOI.mjs";
3
3
  import { t as HttpMethod } from "../types-DMuSQeLL.mjs";
4
- import { c as EndpointSchemas, i as Endpoint } from "../Endpoint-DtI7heFm.mjs";
5
- import { t as Queue } from "../Queue-YmvN2vEP.mjs";
6
- import { t as Subscriber } from "../Subscriber-BjHYe5hK.mjs";
7
- import { t as KyselyDatabase } from "../kysely-BJ8IQ_1P.mjs";
8
- import { r as Fake } from "../external-api-DS3mujT5.mjs";
4
+ import { c as EndpointSchemas, i as Endpoint } from "../Endpoint-BpboleFh.mjs";
5
+ import { t as Queue } from "../Queue-DlsHRzUp.mjs";
6
+ import { t as Subscriber } from "../Subscriber-CtN9R48-.mjs";
7
+ import { t as KyselyDatabase } from "../kysely-Bqov3fwv.mjs";
8
+ import { r as Fake } from "../external-api-CWY9orcO.mjs";
9
9
  import { EventPublisher, ExtractPublisherMessage } from "@geekmidas/events";
10
10
  import { Kysely } from "kysely";
11
11
  import { Service, ServiceDiscovery, ServiceRecord } from "@geekmidas/services";
@@ -151,39 +151,46 @@ type TestFunctionRequest<TInput extends ComposableStandardSchema | undefined = u
151
151
  /**
152
152
  * In-memory test driver for a {@link Queue} worker. Hand it a batch of messages
153
153
  * and it registers the queue's services, runs the handler in a request context,
154
- * and returns the handler result — no SQS/pg-boss required.
154
+ * and returns the handler result — no SQS/pg-boss required. A queue with a
155
+ * database gets `db` registered from it, or the one the request passes.
155
156
  *
156
157
  * @example
157
158
  * const adapter = new TestQueueAdaptor(ordersQueue);
158
159
  * await adapter.invoke({ messages: [{ orderId: '123' }] });
159
160
  */
160
- export declare class TestQueueAdaptor<TName extends string = string, TMessage extends StandardSchemaV1 = StandardSchemaV1, TServices extends Service[] = [], TLogger extends Logger = Logger> {
161
+ export declare class TestQueueAdaptor<TName extends string = string, TMessage extends StandardSchemaV1 = StandardSchemaV1, TServices extends Service[] = [], TLogger extends Logger = Logger, TDatabase = undefined, TDatabaseServiceName extends string = string> {
161
162
  private readonly queue;
162
163
  private serviceDiscovery;
163
164
  static getDefaultServiceDiscovery(): any;
164
- constructor(queue: Queue<TName, TMessage, TServices, TLogger>, serviceDiscovery?: ServiceDiscovery<any>);
165
- invoke(request: TestQueueRequest<TMessage, TServices>): Promise<unknown>;
165
+ constructor(queue: Queue<TName, TMessage, TServices, TLogger, TDatabase, TDatabaseServiceName>, serviceDiscovery?: ServiceDiscovery<any>);
166
+ invoke(request: TestQueueRequest<TMessage, TServices, TDatabase>): Promise<unknown>;
167
+ private getDatabase;
166
168
  }
167
- type TestQueueRequest<TMessage extends StandardSchemaV1 = StandardSchemaV1, TServices extends Service[] = []> = {
169
+ type TestQueueRequest<TMessage extends StandardSchemaV1 = StandardSchemaV1, TServices extends Service[] = [], TDatabase = undefined> = {
168
170
  messages: InferStandardSchema<TMessage>[];
169
171
  services?: ServiceRecord<TServices>;
172
+ /** Stands in for the queue's database — a transaction, say. */
173
+ db?: TDatabase;
170
174
  };
171
175
  //#endregion
172
176
  //#region src/subscribers/TestSubscriberAdaptor.d.ts
173
177
  type ExtractEventPayloads<TPublisher extends EventPublisher<any> | undefined, TEventTypes extends any[]> = TPublisher extends EventPublisher<any> ? Extract<ExtractPublisherMessage<TPublisher>, {
174
178
  type: TEventTypes[number];
175
179
  }> : never;
176
- export declare class TestSubscriberAdaptor<TServices extends Service[] = [], TLogger extends Logger = Logger, OutSchema extends StandardSchemaV1 | undefined = undefined, TEventPublisher extends EventPublisher<any> | undefined = undefined, TSubscribedEvents extends ExtractPublisherMessage<TEventPublisher>['type'][] = ExtractPublisherMessage<TEventPublisher>['type'][]> {
180
+ export declare class TestSubscriberAdaptor<TServices extends Service[] = [], TLogger extends Logger = Logger, OutSchema extends StandardSchemaV1 | undefined = undefined, TEventPublisher extends EventPublisher<any> | undefined = undefined, TSubscribedEvents extends ExtractPublisherMessage<TEventPublisher>['type'][] = ExtractPublisherMessage<TEventPublisher>['type'][], TDatabase = undefined, TDatabaseServiceName extends string = string> {
177
181
  private readonly subscriber;
178
182
  private serviceDiscovery;
179
183
  static getDefaultServiceDiscovery(): any;
180
- constructor(subscriber: Subscriber<TServices, TLogger, OutSchema, TEventPublisher, TSubscribedEvents>, serviceDiscovery?: ServiceDiscovery<any>);
181
- invoke(request: TestSubscriberRequest<TEventPublisher, TSubscribedEvents, TServices>): Promise<InferStandardSchema<OutSchema>>;
184
+ constructor(subscriber: Subscriber<TServices, TLogger, OutSchema, TEventPublisher, TSubscribedEvents, TDatabase, TDatabaseServiceName>, serviceDiscovery?: ServiceDiscovery<any>);
185
+ invoke(request: TestSubscriberRequest<TEventPublisher, TSubscribedEvents, TServices, TDatabase>): Promise<InferStandardSchema<OutSchema>>;
186
+ private getDatabase;
182
187
  private filterEvents;
183
188
  }
184
- type TestSubscriberRequest<TEventPublisher extends EventPublisher<any> | undefined = undefined, TSubscribedEvents extends any[] = [], TServices extends Service[] = []> = {
189
+ type TestSubscriberRequest<TEventPublisher extends EventPublisher<any> | undefined = undefined, TSubscribedEvents extends any[] = [], TServices extends Service[] = [], TDatabase = undefined> = {
185
190
  events: ExtractEventPayloads<TEventPublisher, TSubscribedEvents>[];
186
191
  services?: ServiceRecord<TServices>;
192
+ /** Stands in for the subscriber's database — a transaction, say. */
193
+ db?: TDatabase;
187
194
  };
188
195
  //#endregion
189
196
  //#region src/testing/manifest.d.ts
@@ -218,6 +225,14 @@ interface TestManifest {
218
225
  surface: string;
219
226
  source: TestManifestSource;
220
227
  }[];
228
+ /**
229
+ * Every topic subscriber — what a topic's events are delivered to. Not a
230
+ * construct, so not in `constructs`: the build finds them, as it finds
231
+ * endpoints.
232
+ */
233
+ subscribers?: {
234
+ source: TestManifestSource;
235
+ }[];
221
236
  /**
222
237
  * The test stage's environment — reconcile's output, keyed as the
223
238
  * constructs derive their keys.
@@ -315,8 +330,10 @@ interface FeatureContext<TBrowser extends Browser, TDatabases extends DatabaseSc
315
330
  mailbox: (address: string) => Mailbox;
316
331
  /**
317
332
  * What this test published to a topic or enqueued on a queue, in order.
318
- * Nothing is delivered — a subscriber or a worker is tested on its own, by
319
- * handing it events — so this is where publishing is asserted.
333
+ *
334
+ * Also delivered: once each request the test makes has answered, a queue's
335
+ * messages reach its consumer and a topic's events every subscriber that
336
+ * named them, in this test's transaction — see {@link deliver}.
320
337
  */
321
338
  published: (channel: {
322
339
  id: string;
@@ -326,12 +343,12 @@ interface FeatureContext<TBrowser extends Browser, TDatabases extends DatabaseSc
326
343
  * with this test's services: its databases resolve to this test's
327
344
  * transactions, as an endpoint's do.
328
345
  */
329
- subscriber: <S extends Subscriber<any, any, any, any, any>>(subscriber: S) => SubscriberAdaptorOf<S>;
346
+ subscriber: <S extends Subscriber<any, any, any, any, any, any, any>>(subscriber: S) => SubscriberAdaptorOf<S>;
330
347
  /** A queue's worker, run on its own with this test's services. */
331
- queue: <Q extends Queue<any, any, any, any>>(queue: Q) => QueueAdaptorOf<Q>;
348
+ queue: <Q extends Queue<any, any, any, any, any, any>>(queue: Q) => QueueAdaptorOf<Q>;
332
349
  }
333
- type SubscriberAdaptorOf<S> = S extends Subscriber<infer TServices, infer TLogger, infer OutSchema, infer TEventPublisher, infer TSubscribedEvents> ? TestSubscriberAdaptor<TServices, TLogger, OutSchema, TEventPublisher, TSubscribedEvents> : never;
334
- type QueueAdaptorOf<Q> = Q extends Queue<infer TName, infer TMessage, infer TServices, infer TLogger> ? TestQueueAdaptor<TName, TMessage, TServices, TLogger> : never;
350
+ type SubscriberAdaptorOf<S> = S extends Subscriber<infer TServices, infer TLogger, infer OutSchema, infer TEventPublisher, infer TSubscribedEvents, infer TDatabase, infer TDatabaseServiceName> ? TestSubscriberAdaptor<TServices, TLogger, OutSchema, TEventPublisher, TSubscribedEvents, TDatabase, TDatabaseServiceName> : never;
351
+ type QueueAdaptorOf<Q> = Q extends Queue<infer TName, infer TMessage, infer TServices, infer TLogger, infer TDatabase, infer TDatabaseServiceName> ? TestQueueAdaptor<TName, TMessage, TServices, TLogger, TDatabase, TDatabaseServiceName> : never;
335
352
  /** The schema a database construct was declared with — what `db` is typed by. */
336
353
  type DatabaseOf<C> = C extends KyselyDatabase<infer DB, any> ? DB : unknown;
337
354
  /** One message as it was published: its type and its payload. */
@@ -1 +1 @@
1
- {"version":3,"file":"testing.d.mts","names":["TestBrowser"],"sources":["../../src/endpoints/MswEndpointAdaptor.ts","../../src/endpoints/TestEndpointAdaptor.ts","../../src/functions/TestFunctionAdaptor.ts","../../src/queue/TestQueueAdaptor.ts","../../src/subscribers/TestSubscriberAdaptor.ts","../../src/testing/manifest.ts","../../src/testing/featureTest.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;UAyDiB;;EAEhB;;;;;;;;;UAUgB;;EAEhB,WAAW;;EAEX;;EAEA;;;;;UAiBgB;;EAEhB,UAAU;;EAEV,kBAAkB,YAAY,SAAS;;;;;;;;;;;;;;;;;wBAkBxB,kBACf,WAAW,0CACX,SAAS,2BACP;;;KC9ES,iBAAiB;EAC5B,MAAM;EACN;EACA,SAAS;;qBAwCG,oBACZ,uBACA,gBAAgB,YAChB,eAAe,sBACf,mBAAmB,0CACnB,kBAAkB,gBAClB,gBAAgB,SAAS,QACzB,oBACA,sBAAsB,sCACtB,kDACA,qBAAqB,mCAAmC,kCAIxD,uBACA;mBAqCkB;UAcT;SAjDF,0BACN,uBACA,gBAAgB,YAChB,eAAe,sBACf,mBAAmB,0CACnB,kBAAkB,gBAClB,gBAAgB,SAAS,QACzB,oBACA,sBAAsB,sCACtB,kDACA,qBAAqB,mCAAmC,kCAIxD,uBACA,8CAEA,WAAW,SACV,QACA,SACA,QACA,YACA,WACA,SACA,UACA,eACA,0BACA,cACA,WACA;EAKF,YACkB,UAAU,SAC1B,QACA,SACA,QACA,YACA,WACA,SACA,UACA,eACA,0BACA,cACA,WACA,uBAEO,mBAAkB;EAKrB,YACL,KAAK,mBACJ,QACA,WACA,eACA,0BACA,WACA,wBAEC,QAAQ,iBAAiB,oBAAoB;EAsM1C,QACL,KAAK,mBACJ,QACA,WACA,eACA,0BACA,WACA,wBAEC,QAAQ,oBAAoB;;;;;KAS3B,wBACJ,sBAAsB,wCACnB;;EAID,gBAAgB;;;;;KAMd,oBAAoB,yBAAyB;;EAI/C,UAAU;;KAGD,mBACX,eAAe,sBACf,kBAAkB,gBAClB,sBAAsB,sCACtB,mDACA,uBACA;EAEA,UAAU,cAAc;EACxB,SAAS;IACN,8BAA8B,UACjC,wBAAwB,iBACxB,oBAAoB;;;qBCpYR,oBACZ,eAAe,kDACf,mBAAmB,0CACnB,kBAAkB,gBAClB,gBAAgB,SAAS,QACzB,sBAAsB,sCACtB,kDACA,uBACA,8CACA,qBAAqB,mCAAmC;mBAoCtC;UAYT;SA3CF,2BACN,eAAe,kDACf,mBAAmB,0CACnB,kBAAkB,gBAClB,gBAAgB,SAAS,QACzB,sBAAsB,sCACtB,kDACA,uBACA,8CACA,qBAAqB,mCAAmC,kCAKxD,KAAK,SACJ,QACA,WACA,SACA,YACA,eACA,0BACA,WACA,sBACA;EAOF,YACkB,IAAI,SACpB,QACA,WACA,SACA,YACA,eACA,0BACA,WACA,sBACA,oBAGO,mBAAkB;EAKrB,OACL,KAAK,oBAAoB,QAAQ,WAAW,WAAW,gBACrD,QAAQ,oBAAoB;;KAoGpB,oBACX,eAAe,kDACf,kBAAkB,gBAClB,uBACA,qBAAqB,mCAAmC;EAKxD,OAAO,8BAA8B;EACrC,UAAU,cAAc;EACxB,KAAK;EACL,UAAU,QAAQ;IACf;EAAgC,OAAO;;;;;;;;;;;;;qBCrL9B,iBACZ,+BACA,iBAAiB,mBAAmB,kBACpC,kBAAkB,gBAClB,gBAAgB,SAAS;mBAOP;UACT;SANF;EAIP,YACkB,OAAO,MAAM,OAAO,UAAU,WAAW,UAClD,mBAAkB;EAGrB,OACL,SAAS,iBAAiB,UAAU,aAClC;;KAsBQ,iBACX,iBAAiB,mBAAmB,kBACpC,kBAAkB;EAElB,UAAU,oBAAoB;EAC9B,WAAW,cAAc;;;;KChDrB,qBACJ,mBAAmB,iCACnB,6BACG,mBAAmB,sBACpB,QAAQ,wBAAwB;EAAe,MAAM;;qBAG3C,sBACZ,kBAAkB,gBAClB,gBAAgB,SAAS,QACzB,kBAAkB,0CAClB,wBAAwB,6CACxB,0BACC,wBAAwB,6BAA6B,wBAAwB;mBAO5D;UAOT;SAZF;EAIP,YACkB,YAAY,WAC5B,WACA,SACA,WACA,iBACA,oBAEO,mBAAkB;EAGrB,OACL,SAAS,sBACR,iBACA,mBACA,aAEC,QAAQ,oBAAoB;UAmDvB;;KAaG,sBACX,wBAAwB,6CACxB,sCACA,kBAAkB;EAElB,QAAQ,qBAAqB,iBAAiB;EAC9C,WAAW,cAAc;;;;;;;;;;;;;;;;UCtGT;;EAEhB;;EAEA;;UAGgB;;EAEhB;;EAEA,YAAY;IAAiB;IAAc,QAAQ;;;EAEnD;IAAa;IAAiB,QAAQ;;;;;;EAKtC,KAAK;;;qBAIO;;;;;wBAMG,iBAAiB,gBAAgB,MAAM;;qBAsC1C,uBAAuB;EACnC;;;;;KCzBW,kBAAkB,gBAAgB,IAAI;UAEjC,mBAChB,iBAAiBA,SACjB,mBAAmB;;;;;EAMnB,WAAW;;;;;;;EAOX,UAAU,SAAS,eAAe;;EAElC,oBAAoB;;;;;;;;EAQpB,YAAY;;;;;;EAMZ,QAAQ,SAAS,eAAe;;;KAIrB,kBAAkB;;;;;;;;UASb,cAAc,mBAAmB;EACjD,IAAI,gBAAgB,qBACnB,MAAM,IACJ,QAAQ,OAAO,WAAW;;;;;;;;UASb,cAAc,mBAAmB;EACjD,IAAI,gBAAgB,qBACnB,MAAM,IACJ,QAAQ,WAAW,WAAW;;UAGjB,eAChB,iBAAiBA,SACjB,mBAAmB,sBACnB,mBAAmB;;EAGnB,SAAS;;;;;;EAMT,IAAI,cAAc;;;;;;EAMlB,WAAW,cAAc;;;;;;EAMzB,OAAO;;EAEP,UAAU,oBAAoB;;;;;;EAM9B,YAAY;IAAW;QAAiB;;;;;;EAMxC,aAAa,UAAU,qCACtB,YAAY,MACR,oBAAoB;;EAEzB,QAAQ,UAAU,2BAA2B,OAAO,MAAM,eAAe;;KAGrE,oBAAoB,KACxB,UAAU,iBACH,iBACA,eACA,iBACA,uBACA,qBAEJ,sBACA,WACA,SACA,WACA,iBACA;KAIC,eAAe,KACnB,UAAU,YAAY,aAAa,gBAAgB,iBAAiB,WACjE,iBAAiB,OAAO,UAAU,WAAW;;KAIrC,WAAW,KACtB,UAAU,qBAAqB,WAAW;;UAG1B;EAChB;EACA;;KAGI,UACJ,iBAAiBA,SACjB,mBAAmB,iBACnB,mBAAmB,oBACf,SAAS,eAAe,UAAU,YAAY;UAElC,UAChB,iBAAiBA,SACjB,mBAAmB,sBACnB,mBAAmB;GAGlB,cACA,IAAI,UAAU,UAAU,YAAY,aACpC;EAED,KACC,cACA,IAAI,UAAU,UAAU,YAAY,aACpC;EAED,KACC,cACA,IAAI,UAAU,UAAU,YAAY,aACpC;;wBAsCc,YACf,iBAAiBA,UAAcA,SAC/B,mBAAmB,sBACnB,mBAAmB,sBAEnB,UAAS,mBAAmB,UAAU,cACpC,UAAU,UAAU,YAAY;;UA4blB,oBAAoB;EACpC;IACC,UAAU;MACT;QACG;MAAU;QAAU;;;;EAEzB,cAAc;IAAU,MAAM;;;;;;;;;;;;wBAYT,oBAAoB,UACzC,SAASA,SACT,MAAM,oBAAoB,WAC1B,iBACE,QAAQ;;qBAkDE,qBAAqB;WAEvB;WACA;EAFV,YACU,eACA;;;qBAQE,2BAA2B;WAE7B;WACA;EAFV,YACU,aACA;;;qBAcE,gBAAgB;EAC5B;;;qBAWY,wBAAwB;WAE1B;WACA;EAFV,YACU,kBACA;;;qBAeE,uBAAuB;WAEzB;WACA;EAFV,YACU,iBACA"}
1
+ {"version":3,"file":"testing.d.mts","names":["TestBrowser"],"sources":["../../src/endpoints/MswEndpointAdaptor.ts","../../src/endpoints/TestEndpointAdaptor.ts","../../src/functions/TestFunctionAdaptor.ts","../../src/queue/TestQueueAdaptor.ts","../../src/subscribers/TestSubscriberAdaptor.ts","../../src/testing/manifest.ts","../../src/testing/featureTest.ts"],"mappings":"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"}
@@ -1,12 +1,12 @@
1
1
  import { BetterAuth } from "../auth.mjs";
2
- import { a as publishEvents, i as publishConstructEvents, t as FunctionBuilder } from "../functions-DCIfCRR-.mjs";
3
- import { n as ResponseBuilder, t as Endpoint } from "../Endpoint-CQAeh1Rh.mjs";
4
- import { t as Queue } from "../Queue-C1uDgjxt.mjs";
2
+ import { a as publishEvents, i as publishConstructEvents, t as FunctionBuilder } from "../functions-Di6n5ltG.mjs";
3
+ import { n as ResponseBuilder, t as Endpoint } from "../Endpoint-BDgmfml0.mjs";
4
+ import { t as Queue } from "../Queue-hwPN-t31.mjs";
5
5
  import { Email } from "../email.mjs";
6
6
  import { KyselyDatabase } from "../database/kysely.mjs";
7
7
  import { c as createObjectHeaders, r as createCookieHeaderAccessor } from "../lazyAccessors-CFanua0O.mjs";
8
8
  import { t as Topic } from "../Topic-hPffOsot.mjs";
9
- import { t as HonoEndpoint } from "../HonoEndpointAdaptor-Aui-x9Lg.mjs";
9
+ import { t as HonoEndpoint } from "../HonoEndpointAdaptor-DL_fCB9O.mjs";
10
10
  import { n as executeWithAuditTransaction } from "../processAudits-BpRlPQMW.mjs";
11
11
  import { provideKey } from "@geekmidas/manifest";
12
12
  import { ForbiddenError } from "@geekmidas/errors";
@@ -342,7 +342,8 @@ var TestFunctionAdaptor = class TestFunctionAdaptor {
342
342
  /**
343
343
  * In-memory test driver for a {@link Queue} worker. Hand it a batch of messages
344
344
  * and it registers the queue's services, runs the handler in a request context,
345
- * and returns the handler result — no SQS/pg-boss required.
345
+ * and returns the handler result — no SQS/pg-boss required. A queue with a
346
+ * database gets `db` registered from it, or the one the request passes.
346
347
  *
347
348
  * @example
348
349
  * const adapter = new TestQueueAdaptor(ordersQueue);
@@ -361,6 +362,7 @@ var TestQueueAdaptor = class TestQueueAdaptor {
361
362
  async invoke(request) {
362
363
  const logger = this.queue.logger.child({ test: true });
363
364
  const services = request.services ?? await this.serviceDiscovery.register(this.queue.services);
365
+ const db = request.db !== void 0 ? request.db : await this.getDatabase();
364
366
  const requestId = `test-${Date.now()}`;
365
367
  return runWithRequestContext({
366
368
  logger,
@@ -369,9 +371,15 @@ var TestQueueAdaptor = class TestQueueAdaptor {
369
371
  }, () => this.queue.handler({
370
372
  messages: request.messages,
371
373
  services,
372
- logger
374
+ logger,
375
+ db
373
376
  }));
374
377
  }
378
+ async getDatabase() {
379
+ const service = this.queue.databaseService;
380
+ if (!service) return void 0;
381
+ return (await this.serviceDiscovery.register([service]))[service.serviceName];
382
+ }
375
383
  };
376
384
  //#endregion
377
385
  //#region src/subscribers/TestSubscriberAdaptor.ts
@@ -390,6 +398,7 @@ var TestSubscriberAdaptor = class TestSubscriberAdaptor {
390
398
  let services;
391
399
  if (request.services) services = request.services;
392
400
  else services = await this.serviceDiscovery.register(this.subscriber.services);
401
+ const db = request.db !== void 0 ? request.db : await this.getDatabase();
393
402
  const filteredEvents = this.filterEvents(request.events);
394
403
  if (filteredEvents.length === 0) return { batchItemFailures: [] };
395
404
  const requestId = `test-${Date.now()}`;
@@ -401,7 +410,8 @@ var TestSubscriberAdaptor = class TestSubscriberAdaptor {
401
410
  const result = await this.subscriber.handler({
402
411
  events: filteredEvents,
403
412
  services,
404
- logger
413
+ logger,
414
+ db
405
415
  });
406
416
  let output = result;
407
417
  if (this.subscriber.outputSchema && result) {
@@ -412,6 +422,11 @@ var TestSubscriberAdaptor = class TestSubscriberAdaptor {
412
422
  return output;
413
423
  });
414
424
  }
425
+ async getDatabase() {
426
+ const service = this.subscriber.databaseService;
427
+ if (!service) return void 0;
428
+ return (await this.serviceDiscovery.register([service]))[service.serviceName];
429
+ }
415
430
  filterEvents(events) {
416
431
  if (!this.subscriber.subscribedEvents) return events;
417
432
  return events.filter((event) => this.subscriber.subscribedEvents.includes(event.type));
@@ -515,7 +530,16 @@ function featureTest(options = {}) {
515
530
  if (isLocal(new URL(request.url))) return;
516
531
  print.error();
517
532
  } });
518
- restoreFetch = installContextFetch();
533
+ const restoreStamp = installContextFetch();
534
+ const stamped = globalThis.fetch;
535
+ globalThis.fetch = deliveringFetch(stamped, (id) => {
536
+ const state = contexts.get(id);
537
+ return state ? deliver(app, state, id) : Promise.resolve();
538
+ });
539
+ restoreFetch = () => {
540
+ globalThis.fetch = stamped;
541
+ restoreStamp();
542
+ };
519
543
  });
520
544
  afterAll(() => {
521
545
  restoreFetch();
@@ -530,7 +554,9 @@ function featureTest(options = {}) {
530
554
  surfaces: /* @__PURE__ */ new Map(),
531
555
  auth: /* @__PURE__ */ new Map(),
532
556
  addresses: /* @__PURE__ */ new Set(),
533
- published: /* @__PURE__ */ new Map()
557
+ published: /* @__PURE__ */ new Map(),
558
+ pending: [],
559
+ delivering: false
534
560
  };
535
561
  const readMail = app.readMail;
536
562
  if (readMail) state.mailbox = (address) => {
@@ -570,8 +596,8 @@ function featureTest(options = {}) {
570
596
  return state.mailbox(address);
571
597
  },
572
598
  published: (channel) => [...state.published.get(channel.id) ?? []],
573
- subscriber: (subscriber) => new TestSubscriberAdaptor(subscriber, state.discovery),
574
- queue: (queue) => new TestQueueAdaptor(queue, state.discovery)
599
+ subscriber: (subscriber) => thenDeliver(new TestSubscriberAdaptor(subscriber, state.discovery), () => deliver(app, state, id)),
600
+ queue: (queue) => thenDeliver(new TestQueueAdaptor(queue, state.discovery), () => deliver(app, state, id))
575
601
  });
576
602
  } finally {
577
603
  restore();
@@ -607,6 +633,10 @@ async function load(manifest, modules) {
607
633
  const imported = async ({ file, export: name }) => (modules[file] ?? await import(file))[name];
608
634
  const constructs = await Promise.all(Object.values(manifest.constructs).map(({ source }) => imported(source)));
609
635
  const endpoints = (await Promise.all(manifest.endpoints.map(({ source }) => imported(source)))).filter((value) => Endpoint.isEndpoint(value));
636
+ const subscribers = (await Promise.all((manifest.subscribers ?? []).map(async ({ source }) => ({
637
+ name: source.export,
638
+ subscriber: await imported(source)
639
+ })))).filter((entry) => entry.subscriber?.__IS_SUBSCRIBER__ === true);
610
640
  const unique = (values) => [...new Set(values)];
611
641
  const databases = unique(constructs.filter((value) => value instanceof KyselyDatabase));
612
642
  const auths = unique(constructs.filter((value) => value instanceof BetterAuth));
@@ -620,6 +650,7 @@ async function load(manifest, modules) {
620
650
  auths,
621
651
  emails,
622
652
  channels,
653
+ subscribers,
623
654
  ...inbox ? { readMail: createMailbox({ inbox }) } : {}
624
655
  };
625
656
  }
@@ -631,10 +662,15 @@ async function load(manifest, modules) {
631
662
  function recorders(channels, state) {
632
663
  return channels.map((channel) => {
633
664
  const publisher = { async publish(messages) {
634
- state.published.set(channel.id, [...state.published.get(channel.id) ?? [], ...messages.map(({ type, payload }) => ({
665
+ const sent = messages.map(({ type, payload }) => ({
635
666
  type,
636
667
  payload
637
- }))]);
668
+ }));
669
+ state.published.set(channel.id, [...state.published.get(channel.id) ?? [], ...sent]);
670
+ state.pending.push({
671
+ channel,
672
+ messages: sent
673
+ });
638
674
  } };
639
675
  return {
640
676
  serviceName: channel.service.serviceName,
@@ -668,6 +704,90 @@ function databasesFor(factories, databases) {
668
704
  * the one place a test's connection can be handed over. Outside a test it is
669
705
  * the database it always was.
670
706
  */
707
+ /** Rounds of delivery before a chain of consumers is called a loop. */
708
+ const MAX_DELIVERY_ROUNDS = 25;
709
+ /**
710
+ * Deliver what this test published, in-process, as the broker would — and
711
+ * keep delivering what the consumers publish in turn, until nothing is left.
712
+ *
713
+ * - A queue's messages go to its one consumer, as a batch.
714
+ * - A topic's events go to every subscriber that named their type, and only
715
+ * those: fan-out, as the filter policy (SNS) or the per-subscriber queue
716
+ * (pg-boss) does it.
717
+ * - Each payload is checked against the consumer's schema first. Turning an
718
+ * SNS envelope or an SQS record into `{ type, payload }` is each adaptor's
719
+ * job and tested there; what is tested here is what the handler is handed.
720
+ * - Consumers run as the server side of this test, so their databases are
721
+ * this test's transactions and their writes roll back with it.
722
+ * - A consumer that throws fails the test. Deployed, the message would be
723
+ * retried; here a retry would only hide the bug.
724
+ */
725
+ async function deliver(app, state, id) {
726
+ if (state.delivering) return;
727
+ state.delivering = true;
728
+ try {
729
+ for (let round = 0; state.pending.length > 0; round++) {
730
+ if (round === MAX_DELIVERY_ROUNDS) throw new DeliveryDidNotSettle(MAX_DELIVERY_ROUNDS, [...new Set(state.pending.map(({ channel }) => channel.id))]);
731
+ for (const { channel, messages } of state.pending.splice(0)) if (channel instanceof Queue) await toQueue(channel, messages, state, id);
732
+ else await toSubscribers(channel, messages, app, state, id);
733
+ }
734
+ } finally {
735
+ state.delivering = false;
736
+ }
737
+ }
738
+ async function toQueue(queue, messages, state, id) {
739
+ const payloads = [];
740
+ for (const message of messages) payloads.push(await accepted(queue.messageSchema, message, `queue '${queue.name}'`));
741
+ await runAsServer(id, () => new TestQueueAdaptor(queue, state.discovery).invoke({ messages: payloads })).catch((error) => {
742
+ throw new DeliveryFailed(`queue '${queue.name}'`, messages, error);
743
+ });
744
+ }
745
+ async function toSubscribers(topic, messages, app, state, id) {
746
+ for (const { name, subscriber } of app.subscribers) {
747
+ if (subscriber.topicName !== topic.name) continue;
748
+ const named = messages.filter(({ type }) => (subscriber.subscribedEvents ?? []).includes(type));
749
+ if (named.length === 0) continue;
750
+ const consumer = `subscriber '${name}'`;
751
+ const events = [];
752
+ for (const message of named) {
753
+ const schema = topic.eventSchemas[message.type];
754
+ events.push({
755
+ type: message.type,
756
+ payload: await accepted(schema, message, consumer)
757
+ });
758
+ }
759
+ await runAsServer(id, () => new TestSubscriberAdaptor(subscriber, state.discovery).invoke({ events })).catch((error) => {
760
+ throw new DeliveryFailed(consumer, named, error);
761
+ });
762
+ }
763
+ }
764
+ /** The payload, if the consumer's schema takes it — what the handler is handed. */
765
+ async function accepted(schema, message, consumer) {
766
+ const standard = schema?.["~standard"];
767
+ if (!standard) return message.payload;
768
+ const result = await standard.validate(message.payload);
769
+ if (result.issues) throw new MessageRejected(consumer, message, result.issues);
770
+ return result.value;
771
+ }
772
+ /** `fetch`, delivering what the test published once each of its requests answers. */
773
+ function deliveringFetch(inner, settle) {
774
+ return async (input, init) => {
775
+ const context = currentTestContext();
776
+ const response = await inner(input, init);
777
+ if (context?.side === "client") await settle(context.id);
778
+ return response;
779
+ };
780
+ }
781
+ /** An adaptor whose `invoke` delivers what it published before returning. */
782
+ function thenDeliver(adaptor, settle) {
783
+ const invoke = adaptor.invoke.bind(adaptor);
784
+ adaptor.invoke = (async (...args) => {
785
+ const result = await invoke(...args);
786
+ await settle();
787
+ return result;
788
+ });
789
+ return adaptor;
790
+ }
671
791
  function bindToTests(database) {
672
792
  if (bound.has(database)) return;
673
793
  bound.add(database);
@@ -838,6 +958,43 @@ var UnknownFactory = class extends Error {
838
958
  this.name = "UnknownFactory";
839
959
  }
840
960
  };
961
+ /** A published message the consumer's own schema refuses. */
962
+ var MessageRejected = class extends Error {
963
+ consumer;
964
+ published;
965
+ issues;
966
+ constructor(consumer, published, issues) {
967
+ super(`${consumer} refuses '${published.type}': ${issues.map((issue) => issue.message).join("; ")}. What is published must be what the consumer's schema takes — fix the producer, or the schema.`);
968
+ this.consumer = consumer;
969
+ this.published = published;
970
+ this.issues = issues;
971
+ this.name = "MessageRejected";
972
+ }
973
+ };
974
+ /** A consumer that threw while handling what the test published. */
975
+ var DeliveryFailed = class extends Error {
976
+ consumer;
977
+ messages;
978
+ cause;
979
+ constructor(consumer, messages, cause) {
980
+ super(`${consumer} failed handling ${messages.map(({ type }) => `'${type}'`).join(", ")}: ${cause?.message ?? String(cause)}. Deployed, the message would be retried; here the failure is the result.`, { cause });
981
+ this.consumer = consumer;
982
+ this.messages = messages;
983
+ this.cause = cause;
984
+ this.name = "DeliveryFailed";
985
+ }
986
+ };
987
+ /** Consumers that kept publishing to each other without settling. */
988
+ var DeliveryDidNotSettle = class extends Error {
989
+ rounds;
990
+ channels;
991
+ constructor(rounds, channels) {
992
+ super(`Delivery did not settle after ${rounds} rounds — consumers are still publishing to ${channels.join(", ")}. A consumer that publishes to what triggers it loops forever deployed too.`);
993
+ this.rounds = rounds;
994
+ this.channels = channels;
995
+ this.name = "DeliveryDidNotSettle";
996
+ }
997
+ };
841
998
  //#endregion
842
999
  export { NoInbox, NoTestManifest, SignInFailed, TEST_CONTEXT_HEADER, TEST_MANIFEST_ENV, TestEndpointAdaptor, TestFunctionAdaptor, TestQueueAdaptor, TestSubscriberAdaptor, UnknownDatabase, UnknownFactory, UnknownTestContext, createMswHandlers, featureTest, loadTestManifest, signInWithMagicLink };
843
1000