@geekmidas/cli 10.0.0-alpha.3 → 10.0.0-alpha.31

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 (255) hide show
  1. package/README.md +25 -48
  2. package/bin/adjacent-tsconfig.mjs +97 -0
  3. package/bin/gkm.mjs +7 -1
  4. package/dist/{HostingerProvider-h3EbEp-Z.cjs → HostingerProvider-BZFGYYVA.cjs} +21 -22
  5. package/dist/HostingerProvider-BZFGYYVA.cjs.map +1 -0
  6. package/dist/{HostingerProvider-Cft7lEYr.mjs → HostingerProvider-GF6NAZAK.mjs} +20 -21
  7. package/dist/HostingerProvider-GF6NAZAK.mjs.map +1 -0
  8. package/dist/{LocalStateProvider-Db9SEjyH.cjs → LocalStateProvider-7HR6SS2t.cjs} +11 -6
  9. package/dist/LocalStateProvider-7HR6SS2t.cjs.map +1 -0
  10. package/dist/{LocalStateProvider-Bn6tS-oL.mjs → LocalStateProvider-D7QyJoLM.mjs} +10 -4
  11. package/dist/LocalStateProvider-D7QyJoLM.mjs.map +1 -0
  12. package/dist/{openapi-c9bpieI5.cjs → OpenApiTsGenerator-D1nhN98m.cjs} +135 -298
  13. package/dist/OpenApiTsGenerator-D1nhN98m.cjs.map +1 -0
  14. package/dist/{openapi-CY9xFkTH.mjs → OpenApiTsGenerator-hDINScnz.mjs} +106 -250
  15. package/dist/OpenApiTsGenerator-hDINScnz.mjs.map +1 -0
  16. package/dist/{Route53Provider-RdpUDJQk.mjs → Route53Provider-Cvj40A8I.mjs} +12 -12
  17. package/dist/Route53Provider-Cvj40A8I.mjs.map +1 -0
  18. package/dist/{Route53Provider-di2fMM5N.cjs → Route53Provider-DVILBsvV.cjs} +20 -21
  19. package/dist/Route53Provider-DVILBsvV.cjs.map +1 -0
  20. package/dist/{SSMStateProvider-BRt2py-A.mjs → SSMStateProvider-B0Hu1MKZ.mjs} +13 -4
  21. package/dist/SSMStateProvider-B0Hu1MKZ.mjs.map +1 -0
  22. package/dist/{SSMStateProvider-DyX8s9HI.cjs → SSMStateProvider-VrQ-yeqd.cjs} +17 -9
  23. package/dist/SSMStateProvider-VrQ-yeqd.cjs.map +1 -0
  24. package/dist/{backup-provisioner-BrsHwYG0.cjs → backup-provisioner-BmhIO_Yr.cjs} +21 -19
  25. package/dist/backup-provisioner-BmhIO_Yr.cjs.map +1 -0
  26. package/dist/{backup-provisioner-Bgj5Vi_L.mjs → backup-provisioner-DIVCbfee.mjs} +10 -7
  27. package/dist/backup-provisioner-DIVCbfee.mjs.map +1 -0
  28. package/dist/{bundler-BY1OmV1e.cjs → bundler-CYF5mWi9.cjs} +10 -28
  29. package/dist/bundler-CYF5mWi9.cjs.map +1 -0
  30. package/dist/{bundler-Be8Zg4Wd.mjs → bundler-D9IPNvDt.mjs} +9 -26
  31. package/dist/bundler-D9IPNvDt.mjs.map +1 -0
  32. package/dist/{config-CzWnfcXM.mjs → config-BH3Ki69F.mjs} +49 -89
  33. package/dist/config-BH3Ki69F.mjs.map +1 -0
  34. package/dist/{config-BholeD-0.cjs → config-URVD4bTj.cjs} +101 -148
  35. package/dist/config-URVD4bTj.cjs.map +1 -0
  36. package/dist/config.cjs +5 -5
  37. package/dist/config.d.cts +25 -17
  38. package/dist/config.d.cts.map +1 -1
  39. package/dist/config.d.mts +25 -17
  40. package/dist/config.d.mts.map +1 -1
  41. package/dist/config.mjs +3 -5
  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 +3 -3
  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-CAlFgYec.mjs → discover-CMxesskG.mjs} +66 -22
  79. package/dist/discover-CMxesskG.mjs.map +1 -0
  80. package/dist/{discover-DTmFeloL.cjs → discover-CroTIm0K.cjs} +117 -66
  81. package/dist/discover-CroTIm0K.cjs.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/github-B2fis34P.cjs +216 -0
  87. package/dist/github-B2fis34P.cjs.map +1 -0
  88. package/dist/github-BrDmlm1x.mjs +216 -0
  89. package/dist/github-BrDmlm1x.mjs.map +1 -0
  90. package/dist/{index-CHB4tSzX.d.cts → index-p89EzILa.d.mts} +4 -23
  91. package/dist/index-p89EzILa.d.mts.map +1 -0
  92. package/dist/{index-BThUzEIp.d.mts → index-rU9u761a.d.cts} +4 -23
  93. package/dist/index-rU9u761a.d.cts.map +1 -0
  94. package/dist/index.cjs +6028 -4452
  95. package/dist/index.cjs.map +1 -1
  96. package/dist/index.d.cts +1 -1
  97. package/dist/index.d.mts +1 -1
  98. package/dist/index.mjs +5922 -4367
  99. package/dist/index.mjs.map +1 -1
  100. package/dist/migrate-BuCx7tIv.cjs +498 -0
  101. package/dist/migrate-BuCx7tIv.cjs.map +1 -0
  102. package/dist/migrate-CBICVMAi.mjs +493 -0
  103. package/dist/migrate-CBICVMAi.mjs.map +1 -0
  104. package/dist/openapi.cjs +197 -8
  105. package/dist/openapi.cjs.map +1 -0
  106. package/dist/openapi.d.cts +47 -14
  107. package/dist/openapi.d.cts.map +1 -1
  108. package/dist/openapi.d.mts +47 -14
  109. package/dist/openapi.d.mts.map +1 -1
  110. package/dist/openapi.mjs +191 -5
  111. package/dist/openapi.mjs.map +1 -0
  112. package/dist/ready-CvP3JVEw.mjs +355 -0
  113. package/dist/ready-CvP3JVEw.mjs.map +1 -0
  114. package/dist/ready-DXtNfk7v.cjs +390 -0
  115. package/dist/ready-DXtNfk7v.cjs.map +1 -0
  116. package/dist/reconcile/public.cjs +4 -4
  117. package/dist/reconcile/public.d.cts +27 -26
  118. package/dist/reconcile/public.d.cts.map +1 -1
  119. package/dist/reconcile/public.d.mts +27 -26
  120. package/dist/reconcile/public.d.mts.map +1 -1
  121. package/dist/reconcile/public.mjs +3 -4
  122. package/dist/reconcile-BxZTV2vl.cjs +332 -0
  123. package/dist/reconcile-BxZTV2vl.cjs.map +1 -0
  124. package/dist/reconcile-yNq6Shau.mjs +279 -0
  125. package/dist/reconcile-yNq6Shau.mjs.map +1 -0
  126. package/dist/rolldown-runtime-BhDjJH2R.mjs +15 -0
  127. package/dist/{chunk-CUT6urMc.cjs → rolldown-runtime-C0BPl7ul.cjs} +23 -10
  128. package/dist/ssm-BKN1Cg4z.mjs +60 -0
  129. package/dist/ssm-BKN1Cg4z.mjs.map +1 -0
  130. package/dist/ssm-FxeSAt35.cjs +60 -0
  131. package/dist/ssm-FxeSAt35.cjs.map +1 -0
  132. package/dist/{storage-Bi24WfoW.mjs → storage-BjTLjDDp.mjs} +22 -22
  133. package/dist/storage-BjTLjDDp.mjs.map +1 -0
  134. package/dist/{storage-BJmzYxt8.cjs → storage-C2JC31V9.cjs} +65 -84
  135. package/dist/storage-C2JC31V9.cjs.map +1 -0
  136. package/dist/types-CzK6hsXP.d.mts +6286 -0
  137. package/dist/types-CzK6hsXP.d.mts.map +1 -0
  138. package/dist/types-DOOAevjG.d.cts +6287 -0
  139. package/dist/types-DOOAevjG.d.cts.map +1 -0
  140. package/dist/vitest.cjs +61 -0
  141. package/dist/vitest.cjs.map +1 -0
  142. package/dist/vitest.d.cts +28 -0
  143. package/dist/vitest.d.cts.map +1 -0
  144. package/dist/vitest.d.mts +28 -0
  145. package/dist/vitest.d.mts.map +1 -0
  146. package/dist/vitest.mjs +61 -0
  147. package/dist/vitest.mjs.map +1 -0
  148. package/dist/workspace/index.cjs +3 -4
  149. package/dist/workspace/index.d.cts +3 -3
  150. package/dist/workspace/index.d.mts +3 -3
  151. package/dist/workspace/index.mjs +2 -3
  152. package/dist/workspace-Bav3TVrP.cjs +6710 -0
  153. package/dist/workspace-Bav3TVrP.cjs.map +1 -0
  154. package/dist/{credentials-DQmbRnr1.cjs → workspace-BhiMkRuA.cjs} +2076 -1963
  155. package/dist/workspace-BhiMkRuA.cjs.map +1 -0
  156. package/dist/{credentials-BZcp3CGx.mjs → workspace-C97QUCIf.mjs} +1957 -1837
  157. package/dist/workspace-C97QUCIf.mjs.map +1 -0
  158. package/dist/workspace-T4IVGSoB.mjs +6538 -0
  159. package/dist/workspace-T4IVGSoB.mjs.map +1 -0
  160. package/package.json +45 -38
  161. package/dist/CachedStateProvider-BLo7zv7S.cjs +0 -3
  162. package/dist/CachedStateProvider-BxoAm-B2.mjs +0 -3
  163. package/dist/CachedStateProvider-CqPdW7CB.cjs +0 -60
  164. package/dist/CachedStateProvider-CqPdW7CB.cjs.map +0 -1
  165. package/dist/CachedStateProvider-DTniehMP.mjs +0 -54
  166. package/dist/CachedStateProvider-DTniehMP.mjs.map +0 -1
  167. package/dist/HostingerProvider-Cft7lEYr.mjs.map +0 -1
  168. package/dist/HostingerProvider-h3EbEp-Z.cjs.map +0 -1
  169. package/dist/LocalStateProvider-Bn6tS-oL.mjs.map +0 -1
  170. package/dist/LocalStateProvider-Db9SEjyH.cjs.map +0 -1
  171. package/dist/Route53Provider-RdpUDJQk.mjs.map +0 -1
  172. package/dist/Route53Provider-di2fMM5N.cjs.map +0 -1
  173. package/dist/SSMStateProvider-BRt2py-A.mjs.map +0 -1
  174. package/dist/SSMStateProvider-DyX8s9HI.cjs.map +0 -1
  175. package/dist/backup-provisioner-Bgj5Vi_L.mjs.map +0 -1
  176. package/dist/backup-provisioner-BrsHwYG0.cjs.map +0 -1
  177. package/dist/bundler-BY1OmV1e.cjs.map +0 -1
  178. package/dist/bundler-Be8Zg4Wd.mjs.map +0 -1
  179. package/dist/chunk-Duj1WY3L.mjs +0 -7
  180. package/dist/config-BholeD-0.cjs.map +0 -1
  181. package/dist/config-CzWnfcXM.mjs.map +0 -1
  182. package/dist/credentials-B5zRHdAl.mjs +0 -141
  183. package/dist/credentials-B5zRHdAl.mjs.map +0 -1
  184. package/dist/credentials-BZcp3CGx.mjs.map +0 -1
  185. package/dist/credentials-BapzjyV5.cjs +0 -195
  186. package/dist/credentials-BapzjyV5.cjs.map +0 -1
  187. package/dist/credentials-DQmbRnr1.cjs.map +0 -1
  188. package/dist/discover-CAlFgYec.mjs.map +0 -1
  189. package/dist/discover-DTmFeloL.cjs.map +0 -1
  190. package/dist/dokploy-api-BS2xnJLZ.mjs +0 -3
  191. package/dist/dokploy-api-BsVH0y_s.cjs +0 -718
  192. package/dist/dokploy-api-BsVH0y_s.cjs.map +0 -1
  193. package/dist/dokploy-api-BuxDRo3l.cjs +0 -3
  194. package/dist/dokploy-api-aTFPz7_4.mjs +0 -706
  195. package/dist/dokploy-api-aTFPz7_4.mjs.map +0 -1
  196. package/dist/emit-CbcRolsa.cjs.map +0 -1
  197. package/dist/emit-CiZS_5Ub.mjs.map +0 -1
  198. package/dist/encryption-C6jaU0hE.cjs +0 -54
  199. package/dist/encryption-C6jaU0hE.cjs.map +0 -1
  200. package/dist/encryption-CHzzeR8a.cjs +0 -4
  201. package/dist/encryption-CQUncu7v.mjs +0 -3
  202. package/dist/encryption-D-abyhZx.mjs +0 -42
  203. package/dist/encryption-D-abyhZx.mjs.map +0 -1
  204. package/dist/fullstack-secrets-C-GGohke.cjs +0 -111
  205. package/dist/fullstack-secrets-C-GGohke.cjs.map +0 -1
  206. package/dist/fullstack-secrets-D1o9-G5l.mjs +0 -87
  207. package/dist/fullstack-secrets-D1o9-G5l.mjs.map +0 -1
  208. package/dist/generator-CNzBw7g5.cjs +0 -289
  209. package/dist/generator-CNzBw7g5.cjs.map +0 -1
  210. package/dist/generator-VE2JrFlY.mjs +0 -253
  211. package/dist/generator-VE2JrFlY.mjs.map +0 -1
  212. package/dist/index-BThUzEIp.d.mts.map +0 -1
  213. package/dist/index-CHB4tSzX.d.cts.map +0 -1
  214. package/dist/openapi-CY9xFkTH.mjs.map +0 -1
  215. package/dist/openapi-c9bpieI5.cjs.map +0 -1
  216. package/dist/openapi-react-query-Byltvm_7.mjs +0 -167
  217. package/dist/openapi-react-query-Byltvm_7.mjs.map +0 -1
  218. package/dist/openapi-react-query-CmJ1xDbn.cjs +0 -173
  219. package/dist/openapi-react-query-CmJ1xDbn.cjs.map +0 -1
  220. package/dist/openapi-react-query.cjs +0 -4
  221. package/dist/openapi-react-query.d.cts +0 -11
  222. package/dist/openapi-react-query.d.cts.map +0 -1
  223. package/dist/openapi-react-query.d.mts +0 -11
  224. package/dist/openapi-react-query.d.mts.map +0 -1
  225. package/dist/openapi-react-query.mjs +0 -4
  226. package/dist/reconcile-CFs8C_1a.mjs +0 -37
  227. package/dist/reconcile-CFs8C_1a.mjs.map +0 -1
  228. package/dist/reconcile-D0pimNiy.cjs +0 -37
  229. package/dist/reconcile-D0pimNiy.cjs.map +0 -1
  230. package/dist/setup-Bc73t0ve.mjs +0 -443
  231. package/dist/setup-Bc73t0ve.mjs.map +0 -1
  232. package/dist/setup-C48C9hto.cjs +0 -473
  233. package/dist/setup-C48C9hto.cjs.map +0 -1
  234. package/dist/setup-DCuudnCl.mjs +0 -11
  235. package/dist/setup-fG_ivuxO.cjs +0 -11
  236. package/dist/storage-BJmzYxt8.cjs.map +0 -1
  237. package/dist/storage-BM9hGpgv.cjs +0 -7
  238. package/dist/storage-Bi24WfoW.mjs.map +0 -1
  239. package/dist/storage-CYlGwWTj.mjs +0 -3
  240. package/dist/sync-CmEuNZsB.mjs +0 -76
  241. package/dist/sync-CmEuNZsB.mjs.map +0 -1
  242. package/dist/sync-D306yOWu.cjs +0 -4
  243. package/dist/sync-SizaChmC.cjs +0 -93
  244. package/dist/sync-SizaChmC.cjs.map +0 -1
  245. package/dist/sync-hOqAWHR6.mjs +0 -3
  246. package/dist/types-C-arnQ1r.d.mts +0 -2184
  247. package/dist/types-C-arnQ1r.d.mts.map +0 -1
  248. package/dist/types-abJQuk7m.d.cts +0 -2184
  249. package/dist/types-abJQuk7m.d.cts.map +0 -1
  250. package/dist/workspace-7FqprxuJ.mjs +0 -4323
  251. package/dist/workspace-7FqprxuJ.mjs.map +0 -1
  252. package/dist/workspace-BO_KWohI.cjs +0 -9
  253. package/dist/workspace-DK4WWJIn.mjs +0 -8
  254. package/dist/workspace-XvqO9jIv.cjs +0 -4472
  255. package/dist/workspace-XvqO9jIv.cjs.map +0 -1
@@ -1,8 +1,6 @@
1
- import { CacheBackend, EmailBackend } from "../types-C-arnQ1r.mjs";
1
+ import { n as EmailBackend, t as CacheBackend } from "../types-CzK6hsXP.mjs";
2
2
  import { ConstructManifest, Declaration, RouteInfo } from "@geekmidas/manifest";
3
-
4
3
  //#region src/reconcile/discover.d.ts
5
-
6
4
  /** The construct face discovery needs: an id, and the ability to declare. */
7
5
  interface Declarable {
8
6
  id: string;
@@ -15,7 +13,7 @@ interface Declarable {
15
13
  * `service` is still a construct, and requiring one would exclude the kinds that
16
14
  * own no address.
17
15
  */
18
- declare function isDeclarable(value: unknown): value is Declarable;
16
+ export declare function isDeclarable(value: unknown): value is Declarable;
19
17
  interface DiscoverOptions {
20
18
  /** The glob(s) to search. One pattern, not one per kind. */
21
19
  patterns: string | readonly string[];
@@ -39,6 +37,18 @@ interface DiscoverOptions {
39
37
  * caller, which wants the manifest and nothing else, is unchanged.
40
38
  */
41
39
  sources?: Record<string, ConstructSource>;
40
+ /**
41
+ * Filled in, when provided, with the ids each owner's runnables declared an
42
+ * edge to — keyed by the surface an endpoint was built from, or the worker
43
+ * a cron or subscriber was.
44
+ *
45
+ * A runnable is not a declaration: a surface's endpoints are found by the
46
+ * glob, not listed by the surface, so its node says `endpoints: []` until a
47
+ * build folds the routes in. Anything deciding what an app's process reaches
48
+ * — which keys its container is given — needs those edges before any build,
49
+ * and discovery is already importing the files they are in.
50
+ */
51
+ runnables?: Record<string, string[]>;
42
52
  }
43
53
  /** Where a construct was declared, and under what name. */
44
54
  interface ConstructSource {
@@ -46,6 +56,13 @@ interface ConstructSource {
46
56
  file: string;
47
57
  /** The name it was exported as — what an import statement has to say. */
48
58
  exportName: string;
59
+ /**
60
+ * The exported construct itself.
61
+ *
62
+ * What a declaration cannot say — whether it serves itself — the object can
63
+ * be asked, and discovery already imported it.
64
+ */
65
+ construct: unknown;
49
66
  }
50
67
  /**
51
68
  * Build the construct manifest for a project.
@@ -55,12 +72,11 @@ interface ConstructSource {
55
72
  *
56
73
  * @throws {DuplicateConstruct} when two exports claim one id.
57
74
  */
58
- declare function discover(options: DiscoverOptions): Promise<ConstructManifest>;
59
- /** Two constructs claiming one id. */
75
+ export declare function discover(options: DiscoverOptions): Promise<ConstructManifest>;
60
76
  //#endregion
61
77
  //#region src/reconcile/emit.d.ts
62
78
  /** Where the build writes it, relative to the app root. */
63
- declare const MANIFEST_PATH = ".gkm/manifest.ts";
79
+ export declare const MANIFEST_PATH = ".gkm/manifest.ts";
64
80
  /**
65
81
  * Fold the build's generated routes into the surface that serves them.
66
82
  *
@@ -89,37 +105,22 @@ declare const MANIFEST_PATH = ".gkm/manifest.ts";
89
105
  * document's contents depend on which `--provider` ran last. A manifest must not
90
106
  * do that.
91
107
  */
92
- declare function withRoutes(manifest: ConstructManifest, routes: readonly RouteInfo[], options: {
108
+ export declare function withRoutes(manifest: ConstructManifest, routes: readonly RouteInfo[], options: {
93
109
  perRoute: boolean;
94
110
  }): ConstructManifest;
95
- /**
96
- * Fold in the compute the build generated: functions, crons, queue workers and
97
- * topic subscribers.
98
- *
99
- * All four are named by their *export*, the same way an endpoint's handler is —
100
- * `CronGenerator` uses the export key as the name — so none of them can declare
101
- * themselves and all of them are the build's to add. That is why a `Function`
102
- * has no `declare()` and never will.
103
- *
104
- * A worker and a subscriber **nest** inside the queue or topic that triggers
105
- * them, because position carries the trigger. A function and a cron are
106
- * top-level, because nothing triggers them but a caller or a clock.
107
- */
108
-
109
111
  /**
110
112
  * The manifest as TypeScript source.
111
113
  *
112
114
  * Pure, so what gets written can be asserted without touching a filesystem.
113
115
  */
114
- declare function manifestModule(manifest: ConstructManifest, backends?: Backends): string;
116
+ export declare function manifestModule(manifest: ConstructManifest, backends?: Backends): string;
115
117
  /** Write it where the deploy config expects to import it from. */
116
- declare function writeManifestModule(manifest: ConstructManifest, appRoot: string, backends?: Backends): Promise<string>;
118
+ export declare function writeManifestModule(manifest: ConstructManifest, appRoot: string, backends?: Backends): Promise<string>;
117
119
  /** The choices that are deployment config rather than declaration. */
118
120
  interface Backends {
119
121
  cache?: CacheBackend;
120
122
  email?: EmailBackend;
121
123
  }
122
- //# sourceMappingURL=emit.d.ts.map
123
124
  //#endregion
124
- export { DiscoverOptions, MANIFEST_PATH, discover, isDeclarable, manifestModule, withRoutes, writeManifestModule };
125
+ export type { DiscoverOptions };
125
126
  //# sourceMappingURL=public.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"public.d.mts","names":[],"sources":["../../src/reconcile/discover.ts","../../src/reconcile/emit.ts"],"sourcesContent":[],"mappings":";;;;;;AAiGU,UAnEA,UAAA,CAmEA;;aAjEE;;ACKZ;AA8BA;;;;;AAIoB;AA2JJ,iBDxLA,YAAA,CCwLc,KAAA,EAAA,OAAA,CAAA,EAAA,KAAA,IDxLyB,UCwLzB;AAAA,UD5Kb,eAAA,CC4Ka;EAAA;EACF,QACjB,EAAA,MAAA,GAAA,SAAA,MAAA,EAAA;EAAa,GAAA,CAAA,EAAA,MAAA;EA8BF;;;;;AAIZ;EAUO,SAAA,CAAA,EAAQ,OAAA;EAAA;;;AAEJ;;;;;;;;YDtMV,eAAe;;;UAIT,eAAA;;;;;;;;;;;;;;iBAeK,QAAA,UACZ,kBACP,QAAQ;;;;AC5DX;AA8BgB,cA9BH,aAAA,GA8Ba,kBAAA;;;;;AAIN;AA2JpB;;;;AAEwB;AA8BxB;;;;;AAIU;AAUV;;;;AAEqB;;;;;;;;iBA/ML,UAAA,WACL,oCACO;;IAEf;;;;;;;;;;;;;;;;;;;;iBA2Ja,cAAA,WACL,8BACA;;iBA8BW,mBAAA,WACX,+CAEA,WACR;;UAUc,QAAA;UACR;UACA"}
1
+ {"version":3,"file":"public.d.mts","names":[],"sources":["../../src/reconcile/discover.ts","../../src/reconcile/emit.ts"],"mappings":";;;;UA8BU;EACT;EACA,WAAW;;;;;;;;;wBAUI,aAAa,iBAAiB,SAAS;UAYtC;;EAEhB;EACA;;;;;;;EAOA;;;;;;;;;;;;EAYA,UAAU,eAAe;;;;;;;;;;;;EAYzB,YAAY;;;UAII;;EAEhB;;EAEA;;;;;;;EAOA;;;;;;;;;;wBAWqB,SACrB,SAAS,kBACP,QAAQ;;;;qBC/EE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;wBA8BG,WACf,UAAU,mBACV,iBAAiB,aACjB;EAAW;IACT;;;;;;wBA2Ja,eACf,UAAU,mBACV,WAAU;;wBA8BW,oBACrB,UAAU,mBACV,iBACA,WAAU,WACR;;UAUc;EAChB,QAAQ;EACR,QAAQ"}
@@ -1,4 +1,3 @@
1
- import { discover, isDeclarable } from "../discover-CAlFgYec.mjs";
2
- import { MANIFEST_PATH, manifestModule, withRoutes, writeManifestModule } from "../emit-CiZS_5Ub.mjs";
3
-
4
- export { MANIFEST_PATH, discover, isDeclarable, manifestModule, withRoutes, writeManifestModule };
1
+ import { r as isDeclarable, t as discover } from "../discover-CMxesskG.mjs";
2
+ import { a as writeManifestModule, i as withRoutes, n as manifestModule, t as MANIFEST_PATH } from "../emit-Bzq7JsMP.mjs";
3
+ export { MANIFEST_PATH, discover, isDeclarable, manifestModule, withRoutes, writeManifestModule };
@@ -0,0 +1,332 @@
1
+ const require_rolldown_runtime = require("./rolldown-runtime-C0BPl7ul.cjs");
2
+ let node_fs_promises = require("node:fs/promises");
3
+ let node_path = require("node:path");
4
+ let node_crypto = require("node:crypto");
5
+ //#region src/secrets/generator.ts
6
+ /**
7
+ * Generate a secure random password using URL-safe base64 characters.
8
+ * @param length Password length (default: 32)
9
+ */
10
+ function generateSecurePassword(length = 32) {
11
+ return (0, node_crypto.randomBytes)(Math.ceil(length * 3 / 4)).toString("base64url").slice(0, length);
12
+ }
13
+ /** Default service configurations (localhost for local dev via Docker port mapping) */
14
+ const SERVICE_DEFAULTS = {
15
+ postgres: {
16
+ host: "localhost",
17
+ port: 5432,
18
+ username: "app",
19
+ database: "app"
20
+ },
21
+ redis: {
22
+ host: "localhost",
23
+ port: 6379,
24
+ username: "default"
25
+ },
26
+ minio: {
27
+ host: "localhost",
28
+ port: 9e3,
29
+ username: "app",
30
+ bucket: "app"
31
+ },
32
+ mailpit: {
33
+ host: "localhost",
34
+ port: 1025,
35
+ username: "app"
36
+ },
37
+ localstack: {
38
+ host: "localhost",
39
+ port: 4566,
40
+ username: "localstack",
41
+ region: "us-east-1"
42
+ }
43
+ };
44
+ /** Default credentials for pgboss (not a Docker service, reuses postgres) */
45
+ const PGBOSS_DEFAULTS = {
46
+ host: "localhost",
47
+ port: 5432,
48
+ username: "pgboss",
49
+ database: "app"
50
+ };
51
+ /**
52
+ * Generate credentials for a specific service.
53
+ */
54
+ function generateServiceCredentials(service) {
55
+ return {
56
+ ...SERVICE_DEFAULTS[service],
57
+ password: generateSecurePassword()
58
+ };
59
+ }
60
+ /**
61
+ * Generate credentials for multiple services.
62
+ */
63
+ function generateServicesCredentials(services) {
64
+ const result = {};
65
+ for (const service of services) result[service] = generateServiceCredentials(service);
66
+ return result;
67
+ }
68
+ /**
69
+ * Generate connection URL for PostgreSQL.
70
+ */
71
+ function generatePostgresUrl(creds) {
72
+ const { username, password, host, port, database } = creds;
73
+ return `postgresql://${username}:${encodeURIComponent(password)}@${host}:${port}/${database}`;
74
+ }
75
+ /**
76
+ * Generate connection URL for Redis.
77
+ */
78
+ function generateRedisUrl(creds) {
79
+ const { password, host, port } = creds;
80
+ return `redis://:${encodeURIComponent(password)}@${host}:${port}`;
81
+ }
82
+ /**
83
+ * Generate endpoint URL for MinIO (S3-compatible).
84
+ */
85
+ function generateMinioEndpoint(creds) {
86
+ const { host, port } = creds;
87
+ return `http://${host}:${port}`;
88
+ }
89
+ /**
90
+ * Generate connection URL for pg-boss (uses PostgreSQL protocol).
91
+ * Format: pgboss://user:pass@host:port/db?schema=pgboss
92
+ */
93
+ function generatePgBossUrl(creds) {
94
+ const { username, password, host, port, database } = creds;
95
+ return `pgboss://${username}:${encodeURIComponent(password)}@${host}:${port}/${database}?schema=pgboss`;
96
+ }
97
+ /**
98
+ * Generate connection URLs from service credentials.
99
+ */
100
+ function generateConnectionUrls(services) {
101
+ const urls = {};
102
+ if (services.postgres) urls.DATABASE_URL = generatePostgresUrl(services.postgres);
103
+ if (services.redis) urls.REDIS_URL = generateRedisUrl(services.redis);
104
+ if (services.minio) urls.STORAGE_ENDPOINT = generateMinioEndpoint(services.minio);
105
+ if (services.pgboss) {
106
+ const pgbossUrl = generatePgBossUrl(services.pgboss);
107
+ urls.EVENT_PUBLISHER_CONNECTION_STRING = pgbossUrl;
108
+ urls.EVENT_SUBSCRIBER_CONNECTION_STRING = pgbossUrl;
109
+ }
110
+ if (services.mailpit) {
111
+ urls.SMTP_HOST = services.mailpit.host;
112
+ urls.SMTP_PORT = String(services.mailpit.port);
113
+ }
114
+ return urls;
115
+ }
116
+ /**
117
+ * Create a new StageSecrets object with generated credentials.
118
+ * @param stage - The deployment stage (e.g., 'development', 'production')
119
+ * @param services - List of services to generate credentials for
120
+ * @param options - Optional configuration
121
+ * @param options.projectName - Project name used to derive the database name (e.g., 'myapp' → 'myapp_dev')
122
+ */
123
+ function createStageSecrets(stage, services, options) {
124
+ const now = (/* @__PURE__ */ new Date()).toISOString();
125
+ const serviceCredentials = generateServicesCredentials(services);
126
+ if (options?.projectName) {
127
+ if (serviceCredentials.postgres) serviceCredentials.postgres.database = `${options.projectName.replace(/-/g, "_")}_dev`;
128
+ if (serviceCredentials.minio) {
129
+ serviceCredentials.minio.bucket = options.projectName;
130
+ serviceCredentials.minio.username = options.projectName;
131
+ }
132
+ }
133
+ if (serviceCredentials.postgres && !serviceCredentials.pgboss) serviceCredentials.pgboss = {
134
+ ...PGBOSS_DEFAULTS,
135
+ password: generateSecurePassword(),
136
+ host: serviceCredentials.postgres.host,
137
+ port: serviceCredentials.postgres.port,
138
+ database: serviceCredentials.postgres.database
139
+ };
140
+ return {
141
+ stage,
142
+ createdAt: now,
143
+ updatedAt: now,
144
+ services: serviceCredentials,
145
+ urls: generateConnectionUrls(serviceCredentials),
146
+ custom: {}
147
+ };
148
+ }
149
+ /**
150
+ * Rotate password for a specific service.
151
+ */
152
+ function rotateServicePassword(secrets, service) {
153
+ const currentCreds = secrets.services[service];
154
+ if (!currentCreds) throw new Error(`Service "${service}" not configured in secrets`);
155
+ const newCreds = {
156
+ ...currentCreds,
157
+ password: generateSecurePassword()
158
+ };
159
+ const newServices = {
160
+ ...secrets.services,
161
+ [service]: newCreds
162
+ };
163
+ return {
164
+ ...secrets,
165
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
166
+ services: newServices,
167
+ urls: generateConnectionUrls(newServices)
168
+ };
169
+ }
170
+ //#endregion
171
+ //#region src/setup/fullstack-secrets.ts
172
+ /**
173
+ * Generate a secure random password for database users.
174
+ * Uses a combination of timestamp and random bytes for uniqueness.
175
+ */
176
+ function generateDbPassword() {
177
+ return `${Date.now().toString(36)}${Math.random().toString(36).slice(2)}${Math.random().toString(36).slice(2)}`;
178
+ }
179
+ /**
180
+ * Generate database URL for an app.
181
+ * All apps connect to the same database, but use different users/schemas.
182
+ */
183
+ function generateDbUrl(appName, password, projectName, host = "localhost", port = 5432) {
184
+ return `postgresql://${appName.replace(/-/g, "_")}:${password}@${host}:${port}/${`${projectName.replace(/-/g, "_")}_dev`}`;
185
+ }
186
+ /**
187
+ * Generate fullstack-aware custom secrets for a workspace.
188
+ *
189
+ * Generates:
190
+ * - Common secrets: PORT, LOG_LEVEL, JWT_SECRET (no `NODE_ENV` — the command
191
+ * decides that; see `gkm init`)
192
+ * - Per-app database passwords and URLs for backend apps with db service
193
+ * - Better-auth secrets for apps using the better-auth framework
194
+ */
195
+ function generateFullstackCustomSecrets(workspace, containers = []) {
196
+ const hasDb = containers.includes("postgres");
197
+ const customs = {
198
+ PORT: "3000",
199
+ LOG_LEVEL: "debug",
200
+ JWT_SECRET: `dev-${Date.now()}-${Math.random().toString(36).slice(2)}`
201
+ };
202
+ if (!hasDb) return customs;
203
+ const frontendPorts = [];
204
+ for (const [appName, appConfig] of Object.entries(workspace.apps)) {
205
+ if (appConfig.type === "web") {
206
+ frontendPorts.push(appConfig.port);
207
+ const upperName = appName.toUpperCase();
208
+ customs[`${upperName}_URL`] = `http://localhost:${appConfig.port}`;
209
+ continue;
210
+ }
211
+ if (appConfig.type === "mobile") continue;
212
+ const password = generateDbPassword();
213
+ const upperName = appName.toUpperCase();
214
+ customs[`${upperName}_DATABASE_URL`] = generateDbUrl(appName, password, workspace.name);
215
+ customs[`${upperName}_DB_PASSWORD`] = password;
216
+ if (appConfig.framework === "better-auth") {
217
+ customs.AUTH_PORT = String(appConfig.port);
218
+ customs.AUTH_URL = `http://localhost:${appConfig.port}`;
219
+ customs.BETTER_AUTH_SECRET = `better-auth-${Date.now()}-${generateSecurePassword(16)}`;
220
+ customs.BETTER_AUTH_URL = `http://localhost:${appConfig.port}`;
221
+ }
222
+ }
223
+ if (customs.BETTER_AUTH_SECRET) customs.BETTER_AUTH_TRUSTED_ORIGINS = Object.values(workspace.apps).map((a) => a.port).map((p) => `http://localhost:${p}`).join(",");
224
+ return customs;
225
+ }
226
+ /**
227
+ * Extract *_DB_PASSWORD keys from secrets and write docker/.env.
228
+ *
229
+ * The docker/.env file contains database passwords that the PostgreSQL
230
+ * init script reads to create per-app database users.
231
+ */
232
+ async function writeDockerEnvFromSecrets(secrets, workspaceRoot) {
233
+ const dbPasswordEntries = Object.entries(secrets.custom).filter(([key]) => key.endsWith("_DB_PASSWORD"));
234
+ if (secrets.services.pgboss && !dbPasswordEntries.some(([key]) => key === "PGBOSS_DB_PASSWORD")) dbPasswordEntries.push(["PGBOSS_DB_PASSWORD", secrets.services.pgboss.password]);
235
+ if (dbPasswordEntries.length === 0) return;
236
+ const envContent = `# Auto-generated docker environment file
237
+ # Contains database passwords for docker-compose postgres init
238
+ # This file is gitignored - do not commit to version control
239
+ ${dbPasswordEntries.map(([key, value]) => `${key}=${value}`).join("\n")}
240
+ `;
241
+ const envPath = (0, node_path.join)(workspaceRoot, "docker", ".env");
242
+ await (0, node_fs_promises.mkdir)((0, node_path.dirname)(envPath), { recursive: true });
243
+ await (0, node_fs_promises.writeFile)(envPath, envContent);
244
+ }
245
+ //#endregion
246
+ //#region src/secrets/reconcile.ts
247
+ var reconcile_exports = /* @__PURE__ */ require_rolldown_runtime.__exportAll({ reconcileMissingSecrets: () => reconcileMissingSecrets });
248
+ /**
249
+ * Reconcile missing custom secrets for a workspace.
250
+ *
251
+ * Compares current secrets against what generateFullstackCustomSecrets()
252
+ * would produce and backfills any missing keys without overwriting
253
+ * existing values.
254
+ *
255
+ * @returns ReconcileResult if keys were added, null if secrets are up-to-date
256
+ */
257
+ function reconcileMissingSecrets(secrets, workspace, containers = []) {
258
+ if (!(Object.keys(workspace.apps).length > 1)) return null;
259
+ const expectedCustom = generateFullstackCustomSecrets(workspace, containers);
260
+ const addedKeys = [];
261
+ const mergedCustom = { ...secrets.custom };
262
+ for (const [key, value] of Object.entries(expectedCustom)) if (!(key in mergedCustom)) {
263
+ mergedCustom[key] = value;
264
+ addedKeys.push(key);
265
+ }
266
+ if (addedKeys.length === 0) return null;
267
+ return {
268
+ secrets: {
269
+ ...secrets,
270
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
271
+ custom: mergedCustom
272
+ },
273
+ addedKeys
274
+ };
275
+ }
276
+ //#endregion
277
+ Object.defineProperty(exports, "createStageSecrets", {
278
+ enumerable: true,
279
+ get: function() {
280
+ return createStageSecrets;
281
+ }
282
+ });
283
+ Object.defineProperty(exports, "generateConnectionUrls", {
284
+ enumerable: true,
285
+ get: function() {
286
+ return generateConnectionUrls;
287
+ }
288
+ });
289
+ Object.defineProperty(exports, "generateFullstackCustomSecrets", {
290
+ enumerable: true,
291
+ get: function() {
292
+ return generateFullstackCustomSecrets;
293
+ }
294
+ });
295
+ Object.defineProperty(exports, "generateSecurePassword", {
296
+ enumerable: true,
297
+ get: function() {
298
+ return generateSecurePassword;
299
+ }
300
+ });
301
+ Object.defineProperty(exports, "generateServiceCredentials", {
302
+ enumerable: true,
303
+ get: function() {
304
+ return generateServiceCredentials;
305
+ }
306
+ });
307
+ Object.defineProperty(exports, "reconcileMissingSecrets", {
308
+ enumerable: true,
309
+ get: function() {
310
+ return reconcileMissingSecrets;
311
+ }
312
+ });
313
+ Object.defineProperty(exports, "reconcile_exports", {
314
+ enumerable: true,
315
+ get: function() {
316
+ return reconcile_exports;
317
+ }
318
+ });
319
+ Object.defineProperty(exports, "rotateServicePassword", {
320
+ enumerable: true,
321
+ get: function() {
322
+ return rotateServicePassword;
323
+ }
324
+ });
325
+ Object.defineProperty(exports, "writeDockerEnvFromSecrets", {
326
+ enumerable: true,
327
+ get: function() {
328
+ return writeDockerEnvFromSecrets;
329
+ }
330
+ });
331
+
332
+ //# sourceMappingURL=reconcile-BxZTV2vl.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"reconcile-BxZTV2vl.cjs","names":["randomBytes","join","mkdir","dirname","writeFile"],"sources":["../src/secrets/generator.ts","../src/setup/fullstack-secrets.ts","../src/secrets/reconcile.ts"],"sourcesContent":["import { randomBytes } from 'node:crypto';\nimport type {\n\tSecretServiceName,\n\tServiceCredentials,\n\tStageSecrets,\n} from './types';\n\n/**\n * Generate a secure random password using URL-safe base64 characters.\n * @param length Password length (default: 32)\n */\nexport function generateSecurePassword(length = 32): string {\n\treturn randomBytes(Math.ceil((length * 3) / 4))\n\t\t.toString('base64url')\n\t\t.slice(0, length);\n}\n\n/** Default service configurations (localhost for local dev via Docker port mapping) */\nconst SERVICE_DEFAULTS: Record<\n\tSecretServiceName,\n\tOmit<ServiceCredentials, 'password'>\n> = {\n\tpostgres: {\n\t\thost: 'localhost',\n\t\tport: 5432,\n\t\tusername: 'app',\n\t\tdatabase: 'app',\n\t},\n\tredis: {\n\t\thost: 'localhost',\n\t\tport: 6379,\n\t\tusername: 'default',\n\t},\n\tminio: {\n\t\thost: 'localhost',\n\t\tport: 9000,\n\t\tusername: 'app',\n\t\tbucket: 'app',\n\t},\n\tmailpit: {\n\t\thost: 'localhost',\n\t\tport: 1025,\n\t\tusername: 'app',\n\t},\n\tlocalstack: {\n\t\thost: 'localhost',\n\t\tport: 4566,\n\t\tusername: 'localstack',\n\t\tregion: 'us-east-1',\n\t},\n};\n\n/** Default credentials for pgboss (not a Docker service, reuses postgres) */\nconst PGBOSS_DEFAULTS: Omit<ServiceCredentials, 'password'> = {\n\thost: 'localhost',\n\tport: 5432,\n\tusername: 'pgboss',\n\tdatabase: 'app',\n};\n\n/**\n * Generate credentials for a specific service.\n */\nexport function generateServiceCredentials(\n\tservice: SecretServiceName,\n): ServiceCredentials {\n\tconst defaults = SERVICE_DEFAULTS[service];\n\treturn {\n\t\t...defaults,\n\t\tpassword: generateSecurePassword(),\n\t};\n}\n\n/**\n * Generate credentials for multiple services.\n */\nexport function generateServicesCredentials(\n\tservices: SecretServiceName[],\n): StageSecrets['services'] {\n\tconst result: StageSecrets['services'] = {};\n\n\tfor (const service of services) {\n\t\tresult[service] = generateServiceCredentials(service);\n\t}\n\n\treturn result;\n}\n\n/**\n * Generate connection URL for PostgreSQL.\n */\nexport function generatePostgresUrl(creds: ServiceCredentials): string {\n\tconst { username, password, host, port, database } = creds;\n\treturn `postgresql://${username}:${encodeURIComponent(password)}@${host}:${port}/${database}`;\n}\n\n/**\n * Generate connection URL for Redis.\n */\nexport function generateRedisUrl(creds: ServiceCredentials): string {\n\tconst { password, host, port } = creds;\n\treturn `redis://:${encodeURIComponent(password)}@${host}:${port}`;\n}\n\n/**\n * Generate endpoint URL for MinIO (S3-compatible).\n */\nexport function generateMinioEndpoint(creds: ServiceCredentials): string {\n\tconst { host, port } = creds;\n\treturn `http://${host}:${port}`;\n}\n\n/**\n * Generate a LocalStack-compatible access key ID.\n * Must start with 'LSIA' prefix and be at least 20 characters.\n * @see https://docs.localstack.cloud/aws/capabilities/config/credentials/\n */\nexport function generateLocalStackAccessKeyId(): string {\n\tconst suffix = randomBytes(12).toString('base64url').slice(0, 16);\n\treturn `LSIA${suffix}`;\n}\n\n/**\n * Generate connection URL for pg-boss (uses PostgreSQL protocol).\n * Format: pgboss://user:pass@host:port/db?schema=pgboss\n */\nexport function generatePgBossUrl(creds: ServiceCredentials): string {\n\tconst { username, password, host, port, database } = creds;\n\treturn `pgboss://${username}:${encodeURIComponent(password)}@${host}:${port}/${database}?schema=pgboss`;\n}\n\n/**\n * Generate connection URLs from service credentials.\n */\nexport function generateConnectionUrls(\n\tservices: StageSecrets['services'],\n): StageSecrets['urls'] {\n\tconst urls: StageSecrets['urls'] = {};\n\n\tif (services.postgres) {\n\t\turls.DATABASE_URL = generatePostgresUrl(services.postgres);\n\t}\n\n\tif (services.redis) {\n\t\turls.REDIS_URL = generateRedisUrl(services.redis);\n\t}\n\n\tif (services.minio) {\n\t\turls.STORAGE_ENDPOINT = generateMinioEndpoint(services.minio);\n\t}\n\n\t// A topic's or queue's own broker URL is reconcile's, derived from the\n\t// declaration. This pair is what a worker's crons schedule through.\n\tif (services.pgboss) {\n\t\tconst pgbossUrl = generatePgBossUrl(services.pgboss);\n\t\turls.EVENT_PUBLISHER_CONNECTION_STRING = pgbossUrl;\n\t\turls.EVENT_SUBSCRIBER_CONNECTION_STRING = pgbossUrl;\n\t}\n\n\tif (services.mailpit) {\n\t\turls.SMTP_HOST = services.mailpit.host;\n\t\turls.SMTP_PORT = String(services.mailpit.port);\n\t}\n\n\treturn urls;\n}\n\n/**\n * Generate LocalStack service credentials with LSIA-prefixed access key.\n */\nexport function generateLocalStackCredentials(): ServiceCredentials {\n\tconst defaults = SERVICE_DEFAULTS.localstack;\n\treturn {\n\t\t...defaults,\n\t\tpassword: generateSecurePassword(),\n\t\taccessKeyId: generateLocalStackAccessKeyId(),\n\t};\n}\n\n/**\n * Create a new StageSecrets object with generated credentials.\n * @param stage - The deployment stage (e.g., 'development', 'production')\n * @param services - List of services to generate credentials for\n * @param options - Optional configuration\n * @param options.projectName - Project name used to derive the database name (e.g., 'myapp' → 'myapp_dev')\n */\nexport function createStageSecrets(\n\tstage: string,\n\tservices: SecretServiceName[],\n\toptions?: { projectName?: string },\n): StageSecrets {\n\tconst now = new Date().toISOString();\n\tconst serviceCredentials = generateServicesCredentials(services);\n\n\t// Override service defaults with project-derived names if provided\n\tif (options?.projectName) {\n\t\tif (serviceCredentials.postgres) {\n\t\t\tserviceCredentials.postgres.database = `${options.projectName.replace(/-/g, '_')}_dev`;\n\t\t}\n\t\tif (serviceCredentials.minio) {\n\t\t\tserviceCredentials.minio.bucket = options.projectName;\n\t\t\tserviceCredentials.minio.username = options.projectName;\n\t\t}\n\t}\n\n\t// Always create pgboss credentials when postgres is available.\n\t// pgboss reuses postgres host/port/database but with a dedicated user,\n\t// so subscribers work out of the box without explicit events config.\n\tif (serviceCredentials.postgres && !serviceCredentials.pgboss) {\n\t\tserviceCredentials.pgboss = {\n\t\t\t...PGBOSS_DEFAULTS,\n\t\t\tpassword: generateSecurePassword(),\n\t\t\thost: serviceCredentials.postgres.host,\n\t\t\tport: serviceCredentials.postgres.port,\n\t\t\tdatabase: serviceCredentials.postgres.database,\n\t\t};\n\t}\n\n\tconst urls = generateConnectionUrls(serviceCredentials);\n\n\treturn {\n\t\tstage,\n\t\tcreatedAt: now,\n\t\tupdatedAt: now,\n\t\tservices: serviceCredentials,\n\t\turls,\n\t\tcustom: {},\n\t};\n}\n\n/**\n * Rotate password for a specific service.\n */\nexport function rotateServicePassword(\n\tsecrets: StageSecrets,\n\tservice: SecretServiceName,\n): StageSecrets {\n\tconst currentCreds = secrets.services[service];\n\tif (!currentCreds) {\n\t\tthrow new Error(`Service \"${service}\" not configured in secrets`);\n\t}\n\n\tconst newCreds: ServiceCredentials = {\n\t\t...currentCreds,\n\t\tpassword: generateSecurePassword(),\n\t};\n\n\tconst newServices = {\n\t\t...secrets.services,\n\t\t[service]: newCreds,\n\t};\n\n\treturn {\n\t\t...secrets,\n\t\tupdatedAt: new Date().toISOString(),\n\t\tservices: newServices,\n\t\turls: generateConnectionUrls(newServices),\n\t};\n}\n","import { mkdir, writeFile } from 'node:fs/promises';\nimport { dirname, join } from 'node:path';\nimport { generateSecurePassword } from '../secrets/generator.js';\nimport type { StageSecrets } from '../secrets/types.js';\nimport type { NormalizedWorkspace } from '../workspace/types.js';\n\n/**\n * Generate a secure random password for database users.\n * Uses a combination of timestamp and random bytes for uniqueness.\n */\nexport function generateDbPassword(): string {\n\treturn `${Date.now().toString(36)}${Math.random().toString(36).slice(2)}${Math.random().toString(36).slice(2)}`;\n}\n\n/**\n * Generate database URL for an app.\n * All apps connect to the same database, but use different users/schemas.\n */\nexport function generateDbUrl(\n\tappName: string,\n\tpassword: string,\n\tprojectName: string,\n\thost = 'localhost',\n\tport = 5432,\n): string {\n\tconst userName = appName.replace(/-/g, '_');\n\tconst dbName = `${projectName.replace(/-/g, '_')}_dev`;\n\treturn `postgresql://${userName}:${password}@${host}:${port}/${dbName}`;\n}\n\n/**\n * Generate fullstack-aware custom secrets for a workspace.\n *\n * Generates:\n * - Common secrets: PORT, LOG_LEVEL, JWT_SECRET (no `NODE_ENV` — the command\n * decides that; see `gkm init`)\n * - Per-app database passwords and URLs for backend apps with db service\n * - Better-auth secrets for apps using the better-auth framework\n */\nexport function generateFullstackCustomSecrets(\n\tworkspace: NormalizedWorkspace,\n\tcontainers: readonly string[] = [],\n): Record<string, string> {\n\t// A Postgres exists because something declared a database, not because\n\t// config carried a flag saying so.\n\tconst hasDb = containers.includes('postgres');\n\tconst customs: Record<string, string> = {\n\t\tPORT: '3000',\n\t\tLOG_LEVEL: 'debug',\n\t\tJWT_SECRET: `dev-${Date.now()}-${Math.random().toString(36).slice(2)}`,\n\t};\n\n\tif (!hasDb) {\n\t\treturn customs;\n\t}\n\n\t// Collect all frontend ports for trusted origins\n\tconst frontendPorts: number[] = [];\n\n\tfor (const [appName, appConfig] of Object.entries(workspace.apps)) {\n\t\tif (appConfig.type === 'web') {\n\t\t\tfrontendPorts.push(appConfig.port);\n\t\t\tconst upperName = appName.toUpperCase();\n\t\t\tcustoms[`${upperName}_URL`] = `http://localhost:${appConfig.port}`;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Mobile apps (Expo, etc.) don't run on a host port the backend\n\t\t// cares about for CORS, and don't need DB credentials.\n\t\tif (appConfig.type === 'mobile') {\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Backend apps with database: generate per-app DB passwords and URLs\n\t\tconst password = generateDbPassword();\n\t\tconst upperName = appName.toUpperCase();\n\n\t\tcustoms[`${upperName}_DATABASE_URL`] = generateDbUrl(\n\t\t\tappName,\n\t\t\tpassword,\n\t\t\tworkspace.name,\n\t\t);\n\t\tcustoms[`${upperName}_DB_PASSWORD`] = password;\n\n\t\t// Better-auth framework secrets\n\t\tif (appConfig.framework === 'better-auth') {\n\t\t\tcustoms.AUTH_PORT = String(appConfig.port);\n\t\t\tcustoms.AUTH_URL = `http://localhost:${appConfig.port}`;\n\t\t\tcustoms.BETTER_AUTH_SECRET = `better-auth-${Date.now()}-${generateSecurePassword(16)}`;\n\t\t\tcustoms.BETTER_AUTH_URL = `http://localhost:${appConfig.port}`;\n\t\t}\n\t}\n\n\t// Generate trusted origins for better-auth (all app ports)\n\tif (customs.BETTER_AUTH_SECRET) {\n\t\tconst allPorts = Object.values(workspace.apps).map((a) => a.port);\n\t\tcustoms.BETTER_AUTH_TRUSTED_ORIGINS = allPorts\n\t\t\t.map((p) => `http://localhost:${p}`)\n\t\t\t.join(',');\n\t}\n\n\treturn customs;\n}\n\n/**\n * Extract *_DB_PASSWORD keys from secrets and write docker/.env.\n *\n * The docker/.env file contains database passwords that the PostgreSQL\n * init script reads to create per-app database users.\n */\nexport async function writeDockerEnvFromSecrets(\n\tsecrets: StageSecrets,\n\tworkspaceRoot: string,\n): Promise<void> {\n\tconst dbPasswordEntries = Object.entries(secrets.custom).filter(([key]) =>\n\t\tkey.endsWith('_DB_PASSWORD'),\n\t);\n\n\t// Always include pgboss password when pgboss credentials exist\n\tif (\n\t\tsecrets.services.pgboss &&\n\t\t!dbPasswordEntries.some(([key]) => key === 'PGBOSS_DB_PASSWORD')\n\t) {\n\t\tdbPasswordEntries.push([\n\t\t\t'PGBOSS_DB_PASSWORD',\n\t\t\tsecrets.services.pgboss.password,\n\t\t]);\n\t}\n\n\tif (dbPasswordEntries.length === 0) {\n\t\treturn;\n\t}\n\n\tconst envContent = `# Auto-generated docker environment file\n# Contains database passwords for docker-compose postgres init\n# This file is gitignored - do not commit to version control\n${dbPasswordEntries.map(([key, value]) => `${key}=${value}`).join('\\n')}\n`;\n\n\tconst envPath = join(workspaceRoot, 'docker', '.env');\n\tawait mkdir(dirname(envPath), { recursive: true });\n\tawait writeFile(envPath, envContent);\n}\n","import { generateFullstackCustomSecrets } from '../setup/fullstack-secrets.js';\nimport type { NormalizedWorkspace } from '../workspace/types.js';\nimport type { StageSecrets } from './types.js';\n\nexport interface ReconcileResult {\n\t/** The updated secrets with missing keys backfilled */\n\tsecrets: StageSecrets;\n\t/** Keys that were added */\n\taddedKeys: string[];\n}\n\n/**\n * Reconcile missing custom secrets for a workspace.\n *\n * Compares current secrets against what generateFullstackCustomSecrets()\n * would produce and backfills any missing keys without overwriting\n * existing values.\n *\n * @returns ReconcileResult if keys were added, null if secrets are up-to-date\n */\nexport function reconcileMissingSecrets(\n\tsecrets: StageSecrets,\n\tworkspace: NormalizedWorkspace,\n\tcontainers: readonly string[] = [],\n): ReconcileResult | null {\n\tconst isMultiApp = Object.keys(workspace.apps).length > 1;\n\tif (!isMultiApp) {\n\t\treturn null;\n\t}\n\n\tconst expectedCustom = generateFullstackCustomSecrets(workspace, containers);\n\tconst addedKeys: string[] = [];\n\tconst mergedCustom = { ...secrets.custom };\n\n\tfor (const [key, value] of Object.entries(expectedCustom)) {\n\t\tif (!(key in mergedCustom)) {\n\t\t\tmergedCustom[key] = value;\n\t\t\taddedKeys.push(key);\n\t\t}\n\t}\n\n\tif (addedKeys.length === 0) {\n\t\treturn null;\n\t}\n\n\treturn {\n\t\tsecrets: {\n\t\t\t...secrets,\n\t\t\tupdatedAt: new Date().toISOString(),\n\t\t\tcustom: mergedCustom,\n\t\t},\n\t\taddedKeys,\n\t};\n}\n"],"mappings":"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"}