@geekmidas/constructs 10.0.0-alpha.5 → 10.0.0-alpha.51

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 (392) 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-B2OFsfDM.d.cts → Cron-DI3nKoic.d.cts} +22 -8
  11. package/dist/Cron-DI3nKoic.d.cts.map +1 -0
  12. package/dist/{Cron-CqEbBbwH.d.mts → Cron-uYAHPnp7.d.mts} +22 -8
  13. package/dist/Cron-uYAHPnp7.d.mts.map +1 -0
  14. package/dist/CronBuilder-BoHzlWU_.cjs +121 -0
  15. package/dist/CronBuilder-BoHzlWU_.cjs.map +1 -0
  16. package/dist/CronBuilder-CCgt0wCE.mjs +109 -0
  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-Dem2XyCu.d.mts → Endpoint-Bm9HjTPc.d.cts} +70 -93
  23. package/dist/Endpoint-Bm9HjTPc.d.cts.map +1 -0
  24. package/dist/{Endpoint-Dij_wOcc.mjs → Endpoint-CQ9RJ7p2.mjs} +130 -109
  25. package/dist/Endpoint-CQ9RJ7p2.mjs.map +1 -0
  26. package/dist/{Endpoint-DrD8a1yH.d.cts → Endpoint-CwM8Rzfs.d.mts} +71 -94
  27. package/dist/Endpoint-CwM8Rzfs.d.mts.map +1 -0
  28. package/dist/{Endpoint-DODn1RhN.cjs → Endpoint-DOi8c_Gy.cjs} +158 -131
  29. package/dist/Endpoint-DOi8c_Gy.cjs.map +1 -0
  30. package/dist/{index-B8g8POkr.d.cts → EndpointFactory-0plFjvb7.d.mts} +64 -134
  31. package/dist/EndpointFactory-0plFjvb7.d.mts.map +1 -0
  32. package/dist/{index-DbKmfl-q.d.mts → EndpointFactory-B6eZ3RDd.d.cts} +64 -134
  33. package/dist/EndpointFactory-B6eZ3RDd.d.cts.map +1 -0
  34. package/dist/{EndpointFactory-BHFMmFkV.cjs → EndpointFactory-Bo9lkMqB.cjs} +75 -110
  35. package/dist/EndpointFactory-Bo9lkMqB.cjs.map +1 -0
  36. package/dist/{EndpointFactory-b4ituq-s.mjs → EndpointFactory-DR1rebok.mjs} +39 -74
  37. package/dist/EndpointFactory-DR1rebok.mjs.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-BM2jbWht.mjs → HonoEndpointAdaptor-BIS0O3M9.mjs} +41 -47
  43. package/dist/HonoEndpointAdaptor-BIS0O3M9.mjs.map +1 -0
  44. package/dist/{HonoEndpointAdaptor-De6IlBZe.cjs → HonoEndpointAdaptor-CMi0MJsF.cjs} +50 -53
  45. package/dist/HonoEndpointAdaptor-CMi0MJsF.cjs.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 +189 -110
  79. package/dist/adaptors/aws.cjs.map +1 -1
  80. package/dist/adaptors/aws.d.cts +81 -45
  81. package/dist/adaptors/aws.d.cts.map +1 -1
  82. package/dist/adaptors/aws.d.mts +82 -46
  83. package/dist/adaptors/aws.d.mts.map +1 -1
  84. package/dist/adaptors/aws.mjs +161 -85
  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 +704 -90
  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 +669 -71
  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 +68 -10
  147. package/dist/crons/index.cjs.map +1 -1
  148. package/dist/crons/index.d.cts +32 -14
  149. package/dist/crons/index.d.cts.map +1 -1
  150. package/dist/crons/index.d.mts +32 -14
  151. package/dist/crons/index.d.mts.map +1 -1
  152. package/dist/crons/index.mjs +66 -10
  153. package/dist/crons/index.mjs.map +1 -1
  154. package/dist/database/kysely.cjs +40 -15
  155. package/dist/database/kysely.cjs.map +1 -1
  156. package/dist/database/kysely.d.cts +2 -152
  157. package/dist/database/kysely.d.mts +2 -152
  158. package/dist/database/kysely.mjs +28 -5
  159. package/dist/database/kysely.mjs.map +1 -1
  160. package/dist/email.cjs +25 -12
  161. package/dist/email.cjs.map +1 -1
  162. package/dist/email.d.cts +3 -7
  163. package/dist/email.d.cts.map +1 -1
  164. package/dist/email.d.mts +3 -7
  165. package/dist/email.d.mts.map +1 -1
  166. package/dist/email.mjs +16 -3
  167. package/dist/email.mjs.map +1 -1
  168. package/dist/encryption.cjs +96 -0
  169. package/dist/encryption.cjs.map +1 -0
  170. package/dist/encryption.d.cts +117 -0
  171. package/dist/encryption.d.cts.map +1 -0
  172. package/dist/encryption.d.mts +117 -0
  173. package/dist/encryption.d.mts.map +1 -0
  174. package/dist/encryption.mjs +83 -0
  175. package/dist/encryption.mjs.map +1 -0
  176. package/dist/endpoints/index.cjs +8 -10
  177. package/dist/endpoints/index.d.cts +51 -7
  178. package/dist/endpoints/index.d.cts.map +1 -0
  179. package/dist/endpoints/index.d.mts +51 -7
  180. package/dist/endpoints/index.d.mts.map +1 -0
  181. package/dist/endpoints/index.mjs +6 -10
  182. package/dist/external-api-CWY9orcO.d.mts +86 -0
  183. package/dist/external-api-CWY9orcO.d.mts.map +1 -0
  184. package/dist/external-api-D-5WB-sr.d.cts +86 -0
  185. package/dist/external-api-D-5WB-sr.d.cts.map +1 -0
  186. package/dist/external-api.cjs +124 -0
  187. package/dist/external-api.cjs.map +1 -0
  188. package/dist/external-api.d.cts +2 -0
  189. package/dist/external-api.d.mts +2 -0
  190. package/dist/external-api.mjs +121 -0
  191. package/dist/external-api.mjs.map +1 -0
  192. package/dist/file-server.cjs +42 -10
  193. package/dist/file-server.cjs.map +1 -1
  194. package/dist/file-server.d.cts +6 -10
  195. package/dist/file-server.d.cts.map +1 -1
  196. package/dist/file-server.d.mts +6 -10
  197. package/dist/file-server.d.mts.map +1 -1
  198. package/dist/file-server.mjs +34 -2
  199. package/dist/file-server.mjs.map +1 -1
  200. package/dist/functions/index.cjs +2 -6
  201. package/dist/functions/index.d.cts +3 -4
  202. package/dist/functions/index.d.mts +3 -4
  203. package/dist/functions/index.mjs +2 -6
  204. package/dist/{functions-DJJA7VGc.cjs → functions-CbP5ZKma.cjs} +421 -273
  205. package/dist/functions-CbP5ZKma.cjs.map +1 -0
  206. package/dist/{functions-Ck21Uyq0.mjs → functions-Di6n5ltG.mjs} +383 -241
  207. package/dist/functions-Di6n5ltG.mjs.map +1 -0
  208. package/dist/index-BuzRvKOQ.d.cts +115 -0
  209. package/dist/index-BuzRvKOQ.d.cts.map +1 -0
  210. package/dist/index-CTkKOer4.d.mts +115 -0
  211. package/dist/index-CTkKOer4.d.mts.map +1 -0
  212. package/dist/index-CeEtxDmK.d.cts +79 -0
  213. package/dist/index-CeEtxDmK.d.cts.map +1 -0
  214. package/dist/index-CeEtxDmK.d.mts +79 -0
  215. package/dist/index-CeEtxDmK.d.mts.map +1 -0
  216. package/dist/index.cjs +3 -3
  217. package/dist/index.d.cts +4 -4
  218. package/dist/index.d.mts +4 -4
  219. package/dist/index.mjs +2 -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-Bqov3fwv.d.mts +159 -0
  225. package/dist/kysely-Bqov3fwv.d.mts.map +1 -0
  226. package/dist/kysely-DTnkZsub.d.cts +159 -0
  227. package/dist/kysely-DTnkZsub.d.cts.map +1 -0
  228. package/dist/{lazyAccessors-BoJN3SMd.mjs → lazyAccessors-CFanua0O.mjs} +20 -60
  229. package/dist/lazyAccessors-CFanua0O.mjs.map +1 -0
  230. package/dist/{lazyAccessors-e3j2oE2m.cjs → lazyAccessors-hJKGv8Ay.cjs} +60 -113
  231. package/dist/lazyAccessors-hJKGv8Ay.cjs.map +1 -0
  232. package/dist/mobile-app.cjs +73 -0
  233. package/dist/mobile-app.cjs.map +1 -0
  234. package/dist/mobile-app.d.cts +61 -0
  235. package/dist/mobile-app.d.cts.map +1 -0
  236. package/dist/mobile-app.d.mts +61 -0
  237. package/dist/mobile-app.d.mts.map +1 -0
  238. package/dist/mobile-app.mjs +72 -0
  239. package/dist/mobile-app.mjs.map +1 -0
  240. package/dist/object-storage.cjs +18 -10
  241. package/dist/object-storage.cjs.map +1 -1
  242. package/dist/object-storage.d.cts +3 -7
  243. package/dist/object-storage.d.cts.map +1 -1
  244. package/dist/object-storage.d.mts +3 -7
  245. package/dist/object-storage.d.mts.map +1 -1
  246. package/dist/object-storage.mjs +11 -3
  247. package/dist/object-storage.mjs.map +1 -1
  248. package/dist/{processAudits-Dmts9H_b.mjs → processAudits-BpRlPQMW.mjs} +16 -19
  249. package/dist/processAudits-BpRlPQMW.mjs.map +1 -0
  250. package/dist/{processAudits-CGqttuXm.cjs → processAudits-D_2W5x8k.cjs} +26 -30
  251. package/dist/processAudits-D_2W5x8k.cjs.map +1 -0
  252. package/dist/queue/index.cjs +6 -189
  253. package/dist/queue/index.d.cts +3 -60
  254. package/dist/queue/index.d.mts +3 -60
  255. package/dist/queue/index.mjs +3 -186
  256. package/dist/rest-api.cjs +88 -63
  257. package/dist/rest-api.cjs.map +1 -1
  258. package/dist/rest-api.d.cts +68 -61
  259. package/dist/rest-api.d.cts.map +1 -1
  260. package/dist/rest-api.d.mts +68 -61
  261. package/dist/rest-api.d.mts.map +1 -1
  262. package/dist/rest-api.mjs +80 -55
  263. package/dist/rest-api.mjs.map +1 -1
  264. package/dist/{chunk-DWy1uDak.cjs → rolldown-runtime-y5ARvAq5.cjs} +14 -18
  265. package/dist/site.cjs +34 -9
  266. package/dist/site.cjs.map +1 -1
  267. package/dist/site.d.cts +17 -22
  268. package/dist/site.d.cts.map +1 -1
  269. package/dist/site.d.mts +17 -22
  270. package/dist/site.d.mts.map +1 -1
  271. package/dist/site.mjs +30 -5
  272. package/dist/site.mjs.map +1 -1
  273. package/dist/subscribers/index.cjs +2 -11
  274. package/dist/subscribers/index.d.cts +3 -14
  275. package/dist/subscribers/index.d.mts +3 -14
  276. package/dist/subscribers/index.mjs +2 -11
  277. package/dist/surfaceEnv-CNimK76p.cjs +56 -0
  278. package/dist/surfaceEnv-CNimK76p.cjs.map +1 -0
  279. package/dist/surfaceEnv-wMT5QzgZ.mjs +45 -0
  280. package/dist/surfaceEnv-wMT5QzgZ.mjs.map +1 -0
  281. package/dist/{telemetry-C3L0iS28.d.cts → telemetry-DGcFlVpB.d.cts} +2 -5
  282. package/dist/telemetry-DGcFlVpB.d.cts.map +1 -0
  283. package/dist/{telemetry-D7bVFLGi.d.mts → telemetry-DGcFlVpB.d.mts} +2 -5
  284. package/dist/telemetry-DGcFlVpB.d.mts.map +1 -0
  285. package/dist/topic/index.cjs +3 -137
  286. package/dist/topic/index.d.cts +2 -32
  287. package/dist/topic/index.d.mts +2 -32
  288. package/dist/topic/index.mjs +2 -134
  289. package/dist/{types-BlAkSuGI.d.cts → types-DMuSQeLL.d.cts} +3 -5
  290. package/dist/types-DMuSQeLL.d.cts.map +1 -0
  291. package/dist/{types-aKksMEWL.d.mts → types-DMuSQeLL.d.mts} +3 -5
  292. package/dist/types-DMuSQeLL.d.mts.map +1 -0
  293. package/dist/types.d.cts +1 -1
  294. package/dist/types.d.mts +1 -1
  295. package/dist/types.mjs +1 -0
  296. package/dist/worker.cjs +137 -38
  297. package/dist/worker.cjs.map +1 -1
  298. package/dist/worker.d.cts +113 -44
  299. package/dist/worker.d.cts.map +1 -1
  300. package/dist/worker.d.mts +113 -43
  301. package/dist/worker.d.mts.map +1 -1
  302. package/dist/worker.mjs +132 -33
  303. package/dist/worker.mjs.map +1 -1
  304. package/package.json +81 -41
  305. package/dist/Construct-BD5neF7w.mjs.map +0 -1
  306. package/dist/Construct-C0ijr2qp.d.cts +0 -117
  307. package/dist/Construct-C0ijr2qp.d.cts.map +0 -1
  308. package/dist/Construct-Ct8nalEi.d.mts +0 -117
  309. package/dist/Construct-Ct8nalEi.d.mts.map +0 -1
  310. package/dist/Construct-CyS3RpTL.cjs.map +0 -1
  311. package/dist/Cron-B2OFsfDM.d.cts.map +0 -1
  312. package/dist/Cron-CqEbBbwH.d.mts.map +0 -1
  313. package/dist/CronBuilder-Bg-9h2cc.d.mts +0 -44
  314. package/dist/CronBuilder-Bg-9h2cc.d.mts.map +0 -1
  315. package/dist/CronBuilder-CdibiHNB.mjs +0 -84
  316. package/dist/CronBuilder-CdibiHNB.mjs.map +0 -1
  317. package/dist/CronBuilder-DyUr6nYz.cjs +0 -96
  318. package/dist/CronBuilder-DyUr6nYz.cjs.map +0 -1
  319. package/dist/CronBuilder-LSJMfqnq.d.cts +0 -44
  320. package/dist/CronBuilder-LSJMfqnq.d.cts.map +0 -1
  321. package/dist/Endpoint-DODn1RhN.cjs.map +0 -1
  322. package/dist/Endpoint-Dem2XyCu.d.mts.map +0 -1
  323. package/dist/Endpoint-Dij_wOcc.mjs.map +0 -1
  324. package/dist/Endpoint-DrD8a1yH.d.cts.map +0 -1
  325. package/dist/EndpointFactory-BHFMmFkV.cjs.map +0 -1
  326. package/dist/EndpointFactory-b4ituq-s.mjs.map +0 -1
  327. package/dist/HonoEndpointAdaptor-BM2jbWht.mjs.map +0 -1
  328. package/dist/HonoEndpointAdaptor-De6IlBZe.cjs.map +0 -1
  329. package/dist/Queue-D7ZuwBhy.d.cts.map +0 -1
  330. package/dist/Queue-gVGfi2Yk.d.mts.map +0 -1
  331. package/dist/Subscriber-2mEi0ImH.d.cts.map +0 -1
  332. package/dist/Subscriber-xTJ9ayPN.d.mts.map +0 -1
  333. package/dist/SubscriberBuilder-4OPehf2R.cjs.map +0 -1
  334. package/dist/SubscriberBuilder-BjkbeT9l.mjs.map +0 -1
  335. package/dist/SubscriberBuilder-Dptmo-1A.d.mts +0 -62
  336. package/dist/SubscriberBuilder-Dptmo-1A.d.mts.map +0 -1
  337. package/dist/SubscriberBuilder-waNhzjSM.d.cts +0 -62
  338. package/dist/SubscriberBuilder-waNhzjSM.d.cts.map +0 -1
  339. package/dist/Topic-19QeHBIR.d.cts +0 -91
  340. package/dist/Topic-19QeHBIR.d.cts.map +0 -1
  341. package/dist/Topic-DuFeqkBh.d.mts +0 -91
  342. package/dist/Topic-DuFeqkBh.d.mts.map +0 -1
  343. package/dist/auth.d.cts.map +0 -1
  344. package/dist/auth.d.mts.map +0 -1
  345. package/dist/cache-0ANvRQnD.mjs +0 -51
  346. package/dist/cache-0ANvRQnD.mjs.map +0 -1
  347. package/dist/cache-3WSvAulx.cjs +0 -57
  348. package/dist/cache-3WSvAulx.cjs.map +0 -1
  349. package/dist/cache-BrRz3fEB.d.mts.map +0 -1
  350. package/dist/cache-BtZY_tHe.d.cts.map +0 -1
  351. package/dist/clone-DblgEZZa.mjs.map +0 -1
  352. package/dist/clone-Dy0cR2SZ.cjs.map +0 -1
  353. package/dist/construct-interface-BfjcOD_E.cjs +0 -117
  354. package/dist/construct-interface-BfjcOD_E.cjs.map +0 -1
  355. package/dist/construct-interface-D9d4Gm4p.d.cts.map +0 -1
  356. package/dist/construct-interface-Z4CpS8tK.mjs +0 -81
  357. package/dist/construct-interface-Z4CpS8tK.mjs.map +0 -1
  358. package/dist/construct-interface-g5GM5pwR.d.mts.map +0 -1
  359. package/dist/database/kysely.d.cts.map +0 -1
  360. package/dist/database/kysely.d.mts.map +0 -1
  361. package/dist/functions-Ck21Uyq0.mjs.map +0 -1
  362. package/dist/functions-DJJA7VGc.cjs.map +0 -1
  363. package/dist/index-AIfVzkhi.d.cts +0 -170
  364. package/dist/index-AIfVzkhi.d.cts.map +0 -1
  365. package/dist/index-B8g8POkr.d.cts.map +0 -1
  366. package/dist/index-D3zjrwjr.d.mts +0 -169
  367. package/dist/index-D3zjrwjr.d.mts.map +0 -1
  368. package/dist/index-DbKmfl-q.d.mts.map +0 -1
  369. package/dist/lazyAccessors-BoJN3SMd.mjs.map +0 -1
  370. package/dist/lazyAccessors-e3j2oE2m.cjs.map +0 -1
  371. package/dist/processAudits-CGqttuXm.cjs.map +0 -1
  372. package/dist/processAudits-Dmts9H_b.mjs.map +0 -1
  373. package/dist/queue/index.cjs.map +0 -1
  374. package/dist/queue/index.d.cts.map +0 -1
  375. package/dist/queue/index.d.mts.map +0 -1
  376. package/dist/queue/index.mjs.map +0 -1
  377. package/dist/subscribers/index.cjs.map +0 -1
  378. package/dist/subscribers/index.d.cts.map +0 -1
  379. package/dist/subscribers/index.d.mts.map +0 -1
  380. package/dist/subscribers/index.mjs.map +0 -1
  381. package/dist/surfaceEnv-BFXEms2f.cjs +0 -39
  382. package/dist/surfaceEnv-BFXEms2f.cjs.map +0 -1
  383. package/dist/surfaceEnv-C3Ktahea.mjs +0 -27
  384. package/dist/surfaceEnv-C3Ktahea.mjs.map +0 -1
  385. package/dist/telemetry-C3L0iS28.d.cts.map +0 -1
  386. package/dist/telemetry-D7bVFLGi.d.mts.map +0 -1
  387. package/dist/topic/index.cjs.map +0 -1
  388. package/dist/topic/index.d.cts.map +0 -1
  389. package/dist/topic/index.d.mts.map +0 -1
  390. package/dist/topic/index.mjs.map +0 -1
  391. package/dist/types-BlAkSuGI.d.cts.map +0 -1
  392. package/dist/types-aKksMEWL.d.mts.map +0 -1
package/README.md CHANGED
@@ -26,21 +26,20 @@ pnpm add @geekmidas/constructs
26
26
 
27
27
  ```typescript
28
28
  // The HTTP surface. Endpoints are built from it — `api.get(…)`, or
29
- // `api.endpoints` for a branch that a group of endpoints shares.
29
+ // `api.database(db)` for a branch that a group of endpoints shares.
30
30
  import { RestApi } from '@geekmidas/constructs/rest-api';
31
31
 
32
32
  // Endpoint internals: the factory a surface hands you, and the builder it
33
33
  // returns. There is no free-standing `e` — an endpoint belongs to a surface.
34
34
  import { EndpointBuilder, EndpointFactory } from '@geekmidas/constructs/endpoints';
35
35
 
36
- // Functions
37
- import { f, FunctionBuilder } from '@geekmidas/constructs/functions';
36
+ // The process with no port. Crons, topic subscribers, queues and functions
37
+ // are built from it — `worker.cron(…)`, `worker.topic(…)`, `worker.queue(…)`,
38
+ // `worker.input(…)` — and carry its logger.
39
+ import { Worker } from '@geekmidas/constructs/worker';
38
40
 
39
- // Crons
40
- import { c, CronBuilder } from '@geekmidas/constructs/crons';
41
-
42
- // Subscribers
43
- import { s, SubscriberBuilder } from '@geekmidas/constructs/subscribers';
41
+ // A declared event contract. Its publisher is its `service`.
42
+ import { Topic } from '@geekmidas/constructs/topic';
44
43
  ```
45
44
 
46
45
  ## Quick Start
@@ -57,6 +56,7 @@ import { RestApi } from '@geekmidas/constructs/rest-api';
57
56
  import { logger } from './logger';
58
57
 
59
58
  export const api = new RestApi('Api', {
59
+ path: 'apps/api',
60
60
  // Required, and `'none'` is a valid answer that has to be typed out. An API
61
61
  // that ships open because a field was left off is the one default worth
62
62
  // refusing to have.
@@ -125,15 +125,31 @@ export const searchUsers = api
125
125
  });
126
126
  ```
127
127
 
128
+ ### The Worker
129
+
130
+ Everything that is not an HTTP route is built from a `Worker`: the process
131
+ that runs a schedule, drains a queue or consumes a topic. It takes no
132
+ authorizer, because nothing reaches it from outside.
133
+
134
+ ```typescript
135
+ // constructs/worker.ts
136
+ import { Worker } from '@geekmidas/constructs/worker';
137
+ import { database } from './database';
138
+ import { logger } from './logger';
139
+
140
+ // `.database(…)` is where a server target keeps cron schedules.
141
+ export const worker = new Worker('Jobs', { logger }).database(database);
142
+ ```
143
+
128
144
  ### Cloud Functions
129
145
 
130
- Create serverless functions with input/output validation:
146
+ Create functions with input/output validation:
131
147
 
132
148
  ```typescript
133
- import { f } from '@geekmidas/constructs/functions';
149
+ import { worker } from '../constructs/worker';
134
150
  import { z } from 'zod';
135
151
 
136
- export const processOrder = f
152
+ export const processOrder = worker
137
153
  .input(z.object({
138
154
  orderId: z.string(),
139
155
  items: z.array(z.object({
@@ -144,13 +160,12 @@ export const processOrder = f
144
160
  .output(z.object({
145
161
  orderId: z.string(),
146
162
  status: z.enum(['processing', 'completed', 'failed']),
147
- processedAt: z.string().datetime()
163
+ processedAt: z.iso.datetime()
148
164
  }))
149
165
  .timeout(300000) // 5 minutes
150
166
  .handle(async ({ input, logger }) => {
151
167
  logger.info(`Processing order ${input.orderId}`);
152
168
 
153
- // Process order logic
154
169
  for (const item of input.items) {
155
170
  logger.info(`Processing item ${item.id}, quantity: ${item.quantity}`);
156
171
  }
@@ -165,87 +180,99 @@ export const processOrder = f
165
180
 
166
181
  ### Scheduled Tasks (Crons)
167
182
 
168
- Define cron jobs with schedules:
169
-
170
183
  ```typescript
171
- import { cron } from '@geekmidas/constructs/crons';
184
+ import { worker } from '../constructs/worker';
172
185
 
173
186
  // Daily report at 9 AM UTC
174
- export const dailyReport = cron
175
- .schedule('cron(0 9 * * ? *)')
187
+ export const dailyReport = worker
188
+ .cron('cron(0 9 * * ? *)')
176
189
  .timeout(600000) // 10 minutes
177
190
  .handle(async ({ logger }) => {
178
- logger.info('Generating daily report');
179
-
180
- const reportDate = new Date().toISOString().split('T')[0];
181
191
  const reportData = {
182
- date: reportDate,
192
+ date: new Date().toISOString().split('T')[0],
183
193
  totalOrders: 150,
184
- totalRevenue: 12500.00
185
194
  };
186
195
 
187
- logger.info('Daily report generated', reportData);
196
+ logger.info(reportData, 'Daily report generated');
188
197
  return reportData;
189
198
  });
190
199
 
191
200
  // Hourly cleanup
192
- export const hourlyCleanup = cron
193
- .schedule('rate(1 hour)')
194
- .timeout(300000) // 5 minutes
195
- .handle(async ({ logger }) => {
196
- logger.info('Running hourly cleanup');
197
-
198
- const itemsCleaned = 42;
199
- logger.info(`Cleaned ${itemsCleaned} items`);
201
+ export const hourlyCleanup = worker
202
+ .cron('rate(1 hour)')
203
+ .dependsOn([database])
204
+ .handle(async ({ services, logger }) => {
205
+ const result = await services.database
206
+ .deleteFrom('sessions')
207
+ .where('expires_at', '<', new Date())
208
+ .executeTakeFirst();
200
209
 
201
- return { itemsCleaned };
210
+ logger.info({ deleted: Number(result.numDeletedRows) }, 'Cleaned up');
202
211
  });
203
212
  ```
204
213
 
205
- ### Event Subscribers
214
+ On AWS a cron is an EventBridge rule; on a server the worker schedules it in
215
+ the database it was given.
216
+
217
+ ### Topics and Subscribers
206
218
 
207
- Handle events with type-safe message processing:
219
+ A topic declares the event contract once. A subscriber binds to it from the
220
+ worker and is typed by it:
208
221
 
209
222
  ```typescript
210
- import { SubscriberBuilder } from '@geekmidas/constructs/subscribers';
223
+ // constructs/topics.ts
224
+ import { Topic } from '@geekmidas/constructs/topic';
211
225
  import { z } from 'zod';
212
226
 
213
- export const userEventsSubscriber = new SubscriberBuilder()
214
- .subscribe(['user.created', 'user.updated', 'user.deleted'])
215
- .timeout(30000)
216
- .output(z.object({
217
- processed: z.number(),
218
- success: z.boolean()
219
- }))
220
- .handle(async ({ events, logger }) => {
221
- logger.info(
222
- { eventCount: events.length },
223
- 'Processing user events'
224
- );
227
+ export const users = new Topic('Users', {
228
+ events: {
229
+ 'user.created': z.object({ userId: z.string(), email: z.email() }),
230
+ 'user.updated': z.object({ userId: z.string(), changes: z.array(z.string()) }),
231
+ },
232
+ });
225
233
 
234
+ // subscribers/userEvents.ts
235
+ export const userEventsSubscriber = worker
236
+ .topic(users)
237
+ .subscribe(['user.created', 'user.updated'])
238
+ .handle(async ({ events, logger }) => {
226
239
  for (const event of events) {
227
- try {
228
- switch (event.type) {
229
- case 'user.created':
230
- logger.info({ userId: event.data.userId }, 'User created');
231
- break;
232
- case 'user.updated':
233
- logger.info({ userId: event.data.userId }, 'User updated');
234
- break;
235
- case 'user.deleted':
236
- logger.info({ userId: event.data.userId }, 'User deleted');
237
- break;
238
- }
239
- } catch (error) {
240
- logger.error({ error, event }, 'Failed to process event');
241
- throw error;
242
- }
240
+ // event.type narrows event.payload to that event's schema
241
+ logger.info({ type: event.type, userId: event.payload.userId }, 'User event');
243
242
  }
243
+ });
244
+ ```
244
245
 
245
- return {
246
- processed: events.length,
247
- success: true
248
- };
246
+ A subscriber is bound, not handed a publisher. One that emits follow-ups
247
+ depends on the topic it emits to: `.dependsOn([notifications])`.
248
+
249
+ ### Queues
250
+
251
+ A queue and its one consumer are one construct. Producers send by depending on
252
+ it:
253
+
254
+ ```typescript
255
+ // queues/emails.ts
256
+ export const emails = worker
257
+ .queue('Emails')
258
+ .message(z.object({ to: z.email(), template: z.enum(['welcome']) }))
259
+ .dependsOn([mail])
260
+ .handle(async ({ messages, services }) => {
261
+ for (const { to, template } of messages) {
262
+ await services.mail.sendTemplate(template, { to, subject: 'Welcome', props: {} });
263
+ }
264
+ });
265
+
266
+ // endpoints/invites.ts
267
+ export const invite = api
268
+ .post('/invites')
269
+ .body(z.object({ email: z.email() }))
270
+ .dependsOn([emails])
271
+ .handle(async ({ body, services }) => {
272
+ // `type` is the queue's name exactly as written
273
+ await services.emails.publish([
274
+ { type: 'Emails', payload: { to: body.email, template: 'welcome' } },
275
+ ]);
249
276
  });
250
277
  ```
251
278
 
@@ -288,7 +315,7 @@ For custom authentication methods, use `.securitySchemes()` on the surface's fac
288
315
  ```typescript
289
316
  import { api } from '../constructs/api';
290
317
 
291
- const router = api.endpoints
318
+ const router = api
292
319
  .securitySchemes({
293
320
  // Custom OAuth2 with specific flows
294
321
  oauth2: {
@@ -327,7 +354,7 @@ Set a default authorizer for every endpoint built from one branch:
327
354
  // A branch of the surface's factory, with a default every endpoint on it
328
355
  // inherits. (The surface's own `default` does the same thing for every
329
356
  // endpoint it serves — this narrows it for one group.)
330
- const router = api.endpoints.authorizer('jwt');
357
+ const router = api.authorizer('jwt');
331
358
 
332
359
  // Protected by default
333
360
  export const getProfile = router
@@ -343,99 +370,69 @@ export const getHealth = router
343
370
  .handle(async () => ({ status: 'ok' }));
344
371
  ```
345
372
 
346
- ### Service Discovery
373
+ ### Dependencies
347
374
 
348
- Inject services into your constructs:
375
+ `.dependsOn([...])` takes constructs. Each one's client lands in the handler's
376
+ `services` under the construct's own id, and the edge is what the manifest
377
+ records — so the environment, the runtime client and the cloud access all come
378
+ from the one line:
349
379
 
350
380
  ```typescript
351
381
  import { api } from '../constructs/api';
352
- import type { Service } from '@geekmidas/services';
353
- import type { EnvironmentParser } from '@geekmidas/envkit';
354
- import { Kysely } from 'kysely';
382
+ import { database } from '../constructs/database';
355
383
  import { z } from 'zod';
356
384
 
357
- // Define a database service
358
- const databaseService = {
359
- serviceName: 'database' as const,
360
- async register(envParser: EnvironmentParser<{}>) {
361
- const config = envParser.create((get) => ({
362
- url: get('DATABASE_URL').string()
363
- })).parse();
364
-
365
- const db = new Kysely({ /* config */ });
366
- return db;
367
- }
368
- } satisfies Service<'database', Kysely<Database>>;
369
-
370
- // Use service in endpoint
371
385
  export const getUserFromDb = api
372
386
  .get('/users/:id')
373
387
  .params(z.object({ id: z.string() }))
374
- .services([databaseService])
388
+ .dependsOn([database])
375
389
  .handle(async ({ params, services }) => {
376
- // services.database is fully typed
377
- const user = await services.database
390
+ // services.database is a Kysely client typed by the construct's schema
391
+ return services.database
378
392
  .selectFrom('users')
379
393
  .where('id', '=', params.id)
380
394
  .selectAll()
381
395
  .executeTakeFirst();
382
-
383
- return user;
384
396
  });
385
397
  ```
386
398
 
399
+ A hand-written `Service` still works through `.services()` on every builder,
400
+ for code that has not moved to a construct yet. It records no edge, so a deploy
401
+ target cannot grant it anything.
402
+
387
403
  ### Event Publishing
388
404
 
389
- Publish events from any construct:
405
+ An endpoint, function or cron publishes to a topic with `.event(topic, …)`,
406
+ once its handler has succeeded:
390
407
 
391
408
  ```typescript
392
- import { api } from '../constructs/api';
393
- import type { Service } from '@geekmidas/services';
394
- import type { EventPublisher, PublishableMessage } from '@geekmidas/events';
395
- import { z } from 'zod';
396
-
397
- // Define event types
398
- type UserEvents =
399
- | PublishableMessage<'user.created', { userId: string; email: string }>
400
- | PublishableMessage<'user.updated', { userId: string }>;
401
-
402
- // Create event publisher service
403
- const userEventPublisher = {
404
- serviceName: 'userEventPublisher' as const,
405
- async register(envParser: EnvironmentParser<{}>) {
406
- const config = envParser.create((get) => ({
407
- publisherUrl: get('EVENT_PUBLISHER_URL').string()
408
- })).parse();
409
+ import { users } from '../constructs/topics';
409
410
 
410
- const { Publisher } = await import('@geekmidas/events');
411
- return Publisher.fromConnectionString<UserEvents>(config.publisherUrl);
412
- }
413
- } satisfies Service<'userEventPublisher', EventPublisher<UserEvents>>;
414
-
415
- // Use in endpoint with event publishing
416
- export const createUser = api
411
+ export const createUser = router
417
412
  .post('/users')
418
- .body(z.object({
419
- name: z.string(),
420
- email: z.email()
421
- }))
422
- .publisher(userEventPublisher)
423
- .event('user.created', (body, result) => ({
424
- userId: result.id,
425
- email: body.email
426
- }))
427
- .handle(async ({ body, publish }) => {
428
- const user = {
429
- id: crypto.randomUUID(),
430
- name: body.name,
431
- email: body.email
432
- };
433
-
434
- // Events are automatically published after successful execution
435
- return user;
436
- });
413
+ .body(z.object({ name: z.string(), email: z.email() }))
414
+ .output(z.object({ id: z.string(), name: z.string(), email: z.email() }))
415
+ .event(users, {
416
+ type: 'user.created',
417
+ payload: (user) => ({ userId: user.id, email: user.email }),
418
+ when: (user) => !user.email.endsWith('@example.com'), // optional
419
+ })
420
+ .handle(async ({ body }) => ({ id: crypto.randomUUID(), ...body }));
437
421
  ```
438
422
 
423
+ - `type` is checked against the topic's events, and `payload` against that
424
+ event's schema.
425
+ - `.event()` is repeatable across topics. Two calls to two topics publish to
426
+ each, every event through its own topic's publisher.
427
+ - It also puts the topic's publisher in the handler as `services.users`, as
428
+ `.dependsOn([users])` would, for events the handler decides on:
429
+ `await services.users.publish([{ type: 'user.updated', payload }])`.
430
+ - A failed publish is logged, never thrown — the handler already succeeded.
431
+
432
+ The publisher reads `USERS_PUBLISHER_CONNECTION_STRING`, which only constructs
433
+ that publish to the topic are given, and picks its transport from the protocol:
434
+ `pgboss://` locally, `sns://` deployed.
435
+
439
436
  ### Database Context
440
437
 
441
438
  Inject a database instance directly into the handler context using `.database()`:
@@ -632,10 +629,11 @@ For complex scenarios, use `ctx.auditor` to record audits manually within your h
632
629
 
633
630
  ```typescript
634
631
  export const processOrder = api
635
- .post('/orders')
636
- .database(databaseService)
637
- .services([paymentService])
632
+ .database(database)
638
633
  .auditor(auditStorageService)
634
+ .post('/orders')
635
+ // `payments` is an ExternalApi whose client has `charge()`
636
+ .dependsOn([payments])
639
637
  .actor(({ session }) => ({ id: session.userId, type: 'user' }))
640
638
  .handle(async ({ body, db, services, auditor }) => {
641
639
  // db is automatically the transaction when auditor uses KyselyAuditStorage
@@ -646,7 +644,7 @@ export const processOrder = api
646
644
  .executeTakeFirstOrThrow();
647
645
 
648
646
  // Manual audit for payment (external service call)
649
- const payment = await services.payment.charge(order.total);
647
+ const payment = await services.payments.charge(order.total);
650
648
  auditor.audit('payment.processed', {
651
649
  orderId: order.id,
652
650
  amount: order.total,
@@ -907,6 +905,69 @@ export const sendMessage = api
907
905
  });
908
906
  ```
909
907
 
908
+ ## Feature Tests
909
+
910
+ A feature test drives an app the way it runs deployed: a browser signs in and
911
+ calls the API, the API asks the auth server who is calling, each over its URL,
912
+ and every database is in its own transaction, rolled back after the test.
913
+ Nothing runs as a server — each URL an app's constructs answer on is served
914
+ in-process through MSW, from the real handler, for the test that made the
915
+ request. Postgres, Mailpit and MinIO are the real local ones `gkm test` starts.
916
+
917
+ Nothing is declared in test code. `gkm test` writes `.gkm/test/` into each app:
918
+
919
+ - `manifest.json` — which construct and endpoint is exported where, and the
920
+ test stage's environment, keyed as the constructs derive their keys;
921
+ - `clients/<surface>.ts` — each surface's typed client, from the same generator
922
+ `gkm build` uses;
923
+ - `index.ts` — a `Browser` with a client per surface (`Api` → `browser.api`)
924
+ and per auth server (`browser.auth`, its better-auth plugins paired with
925
+ their client plugins), and the configured `it`.
926
+
927
+ Map it once in the app's `package.json` — `"imports": { "#test":
928
+ "./.gkm/test/index.ts" }` — and a test is:
929
+
930
+ ```typescript
931
+ import { it } from '#test';
932
+
933
+ it('shows the signed-in user their orders', async ({ browser, db, factories }) => {
934
+ const factory = await factories.get('database');
935
+ await factory.insert('orders', { email: 'ada@shop.test' });
936
+
937
+ await browser.signIn('ada@shop.test');
938
+ const { orders } = await browser.api.get('/orders');
939
+ expect(orders).toHaveLength(1);
940
+
941
+ const app = await db.get('database');
942
+ expect(await app.selectFrom('orders').selectAll().execute()).toHaveLength(1);
943
+ });
944
+ ```
945
+
946
+ - **`browser`** — already the global `fetch`; its cookie jar follows the
947
+ browser's rules, so a session cookie set for the wrong domain never reaches
948
+ the API.
949
+ - **`browser.signIn(email)`** — when the auth server has the magic-link plugin
950
+ and the app sends mail: the link requested, read from the inbox and
951
+ followed, as a person signs in. Returns the session the auth server reports.
952
+ - **`db.get(name)`** — the app's own databases by service name
953
+ (`db.get('database')`), each this test's transaction, typed by its schema.
954
+ Opened on first use by whatever reaches it first — the test, a factory, an
955
+ endpoint — and the same one for all of them. A tenant an auth server owns is
956
+ not among them: it is reached through the auth server, as the app reaches
957
+ it. Nor is a reader.
958
+ - **`factories.get(name)`** — each of those databases' factory, from
959
+ `test/factories/<construct>.ts` at the project root, on the same
960
+ transaction: `(await factories.get('database')).insert('users', …)`.
961
+ - **`mailbox(address)`** — the mail actually sent, read from Mailpit.
962
+ - **`published(topic | queue)`** — what the test published or enqueued.
963
+ Nothing is delivered: a subscriber or a worker is run on its own with
964
+ **`subscriber(s).invoke({ events })`** / **`queue(q).invoke({ messages })`**,
965
+ on the test's services and transactions.
966
+ - Each database construct — the app's and each schema tenant — gets its own
967
+ transaction on its own connection, as deployed.
968
+ - A request that belongs to no running test is refused with
969
+ `UnknownTestContext` rather than reaching another test's data.
970
+
910
971
  ## AWS Lambda Adapters
911
972
 
912
973
  Deploy your constructs to AWS Lambda:
@@ -1033,19 +1094,19 @@ Every construct has an async `getEnvironment()` method that returns the environm
1033
1094
 
1034
1095
  ```typescript
1035
1096
  import { api } from '../constructs/api';
1036
- import { databaseService } from './services/database';
1037
- import { cacheService } from './services/cache';
1097
+ import { cache } from '../constructs/cache';
1098
+ import { database } from '../constructs/database';
1038
1099
 
1039
1100
  const endpoint = api
1040
1101
  .get('/users')
1041
- .services([databaseService, cacheService])
1102
+ .dependsOn([database, cache])
1042
1103
  .handle(async ({ services }) => {
1043
1104
  // Implementation
1044
1105
  });
1045
1106
 
1046
1107
  // Detect required environment variables
1047
1108
  const envVars = await endpoint.getEnvironment();
1048
- // Returns: ['CACHE_URL', 'DATABASE_URL'] (sorted alphabetically)
1109
+ // Returns: ['DATABASE_URL', 'SESSIONS_URL'] (sorted alphabetically)
1049
1110
  ```
1050
1111
 
1051
1112
  ### How It Works
@@ -1133,33 +1194,37 @@ This manifest can then be used by infrastructure-as-code tools (Terraform, CDK,
1133
1194
  - **Deduplication**: Each variable listed once even if used by multiple services
1134
1195
  - **Sorted Output**: Variables always returned in alphabetical order
1135
1196
  - **Error Resilient**: Parse failures don't affect detection
1136
- - **Publisher Support**: Detects variables from `.publisher()` services
1197
+ - **Topic Support**: A topic named by `.event(topic, …)` contributes its `<ID>_PUBLISHER_CONNECTION_STRING`
1137
1198
 
1138
1199
  ### Example with Multiple Services
1139
1200
 
1140
1201
  ```typescript
1141
1202
  import { api } from '../constructs/api';
1142
- import { databaseService } from './services/database';
1143
- import { cacheService } from './services/cache';
1144
- import { emailService } from './services/email';
1203
+ import { cache } from '../constructs/cache';
1204
+ import { database } from '../constructs/database';
1205
+ import { mail } from '../constructs/email';
1206
+ import { users } from '../constructs/topics';
1145
1207
 
1146
1208
  const endpoint = api
1147
1209
  .post('/users')
1148
- .services([databaseService, cacheService, emailService])
1210
+ .dependsOn([database, cache, mail])
1211
+ .output(userSchema)
1212
+ .event(users, {
1213
+ type: 'user.created',
1214
+ payload: (user) => ({ userId: user.id, email: user.email }),
1215
+ })
1149
1216
  .handle(async ({ services }) => {
1150
1217
  // Create user
1151
1218
  });
1152
1219
 
1153
- // Automatically detects all variables from all services
1220
+ // Detects the keys of every construct it names
1154
1221
  const envVars = await endpoint.getEnvironment();
1155
1222
  // Returns: [
1156
- // 'CACHE_URL',
1157
1223
  // 'DATABASE_URL',
1158
- // 'DATABASE_PORT',
1159
- // 'SMTP_HOST',
1160
- // 'SMTP_PORT',
1161
- // 'SMTP_USER',
1162
- // 'SMTP_PASS'
1224
+ // 'MAIL_FROM',
1225
+ // 'MAIL_URL',
1226
+ // 'SESSIONS_URL',
1227
+ // 'USERS_PUBLISHER_CONNECTION_STRING'
1163
1228
  // ]
1164
1229
  ```
1165
1230