@geekmidas/constructs 10.0.0-alpha.6 → 10.0.0-alpha.61

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 (405) hide show
  1. package/README.md +223 -158
  2. package/dist/{Construct-BD5neF7w.mjs → Construct-BO1X-kt9.mjs} +32 -33
  3. package/dist/Construct-BO1X-kt9.mjs.map +1 -0
  4. package/dist/Construct-BQALFCh2.d.cts +230 -0
  5. package/dist/Construct-BQALFCh2.d.cts.map +1 -0
  6. package/dist/{Construct-CyS3RpTL.cjs → Construct-DmvXceVY.cjs} +52 -47
  7. package/dist/Construct-DmvXceVY.cjs.map +1 -0
  8. package/dist/Construct-QXnl3VqT.d.mts +230 -0
  9. package/dist/Construct-QXnl3VqT.d.mts.map +1 -0
  10. package/dist/{Cron-DmQ8vQ4b.d.cts → Cron-DI3nKoic.d.cts} +15 -9
  11. package/dist/Cron-DI3nKoic.d.cts.map +1 -0
  12. package/dist/{Cron-dh4rUgib.d.mts → Cron-uYAHPnp7.d.mts} +15 -9
  13. package/dist/Cron-uYAHPnp7.d.mts.map +1 -0
  14. package/dist/{CronBuilder-Da0C0edR.cjs → CronBuilder-BoHzlWU_.cjs} +47 -31
  15. package/dist/CronBuilder-BoHzlWU_.cjs.map +1 -0
  16. package/dist/{CronBuilder-CYKT5RiO.mjs → CronBuilder-CCgt0wCE.mjs} +37 -21
  17. package/dist/CronBuilder-CCgt0wCE.mjs.map +1 -0
  18. package/dist/CronBuilder-DaSUm2Na.d.mts +47 -0
  19. package/dist/CronBuilder-DaSUm2Na.d.mts.map +1 -0
  20. package/dist/CronBuilder-g1lZLWyG.d.cts +47 -0
  21. package/dist/CronBuilder-g1lZLWyG.d.cts.map +1 -0
  22. package/dist/{Endpoint-BjWKinFA.d.mts → Endpoint-BJDBZBZu.d.mts} +75 -91
  23. package/dist/Endpoint-BJDBZBZu.d.mts.map +1 -0
  24. package/dist/{Endpoint-DCQPMdUX.mjs → Endpoint-CMWWrQ7u.mjs} +140 -109
  25. package/dist/Endpoint-CMWWrQ7u.mjs.map +1 -0
  26. package/dist/{Endpoint-dav89W6-.d.cts → Endpoint-DV3jK5sP.d.cts} +74 -90
  27. package/dist/Endpoint-DV3jK5sP.d.cts.map +1 -0
  28. package/dist/{Endpoint-DcWXE-SZ.cjs → Endpoint-DfiXTm_v.cjs} +168 -131
  29. package/dist/Endpoint-DfiXTm_v.cjs.map +1 -0
  30. package/dist/{EndpointFactory-CjV8F_lJ.mjs → EndpointFactory-7g4Dg6cW.mjs} +41 -75
  31. package/dist/EndpointFactory-7g4Dg6cW.mjs.map +1 -0
  32. package/dist/{EndpointFactory-CdWB7wPw.cjs → EndpointFactory-CLxrcS0O.cjs} +77 -111
  33. package/dist/EndpointFactory-CLxrcS0O.cjs.map +1 -0
  34. package/dist/{index-Bd5FqCoe.d.cts → EndpointFactory-CLzCLkLt.d.cts} +64 -133
  35. package/dist/EndpointFactory-CLzCLkLt.d.cts.map +1 -0
  36. package/dist/{index-lAO9egTb.d.mts → EndpointFactory-gaF4yRpP.d.mts} +65 -134
  37. package/dist/EndpointFactory-gaF4yRpP.d.mts.map +1 -0
  38. package/dist/Function-DuqGcbOI.d.mts +76 -0
  39. package/dist/Function-DuqGcbOI.d.mts.map +1 -0
  40. package/dist/Function-Pu-1kKZz.d.cts +76 -0
  41. package/dist/Function-Pu-1kKZz.d.cts.map +1 -0
  42. package/dist/{HonoEndpointAdaptor-DtL9j19R.cjs → HonoEndpointAdaptor-B22boEAR.cjs} +52 -54
  43. package/dist/HonoEndpointAdaptor-B22boEAR.cjs.map +1 -0
  44. package/dist/{HonoEndpointAdaptor-P1ahhZHu.mjs → HonoEndpointAdaptor-vY4JKG8i.mjs} +42 -47
  45. package/dist/HonoEndpointAdaptor-vY4JKG8i.mjs.map +1 -0
  46. package/dist/Queue-D5jcw0mu.cjs +109 -0
  47. package/dist/Queue-D5jcw0mu.cjs.map +1 -0
  48. package/dist/{Queue-D7ZuwBhy.d.cts → Queue-DlsHRzUp.d.mts} +48 -48
  49. package/dist/Queue-DlsHRzUp.d.mts.map +1 -0
  50. package/dist/{Queue-gVGfi2Yk.d.mts → Queue-HPyi0e1i.d.cts} +49 -49
  51. package/dist/Queue-HPyi0e1i.d.cts.map +1 -0
  52. package/dist/Queue-hwPN-t31.mjs +104 -0
  53. package/dist/Queue-hwPN-t31.mjs.map +1 -0
  54. package/dist/QueueBuilder-BFQn3OzZ.cjs +135 -0
  55. package/dist/QueueBuilder-BFQn3OzZ.cjs.map +1 -0
  56. package/dist/QueueBuilder-DCuYdjMw.mjs +118 -0
  57. package/dist/QueueBuilder-DCuYdjMw.mjs.map +1 -0
  58. package/dist/QueueBuilder-OSi6LkV9.d.cts +75 -0
  59. package/dist/QueueBuilder-OSi6LkV9.d.cts.map +1 -0
  60. package/dist/QueueBuilder-QHsnVt1P.d.mts +75 -0
  61. package/dist/QueueBuilder-QHsnVt1P.d.mts.map +1 -0
  62. package/dist/{Subscriber-2mEi0ImH.d.cts → Subscriber-Bpp02cGr.d.cts} +29 -20
  63. package/dist/Subscriber-Bpp02cGr.d.cts.map +1 -0
  64. package/dist/{Subscriber-xTJ9ayPN.d.mts → Subscriber-CtN9R48-.d.mts} +29 -20
  65. package/dist/Subscriber-CtN9R48-.d.mts.map +1 -0
  66. package/dist/{SubscriberBuilder-4OPehf2R.cjs → SubscriberBuilder-C2PwqwIl.cjs} +61 -36
  67. package/dist/SubscriberBuilder-C2PwqwIl.cjs.map +1 -0
  68. package/dist/SubscriberBuilder-CuCMFpYW.d.mts +67 -0
  69. package/dist/SubscriberBuilder-CuCMFpYW.d.mts.map +1 -0
  70. package/dist/{SubscriberBuilder-BjkbeT9l.mjs → SubscriberBuilder-DMFk_Ap1.mjs} +50 -24
  71. package/dist/SubscriberBuilder-DMFk_Ap1.mjs.map +1 -0
  72. package/dist/SubscriberBuilder-g3fAVWgs.d.cts +67 -0
  73. package/dist/SubscriberBuilder-g3fAVWgs.d.cts.map +1 -0
  74. package/dist/Topic-CkxOTrMv.cjs +104 -0
  75. package/dist/Topic-CkxOTrMv.cjs.map +1 -0
  76. package/dist/Topic-hPffOsot.mjs +99 -0
  77. package/dist/Topic-hPffOsot.mjs.map +1 -0
  78. package/dist/adaptors/aws.cjs +118 -216
  79. package/dist/adaptors/aws.cjs.map +1 -1
  80. package/dist/adaptors/aws.d.cts +34 -53
  81. package/dist/adaptors/aws.d.cts.map +1 -1
  82. package/dist/adaptors/aws.d.mts +35 -54
  83. package/dist/adaptors/aws.d.mts.map +1 -1
  84. package/dist/adaptors/aws.mjs +91 -191
  85. package/dist/adaptors/aws.mjs.map +1 -1
  86. package/dist/adaptors/hono.cjs +3 -10
  87. package/dist/adaptors/hono.d.cts +7 -16
  88. package/dist/adaptors/hono.d.cts.map +1 -1
  89. package/dist/adaptors/hono.d.mts +8 -17
  90. package/dist/adaptors/hono.d.mts.map +1 -1
  91. package/dist/adaptors/hono.mjs +2 -10
  92. package/dist/adaptors/testing.cjs +711 -89
  93. package/dist/adaptors/testing.cjs.map +1 -1
  94. package/dist/adaptors/testing.d.cts +325 -54
  95. package/dist/adaptors/testing.d.cts.map +1 -1
  96. package/dist/adaptors/testing.d.mts +325 -54
  97. package/dist/adaptors/testing.d.mts.map +1 -1
  98. package/dist/adaptors/testing.mjs +676 -70
  99. package/dist/adaptors/testing.mjs.map +1 -1
  100. package/dist/auth-CIFXNuDk.d.cts +194 -0
  101. package/dist/auth-CIFXNuDk.d.cts.map +1 -0
  102. package/dist/auth-CJ9Ff6Lu.d.mts +194 -0
  103. package/dist/auth-CJ9Ff6Lu.d.mts.map +1 -0
  104. package/dist/auth.cjs +172 -31
  105. package/dist/auth.cjs.map +1 -1
  106. package/dist/auth.d.cts +2 -108
  107. package/dist/auth.d.mts +2 -108
  108. package/dist/auth.mjs +161 -24
  109. package/dist/auth.mjs.map +1 -1
  110. package/dist/{cache-BrRz3fEB.d.mts → cache-CXh6GIgb.d.mts} +3 -6
  111. package/dist/cache-CXh6GIgb.d.mts.map +1 -0
  112. package/dist/{cache-BtZY_tHe.d.cts → cache-DnGDGly3.d.cts} +3 -6
  113. package/dist/cache-DnGDGly3.d.cts.map +1 -0
  114. package/dist/cache.cjs +68 -2
  115. package/dist/cache.cjs.map +1 -0
  116. package/dist/cache.d.cts +1 -2
  117. package/dist/cache.d.mts +1 -2
  118. package/dist/cache.mjs +67 -2
  119. package/dist/cache.mjs.map +1 -0
  120. package/dist/cipher-C1lEFX63.mjs +225 -0
  121. package/dist/cipher-C1lEFX63.mjs.map +1 -0
  122. package/dist/cipher-CVxfwLjk.cjs +332 -0
  123. package/dist/cipher-CVxfwLjk.cjs.map +1 -0
  124. package/dist/{clone-DblgEZZa.mjs → clone-EKNovYHu.mjs} +3 -3
  125. package/dist/clone-EKNovYHu.mjs.map +1 -0
  126. package/dist/{clone-Dy0cR2SZ.cjs → clone-UGJpvQnL.cjs} +7 -8
  127. package/dist/clone-UGJpvQnL.cjs.map +1 -0
  128. package/dist/{construct-interface-D9d4Gm4p.d.cts → construct-interface-B1AfqRl4.d.cts} +42 -11
  129. package/dist/construct-interface-B1AfqRl4.d.cts.map +1 -0
  130. package/dist/{construct-interface-g5GM5pwR.d.mts → construct-interface-DluK3_da.d.mts} +42 -11
  131. package/dist/construct-interface-DluK3_da.d.mts.map +1 -0
  132. package/dist/construct-interface.cjs +113 -7
  133. package/dist/construct-interface.cjs.map +1 -0
  134. package/dist/construct-interface.d.cts +2 -2
  135. package/dist/construct-interface.d.mts +2 -2
  136. package/dist/construct-interface.mjs +106 -2
  137. package/dist/construct-interface.mjs.map +1 -0
  138. package/dist/credential.cjs +63 -16
  139. package/dist/credential.cjs.map +1 -1
  140. package/dist/credential.d.cts +16 -9
  141. package/dist/credential.d.cts.map +1 -1
  142. package/dist/credential.d.mts +16 -9
  143. package/dist/credential.d.mts.map +1 -1
  144. package/dist/credential.mjs +58 -12
  145. package/dist/credential.mjs.map +1 -1
  146. package/dist/crons/index.cjs +105 -7
  147. package/dist/crons/index.cjs.map +1 -1
  148. package/dist/crons/index.d.cts +40 -11
  149. package/dist/crons/index.d.cts.map +1 -1
  150. package/dist/crons/index.d.mts +40 -11
  151. package/dist/crons/index.d.mts.map +1 -1
  152. package/dist/crons/index.mjs +103 -8
  153. package/dist/crons/index.mjs.map +1 -1
  154. package/dist/database/kysely.cjs +4 -181
  155. package/dist/database/kysely.d.cts +2 -152
  156. package/dist/database/kysely.d.mts +2 -152
  157. package/dist/database/kysely.mjs +2 -180
  158. package/dist/email.cjs +25 -12
  159. package/dist/email.cjs.map +1 -1
  160. package/dist/email.d.cts +3 -7
  161. package/dist/email.d.cts.map +1 -1
  162. package/dist/email.d.mts +3 -7
  163. package/dist/email.d.mts.map +1 -1
  164. package/dist/email.mjs +16 -3
  165. package/dist/email.mjs.map +1 -1
  166. package/dist/encryption.cjs +96 -0
  167. package/dist/encryption.cjs.map +1 -0
  168. package/dist/encryption.d.cts +117 -0
  169. package/dist/encryption.d.cts.map +1 -0
  170. package/dist/encryption.d.mts +117 -0
  171. package/dist/encryption.d.mts.map +1 -0
  172. package/dist/encryption.mjs +83 -0
  173. package/dist/encryption.mjs.map +1 -0
  174. package/dist/endpoints/index.cjs +8 -10
  175. package/dist/endpoints/index.d.cts +51 -7
  176. package/dist/endpoints/index.d.cts.map +1 -0
  177. package/dist/endpoints/index.d.mts +51 -7
  178. package/dist/endpoints/index.d.mts.map +1 -0
  179. package/dist/endpoints/index.mjs +6 -10
  180. package/dist/external-api-CWY9orcO.d.mts +86 -0
  181. package/dist/external-api-CWY9orcO.d.mts.map +1 -0
  182. package/dist/external-api-D-5WB-sr.d.cts +86 -0
  183. package/dist/external-api-D-5WB-sr.d.cts.map +1 -0
  184. package/dist/external-api.cjs +124 -0
  185. package/dist/external-api.cjs.map +1 -0
  186. package/dist/external-api.d.cts +2 -0
  187. package/dist/external-api.d.mts +2 -0
  188. package/dist/external-api.mjs +121 -0
  189. package/dist/external-api.mjs.map +1 -0
  190. package/dist/file-server.cjs +42 -10
  191. package/dist/file-server.cjs.map +1 -1
  192. package/dist/file-server.d.cts +6 -10
  193. package/dist/file-server.d.cts.map +1 -1
  194. package/dist/file-server.d.mts +6 -10
  195. package/dist/file-server.d.mts.map +1 -1
  196. package/dist/file-server.mjs +34 -2
  197. package/dist/file-server.mjs.map +1 -1
  198. package/dist/functions/index.cjs +3 -6
  199. package/dist/functions/index.d.cts +3 -4
  200. package/dist/functions/index.d.mts +3 -4
  201. package/dist/functions/index.mjs +2 -6
  202. package/dist/{functions-i_la-N5r.cjs → functions-CbP5ZKma.cjs} +414 -264
  203. package/dist/functions-CbP5ZKma.cjs.map +1 -0
  204. package/dist/{functions-14lpEFL4.mjs → functions-Di6n5ltG.mjs} +376 -238
  205. package/dist/{functions-14lpEFL4.mjs.map → functions-Di6n5ltG.mjs.map} +1 -1
  206. package/dist/index-BuzRvKOQ.d.cts +115 -0
  207. package/dist/index-BuzRvKOQ.d.cts.map +1 -0
  208. package/dist/index-CTkKOer4.d.mts +115 -0
  209. package/dist/index-CTkKOer4.d.mts.map +1 -0
  210. package/dist/index-CeEtxDmK.d.cts +79 -0
  211. package/dist/index-CeEtxDmK.d.cts.map +1 -0
  212. package/dist/index-CeEtxDmK.d.mts +79 -0
  213. package/dist/index-CeEtxDmK.d.mts.map +1 -0
  214. package/dist/index.cjs +6 -3
  215. package/dist/index.d.cts +26 -4
  216. package/dist/index.d.cts.map +1 -0
  217. package/dist/index.d.mts +26 -4
  218. package/dist/index.d.mts.map +1 -0
  219. package/dist/index.mjs +3 -3
  220. package/dist/kms-B-Hm3d5r.cjs +85 -0
  221. package/dist/kms-B-Hm3d5r.cjs.map +1 -0
  222. package/dist/kms-BdUlMJEZ.mjs +85 -0
  223. package/dist/kms-BdUlMJEZ.mjs.map +1 -0
  224. package/dist/kysely-BEm5sDlU.d.cts +173 -0
  225. package/dist/kysely-BEm5sDlU.d.cts.map +1 -0
  226. package/dist/kysely-BRzzawr2.cjs +301 -0
  227. package/dist/kysely-BRzzawr2.cjs.map +1 -0
  228. package/dist/kysely-BYfM6Zby.mjs +288 -0
  229. package/dist/kysely-BYfM6Zby.mjs.map +1 -0
  230. package/dist/kysely-CjuvdXEV.d.mts +173 -0
  231. package/dist/kysely-CjuvdXEV.d.mts.map +1 -0
  232. package/dist/{lazyAccessors-BoJN3SMd.mjs → lazyAccessors-CFanua0O.mjs} +20 -60
  233. package/dist/lazyAccessors-CFanua0O.mjs.map +1 -0
  234. package/dist/{lazyAccessors-e3j2oE2m.cjs → lazyAccessors-hJKGv8Ay.cjs} +60 -113
  235. package/dist/lazyAccessors-hJKGv8Ay.cjs.map +1 -0
  236. package/dist/mobile-app.cjs +73 -0
  237. package/dist/mobile-app.cjs.map +1 -0
  238. package/dist/mobile-app.d.cts +61 -0
  239. package/dist/mobile-app.d.cts.map +1 -0
  240. package/dist/mobile-app.d.mts +61 -0
  241. package/dist/mobile-app.d.mts.map +1 -0
  242. package/dist/mobile-app.mjs +72 -0
  243. package/dist/mobile-app.mjs.map +1 -0
  244. package/dist/object-storage.cjs +18 -10
  245. package/dist/object-storage.cjs.map +1 -1
  246. package/dist/object-storage.d.cts +3 -7
  247. package/dist/object-storage.d.cts.map +1 -1
  248. package/dist/object-storage.d.mts +3 -7
  249. package/dist/object-storage.d.mts.map +1 -1
  250. package/dist/object-storage.mjs +11 -3
  251. package/dist/object-storage.mjs.map +1 -1
  252. package/dist/{processAudits-Dmts9H_b.mjs → processAudits-BpRlPQMW.mjs} +16 -19
  253. package/dist/processAudits-BpRlPQMW.mjs.map +1 -0
  254. package/dist/{processAudits-CGqttuXm.cjs → processAudits-D_2W5x8k.cjs} +26 -30
  255. package/dist/processAudits-D_2W5x8k.cjs.map +1 -0
  256. package/dist/queue/index.cjs +6 -189
  257. package/dist/queue/index.d.cts +3 -60
  258. package/dist/queue/index.d.mts +3 -60
  259. package/dist/queue/index.mjs +3 -186
  260. package/dist/rest-api.cjs +88 -63
  261. package/dist/rest-api.cjs.map +1 -1
  262. package/dist/rest-api.d.cts +68 -61
  263. package/dist/rest-api.d.cts.map +1 -1
  264. package/dist/rest-api.d.mts +68 -61
  265. package/dist/rest-api.d.mts.map +1 -1
  266. package/dist/rest-api.mjs +80 -55
  267. package/dist/rest-api.mjs.map +1 -1
  268. package/dist/{chunk-DWy1uDak.cjs → rolldown-runtime-y5ARvAq5.cjs} +14 -18
  269. package/dist/runSubscriber-BRp9a_qi.cjs +126 -0
  270. package/dist/runSubscriber-BRp9a_qi.cjs.map +1 -0
  271. package/dist/runSubscriber-BYEY_bfA.mjs +109 -0
  272. package/dist/runSubscriber-BYEY_bfA.mjs.map +1 -0
  273. package/dist/shutdown-BMJmAhSt.cjs +38 -0
  274. package/dist/shutdown-BMJmAhSt.cjs.map +1 -0
  275. package/dist/shutdown-C7xa8x9S.mjs +27 -0
  276. package/dist/shutdown-C7xa8x9S.mjs.map +1 -0
  277. package/dist/site.cjs +34 -9
  278. package/dist/site.cjs.map +1 -1
  279. package/dist/site.d.cts +17 -22
  280. package/dist/site.d.cts.map +1 -1
  281. package/dist/site.d.mts +17 -22
  282. package/dist/site.d.mts.map +1 -1
  283. package/dist/site.mjs +30 -5
  284. package/dist/site.mjs.map +1 -1
  285. package/dist/subscribers/index.cjs +111 -6
  286. package/dist/subscribers/index.cjs.map +1 -0
  287. package/dist/subscribers/index.d.cts +50 -6
  288. package/dist/subscribers/index.d.cts.map +1 -0
  289. package/dist/subscribers/index.d.mts +50 -6
  290. package/dist/subscribers/index.d.mts.map +1 -0
  291. package/dist/subscribers/index.mjs +108 -5
  292. package/dist/subscribers/index.mjs.map +1 -0
  293. package/dist/surfaceEnv-CNimK76p.cjs +56 -0
  294. package/dist/surfaceEnv-CNimK76p.cjs.map +1 -0
  295. package/dist/surfaceEnv-wMT5QzgZ.mjs +45 -0
  296. package/dist/surfaceEnv-wMT5QzgZ.mjs.map +1 -0
  297. package/dist/{telemetry-C3L0iS28.d.cts → telemetry-DGcFlVpB.d.cts} +2 -5
  298. package/dist/telemetry-DGcFlVpB.d.cts.map +1 -0
  299. package/dist/{telemetry-D7bVFLGi.d.mts → telemetry-DGcFlVpB.d.mts} +2 -5
  300. package/dist/telemetry-DGcFlVpB.d.mts.map +1 -0
  301. package/dist/topic/index.cjs +3 -137
  302. package/dist/topic/index.d.cts +2 -4
  303. package/dist/topic/index.d.mts +2 -4
  304. package/dist/topic/index.mjs +2 -134
  305. package/dist/{types-BlAkSuGI.d.cts → types-DMuSQeLL.d.cts} +3 -5
  306. package/dist/types-DMuSQeLL.d.cts.map +1 -0
  307. package/dist/{types-aKksMEWL.d.mts → types-DMuSQeLL.d.mts} +3 -5
  308. package/dist/types-DMuSQeLL.d.mts.map +1 -0
  309. package/dist/types.d.cts +1 -1
  310. package/dist/types.d.mts +1 -1
  311. package/dist/types.mjs +1 -0
  312. package/dist/worker.cjs +58 -34
  313. package/dist/worker.cjs.map +1 -1
  314. package/dist/worker.d.cts +63 -45
  315. package/dist/worker.d.cts.map +1 -1
  316. package/dist/worker.d.mts +63 -44
  317. package/dist/worker.d.mts.map +1 -1
  318. package/dist/worker.mjs +53 -29
  319. package/dist/worker.mjs.map +1 -1
  320. package/package.json +82 -41
  321. package/dist/Construct-BD5neF7w.mjs.map +0 -1
  322. package/dist/Construct-C0ijr2qp.d.cts +0 -117
  323. package/dist/Construct-C0ijr2qp.d.cts.map +0 -1
  324. package/dist/Construct-Ct8nalEi.d.mts +0 -117
  325. package/dist/Construct-Ct8nalEi.d.mts.map +0 -1
  326. package/dist/Construct-CyS3RpTL.cjs.map +0 -1
  327. package/dist/Cron-DmQ8vQ4b.d.cts.map +0 -1
  328. package/dist/Cron-dh4rUgib.d.mts.map +0 -1
  329. package/dist/CronBuilder-BquXDbDI.d.cts +0 -44
  330. package/dist/CronBuilder-BquXDbDI.d.cts.map +0 -1
  331. package/dist/CronBuilder-CGgY2080.d.mts +0 -44
  332. package/dist/CronBuilder-CGgY2080.d.mts.map +0 -1
  333. package/dist/CronBuilder-CYKT5RiO.mjs.map +0 -1
  334. package/dist/CronBuilder-Da0C0edR.cjs.map +0 -1
  335. package/dist/Endpoint-BjWKinFA.d.mts.map +0 -1
  336. package/dist/Endpoint-DCQPMdUX.mjs.map +0 -1
  337. package/dist/Endpoint-DcWXE-SZ.cjs.map +0 -1
  338. package/dist/Endpoint-dav89W6-.d.cts.map +0 -1
  339. package/dist/EndpointFactory-CdWB7wPw.cjs.map +0 -1
  340. package/dist/EndpointFactory-CjV8F_lJ.mjs.map +0 -1
  341. package/dist/HonoEndpointAdaptor-DtL9j19R.cjs.map +0 -1
  342. package/dist/HonoEndpointAdaptor-P1ahhZHu.mjs.map +0 -1
  343. package/dist/Queue-D7ZuwBhy.d.cts.map +0 -1
  344. package/dist/Queue-gVGfi2Yk.d.mts.map +0 -1
  345. package/dist/Subscriber-2mEi0ImH.d.cts.map +0 -1
  346. package/dist/Subscriber-xTJ9ayPN.d.mts.map +0 -1
  347. package/dist/SubscriberBuilder-4OPehf2R.cjs.map +0 -1
  348. package/dist/SubscriberBuilder-BjkbeT9l.mjs.map +0 -1
  349. package/dist/SubscriberBuilder-Dptmo-1A.d.mts +0 -62
  350. package/dist/SubscriberBuilder-Dptmo-1A.d.mts.map +0 -1
  351. package/dist/SubscriberBuilder-waNhzjSM.d.cts +0 -62
  352. package/dist/SubscriberBuilder-waNhzjSM.d.cts.map +0 -1
  353. package/dist/Topic-19QeHBIR.d.cts +0 -91
  354. package/dist/Topic-19QeHBIR.d.cts.map +0 -1
  355. package/dist/Topic-DuFeqkBh.d.mts +0 -91
  356. package/dist/Topic-DuFeqkBh.d.mts.map +0 -1
  357. package/dist/auth.d.cts.map +0 -1
  358. package/dist/auth.d.mts.map +0 -1
  359. package/dist/cache-0ANvRQnD.mjs +0 -51
  360. package/dist/cache-0ANvRQnD.mjs.map +0 -1
  361. package/dist/cache-3WSvAulx.cjs +0 -57
  362. package/dist/cache-3WSvAulx.cjs.map +0 -1
  363. package/dist/cache-BrRz3fEB.d.mts.map +0 -1
  364. package/dist/cache-BtZY_tHe.d.cts.map +0 -1
  365. package/dist/clone-DblgEZZa.mjs.map +0 -1
  366. package/dist/clone-Dy0cR2SZ.cjs.map +0 -1
  367. package/dist/construct-interface-BfjcOD_E.cjs +0 -117
  368. package/dist/construct-interface-BfjcOD_E.cjs.map +0 -1
  369. package/dist/construct-interface-D9d4Gm4p.d.cts.map +0 -1
  370. package/dist/construct-interface-Z4CpS8tK.mjs +0 -81
  371. package/dist/construct-interface-Z4CpS8tK.mjs.map +0 -1
  372. package/dist/construct-interface-g5GM5pwR.d.mts.map +0 -1
  373. package/dist/database/kysely.cjs.map +0 -1
  374. package/dist/database/kysely.d.cts.map +0 -1
  375. package/dist/database/kysely.d.mts.map +0 -1
  376. package/dist/database/kysely.mjs.map +0 -1
  377. package/dist/functions-i_la-N5r.cjs.map +0 -1
  378. package/dist/index-Bd5FqCoe.d.cts.map +0 -1
  379. package/dist/index-BknhM6Ux.d.mts +0 -31
  380. package/dist/index-BknhM6Ux.d.mts.map +0 -1
  381. package/dist/index-CBSfrowv.d.cts +0 -31
  382. package/dist/index-CBSfrowv.d.cts.map +0 -1
  383. package/dist/index-D24Xm79M.d.cts +0 -171
  384. package/dist/index-D24Xm79M.d.cts.map +0 -1
  385. package/dist/index-_ajboYxK.d.mts +0 -171
  386. package/dist/index-_ajboYxK.d.mts.map +0 -1
  387. package/dist/index-lAO9egTb.d.mts.map +0 -1
  388. package/dist/lazyAccessors-BoJN3SMd.mjs.map +0 -1
  389. package/dist/lazyAccessors-e3j2oE2m.cjs.map +0 -1
  390. package/dist/processAudits-CGqttuXm.cjs.map +0 -1
  391. package/dist/processAudits-Dmts9H_b.mjs.map +0 -1
  392. package/dist/queue/index.cjs.map +0 -1
  393. package/dist/queue/index.d.cts.map +0 -1
  394. package/dist/queue/index.d.mts.map +0 -1
  395. package/dist/queue/index.mjs.map +0 -1
  396. package/dist/surfaceEnv-BFXEms2f.cjs +0 -39
  397. package/dist/surfaceEnv-BFXEms2f.cjs.map +0 -1
  398. package/dist/surfaceEnv-C3Ktahea.mjs +0 -27
  399. package/dist/surfaceEnv-C3Ktahea.mjs.map +0 -1
  400. package/dist/telemetry-C3L0iS28.d.cts.map +0 -1
  401. package/dist/telemetry-D7bVFLGi.d.mts.map +0 -1
  402. package/dist/topic/index.cjs.map +0 -1
  403. package/dist/topic/index.mjs.map +0 -1
  404. package/dist/types-BlAkSuGI.d.cts.map +0 -1
  405. package/dist/types-aKksMEWL.d.mts.map +0 -1
@@ -1,25 +1,33 @@
1
- import "../Construct-BD5neF7w.mjs";
2
- import "../construct-interface-Z4CpS8tK.mjs";
3
- import { FunctionBuilder } from "../functions-14lpEFL4.mjs";
4
- import "../clone-DblgEZZa.mjs";
5
- import { Endpoint, ResponseBuilder } from "../Endpoint-DCQPMdUX.mjs";
6
- import { createCookieHeaderAccessor, createObjectHeaders, publishConstructEvents, publishEvents } from "../lazyAccessors-BoJN3SMd.mjs";
7
- import { executeWithAuditTransaction } from "../processAudits-Dmts9H_b.mjs";
8
- import { HonoEndpoint } from "../HonoEndpointAdaptor-P1ahhZHu.mjs";
1
+ import { isConsumable } from "../construct-interface.mjs";
2
+ import { BetterAuth } from "../auth.mjs";
3
+ import { a as publishEvents, i as publishConstructEvents, t as FunctionBuilder } from "../functions-Di6n5ltG.mjs";
4
+ import { n as ResponseBuilder, t as Endpoint } from "../Endpoint-CMWWrQ7u.mjs";
5
+ import { t as Queue } from "../Queue-hwPN-t31.mjs";
6
+ import { Email } from "../email.mjs";
7
+ import { t as KyselyDatabase } from "../kysely-BYfM6Zby.mjs";
8
+ import { c as createObjectHeaders, r as createCookieHeaderAccessor } from "../lazyAccessors-CFanua0O.mjs";
9
+ import { t as Topic } from "../Topic-hPffOsot.mjs";
10
+ import { t as HonoEndpoint } from "../HonoEndpointAdaptor-vY4JKG8i.mjs";
11
+ import { n as executeWithAuditTransaction } from "../processAudits-BpRlPQMW.mjs";
12
+ import { provideKey } from "@geekmidas/manifest";
13
+ import { randomUUID } from "node:crypto";
9
14
  import { ForbiddenError } from "@geekmidas/errors";
10
15
  import { EnvironmentParser } from "@geekmidas/envkit";
11
- import { ServiceDiscovery, runWithRequestContext } from "@geekmidas/services";
12
- import { DefaultAuditor } from "@geekmidas/audit";
16
+ import { ServiceDiscovery, runWithRequestContext, serviceContext } from "@geekmidas/services";
13
17
  import { Hono } from "hono";
18
+ import { DefaultAuditor } from "@geekmidas/audit";
19
+ import { TEST_CONTEXT_HEADER, currentTestContext, installContextFetch, runAsServer, runInTestContext, testContextOf } from "@geekmidas/testkit/context";
14
20
  import { http } from "msw";
15
-
21
+ import { Browser } from "@geekmidas/testkit/browser";
22
+ import { faker } from "@geekmidas/testkit/faker";
23
+ import { createMailbox } from "@geekmidas/testkit/mailbox";
24
+ import { TransactionRegistry } from "@geekmidas/testkit/transactions";
25
+ import { setupServer } from "msw/node";
26
+ import { afterAll, beforeAll, test } from "vitest";
27
+ import { existsSync, readFileSync } from "node:fs";
28
+ import tls from "node:tls";
29
+ import { fileURLToPath } from "node:url";
16
30
  //#region src/endpoints/MswEndpointAdaptor.ts
17
- /**
18
- * Header used to identify which test context a request belongs to.
19
- * Each concurrent test registers its own context (services, db transaction, etc.)
20
- * and the MSW handler looks it up by this header value.
21
- */
22
- const TEST_CONTEXT_HEADER = "x-test-context-id";
23
31
  const MSW_HTTP_METHODS = [
24
32
  "get",
25
33
  "post",
@@ -67,7 +75,6 @@ function createMswHandlers(endpoints, options) {
67
75
  break;
68
76
  }
69
77
  }
70
- if (ctxOptions.publisher) serviceDefs.push(ctxOptions.publisher);
71
78
  if (ctxOptions.auditorStorage !== void 0) {
72
79
  for (const endpoint of endpoints) if (endpoint.auditorStorageService) {
73
80
  serviceDefs.push({
@@ -111,7 +118,6 @@ function createMswHandlers(endpoints, options) {
111
118
  registerContext
112
119
  };
113
120
  }
114
-
115
121
  //#endregion
116
122
  //#region src/endpoints/TestEndpointAdaptor.ts
117
123
  /**
@@ -131,6 +137,8 @@ function serializeCookie(name, value, options) {
131
137
  return cookieString;
132
138
  }
133
139
  var TestEndpointAdaptor = class TestEndpointAdaptor {
140
+ endpoint;
141
+ serviceDiscovery;
134
142
  static getDefaultServiceDiscover(_endpoint) {
135
143
  return ServiceDiscovery.getInstance(new EnvironmentParser({}));
136
144
  }
@@ -153,10 +161,12 @@ var TestEndpointAdaptor = class TestEndpointAdaptor {
153
161
  method: this.endpoint.method
154
162
  });
155
163
  const rawDb = ctx.database;
164
+ const operation = `${this.endpoint.method} ${this.endpoint.route}`;
156
165
  return runWithRequestContext({
157
166
  logger,
158
167
  requestId,
159
- startTime
168
+ startTime,
169
+ operation
160
170
  }, async () => {
161
171
  const session = await this.endpoint.getSession({
162
172
  logger,
@@ -165,7 +175,7 @@ var TestEndpointAdaptor = class TestEndpointAdaptor {
165
175
  cookie,
166
176
  ...rawDb !== void 0 && { db: rawDb }
167
177
  });
168
- const isAuthorized = await this.endpoint.authorize({
178
+ if (!await this.endpoint.authorize({
169
179
  header,
170
180
  cookie,
171
181
  services: ctx.services,
@@ -175,8 +185,7 @@ var TestEndpointAdaptor = class TestEndpointAdaptor {
175
185
  body,
176
186
  query,
177
187
  params
178
- });
179
- if (!isAuthorized) {
188
+ })) {
180
189
  logger.warn("Forbidden access attempt");
181
190
  throw new ForbiddenError("Forbidden access to the endpoint", "You do not have permission to access this resource.");
182
191
  }
@@ -198,24 +207,22 @@ var TestEndpointAdaptor = class TestEndpointAdaptor {
198
207
  } catch (error) {
199
208
  logger.error(error, "Failed to extract actor for audits");
200
209
  }
201
- const auditor = new DefaultAuditor({
202
- actor,
203
- storage: auditorStorage,
204
- metadata: {
205
- endpoint: this.endpoint.route,
206
- method: this.endpoint.method
207
- }
208
- });
209
210
  auditContext = {
210
- auditor,
211
+ auditor: new DefaultAuditor({
212
+ actor,
213
+ storage: auditorStorage,
214
+ metadata: {
215
+ endpoint: this.endpoint.route,
216
+ method: this.endpoint.method
217
+ }
218
+ }),
211
219
  storage: auditorStorage
212
220
  };
213
221
  }
214
222
  const audits = this.endpoint.audits;
215
223
  if (!auditContext && audits?.length) logger.warn("No auditor storage service available");
216
- const result = await executeWithAuditTransaction(auditContext, async (auditor) => {
217
- const trx = auditor?.getTransaction?.();
218
- const db = trx ?? rawDb;
224
+ const { output, metadata } = await executeWithAuditTransaction(auditContext, async (auditor) => {
225
+ const db = auditor?.getTransaction?.() ?? rawDb;
219
226
  const responseBuilder = new ResponseBuilder();
220
227
  const response = await this.endpoint.handler({
221
228
  body,
@@ -230,36 +237,33 @@ var TestEndpointAdaptor = class TestEndpointAdaptor {
230
237
  db
231
238
  }, responseBuilder);
232
239
  let data = response;
233
- let metadata$1 = responseBuilder.getMetadata();
240
+ let metadata = responseBuilder.getMetadata();
234
241
  if (Endpoint.hasMetadata(response)) {
235
242
  data = response.data;
236
- metadata$1 = response.metadata;
243
+ metadata = response.metadata;
237
244
  }
238
- const output$1 = await this.endpoint.parseOutput(data);
239
245
  return {
240
- output: output$1,
241
- metadata: metadata$1,
246
+ output: await this.endpoint.parseOutput(data),
247
+ metadata,
242
248
  responseBuilder
243
249
  };
244
- }, async (result$1, auditor) => {
250
+ }, async (result, auditor) => {
245
251
  if (!audits?.length) return;
246
252
  for (const audit of audits) {
247
- if (audit.when && !audit.when(result$1.output)) continue;
248
- const payload = audit.payload(result$1.output);
249
- const entityId = audit.entityId?.(result$1.output);
253
+ if (audit.when && !audit.when(result.output)) continue;
254
+ const payload = audit.payload(result.output);
255
+ const entityId = audit.entityId?.(result.output);
250
256
  auditor.audit(audit.type, payload, {
251
257
  table: audit.table,
252
258
  entityId
253
259
  });
254
260
  }
255
261
  }, { db: rawDb });
256
- const { output, metadata } = result;
257
- ctx.publisher && await this.serviceDiscovery.register([ctx.publisher]);
258
- await publishConstructEvents(this.endpoint, output, this.serviceDiscovery);
262
+ await publishConstructEvents(this.endpoint, output, this.serviceDiscovery, this.endpoint.logger, ctx.services);
259
263
  const headers = { ...metadata.headers || {} };
260
264
  if (metadata.cookies && metadata.cookies.size > 0) {
261
265
  const setCookieValues = [];
262
- for (const [name, cookie$1] of metadata.cookies.entries()) setCookieValues.push(serializeCookie(name, cookie$1.value, cookie$1.options));
266
+ for (const [name, cookie] of metadata.cookies.entries()) setCookieValues.push(serializeCookie(name, cookie.value, cookie.options));
263
267
  headers["set-cookie"] = setCookieValues;
264
268
  }
265
269
  return {
@@ -270,14 +274,14 @@ var TestEndpointAdaptor = class TestEndpointAdaptor {
270
274
  });
271
275
  }
272
276
  async request(ctx) {
273
- const response = await this.fullRequest(ctx);
274
- return response.body;
277
+ return (await this.fullRequest(ctx)).body;
275
278
  }
276
279
  };
277
-
278
280
  //#endregion
279
281
  //#region src/functions/TestFunctionAdaptor.ts
280
282
  var TestFunctionAdaptor = class TestFunctionAdaptor {
283
+ fn;
284
+ serviceDiscovery;
281
285
  static getDefaultServiceDiscovery(_fn) {
282
286
  return ServiceDiscovery.getInstance(new EnvironmentParser({}));
283
287
  }
@@ -293,15 +297,11 @@ var TestFunctionAdaptor = class TestFunctionAdaptor {
293
297
  else services = await this.serviceDiscovery.register(this.fn.services);
294
298
  let db;
295
299
  if ("db" in ctx && ctx.db !== void 0) db = ctx.db;
296
- else if (this.fn.databaseService) {
297
- const dbServices = await this.serviceDiscovery.register([this.fn.databaseService]);
298
- db = dbServices[this.fn.databaseService.serviceName];
299
- }
300
+ else if (this.fn.databaseService) db = (await this.serviceDiscovery.register([this.fn.databaseService]))[this.fn.databaseService.serviceName];
300
301
  let auditor;
301
302
  if ("auditor" in ctx && ctx.auditor !== void 0) auditor = ctx.auditor;
302
303
  else if (this.fn.auditorStorageService) {
303
- const auditServices = await this.serviceDiscovery.register([this.fn.auditorStorageService]);
304
- const storage = auditServices[this.fn.auditorStorageService.serviceName];
304
+ const storage = (await this.serviceDiscovery.register([this.fn.auditorStorageService]))[this.fn.auditorStorageService.serviceName];
305
305
  auditor = new DefaultAuditor({
306
306
  actor: {
307
307
  id: "system",
@@ -315,11 +315,10 @@ var TestFunctionAdaptor = class TestFunctionAdaptor {
315
315
  });
316
316
  }
317
317
  const requestId = `test-${Date.now()}`;
318
- const startTime = Date.now();
319
318
  return runWithRequestContext({
320
319
  logger,
321
320
  requestId,
322
- startTime
321
+ startTime: Date.now()
323
322
  }, async () => {
324
323
  const response = await this.fn.fn({
325
324
  input: parsedInput,
@@ -336,24 +335,26 @@ var TestFunctionAdaptor = class TestFunctionAdaptor {
336
335
  await auditor.flush();
337
336
  }
338
337
  }
339
- await publishEvents(logger, this.serviceDiscovery, this.fn.events, output, this.fn.publisherService);
338
+ await publishEvents(logger, this.serviceDiscovery, this.fn.events, output, services);
340
339
  return output;
341
340
  });
342
341
  }
343
342
  };
344
-
345
343
  //#endregion
346
344
  //#region src/queue/TestQueueAdaptor.ts
347
345
  /**
348
346
  * In-memory test driver for a {@link Queue} worker. Hand it a batch of messages
349
347
  * and it registers the queue's services, runs the handler in a request context,
350
- * and returns the handler result — no SQS/pg-boss required.
348
+ * and returns the handler result — no SQS/pg-boss required. A queue with a
349
+ * database gets `db` registered from it, or the one the request passes.
351
350
  *
352
351
  * @example
353
352
  * const adapter = new TestQueueAdaptor(ordersQueue);
354
353
  * await adapter.invoke({ messages: [{ orderId: '123' }] });
355
354
  */
356
355
  var TestQueueAdaptor = class TestQueueAdaptor {
356
+ queue;
357
+ serviceDiscovery;
357
358
  static getDefaultServiceDiscovery() {
358
359
  return ServiceDiscovery.getInstance(new EnvironmentParser({}));
359
360
  }
@@ -364,23 +365,33 @@ var TestQueueAdaptor = class TestQueueAdaptor {
364
365
  async invoke(request) {
365
366
  const logger = this.queue.logger.child({ test: true });
366
367
  const services = request.services ?? await this.serviceDiscovery.register(this.queue.services);
368
+ const db = request.db !== void 0 ? request.db : await this.getDatabase();
367
369
  const requestId = `test-${Date.now()}`;
368
370
  const startTime = Date.now();
371
+ const operation = `queue ${this.queue.name}`;
369
372
  return runWithRequestContext({
370
373
  logger,
371
374
  requestId,
372
- startTime
375
+ startTime,
376
+ operation
373
377
  }, () => this.queue.handler({
374
378
  messages: request.messages,
375
379
  services,
376
- logger
380
+ logger,
381
+ db
377
382
  }));
378
383
  }
384
+ async getDatabase() {
385
+ const service = this.queue.databaseService;
386
+ if (!service) return void 0;
387
+ return (await this.serviceDiscovery.register([service]))[service.serviceName];
388
+ }
379
389
  };
380
-
381
390
  //#endregion
382
391
  //#region src/subscribers/TestSubscriberAdaptor.ts
383
392
  var TestSubscriberAdaptor = class TestSubscriberAdaptor {
393
+ subscriber;
394
+ serviceDiscovery;
384
395
  static getDefaultServiceDiscovery() {
385
396
  return ServiceDiscovery.getInstance(new EnvironmentParser({}));
386
397
  }
@@ -393,19 +404,23 @@ var TestSubscriberAdaptor = class TestSubscriberAdaptor {
393
404
  let services;
394
405
  if (request.services) services = request.services;
395
406
  else services = await this.serviceDiscovery.register(this.subscriber.services);
407
+ const db = request.db !== void 0 ? request.db : await this.getDatabase();
396
408
  const filteredEvents = this.filterEvents(request.events);
397
409
  if (filteredEvents.length === 0) return { batchItemFailures: [] };
398
410
  const requestId = `test-${Date.now()}`;
399
411
  const startTime = Date.now();
412
+ const operation = `subscriber ${this.subscriber.topicName ?? "test"}`;
400
413
  return runWithRequestContext({
401
414
  logger,
402
415
  requestId,
403
- startTime
416
+ startTime,
417
+ operation
404
418
  }, async () => {
405
419
  const result = await this.subscriber.handler({
406
420
  events: filteredEvents,
407
421
  services,
408
- logger
422
+ logger,
423
+ db
409
424
  });
410
425
  let output = result;
411
426
  if (this.subscriber.outputSchema && result) {
@@ -413,16 +428,607 @@ var TestSubscriberAdaptor = class TestSubscriberAdaptor {
413
428
  if (validationResult.issues) throw new Error("Subscriber output validation failed");
414
429
  output = validationResult.value;
415
430
  }
416
- await publishEvents(logger, this.serviceDiscovery, this.subscriber.events, output, this.subscriber.publisherService);
417
431
  return output;
418
432
  });
419
433
  }
434
+ async getDatabase() {
435
+ const service = this.subscriber.databaseService;
436
+ if (!service) return void 0;
437
+ return (await this.serviceDiscovery.register([service]))[service.serviceName];
438
+ }
420
439
  filterEvents(events) {
421
440
  if (!this.subscriber.subscribedEvents) return events;
422
441
  return events.filter((event) => this.subscriber.subscribedEvents.includes(event.type));
423
442
  }
424
443
  };
425
-
426
444
  //#endregion
427
- export { TEST_CONTEXT_HEADER, TestEndpointAdaptor, TestFunctionAdaptor, TestQueueAdaptor, TestSubscriberAdaptor, createMswHandlers };
445
+ //#region src/testing/manifest.ts
446
+ /**
447
+ * The test manifest: what `gkm test` knows about an app, written down for the
448
+ * suite it starts.
449
+ *
450
+ * `gkm test` discovers the constructs, reconciles the test stage and resolves
451
+ * its environment — then, until this existed, threw all of it away and left a
452
+ * test to declare it again by hand. The manifest keeps it: which construct and
453
+ * endpoint is exported where, and the environment the test stage resolved,
454
+ * under the keys the constructs themselves derive. A feature test is built from
455
+ * it, so nothing a test says can drift from what the app declares.
456
+ */
457
+ /** The environment variable `gkm test` names the manifest in. */
458
+ const TEST_MANIFEST_ENV = "GKM_TEST_MANIFEST";
459
+ /**
460
+ * Read a test manifest: from a path, a `file:` URL, or — given nothing — the
461
+ * one `gkm test` named in `GKM_TEST_MANIFEST`.
462
+ */
463
+ function loadTestManifest(from) {
464
+ const location = from ?? process.env["GKM_TEST_MANIFEST"];
465
+ if (!location) throw new NoTestManifest();
466
+ trustLocalEdge();
467
+ const path = location instanceof URL || location.startsWith("file:") ? fileURLToPath(location) : location;
468
+ return JSON.parse(readFileSync(path, "utf-8"));
469
+ }
470
+ let trusted = false;
471
+ /**
472
+ * Trust the local edge's certificate authority in this thread.
473
+ *
474
+ * `NODE_EXTRA_CA_CERTS` does it for a process started with it — which a
475
+ * suite started by `gkm test` is, and one started by plain `vitest` or an
476
+ * editor is not: its setup only learns the path once Vitest is running, and a
477
+ * worker *thread* shares that process and keeps a TLS store of its own. Every
478
+ * feature test loads the manifest, so this is the one place each worker passes
479
+ * through.
480
+ */
481
+ function trustLocalEdge() {
482
+ const certificate = process.env.NODE_EXTRA_CA_CERTS;
483
+ if (trusted || !certificate || !existsSync(certificate)) return;
484
+ trusted = true;
485
+ tls.setDefaultCACertificates([...tls.getCACertificates("default"), readFileSync(certificate, "utf-8")]);
486
+ }
487
+ /** A feature test ran without a manifest to build itself from. */
488
+ var NoTestManifest = class extends Error {
489
+ constructor() {
490
+ super(`No test manifest: run the suite with \`gkm test\`, or add \`globalSetup: ['@geekmidas/cli/vitest']\` to the root vitest config — either writes one and names it in ${TEST_MANIFEST_ENV}.`);
491
+ this.name = "NoTestManifest";
492
+ }
493
+ };
494
+ //#endregion
495
+ //#region src/testing/featureTest.ts
496
+ /**
497
+ * `featureTest`: an app, driven the way it runs deployed.
498
+ *
499
+ * A browser signs in and calls the API; the API calls the auth server; each
500
+ * over its URL, each database in its own transaction. Nothing runs as a server:
501
+ * every URL an app's constructs answer on is served in-process through MSW,
502
+ * from the real handler, for the test that made the request. Everything else
503
+ * with a real local equivalent — Postgres, Mailpit, MinIO — is used directly.
504
+ *
505
+ * It is built from the test manifest `gkm test` writes — the constructs and
506
+ * endpoints the app exports, and the environment the test stage resolved — so
507
+ * a test declares none of it. `gkm test` also generates the configured `it`
508
+ * and a `Browser` with a typed client per surface:
509
+ *
510
+ * ```ts
511
+ * import { it } from '#test';
512
+ *
513
+ * it('shows the signed-in user their profile', async ({ browser, mailbox }) => {
514
+ * await browser.auth.signIn.magicLink({ email: 'ada@shop.test' });
515
+ * await browser.visit((await mailbox('ada@shop.test').last()).link!);
516
+ * expect(await browser.api.get('/profile')).toMatchObject({ email: 'ada@shop.test' });
517
+ * });
518
+ * ```
519
+ */
520
+ /** Every test in flight in this process, by id. */
521
+ const contexts = /* @__PURE__ */ new Map();
522
+ /** Databases already resolving to test transactions — patched once each. */
523
+ const bound = /* @__PURE__ */ new WeakSet();
524
+ function featureTest(options = {}) {
525
+ const manifest = options.manifest ?? loadTestManifest();
526
+ const BrowserClass = options.browser ?? Browser;
527
+ let app;
528
+ let factoryDatabases = [];
529
+ let owned = [];
530
+ let network;
531
+ let restoreFetch = () => {};
532
+ beforeAll(async () => {
533
+ app = await load(manifest, options.modules ?? {});
534
+ owned = ownDatabases(app, manifest);
535
+ factoryDatabases = databasesFor(options.factories ?? {}, owned);
536
+ for (const database of app.databases) bindToTests(database);
537
+ network = setupServer(...surfaceHandlers(app.endpoints, manifest.env), ...app.auths.map((auth) => authHandler(auth, manifest.env, app.envParser)), ...Object.entries(options.fakes ?? {}).flatMap(([id, fake]) => fakeHandler(id, fake, manifest.env)));
538
+ network.listen({ onUnhandledRequest(request, print) {
539
+ if (isLocal(new URL(request.url))) return;
540
+ print.error();
541
+ } });
542
+ const restoreStamp = installContextFetch();
543
+ const stamped = globalThis.fetch;
544
+ globalThis.fetch = deliveringFetch(stamped, (id) => {
545
+ const state = contexts.get(id);
546
+ return state ? deliver(app, state, id) : Promise.resolve();
547
+ });
548
+ restoreFetch = () => {
549
+ globalThis.fetch = stamped;
550
+ restoreStamp();
551
+ };
552
+ });
553
+ afterAll(() => {
554
+ restoreFetch();
555
+ network?.close();
556
+ });
557
+ const run = (name, fn) => async () => {
558
+ const id = randomUUID();
559
+ faker.seed(seedOf(name));
560
+ const state = {
561
+ transactions: new TransactionRegistry(),
562
+ discovery: new ServiceDiscovery(app.envParser),
563
+ surfaces: /* @__PURE__ */ new Map(),
564
+ auth: /* @__PURE__ */ new Map(),
565
+ addresses: /* @__PURE__ */ new Set(),
566
+ published: /* @__PURE__ */ new Map(),
567
+ pending: [],
568
+ delivering: false
569
+ };
570
+ const readMail = app.readMail;
571
+ if (readMail) state.mailbox = (address) => {
572
+ state.addresses.add(address);
573
+ return readMail(address);
574
+ };
575
+ contexts.set(id, state);
576
+ await state.discovery.register(recorders(app.channels, state));
577
+ try {
578
+ await runInTestContext(id, async () => {
579
+ const browser = new BrowserClass();
580
+ const restore = browser.install();
581
+ try {
582
+ const transaction = (database) => state.transactions.get(database.id, urlOf(database, app.envParser), database.clientConfig);
583
+ const db = { get: (name) => {
584
+ const database = owned.find((candidate) => candidate.service.serviceName === name);
585
+ if (!database) throw new UnknownDatabase(name, owned.map((candidate) => candidate.service.serviceName));
586
+ return transaction(database);
587
+ } };
588
+ const built = /* @__PURE__ */ new Map();
589
+ await fn({
590
+ browser,
591
+ db,
592
+ factories: { get: (name) => {
593
+ const database = factoryDatabases.find(([candidate]) => candidate === name)?.[1];
594
+ if (!database) throw new UnknownFactory(name, factoryDatabases.map(([candidate]) => candidate));
595
+ let factory = built.get(name);
596
+ if (!factory) {
597
+ factory = transaction(database).then(options.factories[name]);
598
+ built.set(name, factory);
599
+ }
600
+ return factory;
601
+ } },
602
+ faker,
603
+ mailbox: (address) => {
604
+ if (!state.mailbox) throw new NoInbox();
605
+ return state.mailbox(address);
606
+ },
607
+ published: (channel) => [...state.published.get(channel.id) ?? []],
608
+ services: { get: (name) => resolveService(app, state, name) },
609
+ subscriber: (subscriber) => thenDeliver(new TestSubscriberAdaptor(subscriber, state.discovery), () => deliver(app, state, id)),
610
+ queue: (queue) => thenDeliver(new TestQueueAdaptor(queue, state.discovery), () => deliver(app, state, id))
611
+ });
612
+ } finally {
613
+ restore();
614
+ }
615
+ });
616
+ } finally {
617
+ contexts.delete(id);
618
+ await Promise.all([state.transactions.rollbackAll(), ...[...state.addresses].map((address) => app.readMail?.(address).clear())]);
619
+ }
620
+ };
621
+ const it = ((name, fn, timeout) => test(name, run(name, fn), timeout));
622
+ it.only = (name, fn, timeout) => test.only(name, run(name, fn), timeout);
623
+ it.skip = (name, fn, timeout) => test.skip(name, run(name, fn), timeout);
624
+ return it;
625
+ }
626
+ /**
627
+ * A test's faker seed, from its name: the same test draws the same data on
628
+ * every run, and two tests draw different data.
629
+ */
630
+ function seedOf(name) {
631
+ let hash = 0;
632
+ for (const char of name) hash = Math.imul(hash, 31) + char.charCodeAt(0) | 0;
633
+ return hash >>> 0;
634
+ }
635
+ /**
636
+ * Import what the manifest points at.
637
+ *
638
+ * The same modules the app runs, so a construct here *is* the app's construct —
639
+ * the one its endpoints were built from — never a copy declared again.
640
+ */
641
+ async function load(manifest, modules) {
642
+ const envParser = new EnvironmentParser({ ...manifest.env });
643
+ const imported = async ({ file, export: name }) => (modules[file] ?? await import(file))[name];
644
+ const constructs = await Promise.all(Object.values(manifest.constructs).map(({ source }) => imported(source)));
645
+ const endpoints = (await Promise.all(manifest.endpoints.map(({ source }) => imported(source)))).filter((value) => Endpoint.isEndpoint(value));
646
+ const subscribers = (await Promise.all((manifest.subscribers ?? []).map(async ({ source }) => ({
647
+ name: source.export,
648
+ subscriber: await imported(source)
649
+ })))).filter((entry) => entry.subscriber?.__IS_SUBSCRIBER__ === true);
650
+ const unique = (values) => [...new Set(values)];
651
+ const databases = unique(constructs.filter((value) => value instanceof KyselyDatabase));
652
+ const auths = unique(constructs.filter((value) => value instanceof BetterAuth));
653
+ const emails = unique(constructs.filter((value) => value instanceof Email));
654
+ const consumables = unique(constructs.filter(isConsumable));
655
+ const channels = unique(constructs.filter((value) => value instanceof Topic || value instanceof Queue));
656
+ const inbox = emails.map((email) => manifest.env[provideKey(email.id, "inboxUrl")]).find(Boolean);
657
+ return {
658
+ envParser,
659
+ endpoints,
660
+ databases,
661
+ auths,
662
+ emails,
663
+ channels,
664
+ consumables,
665
+ subscribers,
666
+ ...inbox ? { readMail: createMailbox({ inbox }) } : {}
667
+ };
668
+ }
669
+ /**
670
+ * A publisher that records rather than sends, under the name a topic or queue
671
+ * is injected by — `services.users` — which is also the one `.event(users, …)`
672
+ * publishes through.
673
+ */
674
+ function recorders(channels, state) {
675
+ return channels.map((channel) => {
676
+ const publisher = { async publish(messages) {
677
+ const sent = messages.map(({ type, payload }) => ({
678
+ type,
679
+ payload
680
+ }));
681
+ state.published.set(channel.id, [...state.published.get(channel.id) ?? [], ...sent]);
682
+ state.pending.push({
683
+ channel,
684
+ messages: sent
685
+ });
686
+ } };
687
+ return {
688
+ serviceName: channel.service.serviceName,
689
+ register: () => publisher
690
+ };
691
+ });
692
+ }
693
+ /**
694
+ * The databases a test is handed: the app's own. A schema tenant an auth server
695
+ * owns is reached through that server, as the app reaches it, and a reader is
696
+ * the same database through a read-only role — neither is another database to
697
+ * test against.
698
+ */
699
+ function ownDatabases(app, manifest) {
700
+ const owners = new Set(app.auths.map((auth) => auth.databaseId));
701
+ return app.databases.filter((database) => !owners.has(database.id) && manifest.constructs[database.id]?.kind !== "database-reader");
702
+ }
703
+ /** Each factory's database, found by the service name it is keyed by. */
704
+ function databasesFor(factories, databases) {
705
+ return Object.keys(factories).map((name) => {
706
+ const database = databases.find((candidate) => candidate.service.serviceName === name);
707
+ if (!database) throw new UnknownFactory(name, databases.map((candidate) => candidate.service.serviceName));
708
+ return [name, database];
709
+ });
710
+ }
711
+ /**
712
+ * Make a database resolve, inside a test, to that test's transaction.
713
+ *
714
+ * Everything reaches a database through its service — an endpoint through
715
+ * service discovery, the auth server through its tenant directly — so this is
716
+ * the one place a test's connection can be handed over. Outside a test it is
717
+ * the database it always was.
718
+ */
719
+ /** Rounds of delivery before a chain of consumers is called a loop. */
720
+ const MAX_DELIVERY_ROUNDS = 25;
721
+ /**
722
+ * Deliver what this test published, in-process, as the broker would — and
723
+ * keep delivering what the consumers publish in turn, until nothing is left.
724
+ *
725
+ * - A queue's messages go to its one consumer, as a batch.
726
+ * - A topic's events go to every subscriber that named their type, and only
727
+ * those: fan-out, as the filter policy (SNS) or the per-subscriber queue
728
+ * (pg-boss) does it.
729
+ * - Each payload is checked against the consumer's schema first. Turning an
730
+ * SNS envelope or an SQS record into `{ type, payload }` is each adaptor's
731
+ * job and tested there; what is tested here is what the handler is handed.
732
+ * - Consumers run as the server side of this test, so their databases are
733
+ * this test's transactions and their writes roll back with it.
734
+ * - A consumer that throws fails the test. Deployed, the message would be
735
+ * retried; here a retry would only hide the bug.
736
+ */
737
+ async function deliver(app, state, id) {
738
+ if (state.delivering) return;
739
+ state.delivering = true;
740
+ try {
741
+ for (let round = 0; state.pending.length > 0; round++) {
742
+ if (round === MAX_DELIVERY_ROUNDS) throw new DeliveryDidNotSettle(MAX_DELIVERY_ROUNDS, [...new Set(state.pending.map(({ channel }) => channel.id))]);
743
+ for (const { channel, messages } of state.pending.splice(0)) if (channel instanceof Queue) await toQueue(channel, messages, state, id);
744
+ else await toSubscribers(channel, messages, app, state, id);
745
+ }
746
+ } finally {
747
+ state.delivering = false;
748
+ }
749
+ }
750
+ async function toQueue(queue, messages, state, id) {
751
+ const payloads = [];
752
+ for (const message of messages) payloads.push(await accepted(queue.messageSchema, message, `queue '${queue.name}'`));
753
+ await runAsServer(id, () => new TestQueueAdaptor(queue, state.discovery).invoke({ messages: payloads })).catch((error) => {
754
+ throw new DeliveryFailed(`queue '${queue.name}'`, messages, error);
755
+ });
756
+ }
757
+ async function toSubscribers(topic, messages, app, state, id) {
758
+ for (const { name, subscriber } of app.subscribers) {
759
+ if (subscriber.topicName !== topic.name) continue;
760
+ const named = messages.filter(({ type }) => (subscriber.subscribedEvents ?? []).includes(type));
761
+ if (named.length === 0) continue;
762
+ const consumer = `subscriber '${name}'`;
763
+ const events = [];
764
+ for (const message of named) {
765
+ const schema = topic.eventSchemas[message.type];
766
+ events.push({
767
+ type: message.type,
768
+ payload: await accepted(schema, message, consumer)
769
+ });
770
+ }
771
+ await runAsServer(id, () => new TestSubscriberAdaptor(subscriber, state.discovery).invoke({ events })).catch((error) => {
772
+ throw new DeliveryFailed(consumer, named, error);
773
+ });
774
+ }
775
+ }
776
+ /** The payload, if the consumer's schema takes it — what the handler is handed. */
777
+ async function accepted(schema, message, consumer) {
778
+ const standard = schema?.["~standard"];
779
+ if (!standard) return message.payload;
780
+ const result = await standard.validate(message.payload);
781
+ if (result.issues) throw new MessageRejected(consumer, message, result.issues);
782
+ return result.value;
783
+ }
784
+ /** `fetch`, delivering what the test published once each of its requests answers. */
785
+ function deliveringFetch(inner, settle) {
786
+ return async (input, init) => {
787
+ const context = currentTestContext();
788
+ const response = await inner(input, init);
789
+ if (context?.side === "client") await settle(context.id);
790
+ return response;
791
+ };
792
+ }
793
+ /** An adaptor whose `invoke` delivers what it published before returning. */
794
+ function thenDeliver(adaptor, settle) {
795
+ const invoke = adaptor.invoke.bind(adaptor);
796
+ adaptor.invoke = (async (...args) => {
797
+ const result = await invoke(...args);
798
+ await settle();
799
+ return result;
800
+ });
801
+ return adaptor;
802
+ }
803
+ function bindToTests(database) {
804
+ if (bound.has(database)) return;
805
+ bound.add(database);
806
+ const service = database.service;
807
+ const register = service.register;
808
+ service.register = (options) => {
809
+ const context = currentTestContext();
810
+ const state = context && contexts.get(context.id);
811
+ if (!state) return register(options);
812
+ return state.transactions.get(database.id, urlOf(database, options.envParser), database.clientConfig);
813
+ };
814
+ }
815
+ function urlOf(database, envParser) {
816
+ return envParser.create((get) => ({ url: get(provideKey(database.id, "url")).string() })).parse().url;
817
+ }
818
+ /** Each surface's endpoints, served at its URL for the test that asked. */
819
+ function surfaceHandlers(endpoints, env) {
820
+ const bySurface = /* @__PURE__ */ new Map();
821
+ for (const endpoint of endpoints) {
822
+ const surface = endpoint.surface?.id;
823
+ if (!surface) continue;
824
+ bySurface.set(surface, [...bySurface.get(surface) ?? [], endpoint]);
825
+ }
826
+ return [...bySurface].flatMap(([surface, served]) => {
827
+ const base = env[provideKey(surface, "url")];
828
+ if (!base) return [];
829
+ return http.all(`${trim(base)}/*`, ({ request }) => serve(request, async (state) => {
830
+ let app = state.surfaces.get(surface);
831
+ if (!app) {
832
+ app = Promise.resolve().then(() => {
833
+ const hono = new Hono();
834
+ HonoEndpoint.addRoutes(served, state.discovery, hono);
835
+ return hono;
836
+ });
837
+ state.surfaces.set(surface, app);
838
+ }
839
+ return (await app).fetch(request);
840
+ }));
841
+ });
842
+ }
843
+ /**
844
+ * An external API's app fake, answering at the URL the test stage resolved for
845
+ * it — so a handler that calls Polar calls the fake, and the test sets up
846
+ * nothing.
847
+ *
848
+ * Not per test, unlike a surface: a fake stands in for somebody else's server,
849
+ * which no test's transaction reaches. An image fake has no handler here — its
850
+ * container answers on localhost, which is let through.
851
+ */
852
+ function fakeHandler(id, fake, env) {
853
+ const base = env[provideKey(id, "url")];
854
+ if (fake.kind !== "app" || !base) return [];
855
+ return [http.all(`${trim(base)}/*`, ({ request }) => fake.handler.fetch(request))];
856
+ }
857
+ /**
858
+ * A construct's client for this test, by service name — through the test's own
859
+ * discovery, so a topic or queue is its recorder and a database its
860
+ * transaction, exactly as the test's endpoints get them.
861
+ */
862
+ async function resolveService(app, state, name) {
863
+ const construct = app.consumables.find((candidate) => candidate.service.serviceName === name);
864
+ if (!construct) throw new UnknownService(name, app.consumables.map((candidate) => candidate.service.serviceName));
865
+ return (await state.discovery.register([construct.service]))[name];
866
+ }
867
+ /** An auth server, served at its URL, on the transaction of the test that asked. */
868
+ function authHandler(auth, env, envParser) {
869
+ const base = trim(env[provideKey(auth.id, "url")] ?? "");
870
+ return http.all(`${base}/*`, ({ request }) => serve(request, async (state) => {
871
+ let app = state.auth.get(auth);
872
+ if (!app) {
873
+ app = auth.server({
874
+ envParser,
875
+ context: serviceContext
876
+ }).then(({ app }) => app);
877
+ state.auth.set(auth, app);
878
+ }
879
+ return (await app).fetch(request);
880
+ }));
881
+ }
882
+ /** Handle a request as the server side of the test it was made for. */
883
+ async function serve(request, handle) {
884
+ const id = testContextOf(request);
885
+ const state = id ? contexts.get(id) : void 0;
886
+ if (!id || !state) throw new UnknownTestContext(request.url, id);
887
+ return runAsServer(id, () => handle(state));
888
+ }
889
+ function trim(url) {
890
+ return url.replace(/\/$/, "");
891
+ }
892
+ function isLocal(url) {
893
+ return url.hostname === "localhost" || url.hostname === "127.0.0.1" || url.hostname.endsWith(".localhost");
894
+ }
895
+ /**
896
+ * Sign a test's browser in the way a person does: ask the auth server for a
897
+ * magic link, open the email it sent, follow the link.
898
+ *
899
+ * What the generated `browser.signIn(email)` calls. The address's mail is
900
+ * cleared first — so the link is this request's, not one an earlier test left
901
+ * — and cleared again after the test, like any address a test reads. Returns
902
+ * the session the auth server then reports, as better-auth hands it back.
903
+ */
904
+ async function signInWithMagicLink(browser, auth, email = freshAddress()) {
905
+ const context = currentTestContext();
906
+ const state = context && contexts.get(context.id);
907
+ if (!state) throw new UnknownTestContext("signIn", context?.id);
908
+ if (!state.mailbox) throw new NoInbox();
909
+ const inbox = state.mailbox(email);
910
+ await inbox.clear();
911
+ const requested = await auth.signIn.magicLink({ email });
912
+ if (requested.error) throw new SignInFailed(email, `the auth server refused the magic link: ${requested.error.message ?? "no reason given"}`);
913
+ const mail = await inbox.last();
914
+ if (!mail.link) throw new SignInFailed(email, "its email held no link");
915
+ await browser.visit(mail.link);
916
+ const { data } = await auth.getSession();
917
+ if (!data) throw new SignInFailed(email, "the auth server reported no session after the link was opened");
918
+ return data;
919
+ }
920
+ /**
921
+ * An address nobody else signs in as — what `browser.signIn()` uses when the
922
+ * test does not care who it is.
923
+ *
924
+ * Unique rather than only seeded: tests in other files run at the same time,
925
+ * against the same Mailpit and the same unique columns, and a seeded address
926
+ * repeats wherever two tests share a name. The readable half is the seeded
927
+ * faker's, so a failure still names somebody.
928
+ */
929
+ function freshAddress() {
930
+ return `${faker.internet.username().toLowerCase().replace(/[^a-z0-9]/g, "")}.${randomUUID().slice(0, 8)}@example.test`;
931
+ }
932
+ /** `browser.signIn` finished without a session. */
933
+ var SignInFailed = class extends Error {
934
+ email;
935
+ reason;
936
+ constructor(email, reason) {
937
+ super(`Signing ${email} in failed: ${reason}.`);
938
+ this.email = email;
939
+ this.reason = reason;
940
+ this.name = "SignInFailed";
941
+ }
942
+ };
943
+ /** A request reached an in-process server without a test to belong to. */
944
+ var UnknownTestContext = class extends Error {
945
+ url;
946
+ id;
947
+ constructor(url, id) {
948
+ super(id ? `${url} was requested for test ${id}, which is not running. A request that outlives its test — an un-awaited call — lands here.` : `${url} was requested outside any test. Make the request inside a featureTest, so it reaches that test's transactions.`);
949
+ this.url = url;
950
+ this.id = id;
951
+ this.name = "UnknownTestContext";
952
+ }
953
+ };
954
+ /** `mailbox` was used in an app that declares no Email construct. */
955
+ var NoInbox = class extends Error {
956
+ constructor() {
957
+ super("mailbox() reads the inbox of the app's Email construct, and none was found in featureTest's modules — or `gkm test` did not inject its <ID>_INBOX_URL.");
958
+ this.name = "NoInbox";
959
+ }
960
+ };
961
+ /** `db.get(name)` named no database the test is handed. */
962
+ var UnknownDatabase = class extends Error {
963
+ database;
964
+ known;
965
+ constructor(database, known) {
966
+ super(`db.get('${database}') names no database of this app's. ` + (known.length > 0 ? `Its databases: ${known.join(", ")}. ` : "It declares no database of its own. ") + "A tenant an auth server owns is reached through that server, and a reader through the database it reads.");
967
+ this.database = database;
968
+ this.known = known;
969
+ this.name = "UnknownDatabase";
970
+ }
971
+ };
972
+ /** A factory keyed by a service name no database the app declares has. */
973
+ var UnknownFactory = class extends Error {
974
+ factory;
975
+ known;
976
+ constructor(factory, known) {
977
+ super(`There is a test factory for '${factory}', and no database this app declares is called that. ` + (known.length > 0 ? `Its databases: ${known.join(", ")}. ` : "It declares no database. ") + `Name the file after the database construct: test/factories/<construct>.ts.`);
978
+ this.factory = factory;
979
+ this.known = known;
980
+ this.name = "UnknownFactory";
981
+ }
982
+ };
983
+ /** A published message the consumer's own schema refuses. */
984
+ var MessageRejected = class extends Error {
985
+ consumer;
986
+ published;
987
+ issues;
988
+ constructor(consumer, published, issues) {
989
+ 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.`);
990
+ this.consumer = consumer;
991
+ this.published = published;
992
+ this.issues = issues;
993
+ this.name = "MessageRejected";
994
+ }
995
+ };
996
+ /** A consumer that threw while handling what the test published. */
997
+ var DeliveryFailed = class extends Error {
998
+ consumer;
999
+ messages;
1000
+ cause;
1001
+ constructor(consumer, messages, cause) {
1002
+ 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 });
1003
+ this.consumer = consumer;
1004
+ this.messages = messages;
1005
+ this.cause = cause;
1006
+ this.name = "DeliveryFailed";
1007
+ }
1008
+ };
1009
+ /** Consumers that kept publishing to each other without settling. */
1010
+ var DeliveryDidNotSettle = class extends Error {
1011
+ rounds;
1012
+ channels;
1013
+ constructor(rounds, channels) {
1014
+ 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.`);
1015
+ this.rounds = rounds;
1016
+ this.channels = channels;
1017
+ this.name = "DeliveryDidNotSettle";
1018
+ }
1019
+ };
1020
+ /** `services.get(name)` for a name no construct of the app is served by. */
1021
+ var UnknownService = class extends Error {
1022
+ serviceName;
1023
+ available;
1024
+ constructor(serviceName, available) {
1025
+ super(`The app declares no construct served as '${serviceName}'. Its services are: ${available.join(", ") || "none"}.`);
1026
+ this.serviceName = serviceName;
1027
+ this.available = available;
1028
+ this.name = "UnknownService";
1029
+ }
1030
+ };
1031
+ //#endregion
1032
+ export { DeliveryDidNotSettle, DeliveryFailed, MessageRejected, NoInbox, NoTestManifest, SignInFailed, TEST_CONTEXT_HEADER, TEST_MANIFEST_ENV, TestEndpointAdaptor, TestFunctionAdaptor, TestQueueAdaptor, TestSubscriberAdaptor, UnknownDatabase, UnknownFactory, UnknownService, UnknownTestContext, createMswHandlers, featureTest, loadTestManifest, signInWithMagicLink };
1033
+
428
1034
  //# sourceMappingURL=testing.mjs.map