ultraenv 1.0.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 (89) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +2058 -0
  3. package/bin/ultraenv.mjs +3 -0
  4. package/dist/chunk-2USZPWLZ.js +288 -0
  5. package/dist/chunk-3UV2QNJL.js +270 -0
  6. package/dist/chunk-3VYXPTYV.js +179 -0
  7. package/dist/chunk-4XUYMRK5.js +366 -0
  8. package/dist/chunk-5G2DU52U.js +189 -0
  9. package/dist/chunk-6KS56D6E.js +172 -0
  10. package/dist/chunk-AWN6ADV7.js +328 -0
  11. package/dist/chunk-CHVO6NWI.js +203 -0
  12. package/dist/chunk-CIFMBJ4H.js +3975 -0
  13. package/dist/chunk-GC7RXHLA.js +253 -0
  14. package/dist/chunk-HFXQGJY3.js +445 -0
  15. package/dist/chunk-IGFVP24Q.js +91 -0
  16. package/dist/chunk-IKPTKALB.js +78 -0
  17. package/dist/chunk-JB7RKV3C.js +66 -0
  18. package/dist/chunk-MNVFG7H4.js +611 -0
  19. package/dist/chunk-MSXMESFP.js +1910 -0
  20. package/dist/chunk-N5PAV4NM.js +127 -0
  21. package/dist/chunk-NBOABPHM.js +158 -0
  22. package/dist/chunk-OMAOROL4.js +49 -0
  23. package/dist/chunk-R7PZRSZ7.js +105 -0
  24. package/dist/chunk-TE7HPLA6.js +73 -0
  25. package/dist/chunk-TMT5KCO3.js +101 -0
  26. package/dist/chunk-UEWYFN6A.js +189 -0
  27. package/dist/chunk-WMHN5RW2.js +128 -0
  28. package/dist/chunk-XC65ORJ5.js +70 -0
  29. package/dist/chunk-YMMP4VQL.js +118 -0
  30. package/dist/chunk-YN2KGTCB.js +33 -0
  31. package/dist/chunk-YTICOB5M.js +65 -0
  32. package/dist/chunk-YVWLXFUT.js +107 -0
  33. package/dist/ci-check-sync-VBMSVWIV.js +48 -0
  34. package/dist/ci-scan-24MT5XGS.js +41 -0
  35. package/dist/ci-setup-C2NKEFRD.js +135 -0
  36. package/dist/ci-validate-7AW24LSQ.js +57 -0
  37. package/dist/cli/index.cjs +9217 -0
  38. package/dist/cli/index.d.cts +9 -0
  39. package/dist/cli/index.d.ts +9 -0
  40. package/dist/cli/index.js +339 -0
  41. package/dist/comparator-RDKX3OI7.js +13 -0
  42. package/dist/completion-MW35C2XO.js +168 -0
  43. package/dist/config-O5YRQP5Z.js +13 -0
  44. package/dist/debug-PTPXAF3K.js +131 -0
  45. package/dist/declaration-LEME4AFZ.js +10 -0
  46. package/dist/doctor-FZAUPKHS.js +129 -0
  47. package/dist/envs-compare-5K3HESX5.js +49 -0
  48. package/dist/envs-create-2XXHXMGA.js +58 -0
  49. package/dist/envs-list-NQM5252B.js +59 -0
  50. package/dist/envs-switch-6L2AQYID.js +50 -0
  51. package/dist/envs-validate-FL73Q76T.js +89 -0
  52. package/dist/fs-VH7ATUS3.js +31 -0
  53. package/dist/generator-LFZBMZZS.js +14 -0
  54. package/dist/git-BZS4DPAI.js +30 -0
  55. package/dist/help-3XJBXEHE.js +121 -0
  56. package/dist/index.cjs +12907 -0
  57. package/dist/index.d.cts +2562 -0
  58. package/dist/index.d.ts +2562 -0
  59. package/dist/index.js +3212 -0
  60. package/dist/init-Y7JQ2KYJ.js +146 -0
  61. package/dist/install-hook-SKXIV6NV.js +111 -0
  62. package/dist/json-schema-I26YNQBH.js +10 -0
  63. package/dist/key-manager-O3G55WPU.js +25 -0
  64. package/dist/middleware/express.cjs +103 -0
  65. package/dist/middleware/express.d.cts +115 -0
  66. package/dist/middleware/express.d.ts +115 -0
  67. package/dist/middleware/express.js +8 -0
  68. package/dist/middleware/fastify.cjs +91 -0
  69. package/dist/middleware/fastify.d.cts +111 -0
  70. package/dist/middleware/fastify.d.ts +111 -0
  71. package/dist/middleware/fastify.js +8 -0
  72. package/dist/module-IDIZPP4M.js +10 -0
  73. package/dist/protect-NCWPM6VC.js +161 -0
  74. package/dist/scan-TRLY36TT.js +58 -0
  75. package/dist/schema/index.cjs +4074 -0
  76. package/dist/schema/index.d.cts +1244 -0
  77. package/dist/schema/index.d.ts +1244 -0
  78. package/dist/schema/index.js +152 -0
  79. package/dist/sync-TMHMTLH2.js +186 -0
  80. package/dist/typegen-SQOSXBWM.js +80 -0
  81. package/dist/validate-IOAM5HWS.js +100 -0
  82. package/dist/vault-decrypt-U6HJZNBV.js +111 -0
  83. package/dist/vault-diff-B3ZOQTWI.js +132 -0
  84. package/dist/vault-encrypt-GUSLCSKS.js +112 -0
  85. package/dist/vault-init-GUBOTOUL.js +106 -0
  86. package/dist/vault-rekey-DAHT7JCN.js +132 -0
  87. package/dist/vault-status-GDLRU2OK.js +90 -0
  88. package/dist/vault-verify-CD76FJSF.js +102 -0
  89. package/package.json +106 -0
@@ -0,0 +1,132 @@
1
+ import {
2
+ readVaultFile
3
+ } from "./chunk-NBOABPHM.js";
4
+ import {
5
+ maskValue
6
+ } from "./chunk-TE7HPLA6.js";
7
+ import {
8
+ parseEnvFile
9
+ } from "./chunk-HFXQGJY3.js";
10
+ import {
11
+ bold,
12
+ cyan,
13
+ green,
14
+ red,
15
+ yellow
16
+ } from "./chunk-OMAOROL4.js";
17
+ import {
18
+ writeError,
19
+ writeLine
20
+ } from "./chunk-YN2KGTCB.js";
21
+ import {
22
+ exists,
23
+ readFile
24
+ } from "./chunk-3VYXPTYV.js";
25
+ import {
26
+ isEncryptedValue
27
+ } from "./chunk-2USZPWLZ.js";
28
+ import "./chunk-XC65ORJ5.js";
29
+ import "./chunk-5G2DU52U.js";
30
+
31
+ // src/cli/commands/vault-diff.ts
32
+ import { resolve, join } from "path";
33
+ async function run(args, ctx) {
34
+ try {
35
+ const cwd = args.flags["--cwd"] ?? ctx.cwd;
36
+ const baseDir = resolve(cwd);
37
+ const envName = args.flags["--env"] ?? "production";
38
+ writeLine(bold(`\u{1F4CA} Comparing .env.${envName} vs vault`));
39
+ writeLine("");
40
+ const vaultPath = join(baseDir, ".env.vault");
41
+ if (!await exists(vaultPath)) {
42
+ writeError(red(" .env.vault not found."));
43
+ return 1;
44
+ }
45
+ const vault = await readVaultFile(vaultPath);
46
+ const entry = vault.get(envName.toLowerCase());
47
+ if (!entry) {
48
+ writeError(red(` Environment "${envName}" not found in vault.`));
49
+ return 1;
50
+ }
51
+ const envPath = join(baseDir, `.env.${envName}`);
52
+ if (!await exists(envPath)) {
53
+ writeError(red(` .env.${envName} not found.`));
54
+ return 1;
55
+ }
56
+ const envContent = await readFile(envPath);
57
+ const parsed = parseEnvFile(envContent, envPath);
58
+ const vaultVars = {};
59
+ for (const line of entry.encrypted.split("\n")) {
60
+ const eqIdx = line.indexOf("=");
61
+ if (eqIdx === -1) continue;
62
+ const key = line.slice(0, eqIdx);
63
+ const value = line.slice(eqIdx + 1);
64
+ vaultVars[key] = value;
65
+ }
66
+ const envKeys = new Set(parsed.vars.map((v) => v.key));
67
+ const vaultKeys = new Set(Object.keys(vaultVars));
68
+ const onlyInEnv = [];
69
+ const onlyInVault = [];
70
+ const different = [];
71
+ const same = [];
72
+ for (const key of envKeys) {
73
+ if (!vaultKeys.has(key)) {
74
+ onlyInEnv.push(key);
75
+ }
76
+ }
77
+ for (const key of vaultKeys) {
78
+ if (!envKeys.has(key)) {
79
+ onlyInVault.push(key);
80
+ }
81
+ }
82
+ for (const key of envKeys) {
83
+ if (!vaultKeys.has(key)) continue;
84
+ const envVal = parsed.vars.find((v) => v.key === key)?.value ?? "";
85
+ const vaultVal = vaultVars[key] ?? "";
86
+ if (!isEncryptedValue(vaultVal) && envVal !== vaultVal) {
87
+ different.push(key);
88
+ } else if (isEncryptedValue(vaultVal)) {
89
+ same.push(key);
90
+ } else {
91
+ same.push(key);
92
+ }
93
+ }
94
+ if (onlyInEnv.length > 0) {
95
+ writeLine(yellow(` Only in .env (${onlyInEnv.length}):`));
96
+ for (const key of onlyInEnv) {
97
+ const val = parsed.vars.find((v) => v.key === key)?.value ?? "";
98
+ writeLine(` + ${key}=${maskValue(val)}`);
99
+ }
100
+ writeLine("");
101
+ }
102
+ if (onlyInVault.length > 0) {
103
+ writeLine(yellow(` Only in vault (${onlyInVault.length}):`));
104
+ for (const key of onlyInVault) {
105
+ writeLine(` - ${key}`);
106
+ }
107
+ writeLine("");
108
+ }
109
+ if (different.length > 0) {
110
+ writeLine(yellow(` Different (${different.length}):`));
111
+ for (const key of different) {
112
+ writeLine(` ~ ${key}`);
113
+ }
114
+ writeLine("");
115
+ }
116
+ if (onlyInEnv.length === 0 && onlyInVault.length === 0 && different.length === 0) {
117
+ writeLine(green(` \u2713 .env.${envName} and vault are in sync (${same.length} variables)`));
118
+ } else {
119
+ writeLine(cyan(` ${same.length} variable(s) matched.`));
120
+ writeLine(yellow(` Run "ultraenv vault encrypt --env ${envName}" to sync.`));
121
+ }
122
+ writeLine("");
123
+ return 0;
124
+ } catch (error) {
125
+ const msg = error instanceof Error ? error.message : String(error);
126
+ writeError(red(` Vault diff error: ${msg}`));
127
+ return 1;
128
+ }
129
+ }
130
+ export {
131
+ run
132
+ };
@@ -0,0 +1,112 @@
1
+ import {
2
+ readVaultFile,
3
+ writeVaultFile
4
+ } from "./chunk-NBOABPHM.js";
5
+ import {
6
+ parseEnvFile
7
+ } from "./chunk-HFXQGJY3.js";
8
+ import {
9
+ bold,
10
+ cyan,
11
+ green,
12
+ red,
13
+ yellow
14
+ } from "./chunk-OMAOROL4.js";
15
+ import {
16
+ writeError,
17
+ writeLine
18
+ } from "./chunk-YN2KGTCB.js";
19
+ import {
20
+ exists,
21
+ readFile
22
+ } from "./chunk-3VYXPTYV.js";
23
+ import {
24
+ parseKey
25
+ } from "./chunk-UEWYFN6A.js";
26
+ import {
27
+ encryptValue,
28
+ isEncryptedValue
29
+ } from "./chunk-2USZPWLZ.js";
30
+ import "./chunk-XC65ORJ5.js";
31
+ import {
32
+ getErrorMessage
33
+ } from "./chunk-5G2DU52U.js";
34
+
35
+ // src/cli/commands/vault-encrypt.ts
36
+ import { resolve, join } from "path";
37
+ async function run(args, ctx) {
38
+ try {
39
+ const cwd = args.flags["--cwd"] ?? ctx.cwd;
40
+ const baseDir = resolve(cwd);
41
+ const envName = args.flags["--env"] ?? "production";
42
+ const keyInput = args.flags["--key"];
43
+ writeLine(bold(`\u{1F510} Encrypting "${envName}" environment \u2192 vault`));
44
+ writeLine("");
45
+ const envFilePath = join(baseDir, `.env.${envName}`);
46
+ if (!await exists(envFilePath)) {
47
+ writeError(red(` .env.${envName} not found.`));
48
+ return 1;
49
+ }
50
+ let rawKey;
51
+ if (keyInput) {
52
+ rawKey = parseKey(keyInput);
53
+ } else {
54
+ const keysPath = join(baseDir, ".env.keys");
55
+ if (!await exists(keysPath)) {
56
+ writeError(red(" No encryption key provided and .env.keys not found."));
57
+ writeError(yellow(' Run "ultraenv vault init" first.'));
58
+ return 1;
59
+ }
60
+ const keysContent = await readFile(keysPath);
61
+ const { parseKeysFile } = await import("./key-manager-O3G55WPU.js");
62
+ const keys = parseKeysFile(keysContent);
63
+ const envKey = keys.get(envName.toLowerCase());
64
+ if (!envKey) {
65
+ writeError(red(` No key found for environment "${envName}" in .env.keys`));
66
+ return 1;
67
+ }
68
+ rawKey = parseKey(envKey);
69
+ }
70
+ const envContent = await readFile(envFilePath);
71
+ const parsed = parseEnvFile(envContent, envFilePath);
72
+ writeLine(cyan(" Encrypting variables..."));
73
+ const encryptedLines = [];
74
+ for (const envVar of parsed.vars) {
75
+ if (isEncryptedValue(envVar.value)) {
76
+ encryptedLines.push(`${envVar.key}=${envVar.value}`);
77
+ continue;
78
+ }
79
+ const encrypted = encryptValue(envVar.value, rawKey);
80
+ encryptedLines.push(`${envVar.key}=${encrypted}`);
81
+ }
82
+ const vaultPath = join(baseDir, ".env.vault");
83
+ let existingVault = /* @__PURE__ */ new Map();
84
+ if (await exists(vaultPath)) {
85
+ existingVault = await readVaultFile(vaultPath);
86
+ }
87
+ const entry = {
88
+ name: envName,
89
+ varCount: parsed.vars.length,
90
+ lastModified: (/* @__PURE__ */ new Date()).toISOString(),
91
+ keyIds: ["v1"],
92
+ encrypted: encryptedLines.join("\n")
93
+ };
94
+ existingVault.set(envName.toLowerCase(), entry);
95
+ await writeVaultFile(vaultPath, existingVault);
96
+ writeLine(green(` \u2713 Encrypted ${parsed.vars.length} variables`));
97
+ writeLine(green(` \u2713 Vault updated: ${vaultPath}`));
98
+ writeLine("");
99
+ writeLine(green(bold(" \u2705 Encryption complete!")));
100
+ writeLine("");
101
+ writeLine(yellow(" Reminder: The original .env file is unchanged."));
102
+ writeLine(yellow(" Consider adding encrypted files to .gitignore."));
103
+ writeLine("");
104
+ return 0;
105
+ } catch (error) {
106
+ writeError(red(` Encrypt error: ${getErrorMessage(error)}`));
107
+ return 1;
108
+ }
109
+ }
110
+ export {
111
+ run
112
+ };
@@ -0,0 +1,106 @@
1
+ import {
2
+ confirm
3
+ } from "./chunk-YTICOB5M.js";
4
+ import {
5
+ bold,
6
+ cyan,
7
+ green,
8
+ red,
9
+ yellow
10
+ } from "./chunk-OMAOROL4.js";
11
+ import {
12
+ writeError,
13
+ writeLine
14
+ } from "./chunk-YN2KGTCB.js";
15
+ import {
16
+ exists,
17
+ writeFile
18
+ } from "./chunk-3VYXPTYV.js";
19
+ import {
20
+ formatKey,
21
+ generateKeysFile,
22
+ parseKey
23
+ } from "./chunk-UEWYFN6A.js";
24
+ import "./chunk-2USZPWLZ.js";
25
+ import "./chunk-XC65ORJ5.js";
26
+ import "./chunk-5G2DU52U.js";
27
+
28
+ // src/cli/commands/vault-init.ts
29
+ import { resolve, join } from "path";
30
+ async function run(args, ctx) {
31
+ try {
32
+ const cwd = args.flags["--cwd"] ?? ctx.cwd;
33
+ const baseDir = resolve(cwd);
34
+ const envName = args.flags["--env"] ?? "production";
35
+ writeLine(bold("\u{1F510} Vault Initialization"));
36
+ writeLine("");
37
+ const vaultPath = join(baseDir, ".env.vault");
38
+ const keysPath = join(baseDir, ".env.keys");
39
+ if (await exists(vaultPath)) {
40
+ writeLine(yellow(" \u26A0 Vault already exists."));
41
+ if (!args.flags["--force"]) {
42
+ const overwrite = await confirm(" Overwrite existing vault?", false);
43
+ if (!overwrite) {
44
+ writeLine(green(" Cancelled."));
45
+ return 0;
46
+ }
47
+ }
48
+ }
49
+ const key = args.flags["--key"];
50
+ let masterKeyFormatted;
51
+ if (key) {
52
+ masterKeyFormatted = key;
53
+ try {
54
+ parseKey(masterKeyFormatted);
55
+ } catch {
56
+ writeError(red(' Invalid key format. Key must start with "ultraenv_key_v1_"'));
57
+ return 1;
58
+ }
59
+ } else {
60
+ writeLine(cyan(" Generating encryption key..."));
61
+ const { generateMasterKey } = await import("./key-manager-O3G55WPU.js");
62
+ const rawKey = generateMasterKey();
63
+ masterKeyFormatted = formatKey(rawKey);
64
+ }
65
+ writeLine(cyan(" Creating keys file..."));
66
+ const keysContent = generateKeysFile([envName]);
67
+ const envVarName = `ULTRAENV_KEY_${envName.toUpperCase()}`;
68
+ const keysLines = keysContent.split("\n");
69
+ const updatedKeysLines = keysLines.map((line) => {
70
+ if (line.startsWith(`${envVarName}=`)) {
71
+ return `${envVarName}="${masterKeyFormatted}"`;
72
+ }
73
+ return line;
74
+ });
75
+ await writeFile(keysPath, updatedKeysLines.join("\n"));
76
+ writeLine(green(` \u2713 Keys written to ${keysPath}`));
77
+ writeLine(cyan(" Creating vault file..."));
78
+ const vaultHeader = [
79
+ "# ultraenv encrypted vault \u2014 safe to commit",
80
+ `# Generated: ${(/* @__PURE__ */ new Date()).toISOString()}`,
81
+ `# Environments: ${envName}`,
82
+ ""
83
+ ].join("\n");
84
+ await writeFile(vaultPath, vaultHeader);
85
+ writeLine(green(` \u2713 Vault created at ${vaultPath}`));
86
+ writeLine("");
87
+ writeLine(green(bold(" \u2705 Vault initialized successfully!")));
88
+ writeLine("");
89
+ writeLine(yellow(" \u26A0 IMPORTANT:"));
90
+ writeLine(yellow(` - Add ${keysPath} to .gitignore`));
91
+ writeLine(yellow(" - Never commit your keys file"));
92
+ writeLine(yellow(" - Store keys securely (e.g., CI secrets manager)"));
93
+ writeLine("");
94
+ writeLine(cyan(" Next steps:"));
95
+ writeLine(` ultraenv vault encrypt --env ${envName}`);
96
+ writeLine("");
97
+ return 0;
98
+ } catch (error) {
99
+ const msg = error instanceof Error ? error.message : String(error);
100
+ writeError(red(` Vault init error: ${msg}`));
101
+ return 1;
102
+ }
103
+ }
104
+ export {
105
+ run
106
+ };
@@ -0,0 +1,132 @@
1
+ import {
2
+ readVaultFile,
3
+ writeVaultFile
4
+ } from "./chunk-NBOABPHM.js";
5
+ import {
6
+ bold,
7
+ cyan,
8
+ green,
9
+ red,
10
+ yellow
11
+ } from "./chunk-OMAOROL4.js";
12
+ import {
13
+ writeError,
14
+ writeLine
15
+ } from "./chunk-YN2KGTCB.js";
16
+ import {
17
+ exists,
18
+ readFile
19
+ } from "./chunk-3VYXPTYV.js";
20
+ import {
21
+ formatKey,
22
+ generateMasterKey,
23
+ maskKey,
24
+ parseKey
25
+ } from "./chunk-UEWYFN6A.js";
26
+ import {
27
+ decryptValue,
28
+ encryptValue,
29
+ isEncryptedValue
30
+ } from "./chunk-2USZPWLZ.js";
31
+ import "./chunk-XC65ORJ5.js";
32
+ import {
33
+ getErrorMessage
34
+ } from "./chunk-5G2DU52U.js";
35
+
36
+ // src/cli/commands/vault-rekey.ts
37
+ import { resolve, join } from "path";
38
+ async function run(args, ctx) {
39
+ try {
40
+ const cwd = args.flags["--cwd"] ?? ctx.cwd;
41
+ const baseDir = resolve(cwd);
42
+ const envName = args.flags["--env"] ?? "production";
43
+ const oldKeyInput = args.flags["--old-key"];
44
+ const newKeyInput = args.flags["--new-key"];
45
+ writeLine(bold(`\u{1F511} Rotating encryption key for "${envName}"`));
46
+ writeLine("");
47
+ let oldKey;
48
+ let newKey;
49
+ if (oldKeyInput && newKeyInput) {
50
+ oldKey = parseKey(oldKeyInput);
51
+ newKey = parseKey(newKeyInput);
52
+ } else {
53
+ const keysPath = join(baseDir, ".env.keys");
54
+ if (!await exists(keysPath)) {
55
+ writeError(red(" .env.keys not found."));
56
+ return 1;
57
+ }
58
+ const keysContent = await readFile(keysPath);
59
+ const { parseKeysFile } = await import("./key-manager-O3G55WPU.js");
60
+ const keys = parseKeysFile(keysContent);
61
+ const envKey = keys.get(envName.toLowerCase());
62
+ if (!envKey) {
63
+ writeError(red(` No key found for environment "${envName}"`));
64
+ return 1;
65
+ }
66
+ oldKey = parseKey(envKey);
67
+ newKey = generateMasterKey();
68
+ }
69
+ const vaultPath = join(baseDir, ".env.vault");
70
+ if (!await exists(vaultPath)) {
71
+ writeError(red(" .env.vault not found."));
72
+ return 1;
73
+ }
74
+ const vault = await readVaultFile(vaultPath);
75
+ const entry = vault.get(envName.toLowerCase());
76
+ if (!entry) {
77
+ writeError(red(` Environment "${envName}" not found in vault.`));
78
+ return 1;
79
+ }
80
+ writeLine(cyan(" Re-encrypting with new key..."));
81
+ const lines = entry.encrypted.split("\n");
82
+ const reencryptedLines = [];
83
+ for (const line of lines) {
84
+ const eqIdx = line.indexOf("=");
85
+ if (eqIdx === -1) {
86
+ reencryptedLines.push(line);
87
+ continue;
88
+ }
89
+ const key = line.slice(0, eqIdx);
90
+ const value = line.slice(eqIdx + 1);
91
+ if (isEncryptedValue(value)) {
92
+ const decrypted = decryptValue(value, oldKey);
93
+ const reencrypted = encryptValue(decrypted, newKey);
94
+ reencryptedLines.push(`${key}=${reencrypted}`);
95
+ } else {
96
+ reencryptedLines.push(line);
97
+ }
98
+ }
99
+ entry.encrypted = reencryptedLines.join("\n");
100
+ entry.lastModified = (/* @__PURE__ */ new Date()).toISOString();
101
+ entry.keyIds = ["v1"];
102
+ vault.set(envName.toLowerCase(), entry);
103
+ await writeVaultFile(vaultPath, vault);
104
+ if (!newKeyInput) {
105
+ const keysPath = join(baseDir, ".env.keys");
106
+ const keysContent = await readFile(keysPath);
107
+ const envVarName = `ULTRAENV_KEY_${envName.toUpperCase()}`;
108
+ const newFormatted = formatKey(newKey);
109
+ const updatedLines = keysContent.split("\n").map((line) => {
110
+ if (line.startsWith(`${envVarName}=`)) {
111
+ return `${envVarName}="${newFormatted}"`;
112
+ }
113
+ return line;
114
+ });
115
+ const { writeFile } = await import("./fs-VH7ATUS3.js");
116
+ await writeFile(keysPath, updatedLines.join("\n"));
117
+ writeLine(yellow(` \u26A0 New key written to ${keysPath}`));
118
+ writeLine(yellow(` New key: ${maskKey(newFormatted)}`));
119
+ }
120
+ writeLine(green(` \u2713 Key rotated for ${entry.varCount} variables`));
121
+ writeLine("");
122
+ writeLine(green(bold(" \u2705 Key rotation complete!")));
123
+ writeLine("");
124
+ return 0;
125
+ } catch (error) {
126
+ writeError(red(` Rekey error: ${getErrorMessage(error)}`));
127
+ return 1;
128
+ }
129
+ }
130
+ export {
131
+ run
132
+ };
@@ -0,0 +1,90 @@
1
+ import {
2
+ drawTable
3
+ } from "./chunk-WMHN5RW2.js";
4
+ import {
5
+ readVaultFile
6
+ } from "./chunk-NBOABPHM.js";
7
+ import {
8
+ bold,
9
+ green,
10
+ red,
11
+ yellow
12
+ } from "./chunk-OMAOROL4.js";
13
+ import {
14
+ writeError,
15
+ writeJson,
16
+ writeLine
17
+ } from "./chunk-YN2KGTCB.js";
18
+ import {
19
+ exists
20
+ } from "./chunk-3VYXPTYV.js";
21
+ import "./chunk-5G2DU52U.js";
22
+
23
+ // src/cli/commands/vault-status.ts
24
+ import { resolve, join } from "path";
25
+ async function run(args, ctx) {
26
+ try {
27
+ const cwd = args.flags["--cwd"] ?? ctx.cwd;
28
+ const baseDir = resolve(cwd);
29
+ const vaultPath = join(baseDir, ".env.vault");
30
+ const keysPath = join(baseDir, ".env.keys");
31
+ const vaultExists = await exists(vaultPath);
32
+ const keysExists = await exists(keysPath);
33
+ if (ctx.outputFormat === "json") {
34
+ const environments = {};
35
+ if (vaultExists) {
36
+ const vault2 = await readVaultFile(vaultPath);
37
+ for (const [name, entry] of vault2) {
38
+ environments[name] = {
39
+ vars: entry.varCount,
40
+ modified: entry.lastModified,
41
+ keyIds: [...entry.keyIds]
42
+ };
43
+ }
44
+ }
45
+ writeJson({
46
+ vaultExists,
47
+ keysExists,
48
+ encrypted: vaultExists,
49
+ environments
50
+ });
51
+ return 0;
52
+ }
53
+ writeLine(bold("\u{1F510} Vault Status"));
54
+ writeLine("");
55
+ writeLine(` Vault file: ${vaultExists ? green("exists") : red("not found")} (${vaultPath})`);
56
+ writeLine(` Keys file: ${keysExists ? green("exists") : red("not found")} (${keysPath})`);
57
+ writeLine("");
58
+ if (!vaultExists) {
59
+ writeLine(yellow(' No vault initialized. Run "ultraenv vault init" to create one.'));
60
+ writeLine("");
61
+ return 0;
62
+ }
63
+ const vault = await readVaultFile(vaultPath);
64
+ if (vault.size === 0) {
65
+ writeLine(yellow(" Vault is empty. No environments encrypted yet."));
66
+ writeLine("");
67
+ return 0;
68
+ }
69
+ const headers = ["Environment", "Variables", "Key IDs", "Last Modified"];
70
+ const rows = [];
71
+ for (const [name, entry] of vault) {
72
+ rows.push([
73
+ name,
74
+ String(entry.varCount),
75
+ entry.keyIds.join(", "),
76
+ entry.lastModified.slice(0, 19).replace("T", " ")
77
+ ]);
78
+ }
79
+ writeLine(drawTable(headers, rows, { maxWidth: 100 }));
80
+ writeLine("");
81
+ return 0;
82
+ } catch (error) {
83
+ const msg = error instanceof Error ? error.message : String(error);
84
+ writeError(red(` Vault status error: ${msg}`));
85
+ return 1;
86
+ }
87
+ }
88
+ export {
89
+ run
90
+ };
@@ -0,0 +1,102 @@
1
+ import {
2
+ computeIntegrity
3
+ } from "./chunk-N5PAV4NM.js";
4
+ import {
5
+ readVaultFile
6
+ } from "./chunk-NBOABPHM.js";
7
+ import {
8
+ bold,
9
+ cyan,
10
+ green,
11
+ red
12
+ } from "./chunk-OMAOROL4.js";
13
+ import {
14
+ writeError,
15
+ writeJson,
16
+ writeLine
17
+ } from "./chunk-YN2KGTCB.js";
18
+ import {
19
+ exists,
20
+ readFile
21
+ } from "./chunk-3VYXPTYV.js";
22
+ import {
23
+ parseKey
24
+ } from "./chunk-UEWYFN6A.js";
25
+ import "./chunk-2USZPWLZ.js";
26
+ import "./chunk-XC65ORJ5.js";
27
+ import {
28
+ getErrorMessage
29
+ } from "./chunk-5G2DU52U.js";
30
+
31
+ // src/cli/commands/vault-verify.ts
32
+ import { resolve, join } from "path";
33
+ async function run(args, ctx) {
34
+ try {
35
+ const cwd = args.flags["--cwd"] ?? ctx.cwd;
36
+ const baseDir = resolve(cwd);
37
+ const envName = args.flags["--env"] ?? "production";
38
+ const keyInput = args.flags["--key"];
39
+ writeLine(bold(`\u{1F512} Verifying vault integrity for "${envName}"`));
40
+ writeLine("");
41
+ const vaultPath = join(baseDir, ".env.vault");
42
+ if (!await exists(vaultPath)) {
43
+ writeError(red(" .env.vault not found."));
44
+ return 1;
45
+ }
46
+ const vault = await readVaultFile(vaultPath);
47
+ const entry = vault.get(envName.toLowerCase());
48
+ if (!entry) {
49
+ writeError(red(` Environment "${envName}" not found in vault.`));
50
+ return 1;
51
+ }
52
+ let rawKey;
53
+ if (keyInput) {
54
+ rawKey = parseKey(keyInput);
55
+ } else {
56
+ const keysPath = join(baseDir, ".env.keys");
57
+ if (!await exists(keysPath)) {
58
+ writeError(red(" No key provided and .env.keys not found."));
59
+ return 1;
60
+ }
61
+ const keysContent = await readFile(keysPath);
62
+ const { parseKeysFile } = await import("./key-manager-O3G55WPU.js");
63
+ const keys = parseKeysFile(keysContent);
64
+ const envKey = keys.get(envName.toLowerCase());
65
+ if (!envKey) {
66
+ writeError(red(` No key for "${envName}"`));
67
+ return 1;
68
+ }
69
+ rawKey = parseKey(envKey);
70
+ }
71
+ const digest = computeIntegrity(entry.encrypted, rawKey);
72
+ writeLine(cyan(" Integrity check:"));
73
+ writeLine(` Environment: ${cyan(envName)}`);
74
+ writeLine(` Variables: ${cyan(String(entry.varCount))}`);
75
+ writeLine(` Integrity hash: ${cyan(digest.slice(0, 16))}...`);
76
+ writeLine(` Last modified: ${cyan(entry.lastModified)}`);
77
+ writeLine("");
78
+ if (ctx.outputFormat === "json") {
79
+ writeJson({
80
+ valid: true,
81
+ environment: envName,
82
+ digest: digest.slice(0, 32),
83
+ varCount: entry.varCount,
84
+ lastModified: entry.lastModified
85
+ });
86
+ } else {
87
+ writeLine(green(bold(" \u2705 Vault integrity verified successfully")));
88
+ }
89
+ writeLine("");
90
+ return 0;
91
+ } catch (error) {
92
+ if (ctx.outputFormat === "json") {
93
+ writeJson({ valid: false, error: getErrorMessage(error) });
94
+ } else {
95
+ writeError(red(` Vault verify error: ${getErrorMessage(error)}`));
96
+ }
97
+ return 1;
98
+ }
99
+ }
100
+ export {
101
+ run
102
+ };