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

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-BTZd2u0f.cjs} +21 -22
  7. package/dist/HostingerProvider-BTZd2u0f.cjs.map +1 -0
  8. package/dist/{HostingerProvider-Cft7lEYr.mjs → HostingerProvider-DgzKa_Tj.mjs} +20 -21
  9. package/dist/HostingerProvider-DgzKa_Tj.mjs.map +1 -0
  10. package/dist/LegacyStateStore-CToa2hga.mjs +89 -0
  11. package/dist/LegacyStateStore-CToa2hga.mjs.map +1 -0
  12. package/dist/LegacyStateStore-CidlPT0N.cjs +89 -0
  13. package/dist/LegacyStateStore-CidlPT0N.cjs.map +1 -0
  14. package/dist/LocalStateStore-BFLiOocU.mjs +165 -0
  15. package/dist/LocalStateStore-BFLiOocU.mjs.map +1 -0
  16. package/dist/LocalStateStore-Dpuqka1N.cjs +176 -0
  17. package/dist/LocalStateStore-Dpuqka1N.cjs.map +1 -0
  18. package/dist/{openapi-D-dx9Akj.cjs → OpenApiTsGenerator-BTuUumsV.cjs} +330 -469
  19. package/dist/OpenApiTsGenerator-BTuUumsV.cjs.map +1 -0
  20. package/dist/{openapi-Bw8DWFWz.mjs → OpenApiTsGenerator-CvVr1Ilz.mjs} +295 -403
  21. package/dist/OpenApiTsGenerator-CvVr1Ilz.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-aaGkjcxO.mjs +161 -0
  27. package/dist/S3StateStore-aaGkjcxO.mjs.map +1 -0
  28. package/dist/S3StateStore-cnm813Xn.cjs +160 -0
  29. package/dist/S3StateStore-cnm813Xn.cjs.map +1 -0
  30. package/dist/SSMStateStore-BllaJKGo.mjs +154 -0
  31. package/dist/SSMStateStore-BllaJKGo.mjs.map +1 -0
  32. package/dist/SSMStateStore-DwaGprVX.cjs +153 -0
  33. package/dist/SSMStateStore-DwaGprVX.cjs.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-BY1OmV1e.cjs → bundler-CzXZPSBJ.cjs} +20 -32
  47. package/dist/bundler-CzXZPSBJ.cjs.map +1 -0
  48. package/dist/{bundler-Be8Zg4Wd.mjs → bundler-DJVR4QlW.mjs} +18 -29
  49. package/dist/bundler-DJVR4QlW.mjs.map +1 -0
  50. package/dist/cli-D_qTl20Z.cjs +69 -0
  51. package/dist/cli-D_qTl20Z.cjs.map +1 -0
  52. package/dist/cli-DzR1hpum.mjs +69 -0
  53. package/dist/cli-DzR1hpum.mjs.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-0fBVeWO-.cjs +3518 -0
  107. package/dist/deploy-0fBVeWO-.cjs.map +1 -0
  108. package/dist/deploy-D6Q09OkA.mjs +3429 -0
  109. package/dist/deploy-D6Q09OkA.mjs.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-CML4UaPi.cjs +91 -0
  119. package/dist/encryption-CML4UaPi.cjs.map +1 -0
  120. package/dist/encryption-aDA2AzVx.mjs +90 -0
  121. package/dist/encryption-aDA2AzVx.mjs.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 +9096 -12213
  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 +9067 -12192
  143. package/dist/index.mjs.map +1 -1
  144. package/dist/migrate-BTqIflwc.cjs +743 -0
  145. package/dist/migrate-BTqIflwc.cjs.map +1 -0
  146. package/dist/migrate-B_6KofUo.mjs +736 -0
  147. package/dist/migrate-B_6KofUo.mjs.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-CCLIAkwR.cjs +807 -0
  157. package/dist/ready-CCLIAkwR.cjs.map +1 -0
  158. package/dist/ready-CIHpnUc5.mjs +760 -0
  159. package/dist/ready-CIHpnUc5.mjs.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-BM8fpCas.mjs +6321 -0
  173. package/dist/sniffer-BM8fpCas.mjs.map +1 -0
  174. package/dist/sniffer-DIv12ncU.cjs +6707 -0
  175. package/dist/sniffer-DIv12ncU.cjs.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,14 +1,9 @@
1
- const require_chunk = require('./chunk-CUT6urMc.cjs');
2
- const require_discover = require('./discover-DTmFeloL.cjs');
3
- const require_config = require('./config-CNz5KaSR.cjs');
4
- const node_path = require_chunk.__toESM(require("node:path"));
5
- const __geekmidas_manifest = require_chunk.__toESM(require("@geekmidas/manifest"));
6
- const node_fs_promises = require_chunk.__toESM(require("node:fs/promises"));
7
- const node_child_process = require_chunk.__toESM(require("node:child_process"));
8
- const __geekmidas_constructs_endpoints = require_chunk.__toESM(require("@geekmidas/constructs/endpoints"));
9
- const node_url = require_chunk.__toESM(require("node:url"));
10
- const __geekmidas_schema_conversion = require_chunk.__toESM(require("@geekmidas/schema/conversion"));
11
-
1
+ const require_discover = require("./discover-Bc-4eA_p.cjs");
2
+ let node_path = require("node:path");
3
+ let node_fs = require("node:fs");
4
+ let node_fs_promises = require("node:fs/promises");
5
+ let _geekmidas_constructs_endpoints = require("@geekmidas/constructs/endpoints");
6
+ let _geekmidas_schema_conversion = require("@geekmidas/schema/conversion");
12
7
  //#region src/build/endpoint-analyzer.ts
13
8
  /**
14
9
  * Analyze an endpoint to extract its features
@@ -85,7 +80,6 @@ function summarizeAnalysis(analyses) {
85
80
  byFeature
86
81
  };
87
82
  }
88
-
89
83
  //#endregion
90
84
  //#region src/build/handler-templates.ts
91
85
  /**
@@ -107,8 +101,7 @@ function generateMinimalHandler(analysis) {
107
101
  const { exportName, features } = analysis;
108
102
  const method = analysis.method.toLowerCase();
109
103
  const validators = generateValidators(exportName, features);
110
- const hasValidators = validators.length > 0;
111
- if (!hasValidators && !features.hasOutputValidation) return `
104
+ if (!(validators.length > 0) && !features.hasOutputValidation) return `
112
105
  // Minimal handler: ${analysis.route} (${analysis.method})
113
106
  app.${method}('${analysis.route}', async (c) => {
114
107
  const result = await ${exportName}.handler(
@@ -256,10 +249,10 @@ function generateValidatorsFile(analyses) {
256
249
  const needsQuery = analyses.some((a) => a.features.hasQueryValidation);
257
250
  const needsParams = analyses.some((a) => a.features.hasParamValidation);
258
251
  if (!needsBody && !needsQuery && !needsParams) return `// No validators needed for this build\nexport {};\n`;
259
- const exports$1 = [];
252
+ const exports = [];
260
253
  const factories = [];
261
254
  if (needsBody) {
262
- exports$1.push("validateBody");
255
+ exports.push("validateBody");
263
256
  factories.push(`
264
257
  export const validateBody = (endpoint: any) =>
265
258
  validator('json', async (value, c) => {
@@ -270,7 +263,7 @@ export const validateBody = (endpoint: any) =>
270
263
  });`);
271
264
  }
272
265
  if (needsQuery) {
273
- exports$1.push("validateQuery");
266
+ exports.push("validateQuery");
274
267
  factories.push(`
275
268
  export const validateQuery = (endpoint: any) =>
276
269
  validator('query', async (_, c) => {
@@ -282,7 +275,7 @@ export const validateQuery = (endpoint: any) =>
282
275
  });`);
283
276
  }
284
277
  if (needsParams) {
285
- exports$1.push("validateParams");
278
+ exports.push("validateParams");
286
279
  factories.push(`
287
280
  export const validateParams = (endpoint: any) =>
288
281
  validator('param', async (params, c) => {
@@ -306,8 +299,7 @@ ${factories.join("\n")}
306
299
  */
307
300
  function generateMinimalEndpointFile(analysis, endpointImport) {
308
301
  const { exportName, features } = analysis;
309
- const needsValidators = features.hasBodyValidation || features.hasQueryValidation || features.hasParamValidation;
310
- const validatorImport = needsValidators ? generateValidatorImportsForEndpoint(analysis) : "";
302
+ const validatorImport = features.hasBodyValidation || features.hasQueryValidation || features.hasParamValidation ? generateValidatorImportsForEndpoint(analysis) : "";
311
303
  const handler = generateMinimalHandler(analysis);
312
304
  return `/**
313
305
  * Minimal endpoint: ${analysis.route} (${analysis.method})
@@ -332,8 +324,7 @@ ${handler}
332
324
  */
333
325
  function generateStandardEndpointFile(analysis, endpointImport) {
334
326
  const { exportName, features } = analysis;
335
- const needsValidators = features.hasBodyValidation || features.hasQueryValidation || features.hasParamValidation;
336
- const validatorImport = needsValidators ? generateValidatorImportsForEndpoint(analysis) : "";
327
+ const validatorImport = features.hasBodyValidation || features.hasQueryValidation || features.hasParamValidation ? generateValidatorImportsForEndpoint(analysis) : "";
337
328
  const eventsImport = features.hasEvents ? `import { publishConstructEvents } from '@geekmidas/constructs/endpoints';` : "";
338
329
  const handler = generateStandardHandler(analysis);
339
330
  return `/**
@@ -425,7 +416,7 @@ export function setupFullEndpoints(
425
416
  }
426
417
  const imports = tierEndpoints.map((a) => `import { setup${capitalize(a.exportName)} } from './${a.exportName}.js';`).join("\n");
427
418
  if (tier === "minimal") {
428
- const calls$1 = tierEndpoints.map((a) => ` setup${capitalize(a.exportName)}(app, logger);`).join("\n");
419
+ const calls = tierEndpoints.map((a) => ` setup${capitalize(a.exportName)}(app, logger);`).join("\n");
429
420
  return `/**
430
421
  * Minimal-tier endpoint index (${tierEndpoints.length} endpoints)
431
422
  * Near-raw-Hono performance
@@ -438,12 +429,12 @@ export function setupMinimalEndpoints(
438
429
  app: Hono,
439
430
  logger: Logger,
440
431
  ): void {
441
- ${calls$1}
432
+ ${calls}
442
433
  }
443
434
  `;
444
435
  }
445
436
  if (tier === "standard") {
446
- const calls$1 = tierEndpoints.map((a) => ` setup${capitalize(a.exportName)}(app, serviceDiscovery, logger);`).join("\n");
437
+ const calls = tierEndpoints.map((a) => ` setup${capitalize(a.exportName)}(app, serviceDiscovery, logger);`).join("\n");
447
438
  return `/**
448
439
  * Standard-tier endpoint index (${tierEndpoints.length} endpoints)
449
440
  * Auth and/or services enabled
@@ -458,7 +449,7 @@ export function setupStandardEndpoints(
458
449
  serviceDiscovery: ServiceDiscovery<any, any>,
459
450
  logger: Logger,
460
451
  ): void {
461
- ${calls$1}
452
+ ${calls}
462
453
  }
463
454
  `;
464
455
  }
@@ -528,9 +519,7 @@ function generateEndpointFilesNested(analyses, endpointImports) {
528
519
  case "standard":
529
520
  files[fileName] = generateStandardEndpointFile(analysis, endpointImport);
530
521
  break;
531
- case "full":
532
- files[fileName] = generateFullEndpointFile(analysis, endpointImport);
533
- break;
522
+ case "full": files[fileName] = generateFullEndpointFile(analysis, endpointImport);
534
523
  }
535
524
  }
536
525
  return files;
@@ -587,7 +576,142 @@ export async function setupEndpoints(
587
576
  }
588
577
  `;
589
578
  }
579
+ //#endregion
580
+ //#region src/generators/telemetry.ts
581
+ /**
582
+ * Every package `@geekmidas/telescope/instrumentation` loads at runtime.
583
+ *
584
+ * All of them, rather than one as a proxy: the production bundle follows each
585
+ * import, and a single missing one fails the build rather than the telemetry.
586
+ */
587
+ const TELEMETRY_PACKAGES = [
588
+ "@opentelemetry/api",
589
+ "@opentelemetry/auto-instrumentations-node",
590
+ "@opentelemetry/exporter-logs-otlp-http",
591
+ "@opentelemetry/exporter-trace-otlp-http",
592
+ "@opentelemetry/instrumentation-pino",
593
+ "@opentelemetry/resources",
594
+ "@opentelemetry/sdk-logs",
595
+ "@opentelemetry/sdk-node",
596
+ "@opentelemetry/sdk-trace-base",
597
+ "@opentelemetry/sdk-trace-node",
598
+ "@opentelemetry/semantic-conventions"
599
+ ];
600
+ /**
601
+ * The directory of `name` as `node_modules` lookup finds it from `fromDir`,
602
+ * symlinks resolved — or undefined.
603
+ *
604
+ * The directory walk alone, not `require.resolve`: that also searches
605
+ * `NODE_PATH`, which a package manager's bin shim sets to its own store, so a
606
+ * `gkm build` run through one would find packages the app never installed —
607
+ * and the bundler, which does not look there, would then fail on them.
608
+ */
609
+ function packageDir(fromDir, name) {
610
+ for (let dir = (0, node_path.resolve)(fromDir);; dir = (0, node_path.dirname)(dir)) {
611
+ const candidate = (0, node_path.join)(dir, "node_modules", name);
612
+ if ((0, node_fs.existsSync)((0, node_path.join)(candidate, "package.json"))) return (0, node_fs.realpathSync)(candidate);
613
+ if ((0, node_path.dirname)(dir) === dir) return void 0;
614
+ }
615
+ }
616
+ /**
617
+ * Whether the telemetry packages resolve the way the bundler will resolve them:
618
+ * telescope from the app, and the OpenTelemetry packages from telescope —
619
+ * where a peer is linked under pnpm, which need not be where the app sees it.
620
+ */
621
+ function telemetryResolvesFrom(appRoot) {
622
+ const telescope = packageDir(appRoot, "@geekmidas/telescope");
623
+ if (!telescope) return false;
624
+ return TELEMETRY_PACKAGES.every((pkg) => packageDir(telescope, pkg));
625
+ }
626
+ /** The telemetry half of a build context. */
627
+ function telemetryFor(options) {
628
+ return {
629
+ serviceName: options.surfaceId ?? (0, node_path.basename)(options.appRoot),
630
+ ...options.workspaceName && { serviceNamespace: options.workspaceName },
631
+ available: telemetryResolvesFrom(options.appRoot)
632
+ };
633
+ }
634
+ const HEADER = `/**
635
+ * Generated by 'gkm build --production'.
636
+ *
637
+ * Starts OpenTelemetry when OTEL_EXPORTER_OTLP_ENDPOINT names a collector, and
638
+ * does nothing otherwise: without it, the telemetry packages are not loaded.
639
+ * The standard OTEL_* variables (OTEL_TRACES_SAMPLER, OTEL_TRACES_SAMPLER_ARG,
640
+ * OTEL_EXPORTER_OTLP_HEADERS, OTEL_RESOURCE_ATTRIBUTES, OTEL_SERVICE_NAME)
641
+ * configure the rest.
642
+ */
643
+
644
+ /** Telemetry was asked for and cannot start. The server runs without it. */
645
+ export class TelemetryUnavailable extends Error {
646
+ constructor(readonly reason: string, options?: { cause?: unknown }) {
647
+ super(
648
+ \`OTEL_EXPORTER_OTLP_ENDPOINT is set, but \${reason} This server exports no traces or logs until that is fixed.\`,
649
+ options,
650
+ );
651
+ this.name = 'TelemetryUnavailable';
652
+ }
653
+ }
654
+ `;
655
+ /**
656
+ * The entry's `telemetry.ts`: a `startTelemetry()` the server awaits before it
657
+ * imports the app, so the libraries the app loads are instrumented.
658
+ *
659
+ * Failing to start telemetry warns (a named `TelemetryUnavailable`, through
660
+ * `process.emitWarning`) and never stops the server: an outage in observability
661
+ * is not a reason to have an outage in the service.
662
+ */
663
+ function generateTelemetryModule(telemetry) {
664
+ if (!telemetry?.available) return `${HEADER}
665
+ export async function startTelemetry(): Promise<void> {
666
+ if (!process.env.OTEL_EXPORTER_OTLP_ENDPOINT) return;
667
+
668
+ process.emitWarning(
669
+ new TelemetryUnavailable(
670
+ 'this server was built without @geekmidas/telescope and the @opentelemetry packages it needs. Add them to the app and rebuild.',
671
+ ),
672
+ );
673
+ }
674
+ `;
675
+ const options = [
676
+ `serviceName: ${JSON.stringify(telemetry.serviceName)},`,
677
+ ...telemetry.serviceNamespace ? [`serviceNamespace: ${JSON.stringify(telemetry.serviceNamespace)},`] : [],
678
+ "deploymentEnvironment: process.env.STAGE,",
679
+ "handleSignals: false,"
680
+ ];
681
+ return `${HEADER}
682
+ export async function startTelemetry(): Promise<void> {
683
+ if (!process.env.OTEL_EXPORTER_OTLP_ENDPOINT) return;
684
+
685
+ let instrumentation;
686
+ try {
687
+ instrumentation = await import('@geekmidas/telescope/instrumentation');
688
+ } catch (cause) {
689
+ process.emitWarning(
690
+ new TelemetryUnavailable(
691
+ '@geekmidas/telescope/instrumentation or an @opentelemetry package it needs could not be loaded. Install them in the app and rebuild.',
692
+ { cause },
693
+ ),
694
+ );
695
+ return;
696
+ }
590
697
 
698
+ instrumentation.setupTelemetry({
699
+ ${options.join("\n ")}
700
+ });
701
+
702
+ // Flush what is buffered when the process is told to stop. When nothing
703
+ // else handles the signal, re-raise it once flushed, so the process still
704
+ // stops the way it would have without this listener.
705
+ for (const signal of ['SIGTERM', 'SIGINT'] as const) {
706
+ process.once(signal, () => {
707
+ void instrumentation.flushTelemetry().finally(() => {
708
+ if (process.listenerCount(signal) === 0) process.kill(process.pid, signal);
709
+ });
710
+ });
711
+ }
712
+ }
713
+ `;
714
+ }
591
715
  //#endregion
592
716
  //#region src/generators/EndpointGenerator.ts
593
717
  /**
@@ -605,11 +729,11 @@ export async function setupEndpoints(
605
729
  * Falls back to the configured paths for an app that declares no surface.
606
730
  */
607
731
  function runtimeFor(context, fromDir, owner) {
608
- const module$1 = owner ? context.owners?.[owner] ?? context.surface?.module : context.surface?.module;
609
- if (module$1) {
610
- const specifier = importSpecifier(fromDir, module$1.specifier);
732
+ const module = owner ? context.owners?.[owner] ?? context.surface?.module : context.surface?.module;
733
+ if (module) {
734
+ const specifier = importSpecifier(fromDir, module.specifier);
611
735
  return {
612
- imports: `import { ${module$1.exportName} as __surface } from '${specifier}';`,
736
+ imports: `import { ${module.exportName} as __surface } from '${specifier}';`,
613
737
  bindings: [
614
738
  "// What this construct was declared with. Objects, not module paths:",
615
739
  "// the entry imports the owner, so there is nothing to print.",
@@ -677,48 +801,35 @@ function corsFor(surface) {
677
801
  }
678
802
  var EndpointGenerator = class extends require_discover.ConstructGenerator {
679
803
  isConstruct(value) {
680
- return __geekmidas_constructs_endpoints.Endpoint.isEndpoint(value);
804
+ return _geekmidas_constructs_endpoints.Endpoint.isEndpoint(value);
681
805
  }
682
806
  async build(context, constructs, outputDir, options) {
683
- const provider = options?.provider || "aws-apigatewayv2";
807
+ const target = options?.target ?? "aws";
808
+ const root = options?.root ?? process.cwd();
684
809
  const enableOpenApi = options?.enableOpenApi || false;
685
810
  const logger = console;
686
811
  const routes = [];
687
812
  if (constructs.length === 0) return routes;
688
- if (provider === "server") {
813
+ if (target === "server") {
689
814
  await this.generateEndpointsFile(outputDir, constructs, context);
690
815
  const appFile = await this.generateAppFile(outputDir, context);
691
816
  routes.push({
692
817
  path: "*",
693
818
  method: "ALL",
694
- handler: (0, node_path.relative)(process.cwd(), appFile),
819
+ handler: (0, node_path.relative)(root, appFile),
695
820
  authorizer: "none"
696
821
  });
697
822
  logger.log(`Generated server with ${constructs.length} endpoints${enableOpenApi ? " (OpenAPI enabled)" : ""}`);
698
- } else if (provider === "aws-lambda") {
699
- const routesDir = (0, node_path.join)(outputDir, "routes");
700
- await (0, node_fs_promises.mkdir)(routesDir, { recursive: true });
701
- for (const { key, construct, path } of constructs) {
702
- const handlerFile = await this.generateHandlerFile(routesDir, path.relative, key, "aws-apigatewayv2", construct, context);
703
- const routeInfo = {
704
- path: construct._path,
705
- method: construct.method,
706
- handler: (0, node_path.relative)(process.cwd(), handlerFile).replace(/\.ts$/, ".handler"),
707
- timeout: construct.timeout,
708
- memorySize: construct.memorySize,
709
- environment: await construct.getEnvironment({ markOptional: context.markOptional }),
710
- dependencies: construct.constructs,
711
- authorizer: construct.authorizer?.name ?? "none"
712
- };
713
- routes.push(routeInfo);
714
- logger.log(`Generated handler for ${routeInfo.method} ${routeInfo.path}`);
715
- }
716
- } else for (const { key, construct, path } of constructs) {
717
- const handlerFile = await this.generateHandlerFile(outputDir, path.relative, key, provider, construct, context);
823
+ return routes;
824
+ }
825
+ const routesDir = (0, node_path.join)(outputDir, "routes");
826
+ await (0, node_fs_promises.mkdir)(routesDir, { recursive: true });
827
+ for (const { key, construct, path } of constructs) {
828
+ const handlerFile = await this.generateHandlerFile(routesDir, path.relative, key, context);
718
829
  const routeInfo = {
719
830
  path: construct._path,
720
831
  method: construct.method,
721
- handler: (0, node_path.relative)(process.cwd(), handlerFile).replace(/\.ts$/, ".handler"),
832
+ handler: (0, node_path.relative)(root, handlerFile).replace(/\.ts$/, ".handler"),
722
833
  timeout: construct.timeout,
723
834
  memorySize: construct.memorySize,
724
835
  environment: await construct.getEnvironment({ markOptional: context.markOptional }),
@@ -730,38 +841,21 @@ var EndpointGenerator = class extends require_discover.ConstructGenerator {
730
841
  }
731
842
  return routes;
732
843
  }
733
- async generateHandlerFile(outputDir, sourceFile, exportName, provider, _endpoint, context) {
734
- const handlerFileName = `${exportName}.ts`;
735
- const handlerPath = (0, node_path.join)(outputDir, handlerFileName);
736
- const relativePath = (0, node_path.relative)((0, node_path.dirname)(handlerPath), sourceFile);
737
- const importPath = relativePath.replace(/\.ts$/, ".js");
738
- let content;
739
- switch (provider) {
740
- case "aws-apigatewayv1":
741
- content = this.generateAWSApiGatewayV1Handler(importPath, exportName, context.storageDrivers);
742
- break;
743
- case "aws-apigatewayv2":
744
- content = this.generateAWSApiGatewayV2Handler(importPath, exportName, context.storageDrivers);
745
- break;
746
- case "server":
747
- content = this.generateServerHandler(importPath, exportName);
748
- break;
749
- default: throw new Error(`Unsupported provider: ${provider}`);
750
- }
751
- await (0, node_fs_promises.writeFile)(handlerPath, content);
844
+ async generateHandlerFile(outputDir, sourceFile, exportName, context) {
845
+ const handlerPath = (0, node_path.join)(outputDir, `${exportName}.ts`);
846
+ const importPath = (0, node_path.relative)((0, node_path.dirname)(handlerPath), sourceFile).replace(/\.ts$/, ".js");
847
+ await (0, node_fs_promises.writeFile)(handlerPath, this.generateAWSApiGatewayV2Handler(importPath, exportName, context.storageDrivers));
752
848
  return handlerPath;
753
849
  }
754
850
  async generateEndpointsFile(outputDir, endpoints, context) {
755
- const endpointsFileName = "endpoints.ts";
756
- const endpointsPath = (0, node_path.join)(outputDir, endpointsFileName);
851
+ const endpointsPath = (0, node_path.join)(outputDir, "endpoints.ts");
757
852
  const importsByFile = /* @__PURE__ */ new Map();
758
853
  for (const { path, key } of endpoints) {
759
- const relativePath = (0, node_path.relative)((0, node_path.dirname)(endpointsPath), path.relative);
760
- const importPath = relativePath.replace(/\.ts$/, ".js");
854
+ const importPath = (0, node_path.relative)((0, node_path.dirname)(endpointsPath), path.relative).replace(/\.ts$/, ".js");
761
855
  if (!importsByFile.has(importPath)) importsByFile.set(importPath, []);
762
856
  importsByFile.get(importPath)?.push(key);
763
857
  }
764
- const endpointImports = Array.from(importsByFile.entries()).map(([importPath, exports$1]) => `import { ${exports$1.join(", ")} } from '${importPath}';`).join("\n");
858
+ const endpointImports = Array.from(importsByFile.entries()).map(([importPath, exports]) => `import { ${exports.join(", ")} } from '${importPath}';`).join("\n");
765
859
  const allExportNames = endpoints.map(({ key }) => key);
766
860
  if (context.production?.enabled && context.production.optimizedHandlers) return this.generateOptimizedEndpointsFile(endpointsPath, endpoints, endpointImports, allExportNames);
767
861
  const content = `import type { EnvironmentParser } from '@geekmidas/envkit';
@@ -772,7 +866,7 @@ import { ServiceDiscovery } from '@geekmidas/services';
772
866
  import type { Hono } from 'hono';
773
867
  ${endpointImports}
774
868
 
775
- export const endpoints: Endpoint<any, any, any, any, any, any, any, any, any, any, any, any, any, any>[] = [
869
+ export const endpoints: Endpoint<any, any, any, any, any, any, any, any, any, any, any, any>[] = [
776
870
  ${allExportNames.join(",\n ")}
777
871
  ];
778
872
 
@@ -823,11 +917,9 @@ export async function setupEndpoints(
823
917
  const analyses = endpoints.map(({ key, construct }) => analyzeEndpoint(construct, key));
824
918
  const endpointImports = endpoints.map(({ key, path }) => {
825
919
  const tierDir = (0, node_path.join)(endpointsDir, "standard");
826
- const relativePath = (0, node_path.relative)(tierDir, path.relative);
827
- const importPath = relativePath.replace(/\.ts$/, ".js");
828
920
  return {
829
921
  exportName: key,
830
- importPath
922
+ importPath: (0, node_path.relative)(tierDir, path.relative).replace(/\.ts$/, ".js")
831
923
  };
832
924
  });
833
925
  const summary = summarizeAnalysis(analyses);
@@ -849,43 +941,33 @@ export async function setupEndpoints(
849
941
  }
850
942
  async generateAppFile(outputDir, context) {
851
943
  if (context.production?.enabled) return this.generateProductionAppFile(outputDir, context);
852
- const appFileName = "app.ts";
853
- const appPath = (0, node_path.join)(outputDir, appFileName);
944
+ const appPath = (0, node_path.join)(outputDir, "app.ts");
854
945
  const runtime = runtimeFor(context, (0, node_path.dirname)(appPath));
855
946
  const telescopeEnabled = context.telescope?.enabled;
856
947
  const telescopeWebSocketEnabled = context.telescope?.websocket;
857
948
  const usesExternalTelescope = !!context.telescope?.telescopePath;
858
- const studioEnabled = context.studio?.enabled;
859
- const usesExternalStudio = !!context.studio?.studioPath;
860
- const studioFromDatabase = !usesExternalStudio && !!context.studio?.database;
861
949
  const telescopeFromSurface = !!context.surface?.module && !usesExternalTelescope;
862
950
  let telescopeImports = "";
863
- if (telescopeEnabled) if (telescopeFromSurface) telescopeImports = "import { createMiddleware, createUI } from '@geekmidas/telescope/hono';";
864
- else if (usesExternalTelescope) {
865
- const relativeTelescopePath = (0, node_path.relative)((0, node_path.dirname)(appPath), context.telescope?.telescopePath);
866
- telescopeImports = `import ${context.telescope?.telescopeImportPattern} from '${relativeTelescopePath}';
867
- import { createMiddleware, createUI } from '@geekmidas/telescope/hono';`;
868
- } else telescopeImports = `import { Telescope, InMemoryStorage } from '@geekmidas/telescope';
869
- import { createMiddleware, createUI } from '@geekmidas/telescope/hono';`;
870
- let studioImports = "";
871
- if (studioEnabled) if (usesExternalStudio) {
872
- const relativeStudioPath = (0, node_path.relative)((0, node_path.dirname)(appPath), context.studio?.studioPath);
873
- studioImports = `import ${context.studio?.studioImportPattern} from '${relativeStudioPath}';
874
- import { createStudioApp } from '@geekmidas/studio/server/hono';`;
875
- } else if (studioFromDatabase) {
876
- const dbSpecifier = importSpecifier((0, node_path.dirname)(appPath), context.studio.database.specifier);
877
- studioImports = `import { snifferContext } from '@geekmidas/constructs';
878
- import { Direction, InMemoryMonitoringStorage, Studio } from '@geekmidas/studio';
879
- import { ${context.studio.database.exportName} as __studioDb } from '${dbSpecifier}';
880
- import { createStudioApp } from '@geekmidas/studio/server/hono';`;
881
- } else studioImports = "";
951
+ if (telescopeEnabled) {
952
+ if (telescopeFromSurface) telescopeImports = `import { Telescope, InMemoryStorage } from '@geekmidas/telescope';
953
+ import { createApi, createMiddleware } from '@geekmidas/telescope/hono';`;
954
+ else if (usesExternalTelescope) {
955
+ const relativeTelescopePath = (0, node_path.relative)((0, node_path.dirname)(appPath), context.telescope?.telescopePath);
956
+ telescopeImports = `import ${context.telescope?.telescopeImportPattern} from '${relativeTelescopePath}';
957
+ import { createApi, createMiddleware } from '@geekmidas/telescope/hono';`;
958
+ } else telescopeImports = `import { Telescope, InMemoryStorage } from '@geekmidas/telescope';
959
+ import { createApi, createMiddleware } from '@geekmidas/telescope/hono';`;
960
+ }
961
+ const databaseApi = context.databaseApi;
962
+ const databaseApiImports = databaseApi ? `import { snifferContext } from '@geekmidas/constructs';
963
+ import { createIntrospectionHandler } from '@geekmidas/db/introspect';
964
+ import { ${databaseApi.database.exportName} as __introspectedDb } from '${importSpecifier((0, node_path.dirname)(appPath), databaseApi.database.specifier)}';` : "";
882
965
  const cors = corsFor(context.surface);
883
966
  let hooksImports = "";
884
967
  let beforeSetupCall = "";
885
968
  let afterSetupCall = "";
886
969
  if (context.hooks?.serverHooksPath) {
887
- const relativeHooksPath = (0, node_path.relative)((0, node_path.dirname)(appPath), context.hooks.serverHooksPath);
888
- hooksImports = `import * as serverHooks from '${relativeHooksPath}';`;
970
+ hooksImports = `import * as serverHooks from '${(0, node_path.relative)((0, node_path.dirname)(appPath), context.hooks.serverHooksPath)}';`;
889
971
  beforeSetupCall = `
890
972
  // Call beforeSetup hook if defined
891
973
  if (typeof serverHooks.beforeSetup === 'function') {
@@ -931,16 +1013,17 @@ import { createStudioApp } from '@geekmidas/studio/server/hono';`;
931
1013
  }
932
1014
  ` : "";
933
1015
  let telescopeSetup = "";
934
- if (telescopeEnabled) if (telescopeFromSurface || usesExternalTelescope) telescopeSetup = `
1016
+ if (telescopeEnabled) {
1017
+ if (telescopeFromSurface || usesExternalTelescope) telescopeSetup = `
935
1018
  ${telescopeWebSocketSetupCode}
936
1019
  // Add telescope middleware (before endpoints to capture all requests)
937
1020
  honoApp.use('*', createMiddleware(telescope));
938
1021
 
939
- // Mount telescope UI
940
- const telescopeUI = createUI(telescope);
941
- honoApp.route('${context.telescope?.path}', telescopeUI);
1022
+ // Mount Telescope's JSON API
1023
+ const telescopeApi = createApi(telescope);
1024
+ honoApp.route('${context.telescope?.path}', telescopeApi);
942
1025
  `;
943
- else telescopeSetup = `
1026
+ else telescopeSetup = `
944
1027
  // Setup Telescope for debugging/monitoring
945
1028
  const telescopeStorage = new InMemoryStorage({ maxEntries: ${context.telescope?.maxEntries} });
946
1029
  const telescope = new Telescope({
@@ -954,31 +1037,21 @@ ${telescopeWebSocketSetupCode}
954
1037
  // Add telescope middleware (before endpoints to capture all requests)
955
1038
  honoApp.use('*', createMiddleware(telescope));
956
1039
 
957
- // Mount telescope UI
958
- const telescopeUI = createUI(telescope);
959
- honoApp.route('${context.telescope?.path}', telescopeUI);
1040
+ // Mount Telescope's JSON API
1041
+ const telescopeApi = createApi(telescope);
1042
+ honoApp.route('${context.telescope?.path}', telescopeApi);
960
1043
  `;
961
- let studioSetup = "";
962
- if (studioEnabled && studioFromDatabase) studioSetup = `
963
- // Studio, built from the declared database. The client comes from the
964
- // construct, so what you inspect is by definition what the handlers write to.
965
- const studio = new Studio({
966
- monitoring: { storage: new InMemoryMonitoringStorage({ maxEntries: 100 }) },
967
- data: {
968
- db: await __studioDb.service.register({ envParser, context: snifferContext }),
969
- cursor: { field: 'id', direction: Direction.Desc },
970
- },
971
- enabled: true,
1044
+ }
1045
+ const databaseApiSetup = databaseApi ? `
1046
+ // The database's structure and rows as JSON, read-only, for whatever tool
1047
+ // the developer points at it. Dev only: it answers anyone who can reach the
1048
+ // port.
1049
+ const databaseApi = createIntrospectionHandler({
1050
+ db: await __introspectedDb.service.register({ envParser, context: snifferContext }),
1051
+ basePath: '${databaseApi.path}',
972
1052
  });
973
-
974
- const studioApp = createStudioApp(studio);
975
- honoApp.route('${context.studio?.path}', studioApp);
976
- `;
977
- else if (studioEnabled && usesExternalStudio) studioSetup = `
978
- // Mount Studio data browser UI
979
- const studioApp = createStudioApp(studio);
980
- honoApp.route('${context.studio?.path}', studioApp);
981
- `;
1053
+ honoApp.all('${databaseApi.path}/*', (c) => databaseApi(c.req.raw));
1054
+ ` : "";
982
1055
  const content = `/**
983
1056
  * Generated server application
984
1057
  *
@@ -994,24 +1067,37 @@ import { setupQueues } from './queues.js';
994
1067
  import { setupCrons } from './crons.js';
995
1068
  ${runtime.imports}
996
1069
  ${telescopeImports}
997
- ${studioImports}
1070
+ ${databaseApiImports}
998
1071
  ${hooksImports}
999
1072
  ${cors.imports}
1000
1073
  ${context.storageDrivers?.imports ?? ""}
1001
1074
 
1002
1075
  ${runtime.bindings}
1003
- ${telescopeFromSurface ? "const telescope = __surface.telescope;" : ""}
1076
+ ${telescopeEnabled && telescopeFromSurface ? `// The surface's own Telescope, or the one \`telescope\` config describes.
1077
+ const telescope =
1078
+ __surface.telescope ??
1079
+ new Telescope({
1080
+ enabled: true,
1081
+ path: '${context.telescope?.path}',
1082
+ ignorePatterns: ${JSON.stringify(context.telescope?.ignore)},
1083
+ recordBody: ${context.telescope?.recordBody},
1084
+ storage: new InMemoryStorage({ maxEntries: ${context.telescope?.maxEntries} }),
1085
+ });` : ""}
1004
1086
 
1005
1087
  ${context.storageDrivers?.setup ? `// Which storage drivers exist is the entry point's decision: the scheme in
1006
1088
  // each injected URL picks one, so no construct and no application module names
1007
1089
  // a provider.
1008
1090
  ${context.storageDrivers.setup}
1009
1091
  ` : ""}
1010
- export interface ServerApp {
1092
+ ${context.surface ? `// Who this server is to Postgres: application_name on every connection.
1093
+ process.env.GKM_APP_NAME ??= ${JSON.stringify(context.surface.id)};
1094
+
1095
+ ` : ""}export interface ServerApp {
1011
1096
  app: HonoType;
1012
1097
  start: (options?: {
1013
1098
  port?: number;
1014
- serve: (app: HonoType, port: number) => void | Promise<void>;
1099
+ /** Returns the server, so a shutdown can stop it taking requests. */
1100
+ serve: (app: HonoType, port: number) => unknown;
1015
1101
  }) => Promise<void>;
1016
1102
  }
1017
1103
 
@@ -1051,7 +1137,7 @@ export interface ServerApp {
1051
1137
  */
1052
1138
  export async function createApp(app?: HonoType, enableOpenApi: boolean = true): Promise<ServerApp> {
1053
1139
  const honoApp = app || new Hono();
1054
- ${telescopeSetup}${cors.setup}${beforeSetupCall}${studioSetup}
1140
+ ${telescopeSetup}${cors.setup}${beforeSetupCall}${databaseApiSetup}
1055
1141
  // Setup HTTP endpoints
1056
1142
  await setupEndpoints(honoApp, envParser, logger, enableOpenApi);
1057
1143
  ${afterSetupCall}
@@ -1069,9 +1155,11 @@ ${afterSetupCall}
1069
1155
 
1070
1156
  const port = options.port ?? 3000;
1071
1157
 
1072
- // Start subscribers in background (non-blocking, local development only)
1073
- await setupSubscribers(envParser, logger).catch((error) => {
1158
+ // Mount pushed subscribers' routes and start polled ones. What comes
1159
+ // back subscribes the routes, once the server can answer them.
1160
+ const subscribeForPush = await setupSubscribers(honoApp, envParser, logger).catch((error) => {
1074
1161
  logger.error({ error }, 'Failed to start subscribers');
1162
+ return async (_port: number) => {};
1075
1163
  });
1076
1164
 
1077
1165
  // Start queue workers in background (non-blocking, local development only)
@@ -1091,6 +1179,8 @@ ${afterSetupCall}
1091
1179
  await options.serve(honoApp, port);
1092
1180
 
1093
1181
  logger.info({ port }, 'Server started');
1182
+
1183
+ await subscribeForPush(port);
1094
1184
  }
1095
1185
  };
1096
1186
  }
@@ -1111,26 +1201,6 @@ export default createApp;
1111
1201
  * object. Nothing has to be printed now, which is also why nothing has to be
1112
1202
  * named in config.
1113
1203
  */
1114
- generateAWSApiGatewayV1Handler(importPath, exportName, drivers) {
1115
- return `import { AmazonApiGatewayV1Endpoint } from '@geekmidas/constructs/aws';
1116
- import { ${exportName} } from '${importPath}';
1117
- ${drivers?.imports ?? ""}
1118
- ${drivers?.setup ? `\n// The handler registers the drivers its target needs.\n${drivers.setup}\n` : ""}
1119
- const adapter = new AmazonApiGatewayV1Endpoint(${exportName});
1120
-
1121
- export const handler = adapter.handler;
1122
- `;
1123
- }
1124
- /**
1125
- * One Lambda, one endpoint — and no environment import.
1126
- *
1127
- * The endpoint was built from its surface, so it carries the parser the
1128
- * adaptor needs. This used to read
1129
- * `import { envParser } from '../../config/env'`, a line the build wrote
1130
- * because a generator can print a module specifier and cannot print an
1131
- * object. Nothing has to be printed now, which is also why nothing has to be
1132
- * named in config.
1133
- */
1134
1204
  generateAWSApiGatewayV2Handler(importPath, exportName, drivers) {
1135
1205
  return `import { AmazonApiGatewayV2Endpoint } from '@geekmidas/constructs/aws';
1136
1206
  import { ${exportName} } from '${importPath}';
@@ -1139,13 +1209,6 @@ ${drivers?.setup ? `\n// The handler registers the drivers its target needs.\n${
1139
1209
  const adapter = new AmazonApiGatewayV2Endpoint(${exportName});
1140
1210
 
1141
1211
  export const handler = adapter.handler;
1142
- `;
1143
- }
1144
- generateServerHandler(importPath, exportName) {
1145
- return `import { ${exportName} } from '${importPath}';
1146
-
1147
- // Server handler - implement based on your server framework
1148
- export const handler = ${exportName};
1149
1212
  `;
1150
1213
  }
1151
1214
  /**
@@ -1153,8 +1216,7 @@ export const handler = ${exportName};
1153
1216
  * No dev tools (Telescope, Studio, WebSocket), includes health checks and graceful shutdown
1154
1217
  */
1155
1218
  async generateProductionAppFile(outputDir, context) {
1156
- const appFileName = "app.ts";
1157
- const appPath = (0, node_path.join)(outputDir, appFileName);
1219
+ const appPath = (0, node_path.join)(outputDir, "app.ts");
1158
1220
  const runtime = runtimeFor(context, (0, node_path.dirname)(appPath));
1159
1221
  const production = context.production;
1160
1222
  const healthCheckPath = production.healthCheck;
@@ -1166,8 +1228,7 @@ export const handler = ${exportName};
1166
1228
  let beforeSetupCall = "";
1167
1229
  let afterSetupCall = "";
1168
1230
  if (context.hooks?.serverHooksPath) {
1169
- const relativeHooksPath = (0, node_path.relative)((0, node_path.dirname)(appPath), context.hooks.serverHooksPath);
1170
- hooksImports = `import * as serverHooks from '${relativeHooksPath}';`;
1231
+ hooksImports = `import * as serverHooks from '${(0, node_path.relative)((0, node_path.dirname)(appPath), context.hooks.serverHooksPath)}';`;
1171
1232
  beforeSetupCall = `
1172
1233
  // Call beforeSetup hook if defined
1173
1234
  if (typeof serverHooks.beforeSetup === 'function') {
@@ -1182,9 +1243,11 @@ export const handler = ${exportName};
1182
1243
  `;
1183
1244
  }
1184
1245
  const subscriberSetup = includeSubscribers ? `
1185
- // Start subscribers in background
1186
- await setupSubscribers(envParser, logger).catch((error) => {
1246
+ // Mount pushed subscribers' routes and start polled ones. What comes
1247
+ // back subscribes the routes, once the server can answer them.
1248
+ const subscribeForPush = await setupSubscribers(honoApp, envParser, logger).catch((error) => {
1187
1249
  logger.error({ error }, 'Failed to start subscribers');
1250
+ return async (_port: number) => {};
1188
1251
  });
1189
1252
 
1190
1253
  // Start queue workers in background
@@ -1202,15 +1265,29 @@ export const handler = ${exportName};
1202
1265
  import { setupQueues } from './queues.js';
1203
1266
  import { setupCrons } from './crons.js';` : "";
1204
1267
  const gracefulShutdownCode = enableGracefulShutdown ? `
1205
- // Graceful shutdown handling
1268
+ // Graceful shutdown: stop taking requests, let in-flight ones finish, then
1269
+ // close what constructs opened (database pools) — so a rolling deploy does
1270
+ // not leave the old task holding connections. Bounded by
1271
+ // GKM_SHUTDOWN_TIMEOUT_MS, 8s by default: under Docker's 10s stop timeout,
1272
+ // so the process exits on its own terms rather than being killed mid-drain.
1206
1273
  let isShuttingDown = false;
1207
1274
 
1208
1275
  const shutdown = async () => {
1209
1276
  if (isShuttingDown) return;
1210
1277
  isShuttingDown = true;
1211
- logger.info('Graceful shutdown initiated');
1212
- // Allow in-flight requests to complete (30s timeout)
1213
- setTimeout(() => process.exit(0), 30000);
1278
+ const deadline = Number(process.env.GKM_SHUTDOWN_TIMEOUT_MS) || 8000;
1279
+ logger.info({ deadline }, 'Graceful shutdown initiated');
1280
+ setTimeout(() => {
1281
+ logger.warn({ deadline }, 'Shutdown deadline reached, exiting');
1282
+ process.exit(1);
1283
+ }, deadline).unref();
1284
+ await new Promise<void>((resolve) => {
1285
+ const close = (server as { close?: (done: () => void) => void } | undefined)?.close;
1286
+ if (typeof close === 'function') close.call(server, () => resolve());
1287
+ else resolve();
1288
+ });
1289
+ await runShutdownHooks((error) => logger.error({ error }, 'Shutdown hook failed'));
1290
+ process.exit(0);
1214
1291
  };
1215
1292
 
1216
1293
  process.on('SIGTERM', shutdown);
@@ -1228,7 +1305,7 @@ import { setupCrons } from './crons.js';` : "";
1228
1305
  */
1229
1306
  import { Hono } from 'hono';
1230
1307
  import type { Hono as HonoType } from 'hono';
1231
- import { setupEndpoints } from '${endpointsImportPath}';
1308
+ ${enableGracefulShutdown ? "import { runShutdownHooks } from '@geekmidas/constructs';\n" : ""}import { setupEndpoints } from '${endpointsImportPath}';
1232
1309
  ${subscriberImport}
1233
1310
  ${runtime.imports}
1234
1311
  ${runtime.bindings}
@@ -1239,7 +1316,10 @@ ${context.storageDrivers?.imports ?? ""}
1239
1316
  ${context.storageDrivers?.setup ? `// The entry point registers the drivers its target needs.
1240
1317
  ${context.storageDrivers.setup}
1241
1318
  ` : ""}
1242
- export interface ServerApp {
1319
+ ${context.surface ? `// Who this server is to Postgres: application_name on every connection.
1320
+ process.env.GKM_APP_NAME ??= ${JSON.stringify(context.surface.id)};
1321
+
1322
+ ` : ""}export interface ServerApp {
1243
1323
  app: HonoType;
1244
1324
  start: (options?: {
1245
1325
  port?: number;
@@ -1272,13 +1352,15 @@ ${afterSetupCall}
1272
1352
  }
1273
1353
 
1274
1354
  const port = options.port ?? Number(process.env.PORT) ?? 3000;
1355
+ let server: unknown;
1275
1356
  ${gracefulShutdownCode}${subscriberSetup}
1276
1357
  logger.info({ port }, 'Starting production server');
1277
1358
 
1278
1359
  // Start HTTP server using provided serve function
1279
- await options.serve(honoApp, port);
1360
+ server = await options.serve(honoApp, port);
1280
1361
 
1281
1362
  logger.info({ port }, 'Production server started');
1363
+ ${includeSubscribers ? "\n await subscribeForPush(port);" : ""}
1282
1364
  }
1283
1365
  };
1284
1366
  }
@@ -1287,21 +1369,27 @@ ${gracefulShutdownCode}${subscriberSetup}
1287
1369
  export default createApp;
1288
1370
  `;
1289
1371
  await (0, node_fs_promises.writeFile)(appPath, content);
1290
- await this.generateProductionServerEntry(outputDir);
1372
+ await this.generateProductionServerEntry(outputDir, context);
1291
1373
  return appPath;
1292
1374
  }
1293
1375
  /**
1294
1376
  * Generate production server.ts entry point
1295
1377
  */
1296
- async generateProductionServerEntry(outputDir) {
1378
+ async generateProductionServerEntry(outputDir, context) {
1297
1379
  const serverPath = (0, node_path.join)(outputDir, "server.ts");
1298
- const content = `#!/usr/bin/env node
1380
+ await (0, node_fs_promises.writeFile)((0, node_path.join)(outputDir, "telemetry.ts"), generateTelemetryModule(context.telemetry));
1381
+ await (0, node_fs_promises.writeFile)(serverPath, `#!/usr/bin/env node
1299
1382
  /**
1300
1383
  * Production server entry point
1301
- * Generated by 'gkm build --provider server --production'
1384
+ * Generated by 'gkm build --production'
1302
1385
  */
1303
1386
  import { serve } from '@hono/node-server';
1304
- import { createApp } from './app.js';
1387
+ import { startTelemetry } from './telemetry.js';
1388
+
1389
+ // Before the app is imported, so the libraries it loads are instrumented.
1390
+ await startTelemetry();
1391
+
1392
+ const { createApp } = await import('./app.js');
1305
1393
 
1306
1394
  const port = Number(process.env.PORT) || 3000;
1307
1395
 
@@ -1309,13 +1397,11 @@ const { start } = await createApp();
1309
1397
 
1310
1398
  await start({
1311
1399
  port,
1312
- serve: (app, port) => { serve({ fetch: app.fetch, port }); },
1400
+ serve: (app, port) => serve({ fetch: app.fetch, port }),
1313
1401
  });
1314
- `;
1315
- await (0, node_fs_promises.writeFile)(serverPath, content);
1402
+ `);
1316
1403
  }
1317
1404
  };
1318
-
1319
1405
  //#endregion
1320
1406
  //#region src/generators/OpenApiTsGenerator.ts
1321
1407
  /**
@@ -1466,11 +1552,11 @@ var OpenApiTsGenerator = class {
1466
1552
  }
1467
1553
  }
1468
1554
  }
1469
- const registrySchemas = await (0, __geekmidas_schema_conversion.getRegisteredZodJsonSchemas)();
1555
+ const registrySchemas = await (0, _geekmidas_schema_conversion.getRegisteredZodJsonSchemas)();
1470
1556
  for (const [rawName, rawSchema] of Object.entries(registrySchemas)) {
1471
1557
  const defName = this.pascalCase(rawName);
1472
1558
  if (collectedDefs.has(defName) || generatedNames.has(defName)) continue;
1473
- const { id: _id, $defs: _defs,...rest } = rawSchema;
1559
+ const { id: _id, $defs: _defs, ...rest } = rawSchema;
1474
1560
  collectedDefs.set(defName, rest);
1475
1561
  }
1476
1562
  for (const [defName, defSchema] of collectedDefs) if (!generatedNames.has(defName)) {
@@ -1486,7 +1572,7 @@ var OpenApiTsGenerator = class {
1486
1572
  */
1487
1573
  async getSchemaName(schema, defaultName) {
1488
1574
  try {
1489
- const metadata = await (0, __geekmidas_schema_conversion.getSchemaMetadata)(schema);
1575
+ const metadata = await (0, _geekmidas_schema_conversion.getSchemaMetadata)(schema);
1490
1576
  if (metadata?.id) return this.pascalCase(metadata.id);
1491
1577
  } catch {}
1492
1578
  return defaultName;
@@ -1506,17 +1592,17 @@ var OpenApiTsGenerator = class {
1506
1592
  async schemaToInterfaceWithDefs(schema, name, collectedDefs) {
1507
1593
  try {
1508
1594
  const vendor = schema["~standard"]?.vendor;
1509
- if (!vendor || !(vendor in __geekmidas_schema_conversion.StandardSchemaJsonSchema)) return null;
1510
- const toJsonSchema = __geekmidas_schema_conversion.StandardSchemaJsonSchema[vendor];
1595
+ if (!vendor || !(vendor in _geekmidas_schema_conversion.StandardSchemaJsonSchema)) return unknownType(name);
1596
+ const toJsonSchema = _geekmidas_schema_conversion.StandardSchemaJsonSchema[vendor];
1511
1597
  const jsonSchema = await toJsonSchema(schema);
1512
- if (!jsonSchema) return null;
1598
+ if (!jsonSchema) return unknownType(name);
1513
1599
  if (jsonSchema.$defs && typeof jsonSchema.$defs === "object") {
1514
1600
  for (const [defName, defSchema] of Object.entries(jsonSchema.$defs)) if (!collectedDefs.has(defName)) {
1515
- const { id,...schemaWithoutId } = defSchema;
1601
+ const { id, ...schemaWithoutId } = defSchema;
1516
1602
  collectedDefs.set(defName, schemaWithoutId);
1517
1603
  }
1518
1604
  }
1519
- const { $defs,...schemaWithoutDefs } = jsonSchema;
1605
+ const { $defs, ...schemaWithoutDefs } = jsonSchema;
1520
1606
  const ref = schemaWithoutDefs.$ref;
1521
1607
  if (ref && Object.keys(schemaWithoutDefs).every((k) => k === "$ref" || k === "$schema")) {
1522
1608
  const target = ref.split("/").pop();
@@ -1524,14 +1610,11 @@ var OpenApiTsGenerator = class {
1524
1610
  }
1525
1611
  return this.jsonSchemaToInterface(schemaWithoutDefs, name);
1526
1612
  } catch {
1527
- return null;
1613
+ return unknownType(name);
1528
1614
  }
1529
1615
  }
1530
1616
  jsonSchemaToInterface(schema, name) {
1531
- if (schema.type !== "object" || !schema.properties) {
1532
- const typeStr = this.jsonSchemaTypeToTs(schema);
1533
- return `export type ${name} = ${typeStr};`;
1534
- }
1617
+ if (schema.type !== "object" || !schema.properties) return `export type ${name} = ${this.jsonSchemaTypeToTs(schema)};`;
1535
1618
  const props = [];
1536
1619
  const required = new Set(schema.required || []);
1537
1620
  for (const [propName, propSchema] of Object.entries(schema.properties)) {
@@ -1544,13 +1627,15 @@ var OpenApiTsGenerator = class {
1544
1627
  }
1545
1628
  jsonSchemaTypeToTs(schema) {
1546
1629
  if (!schema) return "unknown";
1547
- if (schema.$ref) {
1548
- const refName = schema.$ref.split("/").pop() || "unknown";
1549
- return refName;
1550
- }
1630
+ if (schema.$ref) return schema.$ref.split("/").pop() || "unknown";
1631
+ if (schema.const !== void 0) return typeof schema.const === "string" ? `'${schema.const}'` : String(schema.const);
1551
1632
  if (schema.anyOf) return schema.anyOf.map((s) => this.jsonSchemaTypeToTs(s)).join(" | ");
1552
1633
  if (schema.oneOf) return schema.oneOf.map((s) => this.jsonSchemaTypeToTs(s)).join(" | ");
1553
1634
  if (schema.allOf) return schema.allOf.map((s) => this.jsonSchemaTypeToTs(s)).join(" & ");
1635
+ if (Array.isArray(schema.type)) return schema.type.map((type) => this.jsonSchemaTypeToTs({
1636
+ ...schema,
1637
+ type
1638
+ })).join(" | ");
1554
1639
  switch (schema.type) {
1555
1640
  case "string":
1556
1641
  if (schema.enum) return schema.enum.map((e) => `'${e}'`).join(" | ");
@@ -1574,10 +1659,7 @@ var OpenApiTsGenerator = class {
1574
1659
  }
1575
1660
  return `{ ${props.join("; ")} }`;
1576
1661
  }
1577
- if (schema.additionalProperties) {
1578
- const valueType = this.jsonSchemaTypeToTs(schema.additionalProperties);
1579
- return `Record<string, ${valueType}>`;
1580
- }
1662
+ if (schema.additionalProperties) return `Record<string, ${this.jsonSchemaTypeToTs(schema.additionalProperties)}>`;
1581
1663
  return "Record<string, unknown>";
1582
1664
  default: return "unknown";
1583
1665
  }
@@ -1598,10 +1680,7 @@ var OpenApiTsGenerator = class {
1598
1680
  }
1599
1681
  const firstWithParams = infos.find((i) => i.input?.params);
1600
1682
  let paramsEntry = "";
1601
- if (firstWithParams?.input?.params) {
1602
- const paramsName = await this.getSchemaName(firstWithParams.input.params, `${this.getSchemaBaseName(firstWithParams)}Params`);
1603
- paramsEntry = `\n parameters: {\n path: ${paramsName};\n };`;
1604
- }
1683
+ if (firstWithParams?.input?.params) paramsEntry = `\n parameters: {\n path: ${await this.getSchemaName(firstWithParams.input.params, `${this.getSchemaBaseName(firstWithParams)}Params`)};\n };`;
1605
1684
  pathEntries.push(` '${route}': {${paramsEntry}\n${methodEntries.join("\n")}\n };`);
1606
1685
  }
1607
1686
  return `export interface paths {\n${pathEntries.join("\n")}\n}`;
@@ -1640,8 +1719,7 @@ var OpenApiTsGenerator = class {
1640
1719
  return acc;
1641
1720
  }, {});
1642
1721
  const schemeNames = securitySchemes.map((s) => `'${s.name}'`).join(" | ");
1643
- const hasSecuritySchemes = schemeNames.length > 0;
1644
- const createApiSection = hasSecuritySchemes ? `
1722
+ const createApiSection = schemeNames.length > 0 ? `
1645
1723
  // ============================================================
1646
1724
  // API Client Factory
1647
1725
  // ============================================================
@@ -1665,6 +1743,8 @@ export interface CreateApiOptions {
1665
1743
  queryClient?: QueryClient;
1666
1744
  /** Optional request interceptor */
1667
1745
  onRequest?: (config: RequestInit) => RequestInit | Promise<RequestInit>;
1746
+ /** The \`fetch\` requests go out on — a test browser's, for one */
1747
+ fetch?: typeof fetch;
1668
1748
  }
1669
1749
 
1670
1750
  /**
@@ -1694,6 +1774,7 @@ export function createApi(options: CreateApiOptions) {
1694
1774
  securitySchemes,
1695
1775
  authStrategies: options.authStrategies,
1696
1776
  onRequest: options.onRequest,
1777
+ ...(options.fetch ? { fetch: options.fetch } : {}),
1697
1778
  });
1698
1779
 
1699
1780
  const hooks = createEndpointHooks<paths>(fetcher, { queryClient: options.queryClient });
@@ -1818,258 +1899,38 @@ ${createApiSection}
1818
1899
  `;
1819
1900
  }
1820
1901
  };
1821
-
1822
- //#endregion
1823
- //#region src/workspace/client-generator.ts
1824
1902
  /**
1825
- * Normalize routes to an array of patterns.
1826
- * Handles string, string[], and PartitionedRoutes (extracts paths).
1827
- * @internal Exported for use in dev command
1903
+ * The declaration for a schema that cannot be converted — a vendor with no
1904
+ * converter, or one that fails. The paths interface names it either way, so
1905
+ * leaving it undeclared made the generated client fail to compile.
1828
1906
  */
1829
- function normalizeRoutes(routes) {
1830
- if (!routes) return [];
1831
- if (require_discover.isPartitionedRoutes(routes)) return Array.isArray(routes.paths) ? routes.paths : [routes.paths];
1832
- return Array.isArray(routes) ? routes : [routes];
1907
+ function unknownType(name) {
1908
+ return `export type ${name} = unknown;`;
1833
1909
  }
1834
-
1835
1910
  //#endregion
1836
- //#region src/openapi.ts
1837
- /**
1838
- * Default output path for generated OpenAPI client (used for single-app configs)
1839
- */
1840
- const OPENAPI_OUTPUT_PATH = "./.gkm/openapi.ts";
1841
- /**
1842
- * Where a surface's generated client lands.
1843
- *
1844
- * Named from the surface, so `new RestApi('Webhooks')` writes
1845
- * `.gkm/openapi/webhooks.ts` — the same kebab form that gives it its container
1846
- * name and its `WEBHOOKS_URL`.
1847
- */
1848
- function openApiPathFor(surfaceId) {
1849
- return `./.gkm/openapi/${(0, __geekmidas_manifest.kebabCase)(surfaceId)}.ts`;
1850
- }
1851
- /**
1852
- * Resolve OpenAPI config from GkmConfig
1853
- */
1854
- function resolveOpenApiConfig(config) {
1855
- if (config.openapi === false) return { enabled: false };
1856
- if (config.openapi === true || config.openapi === void 0) return {
1857
- enabled: true,
1858
- title: "API Documentation",
1859
- version: "1.0.0",
1860
- description: "Auto-generated API documentation from endpoints"
1861
- };
1862
- return {
1863
- enabled: config.openapi.enabled !== false,
1864
- title: config.openapi.title || "API Documentation",
1865
- version: config.openapi.version || "1.0.0",
1866
- description: config.openapi.description || "Auto-generated API documentation from endpoints"
1867
- };
1868
- }
1869
- /**
1870
- * Load endpoints from a glob, then generate.
1871
- *
1872
- * For the callers that have no endpoints in hand — `gkm openapi`, and `gkm dev`
1873
- * regenerating on reload. The glob is the app's derived one, off `AppSpec.code`,
1874
- * not a `routes` field anybody wrote.
1875
- */
1876
- async function generateOpenApiFrom(routes, options = {}) {
1877
- const loaded = await new EndpointGenerator().load(routes, void 0, options.bustCache);
1878
- return generateOpenApi(loaded.map(({ construct }) => construct), options);
1879
- }
1880
- /**
1881
- * Generate an OpenAPI spec for each surface these endpoints name.
1882
- *
1883
- * Takes the endpoints, not a glob to find them with. The build has already
1884
- * loaded every one of them to generate handlers, so globbing again was a second
1885
- * discovery pass over the same files — and the reason this function needed a
1886
- * `routes` to be told where to look, which is how a retired config field stayed
1887
- * load-bearing.
1888
- *
1889
- * @returns What was written, or null if disabled or there were none
1890
- */
1891
- async function generateOpenApi(endpoints, options = {}) {
1892
- const logger = options.silent ? { log: () => {} } : console;
1893
- const openApiConfig = resolveOpenApiConfig({ openapi: options.openapi });
1894
- if (!openApiConfig.enabled) return null;
1895
- if (endpoints.length === 0) {
1896
- logger.log("No valid endpoints found for OpenAPI generation");
1897
- return null;
1911
+ Object.defineProperty(exports, "EndpointGenerator", {
1912
+ enumerable: true,
1913
+ get: function() {
1914
+ return EndpointGenerator;
1898
1915
  }
1899
- const bySurface = /* @__PURE__ */ new Map();
1900
- for (const endpoint of endpoints) {
1901
- const owner = endpoint.owner ?? endpoint.surface?.id;
1902
- if (!owner) continue;
1903
- const existing = bySurface.get(owner);
1904
- if (existing) existing.push(endpoint);
1905
- else bySurface.set(owner, [endpoint]);
1906
- }
1907
- if (bySurface.size === 0) {
1908
- logger.log("No endpoints named a surface, so no OpenAPI was generated");
1909
- return null;
1910
- }
1911
- const tsGenerator = new OpenApiTsGenerator();
1912
- const written = [];
1913
- for (const [surfaceId, surfaceEndpoints] of bySurface) {
1914
- const relative$1 = openApiPathFor(surfaceId);
1915
- const outputPath = (0, node_path.join)(process.cwd(), relative$1);
1916
- await (0, node_fs_promises.mkdir)((0, node_path.dirname)(outputPath), { recursive: true });
1917
- const tsContent = await tsGenerator.generate(surfaceEndpoints, {
1918
- title: openApiConfig.title ?? surfaceId,
1919
- version: openApiConfig.version,
1920
- description: openApiConfig.description
1921
- });
1922
- await (0, node_fs_promises.writeFile)(outputPath, tsContent);
1923
- written.push(relative$1);
1924
- logger.log(`📄 OpenAPI client generated: ${relative$1} (${surfaceEndpoints.length} endpoints)`);
1925
- }
1926
- return {
1927
- outputPath: (0, node_path.join)(process.cwd(), written[0]),
1928
- outputPaths: written.map((r) => (0, node_path.join)(process.cwd(), r)),
1929
- endpointCount: endpoints.length
1930
- };
1931
- }
1932
- async function openapiCommand(options = {}) {
1933
- const logger = console;
1934
- try {
1935
- const loadedConfig = await require_config.loadWorkspaceConfig(options.cwd);
1936
- if (loadedConfig.type === "single") {
1937
- const config = loadedConfig.raw;
1938
- if (!config.openapi) config.openapi = { enabled: true };
1939
- const result = await generateOpenApiFrom(config.constructs, { openapi: config.openapi });
1940
- if (result) logger.log(`Found ${result.endpointCount} endpoints`);
1941
- } else {
1942
- const { workspace } = loadedConfig;
1943
- const workspaceRoot = workspace.root;
1944
- const backendApps = Object.entries(workspace.apps).filter(([_, app]) => app.type === "backend" && app.openapi !== false && (typeof app.openapi !== "object" || app.openapi.enabled !== false));
1945
- if (backendApps.length === 0) {
1946
- logger.log("No backend apps with OpenAPI enabled found");
1947
- return;
1948
- }
1949
- if (options.app) {
1950
- const entry = backendApps.find(([name]) => name === options.app);
1951
- if (!entry) throw new Error(`App "${options.app}" not found or has OpenAPI disabled`);
1952
- const [appName, app] = entry;
1953
- const result = await generateOpenApiForApp(workspaceRoot, appName, app);
1954
- if (result) logger.log(`📄 [${appName}] Generated OpenAPI (${result.endpointCount} endpoints)`);
1955
- return;
1956
- }
1957
- for (const [appName, app] of backendApps) {
1958
- const appPath = (0, node_path.join)(workspaceRoot, app.path);
1959
- if ((0, node_path.resolve)(appPath) === (0, node_path.resolve)(workspaceRoot)) {
1960
- const result = await generateOpenApiForApp(workspaceRoot, appName, app, false);
1961
- if (result) logger.log(`Found ${result.endpointCount} endpoints`);
1962
- continue;
1963
- }
1964
- await runOpenApiInSubprocess(appPath, appName);
1965
- }
1966
- }
1967
- } catch (error) {
1968
- throw new Error(`OpenAPI generation failed: ${error.message}`);
1969
- }
1970
- }
1971
- /**
1972
- * Generate OpenAPI for a single named app within a workspace.
1973
- * Runs in-process. The caller is responsible for ensuring `process.cwd()`
1974
- * is the app's directory so tsx loads the app's tsconfig path aliases.
1975
- */
1976
- async function generateOpenApiForApp(workspaceRoot, _appName, app, silent = true) {
1977
- if (app.type !== "backend") return null;
1978
- const appPath = (0, node_path.join)(workspaceRoot, app.path);
1979
- const globs = [(0, node_path.join)(appPath, "**/*.ts")];
1980
- return generateOpenApiFrom(globs, {
1981
- openapi: app.openapi ?? { enabled: true },
1982
- silent
1983
- });
1984
- }
1985
- /**
1986
- * Resolve the gkm bin path. Tests can override via `GKM_BIN_PATH` env var
1987
- * to avoid depending on the built dist.
1988
- */
1989
- function resolveGkmBinPath() {
1990
- if (process.env.GKM_BIN_PATH) return process.env.GKM_BIN_PATH;
1991
- return (0, node_url.fileURLToPath)(new URL("../bin/gkm.mjs", require("url").pathToFileURL(__filename).href));
1992
- }
1993
- /**
1994
- * Spawn a subprocess that runs `gkm openapi --app <name>` with `cwd` set to
1995
- * the app's directory. Inherits `NODE_OPTIONS` (which already contains
1996
- * `--import tsx`), so the child gets a fresh tsx instance whose tsconfig
1997
- * discovery picks up the app's tsconfig path aliases.
1998
- */
1999
- async function runOpenApiInSubprocess(appCwd, appName) {
2000
- const binPath = resolveGkmBinPath();
2001
- await new Promise((resolve$1, reject) => {
2002
- const child = (0, node_child_process.spawn)(process.execPath, [
2003
- binPath,
2004
- "openapi",
2005
- "--app",
2006
- appName
2007
- ], {
2008
- cwd: appCwd,
2009
- stdio: "inherit",
2010
- env: process.env
2011
- });
2012
- child.on("error", reject);
2013
- child.on("close", (code) => {
2014
- if (code === 0) resolve$1();
2015
- else reject(new Error(`OpenAPI generation for app "${appName}" exited with code ${code}`));
2016
- });
2017
- });
2018
- }
2019
-
2020
- //#endregion
2021
- Object.defineProperty(exports, 'EndpointGenerator', {
2022
- enumerable: true,
2023
- get: function () {
2024
- return EndpointGenerator;
2025
- }
2026
- });
2027
- Object.defineProperty(exports, 'OPENAPI_OUTPUT_PATH', {
2028
- enumerable: true,
2029
- get: function () {
2030
- return OPENAPI_OUTPUT_PATH;
2031
- }
2032
- });
2033
- Object.defineProperty(exports, 'generateOpenApi', {
2034
- enumerable: true,
2035
- get: function () {
2036
- return generateOpenApi;
2037
- }
2038
- });
2039
- Object.defineProperty(exports, 'generateOpenApiFrom', {
2040
- enumerable: true,
2041
- get: function () {
2042
- return generateOpenApiFrom;
2043
- }
2044
- });
2045
- Object.defineProperty(exports, 'normalizeRoutes', {
2046
- enumerable: true,
2047
- get: function () {
2048
- return normalizeRoutes;
2049
- }
2050
- });
2051
- Object.defineProperty(exports, 'openApiPathFor', {
2052
- enumerable: true,
2053
- get: function () {
2054
- return openApiPathFor;
2055
- }
2056
1916
  });
2057
- Object.defineProperty(exports, 'openapiCommand', {
2058
- enumerable: true,
2059
- get: function () {
2060
- return openapiCommand;
2061
- }
1917
+ Object.defineProperty(exports, "OpenApiTsGenerator", {
1918
+ enumerable: true,
1919
+ get: function() {
1920
+ return OpenApiTsGenerator;
1921
+ }
2062
1922
  });
2063
- Object.defineProperty(exports, 'resolveOpenApiConfig', {
2064
- enumerable: true,
2065
- get: function () {
2066
- return resolveOpenApiConfig;
2067
- }
1923
+ Object.defineProperty(exports, "runtimeFor", {
1924
+ enumerable: true,
1925
+ get: function() {
1926
+ return runtimeFor;
1927
+ }
2068
1928
  });
2069
- Object.defineProperty(exports, 'runtimeFor', {
2070
- enumerable: true,
2071
- get: function () {
2072
- return runtimeFor;
2073
- }
1929
+ Object.defineProperty(exports, "telemetryFor", {
1930
+ enumerable: true,
1931
+ get: function() {
1932
+ return telemetryFor;
1933
+ }
2074
1934
  });
2075
- //# sourceMappingURL=openapi-D-dx9Akj.cjs.map
1935
+
1936
+ //# sourceMappingURL=OpenApiTsGenerator-BTuUumsV.cjs.map