@geekmidas/cli 10.0.0-alpha.4 → 10.0.0-alpha.41

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 (257) hide show
  1. package/README.md +52 -74
  2. package/bin/adjacent-tsconfig.mjs +97 -0
  3. package/bin/gkm.mjs +7 -1
  4. package/dist/{HostingerProvider-h3EbEp-Z.cjs → HostingerProvider-BZFGYYVA.cjs} +21 -22
  5. package/dist/HostingerProvider-BZFGYYVA.cjs.map +1 -0
  6. package/dist/{HostingerProvider-Cft7lEYr.mjs → HostingerProvider-Bh6K7QYz.mjs} +20 -21
  7. package/dist/HostingerProvider-Bh6K7QYz.mjs.map +1 -0
  8. package/dist/{LocalStateProvider-Db9SEjyH.cjs → LocalStateProvider-7HR6SS2t.cjs} +11 -6
  9. package/dist/LocalStateProvider-7HR6SS2t.cjs.map +1 -0
  10. package/dist/{LocalStateProvider-Bn6tS-oL.mjs → LocalStateProvider-D7QyJoLM.mjs} +10 -4
  11. package/dist/LocalStateProvider-D7QyJoLM.mjs.map +1 -0
  12. package/dist/{openapi-CA0yJUTN.cjs → OpenApiTsGenerator-B4Kj_qNU.cjs} +142 -303
  13. package/dist/OpenApiTsGenerator-B4Kj_qNU.cjs.map +1 -0
  14. package/dist/{openapi-kkQbsRVj.mjs → OpenApiTsGenerator-CEh3EKN3.mjs} +113 -255
  15. package/dist/OpenApiTsGenerator-CEh3EKN3.mjs.map +1 -0
  16. package/dist/{Route53Provider-RdpUDJQk.mjs → Route53Provider-Cvj40A8I.mjs} +12 -12
  17. package/dist/Route53Provider-Cvj40A8I.mjs.map +1 -0
  18. package/dist/{Route53Provider-di2fMM5N.cjs → Route53Provider-DVILBsvV.cjs} +20 -21
  19. package/dist/Route53Provider-DVILBsvV.cjs.map +1 -0
  20. package/dist/{SSMStateProvider-BRt2py-A.mjs → SSMStateProvider-B0Hu1MKZ.mjs} +13 -4
  21. package/dist/SSMStateProvider-B0Hu1MKZ.mjs.map +1 -0
  22. package/dist/{SSMStateProvider-DyX8s9HI.cjs → SSMStateProvider-VrQ-yeqd.cjs} +17 -9
  23. package/dist/SSMStateProvider-VrQ-yeqd.cjs.map +1 -0
  24. package/dist/aws-DkHdTV-p.cjs +61 -0
  25. package/dist/aws-DkHdTV-p.cjs.map +1 -0
  26. package/dist/aws-DojzQnLd.mjs +61 -0
  27. package/dist/aws-DojzQnLd.mjs.map +1 -0
  28. package/dist/{backup-provisioner-BrsHwYG0.cjs → backup-provisioner-BmhIO_Yr.cjs} +21 -19
  29. package/dist/backup-provisioner-BmhIO_Yr.cjs.map +1 -0
  30. package/dist/{backup-provisioner-Bgj5Vi_L.mjs → backup-provisioner-DIVCbfee.mjs} +10 -7
  31. package/dist/backup-provisioner-DIVCbfee.mjs.map +1 -0
  32. package/dist/{bundler-Be8Zg4Wd.mjs → bundler--fyybf1N.mjs} +19 -30
  33. package/dist/bundler--fyybf1N.mjs.map +1 -0
  34. package/dist/{bundler-BY1OmV1e.cjs → bundler-By6_sXiL.cjs} +20 -32
  35. package/dist/bundler-By6_sXiL.cjs.map +1 -0
  36. package/dist/{config-WRdsQYZK.mjs → config-5watB1D0.mjs} +142 -154
  37. package/dist/config-5watB1D0.mjs.map +1 -0
  38. package/dist/{config-C21ocYNd.cjs → config-CJ-PAb7M.cjs} +209 -210
  39. package/dist/config-CJ-PAb7M.cjs.map +1 -0
  40. package/dist/config.cjs +9 -6
  41. package/dist/config.d.cts +62 -33
  42. package/dist/config.d.cts.map +1 -1
  43. package/dist/config.d.mts +62 -33
  44. package/dist/config.d.mts.map +1 -1
  45. package/dist/config.mjs +3 -5
  46. package/dist/deploy/sniffer-envkit-patch.cjs +18 -10
  47. package/dist/deploy/sniffer-envkit-patch.cjs.map +1 -1
  48. package/dist/deploy/sniffer-envkit-patch.d.cts +0 -2
  49. package/dist/deploy/sniffer-envkit-patch.d.cts.map +1 -1
  50. package/dist/deploy/sniffer-envkit-patch.d.mts +0 -2
  51. package/dist/deploy/sniffer-envkit-patch.d.mts.map +1 -1
  52. package/dist/deploy/sniffer-envkit-patch.mjs +10 -2
  53. package/dist/deploy/sniffer-envkit-patch.mjs.map +1 -1
  54. package/dist/deploy/sniffer-hooks.cjs +13 -7
  55. package/dist/deploy/sniffer-hooks.cjs.map +1 -1
  56. package/dist/deploy/sniffer-hooks.d.cts +1 -2
  57. package/dist/deploy/sniffer-hooks.d.cts.map +1 -1
  58. package/dist/deploy/sniffer-hooks.d.mts +1 -2
  59. package/dist/deploy/sniffer-hooks.d.mts.map +1 -1
  60. package/dist/deploy/sniffer-hooks.mjs +9 -2
  61. package/dist/deploy/sniffer-hooks.mjs.map +1 -1
  62. package/dist/deploy/sniffer-loader.cjs +16 -7
  63. package/dist/deploy/sniffer-loader.cjs.map +1 -1
  64. package/dist/deploy/sniffer-loader.d.cts +1 -1
  65. package/dist/deploy/sniffer-loader.d.mts +1 -1
  66. package/dist/deploy/sniffer-loader.mjs +13 -2
  67. package/dist/deploy/sniffer-loader.mjs.map +1 -1
  68. package/dist/deploy/sniffer-routes-worker.cjs +11 -11
  69. package/dist/deploy/sniffer-routes-worker.cjs.map +1 -1
  70. package/dist/deploy/sniffer-routes-worker.d.cts +1 -1
  71. package/dist/deploy/sniffer-routes-worker.d.mts +1 -1
  72. package/dist/deploy/sniffer-routes-worker.mjs +3 -3
  73. package/dist/deploy/sniffer-routes-worker.mjs.map +1 -1
  74. package/dist/deploy/sniffer-worker.cjs +15 -6
  75. package/dist/deploy/sniffer-worker.cjs.map +1 -1
  76. package/dist/deploy/sniffer-worker.d.cts +1 -3
  77. package/dist/deploy/sniffer-worker.d.cts.map +1 -1
  78. package/dist/deploy/sniffer-worker.d.mts +1 -3
  79. package/dist/deploy/sniffer-worker.d.mts.map +1 -1
  80. package/dist/deploy/sniffer-worker.mjs +15 -4
  81. package/dist/deploy/sniffer-worker.mjs.map +1 -1
  82. package/dist/{discover-DTmFeloL.cjs → discover-B0f_kuNN.cjs} +118 -66
  83. package/dist/discover-B0f_kuNN.cjs.map +1 -0
  84. package/dist/{discover-CAlFgYec.mjs → discover-BLhf7V_J.mjs} +67 -22
  85. package/dist/discover-BLhf7V_J.mjs.map +1 -0
  86. package/dist/{emit-CbcRolsa.cjs → emit-BdoPFjZf.cjs} +53 -36
  87. package/dist/emit-BdoPFjZf.cjs.map +1 -0
  88. package/dist/{emit-CiZS_5Ub.mjs → emit-Bzq7JsMP.mjs} +24 -6
  89. package/dist/emit-Bzq7JsMP.mjs.map +1 -0
  90. package/dist/github-BAr8WGkR.cjs +213 -0
  91. package/dist/github-BAr8WGkR.cjs.map +1 -0
  92. package/dist/github-D5MthUlR.mjs +213 -0
  93. package/dist/github-D5MthUlR.mjs.map +1 -0
  94. package/dist/{index-DCtipn2h.d.cts → index-B3PeGOQp.d.cts} +4 -23
  95. package/dist/index-B3PeGOQp.d.cts.map +1 -0
  96. package/dist/{index-BThUzEIp.d.mts → index-BOyaGcCm.d.mts} +4 -23
  97. package/dist/index-BOyaGcCm.d.mts.map +1 -0
  98. package/dist/index.cjs +7071 -4519
  99. package/dist/index.cjs.map +1 -1
  100. package/dist/index.d.cts +1 -1
  101. package/dist/index.d.mts +1 -1
  102. package/dist/index.mjs +7117 -4586
  103. package/dist/index.mjs.map +1 -1
  104. package/dist/migrate-BVI3yqcE.mjs +736 -0
  105. package/dist/migrate-BVI3yqcE.mjs.map +1 -0
  106. package/dist/migrate-CFOUApUt.cjs +743 -0
  107. package/dist/migrate-CFOUApUt.cjs.map +1 -0
  108. package/dist/openapi.cjs +197 -8
  109. package/dist/openapi.cjs.map +1 -0
  110. package/dist/openapi.d.cts +47 -14
  111. package/dist/openapi.d.cts.map +1 -1
  112. package/dist/openapi.d.mts +47 -14
  113. package/dist/openapi.d.mts.map +1 -1
  114. package/dist/openapi.mjs +191 -5
  115. package/dist/openapi.mjs.map +1 -0
  116. package/dist/ready-D8UXsP6q.mjs +516 -0
  117. package/dist/ready-D8UXsP6q.mjs.map +1 -0
  118. package/dist/ready-mcxamf73.cjs +563 -0
  119. package/dist/ready-mcxamf73.cjs.map +1 -0
  120. package/dist/reconcile/public.cjs +4 -4
  121. package/dist/reconcile/public.d.cts +27 -26
  122. package/dist/reconcile/public.d.cts.map +1 -1
  123. package/dist/reconcile/public.d.mts +27 -26
  124. package/dist/reconcile/public.d.mts.map +1 -1
  125. package/dist/reconcile/public.mjs +3 -4
  126. package/dist/{reconcile-CFs8C_1a.mjs → reconcile--I7V4Klj.mjs} +4 -7
  127. package/dist/reconcile--I7V4Klj.mjs.map +1 -0
  128. package/dist/{reconcile-D0pimNiy.cjs → reconcile-CuCQBa5-.cjs} +5 -8
  129. package/dist/reconcile-CuCQBa5-.cjs.map +1 -0
  130. package/dist/rolldown-runtime-BhDjJH2R.mjs +15 -0
  131. package/dist/{chunk-CUT6urMc.cjs → rolldown-runtime-C0BPl7ul.cjs} +23 -10
  132. package/dist/storage-BzaUxmqe.mjs +124 -0
  133. package/dist/storage-BzaUxmqe.mjs.map +1 -0
  134. package/dist/storage-CSGoC3bK.cjs +152 -0
  135. package/dist/storage-CSGoC3bK.cjs.map +1 -0
  136. package/dist/store-DQgxT_WR.cjs +211 -0
  137. package/dist/store-DQgxT_WR.cjs.map +1 -0
  138. package/dist/store-DeGATCS-.mjs +182 -0
  139. package/dist/store-DeGATCS-.mjs.map +1 -0
  140. package/dist/types-0R124hrY.d.mts +6324 -0
  141. package/dist/types-0R124hrY.d.mts.map +1 -0
  142. package/dist/types-DfdYe31u.d.cts +6325 -0
  143. package/dist/types-DfdYe31u.d.cts.map +1 -0
  144. package/dist/vitest.cjs +65 -0
  145. package/dist/vitest.cjs.map +1 -0
  146. package/dist/vitest.d.cts +29 -0
  147. package/dist/vitest.d.cts.map +1 -0
  148. package/dist/vitest.d.mts +29 -0
  149. package/dist/vitest.d.mts.map +1 -0
  150. package/dist/vitest.mjs +65 -0
  151. package/dist/vitest.mjs.map +1 -0
  152. package/dist/workspace/index.cjs +3 -4
  153. package/dist/workspace/index.d.cts +3 -3
  154. package/dist/workspace/index.d.mts +3 -3
  155. package/dist/workspace/index.mjs +2 -3
  156. package/dist/{credentials-G1JwBoXH.cjs → workspace-BIqeeqcR.cjs} +2248 -1809
  157. package/dist/workspace-BIqeeqcR.cjs.map +1 -0
  158. package/dist/{workspace-BFMrAKqI.mjs → workspace-DOmIhiau.mjs} +863 -952
  159. package/dist/workspace-DOmIhiau.mjs.map +1 -0
  160. package/dist/{credentials-BBIRJVp4.mjs → workspace-DwS1JK5u.mjs} +2114 -1706
  161. package/dist/workspace-DwS1JK5u.mjs.map +1 -0
  162. package/dist/{workspace-BcucjwvA.cjs → workspace-RYSYtHP7.cjs} +1032 -1098
  163. package/dist/workspace-RYSYtHP7.cjs.map +1 -0
  164. package/package.json +29 -20
  165. package/dist/CachedStateProvider-BLo7zv7S.cjs +0 -3
  166. package/dist/CachedStateProvider-BxoAm-B2.mjs +0 -3
  167. package/dist/CachedStateProvider-CqPdW7CB.cjs +0 -60
  168. package/dist/CachedStateProvider-CqPdW7CB.cjs.map +0 -1
  169. package/dist/CachedStateProvider-DTniehMP.mjs +0 -54
  170. package/dist/CachedStateProvider-DTniehMP.mjs.map +0 -1
  171. package/dist/HostingerProvider-Cft7lEYr.mjs.map +0 -1
  172. package/dist/HostingerProvider-h3EbEp-Z.cjs.map +0 -1
  173. package/dist/LocalStateProvider-Bn6tS-oL.mjs.map +0 -1
  174. package/dist/LocalStateProvider-Db9SEjyH.cjs.map +0 -1
  175. package/dist/Route53Provider-RdpUDJQk.mjs.map +0 -1
  176. package/dist/Route53Provider-di2fMM5N.cjs.map +0 -1
  177. package/dist/SSMStateProvider-BRt2py-A.mjs.map +0 -1
  178. package/dist/SSMStateProvider-DyX8s9HI.cjs.map +0 -1
  179. package/dist/backup-provisioner-Bgj5Vi_L.mjs.map +0 -1
  180. package/dist/backup-provisioner-BrsHwYG0.cjs.map +0 -1
  181. package/dist/bundler-BY1OmV1e.cjs.map +0 -1
  182. package/dist/bundler-Be8Zg4Wd.mjs.map +0 -1
  183. package/dist/chunk-Duj1WY3L.mjs +0 -7
  184. package/dist/config-C21ocYNd.cjs.map +0 -1
  185. package/dist/config-WRdsQYZK.mjs.map +0 -1
  186. package/dist/credentials-B5zRHdAl.mjs +0 -141
  187. package/dist/credentials-B5zRHdAl.mjs.map +0 -1
  188. package/dist/credentials-BBIRJVp4.mjs.map +0 -1
  189. package/dist/credentials-BapzjyV5.cjs +0 -195
  190. package/dist/credentials-BapzjyV5.cjs.map +0 -1
  191. package/dist/credentials-G1JwBoXH.cjs.map +0 -1
  192. package/dist/discover-CAlFgYec.mjs.map +0 -1
  193. package/dist/discover-DTmFeloL.cjs.map +0 -1
  194. package/dist/dokploy-api-BS2xnJLZ.mjs +0 -3
  195. package/dist/dokploy-api-BsVH0y_s.cjs +0 -718
  196. package/dist/dokploy-api-BsVH0y_s.cjs.map +0 -1
  197. package/dist/dokploy-api-BuxDRo3l.cjs +0 -3
  198. package/dist/dokploy-api-aTFPz7_4.mjs +0 -706
  199. package/dist/dokploy-api-aTFPz7_4.mjs.map +0 -1
  200. package/dist/emit-CbcRolsa.cjs.map +0 -1
  201. package/dist/emit-CiZS_5Ub.mjs.map +0 -1
  202. package/dist/encryption-C6jaU0hE.cjs +0 -54
  203. package/dist/encryption-C6jaU0hE.cjs.map +0 -1
  204. package/dist/encryption-CHzzeR8a.cjs +0 -4
  205. package/dist/encryption-CQUncu7v.mjs +0 -3
  206. package/dist/encryption-D-abyhZx.mjs +0 -42
  207. package/dist/encryption-D-abyhZx.mjs.map +0 -1
  208. package/dist/fullstack-secrets-C-GGohke.cjs +0 -111
  209. package/dist/fullstack-secrets-C-GGohke.cjs.map +0 -1
  210. package/dist/fullstack-secrets-D1o9-G5l.mjs +0 -87
  211. package/dist/fullstack-secrets-D1o9-G5l.mjs.map +0 -1
  212. package/dist/generator-CNzBw7g5.cjs +0 -289
  213. package/dist/generator-CNzBw7g5.cjs.map +0 -1
  214. package/dist/generator-VE2JrFlY.mjs +0 -253
  215. package/dist/generator-VE2JrFlY.mjs.map +0 -1
  216. package/dist/index-BThUzEIp.d.mts.map +0 -1
  217. package/dist/index-DCtipn2h.d.cts.map +0 -1
  218. package/dist/openapi-CA0yJUTN.cjs.map +0 -1
  219. package/dist/openapi-kkQbsRVj.mjs.map +0 -1
  220. package/dist/openapi-react-query-Byltvm_7.mjs +0 -167
  221. package/dist/openapi-react-query-Byltvm_7.mjs.map +0 -1
  222. package/dist/openapi-react-query-CmJ1xDbn.cjs +0 -173
  223. package/dist/openapi-react-query-CmJ1xDbn.cjs.map +0 -1
  224. package/dist/openapi-react-query.cjs +0 -4
  225. package/dist/openapi-react-query.d.cts +0 -11
  226. package/dist/openapi-react-query.d.cts.map +0 -1
  227. package/dist/openapi-react-query.d.mts +0 -11
  228. package/dist/openapi-react-query.d.mts.map +0 -1
  229. package/dist/openapi-react-query.mjs +0 -4
  230. package/dist/reconcile-CFs8C_1a.mjs.map +0 -1
  231. package/dist/reconcile-D0pimNiy.cjs.map +0 -1
  232. package/dist/setup-B5_oHHUj.cjs +0 -11
  233. package/dist/setup-Cm2UnAdh.cjs +0 -473
  234. package/dist/setup-Cm2UnAdh.cjs.map +0 -1
  235. package/dist/setup-DXvRLTZN.mjs +0 -443
  236. package/dist/setup-DXvRLTZN.mjs.map +0 -1
  237. package/dist/setup-ZijS4qeC.mjs +0 -11
  238. package/dist/storage-BJmzYxt8.cjs +0 -363
  239. package/dist/storage-BJmzYxt8.cjs.map +0 -1
  240. package/dist/storage-BM9hGpgv.cjs +0 -7
  241. package/dist/storage-Bi24WfoW.mjs +0 -297
  242. package/dist/storage-Bi24WfoW.mjs.map +0 -1
  243. package/dist/storage-CYlGwWTj.mjs +0 -3
  244. package/dist/sync-CmEuNZsB.mjs +0 -76
  245. package/dist/sync-CmEuNZsB.mjs.map +0 -1
  246. package/dist/sync-D306yOWu.cjs +0 -4
  247. package/dist/sync-SizaChmC.cjs +0 -93
  248. package/dist/sync-SizaChmC.cjs.map +0 -1
  249. package/dist/sync-hOqAWHR6.mjs +0 -3
  250. package/dist/types-BhIl-COG.d.cts +0 -2184
  251. package/dist/types-BhIl-COG.d.cts.map +0 -1
  252. package/dist/types-C-arnQ1r.d.mts +0 -2184
  253. package/dist/types-C-arnQ1r.d.mts.map +0 -1
  254. package/dist/workspace-BFMrAKqI.mjs.map +0 -1
  255. package/dist/workspace-BcucjwvA.cjs.map +0 -1
  256. package/dist/workspace-DdJss8I6.cjs +0 -9
  257. package/dist/workspace-k4l3rsFh.mjs +0 -8
@@ -1,12 +1,8 @@
1
- import { ConstructGenerator, isPartitionedRoutes } from "./discover-CAlFgYec.mjs";
2
- import { loadWorkspaceConfig } from "./config-WRdsQYZK.mjs";
3
- import { dirname, join, relative } from "node:path";
1
+ import { i as ConstructGenerator } from "./discover-BLhf7V_J.mjs";
4
2
  import { mkdir, writeFile } from "node:fs/promises";
5
- import { spawn } from "node:child_process";
3
+ import { dirname, join, relative } from "node:path";
6
4
  import { Endpoint } from "@geekmidas/constructs/endpoints";
7
- import { fileURLToPath } from "node:url";
8
5
  import { StandardSchemaJsonSchema, getRegisteredZodJsonSchemas, getSchemaMetadata } from "@geekmidas/schema/conversion";
9
-
10
6
  //#region src/build/endpoint-analyzer.ts
11
7
  /**
12
8
  * Analyze an endpoint to extract its features
@@ -83,7 +79,6 @@ function summarizeAnalysis(analyses) {
83
79
  byFeature
84
80
  };
85
81
  }
86
-
87
82
  //#endregion
88
83
  //#region src/build/handler-templates.ts
89
84
  /**
@@ -105,8 +100,7 @@ function generateMinimalHandler(analysis) {
105
100
  const { exportName, features } = analysis;
106
101
  const method = analysis.method.toLowerCase();
107
102
  const validators = generateValidators(exportName, features);
108
- const hasValidators = validators.length > 0;
109
- if (!hasValidators && !features.hasOutputValidation) return `
103
+ if (!(validators.length > 0) && !features.hasOutputValidation) return `
110
104
  // Minimal handler: ${analysis.route} (${analysis.method})
111
105
  app.${method}('${analysis.route}', async (c) => {
112
106
  const result = await ${exportName}.handler(
@@ -304,8 +298,7 @@ ${factories.join("\n")}
304
298
  */
305
299
  function generateMinimalEndpointFile(analysis, endpointImport) {
306
300
  const { exportName, features } = analysis;
307
- const needsValidators = features.hasBodyValidation || features.hasQueryValidation || features.hasParamValidation;
308
- const validatorImport = needsValidators ? generateValidatorImportsForEndpoint(analysis) : "";
301
+ const validatorImport = features.hasBodyValidation || features.hasQueryValidation || features.hasParamValidation ? generateValidatorImportsForEndpoint(analysis) : "";
309
302
  const handler = generateMinimalHandler(analysis);
310
303
  return `/**
311
304
  * Minimal endpoint: ${analysis.route} (${analysis.method})
@@ -330,8 +323,7 @@ ${handler}
330
323
  */
331
324
  function generateStandardEndpointFile(analysis, endpointImport) {
332
325
  const { exportName, features } = analysis;
333
- const needsValidators = features.hasBodyValidation || features.hasQueryValidation || features.hasParamValidation;
334
- const validatorImport = needsValidators ? generateValidatorImportsForEndpoint(analysis) : "";
326
+ const validatorImport = features.hasBodyValidation || features.hasQueryValidation || features.hasParamValidation ? generateValidatorImportsForEndpoint(analysis) : "";
335
327
  const eventsImport = features.hasEvents ? `import { publishConstructEvents } from '@geekmidas/constructs/endpoints';` : "";
336
328
  const handler = generateStandardHandler(analysis);
337
329
  return `/**
@@ -423,7 +415,7 @@ export function setupFullEndpoints(
423
415
  }
424
416
  const imports = tierEndpoints.map((a) => `import { setup${capitalize(a.exportName)} } from './${a.exportName}.js';`).join("\n");
425
417
  if (tier === "minimal") {
426
- const calls$1 = tierEndpoints.map((a) => ` setup${capitalize(a.exportName)}(app, logger);`).join("\n");
418
+ const calls = tierEndpoints.map((a) => ` setup${capitalize(a.exportName)}(app, logger);`).join("\n");
427
419
  return `/**
428
420
  * Minimal-tier endpoint index (${tierEndpoints.length} endpoints)
429
421
  * Near-raw-Hono performance
@@ -436,12 +428,12 @@ export function setupMinimalEndpoints(
436
428
  app: Hono,
437
429
  logger: Logger,
438
430
  ): void {
439
- ${calls$1}
431
+ ${calls}
440
432
  }
441
433
  `;
442
434
  }
443
435
  if (tier === "standard") {
444
- const calls$1 = tierEndpoints.map((a) => ` setup${capitalize(a.exportName)}(app, serviceDiscovery, logger);`).join("\n");
436
+ const calls = tierEndpoints.map((a) => ` setup${capitalize(a.exportName)}(app, serviceDiscovery, logger);`).join("\n");
445
437
  return `/**
446
438
  * Standard-tier endpoint index (${tierEndpoints.length} endpoints)
447
439
  * Auth and/or services enabled
@@ -456,7 +448,7 @@ export function setupStandardEndpoints(
456
448
  serviceDiscovery: ServiceDiscovery<any, any>,
457
449
  logger: Logger,
458
450
  ): void {
459
- ${calls$1}
451
+ ${calls}
460
452
  }
461
453
  `;
462
454
  }
@@ -526,9 +518,7 @@ function generateEndpointFilesNested(analyses, endpointImports) {
526
518
  case "standard":
527
519
  files[fileName] = generateStandardEndpointFile(analysis, endpointImport);
528
520
  break;
529
- case "full":
530
- files[fileName] = generateFullEndpointFile(analysis, endpointImport);
531
- break;
521
+ case "full": files[fileName] = generateFullEndpointFile(analysis, endpointImport);
532
522
  }
533
523
  }
534
524
  return files;
@@ -585,7 +575,6 @@ export async function setupEndpoints(
585
575
  }
586
576
  `;
587
577
  }
588
-
589
578
  //#endregion
590
579
  //#region src/generators/EndpointGenerator.ts
591
580
  /**
@@ -602,24 +591,21 @@ export async function setupEndpoints(
602
591
  *
603
592
  * Falls back to the configured paths for an app that declares no surface.
604
593
  */
605
- function runtimeFor(context, fromDir) {
606
- const module = context.surface?.module;
594
+ function runtimeFor(context, fromDir, owner) {
595
+ const module = owner ? context.owners?.[owner] ?? context.surface?.module : context.surface?.module;
607
596
  if (module) {
608
597
  const specifier = importSpecifier(fromDir, module.specifier);
609
598
  return {
610
599
  imports: `import { ${module.exportName} as __surface } from '${specifier}';`,
611
600
  bindings: [
612
- "// What this surface was declared with. Objects, not module paths:",
613
- "// the entry imports the surface, so there is nothing to print.",
601
+ "// What this construct was declared with. Objects, not module paths:",
602
+ "// the entry imports the owner, so there is nothing to print.",
614
603
  "const envParser = __surface.envParser;",
615
604
  "const logger = __surface.logger;"
616
605
  ].join("\n")
617
606
  };
618
607
  }
619
- return {
620
- imports: [`import ${context.envParserImportPattern} from '${importSpecifier(fromDir, context.envParserPath)}';`, `import ${context.loggerImportPattern} from '${importSpecifier(fromDir, context.loggerPath)}';`].join("\n"),
621
- bindings: ""
622
- };
608
+ 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\`.`);
623
609
  }
624
610
  /** A relative specifier ESM will accept: always prefixed, never bare. */
625
611
  function importSpecifier(fromDir, target) {
@@ -734,8 +720,7 @@ var EndpointGenerator = class extends ConstructGenerator {
734
720
  async generateHandlerFile(outputDir, sourceFile, exportName, provider, _endpoint, context) {
735
721
  const handlerFileName = `${exportName}.ts`;
736
722
  const handlerPath = join(outputDir, handlerFileName);
737
- const relativePath = relative(dirname(handlerPath), sourceFile);
738
- const importPath = relativePath.replace(/\.ts$/, ".js");
723
+ const importPath = relative(dirname(handlerPath), sourceFile).replace(/\.ts$/, ".js");
739
724
  let content;
740
725
  switch (provider) {
741
726
  case "aws-apigatewayv1":
@@ -753,12 +738,10 @@ var EndpointGenerator = class extends ConstructGenerator {
753
738
  return handlerPath;
754
739
  }
755
740
  async generateEndpointsFile(outputDir, endpoints, context) {
756
- const endpointsFileName = "endpoints.ts";
757
- const endpointsPath = join(outputDir, endpointsFileName);
741
+ const endpointsPath = join(outputDir, "endpoints.ts");
758
742
  const importsByFile = /* @__PURE__ */ new Map();
759
743
  for (const { path, key } of endpoints) {
760
- const relativePath = relative(dirname(endpointsPath), path.relative);
761
- const importPath = relativePath.replace(/\.ts$/, ".js");
744
+ const importPath = relative(dirname(endpointsPath), path.relative).replace(/\.ts$/, ".js");
762
745
  if (!importsByFile.has(importPath)) importsByFile.set(importPath, []);
763
746
  importsByFile.get(importPath)?.push(key);
764
747
  }
@@ -773,7 +756,7 @@ import { ServiceDiscovery } from '@geekmidas/services';
773
756
  import type { Hono } from 'hono';
774
757
  ${endpointImports}
775
758
 
776
- export const endpoints: Endpoint<any, any, any, any, any, any, any, any, any, any, any, any, any, any>[] = [
759
+ export const endpoints: Endpoint<any, any, any, any, any, any, any, any, any, any, any, any>[] = [
777
760
  ${allExportNames.join(",\n ")}
778
761
  ];
779
762
 
@@ -824,11 +807,9 @@ export async function setupEndpoints(
824
807
  const analyses = endpoints.map(({ key, construct }) => analyzeEndpoint(construct, key));
825
808
  const endpointImports = endpoints.map(({ key, path }) => {
826
809
  const tierDir = join(endpointsDir, "standard");
827
- const relativePath = relative(tierDir, path.relative);
828
- const importPath = relativePath.replace(/\.ts$/, ".js");
829
810
  return {
830
811
  exportName: key,
831
- importPath
812
+ importPath: relative(tierDir, path.relative).replace(/\.ts$/, ".js")
832
813
  };
833
814
  });
834
815
  const summary = summarizeAnalysis(analyses);
@@ -850,8 +831,7 @@ export async function setupEndpoints(
850
831
  }
851
832
  async generateAppFile(outputDir, context) {
852
833
  if (context.production?.enabled) return this.generateProductionAppFile(outputDir, context);
853
- const appFileName = "app.ts";
854
- const appPath = join(outputDir, appFileName);
834
+ const appPath = join(outputDir, "app.ts");
855
835
  const runtime = runtimeFor(context, dirname(appPath));
856
836
  const telescopeEnabled = context.telescope?.enabled;
857
837
  const telescopeWebSocketEnabled = context.telescope?.websocket;
@@ -861,32 +841,36 @@ export async function setupEndpoints(
861
841
  const studioFromDatabase = !usesExternalStudio && !!context.studio?.database;
862
842
  const telescopeFromSurface = !!context.surface?.module && !usesExternalTelescope;
863
843
  let telescopeImports = "";
864
- if (telescopeEnabled) if (telescopeFromSurface) telescopeImports = "import { createMiddleware, createUI } from '@geekmidas/telescope/hono';";
865
- else if (usesExternalTelescope) {
866
- const relativeTelescopePath = relative(dirname(appPath), context.telescope?.telescopePath);
867
- telescopeImports = `import ${context.telescope?.telescopeImportPattern} from '${relativeTelescopePath}';
844
+ if (telescopeEnabled) {
845
+ if (telescopeFromSurface) telescopeImports = `import { Telescope, InMemoryStorage } from '@geekmidas/telescope';
846
+ import { createMiddleware, createUI } from '@geekmidas/telescope/hono';`;
847
+ else if (usesExternalTelescope) {
848
+ const relativeTelescopePath = relative(dirname(appPath), context.telescope?.telescopePath);
849
+ telescopeImports = `import ${context.telescope?.telescopeImportPattern} from '${relativeTelescopePath}';
868
850
  import { createMiddleware, createUI } from '@geekmidas/telescope/hono';`;
869
- } else telescopeImports = `import { Telescope, InMemoryStorage } from '@geekmidas/telescope';
851
+ } else telescopeImports = `import { Telescope, InMemoryStorage } from '@geekmidas/telescope';
870
852
  import { createMiddleware, createUI } from '@geekmidas/telescope/hono';`;
853
+ }
871
854
  let studioImports = "";
872
- if (studioEnabled) if (usesExternalStudio) {
873
- const relativeStudioPath = relative(dirname(appPath), context.studio?.studioPath);
874
- studioImports = `import ${context.studio?.studioImportPattern} from '${relativeStudioPath}';
855
+ if (studioEnabled) {
856
+ if (usesExternalStudio) {
857
+ const relativeStudioPath = relative(dirname(appPath), context.studio?.studioPath);
858
+ studioImports = `import ${context.studio?.studioImportPattern} from '${relativeStudioPath}';
875
859
  import { createStudioApp } from '@geekmidas/studio/server/hono';`;
876
- } else if (studioFromDatabase) {
877
- const dbSpecifier = importSpecifier(dirname(appPath), context.studio.database.specifier);
878
- studioImports = `import { snifferContext } from '@geekmidas/constructs';
860
+ } else if (studioFromDatabase) {
861
+ const dbSpecifier = importSpecifier(dirname(appPath), context.studio.database.specifier);
862
+ studioImports = `import { snifferContext } from '@geekmidas/constructs';
879
863
  import { Direction, InMemoryMonitoringStorage, Studio } from '@geekmidas/studio';
880
864
  import { ${context.studio.database.exportName} as __studioDb } from '${dbSpecifier}';
881
865
  import { createStudioApp } from '@geekmidas/studio/server/hono';`;
882
- } else studioImports = "";
866
+ } else studioImports = "";
867
+ }
883
868
  const cors = corsFor(context.surface);
884
869
  let hooksImports = "";
885
870
  let beforeSetupCall = "";
886
871
  let afterSetupCall = "";
887
872
  if (context.hooks?.serverHooksPath) {
888
- const relativeHooksPath = relative(dirname(appPath), context.hooks.serverHooksPath);
889
- hooksImports = `import * as serverHooks from '${relativeHooksPath}';`;
873
+ hooksImports = `import * as serverHooks from '${relative(dirname(appPath), context.hooks.serverHooksPath)}';`;
890
874
  beforeSetupCall = `
891
875
  // Call beforeSetup hook if defined
892
876
  if (typeof serverHooks.beforeSetup === 'function') {
@@ -932,7 +916,8 @@ import { createStudioApp } from '@geekmidas/studio/server/hono';`;
932
916
  }
933
917
  ` : "";
934
918
  let telescopeSetup = "";
935
- if (telescopeEnabled) if (telescopeFromSurface || usesExternalTelescope) telescopeSetup = `
919
+ if (telescopeEnabled) {
920
+ if (telescopeFromSurface || usesExternalTelescope) telescopeSetup = `
936
921
  ${telescopeWebSocketSetupCode}
937
922
  // Add telescope middleware (before endpoints to capture all requests)
938
923
  honoApp.use('*', createMiddleware(telescope));
@@ -941,7 +926,7 @@ ${telescopeWebSocketSetupCode}
941
926
  const telescopeUI = createUI(telescope);
942
927
  honoApp.route('${context.telescope?.path}', telescopeUI);
943
928
  `;
944
- else telescopeSetup = `
929
+ else telescopeSetup = `
945
930
  // Setup Telescope for debugging/monitoring
946
931
  const telescopeStorage = new InMemoryStorage({ maxEntries: ${context.telescope?.maxEntries} });
947
932
  const telescope = new Telescope({
@@ -959,6 +944,7 @@ ${telescopeWebSocketSetupCode}
959
944
  const telescopeUI = createUI(telescope);
960
945
  honoApp.route('${context.telescope?.path}', telescopeUI);
961
946
  `;
947
+ }
962
948
  let studioSetup = "";
963
949
  if (studioEnabled && studioFromDatabase) studioSetup = `
964
950
  // Studio, built from the declared database. The client comes from the
@@ -992,6 +978,7 @@ import type { Hono as HonoType } from 'hono';
992
978
  import { setupEndpoints } from './endpoints.js';
993
979
  import { setupSubscribers } from './subscribers.js';
994
980
  import { setupQueues } from './queues.js';
981
+ import { setupCrons } from './crons.js';
995
982
  ${runtime.imports}
996
983
  ${telescopeImports}
997
984
  ${studioImports}
@@ -1000,7 +987,16 @@ ${cors.imports}
1000
987
  ${context.storageDrivers?.imports ?? ""}
1001
988
 
1002
989
  ${runtime.bindings}
1003
- ${telescopeFromSurface ? "const telescope = __surface.telescope;" : ""}
990
+ ${telescopeEnabled && telescopeFromSurface ? `// The surface's own Telescope, or the one \`telescope\` config describes.
991
+ const telescope =
992
+ __surface.telescope ??
993
+ new Telescope({
994
+ enabled: true,
995
+ path: '${context.telescope?.path}',
996
+ ignorePatterns: ${JSON.stringify(context.telescope?.ignore)},
997
+ recordBody: ${context.telescope?.recordBody},
998
+ storage: new InMemoryStorage({ maxEntries: ${context.telescope?.maxEntries} }),
999
+ });` : ""}
1004
1000
 
1005
1001
  ${context.storageDrivers?.setup ? `// Which storage drivers exist is the entry point's decision: the scheme in
1006
1002
  // each injected URL picks one, so no construct and no application module names
@@ -1069,9 +1065,11 @@ ${afterSetupCall}
1069
1065
 
1070
1066
  const port = options.port ?? 3000;
1071
1067
 
1072
- // Start subscribers in background (non-blocking, local development only)
1073
- await setupSubscribers(envParser, logger).catch((error) => {
1068
+ // Mount pushed subscribers' routes and start polled ones. What comes
1069
+ // back subscribes the routes, once the server can answer them.
1070
+ const subscribeForPush = await setupSubscribers(honoApp, envParser, logger).catch((error) => {
1074
1071
  logger.error({ error }, 'Failed to start subscribers');
1072
+ return async (_port: number) => {};
1075
1073
  });
1076
1074
 
1077
1075
  // Start queue workers in background (non-blocking, local development only)
@@ -1079,12 +1077,20 @@ ${afterSetupCall}
1079
1077
  logger.error({ error }, 'Failed to start queue workers');
1080
1078
  });
1081
1079
 
1080
+ // Schedule this app's crons. Caught like the others: a scheduler that
1081
+ // cannot start is not a reason for the HTTP server not to.
1082
+ await setupCrons(envParser, logger).catch((error) => {
1083
+ logger.error({ error }, 'Failed to schedule crons');
1084
+ });
1085
+
1082
1086
  logger.info({ port }, 'Starting server');
1083
1087
 
1084
1088
  // Start HTTP server using provided serve function
1085
1089
  await options.serve(honoApp, port);
1086
1090
 
1087
1091
  logger.info({ port }, 'Server started');
1092
+
1093
+ await subscribeForPush(port);
1088
1094
  }
1089
1095
  };
1090
1096
  }
@@ -1147,10 +1153,8 @@ export const handler = ${exportName};
1147
1153
  * No dev tools (Telescope, Studio, WebSocket), includes health checks and graceful shutdown
1148
1154
  */
1149
1155
  async generateProductionAppFile(outputDir, context) {
1150
- const appFileName = "app.ts";
1151
- const appPath = join(outputDir, appFileName);
1152
- const relativeLoggerPath = relative(dirname(appPath), context.loggerPath);
1153
- const relativeEnvParserPath = relative(dirname(appPath), context.envParserPath);
1156
+ const appPath = join(outputDir, "app.ts");
1157
+ const runtime = runtimeFor(context, dirname(appPath));
1154
1158
  const production = context.production;
1155
1159
  const healthCheckPath = production.healthCheck;
1156
1160
  const enableGracefulShutdown = production.gracefulShutdown;
@@ -1161,8 +1165,7 @@ export const handler = ${exportName};
1161
1165
  let beforeSetupCall = "";
1162
1166
  let afterSetupCall = "";
1163
1167
  if (context.hooks?.serverHooksPath) {
1164
- const relativeHooksPath = relative(dirname(appPath), context.hooks.serverHooksPath);
1165
- hooksImports = `import * as serverHooks from '${relativeHooksPath}';`;
1168
+ hooksImports = `import * as serverHooks from '${relative(dirname(appPath), context.hooks.serverHooksPath)}';`;
1166
1169
  beforeSetupCall = `
1167
1170
  // Call beforeSetup hook if defined
1168
1171
  if (typeof serverHooks.beforeSetup === 'function') {
@@ -1177,18 +1180,27 @@ export const handler = ${exportName};
1177
1180
  `;
1178
1181
  }
1179
1182
  const subscriberSetup = includeSubscribers ? `
1180
- // Start subscribers in background
1181
- await setupSubscribers(envParser, logger).catch((error) => {
1183
+ // Mount pushed subscribers' routes and start polled ones. What comes
1184
+ // back subscribes the routes, once the server can answer them.
1185
+ const subscribeForPush = await setupSubscribers(honoApp, envParser, logger).catch((error) => {
1182
1186
  logger.error({ error }, 'Failed to start subscribers');
1187
+ return async (_port: number) => {};
1183
1188
  });
1184
1189
 
1185
1190
  // Start queue workers in background
1186
1191
  await setupQueues(envParser, logger).catch((error) => {
1187
1192
  logger.error({ error }, 'Failed to start queue workers');
1188
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
+ });
1189
1200
  ` : "";
1190
1201
  const subscriberImport = includeSubscribers ? `import { setupSubscribers } from './subscribers.js';
1191
- import { setupQueues } from './queues.js';` : "";
1202
+ import { setupQueues } from './queues.js';
1203
+ import { setupCrons } from './crons.js';` : "";
1192
1204
  const gracefulShutdownCode = enableGracefulShutdown ? `
1193
1205
  // Graceful shutdown handling
1194
1206
  let isShuttingDown = false;
@@ -1204,7 +1216,6 @@ import { setupQueues } from './queues.js';` : "";
1204
1216
  process.on('SIGTERM', shutdown);
1205
1217
  process.on('SIGINT', shutdown);
1206
1218
  ` : "";
1207
- const endpointsImportPath = production.optimizedHandlers ? "./endpoints/index.js" : "./endpoints.js";
1208
1219
  const content = `/**
1209
1220
  * Generated production server application
1210
1221
  *
@@ -1216,10 +1227,10 @@ import { setupQueues } from './queues.js';` : "";
1216
1227
  */
1217
1228
  import { Hono } from 'hono';
1218
1229
  import type { Hono as HonoType } from 'hono';
1219
- import { setupEndpoints } from '${endpointsImportPath}';
1230
+ import { setupEndpoints } from '${production.optimizedHandlers ? "./endpoints/index.js" : "./endpoints.js"}';
1220
1231
  ${subscriberImport}
1221
- import ${context.envParserImportPattern} from '${relativeEnvParserPath}';
1222
- import ${context.loggerImportPattern} from '${relativeLoggerPath}';
1232
+ ${runtime.imports}
1233
+ ${runtime.bindings}
1223
1234
  ${hooksImports}
1224
1235
  ${cors.imports}
1225
1236
  ${context.storageDrivers?.imports ?? ""}
@@ -1267,6 +1278,7 @@ ${gracefulShutdownCode}${subscriberSetup}
1267
1278
  await options.serve(honoApp, port);
1268
1279
 
1269
1280
  logger.info({ port }, 'Production server started');
1281
+ ${includeSubscribers ? "\n await subscribeForPush(port);" : ""}
1270
1282
  }
1271
1283
  };
1272
1284
  }
@@ -1283,7 +1295,7 @@ export default createApp;
1283
1295
  */
1284
1296
  async generateProductionServerEntry(outputDir) {
1285
1297
  const serverPath = join(outputDir, "server.ts");
1286
- const content = `#!/usr/bin/env node
1298
+ await writeFile(serverPath, `#!/usr/bin/env node
1287
1299
  /**
1288
1300
  * Production server entry point
1289
1301
  * Generated by 'gkm build --provider server --production'
@@ -1299,11 +1311,9 @@ await start({
1299
1311
  port,
1300
1312
  serve: (app, port) => { serve({ fetch: app.fetch, port }); },
1301
1313
  });
1302
- `;
1303
- await writeFile(serverPath, content);
1314
+ `);
1304
1315
  }
1305
1316
  };
1306
-
1307
1317
  //#endregion
1308
1318
  //#region src/generators/OpenApiTsGenerator.ts
1309
1319
  /**
@@ -1458,7 +1468,7 @@ var OpenApiTsGenerator = class {
1458
1468
  for (const [rawName, rawSchema] of Object.entries(registrySchemas)) {
1459
1469
  const defName = this.pascalCase(rawName);
1460
1470
  if (collectedDefs.has(defName) || generatedNames.has(defName)) continue;
1461
- const { id: _id, $defs: _defs,...rest } = rawSchema;
1471
+ const { id: _id, $defs: _defs, ...rest } = rawSchema;
1462
1472
  collectedDefs.set(defName, rest);
1463
1473
  }
1464
1474
  for (const [defName, defSchema] of collectedDefs) if (!generatedNames.has(defName)) {
@@ -1494,17 +1504,17 @@ var OpenApiTsGenerator = class {
1494
1504
  async schemaToInterfaceWithDefs(schema, name, collectedDefs) {
1495
1505
  try {
1496
1506
  const vendor = schema["~standard"]?.vendor;
1497
- if (!vendor || !(vendor in StandardSchemaJsonSchema)) return null;
1507
+ if (!vendor || !(vendor in StandardSchemaJsonSchema)) return unknownType(name);
1498
1508
  const toJsonSchema = StandardSchemaJsonSchema[vendor];
1499
1509
  const jsonSchema = await toJsonSchema(schema);
1500
- if (!jsonSchema) return null;
1510
+ if (!jsonSchema) return unknownType(name);
1501
1511
  if (jsonSchema.$defs && typeof jsonSchema.$defs === "object") {
1502
1512
  for (const [defName, defSchema] of Object.entries(jsonSchema.$defs)) if (!collectedDefs.has(defName)) {
1503
- const { id,...schemaWithoutId } = defSchema;
1513
+ const { id, ...schemaWithoutId } = defSchema;
1504
1514
  collectedDefs.set(defName, schemaWithoutId);
1505
1515
  }
1506
1516
  }
1507
- const { $defs,...schemaWithoutDefs } = jsonSchema;
1517
+ const { $defs, ...schemaWithoutDefs } = jsonSchema;
1508
1518
  const ref = schemaWithoutDefs.$ref;
1509
1519
  if (ref && Object.keys(schemaWithoutDefs).every((k) => k === "$ref" || k === "$schema")) {
1510
1520
  const target = ref.split("/").pop();
@@ -1512,14 +1522,11 @@ var OpenApiTsGenerator = class {
1512
1522
  }
1513
1523
  return this.jsonSchemaToInterface(schemaWithoutDefs, name);
1514
1524
  } catch {
1515
- return null;
1525
+ return unknownType(name);
1516
1526
  }
1517
1527
  }
1518
1528
  jsonSchemaToInterface(schema, name) {
1519
- if (schema.type !== "object" || !schema.properties) {
1520
- const typeStr = this.jsonSchemaTypeToTs(schema);
1521
- return `export type ${name} = ${typeStr};`;
1522
- }
1529
+ if (schema.type !== "object" || !schema.properties) return `export type ${name} = ${this.jsonSchemaTypeToTs(schema)};`;
1523
1530
  const props = [];
1524
1531
  const required = new Set(schema.required || []);
1525
1532
  for (const [propName, propSchema] of Object.entries(schema.properties)) {
@@ -1532,13 +1539,15 @@ var OpenApiTsGenerator = class {
1532
1539
  }
1533
1540
  jsonSchemaTypeToTs(schema) {
1534
1541
  if (!schema) return "unknown";
1535
- if (schema.$ref) {
1536
- const refName = schema.$ref.split("/").pop() || "unknown";
1537
- return refName;
1538
- }
1542
+ if (schema.$ref) return schema.$ref.split("/").pop() || "unknown";
1543
+ if (schema.const !== void 0) return typeof schema.const === "string" ? `'${schema.const}'` : String(schema.const);
1539
1544
  if (schema.anyOf) return schema.anyOf.map((s) => this.jsonSchemaTypeToTs(s)).join(" | ");
1540
1545
  if (schema.oneOf) return schema.oneOf.map((s) => this.jsonSchemaTypeToTs(s)).join(" | ");
1541
1546
  if (schema.allOf) return schema.allOf.map((s) => this.jsonSchemaTypeToTs(s)).join(" & ");
1547
+ if (Array.isArray(schema.type)) return schema.type.map((type) => this.jsonSchemaTypeToTs({
1548
+ ...schema,
1549
+ type
1550
+ })).join(" | ");
1542
1551
  switch (schema.type) {
1543
1552
  case "string":
1544
1553
  if (schema.enum) return schema.enum.map((e) => `'${e}'`).join(" | ");
@@ -1562,10 +1571,7 @@ var OpenApiTsGenerator = class {
1562
1571
  }
1563
1572
  return `{ ${props.join("; ")} }`;
1564
1573
  }
1565
- if (schema.additionalProperties) {
1566
- const valueType = this.jsonSchemaTypeToTs(schema.additionalProperties);
1567
- return `Record<string, ${valueType}>`;
1568
- }
1574
+ if (schema.additionalProperties) return `Record<string, ${this.jsonSchemaTypeToTs(schema.additionalProperties)}>`;
1569
1575
  return "Record<string, unknown>";
1570
1576
  default: return "unknown";
1571
1577
  }
@@ -1586,10 +1592,7 @@ var OpenApiTsGenerator = class {
1586
1592
  }
1587
1593
  const firstWithParams = infos.find((i) => i.input?.params);
1588
1594
  let paramsEntry = "";
1589
- if (firstWithParams?.input?.params) {
1590
- const paramsName = await this.getSchemaName(firstWithParams.input.params, `${this.getSchemaBaseName(firstWithParams)}Params`);
1591
- paramsEntry = `\n parameters: {\n path: ${paramsName};\n };`;
1592
- }
1595
+ if (firstWithParams?.input?.params) paramsEntry = `\n parameters: {\n path: ${await this.getSchemaName(firstWithParams.input.params, `${this.getSchemaBaseName(firstWithParams)}Params`)};\n };`;
1593
1596
  pathEntries.push(` '${route}': {${paramsEntry}\n${methodEntries.join("\n")}\n };`);
1594
1597
  }
1595
1598
  return `export interface paths {\n${pathEntries.join("\n")}\n}`;
@@ -1628,8 +1631,7 @@ var OpenApiTsGenerator = class {
1628
1631
  return acc;
1629
1632
  }, {});
1630
1633
  const schemeNames = securitySchemes.map((s) => `'${s.name}'`).join(" | ");
1631
- const hasSecuritySchemes = schemeNames.length > 0;
1632
- const createApiSection = hasSecuritySchemes ? `
1634
+ const createApiSection = schemeNames.length > 0 ? `
1633
1635
  // ============================================================
1634
1636
  // API Client Factory
1635
1637
  // ============================================================
@@ -1653,6 +1655,8 @@ export interface CreateApiOptions {
1653
1655
  queryClient?: QueryClient;
1654
1656
  /** Optional request interceptor */
1655
1657
  onRequest?: (config: RequestInit) => RequestInit | Promise<RequestInit>;
1658
+ /** The \`fetch\` requests go out on — a test browser's, for one */
1659
+ fetch?: typeof fetch;
1656
1660
  }
1657
1661
 
1658
1662
  /**
@@ -1682,6 +1686,7 @@ export function createApi(options: CreateApiOptions) {
1682
1686
  securitySchemes,
1683
1687
  authStrategies: options.authStrategies,
1684
1688
  onRequest: options.onRequest,
1689
+ ...(options.fetch ? { fetch: options.fetch } : {}),
1685
1690
  });
1686
1691
 
1687
1692
  const hooks = createEndpointHooks<paths>(fetcher, { queryClient: options.queryClient });
@@ -1806,162 +1811,15 @@ ${createApiSection}
1806
1811
  `;
1807
1812
  }
1808
1813
  };
1809
-
1810
- //#endregion
1811
- //#region src/workspace/client-generator.ts
1812
1814
  /**
1813
- * Normalize routes to an array of patterns.
1814
- * Handles string, string[], and PartitionedRoutes (extracts paths).
1815
- * @internal Exported for use in dev command
1815
+ * The declaration for a schema that cannot be converted — a vendor with no
1816
+ * converter, or one that fails. The paths interface names it either way, so
1817
+ * leaving it undeclared made the generated client fail to compile.
1816
1818
  */
1817
- function normalizeRoutes(routes) {
1818
- if (!routes) return [];
1819
- if (isPartitionedRoutes(routes)) return Array.isArray(routes.paths) ? routes.paths : [routes.paths];
1820
- return Array.isArray(routes) ? routes : [routes];
1819
+ function unknownType(name) {
1820
+ return `export type ${name} = unknown;`;
1821
1821
  }
1822
-
1823
1822
  //#endregion
1824
- //#region src/openapi.ts
1825
- /**
1826
- * Default output path for generated OpenAPI client (used for single-app configs)
1827
- */
1828
- const OPENAPI_OUTPUT_PATH = "./.gkm/openapi.ts";
1829
- /**
1830
- * Resolve OpenAPI config from GkmConfig
1831
- */
1832
- function resolveOpenApiConfig(config) {
1833
- if (config.openapi === false) return { enabled: false };
1834
- if (config.openapi === true || config.openapi === void 0) return {
1835
- enabled: true,
1836
- title: "API Documentation",
1837
- version: "1.0.0",
1838
- description: "Auto-generated API documentation from endpoints"
1839
- };
1840
- return {
1841
- enabled: config.openapi.enabled !== false,
1842
- title: config.openapi.title || "API Documentation",
1843
- version: config.openapi.version || "1.0.0",
1844
- description: config.openapi.description || "Auto-generated API documentation from endpoints"
1845
- };
1846
- }
1847
- /**
1848
- * Generate OpenAPI spec from endpoints
1849
- * @returns Object with output path and endpoint count, or null if disabled
1850
- */
1851
- async function generateOpenApi(config, options = {}) {
1852
- const logger = options.silent ? { log: () => {} } : console;
1853
- const openApiConfig = resolveOpenApiConfig(config);
1854
- if (!openApiConfig.enabled) return null;
1855
- const endpointGenerator = new EndpointGenerator();
1856
- const loadedEndpoints = await endpointGenerator.load(config.routes, void 0, options.bustCache);
1857
- if (loadedEndpoints.length === 0) {
1858
- logger.log("No valid endpoints found for OpenAPI generation");
1859
- return null;
1860
- }
1861
- const endpoints = loadedEndpoints.map(({ construct }) => construct);
1862
- const outputPath = join(process.cwd(), OPENAPI_OUTPUT_PATH);
1863
- await mkdir(dirname(outputPath), { recursive: true });
1864
- const tsGenerator = new OpenApiTsGenerator();
1865
- const tsContent = await tsGenerator.generate(endpoints, {
1866
- title: openApiConfig.title,
1867
- version: openApiConfig.version,
1868
- description: openApiConfig.description
1869
- });
1870
- await writeFile(outputPath, tsContent);
1871
- logger.log(`📄 OpenAPI client generated: ${OPENAPI_OUTPUT_PATH}`);
1872
- return {
1873
- outputPath,
1874
- endpointCount: loadedEndpoints.length
1875
- };
1876
- }
1877
- async function openapiCommand(options = {}) {
1878
- const logger = console;
1879
- try {
1880
- const loadedConfig = await loadWorkspaceConfig(options.cwd);
1881
- if (loadedConfig.type === "single") {
1882
- const config = loadedConfig.raw;
1883
- if (!config.openapi) config.openapi = { enabled: true };
1884
- const result = await generateOpenApi(config);
1885
- if (result) logger.log(`Found ${result.endpointCount} endpoints`);
1886
- } else {
1887
- const { workspace } = loadedConfig;
1888
- const workspaceRoot = workspace.root;
1889
- const backendApps = Object.entries(workspace.apps).filter(([_, app]) => app.type === "backend" && app.routes !== void 0 && app.openapi !== false && (typeof app.openapi !== "object" || app.openapi.enabled !== false));
1890
- if (backendApps.length === 0) {
1891
- logger.log("No backend apps with OpenAPI enabled found");
1892
- return;
1893
- }
1894
- if (options.app) {
1895
- const entry = backendApps.find(([name]) => name === options.app);
1896
- if (!entry) throw new Error(`App "${options.app}" not found or has OpenAPI disabled`);
1897
- const [appName, app] = entry;
1898
- const result = await generateOpenApiForApp(workspaceRoot, appName, app);
1899
- if (result) logger.log(`📄 [${appName}] Generated OpenAPI (${result.endpointCount} endpoints)`);
1900
- return;
1901
- }
1902
- for (const [appName, app] of backendApps) {
1903
- if (app.type !== "backend" || !app.routes) continue;
1904
- const appPath = join(workspaceRoot, app.path);
1905
- await runOpenApiInSubprocess(appPath, appName);
1906
- }
1907
- }
1908
- } catch (error) {
1909
- throw new Error(`OpenAPI generation failed: ${error.message}`);
1910
- }
1911
- }
1912
- /**
1913
- * Generate OpenAPI for a single named app within a workspace.
1914
- * Runs in-process. The caller is responsible for ensuring `process.cwd()`
1915
- * is the app's directory so tsx loads the app's tsconfig path aliases.
1916
- */
1917
- async function generateOpenApiForApp(workspaceRoot, _appName, app) {
1918
- if (app.type !== "backend" || !app.routes) return null;
1919
- const appPath = join(workspaceRoot, app.path);
1920
- const routes = normalizeRoutes(app.routes);
1921
- const routesGlob = routes.map((r) => join(appPath, r));
1922
- const gkmConfig = {
1923
- routes: routesGlob,
1924
- envParser: app.envParser || "",
1925
- logger: app.logger || "",
1926
- openapi: app.openapi
1927
- };
1928
- return generateOpenApi(gkmConfig, { silent: true });
1929
- }
1930
- /**
1931
- * Resolve the gkm bin path. Tests can override via `GKM_BIN_PATH` env var
1932
- * to avoid depending on the built dist.
1933
- */
1934
- function resolveGkmBinPath() {
1935
- if (process.env.GKM_BIN_PATH) return process.env.GKM_BIN_PATH;
1936
- return fileURLToPath(new URL("../bin/gkm.mjs", import.meta.url));
1937
- }
1938
- /**
1939
- * Spawn a subprocess that runs `gkm openapi --app <name>` with `cwd` set to
1940
- * the app's directory. Inherits `NODE_OPTIONS` (which already contains
1941
- * `--import tsx`), so the child gets a fresh tsx instance whose tsconfig
1942
- * discovery picks up the app's tsconfig path aliases.
1943
- */
1944
- async function runOpenApiInSubprocess(appCwd, appName) {
1945
- const binPath = resolveGkmBinPath();
1946
- await new Promise((resolve$1, reject) => {
1947
- const child = spawn(process.execPath, [
1948
- binPath,
1949
- "openapi",
1950
- "--app",
1951
- appName
1952
- ], {
1953
- cwd: appCwd,
1954
- stdio: "inherit",
1955
- env: process.env
1956
- });
1957
- child.on("error", reject);
1958
- child.on("close", (code) => {
1959
- if (code === 0) resolve$1();
1960
- else reject(new Error(`OpenAPI generation for app "${appName}" exited with code ${code}`));
1961
- });
1962
- });
1963
- }
1823
+ export { EndpointGenerator as n, runtimeFor as r, OpenApiTsGenerator as t };
1964
1824
 
1965
- //#endregion
1966
- export { EndpointGenerator, OPENAPI_OUTPUT_PATH, generateOpenApi, normalizeRoutes, openapiCommand, resolveOpenApiConfig };
1967
- //# sourceMappingURL=openapi-kkQbsRVj.mjs.map
1825
+ //# sourceMappingURL=OpenApiTsGenerator-CEh3EKN3.mjs.map