ultraenv 1.0.0 → 1.0.2

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/README.md +67 -1857
  2. package/dist/{chunk-GC7RXHLA.js → chunk-2MBSLURI.js} +16 -17
  3. package/dist/{chunk-IGFVP24Q.js → chunk-3AF476D7.js} +1 -1
  4. package/dist/{chunk-N5PAV4NM.js → chunk-5WUBB633.js} +17 -26
  5. package/dist/{chunk-2USZPWLZ.js → chunk-6NFA23AY.js} +28 -39
  6. package/dist/{chunk-AWN6ADV7.js → chunk-6X3BUE5S.js} +45 -54
  7. package/dist/{chunk-NBOABPHM.js → chunk-72UKVOO5.js} +24 -40
  8. package/dist/{chunk-JB7RKV3C.js → chunk-7AHG2IP4.js} +1 -7
  9. package/dist/{chunk-6KS56D6E.js → chunk-7VJ7LK2M.js} +1 -1
  10. package/dist/{chunk-CIFMBJ4H.js → chunk-BNUHE2ZI.js} +57 -21
  11. package/dist/{chunk-HFXQGJY3.js → chunk-CVJPO3QY.js} +13 -27
  12. package/dist/{chunk-IKPTKALB.js → chunk-F7YSINGU.js} +1 -3
  13. package/dist/{chunk-3VYXPTYV.js → chunk-FSKVYBEP.js} +1 -1
  14. package/dist/{chunk-4XUYMRK5.js → chunk-GJC64ZG7.js} +4 -3
  15. package/dist/{chunk-YMMP4VQL.js → chunk-H3QEGEZ6.js} +1 -1
  16. package/dist/{chunk-CHVO6NWI.js → chunk-LFIKYFPS.js} +2 -2
  17. package/dist/{chunk-3UV2QNJL.js → chunk-LJSCUOD4.js} +19 -21
  18. package/dist/{chunk-YVWLXFUT.js → chunk-LQZK6BBQ.js} +2 -2
  19. package/dist/{chunk-5G2DU52U.js → chunk-N7GOHQBF.js} +7 -1
  20. package/dist/{chunk-MSXMESFP.js → chunk-OBLMAUCF.js} +8 -14
  21. package/dist/{chunk-UEWYFN6A.js → chunk-RJTUAMK3.js} +16 -29
  22. package/dist/{chunk-MNVFG7H4.js → chunk-XPZC32UY.js} +16 -25
  23. package/dist/{chunk-WMHN5RW2.js → chunk-YLGJQOMM.js} +3 -9
  24. package/dist/{ci-check-sync-VBMSVWIV.js → ci-check-sync-UO5PARKO.js} +4 -4
  25. package/dist/{ci-scan-24MT5XGS.js → ci-scan-5D7QBN5X.js} +2 -5
  26. package/dist/{ci-setup-C2NKEFRD.js → ci-setup-J34DS6KD.js} +2 -2
  27. package/dist/{ci-validate-7AW24LSQ.js → ci-validate-LWP5NBDN.js} +4 -4
  28. package/dist/cli/index.cjs +470 -390
  29. package/dist/cli/index.js +130 -55
  30. package/dist/comparator-AIRTWBOL.js +13 -0
  31. package/dist/{config-O5YRQP5Z.js → config-67GDO3CW.js} +3 -3
  32. package/dist/{debug-PTPXAF3K.js → debug-6VCX3QSP.js} +6 -6
  33. package/dist/{declaration-LEME4AFZ.js → declaration-YGOVZOXG.js} +3 -3
  34. package/dist/{doctor-FZAUPKHS.js → doctor-FF7QOTP2.js} +7 -5
  35. package/dist/{envs-compare-5K3HESX5.js → envs-compare-P7GPKGQX.js} +4 -4
  36. package/dist/{envs-create-2XXHXMGA.js → envs-create-ISG4SECU.js} +4 -4
  37. package/dist/{envs-list-NQM5252B.js → envs-list-PUW67HOC.js} +5 -5
  38. package/dist/{envs-switch-6L2AQYID.js → envs-switch-P4YDJ6LG.js} +4 -4
  39. package/dist/{envs-validate-FL73Q76T.js → envs-validate-VNKBKYO3.js} +6 -9
  40. package/dist/{fs-VH7ATUS3.js → fs-7HKOZY5K.js} +2 -2
  41. package/dist/{generator-LFZBMZZS.js → generator-O23ATCIY.js} +4 -4
  42. package/dist/{help-3XJBXEHE.js → help-THFLI6YT.js} +108 -26
  43. package/dist/index.cjs +295 -381
  44. package/dist/index.d.cts +1 -1
  45. package/dist/index.d.ts +1 -1
  46. package/dist/index.js +81 -100
  47. package/dist/{init-Y7JQ2KYJ.js → init-KBLVTHQW.js} +15 -11
  48. package/dist/{install-hook-SKXIV6NV.js → install-hook-42F22BLY.js} +2 -2
  49. package/dist/{json-schema-I26YNQBH.js → json-schema-YULPWDKA.js} +3 -3
  50. package/dist/{key-manager-O3G55WPU.js → key-manager-WDWPX3IQ.js} +3 -3
  51. package/dist/middleware/express.cjs +1 -3
  52. package/dist/middleware/express.js +1 -1
  53. package/dist/middleware/fastify.cjs +1 -7
  54. package/dist/middleware/fastify.js +1 -1
  55. package/dist/{module-IDIZPP4M.js → module-FGH2V6N2.js} +3 -3
  56. package/dist/{protect-NCWPM6VC.js → protect-A4G7LQFJ.js} +26 -24
  57. package/dist/{scan-TRLY36TT.js → scan-4BXGHR33.js} +1 -1
  58. package/dist/schema/index.cjs +57 -21
  59. package/dist/schema/index.js +1 -1
  60. package/dist/{sync-TMHMTLH2.js → sync-MYLMDDY6.js} +23 -14
  61. package/dist/{typegen-SQOSXBWM.js → typegen-GLBRHWSK.js} +17 -23
  62. package/dist/{validate-IOAM5HWS.js → validate-J73ETKXD.js} +5 -5
  63. package/dist/{vault-decrypt-U6HJZNBV.js → vault-decrypt-V3GY5HES.js} +7 -7
  64. package/dist/{vault-diff-B3ZOQTWI.js → vault-diff-QVE6S6KP.js} +5 -5
  65. package/dist/{vault-encrypt-GUSLCSKS.js → vault-encrypt-WUBY3OVF.js} +7 -7
  66. package/dist/{vault-init-GUBOTOUL.js → vault-init-EWSAED44.js} +5 -5
  67. package/dist/{vault-rekey-DAHT7JCN.js → vault-rekey-VODMGCNA.js} +7 -7
  68. package/dist/{vault-status-GDLRU2OK.js → vault-status-YXDK6O7X.js} +4 -4
  69. package/dist/{vault-verify-CD76FJSF.js → vault-verify-SSXGTVBK.js} +7 -7
  70. package/package.json +1 -1
  71. package/dist/comparator-RDKX3OI7.js +0 -13
@@ -1,15 +1,15 @@
1
1
  import {
2
2
  parseEnvFile
3
- } from "./chunk-HFXQGJY3.js";
3
+ } from "./chunk-CVJPO3QY.js";
4
4
  import {
5
5
  exists,
6
6
  listFiles,
7
7
  readFile,
8
8
  writeFile
9
- } from "./chunk-3VYXPTYV.js";
9
+ } from "./chunk-FSKVYBEP.js";
10
10
  import {
11
11
  FileSystemError
12
- } from "./chunk-5G2DU52U.js";
12
+ } from "./chunk-N7GOHQBF.js";
13
13
 
14
14
  // src/environments/manager.ts
15
15
  import { resolve, join } from "path";
@@ -161,12 +161,14 @@ async function validateAllEnvironments(schema, cwd) {
161
161
  const message = error instanceof Error ? error.message : String(error);
162
162
  results.set(envName ?? pattern, {
163
163
  valid: false,
164
- errors: [{
165
- field: "",
166
- value: "",
167
- message: `Failed to read/parse file: ${message}`,
168
- hint: "Check that the file is a valid .env file."
169
- }],
164
+ errors: [
165
+ {
166
+ field: "",
167
+ value: "",
168
+ message: `Failed to read/parse file: ${message}`,
169
+ hint: "Check that the file is a valid .env file."
170
+ }
171
+ ],
170
172
  warnings: []
171
173
  });
172
174
  }
@@ -177,14 +179,11 @@ async function switchEnvironment(envName, cwd) {
177
179
  const baseDir = resolve(cwd ?? process.cwd());
178
180
  const envFile = join(baseDir, `.env.${envName}`);
179
181
  if (!await exists(envFile)) {
180
- throw new FileSystemError(
181
- `Environment file ".env.${envName}" not found`,
182
- {
183
- path: envFile,
184
- operation: "read",
185
- hint: `Create a ".env.${envName}" file first, or use "ultraenv env create ${envName}".`
186
- }
187
- );
182
+ throw new FileSystemError(`Environment file ".env.${envName}" not found`, {
183
+ path: envFile,
184
+ operation: "read",
185
+ hint: `Create a ".env.${envName}" file first, or use "ultraenv env create ${envName}".`
186
+ });
188
187
  }
189
188
  const content = await readFile(envFile);
190
189
  const header = [
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  writeFile
3
- } from "./chunk-3VYXPTYV.js";
3
+ } from "./chunk-FSKVYBEP.js";
4
4
 
5
5
  // src/typegen/declaration.ts
6
6
  var DEFAULT_HEADER = "// Auto-generated by ultraenv \u2014 DO NOT EDIT";
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  EncryptionError
3
- } from "./chunk-5G2DU52U.js";
3
+ } from "./chunk-N7GOHQBF.js";
4
4
 
5
5
  // src/vault/integrity.ts
6
6
  import { createHmac, timingSafeEqual as cryptoTimingSafeEqual } from "crypto";
@@ -8,16 +8,14 @@ var HMAC_ALGORITHM = "sha256";
8
8
  var HMAC_DIGEST_LENGTH = 64;
9
9
  function computeIntegrity(data, key) {
10
10
  if (key.length === 0) {
11
- throw new EncryptionError(
12
- "Cannot compute integrity with an empty key",
13
- { hint: "Provide a valid encryption key for integrity computation." }
14
- );
11
+ throw new EncryptionError("Cannot compute integrity with an empty key", {
12
+ hint: "Provide a valid encryption key for integrity computation."
13
+ });
15
14
  }
16
15
  if (data.length === 0) {
17
- throw new EncryptionError(
18
- "Cannot compute integrity for empty data",
19
- { hint: "Provide non-empty data for integrity computation." }
20
- );
16
+ throw new EncryptionError("Cannot compute integrity for empty data", {
17
+ hint: "Provide non-empty data for integrity computation."
18
+ });
21
19
  }
22
20
  const hmac = createHmac(HMAC_ALGORITHM, key);
23
21
  hmac.update(data, "utf-8");
@@ -25,21 +23,20 @@ function computeIntegrity(data, key) {
25
23
  }
26
24
  function verifyIntegrity(data, key, expected) {
27
25
  if (key.length === 0) {
28
- throw new EncryptionError(
29
- "Cannot verify integrity with an empty key"
30
- );
26
+ throw new EncryptionError("Cannot verify integrity with an empty key");
31
27
  }
32
28
  if (expected.length !== HMAC_DIGEST_LENGTH) {
33
29
  throw new EncryptionError(
34
30
  `Invalid expected digest length: expected ${HMAC_DIGEST_LENGTH} hex characters, got ${expected.length}`,
35
- { hint: "The integrity digest should be a 64-character lowercase hex string from computeIntegrity()." }
31
+ {
32
+ hint: "The integrity digest should be a 64-character lowercase hex string from computeIntegrity()."
33
+ }
36
34
  );
37
35
  }
38
36
  if (!/^[0-9a-f]{64}$/.test(expected)) {
39
- throw new EncryptionError(
40
- "Invalid expected digest format: must be a lowercase hex string",
41
- { hint: "Ensure the stored digest is a 64-character lowercase hex string." }
42
- );
37
+ throw new EncryptionError("Invalid expected digest format: must be a lowercase hex string", {
38
+ hint: "Ensure the stored digest is a 64-character lowercase hex string."
39
+ });
43
40
  }
44
41
  try {
45
42
  const computed = computeIntegrity(data, key);
@@ -53,14 +50,10 @@ function verifyIntegrity(data, key, expected) {
53
50
  }
54
51
  function computeVaultChecksum(environments, key) {
55
52
  if (key.length === 0) {
56
- throw new EncryptionError(
57
- "Cannot compute vault checksum with an empty key"
58
- );
53
+ throw new EncryptionError("Cannot compute vault checksum with an empty key");
59
54
  }
60
55
  if (environments.size === 0) {
61
- throw new EncryptionError(
62
- "Cannot compute vault checksum for empty environment set"
63
- );
56
+ throw new EncryptionError("Cannot compute vault checksum for empty environment set");
64
57
  }
65
58
  const sortedNames = Array.from(environments.keys()).sort();
66
59
  const parts = [];
@@ -76,9 +69,7 @@ function computeVaultChecksum(environments, key) {
76
69
  }
77
70
  function verifyVaultChecksum(environments, key, expected) {
78
71
  if (key.length === 0) {
79
- throw new EncryptionError(
80
- "Cannot verify vault checksum with an empty key"
81
- );
72
+ throw new EncryptionError("Cannot verify vault checksum with an empty key");
82
73
  }
83
74
  if (expected.length !== HMAC_DIGEST_LENGTH) {
84
75
  throw new EncryptionError(
@@ -4,7 +4,7 @@ import {
4
4
  } from "./chunk-XC65ORJ5.js";
5
5
  import {
6
6
  EncryptionError
7
- } from "./chunk-5G2DU52U.js";
7
+ } from "./chunk-N7GOHQBF.js";
8
8
 
9
9
  // src/utils/crypto.ts
10
10
  import {
@@ -38,11 +38,7 @@ function manualHkdf(ikm, salt, info, length) {
38
38
  const okm = Buffer.alloc(length);
39
39
  let previous = Buffer.alloc(0);
40
40
  for (let i = 1; i <= n; i++) {
41
- const hmacData = Buffer.concat([
42
- previous,
43
- infoBuffer,
44
- Buffer.from([i])
45
- ]);
41
+ const hmacData = Buffer.concat([previous, infoBuffer, Buffer.from([i])]);
46
42
  previous = createHmac("sha256", prk).update(hmacData).digest();
47
43
  const offset = (i - 1) * hashLen;
48
44
  const copyLen = Math.min(hashLen, length - offset);
@@ -59,10 +55,7 @@ function encrypt(key, plaintext) {
59
55
  const iv = cryptoRandomBytes(12);
60
56
  const algo = `aes-${key.length * 8}-gcm`;
61
57
  const cipher = createCipheriv(algo, key, iv);
62
- const ciphertext = Buffer.concat([
63
- cipher.update(plaintext),
64
- cipher.final()
65
- ]);
58
+ const ciphertext = Buffer.concat([cipher.update(plaintext), cipher.final()]);
66
59
  const authTag = cipher.getAuthTag();
67
60
  return { iv, authTag, ciphertext };
68
61
  }
@@ -76,10 +69,7 @@ function decrypt(key, iv, authTag, ciphertext) {
76
69
  const decipher = createDecipheriv(algo, key, iv);
77
70
  decipher.setAuthTag(authTag);
78
71
  try {
79
- return Buffer.concat([
80
- decipher.update(ciphertext),
81
- decipher.final()
82
- ]);
72
+ return Buffer.concat([decipher.update(ciphertext), decipher.final()]);
83
73
  } catch (error) {
84
74
  const message = error instanceof Error ? error.message : String(error);
85
75
  throw new Error(
@@ -111,14 +101,15 @@ function encryptEnvironment(data, key) {
111
101
  if (key.length !== 32) {
112
102
  throw new EncryptionError(
113
103
  `Invalid key length: expected 32 bytes for AES-256, got ${key.length}`,
114
- { hint: "Generate a new key using generateMasterKey() or ensure you are using the correct key file." }
104
+ {
105
+ hint: "Generate a new key using generateMasterKey() or ensure you are using the correct key file."
106
+ }
115
107
  );
116
108
  }
117
109
  if (Object.keys(data).length === 0) {
118
- throw new EncryptionError(
119
- "Cannot encrypt empty environment data",
120
- { hint: "Provide at least one environment variable to encrypt." }
121
- );
110
+ throw new EncryptionError("Cannot encrypt empty environment data", {
111
+ hint: "Provide at least one environment variable to encrypt."
112
+ });
122
113
  }
123
114
  try {
124
115
  const serialized = serializeEnvData(data);
@@ -147,7 +138,9 @@ function decryptEnvironment(encrypted, key) {
147
138
  if (encrypted.algorithm !== ENCRYPTION_ALGORITHM) {
148
139
  throw new EncryptionError(
149
140
  `Unsupported algorithm: "${encrypted.algorithm}". Expected "${ENCRYPTION_ALGORITHM}".`,
150
- { hint: "This vault was encrypted with a different algorithm. You may need to migrate the vault." }
141
+ {
142
+ hint: "This vault was encrypted with a different algorithm. You may need to migrate the vault."
143
+ }
151
144
  );
152
145
  }
153
146
  if (encrypted.iv.length !== IV_LENGTH) {
@@ -204,12 +197,9 @@ function decryptValue(encrypted, key) {
204
197
  );
205
198
  }
206
199
  if (!encrypted.startsWith(ENCRYPTED_PREFIX)) {
207
- throw new EncryptionError(
208
- "Invalid encrypted value format: missing required prefix",
209
- {
210
- hint: `Expected the value to start with "${ENCRYPTED_PREFIX}". This value may not have been encrypted by ultraenv.`
211
- }
212
- );
200
+ throw new EncryptionError("Invalid encrypted value format: missing required prefix", {
201
+ hint: `Expected the value to start with "${ENCRYPTED_PREFIX}". This value may not have been encrypted by ultraenv.`
202
+ });
213
203
  }
214
204
  const payload = encrypted.slice(ENCRYPTED_PREFIX.length);
215
205
  const parts = payload.split(":");
@@ -225,16 +215,14 @@ function decryptValue(encrypted, key) {
225
215
  const authTagB64 = parts[1];
226
216
  const ciphertextB64 = parts[2];
227
217
  if (ivB64 === void 0 || authTagB64 === void 0 || ciphertextB64 === void 0) {
228
- throw new EncryptionError(
229
- "Invalid encrypted value: unexpected component structure",
230
- { hint: "The encrypted data may be corrupted. Try re-encrypting the value." }
231
- );
218
+ throw new EncryptionError("Invalid encrypted value: unexpected component structure", {
219
+ hint: "The encrypted data may be corrupted. Try re-encrypting the value."
220
+ });
232
221
  }
233
222
  if (ivB64.length === 0 || authTagB64.length === 0 || ciphertextB64.length === 0) {
234
- throw new EncryptionError(
235
- "Invalid encrypted value: one or more base64 components are empty",
236
- { hint: "The encrypted data may be corrupted. Try re-encrypting the value." }
237
- );
223
+ throw new EncryptionError("Invalid encrypted value: one or more base64 components are empty", {
224
+ hint: "The encrypted data may be corrupted. Try re-encrypting the value."
225
+ });
238
226
  }
239
227
  try {
240
228
  const iv = base64ToBuffer(ivB64);
@@ -243,7 +231,9 @@ function decryptValue(encrypted, key) {
243
231
  if (iv.length !== IV_LENGTH) {
244
232
  throw new EncryptionError(
245
233
  `Invalid IV length: expected ${IV_LENGTH} bytes, got ${iv.length}`,
246
- { hint: "The encrypted data may be corrupted or was produced by a different version of ultraenv." }
234
+ {
235
+ hint: "The encrypted data may be corrupted or was produced by a different version of ultraenv."
236
+ }
247
237
  );
248
238
  }
249
239
  if (authTag.length !== AUTH_TAG_LENGTH) {
@@ -258,10 +248,9 @@ function decryptValue(encrypted, key) {
258
248
  if (error instanceof EncryptionError) throw error;
259
249
  const message = error instanceof Error ? error.message : String(error);
260
250
  if (message.includes("Invalid") || message.includes("base64")) {
261
- throw new EncryptionError(
262
- "Invalid base64 encoding in encrypted value",
263
- { hint: "The encrypted data may be corrupted. Ensure the value was not modified." }
264
- );
251
+ throw new EncryptionError("Invalid base64 encoding in encrypted value", {
252
+ hint: "The encrypted data may be corrupted. Ensure the value was not modified."
253
+ });
265
254
  }
266
255
  throw new EncryptionError(
267
256
  "Failed to decrypt value. The key may be incorrect or the ciphertext was tampered with.",
@@ -1,15 +1,15 @@
1
1
  import {
2
2
  parseEnvFile
3
- } from "./chunk-HFXQGJY3.js";
3
+ } from "./chunk-CVJPO3QY.js";
4
4
  import {
5
5
  exists,
6
6
  readFile,
7
7
  removeFile,
8
8
  writeFile
9
- } from "./chunk-3VYXPTYV.js";
9
+ } from "./chunk-FSKVYBEP.js";
10
10
  import {
11
11
  FileSystemError
12
- } from "./chunk-5G2DU52U.js";
12
+ } from "./chunk-N7GOHQBF.js";
13
13
 
14
14
  // src/environments/creator.ts
15
15
  import { resolve, join } from "path";
@@ -173,14 +173,11 @@ function validateEnvironmentName(name) {
173
173
  });
174
174
  }
175
175
  if (name.length > 64) {
176
- throw new FileSystemError(
177
- `Environment name too long: ${name.length} characters (max 64)`,
178
- {
179
- path: "",
180
- operation: "validate",
181
- hint: "Use a shorter environment name."
182
- }
183
- );
176
+ throw new FileSystemError(`Environment name too long: ${name.length} characters (max 64)`, {
177
+ path: "",
178
+ operation: "validate",
179
+ hint: "Use a shorter environment name."
180
+ });
184
181
  }
185
182
  if (!/^[a-zA-Z0-9_-]+$/.test(name)) {
186
183
  throw new FileSystemError(
@@ -194,14 +191,11 @@ function validateEnvironmentName(name) {
194
191
  }
195
192
  const reserved = ["local", "example", "template", "bak", "backup", "old", "tmp", "temp"];
196
193
  if (reserved.includes(name.toLowerCase())) {
197
- throw new FileSystemError(
198
- `Reserved environment name: "${name}"`,
199
- {
200
- path: "",
201
- operation: "validate",
202
- hint: `The name "${name}" is reserved. Choose a different name.`
203
- }
204
- );
194
+ throw new FileSystemError(`Reserved environment name: "${name}"`, {
195
+ path: "",
196
+ operation: "validate",
197
+ hint: `The name "${name}" is reserved. Choose a different name.`
198
+ });
205
199
  }
206
200
  }
207
201
  async function createEnvironment(name, options) {
@@ -209,28 +203,22 @@ async function createEnvironment(name, options) {
209
203
  const baseDir = resolve(options?.cwd ?? process.cwd());
210
204
  const outputPath = join(baseDir, `.env.${name}`);
211
205
  if (await exists(outputPath)) {
212
- throw new FileSystemError(
213
- `Environment file already exists: ".env.${name}"`,
214
- {
215
- path: outputPath,
216
- operation: "create",
217
- hint: "Delete the existing file first, or use a different environment name."
218
- }
219
- );
206
+ throw new FileSystemError(`Environment file already exists: ".env.${name}"`, {
207
+ path: outputPath,
208
+ operation: "create",
209
+ hint: "Delete the existing file first, or use a different environment name."
210
+ });
220
211
  }
221
212
  let content;
222
213
  let variables = [];
223
214
  if (options?.copyFrom !== void 0) {
224
215
  const sourcePath = join(baseDir, `.env.${options.copyFrom}`);
225
216
  if (!await exists(sourcePath)) {
226
- throw new FileSystemError(
227
- `Source environment not found: ".env.${options.copyFrom}"`,
228
- {
229
- path: sourcePath,
230
- operation: "read",
231
- hint: `Ensure ".env.${options.copyFrom}" exists before copying.`
232
- }
233
- );
217
+ throw new FileSystemError(`Source environment not found: ".env.${options.copyFrom}"`, {
218
+ path: sourcePath,
219
+ operation: "read",
220
+ hint: `Ensure ".env.${options.copyFrom}" exists before copying.`
221
+ });
234
222
  }
235
223
  content = await readFile(sourcePath);
236
224
  variables = extractVariables(content, options?.schema);
@@ -251,14 +239,11 @@ async function createEnvironment(name, options) {
251
239
  } else if (await exists(templatePath)) {
252
240
  content = await readFile(templatePath);
253
241
  } else {
254
- throw new FileSystemError(
255
- `Template not found: "${options.fromTemplate}"`,
256
- {
257
- path: templatePath,
258
- operation: "read",
259
- hint: "Use a built-in template name (nodejs, nextjs, docker) or a valid file path."
260
- }
261
- );
242
+ throw new FileSystemError(`Template not found: "${options.fromTemplate}"`, {
243
+ path: templatePath,
244
+ operation: "read",
245
+ hint: "Use a built-in template name (nodejs, nextjs, docker) or a valid file path."
246
+ });
262
247
  }
263
248
  variables = extractVariables(content, options?.schema);
264
249
  const values = collectValues(variables, options?.values);
@@ -293,23 +278,29 @@ async function createEnvironment(name, options) {
293
278
  }
294
279
  function listTemplates() {
295
280
  return [
296
- { name: "nodejs", description: "Node.js backend environment (PORT, DATABASE_URL, JWT, CORS, etc.)" },
297
- { name: "nextjs", description: "Next.js frontend environment (NEXT_PUBLIC_* variables, analytics, etc.)" },
298
- { name: "docker", description: "Docker deployment environment (container ports, Postgres, Redis, etc.)" }
281
+ {
282
+ name: "nodejs",
283
+ description: "Node.js backend environment (PORT, DATABASE_URL, JWT, CORS, etc.)"
284
+ },
285
+ {
286
+ name: "nextjs",
287
+ description: "Next.js frontend environment (NEXT_PUBLIC_* variables, analytics, etc.)"
288
+ },
289
+ {
290
+ name: "docker",
291
+ description: "Docker deployment environment (container ports, Postgres, Redis, etc.)"
292
+ }
299
293
  ];
300
294
  }
301
295
  async function removeEnvironment(name, cwd) {
302
296
  const baseDir = resolve(cwd ?? process.cwd());
303
297
  const filePath = join(baseDir, `.env.${name}`);
304
298
  if (!await exists(filePath)) {
305
- throw new FileSystemError(
306
- `Environment file not found: ".env.${name}"`,
307
- {
308
- path: filePath,
309
- operation: "unlink",
310
- hint: "The environment does not exist."
311
- }
312
- );
299
+ throw new FileSystemError(`Environment file not found: ".env.${name}"`, {
300
+ path: filePath,
301
+ operation: "unlink",
302
+ hint: "The environment does not exist."
303
+ });
313
304
  }
314
305
  await removeFile(filePath);
315
306
  }
@@ -1,10 +1,10 @@
1
1
  import {
2
2
  readFile,
3
3
  writeFile
4
- } from "./chunk-3VYXPTYV.js";
4
+ } from "./chunk-FSKVYBEP.js";
5
5
  import {
6
6
  VaultError
7
- } from "./chunk-5G2DU52U.js";
7
+ } from "./chunk-N7GOHQBF.js";
8
8
 
9
9
  // src/vault/vault-file.ts
10
10
  var VAULT_VAR_PREFIX = "ULTRAENV_VAULT_";
@@ -20,21 +20,14 @@ function parseVaultFile(content) {
20
20
  if (rawLine === void 0) continue;
21
21
  const line = rawLine.trim();
22
22
  if (line.length === 0 || line.startsWith("#")) continue;
23
- const match = line.match(
24
- new RegExp(`^${VAULT_VAR_PREFIX}([A-Za-z0-9_]+)="(.*)"$`)
25
- );
23
+ const match = line.match(new RegExp(`^${VAULT_VAR_PREFIX}([A-Za-z0-9_]+)="(.*)"$`));
26
24
  if (!match) {
27
- const plainMatch = line.match(
28
- new RegExp(`^${VAULT_VAR_PREFIX}([A-Za-z0-9_]+)=(.*)$`)
29
- );
25
+ const plainMatch = line.match(new RegExp(`^${VAULT_VAR_PREFIX}([A-Za-z0-9_]+)=(.*)$`));
30
26
  if (!plainMatch) {
31
- throw new VaultError(
32
- `Invalid vault file format at line ${lineNumber}: "${line}"`,
33
- {
34
- operation: "parse",
35
- hint: `Each environment entry should be in the format: ${VAULT_VAR_PREFIX}{ENVIRONMENT}="encrypted:..."`
36
- }
37
- );
27
+ throw new VaultError(`Invalid vault file format at line ${lineNumber}: "${line}"`, {
28
+ operation: "parse",
29
+ hint: `Each environment entry should be in the format: ${VAULT_VAR_PREFIX}{ENVIRONMENT}="encrypted:..."`
30
+ });
38
31
  }
39
32
  const envName2 = plainMatch[1].toLowerCase();
40
33
  const encryptedValue2 = plainMatch[2];
@@ -87,41 +80,32 @@ async function readVaultFile(path) {
87
80
  return parseVaultFile(content);
88
81
  } catch (error) {
89
82
  if (error instanceof VaultError) throw error;
90
- throw new VaultError(
91
- `Failed to read vault file "${path}"`,
92
- {
93
- operation: "read",
94
- /* v8 ignore start */
95
- cause: error instanceof Error ? error : void 0
96
- /* v8 ignore stop */
97
- }
98
- );
83
+ throw new VaultError(`Failed to read vault file "${path}"`, {
84
+ operation: "read",
85
+ /* v8 ignore start */
86
+ cause: error instanceof Error ? error : void 0
87
+ /* v8 ignore stop */
88
+ });
99
89
  }
100
90
  }
101
91
  async function writeVaultFile(path, environments) {
102
92
  if (environments.size === 0) {
103
- throw new VaultError(
104
- "Cannot write an empty vault file",
105
- {
106
- operation: "write",
107
- hint: "Add at least one environment to the vault before writing."
108
- }
109
- );
93
+ throw new VaultError("Cannot write an empty vault file", {
94
+ operation: "write",
95
+ hint: "Add at least one environment to the vault before writing."
96
+ });
110
97
  }
111
98
  try {
112
99
  const content = serializeVaultFile(environments);
113
100
  await writeFile(path, content, "utf-8");
114
101
  } catch (error) {
115
102
  if (error instanceof VaultError) throw error;
116
- throw new VaultError(
117
- `Failed to write vault file "${path}"`,
118
- {
119
- operation: "write",
120
- /* v8 ignore start */
121
- cause: error instanceof Error ? error : void 0
122
- /* v8 ignore stop */
123
- }
124
- );
103
+ throw new VaultError(`Failed to write vault file "${path}"`, {
104
+ operation: "write",
105
+ /* v8 ignore start */
106
+ cause: error instanceof Error ? error : void 0
107
+ /* v8 ignore stop */
108
+ });
125
109
  }
126
110
  }
127
111
  function getEnvironmentData(vault, env) {
@@ -20,13 +20,7 @@ function ultraenvPlugin(fastify, options = {}, done) {
20
20
  }
21
21
  const allowSet = new Set(allowList.map((k) => k.toUpperCase()));
22
22
  const denySet = new Set(denyList.map((k) => k.toUpperCase()));
23
- const filteredEnv = buildFastifyEnv(
24
- source,
25
- allPrefixes,
26
- allowSet,
27
- denySet,
28
- exposeNodeEnv
29
- );
23
+ const filteredEnv = buildFastifyEnv(source, allPrefixes, allowSet, denySet, exposeNodeEnv);
30
24
  fastify.decorate("env", filteredEnv);
31
25
  done();
32
26
  }
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  writeFile
3
- } from "./chunk-3VYXPTYV.js";
3
+ } from "./chunk-FSKVYBEP.js";
4
4
 
5
5
  // src/typegen/json-schema.ts
6
6
  var JSON_SCHEMA_DRAFT_07 = "http://json-schema.org/draft-07/schema#";