varlock 0.0.4 → 0.0.5

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 (101) hide show
  1. package/dist/auto-load.js +5 -6
  2. package/dist/{chunk-7UQXFWKN.js → chunk-365YVT72.js} +93 -3
  3. package/dist/chunk-365YVT72.js.map +1 -0
  4. package/dist/{chunk-ZIN4KXR6.js → chunk-7SCZ3YWG.js} +10 -9
  5. package/dist/chunk-7SCZ3YWG.js.map +1 -0
  6. package/dist/{chunk-SVDXBE6D.js → chunk-C2ZQAQUU.js} +3 -4
  7. package/dist/chunk-C2ZQAQUU.js.map +1 -0
  8. package/dist/chunk-EVHLEWHL.js +59 -0
  9. package/dist/chunk-EVHLEWHL.js.map +1 -0
  10. package/dist/{chunk-XPHGSDAF.js → chunk-GAQWSZCY.js} +3 -4
  11. package/dist/chunk-GAQWSZCY.js.map +1 -0
  12. package/dist/{chunk-DHFEY3C4.js → chunk-GCUCCUG5.js} +25 -7
  13. package/dist/chunk-GCUCCUG5.js.map +1 -0
  14. package/dist/{chunk-A4AHZSZB.js → chunk-GVAD672U.js} +15 -27
  15. package/dist/chunk-GVAD672U.js.map +1 -0
  16. package/dist/{chunk-NN3XFBPE.js → chunk-HMRN5QZL.js} +3 -3
  17. package/dist/{chunk-NN3XFBPE.js.map → chunk-HMRN5QZL.js.map} +1 -1
  18. package/dist/{chunk-DROJWTCD.js → chunk-K2N2TG4M.js} +1396 -1432
  19. package/dist/chunk-K2N2TG4M.js.map +1 -0
  20. package/dist/chunk-LHTLO65N.js +99 -0
  21. package/dist/chunk-LHTLO65N.js.map +1 -0
  22. package/dist/{chunk-VN64D2EQ.js → chunk-LU2R63B4.js} +3 -4
  23. package/dist/chunk-LU2R63B4.js.map +1 -0
  24. package/dist/{chunk-B4UBSMSZ.js → chunk-PUGFIZE3.js} +4 -3
  25. package/dist/chunk-PUGFIZE3.js.map +1 -0
  26. package/dist/chunk-PZE4KJJW.js +14 -0
  27. package/dist/{chunk-RUB5A7IC.js.map → chunk-PZE4KJJW.js.map} +1 -1
  28. package/dist/{chunk-RCHPHIHX.js → chunk-RZT65DRA.js} +2 -2
  29. package/dist/chunk-RZT65DRA.js.map +1 -0
  30. package/dist/chunk-UFAGBKYG.js +54 -0
  31. package/dist/chunk-UFAGBKYG.js.map +1 -0
  32. package/dist/{chunk-H2TT4DP5.js → chunk-VVJO4FC3.js} +17 -161
  33. package/dist/chunk-VVJO4FC3.js.map +1 -0
  34. package/dist/chunk-VVKXMIKQ.js +180 -0
  35. package/dist/chunk-VVKXMIKQ.js.map +1 -0
  36. package/dist/{chunk-DOIKZ3NG.js → chunk-WFN3ZXGS.js} +6 -6
  37. package/dist/chunk-WFN3ZXGS.js.map +1 -0
  38. package/dist/chunk-Y7WD33L3.js +17 -0
  39. package/dist/chunk-Y7WD33L3.js.map +1 -0
  40. package/dist/{chunk-C273RDM5.js → chunk-Z5KNSSLC.js} +10 -8
  41. package/dist/chunk-Z5KNSSLC.js.map +1 -0
  42. package/dist/cli/cli-executable.js +702 -158
  43. package/dist/cli/cli-executable.js.map +1 -1
  44. package/dist/doctor.command-NUG3BYDQ.js +7 -0
  45. package/dist/{doctor.command-7BQSOQWW.js.map → doctor.command-NUG3BYDQ.js.map} +1 -1
  46. package/dist/dotenv-compat.js +5 -6
  47. package/dist/encrypt.command-AGHQ4KTI.js +7 -0
  48. package/dist/{encrypt.command-VGJABHNK.js.map → encrypt.command-AGHQ4KTI.js.map} +1 -1
  49. package/dist/env-B8lQt2sl.d.ts +42 -0
  50. package/dist/help.command-B7VWA53B.js +5 -0
  51. package/dist/{help.command-YZDL2VEQ.js.map → help.command-B7VWA53B.js.map} +1 -1
  52. package/dist/index.d.ts +1 -2
  53. package/dist/index.js +11 -10
  54. package/dist/index.js.map +1 -1
  55. package/dist/init.command-DHE2Q6FX.js +13 -0
  56. package/dist/{init.command-CY3ZOIGP.js.map → init.command-DHE2Q6FX.js.map} +1 -1
  57. package/dist/load.command-GGE4OANH.js +12 -0
  58. package/dist/{load.command-ZFNTAAJE.js.map → load.command-GGE4OANH.js.map} +1 -1
  59. package/dist/login.command-25PKQUGR.js +10 -0
  60. package/dist/{login.command-KYZ4FXS5.js.map → login.command-25PKQUGR.js.map} +1 -1
  61. package/dist/run.command-BLL6AL52.js +12 -0
  62. package/dist/{run.command-VRKI6ZVN.js.map → run.command-BLL6AL52.js.map} +1 -1
  63. package/dist/runtime/env.d.ts +1 -27
  64. package/dist/runtime/env.js +1 -1
  65. package/dist/runtime/patch-console.js +2 -3
  66. package/dist/runtime/patch-response.js +2 -3
  67. package/dist/runtime/patch-server-response.js +2 -3
  68. package/dist/telemetry.command-MVL3E366.js +10 -0
  69. package/dist/telemetry.command-MVL3E366.js.map +1 -0
  70. package/package.json +7 -3
  71. package/dist/chunk-7UQXFWKN.js.map +0 -1
  72. package/dist/chunk-A4AHZSZB.js.map +0 -1
  73. package/dist/chunk-B4UBSMSZ.js.map +0 -1
  74. package/dist/chunk-C273RDM5.js.map +0 -1
  75. package/dist/chunk-CLVBJA4G.js +0 -107
  76. package/dist/chunk-CLVBJA4G.js.map +0 -1
  77. package/dist/chunk-DHFEY3C4.js.map +0 -1
  78. package/dist/chunk-DOIKZ3NG.js.map +0 -1
  79. package/dist/chunk-DROJWTCD.js.map +0 -1
  80. package/dist/chunk-GSRDZVQI.js +0 -26
  81. package/dist/chunk-GSRDZVQI.js.map +0 -1
  82. package/dist/chunk-H2TT4DP5.js.map +0 -1
  83. package/dist/chunk-QCC3P7BT.js +0 -39
  84. package/dist/chunk-QCC3P7BT.js.map +0 -1
  85. package/dist/chunk-RCHPHIHX.js.map +0 -1
  86. package/dist/chunk-RUB5A7IC.js +0 -14
  87. package/dist/chunk-SVDXBE6D.js.map +0 -1
  88. package/dist/chunk-VN64D2EQ.js.map +0 -1
  89. package/dist/chunk-XHOJF7U7.js +0 -12
  90. package/dist/chunk-XHOJF7U7.js.map +0 -1
  91. package/dist/chunk-XPHGSDAF.js.map +0 -1
  92. package/dist/chunk-ZIN4KXR6.js.map +0 -1
  93. package/dist/doctor.command-7BQSOQWW.js +0 -6
  94. package/dist/encrypt.command-VGJABHNK.js +0 -6
  95. package/dist/help.command-YZDL2VEQ.js +0 -5
  96. package/dist/init.command-CY3ZOIGP.js +0 -11
  97. package/dist/load.command-ZFNTAAJE.js +0 -10
  98. package/dist/login.command-KYZ4FXS5.js +0 -7
  99. package/dist/opt-out.command-Y4KUQ6PQ.js +0 -5
  100. package/dist/opt-out.command-Y4KUQ6PQ.js.map +0 -1
  101. package/dist/run.command-VRKI6ZVN.js +0 -10
@@ -1,10 +1,10 @@
1
1
  import { __name } from './chunk-XN24GZXQ.js';
2
2
  import { exec } from 'node:child_process';
3
3
  import { promisify } from 'node:util';
4
- import fs from 'node:fs/promises';
4
+ import fs2 from 'node:fs/promises';
5
5
  import path from 'node:path';
6
6
  import { ParsedEnvSpecStaticValue, ParsedEnvSpecFunctionCall, ParsedEnvSpecKeyValuePair, parseEnvSpecDotEnvFile } from '@env-spec/parser';
7
- import fs2 from 'node:fs';
7
+ import fs from 'node:fs';
8
8
 
9
9
  // ../../node_modules/.pnpm/@sindresorhus+is@7.0.1/node_modules/@sindresorhus/is/distribution/index.js
10
10
  var typedArrayTypeNames = [
@@ -701,7 +701,7 @@ function mapValues(obj, fn) {
701
701
  }
702
702
  __name(mapValues, "mapValues");
703
703
  function times(count, fn) {
704
- return Array.from({ length: count }, (_2, i) => fn(i));
704
+ return Array.from({ length: count }, (_3, i) => fn(i));
705
705
  }
706
706
  __name(times, "times");
707
707
  function map(array, fn) {
@@ -880,1592 +880,1556 @@ var EmptyRequiredValueError = class extends ValidationError {
880
880
  }
881
881
  };
882
882
 
883
- // ../env-graph/src/lib/simple-queue.ts
884
- var SimpleQueue = class {
885
- static {
886
- __name(this, "SimpleQueue");
887
- }
888
- queue = [];
889
- processing = false;
890
- /** Add a task to the queue and return a promise that resolves when the task is complete */
891
- async enqueue(task) {
892
- return new Promise((resolve, reject) => {
893
- this.queue.push(async () => {
894
- try {
895
- const result = await task();
896
- resolve(result);
897
- } catch (err) {
898
- reject(err);
899
- }
900
- });
901
- this.processQueue();
902
- });
903
- }
904
- async processQueue() {
905
- if (this.processing || this.queue.length === 0) {
906
- return;
907
- }
908
- this.processing = true;
909
- const task = this.queue.shift();
910
- if (task) {
911
- try {
912
- await task();
913
- } finally {
914
- this.processing = false;
915
- this.processQueue();
916
- }
917
- }
918
- }
919
- };
920
-
921
- // ../env-graph/src/lib/resolver.ts
922
- var execAsync = promisify(exec);
923
- var Resolver = class {
924
- constructor(fnArgs) {
925
- this.fnArgs = fnArgs;
926
- }
927
- static {
928
- __name(this, "Resolver");
929
- }
930
- static fnName;
931
- inferredType;
932
- _schemaErrors = [];
933
- _depsObj = {};
934
- get childResolvers() {
935
- return this.fnArgs.flatMap((r) => my_dash_default.isPlainObject(r) ? my_dash_default.values(r) : r);
936
- }
937
- get schemaErrors() {
938
- return [
939
- ...this._schemaErrors,
940
- ...this.childResolvers.flatMap((r) => r.schemaErrors)
941
- ];
942
- }
943
- get depsObj() {
944
- const mergedDepsObj = { ...this._depsObj };
945
- this.childResolvers.forEach((r) => Object.assign(mergedDepsObj, r.depsObj));
946
- return mergedDepsObj;
947
- }
948
- get deps() {
949
- return Object.keys(this.depsObj);
950
- }
951
- configItem;
952
- async process(configItem) {
953
- this.configItem = configItem;
954
- try {
955
- await this._process(configItem);
956
- } catch (error) {
957
- if (error instanceof SchemaError) {
958
- this._schemaErrors.push(error);
959
- } else if (error instanceof Error) {
960
- this._schemaErrors.push(new SchemaError(error));
961
- } else {
962
- throw new Error(`Non-error thrown while processing resolver - ${error}`);
963
- }
964
- }
965
- this.childResolvers.forEach((r) => r.process(configItem));
966
- }
967
- // meant to be used by subclass _process methods
968
- addDep(key) {
969
- this._depsObj[key] = true;
970
- if (!this.configItem) throw new Error("expected configItem to be set");
971
- if (!this.configItem.envGraph.configSchema[key]) {
972
- this._schemaErrors.push(new SchemaError(`Unknown referenced key: ${key}`));
973
- }
974
- }
975
- async resolve() {
976
- const resolvedValue = await this._resolve();
977
- return resolvedValue;
978
- }
979
- // meant to be used by subclass _resolve methods
980
- getDepValue(key) {
981
- const depItem = this.configItem?.envGraph.configSchema[key];
982
- if (!depItem) throw new Error(`Expected to find item - ${key}`);
983
- return depItem.resolvedValue;
984
- }
985
- };
986
- var StaticValueResolver = class extends Resolver {
987
- constructor(staticValue) {
988
- super([]);
989
- this.staticValue = staticValue;
990
- if (staticValue !== void 0) {
991
- this.inferredType = typeof staticValue;
992
- }
883
+ // ../env-graph/src/lib/data-types.ts
884
+ var EnvGraphDataType = class {
885
+ constructor(def, factory) {
886
+ this.def = def;
887
+ this.factory = factory;
993
888
  }
994
889
  static {
995
- __name(this, "StaticValueResolver");
996
- }
997
- label = "static";
998
- icon = "bi:dash";
999
- async _resolve() {
1000
- return this.staticValue;
890
+ __name(this, "EnvGraphDataType");
1001
891
  }
1002
- async _process() {
892
+ get name() {
893
+ return this.def.name;
1003
894
  }
1004
- };
1005
- var ErrorResolver = class extends Resolver {
1006
- static {
1007
- __name(this, "ErrorResolver");
895
+ get icon() {
896
+ return this.def.icon;
1008
897
  }
1009
- constructor(err) {
1010
- super([]);
1011
- this._schemaErrors.push(err);
898
+ /** @internal */
899
+ get _rawDef() {
900
+ return this.def;
1012
901
  }
1013
- label = "error";
1014
- icon = "bi:dash";
1015
- async _resolve() {
1016
- return void 0;
902
+ coerce(val) {
903
+ return this.def.coerce ? this.def.coerce(val) : val;
1017
904
  }
1018
- async _process() {
905
+ validate(val) {
906
+ return this.def.validate ? this.def.validate(val) : true;
1019
907
  }
1020
908
  };
1021
- var ConcatResolver = class extends Resolver {
1022
- static {
1023
- __name(this, "ConcatResolver");
1024
- }
1025
- static fnName = "concat";
1026
- label = "concat";
1027
- icon = "material-symbols:join";
1028
- inferredType = "string";
1029
- async _process() {
1030
- if (this.fnArgs.some((arg) => my_dash_default.isPlainObject(arg))) {
1031
- throw new SchemaError("concat() does not support key-value arguments");
909
+ function createEnvGraphDataType(dataTypeDef) {
910
+ const typeFactoryFn = /* @__PURE__ */ __name((...usageOpts) => {
911
+ return new EnvGraphDataType(
912
+ my_dash_default.isFunction(dataTypeDef) ? dataTypeDef(...usageOpts) : dataTypeDef,
913
+ typeFactoryFn
914
+ );
915
+ }, "typeFactoryFn");
916
+ typeFactoryFn._isEnvGraphDataTypeFactory = true;
917
+ const exampleInstance = typeFactoryFn(...[]);
918
+ typeFactoryFn.dataTypeName = exampleInstance.name;
919
+ return typeFactoryFn;
920
+ }
921
+ __name(createEnvGraphDataType, "createEnvGraphDataType");
922
+ function coerceToString(rawVal) {
923
+ if (rawVal === void 0 || rawVal === null) return "";
924
+ return my_dash_default.isString(rawVal) ? rawVal : String(rawVal);
925
+ }
926
+ __name(coerceToString, "coerceToString");
927
+ function coerceToNumber(rawVal) {
928
+ let numVal;
929
+ if (my_dash_default.isString(rawVal)) {
930
+ const parsed = parseFloat(rawVal);
931
+ if (my_dash_default.isNan(parsed) || parsed === Infinity || parsed === -Infinity) {
932
+ throw new CoercionError("Unable to coerce string to number");
1032
933
  }
1033
- if (this.fnArgs.length < 2) {
1034
- throw new SchemaError("concat() expects at least two arguments");
934
+ numVal = parsed;
935
+ } else if (my_dash_default.isNumber(rawVal)) {
936
+ if (numVal === Infinity || numVal === -Infinity) {
937
+ throw new CoercionError("Inifinity is not a valid number");
1035
938
  }
939
+ numVal = rawVal;
940
+ } else {
941
+ throw new CoercionError(`Cannot convert ${rawVal} to number`);
1036
942
  }
1037
- async _resolve() {
1038
- const resolvedValues = [];
1039
- for (const arg of this.fnArgs) {
1040
- if (my_dash_default.isPlainObject(arg)) {
1041
- throw new Error("concat() does not support key-value arguments");
943
+ return numVal;
944
+ }
945
+ __name(coerceToNumber, "coerceToNumber");
946
+ var StringDataType = createEnvGraphDataType(
947
+ (settings) => ({
948
+ name: "string",
949
+ icon: "carbon:string-text",
950
+ coerce: /* @__PURE__ */ __name((rawVal) => {
951
+ let val = coerceToString(rawVal);
952
+ if (settings?.toUpperCase) val = val.toUpperCase();
953
+ if (settings?.toLowerCase) val = val.toLowerCase();
954
+ return val;
955
+ }, "coerce"),
956
+ validate: /* @__PURE__ */ __name((val) => {
957
+ const errors = [];
958
+ if (settings?.minLength !== void 0 && val.length < settings.minLength) {
959
+ errors.push(new ValidationError(`Length must be more than ${settings.minLength}`));
1042
960
  }
1043
- const resolvedChildValue = await arg.resolve();
1044
- resolvedValues.push(String(resolvedChildValue ?? ""));
1045
- }
1046
- return resolvedValues.join("");
1047
- }
1048
- };
1049
- var FallbackResolver = class extends Resolver {
1050
- static {
1051
- __name(this, "FallbackResolver");
1052
- }
1053
- static fnName = "fallback";
1054
- label = "fallback";
1055
- icon = "memory:table-top-stairs-up";
1056
- async _process() {
1057
- if (this.fnArgs.some((arg) => my_dash_default.isPlainObject(arg))) {
1058
- throw new SchemaError("fallback() does not support key-value arguments");
1059
- }
1060
- if (this.fnArgs.length < 2) {
1061
- throw new SchemaError("fallback() expects at least two arguments");
1062
- }
1063
- }
1064
- async _resolve() {
1065
- for (const arg of this.fnArgs) {
1066
- if (my_dash_default.isPlainObject(arg)) throw new Error("fallback() does not support key-value arguments");
1067
- const resolvedChildValue = await arg.resolve();
1068
- if (resolvedChildValue !== void 0 && resolvedChildValue !== "") {
1069
- return resolvedChildValue;
961
+ if (settings?.maxLength !== void 0 && val.length > settings.maxLength) {
962
+ errors.push(new ValidationError(`Length must be less than ${settings.maxLength}`));
1070
963
  }
964
+ if (settings?.isLength !== void 0 && val.length !== settings.isLength) {
965
+ errors.push(new ValidationError(`Length must be exactly ${settings.isLength}`));
966
+ }
967
+ if (settings?.startsWith && !val.startsWith(settings.startsWith)) {
968
+ errors.push(new ValidationError(`Value must start with "${settings.startsWith}"`));
969
+ }
970
+ if (settings?.endsWith && !val.endsWith(settings.endsWith)) {
971
+ errors.push(new ValidationError(`Value must start with "${settings.endsWith}"`));
972
+ }
973
+ if (settings?.matches) {
974
+ const regex = my_dash_default.isString(settings.matches) ? new RegExp(settings.matches) : settings.matches;
975
+ const matches = val.match(regex);
976
+ if (!matches) {
977
+ errors.push(new ValidationError(`Value must match regex "${settings.matches}"`));
978
+ }
979
+ }
980
+ return errors.length ? errors : true;
981
+ }, "validate")
982
+ })
983
+ );
984
+ var NumberDataType = createEnvGraphDataType(
985
+ (settings) => ({
986
+ name: "number",
987
+ icon: "carbon:string-integer",
988
+ coerce(rawVal) {
989
+ let numVal = coerceToNumber(rawVal);
990
+ if (settings?.coerceToMinMaxRange) {
991
+ if (settings?.min !== void 0) numVal = Math.max(settings?.min, numVal);
992
+ if (settings?.max !== void 0) numVal = Math.min(settings?.max, numVal);
993
+ }
994
+ if (settings?.isInt === true || settings?.precision === 0) {
995
+ numVal = Math.round(numVal);
996
+ } else if (settings?.precision) {
997
+ const p = 10 ** settings.precision;
998
+ numVal = Math.round(numVal * p) / p;
999
+ }
1000
+ return numVal;
1001
+ },
1002
+ validate(val) {
1003
+ const errors = [];
1004
+ if (settings?.min !== void 0 && val < settings?.min) {
1005
+ errors.push(new ValidationError(`Min value is ${settings?.min}`));
1006
+ }
1007
+ if (settings?.max !== void 0 && val > settings?.max) {
1008
+ errors.push(new ValidationError(`Max value is ${settings?.max}`));
1009
+ }
1010
+ if (settings?.isDivisibleBy !== void 0 && val % settings.isDivisibleBy !== 0) {
1011
+ errors.push(new ValidationError(`Value must be divisible by ${settings?.isDivisibleBy}`));
1012
+ }
1013
+ return errors.length ? errors : true;
1071
1014
  }
1072
- }
1073
- };
1074
- var ExecResolver = class _ExecResolver extends Resolver {
1075
- static {
1076
- __name(this, "ExecResolver");
1077
- }
1078
- static fnName = "exec";
1079
- label = "exec";
1080
- icon = "iconoir:terminal";
1081
- async _process() {
1082
- if (this.fnArgs.length !== 1) {
1083
- throw new SchemaError("exec() expects a single child arg");
1084
- }
1085
- if (this.fnArgs.some((arg) => my_dash_default.isPlainObject(arg))) {
1086
- throw new SchemaError("exec() does not support key-value arguments");
1087
- }
1088
- }
1089
- static execQueue = new SimpleQueue();
1090
- async _resolve() {
1091
- if (my_dash_default.isPlainObject(this.fnArgs[0])) throw new Error("exec() does not support key-value arguments");
1092
- const commandStr = await this.fnArgs[0].resolve();
1093
- if (typeof commandStr !== "string") {
1094
- throw new ResolutionError("exec() expects a string child arg");
1095
- }
1096
- try {
1097
- const { stdout, stderr } = await _ExecResolver.execQueue.enqueue(() => execAsync(commandStr));
1098
- return stdout.replace(/\n$/, "");
1099
- } catch (err) {
1100
- console.log("exec() failed", err);
1101
- throw new ResolutionError(`exec() command failed: ${commandStr}`);
1102
- }
1103
- }
1104
- };
1105
- var RefResolver = class extends Resolver {
1106
- static {
1107
- __name(this, "RefResolver");
1108
- }
1109
- static fnName = "ref";
1110
- label = "ref";
1111
- icon = "mdi-light:content-duplicate";
1112
- refKey;
1113
- async _process() {
1114
- if (this.fnArgs.length !== 1) {
1115
- throw new SchemaError("ref() expects a single child arg");
1116
- }
1117
- if (!(this.fnArgs[0] instanceof StaticValueResolver)) {
1118
- throw new SchemaError("ref() expects a single static value passed in");
1119
- }
1120
- const keyName = this.fnArgs[0].staticValue;
1121
- if (typeof keyName !== "string") {
1122
- throw new SchemaError("ref() expects a string keyname passed in");
1123
- }
1124
- this.refKey = keyName;
1125
- this.addDep(keyName);
1126
- }
1127
- async _resolve() {
1128
- if (!this.refKey) throw new Error("expected refKey to be set");
1129
- return this.getDepValue(this.refKey);
1130
- }
1131
- };
1132
- var RegexResolver = class extends Resolver {
1133
- static {
1134
- __name(this, "RegexResolver");
1135
- }
1136
- static fnName = "regex";
1137
- label = "regex";
1138
- icon = "mdi:regex";
1139
- regex;
1140
- async _process() {
1141
- if (this.fnArgs.length !== 1) {
1142
- throw new SchemaError("regex() expects a single child arg");
1143
- }
1144
- if (!(this.fnArgs[0] instanceof StaticValueResolver)) {
1145
- throw new SchemaError("regex() expects a single static value passed in");
1146
- }
1147
- const regexStr = this.fnArgs[0].staticValue;
1148
- if (typeof regexStr !== "string") {
1149
- throw new SchemaError("regex() expects a string");
1150
- }
1151
- this.regex = new RegExp(regexStr);
1152
- }
1153
- async _resolve() {
1154
- if (!this.regex) throw new Error("expected regex to be set");
1155
- return this.regex;
1156
- }
1157
- };
1158
- var RemapResolver = class extends Resolver {
1159
- static {
1160
- __name(this, "RemapResolver");
1161
- }
1162
- static fnName = "remap";
1163
- label = "remap";
1164
- icon = "codicon:replace";
1165
- remappings;
1166
- async _process() {
1167
- if (my_dash_default.isPlainObject(this.fnArgs[0])) {
1168
- throw new SchemaError("remap() expects the first arg to be the value to remap");
1169
- }
1170
- if (!my_dash_default.isPlainObject(this.fnArgs[1])) {
1171
- throw new SchemaError("remap() expects the all args after the first to be key-value pairs of remappings");
1172
- }
1173
- if (this.fnArgs.length !== 2) {
1174
- throw new SchemaError("remap() should not have any additional non key-value args after remappings");
1015
+ })
1016
+ );
1017
+ var BooleanDataType = createEnvGraphDataType({
1018
+ name: "boolean",
1019
+ icon: "carbon:boolean",
1020
+ // probably want allow some settings
1021
+ // - more strict about coercion or adding additional true/false values
1022
+ // - coercing to other values - like 0,1
1023
+ coerce(val) {
1024
+ if (my_dash_default.isBoolean(val)) {
1025
+ return val;
1026
+ } else if (my_dash_default.isString(val)) {
1027
+ const cleanVal = val.toLowerCase().trim();
1028
+ if (["t", "true", "yes", "on", "1"].includes(cleanVal)) return true;
1029
+ if (["f", "false", "no", "off", "0"].includes(cleanVal)) return false;
1030
+ throw new CoercionError("Unable to coerce string value to boolean");
1031
+ } else if (my_dash_default.isNumber(val)) {
1032
+ if (val === 0) return false;
1033
+ if (val === 1) return true;
1034
+ throw new CoercionError("Unable to coerce number value to boolean (only 0 or 1 is valid)");
1035
+ } else {
1036
+ throw new CoercionError("Unable to coerce value to boolean");
1175
1037
  }
1176
- this.remappings = this.fnArgs[1];
1038
+ },
1039
+ // TODO: add settings to be more strict, or to allow other values to coerce to true/false
1040
+ validate(val) {
1041
+ if (my_dash_default.isBoolean(val)) return true;
1042
+ return new ValidationError("Value must be `true` or `false`");
1177
1043
  }
1178
- async _resolve() {
1179
- if (my_dash_default.isPlainObject(this.fnArgs[0])) {
1180
- throw new SchemaError("remap() expects the first arg to be the value to remap");
1181
- }
1182
- if (!my_dash_default.isPlainObject(this.fnArgs[1])) {
1183
- throw new SchemaError("remap() expects the all args after the first to be key-value pairs of remappings");
1044
+ });
1045
+ var UrlDataType = createEnvGraphDataType(
1046
+ (settings) => ({
1047
+ name: "url",
1048
+ icon: "carbon:url",
1049
+ coerce(rawVal) {
1050
+ const val = coerceToString(rawVal);
1051
+ if (settings?.prependHttps && !val.startsWith("https://")) return `https://${val}`;
1052
+ return val;
1053
+ },
1054
+ validate(val) {
1055
+ const url = new URL(val);
1056
+ if (settings?.allowedDomains && !settings.allowedDomains.includes(url.host.toLowerCase())) {
1057
+ return new ValidationError(`Domain (${url.host}) is not in allowed list: ${settings.allowedDomains.join(",")}`);
1058
+ }
1059
+ return true;
1184
1060
  }
1185
- const originalValue = await this.fnArgs[0].resolve();
1186
- if (!this.remappings) throw new Error("expected remappings to be set");
1187
- for (const [remappedVal, matchValResolver] of Object.entries(this.remappings)) {
1188
- const matchVal = await matchValResolver.resolve();
1189
- if (matchVal instanceof RegExp && originalValue !== void 0) {
1190
- if (matchVal.test(String(originalValue))) return remappedVal;
1191
- } else {
1192
- if (matchVal === originalValue) return remappedVal;
1061
+ })
1062
+ );
1063
+ var SimpleObjectDataType = createEnvGraphDataType({
1064
+ name: "simple-object",
1065
+ icon: "tabler:code-dots",
1066
+ // curly brackets with nothing inside
1067
+ coerce(val) {
1068
+ if (my_dash_default.isPlainObject(val)) return val;
1069
+ if (my_dash_default.isString(val)) {
1070
+ try {
1071
+ const parsedObj = JSON.parse(val);
1072
+ if (my_dash_default.isPlainObject(parsedObj)) return parsedObj;
1073
+ return new CoercionError("Unable to coerce JSON parsed string to object");
1074
+ } catch (err) {
1075
+ return new CoercionError("Error parsing JSON string while coercing string to object");
1193
1076
  }
1194
1077
  }
1195
- return originalValue;
1196
- }
1197
- };
1198
- var BaseResolvers = [
1199
- ConcatResolver,
1200
- FallbackResolver,
1201
- RefResolver,
1202
- ExecResolver,
1203
- RemapResolver,
1204
- RegexResolver
1205
- ];
1206
-
1207
- // ../env-graph/src/lib/data-source.ts
1208
- var DATA_SOURCE_TYPES = Object.freeze({
1209
- schema: {
1210
- fileSuffixes: ["schema"],
1211
- precedence: 0
1212
- },
1213
- example: {
1214
- fileSuffixes: ["sample", "example"],
1215
- precedence: 1
1216
- },
1217
- defaults: {
1218
- fileSuffixes: ["default", "defaults"],
1219
- precedence: 2
1220
- },
1221
- values: {
1222
- fileSuffixes: [],
1223
- precedence: 3
1078
+ return new CoercionError("Cannot coerce value to object");
1224
1079
  },
1225
- overrides: {
1226
- fileSuffixes: ["local", "override"],
1227
- precedence: 4
1080
+ validate(val) {
1081
+ if (my_dash_default.isPlainObject(val)) return true;
1082
+ return new ValidationError("Value must be an object");
1228
1083
  }
1229
1084
  });
1230
- var EnvGraphDataSource = class {
1231
- static {
1232
- __name(this, "EnvGraphDataSource");
1233
- }
1234
- static DATA_SOURCE_TYPES = DATA_SOURCE_TYPES;
1235
- // reference back to the graph
1236
- graph;
1237
- type = "values";
1238
- applyForEnv;
1239
- disabled = false;
1240
- ignoreNewDefs = false;
1241
- /** an error encountered while loading/parsing the data source */
1242
- loadingError;
1243
- get isValid() {
1244
- return !this.loadingError;
1245
- }
1246
- configItemDefs = {};
1247
- decorators = {};
1248
- getStaticValues() {
1249
- const obj = {};
1250
- for (const [key, def] of Object.entries(this.configItemDefs)) {
1251
- if (def.resolver instanceof StaticValueResolver) {
1252
- obj[key] = String(def.resolver.staticValue ?? "");
1085
+ var EnumDataType = createEnvGraphDataType(
1086
+ (...enumOptions) => ({
1087
+ name: "enum",
1088
+ icon: "material-symbols-light:category",
1089
+ // a few shapes... not sure about this one
1090
+ coerce(val) {
1091
+ if (my_dash_default.isString(val) || my_dash_default.isNumber(val) || my_dash_default.isBoolean(val)) return val;
1092
+ return new CoercionError("Value must be a string, number, or boolean");
1093
+ },
1094
+ validate(val) {
1095
+ const possibleValues = enumOptions || [];
1096
+ if (!possibleValues.includes(val)) {
1097
+ throw new ValidationError("Current value is not in list of possible values", {
1098
+ tip: `Possible values are: "${possibleValues.join('", "')}"`
1099
+ });
1253
1100
  }
1101
+ },
1102
+ _rawEnumOptions: enumOptions
1103
+ })
1104
+ );
1105
+ var EMAIL_REGEX = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
1106
+ var EmailDataType = createEnvGraphDataType(
1107
+ (settings) => ({
1108
+ name: "email",
1109
+ icon: "iconoir:at-sign",
1110
+ typeDescription: "standard email address",
1111
+ coerce(rawVal) {
1112
+ let val = coerceToString(rawVal);
1113
+ if (settings?.normalize) val = val.toLowerCase();
1114
+ return val;
1115
+ },
1116
+ validate(val) {
1117
+ const result = EMAIL_REGEX.test(val);
1118
+ if (result) return true;
1119
+ return new ValidationError("Value must be a valid email address");
1254
1120
  }
1255
- return obj;
1121
+ })
1122
+ );
1123
+ var IP_V4_ADDRESS_REGEX = /^(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}$/;
1124
+ var IP_V6_ADDRESS_REGEX = /^(?:(?:[a-fA-F\d]{1,4}:){7}(?:[a-fA-F\d]{1,4}|:)|(?:[a-fA-F\d]{1,4}:){6}(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|:[a-fA-F\d]{1,4}|:)|(?:[a-fA-F\d]{1,4}:){5}(?::(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,2}|:)|(?:[a-fA-F\d]{1,4}:){4}(?:(?::[a-fA-F\d]{1,4}){0,1}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,3}|:)|(?:[a-fA-F\d]{1,4}:){3}(?:(?::[a-fA-F\d]{1,4}){0,2}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,4}|:)|(?:[a-fA-F\d]{1,4}:){2}(?:(?::[a-fA-F\d]{1,4}){0,3}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,5}|:)|(?:[a-fA-F\d]{1,4}:){1}(?:(?::[a-fA-F\d]{1,4}){0,4}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,6}|:)|(?::(?:(?::[a-fA-F\d]{1,4}){0,5}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,7}|:)))(?:%[0-9a-zA-Z]{1,})?$/;
1125
+ var ipAddressDataType = createEnvGraphDataType(
1126
+ (settings) => ({
1127
+ name: "ip",
1128
+ icon: "iconoir:ip-address-tag",
1129
+ typeDescription: "ip v4 or v6 address",
1130
+ coerce(rawVal) {
1131
+ let val = coerceToString(rawVal);
1132
+ if (settings?.normalize) val = val.toLowerCase();
1133
+ return val;
1134
+ },
1135
+ validate(val) {
1136
+ const regex = settings?.version === 6 ? IP_V6_ADDRESS_REGEX : IP_V4_ADDRESS_REGEX;
1137
+ const result = regex.test(val);
1138
+ if (result) return true;
1139
+ return new ValidationError("Value must be a valid IP address");
1140
+ }
1141
+ })
1142
+ );
1143
+ var PortDataType = createEnvGraphDataType(
1144
+ (settings) => ({
1145
+ name: "port",
1146
+ icon: "material-symbols:captive-portal",
1147
+ //! globe with arrow - not sure about this one
1148
+ typeDescription: "valid port number between 0 and 65535",
1149
+ coerce(rawVal) {
1150
+ if (my_dash_default.isString(rawVal)) {
1151
+ if (rawVal.includes(".")) throw new CoercionError("Port number must be an integer");
1152
+ if (rawVal.includes("e")) throw new CoercionError("Port number should be an integer, not in exponential notation");
1153
+ }
1154
+ return coerceToNumber(rawVal);
1155
+ },
1156
+ validate(val) {
1157
+ if (settings?.min !== void 0 && val < settings?.min) {
1158
+ return new ValidationError(`Min value is ${settings?.min}`);
1159
+ }
1160
+ if (settings?.max !== void 0 && val > settings?.max) {
1161
+ return new ValidationError(`Max value is ${settings?.max}`);
1162
+ }
1163
+ if (val < 0 || val > 65535) {
1164
+ return new ValidationError("Value must be a valid port number (0-65535)");
1165
+ }
1166
+ return true;
1167
+ }
1168
+ })
1169
+ );
1170
+ var SEMVER_REGEX = /^(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-]+)*))?$/;
1171
+ var SemverDataType = createEnvGraphDataType(
1172
+ (settings) => ({
1173
+ name: "semver",
1174
+ icon: "simple-icons:semver",
1175
+ typeDescription: "semantic version string",
1176
+ validate(val) {
1177
+ const result = SEMVER_REGEX.test(val);
1178
+ if (result) return true;
1179
+ return new ValidationError("Value must be a valid semantic version string");
1180
+ }
1181
+ })
1182
+ );
1183
+ var ISO_DATE_REGEX = /^(?:[+-]?\d{4}(?!\d{2}\b))(?:(-?)(?:(?:0[1-9]|1[0-2])(?:\1(?:[12]\d|0[1-9]|3[01]))?|W(?:[0-4]\d|5[0-2])(?:-?[1-7])?|(?:00[1-9]|0[1-9]\d|[12]\d{2}|3(?:[0-5]\d|6[1-6])))(?:[T\s](?:(?:(?:[01]\d|2[0-3])(?:(:?)[0-5]\d)?|24:?00)(?:[.,]\d+(?!:))?)?(?:\2[0-5]\d(?:[.,]\d+)?)?(?:[zZ]|(?:[+-])(?:[01]\d|2[0-3]):?(?:[0-5]\d)?)?)?)?$/;
1184
+ var IsoDateDataType = createEnvGraphDataType({
1185
+ name: "isoDate",
1186
+ icon: "formkit:datetime",
1187
+ typeDescription: "ISO 8601 date string with optional time and milliseconds",
1188
+ validate(val) {
1189
+ const result = ISO_DATE_REGEX.test(val);
1190
+ if (result) return true;
1191
+ return new ValidationError("Value must be a valid ISO 8601 date string");
1192
+ }
1193
+ });
1194
+ var UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-5][0-9a-f]{3}-[089ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
1195
+ var UuidDataType = createEnvGraphDataType({
1196
+ name: "uuid",
1197
+ icon: "mdi:identifier",
1198
+ typeDescription: "UUID string V1-V5 per RFC4122, including NIL",
1199
+ validate(val) {
1200
+ const result = UUID_REGEX.test(val);
1201
+ if (result) return true;
1202
+ return new ValidationError("Value must be a valid UUID string");
1203
+ }
1204
+ });
1205
+ var MD5_REGEX = /^[a-f0-9]{32}$/;
1206
+ var Md5DataType = createEnvGraphDataType({
1207
+ name: "md5",
1208
+ typeDescription: "MD5 hash string",
1209
+ validate(val) {
1210
+ const result = MD5_REGEX.test(val);
1211
+ if (result) return true;
1212
+ return new ValidationError("Value must be a valid MD5 hash string");
1256
1213
  }
1214
+ });
1215
+ var BaseDataTypes = {
1216
+ string: StringDataType,
1217
+ number: NumberDataType,
1218
+ boolean: BooleanDataType,
1219
+ simpleObject: SimpleObjectDataType,
1220
+ enum: EnumDataType,
1221
+ email: EmailDataType,
1222
+ url: UrlDataType,
1223
+ ipAddress: ipAddressDataType,
1224
+ port: PortDataType,
1225
+ semver: SemverDataType,
1226
+ isoDate: IsoDateDataType,
1227
+ uuid: UuidDataType,
1228
+ md5: Md5DataType
1257
1229
  };
1258
- var ProcessEnvDataSource = class _ProcessEnvDataSource extends EnvGraphDataSource {
1230
+
1231
+ // ../env-graph/src/lib/simple-queue.ts
1232
+ var SimpleQueue = class {
1259
1233
  static {
1260
- __name(this, "ProcessEnvDataSource");
1234
+ __name(this, "SimpleQueue");
1261
1235
  }
1262
- type = "overrides";
1263
- typeLabel = "process";
1264
- label = "process.env";
1265
- ignoreNewDefs = true;
1266
- static processEnvValues;
1267
- // ? do we want to set decorator values from env vars here? -- ex: _ENV_FLAG_KEY
1268
- // depends if we want those to work only within process.env
1269
- constructor() {
1270
- super();
1271
- if (!_ProcessEnvDataSource.processEnvValues) {
1272
- _ProcessEnvDataSource.processEnvValues = {};
1273
- for (const itemKey of Object.keys(process.env)) {
1274
- _ProcessEnvDataSource.processEnvValues[itemKey] = process.env[itemKey];
1275
- }
1236
+ queue = [];
1237
+ processing = false;
1238
+ /** Add a task to the queue and return a promise that resolves when the task is complete */
1239
+ async enqueue(task) {
1240
+ return new Promise((resolve, reject) => {
1241
+ this.queue.push(async () => {
1242
+ try {
1243
+ const result = await task();
1244
+ resolve(result);
1245
+ } catch (err) {
1246
+ reject(err);
1247
+ }
1248
+ });
1249
+ this.processQueue();
1250
+ });
1251
+ }
1252
+ async processQueue() {
1253
+ if (this.processing || this.queue.length === 0) {
1254
+ return;
1276
1255
  }
1277
- for (const itemKey of Object.keys(_ProcessEnvDataSource.processEnvValues)) {
1278
- this.configItemDefs[itemKey] = {
1279
- resolver: new StaticValueResolver(_ProcessEnvDataSource.processEnvValues[itemKey])
1280
- };
1256
+ this.processing = true;
1257
+ const task = this.queue.shift();
1258
+ if (task) {
1259
+ try {
1260
+ await task();
1261
+ } finally {
1262
+ this.processing = false;
1263
+ this.processQueue();
1264
+ }
1281
1265
  }
1282
1266
  }
1283
1267
  };
1284
- var EnvSourceParseError = class extends Error {
1285
- constructor(message, location) {
1286
- super(message);
1287
- this.location = location;
1268
+
1269
+ // ../env-graph/src/lib/resolver.ts
1270
+ var execAsync = promisify(exec);
1271
+ var Resolver = class {
1272
+ constructor(fnArgs) {
1273
+ this.fnArgs = fnArgs;
1288
1274
  }
1289
1275
  static {
1290
- __name(this, "EnvSourceParseError");
1276
+ __name(this, "Resolver");
1291
1277
  }
1292
- };
1293
- var FileBasedDataSource = class extends EnvGraphDataSource {
1294
- static {
1295
- __name(this, "FileBasedDataSource");
1278
+ static fnName;
1279
+ inferredType;
1280
+ _schemaErrors = [];
1281
+ _depsObj = {};
1282
+ get childResolvers() {
1283
+ return this.fnArgs.flatMap((r) => my_dash_default.isPlainObject(r) ? my_dash_default.values(r) : r);
1296
1284
  }
1297
- isGitIgnored;
1298
- fullPath;
1299
- fileName;
1300
- rawContents;
1301
- get typeLabel() {
1302
- return this.constructor.format;
1285
+ get schemaErrors() {
1286
+ return [
1287
+ ...this._schemaErrors,
1288
+ ...this.childResolvers.flatMap((r) => r.schemaErrors)
1289
+ ];
1303
1290
  }
1304
- get label() {
1305
- return this.fileName;
1291
+ get depsObj() {
1292
+ const mergedDepsObj = { ...this._depsObj };
1293
+ this.childResolvers.forEach((r) => Object.assign(mergedDepsObj, r.depsObj));
1294
+ return mergedDepsObj;
1306
1295
  }
1307
- static format = "unknown";
1308
- // no abstract static
1309
- static validFileExtensions = [];
1310
- get validFileExtensions() {
1311
- return this.constructor.validFileExtensions;
1296
+ get deps() {
1297
+ return Object.keys(this.depsObj);
1312
1298
  }
1313
- constructor(fullPath, opts) {
1314
- super();
1315
- this.fullPath = fullPath;
1316
- this.fileName = path.basename(fullPath);
1317
- if (opts?.overrideContents) {
1318
- this.rawContents = opts.overrideContents;
1319
- this.isGitIgnored = opts.overrideGitIgnored;
1320
- }
1321
- if (!this.fileName.startsWith(".env")) {
1322
- throw new Error('file name must start with ".env"');
1323
- }
1324
- const fileNameParts = this.fileName.substring(1).split(".");
1325
- const maybeExtension = fileNameParts[fileNameParts.length - 1];
1326
- if (this.validFileExtensions.includes(maybeExtension)) {
1327
- fileNameParts.pop();
1328
- }
1329
- const maybeFileType = fileNameParts[fileNameParts.length - 1];
1330
- for (const [possibleSourceType, possibleSourceSpec] of Object.entries(DATA_SOURCE_TYPES)) {
1331
- if (possibleSourceSpec.fileSuffixes.includes(maybeFileType)) {
1332
- this.type = possibleSourceType;
1333
- break;
1299
+ configItem;
1300
+ async process(configItem) {
1301
+ this.configItem = configItem;
1302
+ try {
1303
+ await this._process(configItem);
1304
+ } catch (error) {
1305
+ if (error instanceof SchemaError) {
1306
+ this._schemaErrors.push(error);
1307
+ } else if (error instanceof Error) {
1308
+ this._schemaErrors.push(new SchemaError(error));
1309
+ } else {
1310
+ throw new Error(`Non-error thrown while processing resolver - ${error}`);
1334
1311
  }
1335
1312
  }
1336
- if (this.type !== "values") fileNameParts.pop();
1337
- if (fileNameParts.length > 2) {
1338
- throw Error(`Unsure how to interpret filename - ${this.fileName}`);
1339
- } else if (fileNameParts.length === 2) {
1340
- this.applyForEnv = fileNameParts[1];
1341
- if (this.applyForEnv === "dev") this.applyForEnv = "development";
1342
- if (this.applyForEnv === "stage") this.applyForEnv = "staging";
1343
- if (this.applyForEnv === "prod") this.applyForEnv = "production";
1344
- }
1313
+ this.childResolvers.forEach((r) => r.process(configItem));
1345
1314
  }
1346
- // no async constructors... :(
1347
- async finishInit() {
1348
- if (!this.rawContents) {
1349
- this.isGitIgnored = await checkIsFileGitIgnored(this.fullPath);
1350
- this.rawContents = await fs.readFile(this.fullPath, "utf8");
1315
+ // meant to be used by subclass _process methods
1316
+ addDep(key) {
1317
+ this._depsObj[key] = true;
1318
+ if (!this.configItem) throw new Error("expected configItem to be set");
1319
+ if (!this.configItem.envGraph.configSchema[key]) {
1320
+ this._schemaErrors.push(new SchemaError(`Unknown referenced key: ${key}`));
1351
1321
  }
1352
- await this._parseContents();
1322
+ }
1323
+ async resolve() {
1324
+ const resolvedValue = await this._resolve();
1325
+ return resolvedValue;
1326
+ }
1327
+ // meant to be used by subclass _resolve methods
1328
+ getDepValue(key) {
1329
+ const depItem = this.configItem?.envGraph.configSchema[key];
1330
+ if (!depItem) throw new Error(`Expected to find item - ${key}`);
1331
+ return depItem.resolvedValue;
1353
1332
  }
1354
1333
  };
1355
- var DotEnvFileDataSource = class extends FileBasedDataSource {
1334
+ var StaticValueResolver = class extends Resolver {
1335
+ constructor(staticValue) {
1336
+ super([]);
1337
+ this.staticValue = staticValue;
1338
+ if (staticValue !== void 0) {
1339
+ this.inferredType = typeof staticValue;
1340
+ }
1341
+ }
1356
1342
  static {
1357
- __name(this, "DotEnvFileDataSource");
1343
+ __name(this, "StaticValueResolver");
1358
1344
  }
1359
- static format = ".env";
1360
- static validFileExtensions = [];
1361
- // no extension for dotenv files!
1362
- parsedFile;
1363
- convertParserValueToResolvers(value) {
1364
- if (!this.graph) throw new Error("expected graph to be set");
1365
- if (value === void 0) {
1366
- return new StaticValueResolver(void 0);
1367
- } else if (value instanceof ParsedEnvSpecStaticValue) {
1368
- return new StaticValueResolver(value.unescapedValue);
1369
- } else if (value instanceof ParsedEnvSpecFunctionCall) {
1370
- const ResolverFnClass = this.graph.registeredResolverFunctions[value.name];
1371
- if (!ResolverFnClass) {
1372
- return new ErrorResolver(new SchemaError(`Unknown resolver function: ${value.name}()`));
1373
- }
1374
- const argsFromParser = value.data.args.values;
1375
- let keyValueArgs;
1376
- const argsAsResolversArray = [];
1377
- for (const arg of argsFromParser) {
1378
- if (arg instanceof ParsedEnvSpecKeyValuePair) {
1379
- keyValueArgs ??= {};
1380
- keyValueArgs[arg.key] = this.convertParserValueToResolvers(arg.value);
1381
- } else {
1382
- if (keyValueArgs) {
1383
- return new ErrorResolver(new SchemaError("After switching to key-value function args, cannot switch back"));
1384
- }
1385
- argsAsResolversArray.push(this.convertParserValueToResolvers(arg));
1386
- }
1387
- }
1388
- if (keyValueArgs) argsAsResolversArray.push(keyValueArgs);
1389
- return new ResolverFnClass(argsAsResolversArray);
1390
- } else {
1391
- throw new Error("Unknown value type");
1392
- }
1345
+ label = "static";
1346
+ icon = "bi:dash";
1347
+ async _resolve() {
1348
+ return this.staticValue;
1393
1349
  }
1394
- async _parseContents() {
1395
- const rawContents = this.rawContents;
1396
- this.parsedFile = await tryCatch(
1397
- () => parseEnvSpecDotEnvFile(rawContents),
1398
- (error) => {
1399
- this.loadingError = new EnvSourceParseError(error.message, {
1400
- path: this.fullPath,
1401
- lineNumber: error.location.start.line,
1402
- colNumber: error.location.start.column,
1403
- lineStr: rawContents.split("\n")[error.location.start.line - 1]
1404
- });
1405
- this.loadingError.cause = error;
1406
- }
1407
- );
1408
- if (this.loadingError) return;
1409
- if (!this.parsedFile) throw new Error("Failed to parse .env file");
1410
- this.decorators = this.parsedFile.decoratorsObject;
1411
- if (!this.graph) throw new Error("expected graph to be set");
1412
- for (const item of this.parsedFile.configItems) {
1413
- item.processExpansion();
1414
- this.configItemDefs[item.key] = {
1415
- resolver: this.convertParserValueToResolvers(item.expandedValue),
1416
- description: item.description,
1417
- decorators: item.decoratorsObject
1418
- };
1419
- }
1350
+ async _process() {
1420
1351
  }
1421
1352
  };
1422
- var ConfigItem = class {
1423
- constructor(envGraph, key) {
1424
- this.envGraph = envGraph;
1425
- this.key = key;
1426
- }
1353
+ var ErrorResolver = class extends Resolver {
1427
1354
  static {
1428
- __name(this, "ConfigItem");
1355
+ __name(this, "ErrorResolver");
1429
1356
  }
1430
- defs = [];
1431
- addDef(itemDef, source) {
1432
- this.defs.unshift({ itemDef, source });
1357
+ constructor(err) {
1358
+ super([]);
1359
+ this._schemaErrors.push(err);
1433
1360
  }
1434
- get description() {
1435
- for (const def of this.defs) {
1436
- if (def.itemDef.description) return def.itemDef.description;
1437
- }
1361
+ label = "error";
1362
+ icon = "bi:dash";
1363
+ async _resolve() {
1364
+ return void 0;
1438
1365
  }
1439
- get icon() {
1440
- const explicitIcon = this.getDecoratorValueString("icon");
1441
- if (explicitIcon) return explicitIcon;
1442
- return this.dataType?.icon;
1366
+ async _process() {
1443
1367
  }
1444
- get docsLinks() {
1445
- const links = [];
1446
- const docsUrl = this.getDecoratorValueString("docsUrl");
1447
- if (docsUrl) links.push({ url: docsUrl });
1448
- return links;
1368
+ };
1369
+ var ConcatResolver = class extends Resolver {
1370
+ static {
1371
+ __name(this, "ConcatResolver");
1449
1372
  }
1450
- get valueResolver() {
1451
- for (const def of this.defs) {
1452
- if (def.itemDef.resolver) return def.itemDef.resolver;
1373
+ static fnName = "concat";
1374
+ label = "concat";
1375
+ icon = "material-symbols:join";
1376
+ inferredType = "string";
1377
+ async _process() {
1378
+ if (this.fnArgs.some((arg) => my_dash_default.isPlainObject(arg))) {
1379
+ throw new SchemaError("concat() does not support key-value arguments");
1453
1380
  }
1454
- }
1455
- getDecorator(decoratorName) {
1456
- for (const def of this.defs) {
1457
- const defDecorators = def.itemDef.decorators || {};
1458
- if (decoratorName in defDecorators) {
1459
- return defDecorators[decoratorName];
1460
- }
1381
+ if (this.fnArgs.length < 2) {
1382
+ throw new SchemaError("concat() expects at least two arguments");
1461
1383
  }
1462
1384
  }
1463
- getDecoratorValueRaw(decoratorName) {
1464
- for (const def of this.defs) {
1465
- const defDecorators = def.itemDef.decorators || {};
1466
- if (decoratorName in defDecorators) {
1467
- return defDecorators[decoratorName].value;
1385
+ async _resolve() {
1386
+ const resolvedValues = [];
1387
+ for (const arg of this.fnArgs) {
1388
+ if (my_dash_default.isPlainObject(arg)) {
1389
+ throw new Error("concat() does not support key-value arguments");
1468
1390
  }
1391
+ const resolvedChildValue = await arg.resolve();
1392
+ resolvedValues.push(String(resolvedChildValue ?? ""));
1469
1393
  }
1394
+ return resolvedValues.join("");
1470
1395
  }
1471
- getDecoratorValueString(decoratorName) {
1472
- const dec = this.getDecoratorValueRaw(decoratorName);
1473
- if (dec instanceof ParsedEnvSpecStaticValue) return String(dec.value);
1474
- }
1475
- dataType;
1476
- schemaErrors = [];
1477
- get resolverSchemaErrors() {
1478
- return this.valueResolver?.schemaErrors || [];
1396
+ };
1397
+ var FallbackResolver = class extends Resolver {
1398
+ static {
1399
+ __name(this, "FallbackResolver");
1479
1400
  }
1480
- async process() {
1481
- const finalOverrideDef = this.envGraph.finalOverridesDataSource?.configItemDefs[this.key];
1482
- if (finalOverrideDef) {
1483
- this.defs.unshift({ itemDef: finalOverrideDef, source: this.envGraph.finalOverridesDataSource });
1484
- }
1485
- for (const def of this.defs) {
1486
- await def.itemDef.resolver?.process(this);
1401
+ static fnName = "fallback";
1402
+ label = "fallback";
1403
+ icon = "memory:table-top-stairs-up";
1404
+ async _process() {
1405
+ if (this.fnArgs.some((arg) => my_dash_default.isPlainObject(arg))) {
1406
+ throw new SchemaError("fallback() does not support key-value arguments");
1487
1407
  }
1488
- const typeDecoratorValue = this.getDecoratorValueRaw("type");
1489
- let dataTypeName;
1490
- let dataTypeArgs;
1491
- if (typeDecoratorValue instanceof ParsedEnvSpecStaticValue) {
1492
- dataTypeName = typeDecoratorValue.value;
1493
- } else if (typeDecoratorValue instanceof ParsedEnvSpecFunctionCall) {
1494
- dataTypeName = typeDecoratorValue.name;
1495
- dataTypeArgs = typeDecoratorValue.simplifiedArgs;
1408
+ if (this.fnArgs.length < 2) {
1409
+ throw new SchemaError("fallback() expects at least two arguments");
1496
1410
  }
1497
- if (!dataTypeName) {
1498
- if (this.valueResolver?.inferredType) {
1499
- dataTypeName = this.valueResolver.inferredType;
1411
+ }
1412
+ async _resolve() {
1413
+ for (const arg of this.fnArgs) {
1414
+ if (my_dash_default.isPlainObject(arg)) throw new Error("fallback() does not support key-value arguments");
1415
+ const resolvedChildValue = await arg.resolve();
1416
+ if (resolvedChildValue !== void 0 && resolvedChildValue !== "") {
1417
+ return resolvedChildValue;
1500
1418
  }
1501
1419
  }
1502
- dataTypeName ||= "string";
1503
- dataTypeArgs ||= [];
1504
- if (!(dataTypeName in this.envGraph.dataTypesRegistry)) {
1505
- this.schemaErrors.push(new SchemaError(`unknown data type: ${dataTypeName}`));
1506
- } else {
1507
- const dataTypeFactory = this.envGraph.dataTypesRegistry[dataTypeName];
1508
- this.dataType = dataTypeFactory(...my_dash_default.isPlainObject(dataTypeArgs) ? [dataTypeArgs] : dataTypeArgs);
1509
- }
1510
1420
  }
1511
- get isRequired() {
1512
- for (const def of this.defs) {
1513
- const defDecorators = def.itemDef.decorators || {};
1514
- if ("required" in defDecorators) {
1515
- const val = defDecorators.required.simplifiedValue;
1516
- if (typeof val === "boolean") return val;
1517
- if (typeof val === "string") return val === "true";
1518
- return Boolean(val);
1519
- }
1520
- if ("optional" in defDecorators) {
1521
- const val = defDecorators.optional.simplifiedValue;
1522
- if (typeof val === "boolean") return !val;
1523
- if (typeof val === "string") return val !== "true";
1524
- return !val;
1525
- }
1526
- if ("defaultRequired" in def.source.decorators) {
1527
- const val = def.source.decorators.defaultRequired.simplifiedValue;
1528
- if (val === "infer") {
1529
- if (def.source.type === "schema") {
1530
- const resolver = def.itemDef.resolver;
1531
- if (resolver instanceof StaticValueResolver) {
1532
- return resolver.staticValue !== void 0 && resolver.staticValue !== "";
1533
- } else {
1534
- return true;
1535
- }
1536
- } else {
1537
- continue;
1538
- }
1539
- }
1540
- return val;
1541
- }
1542
- }
1543
- return true;
1421
+ };
1422
+ var ExecResolver = class _ExecResolver extends Resolver {
1423
+ static {
1424
+ __name(this, "ExecResolver");
1544
1425
  }
1545
- get isSensitive() {
1546
- for (const def of this.defs) {
1547
- const defDecorators = def.itemDef.decorators || {};
1548
- if ("sensitive" in defDecorators) {
1549
- return defDecorators.sensitive.simplifiedValue;
1550
- } else if ("defaultSensitive" in def.source.decorators) {
1551
- const dec = def.source.decorators.defaultSensitive;
1552
- if (dec.value instanceof ParsedEnvSpecFunctionCall && dec.value.name === "inferFromPrefix") {
1553
- const args = dec.value.simplifiedArgs;
1554
- const prefix = Array.isArray(args) && args.length > 0 ? args[0] : void 0;
1555
- if (typeof prefix === "string" && this.key.startsWith(prefix)) {
1556
- return false;
1557
- }
1558
- return true;
1559
- }
1560
- return dec.simplifiedValue;
1561
- }
1426
+ static fnName = "exec";
1427
+ label = "exec";
1428
+ icon = "iconoir:terminal";
1429
+ async _process() {
1430
+ if (this.fnArgs.length !== 1) {
1431
+ throw new SchemaError("exec() expects a single child arg");
1432
+ }
1433
+ if (this.fnArgs.some((arg) => my_dash_default.isPlainObject(arg))) {
1434
+ throw new SchemaError("exec() does not support key-value arguments");
1562
1435
  }
1563
- return true;
1564
- }
1565
- get errors() {
1566
- return my_dash_default.compact([
1567
- ...this.schemaErrors || [],
1568
- ...this.resolverSchemaErrors || [],
1569
- this.resolutionError,
1570
- this.coercionError,
1571
- ...this.validationErrors || []
1572
- ]);
1573
- }
1574
- get validationState() {
1575
- const errors = this.errors;
1576
- if (!errors.length) return "valid";
1577
- return my_dash_default.some(errors, (e) => !e.isWarning) ? "error" : "warn";
1578
- }
1579
- /** resolved value _before coercion_ */
1580
- resolvedRawValue;
1581
- isResolved = false;
1582
- /** resolved value after coercion */
1583
- resolvedValue;
1584
- isValidated = false;
1585
- resolutionError;
1586
- coercionError;
1587
- validationErrors;
1588
- get isCoerced() {
1589
- return this.resolvedRawValue !== this.resolvedValue;
1590
1436
  }
1591
- async resolve() {
1592
- if (this.schemaErrors.length) return;
1593
- if (this.resolverSchemaErrors.length) return;
1594
- if (!this.valueResolver) throw new Error("Expected a resolver to be set");
1595
- if (this.isResolved) {
1596
- return;
1437
+ static execQueue = new SimpleQueue();
1438
+ async _resolve() {
1439
+ if (my_dash_default.isPlainObject(this.fnArgs[0])) throw new Error("exec() does not support key-value arguments");
1440
+ const commandStr = await this.fnArgs[0].resolve();
1441
+ if (typeof commandStr !== "string") {
1442
+ throw new ResolutionError("exec() expects a string child arg");
1597
1443
  }
1598
1444
  try {
1599
- this.resolvedRawValue = await this.valueResolver.resolve();
1445
+ const { stdout, stderr } = await _ExecResolver.execQueue.enqueue(() => execAsync(commandStr));
1446
+ return stdout.replace(/\n$/, "");
1600
1447
  } catch (err) {
1601
- this.resolutionError = new ResolutionError(`error resolving value: ${err}`);
1602
- this.resolutionError.cause = err;
1603
- }
1604
- if (this.resolvedRawValue instanceof RegExp) {
1605
- this.resolutionError = new ResolutionError("regex() is meant to be used within function args, not as a final resolved value");
1448
+ console.log("exec() failed", err);
1449
+ throw new ResolutionError(`exec() command failed: ${commandStr}`);
1606
1450
  }
1607
- if (this.resolutionError) return;
1608
- this.isResolved = true;
1609
- if (this.resolvedRawValue === void 0 || this.resolvedRawValue === "") {
1610
- this.resolvedValue = this.resolvedRawValue;
1611
- if (this.isRequired) {
1612
- this.validationErrors = [new EmptyRequiredValueError(void 0)];
1613
- }
1614
- return;
1451
+ }
1452
+ };
1453
+ var RefResolver = class extends Resolver {
1454
+ static {
1455
+ __name(this, "RefResolver");
1456
+ }
1457
+ static fnName = "ref";
1458
+ label = "ref";
1459
+ icon = "mdi-light:content-duplicate";
1460
+ refKey;
1461
+ async _process() {
1462
+ if (this.fnArgs.length !== 1) {
1463
+ throw new SchemaError("ref() expects a single child arg");
1615
1464
  }
1616
- if (!this.dataType) throw new Error("expected dataType to be set");
1617
- try {
1618
- const coerceResult = this.dataType.coerce(this.resolvedRawValue);
1619
- if (coerceResult instanceof Error) throw coerceResult;
1620
- this.resolvedValue = coerceResult;
1621
- } catch (err) {
1622
- if (err instanceof CoercionError) {
1623
- this.coercionError = err;
1624
- return;
1625
- } else if (err instanceof Error) {
1626
- this.coercionError = new CoercionError("Unexpected error coercing value");
1627
- this.coercionError.cause = err;
1628
- } else {
1629
- this.coercionError = new CoercionError(`Unexpected non-error throw during coerce - ${err}`);
1630
- }
1631
- return;
1465
+ if (!(this.fnArgs[0] instanceof StaticValueResolver)) {
1466
+ throw new SchemaError("ref() expects a single static value passed in");
1632
1467
  }
1633
- try {
1634
- const validateResult = this.dataType.validate(this.resolvedValue);
1635
- if (validateResult instanceof Error || my_dash_default.isArray(validateResult) && validateResult[0] instanceof Error) throw validateResult;
1636
- if (validateResult === false) {
1637
- throw new ValidationError("validation failed with `false` return value");
1638
- }
1639
- this.isValidated = true;
1640
- } catch (err) {
1641
- if (my_dash_default.isArray(err)) {
1642
- this.validationErrors = err;
1643
- } else if (err instanceof ValidationError) {
1644
- this.validationErrors = [err];
1645
- } else if (err instanceof Error) {
1646
- const validationError = new ValidationError("Unexpected error during validation");
1647
- validationError.cause = err;
1648
- console.log(err);
1649
- this.validationErrors = [validationError];
1650
- } else {
1651
- const validationError = new ValidationError(`Unexpected non-error thrown during validation - ${err}`);
1652
- validationError.cause = err;
1653
- this.validationErrors = [validationError];
1654
- }
1655
- return;
1468
+ const keyName = this.fnArgs[0].staticValue;
1469
+ if (typeof keyName !== "string") {
1470
+ throw new SchemaError("ref() expects a string keyname passed in");
1656
1471
  }
1472
+ this.refKey = keyName;
1473
+ this.addDep(keyName);
1657
1474
  }
1658
- get isValid() {
1659
- return this.validationState === "valid";
1475
+ async _resolve() {
1476
+ if (!this.refKey) throw new Error("expected refKey to be set");
1477
+ return this.getDepValue(this.refKey);
1660
1478
  }
1661
1479
  };
1662
-
1663
- // ../env-graph/src/lib/data-types.ts
1664
- var EnvGraphDataType = class {
1665
- constructor(def, factory) {
1666
- this.def = def;
1667
- this.factory = factory;
1668
- }
1480
+ var RegexResolver = class extends Resolver {
1669
1481
  static {
1670
- __name(this, "EnvGraphDataType");
1671
- }
1672
- get name() {
1673
- return this.def.name;
1482
+ __name(this, "RegexResolver");
1674
1483
  }
1675
- get icon() {
1676
- return this.def.icon;
1484
+ static fnName = "regex";
1485
+ label = "regex";
1486
+ icon = "mdi:regex";
1487
+ regex;
1488
+ async _process() {
1489
+ if (this.fnArgs.length !== 1) {
1490
+ throw new SchemaError("regex() expects a single child arg");
1491
+ }
1492
+ if (!(this.fnArgs[0] instanceof StaticValueResolver)) {
1493
+ throw new SchemaError("regex() expects a single static value passed in");
1494
+ }
1495
+ const regexStr = this.fnArgs[0].staticValue;
1496
+ if (typeof regexStr !== "string") {
1497
+ throw new SchemaError("regex() expects a string");
1498
+ }
1499
+ this.regex = new RegExp(regexStr);
1677
1500
  }
1678
- /** @internal */
1679
- get _rawDef() {
1680
- return this.def;
1501
+ async _resolve() {
1502
+ if (!this.regex) throw new Error("expected regex to be set");
1503
+ return this.regex;
1681
1504
  }
1682
- coerce(val) {
1683
- return this.def.coerce ? this.def.coerce(val) : val;
1505
+ };
1506
+ var RemapResolver = class extends Resolver {
1507
+ static {
1508
+ __name(this, "RemapResolver");
1684
1509
  }
1685
- validate(val) {
1686
- return this.def.validate ? this.def.validate(val) : true;
1510
+ static fnName = "remap";
1511
+ label = "remap";
1512
+ icon = "codicon:replace";
1513
+ remappings;
1514
+ async _process() {
1515
+ if (my_dash_default.isPlainObject(this.fnArgs[0])) {
1516
+ throw new SchemaError("remap() expects the first arg to be the value to remap");
1517
+ }
1518
+ if (!my_dash_default.isPlainObject(this.fnArgs[1])) {
1519
+ throw new SchemaError("remap() expects the all args after the first to be key-value pairs of remappings");
1520
+ }
1521
+ if (this.fnArgs.length !== 2) {
1522
+ throw new SchemaError("remap() should not have any additional non key-value args after remappings");
1523
+ }
1524
+ this.remappings = this.fnArgs[1];
1687
1525
  }
1688
- };
1689
- function createEnvGraphDataType(dataTypeDef) {
1690
- const typeFactoryFn = /* @__PURE__ */ __name((...usageOpts) => {
1691
- return new EnvGraphDataType(
1692
- my_dash_default.isFunction(dataTypeDef) ? dataTypeDef(...usageOpts) : dataTypeDef,
1693
- typeFactoryFn
1694
- );
1695
- }, "typeFactoryFn");
1696
- typeFactoryFn._isEnvGraphDataTypeFactory = true;
1697
- const exampleInstance = typeFactoryFn(...[]);
1698
- typeFactoryFn.dataTypeName = exampleInstance.name;
1699
- return typeFactoryFn;
1700
- }
1701
- __name(createEnvGraphDataType, "createEnvGraphDataType");
1702
- function coerceToString(rawVal) {
1703
- if (rawVal === void 0 || rawVal === null) return "";
1704
- return my_dash_default.isString(rawVal) ? rawVal : String(rawVal);
1705
- }
1706
- __name(coerceToString, "coerceToString");
1707
- function coerceToNumber(rawVal) {
1708
- let numVal;
1709
- if (my_dash_default.isString(rawVal)) {
1710
- const parsed = parseFloat(rawVal);
1711
- if (my_dash_default.isNan(parsed) || parsed === Infinity || parsed === -Infinity) {
1712
- throw new CoercionError("Unable to coerce string to number");
1526
+ async _resolve() {
1527
+ if (my_dash_default.isPlainObject(this.fnArgs[0])) {
1528
+ throw new SchemaError("remap() expects the first arg to be the value to remap");
1713
1529
  }
1714
- numVal = parsed;
1715
- } else if (my_dash_default.isNumber(rawVal)) {
1716
- if (numVal === Infinity || numVal === -Infinity) {
1717
- throw new CoercionError("Inifinity is not a valid number");
1530
+ if (!my_dash_default.isPlainObject(this.fnArgs[1])) {
1531
+ throw new SchemaError("remap() expects the all args after the first to be key-value pairs of remappings");
1718
1532
  }
1719
- numVal = rawVal;
1720
- } else {
1721
- throw new CoercionError(`Cannot convert ${rawVal} to number`);
1722
- }
1723
- return numVal;
1724
- }
1725
- __name(coerceToNumber, "coerceToNumber");
1726
- var StringDataType = createEnvGraphDataType(
1727
- (settings) => ({
1728
- name: "string",
1729
- icon: "carbon:string-text",
1730
- coerce: /* @__PURE__ */ __name((rawVal) => {
1731
- let val = coerceToString(rawVal);
1732
- if (settings?.toUpperCase) val = val.toUpperCase();
1733
- if (settings?.toLowerCase) val = val.toLowerCase();
1734
- return val;
1735
- }, "coerce"),
1736
- validate: /* @__PURE__ */ __name((val) => {
1737
- const errors = [];
1738
- if (settings?.minLength !== void 0 && val.length < settings.minLength) {
1739
- errors.push(new ValidationError(`Length must be more than ${settings.minLength}`));
1740
- }
1741
- if (settings?.maxLength !== void 0 && val.length > settings.maxLength) {
1742
- errors.push(new ValidationError(`Length must be less than ${settings.maxLength}`));
1743
- }
1744
- if (settings?.isLength !== void 0 && val.length !== settings.isLength) {
1745
- errors.push(new ValidationError(`Length must be exactly ${settings.isLength}`));
1746
- }
1747
- if (settings?.startsWith && !val.startsWith(settings.startsWith)) {
1748
- errors.push(new ValidationError(`Value must start with "${settings.startsWith}"`));
1749
- }
1750
- if (settings?.endsWith && !val.endsWith(settings.endsWith)) {
1751
- errors.push(new ValidationError(`Value must start with "${settings.endsWith}"`));
1752
- }
1753
- if (settings?.matches) {
1754
- const regex = my_dash_default.isString(settings.matches) ? new RegExp(settings.matches) : settings.matches;
1755
- const matches = val.match(regex);
1756
- if (!matches) {
1757
- errors.push(new ValidationError(`Value must match regex "${settings.matches}"`));
1758
- }
1759
- }
1760
- return errors.length ? errors : true;
1761
- }, "validate")
1762
- })
1763
- );
1764
- var NumberDataType = createEnvGraphDataType(
1765
- (settings) => ({
1766
- name: "number",
1767
- icon: "carbon:string-integer",
1768
- coerce(rawVal) {
1769
- let numVal = coerceToNumber(rawVal);
1770
- if (settings?.coerceToMinMaxRange) {
1771
- if (settings?.min !== void 0) numVal = Math.max(settings?.min, numVal);
1772
- if (settings?.max !== void 0) numVal = Math.min(settings?.max, numVal);
1773
- }
1774
- if (settings?.isInt === true || settings?.precision === 0) {
1775
- numVal = Math.round(numVal);
1776
- } else if (settings?.precision) {
1777
- const p = 10 ** settings.precision;
1778
- numVal = Math.round(numVal * p) / p;
1779
- }
1780
- return numVal;
1781
- },
1782
- validate(val) {
1783
- const errors = [];
1784
- if (settings?.min !== void 0 && val < settings?.min) {
1785
- errors.push(new ValidationError(`Min value is ${settings?.min}`));
1786
- }
1787
- if (settings?.max !== void 0 && val > settings?.max) {
1788
- errors.push(new ValidationError(`Max value is ${settings?.max}`));
1789
- }
1790
- if (settings?.isDivisibleBy !== void 0 && val % settings.isDivisibleBy !== 0) {
1791
- errors.push(new ValidationError(`Value must be divisible by ${settings?.isDivisibleBy}`));
1533
+ const originalValue = await this.fnArgs[0].resolve();
1534
+ if (!this.remappings) throw new Error("expected remappings to be set");
1535
+ for (const [remappedVal, matchValResolver] of Object.entries(this.remappings)) {
1536
+ const matchVal = await matchValResolver.resolve();
1537
+ if (matchVal instanceof RegExp && originalValue !== void 0) {
1538
+ if (matchVal.test(String(originalValue))) return remappedVal;
1539
+ } else {
1540
+ if (matchVal === originalValue) return remappedVal;
1792
1541
  }
1793
- return errors.length ? errors : true;
1794
1542
  }
1795
- })
1796
- );
1797
- var BooleanDataType = createEnvGraphDataType({
1798
- name: "boolean",
1799
- icon: "carbon:boolean",
1800
- // probably want allow some settings
1801
- // - more strict about coercion or adding additional true/false values
1802
- // - coercing to other values - like 0,1
1803
- coerce(val) {
1804
- if (my_dash_default.isBoolean(val)) {
1805
- return val;
1806
- } else if (my_dash_default.isString(val)) {
1807
- const cleanVal = val.toLowerCase().trim();
1808
- if (["t", "true", "yes", "on", "1"].includes(cleanVal)) return true;
1809
- if (["f", "false", "no", "off", "0"].includes(cleanVal)) return false;
1810
- throw new CoercionError("Unable to coerce string value to boolean");
1811
- } else if (my_dash_default.isNumber(val)) {
1812
- if (val === 0) return false;
1813
- if (val === 1) return true;
1814
- throw new CoercionError("Unable to coerce number value to boolean (only 0 or 1 is valid)");
1815
- } else {
1816
- throw new CoercionError("Unable to coerce value to boolean");
1543
+ return originalValue;
1544
+ }
1545
+ };
1546
+ var BaseResolvers = [
1547
+ ConcatResolver,
1548
+ FallbackResolver,
1549
+ RefResolver,
1550
+ ExecResolver,
1551
+ RemapResolver,
1552
+ RegexResolver
1553
+ ];
1554
+
1555
+ // ../env-graph/src/lib/graph-utils.ts
1556
+ function findGraphCycles(graph) {
1557
+ const visited = /* @__PURE__ */ new Set();
1558
+ const recursionStack = /* @__PURE__ */ new Set();
1559
+ const cycles = [];
1560
+ const currentPath = [];
1561
+ function dfs(node) {
1562
+ if (recursionStack.has(node)) {
1563
+ const cycleStart = currentPath.indexOf(node);
1564
+ const cycle = currentPath.slice(cycleStart);
1565
+ cycles.push(cycle);
1566
+ return;
1817
1567
  }
1818
- },
1819
- // TODO: add settings to be more strict, or to allow other values to coerce to true/false
1820
- validate(val) {
1821
- if (my_dash_default.isBoolean(val)) return true;
1822
- return new ValidationError("Value must be `true` or `false`");
1568
+ if (visited.has(node)) {
1569
+ return;
1570
+ }
1571
+ visited.add(node);
1572
+ recursionStack.add(node);
1573
+ currentPath.push(node);
1574
+ for (const neighbor of graph[node] || []) {
1575
+ dfs(neighbor);
1576
+ }
1577
+ recursionStack.delete(node);
1578
+ currentPath.pop();
1823
1579
  }
1824
- });
1825
- var UrlDataType = createEnvGraphDataType(
1826
- (settings) => ({
1827
- name: "url",
1828
- icon: "carbon:url",
1829
- coerce(rawVal) {
1830
- const val = coerceToString(rawVal);
1831
- if (settings?.prependHttps && !val.startsWith("https://")) return `https://${val}`;
1832
- return val;
1833
- },
1834
- validate(val) {
1835
- const url = new URL(val);
1836
- if (settings?.allowedDomains && !settings.allowedDomains.includes(url.host.toLowerCase())) {
1837
- return new ValidationError(`Domain (${url.host}) is not in allowed list: ${settings.allowedDomains.join(",")}`);
1838
- }
1839
- return true;
1580
+ __name(dfs, "dfs");
1581
+ for (const node of Object.keys(graph)) {
1582
+ if (!visited.has(node)) {
1583
+ dfs(node);
1840
1584
  }
1841
- })
1842
- );
1843
- var SimpleObjectDataType = createEnvGraphDataType({
1844
- name: "simple-object",
1845
- icon: "tabler:code-dots",
1846
- // curly brackets with nothing inside
1847
- coerce(val) {
1848
- if (my_dash_default.isPlainObject(val)) return val;
1849
- if (my_dash_default.isString(val)) {
1850
- try {
1851
- const parsedObj = JSON.parse(val);
1852
- if (my_dash_default.isPlainObject(parsedObj)) return parsedObj;
1853
- return new CoercionError("Unable to coerce JSON parsed string to object");
1854
- } catch (err) {
1855
- return new CoercionError("Error parsing JSON string while coercing string to object");
1856
- }
1585
+ }
1586
+ return cycles;
1587
+ }
1588
+ __name(findGraphCycles, "findGraphCycles");
1589
+ var AUTOGENERATED_FILE_BANNER = `
1590
+ // \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1}
1591
+ // \u{1F6D1} THIS IS AN AUTOGENERATED FILE - DO NOT EDIT DIRECTLY \u{1F6D1}
1592
+ // \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1}
1593
+ `;
1594
+ var ICON_SIZE = 20;
1595
+ var iconCacheFolderInit = false;
1596
+ var iconInMemoryCache = {};
1597
+ async function fetchIconSvg(iconifyName, color = "808080", iconCacheFolder = "/tmp/varlock-icon-cache") {
1598
+ if (!iconCacheFolderInit) {
1599
+ fs.mkdirSync(iconCacheFolder, { recursive: true });
1600
+ iconCacheFolderInit = true;
1601
+ }
1602
+ const iconPath = `${iconCacheFolder}/${iconifyName}-${ICON_SIZE}.svg`;
1603
+ let svgSrc;
1604
+ if (iconInMemoryCache[iconPath]) {
1605
+ svgSrc = iconInMemoryCache[iconPath];
1606
+ } else if (fs.existsSync(iconPath)) {
1607
+ const svgFileBuffer = await fs.promises.readFile(iconPath, "utf-8");
1608
+ svgSrc = svgFileBuffer.toString();
1609
+ iconInMemoryCache[iconPath] = svgSrc;
1610
+ } else {
1611
+ try {
1612
+ const iconSvg = await fetch(`https://api.iconify.design/${iconifyName.replace(":", "/")}.svg?height=${ICON_SIZE}`);
1613
+ svgSrc = await iconSvg.text();
1614
+ } catch (err) {
1615
+ return;
1616
+ }
1617
+ if (!svgSrc) return;
1618
+ if (svgSrc) {
1619
+ await fs.promises.writeFile(iconPath, svgSrc, "utf-8");
1620
+ iconInMemoryCache[iconPath] = svgSrc;
1857
1621
  }
1858
- return new CoercionError("Cannot coerce value to object");
1859
- },
1860
- validate(val) {
1861
- if (my_dash_default.isPlainObject(val)) return true;
1862
- return new ValidationError("Value must be an object");
1863
1622
  }
1864
- });
1865
- var EnumDataType = createEnvGraphDataType(
1866
- (...enumOptions) => ({
1867
- name: "enum",
1868
- icon: "material-symbols-light:category",
1869
- // a few shapes... not sure about this one
1870
- coerce(val) {
1871
- if (my_dash_default.isString(val) || my_dash_default.isNumber(val) || my_dash_default.isBoolean(val)) return val;
1872
- return new CoercionError("Value must be a string, number, or boolean");
1873
- },
1874
- validate(val) {
1875
- const possibleValues = enumOptions || [];
1876
- if (!possibleValues.includes(val)) {
1877
- throw new ValidationError("Current value is not in list of possible values", {
1878
- tip: `Possible values are: "${possibleValues.join('", "')}"`
1879
- });
1623
+ const hexColor = color.startsWith("#") ? color : `#${color}`;
1624
+ const colorizedSvg = svgSrc.replaceAll("currentColor", hexColor);
1625
+ return colorizedSvg;
1626
+ }
1627
+ __name(fetchIconSvg, "fetchIconSvg");
1628
+ async function getTsDefinitionForItem(item, indentLevel = 0) {
1629
+ const i = my_dash_default.times(indentLevel, () => " ").join("");
1630
+ const itemSrc = [];
1631
+ const jsDocLines = [];
1632
+ jsDocLines.push(`**${item.key}**${item.isSensitive ? " \u{1F510} _sensitive_" : ""}`);
1633
+ if (item.description) jsDocLines.push(...item.description.split("\n"));
1634
+ const iconName = item.icon;
1635
+ if (iconName) {
1636
+ const iconSvg = await fetchIconSvg(iconName);
1637
+ if (iconSvg) jsDocLines.push(`![icon](data:image/svg+xml;utf-8,${encodeURIComponent(iconSvg)}) `);
1638
+ }
1639
+ const docsLinks = item.docsLinks;
1640
+ if (docsLinks.length) {
1641
+ jsDocLines.push("");
1642
+ docsLinks.forEach((docsEntry) => {
1643
+ const docsLink = my_dash_default.compact([docsEntry.url, docsEntry.description]).join(" | ");
1644
+ jsDocLines.push(`\u{1F4DA} {@link ${docsLink}}`);
1645
+ });
1646
+ }
1647
+ if (jsDocLines.length === 1) {
1648
+ itemSrc.push(`/** ${jsDocLines[0]} */`);
1649
+ } else if (jsDocLines.length > 1) {
1650
+ itemSrc.push(...[
1651
+ "/**",
1652
+ // extra 2 trailing spaces are needed to make line breaks visible
1653
+ ...my_dash_default.flatMap(jsDocLines, (line) => [` * ${line} `]),
1654
+ " */"
1655
+ ]);
1656
+ }
1657
+ const dataType = item.dataType;
1658
+ const dataTypeName = dataType?.name;
1659
+ let itemTsType = "string";
1660
+ if (dataType) {
1661
+ if (dataTypeName === "number" || dataTypeName === "port") {
1662
+ itemTsType = "number";
1663
+ } else if (dataTypeName === "boolean") {
1664
+ itemTsType = "boolean";
1665
+ } else if (dataTypeName === "simple-object") {
1666
+ itemTsType = "Record<string, any>";
1667
+ } else if (dataTypeName === "enum") {
1668
+ const rawEnumOptions = dataType._rawDef._rawEnumOptions;
1669
+ let enumOptions = [];
1670
+ enumOptions = rawEnumOptions;
1671
+ if (!enumOptions.length) {
1672
+ itemTsType = "never";
1673
+ } else {
1674
+ itemTsType = my_dash_default.map(enumOptions, JSON.stringify).join(" | ");
1880
1675
  }
1881
- },
1882
- _rawEnumOptions: enumOptions
1883
- })
1884
- );
1885
- var EMAIL_REGEX = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
1886
- var EmailDataType = createEnvGraphDataType(
1887
- (settings) => ({
1888
- name: "email",
1889
- icon: "iconoir:at-sign",
1890
- typeDescription: "standard email address",
1891
- coerce(rawVal) {
1892
- let val = coerceToString(rawVal);
1893
- if (settings?.normalize) val = val.toLowerCase();
1894
- return val;
1895
- },
1896
- validate(val) {
1897
- const result = EMAIL_REGEX.test(val);
1898
- if (result) return true;
1899
- return new ValidationError("Value must be a valid email address");
1900
1676
  }
1901
- })
1902
- );
1903
- var IP_V4_ADDRESS_REGEX = /^(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}$/;
1904
- var IP_V6_ADDRESS_REGEX = /^(?:(?:[a-fA-F\d]{1,4}:){7}(?:[a-fA-F\d]{1,4}|:)|(?:[a-fA-F\d]{1,4}:){6}(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|:[a-fA-F\d]{1,4}|:)|(?:[a-fA-F\d]{1,4}:){5}(?::(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,2}|:)|(?:[a-fA-F\d]{1,4}:){4}(?:(?::[a-fA-F\d]{1,4}){0,1}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,3}|:)|(?:[a-fA-F\d]{1,4}:){3}(?:(?::[a-fA-F\d]{1,4}){0,2}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,4}|:)|(?:[a-fA-F\d]{1,4}:){2}(?:(?::[a-fA-F\d]{1,4}){0,3}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,5}|:)|(?:[a-fA-F\d]{1,4}:){1}(?:(?::[a-fA-F\d]{1,4}){0,4}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,6}|:)|(?::(?:(?::[a-fA-F\d]{1,4}){0,5}:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)(?:\\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]\d|\d)){3}|(?::[a-fA-F\d]{1,4}){1,7}|:)))(?:%[0-9a-zA-Z]{1,})?$/;
1905
- var ipAddressDataType = createEnvGraphDataType(
1906
- (settings) => ({
1907
- name: "ip",
1908
- icon: "iconoir:ip-address-tag",
1909
- typeDescription: "ip v4 or v6 address",
1910
- coerce(rawVal) {
1911
- let val = coerceToString(rawVal);
1912
- if (settings?.normalize) val = val.toLowerCase();
1913
- return val;
1914
- },
1915
- validate(val) {
1916
- const regex = settings?.version === 6 ? IP_V6_ADDRESS_REGEX : IP_V4_ADDRESS_REGEX;
1917
- const result = regex.test(val);
1918
- if (result) return true;
1919
- return new ValidationError("Value must be a valid IP address");
1677
+ }
1678
+ itemSrc.push(`readonly ${item.key}${item.isRequired ? "" : "?"}: ${itemTsType};`);
1679
+ itemSrc.push("");
1680
+ return my_dash_default.map(itemSrc, (line) => `${i}${line}`);
1681
+ }
1682
+ __name(getTsDefinitionForItem, "getTsDefinitionForItem");
1683
+ async function generateTsTypesSrc(graph) {
1684
+ const tsSrc = [
1685
+ AUTOGENERATED_FILE_BANNER,
1686
+ // might want to add some options to let users inject this, or somehow detect eslint, but fine for now
1687
+ "/* eslint-disable */",
1688
+ "export type CoercedEnvSchema = {"
1689
+ ];
1690
+ const exposedNonSensitiveKeys = [];
1691
+ for (const itemKey in graph.configSchema) {
1692
+ const configItem = graph.configSchema[itemKey];
1693
+ tsSrc.push(...await getTsDefinitionForItem(configItem, 1));
1694
+ if (!configItem.isSensitive) exposedNonSensitiveKeys.push(itemKey);
1695
+ }
1696
+ tsSrc.push("};\n");
1697
+ tsSrc.push(`
1698
+ declare module 'varlock/env' {
1699
+ export interface TypedEnvSchema extends CoercedEnvSchema {}
1700
+ export interface PublicTypedEnvSchema extends Pick<CoercedEnvSchema, '${exposedNonSensitiveKeys.join("' | '")}'> {}
1701
+ }
1702
+ `);
1703
+ tsSrc.push(`
1704
+ export type EnvSchemaAsStrings = {
1705
+ [Property in keyof CoercedEnvSchema]:
1706
+ CoercedEnvSchema[Property] extends string ? CoercedEnvSchema[Property]
1707
+ : (CoercedEnvSchema[Property] extends boolean ? ('true' | 'false') : string)
1708
+ };
1709
+ `);
1710
+ const IMPORT_META_AUGMENTATION = `
1711
+ // add types for global import.meta.env
1712
+ interface ImportMetaEnv extends EnvSchemaAsStrings {}
1713
+ interface ImportMeta {
1714
+ readonly env: ImportMetaEnv;
1715
+ }`;
1716
+ const PROCESS_ENV_AUGMENTATION = `
1717
+ // add types for global process.env
1718
+ namespace NodeJS {
1719
+ interface ProcessEnv extends EnvSchemaAsStrings {}
1720
+ }`;
1721
+ tsSrc.push(...[
1722
+ "declare global {",
1723
+ IMPORT_META_AUGMENTATION,
1724
+ PROCESS_ENV_AUGMENTATION,
1725
+ "}"
1726
+ ].filter(Boolean));
1727
+ return tsSrc.join("\n");
1728
+ }
1729
+ __name(generateTsTypesSrc, "generateTsTypesSrc");
1730
+ async function generateTypes(graph, lang, outputPath) {
1731
+ if (lang !== "ts") throw new Error(`Unsupported @generateTypes lang: ${lang}`);
1732
+ const tsSrc = await generateTsTypesSrc(graph);
1733
+ if (!graph.basePath) return;
1734
+ const typesPath = path.join(graph.basePath, outputPath);
1735
+ await fs.promises.writeFile(typesPath, tsSrc, "utf-8");
1736
+ }
1737
+ __name(generateTypes, "generateTypes");
1738
+
1739
+ // ../env-graph/src/lib/env-graph.ts
1740
+ var EnvGraph2 = class {
1741
+ static {
1742
+ __name(this, "EnvGraph");
1743
+ }
1744
+ // TODO: not sure if this should be the graph of _everything_ in a workspace/project
1745
+ // or just the files that are relevant to the current resolution attempt
1746
+ // (which would mean it's always through the lens of the current directory/package)
1747
+ basePath;
1748
+ /** array of data sources */
1749
+ dataSources = [];
1750
+ finalOverridesDataSource;
1751
+ /** config item key of env flag (toggles env-specific data sources enabled) */
1752
+ envFlagKey;
1753
+ /** current value of the environment flag */
1754
+ envFlagValue;
1755
+ configSchema = {};
1756
+ addDataSource(dataSource) {
1757
+ dataSource.graph = this;
1758
+ this.dataSources.push(dataSource);
1759
+ }
1760
+ get schemaDataSource() {
1761
+ const schemas = this.dataSources.filter((f) => f.type === "schema");
1762
+ if (schemas.length > 1) throw new Error("Multiple schema data sources found");
1763
+ if (schemas.length === 0) return void 0;
1764
+ return schemas[0];
1765
+ }
1766
+ get sortedDataSources() {
1767
+ return my_dash_default.sortBy(this.dataSources, (f) => 10 * EnvGraphDataSource.DATA_SOURCE_TYPES[f.type].precedence + (f.applyForEnv ? 1 : 0));
1768
+ }
1769
+ registeredResolverFunctions = {};
1770
+ registerResolver(resolverClass) {
1771
+ const fnName = resolverClass.fnName;
1772
+ if (fnName in this.registeredResolverFunctions) {
1773
+ throw new Error(`Resolver ${fnName} already registered`);
1920
1774
  }
1921
- })
1922
- );
1923
- var PortDataType = createEnvGraphDataType(
1924
- (settings) => ({
1925
- name: "port",
1926
- icon: "material-symbols:captive-portal",
1927
- //! globe with arrow - not sure about this one
1928
- typeDescription: "valid port number between 0 and 65535",
1929
- coerce(rawVal) {
1930
- if (my_dash_default.isString(rawVal)) {
1931
- if (rawVal.includes(".")) throw new CoercionError("Port number must be an integer");
1932
- if (rawVal.includes("e")) throw new CoercionError("Port number should be an integer, not in exponential notation");
1775
+ this.registeredResolverFunctions[fnName] = resolverClass;
1776
+ }
1777
+ dataTypesRegistry = {};
1778
+ registerDataType(factory) {
1779
+ this.dataTypesRegistry[factory.dataTypeName] = factory;
1780
+ }
1781
+ constructor() {
1782
+ for (const dataType of my_dash_default.values(BaseDataTypes)) {
1783
+ this.registerDataType(dataType);
1784
+ }
1785
+ for (const resolverClass of BaseResolvers) {
1786
+ this.registerResolver(resolverClass);
1787
+ }
1788
+ }
1789
+ async finishLoad() {
1790
+ const sortedDataSources = this.sortedDataSources;
1791
+ for (const source of sortedDataSources) {
1792
+ if (source.loadingError) {
1793
+ throw source.loadingError;
1933
1794
  }
1934
- return coerceToNumber(rawVal);
1935
- },
1936
- validate(val) {
1937
- if (settings?.min !== void 0 && val < settings?.min) {
1938
- return new ValidationError(`Min value is ${settings?.min}`);
1795
+ if (source.type === "example") {
1796
+ source.disabled = true;
1797
+ continue;
1939
1798
  }
1940
- if (settings?.max !== void 0 && val > settings?.max) {
1941
- return new ValidationError(`Max value is ${settings?.max}`);
1799
+ if (source.decorators?.envFlag) {
1800
+ if (source.applyForEnv) {
1801
+ throw new Error(`@envFlag cannot be set from within an env-specific data source - ${source.label}`);
1802
+ } else if (this.envFlagKey) {
1803
+ throw new Error("only a single @envFlag setting is allowed");
1804
+ } else {
1805
+ const envFlagKey = source.decorators.envFlag.simplifiedValue;
1806
+ if (!my_dash_default.isString(envFlagKey)) {
1807
+ throw new Error("@envFlag must be a string");
1808
+ } else {
1809
+ this.envFlagKey = envFlagKey;
1810
+ }
1811
+ }
1942
1812
  }
1943
- if (val < 0 || val > 65535) {
1944
- return new ValidationError("Value must be a valid port number (0-65535)");
1813
+ if (source.applyForEnv) {
1814
+ if (source.applyForEnv && this.envFlagValue !== source.applyForEnv) {
1815
+ source.disabled = true;
1816
+ continue;
1817
+ }
1818
+ }
1819
+ if (source.decorators?.disable && source.decorators.disable.simplifiedValue) {
1820
+ source.disabled = true;
1821
+ continue;
1822
+ }
1823
+ for (const itemKey in source.configItemDefs) {
1824
+ if (source.ignoreNewDefs && !this.configSchema[itemKey]) continue;
1825
+ const itemDef = source.configItemDefs[itemKey];
1826
+ this.configSchema[itemKey] ??= new ConfigItem3(this, itemKey);
1827
+ this.configSchema[itemKey].addDef(itemDef, source);
1828
+ }
1829
+ if (source.type === "schema" && this.envFlagKey) {
1830
+ if (!this.configSchema[this.envFlagKey]) {
1831
+ throw new Error(`@envFlag key ${this.envFlagKey} not found in schema`);
1832
+ }
1833
+ const envFlagItem = this.configSchema[this.envFlagKey];
1834
+ await envFlagItem.process();
1835
+ for (const depKey of envFlagItem.valueResolver?.deps || []) {
1836
+ const depItem = this.configSchema[depKey];
1837
+ if (!depItem) {
1838
+ throw new Error(`envFlag resolver is using non-existant dependency: ${depKey}`);
1839
+ }
1840
+ await depItem.process();
1841
+ if (depItem.valueResolver?.deps.length) {
1842
+ throw new Error("envFlag cannot follow a chain of dependencies");
1843
+ }
1844
+ await depItem.resolve();
1845
+ }
1846
+ await envFlagItem.resolve();
1847
+ if (!envFlagItem.isValid) {
1848
+ const err = new Error("resolved @envFlag value is not valid");
1849
+ err.cause = envFlagItem.errors[0];
1850
+ throw err;
1851
+ }
1852
+ if (envFlagItem.resolvedValue) {
1853
+ if (!my_dash_default.isString(envFlagItem.resolvedValue)) {
1854
+ throw new Error("expected resolved @envFlag value to be a string");
1855
+ }
1856
+ this.envFlagValue = envFlagItem.resolvedValue;
1857
+ }
1945
1858
  }
1946
- return true;
1947
1859
  }
1948
- })
1949
- );
1950
- var SEMVER_REGEX = /^(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-]+)*))?$/;
1951
- var SemverDataType = createEnvGraphDataType(
1952
- (settings) => ({
1953
- name: "semver",
1954
- icon: "simple-icons:semver",
1955
- typeDescription: "semantic version string",
1956
- validate(val) {
1957
- const result = SEMVER_REGEX.test(val);
1958
- if (result) return true;
1959
- return new ValidationError("Value must be a valid semantic version string");
1860
+ for (const itemKey in this.configSchema) {
1861
+ const item = this.configSchema[itemKey];
1862
+ await item.process();
1960
1863
  }
1961
- })
1962
- );
1963
- var ISO_DATE_REGEX = /^(?:[+-]?\d{4}(?!\d{2}\b))(?:(-?)(?:(?:0[1-9]|1[0-2])(?:\1(?:[12]\d|0[1-9]|3[01]))?|W(?:[0-4]\d|5[0-2])(?:-?[1-7])?|(?:00[1-9]|0[1-9]\d|[12]\d{2}|3(?:[0-5]\d|6[1-6])))(?:[T\s](?:(?:(?:[01]\d|2[0-3])(?:(:?)[0-5]\d)?|24:?00)(?:[.,]\d+(?!:))?)?(?:\2[0-5]\d(?:[.,]\d+)?)?(?:[zZ]|(?:[+-])(?:[01]\d|2[0-3]):?(?:[0-5]\d)?)?)?)?$/;
1964
- var IsoDateDataType = createEnvGraphDataType({
1965
- name: "isoDate",
1966
- icon: "formkit:datetime",
1967
- typeDescription: "ISO 8601 date string with optional time and milliseconds",
1968
- validate(val) {
1969
- const result = ISO_DATE_REGEX.test(val);
1970
- if (result) return true;
1971
- return new ValidationError("Value must be a valid ISO 8601 date string");
1972
- }
1973
- });
1974
- var UUID_REGEX = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-5][0-9a-f]{3}-[089ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
1975
- var UuidDataType = createEnvGraphDataType({
1976
- name: "uuid",
1977
- icon: "mdi:identifier",
1978
- typeDescription: "UUID string V1-V5 per RFC4122, including NIL",
1979
- validate(val) {
1980
- const result = UUID_REGEX.test(val);
1981
- if (result) return true;
1982
- return new ValidationError("Value must be a valid UUID string");
1983
- }
1984
- });
1985
- var MD5_REGEX = /^[a-f0-9]{32}$/;
1986
- var Md5DataType = createEnvGraphDataType({
1987
- name: "md5",
1988
- typeDescription: "MD5 hash string",
1989
- validate(val) {
1990
- const result = MD5_REGEX.test(val);
1991
- if (result) return true;
1992
- return new ValidationError("Value must be a valid MD5 hash string");
1993
- }
1994
- });
1995
- var BaseDataTypes = {
1996
- string: StringDataType,
1997
- number: NumberDataType,
1998
- boolean: BooleanDataType,
1999
- simpleObject: SimpleObjectDataType,
2000
- enum: EnumDataType,
2001
- email: EmailDataType,
2002
- url: UrlDataType,
2003
- ipAddress: ipAddressDataType,
2004
- port: PortDataType,
2005
- semver: SemverDataType,
2006
- isoDate: IsoDateDataType,
2007
- uuid: UuidDataType,
2008
- md5: Md5DataType
2009
- };
2010
-
2011
- // ../env-graph/src/lib/graph-utils.ts
2012
- function findGraphCycles(graph) {
2013
- const visited = /* @__PURE__ */ new Set();
2014
- const recursionStack = /* @__PURE__ */ new Set();
2015
- const cycles = [];
2016
- const currentPath = [];
2017
- function dfs(node) {
2018
- if (recursionStack.has(node)) {
2019
- const cycleStart = currentPath.indexOf(node);
2020
- const cycle = currentPath.slice(cycleStart);
2021
- cycles.push(cycle);
2022
- return;
1864
+ const cycles = findGraphCycles(this.graphAdjacencyList);
1865
+ for (const cycleItemKeys of cycles) {
1866
+ for (const itemKey of cycleItemKeys) {
1867
+ const item = this.configSchema[itemKey];
1868
+ item.schemaErrors.push(
1869
+ new SchemaError(
1870
+ cycleItemKeys.length === 1 ? "Item cannot have dependency on itself" : `Dependency cycle detected: (${cycleItemKeys.join(", ")})`
1871
+ )
1872
+ );
1873
+ }
2023
1874
  }
2024
- if (visited.has(node)) {
2025
- return;
1875
+ }
1876
+ get graphAdjacencyList() {
1877
+ const adjList = {};
1878
+ for (const itemKey in this.configSchema) {
1879
+ const item = this.configSchema[itemKey];
1880
+ adjList[itemKey] = item.valueResolver?.deps || [];
2026
1881
  }
2027
- visited.add(node);
2028
- recursionStack.add(node);
2029
- currentPath.push(node);
2030
- for (const neighbor of graph[node] || []) {
2031
- dfs(neighbor);
1882
+ return adjList;
1883
+ }
1884
+ async resolveEnvValues() {
1885
+ const adjList = this.graphAdjacencyList;
1886
+ const reverseAdjList = {};
1887
+ for (const itemKey in adjList) {
1888
+ const itemDeps = adjList[itemKey];
1889
+ for (const dep of itemDeps) {
1890
+ reverseAdjList[dep] ??= [];
1891
+ reverseAdjList[dep].push(itemKey);
1892
+ }
2032
1893
  }
2033
- recursionStack.delete(node);
2034
- currentPath.pop();
1894
+ const itemsToResolveStatus = my_dash_default.mapValues(this.configSchema, () => false);
1895
+ const deferred = new Promise((resolve, reject) => {
1896
+ const markItemCompleted = /* @__PURE__ */ __name((itemKey) => {
1897
+ delete itemsToResolveStatus[itemKey];
1898
+ if (reverseAdjList[itemKey]) {
1899
+ reverseAdjList[itemKey].forEach(resolveItem);
1900
+ }
1901
+ if (my_dash_default.keys(itemsToResolveStatus).length === 0) resolve();
1902
+ }, "markItemCompleted");
1903
+ const resolveItem = /* @__PURE__ */ __name(async (itemKey) => {
1904
+ if (itemsToResolveStatus[itemKey] !== false) return;
1905
+ const item = this.configSchema[itemKey];
1906
+ if (item.errors.length) {
1907
+ markItemCompleted(itemKey);
1908
+ return;
1909
+ }
1910
+ for (const depKey of adjList[itemKey]) {
1911
+ const depItem = this.configSchema[depKey];
1912
+ if (depItem.validationState === "error") {
1913
+ item.resolutionError = new ResolutionError(`Dependency ${depKey} is invalid`);
1914
+ markItemCompleted(itemKey);
1915
+ return;
1916
+ } else if (depKey in itemsToResolveStatus) {
1917
+ return;
1918
+ }
1919
+ }
1920
+ itemsToResolveStatus[itemKey] = true;
1921
+ await item.resolve();
1922
+ markItemCompleted(itemKey);
1923
+ }, "resolveItem");
1924
+ for (const itemKey in this.configSchema) {
1925
+ resolveItem(itemKey);
1926
+ }
1927
+ });
1928
+ return deferred;
2035
1929
  }
2036
- __name(dfs, "dfs");
2037
- for (const node of Object.keys(graph)) {
2038
- if (!visited.has(node)) {
2039
- dfs(node);
1930
+ getResolvedEnvObject() {
1931
+ const envObject = {};
1932
+ for (const itemKey in this.configSchema) {
1933
+ const item = this.configSchema[itemKey];
1934
+ envObject[itemKey] = item.resolvedValue;
2040
1935
  }
1936
+ return envObject;
2041
1937
  }
2042
- return cycles;
2043
- }
2044
- __name(findGraphCycles, "findGraphCycles");
2045
- var AUTOGENERATED_FILE_BANNER = `
2046
- // \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1}
2047
- // \u{1F6D1} THIS IS AN AUTOGENERATED FILE - DO NOT EDIT DIRECTLY \u{1F6D1}
2048
- // \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1} \u{1F6D1}
2049
- `;
2050
- var ICON_SIZE = 20;
2051
- var iconCacheFolderInit = false;
2052
- var iconInMemoryCache = {};
2053
- async function fetchIconSvg(iconifyName, color = "808080", iconCacheFolder = "/tmp/varlock-icon-cache") {
2054
- if (!iconCacheFolderInit) {
2055
- fs2.mkdirSync(iconCacheFolder, { recursive: true });
2056
- iconCacheFolderInit = true;
2057
- }
2058
- const iconPath = `${iconCacheFolder}/${iconifyName}-${ICON_SIZE}.svg`;
2059
- let svgSrc;
2060
- if (iconInMemoryCache[iconPath]) {
2061
- svgSrc = iconInMemoryCache[iconPath];
2062
- } else if (fs2.existsSync(iconPath)) {
2063
- const svgFileBuffer = await fs2.promises.readFile(iconPath, "utf-8");
2064
- svgSrc = svgFileBuffer.toString();
2065
- iconInMemoryCache[iconPath] = svgSrc;
2066
- } else {
2067
- try {
2068
- const iconSvg = await fetch(`https://api.iconify.design/${iconifyName.replace(":", "/")}.svg?height=${ICON_SIZE}`);
2069
- svgSrc = await iconSvg.text();
2070
- } catch (err) {
2071
- return;
1938
+ getSerializedGraph() {
1939
+ const serializedGraph = {
1940
+ basePath: this.basePath,
1941
+ sources: [],
1942
+ config: {},
1943
+ settings: {}
1944
+ };
1945
+ for (const source of this.sortedDataSources) {
1946
+ serializedGraph.sources.push({
1947
+ label: source.label,
1948
+ enabled: !source.disabled,
1949
+ path: source instanceof FileBasedDataSource ? path.relative(this.basePath ?? "", source.fullPath) : void 0
1950
+ });
2072
1951
  }
2073
- if (!svgSrc) return;
2074
- if (svgSrc) {
2075
- await fs2.promises.writeFile(iconPath, svgSrc, "utf-8");
2076
- iconInMemoryCache[iconPath] = svgSrc;
1952
+ for (const itemKey in this.configSchema) {
1953
+ const item = this.configSchema[itemKey];
1954
+ serializedGraph.config[itemKey] = {
1955
+ value: item.resolvedValue,
1956
+ isSensitive: item.isSensitive
1957
+ };
2077
1958
  }
1959
+ serializedGraph.settings.redactLogs = this.getRootDecoratorValue("redactLogs") ?? true;
1960
+ serializedGraph.settings.preventLeaks = this.getRootDecoratorValue("preventLeaks") ?? true;
1961
+ return serializedGraph;
2078
1962
  }
2079
- const hexColor = color.startsWith("#") ? color : `#${color}`;
2080
- const colorizedSvg = svgSrc.replaceAll("currentColor", hexColor);
2081
- return colorizedSvg;
2082
- }
2083
- __name(fetchIconSvg, "fetchIconSvg");
2084
- async function getTsDefinitionForItem(item, indentLevel = 0) {
2085
- const i = my_dash_default.times(indentLevel, () => " ").join("");
2086
- const itemSrc = [];
2087
- const jsDocLines = [];
2088
- jsDocLines.push(`**${item.key}**${item.isSensitive ? " \u{1F510} _sensitive_" : ""}`);
2089
- if (item.description) jsDocLines.push(...item.description.split("\n"));
2090
- const iconName = item.icon;
2091
- if (iconName) {
2092
- const iconSvg = await fetchIconSvg(iconName);
2093
- if (iconSvg) jsDocLines.push(`![icon](data:image/svg+xml;utf-8,${encodeURIComponent(iconSvg)}) `);
2094
- }
2095
- const docsLinks = item.docsLinks;
2096
- if (docsLinks.length) {
2097
- jsDocLines.push("");
2098
- docsLinks.forEach((docsEntry) => {
2099
- const docsLink = my_dash_default.compact([docsEntry.url, docsEntry.description]).join(" | ");
2100
- jsDocLines.push(`\u{1F4DA} {@link ${docsLink}}`);
2101
- });
2102
- }
2103
- if (jsDocLines.length === 1) {
2104
- itemSrc.push(`/** ${jsDocLines[0]} */`);
2105
- } else if (jsDocLines.length > 1) {
2106
- itemSrc.push(...[
2107
- "/**",
2108
- // extra 2 trailing spaces are needed to make line breaks visible
2109
- ...my_dash_default.flatMap(jsDocLines, (line) => [` * ${line} `]),
2110
- " */"
2111
- ]);
1963
+ get isInvalid() {
1964
+ return my_dash_default.some(my_dash_default.values(this.configSchema), (i) => !i.isValid);
2112
1965
  }
2113
- const dataType = item.dataType;
2114
- const dataTypeName = dataType?.name;
2115
- let itemTsType = "string";
2116
- if (dataType) {
2117
- if (dataTypeName === "number" || dataTypeName === "port") {
2118
- itemTsType = "number";
2119
- } else if (dataTypeName === "boolean") {
2120
- itemTsType = "boolean";
2121
- } else if (dataTypeName === "simple-object") {
2122
- itemTsType = "Record<string, any>";
2123
- } else if (dataTypeName === "enum") {
2124
- const rawEnumOptions = dataType._rawDef._rawEnumOptions;
2125
- let enumOptions = [];
2126
- enumOptions = rawEnumOptions;
2127
- if (!enumOptions.length) {
2128
- itemTsType = "never";
2129
- } else {
2130
- itemTsType = my_dash_default.map(enumOptions, JSON.stringify).join(" | ");
2131
- }
2132
- }
1966
+ async generateTypes(lang, outputPath) {
1967
+ await generateTypes(this, lang, outputPath);
2133
1968
  }
2134
- itemSrc.push(`readonly ${item.key}${item.isRequired ? "" : "?"}: ${itemTsType};`);
2135
- itemSrc.push("");
2136
- return my_dash_default.map(itemSrc, (line) => `${i}${line}`);
2137
- }
2138
- __name(getTsDefinitionForItem, "getTsDefinitionForItem");
2139
- async function generateTsTypesSrc(graph) {
2140
- const tsSrc = [
2141
- AUTOGENERATED_FILE_BANNER,
2142
- // might want to add some options to let users inject this, or somehow detect eslint, but fine for now
2143
- "/* eslint-disable */",
2144
- "export type CoercedEnvSchema = {"
2145
- ];
2146
- const exposedNonSensitiveKeys = [];
2147
- for (const itemKey in graph.configSchema) {
2148
- const configItem = graph.configSchema[itemKey];
2149
- tsSrc.push(...await getTsDefinitionForItem(configItem, 1));
2150
- if (!configItem.isSensitive) exposedNonSensitiveKeys.push(itemKey);
1969
+ getRootDecoratorValue(decoratorName) {
1970
+ const dec = this.schemaDataSource?.decorators?.[decoratorName];
1971
+ return dec?.simplifiedValue;
2151
1972
  }
2152
- tsSrc.push("};\n");
2153
- tsSrc.push(`
2154
- declare module 'varlock/env' {
2155
- export interface TypedEnvSchema extends CoercedEnvSchema {}
2156
- export interface PublicTypedEnvSchema extends Pick<CoercedEnvSchema, '${exposedNonSensitiveKeys.join("' | '")}'> {}
2157
- }
2158
- `);
2159
- tsSrc.push(`
2160
- export type EnvSchemaAsStrings = {
2161
- [Property in keyof CoercedEnvSchema]:
2162
- CoercedEnvSchema[Property] extends string ? CoercedEnvSchema[Property]
2163
- : (CoercedEnvSchema[Property] extends boolean ? ('true' | 'false') : string)
2164
1973
  };
2165
- `);
2166
- tsSrc.push(`
2167
- declare global {
2168
- namespace NodeJS {
2169
- interface ProcessEnv extends EnvSchemaAsStrings {}
2170
- }
2171
- }`);
2172
- return tsSrc.join("\n");
2173
- }
2174
- __name(generateTsTypesSrc, "generateTsTypesSrc");
2175
- async function generateTypes(graph, lang, outputPath) {
2176
- if (lang !== "ts") throw new Error(`Unsupported @generateTypes lang: ${lang}`);
2177
- const tsSrc = await generateTsTypesSrc(graph);
2178
- if (!graph.basePath) return;
2179
- const typesPath = path.join(graph.basePath, outputPath);
2180
- await fs2.promises.writeFile(typesPath, tsSrc, "utf-8");
2181
- }
2182
- __name(generateTypes, "generateTypes");
2183
1974
 
2184
- // ../env-graph/src/lib/env-graph.ts
2185
- var EnvGraph = class {
1975
+ // ../env-graph/src/lib/config-item.ts
1976
+ var ConfigItem3 = class {
1977
+ constructor(envGraph, key) {
1978
+ this.envGraph = envGraph;
1979
+ this.key = key;
1980
+ }
2186
1981
  static {
2187
- __name(this, "EnvGraph");
1982
+ __name(this, "ConfigItem");
2188
1983
  }
2189
- // TODO: not sure if this should be the graph of _everything_ in a workspace/project
2190
- // or just the files that are relevant to the current resolution attempt
2191
- // (which would mean it's always through the lens of the current directory/package)
2192
- basePath;
2193
- /** array of data sources */
2194
- dataSources = [];
2195
- finalOverridesDataSource;
2196
- /** config item key of env flag (toggles env-specific data sources enabled) */
2197
- envFlagKey;
2198
- /** current value of the environment flag */
2199
- envFlagValue;
2200
- configSchema = {};
2201
- addDataSource(dataSource) {
2202
- dataSource.graph = this;
2203
- this.dataSources.push(dataSource);
1984
+ defs = [];
1985
+ addDef(itemDef, source) {
1986
+ this.defs.unshift({ itemDef, source });
2204
1987
  }
2205
- get schemaDataSource() {
2206
- const schemas = this.dataSources.filter((f) => f.type === "schema");
2207
- if (schemas.length > 1) throw new Error("Multiple schema data sources found");
2208
- if (schemas.length === 0) return void 0;
2209
- return schemas[0];
1988
+ get description() {
1989
+ for (const def of this.defs) {
1990
+ if (def.itemDef.description) return def.itemDef.description;
1991
+ }
2210
1992
  }
2211
- get sortedDataSources() {
2212
- return my_dash_default.sortBy(this.dataSources, (f) => 10 * EnvGraphDataSource.DATA_SOURCE_TYPES[f.type].precedence + (f.applyForEnv ? 1 : 0));
1993
+ get icon() {
1994
+ const explicitIcon = this.getDecoratorValueString("icon");
1995
+ if (explicitIcon) return explicitIcon;
1996
+ return this.dataType?.icon;
2213
1997
  }
2214
- registeredResolverFunctions = {};
2215
- registerResolver(resolverClass) {
2216
- const fnName = resolverClass.fnName;
2217
- if (fnName in this.registeredResolverFunctions) {
2218
- throw new Error(`Resolver ${fnName} already registered`);
1998
+ get docsLinks() {
1999
+ const links = [];
2000
+ const docsUrl = this.getDecoratorValueString("docsUrl");
2001
+ if (docsUrl) links.push({ url: docsUrl });
2002
+ return links;
2003
+ }
2004
+ get valueResolver() {
2005
+ for (const def of this.defs) {
2006
+ if (def.itemDef.resolver) return def.itemDef.resolver;
2219
2007
  }
2220
- this.registeredResolverFunctions[fnName] = resolverClass;
2221
2008
  }
2222
- dataTypesRegistry = {};
2223
- registerDataType(factory) {
2224
- this.dataTypesRegistry[factory.dataTypeName] = factory;
2009
+ getDecorator(decoratorName) {
2010
+ for (const def of this.defs) {
2011
+ const defDecorators = def.itemDef.decorators || {};
2012
+ if (decoratorName in defDecorators) {
2013
+ return defDecorators[decoratorName];
2014
+ }
2015
+ }
2225
2016
  }
2226
- constructor() {
2227
- for (const dataType of my_dash_default.values(BaseDataTypes)) {
2228
- this.registerDataType(dataType);
2017
+ getDecoratorValueRaw(decoratorName) {
2018
+ for (const def of this.defs) {
2019
+ const defDecorators = def.itemDef.decorators || {};
2020
+ if (decoratorName in defDecorators) {
2021
+ return defDecorators[decoratorName].value;
2022
+ }
2023
+ }
2024
+ }
2025
+ getDecoratorValueString(decoratorName) {
2026
+ const dec = this.getDecoratorValueRaw(decoratorName);
2027
+ if (dec instanceof ParsedEnvSpecStaticValue) return String(dec.value);
2028
+ }
2029
+ dataType;
2030
+ schemaErrors = [];
2031
+ get resolverSchemaErrors() {
2032
+ return this.valueResolver?.schemaErrors || [];
2033
+ }
2034
+ async process() {
2035
+ const finalOverrideDef = this.envGraph.finalOverridesDataSource?.configItemDefs[this.key];
2036
+ if (finalOverrideDef) {
2037
+ this.defs.unshift({ itemDef: finalOverrideDef, source: this.envGraph.finalOverridesDataSource });
2038
+ }
2039
+ for (const def of this.defs) {
2040
+ await def.itemDef.resolver?.process(this);
2041
+ }
2042
+ const typeDecoratorValue = this.getDecoratorValueRaw("type");
2043
+ let dataTypeName;
2044
+ let dataTypeArgs;
2045
+ if (typeDecoratorValue instanceof ParsedEnvSpecStaticValue) {
2046
+ dataTypeName = typeDecoratorValue.value;
2047
+ } else if (typeDecoratorValue instanceof ParsedEnvSpecFunctionCall) {
2048
+ dataTypeName = typeDecoratorValue.name;
2049
+ dataTypeArgs = typeDecoratorValue.simplifiedArgs;
2229
2050
  }
2230
- for (const resolverClass of BaseResolvers) {
2231
- this.registerResolver(resolverClass);
2051
+ if (!dataTypeName) {
2052
+ if (this.valueResolver?.inferredType) {
2053
+ dataTypeName = this.valueResolver.inferredType;
2054
+ }
2055
+ }
2056
+ dataTypeName ||= "string";
2057
+ dataTypeArgs ||= [];
2058
+ if (!(dataTypeName in this.envGraph.dataTypesRegistry)) {
2059
+ this.schemaErrors.push(new SchemaError(`unknown data type: ${dataTypeName}`));
2060
+ } else {
2061
+ const dataTypeFactory = this.envGraph.dataTypesRegistry[dataTypeName];
2062
+ this.dataType = dataTypeFactory(...my_dash_default.isPlainObject(dataTypeArgs) ? [dataTypeArgs] : dataTypeArgs);
2232
2063
  }
2233
2064
  }
2234
- async finishLoad() {
2235
- const sortedDataSources = this.sortedDataSources;
2236
- for (const source of sortedDataSources) {
2237
- if (source.loadingError) {
2238
- throw source.loadingError;
2065
+ get isRequired() {
2066
+ for (const def of this.defs) {
2067
+ const defDecorators = def.itemDef.decorators || {};
2068
+ if ("required" in defDecorators) {
2069
+ const val = defDecorators.required.simplifiedValue;
2070
+ if (typeof val === "boolean") return val;
2071
+ if (typeof val === "string") return val === "true";
2072
+ return Boolean(val);
2239
2073
  }
2240
- if (source.type === "example") {
2241
- source.disabled = true;
2242
- continue;
2074
+ if ("optional" in defDecorators) {
2075
+ const val = defDecorators.optional.simplifiedValue;
2076
+ if (typeof val === "boolean") return !val;
2077
+ if (typeof val === "string") return val !== "true";
2078
+ return !val;
2243
2079
  }
2244
- if (source.decorators?.envFlag) {
2245
- if (source.applyForEnv) {
2246
- throw new Error(`@envFlag cannot be set from within an env-specific data source - ${source.label}`);
2247
- } else if (this.envFlagKey) {
2248
- throw new Error("only a single @envFlag setting is allowed");
2249
- } else {
2250
- const envFlagKey = source.decorators.envFlag.simplifiedValue;
2251
- if (!my_dash_default.isString(envFlagKey)) {
2252
- throw new Error("@envFlag must be a string");
2080
+ if ("defaultRequired" in def.source.decorators) {
2081
+ const val = def.source.decorators.defaultRequired.simplifiedValue;
2082
+ if (val === "infer") {
2083
+ if (def.source.type === "schema") {
2084
+ const resolver = def.itemDef.resolver;
2085
+ if (resolver instanceof StaticValueResolver) {
2086
+ return resolver.staticValue !== void 0 && resolver.staticValue !== "";
2087
+ } else {
2088
+ return true;
2089
+ }
2253
2090
  } else {
2254
- this.envFlagKey = envFlagKey;
2091
+ continue;
2255
2092
  }
2256
2093
  }
2094
+ return val;
2257
2095
  }
2258
- if (source.applyForEnv) {
2259
- if (source.applyForEnv && this.envFlagValue !== source.applyForEnv) {
2260
- source.disabled = true;
2261
- continue;
2096
+ }
2097
+ return true;
2098
+ }
2099
+ get isSensitive() {
2100
+ for (const def of this.defs) {
2101
+ const defDecorators = def.itemDef.decorators || {};
2102
+ if ("sensitive" in defDecorators) {
2103
+ return defDecorators.sensitive.simplifiedValue;
2104
+ } else if ("defaultSensitive" in def.source.decorators) {
2105
+ const dec = def.source.decorators.defaultSensitive;
2106
+ if (dec.value instanceof ParsedEnvSpecFunctionCall && dec.value.name === "inferFromPrefix") {
2107
+ const args = dec.value.simplifiedArgs;
2108
+ const prefix = Array.isArray(args) && args.length > 0 ? args[0] : void 0;
2109
+ if (typeof prefix === "string" && this.key.startsWith(prefix)) {
2110
+ return false;
2111
+ }
2112
+ return true;
2262
2113
  }
2114
+ return dec.simplifiedValue;
2263
2115
  }
2264
- if (source.decorators?.disable && source.decorators.disable.simplifiedValue) {
2265
- source.disabled = true;
2266
- continue;
2116
+ }
2117
+ return true;
2118
+ }
2119
+ get errors() {
2120
+ return my_dash_default.compact([
2121
+ ...this.schemaErrors || [],
2122
+ ...this.resolverSchemaErrors || [],
2123
+ this.resolutionError,
2124
+ this.coercionError,
2125
+ ...this.validationErrors || []
2126
+ ]);
2127
+ }
2128
+ get validationState() {
2129
+ const errors = this.errors;
2130
+ if (!errors.length) return "valid";
2131
+ return my_dash_default.some(errors, (e) => !e.isWarning) ? "error" : "warn";
2132
+ }
2133
+ /** resolved value _before coercion_ */
2134
+ resolvedRawValue;
2135
+ isResolved = false;
2136
+ /** resolved value after coercion */
2137
+ resolvedValue;
2138
+ isValidated = false;
2139
+ resolutionError;
2140
+ coercionError;
2141
+ validationErrors;
2142
+ get isCoerced() {
2143
+ return this.resolvedRawValue !== this.resolvedValue;
2144
+ }
2145
+ async resolve() {
2146
+ if (this.schemaErrors.length) return;
2147
+ if (this.resolverSchemaErrors.length) return;
2148
+ if (!this.valueResolver) throw new Error("Expected a resolver to be set");
2149
+ if (this.isResolved) {
2150
+ return;
2151
+ }
2152
+ try {
2153
+ this.resolvedRawValue = await this.valueResolver.resolve();
2154
+ } catch (err) {
2155
+ this.resolutionError = new ResolutionError(`error resolving value: ${err}`);
2156
+ this.resolutionError.cause = err;
2157
+ }
2158
+ if (this.resolvedRawValue instanceof RegExp) {
2159
+ this.resolutionError = new ResolutionError("regex() is meant to be used within function args, not as a final resolved value");
2160
+ }
2161
+ if (this.resolutionError) return;
2162
+ this.isResolved = true;
2163
+ if (this.resolvedRawValue === void 0 || this.resolvedRawValue === "") {
2164
+ this.resolvedValue = this.resolvedRawValue;
2165
+ if (this.isRequired) {
2166
+ this.validationErrors = [new EmptyRequiredValueError(void 0)];
2267
2167
  }
2268
- for (const itemKey in source.configItemDefs) {
2269
- if (source.ignoreNewDefs && !this.configSchema[itemKey]) continue;
2270
- const itemDef = source.configItemDefs[itemKey];
2271
- this.configSchema[itemKey] ??= new ConfigItem(this, itemKey);
2272
- this.configSchema[itemKey].addDef(itemDef, source);
2168
+ return;
2169
+ }
2170
+ if (!this.dataType) throw new Error("expected dataType to be set");
2171
+ try {
2172
+ const coerceResult = this.dataType.coerce(this.resolvedRawValue);
2173
+ if (coerceResult instanceof Error) throw coerceResult;
2174
+ this.resolvedValue = coerceResult;
2175
+ } catch (err) {
2176
+ if (err instanceof CoercionError) {
2177
+ this.coercionError = err;
2178
+ return;
2179
+ } else if (err instanceof Error) {
2180
+ this.coercionError = new CoercionError("Unexpected error coercing value");
2181
+ this.coercionError.cause = err;
2182
+ } else {
2183
+ this.coercionError = new CoercionError(`Unexpected non-error throw during coerce - ${err}`);
2273
2184
  }
2274
- if (source.type === "schema" && this.envFlagKey) {
2275
- if (!this.configSchema[this.envFlagKey]) {
2276
- throw new Error(`@envFlag key ${this.envFlagKey} not found in schema`);
2277
- }
2278
- const envFlagItem = this.configSchema[this.envFlagKey];
2279
- await envFlagItem.process();
2280
- for (const depKey of envFlagItem.valueResolver?.deps || []) {
2281
- const depItem = this.configSchema[depKey];
2282
- if (!depItem) {
2283
- throw new Error(`envFlag resolver is using non-existant dependency: ${depKey}`);
2284
- }
2285
- await depItem.process();
2286
- if (depItem.valueResolver?.deps.length) {
2287
- throw new Error("envFlag cannot follow a chain of dependencies");
2288
- }
2289
- await depItem.resolve();
2290
- }
2291
- await envFlagItem.resolve();
2292
- if (!envFlagItem.isValid) {
2293
- const err = new Error("resolved @envFlag value is not valid");
2294
- err.cause = envFlagItem.errors[0];
2295
- throw err;
2296
- }
2297
- if (envFlagItem.resolvedValue) {
2298
- if (!my_dash_default.isString(envFlagItem.resolvedValue)) {
2299
- throw new Error("expected resolved @envFlag value to be a string");
2300
- }
2301
- this.envFlagValue = envFlagItem.resolvedValue;
2302
- }
2185
+ return;
2186
+ }
2187
+ try {
2188
+ const validateResult = this.dataType.validate(this.resolvedValue);
2189
+ if (validateResult instanceof Error || my_dash_default.isArray(validateResult) && validateResult[0] instanceof Error) throw validateResult;
2190
+ if (validateResult === false) {
2191
+ throw new ValidationError("validation failed with `false` return value");
2192
+ }
2193
+ this.isValidated = true;
2194
+ } catch (err) {
2195
+ if (my_dash_default.isArray(err)) {
2196
+ this.validationErrors = err;
2197
+ } else if (err instanceof ValidationError) {
2198
+ this.validationErrors = [err];
2199
+ } else if (err instanceof Error) {
2200
+ const validationError = new ValidationError("Unexpected error during validation");
2201
+ validationError.cause = err;
2202
+ console.log(err);
2203
+ this.validationErrors = [validationError];
2204
+ } else {
2205
+ const validationError = new ValidationError(`Unexpected non-error thrown during validation - ${err}`);
2206
+ validationError.cause = err;
2207
+ this.validationErrors = [validationError];
2208
+ }
2209
+ return;
2210
+ }
2211
+ }
2212
+ get isValid() {
2213
+ return this.validationState === "valid";
2214
+ }
2215
+ };
2216
+
2217
+ // ../env-graph/src/lib/data-source.ts
2218
+ var DATA_SOURCE_TYPES = Object.freeze({
2219
+ schema: {
2220
+ fileSuffixes: ["schema"],
2221
+ precedence: 0
2222
+ },
2223
+ example: {
2224
+ fileSuffixes: ["sample", "example"],
2225
+ precedence: 1
2226
+ },
2227
+ defaults: {
2228
+ fileSuffixes: ["default", "defaults"],
2229
+ precedence: 2
2230
+ },
2231
+ values: {
2232
+ fileSuffixes: [],
2233
+ precedence: 3
2234
+ },
2235
+ overrides: {
2236
+ fileSuffixes: ["local", "override"],
2237
+ precedence: 4
2238
+ }
2239
+ });
2240
+ var EnvGraphDataSource = class {
2241
+ static {
2242
+ __name(this, "EnvGraphDataSource");
2243
+ }
2244
+ static DATA_SOURCE_TYPES = DATA_SOURCE_TYPES;
2245
+ // reference back to the graph
2246
+ graph;
2247
+ type = "values";
2248
+ applyForEnv;
2249
+ disabled = false;
2250
+ ignoreNewDefs = false;
2251
+ /** an error encountered while loading/parsing the data source */
2252
+ loadingError;
2253
+ get isValid() {
2254
+ return !this.loadingError;
2255
+ }
2256
+ configItemDefs = {};
2257
+ decorators = {};
2258
+ getStaticValues() {
2259
+ const obj = {};
2260
+ for (const [key, def] of Object.entries(this.configItemDefs)) {
2261
+ if (def.resolver instanceof StaticValueResolver) {
2262
+ obj[key] = String(def.resolver.staticValue ?? "");
2303
2263
  }
2304
2264
  }
2305
- for (const itemKey in this.configSchema) {
2306
- const item = this.configSchema[itemKey];
2307
- await item.process();
2265
+ return obj;
2266
+ }
2267
+ };
2268
+ var ProcessEnvDataSource2 = class _ProcessEnvDataSource extends EnvGraphDataSource {
2269
+ static {
2270
+ __name(this, "ProcessEnvDataSource");
2271
+ }
2272
+ type = "overrides";
2273
+ typeLabel = "process";
2274
+ label = "process.env";
2275
+ ignoreNewDefs = true;
2276
+ static processEnvValues;
2277
+ // ? do we want to set decorator values from env vars here? -- ex: _ENV_FLAG_KEY
2278
+ // depends if we want those to work only within process.env
2279
+ constructor() {
2280
+ super();
2281
+ if (!_ProcessEnvDataSource.processEnvValues) {
2282
+ _ProcessEnvDataSource.processEnvValues = {};
2283
+ for (const itemKey of Object.keys(process.env)) {
2284
+ _ProcessEnvDataSource.processEnvValues[itemKey] = process.env[itemKey];
2285
+ }
2308
2286
  }
2309
- const cycles = findGraphCycles(this.graphAdjacencyList);
2310
- for (const cycleItemKeys of cycles) {
2311
- for (const itemKey of cycleItemKeys) {
2312
- const item = this.configSchema[itemKey];
2313
- item.schemaErrors.push(
2314
- new SchemaError(
2315
- cycleItemKeys.length === 1 ? "Item cannot have dependency on itself" : `Dependency cycle detected: (${cycleItemKeys.join(", ")})`
2316
- )
2317
- );
2287
+ for (const itemKey of Object.keys(_ProcessEnvDataSource.processEnvValues)) {
2288
+ this.configItemDefs[itemKey] = {
2289
+ resolver: new StaticValueResolver(_ProcessEnvDataSource.processEnvValues[itemKey])
2290
+ };
2291
+ }
2292
+ }
2293
+ };
2294
+ var EnvSourceParseError = class extends Error {
2295
+ constructor(message, location) {
2296
+ super(message);
2297
+ this.location = location;
2298
+ }
2299
+ static {
2300
+ __name(this, "EnvSourceParseError");
2301
+ }
2302
+ };
2303
+ var FileBasedDataSource = class extends EnvGraphDataSource {
2304
+ static {
2305
+ __name(this, "FileBasedDataSource");
2306
+ }
2307
+ isGitIgnored;
2308
+ fullPath;
2309
+ fileName;
2310
+ rawContents;
2311
+ get typeLabel() {
2312
+ return this.constructor.format;
2313
+ }
2314
+ get label() {
2315
+ return this.fileName;
2316
+ }
2317
+ static format = "unknown";
2318
+ // no abstract static
2319
+ static validFileExtensions = [];
2320
+ get validFileExtensions() {
2321
+ return this.constructor.validFileExtensions;
2322
+ }
2323
+ constructor(fullPath, opts) {
2324
+ super();
2325
+ this.fullPath = fullPath;
2326
+ this.fileName = path.basename(fullPath);
2327
+ if (opts?.overrideContents) {
2328
+ this.rawContents = opts.overrideContents;
2329
+ this.isGitIgnored = opts.overrideGitIgnored;
2330
+ }
2331
+ if (!this.fileName.startsWith(".env")) {
2332
+ throw new Error('file name must start with ".env"');
2333
+ }
2334
+ const fileNameParts = this.fileName.substring(1).split(".");
2335
+ const maybeExtension = fileNameParts[fileNameParts.length - 1];
2336
+ if (this.validFileExtensions.includes(maybeExtension)) {
2337
+ fileNameParts.pop();
2338
+ }
2339
+ const maybeFileType = fileNameParts[fileNameParts.length - 1];
2340
+ for (const [possibleSourceType, possibleSourceSpec] of Object.entries(DATA_SOURCE_TYPES)) {
2341
+ if (possibleSourceSpec.fileSuffixes.includes(maybeFileType)) {
2342
+ this.type = possibleSourceType;
2343
+ break;
2318
2344
  }
2319
2345
  }
2346
+ if (this.type !== "values") fileNameParts.pop();
2347
+ if (fileNameParts.length > 2) {
2348
+ throw Error(`Unsure how to interpret filename - ${this.fileName}`);
2349
+ } else if (fileNameParts.length === 2) {
2350
+ this.applyForEnv = fileNameParts[1];
2351
+ if (this.applyForEnv === "dev") this.applyForEnv = "development";
2352
+ if (this.applyForEnv === "stage") this.applyForEnv = "staging";
2353
+ if (this.applyForEnv === "prod") this.applyForEnv = "production";
2354
+ }
2320
2355
  }
2321
- get graphAdjacencyList() {
2322
- const adjList = {};
2323
- for (const itemKey in this.configSchema) {
2324
- const item = this.configSchema[itemKey];
2325
- adjList[itemKey] = item.valueResolver?.deps || [];
2356
+ // no async constructors... :(
2357
+ async finishInit() {
2358
+ if (!this.rawContents) {
2359
+ this.isGitIgnored = await checkIsFileGitIgnored(this.fullPath);
2360
+ this.rawContents = await fs2.readFile(this.fullPath, "utf8");
2326
2361
  }
2327
- return adjList;
2362
+ await this._parseContents();
2328
2363
  }
2329
- async resolveEnvValues() {
2330
- const adjList = this.graphAdjacencyList;
2331
- const reverseAdjList = {};
2332
- for (const itemKey in adjList) {
2333
- const itemDeps = adjList[itemKey];
2334
- for (const dep of itemDeps) {
2335
- reverseAdjList[dep] ??= [];
2336
- reverseAdjList[dep].push(itemKey);
2364
+ };
2365
+ var DotEnvFileDataSource = class extends FileBasedDataSource {
2366
+ static {
2367
+ __name(this, "DotEnvFileDataSource");
2368
+ }
2369
+ static format = ".env";
2370
+ static validFileExtensions = [];
2371
+ // no extension for dotenv files!
2372
+ parsedFile;
2373
+ convertParserValueToResolvers(value) {
2374
+ if (!this.graph) throw new Error("expected graph to be set");
2375
+ if (value === void 0) {
2376
+ return new StaticValueResolver(void 0);
2377
+ } else if (value instanceof ParsedEnvSpecStaticValue) {
2378
+ return new StaticValueResolver(value.unescapedValue);
2379
+ } else if (value instanceof ParsedEnvSpecFunctionCall) {
2380
+ const ResolverFnClass = this.graph.registeredResolverFunctions[value.name];
2381
+ if (!ResolverFnClass) {
2382
+ return new ErrorResolver(new SchemaError(`Unknown resolver function: ${value.name}()`));
2337
2383
  }
2338
- }
2339
- const itemsToResolveStatus = my_dash_default.mapValues(this.configSchema, () => false);
2340
- const deferred = new Promise((resolve, reject) => {
2341
- const markItemCompleted = /* @__PURE__ */ __name((itemKey) => {
2342
- delete itemsToResolveStatus[itemKey];
2343
- if (reverseAdjList[itemKey]) {
2344
- reverseAdjList[itemKey].forEach(resolveItem);
2345
- }
2346
- if (my_dash_default.keys(itemsToResolveStatus).length === 0) resolve();
2347
- }, "markItemCompleted");
2348
- const resolveItem = /* @__PURE__ */ __name(async (itemKey) => {
2349
- if (itemsToResolveStatus[itemKey] !== false) return;
2350
- const item = this.configSchema[itemKey];
2351
- if (item.errors.length) {
2352
- markItemCompleted(itemKey);
2353
- return;
2354
- }
2355
- for (const depKey of adjList[itemKey]) {
2356
- const depItem = this.configSchema[depKey];
2357
- if (depItem.validationState === "error") {
2358
- item.resolutionError = new ResolutionError(`Dependency ${depKey} is invalid`);
2359
- markItemCompleted(itemKey);
2360
- return;
2361
- } else if (depKey in itemsToResolveStatus) {
2362
- return;
2384
+ const argsFromParser = value.data.args.values;
2385
+ let keyValueArgs;
2386
+ const argsAsResolversArray = [];
2387
+ for (const arg of argsFromParser) {
2388
+ if (arg instanceof ParsedEnvSpecKeyValuePair) {
2389
+ keyValueArgs ??= {};
2390
+ keyValueArgs[arg.key] = this.convertParserValueToResolvers(arg.value);
2391
+ } else {
2392
+ if (keyValueArgs) {
2393
+ return new ErrorResolver(new SchemaError("After switching to key-value function args, cannot switch back"));
2363
2394
  }
2395
+ argsAsResolversArray.push(this.convertParserValueToResolvers(arg));
2364
2396
  }
2365
- itemsToResolveStatus[itemKey] = true;
2366
- await item.resolve();
2367
- markItemCompleted(itemKey);
2368
- }, "resolveItem");
2369
- for (const itemKey in this.configSchema) {
2370
- resolveItem(itemKey);
2371
2397
  }
2372
- });
2373
- return deferred;
2374
- }
2375
- getResolvedEnvObject() {
2376
- const envObject = {};
2377
- for (const itemKey in this.configSchema) {
2378
- const item = this.configSchema[itemKey];
2379
- envObject[itemKey] = item.resolvedValue;
2398
+ if (keyValueArgs) argsAsResolversArray.push(keyValueArgs);
2399
+ return new ResolverFnClass(argsAsResolversArray);
2400
+ } else {
2401
+ throw new Error("Unknown value type");
2380
2402
  }
2381
- return envObject;
2382
2403
  }
2383
- getSerializedGraph() {
2384
- const serializedGraph = {
2385
- sources: [],
2386
- config: {},
2387
- settings: {}
2388
- };
2389
- for (const source of this.sortedDataSources) {
2390
- serializedGraph.sources.push({
2391
- label: source.label,
2392
- enabled: !source.disabled
2393
- });
2394
- }
2395
- for (const itemKey in this.configSchema) {
2396
- const item = this.configSchema[itemKey];
2397
- serializedGraph.config[itemKey] = {
2398
- value: item.resolvedValue,
2399
- isSensitive: item.isSensitive
2404
+ async _parseContents() {
2405
+ const rawContents = this.rawContents;
2406
+ this.parsedFile = await tryCatch(
2407
+ () => parseEnvSpecDotEnvFile(rawContents),
2408
+ (error) => {
2409
+ this.loadingError = new EnvSourceParseError(error.message, {
2410
+ path: this.fullPath,
2411
+ lineNumber: error.location.start.line,
2412
+ colNumber: error.location.start.column,
2413
+ lineStr: rawContents.split("\n")[error.location.start.line - 1]
2414
+ });
2415
+ this.loadingError.cause = error;
2416
+ }
2417
+ );
2418
+ if (this.loadingError) return;
2419
+ if (!this.parsedFile) throw new Error("Failed to parse .env file");
2420
+ this.decorators = this.parsedFile.decoratorsObject;
2421
+ if (!this.graph) throw new Error("expected graph to be set");
2422
+ for (const item of this.parsedFile.configItems) {
2423
+ item.processExpansion();
2424
+ this.configItemDefs[item.key] = {
2425
+ resolver: this.convertParserValueToResolvers(item.expandedValue),
2426
+ description: item.description,
2427
+ decorators: item.decoratorsObject
2400
2428
  };
2401
2429
  }
2402
- serializedGraph.settings.redactLogs = this.getRootDecoratorValue("redactLogs") ?? true;
2403
- serializedGraph.settings.preventLeaks = this.getRootDecoratorValue("preventLeaks") ?? true;
2404
- return serializedGraph;
2405
- }
2406
- get isInvalid() {
2407
- return my_dash_default.some(my_dash_default.values(this.configSchema), (i) => !i.isValid);
2408
- }
2409
- async generateTypes(lang, outputPath) {
2410
- await generateTypes(this, lang, outputPath);
2411
- }
2412
- getRootDecoratorValue(decoratorName) {
2413
- const dec = this.schemaDataSource?.decorators?.[decoratorName];
2414
- return dec?.simplifiedValue;
2415
2430
  }
2416
2431
  };
2417
- var SKIP_FILE_TYPES = [".md", ".d.ts"];
2418
- async function findEnvFiles(opts) {
2419
- const cwd = opts?.cwd || process.cwd();
2420
- const envFiles = [];
2421
- const filesWithinDir = await fs.readdir(cwd);
2422
- for (const fileName of filesWithinDir) {
2423
- if (fileName.startsWith(".env")) {
2424
- let skip = false;
2425
- for (const fileType of SKIP_FILE_TYPES) {
2426
- if (fileName.endsWith(fileType)) skip = true;
2427
- }
2428
- if (skip) continue;
2429
- envFiles.push(path.join(cwd, fileName));
2430
- }
2431
- }
2432
- return envFiles;
2433
- }
2434
- __name(findEnvFiles, "findEnvFiles");
2435
-
2436
- // ../env-graph/src/lib/loader.ts
2437
- function autoDetectContextPath() {
2438
- const PWD = process.env.PWD;
2439
- if (!PWD) {
2440
- throw new Error("PWD is not set");
2441
- }
2442
- return PWD;
2443
- }
2444
- __name(autoDetectContextPath, "autoDetectContextPath");
2445
- async function loadEnvGraph(opts) {
2446
- const contextPath = opts?.contextPath ?? autoDetectContextPath();
2447
- const graph = new EnvGraph();
2448
- graph.basePath = contextPath;
2449
- if (opts?.afterInit) {
2450
- await opts.afterInit(graph);
2451
- }
2452
- if (opts?.currentEnvFallback) {
2453
- graph.envFlagValue = opts.currentEnvFallback;
2454
- }
2455
- const envFilePaths = await findEnvFiles({
2456
- cwd: contextPath
2457
- });
2458
- for (const envFilePath of envFilePaths) {
2459
- const fileDataSource = new DotEnvFileDataSource(envFilePath);
2460
- graph.addDataSource(fileDataSource);
2461
- await fileDataSource.finishInit();
2462
- }
2463
- graph.finalOverridesDataSource = new ProcessEnvDataSource();
2464
- await graph.finishLoad();
2465
- return graph;
2466
- }
2467
- __name(loadEnvGraph, "loadEnvGraph");
2468
2432
 
2469
- export { DotEnvFileDataSource, EnvSourceParseError, StaticValueResolver, checkIsFileGitIgnored, loadEnvGraph, my_dash_default };
2470
- //# sourceMappingURL=chunk-DROJWTCD.js.map
2471
- //# sourceMappingURL=chunk-DROJWTCD.js.map
2433
+ export { DotEnvFileDataSource, EnvGraph2 as EnvGraph, EnvSourceParseError, ProcessEnvDataSource2 as ProcessEnvDataSource, StaticValueResolver, checkIsFileGitIgnored, my_dash_default };
2434
+ //# sourceMappingURL=chunk-K2N2TG4M.js.map
2435
+ //# sourceMappingURL=chunk-K2N2TG4M.js.map