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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (303) hide show
  1. package/README.md +225 -268
  2. package/bin/adjacent-tsconfig.mjs +97 -0
  3. package/bin/gkm.mjs +16 -2
  4. package/bin/owning-tsconfig-jsx-register.mjs +18 -0
  5. package/bin/owning-tsconfig-jsx.mjs +108 -0
  6. package/dist/{HostingerProvider-h3EbEp-Z.cjs → HostingerProvider-CgDaD8VR.cjs} +21 -22
  7. package/dist/HostingerProvider-CgDaD8VR.cjs.map +1 -0
  8. package/dist/{HostingerProvider-Cft7lEYr.mjs → HostingerProvider-DI_Pr2VE.mjs} +20 -21
  9. package/dist/HostingerProvider-DI_Pr2VE.mjs.map +1 -0
  10. package/dist/LegacyStateStore-C7vFAxbu.mjs +89 -0
  11. package/dist/LegacyStateStore-C7vFAxbu.mjs.map +1 -0
  12. package/dist/LegacyStateStore-JbBVFp_2.cjs +89 -0
  13. package/dist/LegacyStateStore-JbBVFp_2.cjs.map +1 -0
  14. package/dist/LocalStateStore-DHj_-CQB.cjs +176 -0
  15. package/dist/LocalStateStore-DHj_-CQB.cjs.map +1 -0
  16. package/dist/LocalStateStore-DfUwQsL8.mjs +165 -0
  17. package/dist/LocalStateStore-DfUwQsL8.mjs.map +1 -0
  18. package/dist/{openapi-D-dx9Akj.cjs → OpenApiTsGenerator-BSrgw7B0.cjs} +360 -470
  19. package/dist/OpenApiTsGenerator-BSrgw7B0.cjs.map +1 -0
  20. package/dist/{openapi-Bw8DWFWz.mjs → OpenApiTsGenerator-q5B0z8Xg.mjs} +325 -404
  21. package/dist/OpenApiTsGenerator-q5B0z8Xg.mjs.map +1 -0
  22. package/dist/{Route53Provider-RdpUDJQk.mjs → Route53Provider-Cvj40A8I.mjs} +12 -12
  23. package/dist/Route53Provider-Cvj40A8I.mjs.map +1 -0
  24. package/dist/{Route53Provider-di2fMM5N.cjs → Route53Provider-DVILBsvV.cjs} +20 -21
  25. package/dist/Route53Provider-DVILBsvV.cjs.map +1 -0
  26. package/dist/S3StateStore-Dq6hHtzY.mjs +161 -0
  27. package/dist/S3StateStore-Dq6hHtzY.mjs.map +1 -0
  28. package/dist/S3StateStore-xqnpUrzy.cjs +160 -0
  29. package/dist/S3StateStore-xqnpUrzy.cjs.map +1 -0
  30. package/dist/SSMStateStore-5dBRwVlJ.cjs +153 -0
  31. package/dist/SSMStateStore-5dBRwVlJ.cjs.map +1 -0
  32. package/dist/SSMStateStore-SUmvAbLi.mjs +154 -0
  33. package/dist/SSMStateStore-SUmvAbLi.mjs.map +1 -0
  34. package/dist/appPorts-C9z9Pzn9.mjs +223 -0
  35. package/dist/appPorts-C9z9Pzn9.mjs.map +1 -0
  36. package/dist/appPorts-Cu79hJF6.cjs +264 -0
  37. package/dist/appPorts-Cu79hJF6.cjs.map +1 -0
  38. package/dist/aws-DkHdTV-p.cjs +61 -0
  39. package/dist/aws-DkHdTV-p.cjs.map +1 -0
  40. package/dist/aws-DojzQnLd.mjs +61 -0
  41. package/dist/aws-DojzQnLd.mjs.map +1 -0
  42. package/dist/{backup-provisioner-BrsHwYG0.cjs → backup-provisioner-BmhIO_Yr.cjs} +21 -19
  43. package/dist/backup-provisioner-BmhIO_Yr.cjs.map +1 -0
  44. package/dist/{backup-provisioner-Bgj5Vi_L.mjs → backup-provisioner-DIVCbfee.mjs} +10 -7
  45. package/dist/backup-provisioner-DIVCbfee.mjs.map +1 -0
  46. package/dist/{bundler-Be8Zg4Wd.mjs → bundler-B5VsKW-_.mjs} +18 -29
  47. package/dist/bundler-B5VsKW-_.mjs.map +1 -0
  48. package/dist/{bundler-BY1OmV1e.cjs → bundler-DXATpO1T.cjs} +20 -32
  49. package/dist/bundler-DXATpO1T.cjs.map +1 -0
  50. package/dist/cli-DEA_J3Sa.mjs +69 -0
  51. package/dist/cli-DEA_J3Sa.mjs.map +1 -0
  52. package/dist/cli-DQdrVkj2.cjs +69 -0
  53. package/dist/cli-DQdrVkj2.cjs.map +1 -0
  54. package/dist/{config-CxP7P-qG.mjs → config-C5-EEdmr.mjs} +144 -127
  55. package/dist/config-C5-EEdmr.mjs.map +1 -0
  56. package/dist/{config-CNz5KaSR.cjs → config-DXnkCEq0.cjs} +212 -184
  57. package/dist/config-DXnkCEq0.cjs.map +1 -0
  58. package/dist/config.cjs +9 -6
  59. package/dist/config.d.cts +124 -33
  60. package/dist/config.d.cts.map +1 -1
  61. package/dist/config.d.mts +124 -33
  62. package/dist/config.d.mts.map +1 -1
  63. package/dist/config.mjs +3 -5
  64. package/dist/deploy/public.cjs +22 -0
  65. package/dist/deploy/public.d.cts +459 -0
  66. package/dist/deploy/public.d.cts.map +1 -0
  67. package/dist/deploy/public.d.mts +459 -0
  68. package/dist/deploy/public.d.mts.map +1 -0
  69. package/dist/deploy/public.mjs +5 -0
  70. package/dist/deploy/sniffer-envkit-patch.cjs +18 -10
  71. package/dist/deploy/sniffer-envkit-patch.cjs.map +1 -1
  72. package/dist/deploy/sniffer-envkit-patch.d.cts +0 -2
  73. package/dist/deploy/sniffer-envkit-patch.d.cts.map +1 -1
  74. package/dist/deploy/sniffer-envkit-patch.d.mts +0 -2
  75. package/dist/deploy/sniffer-envkit-patch.d.mts.map +1 -1
  76. package/dist/deploy/sniffer-envkit-patch.mjs +10 -2
  77. package/dist/deploy/sniffer-envkit-patch.mjs.map +1 -1
  78. package/dist/deploy/sniffer-hooks.cjs +13 -7
  79. package/dist/deploy/sniffer-hooks.cjs.map +1 -1
  80. package/dist/deploy/sniffer-hooks.d.cts +1 -2
  81. package/dist/deploy/sniffer-hooks.d.cts.map +1 -1
  82. package/dist/deploy/sniffer-hooks.d.mts +1 -2
  83. package/dist/deploy/sniffer-hooks.d.mts.map +1 -1
  84. package/dist/deploy/sniffer-hooks.mjs +10 -3
  85. package/dist/deploy/sniffer-hooks.mjs.map +1 -1
  86. package/dist/deploy/sniffer-loader.cjs +16 -7
  87. package/dist/deploy/sniffer-loader.cjs.map +1 -1
  88. package/dist/deploy/sniffer-loader.d.cts +1 -1
  89. package/dist/deploy/sniffer-loader.d.mts +1 -1
  90. package/dist/deploy/sniffer-loader.mjs +14 -3
  91. package/dist/deploy/sniffer-loader.mjs.map +1 -1
  92. package/dist/deploy/sniffer-routes-worker.cjs +11 -11
  93. package/dist/deploy/sniffer-routes-worker.cjs.map +1 -1
  94. package/dist/deploy/sniffer-routes-worker.d.cts +1 -1
  95. package/dist/deploy/sniffer-routes-worker.d.mts +1 -1
  96. package/dist/deploy/sniffer-routes-worker.mjs +3 -3
  97. package/dist/deploy/sniffer-routes-worker.mjs.map +1 -1
  98. package/dist/deploy/sniffer-worker.cjs +15 -6
  99. package/dist/deploy/sniffer-worker.cjs.map +1 -1
  100. package/dist/deploy/sniffer-worker.d.cts +1 -3
  101. package/dist/deploy/sniffer-worker.d.cts.map +1 -1
  102. package/dist/deploy/sniffer-worker.d.mts +1 -3
  103. package/dist/deploy/sniffer-worker.d.mts.map +1 -1
  104. package/dist/deploy/sniffer-worker.mjs +15 -4
  105. package/dist/deploy/sniffer-worker.mjs.map +1 -1
  106. package/dist/deploy-BJcLmVTc.mjs +3282 -0
  107. package/dist/deploy-BJcLmVTc.mjs.map +1 -0
  108. package/dist/deploy-BbJdgQ2b.cjs +3365 -0
  109. package/dist/deploy-BbJdgQ2b.cjs.map +1 -0
  110. package/dist/{discover-DTmFeloL.cjs → discover-Bc-4eA_p.cjs} +131 -103
  111. package/dist/discover-Bc-4eA_p.cjs.map +1 -0
  112. package/dist/{discover-CAlFgYec.mjs → discover-FrYvzkeC.mjs} +91 -58
  113. package/dist/discover-FrYvzkeC.mjs.map +1 -0
  114. package/dist/{emit-CiZS_5Ub.mjs → emit-C1e8qD08.mjs} +13 -26
  115. package/dist/emit-C1e8qD08.mjs.map +1 -0
  116. package/dist/{emit-CbcRolsa.cjs → emit-Dmc1nvdS.cjs} +31 -57
  117. package/dist/emit-Dmc1nvdS.cjs.map +1 -0
  118. package/dist/encryption-DaA9gRXr.mjs +90 -0
  119. package/dist/encryption-DaA9gRXr.mjs.map +1 -0
  120. package/dist/encryption-ojzUo7-z.cjs +91 -0
  121. package/dist/encryption-ojzUo7-z.cjs.map +1 -0
  122. package/dist/fakes-C9RiT6XG.mjs +125 -0
  123. package/dist/fakes-C9RiT6XG.mjs.map +1 -0
  124. package/dist/fakes-zW-jNAbQ.cjs +148 -0
  125. package/dist/fakes-zW-jNAbQ.cjs.map +1 -0
  126. package/dist/github-Cq57poPj.cjs +213 -0
  127. package/dist/github-Cq57poPj.cjs.map +1 -0
  128. package/dist/github-DmCj2u95.mjs +213 -0
  129. package/dist/github-DmCj2u95.mjs.map +1 -0
  130. package/dist/home-DOzBaWaL.cjs +33 -0
  131. package/dist/home-DOzBaWaL.cjs.map +1 -0
  132. package/dist/home-GI7pJl1M.mjs +22 -0
  133. package/dist/home-GI7pJl1M.mjs.map +1 -0
  134. package/dist/{index-DEbaleny.d.mts → index-Da1-oa9W.d.mts} +4 -23
  135. package/dist/index-Da1-oa9W.d.mts.map +1 -0
  136. package/dist/{index-BGGdjueF.d.cts → index-UiWCaGzU.d.cts} +4 -23
  137. package/dist/index-UiWCaGzU.d.cts.map +1 -0
  138. package/dist/index.cjs +10712 -12248
  139. package/dist/index.cjs.map +1 -1
  140. package/dist/index.d.cts +1 -1
  141. package/dist/index.d.mts +1 -1
  142. package/dist/index.mjs +10480 -12040
  143. package/dist/index.mjs.map +1 -1
  144. package/dist/migrate-5_J5JySj.mjs +265 -0
  145. package/dist/migrate-5_J5JySj.mjs.map +1 -0
  146. package/dist/migrate-BScRpCEx.cjs +270 -0
  147. package/dist/migrate-BScRpCEx.cjs.map +1 -0
  148. package/dist/openapi.cjs +198 -10
  149. package/dist/openapi.cjs.map +1 -0
  150. package/dist/openapi.d.cts +21 -19
  151. package/dist/openapi.d.cts.map +1 -1
  152. package/dist/openapi.d.mts +21 -19
  153. package/dist/openapi.d.mts.map +1 -1
  154. package/dist/openapi.mjs +193 -5
  155. package/dist/openapi.mjs.map +1 -0
  156. package/dist/ready-DQIy21W5.mjs +760 -0
  157. package/dist/ready-DQIy21W5.mjs.map +1 -0
  158. package/dist/ready-XlNx-Gbo.cjs +807 -0
  159. package/dist/ready-XlNx-Gbo.cjs.map +1 -0
  160. package/dist/reconcile/public.cjs +3 -5
  161. package/dist/reconcile/public.d.cts +30 -33
  162. package/dist/reconcile/public.d.cts.map +1 -1
  163. package/dist/reconcile/public.d.mts +30 -33
  164. package/dist/reconcile/public.d.mts.map +1 -1
  165. package/dist/reconcile/public.mjs +3 -4
  166. package/dist/{reconcile-CFs8C_1a.mjs → reconcile--I7V4Klj.mjs} +4 -7
  167. package/dist/reconcile--I7V4Klj.mjs.map +1 -0
  168. package/dist/{reconcile-D0pimNiy.cjs → reconcile-CuCQBa5-.cjs} +5 -8
  169. package/dist/reconcile-CuCQBa5-.cjs.map +1 -0
  170. package/dist/rolldown-runtime-BhDjJH2R.mjs +15 -0
  171. package/dist/{chunk-CUT6urMc.cjs → rolldown-runtime-C0BPl7ul.cjs} +23 -10
  172. package/dist/sniffer-CQmJnNJM.cjs +7115 -0
  173. package/dist/sniffer-CQmJnNJM.cjs.map +1 -0
  174. package/dist/sniffer-bdleks5l.mjs +6561 -0
  175. package/dist/sniffer-bdleks5l.mjs.map +1 -0
  176. package/dist/storage-BzaUxmqe.mjs +124 -0
  177. package/dist/storage-BzaUxmqe.mjs.map +1 -0
  178. package/dist/storage-CSGoC3bK.cjs +152 -0
  179. package/dist/storage-CSGoC3bK.cjs.map +1 -0
  180. package/dist/store-BS8A7NcA.mjs +415 -0
  181. package/dist/store-BS8A7NcA.mjs.map +1 -0
  182. package/dist/store-KvNQwYaB.cjs +510 -0
  183. package/dist/store-KvNQwYaB.cjs.map +1 -0
  184. package/dist/types-Bp1mVxG0.d.mts +6410 -0
  185. package/dist/types-Bp1mVxG0.d.mts.map +1 -0
  186. package/dist/types-efNLu9xu.d.cts +6411 -0
  187. package/dist/types-efNLu9xu.d.cts.map +1 -0
  188. package/dist/vitest.cjs +65 -0
  189. package/dist/vitest.cjs.map +1 -0
  190. package/dist/vitest.d.cts +29 -0
  191. package/dist/vitest.d.cts.map +1 -0
  192. package/dist/vitest.d.mts +29 -0
  193. package/dist/vitest.d.mts.map +1 -0
  194. package/dist/vitest.mjs +65 -0
  195. package/dist/vitest.mjs.map +1 -0
  196. package/dist/workspace/index.cjs +3 -4
  197. package/dist/workspace/index.d.cts +3 -3
  198. package/dist/workspace/index.d.mts +3 -3
  199. package/dist/workspace/index.mjs +2 -3
  200. package/dist/{workspace-LKiNyaDy.cjs → workspace-B64Xk1Mb.cjs} +1070 -1118
  201. package/dist/workspace-B64Xk1Mb.cjs.map +1 -0
  202. package/dist/{workspace-DIuZx-cc.mjs → workspace-Bp1xVaOz.mjs} +901 -972
  203. package/dist/workspace-Bp1xVaOz.mjs.map +1 -0
  204. package/package.json +38 -20
  205. package/dist/CachedStateProvider-BLo7zv7S.cjs +0 -3
  206. package/dist/CachedStateProvider-BxoAm-B2.mjs +0 -3
  207. package/dist/CachedStateProvider-CqPdW7CB.cjs +0 -60
  208. package/dist/CachedStateProvider-CqPdW7CB.cjs.map +0 -1
  209. package/dist/CachedStateProvider-DTniehMP.mjs +0 -54
  210. package/dist/CachedStateProvider-DTniehMP.mjs.map +0 -1
  211. package/dist/HostingerProvider-Cft7lEYr.mjs.map +0 -1
  212. package/dist/HostingerProvider-h3EbEp-Z.cjs.map +0 -1
  213. package/dist/LocalStateProvider-Bn6tS-oL.mjs +0 -42
  214. package/dist/LocalStateProvider-Bn6tS-oL.mjs.map +0 -1
  215. package/dist/LocalStateProvider-Db9SEjyH.cjs +0 -43
  216. package/dist/LocalStateProvider-Db9SEjyH.cjs.map +0 -1
  217. package/dist/Route53Provider-RdpUDJQk.mjs.map +0 -1
  218. package/dist/Route53Provider-di2fMM5N.cjs.map +0 -1
  219. package/dist/SSMStateProvider-BRt2py-A.mjs +0 -66
  220. package/dist/SSMStateProvider-BRt2py-A.mjs.map +0 -1
  221. package/dist/SSMStateProvider-DyX8s9HI.cjs +0 -66
  222. package/dist/SSMStateProvider-DyX8s9HI.cjs.map +0 -1
  223. package/dist/backup-provisioner-Bgj5Vi_L.mjs.map +0 -1
  224. package/dist/backup-provisioner-BrsHwYG0.cjs.map +0 -1
  225. package/dist/bundler-BY1OmV1e.cjs.map +0 -1
  226. package/dist/bundler-Be8Zg4Wd.mjs.map +0 -1
  227. package/dist/chunk-Duj1WY3L.mjs +0 -7
  228. package/dist/config-CNz5KaSR.cjs.map +0 -1
  229. package/dist/config-CxP7P-qG.mjs.map +0 -1
  230. package/dist/credentials-B5zRHdAl.mjs +0 -141
  231. package/dist/credentials-B5zRHdAl.mjs.map +0 -1
  232. package/dist/credentials-BK3Z93MX.mjs +0 -2548
  233. package/dist/credentials-BK3Z93MX.mjs.map +0 -1
  234. package/dist/credentials-BapzjyV5.cjs +0 -195
  235. package/dist/credentials-BapzjyV5.cjs.map +0 -1
  236. package/dist/credentials-DzsXZzkx.cjs +0 -2680
  237. package/dist/credentials-DzsXZzkx.cjs.map +0 -1
  238. package/dist/discover-CAlFgYec.mjs.map +0 -1
  239. package/dist/discover-DTmFeloL.cjs.map +0 -1
  240. package/dist/dokploy-api-BS2xnJLZ.mjs +0 -3
  241. package/dist/dokploy-api-BsVH0y_s.cjs +0 -718
  242. package/dist/dokploy-api-BsVH0y_s.cjs.map +0 -1
  243. package/dist/dokploy-api-BuxDRo3l.cjs +0 -3
  244. package/dist/dokploy-api-aTFPz7_4.mjs +0 -706
  245. package/dist/dokploy-api-aTFPz7_4.mjs.map +0 -1
  246. package/dist/emit-CbcRolsa.cjs.map +0 -1
  247. package/dist/emit-CiZS_5Ub.mjs.map +0 -1
  248. package/dist/encryption-C6jaU0hE.cjs +0 -54
  249. package/dist/encryption-C6jaU0hE.cjs.map +0 -1
  250. package/dist/encryption-CHzzeR8a.cjs +0 -4
  251. package/dist/encryption-CQUncu7v.mjs +0 -3
  252. package/dist/encryption-D-abyhZx.mjs +0 -42
  253. package/dist/encryption-D-abyhZx.mjs.map +0 -1
  254. package/dist/fullstack-secrets-C-GGohke.cjs +0 -111
  255. package/dist/fullstack-secrets-C-GGohke.cjs.map +0 -1
  256. package/dist/fullstack-secrets-D1o9-G5l.mjs +0 -87
  257. package/dist/fullstack-secrets-D1o9-G5l.mjs.map +0 -1
  258. package/dist/generator-CNzBw7g5.cjs +0 -289
  259. package/dist/generator-CNzBw7g5.cjs.map +0 -1
  260. package/dist/generator-VE2JrFlY.mjs +0 -253
  261. package/dist/generator-VE2JrFlY.mjs.map +0 -1
  262. package/dist/index-BGGdjueF.d.cts.map +0 -1
  263. package/dist/index-DEbaleny.d.mts.map +0 -1
  264. package/dist/openapi-Bw8DWFWz.mjs.map +0 -1
  265. package/dist/openapi-D-dx9Akj.cjs.map +0 -1
  266. package/dist/openapi-react-query-Byltvm_7.mjs +0 -167
  267. package/dist/openapi-react-query-Byltvm_7.mjs.map +0 -1
  268. package/dist/openapi-react-query-CmJ1xDbn.cjs +0 -173
  269. package/dist/openapi-react-query-CmJ1xDbn.cjs.map +0 -1
  270. package/dist/openapi-react-query.cjs +0 -4
  271. package/dist/openapi-react-query.d.cts +0 -11
  272. package/dist/openapi-react-query.d.cts.map +0 -1
  273. package/dist/openapi-react-query.d.mts +0 -11
  274. package/dist/openapi-react-query.d.mts.map +0 -1
  275. package/dist/openapi-react-query.mjs +0 -4
  276. package/dist/reconcile-CFs8C_1a.mjs.map +0 -1
  277. package/dist/reconcile-D0pimNiy.cjs.map +0 -1
  278. package/dist/setup-8IWPsRIN.cjs +0 -11
  279. package/dist/setup-BWMhbW-p.mjs +0 -443
  280. package/dist/setup-BWMhbW-p.mjs.map +0 -1
  281. package/dist/setup-D7L4BgBT.cjs +0 -473
  282. package/dist/setup-D7L4BgBT.cjs.map +0 -1
  283. package/dist/setup-DGIPd2fh.mjs +0 -11
  284. package/dist/storage-BJmzYxt8.cjs +0 -363
  285. package/dist/storage-BJmzYxt8.cjs.map +0 -1
  286. package/dist/storage-BM9hGpgv.cjs +0 -7
  287. package/dist/storage-Bi24WfoW.mjs +0 -297
  288. package/dist/storage-Bi24WfoW.mjs.map +0 -1
  289. package/dist/storage-CYlGwWTj.mjs +0 -3
  290. package/dist/sync-CmEuNZsB.mjs +0 -76
  291. package/dist/sync-CmEuNZsB.mjs.map +0 -1
  292. package/dist/sync-D306yOWu.cjs +0 -4
  293. package/dist/sync-SizaChmC.cjs +0 -93
  294. package/dist/sync-SizaChmC.cjs.map +0 -1
  295. package/dist/sync-hOqAWHR6.mjs +0 -3
  296. package/dist/types-BLSNdrk0.d.cts +0 -2176
  297. package/dist/types-BLSNdrk0.d.cts.map +0 -1
  298. package/dist/types-C3POXhw3.d.mts +0 -2176
  299. package/dist/types-C3POXhw3.d.mts.map +0 -1
  300. package/dist/workspace-CGaUAw5A.cjs +0 -9
  301. package/dist/workspace-CnTqIlB3.mjs +0 -8
  302. package/dist/workspace-DIuZx-cc.mjs.map +0 -1
  303. package/dist/workspace-LKiNyaDy.cjs.map +0 -1
@@ -1,50 +1,49 @@
1
- const require_chunk = require('./chunk-CUT6urMc.cjs');
2
- const node_path = require_chunk.__toESM(require("node:path"));
3
- const __geekmidas_manifest = require_chunk.__toESM(require("@geekmidas/manifest"));
4
- const fast_glob = require_chunk.__toESM(require("fast-glob"));
5
- const lodash_kebabcase = require_chunk.__toESM(require("lodash.kebabcase"));
6
-
7
- //#region src/types.ts
8
- function isPartitionedRoutes(routes) {
9
- return typeof routes === "object" && routes !== null && !Array.isArray(routes) && "paths" in routes;
10
- }
1
+ const require_rolldown_runtime = require("./rolldown-runtime-C0BPl7ul.cjs");
2
+ let node_path = require("node:path");
3
+ let node_async_hooks = require("node:async_hooks");
4
+ let node_util = require("node:util");
5
+ let _geekmidas_manifest = require("@geekmidas/manifest");
6
+ let fast_glob = require("fast-glob");
7
+ fast_glob = require_rolldown_runtime.__toESM(fast_glob, 1);
8
+ let lodash_kebabcase = require("lodash.kebabcase");
9
+ lodash_kebabcase = require_rolldown_runtime.__toESM(lodash_kebabcase, 1);
10
+ //#region src/output.ts
11
11
  /**
12
- * The backend a project gets when it says nothing, by where it deploys.
12
+ * Where the CLI's progress lines go.
13
13
  *
14
- * Flat defaults could not be right for both: `upstash` on a single box means a
15
- * SaaS round-trip for a cache the database could have held, and `minio` on AWS
16
- * means running a bucket beside S3. So the default is a function of the target,
17
- * and an app that says nothing gets the obvious answer in both places — which
18
- * is the whole of what "zero config" can mean once there is more than one
19
- * target.
14
+ * Commands write their progress through `output` rather than `console`. Run
15
+ * from the terminal that is the same thing. Run inside `deploy()`, each line
16
+ * goes to the run that wrote it instead — as an event its caller can iterate,
17
+ * and to the logger it was handed — so a deploy embedded in another program
18
+ * does not print over that program's own output.
20
19
  *
21
- * `server` covers Dokploy and a bare host alike: the question these answer is
22
- * whether the app is next to a managed cloud or next to its own containers, and
23
- * on that question the two are the same.
24
- *
25
- * A per-construct, per-stage override is the layer above this — see
26
- * `constructs-outstanding.md` — so two buckets in one app can differ. This is
27
- * only what happens when nobody has said anything at all.
20
+ * Carried by `AsyncLocalStorage` rather than passed down, because the lines
21
+ * come from everywhere a deploy reaches — the Dockerfile generator, the env
22
+ * sniffer, construct discovery — and two deploys running in one process must
23
+ * not hear each other.
28
24
  */
29
- const DEFAULT_CACHE = {
30
- aws: "upstash",
31
- server: "db"
32
- };
33
- /** Where a bucket lives when nobody said — see {@link DEFAULT_CACHE}. */
34
- const DEFAULT_STORAGE = {
35
- aws: "s3",
36
- server: "minio"
37
- };
25
+ const current = new node_async_hooks.AsyncLocalStorage();
26
+ /** Runs `fn` with every line written through `output` sent to `sink`. */
27
+ function withOutput(sink, fn) {
28
+ return current.run(sink, fn);
29
+ }
30
+ function write(level, fallback) {
31
+ return (...args) => {
32
+ const sink = current.getStore();
33
+ if (sink) sink(level, (0, node_util.format)(...args));
34
+ else fallback(...args);
35
+ };
36
+ }
38
37
  /**
39
- * Who delivers mail when nobody said.
40
- *
41
- * Flat, unlike the others, and deliberately: mail is a SaaS on every target.
42
- * There is no self-hosted preset to default a container deploy to — Mailpit is
43
- * a development inbox, not a sender — so `server` has no answer of its own to
44
- * give and would only be `ses` written twice.
38
+ * `console`, for the methods the CLI logs through — routed to the current
39
+ * run's sink when there is one.
45
40
  */
46
- const DEFAULT_EMAIL = "ses";
47
-
41
+ const output = {
42
+ log: write("info", (...args) => console.log(...args)),
43
+ info: write("info", (...args) => console.info(...args)),
44
+ warn: write("warn", (...args) => console.warn(...args)),
45
+ error: write("error", (...args) => console.error(...args))
46
+ };
48
47
  //#endregion
49
48
  //#region src/generators/Generator.ts
50
49
  /**
@@ -68,13 +67,8 @@ var ConstructGenerator = class {
68
67
  return generator.build(context, constructs, outputDir, options);
69
68
  }
70
69
  async load(patterns, cwd = process.cwd(), bustCache = false) {
71
- const logger$1 = console;
72
- let globPatterns;
73
- let partitionFn;
74
- if (isPartitionedRoutes(patterns)) {
75
- globPatterns = Array.isArray(patterns.paths) ? patterns.paths : [patterns.paths];
76
- partitionFn = patterns.partition;
77
- } else globPatterns = Array.isArray(patterns) ? patterns : patterns ? [patterns] : [];
70
+ const logger = console;
71
+ const globPatterns = Array.isArray(patterns) ? patterns : patterns ? [patterns] : [];
78
72
  const files = fast_glob.default.stream(globPatterns, {
79
73
  cwd,
80
74
  absolute: true
@@ -83,33 +77,49 @@ var ConstructGenerator = class {
83
77
  const constructs = [];
84
78
  for await (const f of files) try {
85
79
  const file = f.toString();
86
- const importPath = bustCache ? `${file}?t=${Date.now()}` : file;
87
- const module$1 = await import(importPath);
88
- const partition = partitionFn ? partitionFn(file) : void 0;
89
- for (const [key, construct] of Object.entries(module$1)) if (this.isConstruct(construct)) constructs.push({
80
+ const module = await (bustCache ? import(`${file}?t=${Date.now()}`) : import(file));
81
+ for (const [key, construct] of Object.entries(module)) if (this.isConstruct(construct)) constructs.push({
90
82
  key,
91
83
  name: (0, lodash_kebabcase.default)(key),
92
84
  construct,
93
85
  path: {
94
86
  absolute: file,
95
87
  relative: (0, node_path.relative)(process.cwd(), file)
96
- },
97
- partition
88
+ }
98
89
  });
99
90
  } catch (error) {
100
91
  const err = error;
101
- logger$1.error(`Failed to load ${f}: ${err.message}`);
102
- if (err.stack) logger$1.error(err.stack);
92
+ logger.error(`Failed to load ${f}: ${err.message}`);
93
+ if (err.stack) logger.error(err.stack);
103
94
  throw error;
104
95
  }
105
96
  return constructs;
106
97
  }
107
98
  };
108
-
109
99
  //#endregion
110
100
  //#region src/reconcile/discover.ts
111
- /** Matches the rest of the CLI, which logs through `console` directly. */
112
- const logger = console;
101
+ /**
102
+ * Discovery — one glob, one structural test.
103
+ *
104
+ * A glob per kind is the same specialness the construct model removes, and
105
+ * resources have no kind to be listed under: a declared `ObjectStorage` would
106
+ * never be found by `routes:` or `crons:`. So there is one `constructs` glob,
107
+ * every export of every matching module is inspected, and the per-kind
108
+ * `isConstruct` checks collapse into a single question — does it have an id and
109
+ * can it declare?
110
+ *
111
+ * Structural rather than `instanceof` on purpose. A construct from a different
112
+ * copy of `@geekmidas/constructs` — a linked workspace, two versions in a
113
+ * lockfile — is still a construct, and `instanceof` is exactly the check that
114
+ * says otherwise.
115
+ */
116
+ var discover_exports = /* @__PURE__ */ require_rolldown_runtime.__exportAll({
117
+ DuplicateConstruct: () => DuplicateConstruct,
118
+ discover: () => discover,
119
+ isDeclarable: () => isDeclarable
120
+ });
121
+ /** `console`, or the deploy run discovering the manifest. */
122
+ const logger = output;
113
123
  /**
114
124
  * Whether a module export is a construct.
115
125
  *
@@ -160,13 +170,17 @@ async function discover(options) {
160
170
  for await (const found of files) {
161
171
  matched++;
162
172
  const file = found.toString();
163
- const module$1 = await (bustCache ? import(`${file}?t=${Date.now()}`) : import(file));
164
- for (const [exportName, exported] of Object.entries(module$1)) {
165
- if (!isDeclarable(exported)) continue;
173
+ const module = await (bustCache ? import(`${file}?t=${Date.now()}`) : import(file));
174
+ for (const [exportName, exported] of Object.entries(module)) {
175
+ if (!isDeclarable(exported)) {
176
+ if (options.runnables) recordRunnable(options.runnables, exported);
177
+ continue;
178
+ }
166
179
  if (seen.has(exported)) continue;
167
180
  seen.add(exported);
181
+ if (options.runnables && typeof exported.owner === "string") recordRunnable(options.runnables, exported);
168
182
  for (const declaration of exported.declare()) {
169
- const id = (0, __geekmidas_manifest.canonicalId)(declaration.id);
183
+ const id = (0, _geekmidas_manifest.canonicalId)(declaration.id);
170
184
  const source = (0, node_path.relative)(cwd, file);
171
185
  const claimed = sources[id];
172
186
  if (claimed !== void 0 && claimed !== source) throw new DuplicateConstruct(id, [claimed, source]);
@@ -177,16 +191,36 @@ async function discover(options) {
177
191
  sources[id] = source;
178
192
  if (out) out[id] = {
179
193
  file,
180
- exportName
194
+ exportName,
195
+ construct: exported
181
196
  };
182
197
  }
183
198
  }
184
199
  }
185
- (0, __geekmidas_manifest.assertDerivations)(manifest);
200
+ (0, _geekmidas_manifest.assertDerivations)(manifest);
186
201
  warnIfNothingFound(globs, matched, Object.keys(manifest).length);
187
202
  return manifest;
188
203
  }
189
204
  /**
205
+ * Record a runnable's edges under the construct that owns it — the surface an
206
+ * endpoint was built from, or the worker a cron or subscriber was. Anything
207
+ * with no owner, or that is not a runnable at all, is left alone.
208
+ */
209
+ function recordRunnable(runnables, exported) {
210
+ if (typeof exported !== "object" || exported === null) return;
211
+ const runnable = exported;
212
+ const owner = typeof runnable.surface?.id === "string" ? runnable.surface.id : typeof runnable.owner === "string" ? runnable.owner : void 0;
213
+ if (!owner || !Array.isArray(runnable.constructs)) return;
214
+ const key = (0, _geekmidas_manifest.canonicalId)(owner);
215
+ const edges = runnables[key] ?? [];
216
+ runnables[key] = edges;
217
+ for (const id of runnable.constructs) {
218
+ if (typeof id !== "string") continue;
219
+ const target = (0, _geekmidas_manifest.canonicalId)(id);
220
+ if (!edges.includes(target)) edges.push(target);
221
+ }
222
+ }
223
+ /**
190
224
  * Say so when a glob was configured and found nothing.
191
225
  *
192
226
  * The glob is not a filter over declarations already known — it is *how they
@@ -224,48 +258,42 @@ var DuplicateConstruct = class extends Error {
224
258
  this.sources = sources;
225
259
  }
226
260
  };
227
-
228
261
  //#endregion
229
- Object.defineProperty(exports, 'ConstructGenerator', {
230
- enumerable: true,
231
- get: function () {
232
- return ConstructGenerator;
233
- }
234
- });
235
- Object.defineProperty(exports, 'DEFAULT_CACHE', {
236
- enumerable: true,
237
- get: function () {
238
- return DEFAULT_CACHE;
239
- }
262
+ Object.defineProperty(exports, "ConstructGenerator", {
263
+ enumerable: true,
264
+ get: function() {
265
+ return ConstructGenerator;
266
+ }
240
267
  });
241
- Object.defineProperty(exports, 'DEFAULT_EMAIL', {
242
- enumerable: true,
243
- get: function () {
244
- return DEFAULT_EMAIL;
245
- }
268
+ Object.defineProperty(exports, "discover", {
269
+ enumerable: true,
270
+ get: function() {
271
+ return discover;
272
+ }
246
273
  });
247
- Object.defineProperty(exports, 'DEFAULT_STORAGE', {
248
- enumerable: true,
249
- get: function () {
250
- return DEFAULT_STORAGE;
251
- }
274
+ Object.defineProperty(exports, "discover_exports", {
275
+ enumerable: true,
276
+ get: function() {
277
+ return discover_exports;
278
+ }
252
279
  });
253
- Object.defineProperty(exports, 'discover', {
254
- enumerable: true,
255
- get: function () {
256
- return discover;
257
- }
280
+ Object.defineProperty(exports, "isDeclarable", {
281
+ enumerable: true,
282
+ get: function() {
283
+ return isDeclarable;
284
+ }
258
285
  });
259
- Object.defineProperty(exports, 'isDeclarable', {
260
- enumerable: true,
261
- get: function () {
262
- return isDeclarable;
263
- }
286
+ Object.defineProperty(exports, "output", {
287
+ enumerable: true,
288
+ get: function() {
289
+ return output;
290
+ }
264
291
  });
265
- Object.defineProperty(exports, 'isPartitionedRoutes', {
266
- enumerable: true,
267
- get: function () {
268
- return isPartitionedRoutes;
269
- }
292
+ Object.defineProperty(exports, "withOutput", {
293
+ enumerable: true,
294
+ get: function() {
295
+ return withOutput;
296
+ }
270
297
  });
271
- //# sourceMappingURL=discover-DTmFeloL.cjs.map
298
+
299
+ //# sourceMappingURL=discover-Bc-4eA_p.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discover-Bc-4eA_p.cjs","names":["AsyncLocalStorage","format","fg","kebabCase","relative","fg","canonicalId","relative"],"sources":["../src/output.ts","../src/generators/Generator.ts","../src/reconcile/discover.ts"],"sourcesContent":["/**\n * Where the CLI's progress lines go.\n *\n * Commands write their progress through `output` rather than `console`. Run\n * from the terminal that is the same thing. Run inside `deploy()`, each line\n * goes to the run that wrote it instead — as an event its caller can iterate,\n * and to the logger it was handed — so a deploy embedded in another program\n * does not print over that program's own output.\n *\n * Carried by `AsyncLocalStorage` rather than passed down, because the lines\n * come from everywhere a deploy reaches — the Dockerfile generator, the env\n * sniffer, construct discovery — and two deploys running in one process must\n * not hear each other.\n */\n\nimport { AsyncLocalStorage } from 'node:async_hooks';\nimport { format } from 'node:util';\n\n/** How loud a line is. */\nexport type OutputLevel = 'info' | 'warn' | 'error';\n\n/** Receives each line written while it is the current sink. */\nexport type OutputSink = (level: OutputLevel, message: string) => void;\n\nconst current = new AsyncLocalStorage<OutputSink>();\n\n/** Runs `fn` with every line written through `output` sent to `sink`. */\nexport function withOutput<T>(sink: OutputSink, fn: () => T): T {\n\treturn current.run(sink, fn);\n}\n\nfunction write(\n\tlevel: OutputLevel,\n\tfallback: (...args: unknown[]) => void,\n): (...args: unknown[]) => void {\n\treturn (...args) => {\n\t\tconst sink = current.getStore();\n\t\tif (sink) sink(level, format(...args));\n\t\telse fallback(...args);\n\t};\n}\n\n/**\n * `console`, for the methods the CLI logs through — routed to the current\n * run's sink when there is one.\n */\nexport const output = {\n\tlog: write('info', (...args) => console.log(...args)),\n\tinfo: write('info', (...args) => console.info(...args)),\n\twarn: write('warn', (...args) => console.warn(...args)),\n\terror: write('error', (...args) => console.error(...args)),\n};\n","import { relative } from 'node:path';\nimport type { Construct } from '@geekmidas/constructs';\nimport fg from 'fast-glob';\nimport kebabCase from 'lodash.kebabcase';\nimport type { BuildContext } from '../build/types';\nimport type { MainProvider, Routes } from '../types';\n\n/**\n * Zod v4 maintains a process-wide registry of schemas registered via\n * `.meta({ id })`. When we cache-bust user module imports (by appending a\n * `?t=timestamp` query), those modules re-execute and try to register the\n * same ids again, which throws `ID X already exists in the registry`.\n *\n * Clearing the registry in the CLI process is safe: the user's running\n * server lives in a subprocess and has its own isolated registry.\n *\n * Exported for tests.\n */\nexport function clearZodGlobalRegistry(): void {\n\tconst registry = (\n\t\tglobalThis as { __zod_globalRegistry?: { clear?: () => void } }\n\t).__zod_globalRegistry;\n\tif (registry && typeof registry.clear === 'function') {\n\t\tregistry.clear();\n\t}\n}\n\nexport interface GeneratorOptions {\n\t/** Where the build deploys: one Lambda per construct, or one process. */\n\ttarget?: MainProvider;\n\t/**\n\t * What a handler path in the manifest is relative to — the workspace root,\n\t * which is where `sst.config.ts` runs and resolves it from.\n\t */\n\troot?: string;\n\t[key: string]: any;\n}\n\nexport abstract class ConstructGenerator<T extends Construct, R = void> {\n\tabstract isConstruct(value: any): value is T;\n\n\tstatic async build<T extends Construct, R = void>(\n\t\tcontext: BuildContext,\n\t\toutputDir: string,\n\t\tgenerator: ConstructGenerator<T, R>,\n\t\tpatterns?: Routes,\n\t\toptions?: GeneratorOptions,\n\t): Promise<R> {\n\t\tconst constructs = await generator.load(patterns);\n\t\treturn generator.build(context, constructs, outputDir, options);\n\t}\n\n\tabstract build(\n\t\tcontext: BuildContext,\n\t\tconstructs: GeneratedConstruct<T>[],\n\t\toutputDir: string,\n\t\toptions?: GeneratorOptions,\n\t): Promise<R>;\n\n\tasync load(\n\t\tpatterns?: Routes,\n\t\tcwd = process.cwd(),\n\t\tbustCache = false,\n\t): Promise<GeneratedConstruct<T>[]> {\n\t\tconst logger = console;\n\n\t\tconst globPatterns = Array.isArray(patterns)\n\t\t\t? patterns\n\t\t\t: patterns\n\t\t\t\t? [patterns]\n\t\t\t\t: [];\n\n\t\t// Find all files\n\t\tconst files = fg.stream(globPatterns, {\n\t\t\tcwd,\n\t\t\tabsolute: true,\n\t\t});\n\n\t\t// Cache-busted re-imports re-execute user modules, which would try to\n\t\t// re-register Zod schemas with the same `.meta({ id })`. Clear the\n\t\t// global registry once per load to prevent duplicate-id errors.\n\t\tif (bustCache) {\n\t\t\tclearZodGlobalRegistry();\n\t\t}\n\n\t\t// Load constructs\n\t\tconst constructs: GeneratedConstruct<T>[] = [];\n\n\t\tfor await (const f of files) {\n\t\t\ttry {\n\t\t\t\tconst file = f.toString();\n\t\t\t\t// Append cache-busting query param to force re-import of changed modules\n\t\t\t\tconst importPath = bustCache ? `${file}?t=${Date.now()}` : file;\n\t\t\t\tconst module = await import(importPath);\n\n\t\t\t\t// Check all exports for constructs\n\t\t\t\tfor (const [key, construct] of Object.entries(module)) {\n\t\t\t\t\tif (this.isConstruct(construct)) {\n\t\t\t\t\t\tconstructs.push({\n\t\t\t\t\t\t\tkey,\n\t\t\t\t\t\t\tname: kebabCase(key),\n\t\t\t\t\t\t\tconstruct,\n\t\t\t\t\t\t\tpath: {\n\t\t\t\t\t\t\t\tabsolute: file,\n\t\t\t\t\t\t\t\trelative: relative(process.cwd(), file),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tconst err = error as Error;\n\t\t\t\tlogger.error(`Failed to load ${f}: ${err.message}`);\n\t\t\t\tif (err.stack) {\n\t\t\t\t\tlogger.error(err.stack);\n\t\t\t\t}\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t}\n\n\t\treturn constructs;\n\t}\n}\n\nexport interface GeneratedConstruct<T extends Construct> {\n\tkey: string;\n\tname: string;\n\tconstruct: T;\n\tpath: {\n\t\tabsolute: string;\n\t\trelative: string;\n\t};\n}\n","/**\n * Discovery — one glob, one structural test.\n *\n * A glob per kind is the same specialness the construct model removes, and\n * resources have no kind to be listed under: a declared `ObjectStorage` would\n * never be found by `routes:` or `crons:`. So there is one `constructs` glob,\n * every export of every matching module is inspected, and the per-kind\n * `isConstruct` checks collapse into a single question — does it have an id and\n * can it declare?\n *\n * Structural rather than `instanceof` on purpose. A construct from a different\n * copy of `@geekmidas/constructs` — a linked workspace, two versions in a\n * lockfile — is still a construct, and `instanceof` is exactly the check that\n * says otherwise.\n */\n\nimport { relative } from 'node:path';\nimport {\n\tassertDerivations,\n\ttype ConstructManifest,\n\tcanonicalId,\n\ttype Declaration,\n} from '@geekmidas/manifest';\nimport fg from 'fast-glob';\nimport { clearZodGlobalRegistry } from '../generators/Generator';\nimport { output } from '../output';\n\n/** `console`, or the deploy run discovering the manifest. */\nconst logger = output;\n\n/** The construct face discovery needs: an id, and the ability to declare. */\ninterface Declarable {\n\tid: string;\n\tdeclare(): Declaration[];\n}\n\n/**\n * Whether a module export is a construct.\n *\n * Deliberately loose about what else it carries — a construct that also has a\n * `service` is still a construct, and requiring one would exclude the kinds that\n * own no address.\n */\nexport function isDeclarable(value: unknown): value is Declarable {\n\tif (typeof value !== 'object' || value === null) return false;\n\n\tconst candidate = value as Partial<Declarable>;\n\n\treturn (\n\t\ttypeof candidate.id === 'string' &&\n\t\tcandidate.id.length > 0 &&\n\t\ttypeof candidate.declare === 'function'\n\t);\n}\n\nexport interface DiscoverOptions {\n\t/** The glob(s) to search. One pattern, not one per kind. */\n\tpatterns: string | readonly string[];\n\tcwd?: string;\n\t/**\n\t * Re-import changed modules, for the dev watcher.\n\t *\n\t * A single glob makes discovery more central, not less: a new construct file\n\t * has to be picked up on `add`, not only on `change`.\n\t */\n\tbustCache?: boolean;\n\t/**\n\t * Filled in with where each construct was found, when provided.\n\t *\n\t * Discovery is the only thing that knows: it globbed the files and imported\n\t * them. Everything downstream that needs to *write* an import — the build,\n\t * generating a server entry that reads a surface's logger — would otherwise\n\t * have to be told the path in config, which is the string this removes.\n\t *\n\t * An out-parameter rather than a second return value so that every existing\n\t * caller, which wants the manifest and nothing else, is unchanged.\n\t */\n\tsources?: Record<string, ConstructSource>;\n\t/**\n\t * Filled in, when provided, with the ids each owner's runnables declared an\n\t * edge to — keyed by the surface an endpoint was built from, or the worker\n\t * a cron or subscriber was.\n\t *\n\t * A runnable is not a declaration: a surface's endpoints are found by the\n\t * glob, not listed by the surface, so its node says `endpoints: []` until a\n\t * build folds the routes in. Anything deciding what an app's process reaches\n\t * — which keys its container is given — needs those edges before any build,\n\t * and discovery is already importing the files they are in.\n\t */\n\trunnables?: Record<string, string[]>;\n}\n\n/** Where a construct was declared, and under what name. */\nexport interface ConstructSource {\n\t/** Absolute path to the module that exported it. */\n\tfile: string;\n\t/** The name it was exported as — what an import statement has to say. */\n\texportName: string;\n\t/**\n\t * The exported construct itself.\n\t *\n\t * What a declaration cannot say — whether it serves itself — the object can\n\t * be asked, and discovery already imported it.\n\t */\n\tconstruct: unknown;\n}\n\n/**\n * Build the construct manifest for a project.\n *\n * Runs the manifest's own validation before returning, so an app is wrong here\n * — where the error names a file — rather than at deploy.\n *\n * @throws {DuplicateConstruct} when two exports claim one id.\n */\nexport async function discover(\n\toptions: DiscoverOptions,\n): Promise<ConstructManifest> {\n\tconst {\n\t\tpatterns,\n\t\tcwd = process.cwd(),\n\t\tbustCache = false,\n\t\tsources: out,\n\t} = options;\n\n\t// Re-importing user modules re-executes them, and Zod v4 throws on a\n\t// re-registered `.meta({ id })`. Same reason the generators clear it.\n\tif (bustCache) clearZodGlobalRegistry();\n\n\tconst manifest: Record<string, Declaration> = {};\n\t/** Which file declared each id, for the error when two of them do. */\n\tconst sources: Record<string, string> = {};\n\t/**\n\t * Constructs already seen, by identity.\n\t *\n\t * A re-export is the *same object* reached through a second file — ESM\n\t * bindings are live, so `export * from './database.js'` hands back the\n\t * binding rather than a copy. Without this, a barrel file made every\n\t * construct in it appear declared twice, and `constructs/index.ts` is the\n\t * first thing anyone writes in a shared folder.\n\t *\n\t * Identity rather than file is also the more honest rule: what may not\n\t * happen twice is two *different* constructs claiming one id, and that is\n\t * still an error below.\n\t */\n\tconst seen = new WeakSet<object>();\n\n\tconst globs = Array.isArray(patterns) ? [...patterns] : [patterns as string];\n\tconst files = fg.stream(globs, { cwd, absolute: true });\n\n\t/** Matched files, for the diagnostic below. */\n\tlet matched = 0;\n\n\tfor await (const found of files) {\n\t\tmatched++;\n\t\tconst file = found.toString();\n\t\tconst module = await import(bustCache ? `${file}?t=${Date.now()}` : file);\n\n\t\tfor (const [exportName, exported] of Object.entries(module)) {\n\t\t\tif (!isDeclarable(exported)) {\n\t\t\t\tif (options.runnables) recordRunnable(options.runnables, exported);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// The same construct, reached again through a re-export. Skipped\n\t\t\t// rather than re-declared: it has already claimed its id, from the\n\t\t\t// file that defined it.\n\t\t\tif (seen.has(exported as object)) continue;\n\t\t\tseen.add(exported as object);\n\n\t\t\t// A construct that is also something a process runs — a queue and its\n\t\t\t// consumer, built from a worker — reaches what it depends on through\n\t\t\t// that process, exactly as an endpoint or a cron does.\n\t\t\tif (\n\t\t\t\toptions.runnables &&\n\t\t\t\ttypeof (exported as { owner?: unknown }).owner === 'string'\n\t\t\t) {\n\t\t\t\trecordRunnable(options.runnables, exported);\n\t\t\t}\n\n\t\t\tfor (const declaration of exported.declare()) {\n\t\t\t\t// Canonicalise here too: a construct built by hand rather than through\n\t\t\t\t// a constructor is still subject to the same identity rule.\n\t\t\t\tconst id = canonicalId(declaration.id);\n\t\t\t\tconst source = relative(cwd, file);\n\n\t\t\t\tconst claimed = sources[id];\n\t\t\t\tif (claimed !== undefined && claimed !== source) {\n\t\t\t\t\tthrow new DuplicateConstruct(id, [claimed, source]);\n\t\t\t\t}\n\n\t\t\t\tmanifest[id] = { ...declaration, id };\n\t\t\t\tsources[id] = source;\n\t\t\t\tif (out) out[id] = { file, exportName, construct: exported };\n\t\t\t}\n\t\t}\n\t}\n\n\t// Reference integrity before anyone reads it — a schema tenant naming a\n\t// database that was deleted is a manifest error, not a reconcile failure.\n\tassertDerivations(manifest);\n\n\twarnIfNothingFound(globs, matched, Object.keys(manifest).length);\n\n\treturn manifest;\n}\n\n/**\n * Record a runnable's edges under the construct that owns it — the surface an\n * endpoint was built from, or the worker a cron or subscriber was. Anything\n * with no owner, or that is not a runnable at all, is left alone.\n */\nfunction recordRunnable(\n\trunnables: Record<string, string[]>,\n\texported: unknown,\n): void {\n\tif (typeof exported !== 'object' || exported === null) return;\n\n\tconst runnable = exported as {\n\t\tsurface?: { id?: unknown };\n\t\towner?: unknown;\n\t\tconstructs?: unknown;\n\t};\n\tconst owner =\n\t\ttypeof runnable.surface?.id === 'string'\n\t\t\t? runnable.surface.id\n\t\t\t: typeof runnable.owner === 'string'\n\t\t\t\t? runnable.owner\n\t\t\t\t: undefined;\n\tif (!owner || !Array.isArray(runnable.constructs)) return;\n\n\tconst key = canonicalId(owner);\n\tconst edges = runnables[key] ?? [];\n\trunnables[key] = edges;\n\tfor (const id of runnable.constructs) {\n\t\tif (typeof id !== 'string') continue;\n\t\tconst target = canonicalId(id);\n\t\tif (!edges.includes(target)) edges.push(target);\n\t}\n}\n\n/**\n * Say so when a glob was configured and found nothing.\n *\n * The glob is not a filter over declarations already known — it is *how they\n * are found*, by importing what it matches. So a file it misses is a\n * declaration that does not exist, and every symptom of that appears somewhere\n * other than the cause: no container starts, no env key is written, and the\n * application fails on first use against a resource it can see in its own\n * source.\n *\n * Nothing reported it before, because an unmatched file is indistinguishable\n * from a file nobody wrote. These two cases are the ones that are *not*\n * ambiguous — a glob was configured, so something was expected.\n *\n * Silent when no glob is configured at all: that is a project which has not\n * adopted constructs, and has nothing to be missing.\n */\nfunction warnIfNothingFound(\n\tglobs: readonly string[],\n\tmatched: number,\n\tdeclared: number,\n): void {\n\tif (globs.length === 0) return;\n\n\tif (matched === 0) {\n\t\tlogger.warn(\n\t\t\t`\\n⚠️ The constructs glob matched no files, so nothing was declared.\\n` +\n\t\t\t\t` Patterns: ${globs.join(', ')}\\n` +\n\t\t\t\t` Nothing will be provisioned — no containers, no env keys, no ` +\n\t\t\t\t`resources.\\n` +\n\t\t\t\t` A common cause is depth: '*.ts' matches one level, '**/*.ts' ` +\n\t\t\t\t`matches any.`,\n\t\t);\n\t\treturn;\n\t}\n\n\tif (declared === 0) {\n\t\tlogger.warn(\n\t\t\t`\\n⚠️ The constructs glob matched ${matched} file(s) but none declared ` +\n\t\t\t\t`anything.\\n` +\n\t\t\t\t` Patterns: ${globs.join(', ')}\\n` +\n\t\t\t\t` Discovery keeps exports with an 'id' that can 'declare()'. A ` +\n\t\t\t\t`construct that is\\n` +\n\t\t\t\t` built but never exported is invisible to it.`,\n\t\t);\n\t}\n}\n\n/** Two constructs claiming one id. */\nexport class DuplicateConstruct extends Error {\n\t/** The id claimed twice. */\n\treadonly id: string;\n\t/** The files that claimed it. */\n\treadonly sources: readonly string[];\n\n\tconstructor(id: string, sources: readonly string[]) {\n\t\tsuper('Two constructs declare the same id');\n\t\tthis.name = 'DuplicateConstruct';\n\t\tthis.id = id;\n\t\tthis.sources = sources;\n\t}\n}\n"],"mappings":"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"}
@@ -1,49 +1,47 @@
1
+ import { t as __exportAll } from "./rolldown-runtime-BhDjJH2R.mjs";
1
2
  import { relative } from "node:path";
3
+ import { AsyncLocalStorage } from "node:async_hooks";
4
+ import { format } from "node:util";
2
5
  import { assertDerivations, canonicalId } from "@geekmidas/manifest";
3
6
  import fg from "fast-glob";
4
7
  import kebabCase$1 from "lodash.kebabcase";
5
-
6
- //#region src/types.ts
7
- function isPartitionedRoutes(routes) {
8
- return typeof routes === "object" && routes !== null && !Array.isArray(routes) && "paths" in routes;
9
- }
8
+ //#region src/output.ts
10
9
  /**
11
- * The backend a project gets when it says nothing, by where it deploys.
12
- *
13
- * Flat defaults could not be right for both: `upstash` on a single box means a
14
- * SaaS round-trip for a cache the database could have held, and `minio` on AWS
15
- * means running a bucket beside S3. So the default is a function of the target,
16
- * and an app that says nothing gets the obvious answer in both places — which
17
- * is the whole of what "zero config" can mean once there is more than one
18
- * target.
10
+ * Where the CLI's progress lines go.
19
11
  *
20
- * `server` covers Dokploy and a bare host alike: the question these answer is
21
- * whether the app is next to a managed cloud or next to its own containers, and
22
- * on that question the two are the same.
12
+ * Commands write their progress through `output` rather than `console`. Run
13
+ * from the terminal that is the same thing. Run inside `deploy()`, each line
14
+ * goes to the run that wrote it instead — as an event its caller can iterate,
15
+ * and to the logger it was handed — so a deploy embedded in another program
16
+ * does not print over that program's own output.
23
17
  *
24
- * A per-construct, per-stage override is the layer above this — see
25
- * `constructs-outstanding.md` — so two buckets in one app can differ. This is
26
- * only what happens when nobody has said anything at all.
18
+ * Carried by `AsyncLocalStorage` rather than passed down, because the lines
19
+ * come from everywhere a deploy reaches — the Dockerfile generator, the env
20
+ * sniffer, construct discovery — and two deploys running in one process must
21
+ * not hear each other.
27
22
  */
28
- const DEFAULT_CACHE = {
29
- aws: "upstash",
30
- server: "db"
31
- };
32
- /** Where a bucket lives when nobody said — see {@link DEFAULT_CACHE}. */
33
- const DEFAULT_STORAGE = {
34
- aws: "s3",
35
- server: "minio"
36
- };
23
+ const current = new AsyncLocalStorage();
24
+ /** Runs `fn` with every line written through `output` sent to `sink`. */
25
+ function withOutput(sink, fn) {
26
+ return current.run(sink, fn);
27
+ }
28
+ function write(level, fallback) {
29
+ return (...args) => {
30
+ const sink = current.getStore();
31
+ if (sink) sink(level, format(...args));
32
+ else fallback(...args);
33
+ };
34
+ }
37
35
  /**
38
- * Who delivers mail when nobody said.
39
- *
40
- * Flat, unlike the others, and deliberately: mail is a SaaS on every target.
41
- * There is no self-hosted preset to default a container deploy to — Mailpit is
42
- * a development inbox, not a sender — so `server` has no answer of its own to
43
- * give and would only be `ses` written twice.
36
+ * `console`, for the methods the CLI logs through — routed to the current
37
+ * run's sink when there is one.
44
38
  */
45
- const DEFAULT_EMAIL = "ses";
46
-
39
+ const output = {
40
+ log: write("info", (...args) => console.log(...args)),
41
+ info: write("info", (...args) => console.info(...args)),
42
+ warn: write("warn", (...args) => console.warn(...args)),
43
+ error: write("error", (...args) => console.error(...args))
44
+ };
47
45
  //#endregion
48
46
  //#region src/generators/Generator.ts
49
47
  /**
@@ -67,13 +65,8 @@ var ConstructGenerator = class {
67
65
  return generator.build(context, constructs, outputDir, options);
68
66
  }
69
67
  async load(patterns, cwd = process.cwd(), bustCache = false) {
70
- const logger$1 = console;
71
- let globPatterns;
72
- let partitionFn;
73
- if (isPartitionedRoutes(patterns)) {
74
- globPatterns = Array.isArray(patterns.paths) ? patterns.paths : [patterns.paths];
75
- partitionFn = patterns.partition;
76
- } else globPatterns = Array.isArray(patterns) ? patterns : patterns ? [patterns] : [];
68
+ const logger = console;
69
+ const globPatterns = Array.isArray(patterns) ? patterns : patterns ? [patterns] : [];
77
70
  const files = fg.stream(globPatterns, {
78
71
  cwd,
79
72
  absolute: true
@@ -82,9 +75,7 @@ var ConstructGenerator = class {
82
75
  const constructs = [];
83
76
  for await (const f of files) try {
84
77
  const file = f.toString();
85
- const importPath = bustCache ? `${file}?t=${Date.now()}` : file;
86
- const module = await import(importPath);
87
- const partition = partitionFn ? partitionFn(file) : void 0;
78
+ const module = await (bustCache ? import(`${file}?t=${Date.now()}`) : import(file));
88
79
  for (const [key, construct] of Object.entries(module)) if (this.isConstruct(construct)) constructs.push({
89
80
  key,
90
81
  name: kebabCase$1(key),
@@ -92,23 +83,41 @@ var ConstructGenerator = class {
92
83
  path: {
93
84
  absolute: file,
94
85
  relative: relative(process.cwd(), file)
95
- },
96
- partition
86
+ }
97
87
  });
98
88
  } catch (error) {
99
89
  const err = error;
100
- logger$1.error(`Failed to load ${f}: ${err.message}`);
101
- if (err.stack) logger$1.error(err.stack);
90
+ logger.error(`Failed to load ${f}: ${err.message}`);
91
+ if (err.stack) logger.error(err.stack);
102
92
  throw error;
103
93
  }
104
94
  return constructs;
105
95
  }
106
96
  };
107
-
108
97
  //#endregion
109
98
  //#region src/reconcile/discover.ts
110
- /** Matches the rest of the CLI, which logs through `console` directly. */
111
- const logger = console;
99
+ /**
100
+ * Discovery — one glob, one structural test.
101
+ *
102
+ * A glob per kind is the same specialness the construct model removes, and
103
+ * resources have no kind to be listed under: a declared `ObjectStorage` would
104
+ * never be found by `routes:` or `crons:`. So there is one `constructs` glob,
105
+ * every export of every matching module is inspected, and the per-kind
106
+ * `isConstruct` checks collapse into a single question — does it have an id and
107
+ * can it declare?
108
+ *
109
+ * Structural rather than `instanceof` on purpose. A construct from a different
110
+ * copy of `@geekmidas/constructs` — a linked workspace, two versions in a
111
+ * lockfile — is still a construct, and `instanceof` is exactly the check that
112
+ * says otherwise.
113
+ */
114
+ var discover_exports = /* @__PURE__ */ __exportAll({
115
+ DuplicateConstruct: () => DuplicateConstruct,
116
+ discover: () => discover,
117
+ isDeclarable: () => isDeclarable
118
+ });
119
+ /** `console`, or the deploy run discovering the manifest. */
120
+ const logger = output;
112
121
  /**
113
122
  * Whether a module export is a construct.
114
123
  *
@@ -161,9 +170,13 @@ async function discover(options) {
161
170
  const file = found.toString();
162
171
  const module = await (bustCache ? import(`${file}?t=${Date.now()}`) : import(file));
163
172
  for (const [exportName, exported] of Object.entries(module)) {
164
- if (!isDeclarable(exported)) continue;
173
+ if (!isDeclarable(exported)) {
174
+ if (options.runnables) recordRunnable(options.runnables, exported);
175
+ continue;
176
+ }
165
177
  if (seen.has(exported)) continue;
166
178
  seen.add(exported);
179
+ if (options.runnables && typeof exported.owner === "string") recordRunnable(options.runnables, exported);
167
180
  for (const declaration of exported.declare()) {
168
181
  const id = canonicalId(declaration.id);
169
182
  const source = relative(cwd, file);
@@ -176,7 +189,8 @@ async function discover(options) {
176
189
  sources[id] = source;
177
190
  if (out) out[id] = {
178
191
  file,
179
- exportName
192
+ exportName,
193
+ construct: exported
180
194
  };
181
195
  }
182
196
  }
@@ -186,6 +200,25 @@ async function discover(options) {
186
200
  return manifest;
187
201
  }
188
202
  /**
203
+ * Record a runnable's edges under the construct that owns it — the surface an
204
+ * endpoint was built from, or the worker a cron or subscriber was. Anything
205
+ * with no owner, or that is not a runnable at all, is left alone.
206
+ */
207
+ function recordRunnable(runnables, exported) {
208
+ if (typeof exported !== "object" || exported === null) return;
209
+ const runnable = exported;
210
+ const owner = typeof runnable.surface?.id === "string" ? runnable.surface.id : typeof runnable.owner === "string" ? runnable.owner : void 0;
211
+ if (!owner || !Array.isArray(runnable.constructs)) return;
212
+ const key = canonicalId(owner);
213
+ const edges = runnables[key] ?? [];
214
+ runnables[key] = edges;
215
+ for (const id of runnable.constructs) {
216
+ if (typeof id !== "string") continue;
217
+ const target = canonicalId(id);
218
+ if (!edges.includes(target)) edges.push(target);
219
+ }
220
+ }
221
+ /**
189
222
  * Say so when a glob was configured and found nothing.
190
223
  *
191
224
  * The glob is not a filter over declarations already known — it is *how they
@@ -223,7 +256,7 @@ var DuplicateConstruct = class extends Error {
223
256
  this.sources = sources;
224
257
  }
225
258
  };
226
-
227
259
  //#endregion
228
- export { ConstructGenerator, DEFAULT_CACHE, DEFAULT_EMAIL, DEFAULT_STORAGE, discover, isDeclarable, isPartitionedRoutes };
229
- //# sourceMappingURL=discover-CAlFgYec.mjs.map
260
+ export { output as a, ConstructGenerator as i, discover_exports as n, withOutput as o, isDeclarable as r, discover as t };
261
+
262
+ //# sourceMappingURL=discover-FrYvzkeC.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discover-FrYvzkeC.mjs","names":["kebabCase"],"sources":["../src/output.ts","../src/generators/Generator.ts","../src/reconcile/discover.ts"],"sourcesContent":["/**\n * Where the CLI's progress lines go.\n *\n * Commands write their progress through `output` rather than `console`. Run\n * from the terminal that is the same thing. Run inside `deploy()`, each line\n * goes to the run that wrote it instead — as an event its caller can iterate,\n * and to the logger it was handed — so a deploy embedded in another program\n * does not print over that program's own output.\n *\n * Carried by `AsyncLocalStorage` rather than passed down, because the lines\n * come from everywhere a deploy reaches — the Dockerfile generator, the env\n * sniffer, construct discovery — and two deploys running in one process must\n * not hear each other.\n */\n\nimport { AsyncLocalStorage } from 'node:async_hooks';\nimport { format } from 'node:util';\n\n/** How loud a line is. */\nexport type OutputLevel = 'info' | 'warn' | 'error';\n\n/** Receives each line written while it is the current sink. */\nexport type OutputSink = (level: OutputLevel, message: string) => void;\n\nconst current = new AsyncLocalStorage<OutputSink>();\n\n/** Runs `fn` with every line written through `output` sent to `sink`. */\nexport function withOutput<T>(sink: OutputSink, fn: () => T): T {\n\treturn current.run(sink, fn);\n}\n\nfunction write(\n\tlevel: OutputLevel,\n\tfallback: (...args: unknown[]) => void,\n): (...args: unknown[]) => void {\n\treturn (...args) => {\n\t\tconst sink = current.getStore();\n\t\tif (sink) sink(level, format(...args));\n\t\telse fallback(...args);\n\t};\n}\n\n/**\n * `console`, for the methods the CLI logs through — routed to the current\n * run's sink when there is one.\n */\nexport const output = {\n\tlog: write('info', (...args) => console.log(...args)),\n\tinfo: write('info', (...args) => console.info(...args)),\n\twarn: write('warn', (...args) => console.warn(...args)),\n\terror: write('error', (...args) => console.error(...args)),\n};\n","import { relative } from 'node:path';\nimport type { Construct } from '@geekmidas/constructs';\nimport fg from 'fast-glob';\nimport kebabCase from 'lodash.kebabcase';\nimport type { BuildContext } from '../build/types';\nimport type { MainProvider, Routes } from '../types';\n\n/**\n * Zod v4 maintains a process-wide registry of schemas registered via\n * `.meta({ id })`. When we cache-bust user module imports (by appending a\n * `?t=timestamp` query), those modules re-execute and try to register the\n * same ids again, which throws `ID X already exists in the registry`.\n *\n * Clearing the registry in the CLI process is safe: the user's running\n * server lives in a subprocess and has its own isolated registry.\n *\n * Exported for tests.\n */\nexport function clearZodGlobalRegistry(): void {\n\tconst registry = (\n\t\tglobalThis as { __zod_globalRegistry?: { clear?: () => void } }\n\t).__zod_globalRegistry;\n\tif (registry && typeof registry.clear === 'function') {\n\t\tregistry.clear();\n\t}\n}\n\nexport interface GeneratorOptions {\n\t/** Where the build deploys: one Lambda per construct, or one process. */\n\ttarget?: MainProvider;\n\t/**\n\t * What a handler path in the manifest is relative to — the workspace root,\n\t * which is where `sst.config.ts` runs and resolves it from.\n\t */\n\troot?: string;\n\t[key: string]: any;\n}\n\nexport abstract class ConstructGenerator<T extends Construct, R = void> {\n\tabstract isConstruct(value: any): value is T;\n\n\tstatic async build<T extends Construct, R = void>(\n\t\tcontext: BuildContext,\n\t\toutputDir: string,\n\t\tgenerator: ConstructGenerator<T, R>,\n\t\tpatterns?: Routes,\n\t\toptions?: GeneratorOptions,\n\t): Promise<R> {\n\t\tconst constructs = await generator.load(patterns);\n\t\treturn generator.build(context, constructs, outputDir, options);\n\t}\n\n\tabstract build(\n\t\tcontext: BuildContext,\n\t\tconstructs: GeneratedConstruct<T>[],\n\t\toutputDir: string,\n\t\toptions?: GeneratorOptions,\n\t): Promise<R>;\n\n\tasync load(\n\t\tpatterns?: Routes,\n\t\tcwd = process.cwd(),\n\t\tbustCache = false,\n\t): Promise<GeneratedConstruct<T>[]> {\n\t\tconst logger = console;\n\n\t\tconst globPatterns = Array.isArray(patterns)\n\t\t\t? patterns\n\t\t\t: patterns\n\t\t\t\t? [patterns]\n\t\t\t\t: [];\n\n\t\t// Find all files\n\t\tconst files = fg.stream(globPatterns, {\n\t\t\tcwd,\n\t\t\tabsolute: true,\n\t\t});\n\n\t\t// Cache-busted re-imports re-execute user modules, which would try to\n\t\t// re-register Zod schemas with the same `.meta({ id })`. Clear the\n\t\t// global registry once per load to prevent duplicate-id errors.\n\t\tif (bustCache) {\n\t\t\tclearZodGlobalRegistry();\n\t\t}\n\n\t\t// Load constructs\n\t\tconst constructs: GeneratedConstruct<T>[] = [];\n\n\t\tfor await (const f of files) {\n\t\t\ttry {\n\t\t\t\tconst file = f.toString();\n\t\t\t\t// Append cache-busting query param to force re-import of changed modules\n\t\t\t\tconst importPath = bustCache ? `${file}?t=${Date.now()}` : file;\n\t\t\t\tconst module = await import(importPath);\n\n\t\t\t\t// Check all exports for constructs\n\t\t\t\tfor (const [key, construct] of Object.entries(module)) {\n\t\t\t\t\tif (this.isConstruct(construct)) {\n\t\t\t\t\t\tconstructs.push({\n\t\t\t\t\t\t\tkey,\n\t\t\t\t\t\t\tname: kebabCase(key),\n\t\t\t\t\t\t\tconstruct,\n\t\t\t\t\t\t\tpath: {\n\t\t\t\t\t\t\t\tabsolute: file,\n\t\t\t\t\t\t\t\trelative: relative(process.cwd(), file),\n\t\t\t\t\t\t\t},\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch (error) {\n\t\t\t\tconst err = error as Error;\n\t\t\t\tlogger.error(`Failed to load ${f}: ${err.message}`);\n\t\t\t\tif (err.stack) {\n\t\t\t\t\tlogger.error(err.stack);\n\t\t\t\t}\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t}\n\n\t\treturn constructs;\n\t}\n}\n\nexport interface GeneratedConstruct<T extends Construct> {\n\tkey: string;\n\tname: string;\n\tconstruct: T;\n\tpath: {\n\t\tabsolute: string;\n\t\trelative: string;\n\t};\n}\n","/**\n * Discovery — one glob, one structural test.\n *\n * A glob per kind is the same specialness the construct model removes, and\n * resources have no kind to be listed under: a declared `ObjectStorage` would\n * never be found by `routes:` or `crons:`. So there is one `constructs` glob,\n * every export of every matching module is inspected, and the per-kind\n * `isConstruct` checks collapse into a single question — does it have an id and\n * can it declare?\n *\n * Structural rather than `instanceof` on purpose. A construct from a different\n * copy of `@geekmidas/constructs` — a linked workspace, two versions in a\n * lockfile — is still a construct, and `instanceof` is exactly the check that\n * says otherwise.\n */\n\nimport { relative } from 'node:path';\nimport {\n\tassertDerivations,\n\ttype ConstructManifest,\n\tcanonicalId,\n\ttype Declaration,\n} from '@geekmidas/manifest';\nimport fg from 'fast-glob';\nimport { clearZodGlobalRegistry } from '../generators/Generator';\nimport { output } from '../output';\n\n/** `console`, or the deploy run discovering the manifest. */\nconst logger = output;\n\n/** The construct face discovery needs: an id, and the ability to declare. */\ninterface Declarable {\n\tid: string;\n\tdeclare(): Declaration[];\n}\n\n/**\n * Whether a module export is a construct.\n *\n * Deliberately loose about what else it carries — a construct that also has a\n * `service` is still a construct, and requiring one would exclude the kinds that\n * own no address.\n */\nexport function isDeclarable(value: unknown): value is Declarable {\n\tif (typeof value !== 'object' || value === null) return false;\n\n\tconst candidate = value as Partial<Declarable>;\n\n\treturn (\n\t\ttypeof candidate.id === 'string' &&\n\t\tcandidate.id.length > 0 &&\n\t\ttypeof candidate.declare === 'function'\n\t);\n}\n\nexport interface DiscoverOptions {\n\t/** The glob(s) to search. One pattern, not one per kind. */\n\tpatterns: string | readonly string[];\n\tcwd?: string;\n\t/**\n\t * Re-import changed modules, for the dev watcher.\n\t *\n\t * A single glob makes discovery more central, not less: a new construct file\n\t * has to be picked up on `add`, not only on `change`.\n\t */\n\tbustCache?: boolean;\n\t/**\n\t * Filled in with where each construct was found, when provided.\n\t *\n\t * Discovery is the only thing that knows: it globbed the files and imported\n\t * them. Everything downstream that needs to *write* an import — the build,\n\t * generating a server entry that reads a surface's logger — would otherwise\n\t * have to be told the path in config, which is the string this removes.\n\t *\n\t * An out-parameter rather than a second return value so that every existing\n\t * caller, which wants the manifest and nothing else, is unchanged.\n\t */\n\tsources?: Record<string, ConstructSource>;\n\t/**\n\t * Filled in, when provided, with the ids each owner's runnables declared an\n\t * edge to — keyed by the surface an endpoint was built from, or the worker\n\t * a cron or subscriber was.\n\t *\n\t * A runnable is not a declaration: a surface's endpoints are found by the\n\t * glob, not listed by the surface, so its node says `endpoints: []` until a\n\t * build folds the routes in. Anything deciding what an app's process reaches\n\t * — which keys its container is given — needs those edges before any build,\n\t * and discovery is already importing the files they are in.\n\t */\n\trunnables?: Record<string, string[]>;\n}\n\n/** Where a construct was declared, and under what name. */\nexport interface ConstructSource {\n\t/** Absolute path to the module that exported it. */\n\tfile: string;\n\t/** The name it was exported as — what an import statement has to say. */\n\texportName: string;\n\t/**\n\t * The exported construct itself.\n\t *\n\t * What a declaration cannot say — whether it serves itself — the object can\n\t * be asked, and discovery already imported it.\n\t */\n\tconstruct: unknown;\n}\n\n/**\n * Build the construct manifest for a project.\n *\n * Runs the manifest's own validation before returning, so an app is wrong here\n * — where the error names a file — rather than at deploy.\n *\n * @throws {DuplicateConstruct} when two exports claim one id.\n */\nexport async function discover(\n\toptions: DiscoverOptions,\n): Promise<ConstructManifest> {\n\tconst {\n\t\tpatterns,\n\t\tcwd = process.cwd(),\n\t\tbustCache = false,\n\t\tsources: out,\n\t} = options;\n\n\t// Re-importing user modules re-executes them, and Zod v4 throws on a\n\t// re-registered `.meta({ id })`. Same reason the generators clear it.\n\tif (bustCache) clearZodGlobalRegistry();\n\n\tconst manifest: Record<string, Declaration> = {};\n\t/** Which file declared each id, for the error when two of them do. */\n\tconst sources: Record<string, string> = {};\n\t/**\n\t * Constructs already seen, by identity.\n\t *\n\t * A re-export is the *same object* reached through a second file — ESM\n\t * bindings are live, so `export * from './database.js'` hands back the\n\t * binding rather than a copy. Without this, a barrel file made every\n\t * construct in it appear declared twice, and `constructs/index.ts` is the\n\t * first thing anyone writes in a shared folder.\n\t *\n\t * Identity rather than file is also the more honest rule: what may not\n\t * happen twice is two *different* constructs claiming one id, and that is\n\t * still an error below.\n\t */\n\tconst seen = new WeakSet<object>();\n\n\tconst globs = Array.isArray(patterns) ? [...patterns] : [patterns as string];\n\tconst files = fg.stream(globs, { cwd, absolute: true });\n\n\t/** Matched files, for the diagnostic below. */\n\tlet matched = 0;\n\n\tfor await (const found of files) {\n\t\tmatched++;\n\t\tconst file = found.toString();\n\t\tconst module = await import(bustCache ? `${file}?t=${Date.now()}` : file);\n\n\t\tfor (const [exportName, exported] of Object.entries(module)) {\n\t\t\tif (!isDeclarable(exported)) {\n\t\t\t\tif (options.runnables) recordRunnable(options.runnables, exported);\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// The same construct, reached again through a re-export. Skipped\n\t\t\t// rather than re-declared: it has already claimed its id, from the\n\t\t\t// file that defined it.\n\t\t\tif (seen.has(exported as object)) continue;\n\t\t\tseen.add(exported as object);\n\n\t\t\t// A construct that is also something a process runs — a queue and its\n\t\t\t// consumer, built from a worker — reaches what it depends on through\n\t\t\t// that process, exactly as an endpoint or a cron does.\n\t\t\tif (\n\t\t\t\toptions.runnables &&\n\t\t\t\ttypeof (exported as { owner?: unknown }).owner === 'string'\n\t\t\t) {\n\t\t\t\trecordRunnable(options.runnables, exported);\n\t\t\t}\n\n\t\t\tfor (const declaration of exported.declare()) {\n\t\t\t\t// Canonicalise here too: a construct built by hand rather than through\n\t\t\t\t// a constructor is still subject to the same identity rule.\n\t\t\t\tconst id = canonicalId(declaration.id);\n\t\t\t\tconst source = relative(cwd, file);\n\n\t\t\t\tconst claimed = sources[id];\n\t\t\t\tif (claimed !== undefined && claimed !== source) {\n\t\t\t\t\tthrow new DuplicateConstruct(id, [claimed, source]);\n\t\t\t\t}\n\n\t\t\t\tmanifest[id] = { ...declaration, id };\n\t\t\t\tsources[id] = source;\n\t\t\t\tif (out) out[id] = { file, exportName, construct: exported };\n\t\t\t}\n\t\t}\n\t}\n\n\t// Reference integrity before anyone reads it — a schema tenant naming a\n\t// database that was deleted is a manifest error, not a reconcile failure.\n\tassertDerivations(manifest);\n\n\twarnIfNothingFound(globs, matched, Object.keys(manifest).length);\n\n\treturn manifest;\n}\n\n/**\n * Record a runnable's edges under the construct that owns it — the surface an\n * endpoint was built from, or the worker a cron or subscriber was. Anything\n * with no owner, or that is not a runnable at all, is left alone.\n */\nfunction recordRunnable(\n\trunnables: Record<string, string[]>,\n\texported: unknown,\n): void {\n\tif (typeof exported !== 'object' || exported === null) return;\n\n\tconst runnable = exported as {\n\t\tsurface?: { id?: unknown };\n\t\towner?: unknown;\n\t\tconstructs?: unknown;\n\t};\n\tconst owner =\n\t\ttypeof runnable.surface?.id === 'string'\n\t\t\t? runnable.surface.id\n\t\t\t: typeof runnable.owner === 'string'\n\t\t\t\t? runnable.owner\n\t\t\t\t: undefined;\n\tif (!owner || !Array.isArray(runnable.constructs)) return;\n\n\tconst key = canonicalId(owner);\n\tconst edges = runnables[key] ?? [];\n\trunnables[key] = edges;\n\tfor (const id of runnable.constructs) {\n\t\tif (typeof id !== 'string') continue;\n\t\tconst target = canonicalId(id);\n\t\tif (!edges.includes(target)) edges.push(target);\n\t}\n}\n\n/**\n * Say so when a glob was configured and found nothing.\n *\n * The glob is not a filter over declarations already known — it is *how they\n * are found*, by importing what it matches. So a file it misses is a\n * declaration that does not exist, and every symptom of that appears somewhere\n * other than the cause: no container starts, no env key is written, and the\n * application fails on first use against a resource it can see in its own\n * source.\n *\n * Nothing reported it before, because an unmatched file is indistinguishable\n * from a file nobody wrote. These two cases are the ones that are *not*\n * ambiguous — a glob was configured, so something was expected.\n *\n * Silent when no glob is configured at all: that is a project which has not\n * adopted constructs, and has nothing to be missing.\n */\nfunction warnIfNothingFound(\n\tglobs: readonly string[],\n\tmatched: number,\n\tdeclared: number,\n): void {\n\tif (globs.length === 0) return;\n\n\tif (matched === 0) {\n\t\tlogger.warn(\n\t\t\t`\\n⚠️ The constructs glob matched no files, so nothing was declared.\\n` +\n\t\t\t\t` Patterns: ${globs.join(', ')}\\n` +\n\t\t\t\t` Nothing will be provisioned — no containers, no env keys, no ` +\n\t\t\t\t`resources.\\n` +\n\t\t\t\t` A common cause is depth: '*.ts' matches one level, '**/*.ts' ` +\n\t\t\t\t`matches any.`,\n\t\t);\n\t\treturn;\n\t}\n\n\tif (declared === 0) {\n\t\tlogger.warn(\n\t\t\t`\\n⚠️ The constructs glob matched ${matched} file(s) but none declared ` +\n\t\t\t\t`anything.\\n` +\n\t\t\t\t` Patterns: ${globs.join(', ')}\\n` +\n\t\t\t\t` Discovery keeps exports with an 'id' that can 'declare()'. A ` +\n\t\t\t\t`construct that is\\n` +\n\t\t\t\t` built but never exported is invisible to it.`,\n\t\t);\n\t}\n}\n\n/** Two constructs claiming one id. */\nexport class DuplicateConstruct extends Error {\n\t/** The id claimed twice. */\n\treadonly id: string;\n\t/** The files that claimed it. */\n\treadonly sources: readonly string[];\n\n\tconstructor(id: string, sources: readonly string[]) {\n\t\tsuper('Two constructs declare the same id');\n\t\tthis.name = 'DuplicateConstruct';\n\t\tthis.id = id;\n\t\tthis.sources = sources;\n\t}\n}\n"],"mappings":"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"}