@geekmidas/cli 10.0.0-alpha.16 → 10.0.0-alpha.18

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 (90) hide show
  1. package/dist/{bundler-BeNDZdHQ.cjs → bundler-mjqGAvu1.cjs} +2 -2
  2. package/dist/{bundler-BeNDZdHQ.cjs.map → bundler-mjqGAvu1.cjs.map} +1 -1
  3. package/dist/{bundler-BodTL4kf.mjs → bundler-mwH7WOb1.mjs} +2 -2
  4. package/dist/{bundler-BodTL4kf.mjs.map → bundler-mwH7WOb1.mjs.map} +1 -1
  5. package/dist/{config-Q1rvKHvw.cjs → config-DSXI480r.cjs} +2 -2
  6. package/dist/{config-Q1rvKHvw.cjs.map → config-DSXI480r.cjs.map} +1 -1
  7. package/dist/{config-pqGD3hF9.mjs → config-DdKkoUE1.mjs} +2 -2
  8. package/dist/{config-pqGD3hF9.mjs.map → config-DdKkoUE1.mjs.map} +1 -1
  9. package/dist/config.cjs +2 -2
  10. package/dist/config.d.cts +2 -2
  11. package/dist/config.d.mts +2 -2
  12. package/dist/config.mjs +2 -2
  13. package/dist/{credentials-Q6F0uqJq.cjs → credentials-C6Pfn6GY.cjs} +31 -9
  14. package/dist/credentials-C6Pfn6GY.cjs.map +1 -0
  15. package/dist/{credentials-BekkKtY_.mjs → credentials-lbv-j0Be.mjs} +32 -10
  16. package/dist/{credentials-BekkKtY_.mjs.map → credentials-lbv-j0Be.mjs.map} +1 -1
  17. package/dist/discover-BERGFg8v.cjs.map +1 -1
  18. package/dist/discover-CK-n3w6b.mjs.map +1 -1
  19. package/dist/{github-CRwnxKmD.mjs → github-DlIrXPee.mjs} +21 -8
  20. package/dist/github-DlIrXPee.mjs.map +1 -0
  21. package/dist/{github-BfflNPVe.cjs → github-n7N9yOff.cjs} +22 -9
  22. package/dist/github-n7N9yOff.cjs.map +1 -0
  23. package/dist/{index-C-VLwB_Y.d.mts → index-B4H4XF7A.d.mts} +2 -2
  24. package/dist/{index-C-HkOEBt.d.cts.map → index-B4H4XF7A.d.mts.map} +1 -1
  25. package/dist/{index-C-HkOEBt.d.cts → index-RCUizGxL.d.cts} +2 -2
  26. package/dist/{index-C-VLwB_Y.d.mts.map → index-RCUizGxL.d.cts.map} +1 -1
  27. package/dist/index.cjs +164 -172
  28. package/dist/index.cjs.map +1 -1
  29. package/dist/index.mjs +159 -167
  30. package/dist/index.mjs.map +1 -1
  31. package/dist/{openapi-Dcbme-Us.cjs → openapi-B8bu_OXN.cjs} +2 -2
  32. package/dist/{openapi-Dcbme-Us.cjs.map → openapi-B8bu_OXN.cjs.map} +1 -1
  33. package/dist/{openapi-vy4JzhUv.mjs → openapi-DfjbhrsM.mjs} +2 -2
  34. package/dist/{openapi-vy4JzhUv.mjs.map → openapi-DfjbhrsM.mjs.map} +1 -1
  35. package/dist/openapi.cjs +1 -1
  36. package/dist/openapi.d.cts +1 -1
  37. package/dist/openapi.d.mts +1 -1
  38. package/dist/openapi.mjs +1 -1
  39. package/dist/reconcile/public.d.cts +1 -1
  40. package/dist/reconcile/public.d.mts +1 -1
  41. package/dist/{fullstack-secrets-DXsWO-5m.cjs → reconcile-Cq4cO83R.cjs} +45 -1
  42. package/dist/reconcile-Cq4cO83R.cjs.map +1 -0
  43. package/dist/{fullstack-secrets-BET8gqwK.mjs → reconcile-fmoluZmZ.mjs} +34 -2
  44. package/dist/reconcile-fmoluZmZ.mjs.map +1 -0
  45. package/dist/ssm-BKN1Cg4z.mjs +60 -0
  46. package/dist/ssm-BKN1Cg4z.mjs.map +1 -0
  47. package/dist/ssm-FxeSAt35.cjs +60 -0
  48. package/dist/ssm-FxeSAt35.cjs.map +1 -0
  49. package/dist/{storage-C-30BD1e.cjs → storage-DgypfSD6.cjs} +83 -4
  50. package/dist/storage-DgypfSD6.cjs.map +1 -0
  51. package/dist/{storage-P_b3w7uj.mjs → storage-TP0x118M.mjs} +77 -4
  52. package/dist/storage-TP0x118M.mjs.map +1 -0
  53. package/dist/transfer-2aRVVJ6I.mjs +122 -0
  54. package/dist/transfer-2aRVVJ6I.mjs.map +1 -0
  55. package/dist/transfer-C3WZVmj_.cjs +151 -0
  56. package/dist/transfer-C3WZVmj_.cjs.map +1 -0
  57. package/dist/{types-RhXmHR-e.d.cts → types-7R81hu0i.d.mts} +138 -1
  58. package/dist/types-7R81hu0i.d.mts.map +1 -0
  59. package/dist/{types-kvBQjpPo.d.mts → types-N7c2O2m7.d.cts} +140 -1
  60. package/dist/types-N7c2O2m7.d.cts.map +1 -0
  61. package/dist/workspace/index.cjs +1 -1
  62. package/dist/workspace/index.d.cts +2 -2
  63. package/dist/workspace/index.d.mts +2 -2
  64. package/dist/workspace/index.mjs +1 -1
  65. package/dist/{workspace-CgwmXEtc.mjs → workspace-Bu3xNCej.mjs} +14 -3
  66. package/dist/{workspace-CgwmXEtc.mjs.map → workspace-Bu3xNCej.mjs.map} +1 -1
  67. package/dist/{workspace-mFpI_ky_.cjs → workspace-CRD9YinV.cjs} +19 -2
  68. package/dist/{workspace-mFpI_ky_.cjs.map → workspace-CRD9YinV.cjs.map} +1 -1
  69. package/package.json +11 -11
  70. package/dist/credentials-Q6F0uqJq.cjs.map +0 -1
  71. package/dist/fullstack-secrets-BET8gqwK.mjs.map +0 -1
  72. package/dist/fullstack-secrets-DXsWO-5m.cjs.map +0 -1
  73. package/dist/github-BfflNPVe.cjs.map +0 -1
  74. package/dist/github-CRwnxKmD.mjs.map +0 -1
  75. package/dist/keystore-B4PRlbgE.mjs +0 -81
  76. package/dist/keystore-B4PRlbgE.mjs.map +0 -1
  77. package/dist/keystore-DgGRj2Yy.cjs +0 -98
  78. package/dist/keystore-DgGRj2Yy.cjs.map +0 -1
  79. package/dist/reconcile-Dd2iyILf.cjs +0 -34
  80. package/dist/reconcile-Dd2iyILf.cjs.map +0 -1
  81. package/dist/reconcile-DhQ00DpU.mjs +0 -34
  82. package/dist/reconcile-DhQ00DpU.mjs.map +0 -1
  83. package/dist/storage-C-30BD1e.cjs.map +0 -1
  84. package/dist/storage-P_b3w7uj.mjs.map +0 -1
  85. package/dist/sync-B3xxXtJT.mjs +0 -88
  86. package/dist/sync-B3xxXtJT.mjs.map +0 -1
  87. package/dist/sync-D7uTIIEi.cjs +0 -111
  88. package/dist/sync-D7uTIIEi.cjs.map +0 -1
  89. package/dist/types-RhXmHR-e.d.cts.map +0 -1
  90. package/dist/types-kvBQjpPo.d.mts.map +0 -1
package/dist/index.mjs CHANGED
@@ -1,16 +1,15 @@
1
1
  #!/usr/bin/env -S npx tsx
2
2
  import { n as __require, t as __exportAll } from "./rolldown-runtime-BhDjJH2R.mjs";
3
3
  import { i as DEFAULT_CACHE, r as ConstructGenerator, s as isPartitionedRoutes, t as discover } from "./discover-CK-n3w6b.mjs";
4
- import { i as loadConfig, l as derivedApps, n as getAppNameFromCwd, o as loadWorkspaceConfig, r as loadAppConfig, s as parseModuleConfig } from "./config-pqGD3hF9.mjs";
5
- import { C as InvalidStages, E as stageProblems, O as getPublicEnvPrefix, T as deployedProblems, a as getAppBuildOrder, k as stripPublicPrefix, o as getAppGkmConfig, s as getDependencyEnvVars, t as allConstructGlobs, v as getDeployTargetError, w as assertDeployedStage, y as isDeployTargetSupported } from "./workspace-CgwmXEtc.mjs";
6
- import { C as storageBackendFor, S as providerOf, _ as LOCAL_CA_PATH, a as loadEnvFiles, b as cacheBackendFor, c as resolveServicePorts, d as constructGlobs, f as derivedContainers, g as COMPOSE_PATH, i as isPortAvailable, l as rewriteUrlsWithPorts, m as usesConstructs, n as createEntryWrapper, o as loadSecretsForApp, p as reconcileWorkspace, r as findAvailablePort, s as prepareEntryCredentials, t as createCredentialsPreload, u as startWorkspaceServices, v as applyPostgres, x as eventsBackendFor, y as resourceName } from "./credentials-BekkKtY_.mjs";
4
+ import { i as loadConfig, l as derivedApps, n as getAppNameFromCwd, o as loadWorkspaceConfig, r as loadAppConfig, s as parseModuleConfig } from "./config-DdKkoUE1.mjs";
5
+ import { A as stripPublicPrefix, C as InvalidStages, D as stageProblems, E as deployedProblems, T as assertDeployedStage, a as getAppBuildOrder, k as getPublicEnvPrefix, o as getAppGkmConfig, s as getDependencyEnvVars, t as allConstructGlobs, v as getDeployTargetError, y as isDeployTargetSupported } from "./workspace-Bu3xNCej.mjs";
6
+ import { C as storageBackendFor, S as providerOf, _ as LOCAL_CA_PATH, a as loadEnvFiles, b as cacheBackendFor, c as resolveServicePorts, d as constructGlobs, f as derivedContainers, g as COMPOSE_PATH, i as isPortAvailable, l as rewriteUrlsWithPorts, m as usesConstructs, n as createEntryWrapper, o as loadSecretsForApp, p as reconcileWorkspace, r as findAvailablePort, s as prepareEntryCredentials, t as createCredentialsPreload, u as startWorkspaceServices, v as applyPostgres, x as eventsBackendFor, y as resourceName } from "./credentials-lbv-j0Be.mjs";
7
7
  import { a as generateServiceCredentials, i as generateSecurePassword, n as generateConnectionUrls, o as rotateServicePassword, t as createStageSecrets } from "./generator-LfZU7NlU.mjs";
8
- import { t as getKeyPath } from "./keystore-B4PRlbgE.mjs";
9
- import { i as setCustomSecret, n as readStageSecrets, o as toEmbeddableSecrets, r as secretsExist, s as writeStageSecrets, t as maskPassword } from "./storage-P_b3w7uj.mjs";
10
- import { a as openapiCommand, c as runtimeFor, n as generateOpenApi, o as resolveOpenApiConfig, r as generateOpenApiFrom, s as EndpointGenerator, t as OPENAPI_OUTPUT_PATH$1 } from "./openapi-vy4JzhUv.mjs";
8
+ import { c as getKeyPath, i as setCustomSecret, n as readStageSecrets, o as toEmbeddableSecrets, r as secretsExist, s as writeStageSecrets, t as maskPassword } from "./storage-TP0x118M.mjs";
9
+ import { a as openapiCommand, c as runtimeFor, n as generateOpenApi, o as resolveOpenApiConfig, r as generateOpenApiFrom, s as EndpointGenerator, t as OPENAPI_OUTPUT_PATH$1 } from "./openapi-DfjbhrsM.mjs";
11
10
  import { i as withRoutes, r as withCompute } from "./emit-Bzq7JsMP.mjs";
12
- import { n as writeDockerEnvFromSecrets, t as generateFullstackCustomSecrets } from "./fullstack-secrets-BET8gqwK.mjs";
13
- import { n as pullSecrets, r as pushSecrets, t as isSSMConfigured } from "./sync-B3xxXtJT.mjs";
11
+ import { i as writeDockerEnvFromSecrets, r as generateFullstackCustomSecrets } from "./reconcile-fmoluZmZ.mjs";
12
+ import { a as isRemoteStore, n as pullStageSecrets, r as pushStageSecrets, t as NoStoredSecrets } from "./transfer-2aRVVJ6I.mjs";
14
13
  import { createRequire } from "node:module";
15
14
  import { Command } from "commander";
16
15
  import { stdin, stdout } from "node:process";
@@ -38,7 +37,7 @@ import { fileURLToPath, pathToFileURL } from "node:url";
38
37
  import { lookup } from "node:dns/promises";
39
38
  import prompts from "prompts";
40
39
  //#region package.json
41
- var version = "10.0.0-alpha.16";
40
+ var version = "10.0.0-alpha.18";
42
41
  //#endregion
43
42
  //#region src/auth/credentials.ts
44
43
  /**
@@ -2609,7 +2608,7 @@ async function buildForProvider(provider, context, rootOutputDir, endpointGenera
2609
2608
  let masterKey;
2610
2609
  if (context.production?.bundle && !skipBundle) {
2611
2610
  logger$9.log(`\n📦 Bundling production server...`);
2612
- const { bundleServer } = await import("./bundler-BodTL4kf.mjs");
2611
+ const { bundleServer } = await import("./bundler-mwH7WOb1.mjs");
2613
2612
  const allConstructs = [
2614
2613
  ...endpoints.map((e) => e.construct),
2615
2614
  ...functions.map((f) => f.construct),
@@ -8301,7 +8300,6 @@ const DEPENDENCY_VERSIONS = {
8301
8300
  clsx: "~2.1.1",
8302
8301
  "lucide-react": "~1.48.0",
8303
8302
  "tailwind-merge": "~3.7.0",
8304
- "vite-tsconfig-paths": "~5.1.4",
8305
8303
  "@biomejs/biome": "~2.5.14",
8306
8304
  "@faker-js/faker": "~10.6.0",
8307
8305
  turbo: "~2.11.4",
@@ -8312,26 +8310,21 @@ const DEPENDENCY_VERSIONS = {
8312
8310
  "@types/aws-lambda": "~8.10.163"
8313
8311
  };
8314
8312
  /**
8315
- * The build and test toolchain, at the versions it was already on.
8316
- *
8317
- * Held here so it moves in one place, but not moved yet: it changes how every
8318
- * scaffold compiles and runs, and tranche 2 (#40) moves it together with the
8319
- * repository's own toolchain.
8313
+ * The build and test toolchain, at the versions the repository itself builds
8314
+ * and tests with (scripts/dependency-versions.json), so a scaffold compiles
8315
+ * with the compiler its own `@geekmidas` packages were checked against.
8320
8316
  */
8321
8317
  const TOOLCHAIN_VERSIONS = {
8322
- typescript: "~5.8.2",
8323
- tsx: "~4.20.0",
8324
- esbuild: "~0.27.0",
8325
- vitest: "~4.0.0",
8326
- vite: "^7.0.0",
8327
- "@vitejs/plugin-react": "^4.3.4",
8328
- storybook: "^8.4.7",
8329
- "@storybook/addon-a11y": "^8.4.7",
8330
- "@storybook/addon-essentials": "^8.4.7",
8331
- "@storybook/addon-interactions": "^8.4.7",
8332
- "@storybook/react": "^8.4.7",
8333
- "@storybook/react-vite": "^8.4.7",
8334
- "vite@storybook": "^6.0.0"
8318
+ typescript: "~7.0.2",
8319
+ tsx: "~4.23.15",
8320
+ esbuild: "~0.28.2",
8321
+ vitest: "~5.0.2",
8322
+ vite: "~8.3.1",
8323
+ "@vitejs/plugin-react": "^6.1.1",
8324
+ storybook: "^10.6.0",
8325
+ "@storybook/addon-docs": "^10.6.0",
8326
+ "@storybook/addon-a11y": "^10.6.0",
8327
+ "@storybook/react-vite": "^10.6.0"
8335
8328
  };
8336
8329
  /**
8337
8330
  * The Expo app's packages, which track an Expo SDK release (55) rather than
@@ -8361,6 +8354,15 @@ const EXPO_VERSIONS = {
8361
8354
  nativewind: "~4.2.0",
8362
8355
  tailwindcss: "~3.4.0"
8363
8356
  };
8357
+ /**
8358
+ * The pnpm a pnpm scaffold runs under, through \`packageManager\`.
8359
+ *
8360
+ * Pinned in every layout. Without it Corepack takes the newest pnpm, and 11
8361
+ * fails the first install on dependencies with build scripts (esbuild) until
8362
+ * they are approved — a single-app scaffold that did not pin it could not
8363
+ * install at all.
8364
+ */
8365
+ const PNPM_VERSION = "pnpm@10.13.1";
8364
8366
  /** The Biome config schema matching the Biome the scaffold installs. */
8365
8367
  const BIOME_SCHEMA = `https://biomejs.dev/schemas/${DEPENDENCY_VERSIONS["@biomejs/biome"].replace(/^[~^]/, "")}/schema.json`;
8366
8368
  //#endregion
@@ -8380,26 +8382,26 @@ function loadPackageJson() {
8380
8382
  * Run: pnpm --filter @geekmidas/cli sync-versions
8381
8383
  */
8382
8384
  const GEEKMIDAS_VERSIONS = {
8383
- "@geekmidas/audit": "~10.0.0-alpha.16",
8384
- "@geekmidas/auth": "~10.0.0-alpha.16",
8385
- "@geekmidas/cache": "~10.0.0-alpha.16",
8386
- "@geekmidas/client": "~10.0.0-alpha.16",
8387
- "@geekmidas/cloud": "~10.0.0-alpha.16",
8388
- "@geekmidas/constructs": "~10.0.0-alpha.16",
8389
- "@geekmidas/db": "~10.0.0-alpha.16",
8390
- "@geekmidas/emailkit": "~10.0.0-alpha.16",
8391
- "@geekmidas/envkit": "~10.0.0-alpha.16",
8392
- "@geekmidas/errors": "~10.0.0-alpha.16",
8393
- "@geekmidas/events": "~10.0.0-alpha.16",
8394
- "@geekmidas/logger": "~10.0.0-alpha.16",
8395
- "@geekmidas/manifest": "~10.0.0-alpha.16",
8396
- "@geekmidas/rate-limit": "~10.0.0-alpha.16",
8397
- "@geekmidas/schema": "~10.0.0-alpha.16",
8398
- "@geekmidas/services": "~10.0.0-alpha.16",
8399
- "@geekmidas/storage": "~10.0.0-alpha.16",
8400
- "@geekmidas/studio": "~10.0.0-alpha.16",
8401
- "@geekmidas/telescope": "~10.0.0-alpha.16",
8402
- "@geekmidas/testkit": "~10.0.0-alpha.16",
8385
+ "@geekmidas/audit": "~10.0.0-alpha.18",
8386
+ "@geekmidas/auth": "~10.0.0-alpha.18",
8387
+ "@geekmidas/cache": "~10.0.0-alpha.18",
8388
+ "@geekmidas/client": "~10.0.0-alpha.18",
8389
+ "@geekmidas/cloud": "~10.0.0-alpha.18",
8390
+ "@geekmidas/constructs": "~10.0.0-alpha.18",
8391
+ "@geekmidas/db": "~10.0.0-alpha.18",
8392
+ "@geekmidas/emailkit": "~10.0.0-alpha.18",
8393
+ "@geekmidas/envkit": "~10.0.0-alpha.18",
8394
+ "@geekmidas/errors": "~10.0.0-alpha.18",
8395
+ "@geekmidas/events": "~10.0.0-alpha.18",
8396
+ "@geekmidas/logger": "~10.0.0-alpha.18",
8397
+ "@geekmidas/manifest": "~10.0.0-alpha.18",
8398
+ "@geekmidas/rate-limit": "~10.0.0-alpha.18",
8399
+ "@geekmidas/schema": "~10.0.0-alpha.18",
8400
+ "@geekmidas/services": "~10.0.0-alpha.18",
8401
+ "@geekmidas/storage": "~10.0.0-alpha.18",
8402
+ "@geekmidas/studio": "~10.0.0-alpha.18",
8403
+ "@geekmidas/telescope": "~10.0.0-alpha.18",
8404
+ "@geekmidas/testkit": "~10.0.0-alpha.18",
8403
8405
  "@geekmidas/cli": `~${loadPackageJson().version}`
8404
8406
  };
8405
8407
  //#endregion
@@ -8447,7 +8449,6 @@ function generateAuthAppFiles(options) {
8447
8449
  compilerOptions: {
8448
8450
  noEmit: true,
8449
8451
  allowImportingTsExtensions: true,
8450
- baseUrl: ".",
8451
8452
  paths: {
8452
8453
  "~/*": ["./src/*"],
8453
8454
  [`@${options.name}/*`]: ["../../packages/*/src"]
@@ -8503,10 +8504,10 @@ function stageEnv(stages) {
8503
8504
  * Vitest config content with globalSetup for database-enabled apps
8504
8505
  */
8505
8506
  const vitestConfigContent = `import { defineConfig } from 'vitest/config';
8506
- import tsconfigPaths from 'vite-tsconfig-paths';
8507
8507
 
8508
8508
  export default defineConfig({
8509
- plugins: [tsconfigPaths()],
8509
+ // Vite resolves tsconfig \`paths\` itself; no plugin needed.
8510
+ resolve: { tsconfigPaths: true },
8510
8511
  test: {
8511
8512
  environment: 'node',
8512
8513
  globalSetup: './test/globalSetup.ts',
@@ -8572,7 +8573,6 @@ export default defineConfig({${stagesBlock(options.stages)}${options.monorepo ?
8572
8573
  resolveJsonModule: true,
8573
8574
  noEmit: true,
8574
8575
  allowImportingTsExtensions: true,
8575
- baseUrl: ".",
8576
8576
  paths: { "~/*": ["./src/*"] }
8577
8577
  },
8578
8578
  include: ["src/**/*.ts"],
@@ -8696,7 +8696,6 @@ function workspaceApiTsConfig(name) {
8696
8696
  compilerOptions: {
8697
8697
  noEmit: true,
8698
8698
  allowImportingTsExtensions: true,
8699
- baseUrl: ".",
8700
8699
  paths: {
8701
8700
  "~/*": ["./src/*"],
8702
8701
  [`@${name}/constructs/*`]: ["../../constructs/*"],
@@ -8968,6 +8967,32 @@ function deploy(options) {
8968
8967
  role-to-assume: \${{ vars.AWS_ROLE_ARN }}
8969
8968
  aws-region: ${options.region}
8970
8969
  ` : "";
8970
+ const stageSecrets = sst ? `${credentials}
8971
+ # The stage's secrets, from SSM in the account the role belongs to —
8972
+ # pushed there once with \`gkm secrets:push --stage <stage> --profile …\`.
8973
+ # The stage reaches the shell as a variable, never pasted into the script:
8974
+ # on a manual run it is whatever was typed.
8975
+ - name: Stage secrets
8976
+ run: ${pm.exec} gkm secrets:pull --stage "$STAGE"
8977
+ env:
8978
+ STAGE: \${{ matrix.stage }}
8979
+ ` : `
8980
+ # The stage's secrets are kept in the encrypted .gkm/secrets/<stage>.json,
8981
+ # and each environment holds its key as GKM_SECRETS_KEY. .gkm/ is
8982
+ # gitignored, so a checkout has the key but not the file: set
8983
+ # secrets.store in gkm.config.ts to a store CI can reach before deploying
8984
+ # from here.
8985
+ # Owner-only, as the CLI writes its own keys. The stage reaches the shell
8986
+ # as a variable, never pasted into the script: on a manual run it is
8987
+ # whatever was typed.
8988
+ - name: Stage secrets key
8989
+ run: |
8990
+ mkdir -p -m 700 ~/.gkm/${options.name}
8991
+ (umask 077 && printf '%s' "$KEY" > ~/.gkm/${options.name}/"$STAGE".key)
8992
+ env:
8993
+ KEY: \${{ secrets.GKM_SECRETS_KEY }}
8994
+ STAGE: \${{ matrix.stage }}
8995
+ `;
8971
8996
  const deployEnv = sst ? "" : `
8972
8997
  DOKPLOY_API_TOKEN: \${{ secrets.DOKPLOY_API_TOKEN }}
8973
8998
  DOKPLOY_ENDPOINT: \${{ vars.DOKPLOY_ENDPOINT }}`;
@@ -9049,20 +9074,7 @@ ${pm.setup}
9049
9074
  ${pm.setup}
9050
9075
  - name: Install
9051
9076
  run: ${pm.install}
9052
-
9053
- # The stage's secrets are committed encrypted; the key never is. Each
9054
- # environment holds its own as GKM_SECRETS_KEY.
9055
- # Owner-only, as the CLI writes its own keys. The stage reaches the shell
9056
- # as a variable, never pasted into the script: on a manual run it is
9057
- # whatever was typed.
9058
- - name: Stage secrets key
9059
- run: |
9060
- mkdir -p -m 700 ~/.gkm/${options.name}
9061
- (umask 077 && printf '%s' "$KEY" > ~/.gkm/${options.name}/"$STAGE".key)
9062
- env:
9063
- KEY: \${{ secrets.GKM_SECRETS_KEY }}
9064
- STAGE: \${{ matrix.stage }}
9065
- ${credentials}
9077
+ ${stageSecrets}
9066
9078
  - name: Deploy
9067
9079
  run: ${pm.run} "deploy:$STAGE"
9068
9080
  env:
@@ -9971,7 +9983,7 @@ function generateMonorepoFiles(options, _template) {
9971
9983
  version: "0.0.1",
9972
9984
  private: true,
9973
9985
  type: "module",
9974
- packageManager: "pnpm@10.13.1",
9986
+ packageManager: PNPM_VERSION,
9975
9987
  scripts: {
9976
9988
  dev: isFullstack ? "gkm dev" : "turbo dev",
9977
9989
  build: isFullstack ? "gkm build" : "turbo build",
@@ -10125,7 +10137,6 @@ ${isSst ? "\n# SST\n.sst/\n" : ""}`;
10125
10137
  const tsConfig = {
10126
10138
  compilerOptions: {
10127
10139
  ...isFullstack ? {
10128
- baseUrl: ".",
10129
10140
  paths: { [`@${options.name}/constructs/*`]: ["./constructs/*"] },
10130
10141
  allowImportingTsExtensions: true,
10131
10142
  noEmit: true
@@ -10275,12 +10286,24 @@ ${workspaceConstructsGlobs(options.routesStructure, dirname(options.apiPath)).ma
10275
10286
  ],
10276
10287
 
10277
10288
  secrets: {
10278
- enabled: true,
10289
+ enabled: true,${secretsStore(options)}
10279
10290
  },
10280
10291
  });
10281
10292
  `;
10282
10293
  }
10283
10294
  /**
10295
+ * Where a deployed stage's secrets live. On AWS that is SSM in the stage's own
10296
+ * account, which the deploy job reaches with the role it already assumed; a
10297
+ * server target keeps the encrypted local file, the default.
10298
+ */
10299
+ function secretsStore(options) {
10300
+ if (options.deployTarget !== "sst" || !options.region) return "";
10301
+ return `
10302
+ // Deployed stages keep their secrets in SSM, in the account each stage
10303
+ // deploys to: \`gkm secrets:push --stage <stage> --profile <profile>\`.
10304
+ store: { provider: 'ssm', region: '${options.region}' },`;
10305
+ }
10306
+ /**
10284
10307
  * The workspace's constructs, at its root rather than inside an app.
10285
10308
  *
10286
10309
  * They outlive the app that used them first: a site depending on the API is a
@@ -10495,7 +10518,7 @@ const apiTemplate = {
10495
10518
  const kv = cacheFor();
10496
10519
  const db = databaseFor();
10497
10520
  const mail = emailFor();
10498
- const src = (path) => monorepo ? `~/${path}` : `./${path}`;
10521
+ const src = (path) => `~/${path}`;
10499
10522
  const declares = !monorepo;
10500
10523
  const loggerContent = `import { createLogger } from '@geekmidas/logger/${loggerType}';
10501
10524
 
@@ -10578,7 +10601,7 @@ export const healthEndpoint = router
10578
10601
  timestamp: new Date().toISOString(),
10579
10602
  }));
10580
10603
  ` : `import { z } from 'zod';
10581
- import { router } from './router.ts';
10604
+ import { router } from '~/router.ts';
10582
10605
 
10583
10606
  export const healthEndpoint = router
10584
10607
  .get('/health')
@@ -11039,8 +11062,8 @@ export const telescope = new Telescope({
11039
11062
  content: `import { Direction, InMemoryMonitoringStorage, Studio } from '@geekmidas/studio';
11040
11063
  import { Kysely, PostgresDialect } from 'kysely';
11041
11064
  import pg from 'pg';
11042
- import type { Database } from './constructs/database.ts';
11043
- import { envParser } from './config/env.ts';
11065
+ import type { Database } from '~/constructs/database.ts';
11066
+ import { envParser } from '~/config/env.ts';
11044
11067
 
11045
11068
  // The key the database construct publishes — not a hand-written DATABASE_URL.
11046
11069
  const studioConfig = envParser
@@ -11599,7 +11622,6 @@ function generatePackageJson(options, template) {
11599
11622
  devDependencies["@geekmidas/testkit"] = GEEKMIDAS_VERSIONS["@geekmidas/testkit"];
11600
11623
  devDependencies["@faker-js/faker"] = DEPENDENCY_VERSIONS["@faker-js/faker"];
11601
11624
  devDependencies["kysely-ctl"] = DEPENDENCY_VERSIONS["kysely-ctl"];
11602
- devDependencies["vite-tsconfig-paths"] = DEPENDENCY_VERSIONS["vite-tsconfig-paths"];
11603
11625
  }
11604
11626
  if (monorepo) {
11605
11627
  delete devDependencies["@biomejs/biome"];
@@ -11624,6 +11646,7 @@ function generatePackageJson(options, template) {
11624
11646
  version: "0.0.1",
11625
11647
  private: true,
11626
11648
  type: "module",
11649
+ ...!monorepo && options.packageManager === "pnpm" ? { packageManager: PNPM_VERSION } : {},
11627
11650
  exports: {
11628
11651
  "./client": OPENAPI_OUTPUT_PATH,
11629
11652
  "./endpoints": ENDPOINTS_OUTPUT_PATH
@@ -11655,10 +11678,9 @@ function generateSourceFiles(options, template) {
11655
11678
  function generateTestFiles(options, _template) {
11656
11679
  if (!options.constructs.database) return [];
11657
11680
  const db = databaseFor();
11658
- const declares = !options.monorepo;
11659
- const schema = declares ? "../src/constructs/database.ts" : "~/services/database.ts";
11660
- const runtimeUrl = declares ? db.urlKey : "DATABASE_URL";
11661
- const ownerUrl = declares ? db.ownerUrlKey : "DATABASE_URL";
11681
+ const schema = !options.monorepo ? "../src/constructs/database.ts" : "~/services/database.ts";
11682
+ const runtimeUrl = db.urlKey;
11683
+ const ownerUrl = db.ownerUrlKey;
11662
11684
  return [
11663
11685
  {
11664
11686
  path: "kysely.config.ts",
@@ -11832,9 +11854,7 @@ function generateUiPackageFiles(options) {
11832
11854
  },
11833
11855
  devDependencies: {
11834
11856
  "@storybook/addon-a11y": TOOLCHAIN_VERSIONS["@storybook/addon-a11y"],
11835
- "@storybook/addon-essentials": TOOLCHAIN_VERSIONS["@storybook/addon-essentials"],
11836
- "@storybook/addon-interactions": TOOLCHAIN_VERSIONS["@storybook/addon-interactions"],
11837
- "@storybook/react": TOOLCHAIN_VERSIONS["@storybook/react"],
11857
+ "@storybook/addon-docs": TOOLCHAIN_VERSIONS["@storybook/addon-docs"],
11838
11858
  "@storybook/react-vite": TOOLCHAIN_VERSIONS["@storybook/react-vite"],
11839
11859
  "@tailwindcss/vite": DEPENDENCY_VERSIONS["@tailwindcss/vite"],
11840
11860
  "@types/react": DEPENDENCY_VERSIONS["@types/react"],
@@ -11844,7 +11864,7 @@ function generateUiPackageFiles(options) {
11844
11864
  storybook: TOOLCHAIN_VERSIONS["storybook"],
11845
11865
  tailwindcss: DEPENDENCY_VERSIONS["tailwindcss"],
11846
11866
  typescript: TOOLCHAIN_VERSIONS["typescript"],
11847
- vite: TOOLCHAIN_VERSIONS["vite@storybook"]
11867
+ vite: TOOLCHAIN_VERSIONS["vite"]
11848
11868
  },
11849
11869
  peerDependencies: {
11850
11870
  react: ">=18.0.0",
@@ -11863,7 +11883,6 @@ function generateUiPackageFiles(options) {
11863
11883
  ],
11864
11884
  noEmit: true,
11865
11885
  allowImportingTsExtensions: true,
11866
- baseUrl: ".",
11867
11886
  paths: { "~/*": ["./src/*"] }
11868
11887
  },
11869
11888
  include: ["src/**/*"],
@@ -11898,17 +11917,17 @@ function generateUiPackageFiles(options) {
11898
11917
 
11899
11918
  const config: StorybookConfig = {
11900
11919
  stories: ['../src/**/*.stories.@(ts|tsx)'],
11901
- addons: [
11902
- '@storybook/addon-essentials',
11903
- '@storybook/addon-interactions',
11904
- '@storybook/addon-a11y',
11905
- ],
11920
+ // Controls, actions, backgrounds, viewport and interactions are part of
11921
+ // \`storybook\` itself; docs and a11y are add-ons.
11922
+ addons: ['@storybook/addon-docs', '@storybook/addon-a11y'],
11906
11923
  framework: {
11907
11924
  name: '@storybook/react-vite',
11908
11925
  options: {},
11909
11926
  },
11910
- docs: {
11911
- autodocs: 'tag',
11927
+ // \`react-docgen\` parses components itself. The TypeScript-based docgen
11928
+ // calls into TypeScript's JavaScript API, which TypeScript 7 no longer ships.
11929
+ typescript: {
11930
+ reactDocgen: 'react-docgen',
11912
11931
  },
11913
11932
  viteFinal: async (config) => {
11914
11933
  // Add Tailwind CSS v4 plugin
@@ -11921,18 +11940,21 @@ const config: StorybookConfig = {
11921
11940
 
11922
11941
  export default config;
11923
11942
  `;
11924
- const storybookPreview = `import type { Preview } from '@storybook/react';
11943
+ const storybookPreview = `import type { Preview } from '@storybook/react-vite';
11925
11944
  import '../src/styles/globals.css';
11926
11945
 
11927
11946
  const preview: Preview = {
11947
+ // The starting background is a global, not a parameter.
11948
+ initialGlobals: {
11949
+ backgrounds: { value: 'dark' },
11950
+ },
11928
11951
  parameters: {
11929
11952
  backgrounds: {
11930
- default: 'dark',
11931
- values: [
11932
- { name: 'dark', value: '#171717' },
11933
- { name: 'surface', value: '#1c1c1c' },
11934
- { name: 'light', value: '#fafafa' },
11935
- ],
11953
+ options: {
11954
+ dark: { name: 'dark', value: '#171717' },
11955
+ surface: { name: 'surface', value: '#1c1c1c' },
11956
+ light: { name: 'light', value: '#fafafa' },
11957
+ },
11936
11958
  },
11937
11959
  controls: {
11938
11960
  matchers: {
@@ -12095,7 +12117,7 @@ Button.displayName = 'Button';
12095
12117
 
12096
12118
  export { Button, buttonVariants };
12097
12119
  `;
12098
- const buttonStories = `import type { Meta, StoryObj } from '@storybook/react';
12120
+ const buttonStories = `import type { Meta, StoryObj } from '@storybook/react-vite';
12099
12121
  import { Button } from '~/components/ui/button';
12100
12122
 
12101
12123
  const meta: Meta<typeof Button> = {
@@ -12260,7 +12282,7 @@ CardFooter.displayName = 'CardFooter';
12260
12282
 
12261
12283
  export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent };
12262
12284
  `;
12263
- const inputStories = `import type { Meta, StoryObj } from '@storybook/react';
12285
+ const inputStories = `import type { Meta, StoryObj } from '@storybook/react-vite';
12264
12286
  import { Input } from '~/components/ui/input';
12265
12287
 
12266
12288
  const meta: Meta<typeof Input> = {
@@ -12314,7 +12336,7 @@ export const WithValue: Story = {
12314
12336
  },
12315
12337
  };
12316
12338
  `;
12317
- const cardStories = `import type { Meta, StoryObj } from '@storybook/react';
12339
+ const cardStories = `import type { Meta, StoryObj } from '@storybook/react-vite';
12318
12340
  import { Button } from '~/components/ui/button';
12319
12341
  import {
12320
12342
  Card,
@@ -12401,7 +12423,7 @@ Label.displayName = LabelPrimitive.Root.displayName;
12401
12423
 
12402
12424
  export { Label };
12403
12425
  `;
12404
- const labelStories = `import type { Meta, StoryObj } from '@storybook/react';
12426
+ const labelStories = `import type { Meta, StoryObj } from '@storybook/react-vite';
12405
12427
  import { Input } from '~/components/ui/input';
12406
12428
  import { Label } from '~/components/ui/label';
12407
12429
 
@@ -12477,7 +12499,7 @@ function Badge({ className, variant, ...props }: BadgeProps) {
12477
12499
 
12478
12500
  export { Badge, badgeVariants };
12479
12501
  `;
12480
- const badgeStories = `import type { Meta, StoryObj } from '@storybook/react';
12502
+ const badgeStories = `import type { Meta, StoryObj } from '@storybook/react-vite';
12481
12503
  import { Badge } from '~/components/ui/badge';
12482
12504
 
12483
12505
  const meta: Meta<typeof Badge> = {
@@ -12553,7 +12575,7 @@ Separator.displayName = SeparatorPrimitive.Root.displayName;
12553
12575
 
12554
12576
  export { Separator };
12555
12577
  `;
12556
- const separatorStories = `import type { Meta, StoryObj } from '@storybook/react';
12578
+ const separatorStories = `import type { Meta, StoryObj } from '@storybook/react-vite';
12557
12579
  import { Separator } from '~/components/ui/separator';
12558
12580
 
12559
12581
  const meta: Meta<typeof Separator> = {
@@ -12658,7 +12680,7 @@ TabsContent.displayName = TabsPrimitive.Content.displayName;
12658
12680
 
12659
12681
  export { Tabs, TabsList, TabsTrigger, TabsContent };
12660
12682
  `;
12661
- const tabsStories = `import type { Meta, StoryObj } from '@storybook/react';
12683
+ const tabsStories = `import type { Meta, StoryObj } from '@storybook/react-vite';
12662
12684
  import { Tabs, TabsContent, TabsList, TabsTrigger } from '~/components/ui/tabs';
12663
12685
  import { Button } from '~/components/ui/button';
12664
12686
  import { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle } from '~/components/ui/card';
@@ -12762,7 +12784,7 @@ TooltipContent.displayName = TooltipPrimitive.Content.displayName;
12762
12784
 
12763
12785
  export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider };
12764
12786
  `;
12765
- const tooltipStories = `import type { Meta, StoryObj } from '@storybook/react';
12787
+ const tooltipStories = `import type { Meta, StoryObj } from '@storybook/react-vite';
12766
12788
  import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '~/components/ui/tooltip';
12767
12789
  import { Button } from '~/components/ui/button';
12768
12790
 
@@ -12955,7 +12977,7 @@ export {
12955
12977
  DialogDescription,
12956
12978
  };
12957
12979
  `;
12958
- const dialogStories = `import type { Meta, StoryObj } from '@storybook/react';
12980
+ const dialogStories = `import type { Meta, StoryObj } from '@storybook/react-vite';
12959
12981
  import {
12960
12982
  Dialog,
12961
12983
  DialogContent,
@@ -13287,7 +13309,6 @@ export default nextConfig;
13287
13309
  jsx: "preserve",
13288
13310
  incremental: true,
13289
13311
  plugins: [{ name: "next" }],
13290
- baseUrl: ".",
13291
13312
  paths: {
13292
13313
  "~/*": ["./src/*", "../../packages/ui/src/*"],
13293
13314
  [`${apiPackage}/client`]: ["../../apps/api/.gkm/openapi/api.ts"],
@@ -13582,8 +13603,7 @@ function generateTanStackWebFiles(options) {
13582
13603
  tailwindcss: DEPENDENCY_VERSIONS["tailwindcss"],
13583
13604
  tsx: TOOLCHAIN_VERSIONS["tsx"],
13584
13605
  typescript: TOOLCHAIN_VERSIONS["typescript"],
13585
- vite: TOOLCHAIN_VERSIONS["vite"],
13586
- "vite-tsconfig-paths": DEPENDENCY_VERSIONS["vite-tsconfig-paths"]
13606
+ vite: TOOLCHAIN_VERSIONS["vite"]
13587
13607
  }
13588
13608
  };
13589
13609
  const viteConfig = `import { Credentials } from '@geekmidas/envkit/credentials';
@@ -13591,16 +13611,16 @@ import tailwindcss from '@tailwindcss/vite';
13591
13611
  import { tanstackStart } from '@tanstack/react-start/plugin/vite';
13592
13612
  import viteReact from '@vitejs/plugin-react';
13593
13613
  import { defineConfig } from 'vite';
13594
- import tsconfigPaths from 'vite-tsconfig-paths';
13595
13614
 
13596
13615
  export default defineConfig({
13616
+ // Vite resolves tsconfig \`paths\` itself; no plugin needed.
13617
+ resolve: { tsconfigPaths: true },
13597
13618
  server: {
13598
13619
  port: Number(Credentials.PORT ?? 3001),
13599
13620
  },
13600
13621
  // VITE_* vars are inlined automatically; no manual loadEnv needed.
13601
13622
  envPrefix: 'VITE_',
13602
13623
  plugins: [
13603
- tsconfigPaths({ root: import.meta.dirname }),
13604
13624
  tailwindcss(),
13605
13625
  tanstackStart(),
13606
13626
  viteReact(),
@@ -13627,7 +13647,6 @@ export default defineConfig({
13627
13647
  isolatedModules: true,
13628
13648
  jsx: "preserve",
13629
13649
  incremental: true,
13630
- baseUrl: ".",
13631
13650
  types: ["vite/client"],
13632
13651
  paths: {
13633
13652
  "~/*": ["./src/*", "../../packages/ui/src/*"],
@@ -14890,7 +14909,7 @@ async function reconcileLocal(workspace, stage, options) {
14890
14909
  /**
14891
14910
  * Resolve secrets with priority:
14892
14911
  * 1. Local secrets exist → use them (preserves manual additions)
14893
- * 2. SSM configured and has secrets → pull and use
14912
+ * 2. A deployed stage whose store has secrets → pull and use
14894
14913
  * 3. Neither → generate fresh secrets
14895
14914
  *
14896
14915
  * --force skips checks 1 and 2 and always regenerates.
@@ -14909,18 +14928,15 @@ async function resolveSecrets(stage, workspace, options) {
14909
14928
  return reconciled ?? secrets;
14910
14929
  }
14911
14930
  }
14912
- if (isSSMConfigured(workspace)) {
14913
- logger$1.log("☁️ Checking for remote secrets in SSM...");
14931
+ if (isRemoteStore(workspace, stage)) {
14932
+ logger$1.log("☁️ Checking the secrets store...");
14914
14933
  try {
14915
- const remoteSecrets = await pullSecrets(stage, workspace);
14916
- if (remoteSecrets) {
14917
- logger$1.log("✅ Pulled secrets from SSM");
14918
- await writeStageSecrets(remoteSecrets, workspace.root);
14919
- return remoteSecrets;
14920
- }
14921
- logger$1.log(" No remote secrets found");
14934
+ const { secrets } = await pullStageSecrets(workspace, stage);
14935
+ logger$1.log("✅ Pulled secrets from the store");
14936
+ return secrets;
14922
14937
  } catch (error) {
14923
- logger$1.warn(`⚠️ Failed to pull from SSM: ${error.message}`);
14938
+ if (error instanceof NoStoredSecrets) logger$1.log(" The store holds none yet");
14939
+ else logger$1.warn(`⚠️ Could not pull from the store: ${error.message}`);
14924
14940
  }
14925
14941
  }
14926
14942
  logger$1.log("🔐 Generating fresh development secrets...");
@@ -15054,18 +15070,18 @@ async function generateFreshSecrets(stage, workspace, options) {
15054
15070
  const secrets = createFreshWorkspaceSecrets(stage, workspace, await derivedContainers(workspace, stage));
15055
15071
  await writeStageSecrets(secrets, workspace.root);
15056
15072
  logger$1.log(` Secrets written to .gkm/secrets/${stage}.json`);
15057
- if (isSSMConfigured(workspace) && !options.yes) {
15073
+ if (isRemoteStore(workspace, stage) && !options.yes) {
15058
15074
  const { shouldPush } = await prompts({
15059
15075
  type: "confirm",
15060
15076
  name: "shouldPush",
15061
- message: "Push secrets to SSM for team sharing?",
15077
+ message: `Push the "${stage}" secrets to its store?`,
15062
15078
  initial: true
15063
15079
  });
15064
15080
  if (shouldPush) try {
15065
- await pushSecrets(stage, workspace);
15066
- logger$1.log("☁️ Secrets pushed to SSM");
15081
+ await pushStageSecrets(workspace, stage);
15082
+ logger$1.log("☁️ Secrets pushed to the store");
15067
15083
  } catch (error) {
15068
- logger$1.warn(`⚠️ Failed to push to SSM: ${error.message}`);
15084
+ logger$1.warn(`⚠️ Could not push to the store: ${error.message}`);
15069
15085
  }
15070
15086
  }
15071
15087
  return secrets;
@@ -15499,7 +15515,7 @@ const program = new Command();
15499
15515
  program.name("gkm").description("GeekMidas backend framework CLI").version(version).option("--cwd <path>", "Change working directory").option("--debug", "Enable debug mode (verbose errors with stack traces)").hook("preAction", () => {
15500
15516
  if (program.opts().debug);
15501
15517
  });
15502
- program.command("init").description("Scaffold a new project").argument("[name]", "Project name").option("--template <template>", "Project template (minimal, api, serverless, worker)").option("--skip-install", "Skip dependency installation", false).option("-y, --yes", "Skip prompts, use defaults", false).option("--monorepo", "Setup as monorepo with packages/models", false).option("--api-path <path>", "API app path in monorepo (default: apps/api)").option("--pm <manager>", "Package manager (pnpm, npm, yarn, bun)").option("--deploy <target>", "Where it deploys (dokploy, sst, none)").option("--region <region>", "AWS region for an SST deploy (e.g. eu-west-1)").option("--stages <names>", "Deployed stages, comma-separated (e.g. staging,prod)").option("--protected-stage <name>", "Which deployed stage is production").option("--local-stage <name>", "What gkm dev runs as (e.g. dev)").option("--region <region>", "AWS region for an SST deploy (e.g. eu-west-1)").action(async (name, options) => {
15518
+ program.command("init").description("Scaffold a new project").argument("[name]", "Project name").option("--template <template>", "Project template (minimal, api, serverless, worker)").option("--skip-install", "Skip dependency installation", false).option("-y, --yes", "Skip prompts, use defaults", false).option("--monorepo", "Setup as monorepo with packages/models", false).option("--api-path <path>", "API app path in monorepo (default: apps/api)").option("--pm <manager>", "Package manager (pnpm, npm, yarn, bun)").option("--deploy <target>", "Where it deploys (dokploy, sst, none)").option("--region <region>", "AWS region for an SST deploy (e.g. eu-west-1)").option("--stages <names>", "Deployed stages, comma-separated (e.g. staging,prod)").option("--protected-stage <name>", "Which deployed stage is production").option("--local-stage <name>", "What gkm dev runs as (e.g. dev)").action(async (name, options) => {
15503
15519
  try {
15504
15520
  const globalOptions = program.opts();
15505
15521
  if (globalOptions.cwd) process.chdir(globalOptions.cwd);
@@ -15716,54 +15732,30 @@ program.command("secrets:import").description("Import secrets from a JSON file")
15716
15732
  process.exit(1);
15717
15733
  }
15718
15734
  });
15719
- program.command("secrets:push").description("Push secrets to remote provider (SSM)").requiredOption("--stage <stage>", "Stage name").action(async (options) => {
15735
+ program.command("secrets:push").description("Send a deployed stage's secrets to its store (secrets.store)").requiredOption("--stage <stage>", "A deployed stage").option("--profile <profile>", "AWS profile for the stage's account").action(async (options) => {
15720
15736
  try {
15721
15737
  const globalOptions = program.opts();
15722
15738
  if (globalOptions.cwd) process.chdir(globalOptions.cwd);
15723
15739
  const { loadWorkspaceConfig } = await import("./config.mjs");
15724
- const { pushSecrets } = await import("./sync-B3xxXtJT.mjs").then((n) => n.i);
15725
- const { reconcileMissingSecrets } = await import("./reconcile-DhQ00DpU.mjs");
15726
- const { readStageSecrets, writeStageSecrets } = await import("./storage-P_b3w7uj.mjs").then((n) => n.a);
15740
+ const { pushStageSecrets } = await import("./transfer-2aRVVJ6I.mjs").then((n) => n.i);
15727
15741
  const { workspace } = await loadWorkspaceConfig();
15728
- const secrets = await readStageSecrets(options.stage, workspace.root);
15729
- if (secrets) {
15730
- const { derivedContainers } = await import("./credentials-BekkKtY_.mjs").then((n) => n.h);
15731
- const result = reconcileMissingSecrets(secrets, workspace, await derivedContainers(workspace, options.stage));
15732
- if (result) {
15733
- await writeStageSecrets(result.secrets, workspace.root);
15734
- console.log(` Reconciled ${result.addedKeys.length} missing secret(s):`);
15735
- for (const key of result.addedKeys) console.log(` + ${key}`);
15736
- }
15737
- }
15738
- await pushSecrets(options.stage, workspace);
15742
+ const { addedKeys } = await pushStageSecrets(workspace, options.stage, { profile: options.profile });
15743
+ for (const key of addedKeys) console.log(` + ${key} (reconciled)`);
15739
15744
  console.log(`\n✓ Secrets pushed for stage "${options.stage}"`);
15740
15745
  } catch (error) {
15741
15746
  console.error(formatError(error));
15742
15747
  process.exit(1);
15743
15748
  }
15744
15749
  });
15745
- program.command("secrets:pull").description("Pull secrets from remote provider (SSM)").requiredOption("--stage <stage>", "Stage name").action(async (options) => {
15750
+ program.command("secrets:pull").description("Bring a deployed stage's secrets from its store into the local copy").requiredOption("--stage <stage>", "A deployed stage").option("--profile <profile>", "AWS profile for the stage's account").action(async (options) => {
15746
15751
  try {
15747
15752
  const globalOptions = program.opts();
15748
15753
  if (globalOptions.cwd) process.chdir(globalOptions.cwd);
15749
15754
  const { loadWorkspaceConfig } = await import("./config.mjs");
15750
- const { pullSecrets } = await import("./sync-B3xxXtJT.mjs").then((n) => n.i);
15751
- const { writeStageSecrets } = await import("./storage-P_b3w7uj.mjs").then((n) => n.a);
15752
- const { reconcileMissingSecrets } = await import("./reconcile-DhQ00DpU.mjs");
15755
+ const { pullStageSecrets } = await import("./transfer-2aRVVJ6I.mjs").then((n) => n.i);
15753
15756
  const { workspace } = await loadWorkspaceConfig();
15754
- let secrets = await pullSecrets(options.stage, workspace);
15755
- if (!secrets) {
15756
- console.error(`No remote secrets found for stage "${options.stage}".`);
15757
- process.exit(1);
15758
- }
15759
- const { derivedContainers } = await import("./credentials-BekkKtY_.mjs").then((n) => n.h);
15760
- const result = reconcileMissingSecrets(secrets, workspace, await derivedContainers(workspace, options.stage));
15761
- if (result) {
15762
- secrets = result.secrets;
15763
- console.log(` Reconciled ${result.addedKeys.length} missing secret(s):`);
15764
- for (const key of result.addedKeys) console.log(` + ${key}`);
15765
- }
15766
- await writeStageSecrets(secrets, workspace.root);
15757
+ const { addedKeys } = await pullStageSecrets(workspace, options.stage, { profile: options.profile });
15758
+ for (const key of addedKeys) console.log(` + ${key} (reconciled)`);
15767
15759
  console.log(`\n✓ Secrets pulled for stage "${options.stage}"`);
15768
15760
  } catch (error) {
15769
15761
  console.error(formatError(error));
@@ -15775,8 +15767,8 @@ program.command("secrets:reconcile").description("Backfill missing custom secret
15775
15767
  const globalOptions = program.opts();
15776
15768
  if (globalOptions.cwd) process.chdir(globalOptions.cwd);
15777
15769
  const { loadWorkspaceConfig } = await import("./config.mjs");
15778
- const { reconcileMissingSecrets } = await import("./reconcile-DhQ00DpU.mjs");
15779
- const { readStageSecrets, writeStageSecrets } = await import("./storage-P_b3w7uj.mjs").then((n) => n.a);
15770
+ const { reconcileMissingSecrets } = await import("./reconcile-fmoluZmZ.mjs").then((n) => n.n);
15771
+ const { readStageSecrets, writeStageSecrets } = await import("./storage-TP0x118M.mjs").then((n) => n.a);
15780
15772
  const { workspace } = await loadWorkspaceConfig();
15781
15773
  const stage = options.stage ?? workspace.stages.local;
15782
15774
  const secrets = await readStageSecrets(stage, workspace.root);
@@ -15784,7 +15776,7 @@ program.command("secrets:reconcile").description("Backfill missing custom secret
15784
15776
  console.error(`No secrets found for stage "${stage}". Run "gkm secrets:init --stage ${stage}" first.`);
15785
15777
  process.exit(1);
15786
15778
  }
15787
- const { derivedContainers } = await import("./credentials-BekkKtY_.mjs").then((n) => n.h);
15779
+ const { derivedContainers } = await import("./credentials-lbv-j0Be.mjs").then((n) => n.h);
15788
15780
  const result = reconcileMissingSecrets(secrets, workspace, await derivedContainers(workspace, stage));
15789
15781
  if (!result) {
15790
15782
  console.log(`\n✓ Secrets for stage "${stage}" are up-to-date`);
@@ -15843,7 +15835,7 @@ program.command("deploy:github").description("Let GitHub Actions deploy a stage:
15843
15835
  try {
15844
15836
  const globalOptions = program.opts();
15845
15837
  if (globalOptions.cwd) process.chdir(globalOptions.cwd);
15846
- const { deployGithubCommand } = await import("./github-CRwnxKmD.mjs");
15838
+ const { deployGithubCommand } = await import("./github-DlIrXPee.mjs");
15847
15839
  await deployGithubCommand(options);
15848
15840
  } catch (error) {
15849
15841
  console.error(formatError(error));