@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
@@ -0,0 +1,182 @@
1
+ import { t as __exportAll } from "./rolldown-runtime-BhDjJH2R.mjs";
2
+ import { existsSync } from "node:fs";
3
+ import { chmod, mkdir, readFile, writeFile } from "node:fs/promises";
4
+ import { homedir } from "node:os";
5
+ import { basename, join } from "node:path";
6
+ import { createCipheriv, createDecipheriv, randomBytes } from "node:crypto";
7
+ //#region src/secrets/keystore.ts
8
+ /** Key length for AES-256 encryption */
9
+ const KEY_LENGTH = 32;
10
+ /**
11
+ * Get the keystore directory for a project.
12
+ * Keys are stored at ~/.gkm/{project-name}/
13
+ *
14
+ * @param projectName - Name of the project (defaults to current directory name)
15
+ * @returns Path to the keystore directory
16
+ */
17
+ function getKeystoreDir(projectName) {
18
+ const name = projectName ?? basename(process.cwd());
19
+ return join(homedir(), ".gkm", name);
20
+ }
21
+ /**
22
+ * Get the path to a stage's encryption key.
23
+ *
24
+ * @param stage - Stage name (e.g., 'development', 'production')
25
+ * @param projectName - Name of the project (defaults to current directory name)
26
+ * @returns Path to the key file
27
+ */
28
+ function getKeyPath(stage, projectName) {
29
+ return join(getKeystoreDir(projectName), `${stage}.key`);
30
+ }
31
+ /**
32
+ * Generate a new encryption key for a stage.
33
+ * The key is stored at ~/.gkm/{project-name}/{stage}.key with restricted permissions.
34
+ *
35
+ * @param stage - Stage name
36
+ * @param projectName - Project name (defaults to current directory name)
37
+ * @returns The generated key as a hex string
38
+ */
39
+ async function generateKey(stage, projectName) {
40
+ const keyDir = getKeystoreDir(projectName);
41
+ const keyPath = getKeyPath(stage, projectName);
42
+ await mkdir(keyDir, {
43
+ recursive: true,
44
+ mode: 448
45
+ });
46
+ const key = randomBytes(KEY_LENGTH).toString("hex");
47
+ await writeFile(keyPath, key, {
48
+ mode: 384,
49
+ encoding: "utf-8"
50
+ });
51
+ await chmod(keyPath, 384);
52
+ return key;
53
+ }
54
+ /**
55
+ * Read an encryption key for a stage.
56
+ *
57
+ * @param stage - Stage name
58
+ * @param projectName - Project name (defaults to current directory name)
59
+ * @returns The key as a hex string, or null if not found
60
+ */
61
+ async function readKey(stage, projectName) {
62
+ const keyPath = getKeyPath(stage, projectName);
63
+ if (!existsSync(keyPath)) return null;
64
+ return (await readFile(keyPath, "utf-8")).trim();
65
+ }
66
+ /**
67
+ * Get or create a key for a stage.
68
+ * If the key already exists, it is returned. Otherwise, a new key is generated.
69
+ *
70
+ * @param stage - Stage name
71
+ * @param projectName - Project name (defaults to current directory name)
72
+ * @returns The key as a hex string
73
+ */
74
+ async function getOrCreateKey(stage, projectName) {
75
+ const existingKey = await readKey(stage, projectName);
76
+ if (existingKey) return existingKey;
77
+ return generateKey(stage, projectName);
78
+ }
79
+ //#endregion
80
+ //#region src/secrets/file.ts
81
+ /** Where the files live, relative to the project root. */
82
+ const SECRETS_DIR = ".gkm/secrets";
83
+ /** AES-256-GCM configuration */
84
+ const ALGORITHM = "aes-256-gcm";
85
+ const IV_LENGTH = 12;
86
+ /**
87
+ * A stage's secrets as an encrypted file on this machine:
88
+ * `.gkm/secrets/<stage>.json`, with its key at `~/.gkm/<project>/<stage>.key`.
89
+ *
90
+ * The local stage's store, always — its secrets belong to the machine running
91
+ * `gkm dev` — and a deployed stage's when `secrets.store` is `'file'`.
92
+ */
93
+ var FileSecretsStore = class {
94
+ root;
95
+ name = "file";
96
+ constructor(root) {
97
+ this.root = root;
98
+ }
99
+ /** The file a stage's secrets are kept in. */
100
+ path(stage) {
101
+ return join(this.root, SECRETS_DIR, `${stage}.json`);
102
+ }
103
+ async read(stage) {
104
+ const path = this.path(stage);
105
+ if (!existsSync(path)) return null;
106
+ const data = JSON.parse(await readFile(path, "utf-8"));
107
+ if (!(data.version === 1 && data.encrypted && data.iv)) return data;
108
+ const project = basename(this.root);
109
+ const key = await readKey(stage, project);
110
+ if (!key) throw new MissingSecretsKey(stage, project);
111
+ return decrypt(data, key);
112
+ }
113
+ async write(stage, secrets) {
114
+ await mkdir(join(this.root, SECRETS_DIR), { recursive: true });
115
+ const key = await getOrCreateKey(stage, basename(this.root));
116
+ await writeFile(this.path(stage), JSON.stringify(encrypt(secrets, key), null, 2), "utf-8");
117
+ }
118
+ };
119
+ /** A stage's secrets file exists, and the key that opens it does not. */
120
+ var MissingSecretsKey = class extends Error {
121
+ stage;
122
+ project;
123
+ constructor(stage, project) {
124
+ super(`Decryption key not found for stage "${stage}". Expected key at: ~/.gkm/${project}/${stage}.key`);
125
+ this.stage = stage;
126
+ this.project = project;
127
+ this.name = "MissingSecretsKey";
128
+ }
129
+ };
130
+ function encrypt(secrets, keyHex) {
131
+ const key = Buffer.from(keyHex, "hex");
132
+ const iv = randomBytes(IV_LENGTH);
133
+ const cipher = createCipheriv(ALGORITHM, key, iv);
134
+ const ciphertext = Buffer.concat([cipher.update(JSON.stringify(secrets), "utf-8"), cipher.final()]);
135
+ return {
136
+ version: 1,
137
+ encrypted: Buffer.concat([ciphertext, cipher.getAuthTag()]).toString("base64"),
138
+ iv: iv.toString("hex")
139
+ };
140
+ }
141
+ function decrypt(data, keyHex) {
142
+ const key = Buffer.from(keyHex, "hex");
143
+ const combined = Buffer.from(data.encrypted, "base64");
144
+ const decipher = createDecipheriv(ALGORITHM, key, Buffer.from(data.iv, "hex"));
145
+ decipher.setAuthTag(combined.subarray(-16));
146
+ const plaintext = Buffer.concat([decipher.update(combined.subarray(0, -16)), decipher.final()]);
147
+ return JSON.parse(plaintext.toString("utf-8"));
148
+ }
149
+ //#endregion
150
+ //#region src/secrets/store.ts
151
+ var store_exports = /* @__PURE__ */ __exportAll({
152
+ FileSecretsStore: () => FileSecretsStore,
153
+ isRemoteStore: () => isRemoteStore,
154
+ secretsStoreFor: () => secretsStoreFor
155
+ });
156
+ /**
157
+ * The store a stage's secrets are kept in — what every command reads and
158
+ * writes, for the stage it acts on.
159
+ *
160
+ * The local stage is always the file: its secrets belong to the machine
161
+ * running `gkm dev`. A deployed stage uses `secrets.store`.
162
+ */
163
+ async function secretsStoreFor(workspace, stage, options = {}) {
164
+ const configured = workspace.secrets.store ?? "file";
165
+ if (stage === workspace.stages.local || configured === "file") return new FileSecretsStore(workspace.root);
166
+ if (configured.provider !== "ssm") return configured.provider;
167
+ const { AwsSecretsStore } = await import("./aws-DojzQnLd.mjs");
168
+ return new AwsSecretsStore({
169
+ project: workspace.name,
170
+ region: configured.region,
171
+ ...options.profile ? { profile: options.profile } : {}
172
+ });
173
+ }
174
+ /** Whether a stage's secrets live somewhere other than this machine. */
175
+ function isRemoteStore(workspace, stage) {
176
+ const configured = workspace.secrets.store ?? "file";
177
+ return stage !== workspace.stages.local && configured !== "file";
178
+ }
179
+ //#endregion
180
+ export { getKeyPath as a, FileSecretsStore as i, secretsStoreFor as n, store_exports as r, isRemoteStore as t };
181
+
182
+ //# sourceMappingURL=store-DeGATCS-.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store-DeGATCS-.mjs","names":[],"sources":["../src/secrets/keystore.ts","../src/secrets/file.ts","../src/secrets/store.ts"],"sourcesContent":["import { randomBytes } from 'node:crypto';\nimport { existsSync } from 'node:fs';\nimport { chmod, mkdir, readFile, rm, writeFile } from 'node:fs/promises';\nimport { homedir } from 'node:os';\nimport { basename, join } from 'node:path';\n\n/** Key length for AES-256 encryption */\nconst KEY_LENGTH = 32; // 256 bits\n\n/**\n * Get the keystore directory for a project.\n * Keys are stored at ~/.gkm/{project-name}/\n *\n * @param projectName - Name of the project (defaults to current directory name)\n * @returns Path to the keystore directory\n */\nexport function getKeystoreDir(projectName?: string): string {\n\tconst name = projectName ?? basename(process.cwd());\n\treturn join(homedir(), '.gkm', name);\n}\n\n/**\n * Get the path to a stage's encryption key.\n *\n * @param stage - Stage name (e.g., 'development', 'production')\n * @param projectName - Name of the project (defaults to current directory name)\n * @returns Path to the key file\n */\nexport function getKeyPath(stage: string, projectName?: string): string {\n\treturn join(getKeystoreDir(projectName), `${stage}.key`);\n}\n\n/**\n * Check if a key exists for a stage.\n */\nexport function keyExists(stage: string, projectName?: string): boolean {\n\treturn existsSync(getKeyPath(stage, projectName));\n}\n\n/**\n * Generate a new encryption key for a stage.\n * The key is stored at ~/.gkm/{project-name}/{stage}.key with restricted permissions.\n *\n * @param stage - Stage name\n * @param projectName - Project name (defaults to current directory name)\n * @returns The generated key as a hex string\n */\nexport async function generateKey(\n\tstage: string,\n\tprojectName?: string,\n): Promise<string> {\n\tconst keyDir = getKeystoreDir(projectName);\n\tconst keyPath = getKeyPath(stage, projectName);\n\n\t// Ensure keystore directory exists with restricted permissions\n\tawait mkdir(keyDir, { recursive: true, mode: 0o700 });\n\n\t// Generate random key\n\tconst key = randomBytes(KEY_LENGTH).toString('hex');\n\n\t// Write key with restricted permissions (owner read/write only)\n\tawait writeFile(keyPath, key, { mode: 0o600, encoding: 'utf-8' });\n\n\t// Ensure permissions are set correctly (in case file existed)\n\tawait chmod(keyPath, 0o600);\n\n\treturn key;\n}\n\n/**\n * Read an encryption key for a stage.\n *\n * @param stage - Stage name\n * @param projectName - Project name (defaults to current directory name)\n * @returns The key as a hex string, or null if not found\n */\nexport async function readKey(\n\tstage: string,\n\tprojectName?: string,\n): Promise<string | null> {\n\tconst keyPath = getKeyPath(stage, projectName);\n\n\tif (!existsSync(keyPath)) {\n\t\treturn null;\n\t}\n\n\tconst key = await readFile(keyPath, 'utf-8');\n\treturn key.trim();\n}\n\n/**\n * Read an encryption key for a stage, throwing if not found.\n */\nexport async function requireKey(\n\tstage: string,\n\tprojectName?: string,\n): Promise<string> {\n\tconst key = await readKey(stage, projectName);\n\n\tif (!key) {\n\t\tconst name = projectName ?? basename(process.cwd());\n\t\tthrow new Error(\n\t\t\t`Encryption key not found for stage \"${stage}\" in project \"${name}\". ` +\n\t\t\t\t`Expected key at: ${getKeyPath(stage, projectName)}`,\n\t\t);\n\t}\n\n\treturn key;\n}\n\n/**\n * Delete a key for a stage.\n */\nexport async function deleteKey(\n\tstage: string,\n\tprojectName?: string,\n): Promise<void> {\n\tconst keyPath = getKeyPath(stage, projectName);\n\n\tif (existsSync(keyPath)) {\n\t\tawait rm(keyPath);\n\t}\n}\n\n/**\n * Get or create a key for a stage.\n * If the key already exists, it is returned. Otherwise, a new key is generated.\n *\n * @param stage - Stage name\n * @param projectName - Project name (defaults to current directory name)\n * @returns The key as a hex string\n */\nexport async function getOrCreateKey(\n\tstage: string,\n\tprojectName?: string,\n): Promise<string> {\n\tconst existingKey = await readKey(stage, projectName);\n\n\tif (existingKey) {\n\t\treturn existingKey;\n\t}\n\n\treturn generateKey(stage, projectName);\n}\n","import { createCipheriv, createDecipheriv, randomBytes } from 'node:crypto';\nimport { existsSync } from 'node:fs';\nimport { mkdir, readFile, writeFile } from 'node:fs/promises';\nimport { basename, join } from 'node:path';\nimport { getOrCreateKey, readKey } from './keystore';\nimport type { SecretsStore } from './store.js';\nimport type { StageSecrets } from './types';\n\n/** Where the files live, relative to the project root. */\nconst SECRETS_DIR = '.gkm/secrets';\n\n/** AES-256-GCM configuration */\nconst ALGORITHM = 'aes-256-gcm';\nconst IV_LENGTH = 12; // 96 bits for GCM\nconst AUTH_TAG_LENGTH = 16; // 128 bits\n\n/** Encrypted secrets file structure */\ninterface EncryptedSecretsFile {\n\t/** Version for future format changes */\n\tversion: 1;\n\t/** Base64 encoded encrypted data (ciphertext + auth tag) */\n\tencrypted: string;\n\t/** Hex encoded IV */\n\tiv: string;\n}\n\n/**\n * A stage's secrets as an encrypted file on this machine:\n * `.gkm/secrets/<stage>.json`, with its key at `~/.gkm/<project>/<stage>.key`.\n *\n * The local stage's store, always — its secrets belong to the machine running\n * `gkm dev` — and a deployed stage's when `secrets.store` is `'file'`.\n */\nexport class FileSecretsStore implements SecretsStore {\n\treadonly name = 'file';\n\n\tconstructor(private readonly root: string) {}\n\n\t/** The file a stage's secrets are kept in. */\n\tpath(stage: string): string {\n\t\treturn join(this.root, SECRETS_DIR, `${stage}.json`);\n\t}\n\n\tasync read(stage: string): Promise<StageSecrets | null> {\n\t\tconst path = this.path(stage);\n\t\tif (!existsSync(path)) return null;\n\n\t\tconst data = JSON.parse(await readFile(path, 'utf-8'));\n\n\t\t// Legacy: unencrypted format (for backwards compatibility)\n\t\tif (!(data.version === 1 && data.encrypted && data.iv)) {\n\t\t\treturn data as StageSecrets;\n\t\t}\n\n\t\tconst project = basename(this.root);\n\t\tconst key = await readKey(stage, project);\n\t\tif (!key) throw new MissingSecretsKey(stage, project);\n\n\t\treturn decrypt(data as EncryptedSecretsFile, key);\n\t}\n\n\tasync write(stage: string, secrets: StageSecrets): Promise<void> {\n\t\tawait mkdir(join(this.root, SECRETS_DIR), { recursive: true });\n\n\t\tconst key = await getOrCreateKey(stage, basename(this.root));\n\t\tawait writeFile(\n\t\t\tthis.path(stage),\n\t\t\tJSON.stringify(encrypt(secrets, key), null, 2),\n\t\t\t'utf-8',\n\t\t);\n\t}\n}\n\n/** A stage's secrets file exists, and the key that opens it does not. */\nexport class MissingSecretsKey extends Error {\n\tconstructor(\n\t\treadonly stage: string,\n\t\treadonly project: string,\n\t) {\n\t\tsuper(\n\t\t\t`Decryption key not found for stage \"${stage}\". ` +\n\t\t\t\t`Expected key at: ~/.gkm/${project}/${stage}.key`,\n\t\t);\n\t\tthis.name = 'MissingSecretsKey';\n\t}\n}\n\nfunction encrypt(secrets: StageSecrets, keyHex: string): EncryptedSecretsFile {\n\tconst key = Buffer.from(keyHex, 'hex');\n\tconst iv = randomBytes(IV_LENGTH);\n\n\tconst cipher = createCipheriv(ALGORITHM, key, iv);\n\tconst ciphertext = Buffer.concat([\n\t\tcipher.update(JSON.stringify(secrets), 'utf-8'),\n\t\tcipher.final(),\n\t]);\n\n\t// Ciphertext and auth tag, together\n\tconst combined = Buffer.concat([ciphertext, cipher.getAuthTag()]);\n\n\treturn {\n\t\tversion: 1,\n\t\tencrypted: combined.toString('base64'),\n\t\tiv: iv.toString('hex'),\n\t};\n}\n\nfunction decrypt(data: EncryptedSecretsFile, keyHex: string): StageSecrets {\n\tconst key = Buffer.from(keyHex, 'hex');\n\tconst combined = Buffer.from(data.encrypted, 'base64');\n\n\tconst decipher = createDecipheriv(\n\t\tALGORITHM,\n\t\tkey,\n\t\tBuffer.from(data.iv, 'hex'),\n\t);\n\tdecipher.setAuthTag(combined.subarray(-AUTH_TAG_LENGTH));\n\n\tconst plaintext = Buffer.concat([\n\t\tdecipher.update(combined.subarray(0, -AUTH_TAG_LENGTH)),\n\t\tdecipher.final(),\n\t]);\n\n\treturn JSON.parse(plaintext.toString('utf-8')) as StageSecrets;\n}\n","/**\n * Where a stage's secrets are kept.\n *\n * Every command that needs a stage's secrets — `gkm dev`, `test`, `deploy`,\n * `build`, `setup`, `secrets:*` — asks {@link secretsStoreFor} for that\n * stage's store and reads or writes it. None of them knows whether that is a\n * file on this machine or SSM in the stage's account: the local stage is\n * always the file, and a deployed stage is whatever `secrets.store` names.\n *\n * The same shape deploy state has (`StateProvider`): one interface, a backend\n * per place, and a custom object for any place this package does not ship.\n */\n\nimport type { NormalizedWorkspace } from '../workspace/types.js';\nimport { FileSecretsStore } from './file.js';\nimport type { StageSecrets } from './types.js';\n\nexport interface SecretsStore {\n\t/** Which kind of store this is — `'file'`, `'ssm'`, or a custom one's. */\n\treadonly name: string;\n\t/** The stage's secrets, or null when it has none here. */\n\tread(stage: string): Promise<StageSecrets | null>;\n\t/** Replace the stage's secrets. */\n\twrite(stage: string, secrets: StageSecrets): Promise<void>;\n}\n\n/** Secrets in SSM Parameter Store, in the account of the active credentials. */\nexport interface SsmSecretsStoreConfig {\n\tprovider: 'ssm';\n\tregion: string;\n}\n\n/** Any other backend: an object implementing {@link SecretsStore}. */\nexport interface CustomSecretsStoreConfig {\n\tprovider: SecretsStore;\n}\n\n/**\n * `secrets.store` in gkm.config.ts.\n *\n * `'file'` — the default — keeps each stage's secrets in the encrypted\n * `.gkm/secrets/<stage>.json` beside its key in `~/.gkm/`. It cannot serve a\n * deploy from CI while `.gkm/` is gitignored; `ssm` or a custom store can.\n */\nexport type SecretsStoreConfig =\n\t| 'file'\n\t| SsmSecretsStoreConfig\n\t| CustomSecretsStoreConfig;\n\nexport interface SecretsStoreOptions {\n\t/**\n\t * The AWS profile for the stage's account. Only that profile is used —\n\t * never AWS_* from the environment — so a store cannot quietly land in\n\t * whichever account the shell was exported for.\n\t */\n\tprofile?: string;\n}\n\n/**\n * The store a stage's secrets are kept in — what every command reads and\n * writes, for the stage it acts on.\n *\n * The local stage is always the file: its secrets belong to the machine\n * running `gkm dev`. A deployed stage uses `secrets.store`.\n */\nexport async function secretsStoreFor(\n\tworkspace: NormalizedWorkspace,\n\tstage: string,\n\toptions: SecretsStoreOptions = {},\n): Promise<SecretsStore> {\n\tconst configured = workspace.secrets.store ?? 'file';\n\n\tif (stage === workspace.stages.local || configured === 'file') {\n\t\treturn new FileSecretsStore(workspace.root);\n\t}\n\n\tif (configured.provider !== 'ssm') {\n\t\treturn configured.provider;\n\t}\n\n\tconst { AwsSecretsStore } = await import('./aws.js');\n\treturn new AwsSecretsStore({\n\t\tproject: workspace.name,\n\t\tregion: configured.region,\n\t\t...(options.profile ? { profile: options.profile } : {}),\n\t});\n}\n\n/** Whether a stage's secrets live somewhere other than this machine. */\nexport function isRemoteStore(\n\tworkspace: NormalizedWorkspace,\n\tstage: string,\n): boolean {\n\tconst configured = workspace.secrets.store ?? 'file';\n\treturn stage !== workspace.stages.local && configured !== 'file';\n}\n\nexport { FileSecretsStore };\n"],"mappings":";;;;;;;;AAOA,MAAM,aAAa;;;;;;;;AASnB,SAAgB,eAAe,aAA8B;CAC5D,MAAM,OAAO,eAAe,SAAS,QAAQ,IAAI,CAAC;CAClD,OAAO,KAAK,QAAQ,GAAG,QAAQ,IAAI;AACpC;;;;;;;;AASA,SAAgB,WAAW,OAAe,aAA8B;CACvE,OAAO,KAAK,eAAe,WAAW,GAAG,GAAG,MAAM,KAAK;AACxD;;;;;;;;;AAiBA,eAAsB,YACrB,OACA,aACkB;CAClB,MAAM,SAAS,eAAe,WAAW;CACzC,MAAM,UAAU,WAAW,OAAO,WAAW;CAG7C,MAAM,MAAM,QAAQ;EAAE,WAAW;EAAM,MAAM;CAAM,CAAC;CAGpD,MAAM,MAAM,YAAY,UAAU,CAAC,CAAC,SAAS,KAAK;CAGlD,MAAM,UAAU,SAAS,KAAK;EAAE,MAAM;EAAO,UAAU;CAAQ,CAAC;CAGhE,MAAM,MAAM,SAAS,GAAK;CAE1B,OAAO;AACR;;;;;;;;AASA,eAAsB,QACrB,OACA,aACyB;CACzB,MAAM,UAAU,WAAW,OAAO,WAAW;CAE7C,IAAI,CAAC,WAAW,OAAO,GACtB,OAAO;CAIR,QAAO,MADW,SAAS,SAAS,OAAO,EAAA,CAChC,KAAK;AACjB;;;;;;;;;AA4CA,eAAsB,eACrB,OACA,aACkB;CAClB,MAAM,cAAc,MAAM,QAAQ,OAAO,WAAW;CAEpD,IAAI,aACH,OAAO;CAGR,OAAO,YAAY,OAAO,WAAW;AACtC;;;;ACtIA,MAAM,cAAc;;AAGpB,MAAM,YAAY;AAClB,MAAM,YAAY;;;;;;;;AAoBlB,IAAa,mBAAb,MAAsD;CAGxB;CAF7B,OAAgB;CAEhB,YAAY,MAA+B;EAAd,KAAA,OAAA;CAAe;;CAG5C,KAAK,OAAuB;EAC3B,OAAO,KAAK,KAAK,MAAM,aAAa,GAAG,MAAM,MAAM;CACpD;CAEA,MAAM,KAAK,OAA6C;EACvD,MAAM,OAAO,KAAK,KAAK,KAAK;EAC5B,IAAI,CAAC,WAAW,IAAI,GAAG,OAAO;EAE9B,MAAM,OAAO,KAAK,MAAM,MAAM,SAAS,MAAM,OAAO,CAAC;EAGrD,IAAI,EAAE,KAAK,YAAY,KAAK,KAAK,aAAa,KAAK,KAClD,OAAO;EAGR,MAAM,UAAU,SAAS,KAAK,IAAI;EAClC,MAAM,MAAM,MAAM,QAAQ,OAAO,OAAO;EACxC,IAAI,CAAC,KAAK,MAAM,IAAI,kBAAkB,OAAO,OAAO;EAEpD,OAAO,QAAQ,MAA8B,GAAG;CACjD;CAEA,MAAM,MAAM,OAAe,SAAsC;EAChE,MAAM,MAAM,KAAK,KAAK,MAAM,WAAW,GAAG,EAAE,WAAW,KAAK,CAAC;EAE7D,MAAM,MAAM,MAAM,eAAe,OAAO,SAAS,KAAK,IAAI,CAAC;EAC3D,MAAM,UACL,KAAK,KAAK,KAAK,GACf,KAAK,UAAU,QAAQ,SAAS,GAAG,GAAG,MAAM,CAAC,GAC7C,OACD;CACD;AACD;;AAGA,IAAa,oBAAb,cAAuC,MAAM;CAElC;CACA;CAFV,YACC,OACA,SACC;EACD,MACC,uCAAuC,MAAM,6BACjB,QAAQ,GAAG,MAAM,KAC9C;EANS,KAAA,QAAA;EACA,KAAA,UAAA;EAMT,KAAK,OAAO;CACb;AACD;AAEA,SAAS,QAAQ,SAAuB,QAAsC;CAC7E,MAAM,MAAM,OAAO,KAAK,QAAQ,KAAK;CACrC,MAAM,KAAK,YAAY,SAAS;CAEhC,MAAM,SAAS,eAAe,WAAW,KAAK,EAAE;CAChD,MAAM,aAAa,OAAO,OAAO,CAChC,OAAO,OAAO,KAAK,UAAU,OAAO,GAAG,OAAO,GAC9C,OAAO,MAAM,CACd,CAAC;CAKD,OAAO;EACN,SAAS;EACT,WAJgB,OAAO,OAAO,CAAC,YAAY,OAAO,WAAW,CAAC,CAI5C,CAAC,CAAC,SAAS,QAAQ;EACrC,IAAI,GAAG,SAAS,KAAK;CACtB;AACD;AAEA,SAAS,QAAQ,MAA4B,QAA8B;CAC1E,MAAM,MAAM,OAAO,KAAK,QAAQ,KAAK;CACrC,MAAM,WAAW,OAAO,KAAK,KAAK,WAAW,QAAQ;CAErD,MAAM,WAAW,iBAChB,WACA,KACA,OAAO,KAAK,KAAK,IAAI,KAAK,CAC3B;CACA,SAAS,WAAW,SAAS,SAAS,GAAgB,CAAC;CAEvD,MAAM,YAAY,OAAO,OAAO,CAC/B,SAAS,OAAO,SAAS,SAAS,GAAG,GAAgB,CAAC,GACtD,SAAS,MAAM,CAChB,CAAC;CAED,OAAO,KAAK,MAAM,UAAU,SAAS,OAAO,CAAC;AAC9C;;;;;;;;;;;;;;;AC3DA,eAAsB,gBACrB,WACA,OACA,UAA+B,CAAC,GACR;CACxB,MAAM,aAAa,UAAU,QAAQ,SAAS;CAE9C,IAAI,UAAU,UAAU,OAAO,SAAS,eAAe,QACtD,OAAO,IAAI,iBAAiB,UAAU,IAAI;CAG3C,IAAI,WAAW,aAAa,OAC3B,OAAO,WAAW;CAGnB,MAAM,EAAE,oBAAoB,MAAM,OAAO;CACzC,OAAO,IAAI,gBAAgB;EAC1B,SAAS,UAAU;EACnB,QAAQ,WAAW;EACnB,GAAI,QAAQ,UAAU,EAAE,SAAS,QAAQ,QAAQ,IAAI,CAAC;CACvD,CAAC;AACF;;AAGA,SAAgB,cACf,WACA,OACU;CACV,MAAM,aAAa,UAAU,QAAQ,SAAS;CAC9C,OAAO,UAAU,UAAU,OAAO,SAAS,eAAe;AAC3D"}