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
package/dist/index.cjs CHANGED
@@ -470,7 +470,13 @@ var FileSystemError = class extends UltraenvError {
470
470
  code;
471
471
  constructor(message, options = {}) {
472
472
  const fsCode = options.code ?? options.cause?.code ?? "UNKNOWN";
473
- const opHint = options.path !== void 0 ? `Could not ${options.operation ?? "access"} "${options.path}".` : "";
473
+ const opHint = options.path !== void 0 ? (
474
+ /* v8 ignore start */
475
+ `Could not ${options.operation ?? "access"} "${options.path}".`
476
+ ) : (
477
+ /* v8 ignore stop */
478
+ ""
479
+ );
474
480
  super(message, {
475
481
  code: `FS_${fsCode}`,
476
482
  hint: options.hint ?? `${opHint} Ensure the file exists and you have the necessary permissions.`,
@@ -526,14 +532,11 @@ function resolveEscapeSequence(chars, startIndex, filePath, lineNumber) {
526
532
  }
527
533
  return { resolved: String.fromCodePoint(codePoint), charsConsumed: 4 };
528
534
  }
529
- throw new ParseError(
530
- `Invalid hex escape sequence: ${"\\"}x${hex}`,
531
- {
532
- line: lineNumber,
533
- filePath,
534
- hint: "Hex escapes must be exactly 2 hex digits, e.g. \\x0A for newline."
535
- }
536
- );
535
+ throw new ParseError(`Invalid hex escape sequence: ${"\\"}x${hex}`, {
536
+ line: lineNumber,
537
+ filePath,
538
+ hint: "Hex escapes must be exactly 2 hex digits, e.g. \\x0A for newline."
539
+ });
537
540
  }
538
541
  case "u":
539
542
  case "U": {
@@ -548,14 +551,11 @@ function resolveEscapeSequence(chars, startIndex, filePath, lineNumber) {
548
551
  }
549
552
  return { resolved: String.fromCodePoint(codePoint), charsConsumed: 6 };
550
553
  }
551
- throw new ParseError(
552
- `Invalid unicode escape sequence: ${"\\"}u${hexDigits}`,
553
- {
554
- line: lineNumber,
555
- filePath,
556
- hint: 'Unicode escapes must be exactly 4 hex digits, e.g. \\u0041 for "A".'
557
- }
558
- );
554
+ throw new ParseError(`Invalid unicode escape sequence: ${"\\"}u${hexDigits}`, {
555
+ line: lineNumber,
556
+ filePath,
557
+ hint: 'Unicode escapes must be exactly 4 hex digits, e.g. \\u0041 for "A".'
558
+ });
559
559
  }
560
560
  /* v8 ignore start */
561
561
  default: {
@@ -837,11 +837,7 @@ function parseEnvFile(content, filePath) {
837
837
  comment = trimmedAfter.slice(1).trim();
838
838
  }
839
839
  } else if (firstChar === "'") {
840
- const result = parseSingleQuotedValue(
841
- lines,
842
- lineIndex,
843
- valueStartIndex + 1
844
- );
840
+ const result = parseSingleQuotedValue(lines, lineIndex, valueStartIndex + 1);
845
841
  if (!result.closed) {
846
842
  throw new ParseError("Unterminated single-quoted string", {
847
843
  line: oneBasedLine,
@@ -862,11 +858,7 @@ function parseEnvFile(content, filePath) {
862
858
  comment = trimmedAfter.slice(1).trim();
863
859
  }
864
860
  } else if (firstChar === "`") {
865
- const result = parseBacktickQuotedValue(
866
- lines,
867
- lineIndex,
868
- valueStartIndex + 1
869
- );
861
+ const result = parseBacktickQuotedValue(lines, lineIndex, valueStartIndex + 1);
870
862
  if (!result.closed) {
871
863
  throw new ParseError("Unterminated backtick-quoted string", {
872
864
  line: oneBasedLine,
@@ -1087,12 +1079,9 @@ function expandVariables(vars, env, options) {
1087
1079
  const resolving = /* @__PURE__ */ new Set();
1088
1080
  function expandValue(raw, depth) {
1089
1081
  if (depth > maxDepth) {
1090
- throw new InterpolationError(
1091
- `Maximum interpolation depth (${maxDepth}) exceeded`,
1092
- {
1093
- hint: "Check for deeply nested variable references. Consider simplifying your variable definitions."
1094
- }
1095
- );
1082
+ throw new InterpolationError(`Maximum interpolation depth (${maxDepth}) exceeded`, {
1083
+ hint: "Check for deeply nested variable references. Consider simplifying your variable definitions."
1084
+ });
1096
1085
  }
1097
1086
  const result2 = [];
1098
1087
  let i = 0;
@@ -1128,14 +1117,11 @@ function expandVariables(vars, env, options) {
1128
1117
  const parsed = parseExpression(inner);
1129
1118
  if (resolving.has(parsed.varName)) {
1130
1119
  const chain = Array.from(resolving).concat(parsed.varName).join(" \u2192 ");
1131
- throw new InterpolationError(
1132
- `Circular variable reference detected: ${chain}`,
1133
- {
1134
- variable: parsed.varName,
1135
- circular: true,
1136
- hint: "Break the cycle by removing one of the circular references."
1137
- }
1138
- );
1120
+ throw new InterpolationError(`Circular variable reference detected: ${chain}`, {
1121
+ variable: parsed.varName,
1122
+ circular: true,
1123
+ hint: "Break the cycle by removing one of the circular references."
1124
+ });
1139
1125
  }
1140
1126
  resolving.add(parsed.varName);
1141
1127
  if (parsed.varName in vars && !(parsed.varName in resolvedMap)) {
@@ -1166,14 +1152,11 @@ function expandVariables(vars, env, options) {
1166
1152
  const varName = raw.slice(i, nameEnd);
1167
1153
  if (resolving.has(varName)) {
1168
1154
  const chain = Array.from(resolving).concat(varName).join(" \u2192 ");
1169
- throw new InterpolationError(
1170
- `Circular variable reference detected: ${chain}`,
1171
- {
1172
- variable: varName,
1173
- circular: true,
1174
- hint: "Break the cycle by removing one of the circular references."
1175
- }
1176
- );
1155
+ throw new InterpolationError(`Circular variable reference detected: ${chain}`, {
1156
+ variable: varName,
1157
+ circular: true,
1158
+ hint: "Break the cycle by removing one of the circular references."
1159
+ });
1177
1160
  }
1178
1161
  resolving.add(varName);
1179
1162
  if (varName in vars && !(varName in resolvedMap)) {
@@ -1949,7 +1932,8 @@ function parseYamlScalar(value) {
1949
1932
  if (cleanValue === "") return "";
1950
1933
  if (cleanValue === "true" || cleanValue === "True" || cleanValue === "TRUE") return true;
1951
1934
  if (cleanValue === "false" || cleanValue === "False" || cleanValue === "FALSE") return false;
1952
- if (cleanValue === "null" || cleanValue === "Null" || cleanValue === "NULL" || cleanValue === "~") return null;
1935
+ if (cleanValue === "null" || cleanValue === "Null" || cleanValue === "NULL" || cleanValue === "~")
1936
+ return null;
1953
1937
  if (/^-?\d+$/.test(cleanValue)) return parseInt(cleanValue, 10);
1954
1938
  if (/^-?\d+\.\d+$/.test(cleanValue)) return parseFloat(cleanValue);
1955
1939
  if (cleanValue.startsWith('"') && cleanValue.endsWith('"') || cleanValue.startsWith("'") && cleanValue.endsWith("'")) {
@@ -2329,9 +2313,7 @@ function resolveVariables(vars, schema, aliasMap) {
2329
2313
  result[key] = vars[key];
2330
2314
  continue;
2331
2315
  }
2332
- const caseInsensitiveKey = Object.keys(vars).find(
2333
- (k) => k.toLowerCase() === key.toLowerCase()
2334
- );
2316
+ const caseInsensitiveKey = Object.keys(vars).find((k) => k.toLowerCase() === key.toLowerCase());
2335
2317
  if (caseInsensitiveKey !== void 0 && vars[caseInsensitiveKey] !== void 0) {
2336
2318
  result[key] = vars[caseInsensitiveKey];
2337
2319
  continue;
@@ -2344,9 +2326,7 @@ function resolveVariables(vars, schema, aliasMap) {
2344
2326
  foundAlias = true;
2345
2327
  break;
2346
2328
  }
2347
- const ciAlias = Object.keys(vars).find(
2348
- (k) => k.toLowerCase() === alias.toLowerCase()
2349
- );
2329
+ const ciAlias = Object.keys(vars).find((k) => k.toLowerCase() === alias.toLowerCase());
2350
2330
  if (ciAlias !== void 0 && vars[ciAlias] !== void 0) {
2351
2331
  result[key] = vars[ciAlias];
2352
2332
  foundAlias = true;
@@ -3496,7 +3476,10 @@ function parseAndValidateEmail(raw, opts) {
3496
3476
  return { success: false, error: "Email must not be empty" };
3497
3477
  }
3498
3478
  if (trimmed.length > maxLen) {
3499
- return { success: false, error: `Email must be at most ${maxLen} characters, got ${trimmed.length}` };
3479
+ return {
3480
+ success: false,
3481
+ error: `Email must be at most ${maxLen} characters, got ${trimmed.length}`
3482
+ };
3500
3483
  }
3501
3484
  if (!EMAIL_REGEX2.test(trimmed)) {
3502
3485
  return { success: false, error: `"${trimmed}" is not a valid email address` };
@@ -3505,7 +3488,10 @@ function parseAndValidateEmail(raw, opts) {
3505
3488
  const localPart = trimmed.slice(0, atIndex);
3506
3489
  const domain = trimmed.slice(atIndex + 1);
3507
3490
  if (localPart.length > maxLocal) {
3508
- return { success: false, error: `Email local part must be at most ${maxLocal} characters, got ${localPart.length}` };
3491
+ return {
3492
+ success: false,
3493
+ error: `Email local part must be at most ${maxLocal} characters, got ${localPart.length}`
3494
+ };
3509
3495
  }
3510
3496
  if (opts.allowPlusAddressing === false && localPart.includes("+")) {
3511
3497
  return { success: false, error: "Plus addressing (+) is not allowed" };
@@ -3514,7 +3500,10 @@ function parseAndValidateEmail(raw, opts) {
3514
3500
  const tld = domain.split(".").pop() ?? "";
3515
3501
  const allowed = opts.allowedTlds.map((t2) => t2.toLowerCase());
3516
3502
  if (!allowed.includes(tld.toLowerCase())) {
3517
- return { success: false, error: `Email TLD must be one of: ${allowed.join(", ")}. Got ".${tld}"` };
3503
+ return {
3504
+ success: false,
3505
+ error: `Email TLD must be one of: ${allowed.join(", ")}. Got ".${tld}"`
3506
+ };
3518
3507
  }
3519
3508
  }
3520
3509
  if (opts.blockedDomains !== void 0) {
@@ -3549,7 +3538,10 @@ function parseAndValidateIp(raw, opts) {
3549
3538
  }
3550
3539
  if (version === "6" && !isV6) {
3551
3540
  if (opts.allowMappedV4 === false && isMappedV4) {
3552
- return { success: false, error: `"${trimmed}" is an IPv4-mapped IPv6 address, which is not allowed` };
3541
+ return {
3542
+ success: false,
3543
+ error: `"${trimmed}" is an IPv4-mapped IPv6 address, which is not allowed`
3544
+ };
3553
3545
  }
3554
3546
  return { success: false, error: `"${trimmed}" is not a valid IPv6 address` };
3555
3547
  }
@@ -3557,7 +3549,10 @@ function parseAndValidateIp(raw, opts) {
3557
3549
  return { success: false, error: `"${trimmed}" is not a valid IP address` };
3558
3550
  }
3559
3551
  if (version === "6" && isMappedV4 && opts.allowMappedV4 === false) {
3560
- return { success: false, error: `"${trimmed}" is an IPv4-mapped IPv6 address, which is not allowed` };
3552
+ return {
3553
+ success: false,
3554
+ error: `"${trimmed}" is an IPv4-mapped IPv6 address, which is not allowed`
3555
+ };
3561
3556
  }
3562
3557
  return { success: true, value: trimmed };
3563
3558
  }
@@ -3906,7 +3901,9 @@ function createBase64Schema(opts) {
3906
3901
  var SEMVER_CORE = "(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)";
3907
3902
  var SEMVER_PRERELEASE = "(?:-((?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[a-zA-Z-][0-9a-zA-Z-]*))*))";
3908
3903
  var SEMVER_BUILD = "(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))";
3909
- var STRICT_SEMVER_REGEX = new RegExp(`^${SEMVER_CORE}(?:${SEMVER_PRERELEASE})?(?:${SEMVER_BUILD})?$`);
3904
+ var STRICT_SEMVER_REGEX = new RegExp(
3905
+ `^${SEMVER_CORE}(?:${SEMVER_PRERELEASE})?(?:${SEMVER_BUILD})?$`
3906
+ );
3910
3907
  var LOOSE_SEMVER_REGEX = /^v?(0|[1-9]\d*)(?:\.(0|[1-9]\d*))?(?:\.(0|[1-9]\d*))?(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/;
3911
3908
  function parseAndValidateSemver(raw, opts) {
3912
3909
  const trimmed = raw.trim();
@@ -3928,7 +3925,9 @@ function parseAndValidateSemver(raw, opts) {
3928
3925
  };
3929
3926
  }
3930
3927
  if (!loose) {
3931
- const match = content.match(new RegExp(`^${SEMVER_CORE}(?:${SEMVER_PRERELEASE})?(?:${SEMVER_BUILD})?$`));
3928
+ const match = content.match(
3929
+ new RegExp(`^${SEMVER_CORE}(?:${SEMVER_PRERELEASE})?(?:${SEMVER_BUILD})?$`)
3930
+ );
3932
3931
  if (match) {
3933
3932
  const prerelease = match[4];
3934
3933
  const build = match[5];
@@ -4032,7 +4031,14 @@ function parseAndValidateCron(raw, opts) {
4032
4031
  }
4033
4032
  const fields = trimmed.split(/\s+/);
4034
4033
  if (opts.allowSeconds === true && fields.length === 6) {
4035
- const ranges = [[0, 59], [0, 59], [0, 23], [1, 31], [1, 12], [0, 6]];
4034
+ const ranges = [
4035
+ [0, 59],
4036
+ [0, 59],
4037
+ [0, 23],
4038
+ [1, 31],
4039
+ [1, 12],
4040
+ [0, 6]
4041
+ ];
4036
4042
  for (let i = 0; i < fields.length; i++) {
4037
4043
  const range = ranges[i] ?? [0, 59];
4038
4044
  const error = validateCronField(fields[i] ?? "", range[0] ?? 0, range[1] ?? 0);
@@ -4041,7 +4047,14 @@ function parseAndValidateCron(raw, opts) {
4041
4047
  return { success: true, value: trimmed };
4042
4048
  }
4043
4049
  if (opts.allowYear === true && fields.length === 6) {
4044
- const ranges = [[0, 59], [0, 23], [1, 31], [1, 12], [0, 6], [1970, 2099]];
4050
+ const ranges = [
4051
+ [0, 59],
4052
+ [0, 23],
4053
+ [1, 31],
4054
+ [1, 12],
4055
+ [0, 6],
4056
+ [1970, 2099]
4057
+ ];
4045
4058
  for (let i = 0; i < fields.length; i++) {
4046
4059
  const range = ranges[i] ?? [0, 59];
4047
4060
  const error = validateCronField(fields[i] ?? "", range[0] ?? 0, range[1] ?? 0);
@@ -4050,7 +4063,13 @@ function parseAndValidateCron(raw, opts) {
4050
4063
  return { success: true, value: trimmed };
4051
4064
  }
4052
4065
  if (fields.length === 5) {
4053
- const ranges = [[0, 59], [0, 23], [1, 31], [1, 12], [0, 6]];
4066
+ const ranges = [
4067
+ [0, 59],
4068
+ [0, 23],
4069
+ [1, 31],
4070
+ [1, 12],
4071
+ [0, 6]
4072
+ ];
4054
4073
  for (let i = 0; i < fields.length; i++) {
4055
4074
  const range = ranges[i] ?? [0, 59];
4056
4075
  const error = validateCronField(fields[i] ?? "", range[0] ?? 0, range[1] ?? 0);
@@ -5639,10 +5658,8 @@ function defineEnv(schema, vars, options) {
5639
5658
  const messages = result.errors.map((e) => ` - ${e.field}: ${e.message}`).join("\n");
5640
5659
  const unknownMsg = result.unknown.length > 0 ? `
5641
5660
  Unknown variables: ${result.unknown.join(", ")}` : "";
5642
- throw new Error(
5643
- `Environment validation failed:
5644
- ${messages}${unknownMsg}`
5645
- );
5661
+ throw new Error(`Environment validation failed:
5662
+ ${messages}${unknownMsg}`);
5646
5663
  }
5647
5664
  return result.values;
5648
5665
  }
@@ -5789,11 +5806,15 @@ var EnvFileWatcher = class {
5789
5806
  if (this.state.nativeWatchers.has(filePath)) return;
5790
5807
  if (this.shouldIgnore(filePath)) return;
5791
5808
  try {
5792
- const nativeWatcher = (0, import_node_fs4.watch)(filePath, {
5793
- persistent: true
5794
- }, (eventType, filename) => {
5795
- this.handleFileEvent(eventType, filePath, filename);
5796
- });
5809
+ const nativeWatcher = (0, import_node_fs4.watch)(
5810
+ filePath,
5811
+ {
5812
+ persistent: true
5813
+ },
5814
+ (eventType, filename) => {
5815
+ this.handleFileEvent(eventType, filePath, filename);
5816
+ }
5817
+ );
5797
5818
  nativeWatcher.on("error", () => {
5798
5819
  this.emitChangeEvent(filePath);
5799
5820
  this.state.nativeWatchers.delete(filePath);
@@ -5819,27 +5840,31 @@ var EnvFileWatcher = class {
5819
5840
  const dirWatchKey = `__dir__:${dirPath}`;
5820
5841
  if (this.state.nativeWatchers.has(dirWatchKey)) return;
5821
5842
  try {
5822
- const nativeWatcher = (0, import_node_fs4.watch)(dirPath, {
5823
- persistent: true
5824
- }, (eventType, filename) => {
5825
- if (filename === null) return;
5826
- const fullPath = (0, import_node_path4.resolve)((0, import_node_path4.join)(dirPath, filename));
5827
- if (isEnvFileName(filename) && !this.shouldIgnore(fullPath)) {
5828
- if (eventType === "rename") {
5829
- if ((0, import_node_fs5.existsSync)(fullPath) && !this.state.nativeWatchers.has(fullPath)) {
5830
- this.watchFile(fullPath);
5831
- this.debouncedEmit(fullPath, "add");
5832
- } else if (!(0, import_node_fs5.existsSync)(fullPath) && this.state.nativeWatchers.has(fullPath)) {
5833
- const watcher = this.state.nativeWatchers.get(fullPath);
5834
- if (watcher !== void 0) {
5835
- watcher.close();
5836
- this.state.nativeWatchers.delete(fullPath);
5843
+ const nativeWatcher = (0, import_node_fs4.watch)(
5844
+ dirPath,
5845
+ {
5846
+ persistent: true
5847
+ },
5848
+ (eventType, filename) => {
5849
+ if (filename === null) return;
5850
+ const fullPath = (0, import_node_path4.resolve)((0, import_node_path4.join)(dirPath, filename));
5851
+ if (isEnvFileName(filename) && !this.shouldIgnore(fullPath)) {
5852
+ if (eventType === "rename") {
5853
+ if ((0, import_node_fs5.existsSync)(fullPath) && !this.state.nativeWatchers.has(fullPath)) {
5854
+ this.watchFile(fullPath);
5855
+ this.debouncedEmit(fullPath, "add");
5856
+ } else if (!(0, import_node_fs5.existsSync)(fullPath) && this.state.nativeWatchers.has(fullPath)) {
5857
+ const watcher = this.state.nativeWatchers.get(fullPath);
5858
+ if (watcher !== void 0) {
5859
+ watcher.close();
5860
+ this.state.nativeWatchers.delete(fullPath);
5861
+ }
5862
+ this.debouncedEmit(fullPath, "unlink");
5837
5863
  }
5838
- this.debouncedEmit(fullPath, "unlink");
5839
5864
  }
5840
5865
  }
5841
5866
  }
5842
- });
5867
+ );
5843
5868
  nativeWatcher.on("error", () => {
5844
5869
  this.state.nativeWatchers.delete(dirWatchKey);
5845
5870
  setTimeout(() => {
@@ -5964,11 +5989,7 @@ function manualHkdf(ikm, salt, info, length) {
5964
5989
  const okm = Buffer.alloc(length);
5965
5990
  let previous = Buffer.alloc(0);
5966
5991
  for (let i = 1; i <= n; i++) {
5967
- const hmacData = Buffer.concat([
5968
- previous,
5969
- infoBuffer,
5970
- Buffer.from([i])
5971
- ]);
5992
+ const hmacData = Buffer.concat([previous, infoBuffer, Buffer.from([i])]);
5972
5993
  previous = (0, import_node_crypto.createHmac)("sha256", prk).update(hmacData).digest();
5973
5994
  const offset = (i - 1) * hashLen;
5974
5995
  const copyLen = Math.min(hashLen, length - offset);
@@ -5985,10 +6006,7 @@ function encrypt(key, plaintext) {
5985
6006
  const iv = (0, import_node_crypto.randomBytes)(12);
5986
6007
  const algo = `aes-${key.length * 8}-gcm`;
5987
6008
  const cipher = (0, import_node_crypto.createCipheriv)(algo, key, iv);
5988
- const ciphertext = Buffer.concat([
5989
- cipher.update(plaintext),
5990
- cipher.final()
5991
- ]);
6009
+ const ciphertext = Buffer.concat([cipher.update(plaintext), cipher.final()]);
5992
6010
  const authTag = cipher.getAuthTag();
5993
6011
  return { iv, authTag, ciphertext };
5994
6012
  }
@@ -6002,10 +6020,7 @@ function decrypt(key, iv, authTag, ciphertext) {
6002
6020
  const decipher = (0, import_node_crypto.createDecipheriv)(algo, key, iv);
6003
6021
  decipher.setAuthTag(authTag);
6004
6022
  try {
6005
- return Buffer.concat([
6006
- decipher.update(ciphertext),
6007
- decipher.final()
6008
- ]);
6023
+ return Buffer.concat([decipher.update(ciphertext), decipher.final()]);
6009
6024
  } catch (error) {
6010
6025
  const message = error instanceof Error ? error.message : String(error);
6011
6026
  throw new Error(
@@ -6037,14 +6052,15 @@ function encryptEnvironment(data, key) {
6037
6052
  if (key.length !== 32) {
6038
6053
  throw new EncryptionError(
6039
6054
  `Invalid key length: expected 32 bytes for AES-256, got ${key.length}`,
6040
- { hint: "Generate a new key using generateMasterKey() or ensure you are using the correct key file." }
6055
+ {
6056
+ hint: "Generate a new key using generateMasterKey() or ensure you are using the correct key file."
6057
+ }
6041
6058
  );
6042
6059
  }
6043
6060
  if (Object.keys(data).length === 0) {
6044
- throw new EncryptionError(
6045
- "Cannot encrypt empty environment data",
6046
- { hint: "Provide at least one environment variable to encrypt." }
6047
- );
6061
+ throw new EncryptionError("Cannot encrypt empty environment data", {
6062
+ hint: "Provide at least one environment variable to encrypt."
6063
+ });
6048
6064
  }
6049
6065
  try {
6050
6066
  const serialized = serializeEnvData(data);
@@ -6073,7 +6089,9 @@ function decryptEnvironment(encrypted, key) {
6073
6089
  if (encrypted.algorithm !== ENCRYPTION_ALGORITHM) {
6074
6090
  throw new EncryptionError(
6075
6091
  `Unsupported algorithm: "${encrypted.algorithm}". Expected "${ENCRYPTION_ALGORITHM}".`,
6076
- { hint: "This vault was encrypted with a different algorithm. You may need to migrate the vault." }
6092
+ {
6093
+ hint: "This vault was encrypted with a different algorithm. You may need to migrate the vault."
6094
+ }
6077
6095
  );
6078
6096
  }
6079
6097
  if (encrypted.iv.length !== IV_LENGTH) {
@@ -6130,12 +6148,9 @@ function decryptValue(encrypted, key) {
6130
6148
  );
6131
6149
  }
6132
6150
  if (!encrypted.startsWith(ENCRYPTED_PREFIX)) {
6133
- throw new EncryptionError(
6134
- "Invalid encrypted value format: missing required prefix",
6135
- {
6136
- hint: `Expected the value to start with "${ENCRYPTED_PREFIX}". This value may not have been encrypted by ultraenv.`
6137
- }
6138
- );
6151
+ throw new EncryptionError("Invalid encrypted value format: missing required prefix", {
6152
+ hint: `Expected the value to start with "${ENCRYPTED_PREFIX}". This value may not have been encrypted by ultraenv.`
6153
+ });
6139
6154
  }
6140
6155
  const payload = encrypted.slice(ENCRYPTED_PREFIX.length);
6141
6156
  const parts = payload.split(":");
@@ -6151,16 +6166,14 @@ function decryptValue(encrypted, key) {
6151
6166
  const authTagB64 = parts[1];
6152
6167
  const ciphertextB64 = parts[2];
6153
6168
  if (ivB64 === void 0 || authTagB64 === void 0 || ciphertextB64 === void 0) {
6154
- throw new EncryptionError(
6155
- "Invalid encrypted value: unexpected component structure",
6156
- { hint: "The encrypted data may be corrupted. Try re-encrypting the value." }
6157
- );
6169
+ throw new EncryptionError("Invalid encrypted value: unexpected component structure", {
6170
+ hint: "The encrypted data may be corrupted. Try re-encrypting the value."
6171
+ });
6158
6172
  }
6159
6173
  if (ivB64.length === 0 || authTagB64.length === 0 || ciphertextB64.length === 0) {
6160
- throw new EncryptionError(
6161
- "Invalid encrypted value: one or more base64 components are empty",
6162
- { hint: "The encrypted data may be corrupted. Try re-encrypting the value." }
6163
- );
6174
+ throw new EncryptionError("Invalid encrypted value: one or more base64 components are empty", {
6175
+ hint: "The encrypted data may be corrupted. Try re-encrypting the value."
6176
+ });
6164
6177
  }
6165
6178
  try {
6166
6179
  const iv = base64ToBuffer(ivB64);
@@ -6169,7 +6182,9 @@ function decryptValue(encrypted, key) {
6169
6182
  if (iv.length !== IV_LENGTH) {
6170
6183
  throw new EncryptionError(
6171
6184
  `Invalid IV length: expected ${IV_LENGTH} bytes, got ${iv.length}`,
6172
- { hint: "The encrypted data may be corrupted or was produced by a different version of ultraenv." }
6185
+ {
6186
+ hint: "The encrypted data may be corrupted or was produced by a different version of ultraenv."
6187
+ }
6173
6188
  );
6174
6189
  }
6175
6190
  if (authTag.length !== AUTH_TAG_LENGTH) {
@@ -6184,10 +6199,9 @@ function decryptValue(encrypted, key) {
6184
6199
  if (error instanceof EncryptionError) throw error;
6185
6200
  const message = error instanceof Error ? error.message : String(error);
6186
6201
  if (message.includes("Invalid") || message.includes("base64")) {
6187
- throw new EncryptionError(
6188
- "Invalid base64 encoding in encrypted value",
6189
- { hint: "The encrypted data may be corrupted. Ensure the value was not modified." }
6190
- );
6202
+ throw new EncryptionError("Invalid base64 encoding in encrypted value", {
6203
+ hint: "The encrypted data may be corrupted. Ensure the value was not modified."
6204
+ });
6191
6205
  }
6192
6206
  throw new EncryptionError(
6193
6207
  "Failed to decrypt value. The key may be incorrect or the ciphertext was tampered with.",
@@ -6217,10 +6231,9 @@ function deriveEnvironmentKey(masterKey, environment) {
6217
6231
  );
6218
6232
  }
6219
6233
  if (environment.length === 0) {
6220
- throw new EncryptionError(
6221
- "Environment name cannot be empty",
6222
- { hint: 'Provide a valid environment name (e.g., "development", "production").' }
6223
- );
6234
+ throw new EncryptionError("Environment name cannot be empty", {
6235
+ hint: 'Provide a valid environment name (e.g., "development", "production").'
6236
+ });
6224
6237
  }
6225
6238
  if (HKDF_SALT.length < DEFAULT_SALT_LENGTH) {
6226
6239
  const paddedSalt = Buffer.alloc(DEFAULT_SALT_LENGTH);
@@ -6232,12 +6245,7 @@ function deriveEnvironmentKey(masterKey, environment) {
6232
6245
  DEFAULT_KEY_LENGTH
6233
6246
  );
6234
6247
  }
6235
- return deriveKey(
6236
- masterKey,
6237
- HKDF_SALT,
6238
- `${HKDF_INFO_PREFIX}${environment}`,
6239
- DEFAULT_KEY_LENGTH
6240
- );
6248
+ return deriveKey(masterKey, HKDF_SALT, `${HKDF_INFO_PREFIX}${environment}`, DEFAULT_KEY_LENGTH);
6241
6249
  }
6242
6250
  function formatKey(key) {
6243
6251
  if (key.length === 0) {
@@ -6257,21 +6265,17 @@ function parseKey2(formatted) {
6257
6265
  }
6258
6266
  const base64Part = formatted.slice(KEY_PREFIX.length);
6259
6267
  if (base64Part.length === 0) {
6260
- throw new EncryptionError(
6261
- "Invalid key format: base64 payload is empty after prefix",
6262
- { hint: "The key appears to be truncated. Generate a new key." }
6263
- );
6268
+ throw new EncryptionError("Invalid key format: base64 payload is empty after prefix", {
6269
+ hint: "The key appears to be truncated. Generate a new key."
6270
+ });
6264
6271
  }
6265
6272
  try {
6266
6273
  return base64ToBuffer(base64Part);
6267
6274
  } catch (error) {
6268
- throw new EncryptionError(
6269
- "Failed to decode key: invalid base64 encoding",
6270
- {
6271
- cause: error instanceof Error ? error : void 0,
6272
- hint: 'The key may be corrupted. Generate a new key with "ultraenv key generate".'
6273
- }
6274
- );
6275
+ throw new EncryptionError("Failed to decode key: invalid base64 encoding", {
6276
+ cause: error instanceof Error ? error : void 0,
6277
+ hint: 'The key may be corrupted. Generate a new key with "ultraenv key generate".'
6278
+ });
6275
6279
  }
6276
6280
  }
6277
6281
  function isValidKeyFormat(formatted) {
@@ -6333,12 +6337,9 @@ function parseKeysFile(content) {
6333
6337
  if (!eqMatch) {
6334
6338
  const plainMatch = line.match(/^ULTRAENV_KEY_([A-Za-z0-9_]+)=(.*)$/);
6335
6339
  if (!plainMatch) {
6336
- throw new EncryptionError(
6337
- `Invalid keys file format at line ${i + 1}: "${line}"`,
6338
- {
6339
- hint: 'Each key entry should be in the format: ULTRAENV_KEY_{ENVIRONMENT}="ultraenv_key_v1_..."'
6340
- }
6341
- );
6340
+ throw new EncryptionError(`Invalid keys file format at line ${i + 1}: "${line}"`, {
6341
+ hint: 'Each key entry should be in the format: ULTRAENV_KEY_{ENVIRONMENT}="ultraenv_key_v1_..."'
6342
+ });
6342
6343
  }
6343
6344
  const envName2 = plainMatch[1].toLowerCase();
6344
6345
  const keyValue2 = plainMatch[2];
@@ -6379,21 +6380,14 @@ function parseVaultFile(content) {
6379
6380
  if (rawLine === void 0) continue;
6380
6381
  const line = rawLine.trim();
6381
6382
  if (line.length === 0 || line.startsWith("#")) continue;
6382
- const match = line.match(
6383
- new RegExp(`^${VAULT_VAR_PREFIX}([A-Za-z0-9_]+)="(.*)"$`)
6384
- );
6383
+ const match = line.match(new RegExp(`^${VAULT_VAR_PREFIX}([A-Za-z0-9_]+)="(.*)"$`));
6385
6384
  if (!match) {
6386
- const plainMatch = line.match(
6387
- new RegExp(`^${VAULT_VAR_PREFIX}([A-Za-z0-9_]+)=(.*)$`)
6388
- );
6385
+ const plainMatch = line.match(new RegExp(`^${VAULT_VAR_PREFIX}([A-Za-z0-9_]+)=(.*)$`));
6389
6386
  if (!plainMatch) {
6390
- throw new VaultError(
6391
- `Invalid vault file format at line ${lineNumber}: "${line}"`,
6392
- {
6393
- operation: "parse",
6394
- hint: `Each environment entry should be in the format: ${VAULT_VAR_PREFIX}{ENVIRONMENT}="encrypted:..."`
6395
- }
6396
- );
6387
+ throw new VaultError(`Invalid vault file format at line ${lineNumber}: "${line}"`, {
6388
+ operation: "parse",
6389
+ hint: `Each environment entry should be in the format: ${VAULT_VAR_PREFIX}{ENVIRONMENT}="encrypted:..."`
6390
+ });
6397
6391
  }
6398
6392
  const envName2 = plainMatch[1].toLowerCase();
6399
6393
  const encryptedValue2 = plainMatch[2];
@@ -6446,41 +6440,32 @@ async function readVaultFile(path) {
6446
6440
  return parseVaultFile(content);
6447
6441
  } catch (error) {
6448
6442
  if (error instanceof VaultError) throw error;
6449
- throw new VaultError(
6450
- `Failed to read vault file "${path}"`,
6451
- {
6452
- operation: "read",
6453
- /* v8 ignore start */
6454
- cause: error instanceof Error ? error : void 0
6455
- /* v8 ignore stop */
6456
- }
6457
- );
6443
+ throw new VaultError(`Failed to read vault file "${path}"`, {
6444
+ operation: "read",
6445
+ /* v8 ignore start */
6446
+ cause: error instanceof Error ? error : void 0
6447
+ /* v8 ignore stop */
6448
+ });
6458
6449
  }
6459
6450
  }
6460
6451
  async function writeVaultFile(path, environments) {
6461
6452
  if (environments.size === 0) {
6462
- throw new VaultError(
6463
- "Cannot write an empty vault file",
6464
- {
6465
- operation: "write",
6466
- hint: "Add at least one environment to the vault before writing."
6467
- }
6468
- );
6453
+ throw new VaultError("Cannot write an empty vault file", {
6454
+ operation: "write",
6455
+ hint: "Add at least one environment to the vault before writing."
6456
+ });
6469
6457
  }
6470
6458
  try {
6471
6459
  const content = serializeVaultFile(environments);
6472
6460
  await writeFile(path, content, "utf-8");
6473
6461
  } catch (error) {
6474
6462
  if (error instanceof VaultError) throw error;
6475
- throw new VaultError(
6476
- `Failed to write vault file "${path}"`,
6477
- {
6478
- operation: "write",
6479
- /* v8 ignore start */
6480
- cause: error instanceof Error ? error : void 0
6481
- /* v8 ignore stop */
6482
- }
6483
- );
6463
+ throw new VaultError(`Failed to write vault file "${path}"`, {
6464
+ operation: "write",
6465
+ /* v8 ignore start */
6466
+ cause: error instanceof Error ? error : void 0
6467
+ /* v8 ignore stop */
6468
+ });
6484
6469
  }
6485
6470
  }
6486
6471
  function getEnvironmentData(vault, env) {
@@ -6513,16 +6498,14 @@ var HMAC_ALGORITHM = "sha256";
6513
6498
  var HMAC_DIGEST_LENGTH = 64;
6514
6499
  function computeIntegrity(data, key) {
6515
6500
  if (key.length === 0) {
6516
- throw new EncryptionError(
6517
- "Cannot compute integrity with an empty key",
6518
- { hint: "Provide a valid encryption key for integrity computation." }
6519
- );
6501
+ throw new EncryptionError("Cannot compute integrity with an empty key", {
6502
+ hint: "Provide a valid encryption key for integrity computation."
6503
+ });
6520
6504
  }
6521
6505
  if (data.length === 0) {
6522
- throw new EncryptionError(
6523
- "Cannot compute integrity for empty data",
6524
- { hint: "Provide non-empty data for integrity computation." }
6525
- );
6506
+ throw new EncryptionError("Cannot compute integrity for empty data", {
6507
+ hint: "Provide non-empty data for integrity computation."
6508
+ });
6526
6509
  }
6527
6510
  const hmac = (0, import_node_crypto3.createHmac)(HMAC_ALGORITHM, key);
6528
6511
  hmac.update(data, "utf-8");
@@ -6530,21 +6513,20 @@ function computeIntegrity(data, key) {
6530
6513
  }
6531
6514
  function verifyIntegrity(data, key, expected) {
6532
6515
  if (key.length === 0) {
6533
- throw new EncryptionError(
6534
- "Cannot verify integrity with an empty key"
6535
- );
6516
+ throw new EncryptionError("Cannot verify integrity with an empty key");
6536
6517
  }
6537
6518
  if (expected.length !== HMAC_DIGEST_LENGTH) {
6538
6519
  throw new EncryptionError(
6539
6520
  `Invalid expected digest length: expected ${HMAC_DIGEST_LENGTH} hex characters, got ${expected.length}`,
6540
- { hint: "The integrity digest should be a 64-character lowercase hex string from computeIntegrity()." }
6521
+ {
6522
+ hint: "The integrity digest should be a 64-character lowercase hex string from computeIntegrity()."
6523
+ }
6541
6524
  );
6542
6525
  }
6543
6526
  if (!/^[0-9a-f]{64}$/.test(expected)) {
6544
- throw new EncryptionError(
6545
- "Invalid expected digest format: must be a lowercase hex string",
6546
- { hint: "Ensure the stored digest is a 64-character lowercase hex string." }
6547
- );
6527
+ throw new EncryptionError("Invalid expected digest format: must be a lowercase hex string", {
6528
+ hint: "Ensure the stored digest is a 64-character lowercase hex string."
6529
+ });
6548
6530
  }
6549
6531
  try {
6550
6532
  const computed = computeIntegrity(data, key);
@@ -6558,14 +6540,10 @@ function verifyIntegrity(data, key, expected) {
6558
6540
  }
6559
6541
  function computeVaultChecksum(environments, key) {
6560
6542
  if (key.length === 0) {
6561
- throw new EncryptionError(
6562
- "Cannot compute vault checksum with an empty key"
6563
- );
6543
+ throw new EncryptionError("Cannot compute vault checksum with an empty key");
6564
6544
  }
6565
6545
  if (environments.size === 0) {
6566
- throw new EncryptionError(
6567
- "Cannot compute vault checksum for empty environment set"
6568
- );
6546
+ throw new EncryptionError("Cannot compute vault checksum for empty environment set");
6569
6547
  }
6570
6548
  const sortedNames = Array.from(environments.keys()).sort();
6571
6549
  const parts = [];
@@ -6581,9 +6559,7 @@ function computeVaultChecksum(environments, key) {
6581
6559
  }
6582
6560
  function verifyVaultChecksum(environments, key, expected) {
6583
6561
  if (key.length === 0) {
6584
- throw new EncryptionError(
6585
- "Cannot verify vault checksum with an empty key"
6586
- );
6562
+ throw new EncryptionError("Cannot verify vault checksum with an empty key");
6587
6563
  }
6588
6564
  if (expected.length !== HMAC_DIGEST_LENGTH) {
6589
6565
  throw new EncryptionError(
@@ -6644,9 +6620,7 @@ var SecureBuffer = class _SecureBuffer {
6644
6620
  */
6645
6621
  constructor(size) {
6646
6622
  if (size < 1 || !Number.isInteger(size)) {
6647
- throw new RangeError(
6648
- `SecureBuffer: size must be a positive integer, got ${size}`
6649
- );
6623
+ throw new RangeError(`SecureBuffer: size must be a positive integer, got ${size}`);
6650
6624
  }
6651
6625
  this._buffer = Buffer.alloc(size);
6652
6626
  this._length = size;
@@ -6700,9 +6674,7 @@ var SecureBuffer = class _SecureBuffer {
6700
6674
  */
6701
6675
  fill(value) {
6702
6676
  if (value < 0 || value > 255 || !Number.isInteger(value)) {
6703
- throw new RangeError(
6704
- `SecureBuffer.fill: value must be an integer 0-255, got ${value}`
6705
- );
6677
+ throw new RangeError(`SecureBuffer.fill: value must be an integer 0-255, got ${value}`);
6706
6678
  }
6707
6679
  this._buffer.fill(value);
6708
6680
  this._zeroed = value === 0;
@@ -7143,7 +7115,7 @@ var SECRET_PATTERNS = [
7143
7115
  {
7144
7116
  id: "google-oauth-client-secret",
7145
7117
  name: "Google OAuth Client Secret",
7146
- pattern: /(?:^|["'\s:=,`]GOCSPX-[A-Za-z0-9_-]{28,})(?:["'\s,`;]|$)/gm,
7118
+ pattern: /(?:^|["'\s:=,`])(GOCSPX-[A-Za-z0-9_-]{28,})(?:["'\s,`;]|$)/gm,
7147
7119
  confidence: 0.9,
7148
7120
  severity: "critical",
7149
7121
  description: "Google OAuth Client Secret (new format). Used for OAuth authentication flows.",
@@ -8018,9 +7990,7 @@ function extractCandidates(line) {
8018
7990
  const captured = tokenMatch[1];
8019
7991
  if (captured === void 0) continue;
8020
7992
  const tokenIndex = tokenMatch.index + 1;
8021
- const existing = candidates.some(
8022
- (c) => c.value === captured && c.column === tokenIndex
8023
- );
7993
+ const existing = candidates.some((c) => c.value === captured && c.column === tokenIndex);
8024
7994
  if (!existing) {
8025
7995
  candidates.push({ value: captured, column: tokenMatch.index + 1 });
8026
7996
  }
@@ -8587,15 +8557,9 @@ var DIM = "\x1B[2m";
8587
8557
  function formatTerminal(result) {
8588
8558
  const lines = [];
8589
8559
  const totalCount = result.secrets.length;
8590
- const criticalCount = result.secrets.filter(
8591
- (s) => getSeverity(s.pattern) === "critical"
8592
- ).length;
8593
- const highCount = result.secrets.filter(
8594
- (s) => getSeverity(s.pattern) === "high"
8595
- ).length;
8596
- const mediumCount = result.secrets.filter(
8597
- (s) => getSeverity(s.pattern) === "medium"
8598
- ).length;
8560
+ const criticalCount = result.secrets.filter((s) => getSeverity(s.pattern) === "critical").length;
8561
+ const highCount = result.secrets.filter((s) => getSeverity(s.pattern) === "high").length;
8562
+ const mediumCount = result.secrets.filter((s) => getSeverity(s.pattern) === "medium").length;
8599
8563
  lines.push("");
8600
8564
  lines.push(`${BOLD}=== ultraenv Secret Scan Report ===${RESET}`);
8601
8565
  lines.push("");
@@ -8611,7 +8575,9 @@ function formatTerminal(result) {
8611
8575
  }
8612
8576
  const summaryParts = [];
8613
8577
  if (criticalCount > 0) {
8614
- summaryParts.push(`${SEVERITY_CONFIG.critical.terminalColor}${BOLD}${criticalCount} critical${RESET}`);
8578
+ summaryParts.push(
8579
+ `${SEVERITY_CONFIG.critical.terminalColor}${BOLD}${criticalCount} critical${RESET}`
8580
+ );
8615
8581
  }
8616
8582
  if (highCount > 0) {
8617
8583
  summaryParts.push(`${SEVERITY_CONFIG.high.terminalColor}${BOLD}${highCount} high${RESET}`);
@@ -9248,16 +9214,12 @@ var SyncWatcher = class {
9248
9214
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
9249
9215
  };
9250
9216
  try {
9251
- const needs = await needsUpdate(
9252
- this.options.envPath,
9253
- this.options.examplePath,
9254
- {
9255
- schemaPath: void 0,
9256
- includeDescriptions: this.options.includeDescriptions,
9257
- includeTypes: this.options.includeTypes,
9258
- includeDefaults: this.options.includeDefaults
9259
- }
9260
- );
9217
+ const needs = await needsUpdate(this.options.envPath, this.options.examplePath, {
9218
+ schemaPath: void 0,
9219
+ includeDescriptions: this.options.includeDescriptions,
9220
+ includeTypes: this.options.includeTypes,
9221
+ includeDefaults: this.options.includeDefaults
9222
+ });
9261
9223
  if (!needs) {
9262
9224
  result.success = true;
9263
9225
  if (this.options.onSync !== void 0) {
@@ -9265,16 +9227,12 @@ var SyncWatcher = class {
9265
9227
  }
9266
9228
  return;
9267
9229
  }
9268
- await generateExampleFile(
9269
- this.options.envPath,
9270
- this.options.examplePath,
9271
- {
9272
- schemaPath: void 0,
9273
- includeDescriptions: this.options.includeDescriptions,
9274
- includeTypes: this.options.includeTypes,
9275
- includeDefaults: this.options.includeDefaults
9276
- }
9277
- );
9230
+ await generateExampleFile(this.options.envPath, this.options.examplePath, {
9231
+ schemaPath: void 0,
9232
+ includeDescriptions: this.options.includeDescriptions,
9233
+ includeTypes: this.options.includeTypes,
9234
+ includeDefaults: this.options.includeDefaults
9235
+ });
9278
9236
  result.success = true;
9279
9237
  this.emitEvent({
9280
9238
  type: "change",
@@ -10079,12 +10037,14 @@ async function validateAllEnvironments(schema, cwd) {
10079
10037
  const message = error instanceof Error ? error.message : String(error);
10080
10038
  results.set(envName ?? pattern, {
10081
10039
  valid: false,
10082
- errors: [{
10083
- field: "",
10084
- value: "",
10085
- message: `Failed to read/parse file: ${message}`,
10086
- hint: "Check that the file is a valid .env file."
10087
- }],
10040
+ errors: [
10041
+ {
10042
+ field: "",
10043
+ value: "",
10044
+ message: `Failed to read/parse file: ${message}`,
10045
+ hint: "Check that the file is a valid .env file."
10046
+ }
10047
+ ],
10088
10048
  warnings: []
10089
10049
  });
10090
10050
  }
@@ -10095,14 +10055,11 @@ async function switchEnvironment(envName, cwd) {
10095
10055
  const baseDir = (0, import_node_path7.resolve)(cwd ?? process.cwd());
10096
10056
  const envFile = (0, import_node_path7.join)(baseDir, `.env.${envName}`);
10097
10057
  if (!await exists(envFile)) {
10098
- throw new FileSystemError(
10099
- `Environment file ".env.${envName}" not found`,
10100
- {
10101
- path: envFile,
10102
- operation: "read",
10103
- hint: `Create a ".env.${envName}" file first, or use "ultraenv env create ${envName}".`
10104
- }
10105
- );
10058
+ throw new FileSystemError(`Environment file ".env.${envName}" not found`, {
10059
+ path: envFile,
10060
+ operation: "read",
10061
+ hint: `Create a ".env.${envName}" file first, or use "ultraenv env create ${envName}".`
10062
+ });
10106
10063
  }
10107
10064
  const content = await readFile(envFile);
10108
10065
  const header = [
@@ -10276,24 +10233,18 @@ async function compareEnvironments(env1, env2, cwd, _schema) {
10276
10233
  const resolvedEnv1Path = env1.includes("/") || env1.includes("\\") ? (0, import_node_path8.resolve)(env1) : env1Path;
10277
10234
  const resolvedEnv2Path = env2.includes("/") || env2.includes("\\") ? (0, import_node_path8.resolve)(env2) : env2Path;
10278
10235
  if (!await exists(resolvedEnv1Path)) {
10279
- throw new FileSystemError(
10280
- `Environment file not found: "${resolvedEnv1Path}"`,
10281
- {
10282
- path: resolvedEnv1Path,
10283
- operation: "read",
10284
- hint: `Ensure ".env.${env1}" exists in the project directory.`
10285
- }
10286
- );
10236
+ throw new FileSystemError(`Environment file not found: "${resolvedEnv1Path}"`, {
10237
+ path: resolvedEnv1Path,
10238
+ operation: "read",
10239
+ hint: `Ensure ".env.${env1}" exists in the project directory.`
10240
+ });
10287
10241
  }
10288
10242
  if (!await exists(resolvedEnv2Path)) {
10289
- throw new FileSystemError(
10290
- `Environment file not found: "${resolvedEnv2Path}"`,
10291
- {
10292
- path: resolvedEnv2Path,
10293
- operation: "read",
10294
- hint: `Ensure ".env.${env2}" exists in the project directory.`
10295
- }
10296
- );
10243
+ throw new FileSystemError(`Environment file not found: "${resolvedEnv2Path}"`, {
10244
+ path: resolvedEnv2Path,
10245
+ operation: "read",
10246
+ hint: `Ensure ".env.${env2}" exists in the project directory.`
10247
+ });
10297
10248
  }
10298
10249
  const env1Content = await readFile(resolvedEnv1Path);
10299
10250
  const env2Content = await readFile(resolvedEnv2Path);
@@ -10386,14 +10337,18 @@ function formatComparison(comparison) {
10386
10337
  lines.push("");
10387
10338
  lines.push(`Only in ${comparison.env1Name} (${comparison.onlyInEnv1.length}):`);
10388
10339
  for (const diff of comparison.onlyInEnv1) {
10389
- lines.push(` - ${diff.key}${diff.isSecret ? " [SECRET]" : ""} = ${diff.value1 || "(empty)"}`);
10340
+ lines.push(
10341
+ ` - ${diff.key}${diff.isSecret ? " [SECRET]" : ""} = ${diff.value1 || "(empty)"}`
10342
+ );
10390
10343
  }
10391
10344
  }
10392
10345
  if (comparison.onlyInEnv2.length > 0) {
10393
10346
  lines.push("");
10394
10347
  lines.push(`Only in ${comparison.env2Name} (${comparison.onlyInEnv2.length}):`);
10395
10348
  for (const diff of comparison.onlyInEnv2) {
10396
- lines.push(` + ${diff.key}${diff.isSecret ? " [SECRET]" : ""} = ${diff.value2 || "(empty)"}`);
10349
+ lines.push(
10350
+ ` + ${diff.key}${diff.isSecret ? " [SECRET]" : ""} = ${diff.value2 || "(empty)"}`
10351
+ );
10397
10352
  }
10398
10353
  }
10399
10354
  if (comparison.different.length > 0) {
@@ -10574,14 +10529,11 @@ function validateEnvironmentName(name) {
10574
10529
  });
10575
10530
  }
10576
10531
  if (name.length > 64) {
10577
- throw new FileSystemError(
10578
- `Environment name too long: ${name.length} characters (max 64)`,
10579
- {
10580
- path: "",
10581
- operation: "validate",
10582
- hint: "Use a shorter environment name."
10583
- }
10584
- );
10532
+ throw new FileSystemError(`Environment name too long: ${name.length} characters (max 64)`, {
10533
+ path: "",
10534
+ operation: "validate",
10535
+ hint: "Use a shorter environment name."
10536
+ });
10585
10537
  }
10586
10538
  if (!/^[a-zA-Z0-9_-]+$/.test(name)) {
10587
10539
  throw new FileSystemError(
@@ -10595,14 +10547,11 @@ function validateEnvironmentName(name) {
10595
10547
  }
10596
10548
  const reserved = ["local", "example", "template", "bak", "backup", "old", "tmp", "temp"];
10597
10549
  if (reserved.includes(name.toLowerCase())) {
10598
- throw new FileSystemError(
10599
- `Reserved environment name: "${name}"`,
10600
- {
10601
- path: "",
10602
- operation: "validate",
10603
- hint: `The name "${name}" is reserved. Choose a different name.`
10604
- }
10605
- );
10550
+ throw new FileSystemError(`Reserved environment name: "${name}"`, {
10551
+ path: "",
10552
+ operation: "validate",
10553
+ hint: `The name "${name}" is reserved. Choose a different name.`
10554
+ });
10606
10555
  }
10607
10556
  }
10608
10557
  async function createEnvironment(name, options) {
@@ -10610,28 +10559,22 @@ async function createEnvironment(name, options) {
10610
10559
  const baseDir = (0, import_node_path9.resolve)(options?.cwd ?? process.cwd());
10611
10560
  const outputPath = (0, import_node_path9.join)(baseDir, `.env.${name}`);
10612
10561
  if (await exists(outputPath)) {
10613
- throw new FileSystemError(
10614
- `Environment file already exists: ".env.${name}"`,
10615
- {
10616
- path: outputPath,
10617
- operation: "create",
10618
- hint: "Delete the existing file first, or use a different environment name."
10619
- }
10620
- );
10562
+ throw new FileSystemError(`Environment file already exists: ".env.${name}"`, {
10563
+ path: outputPath,
10564
+ operation: "create",
10565
+ hint: "Delete the existing file first, or use a different environment name."
10566
+ });
10621
10567
  }
10622
10568
  let content;
10623
10569
  let variables = [];
10624
10570
  if (options?.copyFrom !== void 0) {
10625
10571
  const sourcePath = (0, import_node_path9.join)(baseDir, `.env.${options.copyFrom}`);
10626
10572
  if (!await exists(sourcePath)) {
10627
- throw new FileSystemError(
10628
- `Source environment not found: ".env.${options.copyFrom}"`,
10629
- {
10630
- path: sourcePath,
10631
- operation: "read",
10632
- hint: `Ensure ".env.${options.copyFrom}" exists before copying.`
10633
- }
10634
- );
10573
+ throw new FileSystemError(`Source environment not found: ".env.${options.copyFrom}"`, {
10574
+ path: sourcePath,
10575
+ operation: "read",
10576
+ hint: `Ensure ".env.${options.copyFrom}" exists before copying.`
10577
+ });
10635
10578
  }
10636
10579
  content = await readFile(sourcePath);
10637
10580
  variables = extractVariables(content, options?.schema);
@@ -10652,14 +10595,11 @@ async function createEnvironment(name, options) {
10652
10595
  } else if (await exists(templatePath)) {
10653
10596
  content = await readFile(templatePath);
10654
10597
  } else {
10655
- throw new FileSystemError(
10656
- `Template not found: "${options.fromTemplate}"`,
10657
- {
10658
- path: templatePath,
10659
- operation: "read",
10660
- hint: "Use a built-in template name (nodejs, nextjs, docker) or a valid file path."
10661
- }
10662
- );
10598
+ throw new FileSystemError(`Template not found: "${options.fromTemplate}"`, {
10599
+ path: templatePath,
10600
+ operation: "read",
10601
+ hint: "Use a built-in template name (nodejs, nextjs, docker) or a valid file path."
10602
+ });
10663
10603
  }
10664
10604
  variables = extractVariables(content, options?.schema);
10665
10605
  const values = collectValues(variables, options?.values);
@@ -10696,14 +10636,11 @@ async function removeEnvironment(name, cwd) {
10696
10636
  const baseDir = (0, import_node_path9.resolve)(cwd ?? process.cwd());
10697
10637
  const filePath = (0, import_node_path9.join)(baseDir, `.env.${name}`);
10698
10638
  if (!await exists(filePath)) {
10699
- throw new FileSystemError(
10700
- `Environment file not found: ".env.${name}"`,
10701
- {
10702
- path: filePath,
10703
- operation: "unlink",
10704
- hint: "The environment does not exist."
10705
- }
10706
- );
10639
+ throw new FileSystemError(`Environment file not found: ".env.${name}"`, {
10640
+ path: filePath,
10641
+ operation: "unlink",
10642
+ hint: "The environment does not exist."
10643
+ });
10707
10644
  }
10708
10645
  await removeFile(filePath);
10709
10646
  }
@@ -10855,11 +10792,7 @@ var nextjsPreset = {
10855
10792
  };
10856
10793
 
10857
10794
  // src/presets/vite.ts
10858
- var VITE_MODES = [
10859
- "development",
10860
- "production",
10861
- "test"
10862
- ];
10795
+ var VITE_MODES = ["development", "production", "test"];
10863
10796
  var viteSchema = {
10864
10797
  // ── Public (client-exposed) Variables ──────────────────────────────
10865
10798
  VITE_API_URL: {
@@ -12081,10 +12014,8 @@ var awsLambdaPreset = {
12081
12014
  var presets = {};
12082
12015
  function registerPreset(name, preset) {
12083
12016
  if (presets[name] !== void 0) {
12084
- process.stderr.write(
12085
- `[ultraenv] Warning: overwriting existing preset "${name}"
12086
- `
12087
- );
12017
+ process.stderr.write(`[ultraenv] Warning: overwriting existing preset "${name}"
12018
+ `);
12088
12019
  }
12089
12020
  presets[name] = preset;
12090
12021
  }
@@ -12181,9 +12112,7 @@ function buildFilteredEnv(source, prefixes, allowSet, denySet, exposePublic, exp
12181
12112
  function healthCheckRoute(options = {}) {
12182
12113
  const { source = process.env, metadata = {} } = options;
12183
12114
  return (_req, res) => {
12184
- const envKeys = Object.keys(source).filter(
12185
- (k) => source[k] !== void 0 && source[k] !== ""
12186
- );
12115
+ const envKeys = Object.keys(source).filter((k) => source[k] !== void 0 && source[k] !== "");
12187
12116
  const nodeEnv = source["NODE_ENV"] ?? "unknown";
12188
12117
  const response = {
12189
12118
  status: "ok",
@@ -12218,13 +12147,7 @@ function ultraenvPlugin(fastify, options = {}, done) {
12218
12147
  }
12219
12148
  const allowSet = new Set(allowList.map((k) => k.toUpperCase()));
12220
12149
  const denySet = new Set(denyList.map((k) => k.toUpperCase()));
12221
- const filteredEnv = buildFastifyEnv(
12222
- source,
12223
- allPrefixes,
12224
- allowSet,
12225
- denySet,
12226
- exposeNodeEnv
12227
- );
12150
+ const filteredEnv = buildFastifyEnv(source, allPrefixes, allowSet, denySet, exposeNodeEnv);
12228
12151
  fastify.decorate("env", filteredEnv);
12229
12152
  done();
12230
12153
  }
@@ -12266,9 +12189,7 @@ function healthCheck(options = {}) {
12266
12189
  validCount,
12267
12190
  metadata = {}
12268
12191
  } = options;
12269
- const envKeys = Object.entries(source).filter(
12270
- ([, value]) => value !== void 0 && value !== ""
12271
- );
12192
+ const envKeys = Object.entries(source).filter(([, value]) => value !== void 0 && value !== "");
12272
12193
  const loaded = envKeys.length;
12273
12194
  const environment = detectEnvironment2(source);
12274
12195
  const valid = validCount ?? loaded;
@@ -12311,13 +12232,7 @@ function readinessCheck(requiredVars, source) {
12311
12232
  };
12312
12233
  }
12313
12234
  function detectEnvironment2(env) {
12314
- const candidates = [
12315
- "NODE_ENV",
12316
- "APP_ENV",
12317
- "ENVIRONMENT",
12318
- "ENV",
12319
- "STAGE"
12320
- ];
12235
+ const candidates = ["NODE_ENV", "APP_ENV", "ENVIRONMENT", "ENV", "STAGE"];
12321
12236
  for (const candidate of candidates) {
12322
12237
  const value = env[candidate];
12323
12238
  if (value !== void 0 && value !== "") {
@@ -12349,11 +12264,7 @@ function drawTitledBox(title, lines, chars = DOUBLE) {
12349
12264
  if (lines.length === 0) {
12350
12265
  return [hRuleTitled(title, 0, chars), boxLine("", 0, chars), hRuleBottom(0, chars)].join("\n");
12351
12266
  }
12352
- const innerWidth = Math.max(
12353
- ...lines.map((line) => stripAnsi(line).length),
12354
- title.length + 2,
12355
- 0
12356
- );
12267
+ const innerWidth = Math.max(...lines.map((line) => stripAnsi(line).length), title.length + 2, 0);
12357
12268
  const result = [];
12358
12269
  result.push(hRuleTitled(title, innerWidth, chars));
12359
12270
  for (const line of lines) {
@@ -12408,7 +12319,9 @@ function reportValidation(result, options = {}) {
12408
12319
  const c = color ? ANSI : noColorANSI();
12409
12320
  if (result.valid) {
12410
12321
  const lines = [];
12411
- lines.push(`${c.green}${c.bold} \u2713${c.reset} All ${Object.keys(result.validated).length} variables passed validation`);
12322
+ lines.push(
12323
+ `${c.green}${c.bold} \u2713${c.reset} All ${Object.keys(result.validated).length} variables passed validation`
12324
+ );
12412
12325
  if (result.warnings.length > 0) {
12413
12326
  lines.push("");
12414
12327
  for (const warning of result.warnings) {
@@ -12438,13 +12351,17 @@ function reportValidation(result, options = {}) {
12438
12351
  output.push("");
12439
12352
  const warningLines = [];
12440
12353
  for (const warning of result.warnings) {
12441
- warningLines.push(`${c.yellow}\u26A0${c.reset} ${warning.field}: ${warning.message} ${c.dim}[${warning.code}]${c.reset}`);
12354
+ warningLines.push(
12355
+ `${c.yellow}\u26A0${c.reset} ${warning.field}: ${warning.message} ${c.dim}[${warning.code}]${c.reset}`
12356
+ );
12442
12357
  }
12443
12358
  output.push(warningLines.join("\n"));
12444
12359
  }
12445
12360
  if (result.unknown.length > 0) {
12446
12361
  output.push("");
12447
- output.push(`${c.gray}?${c.reset} Unknown variables: ${result.unknown.map((u) => `${c.dim}${u}${c.reset}`).join(", ")}`);
12362
+ output.push(
12363
+ `${c.gray}?${c.reset} Unknown variables: ${result.unknown.map((u) => `${c.dim}${u}${c.reset}`).join(", ")}`
12364
+ );
12448
12365
  }
12449
12366
  return output.join("\n");
12450
12367
  }
@@ -12452,10 +12369,7 @@ function reportError(error, options = {}) {
12452
12369
  const { color = true, boxStyle = DEFAULT_BOX } = options;
12453
12370
  const c = color ? ANSI : noColorANSI();
12454
12371
  const code = error.code ?? "ULTRAENV_ERROR";
12455
- const lines = [
12456
- `${c.red}${c.bold}Error [${code}]${c.reset}`,
12457
- ` ${error.message}`
12458
- ];
12372
+ const lines = [`${c.red}${c.bold}Error [${code}]${c.reset}`, ` ${error.message}`];
12459
12373
  if (error.hint !== void 0) {
12460
12374
  lines.push("");
12461
12375
  lines.push(`${c.cyan} \u{1F4A1} ${error.hint}${c.reset}`);