@geekmidas/cli 0.5.1 → 0.6.0

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 (245) hide show
  1. package/README.md +7 -7
  2. package/dist/{CronGenerator-BPTqNYOR.d.cts → CronGenerator-DWS3CCZt.d.cts} +4 -4
  3. package/dist/{CronGenerator-YAj59JUd.d.mts → CronGenerator-DZjdkEjI.d.mts} +4 -4
  4. package/dist/{EndpointGenerator-ChAD1INz.d.cts → EndpointGenerator-Dh7kMtuL.d.mts} +4 -4
  5. package/dist/{EndpointGenerator-Cj3O1U8-.d.mts → EndpointGenerator-zBsie_7s.d.cts} +4 -4
  6. package/dist/{FunctionGenerator-429-9NER.d.cts → FunctionGenerator-BmDHo27U.d.mts} +4 -4
  7. package/dist/{FunctionGenerator-BQ4ehoID.d.mts → FunctionGenerator-DXjXBxUd.d.cts} +4 -4
  8. package/dist/{Generator-BjHK_qce.d.mts → Generator-BGY-2dgI.d.cts} +3 -3
  9. package/dist/{Generator-DxQMCQp7.d.cts → Generator-yi9DH5TN.d.mts} +3 -3
  10. package/dist/{OpenApiTsGenerator-C4mHHaku.mjs → OpenApiTsGenerator-0ZDYWro5.mjs} +1 -1
  11. package/dist/{OpenApiTsGenerator-C4mHHaku.mjs.map → OpenApiTsGenerator-0ZDYWro5.mjs.map} +1 -1
  12. package/dist/{OpenApiTsGenerator-Be-sKGTT.cjs → OpenApiTsGenerator-wLwpaq_I.cjs} +1 -1
  13. package/dist/{OpenApiTsGenerator-Be-sKGTT.cjs.map → OpenApiTsGenerator-wLwpaq_I.cjs.map} +1 -1
  14. package/dist/{SubscriberGenerator-7uX42xyG.d.mts → SubscriberGenerator-Bb-z3Kvx.d.cts} +4 -4
  15. package/dist/{SubscriberGenerator-Dtb3HS4i.d.cts → SubscriberGenerator-CwsXqCpS.d.mts} +4 -4
  16. package/dist/{api-BKIN0s0S.mjs → api-Bp5TIl1R.mjs} +29 -46
  17. package/dist/api-Bp5TIl1R.mjs.map +1 -0
  18. package/dist/{api-B3SCEHPf.cjs → api-D4W9-tdZ.cjs} +29 -46
  19. package/dist/api-D4W9-tdZ.cjs.map +1 -0
  20. package/dist/build/index.cjs +5 -3
  21. package/dist/build/index.d.cts +1 -1
  22. package/dist/build/index.d.mts +1 -1
  23. package/dist/build/index.mjs +5 -3
  24. package/dist/build/manifests.cjs +1 -1
  25. package/dist/build/manifests.d.cts +1 -1
  26. package/dist/build/manifests.d.mts +1 -1
  27. package/dist/build/manifests.mjs +1 -1
  28. package/dist/build/providerResolver.d.cts +1 -1
  29. package/dist/build/providerResolver.d.mts +1 -1
  30. package/dist/build/types.d.cts +2 -2
  31. package/dist/build/types.d.mts +2 -2
  32. package/dist/{build-B8C_qHir.mjs → build-BLriHKgm.mjs} +3 -3
  33. package/dist/{build-B8C_qHir.mjs.map → build-BLriHKgm.mjs.map} +1 -1
  34. package/dist/{build-D0Wr49bf.cjs → build-Z3yGHcy2.cjs} +3 -3
  35. package/dist/{build-D0Wr49bf.cjs.map → build-Z3yGHcy2.cjs.map} +1 -1
  36. package/dist/{config-CLEDqKO3.cjs → config-BP1IZynR.cjs} +17 -6
  37. package/dist/config-BP1IZynR.cjs.map +1 -0
  38. package/dist/{config-Ba-Gbpbc.d.cts → config-CIzRhm_D.d.mts} +2 -2
  39. package/dist/{config-DBsmMDhf.d.mts → config-CvehIYsb.d.cts} +2 -2
  40. package/dist/{config-Dp8RonV_.mjs → config-UCK12Lrr.mjs} +17 -6
  41. package/dist/config-UCK12Lrr.mjs.map +1 -0
  42. package/dist/config.d.cts +1 -1
  43. package/dist/config.d.mts +1 -1
  44. package/dist/dev/index.cjs +3 -1
  45. package/dist/dev/index.d.cts +2 -2
  46. package/dist/dev/index.d.mts +2 -2
  47. package/dist/dev/index.mjs +3 -1
  48. package/dist/{dev-B734w3L1.mjs → dev-BimlVcuk.mjs} +6 -1
  49. package/dist/dev-BimlVcuk.mjs.map +1 -0
  50. package/dist/{dev-DHqYn8k4.cjs → dev-Dcrb_ZSL.cjs} +6 -1
  51. package/dist/dev-Dcrb_ZSL.cjs.map +1 -0
  52. package/dist/{docker-5d8Yh5_X.cjs → docker-2-ipZDOJ.cjs} +1 -1
  53. package/dist/{docker-5d8Yh5_X.cjs.map → docker-2-ipZDOJ.cjs.map} +1 -1
  54. package/dist/{docker-DlUqdFle.mjs → docker-31GNwU3F.mjs} +1 -1
  55. package/dist/{docker-DlUqdFle.mjs.map → docker-31GNwU3F.mjs.map} +1 -1
  56. package/dist/{env-HfuJRlg5.d.cts → env-CQ3hXAAW.d.mts} +2 -2
  57. package/dist/{env-B-OKjgI4.cjs → env-CS0jvg7k.cjs} +1 -1
  58. package/dist/{env-B-OKjgI4.cjs.map → env-CS0jvg7k.cjs.map} +1 -1
  59. package/dist/{env-nd-iQPYM.d.mts → env-D4YFgMqo.d.cts} +2 -2
  60. package/dist/{env-tv1HlZlw.mjs → env-DEeVOvVu.mjs} +1 -1
  61. package/dist/{env-tv1HlZlw.mjs.map → env-DEeVOvVu.mjs.map} +1 -1
  62. package/dist/generators/CronGenerator.d.cts +4 -4
  63. package/dist/generators/CronGenerator.d.mts +4 -4
  64. package/dist/generators/EndpointGenerator.d.cts +4 -4
  65. package/dist/generators/EndpointGenerator.d.mts +4 -4
  66. package/dist/generators/FunctionGenerator.d.cts +4 -4
  67. package/dist/generators/FunctionGenerator.d.mts +4 -4
  68. package/dist/generators/Generator.d.cts +3 -3
  69. package/dist/generators/Generator.d.mts +3 -3
  70. package/dist/generators/OpenApiTsGenerator.cjs +1 -1
  71. package/dist/generators/OpenApiTsGenerator.mjs +1 -1
  72. package/dist/generators/SubscriberGenerator.d.cts +4 -4
  73. package/dist/generators/SubscriberGenerator.d.mts +4 -4
  74. package/dist/generators/index.d.cts +7 -7
  75. package/dist/generators/index.d.mts +7 -7
  76. package/dist/{index-C523No_B.d.mts → index-DG6xNQMH.d.cts} +25 -8
  77. package/dist/{index-DrzN4xkQ.d.cts → index-DZgrOOOW.d.mts} +25 -8
  78. package/dist/index.cjs +21 -21
  79. package/dist/index.cjs.map +1 -1
  80. package/dist/index.mjs +21 -21
  81. package/dist/index.mjs.map +1 -1
  82. package/dist/init/generators/config.cjs +1 -1
  83. package/dist/init/generators/config.d.cts +2 -2
  84. package/dist/init/generators/config.d.mts +2 -2
  85. package/dist/init/generators/config.mjs +1 -1
  86. package/dist/init/generators/docker.cjs +1 -1
  87. package/dist/init/generators/docker.d.cts +1 -1
  88. package/dist/init/generators/docker.d.mts +1 -1
  89. package/dist/init/generators/docker.mjs +1 -1
  90. package/dist/init/generators/env.cjs +1 -1
  91. package/dist/init/generators/env.d.cts +2 -2
  92. package/dist/init/generators/env.d.mts +2 -2
  93. package/dist/init/generators/env.mjs +1 -1
  94. package/dist/init/generators/index.cjs +9 -4
  95. package/dist/init/generators/index.d.cts +5 -5
  96. package/dist/init/generators/index.d.mts +5 -5
  97. package/dist/init/generators/index.mjs +9 -4
  98. package/dist/init/generators/models.cjs +1 -1
  99. package/dist/init/generators/models.d.cts +1 -1
  100. package/dist/init/generators/models.d.mts +1 -1
  101. package/dist/init/generators/models.mjs +1 -1
  102. package/dist/init/generators/monorepo.cjs +1 -1
  103. package/dist/init/generators/monorepo.d.cts +1 -1
  104. package/dist/init/generators/monorepo.d.mts +1 -1
  105. package/dist/init/generators/monorepo.mjs +1 -1
  106. package/dist/init/generators/package.cjs +6 -1
  107. package/dist/init/generators/package.d.cts +2 -2
  108. package/dist/init/generators/package.d.mts +2 -2
  109. package/dist/init/generators/package.mjs +6 -1
  110. package/dist/init/generators/source.cjs +1 -1
  111. package/dist/init/generators/source.d.cts +2 -2
  112. package/dist/init/generators/source.d.mts +2 -2
  113. package/dist/init/generators/source.mjs +1 -1
  114. package/dist/init/index.cjs +14 -14
  115. package/dist/init/index.d.cts +1 -1
  116. package/dist/init/index.d.mts +1 -1
  117. package/dist/init/index.mjs +14 -14
  118. package/dist/init/templates/api.cjs +1 -1
  119. package/dist/init/templates/api.d.cts +1 -1
  120. package/dist/init/templates/api.d.mts +1 -1
  121. package/dist/init/templates/api.mjs +1 -1
  122. package/dist/init/templates/index.cjs +8 -6
  123. package/dist/init/templates/index.d.cts +2 -2
  124. package/dist/init/templates/index.d.mts +2 -2
  125. package/dist/init/templates/index.mjs +6 -6
  126. package/dist/init/templates/minimal.cjs +1 -1
  127. package/dist/init/templates/minimal.d.cts +1 -1
  128. package/dist/init/templates/minimal.d.mts +1 -1
  129. package/dist/init/templates/minimal.mjs +1 -1
  130. package/dist/init/templates/serverless.cjs +1 -1
  131. package/dist/init/templates/serverless.d.cts +1 -1
  132. package/dist/init/templates/serverless.d.mts +1 -1
  133. package/dist/init/templates/serverless.mjs +1 -1
  134. package/dist/init/templates/worker.cjs +1 -1
  135. package/dist/init/templates/worker.d.cts +1 -1
  136. package/dist/init/templates/worker.d.mts +1 -1
  137. package/dist/init/templates/worker.mjs +1 -1
  138. package/dist/init/utils.cjs +1 -1
  139. package/dist/init/utils.mjs +1 -1
  140. package/dist/{init-CtOnZn3G.mjs → init-BMA7xi8r.mjs} +37 -21
  141. package/dist/init-BMA7xi8r.mjs.map +1 -0
  142. package/dist/{init-qLFsWR-R.cjs → init-D-7WEk-b.cjs} +37 -21
  143. package/dist/init-D-7WEk-b.cjs.map +1 -0
  144. package/dist/{manifests-DIA_2QYd.mjs → manifests-BNKG6AXf.mjs} +1 -1
  145. package/dist/{manifests-DIA_2QYd.mjs.map → manifests-BNKG6AXf.mjs.map} +1 -1
  146. package/dist/{manifests-VJ9-2JpW.cjs → manifests-D13Ej8AE.cjs} +1 -1
  147. package/dist/{manifests-VJ9-2JpW.cjs.map → manifests-D13Ej8AE.cjs.map} +1 -1
  148. package/dist/{minimal-C4GsE45s.mjs → minimal-BkyASH_C.mjs} +15 -9
  149. package/dist/minimal-BkyASH_C.mjs.map +1 -0
  150. package/dist/{minimal-Bdhhpp7v.cjs → minimal-CSFggzdH.cjs} +15 -9
  151. package/dist/minimal-CSFggzdH.cjs.map +1 -0
  152. package/dist/{models-cvNg6Oea.mjs → models-BWlDfviw.mjs} +1 -1
  153. package/dist/{models-cvNg6Oea.mjs.map → models-BWlDfviw.mjs.map} +1 -1
  154. package/dist/{models-DyNwdOcz.cjs → models-BapGSoHC.cjs} +1 -1
  155. package/dist/{models-DyNwdOcz.cjs.map → models-BapGSoHC.cjs.map} +1 -1
  156. package/dist/{monorepo-Cknwzj5C.mjs → monorepo-BBOWhkcd.mjs} +1 -1
  157. package/dist/{monorepo-Cknwzj5C.mjs.map → monorepo-BBOWhkcd.mjs.map} +1 -1
  158. package/dist/{monorepo-sEK8gW59.cjs → monorepo-CFtxHeDh.cjs} +1 -1
  159. package/dist/{monorepo-sEK8gW59.cjs.map → monorepo-CFtxHeDh.cjs.map} +1 -1
  160. package/dist/openapi-CTae4ybf.cjs +98 -0
  161. package/dist/openapi-CTae4ybf.cjs.map +1 -0
  162. package/dist/openapi-Dn9MeKg3.mjs +74 -0
  163. package/dist/openapi-Dn9MeKg3.mjs.map +1 -0
  164. package/dist/{openapi-react-query-DxHjXQvg.cjs → openapi-react-query-Cp-w8_05.cjs} +1 -1
  165. package/dist/{openapi-react-query-DxHjXQvg.cjs.map → openapi-react-query-Cp-w8_05.cjs.map} +1 -1
  166. package/dist/{openapi-react-query-o7Mp1Jd5.mjs → openapi-react-query-_-B3s8v_.mjs} +1 -1
  167. package/dist/{openapi-react-query-o7Mp1Jd5.mjs.map → openapi-react-query-_-B3s8v_.mjs.map} +1 -1
  168. package/dist/openapi-react-query.cjs +1 -1
  169. package/dist/openapi-react-query.mjs +1 -1
  170. package/dist/openapi.cjs +6 -3
  171. package/dist/openapi.d.cts +23 -3
  172. package/dist/openapi.d.mts +23 -3
  173. package/dist/openapi.mjs +3 -3
  174. package/dist/{package-C7WhWU8m.d.mts → package-6h-7QfJZ.d.cts} +2 -2
  175. package/dist/{package-DvWEMz6z.d.cts → package-BCe_KvGv.d.mts} +2 -2
  176. package/dist/{package-CIfmeuSW.mjs → package-C3If80n1.mjs} +7 -1
  177. package/dist/package-C3If80n1.mjs.map +1 -0
  178. package/dist/{package-PP-o1nvq.cjs → package-Dk8IMBOB.cjs} +6 -1
  179. package/dist/package-Dk8IMBOB.cjs.map +1 -0
  180. package/dist/{serverless-Yav3GRVz.cjs → serverless-AGOS-l3G.cjs} +15 -10
  181. package/dist/serverless-AGOS-l3G.cjs.map +1 -0
  182. package/dist/{serverless-DkHBF2vC.mjs → serverless-D5HjJByU.mjs} +15 -10
  183. package/dist/serverless-D5HjJByU.mjs.map +1 -0
  184. package/dist/{source-DT5Xhiob.cjs → source-C1cyfHcF.cjs} +1 -1
  185. package/dist/{source-DT5Xhiob.cjs.map → source-C1cyfHcF.cjs.map} +1 -1
  186. package/dist/{source-D6v2BnKT.d.mts → source-C3LiNUV9.d.mts} +2 -2
  187. package/dist/{source-DnaH_MLA.mjs → source-CkQHBpwu.mjs} +1 -1
  188. package/dist/{source-DnaH_MLA.mjs.map → source-CkQHBpwu.mjs.map} +1 -1
  189. package/dist/{source-D8fK9qRo.d.cts → source-Dtcjbokc.d.cts} +2 -2
  190. package/dist/templates-C0EMmhwb.mjs +88 -0
  191. package/dist/templates-C0EMmhwb.mjs.map +1 -0
  192. package/dist/templates-CbgQ9dw0.cjs +123 -0
  193. package/dist/templates-CbgQ9dw0.cjs.map +1 -0
  194. package/dist/{types-Cxl8-uwV.d.mts → types-Bi7VzDUZ.d.mts} +31 -2
  195. package/dist/{types-C4KITv-y.d.mts → types-D2xYkOal.d.mts} +2 -2
  196. package/dist/{types-DLFN49M3.d.cts → types-DA-r8HWZ.d.cts} +2 -2
  197. package/dist/{types-DB99_qIy.d.cts → types-KmjzMgu8.d.cts} +31 -2
  198. package/dist/types.d.cts +2 -2
  199. package/dist/types.d.mts +2 -2
  200. package/dist/{utils-C31-SWHP.mjs → utils-CKEzCxc1.mjs} +1 -1
  201. package/dist/{utils-C31-SWHP.mjs.map → utils-CKEzCxc1.mjs.map} +1 -1
  202. package/dist/{utils-BX3F4fT8.cjs → utils-DSdN2MTt.cjs} +1 -1
  203. package/dist/{utils-BX3F4fT8.cjs.map → utils-DSdN2MTt.cjs.map} +1 -1
  204. package/dist/{worker--8O5a3Hv.cjs → worker-CGhlqNH-.cjs} +15 -9
  205. package/dist/worker-CGhlqNH-.cjs.map +1 -0
  206. package/dist/{worker-Jme7uOOJ.mjs → worker-CiP420As.mjs} +15 -9
  207. package/dist/worker-CiP420As.mjs.map +1 -0
  208. package/examples/gkm.config.ts +3 -5
  209. package/package.json +4 -4
  210. package/src/__tests__/openapi.spec.ts +395 -302
  211. package/src/dev/index.ts +18 -0
  212. package/src/init/generators/config.ts +23 -5
  213. package/src/init/generators/package.ts +11 -4
  214. package/src/init/index.ts +26 -7
  215. package/src/init/templates/api.ts +38 -56
  216. package/src/init/templates/index.ts +46 -11
  217. package/src/init/templates/minimal.ts +23 -10
  218. package/src/init/templates/serverless.ts +23 -11
  219. package/src/init/templates/worker.ts +23 -10
  220. package/src/openapi.ts +83 -45
  221. package/src/types.ts +30 -0
  222. package/dist/api-B3SCEHPf.cjs.map +0 -1
  223. package/dist/api-BKIN0s0S.mjs.map +0 -1
  224. package/dist/config-CLEDqKO3.cjs.map +0 -1
  225. package/dist/config-Dp8RonV_.mjs.map +0 -1
  226. package/dist/dev-B734w3L1.mjs.map +0 -1
  227. package/dist/dev-DHqYn8k4.cjs.map +0 -1
  228. package/dist/init-CtOnZn3G.mjs.map +0 -1
  229. package/dist/init-qLFsWR-R.cjs.map +0 -1
  230. package/dist/minimal-Bdhhpp7v.cjs.map +0 -1
  231. package/dist/minimal-C4GsE45s.mjs.map +0 -1
  232. package/dist/openapi-BQWPWyNB.cjs +0 -56
  233. package/dist/openapi-BQWPWyNB.cjs.map +0 -1
  234. package/dist/openapi-DBX8cJJ8.mjs +0 -50
  235. package/dist/openapi-DBX8cJJ8.mjs.map +0 -1
  236. package/dist/package-CIfmeuSW.mjs.map +0 -1
  237. package/dist/package-PP-o1nvq.cjs.map +0 -1
  238. package/dist/serverless-DkHBF2vC.mjs.map +0 -1
  239. package/dist/serverless-Yav3GRVz.cjs.map +0 -1
  240. package/dist/templates-CBFUwpBy.mjs +0 -64
  241. package/dist/templates-CBFUwpBy.mjs.map +0 -1
  242. package/dist/templates-DM_rtYYW.cjs +0 -87
  243. package/dist/templates-DM_rtYYW.cjs.map +0 -1
  244. package/dist/worker--8O5a3Hv.cjs.map +0 -1
  245. package/dist/worker-Jme7uOOJ.mjs.map +0 -1
package/src/dev/index.ts CHANGED
@@ -15,6 +15,7 @@ import {
15
15
  FunctionGenerator,
16
16
  SubscriberGenerator,
17
17
  } from '../generators';
18
+ import { generateOpenApi, resolveOpenApiConfig } from '../openapi';
18
19
  import type {
19
20
  GkmConfig,
20
21
  LegacyProvider,
@@ -206,6 +207,12 @@ export async function devCommand(options: DevOptions): Promise<void> {
206
207
  logger.log(`🔭 Telescope enabled at ${telescope.path}`);
207
208
  }
208
209
 
210
+ // Resolve OpenAPI configuration
211
+ const openApiConfig = resolveOpenApiConfig(config);
212
+ if (openApiConfig.enabled) {
213
+ logger.log(`📄 OpenAPI output: ${openApiConfig.output}`);
214
+ }
215
+
209
216
  const buildContext: BuildContext = {
210
217
  envParserPath,
211
218
  envParserImportPattern,
@@ -222,6 +229,11 @@ export async function devCommand(options: DevOptions): Promise<void> {
222
229
  resolved.enableOpenApi,
223
230
  );
224
231
 
232
+ // Generate OpenAPI spec on startup
233
+ if (openApiConfig.enabled) {
234
+ await generateOpenApi(config);
235
+ }
236
+
225
237
  // Determine runtime (default to node)
226
238
  const runtime: Runtime = config.runtime ?? 'node';
227
239
 
@@ -307,6 +319,12 @@ export async function devCommand(options: DevOptions): Promise<void> {
307
319
  resolved.providers[0] as LegacyProvider,
308
320
  resolved.enableOpenApi,
309
321
  );
322
+
323
+ // Regenerate OpenAPI if enabled
324
+ if (openApiConfig.enabled) {
325
+ await generateOpenApi(config, { silent: true });
326
+ }
327
+
310
328
  logger.log('✅ Rebuild complete, restarting server...');
311
329
  await devServer.restart();
312
330
  } catch (error) {
@@ -11,17 +11,29 @@ export function generateConfigFiles(
11
11
  options: TemplateOptions,
12
12
  template: TemplateConfig,
13
13
  ): GeneratedFile[] {
14
- const { telescope } = options;
14
+ const { telescope, routesStructure } = options;
15
15
  const isServerless = template.name === 'serverless';
16
16
  const hasWorker = template.name === 'worker';
17
17
 
18
+ // Get routes glob pattern based on structure
19
+ const getRoutesGlob = () => {
20
+ switch (routesStructure) {
21
+ case 'centralized-endpoints':
22
+ return './src/endpoints/**/*.ts';
23
+ case 'centralized-routes':
24
+ return './src/routes/**/*.ts';
25
+ case 'domain-based':
26
+ return './src/**/routes/*.ts';
27
+ }
28
+ };
29
+
18
30
  // Build gkm.config.ts
19
- let gkmConfig = `import { defineConfig } from '@geekmidas/cli';
31
+ let gkmConfig = `import { defineConfig } from '@geekmidas/cli/config';
20
32
 
21
33
  export default defineConfig({
22
- routes: './src/endpoints/**/*.ts',
23
- envParser: './src/config/env',
24
- logger: './src/config/logger',`;
34
+ routes: '${getRoutesGlob()}',
35
+ envParser: './src/config/env#envParser',
36
+ logger: './src/config/logger#logger',`;
25
37
 
26
38
  if (isServerless || hasWorker) {
27
39
  gkmConfig += `
@@ -42,6 +54,12 @@ export default defineConfig({
42
54
  },`;
43
55
  }
44
56
 
57
+ // Always add openapi config (output path is fixed to .gkm/openapi.ts)
58
+ gkmConfig += `
59
+ openapi: {
60
+ enabled: true,
61
+ },`;
62
+
45
63
  gkmConfig += `
46
64
  });
47
65
  `;
@@ -1,7 +1,8 @@
1
- import type {
2
- GeneratedFile,
3
- TemplateConfig,
4
- TemplateOptions,
1
+ import {
2
+ type GeneratedFile,
3
+ OPENAPI_OUTPUT_PATH,
4
+ type TemplateConfig,
5
+ type TemplateOptions,
5
6
  } from '../templates/index.js';
6
7
 
7
8
  /**
@@ -67,6 +68,12 @@ export function generatePackageJson(
67
68
  version: '0.0.1',
68
69
  private: true,
69
70
  type: 'module',
71
+ exports: {
72
+ './client': {
73
+ types: OPENAPI_OUTPUT_PATH,
74
+ import: OPENAPI_OUTPUT_PATH,
75
+ },
76
+ },
70
77
  scripts,
71
78
  dependencies: sortObject(dependencies),
72
79
  devDependencies: sortObject(devDependencies),
package/src/init/index.ts CHANGED
@@ -13,7 +13,8 @@ import {
13
13
  type TemplateName,
14
14
  type TemplateOptions,
15
15
  getTemplate,
16
- routeStyleChoices,
16
+ loggerTypeChoices,
17
+ routesStructureChoices,
17
18
  templateChoices,
18
19
  } from './templates/index.js';
19
20
  import {
@@ -85,9 +86,16 @@ export async function initCommand(
85
86
  },
86
87
  {
87
88
  type: options.yes ? null : 'select',
88
- name: 'routeStyle',
89
- message: 'Route organization:',
90
- choices: routeStyleChoices,
89
+ name: 'loggerType',
90
+ message: 'Logger:',
91
+ choices: loggerTypeChoices,
92
+ initial: 0,
93
+ },
94
+ {
95
+ type: options.yes ? null : 'select',
96
+ name: 'routesStructure',
97
+ message: 'Routes structure:',
98
+ choices: routesStructureChoices,
91
99
  initial: 0,
92
100
  },
93
101
  {
@@ -137,9 +145,10 @@ export async function initCommand(
137
145
  template: options.template || answers.template || 'minimal',
138
146
  telescope: options.yes ? true : (answers.telescope ?? true),
139
147
  database: options.yes ? true : (answers.database ?? true),
140
- routeStyle: options.yes
141
- ? 'file-based'
142
- : (answers.routeStyle ?? 'file-based'),
148
+ loggerType: options.yes ? 'pino' : (answers.loggerType ?? 'pino'),
149
+ routesStructure: options.yes
150
+ ? 'centralized-endpoints'
151
+ : (answers.routesStructure ?? 'centralized-endpoints'),
143
152
  monorepo,
144
153
  apiPath: monorepo ? (options.apiPath ?? answers.apiPath ?? 'apps/api') : '',
145
154
  };
@@ -199,6 +208,16 @@ export async function initCommand(
199
208
  } catch {
200
209
  console.error('\n Warning: Failed to install dependencies.');
201
210
  }
211
+
212
+ // Format generated files with biome
213
+ try {
214
+ execSync('npx @biomejs/biome format --write --unsafe .', {
215
+ cwd: targetDir,
216
+ stdio: 'inherit',
217
+ });
218
+ } catch {
219
+ // Silently ignore format errors
220
+ }
202
221
  }
203
222
 
204
223
  // Print next steps
@@ -41,6 +41,30 @@ export const apiTemplate: TemplateConfig = {
41
41
  },
42
42
 
43
43
  files: (options: TemplateOptions): GeneratedFile[] => {
44
+ const { loggerType, routesStructure } = options;
45
+
46
+ const loggerContent = `import { createLogger } from '@geekmidas/logger/${loggerType}';
47
+
48
+ export const logger = createLogger();
49
+ `;
50
+
51
+ // Get route path based on structure
52
+ const getRoutePath = (file: string) => {
53
+ switch (routesStructure) {
54
+ case 'centralized-endpoints':
55
+ return `src/endpoints/${file}`;
56
+ case 'centralized-routes':
57
+ return `src/routes/${file}`;
58
+ case 'domain-based': {
59
+ const parts = file.split('/');
60
+ if (parts.length === 1) {
61
+ return `src/${file.replace('.ts', '')}/routes/index.ts`;
62
+ }
63
+ return `src/${parts[0]}/routes/${parts.slice(1).join('/')}`;
64
+ }
65
+ }
66
+ };
67
+
44
68
  const files: GeneratedFile[] = [
45
69
  // src/config/env.ts
46
70
  {
@@ -66,21 +90,15 @@ export const config = envParser
66
90
  `,
67
91
  },
68
92
 
69
- // src/config/logger.ts - using pino
93
+ // src/config/logger.ts
70
94
  {
71
95
  path: 'src/config/logger.ts',
72
- content: `import { PinoLogger } from '@geekmidas/logger/pino';
73
-
74
- export const logger = new PinoLogger({
75
- app: '${options.name}',
76
- level: process.env.LOG_LEVEL || 'info',
77
- });
78
- `,
96
+ content: loggerContent,
79
97
  },
80
98
 
81
- // src/endpoints/health.ts
99
+ // health endpoint
82
100
  {
83
- path: 'src/endpoints/health.ts',
101
+ path: getRoutePath('health.ts'),
84
102
  content: `import { e } from '@geekmidas/constructs/endpoints';
85
103
 
86
104
  export default e
@@ -91,46 +109,11 @@ export default e
91
109
  }));
92
110
  `,
93
111
  },
94
- ];
95
-
96
- // Add user endpoints based on route style
97
- if (options.routeStyle === 'flat') {
98
- files.push(
99
- {
100
- path: 'src/endpoints/users-list.ts',
101
- content: `import { e } from '@geekmidas/constructs/endpoints';
102
-
103
- export default e
104
- .get('/users')
105
- .handle(async () => ({
106
- users: [
107
- { id: '1', name: 'Alice' },
108
- { id: '2', name: 'Bob' },
109
- ],
110
- }));
111
- `,
112
- },
113
- {
114
- path: 'src/endpoints/users-get.ts',
115
- content: `import { e } from '@geekmidas/constructs/endpoints';
116
- import { z } from 'zod';
117
112
 
118
- export default e
119
- .get('/users/:id')
120
- .params(z.object({ id: z.string() }))
121
- .handle(async ({ params }) => ({
122
- id: params.id,
123
- name: 'Alice',
124
- email: 'alice@example.com',
125
- }));
126
- `,
127
- },
128
- );
129
- } else {
130
- files.push(
131
- {
132
- path: 'src/endpoints/users/list.ts',
133
- content: `import { e } from '@geekmidas/constructs/endpoints';
113
+ // users endpoints
114
+ {
115
+ path: getRoutePath('users/list.ts'),
116
+ content: `import { e } from '@geekmidas/constructs/endpoints';
134
117
 
135
118
  export default e
136
119
  .get('/users')
@@ -141,10 +124,10 @@ export default e
141
124
  ],
142
125
  }));
143
126
  `,
144
- },
145
- {
146
- path: 'src/endpoints/users/get.ts',
147
- content: `import { e } from '@geekmidas/constructs/endpoints';
127
+ },
128
+ {
129
+ path: getRoutePath('users/get.ts'),
130
+ content: `import { e } from '@geekmidas/constructs/endpoints';
148
131
  import { z } from 'zod';
149
132
 
150
133
  export default e
@@ -156,9 +139,8 @@ export default e
156
139
  email: 'alice@example.com',
157
140
  }));
158
141
  `,
159
- },
160
- );
161
- }
142
+ },
143
+ ];
162
144
 
163
145
  // Add database service if enabled
164
146
  if (options.database) {
@@ -4,9 +4,22 @@ import { serverlessTemplate } from './serverless.js';
4
4
  import { workerTemplate } from './worker.js';
5
5
 
6
6
  /**
7
- * Route organization style
7
+ * OpenAPI output path (fixed, not configurable)
8
8
  */
9
- export type RouteStyle = 'file-based' | 'flat';
9
+ export const OPENAPI_OUTPUT_PATH = './.gkm/openapi.ts';
10
+
11
+ /**
12
+ * Logger implementation type
13
+ */
14
+ export type LoggerType = 'pino' | 'console';
15
+
16
+ /**
17
+ * Routes structure pattern
18
+ */
19
+ export type RoutesStructure =
20
+ | 'centralized-endpoints'
21
+ | 'centralized-routes'
22
+ | 'domain-based';
10
23
 
11
24
  /**
12
25
  * Options collected from user prompts
@@ -16,7 +29,8 @@ export interface TemplateOptions {
16
29
  template: TemplateName;
17
30
  telescope: boolean;
18
31
  database: boolean;
19
- routeStyle: RouteStyle;
32
+ loggerType: LoggerType;
33
+ routesStructure: RoutesStructure;
20
34
  monorepo: boolean;
21
35
  /** Path for the API app in monorepo (e.g., 'apps/api') */
22
36
  apiPath: string;
@@ -81,18 +95,39 @@ export const templateChoices = [
81
95
  ];
82
96
 
83
97
  /**
84
- * Route style choices for prompts
98
+ * Logger type choices for prompts
99
+ */
100
+ export const loggerTypeChoices = [
101
+ {
102
+ title: 'Pino',
103
+ value: 'pino' as LoggerType,
104
+ description: 'Fast JSON logger for production (recommended)',
105
+ },
106
+ {
107
+ title: 'Console',
108
+ value: 'console' as LoggerType,
109
+ description: 'Simple console logger for development',
110
+ },
111
+ ];
112
+
113
+ /**
114
+ * Routes structure choices for prompts
85
115
  */
86
- export const routeStyleChoices = [
116
+ export const routesStructureChoices = [
117
+ {
118
+ title: 'Centralized (endpoints)',
119
+ value: 'centralized-endpoints' as RoutesStructure,
120
+ description: 'src/endpoints/**/*.ts',
121
+ },
87
122
  {
88
- title: 'File-based',
89
- value: 'file-based' as RouteStyle,
90
- description: 'Folder structure matches URL paths (users/list.ts → /users)',
123
+ title: 'Centralized (routes)',
124
+ value: 'centralized-routes' as RoutesStructure,
125
+ description: 'src/routes/**/*.ts',
91
126
  },
92
127
  {
93
- title: 'Flat',
94
- value: 'flat' as RouteStyle,
95
- description: 'All endpoints in one folder (users-list.ts → /users)',
128
+ title: 'Domain-based',
129
+ value: 'domain-based' as RoutesStructure,
130
+ description: 'src/**/routes/*.ts (e.g., src/users/routes/list.ts)',
96
131
  },
97
132
  ];
98
133
 
@@ -38,6 +38,25 @@ export const minimalTemplate: TemplateConfig = {
38
38
  },
39
39
 
40
40
  files: (options: TemplateOptions): GeneratedFile[] => {
41
+ const { loggerType, routesStructure } = options;
42
+
43
+ const loggerContent = `import { createLogger } from '@geekmidas/logger/${loggerType}';
44
+
45
+ export const logger = createLogger();
46
+ `;
47
+
48
+ // Get route path based on structure
49
+ const getRoutePath = (file: string) => {
50
+ switch (routesStructure) {
51
+ case 'centralized-endpoints':
52
+ return `src/endpoints/${file}`;
53
+ case 'centralized-routes':
54
+ return `src/routes/${file}`;
55
+ case 'domain-based':
56
+ return `src/${file.replace('.ts', '')}/routes/index.ts`;
57
+ }
58
+ };
59
+
41
60
  const files: GeneratedFile[] = [
42
61
  // src/config/env.ts
43
62
  {
@@ -55,21 +74,15 @@ export const config = envParser
55
74
  `,
56
75
  },
57
76
 
58
- // src/config/logger.ts - using pino
77
+ // src/config/logger.ts
59
78
  {
60
79
  path: 'src/config/logger.ts',
61
- content: `import { PinoLogger } from '@geekmidas/logger/pino';
62
-
63
- export const logger = new PinoLogger({
64
- app: '${options.name}',
65
- level: process.env.LOG_LEVEL || 'info',
66
- });
67
- `,
80
+ content: loggerContent,
68
81
  },
69
82
 
70
- // src/endpoints/health.ts
83
+ // health endpoint
71
84
  {
72
- path: 'src/endpoints/health.ts',
85
+ path: getRoutePath('health.ts'),
73
86
  content: `import { e } from '@geekmidas/constructs/endpoints';
74
87
 
75
88
  export default e
@@ -40,6 +40,25 @@ export const serverlessTemplate: TemplateConfig = {
40
40
  },
41
41
 
42
42
  files: (options: TemplateOptions): GeneratedFile[] => {
43
+ const { loggerType, routesStructure } = options;
44
+
45
+ const loggerContent = `import { createLogger } from '@geekmidas/logger/${loggerType}';
46
+
47
+ export const logger = createLogger();
48
+ `;
49
+
50
+ // Get route path based on structure
51
+ const getRoutePath = (file: string) => {
52
+ switch (routesStructure) {
53
+ case 'centralized-endpoints':
54
+ return `src/endpoints/${file}`;
55
+ case 'centralized-routes':
56
+ return `src/routes/${file}`;
57
+ case 'domain-based':
58
+ return `src/${file.replace('.ts', '')}/routes/index.ts`;
59
+ }
60
+ };
61
+
43
62
  const files: GeneratedFile[] = [
44
63
  // src/config/env.ts
45
64
  {
@@ -64,22 +83,15 @@ export const config = envParser
64
83
  `,
65
84
  },
66
85
 
67
- // src/config/logger.ts - using pino
86
+ // src/config/logger.ts
68
87
  {
69
88
  path: 'src/config/logger.ts',
70
- content: `import { PinoLogger } from '@geekmidas/logger/pino';
71
-
72
- export const logger = new PinoLogger({
73
- app: '${options.name}',
74
- stage: process.env.STAGE || 'dev',
75
- level: process.env.LOG_LEVEL || 'info',
76
- });
77
- `,
89
+ content: loggerContent,
78
90
  },
79
91
 
80
- // src/endpoints/health.ts
92
+ // health endpoint
81
93
  {
82
- path: 'src/endpoints/health.ts',
94
+ path: getRoutePath('health.ts'),
83
95
  content: `import { e } from '@geekmidas/constructs/endpoints';
84
96
 
85
97
  export default e
@@ -39,6 +39,25 @@ export const workerTemplate: TemplateConfig = {
39
39
  },
40
40
 
41
41
  files: (options: TemplateOptions): GeneratedFile[] => {
42
+ const { loggerType, routesStructure } = options;
43
+
44
+ const loggerContent = `import { createLogger } from '@geekmidas/logger/${loggerType}';
45
+
46
+ export const logger = createLogger();
47
+ `;
48
+
49
+ // Get route path based on structure
50
+ const getRoutePath = (file: string) => {
51
+ switch (routesStructure) {
52
+ case 'centralized-endpoints':
53
+ return `src/endpoints/${file}`;
54
+ case 'centralized-routes':
55
+ return `src/routes/${file}`;
56
+ case 'domain-based':
57
+ return `src/${file.replace('.ts', '')}/routes/index.ts`;
58
+ }
59
+ };
60
+
42
61
  const files: GeneratedFile[] = [
43
62
  // src/config/env.ts
44
63
  {
@@ -66,21 +85,15 @@ export const config = envParser
66
85
  `,
67
86
  },
68
87
 
69
- // src/config/logger.ts - using pino
88
+ // src/config/logger.ts
70
89
  {
71
90
  path: 'src/config/logger.ts',
72
- content: `import { PinoLogger } from '@geekmidas/logger/pino';
73
-
74
- export const logger = new PinoLogger({
75
- app: '${options.name}',
76
- level: process.env.LOG_LEVEL || 'info',
77
- });
78
- `,
91
+ content: loggerContent,
79
92
  },
80
93
 
81
- // src/endpoints/health.ts
94
+ // health endpoint
82
95
  {
83
- path: 'src/endpoints/health.ts',
96
+ path: getRoutePath('health.ts'),
84
97
  content: `import { e } from '@geekmidas/constructs/endpoints';
85
98
 
86
99
  export default e