@geekmidas/cli 10.0.0-alpha.12 → 10.0.0-alpha.120

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 (517) hide show
  1. package/README.md +310 -377
  2. package/bin/adjacent-tsconfig.mjs +46 -8
  3. package/bin/gkm.mjs +11 -3
  4. package/bin/owning-tsconfig-jsx-register.mjs +18 -0
  5. package/bin/owning-tsconfig-jsx.mjs +108 -0
  6. package/dist/EndpointGenerator-BDa6pPgE.cjs +1090 -0
  7. package/dist/EndpointGenerator-BDa6pPgE.cjs.map +1 -0
  8. package/dist/EndpointGenerator-CP_z_E3e.mjs +1031 -0
  9. package/dist/EndpointGenerator-CP_z_E3e.mjs.map +1 -0
  10. package/dist/GoDaddyProvider-3C8U_tVu.cjs +388 -0
  11. package/dist/GoDaddyProvider-3C8U_tVu.cjs.map +1 -0
  12. package/dist/GoDaddyProvider-D0MQoOM4.mjs +388 -0
  13. package/dist/GoDaddyProvider-D0MQoOM4.mjs.map +1 -0
  14. package/dist/{HostingerProvider-BcyFRbqV.mjs → HostingerProvider-BNpS9aRJ.mjs} +29 -25
  15. package/dist/HostingerProvider-BNpS9aRJ.mjs.map +1 -0
  16. package/dist/{HostingerProvider-BOvsgATO.cjs → HostingerProvider-DR1iws1P.cjs} +29 -25
  17. package/dist/HostingerProvider-DR1iws1P.cjs.map +1 -0
  18. package/dist/LegacyStateStore-CRi7TosX.mjs +124 -0
  19. package/dist/LegacyStateStore-CRi7TosX.mjs.map +1 -0
  20. package/dist/LegacyStateStore-DHsoQGOo.cjs +124 -0
  21. package/dist/LegacyStateStore-DHsoQGOo.cjs.map +1 -0
  22. package/dist/LocalStateStore-BQXTkeoS.cjs +178 -0
  23. package/dist/LocalStateStore-BQXTkeoS.cjs.map +1 -0
  24. package/dist/LocalStateStore-Dkth0jXX.mjs +167 -0
  25. package/dist/LocalStateStore-Dkth0jXX.mjs.map +1 -0
  26. package/dist/OpenApiTsGenerator-CsrukCE-.mjs +536 -0
  27. package/dist/OpenApiTsGenerator-CsrukCE-.mjs.map +1 -0
  28. package/dist/OpenApiTsGenerator-FNhY7Ssz.cjs +541 -0
  29. package/dist/OpenApiTsGenerator-FNhY7Ssz.cjs.map +1 -0
  30. package/dist/{Route53Provider-CH9XH7bz.cjs → Route53Provider-Bllus2NR.cjs} +21 -22
  31. package/dist/Route53Provider-Bllus2NR.cjs.map +1 -0
  32. package/dist/{Route53Provider-C0xmer8U.mjs → Route53Provider-QXxjkZO1.mjs} +13 -13
  33. package/dist/Route53Provider-QXxjkZO1.mjs.map +1 -0
  34. package/dist/S3StateStore-DGKZgyKz.cjs +222 -0
  35. package/dist/S3StateStore-DGKZgyKz.cjs.map +1 -0
  36. package/dist/S3StateStore-pZZnLLBd.mjs +223 -0
  37. package/dist/S3StateStore-pZZnLLBd.mjs.map +1 -0
  38. package/dist/SSMStateStore-CZRMERDA.mjs +205 -0
  39. package/dist/SSMStateStore-CZRMERDA.mjs.map +1 -0
  40. package/dist/SSMStateStore-DzkyjQ5D.cjs +204 -0
  41. package/dist/SSMStateStore-DzkyjQ5D.cjs.map +1 -0
  42. package/dist/SubscriberGenerator-C8CPxrCK.cjs +592 -0
  43. package/dist/SubscriberGenerator-C8CPxrCK.cjs.map +1 -0
  44. package/dist/SubscriberGenerator-y3pncae_.mjs +533 -0
  45. package/dist/SubscriberGenerator-y3pncae_.mjs.map +1 -0
  46. package/dist/add-C0kXOsWS.mjs +717 -0
  47. package/dist/add-C0kXOsWS.mjs.map +1 -0
  48. package/dist/add-Df8cmz0H.cjs +719 -0
  49. package/dist/add-Df8cmz0H.cjs.map +1 -0
  50. package/dist/appPorts-BoXMwolc.mjs +249 -0
  51. package/dist/appPorts-BoXMwolc.mjs.map +1 -0
  52. package/dist/appPorts-IW-OZmRi.cjs +296 -0
  53. package/dist/appPorts-IW-OZmRi.cjs.map +1 -0
  54. package/dist/aws-8QQ8n-t6.mjs +89 -0
  55. package/dist/aws-8QQ8n-t6.mjs.map +1 -0
  56. package/dist/aws-DY9NqQIT.cjs +100 -0
  57. package/dist/aws-DY9NqQIT.cjs.map +1 -0
  58. package/dist/awsStore-Bx5nCFnS.mjs +121 -0
  59. package/dist/awsStore-Bx5nCFnS.mjs.map +1 -0
  60. package/dist/awsStore-u3ehhMoY.cjs +138 -0
  61. package/dist/awsStore-u3ehhMoY.cjs.map +1 -0
  62. package/dist/{backup-provisioner-DXXg6FIL.mjs → backup-provisioner-C8DnCmxK.mjs} +11 -8
  63. package/dist/backup-provisioner-C8DnCmxK.mjs.map +1 -0
  64. package/dist/{backup-provisioner-cE2PuCTb.cjs → backup-provisioner-oDEsPj02.cjs} +22 -20
  65. package/dist/backup-provisioner-oDEsPj02.cjs.map +1 -0
  66. package/dist/backups/runner.cjs +519 -0
  67. package/dist/backups/runner.cjs.map +1 -0
  68. package/dist/backups/runner.d.cts +102 -0
  69. package/dist/backups/runner.d.cts.map +1 -0
  70. package/dist/backups/runner.d.mts +102 -0
  71. package/dist/backups/runner.d.mts.map +1 -0
  72. package/dist/backups/runner.mjs +506 -0
  73. package/dist/backups/runner.mjs.map +1 -0
  74. package/dist/{bundler-Bux2iF-v.mjs → bundler-B-I4Du99.mjs} +35 -16
  75. package/dist/bundler-B-I4Du99.mjs.map +1 -0
  76. package/dist/{bundler-BMekgx7a.cjs → bundler-Dx_grUmc.cjs} +37 -19
  77. package/dist/bundler-Dx_grUmc.cjs.map +1 -0
  78. package/dist/cli-Cd9exatJ.cjs +71 -0
  79. package/dist/cli-Cd9exatJ.cjs.map +1 -0
  80. package/dist/cli-DL7GxGAe.mjs +71 -0
  81. package/dist/cli-DL7GxGAe.mjs.map +1 -0
  82. package/dist/compose-C43c03WZ.mjs +3284 -0
  83. package/dist/compose-C43c03WZ.mjs.map +1 -0
  84. package/dist/compose-Mdgea4Yt.cjs +3427 -0
  85. package/dist/compose-Mdgea4Yt.cjs.map +1 -0
  86. package/dist/config-D48erO2j.d.mts +269 -0
  87. package/dist/config-D48erO2j.d.mts.map +1 -0
  88. package/dist/config-DHDtsQrB.d.cts +269 -0
  89. package/dist/config-DHDtsQrB.d.cts.map +1 -0
  90. package/dist/config.cjs +421 -11
  91. package/dist/config.cjs.map +1 -0
  92. package/dist/config.d.cts +4 -120
  93. package/dist/config.d.mts +4 -120
  94. package/dist/config.mjs +405 -4
  95. package/dist/config.mjs.map +1 -0
  96. package/dist/credentialSchemas-B67WJOOm.cjs +272 -0
  97. package/dist/credentialSchemas-B67WJOOm.cjs.map +1 -0
  98. package/dist/credentialSchemas-DDOLRCLF.mjs +237 -0
  99. package/dist/credentialSchemas-DDOLRCLF.mjs.map +1 -0
  100. package/dist/credentials-B5N5yKk6.mjs +267 -0
  101. package/dist/credentials-B5N5yKk6.mjs.map +1 -0
  102. package/dist/credentials-Zqr3QQYB.cjs +350 -0
  103. package/dist/credentials-Zqr3QQYB.cjs.map +1 -0
  104. package/dist/databases-BPOgTn1u.mjs +522 -0
  105. package/dist/databases-BPOgTn1u.mjs.map +1 -0
  106. package/dist/databases-fOaoBInm.cjs +625 -0
  107. package/dist/databases-fOaoBInm.cjs.map +1 -0
  108. package/dist/define-6poNqm5O.mjs +106 -0
  109. package/dist/define-6poNqm5O.mjs.map +1 -0
  110. package/dist/define-crmMcXFS.cjs +153 -0
  111. package/dist/define-crmMcXFS.cjs.map +1 -0
  112. package/dist/deploy/public.cjs +212 -0
  113. package/dist/deploy/public.cjs.map +1 -0
  114. package/dist/deploy/public.d.cts +654 -0
  115. package/dist/deploy/public.d.cts.map +1 -0
  116. package/dist/deploy/public.d.mts +654 -0
  117. package/dist/deploy/public.d.mts.map +1 -0
  118. package/dist/deploy/public.mjs +145 -0
  119. package/dist/deploy/public.mjs.map +1 -0
  120. package/dist/deploy/sniffer-envkit-patch.cjs +18 -10
  121. package/dist/deploy/sniffer-envkit-patch.cjs.map +1 -1
  122. package/dist/deploy/sniffer-envkit-patch.d.cts +0 -2
  123. package/dist/deploy/sniffer-envkit-patch.d.cts.map +1 -1
  124. package/dist/deploy/sniffer-envkit-patch.d.mts +0 -2
  125. package/dist/deploy/sniffer-envkit-patch.d.mts.map +1 -1
  126. package/dist/deploy/sniffer-envkit-patch.mjs +10 -2
  127. package/dist/deploy/sniffer-envkit-patch.mjs.map +1 -1
  128. package/dist/deploy/sniffer-envparser-worker.cjs +54 -0
  129. package/dist/deploy/sniffer-envparser-worker.cjs.map +1 -0
  130. package/dist/deploy/sniffer-envparser-worker.d.cts +1 -0
  131. package/dist/deploy/sniffer-envparser-worker.d.mts +1 -0
  132. package/dist/deploy/sniffer-envparser-worker.mjs +55 -0
  133. package/dist/deploy/sniffer-envparser-worker.mjs.map +1 -0
  134. package/dist/deploy/sniffer-hooks.cjs +13 -7
  135. package/dist/deploy/sniffer-hooks.cjs.map +1 -1
  136. package/dist/deploy/sniffer-hooks.d.cts +1 -2
  137. package/dist/deploy/sniffer-hooks.d.cts.map +1 -1
  138. package/dist/deploy/sniffer-hooks.d.mts +1 -2
  139. package/dist/deploy/sniffer-hooks.d.mts.map +1 -1
  140. package/dist/deploy/sniffer-hooks.mjs +10 -3
  141. package/dist/deploy/sniffer-hooks.mjs.map +1 -1
  142. package/dist/deploy/sniffer-loader.cjs +16 -7
  143. package/dist/deploy/sniffer-loader.cjs.map +1 -1
  144. package/dist/deploy/sniffer-loader.d.cts +1 -1
  145. package/dist/deploy/sniffer-loader.d.mts +1 -1
  146. package/dist/deploy/sniffer-loader.mjs +14 -3
  147. package/dist/deploy/sniffer-loader.mjs.map +1 -1
  148. package/dist/deploy/sniffer-routes-worker.cjs +11 -11
  149. package/dist/deploy/sniffer-routes-worker.cjs.map +1 -1
  150. package/dist/deploy/sniffer-routes-worker.d.cts +1 -1
  151. package/dist/deploy/sniffer-routes-worker.d.mts +1 -1
  152. package/dist/deploy/sniffer-routes-worker.mjs +4 -4
  153. package/dist/deploy/sniffer-routes-worker.mjs.map +1 -1
  154. package/dist/deploy/sniffer-worker.cjs +15 -6
  155. package/dist/deploy/sniffer-worker.cjs.map +1 -1
  156. package/dist/deploy/sniffer-worker.d.cts +1 -3
  157. package/dist/deploy/sniffer-worker.d.cts.map +1 -1
  158. package/dist/deploy/sniffer-worker.d.mts +1 -3
  159. package/dist/deploy/sniffer-worker.d.mts.map +1 -1
  160. package/dist/deploy/sniffer-worker.mjs +15 -4
  161. package/dist/deploy/sniffer-worker.mjs.map +1 -1
  162. package/dist/deploy-BMM2hx-K.cjs +2401 -0
  163. package/dist/deploy-BMM2hx-K.cjs.map +1 -0
  164. package/dist/deploy-D5YhwDng.mjs +2328 -0
  165. package/dist/deploy-D5YhwDng.mjs.map +1 -0
  166. package/dist/derive-B4vDpzgP.mjs +150 -0
  167. package/dist/derive-B4vDpzgP.mjs.map +1 -0
  168. package/dist/derive-DAbo49sm.cjs +161 -0
  169. package/dist/derive-DAbo49sm.cjs.map +1 -0
  170. package/dist/discover-C5roJuc9.mjs +560 -0
  171. package/dist/discover-C5roJuc9.mjs.map +1 -0
  172. package/dist/discover-CSW_BMWa.d.cts +125 -0
  173. package/dist/discover-CSW_BMWa.d.cts.map +1 -0
  174. package/dist/discover-DozUKs8f.cjs +639 -0
  175. package/dist/discover-DozUKs8f.cjs.map +1 -0
  176. package/dist/discover-xtT7fgWg.d.mts +125 -0
  177. package/dist/discover-xtT7fgWg.d.mts.map +1 -0
  178. package/dist/dns-BIYf20p7.cjs +1057 -0
  179. package/dist/dns-BIYf20p7.cjs.map +1 -0
  180. package/dist/dns-agf2VCdV.mjs +926 -0
  181. package/dist/dns-agf2VCdV.mjs.map +1 -0
  182. package/dist/dokploy-2p4PK6ej.mjs +38 -0
  183. package/dist/dokploy-2p4PK6ej.mjs.map +1 -0
  184. package/dist/dokploy-BANMTroy.cjs +38 -0
  185. package/dist/dokploy-BANMTroy.cjs.map +1 -0
  186. package/dist/drivers-BjGDYfnC.mjs +195 -0
  187. package/dist/drivers-BjGDYfnC.mjs.map +1 -0
  188. package/dist/drivers-DbjiYpW6.cjs +224 -0
  189. package/dist/drivers-DbjiYpW6.cjs.map +1 -0
  190. package/dist/eas-CNi16SoO.cjs +337 -0
  191. package/dist/eas-CNi16SoO.cjs.map +1 -0
  192. package/dist/eas-iT2JDHCh.mjs +334 -0
  193. package/dist/eas-iT2JDHCh.mjs.map +1 -0
  194. package/dist/{emit-CIlvnDvV.mjs → emit-C1e8qD08.mjs} +13 -26
  195. package/dist/emit-C1e8qD08.mjs.map +1 -0
  196. package/dist/{emit-CUD1BWls.cjs → emit-Dmc1nvdS.cjs} +31 -57
  197. package/dist/emit-Dmc1nvdS.cjs.map +1 -0
  198. package/dist/encryption-DkXVbyZc.mjs +89 -0
  199. package/dist/encryption-DkXVbyZc.mjs.map +1 -0
  200. package/dist/encryption-d2lLtkYx.cjs +90 -0
  201. package/dist/encryption-d2lLtkYx.cjs.map +1 -0
  202. package/dist/engine-CatKW6E-.mjs +3089 -0
  203. package/dist/engine-CatKW6E-.mjs.map +1 -0
  204. package/dist/engine-DlEHexED.cjs +3202 -0
  205. package/dist/engine-DlEHexED.cjs.map +1 -0
  206. package/dist/errors-D8Gwp5kU.mjs +23 -0
  207. package/dist/errors-D8Gwp5kU.mjs.map +1 -0
  208. package/dist/errors-DMC4Umsb.cjs +34 -0
  209. package/dist/errors-DMC4Umsb.cjs.map +1 -0
  210. package/dist/github-BAeaC1Pl.cjs +833 -0
  211. package/dist/github-BAeaC1Pl.cjs.map +1 -0
  212. package/dist/github-DErsqKGN.mjs +832 -0
  213. package/dist/github-DErsqKGN.mjs.map +1 -0
  214. package/dist/googlePlay-BVcfFWRO.cjs +931 -0
  215. package/dist/googlePlay-BVcfFWRO.cjs.map +1 -0
  216. package/dist/googlePlay-BXJ5ZjMK.mjs +931 -0
  217. package/dist/googlePlay-BXJ5ZjMK.mjs.map +1 -0
  218. package/dist/identity-CBXr4wNi.mjs +129 -0
  219. package/dist/identity-CBXr4wNi.mjs.map +1 -0
  220. package/dist/identity-CbLfgQNT.cjs +182 -0
  221. package/dist/identity-CbLfgQNT.cjs.map +1 -0
  222. package/dist/{index-BzJ7QJ9c.d.mts → index-8OfpOtSI.d.cts} +39 -20
  223. package/dist/index-8OfpOtSI.d.cts.map +1 -0
  224. package/dist/{index-CfMjtdVC.d.cts → index-Dpji6Bxq.d.mts} +39 -20
  225. package/dist/index-Dpji6Bxq.d.mts.map +1 -0
  226. package/dist/index.cjs +14291 -11898
  227. package/dist/index.cjs.map +1 -1
  228. package/dist/index.d.cts +1 -1
  229. package/dist/index.d.mts +1 -1
  230. package/dist/index.mjs +13938 -11560
  231. package/dist/index.mjs.map +1 -1
  232. package/dist/local-BwC2v2Y8.mjs +224 -0
  233. package/dist/local-BwC2v2Y8.mjs.map +1 -0
  234. package/dist/local-DNhnkugT.cjs +241 -0
  235. package/dist/local-DNhnkugT.cjs.map +1 -0
  236. package/dist/migrate-Bb1MmGHl.mjs +181 -0
  237. package/dist/migrate-Bb1MmGHl.mjs.map +1 -0
  238. package/dist/migrate-D79GI0XM.cjs +271 -0
  239. package/dist/migrate-D79GI0XM.cjs.map +1 -0
  240. package/dist/migrate-L4a273dY.cjs +181 -0
  241. package/dist/migrate-L4a273dY.cjs.map +1 -0
  242. package/dist/migrate-s4QizIoM.mjs +266 -0
  243. package/dist/migrate-s4QizIoM.mjs.map +1 -0
  244. package/dist/openapi.cjs +214 -10
  245. package/dist/openapi.cjs.map +1 -0
  246. package/dist/openapi.d.cts +38 -17
  247. package/dist/openapi.d.cts.map +1 -1
  248. package/dist/openapi.d.mts +38 -17
  249. package/dist/openapi.d.mts.map +1 -1
  250. package/dist/openapi.mjs +208 -5
  251. package/dist/openapi.mjs.map +1 -0
  252. package/dist/projectBucket-BBbQ1lHF.cjs +263 -0
  253. package/dist/projectBucket-BBbQ1lHF.cjs.map +1 -0
  254. package/dist/projectBucket-C_DN4WzF.mjs +222 -0
  255. package/dist/projectBucket-C_DN4WzF.mjs.map +1 -0
  256. package/dist/provider-BqpjG9QM.cjs +57 -0
  257. package/dist/provider-BqpjG9QM.cjs.map +1 -0
  258. package/dist/provider-CEOKk8NS.mjs +46 -0
  259. package/dist/provider-CEOKk8NS.mjs.map +1 -0
  260. package/dist/publish-CcTlmJT6.mjs +123 -0
  261. package/dist/publish-CcTlmJT6.mjs.map +1 -0
  262. package/dist/publish-ydscCYsW.cjs +124 -0
  263. package/dist/publish-ydscCYsW.cjs.map +1 -0
  264. package/dist/ready-BFFP838V.cjs +404 -0
  265. package/dist/ready-BFFP838V.cjs.map +1 -0
  266. package/dist/ready-BOfogqzr.mjs +375 -0
  267. package/dist/ready-BOfogqzr.mjs.map +1 -0
  268. package/dist/reconcile/public.cjs +3 -5
  269. package/dist/reconcile/public.d.cts +11 -87
  270. package/dist/reconcile/public.d.cts.map +1 -1
  271. package/dist/reconcile/public.d.mts +11 -87
  272. package/dist/reconcile/public.d.mts.map +1 -1
  273. package/dist/reconcile/public.mjs +3 -4
  274. package/dist/{reconcile-BI0tWkwz.mjs → reconcile--I7V4Klj.mjs} +4 -7
  275. package/dist/reconcile--I7V4Klj.mjs.map +1 -0
  276. package/dist/{reconcile-Bhw5fmKu.cjs → reconcile-CuCQBa5-.cjs} +5 -8
  277. package/dist/reconcile-CuCQBa5-.cjs.map +1 -0
  278. package/dist/resolve-BLp2trep.mjs +263 -0
  279. package/dist/resolve-BLp2trep.mjs.map +1 -0
  280. package/dist/resolve-BgL-brF9.cjs +316 -0
  281. package/dist/resolve-BgL-brF9.cjs.map +1 -0
  282. package/dist/rollback-2cyLXEH1.cjs +165 -0
  283. package/dist/rollback-2cyLXEH1.cjs.map +1 -0
  284. package/dist/rollback-DwqZ8zzj.mjs +136 -0
  285. package/dist/rollback-DwqZ8zzj.mjs.map +1 -0
  286. package/dist/rolldown-runtime-BhDjJH2R.mjs +15 -0
  287. package/dist/{chunk-CUT6urMc.cjs → rolldown-runtime-C0BPl7ul.cjs} +23 -10
  288. package/dist/run-BJLIerMM.mjs +133 -0
  289. package/dist/run-BJLIerMM.mjs.map +1 -0
  290. package/dist/run-fVZ-rLnc.cjs +174 -0
  291. package/dist/run-fVZ-rLnc.cjs.map +1 -0
  292. package/dist/runtime-ACdfK59n.d.cts +82 -0
  293. package/dist/runtime-ACdfK59n.d.cts.map +1 -0
  294. package/dist/runtime-YyQuekxi.d.mts +82 -0
  295. package/dist/runtime-YyQuekxi.d.mts.map +1 -0
  296. package/dist/s3-CrPoA89T.cjs +215 -0
  297. package/dist/s3-CrPoA89T.cjs.map +1 -0
  298. package/dist/s3-DQXZdmCM.mjs +215 -0
  299. package/dist/s3-DQXZdmCM.mjs.map +1 -0
  300. package/dist/sandbox/config-worker.cjs +43 -0
  301. package/dist/sandbox/config-worker.cjs.map +1 -0
  302. package/dist/sandbox/config-worker.d.cts +1 -0
  303. package/dist/sandbox/config-worker.d.mts +1 -0
  304. package/dist/sandbox/config-worker.mjs +44 -0
  305. package/dist/sandbox/config-worker.mjs.map +1 -0
  306. package/dist/sandbox/credentials-worker.cjs +54 -0
  307. package/dist/sandbox/credentials-worker.cjs.map +1 -0
  308. package/dist/sandbox/credentials-worker.d.cts +1 -0
  309. package/dist/sandbox/credentials-worker.d.mts +1 -0
  310. package/dist/sandbox/credentials-worker.mjs +55 -0
  311. package/dist/sandbox/credentials-worker.mjs.map +1 -0
  312. package/dist/sandbox/discover-worker.cjs +50 -0
  313. package/dist/sandbox/discover-worker.cjs.map +1 -0
  314. package/dist/sandbox/discover-worker.d.cts +1 -0
  315. package/dist/sandbox/discover-worker.d.mts +1 -0
  316. package/dist/sandbox/discover-worker.mjs +51 -0
  317. package/dist/sandbox/discover-worker.mjs.map +1 -0
  318. package/dist/sandbox/migrate-worker.cjs +75 -0
  319. package/dist/sandbox/migrate-worker.cjs.map +1 -0
  320. package/dist/sandbox/migrate-worker.d.cts +1 -0
  321. package/dist/sandbox/migrate-worker.d.mts +1 -0
  322. package/dist/sandbox/migrate-worker.mjs +76 -0
  323. package/dist/sandbox/migrate-worker.mjs.map +1 -0
  324. package/dist/sandbox-C4g1eG31.d.mts +104 -0
  325. package/dist/sandbox-C4g1eG31.d.mts.map +1 -0
  326. package/dist/sandbox-CHv3OYXg.cjs +165 -0
  327. package/dist/sandbox-CHv3OYXg.cjs.map +1 -0
  328. package/dist/sandbox-CbVB7uOD.mjs +118 -0
  329. package/dist/sandbox-CbVB7uOD.mjs.map +1 -0
  330. package/dist/sandbox-CdKgQ3XU.d.cts +104 -0
  331. package/dist/sandbox-CdKgQ3XU.d.cts.map +1 -0
  332. package/dist/{workspace-DPV7FtAv.cjs → schemas-BCwKKA42.mjs} +958 -1816
  333. package/dist/schemas-BCwKKA42.mjs.map +1 -0
  334. package/dist/{workspace-CtnZnWsa.mjs → schemas-BQ_v0lEX.cjs} +1048 -1626
  335. package/dist/schemas-BQ_v0lEX.cjs.map +1 -0
  336. package/dist/secretsManager-CQORubp9.mjs +97 -0
  337. package/dist/secretsManager-CQORubp9.mjs.map +1 -0
  338. package/dist/secretsManager-RAGcEDX1.cjs +108 -0
  339. package/dist/secretsManager-RAGcEDX1.cjs.map +1 -0
  340. package/dist/seeds-C2w4UqVP.cjs +9347 -0
  341. package/dist/seeds-C2w4UqVP.cjs.map +1 -0
  342. package/dist/seeds-Cwtv-U9-.mjs +8350 -0
  343. package/dist/seeds-Cwtv-U9-.mjs.map +1 -0
  344. package/dist/serverSetup-CKs4K9gD.cjs +630 -0
  345. package/dist/serverSetup-CKs4K9gD.cjs.map +1 -0
  346. package/dist/serverSetup-P68H5Lal.mjs +630 -0
  347. package/dist/serverSetup-P68H5Lal.mjs.map +1 -0
  348. package/dist/sniffer-8C4q6Szd.mjs +1825 -0
  349. package/dist/sniffer-8C4q6Szd.mjs.map +1 -0
  350. package/dist/sniffer-CF7wNxMo.cjs +1998 -0
  351. package/dist/sniffer-CF7wNxMo.cjs.map +1 -0
  352. package/dist/sst-B-Uz4cvm.cjs +464 -0
  353. package/dist/sst-B-Uz4cvm.cjs.map +1 -0
  354. package/dist/sst-C1pxbFEd.mjs +441 -0
  355. package/dist/sst-C1pxbFEd.mjs.map +1 -0
  356. package/dist/stage-BvM_u2z4.mjs +302 -0
  357. package/dist/stage-BvM_u2z4.mjs.map +1 -0
  358. package/dist/stage-DEQJGW3r.cjs +313 -0
  359. package/dist/stage-DEQJGW3r.cjs.map +1 -0
  360. package/dist/stages-Cb9rqRbN.mjs +190 -0
  361. package/dist/stages-Cb9rqRbN.mjs.map +1 -0
  362. package/dist/stages-D4SnG5yl.cjs +190 -0
  363. package/dist/stages-D4SnG5yl.cjs.map +1 -0
  364. package/dist/target/public.cjs +15 -0
  365. package/dist/target/public.d.cts +28 -0
  366. package/dist/target/public.d.cts.map +1 -0
  367. package/dist/target/public.d.mts +28 -0
  368. package/dist/target/public.d.mts.map +1 -0
  369. package/dist/target/public.mjs +4 -0
  370. package/dist/terminal-CW_dWeTe.mjs +85 -0
  371. package/dist/terminal-CW_dWeTe.mjs.map +1 -0
  372. package/dist/terminal-DJlqcW_U.cjs +85 -0
  373. package/dist/terminal-DJlqcW_U.cjs.map +1 -0
  374. package/dist/types-B6UXlEkf.d.cts +7650 -0
  375. package/dist/types-B6UXlEkf.d.cts.map +1 -0
  376. package/dist/types-HqVPddRK.d.mts +7649 -0
  377. package/dist/types-HqVPddRK.d.mts.map +1 -0
  378. package/dist/utils-D2Nk1Nv2.cjs +205 -0
  379. package/dist/utils-D2Nk1Nv2.cjs.map +1 -0
  380. package/dist/utils-D_fxUqvU.mjs +156 -0
  381. package/dist/utils-D_fxUqvU.mjs.map +1 -0
  382. package/dist/vitest.cjs +65 -0
  383. package/dist/vitest.cjs.map +1 -0
  384. package/dist/vitest.d.cts +29 -0
  385. package/dist/vitest.d.cts.map +1 -0
  386. package/dist/vitest.d.mts +29 -0
  387. package/dist/vitest.d.mts.map +1 -0
  388. package/dist/vitest.mjs +65 -0
  389. package/dist/vitest.mjs.map +1 -0
  390. package/dist/workerRuntime-BXfhbe13.cjs +108 -0
  391. package/dist/workerRuntime-BXfhbe13.cjs.map +1 -0
  392. package/dist/workerRuntime-CsOyBRx2.mjs +79 -0
  393. package/dist/workerRuntime-CsOyBRx2.mjs.map +1 -0
  394. package/dist/workspace/index.cjs +8 -4
  395. package/dist/workspace/index.d.cts +3 -3
  396. package/dist/workspace/index.d.mts +3 -3
  397. package/dist/workspace/index.mjs +2 -3
  398. package/dist/workspace-BwqQnool.cjs +2806 -0
  399. package/dist/workspace-BwqQnool.cjs.map +1 -0
  400. package/dist/workspace-D1QbNd55.mjs +2394 -0
  401. package/dist/workspace-D1QbNd55.mjs.map +1 -0
  402. package/package.json +54 -22
  403. package/dist/CachedStateProvider-BEBl2wQT.cjs +0 -60
  404. package/dist/CachedStateProvider-BEBl2wQT.cjs.map +0 -1
  405. package/dist/CachedStateProvider-C-8wtlto.mjs +0 -3
  406. package/dist/CachedStateProvider-Co4n5Wvs.mjs +0 -54
  407. package/dist/CachedStateProvider-Co4n5Wvs.mjs.map +0 -1
  408. package/dist/CachedStateProvider-DqhGpzsm.cjs +0 -3
  409. package/dist/HostingerProvider-BOvsgATO.cjs.map +0 -1
  410. package/dist/HostingerProvider-BcyFRbqV.mjs.map +0 -1
  411. package/dist/LocalStateProvider-Bq-0C0sg.mjs +0 -42
  412. package/dist/LocalStateProvider-Bq-0C0sg.mjs.map +0 -1
  413. package/dist/LocalStateProvider-yjXZXZDM.cjs +0 -43
  414. package/dist/LocalStateProvider-yjXZXZDM.cjs.map +0 -1
  415. package/dist/Route53Provider-C0xmer8U.mjs.map +0 -1
  416. package/dist/Route53Provider-CH9XH7bz.cjs.map +0 -1
  417. package/dist/SSMStateProvider-CXtNgPfy.cjs +0 -66
  418. package/dist/SSMStateProvider-CXtNgPfy.cjs.map +0 -1
  419. package/dist/SSMStateProvider-DOZifZfE.mjs +0 -66
  420. package/dist/SSMStateProvider-DOZifZfE.mjs.map +0 -1
  421. package/dist/backup-provisioner-DXXg6FIL.mjs.map +0 -1
  422. package/dist/backup-provisioner-cE2PuCTb.cjs.map +0 -1
  423. package/dist/bundler-BMekgx7a.cjs.map +0 -1
  424. package/dist/bundler-Bux2iF-v.mjs.map +0 -1
  425. package/dist/chunk-Duj1WY3L.mjs +0 -7
  426. package/dist/config-DTsVjKZD.mjs +0 -402
  427. package/dist/config-DTsVjKZD.mjs.map +0 -1
  428. package/dist/config-RYR9j6EF.cjs +0 -462
  429. package/dist/config-RYR9j6EF.cjs.map +0 -1
  430. package/dist/config.d.cts.map +0 -1
  431. package/dist/config.d.mts.map +0 -1
  432. package/dist/credentials-B5zRHdAl.mjs +0 -141
  433. package/dist/credentials-B5zRHdAl.mjs.map +0 -1
  434. package/dist/credentials-BapzjyV5.cjs +0 -195
  435. package/dist/credentials-BapzjyV5.cjs.map +0 -1
  436. package/dist/credentials-DQRvPz2S.cjs +0 -2769
  437. package/dist/credentials-DQRvPz2S.cjs.map +0 -1
  438. package/dist/credentials-jMJC63qs.mjs +0 -2625
  439. package/dist/credentials-jMJC63qs.mjs.map +0 -1
  440. package/dist/discover-BYHQwQqu.mjs +0 -242
  441. package/dist/discover-BYHQwQqu.mjs.map +0 -1
  442. package/dist/discover-DmW9Bscc.cjs +0 -290
  443. package/dist/discover-DmW9Bscc.cjs.map +0 -1
  444. package/dist/dokploy-api-5cK2InBm.cjs +0 -3
  445. package/dist/dokploy-api-D2Ny4Jrc.mjs +0 -3
  446. package/dist/dokploy-api-pdaBryoY.mjs +0 -706
  447. package/dist/dokploy-api-pdaBryoY.mjs.map +0 -1
  448. package/dist/dokploy-api-zqKe9lHH.cjs +0 -718
  449. package/dist/dokploy-api-zqKe9lHH.cjs.map +0 -1
  450. package/dist/emit-CIlvnDvV.mjs.map +0 -1
  451. package/dist/emit-CUD1BWls.cjs.map +0 -1
  452. package/dist/encryption-D2pL3tHH.cjs +0 -54
  453. package/dist/encryption-D2pL3tHH.cjs.map +0 -1
  454. package/dist/encryption-YDsXXi6w.mjs +0 -3
  455. package/dist/encryption-_4zwjOAR.mjs +0 -42
  456. package/dist/encryption-_4zwjOAR.mjs.map +0 -1
  457. package/dist/encryption-sQ2Oxx0d.cjs +0 -4
  458. package/dist/fullstack-secrets-B6KBHf-g.mjs +0 -87
  459. package/dist/fullstack-secrets-B6KBHf-g.mjs.map +0 -1
  460. package/dist/fullstack-secrets-DL8v0y4D.cjs +0 -99
  461. package/dist/fullstack-secrets-DL8v0y4D.cjs.map +0 -1
  462. package/dist/generator-CNzBw7g5.cjs +0 -289
  463. package/dist/generator-CNzBw7g5.cjs.map +0 -1
  464. package/dist/generator-VE2JrFlY.mjs +0 -253
  465. package/dist/generator-VE2JrFlY.mjs.map +0 -1
  466. package/dist/github-BThvbf2W.cjs +0 -197
  467. package/dist/github-BThvbf2W.cjs.map +0 -1
  468. package/dist/github-DpMZurEK.mjs +0 -196
  469. package/dist/github-DpMZurEK.mjs.map +0 -1
  470. package/dist/index-BzJ7QJ9c.d.mts.map +0 -1
  471. package/dist/index-CfMjtdVC.d.cts.map +0 -1
  472. package/dist/keystore-C9rint2E.cjs +0 -101
  473. package/dist/keystore-C9rint2E.cjs.map +0 -1
  474. package/dist/keystore-TxeYM7an.mjs +0 -83
  475. package/dist/keystore-TxeYM7an.mjs.map +0 -1
  476. package/dist/openapi-Bs3-5q_r.mjs +0 -2021
  477. package/dist/openapi-Bs3-5q_r.mjs.map +0 -1
  478. package/dist/openapi-DWLTsYLL.cjs +0 -2075
  479. package/dist/openapi-DWLTsYLL.cjs.map +0 -1
  480. package/dist/openapi-react-query-Byltvm_7.mjs +0 -167
  481. package/dist/openapi-react-query-Byltvm_7.mjs.map +0 -1
  482. package/dist/openapi-react-query-CmJ1xDbn.cjs +0 -173
  483. package/dist/openapi-react-query-CmJ1xDbn.cjs.map +0 -1
  484. package/dist/openapi-react-query.cjs +0 -4
  485. package/dist/openapi-react-query.d.cts +0 -11
  486. package/dist/openapi-react-query.d.cts.map +0 -1
  487. package/dist/openapi-react-query.d.mts +0 -11
  488. package/dist/openapi-react-query.d.mts.map +0 -1
  489. package/dist/openapi-react-query.mjs +0 -4
  490. package/dist/reconcile-BI0tWkwz.mjs.map +0 -1
  491. package/dist/reconcile-Bhw5fmKu.cjs.map +0 -1
  492. package/dist/setup-BmLoNrDX.mjs +0 -12
  493. package/dist/setup-BrR1_xGy.cjs +0 -12
  494. package/dist/setup-BsNR2LBG.cjs +0 -467
  495. package/dist/setup-BsNR2LBG.cjs.map +0 -1
  496. package/dist/setup-D5-JMknk.mjs +0 -437
  497. package/dist/setup-D5-JMknk.mjs.map +0 -1
  498. package/dist/storage-B020InPW.mjs +0 -222
  499. package/dist/storage-B020InPW.mjs.map +0 -1
  500. package/dist/storage-CSNplaJn.cjs +0 -282
  501. package/dist/storage-CSNplaJn.cjs.map +0 -1
  502. package/dist/storage-DGBzMLZa.mjs +0 -4
  503. package/dist/storage-DlVol_oj.cjs +0 -8
  504. package/dist/sync-0ILCb-1S.cjs +0 -93
  505. package/dist/sync-0ILCb-1S.cjs.map +0 -1
  506. package/dist/sync-CzHXiR9c.mjs +0 -76
  507. package/dist/sync-CzHXiR9c.mjs.map +0 -1
  508. package/dist/sync-DYENfOt4.cjs +0 -4
  509. package/dist/sync-HAau6h_R.mjs +0 -3
  510. package/dist/types-DVIx8I1N.d.mts +0 -1950
  511. package/dist/types-DVIx8I1N.d.mts.map +0 -1
  512. package/dist/types-PMP_qXRY.d.cts +0 -1950
  513. package/dist/types-PMP_qXRY.d.cts.map +0 -1
  514. package/dist/workspace-Cji6lE8E.cjs +0 -10
  515. package/dist/workspace-CkJAtRIX.mjs +0 -9
  516. package/dist/workspace-CtnZnWsa.mjs.map +0 -1
  517. package/dist/workspace-DPV7FtAv.cjs.map +0 -1
@@ -1,2075 +0,0 @@
1
- const require_chunk = require('./chunk-CUT6urMc.cjs');
2
- const require_discover = require('./discover-DmW9Bscc.cjs');
3
- const require_config = require('./config-RYR9j6EF.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
-
12
- //#region src/build/endpoint-analyzer.ts
13
- /**
14
- * Analyze an endpoint to extract its features
15
- */
16
- function analyzeEndpointFeatures(endpoint) {
17
- return {
18
- hasAuth: !!endpoint.authorizer,
19
- hasServices: endpoint.services.length > 0,
20
- hasDatabase: !!endpoint.databaseService,
21
- hasBodyValidation: !!endpoint.input?.body,
22
- hasQueryValidation: !!endpoint.input?.query,
23
- hasParamValidation: !!endpoint.input?.params,
24
- hasAudits: (endpoint.audits?.length ?? 0) > 0,
25
- hasEvents: (endpoint.events?.length ?? 0) > 0,
26
- hasRateLimit: !!endpoint.rateLimit,
27
- hasRls: !!endpoint.rlsConfig && !endpoint.rlsBypass,
28
- hasOutputValidation: !!endpoint.outputSchema
29
- };
30
- }
31
- /**
32
- * Determine the optimization tier for an endpoint based on its features
33
- */
34
- function determineEndpointTier(features) {
35
- const { hasAuth, hasServices, hasDatabase, hasAudits, hasEvents, hasRateLimit, hasRls } = features;
36
- if (!hasAuth && !hasServices && !hasDatabase && !hasAudits && !hasEvents && !hasRateLimit && !hasRls) return "minimal";
37
- if (hasAudits || hasRls || hasRateLimit) return "full";
38
- return "standard";
39
- }
40
- /**
41
- * Perform complete analysis of an endpoint
42
- */
43
- function analyzeEndpoint(endpoint, exportName) {
44
- const features = analyzeEndpointFeatures(endpoint);
45
- const tier = determineEndpointTier(features);
46
- return {
47
- route: endpoint.route,
48
- method: endpoint.method,
49
- exportName,
50
- features,
51
- tier,
52
- serviceNames: endpoint.services.map((s) => s.serviceName),
53
- databaseServiceName: endpoint.databaseService?.serviceName
54
- };
55
- }
56
- /**
57
- * Generate a summary of endpoint analysis for logging
58
- */
59
- function summarizeAnalysis(analyses) {
60
- const byTier = {
61
- minimal: 0,
62
- standard: 0,
63
- full: 0
64
- };
65
- const byFeature = {
66
- hasAuth: 0,
67
- hasServices: 0,
68
- hasDatabase: 0,
69
- hasBodyValidation: 0,
70
- hasQueryValidation: 0,
71
- hasParamValidation: 0,
72
- hasAudits: 0,
73
- hasEvents: 0,
74
- hasRateLimit: 0,
75
- hasRls: 0,
76
- hasOutputValidation: 0
77
- };
78
- for (const analysis of analyses) {
79
- byTier[analysis.tier]++;
80
- for (const [feature, enabled] of Object.entries(analysis.features)) if (enabled) byFeature[feature]++;
81
- }
82
- return {
83
- total: analyses.length,
84
- byTier,
85
- byFeature
86
- };
87
- }
88
-
89
- //#endregion
90
- //#region src/build/handler-templates.ts
91
- /**
92
- * Generate validator references for an endpoint
93
- */
94
- function generateValidators(exportName, features) {
95
- const validators = [];
96
- if (features.hasBodyValidation) validators.push(`validateBody(${exportName})`);
97
- if (features.hasQueryValidation) validators.push(`validateQuery(${exportName})`);
98
- if (features.hasParamValidation) validators.push(`validateParams(${exportName})`);
99
- return validators.length > 0 ? `\n ${validators.join(",\n ")},` : "";
100
- }
101
- /**
102
- * Generate a minimal handler (near-raw-Hono performance)
103
- *
104
- * Used for: Health checks, public endpoints with no services
105
- */
106
- function generateMinimalHandler(analysis) {
107
- const { exportName, features } = analysis;
108
- const method = analysis.method.toLowerCase();
109
- const validators = generateValidators(exportName, features);
110
- const hasValidators = validators.length > 0;
111
- if (!hasValidators && !features.hasOutputValidation) return `
112
- // Minimal handler: ${analysis.route} (${analysis.method})
113
- app.${method}('${analysis.route}', async (c) => {
114
- const result = await ${exportName}.handler(
115
- {
116
- services: {},
117
- logger,
118
- body: undefined,
119
- query: undefined,
120
- params: undefined,
121
- session: undefined,
122
- header: Endpoint.createHeaders(c.req.header()),
123
- cookie: Endpoint.createCookies(c.req.header().cookie),
124
- auditor: undefined,
125
- db: undefined,
126
- } as any,
127
- { getMetadata: () => ({}) } as any,
128
- );
129
- return c.json(result, ${exportName}.status as any);
130
- });`;
131
- return `
132
- // Minimal handler with validation: ${analysis.route} (${analysis.method})
133
- app.${method}('${analysis.route}',${validators}
134
- async (c) => {
135
- const result = await ${exportName}.handler(
136
- {
137
- services: {},
138
- logger,
139
- body: ${features.hasBodyValidation ? "(c.req.valid as any)('json')" : "undefined"},
140
- query: ${features.hasQueryValidation ? "(c.req.valid as any)('query')" : "undefined"},
141
- params: ${features.hasParamValidation ? "(c.req.valid as any)('param')" : "undefined"},
142
- session: undefined,
143
- header: Endpoint.createHeaders(c.req.header()),
144
- cookie: Endpoint.createCookies(c.req.header().cookie),
145
- auditor: undefined,
146
- db: undefined,
147
- } as any,
148
- { getMetadata: () => ({}) } as any,
149
- );
150
- ${features.hasOutputValidation ? `const output = await ${exportName}.parseOutput(result);
151
- return c.json(output, ${exportName}.status as any);` : `return c.json(result, ${exportName}.status as any);`}
152
- }
153
- );`;
154
- }
155
- /**
156
- * Generate a standard handler (auth and/or services)
157
- *
158
- * Used for: Authenticated endpoints, endpoints with services
159
- */
160
- function generateStandardHandler(analysis) {
161
- const { exportName, features } = analysis;
162
- const method = analysis.method.toLowerCase();
163
- const validators = generateValidators(exportName, features);
164
- let serviceResolution = "";
165
- if (features.hasServices || features.hasDatabase) serviceResolution = `
166
- const services = await serviceDiscovery.register(${exportName}.services);
167
- ${features.hasDatabase ? `const db = ${exportName}.databaseService
168
- ? (await serviceDiscovery.register([${exportName}.databaseService]) as any)[${exportName}.databaseService.serviceName]
169
- : undefined;` : "const db = undefined;"}`;
170
- else serviceResolution = `
171
- const services = {};
172
- const db = undefined;`;
173
- let authCode = "";
174
- if (features.hasAuth) authCode = `
175
- // Authentication
176
- const session = await ${exportName}.getSession({
177
- services,
178
- logger,
179
- header,
180
- cookie,
181
- ...(db !== undefined && { db }),
182
- } as any);
183
-
184
- const isAuthorized = await ${exportName}.authorize({
185
- header,
186
- cookie,
187
- services,
188
- logger,
189
- session,
190
- } as any);
191
-
192
- if (!isAuthorized) {
193
- return c.json({ error: 'Unauthorized' }, 401);
194
- }`;
195
- let eventCode = "";
196
- if (features.hasEvents) eventCode = `
197
- // Publish events on success
198
- if (Endpoint.isSuccessStatus(${exportName}.status)) {
199
- await (publishConstructEvents as any)(
200
- ${exportName},
201
- result,
202
- serviceDiscovery,
203
- logger,
204
- );
205
- }`;
206
- return `
207
- // Standard handler: ${analysis.route} (${analysis.method})
208
- app.${method}('${analysis.route}',${validators}
209
- async (c) => {
210
- const headerValues = c.req.header();
211
- const header = Endpoint.createHeaders(headerValues);
212
- const cookie = Endpoint.createCookies(headerValues.cookie);
213
- ${serviceResolution}
214
- ${authCode}
215
-
216
- const responseBuilder = new ResponseBuilder();
217
- const result = await ${exportName}.handler(
218
- {
219
- services,
220
- logger,
221
- body: ${features.hasBodyValidation ? "(c.req.valid as any)('json')" : "undefined"},
222
- query: ${features.hasQueryValidation ? "(c.req.valid as any)('query')" : "undefined"},
223
- params: ${features.hasParamValidation ? "(c.req.valid as any)('param')" : "undefined"},
224
- session: ${features.hasAuth ? "session" : "undefined"},
225
- header,
226
- cookie,
227
- auditor: undefined,
228
- db,
229
- } as any,
230
- responseBuilder,
231
- );
232
-
233
- let data = result;
234
- let metadata = responseBuilder.getMetadata();
235
-
236
- if (Endpoint.hasMetadata(result)) {
237
- data = result.data;
238
- metadata = result.metadata;
239
- }
240
-
241
- ${features.hasOutputValidation ? `const output = ${exportName}.outputSchema
242
- ? await ${exportName}.parseOutput(data)
243
- : data;` : "const output = data;"}
244
- ${eventCode}
245
-
246
- const status = (metadata.status ?? ${exportName}.status) as any;
247
- return c.json(output, status);
248
- }
249
- );`;
250
- }
251
- /**
252
- * Generate validators.ts - Shared validator middleware factories
253
- */
254
- function generateValidatorsFile(analyses) {
255
- const needsBody = analyses.some((a) => a.features.hasBodyValidation);
256
- const needsQuery = analyses.some((a) => a.features.hasQueryValidation);
257
- const needsParams = analyses.some((a) => a.features.hasParamValidation);
258
- if (!needsBody && !needsQuery && !needsParams) return `// No validators needed for this build\nexport {};\n`;
259
- const exports$1 = [];
260
- const factories = [];
261
- if (needsBody) {
262
- exports$1.push("validateBody");
263
- factories.push(`
264
- export const validateBody = (endpoint: any) =>
265
- validator('json', async (value, c) => {
266
- if (!endpoint.input?.body) return undefined;
267
- const parsed = await Endpoint.validate(endpoint.input.body, value);
268
- if (parsed.issues) return c.json(parsed.issues, 422);
269
- return parsed.value;
270
- });`);
271
- }
272
- if (needsQuery) {
273
- exports$1.push("validateQuery");
274
- factories.push(`
275
- export const validateQuery = (endpoint: any) =>
276
- validator('query', async (_, c) => {
277
- if (!endpoint.input?.query) return undefined;
278
- const rawQuery = Object.fromEntries(new URL(c.req.url).searchParams);
279
- const parsed = await Endpoint.validate(endpoint.input.query, rawQuery);
280
- if (parsed.issues) return c.json(parsed.issues, 422);
281
- return parsed.value;
282
- });`);
283
- }
284
- if (needsParams) {
285
- exports$1.push("validateParams");
286
- factories.push(`
287
- export const validateParams = (endpoint: any) =>
288
- validator('param', async (params, c) => {
289
- if (!endpoint.input?.params) return undefined;
290
- const parsed = await Endpoint.validate(endpoint.input.params, params);
291
- if (parsed.issues) return c.json(parsed.issues, 422);
292
- return parsed.value;
293
- });`);
294
- }
295
- return `/**
296
- * Generated validator middleware factories
297
- * Shared across all endpoint tiers that need validation
298
- */
299
- import { validator } from 'hono/validator';
300
- import { Endpoint } from '@geekmidas/constructs/endpoints';
301
- ${factories.join("\n")}
302
- `;
303
- }
304
- /**
305
- * Generate a standalone minimal endpoint file
306
- */
307
- function generateMinimalEndpointFile(analysis, endpointImport) {
308
- const { exportName, features } = analysis;
309
- const needsValidators = features.hasBodyValidation || features.hasQueryValidation || features.hasParamValidation;
310
- const validatorImport = needsValidators ? generateValidatorImportsForEndpoint(analysis) : "";
311
- const handler = generateMinimalHandler(analysis);
312
- return `/**
313
- * Minimal endpoint: ${analysis.route} (${analysis.method})
314
- * Near-raw-Hono performance
315
- */
316
- import type { Hono } from 'hono';
317
- import type { Logger } from '@geekmidas/logger';
318
- import { Endpoint } from '@geekmidas/constructs/endpoints';
319
- ${validatorImport}
320
- import { ${exportName} } from '${endpointImport.importPath}';
321
-
322
- export function setup${capitalize(exportName)}(
323
- app: Hono,
324
- logger: Logger,
325
- ): void {
326
- ${handler}
327
- }
328
- `;
329
- }
330
- /**
331
- * Generate a standalone standard endpoint file
332
- */
333
- function generateStandardEndpointFile(analysis, endpointImport) {
334
- const { exportName, features } = analysis;
335
- const needsValidators = features.hasBodyValidation || features.hasQueryValidation || features.hasParamValidation;
336
- const validatorImport = needsValidators ? generateValidatorImportsForEndpoint(analysis) : "";
337
- const eventsImport = features.hasEvents ? `import { publishConstructEvents } from '@geekmidas/constructs/endpoints';` : "";
338
- const handler = generateStandardHandler(analysis);
339
- return `/**
340
- * Standard endpoint: ${analysis.route} (${analysis.method})
341
- * Auth and/or services enabled
342
- */
343
- import type { Hono } from 'hono';
344
- import type { Logger } from '@geekmidas/logger';
345
- import type { ServiceDiscovery } from '@geekmidas/services';
346
- import { Endpoint, ResponseBuilder } from '@geekmidas/constructs/endpoints';
347
- ${eventsImport}
348
- ${validatorImport}
349
- import { ${exportName} } from '${endpointImport.importPath}';
350
-
351
- export function setup${capitalize(exportName)}(
352
- app: Hono,
353
- serviceDiscovery: ServiceDiscovery<any, any>,
354
- logger: Logger,
355
- ): void {
356
- ${handler}
357
- }
358
- `;
359
- }
360
- /**
361
- * Generate a standalone full endpoint file
362
- */
363
- function generateFullEndpointFile(analysis, endpointImport) {
364
- const { exportName } = analysis;
365
- return `/**
366
- * Full endpoint: ${analysis.route} (${analysis.method})
367
- * Complex features: audits, RLS, rate limiting
368
- */
369
- import type { Hono } from 'hono';
370
- import type { ServiceDiscovery } from '@geekmidas/services';
371
- import { HonoEndpoint } from '@geekmidas/constructs/hono';
372
- import { ${exportName} } from '${endpointImport.importPath}';
373
-
374
- export function setup${capitalize(exportName)}(
375
- app: Hono,
376
- serviceDiscovery: ServiceDiscovery<any, any>,
377
- openApiOptions: any,
378
- ): void {
379
- HonoEndpoint.addRoutes([${exportName}] as any, serviceDiscovery, app, openApiOptions);
380
- }
381
- `;
382
- }
383
- /**
384
- * Generate tier index file that imports and calls all endpoint setup functions
385
- */
386
- function generateTierIndexFile(tier, analyses) {
387
- const tierEndpoints = analyses.filter((a) => a.tier === tier);
388
- if (tierEndpoints.length === 0) {
389
- if (tier === "minimal") return `// No minimal-tier endpoints in this build
390
- import type { Hono } from 'hono';
391
- import type { Logger } from '@geekmidas/logger';
392
-
393
- export function setupMinimalEndpoints(
394
- _app: Hono,
395
- _logger: Logger,
396
- ): void {
397
- // No minimal endpoints
398
- }
399
- `;
400
- if (tier === "standard") return `// No standard-tier endpoints in this build
401
- import type { Hono } from 'hono';
402
- import type { Logger } from '@geekmidas/logger';
403
- import type { ServiceDiscovery } from '@geekmidas/services';
404
-
405
- export function setupStandardEndpoints(
406
- _app: Hono,
407
- _serviceDiscovery: ServiceDiscovery<any, any>,
408
- _logger: Logger,
409
- ): void {
410
- // No standard endpoints
411
- }
412
- `;
413
- return `// No full-tier endpoints in this build
414
- import type { Hono } from 'hono';
415
- import type { ServiceDiscovery } from '@geekmidas/services';
416
-
417
- export function setupFullEndpoints(
418
- _app: Hono,
419
- _serviceDiscovery: ServiceDiscovery<any, any>,
420
- _enableOpenApi: boolean,
421
- ): void {
422
- // No full endpoints
423
- }
424
- `;
425
- }
426
- const imports = tierEndpoints.map((a) => `import { setup${capitalize(a.exportName)} } from './${a.exportName}.js';`).join("\n");
427
- if (tier === "minimal") {
428
- const calls$1 = tierEndpoints.map((a) => ` setup${capitalize(a.exportName)}(app, logger);`).join("\n");
429
- return `/**
430
- * Minimal-tier endpoint index (${tierEndpoints.length} endpoints)
431
- * Near-raw-Hono performance
432
- */
433
- import type { Hono } from 'hono';
434
- import type { Logger } from '@geekmidas/logger';
435
- ${imports}
436
-
437
- export function setupMinimalEndpoints(
438
- app: Hono,
439
- logger: Logger,
440
- ): void {
441
- ${calls$1}
442
- }
443
- `;
444
- }
445
- if (tier === "standard") {
446
- const calls$1 = tierEndpoints.map((a) => ` setup${capitalize(a.exportName)}(app, serviceDiscovery, logger);`).join("\n");
447
- return `/**
448
- * Standard-tier endpoint index (${tierEndpoints.length} endpoints)
449
- * Auth and/or services enabled
450
- */
451
- import type { Hono } from 'hono';
452
- import type { Logger } from '@geekmidas/logger';
453
- import type { ServiceDiscovery } from '@geekmidas/services';
454
- ${imports}
455
-
456
- export function setupStandardEndpoints(
457
- app: Hono,
458
- serviceDiscovery: ServiceDiscovery<any, any>,
459
- logger: Logger,
460
- ): void {
461
- ${calls$1}
462
- }
463
- `;
464
- }
465
- const calls = tierEndpoints.map((a) => ` setup${capitalize(a.exportName)}(app, serviceDiscovery, openApiOptions);`).join("\n");
466
- return `/**
467
- * Full-tier endpoint index (${tierEndpoints.length} endpoints)
468
- * Complex features: audits, RLS, rate limiting
469
- */
470
- import type { Hono } from 'hono';
471
- import type { ServiceDiscovery } from '@geekmidas/services';
472
- ${imports}
473
-
474
- export function setupFullEndpoints(
475
- app: Hono,
476
- serviceDiscovery: ServiceDiscovery<any, any>,
477
- enableOpenApi: boolean,
478
- ): void {
479
- const openApiOptions: any = enableOpenApi ? {
480
- docsPath: '/__docs',
481
- openApiOptions: {
482
- title: 'API Documentation',
483
- version: '1.0.0',
484
- description: 'Generated API documentation'
485
- }
486
- } : { docsPath: false };
487
-
488
- ${calls}
489
- }
490
- `;
491
- }
492
- /**
493
- * Generate validator imports for a single endpoint
494
- */
495
- function generateValidatorImportsForEndpoint(analysis) {
496
- const imports = [];
497
- if (analysis.features.hasBodyValidation) imports.push("validateBody");
498
- if (analysis.features.hasQueryValidation) imports.push("validateQuery");
499
- if (analysis.features.hasParamValidation) imports.push("validateParams");
500
- if (imports.length === 0) return "";
501
- return `import { ${imports.join(", ")} } from '../validators.js';`;
502
- }
503
- /**
504
- * Capitalize first letter
505
- */
506
- function capitalize(str) {
507
- return str.charAt(0).toUpperCase() + str.slice(1);
508
- }
509
- /**
510
- * Generate all endpoint files with nested folder structure (per-endpoint files)
511
- */
512
- function generateEndpointFilesNested(analyses, endpointImports) {
513
- const files = {
514
- "validators.ts": generateValidatorsFile(analyses),
515
- "minimal/index.ts": generateTierIndexFile("minimal", analyses),
516
- "standard/index.ts": generateTierIndexFile("standard", analyses),
517
- "full/index.ts": generateTierIndexFile("full", analyses),
518
- "index.ts": generateNestedIndexFile(analyses)
519
- };
520
- for (const analysis of analyses) {
521
- const endpointImport = endpointImports.find((i) => i.exportName === analysis.exportName);
522
- if (!endpointImport) continue;
523
- const fileName = `${analysis.tier}/${analysis.exportName}.ts`;
524
- switch (analysis.tier) {
525
- case "minimal":
526
- files[fileName] = generateMinimalEndpointFile(analysis, endpointImport);
527
- break;
528
- case "standard":
529
- files[fileName] = generateStandardEndpointFile(analysis, endpointImport);
530
- break;
531
- case "full":
532
- files[fileName] = generateFullEndpointFile(analysis, endpointImport);
533
- break;
534
- }
535
- }
536
- return files;
537
- }
538
- /**
539
- * Generate index.ts for nested structure
540
- */
541
- function generateNestedIndexFile(analyses) {
542
- const minimalCount = analyses.filter((a) => a.tier === "minimal").length;
543
- const standardCount = analyses.filter((a) => a.tier === "standard").length;
544
- const fullCount = analyses.filter((a) => a.tier === "full").length;
545
- return `/**
546
- * Generated optimized endpoints
547
- *
548
- * Build-time optimization tiers:
549
- * - minimal: ${minimalCount} endpoints (near-raw-Hono)
550
- * - standard: ${standardCount} endpoints (auth/services)
551
- * - full: ${fullCount} endpoints (audits/rls/rate-limit)
552
- */
553
- import type { EnvironmentParser } from '@geekmidas/envkit';
554
- import type { Logger } from '@geekmidas/logger';
555
- import type { Hono } from 'hono';
556
- import { ServiceDiscovery } from '@geekmidas/services';
557
- import { setupMinimalEndpoints } from './minimal/index.js';
558
- import { setupStandardEndpoints } from './standard/index.js';
559
- import { setupFullEndpoints } from './full/index.js';
560
-
561
- export async function setupEndpoints(
562
- app: Hono,
563
- envParser: EnvironmentParser<any>,
564
- logger: Logger,
565
- enableOpenApi: boolean = false,
566
- ): Promise<void> {
567
- const serviceDiscovery = ServiceDiscovery.getInstance(envParser);
568
-
569
- // Minimal handlers (${minimalCount} endpoints) - near-raw-Hono performance
570
- setupMinimalEndpoints(app, logger);
571
-
572
- // Standard handlers (${standardCount} endpoints) - auth/services
573
- setupStandardEndpoints(app, serviceDiscovery, logger);
574
-
575
- // Full handlers (${fullCount} endpoints) - audits/rls/rate-limit
576
- setupFullEndpoints(app, serviceDiscovery, enableOpenApi);
577
-
578
- // Add Swagger UI if OpenAPI is enabled
579
- if (enableOpenApi) {
580
- try {
581
- const { swaggerUI } = await import('@hono/swagger-ui');
582
- app.get('/__docs/ui', swaggerUI({ url: '/__docs' }));
583
- } catch {
584
- // @hono/swagger-ui not installed, skip Swagger UI
585
- }
586
- }
587
- }
588
- `;
589
- }
590
-
591
- //#endregion
592
- //#region src/generators/EndpointGenerator.ts
593
- /**
594
- * How a generated entry gets its logger and environment parser.
595
- *
596
- * From the surface it serves, when there is one: the surface holds both as
597
- * *objects*, and discovery already recorded which module declares it, so the
598
- * entry imports that module and reads them off it.
599
- *
600
- * The alternative — the shape this replaces — was naming both in config as
601
- * module paths, `envParser: './config/env#envParser'`, and printing an import
602
- * for each. Two strings per app, checked by nothing, describing files the
603
- * surface was already holding the contents of.
604
- *
605
- * Falls back to the configured paths for an app that declares no surface.
606
- */
607
- 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);
611
- return {
612
- imports: `import { ${module$1.exportName} as __surface } from '${specifier}';`,
613
- bindings: [
614
- "// What this construct was declared with. Objects, not module paths:",
615
- "// the entry imports the owner, so there is nothing to print.",
616
- "const envParser = __surface.envParser;",
617
- "const logger = __surface.logger;"
618
- ].join("\n")
619
- };
620
- }
621
- throw new Error(`No owner to take a logger and an environment parser from${owner ? ` for "${owner}"` : ""}. Build it from a \`RestApi\` or a \`Worker\`.`);
622
- }
623
- /** A relative specifier ESM will accept: always prefixed, never bare. */
624
- function importSpecifier(fromDir, target) {
625
- const rel = (0, node_path.relative)(fromDir, target).replace(/\.ts$/, ".js");
626
- return rel.startsWith(".") ? rel : `./${rel}`;
627
- }
628
- /**
629
- * CORS for a surface, derived rather than hand-written.
630
- *
631
- * Who may call a surface is already in the graph — every construct that
632
- * declared an edge to it — and reaches the process as one comma-separated
633
- * value. An application that maintained this by hand maintained a list that was
634
- * wrong in two directions at once: it trusted origins nothing was serving, and
635
- * it could not name hosts a deploy had not chosen yet.
636
- *
637
- * Only the parts a graph cannot answer are configurable, and every one has a
638
- * default: a surface that says nothing about CORS still gets it.
639
- */
640
- function corsFor(surface) {
641
- if (!surface) return {
642
- imports: "",
643
- setup: ""
644
- };
645
- const cors = surface.cors ?? {};
646
- const allowHeaders = [
647
- "content-type",
648
- "authorization",
649
- ...cors.allowHeaders ?? []
650
- ];
651
- return {
652
- imports: `import { cors } from 'hono/cors';`,
653
- setup: `
654
- // Who may call ${surface.id}, read off the graph rather than listed here.
655
- {
656
- const { origins } = envParser
657
- .create((get) => ({
658
- origins: get('${surface.trustedOriginsKey}')
659
- .string()
660
- .default('')
661
- .transform((value: string) =>
662
- value.split(',').map((origin) => origin.trim()).filter(Boolean),
663
- ),
664
- }))
665
- .parse();
666
-
667
- honoApp.use('*', cors({
668
- origin: origins,
669
- allowMethods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH', 'OPTIONS'],
670
- allowHeaders: ${JSON.stringify(allowHeaders)},${cors.exposeHeaders ? `\n exposeHeaders: ${JSON.stringify(cors.exposeHeaders)},` : ""}
671
- credentials: ${cors.credentials ?? true},
672
- maxAge: ${cors.maxAge ?? 86400},
673
- }));
674
- }
675
- `
676
- };
677
- }
678
- var EndpointGenerator = class extends require_discover.ConstructGenerator {
679
- isConstruct(value) {
680
- return __geekmidas_constructs_endpoints.Endpoint.isEndpoint(value);
681
- }
682
- async build(context, constructs, outputDir, options) {
683
- const provider = options?.provider || "aws-apigatewayv2";
684
- const enableOpenApi = options?.enableOpenApi || false;
685
- const logger = console;
686
- const routes = [];
687
- if (constructs.length === 0) return routes;
688
- if (provider === "server") {
689
- await this.generateEndpointsFile(outputDir, constructs, context);
690
- const appFile = await this.generateAppFile(outputDir, context);
691
- routes.push({
692
- path: "*",
693
- method: "ALL",
694
- handler: (0, node_path.relative)(process.cwd(), appFile),
695
- authorizer: "none"
696
- });
697
- 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);
718
- const routeInfo = {
719
- path: construct._path,
720
- method: construct.method,
721
- handler: (0, node_path.relative)(process.cwd(), handlerFile).replace(/\.ts$/, ".handler"),
722
- timeout: construct.timeout,
723
- memorySize: construct.memorySize,
724
- environment: await construct.getEnvironment({ markOptional: context.markOptional }),
725
- dependencies: construct.constructs,
726
- authorizer: construct.authorizer?.name ?? "none"
727
- };
728
- routes.push(routeInfo);
729
- logger.log(`Generated handler for ${routeInfo.method} ${routeInfo.path}`);
730
- }
731
- return routes;
732
- }
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);
752
- return handlerPath;
753
- }
754
- async generateEndpointsFile(outputDir, endpoints, context) {
755
- const endpointsFileName = "endpoints.ts";
756
- const endpointsPath = (0, node_path.join)(outputDir, endpointsFileName);
757
- const importsByFile = /* @__PURE__ */ new Map();
758
- 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");
761
- if (!importsByFile.has(importPath)) importsByFile.set(importPath, []);
762
- importsByFile.get(importPath)?.push(key);
763
- }
764
- const endpointImports = Array.from(importsByFile.entries()).map(([importPath, exports$1]) => `import { ${exports$1.join(", ")} } from '${importPath}';`).join("\n");
765
- const allExportNames = endpoints.map(({ key }) => key);
766
- if (context.production?.enabled && context.production.optimizedHandlers) return this.generateOptimizedEndpointsFile(endpointsPath, endpoints, endpointImports, allExportNames);
767
- const content = `import type { EnvironmentParser } from '@geekmidas/envkit';
768
- import type { Logger } from '@geekmidas/logger';
769
- import { HonoEndpoint } from '@geekmidas/constructs/hono';
770
- import { Endpoint } from '@geekmidas/constructs/endpoints';
771
- import { ServiceDiscovery } from '@geekmidas/services';
772
- import type { Hono } from 'hono';
773
- ${endpointImports}
774
-
775
- export const endpoints: Endpoint<any, any, any, any, any, any, any, any, any, any, any, any, any, any>[] = [
776
- ${allExportNames.join(",\n ")}
777
- ];
778
-
779
- export async function setupEndpoints(
780
- app: Hono,
781
- envParser: EnvironmentParser<any>,
782
- logger: Logger,
783
- enableOpenApi: boolean = true,
784
- ): Promise<void> {
785
- const serviceDiscovery = ServiceDiscovery.getInstance(envParser);
786
-
787
- // Configure OpenAPI options based on enableOpenApi flag
788
- const openApiOptions: any = enableOpenApi ? {
789
- docsPath: '/__docs',
790
- openApiOptions: {
791
- title: 'API Documentation',
792
- version: '1.0.0',
793
- description: 'Generated API documentation'
794
- }
795
- } : { docsPath: false };
796
-
797
- HonoEndpoint.addRoutes(endpoints, serviceDiscovery, app, openApiOptions);
798
-
799
- // Add Swagger UI if OpenAPI is enabled
800
- if (enableOpenApi) {
801
- try {
802
- const { swaggerUI } = await import('@hono/swagger-ui');
803
- app.get('/__docs/ui', swaggerUI({ url: '/__docs' }));
804
- } catch {
805
- // @hono/swagger-ui not installed, skip Swagger UI
806
- }
807
- }
808
- }
809
- `;
810
- await (0, node_fs_promises.writeFile)(endpointsPath, content);
811
- return endpointsPath;
812
- }
813
- /**
814
- * Generate optimized endpoints files with nested folder structure (per-endpoint files)
815
- */
816
- async generateOptimizedEndpointsFile(endpointsPath, endpoints, _endpointImports, _allExportNames) {
817
- const logger = console;
818
- const outputDir = (0, node_path.dirname)(endpointsPath);
819
- const endpointsDir = (0, node_path.join)(outputDir, "endpoints");
820
- await (0, node_fs_promises.mkdir)((0, node_path.join)(endpointsDir, "minimal"), { recursive: true });
821
- await (0, node_fs_promises.mkdir)((0, node_path.join)(endpointsDir, "standard"), { recursive: true });
822
- await (0, node_fs_promises.mkdir)((0, node_path.join)(endpointsDir, "full"), { recursive: true });
823
- const analyses = endpoints.map(({ key, construct }) => analyzeEndpoint(construct, key));
824
- const endpointImports = endpoints.map(({ key, path }) => {
825
- 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
- return {
829
- exportName: key,
830
- importPath
831
- };
832
- });
833
- const summary = summarizeAnalysis(analyses);
834
- logger.log(`\n📊 Endpoint Analysis:`);
835
- logger.log(` Total: ${summary.total} endpoints`);
836
- logger.log(` - Minimal (near-raw-Hono): ${summary.byTier.minimal} endpoints`);
837
- logger.log(` - Standard (auth/services): ${summary.byTier.standard} endpoints`);
838
- logger.log(` - Full (audits/rls/rate-limit): ${summary.byTier.full} endpoints`);
839
- const files = generateEndpointFilesNested(analyses, endpointImports);
840
- for (const [filename, content] of Object.entries(files)) {
841
- const filePath = (0, node_path.join)(endpointsDir, filename);
842
- await (0, node_fs_promises.mkdir)((0, node_path.dirname)(filePath), { recursive: true });
843
- await (0, node_fs_promises.writeFile)(filePath, content);
844
- }
845
- const endpointFiles = Object.keys(files).filter((f) => !f.endsWith("index.ts") && !f.endsWith("validators.ts")).length;
846
- const indexFiles = Object.keys(files).filter((f) => f.endsWith("index.ts")).length;
847
- logger.log(` Generated ${endpointFiles} endpoint files + ${indexFiles} index files + validators.ts`);
848
- return (0, node_path.join)(endpointsDir, "index.ts");
849
- }
850
- async generateAppFile(outputDir, context) {
851
- if (context.production?.enabled) return this.generateProductionAppFile(outputDir, context);
852
- const appFileName = "app.ts";
853
- const appPath = (0, node_path.join)(outputDir, appFileName);
854
- const runtime = runtimeFor(context, (0, node_path.dirname)(appPath));
855
- const telescopeEnabled = context.telescope?.enabled;
856
- const telescopeWebSocketEnabled = context.telescope?.websocket;
857
- 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
- const telescopeFromSurface = !!context.surface?.module && !usesExternalTelescope;
862
- 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 = "";
882
- const cors = corsFor(context.surface);
883
- let hooksImports = "";
884
- let beforeSetupCall = "";
885
- let afterSetupCall = "";
886
- 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}';`;
889
- beforeSetupCall = `
890
- // Call beforeSetup hook if defined
891
- if (typeof serverHooks.beforeSetup === 'function') {
892
- await serverHooks.beforeSetup(honoApp, { envParser, logger });
893
- }
894
- `;
895
- afterSetupCall = `
896
- // Call afterSetup hook if defined
897
- if (typeof serverHooks.afterSetup === 'function') {
898
- await serverHooks.afterSetup(honoApp, { envParser, logger });
899
- }
900
- `;
901
- }
902
- const telescopeWebSocketSetupCode = telescopeWebSocketEnabled ? `
903
- // Setup WebSocket for real-time telescope updates
904
- try {
905
- const { createNodeWebSocket } = await import('@hono/node-ws');
906
- const { injectWebSocket, upgradeWebSocket } = createNodeWebSocket({ app: honoApp });
907
- // Add WebSocket route directly to main app (sub-app routes don't support WS upgrade)
908
- honoApp.get('${context.telescope?.path}/ws', upgradeWebSocket(() => ({
909
- onOpen: (_event: Event, ws: any) => {
910
- telescope.addWsClient(ws);
911
- },
912
- onClose: (_event: Event, ws: any) => {
913
- telescope.removeWsClient(ws);
914
- },
915
- onMessage: (event: MessageEvent, ws: any) => {
916
- try {
917
- const data = JSON.parse(event.data);
918
- if (data.type === 'ping') {
919
- ws.send(JSON.stringify({ type: 'pong' }));
920
- }
921
- } catch {
922
- // Ignore invalid messages
923
- }
924
- },
925
- })));
926
- // Store injectWebSocket for server entry to call after serve()
927
- (honoApp as any).__injectWebSocket = injectWebSocket;
928
- logger.info('Telescope WebSocket enabled');
929
- } catch (e) {
930
- logger.warn({ error: e }, 'WebSocket support not available - install @hono/node-ws for real-time updates');
931
- }
932
- ` : "";
933
- let telescopeSetup = "";
934
- if (telescopeEnabled) if (telescopeFromSurface || usesExternalTelescope) telescopeSetup = `
935
- ${telescopeWebSocketSetupCode}
936
- // Add telescope middleware (before endpoints to capture all requests)
937
- honoApp.use('*', createMiddleware(telescope));
938
-
939
- // Mount telescope UI
940
- const telescopeUI = createUI(telescope);
941
- honoApp.route('${context.telescope?.path}', telescopeUI);
942
- `;
943
- else telescopeSetup = `
944
- // Setup Telescope for debugging/monitoring
945
- const telescopeStorage = new InMemoryStorage({ maxEntries: ${context.telescope?.maxEntries} });
946
- const telescope = new Telescope({
947
- enabled: true,
948
- path: '${context.telescope?.path}',
949
- ignorePatterns: ${JSON.stringify(context.telescope?.ignore)},
950
- recordBody: ${context.telescope?.recordBody},
951
- storage: telescopeStorage,
952
- });
953
- ${telescopeWebSocketSetupCode}
954
- // Add telescope middleware (before endpoints to capture all requests)
955
- honoApp.use('*', createMiddleware(telescope));
956
-
957
- // Mount telescope UI
958
- const telescopeUI = createUI(telescope);
959
- honoApp.route('${context.telescope?.path}', telescopeUI);
960
- `;
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,
972
- });
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
- `;
982
- const content = `/**
983
- * Generated server application
984
- *
985
- * ⚠️ WARNING: This is for LOCAL DEVELOPMENT ONLY
986
- * The subscriber polling mechanism is not production-ready.
987
- * For production, use AWS Lambda with SQS/SNS event sources.
988
- */
989
- import { Hono } from 'hono';
990
- import type { Hono as HonoType } from 'hono';
991
- import { setupEndpoints } from './endpoints.js';
992
- import { setupSubscribers } from './subscribers.js';
993
- import { setupQueues } from './queues.js';
994
- import { setupCrons } from './crons.js';
995
- ${runtime.imports}
996
- ${telescopeImports}
997
- ${studioImports}
998
- ${hooksImports}
999
- ${cors.imports}
1000
- ${context.storageDrivers?.imports ?? ""}
1001
-
1002
- ${runtime.bindings}
1003
- ${telescopeFromSurface ? "const telescope = __surface.telescope;" : ""}
1004
-
1005
- ${context.storageDrivers?.setup ? `// Which storage drivers exist is the entry point's decision: the scheme in
1006
- // each injected URL picks one, so no construct and no application module names
1007
- // a provider.
1008
- ${context.storageDrivers.setup}
1009
- ` : ""}
1010
- export interface ServerApp {
1011
- app: HonoType;
1012
- start: (options?: {
1013
- port?: number;
1014
- serve: (app: HonoType, port: number) => void | Promise<void>;
1015
- }) => Promise<void>;
1016
- }
1017
-
1018
- /**
1019
- * Create and configure the Hono application
1020
- *
1021
- * @param app - Optional Hono app instance to configure (creates new one if not provided)
1022
- * @param enableOpenApi - Enable OpenAPI documentation (default: true)
1023
- * @returns Server app with configured Hono app and start function
1024
- *
1025
- * @example
1026
- * // With Bun
1027
- * import { createApp } from './.gkm/server/app.js';
1028
- *
1029
- * const { app, start } = await createApp();
1030
- *
1031
- * await start({
1032
- * port: 3000,
1033
- * serve: (app, port) => {
1034
- * Bun.serve({ port, fetch: app.fetch });
1035
- * }
1036
- * });
1037
- *
1038
- * @example
1039
- * // With Node.js (using @hono/node-server)
1040
- * import { serve } from '@hono/node-server';
1041
- * import { createApp } from './.gkm/server/app.js';
1042
- *
1043
- * const { app, start } = await createApp();
1044
- *
1045
- * await start({
1046
- * port: 3000,
1047
- * serve: (app, port) => {
1048
- * serve({ fetch: app.fetch, port });
1049
- * }
1050
- * });
1051
- */
1052
- export async function createApp(app?: HonoType, enableOpenApi: boolean = true): Promise<ServerApp> {
1053
- const honoApp = app || new Hono();
1054
- ${telescopeSetup}${cors.setup}${beforeSetupCall}${studioSetup}
1055
- // Setup HTTP endpoints
1056
- await setupEndpoints(honoApp, envParser, logger, enableOpenApi);
1057
- ${afterSetupCall}
1058
-
1059
- return {
1060
- app: honoApp,
1061
- async start(options) {
1062
- if (!options?.serve) {
1063
- throw new Error(
1064
- 'serve function is required. Pass a serve function for your runtime:\\n' +
1065
- ' - Bun: (app, port) => Bun.serve({ port, fetch: app.fetch })\\n' +
1066
- ' - Node: (app, port) => serve({ fetch: app.fetch, port })'
1067
- );
1068
- }
1069
-
1070
- const port = options.port ?? 3000;
1071
-
1072
- // Start subscribers in background (non-blocking, local development only)
1073
- await setupSubscribers(envParser, logger).catch((error) => {
1074
- logger.error({ error }, 'Failed to start subscribers');
1075
- });
1076
-
1077
- // Start queue workers in background (non-blocking, local development only)
1078
- await setupQueues(envParser, logger).catch((error) => {
1079
- logger.error({ error }, 'Failed to start queue workers');
1080
- });
1081
-
1082
- // Schedule this app's crons. Caught like the others: a scheduler that
1083
- // cannot start is not a reason for the HTTP server not to.
1084
- await setupCrons(envParser, logger).catch((error) => {
1085
- logger.error({ error }, 'Failed to schedule crons');
1086
- });
1087
-
1088
- logger.info({ port }, 'Starting server');
1089
-
1090
- // Start HTTP server using provided serve function
1091
- await options.serve(honoApp, port);
1092
-
1093
- logger.info({ port }, 'Server started');
1094
- }
1095
- };
1096
- }
1097
-
1098
- // Default export for convenience
1099
- export default createApp;
1100
- `;
1101
- await (0, node_fs_promises.writeFile)(appPath, content);
1102
- return appPath;
1103
- }
1104
- /**
1105
- * One Lambda, one endpoint — and no environment import.
1106
- *
1107
- * The endpoint was built from its surface, so it carries the parser the
1108
- * adaptor needs. This used to read
1109
- * `import { envParser } from '../../config/env'`, a line the build wrote
1110
- * because a generator can print a module specifier and cannot print an
1111
- * object. Nothing has to be printed now, which is also why nothing has to be
1112
- * named in config.
1113
- */
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
- generateAWSApiGatewayV2Handler(importPath, exportName, drivers) {
1135
- return `import { AmazonApiGatewayV2Endpoint } from '@geekmidas/constructs/aws';
1136
- import { ${exportName} } from '${importPath}';
1137
- ${drivers?.imports ?? ""}
1138
- ${drivers?.setup ? `\n// The handler registers the drivers its target needs.\n${drivers.setup}\n` : ""}
1139
- const adapter = new AmazonApiGatewayV2Endpoint(${exportName});
1140
-
1141
- 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
- `;
1150
- }
1151
- /**
1152
- * Generate a production-optimized app.ts file
1153
- * No dev tools (Telescope, Studio, WebSocket), includes health checks and graceful shutdown
1154
- */
1155
- async generateProductionAppFile(outputDir, context) {
1156
- const appFileName = "app.ts";
1157
- const appPath = (0, node_path.join)(outputDir, appFileName);
1158
- const runtime = runtimeFor(context, (0, node_path.dirname)(appPath));
1159
- const production = context.production;
1160
- const healthCheckPath = production.healthCheck;
1161
- const enableGracefulShutdown = production.gracefulShutdown;
1162
- const enableOpenApi = production.openapi;
1163
- const includeSubscribers = production.subscribers === "include";
1164
- const cors = corsFor(context.surface);
1165
- let hooksImports = "";
1166
- let beforeSetupCall = "";
1167
- let afterSetupCall = "";
1168
- 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}';`;
1171
- beforeSetupCall = `
1172
- // Call beforeSetup hook if defined
1173
- if (typeof serverHooks.beforeSetup === 'function') {
1174
- await serverHooks.beforeSetup(honoApp, { envParser, logger });
1175
- }
1176
- `;
1177
- afterSetupCall = `
1178
- // Call afterSetup hook if defined
1179
- if (typeof serverHooks.afterSetup === 'function') {
1180
- await serverHooks.afterSetup(honoApp, { envParser, logger });
1181
- }
1182
- `;
1183
- }
1184
- const subscriberSetup = includeSubscribers ? `
1185
- // Start subscribers in background
1186
- await setupSubscribers(envParser, logger).catch((error) => {
1187
- logger.error({ error }, 'Failed to start subscribers');
1188
- });
1189
-
1190
- // Start queue workers in background
1191
- await setupQueues(envParser, logger).catch((error) => {
1192
- logger.error({ error }, 'Failed to start queue workers');
1193
- });
1194
-
1195
- // Schedule this app's crons. Caught like the others: a scheduler that
1196
- // cannot start is not a reason for the HTTP server not to.
1197
- await setupCrons(envParser, logger).catch((error) => {
1198
- logger.error({ error }, 'Failed to schedule crons');
1199
- });
1200
- ` : "";
1201
- const subscriberImport = includeSubscribers ? `import { setupSubscribers } from './subscribers.js';
1202
- import { setupQueues } from './queues.js';
1203
- import { setupCrons } from './crons.js';` : "";
1204
- const gracefulShutdownCode = enableGracefulShutdown ? `
1205
- // Graceful shutdown handling
1206
- let isShuttingDown = false;
1207
-
1208
- const shutdown = async () => {
1209
- if (isShuttingDown) return;
1210
- isShuttingDown = true;
1211
- logger.info('Graceful shutdown initiated');
1212
- // Allow in-flight requests to complete (30s timeout)
1213
- setTimeout(() => process.exit(0), 30000);
1214
- };
1215
-
1216
- process.on('SIGTERM', shutdown);
1217
- process.on('SIGINT', shutdown);
1218
- ` : "";
1219
- const endpointsImportPath = production.optimizedHandlers ? "./endpoints/index.js" : "./endpoints.js";
1220
- const content = `/**
1221
- * Generated production server application
1222
- *
1223
- * This is a production-optimized build without dev tools.
1224
- * - No Telescope debugging dashboard
1225
- * - No Studio database browser
1226
- * - No WebSocket updates
1227
- * - Includes health checks and graceful shutdown
1228
- */
1229
- import { Hono } from 'hono';
1230
- import type { Hono as HonoType } from 'hono';
1231
- import { setupEndpoints } from '${endpointsImportPath}';
1232
- ${subscriberImport}
1233
- ${runtime.imports}
1234
- ${runtime.bindings}
1235
- ${hooksImports}
1236
- ${cors.imports}
1237
- ${context.storageDrivers?.imports ?? ""}
1238
-
1239
- ${context.storageDrivers?.setup ? `// The entry point registers the drivers its target needs.
1240
- ${context.storageDrivers.setup}
1241
- ` : ""}
1242
- export interface ServerApp {
1243
- app: HonoType;
1244
- start: (options?: {
1245
- port?: number;
1246
- serve: (app: HonoType, port: number) => void | Promise<void>;
1247
- }) => Promise<void>;
1248
- }
1249
-
1250
- /**
1251
- * Create and configure the production Hono application
1252
- */
1253
- export async function createApp(app?: HonoType): Promise<ServerApp> {
1254
- const honoApp = app || new Hono();
1255
-
1256
- // Health check endpoint (always first)
1257
- honoApp.get('${healthCheckPath}', (c) => c.json({ status: 'ok', timestamp: Date.now() }));
1258
- honoApp.get('/ready', (c) => c.json({ ready: true }));
1259
- ${cors.setup}${beforeSetupCall}
1260
- // Setup HTTP endpoints (OpenAPI: ${enableOpenApi})
1261
- await setupEndpoints(honoApp, envParser, logger, ${enableOpenApi});
1262
- ${afterSetupCall}
1263
- return {
1264
- app: honoApp,
1265
- async start(options) {
1266
- if (!options?.serve) {
1267
- throw new Error(
1268
- 'serve function is required. Pass a serve function for your runtime:\\n' +
1269
- ' - Bun: (app, port) => Bun.serve({ port, fetch: app.fetch })\\n' +
1270
- ' - Node: (app, port) => serve({ fetch: app.fetch, port })'
1271
- );
1272
- }
1273
-
1274
- const port = options.port ?? Number(process.env.PORT) ?? 3000;
1275
- ${gracefulShutdownCode}${subscriberSetup}
1276
- logger.info({ port }, 'Starting production server');
1277
-
1278
- // Start HTTP server using provided serve function
1279
- await options.serve(honoApp, port);
1280
-
1281
- logger.info({ port }, 'Production server started');
1282
- }
1283
- };
1284
- }
1285
-
1286
- // Default export for convenience
1287
- export default createApp;
1288
- `;
1289
- await (0, node_fs_promises.writeFile)(appPath, content);
1290
- await this.generateProductionServerEntry(outputDir);
1291
- return appPath;
1292
- }
1293
- /**
1294
- * Generate production server.ts entry point
1295
- */
1296
- async generateProductionServerEntry(outputDir) {
1297
- const serverPath = (0, node_path.join)(outputDir, "server.ts");
1298
- const content = `#!/usr/bin/env node
1299
- /**
1300
- * Production server entry point
1301
- * Generated by 'gkm build --provider server --production'
1302
- */
1303
- import { serve } from '@hono/node-server';
1304
- import { createApp } from './app.js';
1305
-
1306
- const port = Number(process.env.PORT) || 3000;
1307
-
1308
- const { start } = await createApp();
1309
-
1310
- await start({
1311
- port,
1312
- serve: (app, port) => { serve({ fetch: app.fetch, port }); },
1313
- });
1314
- `;
1315
- await (0, node_fs_promises.writeFile)(serverPath, content);
1316
- }
1317
- };
1318
-
1319
- //#endregion
1320
- //#region src/generators/OpenApiTsGenerator.ts
1321
- /**
1322
- * Generates TypeScript OpenAPI module from endpoints.
1323
- * Outputs:
1324
- * - securitySchemes: typed security scheme definitions
1325
- * - endpointAuth: runtime map of endpoints to auth requirements
1326
- * - paths: TypeScript interface for type-safe fetcher
1327
- * - schema interfaces: reusable TypeScript types from Zod/Valibot schemas
1328
- */
1329
- var OpenApiTsGenerator = class {
1330
- async generate(endpoints, options = {}) {
1331
- const { title = "API", version = "1.0.0", description } = options;
1332
- const endpointInfos = await this.extractEndpointInfos(endpoints);
1333
- const securitySchemes = this.collectSecuritySchemes(endpointInfos);
1334
- const endpointAuth = this.buildEndpointAuthMap(endpointInfos);
1335
- const schemaInterfaces = await this.generateSchemaInterfaces(endpointInfos);
1336
- const pathsInterface = await this.generatePathsInterface(endpointInfos);
1337
- return this.buildModule({
1338
- title,
1339
- version,
1340
- description,
1341
- securitySchemes,
1342
- endpointAuth,
1343
- schemaInterfaces,
1344
- pathsInterface
1345
- });
1346
- }
1347
- async extractEndpointInfos(endpoints) {
1348
- return endpoints.map((ep) => {
1349
- const route = ep.route.replace(/:(\w+)/g, "{$1}");
1350
- const method = ep.method.toUpperCase();
1351
- const securityScheme = ep.authorizer?.securityScheme;
1352
- return {
1353
- endpoint: `${method} ${route}`,
1354
- route,
1355
- method,
1356
- authorizerName: ep.authorizer?.name ?? null,
1357
- authorizerType: ep.authorizer?.type ?? null,
1358
- securityScheme: securityScheme ?? null,
1359
- input: ep.input,
1360
- output: ep.outputSchema,
1361
- description: ep.description,
1362
- tags: ep.tags,
1363
- operationId: ep.operationId,
1364
- responseType: ep.responseType ?? "application/json"
1365
- };
1366
- });
1367
- }
1368
- collectSecuritySchemes(endpointInfos) {
1369
- const schemes = /* @__PURE__ */ new Map();
1370
- for (const info of endpointInfos) if (info.authorizerName && !schemes.has(info.authorizerName)) {
1371
- const scheme = info.securityScheme ?? (info.authorizerType ? this.mapAuthorizerToSecurityScheme(info.authorizerType, info.authorizerName) : null);
1372
- if (scheme) schemes.set(info.authorizerName, {
1373
- name: info.authorizerName,
1374
- type: scheme.type,
1375
- scheme
1376
- });
1377
- }
1378
- return Array.from(schemes.values());
1379
- }
1380
- mapAuthorizerToSecurityScheme(type, _name) {
1381
- switch (type.toLowerCase()) {
1382
- case "jwt":
1383
- case "bearer": return {
1384
- type: "http",
1385
- scheme: "bearer",
1386
- bearerFormat: "JWT"
1387
- };
1388
- case "iam":
1389
- case "aws-sigv4":
1390
- case "sigv4": return {
1391
- type: "apiKey",
1392
- in: "header",
1393
- name: "Authorization",
1394
- "x-amazon-apigateway-authtype": "awsSigv4"
1395
- };
1396
- case "apikey":
1397
- case "api-key": return {
1398
- type: "apiKey",
1399
- in: "header",
1400
- name: "X-API-Key"
1401
- };
1402
- case "oauth2": return {
1403
- type: "oauth2",
1404
- flows: {}
1405
- };
1406
- case "oidc":
1407
- case "openidconnect": return {
1408
- type: "openIdConnect",
1409
- openIdConnectUrl: ""
1410
- };
1411
- default: return {
1412
- type: "http",
1413
- scheme: "bearer"
1414
- };
1415
- }
1416
- }
1417
- buildEndpointAuthMap(endpointInfos) {
1418
- const authMap = {};
1419
- for (const info of endpointInfos) authMap[info.endpoint] = info.authorizerName;
1420
- return authMap;
1421
- }
1422
- async generateSchemaInterfaces(endpointInfos) {
1423
- const interfaces = [];
1424
- const generatedNames = /* @__PURE__ */ new Set();
1425
- const collectedDefs = /* @__PURE__ */ new Map();
1426
- for (const info of endpointInfos) {
1427
- const baseName = this.getSchemaBaseName(info);
1428
- if (info.input?.body) {
1429
- const name = await this.getSchemaName(info.input.body, `${baseName}Input`);
1430
- if (!generatedNames.has(name)) {
1431
- const schema = await this.schemaToInterfaceWithDefs(info.input.body, name, collectedDefs);
1432
- if (schema) {
1433
- interfaces.push(schema);
1434
- generatedNames.add(name);
1435
- }
1436
- }
1437
- }
1438
- if (info.input?.params) {
1439
- const name = await this.getSchemaName(info.input.params, `${baseName}Params`);
1440
- if (!generatedNames.has(name)) {
1441
- const schema = await this.schemaToInterfaceWithDefs(info.input.params, name, collectedDefs);
1442
- if (schema) {
1443
- interfaces.push(schema);
1444
- generatedNames.add(name);
1445
- }
1446
- }
1447
- }
1448
- if (info.input?.query) {
1449
- const name = await this.getSchemaName(info.input.query, `${baseName}Query`);
1450
- if (!generatedNames.has(name)) {
1451
- const schema = await this.schemaToInterfaceWithDefs(info.input.query, name, collectedDefs);
1452
- if (schema) {
1453
- interfaces.push(schema);
1454
- generatedNames.add(name);
1455
- }
1456
- }
1457
- }
1458
- if (info.output) {
1459
- const name = await this.getSchemaName(info.output, `${baseName}Output`);
1460
- if (!generatedNames.has(name)) {
1461
- const schema = await this.schemaToInterfaceWithDefs(info.output, name, collectedDefs);
1462
- if (schema) {
1463
- interfaces.push(schema);
1464
- generatedNames.add(name);
1465
- }
1466
- }
1467
- }
1468
- }
1469
- const registrySchemas = await (0, __geekmidas_schema_conversion.getRegisteredZodJsonSchemas)();
1470
- for (const [rawName, rawSchema] of Object.entries(registrySchemas)) {
1471
- const defName = this.pascalCase(rawName);
1472
- if (collectedDefs.has(defName) || generatedNames.has(defName)) continue;
1473
- const { id: _id, $defs: _defs,...rest } = rawSchema;
1474
- collectedDefs.set(defName, rest);
1475
- }
1476
- for (const [defName, defSchema] of collectedDefs) if (!generatedNames.has(defName)) {
1477
- const interfaceStr = this.jsonSchemaToInterface(defSchema, defName);
1478
- interfaces.push(interfaceStr);
1479
- generatedNames.add(defName);
1480
- }
1481
- return interfaces.join("\n\n");
1482
- }
1483
- /**
1484
- * Get the name for a schema, using metadata `id` if available,
1485
- * otherwise falling back to the provided default name.
1486
- */
1487
- async getSchemaName(schema, defaultName) {
1488
- try {
1489
- const metadata = await (0, __geekmidas_schema_conversion.getSchemaMetadata)(schema);
1490
- if (metadata?.id) return this.pascalCase(metadata.id);
1491
- } catch {}
1492
- return defaultName;
1493
- }
1494
- getSchemaBaseName(info) {
1495
- if (info.operationId) return this.pascalCase(info.operationId);
1496
- const routeParts = info.route.replace(/[{}]/g, "").split("/").filter(Boolean).map((part) => this.pascalCase(part));
1497
- return `${this.pascalCase(info.method.toLowerCase())}${routeParts.join("")}`;
1498
- }
1499
- pascalCase(str) {
1500
- return str.replace(/[-_](.)/g, (_, c) => c.toUpperCase()).replace(/^./, (c) => c.toUpperCase());
1501
- }
1502
- /**
1503
- * Convert schema to interface while collecting $defs for nested schemas
1504
- * with .meta({ id: 'X' }).
1505
- */
1506
- async schemaToInterfaceWithDefs(schema, name, collectedDefs) {
1507
- try {
1508
- const vendor = schema["~standard"]?.vendor;
1509
- if (!vendor || !(vendor in __geekmidas_schema_conversion.StandardSchemaJsonSchema)) return null;
1510
- const toJsonSchema = __geekmidas_schema_conversion.StandardSchemaJsonSchema[vendor];
1511
- const jsonSchema = await toJsonSchema(schema);
1512
- if (!jsonSchema) return null;
1513
- if (jsonSchema.$defs && typeof jsonSchema.$defs === "object") {
1514
- for (const [defName, defSchema] of Object.entries(jsonSchema.$defs)) if (!collectedDefs.has(defName)) {
1515
- const { id,...schemaWithoutId } = defSchema;
1516
- collectedDefs.set(defName, schemaWithoutId);
1517
- }
1518
- }
1519
- const { $defs,...schemaWithoutDefs } = jsonSchema;
1520
- const ref = schemaWithoutDefs.$ref;
1521
- if (ref && Object.keys(schemaWithoutDefs).every((k) => k === "$ref" || k === "$schema")) {
1522
- const target = ref.split("/").pop();
1523
- return target === name ? null : `export type ${name} = ${target};`;
1524
- }
1525
- return this.jsonSchemaToInterface(schemaWithoutDefs, name);
1526
- } catch {
1527
- return null;
1528
- }
1529
- }
1530
- jsonSchemaToInterface(schema, name) {
1531
- if (schema.type !== "object" || !schema.properties) {
1532
- const typeStr = this.jsonSchemaTypeToTs(schema);
1533
- return `export type ${name} = ${typeStr};`;
1534
- }
1535
- const props = [];
1536
- const required = new Set(schema.required || []);
1537
- for (const [propName, propSchema] of Object.entries(schema.properties)) {
1538
- const isRequired = required.has(propName);
1539
- const typeStr = this.jsonSchemaTypeToTs(propSchema);
1540
- const optionalMark = isRequired ? "" : "?";
1541
- props.push(` ${propName}${optionalMark}: ${typeStr};`);
1542
- }
1543
- return `export interface ${name} {\n${props.join("\n")}\n}`;
1544
- }
1545
- jsonSchemaTypeToTs(schema) {
1546
- if (!schema) return "unknown";
1547
- if (schema.$ref) {
1548
- const refName = schema.$ref.split("/").pop() || "unknown";
1549
- return refName;
1550
- }
1551
- if (schema.anyOf) return schema.anyOf.map((s) => this.jsonSchemaTypeToTs(s)).join(" | ");
1552
- if (schema.oneOf) return schema.oneOf.map((s) => this.jsonSchemaTypeToTs(s)).join(" | ");
1553
- if (schema.allOf) return schema.allOf.map((s) => this.jsonSchemaTypeToTs(s)).join(" & ");
1554
- switch (schema.type) {
1555
- case "string":
1556
- if (schema.enum) return schema.enum.map((e) => `'${e}'`).join(" | ");
1557
- return "string";
1558
- case "number":
1559
- case "integer": return "number";
1560
- case "boolean": return "boolean";
1561
- case "null": return "null";
1562
- case "array":
1563
- if (schema.items) return `Array<${this.jsonSchemaTypeToTs(schema.items)}>`;
1564
- return "Array<unknown>";
1565
- case "object":
1566
- if (schema.properties) {
1567
- const props = [];
1568
- const required = new Set(schema.required || []);
1569
- for (const [propName, propSchema] of Object.entries(schema.properties)) {
1570
- const isRequired = required.has(propName);
1571
- const typeStr = this.jsonSchemaTypeToTs(propSchema);
1572
- const optionalMark = isRequired ? "" : "?";
1573
- props.push(`${propName}${optionalMark}: ${typeStr}`);
1574
- }
1575
- return `{ ${props.join("; ")} }`;
1576
- }
1577
- if (schema.additionalProperties) {
1578
- const valueType = this.jsonSchemaTypeToTs(schema.additionalProperties);
1579
- return `Record<string, ${valueType}>`;
1580
- }
1581
- return "Record<string, unknown>";
1582
- default: return "unknown";
1583
- }
1584
- }
1585
- async generatePathsInterface(endpointInfos) {
1586
- const pathGroups = /* @__PURE__ */ new Map();
1587
- for (const info of endpointInfos) {
1588
- const existing = pathGroups.get(info.route) || [];
1589
- existing.push(info);
1590
- pathGroups.set(info.route, existing);
1591
- }
1592
- const pathEntries = [];
1593
- for (const [route, infos] of pathGroups) {
1594
- const methodEntries = [];
1595
- for (const info of infos) {
1596
- const methodDef = await this.generateMethodDefinition(info);
1597
- methodEntries.push(` ${info.method.toLowerCase()}: ${methodDef};`);
1598
- }
1599
- const firstWithParams = infos.find((i) => i.input?.params);
1600
- 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
- }
1605
- pathEntries.push(` '${route}': {${paramsEntry}\n${methodEntries.join("\n")}\n };`);
1606
- }
1607
- return `export interface paths {\n${pathEntries.join("\n")}\n}`;
1608
- }
1609
- async generateMethodDefinition(info) {
1610
- const parts = [];
1611
- const baseName = this.getSchemaBaseName(info);
1612
- if (info.input?.body) {
1613
- const bodyName = await this.getSchemaName(info.input.body, `${baseName}Input`);
1614
- parts.push(`requestBody: {
1615
- content: {
1616
- 'application/json': ${bodyName};
1617
- };
1618
- }`);
1619
- }
1620
- if (info.input?.query) {
1621
- const queryName = await this.getSchemaName(info.input.query, `${baseName}Query`);
1622
- parts.push(`parameters: {
1623
- query: ${queryName};
1624
- }`);
1625
- }
1626
- const outputName = info.output ? await this.getSchemaName(info.output, `${baseName}Output`) : "unknown";
1627
- parts.push(`responses: {
1628
- 200: {
1629
- content: {
1630
- '${info.responseType}': ${outputName};
1631
- };
1632
- };
1633
- }`);
1634
- return `{\n ${parts.join(";\n ")};\n }`;
1635
- }
1636
- buildModule(params) {
1637
- const { title, version, description, securitySchemes, endpointAuth, schemaInterfaces, pathsInterface } = params;
1638
- const securitySchemesObj = securitySchemes.reduce((acc, s) => {
1639
- acc[s.name] = s.scheme;
1640
- return acc;
1641
- }, {});
1642
- const schemeNames = securitySchemes.map((s) => `'${s.name}'`).join(" | ");
1643
- const hasSecuritySchemes = schemeNames.length > 0;
1644
- const createApiSection = hasSecuritySchemes ? `
1645
- // ============================================================
1646
- // API Client Factory
1647
- // ============================================================
1648
-
1649
- import {
1650
- createAuthAwareFetcher,
1651
- type AuthStrategy,
1652
- } from '@geekmidas/client/auth-fetcher';
1653
- import { createEndpointHooks } from '@geekmidas/client/endpoint-hooks';
1654
- import type { QueryClient } from '@tanstack/react-query';
1655
-
1656
- /**
1657
- * Options for creating the API client.
1658
- */
1659
- export interface CreateApiOptions {
1660
- /** Base URL for all API requests (required) */
1661
- baseURL: string;
1662
- /** Auth strategies for each security scheme used in this API */
1663
- authStrategies: Record<SecuritySchemeId, AuthStrategy>;
1664
- /** Optional React Query client instance */
1665
- queryClient?: QueryClient;
1666
- /** Optional request interceptor */
1667
- onRequest?: (config: RequestInit) => RequestInit | Promise<RequestInit>;
1668
- }
1669
-
1670
- /**
1671
- * Create a type-safe API client with authentication and React Query hooks.
1672
- *
1673
- * @example
1674
- * \`\`\`typescript
1675
- * const api = createApi({
1676
- * baseURL: 'https://api.example.com',
1677
- * authStrategies: {
1678
- * jwt: { type: 'bearer', tokenProvider },
1679
- * },
1680
- * });
1681
- *
1682
- * // Imperative fetch
1683
- * const user = await api('GET /users/{id}', { params: { id: '123' } });
1684
- *
1685
- * // React Query hooks
1686
- * const { data } = api.useQuery('GET /users/{id}', { params: { id: '123' } });
1687
- * const mutation = api.useMutation('POST /users');
1688
- * \`\`\`
1689
- */
1690
- export function createApi(options: CreateApiOptions) {
1691
- const fetcher = createAuthAwareFetcher<paths, typeof endpointAuth, typeof securitySchemes>({
1692
- baseURL: options.baseURL,
1693
- endpointAuth,
1694
- securitySchemes,
1695
- authStrategies: options.authStrategies,
1696
- onRequest: options.onRequest,
1697
- });
1698
-
1699
- const hooks = createEndpointHooks<paths>(fetcher, { queryClient: options.queryClient });
1700
-
1701
- return Object.assign(fetcher, hooks);
1702
- }
1703
- ` : `
1704
- // ============================================================
1705
- // API Client Factory
1706
- // ============================================================
1707
-
1708
- import { createTypedFetcher, type FetcherOptions } from '@geekmidas/client/fetcher';
1709
- import { createEndpointHooks } from '@geekmidas/client/endpoint-hooks';
1710
- import type { QueryClient } from '@tanstack/react-query';
1711
-
1712
- /**
1713
- * Options for creating the API client.
1714
- */
1715
- export interface CreateApiOptions extends Omit<FetcherOptions, 'baseURL'> {
1716
- /** Base URL for all API requests (required) */
1717
- baseURL: string;
1718
- /** Optional React Query client instance */
1719
- queryClient?: QueryClient;
1720
- }
1721
-
1722
- /**
1723
- * Create a type-safe API client with React Query hooks.
1724
- *
1725
- * @example
1726
- * \`\`\`typescript
1727
- * const api = createApi({
1728
- * baseURL: 'https://api.example.com',
1729
- * });
1730
- *
1731
- * // Imperative fetch
1732
- * const data = await api('GET /health');
1733
- *
1734
- * // React Query hooks
1735
- * const { data } = api.useQuery('GET /health');
1736
- * \`\`\`
1737
- */
1738
- export function createApi(options: CreateApiOptions) {
1739
- const { queryClient, ...fetcherOptions } = options;
1740
- const request = createTypedFetcher<paths>(fetcherOptions);
1741
-
1742
- const hooks = createEndpointHooks<paths>(request, { queryClient });
1743
-
1744
- return Object.assign(request, hooks);
1745
- }
1746
- `;
1747
- return `// Auto-generated by @geekmidas/cli - DO NOT EDIT
1748
-
1749
- // ============================================================
1750
- // Security Scheme Type
1751
- // ============================================================
1752
-
1753
- interface SecuritySchemeObject {
1754
- type: 'apiKey' | 'http' | 'mutualTLS' | 'oauth2' | 'openIdConnect';
1755
- description?: string;
1756
- name?: string;
1757
- in?: 'query' | 'header' | 'cookie';
1758
- scheme?: string;
1759
- bearerFormat?: string;
1760
- flows?: Record<string, unknown>;
1761
- openIdConnectUrl?: string;
1762
- [key: string]: unknown;
1763
- }
1764
-
1765
- // ============================================================
1766
- // API Info
1767
- // ============================================================
1768
-
1769
- export const apiInfo = {
1770
- title: '${title}',
1771
- version: '${version}',${description ? `\n description: '${description.replace(/'/g, "\\'")}',` : ""}
1772
- } as const;
1773
-
1774
- // ============================================================
1775
- // Security Schemes
1776
- // ============================================================
1777
-
1778
- /**
1779
- * Available security schemes for this API.
1780
- * Maps authorizer names to OpenAPI security scheme definitions.
1781
- */
1782
- export const securitySchemes = ${JSON.stringify(securitySchemesObj, null, 2).replace(/"([a-zA-Z_$][a-zA-Z0-9_$]*)":/g, "$1:")} as const satisfies Record<string, SecuritySchemeObject>;
1783
-
1784
- export type SecuritySchemeId = ${schemeNames || "never"};
1785
-
1786
- // ============================================================
1787
- // Endpoint Authentication Map
1788
- // ============================================================
1789
-
1790
- /**
1791
- * Runtime map of endpoints to their required authentication scheme.
1792
- * \`null\` indicates a public endpoint (no auth required).
1793
- */
1794
- export const endpointAuth = ${JSON.stringify(endpointAuth, null, 2).replace(/"([^"]+)":/g, "'$1':")} as const satisfies Record<string, SecuritySchemeId | null>;
1795
-
1796
- export type EndpointString = keyof typeof endpointAuth;
1797
-
1798
- export type AuthenticatedEndpoint = {
1799
- [K in EndpointString]: typeof endpointAuth[K] extends null ? never : K;
1800
- }[EndpointString];
1801
-
1802
- export type PublicEndpoint = {
1803
- [K in EndpointString]: typeof endpointAuth[K] extends null ? K : never;
1804
- }[EndpointString];
1805
-
1806
- // ============================================================
1807
- // Schema Definitions
1808
- // ============================================================
1809
-
1810
- ${schemaInterfaces}
1811
-
1812
- // ============================================================
1813
- // OpenAPI Paths
1814
- // ============================================================
1815
-
1816
- ${pathsInterface}
1817
- ${createApiSection}
1818
- `;
1819
- }
1820
- };
1821
-
1822
- //#endregion
1823
- //#region src/workspace/client-generator.ts
1824
- /**
1825
- * Normalize routes to an array of patterns.
1826
- * Handles string, string[], and PartitionedRoutes (extracts paths).
1827
- * @internal Exported for use in dev command
1828
- */
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];
1833
- }
1834
-
1835
- //#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 — the conventional
1874
- * directories under it — 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;
1898
- }
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
- });
2057
- Object.defineProperty(exports, 'openapiCommand', {
2058
- enumerable: true,
2059
- get: function () {
2060
- return openapiCommand;
2061
- }
2062
- });
2063
- Object.defineProperty(exports, 'resolveOpenApiConfig', {
2064
- enumerable: true,
2065
- get: function () {
2066
- return resolveOpenApiConfig;
2067
- }
2068
- });
2069
- Object.defineProperty(exports, 'runtimeFor', {
2070
- enumerable: true,
2071
- get: function () {
2072
- return runtimeFor;
2073
- }
2074
- });
2075
- //# sourceMappingURL=openapi-DWLTsYLL.cjs.map