getmyenv 0.5.3 → 0.6.0

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 (161) hide show
  1. package/README.md +57 -13
  2. package/dist/bin.js +1 -24
  3. package/dist/bin.js.map +1 -1
  4. package/dist/cli.d.ts +10 -0
  5. package/dist/cli.d.ts.map +1 -1
  6. package/dist/cli.js +179 -106
  7. package/dist/cli.js.map +1 -1
  8. package/dist/commands/backup.d.ts +2 -1
  9. package/dist/commands/backup.d.ts.map +1 -1
  10. package/dist/commands/backup.js +15 -19
  11. package/dist/commands/backup.js.map +1 -1
  12. package/dist/commands/claim.d.ts +2 -1
  13. package/dist/commands/claim.d.ts.map +1 -1
  14. package/dist/commands/claim.js +114 -80
  15. package/dist/commands/claim.js.map +1 -1
  16. package/dist/commands/context.d.ts +11 -0
  17. package/dist/commands/context.d.ts.map +1 -0
  18. package/dist/commands/context.js +53 -0
  19. package/dist/commands/context.js.map +1 -0
  20. package/dist/commands/export.d.ts +11 -0
  21. package/dist/commands/export.d.ts.map +1 -0
  22. package/dist/commands/export.js +67 -0
  23. package/dist/commands/export.js.map +1 -0
  24. package/dist/commands/guest.d.ts +9 -3
  25. package/dist/commands/guest.d.ts.map +1 -1
  26. package/dist/commands/guest.js +32 -28
  27. package/dist/commands/guest.js.map +1 -1
  28. package/dist/commands/import.d.ts +26 -0
  29. package/dist/commands/import.d.ts.map +1 -0
  30. package/dist/commands/import.js +168 -0
  31. package/dist/commands/import.js.map +1 -0
  32. package/dist/commands/lock.d.ts +5 -0
  33. package/dist/commands/lock.d.ts.map +1 -0
  34. package/dist/commands/lock.js +18 -0
  35. package/dist/commands/lock.js.map +1 -0
  36. package/dist/commands/ls.d.ts +6 -0
  37. package/dist/commands/ls.d.ts.map +1 -0
  38. package/dist/commands/ls.js +37 -0
  39. package/dist/commands/ls.js.map +1 -0
  40. package/dist/commands/restore.d.ts +7 -2
  41. package/dist/commands/restore.d.ts.map +1 -1
  42. package/dist/commands/restore.js +57 -49
  43. package/dist/commands/restore.js.map +1 -1
  44. package/dist/commands/run.d.ts +7 -5
  45. package/dist/commands/run.d.ts.map +1 -1
  46. package/dist/commands/run.js +98 -187
  47. package/dist/commands/run.js.map +1 -1
  48. package/dist/commands/set.d.ts +16 -0
  49. package/dist/commands/set.d.ts.map +1 -0
  50. package/dist/commands/set.js +111 -0
  51. package/dist/commands/set.js.map +1 -0
  52. package/dist/commands/start.d.ts +16 -0
  53. package/dist/commands/start.d.ts.map +1 -0
  54. package/dist/commands/start.js +118 -0
  55. package/dist/commands/start.js.map +1 -0
  56. package/dist/commands/status.d.ts +5 -0
  57. package/dist/commands/status.d.ts.map +1 -0
  58. package/dist/commands/status.js +40 -0
  59. package/dist/commands/status.js.map +1 -0
  60. package/dist/commands/unlink.d.ts +9 -0
  61. package/dist/commands/unlink.d.ts.map +1 -0
  62. package/dist/commands/unlink.js +70 -0
  63. package/dist/commands/unlink.js.map +1 -0
  64. package/dist/lib/api-url.d.ts +12 -0
  65. package/dist/lib/api-url.d.ts.map +1 -1
  66. package/dist/lib/api-url.js +32 -0
  67. package/dist/lib/api-url.js.map +1 -1
  68. package/dist/lib/api.d.ts +35 -23
  69. package/dist/lib/api.d.ts.map +1 -1
  70. package/dist/lib/api.js +23 -59
  71. package/dist/lib/api.js.map +1 -1
  72. package/dist/lib/authorize.d.ts +13 -6
  73. package/dist/lib/authorize.d.ts.map +1 -1
  74. package/dist/lib/authorize.js +68 -61
  75. package/dist/lib/authorize.js.map +1 -1
  76. package/dist/lib/bootstrap.d.ts +18 -15
  77. package/dist/lib/bootstrap.d.ts.map +1 -1
  78. package/dist/lib/bootstrap.js +59 -69
  79. package/dist/lib/bootstrap.js.map +1 -1
  80. package/dist/lib/confirm.js +4 -4
  81. package/dist/lib/confirm.js.map +1 -1
  82. package/dist/lib/context.d.ts +12 -0
  83. package/dist/lib/context.d.ts.map +1 -0
  84. package/dist/lib/context.js +43 -0
  85. package/dist/lib/context.js.map +1 -0
  86. package/dist/lib/credentials.d.ts +8 -13
  87. package/dist/lib/credentials.d.ts.map +1 -1
  88. package/dist/lib/credentials.js +2 -9
  89. package/dist/lib/credentials.js.map +1 -1
  90. package/dist/lib/fs.d.ts +26 -40
  91. package/dist/lib/fs.d.ts.map +1 -1
  92. package/dist/lib/fs.js +112 -326
  93. package/dist/lib/fs.js.map +1 -1
  94. package/dist/lib/guest-key.d.ts +2 -5
  95. package/dist/lib/guest-key.d.ts.map +1 -1
  96. package/dist/lib/guest-key.js +9 -2
  97. package/dist/lib/guest-key.js.map +1 -1
  98. package/dist/lib/identity.d.ts +9 -11
  99. package/dist/lib/identity.d.ts.map +1 -1
  100. package/dist/lib/identity.js +34 -24
  101. package/dist/lib/identity.js.map +1 -1
  102. package/dist/lib/keychain.d.ts +21 -0
  103. package/dist/lib/keychain.d.ts.map +1 -0
  104. package/dist/lib/keychain.js +124 -0
  105. package/dist/lib/keychain.js.map +1 -0
  106. package/dist/lib/pek.d.ts +15 -24
  107. package/dist/lib/pek.d.ts.map +1 -1
  108. package/dist/lib/pek.js +30 -54
  109. package/dist/lib/pek.js.map +1 -1
  110. package/dist/lib/run-env.d.ts +50 -0
  111. package/dist/lib/run-env.d.ts.map +1 -0
  112. package/dist/lib/run-env.js +114 -0
  113. package/dist/lib/run-env.js.map +1 -0
  114. package/dist/lib/unlock.d.ts +24 -0
  115. package/dist/lib/unlock.d.ts.map +1 -0
  116. package/dist/lib/unlock.js +87 -0
  117. package/dist/lib/unlock.js.map +1 -0
  118. package/dist/lib/update-check.d.ts +4 -2
  119. package/dist/lib/update-check.d.ts.map +1 -1
  120. package/dist/lib/update-check.js +54 -68
  121. package/dist/lib/update-check.js.map +1 -1
  122. package/dist/lib/upload.d.ts +21 -0
  123. package/dist/lib/upload.d.ts.map +1 -0
  124. package/dist/lib/upload.js +53 -0
  125. package/dist/lib/upload.js.map +1 -0
  126. package/package.json +5 -3
  127. package/dist/commands/delete.d.ts +0 -6
  128. package/dist/commands/delete.d.ts.map +0 -1
  129. package/dist/commands/delete.js +0 -55
  130. package/dist/commands/delete.js.map +0 -1
  131. package/dist/commands/link.d.ts +0 -16
  132. package/dist/commands/link.d.ts.map +0 -1
  133. package/dist/commands/link.js +0 -142
  134. package/dist/commands/link.js.map +0 -1
  135. package/dist/commands/pull.d.ts +0 -15
  136. package/dist/commands/pull.d.ts.map +0 -1
  137. package/dist/commands/pull.js +0 -155
  138. package/dist/commands/pull.js.map +0 -1
  139. package/dist/commands/push.d.ts +0 -15
  140. package/dist/commands/push.d.ts.map +0 -1
  141. package/dist/commands/push.js +0 -261
  142. package/dist/commands/push.js.map +0 -1
  143. package/dist/commands/remove.d.ts +0 -11
  144. package/dist/commands/remove.d.ts.map +0 -1
  145. package/dist/commands/remove.js +0 -39
  146. package/dist/commands/remove.js.map +0 -1
  147. package/dist/commands/token.d.ts +0 -14
  148. package/dist/commands/token.d.ts.map +0 -1
  149. package/dist/commands/token.js +0 -132
  150. package/dist/commands/token.js.map +0 -1
  151. package/dist/commands/whoami.d.ts +0 -6
  152. package/dist/commands/whoami.d.ts.map +0 -1
  153. package/dist/commands/whoami.js +0 -46
  154. package/dist/commands/whoami.js.map +0 -1
  155. package/dist/lib/env-name.d.ts +0 -3
  156. package/dist/lib/env-name.d.ts.map +0 -1
  157. package/dist/lib/env-name.js +0 -5
  158. package/dist/lib/env-name.js.map +0 -1
  159. package/dist/lib/guest-key.test.d.ts +0 -2
  160. package/dist/lib/guest-key.test.d.ts.map +0 -1
  161. package/dist/lib/guest-key.test.js.map +0 -1
@@ -0,0 +1,168 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import pc from "picocolors";
4
+ import { contextSlugFromEnvFile, ensureGitignoreHasEnv, parseEnvFile, promptConfirm, rootEnvFiles, } from "../lib/fs.js";
5
+ import { ensureTokenAndLink } from "../lib/bootstrap.js";
6
+ import { defaultContextSlug, findContext, resolveContext } from "../lib/context.js";
7
+ import { confirmDiff } from "../lib/confirm.js";
8
+ import { uploadValues } from "../lib/upload.js";
9
+ import { runLine } from "./start.js";
10
+ /** `.env` before `.env.local`, so local files win on merge. */
11
+ function byLocalLast(a, b) {
12
+ const la = a.endsWith(".local") ? 1 : 0;
13
+ const lb = b.endsWith(".local") ? 1 : 0;
14
+ return la - lb || a.localeCompare(b);
15
+ }
16
+ /**
17
+ * Plan which file goes to which context.
18
+ * `.env.<slug>` maps to that context. `.env` and `.env.local` go to the
19
+ * default context, or to -c when given.
20
+ */
21
+ export function planImport(files, opts) {
22
+ const map = new Map();
23
+ for (const file of [...files].sort(byLocalLast)) {
24
+ const fromName = contextSlugFromEnvFile(file);
25
+ const slug = opts.explicitFile
26
+ ? (opts.context ?? fromName ?? opts.defaultSlug)
27
+ : (fromName ?? opts.context ?? opts.defaultSlug);
28
+ if (!opts.explicitFile && opts.context && slug !== opts.context)
29
+ continue;
30
+ map.set(slug, [...(map.get(slug) ?? []), file]);
31
+ }
32
+ return [...map.entries()].map(([slug, list]) => ({ slug, files: list }));
33
+ }
34
+ function titleFromSlug(slug) {
35
+ return slug
36
+ .split("-")
37
+ .map((w) => (w ? w[0].toUpperCase() + w.slice(1) : w))
38
+ .join(" ");
39
+ }
40
+ async function ensureTargetContext(linked, slug, opts) {
41
+ const found = findContext(linked.who.contexts, slug);
42
+ if (found)
43
+ return found;
44
+ if (linked.who.isGuest || linked.who.token.kind !== "folder") {
45
+ const why = linked.who.isGuest ? "Guest projects have Development only." : "Server tokens are read-only.";
46
+ console.error(pc.yellow(`Skipped ${slug}: no such context. ${why}`));
47
+ return null;
48
+ }
49
+ if (opts.dryRun) {
50
+ console.error(pc.dim(`Would create open context ${slug}.`));
51
+ return { id: 0, slug, name: titleFromSlug(slug), protection: "open" };
52
+ }
53
+ const create = opts.yes || (process.stdin.isTTY && (await promptConfirm(`Create open context ${slug}?`, { defaultYes: true })));
54
+ if (!create) {
55
+ const hint = process.stdin.isTTY ? "" : " Or pass --yes.";
56
+ console.error(pc.dim(`Skipped ${slug}. Create it: npx getmyenv context create "${titleFromSlug(slug)}".${hint}`));
57
+ return null;
58
+ }
59
+ const created = await linked.client.request("POST", "/api/cli/contexts", {
60
+ name: titleFromSlug(slug),
61
+ });
62
+ linked.who.contexts.push(created);
63
+ console.error(`${pc.green("✓")} Created context ${created.slug}`);
64
+ return created;
65
+ }
66
+ /** `import [file]`: encrypt .env values locally and upload them to contexts. */
67
+ export async function importCommand(file, opts) {
68
+ const linked = await ensureTokenAndLink({ apiUrl: opts.apiUrl });
69
+ const { who, meta } = linked;
70
+ const explicitContext = opts.context ? resolveContext(who, meta, opts.context).slug : undefined;
71
+ let files;
72
+ if (file) {
73
+ const resolved = path.resolve(process.cwd(), file);
74
+ if (!fs.existsSync(resolved))
75
+ throw new Error(`File not found: ${file}`);
76
+ files = [resolved];
77
+ }
78
+ else {
79
+ files = rootEnvFiles();
80
+ if (files.length === 0) {
81
+ throw new Error("No .env files in this folder. Pass one: npx getmyenv import path/to/.env");
82
+ }
83
+ }
84
+ const targets = planImport(files, {
85
+ explicitFile: Boolean(file),
86
+ context: explicitContext,
87
+ defaultSlug: defaultContextSlug(who, meta),
88
+ });
89
+ if (targets.length === 0) {
90
+ throw new Error(`No .env files map to ${explicitContext}. Pass a file: npx getmyenv import .env -c ${explicitContext}`);
91
+ }
92
+ if (opts.dryRun)
93
+ console.error(pc.dim("Dry run. Nothing is uploaded.\n"));
94
+ let imported = 0;
95
+ let changed = 0;
96
+ let skipped = 0;
97
+ for (const target of targets) {
98
+ const label = target.files.map((f) => path.relative(process.cwd(), f) || f).join(" + ");
99
+ const ctx = await ensureTargetContext(linked, target.slug, opts);
100
+ if (!ctx) {
101
+ skipped++;
102
+ continue;
103
+ }
104
+ if (ctx.protection === "locked") {
105
+ console.error(pc.yellow(`Skipped ${label}: ${ctx.slug} is locked. Set values in the dashboard.`));
106
+ skipped++;
107
+ continue;
108
+ }
109
+ const pairs = {};
110
+ for (const f of target.files)
111
+ Object.assign(pairs, parseEnvFile(f));
112
+ const names = Object.keys(pairs);
113
+ if (names.length === 0) {
114
+ console.error(pc.dim(`Skipped ${label}: no variables.`));
115
+ continue;
116
+ }
117
+ const statusOf = (name) => who.keys.find((k) => k.name === name)?.status[ctx.slug] ?? "missing";
118
+ const hostedOnly = who.keys
119
+ .filter((k) => !(k.name in pairs) && statusOf(k.name) !== "missing")
120
+ .map((k) => k.name);
121
+ console.error(`${pc.bold(label)} -> ${ctx.slug}`);
122
+ for (const name of names.sort()) {
123
+ const sign = pairs[name] === "" ? pc.yellow("○") : statusOf(name) === "missing" ? pc.green("+") : pc.cyan("~");
124
+ console.error(` ${sign} ${name}${pairs[name] === "" ? pc.dim(" (empty, declared only)") : ""}`);
125
+ }
126
+ for (const name of hostedOnly) {
127
+ console.error(` ${opts.prune ? pc.red("-") : pc.dim("=")} ${name}${pc.dim(opts.prune ? " (unset, not in file)" : " (kept, not in file)")}`);
128
+ }
129
+ if (opts.dryRun) {
130
+ console.error("");
131
+ continue;
132
+ }
133
+ if (opts.prune && hostedOnly.length > 0) {
134
+ const ok = await confirmDiff({
135
+ conflicts: hostedOnly.map((name) => ({ name, detail: `unset in ${ctx.slug}` })),
136
+ action: `Unset ${hostedOnly.length} value(s) not in the file`,
137
+ yes: opts.yes,
138
+ });
139
+ if (!ok) {
140
+ console.error(pc.dim("Skipped.\n"));
141
+ skipped++;
142
+ continue;
143
+ }
144
+ }
145
+ const res = await uploadValues({
146
+ linked,
147
+ context: ctx,
148
+ pairs,
149
+ prune: opts.prune,
150
+ vaultPasswordStdin: opts.vaultPasswordStdin,
151
+ });
152
+ imported += res.set.length;
153
+ changed += res.set.length + res.declared.length + res.pruned.length;
154
+ console.error(`${pc.green("✓")} ${res.set.length} set, ${res.declared.length} declared${res.pruned.length ? `, ${res.pruned.length} unset` : ""} in ${ctx.slug}\n`);
155
+ }
156
+ if (opts.dryRun)
157
+ return;
158
+ if (changed === 0 && skipped > 0) {
159
+ throw new Error("Nothing was imported. See the skipped files above.");
160
+ }
161
+ ensureGitignoreHasEnv();
162
+ if (imported > 0) {
163
+ console.error(pc.dim("Your .env files are unchanged. getmyenv run does not need them. Delete them when you are ready.\n"));
164
+ console.error("Start your app with:");
165
+ console.error(pc.cyan(` ${runLine(explicitContext ?? defaultContextSlug(who, meta))}\n`));
166
+ }
167
+ }
168
+ //# sourceMappingURL=import.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"import.js","sourceRoot":"","sources":["../../src/commands/import.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ /** Forget the unlocked project key on this machine. The next run asks for the Vault password. */
2
+ export declare function lockCommand(opts: {
3
+ apiUrl?: string;
4
+ }): Promise<void>;
5
+ //# sourceMappingURL=lock.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lock.d.ts","sourceRoot":"","sources":["../../src/commands/lock.ts"],"names":[],"mappings":"AAMA,iGAAiG;AACjG,wBAAsB,WAAW,CAAC,IAAI,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAY1E"}
@@ -0,0 +1,18 @@
1
+ import pc from "picocolors";
2
+ import { readProjectMeta } from "../lib/fs.js";
3
+ import { readFolderToken } from "../lib/credentials.js";
4
+ import { resolveApiUrl } from "../lib/api.js";
5
+ import { clearCachedPek, keychainAccount } from "../lib/keychain.js";
6
+ /** Forget the unlocked project key on this machine. The next run asks for the Vault password. */
7
+ export async function lockCommand(opts) {
8
+ const projectId = readProjectMeta()?.projectId ?? readFolderToken()?.projectId;
9
+ if (!projectId) {
10
+ console.log(pc.dim("This folder is not linked."));
11
+ return;
12
+ }
13
+ const removed = await clearCachedPek(keychainAccount(resolveApiUrl(opts.apiUrl), projectId));
14
+ console.log(removed
15
+ ? `${pc.green("✓")} Locked. The next run asks for the Vault password.`
16
+ : pc.dim("Already locked."));
17
+ }
18
+ //# sourceMappingURL=lock.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lock.js","sourceRoot":"","sources":["../../src/commands/lock.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAErE,iGAAiG;AACjG,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,IAAyB;IACzD,MAAM,SAAS,GAAG,eAAe,EAAE,EAAE,SAAS,IAAI,eAAe,EAAE,EAAE,SAAS,CAAC;IAC/E,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC,CAAC;QAClD,OAAO;IACT,CAAC;IACD,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,eAAe,CAAC,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,SAAS,CAAC,CAAC,CAAC;IAC7F,OAAO,CAAC,GAAG,CACT,OAAO;QACL,CAAC,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,oDAAoD;QACtE,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAC9B,CAAC;AACJ,CAAC"}
@@ -0,0 +1,6 @@
1
+ /** Key names by context with status. Never values. */
2
+ export declare function lsCommand(opts: {
3
+ context?: string;
4
+ apiUrl?: string;
5
+ }): Promise<void>;
6
+ //# sourceMappingURL=ls.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ls.d.ts","sourceRoot":"","sources":["../../src/commands/ls.ts"],"names":[],"mappings":"AAkBA,sDAAsD;AACtD,wBAAsB,SAAS,CAAC,IAAI,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAuB1F"}
@@ -0,0 +1,37 @@
1
+ import pc from "picocolors";
2
+ import { ensureTokenAndLink } from "../lib/bootstrap.js";
3
+ import { resolveContext } from "../lib/context.js";
4
+ const CELL = {
5
+ set: "set",
6
+ expiring_soon: "expiring",
7
+ expired: "expired",
8
+ missing: "missing",
9
+ };
10
+ function paint(status, text) {
11
+ if (status === "set")
12
+ return pc.green(text);
13
+ if (status === "missing")
14
+ return pc.dim(text);
15
+ return pc.yellow(text);
16
+ }
17
+ /** Key names by context with status. Never values. */
18
+ export async function lsCommand(opts) {
19
+ const { who, meta } = await ensureTokenAndLink({ apiUrl: opts.apiUrl, quiet: true });
20
+ const contexts = opts.context ? [resolveContext(who, meta, opts.context)] : who.contexts;
21
+ if (who.keys.length === 0) {
22
+ console.log(pc.dim("No variables yet. Add one: npx getmyenv set API_KEY"));
23
+ return;
24
+ }
25
+ const nameWidth = Math.max(4, ...who.keys.map((k) => k.name.length));
26
+ const headers = contexts.map((c) => (c.protection === "locked" ? `${c.slug} (locked)` : c.slug));
27
+ const widths = headers.map((h) => Math.max(h.length, 8));
28
+ console.log(pc.bold(["NAME".padEnd(nameWidth), ...headers.map((h, i) => h.padEnd(widths[i]))].join(" ")));
29
+ for (const k of who.keys) {
30
+ const cells = contexts.map((c, i) => {
31
+ const status = k.status[c.slug] ?? "missing";
32
+ return paint(status, CELL[status].padEnd(widths[i]));
33
+ });
34
+ console.log([k.name.padEnd(nameWidth), ...cells].join(" "));
35
+ }
36
+ }
37
+ //# sourceMappingURL=ls.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ls.js","sourceRoot":"","sources":["../../src/commands/ls.ts"],"names":[],"mappings":"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"}
@@ -1,8 +1,13 @@
1
1
  type RestoreOpts = {
2
- apiUrl: string;
3
- intoLinked?: boolean;
2
+ apiUrl?: string;
4
3
  vaultPasswordStdin?: boolean;
4
+ yes?: boolean;
5
+ dryRun?: boolean;
5
6
  };
7
+ /**
8
+ * Restore a backup into this folder's project. The password is checked
9
+ * locally first. Ciphertext is uploaded as is. Locked contexts are skipped.
10
+ */
6
11
  export declare function restoreCommand(file: string, opts: RestoreOpts): Promise<void>;
7
12
  export {};
8
13
  //# sourceMappingURL=restore.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"restore.d.ts","sourceRoot":"","sources":["../../src/commands/restore.ts"],"names":[],"mappings":"AAeA,KAAK,WAAW,GAAG;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B,CAAC;AAEF,wBAAsB,cAAc,CAClC,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,WAAW,GAChB,OAAO,CAAC,IAAI,CAAC,CA+Ef"}
1
+ {"version":3,"file":"restore.d.ts","sourceRoot":"","sources":["../../src/commands/restore.ts"],"names":[],"mappings":"AAaA,KAAK,WAAW,GAAG;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB,CAAC;AAEF;;;GAGG;AACH,wBAAsB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAyEnF"}
@@ -1,66 +1,74 @@
1
1
  import fs from "node:fs";
2
2
  import pc from "picocolors";
3
- import { createWrappedProjectKey, encryptSecret, parseBackup, restoreSecretsFromBackup, serializePayload, serializeWrappedKey, } from "@getmyenv/crypto";
4
- import { readProjectMeta, writeProjectMeta } from "../lib/fs.js";
5
- import { ApiClient } from "../lib/api.js";
3
+ import { parseBackup, restoreValuesFromBackup, serializePayload, serializeWrappedKey, } from "@getmyenv/crypto";
6
4
  import { ensureTokenAndLink } from "../lib/bootstrap.js";
5
+ import { promptConfirm } from "../lib/fs.js";
7
6
  import { resolveVaultPassword } from "../lib/guest-key.js";
7
+ import { writeCachedKey } from "../lib/pek.js";
8
+ /**
9
+ * Restore a backup into this folder's project. The password is checked
10
+ * locally first. Ciphertext is uploaded as is. Locked contexts are skipped.
11
+ */
8
12
  export async function restoreCommand(file, opts) {
9
- console.log(pc.bold("\ngetmyenv restore\n"));
10
13
  if (!fs.existsSync(file))
11
14
  throw new Error(`File not found: ${file}`);
12
- const { who, apiUrl, token } = await ensureTokenAndLink({
13
- apiUrl: opts.apiUrl,
14
- action: "restore",
15
- });
16
- const meta = readProjectMeta();
17
- const client = new ApiClient(apiUrl, token);
18
- if (who.cliScope === "production") {
19
- throw new Error("Production CLI is read-only. Restore with a Development token, or set values in the dashboard.");
20
- }
21
- if (opts.intoLinked && !meta?.projectId) {
22
- throw new Error("No linked project. Run: npx getmyenv run -- <cmd> (or set GETMYENV_TOKEN)");
15
+ if (!opts.yes && !opts.dryRun && (!process.stdin.isTTY || opts.vaultPasswordStdin)) {
16
+ throw new Error("Restore replaces values and the Vault key. Pass --yes to confirm, or --dry-run to preview.");
23
17
  }
24
18
  const envelope = parseBackup(fs.readFileSync(file, "utf8"));
19
+ const { who, client } = await ensureTokenAndLink({ apiUrl: opts.apiUrl });
20
+ if (who.token.kind !== "folder") {
21
+ throw new Error("Restore needs a signed-in folder token. Guest and server tokens cannot restore.");
22
+ }
25
23
  const password = await resolveVaultPassword({
26
- isGuest: who.isGuest,
24
+ isGuest: false,
27
25
  vaultPasswordStdin: opts.vaultPasswordStdin,
28
26
  prompt: "Vault password for this backup (hidden): ",
29
27
  });
30
- const restored = await restoreSecretsFromBackup(password, envelope);
31
- console.log(`Verified ${restored.length} secrets from backup.\n`);
32
- console.log(pc.dim(`Restoring into ${who.projectName} (${who.projectId}).\n`));
33
- const { pek, wrapped } = await createWrappedProjectKey(password);
34
- const secrets = restored.map((s) => {
35
- if (s.status === "placeholder") {
36
- return {
37
- name: s.name,
38
- environment: s.environment,
39
- status: "placeholder",
40
- expiresAt: s.expiresAt,
41
- ciphertext: null,
42
- };
28
+ try {
29
+ await restoreValuesFromBackup(password, envelope);
30
+ }
31
+ catch {
32
+ throw new Error("Could not open the backup. Check the Vault password.");
33
+ }
34
+ console.error(`Backup checked: ${envelope.values.length} values in ${envelope.contexts.length} contexts.\n`);
35
+ const locked = new Set(envelope.contexts.filter((c) => c.protection === "locked").map((c) => c.slug));
36
+ const perContext = new Map();
37
+ for (const v of envelope.values)
38
+ perContext.set(v.context, (perContext.get(v.context) ?? 0) + 1);
39
+ for (const [slug, count] of perContext) {
40
+ const note = locked.has(slug) ? pc.yellow(" (locked, skipped)") : "";
41
+ console.error(` ${slug}: ${count} value${count === 1 ? "" : "s"}${note}`);
42
+ }
43
+ console.error("");
44
+ if (opts.dryRun) {
45
+ console.error(pc.dim(`Dry run. Nothing was restored into ${who.project.name}.`));
46
+ return;
47
+ }
48
+ if (!opts.yes) {
49
+ const ok = await promptConfirm(`Restore into ${who.project.name}? Existing values with the same names are replaced, and the project uses this backup's Vault password.`, { defaultYes: false });
50
+ if (!ok) {
51
+ console.error(pc.dim("Nothing restored."));
52
+ return;
43
53
  }
44
- return {
45
- name: s.name,
46
- environment: s.environment,
47
- status: s.status,
48
- expiresAt: s.expiresAt,
49
- ciphertext: serializePayload(encryptSecret(pek, s.value)),
50
- };
51
- });
52
- const result = await client.request("POST", "/api/cli/restore", {
53
- projectName: envelope.projectName,
54
- projectId: who.projectId,
55
- wrappedProjectKey: JSON.parse(serializeWrappedKey(wrapped)),
56
- secrets,
57
- });
58
- writeProjectMeta({
59
- ...(meta ?? {}),
60
- projectId: result.projectId,
61
- projectName: result.projectName,
62
- apiUrl,
54
+ }
55
+ const res = await client.request("POST", "/api/cli/restore", {
56
+ wrappedProjectKey: envelope.wrappedProjectKey,
57
+ contexts: envelope.contexts,
58
+ keys: envelope.keys,
59
+ ...(envelope.tags ? { tags: envelope.tags } : {}),
60
+ values: envelope.values.map((v) => ({
61
+ key: v.key,
62
+ context: v.context,
63
+ expiresAt: v.expiresAt,
64
+ ciphertext: serializePayload(v.payload),
65
+ })),
63
66
  });
64
- console.log(`${pc.green("✓")} Restored encrypted secrets to ${result.projectName}\n`);
67
+ writeCachedKey(serializeWrappedKey(envelope.wrappedProjectKey));
68
+ console.log(`${pc.green("✓")} Restored ${res.restored} values into ${res.projectName}`);
69
+ if (res.skippedContexts.length > 0) {
70
+ console.log(pc.yellow(`Skipped locked contexts: ${res.skippedContexts.join(", ")}. Restore those in the dashboard.`));
71
+ }
72
+ console.log(pc.dim("The project now uses this backup's Vault password."));
65
73
  }
66
74
  //# sourceMappingURL=restore.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"restore.js","sourceRoot":"","sources":["../../src/commands/restore.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"restore.js","sourceRoot":"","sources":["../../src/commands/restore.ts"],"names":[],"mappings":"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"}
@@ -1,9 +1,11 @@
1
- type RunOpts = {
2
- env: string;
3
- apiUrl: string;
1
+ export type RunOpts = {
2
+ context?: string;
3
+ apiUrl?: string;
4
+ explain?: boolean;
5
+ keepExisting?: boolean;
6
+ allowMissing?: boolean;
4
7
  vaultPasswordStdin?: boolean;
5
- envWasDefault?: boolean;
6
8
  };
9
+ /** Resolve, validate, merge, spawn. */
7
10
  export declare function runCommand(opts: RunOpts, childArgs: string[]): Promise<void>;
8
- export {};
9
11
  //# sourceMappingURL=run.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/commands/run.ts"],"names":[],"mappings":"AAsBA,KAAK,OAAO,GAAG;IACb,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB,CAAC;AAEF,wBAAsB,UAAU,CAC9B,IAAI,EAAE,OAAO,EACb,SAAS,EAAE,MAAM,EAAE,GAClB,OAAO,CAAC,IAAI,CAAC,CA8Qf"}
1
+ {"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/commands/run.ts"],"names":[],"mappings":"AAmBA,MAAM,MAAM,OAAO,GAAG;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B,CAAC;AA+DF,uCAAuC;AACvC,wBAAsB,UAAU,CAAC,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CA4FlF"}