@geekmidas/cli 10.0.0-alpha.2 → 10.0.0-alpha.21

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 (241) hide show
  1. package/README.md +25 -48
  2. package/bin/adjacent-tsconfig.mjs +59 -0
  3. package/bin/gkm.mjs +7 -1
  4. package/dist/{HostingerProvider-Cft7lEYr.mjs → HostingerProvider-BY26bWwB.mjs} +20 -21
  5. package/dist/HostingerProvider-BY26bWwB.mjs.map +1 -0
  6. package/dist/{HostingerProvider-h3EbEp-Z.cjs → HostingerProvider-BZFGYYVA.cjs} +21 -22
  7. package/dist/HostingerProvider-BZFGYYVA.cjs.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/{Route53Provider-RdpUDJQk.mjs → Route53Provider-Cvj40A8I.mjs} +12 -12
  13. package/dist/Route53Provider-Cvj40A8I.mjs.map +1 -0
  14. package/dist/{Route53Provider-di2fMM5N.cjs → Route53Provider-DVILBsvV.cjs} +20 -21
  15. package/dist/Route53Provider-DVILBsvV.cjs.map +1 -0
  16. package/dist/{SSMStateProvider-BRt2py-A.mjs → SSMStateProvider-B0Hu1MKZ.mjs} +13 -4
  17. package/dist/SSMStateProvider-B0Hu1MKZ.mjs.map +1 -0
  18. package/dist/{SSMStateProvider-DyX8s9HI.cjs → SSMStateProvider-VrQ-yeqd.cjs} +17 -9
  19. package/dist/SSMStateProvider-VrQ-yeqd.cjs.map +1 -0
  20. package/dist/{backup-provisioner-BrsHwYG0.cjs → backup-provisioner-BmhIO_Yr.cjs} +21 -19
  21. package/dist/backup-provisioner-BmhIO_Yr.cjs.map +1 -0
  22. package/dist/{backup-provisioner-Bgj5Vi_L.mjs → backup-provisioner-DIVCbfee.mjs} +10 -7
  23. package/dist/backup-provisioner-DIVCbfee.mjs.map +1 -0
  24. package/dist/{bundler-BY1OmV1e.cjs → bundler-mjqGAvu1.cjs} +10 -28
  25. package/dist/bundler-mjqGAvu1.cjs.map +1 -0
  26. package/dist/{bundler-Be8Zg4Wd.mjs → bundler-mwH7WOb1.mjs} +9 -26
  27. package/dist/bundler-mwH7WOb1.mjs.map +1 -0
  28. package/dist/{config-BholeD-0.cjs → config-DSXI480r.cjs} +80 -148
  29. package/dist/config-DSXI480r.cjs.map +1 -0
  30. package/dist/{config-CzWnfcXM.mjs → config-DdKkoUE1.mjs} +33 -88
  31. package/dist/config-DdKkoUE1.mjs.map +1 -0
  32. package/dist/config.cjs +4 -5
  33. package/dist/config.d.cts +14 -17
  34. package/dist/config.d.cts.map +1 -1
  35. package/dist/config.d.mts +14 -17
  36. package/dist/config.d.mts.map +1 -1
  37. package/dist/config.mjs +3 -5
  38. package/dist/{credentials-DQmbRnr1.cjs → credentials-BfmmB4WD.cjs} +1508 -1243
  39. package/dist/credentials-BfmmB4WD.cjs.map +1 -0
  40. package/dist/{credentials-BZcp3CGx.mjs → credentials-CD8ftUS6.mjs} +1374 -1114
  41. package/dist/credentials-CD8ftUS6.mjs.map +1 -0
  42. package/dist/deploy/sniffer-envkit-patch.cjs +18 -10
  43. package/dist/deploy/sniffer-envkit-patch.cjs.map +1 -1
  44. package/dist/deploy/sniffer-envkit-patch.d.cts +0 -2
  45. package/dist/deploy/sniffer-envkit-patch.d.cts.map +1 -1
  46. package/dist/deploy/sniffer-envkit-patch.d.mts +0 -2
  47. package/dist/deploy/sniffer-envkit-patch.d.mts.map +1 -1
  48. package/dist/deploy/sniffer-envkit-patch.mjs +10 -2
  49. package/dist/deploy/sniffer-envkit-patch.mjs.map +1 -1
  50. package/dist/deploy/sniffer-hooks.cjs +13 -7
  51. package/dist/deploy/sniffer-hooks.cjs.map +1 -1
  52. package/dist/deploy/sniffer-hooks.d.cts +1 -2
  53. package/dist/deploy/sniffer-hooks.d.cts.map +1 -1
  54. package/dist/deploy/sniffer-hooks.d.mts +1 -2
  55. package/dist/deploy/sniffer-hooks.d.mts.map +1 -1
  56. package/dist/deploy/sniffer-hooks.mjs +9 -2
  57. package/dist/deploy/sniffer-hooks.mjs.map +1 -1
  58. package/dist/deploy/sniffer-loader.cjs +16 -7
  59. package/dist/deploy/sniffer-loader.cjs.map +1 -1
  60. package/dist/deploy/sniffer-loader.d.cts +1 -1
  61. package/dist/deploy/sniffer-loader.d.mts +1 -1
  62. package/dist/deploy/sniffer-loader.mjs +13 -2
  63. package/dist/deploy/sniffer-loader.mjs.map +1 -1
  64. package/dist/deploy/sniffer-routes-worker.cjs +11 -11
  65. package/dist/deploy/sniffer-routes-worker.cjs.map +1 -1
  66. package/dist/deploy/sniffer-routes-worker.d.cts +1 -1
  67. package/dist/deploy/sniffer-routes-worker.d.mts +1 -1
  68. package/dist/deploy/sniffer-routes-worker.mjs +2 -2
  69. package/dist/deploy/sniffer-routes-worker.mjs.map +1 -1
  70. package/dist/deploy/sniffer-worker.cjs +15 -6
  71. package/dist/deploy/sniffer-worker.cjs.map +1 -1
  72. package/dist/deploy/sniffer-worker.d.cts +1 -3
  73. package/dist/deploy/sniffer-worker.d.cts.map +1 -1
  74. package/dist/deploy/sniffer-worker.d.mts +1 -3
  75. package/dist/deploy/sniffer-worker.d.mts.map +1 -1
  76. package/dist/deploy/sniffer-worker.mjs +15 -4
  77. package/dist/deploy/sniffer-worker.mjs.map +1 -1
  78. package/dist/{discover-DTmFeloL.cjs → discover-BERGFg8v.cjs} +81 -64
  79. package/dist/discover-BERGFg8v.cjs.map +1 -0
  80. package/dist/{discover-CAlFgYec.mjs → discover-CK-n3w6b.mjs} +35 -20
  81. package/dist/discover-CK-n3w6b.mjs.map +1 -0
  82. package/dist/{emit-CbcRolsa.cjs → emit-BdoPFjZf.cjs} +53 -36
  83. package/dist/emit-BdoPFjZf.cjs.map +1 -0
  84. package/dist/{emit-CiZS_5Ub.mjs → emit-Bzq7JsMP.mjs} +24 -6
  85. package/dist/emit-Bzq7JsMP.mjs.map +1 -0
  86. package/dist/{generator-VE2JrFlY.mjs → generator-LfZU7NlU.mjs} +8 -14
  87. package/dist/generator-LfZU7NlU.mjs.map +1 -0
  88. package/dist/{generator-CNzBw7g5.cjs → generator-Wdfp0jCS.cjs} +38 -45
  89. package/dist/generator-Wdfp0jCS.cjs.map +1 -0
  90. package/dist/github-Bho-C6Zg.cjs +216 -0
  91. package/dist/github-Bho-C6Zg.cjs.map +1 -0
  92. package/dist/github-De-yMwVt.mjs +216 -0
  93. package/dist/github-De-yMwVt.mjs.map +1 -0
  94. package/dist/{index-CHB4tSzX.d.cts → index-B4H4XF7A.d.mts} +4 -13
  95. package/dist/index-B4H4XF7A.d.mts.map +1 -0
  96. package/dist/{index-BThUzEIp.d.mts → index-RCUizGxL.d.cts} +4 -13
  97. package/dist/index-RCUizGxL.d.cts.map +1 -0
  98. package/dist/index.cjs +5108 -3381
  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 +5025 -3315
  103. package/dist/index.mjs.map +1 -1
  104. package/dist/{openapi-c9bpieI5.cjs → openapi-B8bu_OXN.cjs} +228 -188
  105. package/dist/openapi-B8bu_OXN.cjs.map +1 -0
  106. package/dist/{openapi-CY9xFkTH.mjs → openapi-DfjbhrsM.mjs} +172 -143
  107. package/dist/openapi-DfjbhrsM.mjs.map +1 -0
  108. package/dist/openapi.cjs +5 -6
  109. package/dist/openapi.d.cts +47 -14
  110. package/dist/openapi.d.cts.map +1 -1
  111. package/dist/openapi.d.mts +47 -14
  112. package/dist/openapi.d.mts.map +1 -1
  113. package/dist/openapi.mjs +2 -6
  114. package/dist/reconcile/public.cjs +4 -4
  115. package/dist/reconcile/public.d.cts +8 -26
  116. package/dist/reconcile/public.d.cts.map +1 -1
  117. package/dist/reconcile/public.d.mts +8 -26
  118. package/dist/reconcile/public.d.mts.map +1 -1
  119. package/dist/reconcile/public.mjs +3 -4
  120. package/dist/{fullstack-secrets-D1o9-G5l.mjs → reconcile-gb1lz1Dk.mjs} +43 -17
  121. package/dist/reconcile-gb1lz1Dk.mjs.map +1 -0
  122. package/dist/{fullstack-secrets-C-GGohke.cjs → reconcile-hx_vBvux.cjs} +63 -38
  123. package/dist/reconcile-hx_vBvux.cjs.map +1 -0
  124. package/dist/rolldown-runtime-BhDjJH2R.mjs +15 -0
  125. package/dist/{chunk-CUT6urMc.cjs → rolldown-runtime-C0BPl7ul.cjs} +23 -10
  126. package/dist/ssm-BKN1Cg4z.mjs +60 -0
  127. package/dist/ssm-BKN1Cg4z.mjs.map +1 -0
  128. package/dist/ssm-FxeSAt35.cjs +60 -0
  129. package/dist/ssm-FxeSAt35.cjs.map +1 -0
  130. package/dist/{storage-BJmzYxt8.cjs → storage-DgypfSD6.cjs} +65 -77
  131. package/dist/storage-DgypfSD6.cjs.map +1 -0
  132. package/dist/{storage-Bi24WfoW.mjs → storage-TP0x118M.mjs} +22 -15
  133. package/dist/storage-TP0x118M.mjs.map +1 -0
  134. package/dist/transfer-CXoyQZbB.cjs +151 -0
  135. package/dist/transfer-CXoyQZbB.cjs.map +1 -0
  136. package/dist/transfer-Gsxfy6m-.mjs +122 -0
  137. package/dist/transfer-Gsxfy6m-.mjs.map +1 -0
  138. package/dist/types-7R81hu0i.d.mts +6302 -0
  139. package/dist/types-7R81hu0i.d.mts.map +1 -0
  140. package/dist/types-N7c2O2m7.d.cts +6303 -0
  141. package/dist/types-N7c2O2m7.d.cts.map +1 -0
  142. package/dist/workspace/index.cjs +3 -3
  143. package/dist/workspace/index.d.cts +3 -3
  144. package/dist/workspace/index.d.mts +3 -3
  145. package/dist/workspace/index.mjs +2 -3
  146. package/dist/workspace-Bu3xNCej.mjs +6563 -0
  147. package/dist/workspace-Bu3xNCej.mjs.map +1 -0
  148. package/dist/workspace-CRD9YinV.cjs +6741 -0
  149. package/dist/workspace-CRD9YinV.cjs.map +1 -0
  150. package/package.json +33 -43
  151. package/dist/CachedStateProvider-BLo7zv7S.cjs +0 -3
  152. package/dist/CachedStateProvider-BxoAm-B2.mjs +0 -3
  153. package/dist/CachedStateProvider-CqPdW7CB.cjs +0 -60
  154. package/dist/CachedStateProvider-CqPdW7CB.cjs.map +0 -1
  155. package/dist/CachedStateProvider-DTniehMP.mjs +0 -54
  156. package/dist/CachedStateProvider-DTniehMP.mjs.map +0 -1
  157. package/dist/HostingerProvider-Cft7lEYr.mjs.map +0 -1
  158. package/dist/HostingerProvider-h3EbEp-Z.cjs.map +0 -1
  159. package/dist/LocalStateProvider-Bn6tS-oL.mjs.map +0 -1
  160. package/dist/LocalStateProvider-Db9SEjyH.cjs.map +0 -1
  161. package/dist/Route53Provider-RdpUDJQk.mjs.map +0 -1
  162. package/dist/Route53Provider-di2fMM5N.cjs.map +0 -1
  163. package/dist/SSMStateProvider-BRt2py-A.mjs.map +0 -1
  164. package/dist/SSMStateProvider-DyX8s9HI.cjs.map +0 -1
  165. package/dist/backup-provisioner-Bgj5Vi_L.mjs.map +0 -1
  166. package/dist/backup-provisioner-BrsHwYG0.cjs.map +0 -1
  167. package/dist/bundler-BY1OmV1e.cjs.map +0 -1
  168. package/dist/bundler-Be8Zg4Wd.mjs.map +0 -1
  169. package/dist/chunk-Duj1WY3L.mjs +0 -7
  170. package/dist/config-BholeD-0.cjs.map +0 -1
  171. package/dist/config-CzWnfcXM.mjs.map +0 -1
  172. package/dist/credentials-B5zRHdAl.mjs +0 -141
  173. package/dist/credentials-B5zRHdAl.mjs.map +0 -1
  174. package/dist/credentials-BZcp3CGx.mjs.map +0 -1
  175. package/dist/credentials-BapzjyV5.cjs +0 -195
  176. package/dist/credentials-BapzjyV5.cjs.map +0 -1
  177. package/dist/credentials-DQmbRnr1.cjs.map +0 -1
  178. package/dist/discover-CAlFgYec.mjs.map +0 -1
  179. package/dist/discover-DTmFeloL.cjs.map +0 -1
  180. package/dist/dokploy-api-BS2xnJLZ.mjs +0 -3
  181. package/dist/dokploy-api-BsVH0y_s.cjs +0 -718
  182. package/dist/dokploy-api-BsVH0y_s.cjs.map +0 -1
  183. package/dist/dokploy-api-BuxDRo3l.cjs +0 -3
  184. package/dist/dokploy-api-aTFPz7_4.mjs +0 -706
  185. package/dist/dokploy-api-aTFPz7_4.mjs.map +0 -1
  186. package/dist/emit-CbcRolsa.cjs.map +0 -1
  187. package/dist/emit-CiZS_5Ub.mjs.map +0 -1
  188. package/dist/encryption-C6jaU0hE.cjs +0 -54
  189. package/dist/encryption-C6jaU0hE.cjs.map +0 -1
  190. package/dist/encryption-CHzzeR8a.cjs +0 -4
  191. package/dist/encryption-CQUncu7v.mjs +0 -3
  192. package/dist/encryption-D-abyhZx.mjs +0 -42
  193. package/dist/encryption-D-abyhZx.mjs.map +0 -1
  194. package/dist/fullstack-secrets-C-GGohke.cjs.map +0 -1
  195. package/dist/fullstack-secrets-D1o9-G5l.mjs.map +0 -1
  196. package/dist/generator-CNzBw7g5.cjs.map +0 -1
  197. package/dist/generator-VE2JrFlY.mjs.map +0 -1
  198. package/dist/index-BThUzEIp.d.mts.map +0 -1
  199. package/dist/index-CHB4tSzX.d.cts.map +0 -1
  200. package/dist/openapi-CY9xFkTH.mjs.map +0 -1
  201. package/dist/openapi-c9bpieI5.cjs.map +0 -1
  202. package/dist/openapi-react-query-Byltvm_7.mjs +0 -167
  203. package/dist/openapi-react-query-Byltvm_7.mjs.map +0 -1
  204. package/dist/openapi-react-query-CmJ1xDbn.cjs +0 -173
  205. package/dist/openapi-react-query-CmJ1xDbn.cjs.map +0 -1
  206. package/dist/openapi-react-query.cjs +0 -4
  207. package/dist/openapi-react-query.d.cts +0 -11
  208. package/dist/openapi-react-query.d.cts.map +0 -1
  209. package/dist/openapi-react-query.d.mts +0 -11
  210. package/dist/openapi-react-query.d.mts.map +0 -1
  211. package/dist/openapi-react-query.mjs +0 -4
  212. package/dist/reconcile-CFs8C_1a.mjs +0 -37
  213. package/dist/reconcile-CFs8C_1a.mjs.map +0 -1
  214. package/dist/reconcile-D0pimNiy.cjs +0 -37
  215. package/dist/reconcile-D0pimNiy.cjs.map +0 -1
  216. package/dist/setup-Bc73t0ve.mjs +0 -443
  217. package/dist/setup-Bc73t0ve.mjs.map +0 -1
  218. package/dist/setup-C48C9hto.cjs +0 -473
  219. package/dist/setup-C48C9hto.cjs.map +0 -1
  220. package/dist/setup-DCuudnCl.mjs +0 -11
  221. package/dist/setup-fG_ivuxO.cjs +0 -11
  222. package/dist/storage-BJmzYxt8.cjs.map +0 -1
  223. package/dist/storage-BM9hGpgv.cjs +0 -7
  224. package/dist/storage-Bi24WfoW.mjs.map +0 -1
  225. package/dist/storage-CYlGwWTj.mjs +0 -3
  226. package/dist/sync-CmEuNZsB.mjs +0 -76
  227. package/dist/sync-CmEuNZsB.mjs.map +0 -1
  228. package/dist/sync-D306yOWu.cjs +0 -4
  229. package/dist/sync-SizaChmC.cjs +0 -93
  230. package/dist/sync-SizaChmC.cjs.map +0 -1
  231. package/dist/sync-hOqAWHR6.mjs +0 -3
  232. package/dist/types-C-arnQ1r.d.mts +0 -2184
  233. package/dist/types-C-arnQ1r.d.mts.map +0 -1
  234. package/dist/types-abJQuk7m.d.cts +0 -2184
  235. package/dist/types-abJQuk7m.d.cts.map +0 -1
  236. package/dist/workspace-7FqprxuJ.mjs +0 -4323
  237. package/dist/workspace-7FqprxuJ.mjs.map +0 -1
  238. package/dist/workspace-BO_KWohI.cjs +0 -9
  239. package/dist/workspace-DK4WWJIn.mjs +0 -8
  240. package/dist/workspace-XvqO9jIv.cjs +0 -4472
  241. package/dist/workspace-XvqO9jIv.cjs.map +0 -1
@@ -1,13 +1,12 @@
1
- const require_chunk = require('./chunk-CUT6urMc.cjs');
2
- const require_discover = require('./discover-DTmFeloL.cjs');
3
- const require_config = require('./config-BholeD-0.cjs');
4
- const node_path = require_chunk.__toESM(require("node:path"));
5
- const node_fs_promises = require_chunk.__toESM(require("node:fs/promises"));
6
- const node_child_process = require_chunk.__toESM(require("node:child_process"));
7
- const __geekmidas_constructs_endpoints = require_chunk.__toESM(require("@geekmidas/constructs/endpoints"));
8
- const node_url = require_chunk.__toESM(require("node:url"));
9
- const __geekmidas_schema_conversion = require_chunk.__toESM(require("@geekmidas/schema/conversion"));
10
-
1
+ const require_discover = require("./discover-BERGFg8v.cjs");
2
+ const require_config = require("./config-DSXI480r.cjs");
3
+ let node_fs_promises = require("node:fs/promises");
4
+ let node_path = require("node:path");
5
+ let node_child_process = require("node:child_process");
6
+ let _geekmidas_manifest = require("@geekmidas/manifest");
7
+ let _geekmidas_constructs_endpoints = require("@geekmidas/constructs/endpoints");
8
+ let node_url = require("node:url");
9
+ let _geekmidas_schema_conversion = require("@geekmidas/schema/conversion");
11
10
  //#region src/build/endpoint-analyzer.ts
12
11
  /**
13
12
  * Analyze an endpoint to extract its features
@@ -84,7 +83,6 @@ function summarizeAnalysis(analyses) {
84
83
  byFeature
85
84
  };
86
85
  }
87
-
88
86
  //#endregion
89
87
  //#region src/build/handler-templates.ts
90
88
  /**
@@ -106,8 +104,7 @@ function generateMinimalHandler(analysis) {
106
104
  const { exportName, features } = analysis;
107
105
  const method = analysis.method.toLowerCase();
108
106
  const validators = generateValidators(exportName, features);
109
- const hasValidators = validators.length > 0;
110
- if (!hasValidators && !features.hasOutputValidation) return `
107
+ if (!(validators.length > 0) && !features.hasOutputValidation) return `
111
108
  // Minimal handler: ${analysis.route} (${analysis.method})
112
109
  app.${method}('${analysis.route}', async (c) => {
113
110
  const result = await ${exportName}.handler(
@@ -255,10 +252,10 @@ function generateValidatorsFile(analyses) {
255
252
  const needsQuery = analyses.some((a) => a.features.hasQueryValidation);
256
253
  const needsParams = analyses.some((a) => a.features.hasParamValidation);
257
254
  if (!needsBody && !needsQuery && !needsParams) return `// No validators needed for this build\nexport {};\n`;
258
- const exports$1 = [];
255
+ const exports = [];
259
256
  const factories = [];
260
257
  if (needsBody) {
261
- exports$1.push("validateBody");
258
+ exports.push("validateBody");
262
259
  factories.push(`
263
260
  export const validateBody = (endpoint: any) =>
264
261
  validator('json', async (value, c) => {
@@ -269,7 +266,7 @@ export const validateBody = (endpoint: any) =>
269
266
  });`);
270
267
  }
271
268
  if (needsQuery) {
272
- exports$1.push("validateQuery");
269
+ exports.push("validateQuery");
273
270
  factories.push(`
274
271
  export const validateQuery = (endpoint: any) =>
275
272
  validator('query', async (_, c) => {
@@ -281,7 +278,7 @@ export const validateQuery = (endpoint: any) =>
281
278
  });`);
282
279
  }
283
280
  if (needsParams) {
284
- exports$1.push("validateParams");
281
+ exports.push("validateParams");
285
282
  factories.push(`
286
283
  export const validateParams = (endpoint: any) =>
287
284
  validator('param', async (params, c) => {
@@ -305,8 +302,7 @@ ${factories.join("\n")}
305
302
  */
306
303
  function generateMinimalEndpointFile(analysis, endpointImport) {
307
304
  const { exportName, features } = analysis;
308
- const needsValidators = features.hasBodyValidation || features.hasQueryValidation || features.hasParamValidation;
309
- const validatorImport = needsValidators ? generateValidatorImportsForEndpoint(analysis) : "";
305
+ const validatorImport = features.hasBodyValidation || features.hasQueryValidation || features.hasParamValidation ? generateValidatorImportsForEndpoint(analysis) : "";
310
306
  const handler = generateMinimalHandler(analysis);
311
307
  return `/**
312
308
  * Minimal endpoint: ${analysis.route} (${analysis.method})
@@ -331,8 +327,7 @@ ${handler}
331
327
  */
332
328
  function generateStandardEndpointFile(analysis, endpointImport) {
333
329
  const { exportName, features } = analysis;
334
- const needsValidators = features.hasBodyValidation || features.hasQueryValidation || features.hasParamValidation;
335
- const validatorImport = needsValidators ? generateValidatorImportsForEndpoint(analysis) : "";
330
+ const validatorImport = features.hasBodyValidation || features.hasQueryValidation || features.hasParamValidation ? generateValidatorImportsForEndpoint(analysis) : "";
336
331
  const eventsImport = features.hasEvents ? `import { publishConstructEvents } from '@geekmidas/constructs/endpoints';` : "";
337
332
  const handler = generateStandardHandler(analysis);
338
333
  return `/**
@@ -424,7 +419,7 @@ export function setupFullEndpoints(
424
419
  }
425
420
  const imports = tierEndpoints.map((a) => `import { setup${capitalize(a.exportName)} } from './${a.exportName}.js';`).join("\n");
426
421
  if (tier === "minimal") {
427
- const calls$1 = tierEndpoints.map((a) => ` setup${capitalize(a.exportName)}(app, logger);`).join("\n");
422
+ const calls = tierEndpoints.map((a) => ` setup${capitalize(a.exportName)}(app, logger);`).join("\n");
428
423
  return `/**
429
424
  * Minimal-tier endpoint index (${tierEndpoints.length} endpoints)
430
425
  * Near-raw-Hono performance
@@ -437,12 +432,12 @@ export function setupMinimalEndpoints(
437
432
  app: Hono,
438
433
  logger: Logger,
439
434
  ): void {
440
- ${calls$1}
435
+ ${calls}
441
436
  }
442
437
  `;
443
438
  }
444
439
  if (tier === "standard") {
445
- const calls$1 = tierEndpoints.map((a) => ` setup${capitalize(a.exportName)}(app, serviceDiscovery, logger);`).join("\n");
440
+ const calls = tierEndpoints.map((a) => ` setup${capitalize(a.exportName)}(app, serviceDiscovery, logger);`).join("\n");
446
441
  return `/**
447
442
  * Standard-tier endpoint index (${tierEndpoints.length} endpoints)
448
443
  * Auth and/or services enabled
@@ -457,7 +452,7 @@ export function setupStandardEndpoints(
457
452
  serviceDiscovery: ServiceDiscovery<any, any>,
458
453
  logger: Logger,
459
454
  ): void {
460
- ${calls$1}
455
+ ${calls}
461
456
  }
462
457
  `;
463
458
  }
@@ -527,9 +522,7 @@ function generateEndpointFilesNested(analyses, endpointImports) {
527
522
  case "standard":
528
523
  files[fileName] = generateStandardEndpointFile(analysis, endpointImport);
529
524
  break;
530
- case "full":
531
- files[fileName] = generateFullEndpointFile(analysis, endpointImport);
532
- break;
525
+ case "full": files[fileName] = generateFullEndpointFile(analysis, endpointImport);
533
526
  }
534
527
  }
535
528
  return files;
@@ -586,7 +579,6 @@ export async function setupEndpoints(
586
579
  }
587
580
  `;
588
581
  }
589
-
590
582
  //#endregion
591
583
  //#region src/generators/EndpointGenerator.ts
592
584
  /**
@@ -603,24 +595,21 @@ export async function setupEndpoints(
603
595
  *
604
596
  * Falls back to the configured paths for an app that declares no surface.
605
597
  */
606
- function runtimeFor(context, fromDir) {
607
- const module$1 = context.surface?.module;
608
- if (module$1) {
609
- const specifier = importSpecifier(fromDir, module$1.specifier);
598
+ function runtimeFor(context, fromDir, owner) {
599
+ const module = owner ? context.owners?.[owner] ?? context.surface?.module : context.surface?.module;
600
+ if (module) {
601
+ const specifier = importSpecifier(fromDir, module.specifier);
610
602
  return {
611
- imports: `import { ${module$1.exportName} as __surface } from '${specifier}';`,
603
+ imports: `import { ${module.exportName} as __surface } from '${specifier}';`,
612
604
  bindings: [
613
- "// What this surface was declared with. Objects, not module paths:",
614
- "// the entry imports the surface, so there is nothing to print.",
605
+ "// What this construct was declared with. Objects, not module paths:",
606
+ "// the entry imports the owner, so there is nothing to print.",
615
607
  "const envParser = __surface.envParser;",
616
608
  "const logger = __surface.logger;"
617
609
  ].join("\n")
618
610
  };
619
611
  }
620
- return {
621
- imports: [`import ${context.envParserImportPattern} from '${importSpecifier(fromDir, context.envParserPath)}';`, `import ${context.loggerImportPattern} from '${importSpecifier(fromDir, context.loggerPath)}';`].join("\n"),
622
- bindings: ""
623
- };
612
+ 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\`.`);
624
613
  }
625
614
  /** A relative specifier ESM will accept: always prefixed, never bare. */
626
615
  function importSpecifier(fromDir, target) {
@@ -679,7 +668,7 @@ function corsFor(surface) {
679
668
  }
680
669
  var EndpointGenerator = class extends require_discover.ConstructGenerator {
681
670
  isConstruct(value) {
682
- return __geekmidas_constructs_endpoints.Endpoint.isEndpoint(value);
671
+ return _geekmidas_constructs_endpoints.Endpoint.isEndpoint(value);
683
672
  }
684
673
  async build(context, constructs, outputDir, options) {
685
674
  const provider = options?.provider || "aws-apigatewayv2";
@@ -735,8 +724,7 @@ var EndpointGenerator = class extends require_discover.ConstructGenerator {
735
724
  async generateHandlerFile(outputDir, sourceFile, exportName, provider, _endpoint, context) {
736
725
  const handlerFileName = `${exportName}.ts`;
737
726
  const handlerPath = (0, node_path.join)(outputDir, handlerFileName);
738
- const relativePath = (0, node_path.relative)((0, node_path.dirname)(handlerPath), sourceFile);
739
- const importPath = relativePath.replace(/\.ts$/, ".js");
727
+ const importPath = (0, node_path.relative)((0, node_path.dirname)(handlerPath), sourceFile).replace(/\.ts$/, ".js");
740
728
  let content;
741
729
  switch (provider) {
742
730
  case "aws-apigatewayv1":
@@ -754,16 +742,14 @@ var EndpointGenerator = class extends require_discover.ConstructGenerator {
754
742
  return handlerPath;
755
743
  }
756
744
  async generateEndpointsFile(outputDir, endpoints, context) {
757
- const endpointsFileName = "endpoints.ts";
758
- const endpointsPath = (0, node_path.join)(outputDir, endpointsFileName);
745
+ const endpointsPath = (0, node_path.join)(outputDir, "endpoints.ts");
759
746
  const importsByFile = /* @__PURE__ */ new Map();
760
747
  for (const { path, key } of endpoints) {
761
- const relativePath = (0, node_path.relative)((0, node_path.dirname)(endpointsPath), path.relative);
762
- const importPath = relativePath.replace(/\.ts$/, ".js");
748
+ const importPath = (0, node_path.relative)((0, node_path.dirname)(endpointsPath), path.relative).replace(/\.ts$/, ".js");
763
749
  if (!importsByFile.has(importPath)) importsByFile.set(importPath, []);
764
750
  importsByFile.get(importPath)?.push(key);
765
751
  }
766
- const endpointImports = Array.from(importsByFile.entries()).map(([importPath, exports$1]) => `import { ${exports$1.join(", ")} } from '${importPath}';`).join("\n");
752
+ const endpointImports = Array.from(importsByFile.entries()).map(([importPath, exports]) => `import { ${exports.join(", ")} } from '${importPath}';`).join("\n");
767
753
  const allExportNames = endpoints.map(({ key }) => key);
768
754
  if (context.production?.enabled && context.production.optimizedHandlers) return this.generateOptimizedEndpointsFile(endpointsPath, endpoints, endpointImports, allExportNames);
769
755
  const content = `import type { EnvironmentParser } from '@geekmidas/envkit';
@@ -825,11 +811,9 @@ export async function setupEndpoints(
825
811
  const analyses = endpoints.map(({ key, construct }) => analyzeEndpoint(construct, key));
826
812
  const endpointImports = endpoints.map(({ key, path }) => {
827
813
  const tierDir = (0, node_path.join)(endpointsDir, "standard");
828
- const relativePath = (0, node_path.relative)(tierDir, path.relative);
829
- const importPath = relativePath.replace(/\.ts$/, ".js");
830
814
  return {
831
815
  exportName: key,
832
- importPath
816
+ importPath: (0, node_path.relative)(tierDir, path.relative).replace(/\.ts$/, ".js")
833
817
  };
834
818
  });
835
819
  const summary = summarizeAnalysis(analyses);
@@ -851,8 +835,7 @@ export async function setupEndpoints(
851
835
  }
852
836
  async generateAppFile(outputDir, context) {
853
837
  if (context.production?.enabled) return this.generateProductionAppFile(outputDir, context);
854
- const appFileName = "app.ts";
855
- const appPath = (0, node_path.join)(outputDir, appFileName);
838
+ const appPath = (0, node_path.join)(outputDir, "app.ts");
856
839
  const runtime = runtimeFor(context, (0, node_path.dirname)(appPath));
857
840
  const telescopeEnabled = context.telescope?.enabled;
858
841
  const telescopeWebSocketEnabled = context.telescope?.websocket;
@@ -862,32 +845,35 @@ export async function setupEndpoints(
862
845
  const studioFromDatabase = !usesExternalStudio && !!context.studio?.database;
863
846
  const telescopeFromSurface = !!context.surface?.module && !usesExternalTelescope;
864
847
  let telescopeImports = "";
865
- if (telescopeEnabled) if (telescopeFromSurface) telescopeImports = "import { createMiddleware, createUI } from '@geekmidas/telescope/hono';";
866
- else if (usesExternalTelescope) {
867
- const relativeTelescopePath = (0, node_path.relative)((0, node_path.dirname)(appPath), context.telescope?.telescopePath);
868
- telescopeImports = `import ${context.telescope?.telescopeImportPattern} from '${relativeTelescopePath}';
848
+ if (telescopeEnabled) {
849
+ if (telescopeFromSurface) telescopeImports = "import { createMiddleware, createUI } from '@geekmidas/telescope/hono';";
850
+ else if (usesExternalTelescope) {
851
+ const relativeTelescopePath = (0, node_path.relative)((0, node_path.dirname)(appPath), context.telescope?.telescopePath);
852
+ telescopeImports = `import ${context.telescope?.telescopeImportPattern} from '${relativeTelescopePath}';
869
853
  import { createMiddleware, createUI } from '@geekmidas/telescope/hono';`;
870
- } else telescopeImports = `import { Telescope, InMemoryStorage } from '@geekmidas/telescope';
854
+ } else telescopeImports = `import { Telescope, InMemoryStorage } from '@geekmidas/telescope';
871
855
  import { createMiddleware, createUI } from '@geekmidas/telescope/hono';`;
856
+ }
872
857
  let studioImports = "";
873
- if (studioEnabled) if (usesExternalStudio) {
874
- const relativeStudioPath = (0, node_path.relative)((0, node_path.dirname)(appPath), context.studio?.studioPath);
875
- studioImports = `import ${context.studio?.studioImportPattern} from '${relativeStudioPath}';
858
+ if (studioEnabled) {
859
+ if (usesExternalStudio) {
860
+ const relativeStudioPath = (0, node_path.relative)((0, node_path.dirname)(appPath), context.studio?.studioPath);
861
+ studioImports = `import ${context.studio?.studioImportPattern} from '${relativeStudioPath}';
876
862
  import { createStudioApp } from '@geekmidas/studio/server/hono';`;
877
- } else if (studioFromDatabase) {
878
- const dbSpecifier = importSpecifier((0, node_path.dirname)(appPath), context.studio.database.specifier);
879
- studioImports = `import { snifferContext } from '@geekmidas/constructs';
863
+ } else if (studioFromDatabase) {
864
+ const dbSpecifier = importSpecifier((0, node_path.dirname)(appPath), context.studio.database.specifier);
865
+ studioImports = `import { snifferContext } from '@geekmidas/constructs';
880
866
  import { Direction, InMemoryMonitoringStorage, Studio } from '@geekmidas/studio';
881
867
  import { ${context.studio.database.exportName} as __studioDb } from '${dbSpecifier}';
882
868
  import { createStudioApp } from '@geekmidas/studio/server/hono';`;
883
- } else studioImports = "";
869
+ } else studioImports = "";
870
+ }
884
871
  const cors = corsFor(context.surface);
885
872
  let hooksImports = "";
886
873
  let beforeSetupCall = "";
887
874
  let afterSetupCall = "";
888
875
  if (context.hooks?.serverHooksPath) {
889
- const relativeHooksPath = (0, node_path.relative)((0, node_path.dirname)(appPath), context.hooks.serverHooksPath);
890
- hooksImports = `import * as serverHooks from '${relativeHooksPath}';`;
876
+ hooksImports = `import * as serverHooks from '${(0, node_path.relative)((0, node_path.dirname)(appPath), context.hooks.serverHooksPath)}';`;
891
877
  beforeSetupCall = `
892
878
  // Call beforeSetup hook if defined
893
879
  if (typeof serverHooks.beforeSetup === 'function') {
@@ -933,7 +919,8 @@ import { createStudioApp } from '@geekmidas/studio/server/hono';`;
933
919
  }
934
920
  ` : "";
935
921
  let telescopeSetup = "";
936
- if (telescopeEnabled) if (telescopeFromSurface || usesExternalTelescope) telescopeSetup = `
922
+ if (telescopeEnabled) {
923
+ if (telescopeFromSurface || usesExternalTelescope) telescopeSetup = `
937
924
  ${telescopeWebSocketSetupCode}
938
925
  // Add telescope middleware (before endpoints to capture all requests)
939
926
  honoApp.use('*', createMiddleware(telescope));
@@ -942,7 +929,7 @@ ${telescopeWebSocketSetupCode}
942
929
  const telescopeUI = createUI(telescope);
943
930
  honoApp.route('${context.telescope?.path}', telescopeUI);
944
931
  `;
945
- else telescopeSetup = `
932
+ else telescopeSetup = `
946
933
  // Setup Telescope for debugging/monitoring
947
934
  const telescopeStorage = new InMemoryStorage({ maxEntries: ${context.telescope?.maxEntries} });
948
935
  const telescope = new Telescope({
@@ -960,6 +947,7 @@ ${telescopeWebSocketSetupCode}
960
947
  const telescopeUI = createUI(telescope);
961
948
  honoApp.route('${context.telescope?.path}', telescopeUI);
962
949
  `;
950
+ }
963
951
  let studioSetup = "";
964
952
  if (studioEnabled && studioFromDatabase) studioSetup = `
965
953
  // Studio, built from the declared database. The client comes from the
@@ -993,6 +981,7 @@ import type { Hono as HonoType } from 'hono';
993
981
  import { setupEndpoints } from './endpoints.js';
994
982
  import { setupSubscribers } from './subscribers.js';
995
983
  import { setupQueues } from './queues.js';
984
+ import { setupCrons } from './crons.js';
996
985
  ${runtime.imports}
997
986
  ${telescopeImports}
998
987
  ${studioImports}
@@ -1080,6 +1069,12 @@ ${afterSetupCall}
1080
1069
  logger.error({ error }, 'Failed to start queue workers');
1081
1070
  });
1082
1071
 
1072
+ // Schedule this app's crons. Caught like the others: a scheduler that
1073
+ // cannot start is not a reason for the HTTP server not to.
1074
+ await setupCrons(envParser, logger).catch((error) => {
1075
+ logger.error({ error }, 'Failed to schedule crons');
1076
+ });
1077
+
1083
1078
  logger.info({ port }, 'Starting server');
1084
1079
 
1085
1080
  // Start HTTP server using provided serve function
@@ -1148,10 +1143,8 @@ export const handler = ${exportName};
1148
1143
  * No dev tools (Telescope, Studio, WebSocket), includes health checks and graceful shutdown
1149
1144
  */
1150
1145
  async generateProductionAppFile(outputDir, context) {
1151
- const appFileName = "app.ts";
1152
- const appPath = (0, node_path.join)(outputDir, appFileName);
1153
- const relativeLoggerPath = (0, node_path.relative)((0, node_path.dirname)(appPath), context.loggerPath);
1154
- const relativeEnvParserPath = (0, node_path.relative)((0, node_path.dirname)(appPath), context.envParserPath);
1146
+ const appPath = (0, node_path.join)(outputDir, "app.ts");
1147
+ const runtime = runtimeFor(context, (0, node_path.dirname)(appPath));
1155
1148
  const production = context.production;
1156
1149
  const healthCheckPath = production.healthCheck;
1157
1150
  const enableGracefulShutdown = production.gracefulShutdown;
@@ -1162,8 +1155,7 @@ export const handler = ${exportName};
1162
1155
  let beforeSetupCall = "";
1163
1156
  let afterSetupCall = "";
1164
1157
  if (context.hooks?.serverHooksPath) {
1165
- const relativeHooksPath = (0, node_path.relative)((0, node_path.dirname)(appPath), context.hooks.serverHooksPath);
1166
- hooksImports = `import * as serverHooks from '${relativeHooksPath}';`;
1158
+ hooksImports = `import * as serverHooks from '${(0, node_path.relative)((0, node_path.dirname)(appPath), context.hooks.serverHooksPath)}';`;
1167
1159
  beforeSetupCall = `
1168
1160
  // Call beforeSetup hook if defined
1169
1161
  if (typeof serverHooks.beforeSetup === 'function') {
@@ -1187,9 +1179,16 @@ export const handler = ${exportName};
1187
1179
  await setupQueues(envParser, logger).catch((error) => {
1188
1180
  logger.error({ error }, 'Failed to start queue workers');
1189
1181
  });
1182
+
1183
+ // Schedule this app's crons. Caught like the others: a scheduler that
1184
+ // cannot start is not a reason for the HTTP server not to.
1185
+ await setupCrons(envParser, logger).catch((error) => {
1186
+ logger.error({ error }, 'Failed to schedule crons');
1187
+ });
1190
1188
  ` : "";
1191
1189
  const subscriberImport = includeSubscribers ? `import { setupSubscribers } from './subscribers.js';
1192
- import { setupQueues } from './queues.js';` : "";
1190
+ import { setupQueues } from './queues.js';
1191
+ import { setupCrons } from './crons.js';` : "";
1193
1192
  const gracefulShutdownCode = enableGracefulShutdown ? `
1194
1193
  // Graceful shutdown handling
1195
1194
  let isShuttingDown = false;
@@ -1205,7 +1204,6 @@ import { setupQueues } from './queues.js';` : "";
1205
1204
  process.on('SIGTERM', shutdown);
1206
1205
  process.on('SIGINT', shutdown);
1207
1206
  ` : "";
1208
- const endpointsImportPath = production.optimizedHandlers ? "./endpoints/index.js" : "./endpoints.js";
1209
1207
  const content = `/**
1210
1208
  * Generated production server application
1211
1209
  *
@@ -1217,10 +1215,10 @@ import { setupQueues } from './queues.js';` : "";
1217
1215
  */
1218
1216
  import { Hono } from 'hono';
1219
1217
  import type { Hono as HonoType } from 'hono';
1220
- import { setupEndpoints } from '${endpointsImportPath}';
1218
+ import { setupEndpoints } from '${production.optimizedHandlers ? "./endpoints/index.js" : "./endpoints.js"}';
1221
1219
  ${subscriberImport}
1222
- import ${context.envParserImportPattern} from '${relativeEnvParserPath}';
1223
- import ${context.loggerImportPattern} from '${relativeLoggerPath}';
1220
+ ${runtime.imports}
1221
+ ${runtime.bindings}
1224
1222
  ${hooksImports}
1225
1223
  ${cors.imports}
1226
1224
  ${context.storageDrivers?.imports ?? ""}
@@ -1284,7 +1282,7 @@ export default createApp;
1284
1282
  */
1285
1283
  async generateProductionServerEntry(outputDir) {
1286
1284
  const serverPath = (0, node_path.join)(outputDir, "server.ts");
1287
- const content = `#!/usr/bin/env node
1285
+ await (0, node_fs_promises.writeFile)(serverPath, `#!/usr/bin/env node
1288
1286
  /**
1289
1287
  * Production server entry point
1290
1288
  * Generated by 'gkm build --provider server --production'
@@ -1300,11 +1298,9 @@ await start({
1300
1298
  port,
1301
1299
  serve: (app, port) => { serve({ fetch: app.fetch, port }); },
1302
1300
  });
1303
- `;
1304
- await (0, node_fs_promises.writeFile)(serverPath, content);
1301
+ `);
1305
1302
  }
1306
1303
  };
1307
-
1308
1304
  //#endregion
1309
1305
  //#region src/generators/OpenApiTsGenerator.ts
1310
1306
  /**
@@ -1455,11 +1451,11 @@ var OpenApiTsGenerator = class {
1455
1451
  }
1456
1452
  }
1457
1453
  }
1458
- const registrySchemas = await (0, __geekmidas_schema_conversion.getRegisteredZodJsonSchemas)();
1454
+ const registrySchemas = await (0, _geekmidas_schema_conversion.getRegisteredZodJsonSchemas)();
1459
1455
  for (const [rawName, rawSchema] of Object.entries(registrySchemas)) {
1460
1456
  const defName = this.pascalCase(rawName);
1461
1457
  if (collectedDefs.has(defName) || generatedNames.has(defName)) continue;
1462
- const { id: _id, $defs: _defs,...rest } = rawSchema;
1458
+ const { id: _id, $defs: _defs, ...rest } = rawSchema;
1463
1459
  collectedDefs.set(defName, rest);
1464
1460
  }
1465
1461
  for (const [defName, defSchema] of collectedDefs) if (!generatedNames.has(defName)) {
@@ -1475,7 +1471,7 @@ var OpenApiTsGenerator = class {
1475
1471
  */
1476
1472
  async getSchemaName(schema, defaultName) {
1477
1473
  try {
1478
- const metadata = await (0, __geekmidas_schema_conversion.getSchemaMetadata)(schema);
1474
+ const metadata = await (0, _geekmidas_schema_conversion.getSchemaMetadata)(schema);
1479
1475
  if (metadata?.id) return this.pascalCase(metadata.id);
1480
1476
  } catch {}
1481
1477
  return defaultName;
@@ -1495,27 +1491,29 @@ var OpenApiTsGenerator = class {
1495
1491
  async schemaToInterfaceWithDefs(schema, name, collectedDefs) {
1496
1492
  try {
1497
1493
  const vendor = schema["~standard"]?.vendor;
1498
- if (!vendor || !(vendor in __geekmidas_schema_conversion.StandardSchemaJsonSchema)) return null;
1499
- const toJsonSchema = __geekmidas_schema_conversion.StandardSchemaJsonSchema[vendor];
1494
+ if (!vendor || !(vendor in _geekmidas_schema_conversion.StandardSchemaJsonSchema)) return unknownType(name);
1495
+ const toJsonSchema = _geekmidas_schema_conversion.StandardSchemaJsonSchema[vendor];
1500
1496
  const jsonSchema = await toJsonSchema(schema);
1501
- if (!jsonSchema) return null;
1497
+ if (!jsonSchema) return unknownType(name);
1502
1498
  if (jsonSchema.$defs && typeof jsonSchema.$defs === "object") {
1503
1499
  for (const [defName, defSchema] of Object.entries(jsonSchema.$defs)) if (!collectedDefs.has(defName)) {
1504
- const { id,...schemaWithoutId } = defSchema;
1500
+ const { id, ...schemaWithoutId } = defSchema;
1505
1501
  collectedDefs.set(defName, schemaWithoutId);
1506
1502
  }
1507
1503
  }
1508
- const { $defs,...schemaWithoutDefs } = jsonSchema;
1504
+ const { $defs, ...schemaWithoutDefs } = jsonSchema;
1505
+ const ref = schemaWithoutDefs.$ref;
1506
+ if (ref && Object.keys(schemaWithoutDefs).every((k) => k === "$ref" || k === "$schema")) {
1507
+ const target = ref.split("/").pop();
1508
+ return target === name ? null : `export type ${name} = ${target};`;
1509
+ }
1509
1510
  return this.jsonSchemaToInterface(schemaWithoutDefs, name);
1510
1511
  } catch {
1511
- return null;
1512
+ return unknownType(name);
1512
1513
  }
1513
1514
  }
1514
1515
  jsonSchemaToInterface(schema, name) {
1515
- if (schema.type !== "object" || !schema.properties) {
1516
- const typeStr = this.jsonSchemaTypeToTs(schema);
1517
- return `export type ${name} = ${typeStr};`;
1518
- }
1516
+ if (schema.type !== "object" || !schema.properties) return `export type ${name} = ${this.jsonSchemaTypeToTs(schema)};`;
1519
1517
  const props = [];
1520
1518
  const required = new Set(schema.required || []);
1521
1519
  for (const [propName, propSchema] of Object.entries(schema.properties)) {
@@ -1528,13 +1526,15 @@ var OpenApiTsGenerator = class {
1528
1526
  }
1529
1527
  jsonSchemaTypeToTs(schema) {
1530
1528
  if (!schema) return "unknown";
1531
- if (schema.$ref) {
1532
- const refName = schema.$ref.split("/").pop() || "unknown";
1533
- return refName;
1534
- }
1529
+ if (schema.$ref) return schema.$ref.split("/").pop() || "unknown";
1530
+ if (schema.const !== void 0) return typeof schema.const === "string" ? `'${schema.const}'` : String(schema.const);
1535
1531
  if (schema.anyOf) return schema.anyOf.map((s) => this.jsonSchemaTypeToTs(s)).join(" | ");
1536
1532
  if (schema.oneOf) return schema.oneOf.map((s) => this.jsonSchemaTypeToTs(s)).join(" | ");
1537
1533
  if (schema.allOf) return schema.allOf.map((s) => this.jsonSchemaTypeToTs(s)).join(" & ");
1534
+ if (Array.isArray(schema.type)) return schema.type.map((type) => this.jsonSchemaTypeToTs({
1535
+ ...schema,
1536
+ type
1537
+ })).join(" | ");
1538
1538
  switch (schema.type) {
1539
1539
  case "string":
1540
1540
  if (schema.enum) return schema.enum.map((e) => `'${e}'`).join(" | ");
@@ -1558,10 +1558,7 @@ var OpenApiTsGenerator = class {
1558
1558
  }
1559
1559
  return `{ ${props.join("; ")} }`;
1560
1560
  }
1561
- if (schema.additionalProperties) {
1562
- const valueType = this.jsonSchemaTypeToTs(schema.additionalProperties);
1563
- return `Record<string, ${valueType}>`;
1564
- }
1561
+ if (schema.additionalProperties) return `Record<string, ${this.jsonSchemaTypeToTs(schema.additionalProperties)}>`;
1565
1562
  return "Record<string, unknown>";
1566
1563
  default: return "unknown";
1567
1564
  }
@@ -1582,10 +1579,7 @@ var OpenApiTsGenerator = class {
1582
1579
  }
1583
1580
  const firstWithParams = infos.find((i) => i.input?.params);
1584
1581
  let paramsEntry = "";
1585
- if (firstWithParams?.input?.params) {
1586
- const paramsName = await this.getSchemaName(firstWithParams.input.params, `${this.getSchemaBaseName(firstWithParams)}Params`);
1587
- paramsEntry = `\n parameters: {\n path: ${paramsName};\n };`;
1588
- }
1582
+ if (firstWithParams?.input?.params) paramsEntry = `\n parameters: {\n path: ${await this.getSchemaName(firstWithParams.input.params, `${this.getSchemaBaseName(firstWithParams)}Params`)};\n };`;
1589
1583
  pathEntries.push(` '${route}': {${paramsEntry}\n${methodEntries.join("\n")}\n };`);
1590
1584
  }
1591
1585
  return `export interface paths {\n${pathEntries.join("\n")}\n}`;
@@ -1624,8 +1618,7 @@ var OpenApiTsGenerator = class {
1624
1618
  return acc;
1625
1619
  }, {});
1626
1620
  const schemeNames = securitySchemes.map((s) => `'${s.name}'`).join(" | ");
1627
- const hasSecuritySchemes = schemeNames.length > 0;
1628
- const createApiSection = hasSecuritySchemes ? `
1621
+ const createApiSection = schemeNames.length > 0 ? `
1629
1622
  // ============================================================
1630
1623
  // API Client Factory
1631
1624
  // ============================================================
@@ -1802,20 +1795,14 @@ ${createApiSection}
1802
1795
  `;
1803
1796
  }
1804
1797
  };
1805
-
1806
- //#endregion
1807
- //#region src/workspace/client-generator.ts
1808
1798
  /**
1809
- * Normalize routes to an array of patterns.
1810
- * Handles string, string[], and PartitionedRoutes (extracts paths).
1811
- * @internal Exported for use in dev command
1799
+ * The declaration for a schema that cannot be converted — a vendor with no
1800
+ * converter, or one that fails. The paths interface names it either way, so
1801
+ * leaving it undeclared made the generated client fail to compile.
1812
1802
  */
1813
- function normalizeRoutes(routes) {
1814
- if (!routes) return [];
1815
- if (require_discover.isPartitionedRoutes(routes)) return Array.isArray(routes.paths) ? routes.paths : [routes.paths];
1816
- return Array.isArray(routes) ? routes : [routes];
1803
+ function unknownType(name) {
1804
+ return `export type ${name} = unknown;`;
1817
1805
  }
1818
-
1819
1806
  //#endregion
1820
1807
  //#region src/openapi.ts
1821
1808
  /**
@@ -1823,6 +1810,16 @@ function normalizeRoutes(routes) {
1823
1810
  */
1824
1811
  const OPENAPI_OUTPUT_PATH = "./.gkm/openapi.ts";
1825
1812
  /**
1813
+ * Where a surface's generated client lands.
1814
+ *
1815
+ * Named from the surface, so `new RestApi('Webhooks')` writes
1816
+ * `.gkm/openapi/webhooks.ts` — the same kebab form that gives it its container
1817
+ * name and its `WEBHOOKS_URL`.
1818
+ */
1819
+ function openApiPathFor(surfaceId) {
1820
+ return `./.gkm/openapi/${(0, _geekmidas_manifest.kebabCase)(surfaceId)}.ts`;
1821
+ }
1822
+ /**
1826
1823
  * Resolve OpenAPI config from GkmConfig
1827
1824
  */
1828
1825
  function resolveOpenApiConfig(config) {
@@ -1841,33 +1838,65 @@ function resolveOpenApiConfig(config) {
1841
1838
  };
1842
1839
  }
1843
1840
  /**
1844
- * Generate OpenAPI spec from endpoints
1845
- * @returns Object with output path and endpoint count, or null if disabled
1841
+ * Load endpoints from a glob, then generate.
1842
+ *
1843
+ * For the callers that have no endpoints in hand — `gkm openapi`, and `gkm dev`
1844
+ * regenerating on reload. The glob is the app's derived one — the conventional
1845
+ * directories under it — not a `routes` field anybody wrote.
1846
1846
  */
1847
- async function generateOpenApi(config, options = {}) {
1847
+ async function generateOpenApiFrom(routes, options = {}) {
1848
+ return generateOpenApi((await new EndpointGenerator().load(routes, void 0, options.bustCache)).map(({ construct }) => construct), options);
1849
+ }
1850
+ /**
1851
+ * Generate an OpenAPI spec for each surface these endpoints name.
1852
+ *
1853
+ * Takes the endpoints, not a glob to find them with. The build has already
1854
+ * loaded every one of them to generate handlers, so globbing again was a second
1855
+ * discovery pass over the same files — and the reason this function needed a
1856
+ * `routes` to be told where to look, which is how a retired config field stayed
1857
+ * load-bearing.
1858
+ *
1859
+ * @returns What was written, or null if disabled or there were none
1860
+ */
1861
+ async function generateOpenApi(endpoints, options = {}) {
1848
1862
  const logger = options.silent ? { log: () => {} } : console;
1849
- const openApiConfig = resolveOpenApiConfig(config);
1863
+ const openApiConfig = resolveOpenApiConfig({ openapi: options.openapi });
1850
1864
  if (!openApiConfig.enabled) return null;
1851
- const endpointGenerator = new EndpointGenerator();
1852
- const loadedEndpoints = await endpointGenerator.load(config.routes, void 0, options.bustCache);
1853
- if (loadedEndpoints.length === 0) {
1865
+ if (endpoints.length === 0) {
1854
1866
  logger.log("No valid endpoints found for OpenAPI generation");
1855
1867
  return null;
1856
1868
  }
1857
- const endpoints = loadedEndpoints.map(({ construct }) => construct);
1858
- const outputPath = (0, node_path.join)(process.cwd(), OPENAPI_OUTPUT_PATH);
1859
- await (0, node_fs_promises.mkdir)((0, node_path.dirname)(outputPath), { recursive: true });
1869
+ const bySurface = /* @__PURE__ */ new Map();
1870
+ for (const endpoint of endpoints) {
1871
+ const owner = endpoint.owner ?? endpoint.surface?.id;
1872
+ if (!owner) continue;
1873
+ const existing = bySurface.get(owner);
1874
+ if (existing) existing.push(endpoint);
1875
+ else bySurface.set(owner, [endpoint]);
1876
+ }
1877
+ if (bySurface.size === 0) {
1878
+ logger.log("No endpoints named a surface, so no OpenAPI was generated");
1879
+ return null;
1880
+ }
1860
1881
  const tsGenerator = new OpenApiTsGenerator();
1861
- const tsContent = await tsGenerator.generate(endpoints, {
1862
- title: openApiConfig.title,
1863
- version: openApiConfig.version,
1864
- description: openApiConfig.description
1865
- });
1866
- await (0, node_fs_promises.writeFile)(outputPath, tsContent);
1867
- logger.log(`📄 OpenAPI client generated: ${OPENAPI_OUTPUT_PATH}`);
1882
+ const written = [];
1883
+ for (const [surfaceId, surfaceEndpoints] of bySurface) {
1884
+ const relative = openApiPathFor(surfaceId);
1885
+ const outputPath = (0, node_path.join)(process.cwd(), relative);
1886
+ await (0, node_fs_promises.mkdir)((0, node_path.dirname)(outputPath), { recursive: true });
1887
+ const tsContent = await tsGenerator.generate(surfaceEndpoints, {
1888
+ title: openApiConfig.title ?? surfaceId,
1889
+ version: openApiConfig.version,
1890
+ description: openApiConfig.description
1891
+ });
1892
+ await (0, node_fs_promises.writeFile)(outputPath, tsContent);
1893
+ written.push(relative);
1894
+ logger.log(`📄 OpenAPI client generated: ${relative} (${surfaceEndpoints.length} endpoints)`);
1895
+ }
1868
1896
  return {
1869
- outputPath,
1870
- endpointCount: loadedEndpoints.length
1897
+ outputPath: (0, node_path.join)(process.cwd(), written[0]),
1898
+ outputPaths: written.map((r) => (0, node_path.join)(process.cwd(), r)),
1899
+ endpointCount: endpoints.length
1871
1900
  };
1872
1901
  }
1873
1902
  async function openapiCommand(options = {}) {
@@ -1877,12 +1906,12 @@ async function openapiCommand(options = {}) {
1877
1906
  if (loadedConfig.type === "single") {
1878
1907
  const config = loadedConfig.raw;
1879
1908
  if (!config.openapi) config.openapi = { enabled: true };
1880
- const result = await generateOpenApi(config);
1909
+ const result = await generateOpenApiFrom(config.constructs, { openapi: config.openapi });
1881
1910
  if (result) logger.log(`Found ${result.endpointCount} endpoints`);
1882
1911
  } else {
1883
1912
  const { workspace } = loadedConfig;
1884
1913
  const workspaceRoot = workspace.root;
1885
- 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));
1914
+ const backendApps = Object.entries(workspace.apps).filter(([_, app]) => app.type === "backend" && app.openapi !== false && (typeof app.openapi !== "object" || app.openapi.enabled !== false));
1886
1915
  if (backendApps.length === 0) {
1887
1916
  logger.log("No backend apps with OpenAPI enabled found");
1888
1917
  return;
@@ -1896,8 +1925,12 @@ async function openapiCommand(options = {}) {
1896
1925
  return;
1897
1926
  }
1898
1927
  for (const [appName, app] of backendApps) {
1899
- if (app.type !== "backend" || !app.routes) continue;
1900
1928
  const appPath = (0, node_path.join)(workspaceRoot, app.path);
1929
+ if ((0, node_path.resolve)(appPath) === (0, node_path.resolve)(workspaceRoot)) {
1930
+ const result = await generateOpenApiForApp(workspaceRoot, appName, app, false);
1931
+ if (result) logger.log(`Found ${result.endpointCount} endpoints`);
1932
+ continue;
1933
+ }
1901
1934
  await runOpenApiInSubprocess(appPath, appName);
1902
1935
  }
1903
1936
  }
@@ -1910,18 +1943,13 @@ async function openapiCommand(options = {}) {
1910
1943
  * Runs in-process. The caller is responsible for ensuring `process.cwd()`
1911
1944
  * is the app's directory so tsx loads the app's tsconfig path aliases.
1912
1945
  */
1913
- async function generateOpenApiForApp(workspaceRoot, _appName, app) {
1914
- if (app.type !== "backend" || !app.routes) return null;
1946
+ async function generateOpenApiForApp(workspaceRoot, _appName, app, silent = true) {
1947
+ if (app.type !== "backend") return null;
1915
1948
  const appPath = (0, node_path.join)(workspaceRoot, app.path);
1916
- const routes = normalizeRoutes(app.routes);
1917
- const routesGlob = routes.map((r) => (0, node_path.join)(appPath, r));
1918
- const gkmConfig = {
1919
- routes: routesGlob,
1920
- envParser: app.envParser || "",
1921
- logger: app.logger || "",
1922
- openapi: app.openapi
1923
- };
1924
- return generateOpenApi(gkmConfig, { silent: true });
1949
+ return generateOpenApiFrom([(0, node_path.join)(appPath, "**/*.ts")], {
1950
+ openapi: app.openapi ?? { enabled: true },
1951
+ silent
1952
+ });
1925
1953
  }
1926
1954
  /**
1927
1955
  * Resolve the gkm bin path. Tests can override via `GKM_BIN_PATH` env var
@@ -1953,46 +1981,58 @@ async function runOpenApiInSubprocess(appCwd, appName) {
1953
1981
  child.on("error", reject);
1954
1982
  child.on("close", (code) => {
1955
1983
  if (code === 0) resolve();
1956
- else reject(new Error(`OpenAPI generation for app "${appName}" exited with code ${code}`));
1984
+ else reject(/* @__PURE__ */ new Error(`OpenAPI generation for app "${appName}" exited with code ${code}`));
1957
1985
  });
1958
1986
  });
1959
1987
  }
1960
-
1961
1988
  //#endregion
1962
- Object.defineProperty(exports, 'EndpointGenerator', {
1963
- enumerable: true,
1964
- get: function () {
1965
- return EndpointGenerator;
1966
- }
1989
+ Object.defineProperty(exports, "EndpointGenerator", {
1990
+ enumerable: true,
1991
+ get: function() {
1992
+ return EndpointGenerator;
1993
+ }
1967
1994
  });
1968
- Object.defineProperty(exports, 'OPENAPI_OUTPUT_PATH', {
1969
- enumerable: true,
1970
- get: function () {
1971
- return OPENAPI_OUTPUT_PATH;
1972
- }
1995
+ Object.defineProperty(exports, "OPENAPI_OUTPUT_PATH", {
1996
+ enumerable: true,
1997
+ get: function() {
1998
+ return OPENAPI_OUTPUT_PATH;
1999
+ }
1973
2000
  });
1974
- Object.defineProperty(exports, 'generateOpenApi', {
1975
- enumerable: true,
1976
- get: function () {
1977
- return generateOpenApi;
1978
- }
2001
+ Object.defineProperty(exports, "generateOpenApi", {
2002
+ enumerable: true,
2003
+ get: function() {
2004
+ return generateOpenApi;
2005
+ }
1979
2006
  });
1980
- Object.defineProperty(exports, 'normalizeRoutes', {
1981
- enumerable: true,
1982
- get: function () {
1983
- return normalizeRoutes;
1984
- }
2007
+ Object.defineProperty(exports, "generateOpenApiFrom", {
2008
+ enumerable: true,
2009
+ get: function() {
2010
+ return generateOpenApiFrom;
2011
+ }
1985
2012
  });
1986
- Object.defineProperty(exports, 'openapiCommand', {
1987
- enumerable: true,
1988
- get: function () {
1989
- return openapiCommand;
1990
- }
2013
+ Object.defineProperty(exports, "openApiPathFor", {
2014
+ enumerable: true,
2015
+ get: function() {
2016
+ return openApiPathFor;
2017
+ }
1991
2018
  });
1992
- Object.defineProperty(exports, 'resolveOpenApiConfig', {
1993
- enumerable: true,
1994
- get: function () {
1995
- return resolveOpenApiConfig;
1996
- }
2019
+ Object.defineProperty(exports, "openapiCommand", {
2020
+ enumerable: true,
2021
+ get: function() {
2022
+ return openapiCommand;
2023
+ }
2024
+ });
2025
+ Object.defineProperty(exports, "resolveOpenApiConfig", {
2026
+ enumerable: true,
2027
+ get: function() {
2028
+ return resolveOpenApiConfig;
2029
+ }
2030
+ });
2031
+ Object.defineProperty(exports, "runtimeFor", {
2032
+ enumerable: true,
2033
+ get: function() {
2034
+ return runtimeFor;
2035
+ }
1997
2036
  });
1998
- //# sourceMappingURL=openapi-c9bpieI5.cjs.map
2037
+
2038
+ //# sourceMappingURL=openapi-B8bu_OXN.cjs.map