@geekmidas/cli 10.0.0-alpha.5 → 10.0.0-alpha.50

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 (267) hide show
  1. package/README.md +196 -257
  2. package/bin/adjacent-tsconfig.mjs +97 -0
  3. package/bin/gkm.mjs +16 -2
  4. package/bin/owning-tsconfig-jsx-register.mjs +18 -0
  5. package/bin/owning-tsconfig-jsx.mjs +108 -0
  6. package/dist/{HostingerProvider-h3EbEp-Z.cjs → HostingerProvider-BZFGYYVA.cjs} +21 -22
  7. package/dist/HostingerProvider-BZFGYYVA.cjs.map +1 -0
  8. package/dist/{HostingerProvider-Cft7lEYr.mjs → HostingerProvider-GF6NAZAK.mjs} +20 -21
  9. package/dist/HostingerProvider-GF6NAZAK.mjs.map +1 -0
  10. package/dist/{LocalStateProvider-Db9SEjyH.cjs → LocalStateProvider-7HR6SS2t.cjs} +11 -6
  11. package/dist/LocalStateProvider-7HR6SS2t.cjs.map +1 -0
  12. package/dist/{LocalStateProvider-Bn6tS-oL.mjs → LocalStateProvider-D7QyJoLM.mjs} +10 -4
  13. package/dist/LocalStateProvider-D7QyJoLM.mjs.map +1 -0
  14. package/dist/{openapi-CA0yJUTN.cjs → OpenApiTsGenerator-BN0PIZxd.cjs} +157 -372
  15. package/dist/OpenApiTsGenerator-BN0PIZxd.cjs.map +1 -0
  16. package/dist/{openapi-kkQbsRVj.mjs → OpenApiTsGenerator-BzIGy8KE.mjs} +128 -324
  17. package/dist/OpenApiTsGenerator-BzIGy8KE.mjs.map +1 -0
  18. package/dist/{Route53Provider-RdpUDJQk.mjs → Route53Provider-Cvj40A8I.mjs} +12 -12
  19. package/dist/Route53Provider-Cvj40A8I.mjs.map +1 -0
  20. package/dist/{Route53Provider-di2fMM5N.cjs → Route53Provider-DVILBsvV.cjs} +20 -21
  21. package/dist/Route53Provider-DVILBsvV.cjs.map +1 -0
  22. package/dist/{SSMStateProvider-BRt2py-A.mjs → SSMStateProvider-B0Hu1MKZ.mjs} +13 -4
  23. package/dist/SSMStateProvider-B0Hu1MKZ.mjs.map +1 -0
  24. package/dist/{SSMStateProvider-DyX8s9HI.cjs → SSMStateProvider-VrQ-yeqd.cjs} +17 -9
  25. package/dist/SSMStateProvider-VrQ-yeqd.cjs.map +1 -0
  26. package/dist/aws-DkHdTV-p.cjs +61 -0
  27. package/dist/aws-DkHdTV-p.cjs.map +1 -0
  28. package/dist/aws-DojzQnLd.mjs +61 -0
  29. package/dist/aws-DojzQnLd.mjs.map +1 -0
  30. package/dist/backends-B9V2XD2M.cjs +82 -0
  31. package/dist/backends-B9V2XD2M.cjs.map +1 -0
  32. package/dist/backends-CSuLl0YP.mjs +59 -0
  33. package/dist/backends-CSuLl0YP.mjs.map +1 -0
  34. package/dist/{backup-provisioner-BrsHwYG0.cjs → backup-provisioner-BmhIO_Yr.cjs} +21 -19
  35. package/dist/backup-provisioner-BmhIO_Yr.cjs.map +1 -0
  36. package/dist/{backup-provisioner-Bgj5Vi_L.mjs → backup-provisioner-DIVCbfee.mjs} +10 -7
  37. package/dist/backup-provisioner-DIVCbfee.mjs.map +1 -0
  38. package/dist/{bundler-Be8Zg4Wd.mjs → bundler--fyybf1N.mjs} +19 -30
  39. package/dist/bundler--fyybf1N.mjs.map +1 -0
  40. package/dist/{bundler-BY1OmV1e.cjs → bundler-By6_sXiL.cjs} +20 -32
  41. package/dist/bundler-By6_sXiL.cjs.map +1 -0
  42. package/dist/{config-C21ocYNd.cjs → config-CsYSyUya.cjs} +209 -210
  43. package/dist/config-CsYSyUya.cjs.map +1 -0
  44. package/dist/{config-WRdsQYZK.mjs → config-D8J5rrTb.mjs} +142 -154
  45. package/dist/config-D8J5rrTb.mjs.map +1 -0
  46. package/dist/config.cjs +9 -6
  47. package/dist/config.d.cts +62 -33
  48. package/dist/config.d.cts.map +1 -1
  49. package/dist/config.d.mts +62 -33
  50. package/dist/config.d.mts.map +1 -1
  51. package/dist/config.mjs +3 -5
  52. package/dist/deploy/sniffer-envkit-patch.cjs +18 -10
  53. package/dist/deploy/sniffer-envkit-patch.cjs.map +1 -1
  54. package/dist/deploy/sniffer-envkit-patch.d.cts +0 -2
  55. package/dist/deploy/sniffer-envkit-patch.d.cts.map +1 -1
  56. package/dist/deploy/sniffer-envkit-patch.d.mts +0 -2
  57. package/dist/deploy/sniffer-envkit-patch.d.mts.map +1 -1
  58. package/dist/deploy/sniffer-envkit-patch.mjs +10 -2
  59. package/dist/deploy/sniffer-envkit-patch.mjs.map +1 -1
  60. package/dist/deploy/sniffer-hooks.cjs +13 -7
  61. package/dist/deploy/sniffer-hooks.cjs.map +1 -1
  62. package/dist/deploy/sniffer-hooks.d.cts +1 -2
  63. package/dist/deploy/sniffer-hooks.d.cts.map +1 -1
  64. package/dist/deploy/sniffer-hooks.d.mts +1 -2
  65. package/dist/deploy/sniffer-hooks.d.mts.map +1 -1
  66. package/dist/deploy/sniffer-hooks.mjs +9 -2
  67. package/dist/deploy/sniffer-hooks.mjs.map +1 -1
  68. package/dist/deploy/sniffer-loader.cjs +16 -7
  69. package/dist/deploy/sniffer-loader.cjs.map +1 -1
  70. package/dist/deploy/sniffer-loader.d.cts +1 -1
  71. package/dist/deploy/sniffer-loader.d.mts +1 -1
  72. package/dist/deploy/sniffer-loader.mjs +13 -2
  73. package/dist/deploy/sniffer-loader.mjs.map +1 -1
  74. package/dist/deploy/sniffer-routes-worker.cjs +11 -11
  75. package/dist/deploy/sniffer-routes-worker.cjs.map +1 -1
  76. package/dist/deploy/sniffer-routes-worker.d.cts +1 -1
  77. package/dist/deploy/sniffer-routes-worker.d.mts +1 -1
  78. package/dist/deploy/sniffer-routes-worker.mjs +3 -3
  79. package/dist/deploy/sniffer-routes-worker.mjs.map +1 -1
  80. package/dist/deploy/sniffer-worker.cjs +15 -6
  81. package/dist/deploy/sniffer-worker.cjs.map +1 -1
  82. package/dist/deploy/sniffer-worker.d.cts +1 -3
  83. package/dist/deploy/sniffer-worker.d.cts.map +1 -1
  84. package/dist/deploy/sniffer-worker.d.mts +1 -3
  85. package/dist/deploy/sniffer-worker.d.mts.map +1 -1
  86. package/dist/deploy/sniffer-worker.mjs +15 -4
  87. package/dist/deploy/sniffer-worker.mjs.map +1 -1
  88. package/dist/{discover-CAlFgYec.mjs → discover-Cf2jAcgF.mjs} +56 -63
  89. package/dist/discover-Cf2jAcgF.mjs.map +1 -0
  90. package/dist/{discover-DTmFeloL.cjs → discover-DXNviAh-.cjs} +86 -110
  91. package/dist/discover-DXNviAh-.cjs.map +1 -0
  92. package/dist/{emit-CiZS_5Ub.mjs → emit-C1e8qD08.mjs} +13 -26
  93. package/dist/emit-C1e8qD08.mjs.map +1 -0
  94. package/dist/{emit-CbcRolsa.cjs → emit-Dmc1nvdS.cjs} +31 -57
  95. package/dist/emit-Dmc1nvdS.cjs.map +1 -0
  96. package/dist/encryption-C7OGMve_.cjs +91 -0
  97. package/dist/encryption-C7OGMve_.cjs.map +1 -0
  98. package/dist/encryption-DyQnPsZN.mjs +90 -0
  99. package/dist/encryption-DyQnPsZN.mjs.map +1 -0
  100. package/dist/github-BfpadQWQ.mjs +213 -0
  101. package/dist/github-BfpadQWQ.mjs.map +1 -0
  102. package/dist/github-BrI1tv6u.cjs +213 -0
  103. package/dist/github-BrI1tv6u.cjs.map +1 -0
  104. package/dist/{index-CHB4tSzX.d.cts → index-BQhJXpaQ.d.mts} +4 -23
  105. package/dist/index-BQhJXpaQ.d.mts.map +1 -0
  106. package/dist/{index-BThUzEIp.d.mts → index-DHJePE0y.d.cts} +4 -23
  107. package/dist/index-DHJePE0y.d.cts.map +1 -0
  108. package/dist/index.cjs +9531 -7200
  109. package/dist/index.cjs.map +1 -1
  110. package/dist/index.d.cts +1 -1
  111. package/dist/index.d.mts +1 -1
  112. package/dist/index.mjs +9412 -7108
  113. package/dist/index.mjs.map +1 -1
  114. package/dist/migrate-B00XpVaO.mjs +736 -0
  115. package/dist/migrate-B00XpVaO.mjs.map +1 -0
  116. package/dist/migrate-CNlew9Ek.cjs +743 -0
  117. package/dist/migrate-CNlew9Ek.cjs.map +1 -0
  118. package/dist/openapi.cjs +198 -8
  119. package/dist/openapi.cjs.map +1 -0
  120. package/dist/openapi.d.cts +53 -15
  121. package/dist/openapi.d.cts.map +1 -1
  122. package/dist/openapi.d.mts +53 -15
  123. package/dist/openapi.d.mts.map +1 -1
  124. package/dist/openapi.mjs +193 -5
  125. package/dist/openapi.mjs.map +1 -0
  126. package/dist/ready-WfT-eWlm.mjs +861 -0
  127. package/dist/ready-WfT-eWlm.mjs.map +1 -0
  128. package/dist/ready-lr2Fm-ep.cjs +932 -0
  129. package/dist/ready-lr2Fm-ep.cjs.map +1 -0
  130. package/dist/reconcile/public.cjs +3 -5
  131. package/dist/reconcile/public.d.cts +30 -33
  132. package/dist/reconcile/public.d.cts.map +1 -1
  133. package/dist/reconcile/public.d.mts +30 -33
  134. package/dist/reconcile/public.d.mts.map +1 -1
  135. package/dist/reconcile/public.mjs +3 -4
  136. package/dist/{reconcile-CFs8C_1a.mjs → reconcile--I7V4Klj.mjs} +4 -7
  137. package/dist/reconcile--I7V4Klj.mjs.map +1 -0
  138. package/dist/{reconcile-D0pimNiy.cjs → reconcile-CuCQBa5-.cjs} +5 -8
  139. package/dist/reconcile-CuCQBa5-.cjs.map +1 -0
  140. package/dist/rolldown-runtime-BhDjJH2R.mjs +15 -0
  141. package/dist/{chunk-CUT6urMc.cjs → rolldown-runtime-C0BPl7ul.cjs} +23 -10
  142. package/dist/storage-BzaUxmqe.mjs +124 -0
  143. package/dist/storage-BzaUxmqe.mjs.map +1 -0
  144. package/dist/storage-CSGoC3bK.cjs +152 -0
  145. package/dist/storage-CSGoC3bK.cjs.map +1 -0
  146. package/dist/store-DQgxT_WR.cjs +211 -0
  147. package/dist/store-DQgxT_WR.cjs.map +1 -0
  148. package/dist/store-DeGATCS-.mjs +182 -0
  149. package/dist/store-DeGATCS-.mjs.map +1 -0
  150. package/dist/types-BbrNu83u.d.mts +6229 -0
  151. package/dist/types-BbrNu83u.d.mts.map +1 -0
  152. package/dist/types-DNqEsctD.d.cts +6230 -0
  153. package/dist/types-DNqEsctD.d.cts.map +1 -0
  154. package/dist/vitest.cjs +65 -0
  155. package/dist/vitest.cjs.map +1 -0
  156. package/dist/vitest.d.cts +29 -0
  157. package/dist/vitest.d.cts.map +1 -0
  158. package/dist/vitest.d.mts +29 -0
  159. package/dist/vitest.d.mts.map +1 -0
  160. package/dist/vitest.mjs +65 -0
  161. package/dist/vitest.mjs.map +1 -0
  162. package/dist/workspace/index.cjs +3 -4
  163. package/dist/workspace/index.d.cts +3 -3
  164. package/dist/workspace/index.d.mts +3 -3
  165. package/dist/workspace/index.mjs +2 -3
  166. package/dist/{credentials-BBIRJVp4.mjs → workspace-BsbxbqV-.mjs} +2201 -1732
  167. package/dist/workspace-BsbxbqV-.mjs.map +1 -0
  168. package/dist/{workspace-BcucjwvA.cjs → workspace-DEibcoBe.cjs} +1038 -1118
  169. package/dist/workspace-DEibcoBe.cjs.map +1 -0
  170. package/dist/{workspace-BFMrAKqI.mjs → workspace-DNzWgM1J.mjs} +869 -972
  171. package/dist/workspace-DNzWgM1J.mjs.map +1 -0
  172. package/dist/{credentials-G1JwBoXH.cjs → workspace-j6ZxvJqq.cjs} +2337 -1849
  173. package/dist/workspace-j6ZxvJqq.cjs.map +1 -0
  174. package/package.json +29 -20
  175. package/dist/CachedStateProvider-BLo7zv7S.cjs +0 -3
  176. package/dist/CachedStateProvider-BxoAm-B2.mjs +0 -3
  177. package/dist/CachedStateProvider-CqPdW7CB.cjs +0 -60
  178. package/dist/CachedStateProvider-CqPdW7CB.cjs.map +0 -1
  179. package/dist/CachedStateProvider-DTniehMP.mjs +0 -54
  180. package/dist/CachedStateProvider-DTniehMP.mjs.map +0 -1
  181. package/dist/HostingerProvider-Cft7lEYr.mjs.map +0 -1
  182. package/dist/HostingerProvider-h3EbEp-Z.cjs.map +0 -1
  183. package/dist/LocalStateProvider-Bn6tS-oL.mjs.map +0 -1
  184. package/dist/LocalStateProvider-Db9SEjyH.cjs.map +0 -1
  185. package/dist/Route53Provider-RdpUDJQk.mjs.map +0 -1
  186. package/dist/Route53Provider-di2fMM5N.cjs.map +0 -1
  187. package/dist/SSMStateProvider-BRt2py-A.mjs.map +0 -1
  188. package/dist/SSMStateProvider-DyX8s9HI.cjs.map +0 -1
  189. package/dist/backup-provisioner-Bgj5Vi_L.mjs.map +0 -1
  190. package/dist/backup-provisioner-BrsHwYG0.cjs.map +0 -1
  191. package/dist/bundler-BY1OmV1e.cjs.map +0 -1
  192. package/dist/bundler-Be8Zg4Wd.mjs.map +0 -1
  193. package/dist/chunk-Duj1WY3L.mjs +0 -7
  194. package/dist/config-C21ocYNd.cjs.map +0 -1
  195. package/dist/config-WRdsQYZK.mjs.map +0 -1
  196. package/dist/credentials-B5zRHdAl.mjs +0 -141
  197. package/dist/credentials-B5zRHdAl.mjs.map +0 -1
  198. package/dist/credentials-BBIRJVp4.mjs.map +0 -1
  199. package/dist/credentials-BapzjyV5.cjs +0 -195
  200. package/dist/credentials-BapzjyV5.cjs.map +0 -1
  201. package/dist/credentials-G1JwBoXH.cjs.map +0 -1
  202. package/dist/discover-CAlFgYec.mjs.map +0 -1
  203. package/dist/discover-DTmFeloL.cjs.map +0 -1
  204. package/dist/dokploy-api-BS2xnJLZ.mjs +0 -3
  205. package/dist/dokploy-api-BsVH0y_s.cjs +0 -718
  206. package/dist/dokploy-api-BsVH0y_s.cjs.map +0 -1
  207. package/dist/dokploy-api-BuxDRo3l.cjs +0 -3
  208. package/dist/dokploy-api-aTFPz7_4.mjs +0 -706
  209. package/dist/dokploy-api-aTFPz7_4.mjs.map +0 -1
  210. package/dist/emit-CbcRolsa.cjs.map +0 -1
  211. package/dist/emit-CiZS_5Ub.mjs.map +0 -1
  212. package/dist/encryption-C6jaU0hE.cjs +0 -54
  213. package/dist/encryption-C6jaU0hE.cjs.map +0 -1
  214. package/dist/encryption-CHzzeR8a.cjs +0 -4
  215. package/dist/encryption-CQUncu7v.mjs +0 -3
  216. package/dist/encryption-D-abyhZx.mjs +0 -42
  217. package/dist/encryption-D-abyhZx.mjs.map +0 -1
  218. package/dist/fullstack-secrets-C-GGohke.cjs +0 -111
  219. package/dist/fullstack-secrets-C-GGohke.cjs.map +0 -1
  220. package/dist/fullstack-secrets-D1o9-G5l.mjs +0 -87
  221. package/dist/fullstack-secrets-D1o9-G5l.mjs.map +0 -1
  222. package/dist/generator-CNzBw7g5.cjs +0 -289
  223. package/dist/generator-CNzBw7g5.cjs.map +0 -1
  224. package/dist/generator-VE2JrFlY.mjs +0 -253
  225. package/dist/generator-VE2JrFlY.mjs.map +0 -1
  226. package/dist/index-BThUzEIp.d.mts.map +0 -1
  227. package/dist/index-CHB4tSzX.d.cts.map +0 -1
  228. package/dist/openapi-CA0yJUTN.cjs.map +0 -1
  229. package/dist/openapi-kkQbsRVj.mjs.map +0 -1
  230. package/dist/openapi-react-query-Byltvm_7.mjs +0 -167
  231. package/dist/openapi-react-query-Byltvm_7.mjs.map +0 -1
  232. package/dist/openapi-react-query-CmJ1xDbn.cjs +0 -173
  233. package/dist/openapi-react-query-CmJ1xDbn.cjs.map +0 -1
  234. package/dist/openapi-react-query.cjs +0 -4
  235. package/dist/openapi-react-query.d.cts +0 -11
  236. package/dist/openapi-react-query.d.cts.map +0 -1
  237. package/dist/openapi-react-query.d.mts +0 -11
  238. package/dist/openapi-react-query.d.mts.map +0 -1
  239. package/dist/openapi-react-query.mjs +0 -4
  240. package/dist/reconcile-CFs8C_1a.mjs.map +0 -1
  241. package/dist/reconcile-D0pimNiy.cjs.map +0 -1
  242. package/dist/setup-B5_oHHUj.cjs +0 -11
  243. package/dist/setup-Cm2UnAdh.cjs +0 -473
  244. package/dist/setup-Cm2UnAdh.cjs.map +0 -1
  245. package/dist/setup-DXvRLTZN.mjs +0 -443
  246. package/dist/setup-DXvRLTZN.mjs.map +0 -1
  247. package/dist/setup-ZijS4qeC.mjs +0 -11
  248. package/dist/storage-BJmzYxt8.cjs +0 -363
  249. package/dist/storage-BJmzYxt8.cjs.map +0 -1
  250. package/dist/storage-BM9hGpgv.cjs +0 -7
  251. package/dist/storage-Bi24WfoW.mjs +0 -297
  252. package/dist/storage-Bi24WfoW.mjs.map +0 -1
  253. package/dist/storage-CYlGwWTj.mjs +0 -3
  254. package/dist/sync-CmEuNZsB.mjs +0 -76
  255. package/dist/sync-CmEuNZsB.mjs.map +0 -1
  256. package/dist/sync-D306yOWu.cjs +0 -4
  257. package/dist/sync-SizaChmC.cjs +0 -93
  258. package/dist/sync-SizaChmC.cjs.map +0 -1
  259. package/dist/sync-hOqAWHR6.mjs +0 -3
  260. package/dist/types-C-arnQ1r.d.mts +0 -2184
  261. package/dist/types-C-arnQ1r.d.mts.map +0 -1
  262. package/dist/types-abJQuk7m.d.cts +0 -2184
  263. package/dist/types-abJQuk7m.d.cts.map +0 -1
  264. package/dist/workspace-BFMrAKqI.mjs.map +0 -1
  265. package/dist/workspace-BcucjwvA.cjs.map +0 -1
  266. package/dist/workspace-DdJss8I6.cjs +0 -9
  267. package/dist/workspace-k4l3rsFh.mjs +0 -8
package/README.md CHANGED
@@ -54,6 +54,7 @@ Create a `gkm.config.ts` file in your project root:
54
54
  import { defineConfig } from '@geekmidas/cli/config';
55
55
 
56
56
  export default defineConfig({
57
+ stages: { local: 'dev', deployed: ['prod'] },
57
58
  // Glob pattern to find endpoint files
58
59
  routes: 'src/routes/**/*.ts',
59
60
 
@@ -142,36 +143,32 @@ export const createUser = api
142
143
 
143
144
  ### 5. Create Subscribers (Optional)
144
145
 
145
- Create event subscribers in `src/subscribers/`:
146
+ Declare the topic once, and a worker to run what has no port; a subscriber is
147
+ built from the worker and binds to the topic:
146
148
 
147
149
  ```typescript
150
+ // src/constructs/topics.ts
151
+ import { Topic } from '@geekmidas/constructs/topic';
152
+ import { z } from 'zod';
153
+
154
+ export const users = new Topic('Users', {
155
+ events: {
156
+ 'user.created': z.object({ userId: z.string(), email: z.email() }),
157
+ 'user.updated': z.object({ userId: z.string() }),
158
+ },
159
+ });
160
+
161
+ // src/constructs/worker.ts
162
+ import { Worker } from '@geekmidas/constructs/worker';
163
+
164
+ export const worker = new Worker('Jobs', { logger });
165
+
148
166
  // src/subscribers/userSubscriber.ts
149
- import { SubscriberBuilder } from '@geekmidas/constructs/subscribers';
150
- import type { Service } from '@geekmidas/services';
151
- import type { EventPublisher, PublishableMessage } from '@geekmidas/events';
152
- import type { EnvironmentParser } from '@geekmidas/envkit';
153
-
154
- // Define event types
155
- type UserEvents =
156
- | PublishableMessage<'user.created', { userId: string; email: string }>
157
- | PublishableMessage<'user.updated', { userId: string }>;
158
-
159
- // Create event publisher service
160
- const userEventPublisher = {
161
- serviceName: 'userEventPublisher' as const,
162
- async register(envParser: EnvironmentParser<{}>) {
163
- const config = envParser.create((get) => ({
164
- publisherUrl: get('EVENT_PUBLISHER_URL').string()
165
- })).parse();
166
-
167
- const { Publisher } = await import('@geekmidas/events');
168
- return Publisher.fromConnectionString<UserEvents>(config.publisherUrl);
169
- }
170
- } satisfies Service<'userEventPublisher', EventPublisher<UserEvents>>;
167
+ import { users } from '../constructs/topics';
168
+ import { worker } from '../constructs/worker';
171
169
 
172
- // Create subscriber
173
- export const userCreatedSubscriber = new SubscriberBuilder()
174
- .publisher(userEventPublisher)
170
+ export const userCreatedSubscriber = worker
171
+ .topic(users)
175
172
  .subscribe(['user.created'])
176
173
  .handle(async ({ events, logger }) => {
177
174
  for (const event of events) {
@@ -181,11 +178,16 @@ export const userCreatedSubscriber = new SubscriberBuilder()
181
178
  });
182
179
  ```
183
180
 
181
+ An endpoint publishes to the topic with `.event(users, { type: 'user.created',
182
+ payload: (user) => ({ userId: user.id, email: user.email }) })`. Declaring the
183
+ topic is what puts a broker in the local plan and resolves
184
+ `USERS_PUBLISHER_CONNECTION_STRING` for whatever publishes to it.
185
+
184
186
  ### 6. Build Handlers
185
187
 
186
188
  ```bash
187
- # Generate AWS Lambda handlers
188
- npx gkm build --provider aws-apigatewayv1
189
+ # Build for where gkm.config.ts deploys (AWS for `deploy: { default: 'sst' }`)
190
+ npx gkm build
189
191
 
190
192
  # Generate server application
191
193
  npx gkm build --provider server
@@ -309,17 +311,20 @@ Generate handlers from your endpoints.
309
311
  gkm build [options]
310
312
  ```
311
313
 
314
+ By default it builds for where the project deploys: `deploy: { default: 'sst' }`
315
+ builds for AWS, one Lambda per construct; `dokploy` (the default when nothing
316
+ is declared) builds a server.
317
+
312
318
  **Options:**
313
- - `--provider <provider>`: Target provider (default: `aws-apigatewayv1`)
314
- - `aws-apigatewayv1`: AWS API Gateway v1 Lambda handlers
315
- - `aws-apigatewayv2`: AWS API Gateway v2 Lambda handlers
319
+ - `--provider <provider>`: Override the deploy target
320
+ - `aws`: One Lambda handler per construct (API Gateway v2 for endpoints)
316
321
  - `server`: Server application with Hono
317
322
  - `--production`: Generate production-optimized bundle (server provider only)
318
323
 
319
324
  **Example:**
320
325
  ```bash
321
- # Generate AWS Lambda handlers
322
- gkm build --provider aws-apigatewayv1
326
+ # Build for where gkm.config.ts deploys
327
+ gkm build
323
328
 
324
329
  # Generate server application
325
330
  gkm build --provider server
@@ -443,7 +448,7 @@ gkm docker [options]
443
448
 
444
449
  **Generated Files:**
445
450
  - `.gkm/docker/Dockerfile` - Multi-stage or slim Dockerfile
446
- - `.gkm/docker/docker-compose.yml` - Docker Compose configuration
451
+ - `docker-compose.constructs.yml` - the containers the constructs imply, and the app (project root)
447
452
  - `.gkm/docker/docker-entrypoint.sh` - Entrypoint script
448
453
  - `.dockerignore` - Docker ignore file (project root)
449
454
 
@@ -490,6 +495,7 @@ Configure Docker settings in `gkm.config.ts`:
490
495
  import { defineConfig } from '@geekmidas/cli/config';
491
496
 
492
497
  export default defineConfig({
498
+ stages: { local: 'dev', deployed: ['prod'] },
493
499
  routes: 'src/routes/**/*.ts',
494
500
  envParser: './src/env.ts',
495
501
  logger: './src/logger.ts',
@@ -503,38 +509,20 @@ export default defineConfig({
503
509
  baseImage: 'node:22-alpine',
504
510
  // Port to expose (default: 3000)
505
511
  port: 3000,
506
- // Docker Compose services
507
- compose: {
508
- services: {
509
- postgres: { image: 'postgis/postgis:16-3.4-alpine' }, // Custom image
510
- redis: true, // Default version
511
- rabbitmq: { version: '3.12-management-alpine' }, // Custom version
512
- },
513
- },
514
512
  },
515
513
  });
516
514
  ```
517
515
 
518
- **Docker Compose Services:**
519
-
520
- Services can be configured with custom versions, custom images, or use defaults:
521
-
522
- ```typescript
523
- // Object format (recommended)
524
- services: {
525
- postgres: { version: '15-alpine' }, // Custom version
526
- redis: true, // Default: redis:7-alpine
527
- rabbitmq: { version: '3.12-management-alpine' },
528
- }
529
-
530
- // Custom images (e.g., PostGIS, Redis Stack)
531
- services: {
532
- postgres: { image: 'postgis/postgis:16-3.4-alpine' }, // Full image reference
533
- redis: { image: 'redis/redis-stack:latest' },
534
- }
516
+ **Compose:** there is no `compose` option. `gkm docker` writes
517
+ `docker-compose.constructs.yml` at the project root from the declared
518
+ constructs; an image pin or an extra service goes in your own
519
+ `docker-compose.yml`, which is merged over it:
535
520
 
536
- // Legacy array format - uses default versions
537
- services: ['postgres', 'redis', 'rabbitmq']
521
+ ```yaml
522
+ # docker-compose.yml
523
+ services:
524
+ postgres:
525
+ image: postgis/postgis:16-3.4-alpine
538
526
  ```
539
527
 
540
528
  **Service Configuration Options:**
@@ -682,8 +670,8 @@ gkm secrets:init --stage production --force
682
670
  ```
683
671
 
684
672
  **Generated:**
685
- - Secure passwords for postgres, redis, rabbitmq (based on `docker.compose.services` config)
686
- - Connection URLs (`DATABASE_URL`, `REDIS_URL`, `RABBITMQ_URL`)
673
+ - Custom secrets for the stage; the containers' credentials are provisioned by
674
+ reconcile from the declared constructs, not stored here
687
675
  - Stored in `.gkm/secrets/<stage>.json` (gitignored)
688
676
 
689
677
  ### `gkm secrets:set`
@@ -929,6 +917,7 @@ This allows the CLI to validate that all required secrets are configured before
929
917
  ```typescript
930
918
  // gkm.config.ts
931
919
  export default defineConfig({
920
+ stages: { local: 'dev', deployed: ['prod'] },
932
921
  routes: 'src/endpoints/**/*.ts',
933
922
  envParser: './src/env.ts',
934
923
  logger: './src/logger.ts',
@@ -937,15 +926,6 @@ export default defineConfig({
937
926
  registry: 'ghcr.io/myorg',
938
927
  imageName: 'my-api',
939
928
  },
940
-
941
- // For Dokploy deployments
942
- providers: {
943
- dokploy: {
944
- endpoint: 'https://dokploy.example.com',
945
- projectId: 'proj_xxx',
946
- applicationId: 'app_xxx',
947
- },
948
- },
949
929
  });
950
930
  ```
951
931
 
@@ -955,7 +935,7 @@ export default defineConfig({
955
935
 
956
936
  ### `gkm deploy:init`
957
937
 
958
- Initialize a new Dokploy deployment by creating a project and application via the Dokploy API. Automatically updates `gkm.config.ts` with the configuration.
938
+ Initialize a new Dokploy deployment by creating a project and application via the Dokploy API. Nothing is written to `gkm.config.ts`: the ids are rediscovered by name on each run and kept in the deploy state file.
959
939
 
960
940
  ```bash
961
941
  gkm deploy:init --project <name> --app <name> [options]
@@ -990,8 +970,7 @@ gkm deploy:init \
990
970
  1. Searches for existing project by name, or creates a new one
991
971
  2. Creates a new application in the project
992
972
  3. Configures registry if `--registry-id` is provided
993
- 4. Updates `gkm.config.ts` with the Dokploy configuration
994
- 5. Shows next steps for secrets and deployment
973
+ 4. Shows next steps for secrets and deployment
995
974
 
996
975
  ### `gkm deploy:list`
997
976
 
@@ -1059,21 +1038,16 @@ The following commands are planned for future releases:
1059
1038
  The `gkm.config.ts` file defines how the CLI discovers and processes your endpoints:
1060
1039
 
1061
1040
  ```typescript
1062
- // Construct types accept a string, string[], or partitioned config
1063
- type Routes = string | string[] | PartitionedRoutes;
1064
-
1065
- interface PartitionedRoutes {
1066
- paths: string | string[];
1067
- partition: (filepath: string) => string;
1068
- }
1041
+ // Construct types accept a glob string or an array of them
1042
+ type Routes = string | string[];
1069
1043
 
1070
1044
  interface GkmConfig {
1071
- routes: Routes; // Glob patterns or partitioned config
1045
+ routes: Routes; // Glob patterns
1072
1046
  envParser: string; // Path to environment parser
1073
1047
  logger: string; // Path to logger configuration
1074
- functions?: Routes; // Glob patterns or partitioned config
1075
- crons?: Routes; // Glob patterns or partitioned config
1076
- subscribers?: Routes; // Glob patterns or partitioned config
1048
+ functions?: Routes; // Glob patterns
1049
+ crons?: Routes; // Glob patterns
1050
+ subscribers?: Routes; // Glob patterns
1077
1051
  runtime?: 'node' | 'bun'; // Runtime environment (default: 'node')
1078
1052
  telescope?: boolean | TelescopeConfig; // Telescope debugging config
1079
1053
  }
@@ -1092,7 +1066,7 @@ interface TelescopeConfig {
1092
1066
 
1093
1067
  #### `routes`
1094
1068
 
1095
- Glob pattern(s) to discover endpoint files. Can be a single pattern, array of patterns, or a partitioned config:
1069
+ Glob pattern(s) to discover endpoint files. Can be a single pattern or an array of patterns:
1096
1070
 
1097
1071
  ```typescript
1098
1072
  // Single pattern
@@ -1104,19 +1078,8 @@ routes: [
1104
1078
  'src/api/**/*.ts',
1105
1079
  'src/handlers/**/*.ts'
1106
1080
  ]
1107
-
1108
- // Partitioned — groups constructs in the generated manifest
1109
- routes: {
1110
- paths: './src/endpoints/**/*.ts',
1111
- partition: (filepath) => {
1112
- const match = filepath.match(/endpoints\/([^/]+)\//);
1113
- return match?.[1] ?? 'default';
1114
- },
1115
- }
1116
1081
  ```
1117
1082
 
1118
- The same partitioned format works for `functions`, `crons`, and `subscribers`. When a `partition` callback is provided, the generated manifest groups constructs by partition name (e.g., `manifest.routes.admin`). Without it, manifest fields remain flat arrays.
1119
-
1120
1083
  #### `envParser`
1121
1084
 
1122
1085
  Path to your environment parser configuration. Supports both default and named exports.
@@ -1216,6 +1179,7 @@ import { defineWorkspace } from '@geekmidas/cli/config';
1216
1179
 
1217
1180
  export default defineWorkspace({
1218
1181
  name: 'my-project',
1182
+ stages: { local: 'dev', deployed: ['prod'] },
1219
1183
  constructs: './constructs/**/*.ts',
1220
1184
  shared: {
1221
1185
  packages: ['packages/*'],
@@ -1239,7 +1203,7 @@ them out of the manifest; none of them is listed in config.
1239
1203
 
1240
1204
  ```typescript
1241
1205
  // constructs/api.ts
1242
- export const api = new RestApi('Api', { defaultAuthorizer: 'none', logger });
1206
+ export const api = new RestApi('Api', { path: 'apps/api', defaultAuthorizer: 'none', logger });
1243
1207
  ```
1244
1208
 
1245
1209
  `gkm build --provider server` generates a Hono server from the endpoints built
@@ -1253,6 +1217,7 @@ An auth server mounts a wildcard, so there is nothing for a glob to find:
1253
1217
  ```typescript
1254
1218
  // constructs/auth.ts
1255
1219
  export const auth = new BetterAuth('Auth', {
1220
+ path: 'apps/auth',
1256
1221
  database: authDb,
1257
1222
  basePath: '/api/auth',
1258
1223
  });
@@ -1271,8 +1236,8 @@ from being read by it.
1271
1236
 
1272
1237
  ```typescript
1273
1238
  // constructs/site.ts
1274
- export const web = new StaticSite('Web').dependsOn([api, auth]);
1275
- export const admin = new StaticSite('Admin', { variant: 'next' }).dependsOn([api]);
1239
+ export const web = new StaticSite('Web', { path: 'apps/web' }).dependsOn([api, auth]);
1240
+ export const admin = new StaticSite('Admin', { path: 'apps/admin', variant: 'next' }).dependsOn([api]);
1276
1241
  ```
1277
1242
 
1278
1243
  `.dependsOn()` is the single fact behind four things that are hand-maintained
@@ -1291,7 +1256,7 @@ gkm docker
1291
1256
  - `.gkm/docker/Dockerfile.api` - Routes-based backend (uses `gkm build`)
1292
1257
  - `.gkm/docker/Dockerfile.auth` - Entry-based backend (uses esbuild bundling)
1293
1258
  - `.gkm/docker/Dockerfile.web` - Next.js standalone output
1294
- - `.gkm/docker/docker-compose.yml` - Full stack with all apps and services
1259
+ - `docker-compose.constructs.yml` - every container the constructs imply, and each app behind the `apps` profile (project root)
1295
1260
  - `.dockerignore` - Optimized ignore patterns
1296
1261
 
1297
1262
  **Dockerfile types by app:**
@@ -1358,12 +1323,10 @@ interface WorkspaceConfig {
1358
1323
  What an app is comes from the declaration, not from here:
1359
1324
 
1360
1325
  ```typescript
1361
- /** Overrides, all optional. A surface normally has none. */
1326
+ /** How a site is built and run. A surface declares only its `path`. */
1362
1327
  interface AppSpec {
1363
- /** Default: `apps/<kebab-id>` if present, else the project root. */
1364
- path?: string;
1365
- /** Default: the conventional directories under `path`. */
1366
- code?: string;
1328
+ /** Required: where the app lives, relative to the workspace root. */
1329
+ path: string;
1367
1330
  /** Default: assigned in a stable order, so adding an app renumbers nothing. */
1368
1331
  port?: number;
1369
1332
  entry?: string;
@@ -1371,42 +1334,24 @@ interface AppSpec {
1371
1334
  }
1372
1335
  ```
1373
1336
 
1374
- ## Providers
1375
-
1376
- ### AWS API Gateway v1
1377
-
1378
- Generates Lambda handlers compatible with AWS API Gateway v1 (REST API).
1379
-
1380
- ```bash
1381
- gkm build --provider aws-apigatewayv1
1382
- ```
1383
-
1384
- **Generated Handler:**
1385
- ```typescript
1386
- import { AmazonApiGatewayV1Endpoint } from '@geekmidas/constructs/aws';
1387
- import { myEndpoint } from '../src/routes/example.js';
1388
- import { envParser } from '../src/env.js';
1389
-
1390
- const adapter = new AmazonApiGatewayV1Endpoint(envParser, myEndpoint);
1337
+ ## Build Targets
1391
1338
 
1392
- export const handler = adapter.handler;
1393
- ```
1339
+ ### AWS
1394
1340
 
1395
- ### AWS API Gateway v2
1396
-
1397
- Generates Lambda handlers compatible with AWS API Gateway v2 (HTTP API).
1341
+ Generates one Lambda handler per construct. Endpoints get an API Gateway v2
1342
+ (HTTP API) adapter.
1398
1343
 
1399
1344
  ```bash
1400
- gkm build --provider aws-apigatewayv2
1345
+ gkm build # with deploy: { default: 'sst' }
1346
+ gkm build --provider aws # whatever the deploy target
1401
1347
  ```
1402
1348
 
1403
1349
  **Generated Handler:**
1404
1350
  ```typescript
1405
1351
  import { AmazonApiGatewayV2Endpoint } from '@geekmidas/constructs/aws';
1406
- import { myEndpoint } from '../src/routes/example.js';
1407
- import { envParser } from '../src/env.js';
1352
+ import { myEndpoint } from '../../../src/routes/example.js';
1408
1353
 
1409
- const adapter = new AmazonApiGatewayV2Endpoint(envParser, myEndpoint);
1354
+ const adapter = new AmazonApiGatewayV2Endpoint(myEndpoint);
1410
1355
 
1411
1356
  export const handler = adapter.handler;
1412
1357
  ```
@@ -1448,139 +1393,141 @@ export default createApp;
1448
1393
 
1449
1394
  ## Output Structure
1450
1395
 
1451
- The CLI generates files in the `.gkm/<provider>` directory:
1396
+ Handlers are generated beside the app, in `<app>/.gkm/<target>`; the manifest
1397
+ at the workspace root, where `sst.config.ts` runs:
1452
1398
 
1453
1399
  ```
1454
- .gkm/
1455
- ├── aws-apigatewayv1/
1456
- │ ├── getUsers.ts # Individual Lambda handler
1457
- │ ├── createUser.ts # Individual Lambda handler
1458
- ├── server/
1459
- │ ├── app.ts # Server application
1460
- │ ├── endpoints.ts # Endpoint exports
1461
- ├── manifest/
1462
- │ ├── aws.ts # AWS manifest with types
1463
- │ └── server.ts # Server manifest with types
1464
- └── openapi.json # OpenAPI specification
1400
+ <root>/
1401
+ ├── .gkm/manifest/
1402
+ │ ├── aws.ts # AWS manifest with types
1403
+ │ └── server.ts # Server manifest with types
1404
+ └── apps/api/.gkm/
1405
+ ├── aws/
1406
+ │ ├── routes/getUsers.ts # One Lambda handler per endpoint
1407
+ │ ├── functions/
1408
+ │ ├── crons/
1409
+ │ ├── queues/
1410
+ │ └── subscribers/
1411
+ └── server/
1412
+ ├── app.ts # Server application
1413
+ └── endpoints.ts # Endpoint exports
1465
1414
  ```
1466
1415
 
1467
1416
  ### Build Manifest
1468
1417
 
1469
- The CLI generates TypeScript manifests with full type information in the `.gkm/manifest/` directory. These manifests export both the data and derived types for type-safe usage.
1418
+ The manifest is the application's, not an app's: the root `gkm build` builds
1419
+ every backend and writes it once, to `.gkm/manifest/aws.ts` or
1420
+ `.gkm/manifest/server.ts` at the workspace root. An app's own build writes no
1421
+ manifest. Every handler path in it is relative to the workspace root. `gkm init`
1422
+ adds a root tsconfig alias for the manifest, `@<project>/manifest`.
1470
1423
 
1471
- #### AWS Manifest (`.gkm/manifest/aws.ts`)
1424
+ It exports two values — every declared construct keyed by id, and the backends
1425
+ the build resolved — and the types derived from them:
1472
1426
 
1473
1427
  ```typescript
1474
- export const manifest = {
1475
- routes: [
1476
- {
1477
- path: '/users',
1478
- method: 'GET',
1479
- handler: '.gkm/aws-apigatewayv1/getUsers.handler',
1480
- authorizer: 'jwt',
1481
- },
1482
- {
1483
- path: '/users',
1484
- method: 'POST',
1485
- handler: '.gkm/aws-apigatewayv1/createUser.handler',
1486
- authorizer: 'jwt',
1487
- },
1488
- ],
1489
- functions: [
1490
- {
1491
- name: 'processData',
1492
- handler: '.gkm/aws-lambda/functions/processData.handler',
1493
- timeout: 60,
1494
- memorySize: 256,
1495
- },
1496
- ],
1497
- crons: [
1498
- {
1499
- name: 'dailyCleanup',
1500
- handler: '.gkm/aws-lambda/crons/dailyCleanup.handler',
1501
- schedule: 'rate(1 day)',
1502
- timeout: 300,
1503
- memorySize: 512,
1428
+ export const constructs = {
1429
+ Database: { id: 'Database', kind: 'database' },
1430
+ Api: {
1431
+ id: 'Api',
1432
+ kind: 'rest-api',
1433
+ path: 'apps/api',
1434
+ endpoints: [
1435
+ {
1436
+ id: 'ApiGET/users',
1437
+ method: 'GET',
1438
+ path: '/users',
1439
+ handler: 'apps/api/.gkm/aws/routes/getUsers.handler',
1440
+ dependencies: [{ target: 'Database', kind: 'database' }],
1441
+ authorizer: 'iam',
1442
+ },
1443
+ ],
1444
+ },
1445
+ ProcessData: {
1446
+ id: 'ProcessData',
1447
+ kind: 'function',
1448
+ handler: 'apps/api/.gkm/aws/functions/processData.handler',
1449
+ dependencies: [],
1450
+ },
1451
+ DailyCleanup: {
1452
+ id: 'DailyCleanup',
1453
+ kind: 'cron',
1454
+ handler: 'apps/api/.gkm/aws/crons/dailyCleanup.handler',
1455
+ schedule: 'rate(1 day)',
1456
+ dependencies: [{ target: 'Database', kind: 'database' }],
1457
+ },
1458
+ Emails: {
1459
+ id: 'Emails',
1460
+ kind: 'queue',
1461
+ // The queue's consumer is nested in it
1462
+ worker: {
1463
+ id: 'emails',
1464
+ handler: 'apps/api/.gkm/aws/queues/emails.handler',
1465
+ dependencies: [],
1504
1466
  },
1505
- ],
1506
- subscribers: [],
1507
- } as const;
1467
+ },
1468
+ Users: {
1469
+ id: 'Users',
1470
+ kind: 'topic',
1471
+ events: ['user.created'],
1472
+ // As are a topic's subscribers
1473
+ subscribers: [
1474
+ {
1475
+ id: 'onUser',
1476
+ handler: 'apps/api/.gkm/aws/subscribers/onUser.handler',
1477
+ events: ['user.created'],
1478
+ dependencies: [],
1479
+ },
1480
+ ],
1481
+ },
1482
+ } as const satisfies ConstructManifest;
1483
+
1484
+ export const backends = { cache: 'upstash', email: 'ses' } as const;
1508
1485
 
1509
1486
  // Derived types
1510
- export type Route = (typeof manifest.routes)[number];
1511
- export type Function = (typeof manifest.functions)[number];
1512
- export type Cron = (typeof manifest.crons)[number];
1513
- export type Subscriber = (typeof manifest.subscribers)[number];
1487
+ export type Ids = IdsOf<typeof constructs>;
1488
+ export type Construct<Id extends Ids> = DeclarationOf<typeof constructs, Id>;
1489
+ export type Kind = Construct<Ids>['kind'];
1514
1490
 
1515
1491
  // Useful union types
1516
- export type Authorizer = Route['authorizer'];
1517
- export type HttpMethod = Route['method'];
1518
- export type RoutePath = Route['path'];
1492
+ export type ProvidedKeys = AllProvidedKeys<typeof constructs>;
1493
+ export type Surfaces = IdsOfKind<typeof constructs, 'rest-api'>;
1494
+ export type CacheBackend = (typeof backends)['cache'];
1495
+ export type EmailBackend = (typeof backends)['email'];
1519
1496
  ```
1520
1497
 
1521
- When routes are partitioned, the manifest groups them by partition name and generates partition-aware types:
1522
-
1523
- ```typescript
1524
- export const manifest = {
1525
- routes: {
1526
- "admin": [{ path: '/admin/users', method: 'GET', handler: '...', authorizer: 'jwt' }],
1527
- "default": [{ path: '/users', method: 'GET', handler: '...', authorizer: 'jwt' }],
1528
- },
1529
- functions: [...], // flat if not partitioned
1530
- } as const;
1498
+ A `RestApi` carries its endpoints, each with its method, path, handler, the
1499
+ dependencies it declared and its authorizer. On AWS the handler is the
1500
+ endpoint's own Lambda (`apps/api/.gkm/aws/routes/<export>.handler`); in the
1501
+ server manifest every endpoint's handler is the app entry
1502
+ (`apps/api/.gkm/server/app.ts`). Functions and crons are top-level
1503
+ declarations; a queue's worker and a topic's subscribers are nested in the
1504
+ queue or topic.
1531
1505
 
1532
- // Partition-aware derived types
1533
- export type RoutePartition = keyof typeof manifest.routes;
1534
- export type Route<P extends RoutePartition = RoutePartition> =
1535
- (typeof manifest.routes)[P][number];
1536
- ```
1506
+ #### Using the Manifest
1537
1507
 
1538
- #### Server Manifest (`.gkm/manifest/server.ts`)
1508
+ On AWS, `fromManifest` from `@geekmidas/cloud/sst` provisions all of it —
1509
+ resources, each API's endpoints, queue consumers, functions and crons:
1539
1510
 
1540
1511
  ```typescript
1541
- export const manifest = {
1542
- app: {
1543
- handler: '.gkm/server/app.ts',
1544
- endpoints: '.gkm/server/endpoints.ts',
1545
- },
1546
- routes: [
1547
- { path: '/users', method: 'GET', authorizer: 'jwt' },
1548
- { path: '/users', method: 'POST', authorizer: 'jwt' },
1549
- ],
1550
- subscribers: [
1551
- { name: 'orderHandler', subscribedEvents: ['order.created'] },
1552
- ],
1553
- } as const;
1554
-
1555
- // Derived types
1556
- export type Route = (typeof manifest.routes)[number];
1557
- export type Subscriber = (typeof manifest.subscribers)[number];
1512
+ // sst.config.ts
1513
+ const { App, fromManifest, Stack } = await import('@geekmidas/cloud/sst');
1514
+ const { backends, constructs } = await import('./.gkm/manifest/aws.js');
1558
1515
 
1559
- // Useful union types
1560
- export type Authorizer = Route['authorizer'];
1561
- export type HttpMethod = Route['method'];
1562
- export type RoutePath = Route['path'];
1516
+ fromManifest(new Stack(app, 'Shop'), constructs, { Database: { vpc } }, backends);
1563
1517
  ```
1564
1518
 
1565
- #### Using Manifest Types
1566
-
1567
- Import the manifest types for type-safe infrastructure configuration:
1519
+ The types narrow to what was declared:
1568
1520
 
1569
1521
  ```typescript
1570
- import { manifest, type Route, type Authorizer } from './.gkm/manifest/aws';
1522
+ import { constructs, type Construct, type Surfaces } from './.gkm/manifest/aws';
1571
1523
 
1572
- // Type-safe route iteration
1573
- for (const route of manifest.routes) {
1574
- console.log(`${route.method} ${route.path} -> ${route.handler}`);
1575
- }
1524
+ const api: Construct<'Api'> = constructs.Api;
1576
1525
 
1577
- // Use union types for validation
1578
- function isValidMethod(method: string): method is HttpMethod {
1579
- return manifest.routes.some((r) => r.method === method);
1526
+ for (const endpoint of api.endpoints) {
1527
+ console.log(`${endpoint.method} ${endpoint.path} -> ${endpoint.handler}`);
1580
1528
  }
1581
1529
 
1582
- // Access authorizer names
1583
- const authorizers = new Set(manifest.routes.map((r) => r.authorizer));
1530
+ const surface: Surfaces = 'Api'; // any other id is a type error
1584
1531
  ```
1585
1532
 
1586
1533
  ## OpenAPI Generation
@@ -1675,17 +1622,17 @@ provider:
1675
1622
 
1676
1623
  functions:
1677
1624
  getUsers:
1678
- handler: .gkm/aws-apigatewayv1/getUsers.handler
1625
+ handler: .gkm/aws/routes/getUsers.handler
1679
1626
  events:
1680
- - http:
1681
- path: users
1627
+ - httpApi:
1628
+ path: /users
1682
1629
  method: get
1683
-
1630
+
1684
1631
  createUser:
1685
- handler: .gkm/aws-apigatewayv1/createUser.handler
1632
+ handler: .gkm/aws/routes/createUser.handler
1686
1633
  events:
1687
- - http:
1688
- path: users
1634
+ - httpApi:
1635
+ path: /users
1689
1636
  method: post
1690
1637
  ```
1691
1638
 
@@ -1883,6 +1830,7 @@ Configure multiple patterns for complex project structures:
1883
1830
  import { defineConfig } from '@geekmidas/cli/config';
1884
1831
 
1885
1832
  export default defineConfig({
1833
+ stages: { local: 'dev', deployed: ['prod'] },
1886
1834
  routes: [
1887
1835
  'src/routes/**/*.ts',
1888
1836
  'src/api/v1/**/*.ts',
@@ -1935,7 +1883,7 @@ Error: OpenAPI generation failed: Invalid endpoint schema
1935
1883
  "dev": "gkm dev",
1936
1884
  "dev:port": "gkm dev --port 8080",
1937
1885
  "build": "gkm build",
1938
- "build:lambda": "gkm build --provider aws-apigatewayv1",
1886
+ "build:lambda": "gkm build --provider aws",
1939
1887
  "build:server": "gkm build --provider server",
1940
1888
  "docs": "gkm openapi --output src/api.ts"
1941
1889
  }
@@ -2029,8 +1977,8 @@ DEBUG=gkm:* npx gkm build
2029
1977
  ### Types
2030
1978
 
2031
1979
  ```typescript
2032
- // Provider options
2033
- type Provider = 'server' | 'aws-apigatewayv1' | 'aws-apigatewayv2';
1980
+ // Build targets
1981
+ type Provider = 'aws' | 'server';
2034
1982
 
2035
1983
  // Runtime options
2036
1984
  type Runtime = 'node' | 'bun';
@@ -2054,17 +2002,8 @@ interface DockerConfig {
2054
2002
  imageName?: string; // Image name (defaults to package.json name)
2055
2003
  baseImage?: string; // Base image (default: node:22-alpine)
2056
2004
  port?: number; // Port to expose (default: 3000)
2057
- compose?: {
2058
- services?: ComposeServicesConfig | ComposeServiceName[];
2059
- };
2060
2005
  }
2061
2006
 
2062
- // Service configuration for docker-compose
2063
- type ComposeServiceName = 'postgres' | 'redis' | 'rabbitmq';
2064
- type ComposeServicesConfig = {
2065
- [K in ComposeServiceName]?: boolean | { version?: string };
2066
- };
2067
-
2068
2007
  // Telescope configuration
2069
2008
  interface TelescopeConfig {
2070
2009
  enabled?: boolean;
@@ -2077,7 +2016,7 @@ interface TelescopeConfig {
2077
2016
 
2078
2017
  // Build options
2079
2018
  interface BuildOptions {
2080
- provider: Provider;
2019
+ provider?: Provider; // default: where gkm.config.ts deploys
2081
2020
  }
2082
2021
 
2083
2022
  // Dev options