getmyenv 0.1.1 → 0.3.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.
- package/LICENSE +1 -1
- package/README.md +12 -4
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +81 -51
- package/dist/cli.js.map +1 -1
- package/dist/commands/backup.d.ts.map +1 -1
- package/dist/commands/backup.js +15 -6
- package/dist/commands/backup.js.map +1 -1
- package/dist/commands/link.d.ts +16 -0
- package/dist/commands/link.d.ts.map +1 -0
- package/dist/commands/link.js +116 -0
- package/dist/commands/link.js.map +1 -0
- package/dist/commands/pull.d.ts +15 -0
- package/dist/commands/pull.d.ts.map +1 -0
- package/dist/commands/pull.js +157 -0
- package/dist/commands/pull.js.map +1 -0
- package/dist/commands/push.d.ts +15 -0
- package/dist/commands/push.d.ts.map +1 -0
- package/dist/commands/push.js +259 -0
- package/dist/commands/push.js.map +1 -0
- package/dist/commands/restore.d.ts.map +1 -1
- package/dist/commands/restore.js +27 -14
- package/dist/commands/restore.js.map +1 -1
- package/dist/commands/run.d.ts +1 -0
- package/dist/commands/run.d.ts.map +1 -1
- package/dist/commands/run.js +66 -25
- package/dist/commands/run.js.map +1 -1
- package/dist/commands/token.d.ts +19 -0
- package/dist/commands/token.d.ts.map +1 -0
- package/dist/commands/token.js +188 -0
- package/dist/commands/token.js.map +1 -0
- package/dist/commands/whoami.d.ts +6 -0
- package/dist/commands/whoami.d.ts.map +1 -0
- package/dist/commands/whoami.js +51 -0
- package/dist/commands/whoami.js.map +1 -0
- package/dist/lib/api.d.ts +17 -10
- package/dist/lib/api.d.ts.map +1 -1
- package/dist/lib/api.js +77 -28
- package/dist/lib/api.js.map +1 -1
- package/dist/lib/bootstrap.d.ts +20 -0
- package/dist/lib/bootstrap.d.ts.map +1 -0
- package/dist/lib/bootstrap.js +64 -0
- package/dist/lib/bootstrap.js.map +1 -0
- package/dist/lib/confirm.d.ts +17 -0
- package/dist/lib/confirm.d.ts.map +1 -0
- package/dist/lib/confirm.js +26 -0
- package/dist/lib/confirm.js.map +1 -0
- package/dist/lib/credentials.d.ts +65 -4
- package/dist/lib/credentials.d.ts.map +1 -1
- package/dist/lib/credentials.js +256 -17
- package/dist/lib/credentials.js.map +1 -1
- package/dist/lib/fs.d.ts +19 -1
- package/dist/lib/fs.d.ts.map +1 -1
- package/dist/lib/fs.js +88 -59
- package/dist/lib/fs.js.map +1 -1
- package/dist/lib/pek.d.ts +32 -0
- package/dist/lib/pek.d.ts.map +1 -0
- package/dist/lib/pek.js +81 -0
- package/dist/lib/pek.js.map +1 -0
- package/package.json +1 -1
- package/dist/commands/add.d.ts +0 -8
- package/dist/commands/add.d.ts.map +0 -1
- package/dist/commands/add.js +0 -64
- package/dist/commands/add.js.map +0 -1
- package/dist/commands/export.d.ts +0 -9
- package/dist/commands/export.d.ts.map +0 -1
- package/dist/commands/export.js +0 -48
- package/dist/commands/export.js.map +0 -1
- package/dist/commands/init.d.ts +0 -2
- package/dist/commands/init.d.ts.map +0 -1
- package/dist/commands/init.js +0 -58
- package/dist/commands/init.js.map +0 -1
- package/dist/commands/login.d.ts +0 -6
- package/dist/commands/login.d.ts.map +0 -1
- package/dist/commands/login.js +0 -35
- package/dist/commands/login.js.map +0 -1
- package/dist/commands/logout.d.ts +0 -2
- package/dist/commands/logout.d.ts.map +0 -1
- package/dist/commands/logout.js +0 -13
- package/dist/commands/logout.js.map +0 -1
- package/dist/commands/migrate.d.ts +0 -13
- package/dist/commands/migrate.d.ts.map +0 -1
- package/dist/commands/migrate.js +0 -127
- package/dist/commands/migrate.js.map +0 -1
- package/dist/commands/status.d.ts +0 -7
- package/dist/commands/status.d.ts.map +0 -1
- package/dist/commands/status.js +0 -76
- package/dist/commands/status.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pull.js","sourceRoot":"","sources":["../../src/commands/pull.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,EACL,aAAa,EACb,YAAY,GACb,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,eAAe,GAChB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAgBzD,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,IAAc;IAC9C,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,mBAAmB,CAAC,CAAC,CAAC;IAC1C,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,CAAC;IACvC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAEhB,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,MAAM,kBAAkB,CAAC;QACjE,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,MAAM,EAAE,MAAM;KACf,CAAC,CAAC;IAEH,IAAI,GAAG,CAAC,QAAQ,KAAK,YAAY,EAAE,CAAC;QAClC,MAAM,IAAI,KAAK,CACb;YACE,8BAA8B;YAC9B,gFAAgF;YAChF,mDAAmD;SACpD,CAAC,IAAI,CAAC,IAAI,CAAC,CACb,CAAC;IACJ,CAAC;IAED,MAAM,IAAI,GAAG,eAAe,EAAE,CAAC;IAC/B,IAAI,WAAW,GAAG,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC7C,IAAI,IAAI,CAAC,aAAa,IAAI,IAAI,EAAE,UAAU,EAAE,CAAC;QAC3C,WAAW,GAAG,IAAI,CAAC,UAAU,CAAC;IAChC,CAAC;IACD,IAAI,WAAW,KAAK,GAAG,CAAC,QAAQ,EAAE,CAAC;QACjC,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACvB,WAAW,GAAG,GAAG,CAAC,QAAQ,CAAC;QAC7B,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,KAAK,CACb;gBACE,kBAAkB,GAAG,CAAC,QAAQ,uBAAuB,WAAW,GAAG;gBACnE,kCAAkC;aACnC,CAAC,IAAI,CAAC,IAAI,CAAC,CACb,CAAC;QACJ,CAAC;IACH,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,kBAAkB,EAAE;QACtD,UAAU,EAAE,IAAI,CAAC,kBAAkB;KACpC,CAAC,CAAC;IAEH,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAE5C,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,OAAO,CAI/B,KAAK,EACL,qBAAqB,SAAS,uBAAuB,kBAAkB,CAAC,WAAW,CAAC,EAAE,CACvF,CAAC;IAEF,MAAM,GAAG,GAAG,MAAM,SAAS,CAAC;QAC1B,QAAQ;QACR,KAAK,EAAE,GAAG,CAAC,QAAQ;QACnB,OAAO,EAAE,IAAI,CAAC,iBAAiB;KAChC,CAAC,CAAC;IAEH,MAAM,MAAM,GAA2B,EAAE,CAAC;IAC1C,MAAM,KAAK,GAAa;QACtB,0CAA0C;QAC1C,kBAAkB,WAAW,EAAE;QAC/B,4BAA4B;QAC5B,EAAE;KACH,CAAC;IAEF,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;QAClC,IAAI,MAAM,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAChC,KAAK,CAAC,IAAI,CAAC,4CAA4C,CAAC,CAAC;YACzD,SAAS;QACX,CAAC;QACD,IACE,MAAM,CAAC,MAAM,KAAK,aAAa;YAC/B,MAAM,CAAC,UAAU,IAAI,IAAI;YACzB,MAAM,CAAC,UAAU,KAAK,EAAE,EACxB,CAAC;YACD,KAAK,CAAC,IAAI,CAAC,8BAA8B,CAAC,CAAC;YAC3C,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC;YAC9B,SAAS;QACX,CAAC;QACD,MAAM,KAAK,GAAG,aAAa,CACzB,GAAG,EACH,YAAY,CAAC,MAAM,CAAC,UAAoB,CAAC,CAC1C,CAAC;QACF,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;QAC5B,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,IAAI,IAAI,KAAK,EAAE,CAAC,CAAC;IACxC,CAAC;IAED,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QAChB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,CAAC;QAC9C,OAAO;IACT,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,CAAC,EAAE,IAAI,IAAI,CAAC,MAAM,IAAI,MAAM,CAAC;IACjD,MAAM,MAAM,GAAG,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;IACtC,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAElD,IAAI,IAAI,CAAC,MAAM,EAAE,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,yBAAyB,OAAO,IAAI,CAAC,CAAC,CAAC;QAC1D,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;YACvC,IAAI,CAAC,CAAC,IAAI,IAAI,KAAK,CAAC;gBAAE,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;iBAC5C,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,MAAM,CAAC,IAAI,CAAC;gBAAE,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;;gBAC7D,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;QAClC,CAAC;QACD,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;YACtC,IAAI,CAAC,CAAC,IAAI,IAAI,MAAM,CAAC;gBAAE,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,eAAe,CAAC,CAAC;QACjE,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,OAAO;IACT,CAAC;IAED,IAAI,IAAI,CAAC,KAAK,IAAI,MAAM,EAAE,CAAC;QACzB,MAAM,MAAM,GAAG,EAAE,GAAG,KAAK,EAAE,CAAC;QAC5B,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;YACnD,IAAI,CAAC,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,CAAC;gBAC7C,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;YACvB,CAAC;QACH,CAAC;QACD,MAAM,WAAW,GAAG;YAClB,mDAAmD;YACnD,kBAAkB,WAAW,EAAE;YAC/B,4BAA4B;YAC5B,EAAE;YACF,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;SACvD,CAAC;QACF,EAAE,CAAC,aAAa,CAAC,OAAO,EAAE,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QAC1E,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,gBAAgB,OAAO,EAAE,CAAC,CAAC;QACvD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,8CAA8C,CAAC,CAAC,CAAC;QACpE,OAAO;IACT,CAAC;IAED,MAAM,SAAS,GAAwC,EAAE,CAAC;IAC1D,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QACnD,IAAI,IAAI,IAAI,KAAK,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,KAAK,EAAE,CAAC;YAC3C,SAAS,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,2BAA2B,EAAE,CAAC,CAAC;QAChE,CAAC;IACH,CAAC;IAED,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACzB,MAAM,EAAE,GAAG,MAAM,WAAW,CAAC;YAC3B,SAAS;YACT,MAAM,EAAE,oCAAoC;YAC5C,GAAG,EAAE,IAAI,CAAC,GAAG;SACd,CAAC,CAAC;QACH,IAAI,CAAC,EAAE,EAAE,CAAC;YACR,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC,CAAC;YACzC,OAAO;QACT,CAAC;IACH,CAAC;IAED,IAAI,MAAM,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACtE,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;QAChD,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;QACvE,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;YACtC,MAAM,EAAE,GAAG,MAAM,WAAW,CAAC;gBAC3B,SAAS,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;oBAClC,IAAI;oBACJ,MAAM,EAAE,oDAAoD;iBAC7D,CAAC,CAAC;gBACH,MAAM,EAAE,oBAAoB;gBAC5B,GAAG,EAAE,IAAI,CAAC,GAAG;aACd,CAAC,CAAC;YACH,IAAI,CAAC,EAAE,EAAE,CAAC;gBACR,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC,CAAC;gBACzC,OAAO;YACT,CAAC;QACH,CAAC;IACH,CAAC;IAED,EAAE,CAAC,aAAa,CAAC,OAAO,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACpE,OAAO,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,OAAO,EAAE,CAAC,CAAC;IACjD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,8CAA8C,CAAC,CAAC,CAAC;AACtE,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
type PushOpts = {
|
|
2
|
+
env: string;
|
|
3
|
+
apiUrl: string;
|
|
4
|
+
file?: string;
|
|
5
|
+
key?: string;
|
|
6
|
+
create?: boolean;
|
|
7
|
+
prune?: boolean;
|
|
8
|
+
yes?: boolean;
|
|
9
|
+
dryRun?: boolean;
|
|
10
|
+
vaultPasswordStdin?: boolean;
|
|
11
|
+
envWasDefault?: boolean;
|
|
12
|
+
};
|
|
13
|
+
export declare function pushCommand(opts: PushOpts): Promise<void>;
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=push.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"push.d.ts","sourceRoot":"","sources":["../../src/commands/push.ts"],"names":[],"mappings":"AA6BA,KAAK,QAAQ,GAAG;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB,CAAC;AA+LF,wBAAsB,WAAW,CAAC,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC,CA8I/D"}
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import pc from "picocolors";
|
|
4
|
+
import { encryptSecret, serializePayload } from "@getmyenv/crypto";
|
|
5
|
+
import { secretNameSchema } from "@getmyenv/shared";
|
|
6
|
+
import { detectLanguages, ensureGitignoreHasEnv, envReadSnippet, inferEnvNameFromFile, isEnvSampleFile, isProductionEnvFilename, listPushEnvFiles, parseEnvFile, promptChoice, promptConfirm, promptHidden, readProjectMeta, writeProjectMeta, } from "../lib/fs.js";
|
|
7
|
+
import { ApiClient, ensureSessionToken, } from "../lib/api.js";
|
|
8
|
+
import { loadPek } from "../lib/pek.js";
|
|
9
|
+
import { confirmDiff } from "../lib/confirm.js";
|
|
10
|
+
import { ensureTokenAndLink } from "../lib/bootstrap.js";
|
|
11
|
+
import { normalizeEnvName } from "../lib/env-name.js";
|
|
12
|
+
async function resolveEnvPath(file) {
|
|
13
|
+
if (file) {
|
|
14
|
+
const resolved = path.resolve(process.cwd(), file);
|
|
15
|
+
if (!fs.existsSync(resolved)) {
|
|
16
|
+
throw new Error(`Env file not found: ${file}`);
|
|
17
|
+
}
|
|
18
|
+
if (isProductionEnvFilename(resolved)) {
|
|
19
|
+
throw new Error([
|
|
20
|
+
`Refusing to push ${path.basename(resolved)}.`,
|
|
21
|
+
"Production-named env files are not uploaded from the CLI.",
|
|
22
|
+
"Set Production values in the dashboard, or use run with a Production token.",
|
|
23
|
+
].join("\n"));
|
|
24
|
+
}
|
|
25
|
+
return resolved;
|
|
26
|
+
}
|
|
27
|
+
const candidates = listPushEnvFiles();
|
|
28
|
+
if (candidates.length === 0) {
|
|
29
|
+
throw new Error([
|
|
30
|
+
"No pushable .env* files found under this folder.",
|
|
31
|
+
"Files whose names contain \"production\" are skipped.",
|
|
32
|
+
"Pass --file <path>, or create a .env file in this folder.",
|
|
33
|
+
].join("\n"));
|
|
34
|
+
}
|
|
35
|
+
const labels = candidates.map((p) => path.relative(process.cwd(), p) || p);
|
|
36
|
+
if (candidates.length === 1) {
|
|
37
|
+
console.log(`Using ${labels[0]}\n`);
|
|
38
|
+
return candidates[0];
|
|
39
|
+
}
|
|
40
|
+
if (!process.stdin.isTTY) {
|
|
41
|
+
throw new Error(`Multiple env files found. Pass --file <path>:\n${labels.map((l) => ` ${l}`).join("\n")}`);
|
|
42
|
+
}
|
|
43
|
+
console.log("Found env files (production* skipped):\n");
|
|
44
|
+
const idx = await promptChoice("Push which file?", labels, 0);
|
|
45
|
+
console.log("");
|
|
46
|
+
return candidates[idx];
|
|
47
|
+
}
|
|
48
|
+
function parseKeyOpt(key) {
|
|
49
|
+
const eq = key.indexOf("=");
|
|
50
|
+
if (eq <= 0) {
|
|
51
|
+
return { name: key.trim() };
|
|
52
|
+
}
|
|
53
|
+
return {
|
|
54
|
+
name: key.slice(0, eq).trim(),
|
|
55
|
+
value: key.slice(eq + 1),
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
async function uploadPairs(pairs, opts) {
|
|
59
|
+
const keys = Object.keys(pairs);
|
|
60
|
+
if (keys.length === 0) {
|
|
61
|
+
throw new Error("No variables to push.");
|
|
62
|
+
}
|
|
63
|
+
const token = await ensureSessionToken(opts.projectId);
|
|
64
|
+
const client = new ApiClient(opts.apiUrl, token);
|
|
65
|
+
const remoteList = await client.request("GET", `/api/cli/projects/${opts.projectId}/secrets?environment=${encodeURIComponent(opts.environment)}`);
|
|
66
|
+
const remoteNames = new Set(remoteList.secrets.map((s) => s.name));
|
|
67
|
+
const localNames = new Set(keys);
|
|
68
|
+
const hostedOnly = [...remoteNames].filter((n) => !localNames.has(n));
|
|
69
|
+
if (opts.dryRun) {
|
|
70
|
+
console.log(pc.dim("Dry run - no changes uploaded.\n"));
|
|
71
|
+
for (const name of keys) {
|
|
72
|
+
const empty = !pairs[name];
|
|
73
|
+
console.log(` ${remoteNames.has(name) ? "~" : "+"} ${name}${empty ? " (placeholder)" : ""}`);
|
|
74
|
+
}
|
|
75
|
+
for (const name of hostedOnly) {
|
|
76
|
+
console.log(` - ${name}${opts.prune ? " (would prune)" : " (kept)"}`);
|
|
77
|
+
}
|
|
78
|
+
console.log("");
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
if (hostedOnly.length > 0 && opts.prune) {
|
|
82
|
+
const ok = await confirmDiff({
|
|
83
|
+
conflicts: hostedOnly.map((name) => ({
|
|
84
|
+
name,
|
|
85
|
+
detail: "hosted only",
|
|
86
|
+
})),
|
|
87
|
+
action: "Delete hosted secrets missing from local file",
|
|
88
|
+
yes: opts.yes,
|
|
89
|
+
});
|
|
90
|
+
if (!ok) {
|
|
91
|
+
console.log(pc.dim("Push cancelled.\n"));
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
console.log(`Encrypting ${keys.length} secret(s) for ${opts.environment}...\n`);
|
|
96
|
+
const password = await promptHidden("Vault password: ", {
|
|
97
|
+
allowStdin: opts.vaultPasswordStdin,
|
|
98
|
+
});
|
|
99
|
+
const { pek, wrappedRaw } = await loadPek({
|
|
100
|
+
password,
|
|
101
|
+
scope: opts.scope,
|
|
102
|
+
allowCreate: true,
|
|
103
|
+
});
|
|
104
|
+
for (const name of keys) {
|
|
105
|
+
const value = pairs[name] ?? "";
|
|
106
|
+
if (!value) {
|
|
107
|
+
await client.request("POST", `/api/cli/projects/${opts.projectId}/secrets`, {
|
|
108
|
+
name,
|
|
109
|
+
environment: opts.environment,
|
|
110
|
+
placeholder: true,
|
|
111
|
+
wrappedProjectKey: JSON.parse(wrappedRaw),
|
|
112
|
+
});
|
|
113
|
+
console.log(` ${pc.green("✓")} ${name} (placeholder)`);
|
|
114
|
+
continue;
|
|
115
|
+
}
|
|
116
|
+
const ciphertext = serializePayload(encryptSecret(pek, value));
|
|
117
|
+
await client.request("POST", `/api/cli/projects/${opts.projectId}/secrets`, {
|
|
118
|
+
name,
|
|
119
|
+
environment: opts.environment,
|
|
120
|
+
ciphertext,
|
|
121
|
+
wrappedProjectKey: JSON.parse(wrappedRaw),
|
|
122
|
+
});
|
|
123
|
+
console.log(` ${pc.green("✓")} ${name}`);
|
|
124
|
+
}
|
|
125
|
+
if (opts.prune && hostedOnly.length > 0) {
|
|
126
|
+
await client.request("DELETE", `/api/cli/projects/${opts.projectId}/secrets`, {
|
|
127
|
+
environment: opts.environment,
|
|
128
|
+
names: hostedOnly,
|
|
129
|
+
});
|
|
130
|
+
for (const name of hostedOnly) {
|
|
131
|
+
console.log(` ${pc.yellow("-")} ${name} (pruned)`);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
const meta = readProjectMeta() ?? {};
|
|
135
|
+
writeProjectMeta({
|
|
136
|
+
...meta,
|
|
137
|
+
projectId: opts.projectId,
|
|
138
|
+
apiUrl: opts.apiUrl,
|
|
139
|
+
defaultEnv: meta.defaultEnv ??
|
|
140
|
+
(opts.scope === "production" ? "production" : "development"),
|
|
141
|
+
});
|
|
142
|
+
console.log(`\n${pc.green("✓")} Pushed ${keys.length} secret(s)\n`);
|
|
143
|
+
}
|
|
144
|
+
export async function pushCommand(opts) {
|
|
145
|
+
console.log(pc.bold("\ngetmyenv push\n"));
|
|
146
|
+
const { who, apiUrl, projectId } = await ensureTokenAndLink({
|
|
147
|
+
apiUrl: opts.apiUrl,
|
|
148
|
+
forceLink: opts.create,
|
|
149
|
+
action: "push",
|
|
150
|
+
});
|
|
151
|
+
if (who.cliScope === "production") {
|
|
152
|
+
throw new Error([
|
|
153
|
+
"Production CLI is read-only.",
|
|
154
|
+
"Set Production values in the dashboard, or use a Development token to push.",
|
|
155
|
+
"Use npx getmyenv run to pass Production secrets as env vars without writing them to disk.",
|
|
156
|
+
].join("\n"));
|
|
157
|
+
}
|
|
158
|
+
const linked = { projectId, projectName: who.projectName };
|
|
159
|
+
let environment = normalizeEnvName(opts.env);
|
|
160
|
+
if (environment !== who.cliScope) {
|
|
161
|
+
if (opts.envWasDefault) {
|
|
162
|
+
environment = who.cliScope;
|
|
163
|
+
}
|
|
164
|
+
else {
|
|
165
|
+
throw new Error([
|
|
166
|
+
`Token scope is ${who.cliScope}, but you passed -e ${environment}.`,
|
|
167
|
+
"Use a matching Development/Production token, or omit -e.",
|
|
168
|
+
].join("\n"));
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
if (opts.key?.trim()) {
|
|
172
|
+
const parsed = parseKeyOpt(opts.key.trim());
|
|
173
|
+
const nameCheck = secretNameSchema.safeParse(parsed.name);
|
|
174
|
+
if (!nameCheck.success) {
|
|
175
|
+
throw new Error("Invalid secret name. Use a valid environment variable name.");
|
|
176
|
+
}
|
|
177
|
+
let value = parsed.value;
|
|
178
|
+
if (value === undefined) {
|
|
179
|
+
value = await promptHidden(`Value for ${parsed.name}: `);
|
|
180
|
+
}
|
|
181
|
+
if (!value)
|
|
182
|
+
throw new Error("Value required");
|
|
183
|
+
console.log(pc.dim(`Environment: ${environment}\n`));
|
|
184
|
+
await uploadPairs({ [parsed.name]: value }, {
|
|
185
|
+
environment,
|
|
186
|
+
apiUrl,
|
|
187
|
+
projectId: linked.projectId,
|
|
188
|
+
scope: who.cliScope,
|
|
189
|
+
vaultPasswordStdin: opts.vaultPasswordStdin,
|
|
190
|
+
prune: false,
|
|
191
|
+
yes: opts.yes,
|
|
192
|
+
dryRun: opts.dryRun,
|
|
193
|
+
});
|
|
194
|
+
return;
|
|
195
|
+
}
|
|
196
|
+
const envPath = await resolveEnvPath(opts.file);
|
|
197
|
+
const baseName = path.basename(envPath);
|
|
198
|
+
const rel = path.relative(process.cwd(), envPath) || baseName;
|
|
199
|
+
if (opts.envWasDefault && opts.env === "development") {
|
|
200
|
+
const inferred = inferEnvNameFromFile(envPath);
|
|
201
|
+
if (inferred === who.cliScope) {
|
|
202
|
+
environment = inferred;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
if (isEnvSampleFile(envPath)) {
|
|
206
|
+
console.log(pc.dim("This looks like a repo sample file. Values may be placeholders.\n"));
|
|
207
|
+
}
|
|
208
|
+
const pairs = parseEnvFile(envPath);
|
|
209
|
+
const keys = Object.keys(pairs);
|
|
210
|
+
if (keys.length === 0) {
|
|
211
|
+
throw new Error(`No variables found in ${rel}`);
|
|
212
|
+
}
|
|
213
|
+
console.log(`Found ${keys.length} variables in ${rel}:\n`);
|
|
214
|
+
for (const k of keys) {
|
|
215
|
+
console.log(` ${pc.green("✓")} ${k}`);
|
|
216
|
+
}
|
|
217
|
+
console.log("");
|
|
218
|
+
console.log(pc.dim(`Environment: ${environment}\n`));
|
|
219
|
+
await uploadPairs(pairs, {
|
|
220
|
+
environment,
|
|
221
|
+
apiUrl,
|
|
222
|
+
projectId: linked.projectId,
|
|
223
|
+
scope: who.cliScope,
|
|
224
|
+
vaultPasswordStdin: opts.vaultPasswordStdin,
|
|
225
|
+
prune: opts.prune,
|
|
226
|
+
yes: opts.yes,
|
|
227
|
+
dryRun: opts.dryRun,
|
|
228
|
+
});
|
|
229
|
+
if (opts.dryRun)
|
|
230
|
+
return;
|
|
231
|
+
ensureGitignoreHasEnv();
|
|
232
|
+
const sample = keys[0] ?? "MY_SECRET";
|
|
233
|
+
const languages = detectLanguages();
|
|
234
|
+
const primary = languages[0]?.language ?? null;
|
|
235
|
+
console.log("Your application still reads it from the environment:\n");
|
|
236
|
+
if (languages.length > 1) {
|
|
237
|
+
for (const lang of languages.slice(0, 4)) {
|
|
238
|
+
console.log(pc.cyan(` ${lang.label}: ${envReadSnippet(lang.language, sample)}`));
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
else {
|
|
242
|
+
console.log(pc.cyan(` ${envReadSnippet(primary, sample)}`));
|
|
243
|
+
}
|
|
244
|
+
console.log("");
|
|
245
|
+
if (process.stdin.isTTY) {
|
|
246
|
+
const migratedName = `${baseName}.migrated.local`;
|
|
247
|
+
const remove = await promptConfirm(`Rename plaintext ${baseName} to ${migratedName}? (never deleted silently)`);
|
|
248
|
+
if (remove) {
|
|
249
|
+
const dest = envPath + ".migrated.local";
|
|
250
|
+
fs.renameSync(envPath, dest);
|
|
251
|
+
console.log(`${pc.green("✓")} Renamed to ${path.basename(dest)}`);
|
|
252
|
+
}
|
|
253
|
+
else {
|
|
254
|
+
console.log(pc.dim(`Kept plaintext ${baseName} in place.`));
|
|
255
|
+
}
|
|
256
|
+
console.log("");
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
//# sourceMappingURL=push.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"push.js","sourceRoot":"","sources":["../../src/commands/push.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"restore.d.ts","sourceRoot":"","sources":["../../src/commands/restore.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"restore.d.ts","sourceRoot":"","sources":["../../src/commands/restore.ts"],"names":[],"mappings":"AAkBA,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,CA2Ff"}
|
package/dist/commands/restore.js
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import pc from "picocolors";
|
|
3
|
-
import { parseBackup, restoreSecretsFromBackup } from "@getmyenv/crypto";
|
|
3
|
+
import { createWrappedProjectKey, encryptSecret, parseBackup, restoreSecretsFromBackup, serializePayload, serializeWrappedKey, } from "@getmyenv/crypto";
|
|
4
4
|
import { promptHidden, readProjectMeta, writeProjectMeta } from "../lib/fs.js";
|
|
5
|
-
import { ApiClient, ensureSessionToken } from "../lib/api.js";
|
|
6
|
-
import { createWrappedProjectKey, encryptSecret, serializePayload, serializeWrappedKey, } from "@getmyenv/crypto";
|
|
5
|
+
import { ApiClient, ensureSessionToken, resolveApiUrl, } from "../lib/api.js";
|
|
7
6
|
export async function restoreCommand(file, opts) {
|
|
8
7
|
console.log(pc.bold("\ngetmyenv restore\n"));
|
|
9
8
|
if (!fs.existsSync(file))
|
|
@@ -15,8 +14,28 @@ export async function restoreCommand(file, opts) {
|
|
|
15
14
|
// Verify decryption works offline first
|
|
16
15
|
const restored = await restoreSecretsFromBackup(password, envelope);
|
|
17
16
|
console.log(`Verified ${restored.length} secrets from backup (offline).\n`);
|
|
18
|
-
const token = await ensureSessionToken();
|
|
19
17
|
const meta = readProjectMeta();
|
|
18
|
+
const token = await ensureSessionToken(meta?.projectId);
|
|
19
|
+
const apiUrl = resolveApiUrl(opts.apiUrl, meta?.projectId);
|
|
20
|
+
const client = new ApiClient(apiUrl, token);
|
|
21
|
+
const who = await client.request("GET", "/api/cli/whoami");
|
|
22
|
+
if (who.cliScope === "production") {
|
|
23
|
+
throw new Error([
|
|
24
|
+
"Production CLI is read-only.",
|
|
25
|
+
"Restore with a Development token, or set values in the dashboard.",
|
|
26
|
+
].join("\n"));
|
|
27
|
+
}
|
|
28
|
+
// CLI tokens are per-project: restore always targets the token's project.
|
|
29
|
+
if (meta?.projectId && String(meta.projectId) !== String(who.projectId)) {
|
|
30
|
+
throw new Error([
|
|
31
|
+
`Linked project (${meta.projectName ?? meta.projectId}) does not match this token (${who.projectName}, ${who.projectId}).`,
|
|
32
|
+
"Run: npx getmyenv link",
|
|
33
|
+
].join("\n"));
|
|
34
|
+
}
|
|
35
|
+
if (opts.intoLinked && !meta?.projectId) {
|
|
36
|
+
throw new Error("No linked project. Run: npx getmyenv link");
|
|
37
|
+
}
|
|
38
|
+
console.log(pc.dim(`Restoring into token project ${who.projectName} (${who.projectId}).\n`));
|
|
20
39
|
// Re-encrypt under a fresh wrapped key for upload (same password)
|
|
21
40
|
const { pek, wrapped } = await createWrappedProjectKey(password);
|
|
22
41
|
const secrets = restored.map((s) => {
|
|
@@ -37,14 +56,9 @@ export async function restoreCommand(file, opts) {
|
|
|
37
56
|
ciphertext: serializePayload(encryptSecret(pek, s.value)),
|
|
38
57
|
};
|
|
39
58
|
});
|
|
40
|
-
const intoLinked = Boolean(opts.intoLinked && meta?.projectId);
|
|
41
|
-
if (meta?.projectId && !opts.intoLinked) {
|
|
42
|
-
console.log(pc.dim("Creating a new project (default). Pass --into-linked to overwrite the linked project.\n"));
|
|
43
|
-
}
|
|
44
|
-
const client = new ApiClient(opts.apiUrl, token);
|
|
45
59
|
const result = await client.request("POST", "/api/cli/restore", {
|
|
46
60
|
projectName: envelope.projectName,
|
|
47
|
-
projectId:
|
|
61
|
+
projectId: who.projectId,
|
|
48
62
|
wrappedProjectKey: JSON.parse(serializeWrappedKey(wrapped)),
|
|
49
63
|
secrets,
|
|
50
64
|
});
|
|
@@ -52,10 +66,9 @@ export async function restoreCommand(file, opts) {
|
|
|
52
66
|
...(meta ?? {}),
|
|
53
67
|
projectId: result.projectId,
|
|
54
68
|
projectName: result.projectName,
|
|
55
|
-
|
|
56
|
-
|
|
69
|
+
apiUrl,
|
|
70
|
+
defaultEnv: meta?.defaultEnv ?? "development",
|
|
57
71
|
});
|
|
58
|
-
console.log(`${pc.green("✓")} Restored encrypted secrets to
|
|
59
|
-
(intoLinked ? " (linked project)\n" : ` as "${result.projectName}"\n`));
|
|
72
|
+
console.log(`${pc.green("✓")} Restored encrypted secrets to ${result.projectName}\n`);
|
|
60
73
|
}
|
|
61
74
|
//# sourceMappingURL=restore.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"restore.js","sourceRoot":"","sources":["../../src/commands/restore.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,MAAM,YAAY,CAAC;AAC5B,OAAO,
|
|
1
|
+
{"version":3,"file":"restore.js","sourceRoot":"","sources":["../../src/commands/restore.ts"],"names":[],"mappings":"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"}
|
package/dist/commands/run.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/commands/run.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"run.d.ts","sourceRoot":"","sources":["../../src/commands/run.ts"],"names":[],"mappings":"AA4BA,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,CA6Qf"}
|
package/dist/commands/run.js
CHANGED
|
@@ -1,34 +1,70 @@
|
|
|
1
1
|
import { spawn } from "node:child_process";
|
|
2
2
|
import pc from "picocolors";
|
|
3
|
-
import { decryptSecret, parsePayload,
|
|
4
|
-
import { promptHidden, readProjectMeta, readRequirements, } from "../lib/fs.js";
|
|
5
|
-
import { ApiClient, ensureSessionToken } from "../lib/api.js";
|
|
3
|
+
import { decryptSecret, parsePayload, signAccessRequest, } from "@getmyenv/crypto";
|
|
4
|
+
import { promptHidden, readProjectMeta, readRequirements, requireLinkedProject, } from "../lib/fs.js";
|
|
5
|
+
import { ApiClient, ensureSessionToken, resolveApiUrl, } from "../lib/api.js";
|
|
6
6
|
import { clearGrant, loadGrant, loadOrCreateIdentity, saveGrant, } from "../lib/identity.js";
|
|
7
|
+
import { unwrapPek } from "../lib/pek.js";
|
|
8
|
+
import { normalizeEnvName } from "../lib/env-name.js";
|
|
7
9
|
export async function runCommand(opts, childArgs) {
|
|
8
10
|
if (childArgs.length === 0) {
|
|
9
11
|
throw new Error("Usage: npx getmyenv run -- <command>");
|
|
10
12
|
}
|
|
11
13
|
console.log(pc.bold("\ngetmyenv\n"));
|
|
12
14
|
const meta = readProjectMeta();
|
|
13
|
-
|
|
14
|
-
|
|
15
|
+
requireLinkedProject(meta);
|
|
16
|
+
const token = await ensureSessionToken(meta.projectId);
|
|
17
|
+
const apiUrl = resolveApiUrl(opts.apiUrl, meta.projectId);
|
|
18
|
+
const client = new ApiClient(apiUrl, token);
|
|
19
|
+
const who = await client.request("GET", "/api/cli/whoami");
|
|
20
|
+
if (String(meta.projectId) !== String(who.projectId)) {
|
|
21
|
+
throw new Error([
|
|
22
|
+
`Linked project (${meta.projectName ?? meta.projectId}) does not match this token (${who.projectName}, ${who.projectId}).`,
|
|
23
|
+
"Run: npx getmyenv link",
|
|
24
|
+
"Or create a CLI token for this project on /cli.",
|
|
25
|
+
].join("\n"));
|
|
26
|
+
}
|
|
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
|
+
who.cliScope === "development"
|
|
39
|
+
? "Use: npx getmyenv run -e development -- <cmd>"
|
|
40
|
+
: "Use: npx getmyenv run -e production -- <cmd>",
|
|
41
|
+
"Or create a matching Development/Production token on /cli.",
|
|
42
|
+
].join("\n"));
|
|
43
|
+
}
|
|
15
44
|
}
|
|
16
|
-
const token = await ensureSessionToken();
|
|
17
|
-
const client = new ApiClient(opts.apiUrl, token);
|
|
18
45
|
const requestedSecretNames = readRequirements();
|
|
46
|
+
const secretsLine = requestedSecretNames.length > 0
|
|
47
|
+
? requestedSecretNames.join(", ")
|
|
48
|
+
: "all active secrets in this environment";
|
|
49
|
+
const needsDashboardWait = who.cliScope === "production";
|
|
50
|
+
console.log(`Token: ${who.label ?? who.cliScope}`);
|
|
51
|
+
console.log(`Project: ${who.projectName} (${who.projectId})`);
|
|
52
|
+
console.log(`Environment: ${environment}`);
|
|
53
|
+
console.log(`API: ${apiUrl}`);
|
|
54
|
+
console.log(`Secrets: ${secretsLine}`);
|
|
55
|
+
console.log(`Access: ${needsDashboardWait
|
|
56
|
+
? "requesting dashboard approval (production)"
|
|
57
|
+
: "not required (development)"}\n`);
|
|
19
58
|
const envInfo = await client.request("GET", `/api/cli/projects/${meta.projectId}`);
|
|
20
|
-
const
|
|
21
|
-
if (!
|
|
22
|
-
throw new Error(`Environment not found: ${
|
|
59
|
+
const envRow = envInfo.environments.find((e) => e.name.toLowerCase() === environment.toLowerCase());
|
|
60
|
+
if (!envRow) {
|
|
61
|
+
throw new Error(`Environment not found: ${environment}`);
|
|
23
62
|
}
|
|
24
|
-
const environmentId = String(
|
|
63
|
+
const environmentId = String(envRow.id);
|
|
25
64
|
const projectId = String(meta.projectId);
|
|
26
65
|
let grant = loadGrant(projectId, environmentId);
|
|
27
66
|
if (!grant) {
|
|
28
67
|
const identity = loadOrCreateIdentity(projectId);
|
|
29
|
-
console.log("Access required\n");
|
|
30
|
-
console.log(`Project:\n ${meta.projectName ?? projectId}`);
|
|
31
|
-
console.log(`Environment:\n ${opts.env}`);
|
|
32
68
|
const timestamp = String(Date.now());
|
|
33
69
|
const message = [
|
|
34
70
|
projectId,
|
|
@@ -41,10 +77,10 @@ export async function runCommand(opts, childArgs) {
|
|
|
41
77
|
try {
|
|
42
78
|
request = await client.request("POST", "/api/cli/requests", {
|
|
43
79
|
projectId: meta.projectId,
|
|
44
|
-
environmentId:
|
|
80
|
+
environmentId: envRow.id,
|
|
45
81
|
identityPublicKey: identity.publicKey,
|
|
46
82
|
identityLabel: process.env.GETMYENV_MACHINE_LABEL ??
|
|
47
|
-
`${process.env.USERNAME ?? process.env.USER ?? "dev"}'s
|
|
83
|
+
`${process.env.USERNAME ?? process.env.USER ?? "dev"}'s machine`,
|
|
48
84
|
signature,
|
|
49
85
|
message,
|
|
50
86
|
timestamp,
|
|
@@ -55,7 +91,6 @@ export async function runCommand(opts, childArgs) {
|
|
|
55
91
|
const msg = err instanceof Error ? err.message : String(err);
|
|
56
92
|
if (/access requests are disabled/i.test(msg)) {
|
|
57
93
|
console.log(`\n${pc.red("✗")} Access requests are disabled for this project.\n`);
|
|
58
|
-
console.log("Enable them in the getmyenv dashboard for this project.\n");
|
|
59
94
|
process.exit(1);
|
|
60
95
|
}
|
|
61
96
|
throw err;
|
|
@@ -70,10 +105,11 @@ export async function runCommand(opts, childArgs) {
|
|
|
70
105
|
environmentId,
|
|
71
106
|
};
|
|
72
107
|
saveGrant(grant);
|
|
73
|
-
console.log(`${pc.green("✓")}
|
|
108
|
+
console.log(`${pc.green("✓")} ${needsDashboardWait
|
|
109
|
+
? "Trusted device - access granted"
|
|
110
|
+
: "Access granted (development)"}\n`);
|
|
74
111
|
}
|
|
75
112
|
else {
|
|
76
|
-
console.log("\nA dashboard approval is required.\n");
|
|
77
113
|
console.log("Open getmyenv to approve access.\n");
|
|
78
114
|
console.log(pc.dim("Tip: choose Trust this device to skip approval next time on this machine.\n"));
|
|
79
115
|
console.log(pc.dim("Waiting..."));
|
|
@@ -99,7 +135,6 @@ export async function runCommand(opts, childArgs) {
|
|
|
99
135
|
}
|
|
100
136
|
if (status.status === "denied") {
|
|
101
137
|
console.log(`\n\n${pc.red("✗")} Access denied\n`);
|
|
102
|
-
console.log("The application was not started.\n");
|
|
103
138
|
process.exit(1);
|
|
104
139
|
}
|
|
105
140
|
if (status.status === "expired" || status.status === "consumed") {
|
|
@@ -111,11 +146,11 @@ export async function runCommand(opts, childArgs) {
|
|
|
111
146
|
console.log("Run the command again to request access.\n");
|
|
112
147
|
process.exit(1);
|
|
113
148
|
}
|
|
114
|
-
console.log(`\n\n${pc.green("✓")} Access approved`);
|
|
149
|
+
console.log(`\n\n${pc.green("✓")} Access approved\n`);
|
|
115
150
|
}
|
|
116
151
|
}
|
|
117
|
-
console.log(`${pc.green("✓")} Environment ready\n`);
|
|
118
152
|
console.log("Loading protected environment...\n");
|
|
153
|
+
// Production always prompts; development also prompts (PEK cache is wrapped key only).
|
|
119
154
|
const password = await promptHidden("Vault password: ", {
|
|
120
155
|
allowStdin: opts.vaultPasswordStdin,
|
|
121
156
|
});
|
|
@@ -123,7 +158,7 @@ export async function runCommand(opts, childArgs) {
|
|
|
123
158
|
try {
|
|
124
159
|
bundle = await client.request("POST", `/api/cli/grants/secrets`, {
|
|
125
160
|
projectId: meta.projectId,
|
|
126
|
-
environmentId:
|
|
161
|
+
environmentId: envRow.id,
|
|
127
162
|
}, { "X-Getmyenv-Grant": grant.grantToken });
|
|
128
163
|
}
|
|
129
164
|
catch (err) {
|
|
@@ -135,17 +170,23 @@ export async function runCommand(opts, childArgs) {
|
|
|
135
170
|
}
|
|
136
171
|
let pek;
|
|
137
172
|
try {
|
|
138
|
-
pek = await
|
|
173
|
+
pek = await unwrapPek({
|
|
174
|
+
password,
|
|
175
|
+
scope: who.cliScope,
|
|
176
|
+
wrapped: bundle.wrappedProjectKey,
|
|
177
|
+
});
|
|
139
178
|
}
|
|
140
179
|
catch {
|
|
141
180
|
clearGrant(projectId, environmentId);
|
|
142
181
|
throw new Error("Could not decrypt secrets. Check your vault password.");
|
|
143
182
|
}
|
|
144
183
|
const env = { ...process.env };
|
|
184
|
+
const loadedNames = [];
|
|
145
185
|
for (const secret of bundle.secrets) {
|
|
146
186
|
env[secret.name] = decryptSecret(pek, parsePayload(secret.ciphertext));
|
|
187
|
+
loadedNames.push(secret.name);
|
|
147
188
|
}
|
|
148
|
-
console.log(`${pc.green("✓")}
|
|
189
|
+
console.log(`${pc.green("✓")} Loaded ${loadedNames.length} secret${loadedNames.length === 1 ? "" : "s"}: ${loadedNames.join(", ") || "(none)"}\n`);
|
|
149
190
|
console.log("Starting application...\n");
|
|
150
191
|
const [cmd, ...args] = childArgs;
|
|
151
192
|
const child = spawn(cmd, args, {
|