getmyenv 0.1.1 → 0.3.1

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 (88) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +12 -4
  3. package/dist/cli.d.ts.map +1 -1
  4. package/dist/cli.js +81 -51
  5. package/dist/cli.js.map +1 -1
  6. package/dist/commands/backup.d.ts.map +1 -1
  7. package/dist/commands/backup.js +15 -6
  8. package/dist/commands/backup.js.map +1 -1
  9. package/dist/commands/link.d.ts +16 -0
  10. package/dist/commands/link.d.ts.map +1 -0
  11. package/dist/commands/link.js +116 -0
  12. package/dist/commands/link.js.map +1 -0
  13. package/dist/commands/pull.d.ts +15 -0
  14. package/dist/commands/pull.d.ts.map +1 -0
  15. package/dist/commands/pull.js +157 -0
  16. package/dist/commands/pull.js.map +1 -0
  17. package/dist/commands/push.d.ts +15 -0
  18. package/dist/commands/push.d.ts.map +1 -0
  19. package/dist/commands/push.js +259 -0
  20. package/dist/commands/push.js.map +1 -0
  21. package/dist/commands/restore.d.ts.map +1 -1
  22. package/dist/commands/restore.js +27 -14
  23. package/dist/commands/restore.js.map +1 -1
  24. package/dist/commands/run.d.ts +1 -0
  25. package/dist/commands/run.d.ts.map +1 -1
  26. package/dist/commands/run.js +66 -25
  27. package/dist/commands/run.js.map +1 -1
  28. package/dist/commands/token.d.ts +19 -0
  29. package/dist/commands/token.d.ts.map +1 -0
  30. package/dist/commands/token.js +188 -0
  31. package/dist/commands/token.js.map +1 -0
  32. package/dist/commands/whoami.d.ts +6 -0
  33. package/dist/commands/whoami.d.ts.map +1 -0
  34. package/dist/commands/whoami.js +51 -0
  35. package/dist/commands/whoami.js.map +1 -0
  36. package/dist/lib/api.d.ts +17 -10
  37. package/dist/lib/api.d.ts.map +1 -1
  38. package/dist/lib/api.js +77 -28
  39. package/dist/lib/api.js.map +1 -1
  40. package/dist/lib/bootstrap.d.ts +20 -0
  41. package/dist/lib/bootstrap.d.ts.map +1 -0
  42. package/dist/lib/bootstrap.js +64 -0
  43. package/dist/lib/bootstrap.js.map +1 -0
  44. package/dist/lib/confirm.d.ts +17 -0
  45. package/dist/lib/confirm.d.ts.map +1 -0
  46. package/dist/lib/confirm.js +26 -0
  47. package/dist/lib/confirm.js.map +1 -0
  48. package/dist/lib/credentials.d.ts +65 -4
  49. package/dist/lib/credentials.d.ts.map +1 -1
  50. package/dist/lib/credentials.js +256 -17
  51. package/dist/lib/credentials.js.map +1 -1
  52. package/dist/lib/fs.d.ts +19 -1
  53. package/dist/lib/fs.d.ts.map +1 -1
  54. package/dist/lib/fs.js +88 -59
  55. package/dist/lib/fs.js.map +1 -1
  56. package/dist/lib/pek.d.ts +32 -0
  57. package/dist/lib/pek.d.ts.map +1 -0
  58. package/dist/lib/pek.js +81 -0
  59. package/dist/lib/pek.js.map +1 -0
  60. package/package.json +1 -1
  61. package/dist/commands/add.d.ts +0 -8
  62. package/dist/commands/add.d.ts.map +0 -1
  63. package/dist/commands/add.js +0 -64
  64. package/dist/commands/add.js.map +0 -1
  65. package/dist/commands/export.d.ts +0 -9
  66. package/dist/commands/export.d.ts.map +0 -1
  67. package/dist/commands/export.js +0 -48
  68. package/dist/commands/export.js.map +0 -1
  69. package/dist/commands/init.d.ts +0 -2
  70. package/dist/commands/init.d.ts.map +0 -1
  71. package/dist/commands/init.js +0 -58
  72. package/dist/commands/init.js.map +0 -1
  73. package/dist/commands/login.d.ts +0 -6
  74. package/dist/commands/login.d.ts.map +0 -1
  75. package/dist/commands/login.js +0 -35
  76. package/dist/commands/login.js.map +0 -1
  77. package/dist/commands/logout.d.ts +0 -2
  78. package/dist/commands/logout.d.ts.map +0 -1
  79. package/dist/commands/logout.js +0 -13
  80. package/dist/commands/logout.js.map +0 -1
  81. package/dist/commands/migrate.d.ts +0 -13
  82. package/dist/commands/migrate.d.ts.map +0 -1
  83. package/dist/commands/migrate.js +0 -127
  84. package/dist/commands/migrate.js.map +0 -1
  85. package/dist/commands/status.d.ts +0 -7
  86. package/dist/commands/status.d.ts.map +0 -1
  87. package/dist/commands/status.js +0 -76
  88. package/dist/commands/status.js.map +0 -1
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2026 getenv.dev
3
+ Copyright (c) 2026 getmyenv
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -3,11 +3,19 @@
3
3
  CLI for [getmyenv](https://getmyenv.com) - encrypted environment variables for any language.
4
4
 
5
5
  ```bash
6
- npx getmyenv login
7
- npx getmyenv migrate
8
- npx getmyenv run -- npm start
6
+ npx getmyenv token # paste per-project token
7
+ npx getmyenv link # link this folder to the project
8
+ npx getmyenv run -- npm run dev # start app with secrets as env vars
9
9
  ```
10
10
 
11
- Create a token at https://getmyenv.com/cli, then `login` (or paste when a command asks). Login may offer to run `migrate`. Migrate searches this folder tree for `.env*` files (including `.env.example` / `.env.sample`) and lists candidates. Use `--file` to pick a path. Defaults to `https://getmyenv.com`. Use `login --api-url` or `--api-url` for another origin.
11
+ Create a project at https://getmyenv.com/projects/new, create a per-project CLI token at https://getmyenv.com/cli, then paste it with `token`. Not a full account login. Daily Development work prefers `run`. `push` and `pull` ask for token and link if missing.
12
+
13
+ - Development token: push / pull / restore / run. Push lists `.env*` files and skips any basename containing `production`.
14
+ - Production token: read-only (`run` / `backup`). Set Production values in the dashboard.
15
+ - Environment comes from token scope. Omit `-e` day to day.
16
+
17
+ API defaults to `https://getmyenv.com`. Use `token --api-url` or `--api-url` for another origin.
18
+
19
+ Commands: `token`, `link`, `push`, `pull`, `run`, `whoami`, `backup`, `restore`.
12
20
 
13
21
  See https://getmyenv.com/docs
package/dist/cli.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AA0BA,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAmI1D"}
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAgCA,wBAAsB,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAmK1D"}
package/dist/cli.js CHANGED
@@ -1,77 +1,102 @@
1
1
  import { Command } from "commander";
2
- import { initCommand } from "./commands/init.js";
3
- import { migrateCommand } from "./commands/migrate.js";
4
- import { addCommand } from "./commands/add.js";
5
- import { statusCommand } from "./commands/status.js";
6
- import { exportCommand } from "./commands/export.js";
7
2
  import { backupCommand } from "./commands/backup.js";
8
3
  import { restoreCommand } from "./commands/restore.js";
9
4
  import { runCommand } from "./commands/run.js";
10
- import { loginCommand } from "./commands/login.js";
11
- import { logoutCommand } from "./commands/logout.js";
5
+ import { tokenCommand, tokenListCommand, tokenRemoveCommand, tokenUseCommand, } from "./commands/token.js";
6
+ import { linkCommand } from "./commands/link.js";
7
+ import { pushCommand } from "./commands/push.js";
8
+ import { pullCommand } from "./commands/pull.js";
9
+ import { whoamiCommand } from "./commands/whoami.js";
12
10
  import { normalizeEnvName } from "./lib/env-name.js";
13
11
  import { resolveApiUrl } from "./lib/api.js";
12
+ import { readProjectMeta } from "./lib/fs.js";
13
+ function envWasDefaultFromArgv() {
14
+ return !process.argv.includes("-e") && !process.argv.includes("--env");
15
+ }
16
+ function defaultEnvOption() {
17
+ const meta = readProjectMeta();
18
+ return meta?.defaultEnv ?? "development";
19
+ }
14
20
  const ENV_OPTION = [
15
21
  "-e, --env <name>",
16
- "Environment (lowercase, e.g. development or production)",
17
- "development",
22
+ "Environment (must match token scope; omit to use the token)",
18
23
  ];
19
- function withNormalizedEnv(fn) {
20
- return (opts) => fn({ ...opts, env: normalizeEnvName(opts.env) });
21
- }
22
24
  export async function runCli(argv) {
23
25
  const apiDefault = resolveApiUrl();
24
26
  const program = new Command();
25
27
  program
26
28
  .name("getmyenv")
27
29
  .description("Keep using environment variables. Stop managing them as files.")
28
- .version("0.1.1");
29
- program
30
- .command("login")
31
- .description("Save a dashboard CLI token (paste once; no shell env needed)")
30
+ .version("0.3.1");
31
+ const token = program
32
+ .command("token")
33
+ .description("Save a per-project CLI token on this machine (not a full account login)")
32
34
  .option("--api-url <url>", "API base URL to remember (default production)")
33
- .action(loginCommand);
35
+ .action((opts) => tokenCommand(opts));
36
+ token
37
+ .command("list")
38
+ .description("List saved per-project tokens")
39
+ .action(() => tokenListCommand());
40
+ token
41
+ .command("use <nameOrId>")
42
+ .description("Set the default saved token")
43
+ .action((nameOrId) => tokenUseCommand(nameOrId));
44
+ token
45
+ .command("remove")
46
+ .description("Remove a saved per-project token")
47
+ .option("--project <name|id>", "Remove token for a specific project")
48
+ .option("--all", "Remove all saved tokens")
49
+ .option("--fresh", "Also clear local .getmyenv/wrapped-key.json")
50
+ .action(tokenRemoveCommand);
34
51
  program
35
- .command("logout")
36
- .description("Clear the saved CLI token")
37
- .action(logoutCommand);
38
- program
39
- .command("init")
40
- .description("Detect expected environment variable names across languages (never collects values)")
41
- .action(initCommand);
52
+ .command("link [projectId]")
53
+ .description("Link this folder to the token's project")
54
+ .option("--name <name>", "Expect project name (exact or unique substring)")
55
+ .option("--expect <name>", "Alias for --name")
56
+ .option("--env <name>", "Set defaultEnv (must match token scope)")
57
+ .option("--force", "Replace an existing link without prompting")
58
+ .option("--clear", "Remove the linked project from this folder")
59
+ .option("--api-url <url>", "API base URL", apiDefault)
60
+ .action((projectId, opts) => linkCommand(projectId, opts));
42
61
  program
43
- .command("migrate")
44
- .description("Encrypt an .env* file locally and upload (searches this folder tree)")
62
+ .command("push")
63
+ .description("Encrypt local secrets and upload to the linked token project")
45
64
  .option(...ENV_OPTION)
46
- .option("-f, --file <path>", "Path to .env file to migrate")
65
+ .option("-f, --file <path>", "Path to .env file to push")
66
+ .option("-k, --key <NAME=VALUE>", "Push a single secret (NAME or NAME=VALUE)")
67
+ .option("--create", "If unlinked, write project.json from the token then upload")
68
+ .option("--prune", "Delete hosted secrets that are not in the local file")
69
+ .option("--yes", "Apply changes without prompting on conflicts")
70
+ .option("--dry-run", "Show what would change without uploading")
47
71
  .option("--api-url <url>", "API base URL", apiDefault)
48
72
  .option("--vault-password-stdin", "Read vault password from stdin (non-interactive)")
49
- .action((opts) => migrateCommand({
73
+ .action((opts) => pushCommand({
50
74
  ...opts,
51
- env: normalizeEnvName(opts.env),
52
- envWasDefault: !process.argv.includes("-e") && !process.argv.includes("--env"),
75
+ env: normalizeEnvName(opts.env ?? defaultEnvOption()),
76
+ envWasDefault: envWasDefaultFromArgv(),
53
77
  }));
54
78
  program
55
- .command("add <name>")
56
- .description("Add a secret via secure interactive input (never pass values on the CLI)")
57
- .option(...ENV_OPTION)
58
- .option("--api-url <url>", "API base URL", apiDefault)
59
- .option("--vault-password-stdin", "Read vault password from stdin (non-interactive)")
60
- .action((name, opts) => addCommand(name, { ...opts, env: normalizeEnvName(opts.env) }));
61
- program
62
- .command("status")
63
- .description("Show secret status for the current project")
64
- .option(...ENV_OPTION)
65
- .option("--api-url <url>", "API base URL", apiDefault)
66
- .action(withNormalizedEnv(statusCommand));
67
- program
68
- .command("export")
69
- .description("Export secrets to a plaintext .env file")
79
+ .command("pull")
80
+ .description("Download secrets to a plaintext .env file")
70
81
  .option(...ENV_OPTION)
71
82
  .option("-o, --output <file>", "Output file", ".env")
83
+ .option("--to <file>", "Alias for --output")
84
+ .option("--stdout", "Write to stdout instead of a file")
85
+ .option("--yes", "Overwrite conflicting local values without prompting")
86
+ .option("--merge", "Only fill missing keys; keep local values")
87
+ .option("--dry-run", "Show what would change without writing")
72
88
  .option("--api-url <url>", "API base URL", apiDefault)
73
89
  .option("--vault-password-stdin", "Read vault password from stdin (non-interactive)")
74
- .action(withNormalizedEnv(exportCommand));
90
+ .action((opts) => pullCommand({
91
+ ...opts,
92
+ env: normalizeEnvName(opts.env ?? defaultEnvOption()),
93
+ envWasDefault: envWasDefaultFromArgv(),
94
+ }));
95
+ program
96
+ .command("whoami")
97
+ .description("Show the active CLI token, project, and defaults")
98
+ .option("--api-url <url>", "API base URL")
99
+ .action(whoamiCommand);
75
100
  program
76
101
  .command("backup")
77
102
  .description("Create a portable encrypted .getmyenv backup")
@@ -80,14 +105,14 @@ export async function runCli(argv) {
80
105
  .action(backupCommand);
81
106
  program
82
107
  .command("restore <file>")
83
- .description("Restore from an encrypted .getmyenv backup (creates a new project by default)")
108
+ .description("Restore from an encrypted .getmyenv backup into the token's project")
84
109
  .option("--api-url <url>", "API base URL", apiDefault)
85
- .option("--into-linked", "Overwrite the project linked in the current directory")
110
+ .option("--into-linked", "Require a linked folder (restore still targets the token project)")
86
111
  .option("--vault-password-stdin", "Read vault password from stdin (non-interactive)")
87
112
  .action(restoreCommand);
88
113
  program
89
114
  .command("run")
90
- .description("Decrypt authorized secrets and run a command with the secrets available as environment variables")
115
+ .description("Decrypt authorized secrets and run a command (token picks Development or Production)")
91
116
  .option(...ENV_OPTION)
92
117
  .option("--api-url <url>", "API base URL", apiDefault)
93
118
  .option("--vault-password-stdin", "Read vault password from stdin (non-interactive)")
@@ -95,10 +120,15 @@ export async function runCli(argv) {
95
120
  .allowExcessArguments(true)
96
121
  .action(async (opts, cmd) => {
97
122
  const args = cmd.args;
98
- // Support: getmyenv run -- npm start
123
+ // Support: getmyenv run -- npm run dev
99
124
  const dashIdx = process.argv.indexOf("--");
100
125
  const childArgs = dashIdx >= 0 ? process.argv.slice(dashIdx + 1) : args;
101
- await runCommand({ ...opts, env: normalizeEnvName(opts.env) }, childArgs);
126
+ await runCommand({
127
+ ...opts,
128
+ env: normalizeEnvName(opts.env ?? defaultEnvOption()),
129
+ envWasDefault: envWasDefaultFromArgv(),
130
+ apiUrl: opts.apiUrl ?? apiDefault,
131
+ }, childArgs);
102
132
  });
103
133
  await program.parseAsync(argv);
104
134
  }
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAE7C,MAAM,UAAU,GAAG;IACjB,kBAAkB;IAClB,yDAAyD;IACzD,aAAa;CACL,CAAC;AAEX,SAAS,iBAAiB,CACxB,EAA8B;IAE9B,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,EAAE,CAAC,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;AACpE,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,IAAc;IACzC,MAAM,UAAU,GAAG,aAAa,EAAE,CAAC;IACnC,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;IAC9B,OAAO;SACJ,IAAI,CAAC,UAAU,CAAC;SAChB,WAAW,CACV,gEAAgE,CACjE;SACA,OAAO,CAAC,OAAO,CAAC,CAAC;IAEpB,OAAO;SACJ,OAAO,CAAC,OAAO,CAAC;SAChB,WAAW,CAAC,8DAA8D,CAAC;SAC3E,MAAM,CAAC,iBAAiB,EAAE,+CAA+C,CAAC;SAC1E,MAAM,CAAC,YAAY,CAAC,CAAC;IAExB,OAAO;SACJ,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,2BAA2B,CAAC;SACxC,MAAM,CAAC,aAAa,CAAC,CAAC;IAEzB,OAAO;SACJ,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CACV,qFAAqF,CACtF;SACA,MAAM,CAAC,WAAW,CAAC,CAAC;IAEvB,OAAO;SACJ,OAAO,CAAC,SAAS,CAAC;SAClB,WAAW,CACV,sEAAsE,CACvE;SACA,MAAM,CAAC,GAAG,UAAU,CAAC;SACrB,MAAM,CAAC,mBAAmB,EAAE,8BAA8B,CAAC;SAC3D,MAAM,CAAC,iBAAiB,EAAE,cAAc,EAAE,UAAU,CAAC;SACrD,MAAM,CACL,wBAAwB,EACxB,kDAAkD,CACnD;SACA,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CACf,cAAc,CAAC;QACb,GAAG,IAAI;QACP,GAAG,EAAE,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC;QAC/B,aAAa,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC;KAC/E,CAAC,CACH,CAAC;IAEJ,OAAO;SACJ,OAAO,CAAC,YAAY,CAAC;SACrB,WAAW,CACV,0EAA0E,CAC3E;SACA,MAAM,CAAC,GAAG,UAAU,CAAC;SACrB,MAAM,CAAC,iBAAiB,EAAE,cAAc,EAAE,UAAU,CAAC;SACrD,MAAM,CACL,wBAAwB,EACxB,kDAAkD,CACnD;SACA,MAAM,CAAC,CAAC,IAAY,EAAE,IAAmE,EAAE,EAAE,CAC5F,UAAU,CAAC,IAAI,EAAE,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAC/D,CAAC;IAEJ,OAAO;SACJ,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,4CAA4C,CAAC;SACzD,MAAM,CAAC,GAAG,UAAU,CAAC;SACrB,MAAM,CAAC,iBAAiB,EAAE,cAAc,EAAE,UAAU,CAAC;SACrD,MAAM,CAAC,iBAAiB,CAAC,aAAa,CAAC,CAAC,CAAC;IAE5C,OAAO;SACJ,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,yCAAyC,CAAC;SACtD,MAAM,CAAC,GAAG,UAAU,CAAC;SACrB,MAAM,CAAC,qBAAqB,EAAE,aAAa,EAAE,MAAM,CAAC;SACpD,MAAM,CAAC,iBAAiB,EAAE,cAAc,EAAE,UAAU,CAAC;SACrD,MAAM,CACL,wBAAwB,EACxB,kDAAkD,CACnD;SACA,MAAM,CAAC,iBAAiB,CAAC,aAAa,CAAC,CAAC,CAAC;IAE5C,OAAO;SACJ,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,8CAA8C,CAAC;SAC3D,MAAM,CAAC,qBAAqB,EAAE,aAAa,CAAC;SAC5C,MAAM,CAAC,iBAAiB,EAAE,cAAc,EAAE,UAAU,CAAC;SACrD,MAAM,CAAC,aAAa,CAAC,CAAC;IAEzB,OAAO;SACJ,OAAO,CAAC,gBAAgB,CAAC;SACzB,WAAW,CACV,+EAA+E,CAChF;SACA,MAAM,CAAC,iBAAiB,EAAE,cAAc,EAAE,UAAU,CAAC;SACrD,MAAM,CACL,eAAe,EACf,uDAAuD,CACxD;SACA,MAAM,CACL,wBAAwB,EACxB,kDAAkD,CACnD;SACA,MAAM,CAAC,cAAc,CAAC,CAAC;IAE1B,OAAO;SACJ,OAAO,CAAC,KAAK,CAAC;SACd,WAAW,CACV,kGAAkG,CACnG;SACA,MAAM,CAAC,GAAG,UAAU,CAAC;SACrB,MAAM,CAAC,iBAAiB,EAAE,cAAc,EAAE,UAAU,CAAC;SACrD,MAAM,CACL,wBAAwB,EACxB,kDAAkD,CACnD;SACA,kBAAkB,CAAC,IAAI,CAAC;SACxB,oBAAoB,CAAC,IAAI,CAAC;SAC1B,MAAM,CAAC,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE;QAC1B,MAAM,IAAI,GAAG,GAAG,CAAC,IAAgB,CAAC;QAClC,qCAAqC;QACrC,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAC3C,MAAM,SAAS,GACb,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;QACxD,MAAM,UAAU,CACd,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,EAC5C,SAAS,CACV,CAAC;IACJ,CAAC,CAAC,CAAC;IAEL,MAAM,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;AACjC,CAAC"}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"backup.d.ts","sourceRoot":"","sources":["../../src/commands/backup.ts"],"names":[],"mappings":"AAYA,KAAK,UAAU,GAAG;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtD,wBAAsB,aAAa,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CA4CnE"}
1
+ {"version":3,"file":"backup.d.ts","sourceRoot":"","sources":["../../src/commands/backup.ts"],"names":[],"mappings":"AAiBA,KAAK,UAAU,GAAG;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAEtD,wBAAsB,aAAa,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CA2DnE"}
@@ -2,16 +2,22 @@ import fs from "node:fs";
2
2
  import path from "node:path";
3
3
  import pc from "picocolors";
4
4
  import { createBackupEnvelope, parsePayload, parseWrappedKey, serializeBackup, } from "@getmyenv/crypto";
5
- import { readProjectMeta } from "../lib/fs.js";
6
- import { ApiClient, ensureSessionToken } from "../lib/api.js";
5
+ import { readProjectMeta, requireLinkedProject } from "../lib/fs.js";
6
+ import { ApiClient, ensureSessionToken, resolveApiUrl, } from "../lib/api.js";
7
7
  export async function backupCommand(opts) {
8
8
  console.log(pc.bold("\ngetmyenv backup\n"));
9
9
  const meta = readProjectMeta();
10
- if (!meta?.projectId) {
11
- throw new Error("Linked project required for backup. Run migrate first, then npx getmyenv login if needed.");
10
+ requireLinkedProject(meta);
11
+ const token = await ensureSessionToken(meta.projectId);
12
+ const apiUrl = resolveApiUrl(opts.apiUrl, meta.projectId);
13
+ const client = new ApiClient(apiUrl, token);
14
+ const who = await client.request("GET", "/api/cli/whoami");
15
+ if (String(meta.projectId) !== String(who.projectId)) {
16
+ throw new Error([
17
+ `Linked project (${meta.projectName ?? meta.projectId}) does not match this token (${who.projectName}, ${who.projectId}).`,
18
+ "Run: npx getmyenv link",
19
+ ].join("\n"));
12
20
  }
13
- const token = await ensureSessionToken();
14
- const client = new ApiClient(opts.apiUrl, token);
15
21
  const data = await client.request("GET", `/api/cli/projects/${meta.projectId}/backup`);
16
22
  const envelope = createBackupEnvelope({
17
23
  projectName: data.projectName,
@@ -30,6 +36,9 @@ export async function backupCommand(opts) {
30
36
  path.join(process.cwd(), `${data.projectName.replace(/\s+/g, "-").toLowerCase()}.getmyenv`);
31
37
  fs.writeFileSync(out, serializeBackup(envelope), { mode: 0o600 });
32
38
  console.log(`${pc.green("✓")} Wrote encrypted backup: ${out}`);
39
+ if (meta.defaultEnv) {
40
+ console.log(pc.dim(`Linked defaultEnv: ${meta.defaultEnv}`));
41
+ }
33
42
  console.log(pc.dim("Portable. No plaintext. Usable offline with your vault password.\n"));
34
43
  }
35
44
  //# sourceMappingURL=backup.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"backup.js","sourceRoot":"","sources":["../../src/commands/backup.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,EACL,oBAAoB,EACpB,YAAY,EACZ,eAAe,EACf,eAAe,GAChB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAI9D,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAAgB;IAClD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC,CAAC;IAC5C,MAAM,IAAI,GAAG,eAAe,EAAE,CAAC;IAC/B,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,CAAC;QACrB,MAAM,IAAI,KAAK,CACb,2FAA2F,CAC5F,CAAC;IACJ,CAAC;IACD,MAAM,KAAK,GAAG,MAAM,kBAAkB,EAAE,CAAC;IAEzC,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IACjD,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,OAAO,CAU9B,KAAK,EAAE,qBAAqB,IAAI,CAAC,SAAS,SAAS,CAAC,CAAC;IAExD,MAAM,QAAQ,GAAG,oBAAoB,CAAC;QACpC,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,iBAAiB,EAAE,eAAe,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;QAC1E,OAAO,EAAE,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAChC,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,WAAW,EAAE,CAAC,CAAC,WAAW;YAC1B,MAAM,EAAE,CAAC,CAAC,MAAM;YAChB,SAAS,EAAE,CAAC,CAAC,SAAS;YACtB,OAAO,EACL,CAAC,CAAC,UAAU,IAAI,IAAI,IAAI,CAAC,CAAC,MAAM,KAAK,aAAa;gBAChD,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,UAAU,CAAC;gBAC5B,CAAC,CAAC,IAAI;SACX,CAAC,CAAC;KACJ,CAAC,CAAC;IAEH,MAAM,GAAG,GACP,IAAI,CAAC,MAAM;QACX,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,GAAG,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;IAC9F,EAAE,CAAC,aAAa,CAAC,GAAG,EAAE,eAAe,CAAC,QAAQ,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAClE,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,4BAA4B,GAAG,EAAE,CAAC,CAAC;IAC/D,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,oEAAoE,CAAC,CAAC,CAAC;AAC5F,CAAC"}
1
+ {"version":3,"file":"backup.js","sourceRoot":"","sources":["../../src/commands/backup.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ type LinkOpts = {
2
+ apiUrl?: string;
3
+ name?: string;
4
+ expect?: string;
5
+ force?: boolean;
6
+ clear?: boolean;
7
+ env?: string;
8
+ /** When true, do not offer push after link (caller is already pushing). */
9
+ skipPushOffer?: boolean;
10
+ };
11
+ /** Clear the linked project from this folder (link --clear). */
12
+ export declare function clearLink(): Promise<void>;
13
+ /** Link this folder to the project bound to the saved CLI token. */
14
+ export declare function linkCommand(_projectIdArg: string | undefined, opts: LinkOpts): Promise<void>;
15
+ export {};
16
+ //# sourceMappingURL=link.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"link.d.ts","sourceRoot":"","sources":["../../src/commands/link.ts"],"names":[],"mappings":"AAmBA,KAAK,QAAQ,GAAG;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,2EAA2E;IAC3E,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB,CAAC;AAEF,gEAAgE;AAChE,wBAAsB,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAqB/C;AAED,oEAAoE;AACpE,wBAAsB,WAAW,CAC/B,aAAa,EAAE,MAAM,GAAG,SAAS,EACjC,IAAI,EAAE,QAAQ,GACb,OAAO,CAAC,IAAI,CAAC,CA6If"}
@@ -0,0 +1,116 @@
1
+ import pc from "picocolors";
2
+ import { ensureGitignoreHasEnv, listPushEnvFiles, promptConfirm, readProjectMeta, writeProjectMeta, } from "../lib/fs.js";
3
+ import { ApiClient, ensureSessionToken, getSessionToken, resolveApiUrl, } from "../lib/api.js";
4
+ import { normalizeEnvName } from "../lib/env-name.js";
5
+ import { tokenCommand } from "./token.js";
6
+ import { pushCommand } from "./push.js";
7
+ /** Clear the linked project from this folder (link --clear). */
8
+ export async function clearLink() {
9
+ console.log(pc.bold("\ngetmyenv link --clear\n"));
10
+ const meta = readProjectMeta();
11
+ if (!meta?.projectId) {
12
+ console.log(pc.dim("No project is linked to this folder.\n"));
13
+ return;
14
+ }
15
+ if (process.stdin.isTTY) {
16
+ const ok = await promptConfirm(`Unlink ${meta.projectName ?? meta.projectId}?`, { defaultYes: false });
17
+ if (!ok) {
18
+ console.log(pc.dim("Kept link.\n"));
19
+ return;
20
+ }
21
+ }
22
+ const { projectId: _id, projectName: _name, defaultEnv: _env, ...rest } = meta;
23
+ writeProjectMeta(rest);
24
+ console.log(`${pc.green("✓")} Unlinked. Local .getmyenv metadata kept.\n`);
25
+ }
26
+ /** Link this folder to the project bound to the saved CLI token. */
27
+ export async function linkCommand(_projectIdArg, opts) {
28
+ if (opts.clear) {
29
+ await clearLink();
30
+ return;
31
+ }
32
+ console.log(pc.bold("\ngetmyenv link\n"));
33
+ if (!getSessionToken()) {
34
+ if (!process.stdin.isTTY) {
35
+ throw new Error("No CLI token. Run: npx getmyenv token");
36
+ }
37
+ await tokenCommand({
38
+ apiUrl: opts.apiUrl,
39
+ skipLinkOffer: true,
40
+ });
41
+ }
42
+ const token = await ensureSessionToken();
43
+ const apiUrl = resolveApiUrl(opts.apiUrl);
44
+ const client = new ApiClient(apiUrl, token);
45
+ const who = await client.request("GET", "/api/cli/whoami");
46
+ const expectName = opts.expect?.trim() || opts.name?.trim();
47
+ if (expectName) {
48
+ const needle = expectName.toLowerCase();
49
+ const matches = who.projectName.toLowerCase() === needle ||
50
+ who.projectName.toLowerCase().includes(needle) ||
51
+ String(who.projectId) === expectName;
52
+ if (!matches) {
53
+ throw new Error(`Token project "${who.projectName}" (${who.projectId}) does not match --expect ${expectName}`);
54
+ }
55
+ }
56
+ let defaultEnv = who.cliScope === "production" ? "production" : "development";
57
+ if (opts.env?.trim()) {
58
+ const requested = normalizeEnvName(opts.env);
59
+ if (requested !== who.cliScope) {
60
+ throw new Error(`Token scope is ${who.cliScope}, but --env ${requested} was passed. Use a matching token or omit --env.`);
61
+ }
62
+ defaultEnv = requested;
63
+ }
64
+ const meta = readProjectMeta() ?? {};
65
+ if (meta.projectId && String(meta.projectId) !== String(who.projectId)) {
66
+ console.log(pc.yellow(`This folder is linked to ${meta.projectName ?? meta.projectId}.`));
67
+ console.log(pc.dim(`Token is for ${who.projectName} (${who.projectId}, ${who.cliScope}).\n`));
68
+ if (!opts.force) {
69
+ if (!process.stdin.isTTY) {
70
+ throw new Error("Already linked to a different project. Re-run with --force, or: npx getmyenv link --clear");
71
+ }
72
+ const ok = await promptConfirm("Replace with token project?", {
73
+ defaultYes: false,
74
+ });
75
+ if (!ok) {
76
+ console.log(pc.dim("Kept existing link.\n"));
77
+ return;
78
+ }
79
+ }
80
+ }
81
+ writeProjectMeta({
82
+ ...meta,
83
+ projectId: who.projectId,
84
+ projectName: who.projectName,
85
+ apiUrl,
86
+ defaultEnv,
87
+ });
88
+ ensureGitignoreHasEnv();
89
+ console.log(`${pc.green("✓")} Linked to ${pc.bold(who.projectName)} (${who.projectId})`);
90
+ console.log(pc.dim(`Token scope: ${who.cliScope}`));
91
+ console.log(pc.dim(`defaultEnv: ${defaultEnv}`));
92
+ if (who.cliScope === "production") {
93
+ console.log(pc.dim("Next: npx getmyenv run -- <cmd> # start app with secrets as env vars (Production is read-only)\n"));
94
+ return;
95
+ }
96
+ if (opts.skipPushOffer || !process.stdin.isTTY) {
97
+ console.log(pc.dim("Next: npx getmyenv run -- <cmd> # start app with secrets as env vars\n"));
98
+ return;
99
+ }
100
+ const pushable = listPushEnvFiles();
101
+ if (pushable.length === 0) {
102
+ console.log(pc.dim("Next: npx getmyenv run -- <cmd> # start app with secrets as env vars\n"));
103
+ return;
104
+ }
105
+ const doPush = await promptConfirm("Push and migrate a local .env file now?", { defaultYes: true });
106
+ if (!doPush) {
107
+ console.log(pc.dim("When you are ready: npx getmyenv run -- <cmd> # start app with secrets as env vars\n"));
108
+ return;
109
+ }
110
+ await pushCommand({
111
+ env: who.cliScope,
112
+ apiUrl,
113
+ envWasDefault: true,
114
+ });
115
+ }
116
+ //# sourceMappingURL=link.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"link.js","sourceRoot":"","sources":["../../src/commands/link.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,EACL,qBAAqB,EACrB,gBAAgB,EAChB,aAAa,EACb,eAAe,EACf,gBAAgB,GACjB,MAAM,cAAc,CAAC;AACtB,OAAO,EACL,SAAS,EACT,kBAAkB,EAClB,eAAe,EACf,aAAa,GAEd,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAaxC,gEAAgE;AAChE,MAAM,CAAC,KAAK,UAAU,SAAS;IAC7B,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC,CAAC;IAClD,MAAM,IAAI,GAAG,eAAe,EAAE,CAAC;IAC/B,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,CAAC;QACrB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,wCAAwC,CAAC,CAAC,CAAC;QAC9D,OAAO;IACT,CAAC;IACD,IAAI,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QACxB,MAAM,EAAE,GAAG,MAAM,aAAa,CAC5B,UAAU,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,SAAS,GAAG,EAC/C,EAAE,UAAU,EAAE,KAAK,EAAE,CACtB,CAAC;QACF,IAAI,CAAC,EAAE,EAAE,CAAC;YACR,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC,CAAC;YACpC,OAAO;QACT,CAAC;IACH,CAAC;IACD,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,WAAW,EAAE,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,GACrE,IAAI,CAAC;IACP,gBAAgB,CAAC,IAAI,CAAC,CAAC;IACvB,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,6CAA6C,CAAC,CAAC;AAC7E,CAAC;AAED,oEAAoE;AACpE,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,aAAiC,EACjC,IAAc;IAEd,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QACf,MAAM,SAAS,EAAE,CAAC;QAClB,OAAO;IACT,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,CAAC;IAE1C,IAAI,CAAC,eAAe,EAAE,EAAE,CAAC;QACvB,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;YACzB,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;QAC3D,CAAC;QACD,MAAM,YAAY,CAAC;YACjB,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,aAAa,EAAE,IAAI;SACpB,CAAC,CAAC;IACL,CAAC;IAED,MAAM,KAAK,GAAG,MAAM,kBAAkB,EAAE,CAAC;IACzC,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC1C,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAC5C,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,OAAO,CAAiB,KAAK,EAAE,iBAAiB,CAAC,CAAC;IAE3E,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,IAAI,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC;IAC5D,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,MAAM,GAAG,UAAU,CAAC,WAAW,EAAE,CAAC;QACxC,MAAM,OAAO,GACX,GAAG,CAAC,WAAW,CAAC,WAAW,EAAE,KAAK,MAAM;YACxC,GAAG,CAAC,WAAW,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC;YAC9C,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,UAAU,CAAC;QACvC,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CACb,kBAAkB,GAAG,CAAC,WAAW,MAAM,GAAG,CAAC,SAAS,6BAA6B,UAAU,EAAE,CAC9F,CAAC;QACJ,CAAC;IACH,CAAC;IAED,IAAI,UAAU,GACZ,GAAG,CAAC,QAAQ,KAAK,YAAY,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,aAAa,CAAC;IAE/D,IAAI,IAAI,CAAC,GAAG,EAAE,IAAI,EAAE,EAAE,CAAC;QACrB,MAAM,SAAS,GAAG,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAE3B,CAAC;QACjB,IAAI,SAAS,KAAK,GAAG,CAAC,QAAQ,EAAE,CAAC;YAC/B,MAAM,IAAI,KAAK,CACb,kBAAkB,GAAG,CAAC,QAAQ,eAAe,SAAS,kDAAkD,CACzG,CAAC;QACJ,CAAC;QACD,UAAU,GAAG,SAAS,CAAC;IACzB,CAAC;IAED,MAAM,IAAI,GAAG,eAAe,EAAE,IAAI,EAAE,CAAC;IACrC,IAAI,IAAI,CAAC,SAAS,IAAI,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;QACvE,OAAO,CAAC,GAAG,CACT,EAAE,CAAC,MAAM,CACP,4BAA4B,IAAI,CAAC,WAAW,IAAI,IAAI,CAAC,SAAS,GAAG,CAClE,CACF,CAAC;QACF,OAAO,CAAC,GAAG,CACT,EAAE,CAAC,GAAG,CACJ,gBAAgB,GAAG,CAAC,WAAW,KAAK,GAAG,CAAC,SAAS,KAAK,GAAG,CAAC,QAAQ,MAAM,CACzE,CACF,CAAC;QACF,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;YAChB,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;gBACzB,MAAM,IAAI,KAAK,CACb,2FAA2F,CAC5F,CAAC;YACJ,CAAC;YACD,MAAM,EAAE,GAAG,MAAM,aAAa,CAAC,6BAA6B,EAAE;gBAC5D,UAAU,EAAE,KAAK;aAClB,CAAC,CAAC;YACH,IAAI,CAAC,EAAE,EAAE,CAAC;gBACR,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC,CAAC;gBAC7C,OAAO;YACT,CAAC;QACH,CAAC;IACH,CAAC;IAED,gBAAgB,CAAC;QACf,GAAG,IAAI;QACP,SAAS,EAAE,GAAG,CAAC,SAAS;QACxB,WAAW,EAAE,GAAG,CAAC,WAAW;QAC5B,MAAM;QACN,UAAU;KACX,CAAC,CAAC;IACH,qBAAqB,EAAE,CAAC;IAExB,OAAO,CAAC,GAAG,CACT,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,cAAc,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,KAAK,GAAG,CAAC,SAAS,GAAG,CAC5E,CAAC;IACF,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,gBAAgB,GAAG,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;IACpD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,eAAe,UAAU,EAAE,CAAC,CAAC,CAAC;IAEjD,IAAI,GAAG,CAAC,QAAQ,KAAK,YAAY,EAAE,CAAC;QAClC,OAAO,CAAC,GAAG,CACT,EAAE,CAAC,GAAG,CACJ,mGAAmG,CACpG,CACF,CAAC;QACF,OAAO;IACT,CAAC;IAED,IAAI,IAAI,CAAC,aAAa,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;QAC/C,OAAO,CAAC,GAAG,CACT,EAAE,CAAC,GAAG,CACJ,yEAAyE,CAC1E,CACF,CAAC;QACF,OAAO;IACT,CAAC;IAED,MAAM,QAAQ,GAAG,gBAAgB,EAAE,CAAC;IACpC,IAAI,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC1B,OAAO,CAAC,GAAG,CACT,EAAE,CAAC,GAAG,CACJ,yEAAyE,CAC1E,CACF,CAAC;QACF,OAAO;IACT,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,aAAa,CAChC,yCAAyC,EACzC,EAAE,UAAU,EAAE,IAAI,EAAE,CACrB,CAAC;IACF,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,CAAC,GAAG,CACT,EAAE,CAAC,GAAG,CACJ,uFAAuF,CACxF,CACF,CAAC;QACF,OAAO;IACT,CAAC;IAED,MAAM,WAAW,CAAC;QAChB,GAAG,EAAE,GAAG,CAAC,QAAQ;QACjB,MAAM;QACN,aAAa,EAAE,IAAI;KACpB,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,15 @@
1
+ type PullOpts = {
2
+ env: string;
3
+ output?: string;
4
+ to?: string;
5
+ stdout?: boolean;
6
+ yes?: boolean;
7
+ merge?: boolean;
8
+ dryRun?: boolean;
9
+ apiUrl: string;
10
+ vaultPasswordStdin?: boolean;
11
+ envWasDefault?: boolean;
12
+ };
13
+ export declare function pullCommand(opts: PullOpts): Promise<void>;
14
+ export {};
15
+ //# sourceMappingURL=pull.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pull.d.ts","sourceRoot":"","sources":["../../src/commands/pull.ts"],"names":[],"mappings":"AAmBA,KAAK,QAAQ,GAAG;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB,CAAC;AAEF,wBAAsB,WAAW,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CA4K/D"}
@@ -0,0 +1,157 @@
1
+ import fs from "node:fs";
2
+ import pc from "picocolors";
3
+ import { decryptSecret, parsePayload, } from "@getmyenv/crypto";
4
+ import { EXPORT_WARNING } from "@getmyenv/shared";
5
+ import { parseEnvFile, promptHidden, readProjectMeta, } from "../lib/fs.js";
6
+ import { ApiClient } from "../lib/api.js";
7
+ import { unwrapPek } from "../lib/pek.js";
8
+ import { confirmDiff } from "../lib/confirm.js";
9
+ import { normalizeEnvName } from "../lib/env-name.js";
10
+ import { ensureTokenAndLink } from "../lib/bootstrap.js";
11
+ export async function pullCommand(opts) {
12
+ console.log(pc.bold("\ngetmyenv pull\n"));
13
+ console.log(pc.yellow(EXPORT_WARNING));
14
+ console.log("");
15
+ const { who, apiUrl, token, projectId } = await ensureTokenAndLink({
16
+ apiUrl: opts.apiUrl,
17
+ action: "pull",
18
+ });
19
+ if (who.cliScope === "production") {
20
+ throw new Error([
21
+ "Production CLI is read-only.",
22
+ "Use npx getmyenv run to pass secrets as env vars without writing them to disk.",
23
+ "Set or change Production values in the dashboard.",
24
+ ].join("\n"));
25
+ }
26
+ const meta = readProjectMeta();
27
+ let environment = normalizeEnvName(opts.env);
28
+ if (opts.envWasDefault && meta?.defaultEnv) {
29
+ environment = meta.defaultEnv;
30
+ }
31
+ if (environment !== who.cliScope) {
32
+ if (opts.envWasDefault) {
33
+ environment = who.cliScope;
34
+ }
35
+ else {
36
+ throw new Error([
37
+ `Token scope is ${who.cliScope}, but you passed -e ${environment}.`,
38
+ "Use a matching token or omit -e.",
39
+ ].join("\n"));
40
+ }
41
+ }
42
+ const password = await promptHidden("Vault password: ", {
43
+ allowStdin: opts.vaultPasswordStdin,
44
+ });
45
+ const client = new ApiClient(apiUrl, token);
46
+ const data = await client.request("GET", `/api/cli/projects/${projectId}/export?environment=${encodeURIComponent(environment)}`);
47
+ const pek = await unwrapPek({
48
+ password,
49
+ scope: who.cliScope,
50
+ wrapped: data.wrappedProjectKey,
51
+ });
52
+ const remote = {};
53
+ const lines = [
54
+ "# Pulled by getmyenv - PLAINTEXT SECRETS",
55
+ `# Environment: ${environment}`,
56
+ "# Do not commit this file.",
57
+ "",
58
+ ];
59
+ for (const secret of data.secrets) {
60
+ if (secret.status === "revoked") {
61
+ lines.push("# revoked - getmyenv is not providing this");
62
+ continue;
63
+ }
64
+ if (secret.status === "placeholder" ||
65
+ secret.ciphertext == null ||
66
+ secret.ciphertext === "") {
67
+ lines.push(`# placeholder - no value yet`);
68
+ lines.push(`${secret.name}=`);
69
+ continue;
70
+ }
71
+ const value = decryptSecret(pek, parsePayload(secret.ciphertext));
72
+ remote[secret.name] = value;
73
+ lines.push(`${secret.name}=${value}`);
74
+ }
75
+ if (opts.stdout) {
76
+ process.stdout.write(lines.join("\n") + "\n");
77
+ return;
78
+ }
79
+ const outPath = opts.to || opts.output || ".env";
80
+ const exists = fs.existsSync(outPath);
81
+ const local = exists ? parseEnvFile(outPath) : {};
82
+ if (opts.dryRun) {
83
+ console.log(pc.dim(`Dry run - would write ${outPath}\n`));
84
+ for (const name of Object.keys(remote)) {
85
+ if (!(name in local))
86
+ console.log(` + ${name}`);
87
+ else if (local[name] !== remote[name])
88
+ console.log(` ~ ${name}`);
89
+ else
90
+ console.log(` = ${name}`);
91
+ }
92
+ for (const name of Object.keys(local)) {
93
+ if (!(name in remote))
94
+ console.log(` - ${name} (local only)`);
95
+ }
96
+ console.log("");
97
+ return;
98
+ }
99
+ if (opts.merge && exists) {
100
+ const merged = { ...local };
101
+ for (const [name, value] of Object.entries(remote)) {
102
+ if (!(name in merged) || merged[name] === "") {
103
+ merged[name] = value;
104
+ }
105
+ }
106
+ const mergedLines = [
107
+ "# Pulled by getmyenv - PLAINTEXT SECRETS (merged)",
108
+ `# Environment: ${environment}`,
109
+ "# Do not commit this file.",
110
+ "",
111
+ ...Object.entries(merged).map(([k, v]) => `${k}=${v}`),
112
+ ];
113
+ fs.writeFileSync(outPath, mergedLines.join("\n") + "\n", { mode: 0o600 });
114
+ console.log(`${pc.green("✓")} Merged into ${outPath}`);
115
+ console.log(pc.dim("Your secrets are yours. Protect this file.\n"));
116
+ return;
117
+ }
118
+ const conflicts = [];
119
+ for (const [name, value] of Object.entries(remote)) {
120
+ if (name in local && local[name] !== value) {
121
+ conflicts.push({ name, detail: "local differs from remote" });
122
+ }
123
+ }
124
+ if (conflicts.length > 0) {
125
+ const ok = await confirmDiff({
126
+ conflicts,
127
+ action: "Overwrite conflicting local values",
128
+ yes: opts.yes,
129
+ });
130
+ if (!ok) {
131
+ console.log(pc.dim("Pull cancelled.\n"));
132
+ return;
133
+ }
134
+ }
135
+ if (exists && conflicts.length === 0 && Object.keys(local).length > 0) {
136
+ const remoteKeys = new Set(Object.keys(remote));
137
+ const localOnly = Object.keys(local).filter((k) => !remoteKeys.has(k));
138
+ if (localOnly.length > 0 && !opts.yes) {
139
+ const ok = await confirmDiff({
140
+ conflicts: localOnly.map((name) => ({
141
+ name,
142
+ detail: "present locally, absent remotely (will be dropped)",
143
+ })),
144
+ action: "Replace local file",
145
+ yes: opts.yes,
146
+ });
147
+ if (!ok) {
148
+ console.log(pc.dim("Pull cancelled.\n"));
149
+ return;
150
+ }
151
+ }
152
+ }
153
+ fs.writeFileSync(outPath, lines.join("\n") + "\n", { mode: 0o600 });
154
+ console.log(`${pc.green("✓")} Wrote ${outPath}`);
155
+ console.log(pc.dim("Your secrets are yours. Protect this file.\n"));
156
+ }
157
+ //# sourceMappingURL=pull.js.map