getmyenv 0.1.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 (71) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +13 -0
  3. package/dist/bin.d.ts +3 -0
  4. package/dist/bin.d.ts.map +1 -0
  5. package/dist/bin.js +9 -0
  6. package/dist/bin.js.map +1 -0
  7. package/dist/cli.d.ts +2 -0
  8. package/dist/cli.d.ts.map +1 -0
  9. package/dist/cli.js +105 -0
  10. package/dist/cli.js.map +1 -0
  11. package/dist/commands/add.d.ts +8 -0
  12. package/dist/commands/add.d.ts.map +1 -0
  13. package/dist/commands/add.js +64 -0
  14. package/dist/commands/add.js.map +1 -0
  15. package/dist/commands/backup.d.ts +7 -0
  16. package/dist/commands/backup.d.ts.map +1 -0
  17. package/dist/commands/backup.js +35 -0
  18. package/dist/commands/backup.js.map +1 -0
  19. package/dist/commands/export.d.ts +9 -0
  20. package/dist/commands/export.d.ts.map +1 -0
  21. package/dist/commands/export.js +48 -0
  22. package/dist/commands/export.js.map +1 -0
  23. package/dist/commands/init.d.ts +2 -0
  24. package/dist/commands/init.d.ts.map +1 -0
  25. package/dist/commands/init.js +58 -0
  26. package/dist/commands/init.js.map +1 -0
  27. package/dist/commands/login.d.ts +6 -0
  28. package/dist/commands/login.d.ts.map +1 -0
  29. package/dist/commands/login.js +35 -0
  30. package/dist/commands/login.js.map +1 -0
  31. package/dist/commands/logout.d.ts +2 -0
  32. package/dist/commands/logout.d.ts.map +1 -0
  33. package/dist/commands/logout.js +13 -0
  34. package/dist/commands/logout.js.map +1 -0
  35. package/dist/commands/migrate.d.ts +13 -0
  36. package/dist/commands/migrate.d.ts.map +1 -0
  37. package/dist/commands/migrate.js +127 -0
  38. package/dist/commands/migrate.js.map +1 -0
  39. package/dist/commands/restore.d.ts +8 -0
  40. package/dist/commands/restore.d.ts.map +1 -0
  41. package/dist/commands/restore.js +61 -0
  42. package/dist/commands/restore.js.map +1 -0
  43. package/dist/commands/run.d.ts +8 -0
  44. package/dist/commands/run.d.ts.map +1 -0
  45. package/dist/commands/run.js +164 -0
  46. package/dist/commands/run.js.map +1 -0
  47. package/dist/commands/status.d.ts +7 -0
  48. package/dist/commands/status.d.ts.map +1 -0
  49. package/dist/commands/status.js +76 -0
  50. package/dist/commands/status.js.map +1 -0
  51. package/dist/lib/api.d.ts +27 -0
  52. package/dist/lib/api.d.ts.map +1 -0
  53. package/dist/lib/api.js +97 -0
  54. package/dist/lib/api.js.map +1 -0
  55. package/dist/lib/credentials.d.ts +9 -0
  56. package/dist/lib/credentials.d.ts.map +1 -0
  57. package/dist/lib/credentials.js +46 -0
  58. package/dist/lib/credentials.js.map +1 -0
  59. package/dist/lib/env-name.d.ts +3 -0
  60. package/dist/lib/env-name.d.ts.map +1 -0
  61. package/dist/lib/env-name.js +5 -0
  62. package/dist/lib/env-name.js.map +1 -0
  63. package/dist/lib/fs.d.ts +56 -0
  64. package/dist/lib/fs.d.ts.map +1 -0
  65. package/dist/lib/fs.js +501 -0
  66. package/dist/lib/fs.js.map +1 -0
  67. package/dist/lib/identity.d.ts +12 -0
  68. package/dist/lib/identity.d.ts.map +1 -0
  69. package/dist/lib/identity.js +38 -0
  70. package/dist/lib/identity.js.map +1 -0
  71. package/package.json +58 -0
@@ -0,0 +1,127 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import pc from "picocolors";
4
+ import { createWrappedProjectKey, encryptSecret, serializePayload, serializeWrappedKey, } from "@getmyenv/crypto";
5
+ import { detectLanguages, ensureGitignoreHasEnv, envReadSnippet, inferEnvNameFromFile, isEnvSampleFile, listEnvFiles, parseEnvFile, promptChoice, promptConfirm, promptHidden, readProjectMeta, writeProjectMeta, } from "../lib/fs.js";
6
+ import { ApiClient, ensureSessionToken, resolveApiUrl } from "../lib/api.js";
7
+ async function resolveEnvPath(file) {
8
+ if (file) {
9
+ const resolved = path.resolve(process.cwd(), file);
10
+ if (!fs.existsSync(resolved)) {
11
+ throw new Error(`Env file not found: ${file}`);
12
+ }
13
+ return resolved;
14
+ }
15
+ const candidates = listEnvFiles();
16
+ if (candidates.length === 0) {
17
+ throw new Error("No .env* files found under this folder (including .example / .sample). Pass --file <path> or create one first.");
18
+ }
19
+ const labels = candidates.map((p) => path.relative(process.cwd(), p) || p);
20
+ if (candidates.length === 1) {
21
+ console.log(`Using ${labels[0]}\n`);
22
+ return candidates[0];
23
+ }
24
+ if (!process.stdin.isTTY) {
25
+ throw new Error(`Multiple env files found. Pass --file <path>:\n${labels.map((l) => ` ${l}`).join("\n")}`);
26
+ }
27
+ console.log("Found env files:\n");
28
+ const idx = await promptChoice("Migrate which file?", labels, 0);
29
+ console.log("");
30
+ return candidates[idx];
31
+ }
32
+ export async function migrateCommand(opts) {
33
+ console.log(pc.bold("\ngetmyenv migrate\n"));
34
+ const envPath = await resolveEnvPath(opts.file);
35
+ const baseName = path.basename(envPath);
36
+ const rel = path.relative(process.cwd(), envPath) || baseName;
37
+ let environment = opts.env;
38
+ if (opts.envWasDefault !== false && opts.env === "development") {
39
+ environment = inferEnvNameFromFile(envPath);
40
+ }
41
+ if (isEnvSampleFile(envPath)) {
42
+ console.log(pc.dim("This looks like a repo sample file. Values may be placeholders.\n"));
43
+ }
44
+ const pairs = parseEnvFile(envPath);
45
+ const keys = Object.keys(pairs);
46
+ if (keys.length === 0) {
47
+ throw new Error(`No variables found in ${rel}`);
48
+ }
49
+ console.log(`Found ${keys.length} variables in ${rel}:\n`);
50
+ for (const k of keys) {
51
+ console.log(` ${pc.green("✓")} ${k}`);
52
+ }
53
+ console.log("");
54
+ console.log(pc.dim(`Environment: ${environment}\n`));
55
+ const password = await promptHidden("Vault password (used for local encryption): ", { allowStdin: opts.vaultPasswordStdin });
56
+ if (password.length < 12 || !/[a-zA-Z]/.test(password) || !/\d/.test(password)) {
57
+ throw new Error("Vault password must be at least 12 characters and include a letter and a number");
58
+ }
59
+ if (!opts.vaultPasswordStdin) {
60
+ const confirm = await promptHidden("Confirm vault password: ");
61
+ if (password !== confirm) {
62
+ throw new Error("Passwords do not match");
63
+ }
64
+ }
65
+ console.log("\nEncrypting locally...\n");
66
+ const { pek, wrapped } = await createWrappedProjectKey(password);
67
+ const encrypted = keys.map((name) => ({
68
+ name,
69
+ ciphertext: serializePayload(encryptSecret(pek, pairs[name])),
70
+ }));
71
+ for (const item of encrypted) {
72
+ console.log(` ${pc.green("✓")} ${item.name}`);
73
+ }
74
+ console.log(`\n${pc.green("✓")} Encrypted locally`);
75
+ const token = await ensureSessionToken();
76
+ const meta = readProjectMeta() ?? {};
77
+ const client = new ApiClient(opts.apiUrl, token);
78
+ const result = await client.request("POST", "/api/cli/migrate", {
79
+ environment,
80
+ wrappedProjectKey: JSON.parse(serializeWrappedKey(wrapped)),
81
+ secrets: encrypted,
82
+ projectName: meta.projectName,
83
+ });
84
+ writeProjectMeta({
85
+ ...meta,
86
+ projectId: result.projectId,
87
+ projectName: result.projectName,
88
+ protectionMode: "advanced",
89
+ apiUrl: opts.apiUrl,
90
+ });
91
+ console.log(`${pc.green("✓")} Uploaded securely\n`);
92
+ ensureGitignoreHasEnv();
93
+ console.log(`${pc.green("✓")} Ensured .env is in .gitignore\n`);
94
+ const sample = keys[0] ?? "MY_SECRET";
95
+ const languages = detectLanguages();
96
+ const primary = languages[0]?.language ?? null;
97
+ console.log("Your application still reads it from the environment:\n");
98
+ if (languages.length > 1) {
99
+ for (const lang of languages.slice(0, 4)) {
100
+ console.log(pc.cyan(` ${lang.label}: ${envReadSnippet(lang.language, sample)}`));
101
+ }
102
+ }
103
+ else {
104
+ console.log(pc.cyan(` ${envReadSnippet(primary, sample)}`));
105
+ }
106
+ console.log("");
107
+ const migratedName = `${baseName}.migrated.local`;
108
+ const remove = await promptConfirm(`Rename plaintext ${baseName} to ${migratedName}? (never deleted silently)`);
109
+ if (remove) {
110
+ const dest = envPath + ".migrated.local";
111
+ fs.renameSync(envPath, dest);
112
+ console.log(`${pc.green("✓")} Renamed to ${path.basename(dest)}`);
113
+ }
114
+ else {
115
+ console.log(pc.dim(`Kept plaintext ${baseName} in place.`));
116
+ }
117
+ console.log("");
118
+ }
119
+ /** Shared entry for login → migrate offer. */
120
+ export async function runMigrateFromLogin(apiUrl) {
121
+ await migrateCommand({
122
+ env: "development",
123
+ envWasDefault: true,
124
+ apiUrl: resolveApiUrl(apiUrl),
125
+ });
126
+ }
127
+ //# sourceMappingURL=migrate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"migrate.js","sourceRoot":"","sources":["../../src/commands/migrate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ type RestoreOpts = {
2
+ apiUrl: string;
3
+ intoLinked?: boolean;
4
+ vaultPasswordStdin?: boolean;
5
+ };
6
+ export declare function restoreCommand(file: string, opts: RestoreOpts): Promise<void>;
7
+ export {};
8
+ //# sourceMappingURL=restore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"restore.d.ts","sourceRoot":"","sources":["../../src/commands/restore.ts"],"names":[],"mappings":"AAYA,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,CAqEf"}
@@ -0,0 +1,61 @@
1
+ import fs from "node:fs";
2
+ import pc from "picocolors";
3
+ import { parseBackup, restoreSecretsFromBackup } from "@getmyenv/crypto";
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";
7
+ export async function restoreCommand(file, opts) {
8
+ console.log(pc.bold("\ngetmyenv restore\n"));
9
+ if (!fs.existsSync(file))
10
+ throw new Error(`File not found: ${file}`);
11
+ const envelope = parseBackup(fs.readFileSync(file, "utf8"));
12
+ const password = await promptHidden("Vault password for this backup: ", {
13
+ allowStdin: opts.vaultPasswordStdin,
14
+ });
15
+ // Verify decryption works offline first
16
+ const restored = await restoreSecretsFromBackup(password, envelope);
17
+ console.log(`Verified ${restored.length} secrets from backup (offline).\n`);
18
+ const token = await ensureSessionToken();
19
+ const meta = readProjectMeta();
20
+ // Re-encrypt under a fresh wrapped key for upload (same password)
21
+ const { pek, wrapped } = await createWrappedProjectKey(password);
22
+ const secrets = restored.map((s) => {
23
+ if (s.status === "placeholder") {
24
+ return {
25
+ name: s.name,
26
+ environment: s.environment,
27
+ status: "placeholder",
28
+ expiresAt: s.expiresAt,
29
+ ciphertext: null,
30
+ };
31
+ }
32
+ return {
33
+ name: s.name,
34
+ environment: s.environment,
35
+ status: s.status,
36
+ expiresAt: s.expiresAt,
37
+ ciphertext: serializePayload(encryptSecret(pek, s.value)),
38
+ };
39
+ });
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
+ const result = await client.request("POST", "/api/cli/restore", {
46
+ projectName: envelope.projectName,
47
+ projectId: intoLinked ? meta?.projectId : undefined,
48
+ wrappedProjectKey: JSON.parse(serializeWrappedKey(wrapped)),
49
+ secrets,
50
+ });
51
+ writeProjectMeta({
52
+ ...(meta ?? {}),
53
+ projectId: result.projectId,
54
+ projectName: result.projectName,
55
+ protectionMode: "advanced",
56
+ apiUrl: opts.apiUrl,
57
+ });
58
+ console.log(`${pc.green("✓")} Restored encrypted secrets to getmyenv` +
59
+ (intoLinked ? " (linked project)\n" : ` as "${result.projectName}"\n`));
60
+ }
61
+ //# sourceMappingURL=restore.js.map
@@ -0,0 +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,EAAE,WAAW,EAAE,wBAAwB,EAAE,MAAM,kBAAkB,CAAC;AACzE,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAC/E,OAAO,EAAE,SAAS,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAC;AAC9D,OAAO,EACL,uBAAuB,EACvB,aAAa,EACb,gBAAgB,EAChB,mBAAmB,GACpB,MAAM,kBAAkB,CAAC;AAQ1B,MAAM,CAAC,KAAK,UAAU,cAAc,CAClC,IAAY,EACZ,IAAiB;IAEjB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC,CAAC;IAC7C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,mBAAmB,IAAI,EAAE,CAAC,CAAC;IAErE,MAAM,QAAQ,GAAG,WAAW,CAAC,EAAE,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;IAC5D,MAAM,QAAQ,GAAG,MAAM,YAAY,CAAC,kCAAkC,EAAE;QACtE,UAAU,EAAE,IAAI,CAAC,kBAAkB;KACpC,CAAC,CAAC;IAEH,wCAAwC;IACxC,MAAM,QAAQ,GAAG,MAAM,wBAAwB,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;IACpE,OAAO,CAAC,GAAG,CAAC,YAAY,QAAQ,CAAC,MAAM,mCAAmC,CAAC,CAAC;IAE5E,MAAM,KAAK,GAAG,MAAM,kBAAkB,EAAE,CAAC;IACzC,MAAM,IAAI,GAAG,eAAe,EAAE,CAAC;IAE/B,kEAAkE;IAClE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,MAAM,uBAAuB,CAAC,QAAQ,CAAC,CAAC;IACjE,MAAM,OAAO,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QACjC,IAAI,CAAC,CAAC,MAAM,KAAK,aAAa,EAAE,CAAC;YAC/B,OAAO;gBACL,IAAI,EAAE,CAAC,CAAC,IAAI;gBACZ,WAAW,EAAE,CAAC,CAAC,WAAW;gBAC1B,MAAM,EAAE,aAAsB;gBAC9B,SAAS,EAAE,CAAC,CAAC,SAAS;gBACtB,UAAU,EAAE,IAAI;aACjB,CAAC;QACJ,CAAC;QACD,OAAO;YACL,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,WAAW,EAAE,CAAC,CAAC,WAAW;YAC1B,MAAM,EAAE,CAAC,CAAC,MAAM;YAChB,SAAS,EAAE,CAAC,CAAC,SAAS;YACtB,UAAU,EAAE,gBAAgB,CAAC,aAAa,CAAC,GAAG,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC;SAC1D,CAAC;IACJ,CAAC,CAAC,CAAC;IAEH,MAAM,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,UAAU,IAAI,IAAI,EAAE,SAAS,CAAC,CAAC;IAC/D,IAAI,IAAI,EAAE,SAAS,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;QACxC,OAAO,CAAC,GAAG,CACT,EAAE,CAAC,GAAG,CACJ,yFAAyF,CAC1F,CACF,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IACjD,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,OAAO,CAGhC,MAAM,EAAE,kBAAkB,EAAE;QAC7B,WAAW,EAAE,QAAQ,CAAC,WAAW;QACjC,SAAS,EAAE,UAAU,CAAC,CAAC,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAC,SAAS;QACnD,iBAAiB,EAAE,IAAI,CAAC,KAAK,CAAC,mBAAmB,CAAC,OAAO,CAAC,CAAC;QAC3D,OAAO;KACR,CAAC,CAAC;IAEH,gBAAgB,CAAC;QACf,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC;QACf,SAAS,EAAE,MAAM,CAAC,SAAS;QAC3B,WAAW,EAAE,MAAM,CAAC,WAAW;QAC/B,cAAc,EAAE,UAAU;QAC1B,MAAM,EAAE,IAAI,CAAC,MAAM;KACpB,CAAC,CAAC;IAEH,OAAO,CAAC,GAAG,CACT,GAAG,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,yCAAyC;QACvD,CAAC,UAAU,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,QAAQ,MAAM,CAAC,WAAW,KAAK,CAAC,CACzE,CAAC;AACJ,CAAC"}
@@ -0,0 +1,8 @@
1
+ type RunOpts = {
2
+ env: string;
3
+ apiUrl: string;
4
+ vaultPasswordStdin?: boolean;
5
+ };
6
+ export declare function runCommand(opts: RunOpts, childArgs: string[]): Promise<void>;
7
+ export {};
8
+ //# sourceMappingURL=run.d.ts.map
@@ -0,0 +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;CAC9B,CAAC;AAEF,wBAAsB,UAAU,CAC9B,IAAI,EAAE,OAAO,EACb,SAAS,EAAE,MAAM,EAAE,GAClB,OAAO,CAAC,IAAI,CAAC,CAwNf"}
@@ -0,0 +1,164 @@
1
+ import { spawn } from "node:child_process";
2
+ import pc from "picocolors";
3
+ import { decryptSecret, parsePayload, parseWrappedKey, signAccessRequest, unwrapProjectKey, } from "@getmyenv/crypto";
4
+ import { promptHidden, readProjectMeta, readRequirements, } from "../lib/fs.js";
5
+ import { ApiClient, ensureSessionToken } from "../lib/api.js";
6
+ import { clearGrant, loadGrant, loadOrCreateIdentity, saveGrant, } from "../lib/identity.js";
7
+ export async function runCommand(opts, childArgs) {
8
+ if (childArgs.length === 0) {
9
+ throw new Error("Usage: npx getmyenv run -- <command>");
10
+ }
11
+ console.log(pc.bold("\ngetmyenv\n"));
12
+ const meta = readProjectMeta();
13
+ if (!meta?.projectId) {
14
+ throw new Error("Link a project (migrate) before running with protected secrets.");
15
+ }
16
+ const token = await ensureSessionToken();
17
+ const client = new ApiClient(opts.apiUrl, token);
18
+ const requestedSecretNames = readRequirements();
19
+ const envInfo = await client.request("GET", `/api/cli/projects/${meta.projectId}`);
20
+ const environment = envInfo.environments.find((e) => e.name.toLowerCase() === opts.env.toLowerCase());
21
+ if (!environment) {
22
+ throw new Error(`Environment not found: ${opts.env}`);
23
+ }
24
+ const environmentId = String(environment.id);
25
+ const projectId = String(meta.projectId);
26
+ let grant = loadGrant(projectId, environmentId);
27
+ if (!grant) {
28
+ 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
+ const timestamp = String(Date.now());
33
+ const message = [
34
+ projectId,
35
+ environmentId,
36
+ identity.publicKey,
37
+ timestamp,
38
+ ].join(":");
39
+ const signature = signAccessRequest(identity.privateKey, message);
40
+ let request;
41
+ try {
42
+ request = await client.request("POST", "/api/cli/requests", {
43
+ projectId: meta.projectId,
44
+ environmentId: environment.id,
45
+ identityPublicKey: identity.publicKey,
46
+ identityLabel: process.env.GETMYENV_MACHINE_LABEL ??
47
+ `${process.env.USERNAME ?? process.env.USER ?? "dev"}'s development environment`,
48
+ signature,
49
+ message,
50
+ timestamp,
51
+ requestedSecretNames: requestedSecretNames.length > 0 ? requestedSecretNames : undefined,
52
+ });
53
+ }
54
+ catch (err) {
55
+ const msg = err instanceof Error ? err.message : String(err);
56
+ if (/access requests are disabled/i.test(msg)) {
57
+ 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
+ process.exit(1);
60
+ }
61
+ throw err;
62
+ }
63
+ if (request.status === "approved" &&
64
+ request.grantToken &&
65
+ request.grantExpiresAt) {
66
+ grant = {
67
+ grantToken: request.grantToken,
68
+ expiresAt: request.grantExpiresAt,
69
+ projectId,
70
+ environmentId,
71
+ };
72
+ saveGrant(grant);
73
+ console.log(`${pc.green("✓")} Trusted device - access granted\n`);
74
+ }
75
+ else {
76
+ console.log("\nA dashboard approval is required.\n");
77
+ console.log("Open getmyenv to approve access.\n");
78
+ console.log(pc.dim("Tip: choose Trust this device to skip approval next time on this machine.\n"));
79
+ console.log(pc.dim("Waiting..."));
80
+ const deadline = new Date(request.expiresAt).getTime();
81
+ let approved = false;
82
+ while (Date.now() < deadline) {
83
+ const remaining = Math.max(0, Math.ceil((deadline - Date.now()) / 1000));
84
+ process.stdout.write(`\r${pc.dim(`Waiting... ${String(remaining).padStart(2, "0")}s`)} `);
85
+ await sleep(1500);
86
+ const status = await client.request("GET", `/api/cli/requests/${request.id}`);
87
+ if (status.status === "approved" &&
88
+ status.grantToken &&
89
+ status.grantExpiresAt) {
90
+ grant = {
91
+ grantToken: status.grantToken,
92
+ expiresAt: status.grantExpiresAt,
93
+ projectId,
94
+ environmentId,
95
+ };
96
+ saveGrant(grant);
97
+ approved = true;
98
+ break;
99
+ }
100
+ if (status.status === "denied") {
101
+ console.log(`\n\n${pc.red("✗")} Access denied\n`);
102
+ console.log("The application was not started.\n");
103
+ process.exit(1);
104
+ }
105
+ if (status.status === "expired" || status.status === "consumed") {
106
+ break;
107
+ }
108
+ }
109
+ if (!approved || !grant) {
110
+ console.log(`\n\n${pc.red("✗")} Approval request expired\n`);
111
+ console.log("Run the command again to request access.\n");
112
+ process.exit(1);
113
+ }
114
+ console.log(`\n\n${pc.green("✓")} Access approved`);
115
+ }
116
+ }
117
+ console.log(`${pc.green("✓")} Environment ready\n`);
118
+ console.log("Loading protected environment...\n");
119
+ const password = await promptHidden("Vault password: ", {
120
+ allowStdin: opts.vaultPasswordStdin,
121
+ });
122
+ let bundle;
123
+ try {
124
+ bundle = await client.request("POST", `/api/cli/grants/secrets`, {
125
+ projectId: meta.projectId,
126
+ environmentId: environment.id,
127
+ }, { "X-Getmyenv-Grant": grant.grantToken });
128
+ }
129
+ catch (err) {
130
+ const msg = err instanceof Error ? err.message : String(err);
131
+ if (/grant already used|invalid grant|grant expired/i.test(msg)) {
132
+ clearGrant(projectId, environmentId);
133
+ }
134
+ throw err;
135
+ }
136
+ let pek;
137
+ try {
138
+ pek = await unwrapProjectKey(password, parseWrappedKey(JSON.stringify(bundle.wrappedProjectKey)));
139
+ }
140
+ catch {
141
+ clearGrant(projectId, environmentId);
142
+ throw new Error("Could not decrypt secrets. Check your vault password.");
143
+ }
144
+ const env = { ...process.env };
145
+ for (const secret of bundle.secrets) {
146
+ env[secret.name] = decryptSecret(pek, parsePayload(secret.ciphertext));
147
+ }
148
+ console.log(`${pc.green("✓")} Protected environment ready\n`);
149
+ console.log("Starting application...\n");
150
+ const [cmd, ...args] = childArgs;
151
+ const child = spawn(cmd, args, {
152
+ env,
153
+ stdio: "inherit",
154
+ shell: process.platform === "win32",
155
+ });
156
+ const code = await new Promise((resolve) => {
157
+ child.on("exit", (c) => resolve(c ?? 1));
158
+ });
159
+ process.exit(code);
160
+ }
161
+ function sleep(ms) {
162
+ return new Promise((r) => setTimeout(r, ms));
163
+ }
164
+ //# sourceMappingURL=run.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"run.js","sourceRoot":"","sources":["../../src/commands/run.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ type StatusOpts = {
2
+ env: string;
3
+ apiUrl: string;
4
+ };
5
+ export declare function statusCommand(opts: StatusOpts): Promise<void>;
6
+ export {};
7
+ //# sourceMappingURL=status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAQA,KAAK,UAAU,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAC;AAmBlD,wBAAsB,aAAa,CAAC,IAAI,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAyEnE"}
@@ -0,0 +1,76 @@
1
+ import pc from "picocolors";
2
+ import { getSecretPresentationStatus, } from "@getmyenv/shared";
3
+ import { readProjectMeta, readRequirements } from "../lib/fs.js";
4
+ import { ApiClient, ensureSessionToken } from "../lib/api.js";
5
+ function icon(status) {
6
+ switch (status) {
7
+ case "active":
8
+ return pc.green("✓");
9
+ case "expiring_soon":
10
+ return pc.yellow("!");
11
+ case "expired":
12
+ return pc.red("✗");
13
+ case "revoked":
14
+ return pc.red("✗");
15
+ case "placeholder":
16
+ return pc.yellow("?");
17
+ case "missing":
18
+ return pc.red("✗");
19
+ }
20
+ }
21
+ export async function statusCommand(opts) {
22
+ console.log(pc.bold(`\n${opts.env}\n`));
23
+ const required = readRequirements();
24
+ const meta = readProjectMeta();
25
+ if (!meta?.projectId) {
26
+ if (required.length === 0) {
27
+ console.log(pc.dim("Run npx getmyenv init first.\n"));
28
+ return;
29
+ }
30
+ for (const name of required) {
31
+ console.log(` ${pc.yellow("?")} ${name}`);
32
+ console.log(pc.dim(" Not synced (run migrate to link a project)"));
33
+ }
34
+ console.log("");
35
+ return;
36
+ }
37
+ const token = await ensureSessionToken();
38
+ const client = new ApiClient(opts.apiUrl, token);
39
+ const data = await client.request("GET", `/api/cli/projects/${meta.projectId}/secrets?environment=${encodeURIComponent(opts.env)}`);
40
+ const byName = new Map(data.secrets.map((s) => [s.name, s]));
41
+ const names = required.length
42
+ ? required
43
+ : data.secrets.map((s) => s.name).sort();
44
+ for (const name of names) {
45
+ const secret = byName.get(name);
46
+ if (!secret) {
47
+ console.log(` ${icon("missing")} ${name}`);
48
+ console.log(pc.dim(" Missing"));
49
+ continue;
50
+ }
51
+ const hasValue = secret.hasValue ??
52
+ (secret.status !== "placeholder");
53
+ if (!hasValue || secret.status === "placeholder") {
54
+ console.log(` ${icon("placeholder")} ${name}`);
55
+ console.log(pc.dim(" Placeholder - no value yet"));
56
+ continue;
57
+ }
58
+ const presentation = getSecretPresentationStatus({
59
+ status: secret.status,
60
+ expiresAt: secret.expiresAt,
61
+ ciphertext: "present",
62
+ });
63
+ console.log(` ${icon(presentation)} ${name}`);
64
+ if (presentation === "expiring_soon") {
65
+ console.log(pc.yellow(" Expiring soon"));
66
+ }
67
+ else if (presentation === "expired") {
68
+ console.log(pc.red(" Expired - getmyenv will no longer provide this secret"));
69
+ }
70
+ else if (presentation === "revoked") {
71
+ console.log(pc.red(" Revoked - getmyenv will no longer provide this secret (external credential unchanged)"));
72
+ }
73
+ }
74
+ console.log("");
75
+ }
76
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * CLI API client. Never logs response bodies that may contain ciphertext details
3
+ * beyond what is needed; never prints secret plaintext.
4
+ */
5
+ import { clearCredentials, credentialsFilePath, readCredentials, writeCredentials } from "./credentials.js";
6
+ /** Keep in sync with packages/cli/package.json version. */
7
+ export declare const CLI_VERSION = "0.1.1";
8
+ /** Resolve API base: env → saved credentials → production. */
9
+ export declare function resolveApiUrl(cliOverride?: string): string;
10
+ /** @deprecated Use resolveApiUrl() - kept for callers that read at module load. */
11
+ export declare const API_URL_DEFAULT: string;
12
+ export declare class ApiClient {
13
+ private baseUrl;
14
+ private token?;
15
+ constructor(baseUrl: string, token?: string | undefined);
16
+ private headers;
17
+ request<T>(method: string, path: string, body?: unknown, extraHeaders?: Record<string, string>): Promise<T>;
18
+ }
19
+ /** Env only (no prompt). Prefer ensureSessionToken for interactive commands. */
20
+ export declare function getSessionToken(): string | undefined;
21
+ /**
22
+ * Env → credentials file → interactive paste (TTY) saved for next time.
23
+ * Non-TTY without a token throws with login instructions.
24
+ */
25
+ export declare function ensureSessionToken(): Promise<string>;
26
+ export { clearCredentials, credentialsFilePath, writeCredentials, readCredentials };
27
+ //# sourceMappingURL=api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/lib/api.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,OAAO,EACL,gBAAgB,EAChB,mBAAmB,EACnB,eAAe,EACf,gBAAgB,EACjB,MAAM,kBAAkB,CAAC;AAE1B,2DAA2D;AAC3D,eAAO,MAAM,WAAW,UAAU,CAAC;AAInC,8DAA8D;AAC9D,wBAAgB,aAAa,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,MAAM,CAQ1D;AAED,mFAAmF;AACnF,eAAO,MAAM,eAAe,QAAkB,CAAC;AAE/C,qBAAa,SAAS;IAElB,OAAO,CAAC,OAAO;IACf,OAAO,CAAC,KAAK,CAAC;gBADN,OAAO,EAAE,MAAM,EACf,KAAK,CAAC,EAAE,MAAM,YAAA;IAGxB,OAAO,CAAC,OAAO;IAWT,OAAO,CAAC,CAAC,EACb,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,IAAI,CAAC,EAAE,OAAO,EACd,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GACpC,OAAO,CAAC,CAAC,CAAC;CAmBd;AAED,gFAAgF;AAChF,wBAAgB,eAAe,IAAI,MAAM,GAAG,SAAS,CAIpD;AAED;;;GAGG;AACH,wBAAsB,kBAAkB,IAAI,OAAO,CAAC,MAAM,CAAC,CA4B1D;AAED,OAAO,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,eAAe,EAAE,CAAC"}
@@ -0,0 +1,97 @@
1
+ /**
2
+ * CLI API client. Never logs response bodies that may contain ciphertext details
3
+ * beyond what is needed; never prints secret plaintext.
4
+ */
5
+ import pc from "picocolors";
6
+ import { promptHidden } from "./fs.js";
7
+ import { clearCredentials, credentialsFilePath, readCredentials, writeCredentials, } from "./credentials.js";
8
+ /** Keep in sync with packages/cli/package.json version. */
9
+ export const CLI_VERSION = "0.1.1";
10
+ const PRODUCTION_API = "https://getmyenv.com";
11
+ /** Resolve API base: env → saved credentials → production. */
12
+ export function resolveApiUrl(cliOverride) {
13
+ if (cliOverride?.trim())
14
+ return cliOverride.trim();
15
+ if (process.env.GETMYENV_API_URL?.trim()) {
16
+ return process.env.GETMYENV_API_URL.trim();
17
+ }
18
+ const saved = readCredentials()?.apiUrl;
19
+ if (saved)
20
+ return saved;
21
+ return PRODUCTION_API;
22
+ }
23
+ /** @deprecated Use resolveApiUrl() - kept for callers that read at module load. */
24
+ export const API_URL_DEFAULT = resolveApiUrl();
25
+ export class ApiClient {
26
+ baseUrl;
27
+ token;
28
+ constructor(baseUrl, token) {
29
+ this.baseUrl = baseUrl;
30
+ this.token = token;
31
+ }
32
+ headers(extra) {
33
+ const h = {
34
+ "Content-Type": "application/json",
35
+ Accept: "application/json",
36
+ "X-Getmyenv-CLI-Version": CLI_VERSION,
37
+ ...extra,
38
+ };
39
+ if (this.token)
40
+ h.Authorization = `Bearer ${this.token}`;
41
+ return h;
42
+ }
43
+ async request(method, path, body, extraHeaders) {
44
+ const res = await fetch(`${this.baseUrl.replace(/\/$/, "")}${path}`, {
45
+ method,
46
+ headers: this.headers(extraHeaders),
47
+ body: body === undefined ? undefined : JSON.stringify(body),
48
+ });
49
+ if (!res.ok) {
50
+ let message = `HTTP ${res.status}`;
51
+ try {
52
+ const data = (await res.json());
53
+ if (data.error)
54
+ message = data.error;
55
+ }
56
+ catch {
57
+ /* ignore */
58
+ }
59
+ throw new Error(message);
60
+ }
61
+ if (res.status === 204)
62
+ return undefined;
63
+ return (await res.json());
64
+ }
65
+ }
66
+ /** Env only (no prompt). Prefer ensureSessionToken for interactive commands. */
67
+ export function getSessionToken() {
68
+ const fromEnv = process.env.GETMYENV_TOKEN?.trim();
69
+ if (fromEnv)
70
+ return fromEnv;
71
+ return readCredentials()?.token;
72
+ }
73
+ /**
74
+ * Env → credentials file → interactive paste (TTY) saved for next time.
75
+ * Non-TTY without a token throws with login instructions.
76
+ */
77
+ export async function ensureSessionToken() {
78
+ const existing = getSessionToken();
79
+ if (existing)
80
+ return existing;
81
+ if (!process.stdin.isTTY) {
82
+ throw new Error("No CLI token. Run: npx getmyenv login (or set GETMYENV_TOKEN for CI)");
83
+ }
84
+ console.log(pc.dim("Create a token at https://getmyenv.com/cli (or your local /cli), then paste it."));
85
+ const token = (await promptHidden("Paste CLI token: ")).trim();
86
+ if (!token) {
87
+ throw new Error("No token entered. Run: npx getmyenv login");
88
+ }
89
+ const file = writeCredentials({
90
+ token,
91
+ apiUrl: readCredentials()?.apiUrl,
92
+ });
93
+ console.log(`${pc.green("✓")} Saved CLI token to ${file}\n`);
94
+ return token;
95
+ }
96
+ export { clearCredentials, credentialsFilePath, writeCredentials, readCredentials };
97
+ //# sourceMappingURL=api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/lib/api.ts"],"names":[],"mappings":"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"}