@geekmidas/constructs 10.0.0-alpha.1 → 10.0.0-alpha.100

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