typed-settings 0.1.1 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. package/README.md +18 -9
  2. package/bin/typed-settings.mjs +5 -0
  3. package/dist/adapters/joi.cjs +1 -26
  4. package/dist/adapters/joi.d.cts +2 -1
  5. package/dist/adapters/joi.d.ts +2 -1
  6. package/dist/adapters/joi.js +1 -1
  7. package/dist/adapters/superstruct.cjs +1 -26
  8. package/dist/adapters/superstruct.js +1 -1
  9. package/dist/adapters/yup.cjs +1 -25
  10. package/dist/adapters/yup.js +1 -1
  11. package/dist/adapters/zod.cjs +3 -36
  12. package/dist/adapters/zod.d.cts +2 -0
  13. package/dist/adapters/zod.d.ts +2 -0
  14. package/dist/adapters/zod.js +1 -33
  15. package/dist/check-XVFZEVNV.js +1 -0
  16. package/dist/chunk-4EAMKDNK.js +3 -0
  17. package/dist/chunk-5D2AQWDG.js +1 -0
  18. package/dist/chunk-C6CG2D4B.js +2 -0
  19. package/dist/chunk-FQYD5ZKE.js +1 -0
  20. package/dist/chunk-NQDE3WLR.js +3 -0
  21. package/dist/chunk-RURPDXIJ.js +1 -0
  22. package/dist/cli/main.cjs +36 -2220
  23. package/dist/cli/main.js +32 -806
  24. package/dist/errors-JkkOM0u-.d.cts +25 -0
  25. package/dist/errors-JkkOM0u-.d.ts +25 -0
  26. package/dist/framework/next.cjs +5 -1153
  27. package/dist/framework/next.d.cts +5 -3
  28. package/dist/framework/next.d.ts +5 -3
  29. package/dist/framework/next.js +1 -15
  30. package/dist/framework/vite.cjs +5 -1151
  31. package/dist/framework/vite.d.cts +10 -3
  32. package/dist/framework/vite.d.ts +10 -3
  33. package/dist/framework/vite.js +1 -14
  34. package/dist/index.cjs +5 -1176
  35. package/dist/index.d.cts +46 -10
  36. package/dist/index.d.ts +46 -10
  37. package/dist/index.js +1 -6
  38. package/dist/node.cjs +6 -1236
  39. package/dist/node.d.cts +23 -9
  40. package/dist/node.d.ts +23 -9
  41. package/dist/node.js +1 -7
  42. package/dist/{types-CClP1lxq.d.ts → types-CcsYDAdO.d.cts} +27 -3
  43. package/dist/{types-CClP1lxq.d.cts → types-CcsYDAdO.d.ts} +27 -3
  44. package/dist/vault/aws.cjs +4 -217
  45. package/dist/vault/aws.d.cts +3 -1
  46. package/dist/vault/aws.d.ts +3 -1
  47. package/dist/vault/aws.js +2 -167
  48. package/dist/vault/hashicorp.cjs +4 -183
  49. package/dist/vault/hashicorp.d.cts +3 -1
  50. package/dist/vault/hashicorp.d.ts +3 -1
  51. package/dist/vault/hashicorp.js +2 -77
  52. package/dist/vault/http.cjs +4 -185
  53. package/dist/vault/http.d.cts +3 -1
  54. package/dist/vault/http.d.ts +3 -1
  55. package/dist/vault/http.js +2 -79
  56. package/package.json +10 -3
  57. package/dist/chunk-33M5GIKQ.js +0 -13
  58. package/dist/chunk-A5TCQJ7L.js +0 -65
  59. package/dist/chunk-EE6LXNJV.js +0 -34
  60. package/dist/chunk-F6DX3HXZ.js +0 -101
  61. package/dist/chunk-OVFMKC2O.js +0 -15
  62. package/dist/chunk-RCO6K3WQ.js +0 -984
  63. package/dist/chunk-RQC6OMVV.js +0 -86
  64. package/dist/chunk-UFUHHR2J.js +0 -38
  65. package/dist/chunk-VTIYOSG2.js +0 -233
  66. package/dist/errors-itGaU4Q8.d.cts +0 -17
  67. package/dist/errors-itGaU4Q8.d.ts +0 -17
  68. package/dist/formats/env.cjs +0 -103
  69. package/dist/formats/env.d.cts +0 -8
  70. package/dist/formats/env.d.ts +0 -8
  71. package/dist/formats/env.js +0 -1
  72. package/dist/formats/json.cjs +0 -15
  73. package/dist/formats/json.d.cts +0 -7
  74. package/dist/formats/json.d.ts +0 -7
  75. package/dist/formats/json.js +0 -1
  76. package/dist/formats/toml.cjs +0 -17
  77. package/dist/formats/toml.d.cts +0 -7
  78. package/dist/formats/toml.d.ts +0 -7
  79. package/dist/formats/toml.js +0 -1
  80. package/dist/formats/yaml.cjs +0 -40
  81. package/dist/formats/yaml.d.cts +0 -8
  82. package/dist/formats/yaml.d.ts +0 -8
  83. package/dist/formats/yaml.js +0 -1
package/dist/cli/main.cjs CHANGED
@@ -1,2245 +1,61 @@
1
1
  #!/usr/bin/env node
2
- 'use strict';
3
-
4
- var yaml = require('yaml');
5
- var smolToml = require('smol-toml');
6
- var util = require('util');
7
- var path = require('path');
8
- var fs = require('fs');
9
- var child_process = require('child_process');
10
-
11
- var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
12
- var __defProp = Object.defineProperty;
13
- var __getOwnPropNames = Object.getOwnPropertyNames;
14
- var __esm = (fn, res) => function __init() {
15
- return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
16
- };
17
- var __export = (target, all) => {
18
- for (var name in all)
19
- __defProp(target, name, { get: all[name], enumerable: true });
20
- };
21
-
22
- // src/errors.ts
23
- function redactValue(key, value) {
24
- if (SECRET_RE.test(key) && typeof value === "string" && value.length > 0) {
25
- if (value.length <= 8) return "(redacted)";
26
- return `${value.slice(0, 3)}-*** (${value.length} chars)`;
27
- }
28
- return String(value);
29
- }
30
- function byteLengthUtf8(text) {
31
- try {
32
- const g = globalThis;
33
- if (g.TextEncoder) return new g.TextEncoder().encode(text).length;
34
- if (g.Buffer) return g.Buffer.byteLength(text, "utf8");
35
- } catch {
36
- }
37
- return text.length;
38
- }
39
- var SECRET_RE, ConfigError;
40
- var init_errors = __esm({
41
- "src/errors.ts"() {
42
- SECRET_RE = /key|secret|token|password|private/i;
43
- ConfigError = class extends Error {
44
- code = "E_INVALID_CONFIG";
45
- issues;
46
- constructor(issues, code = "E_INVALID_CONFIG") {
47
- const lines = issues.map(
48
- (i) => `- ${i.path} (from ${i.from}): ${i.message}`
49
- );
50
- super(`Invalid config (${issues.length} issue${issues.length === 1 ? "" : "s"}):
51
- ${lines.join("\n")}`);
52
- this.name = "ConfigError";
53
- this.code = code;
54
- this.issues = issues;
55
- }
56
- };
57
- }
58
- });
59
-
60
- // src/formats/env.ts
61
- function parseEnvText(text) {
62
- const out = {};
63
- if (text.charCodeAt(0) === 65279) text = text.slice(1);
64
- const lines = splitLogicalLines(text);
65
- for (const rawLine of lines) {
66
- let line = rawLine.trim();
67
- if (!line || line.startsWith("#")) continue;
68
- if (line.startsWith("export ")) line = line.slice(7).trimStart();
69
- const eq = line.indexOf("=");
70
- if (eq === -1) {
71
- throw new Error(`ParseError: bare key without '=': ${JSON.stringify(line)}`);
72
- }
73
- const key = line.slice(0, eq).trim();
74
- let rest = line.slice(eq + 1).trimStart();
75
- if (!key) throw new Error("ParseError: empty key");
76
- out[key] = parseValue(rest);
77
- }
78
- return out;
79
- }
80
- function splitLogicalLines(text) {
81
- const physical = text.split(/\r?\n/);
82
- const out = [];
83
- let buf = "";
84
- let inDouble = false;
85
- for (const pl of physical) {
86
- if (!inDouble) {
87
- const opens = countUnescapedQuotes(pl);
88
- if (opens % 2 === 1 && isValueStartDoubleQuoted(pl)) {
89
- buf = pl;
90
- inDouble = true;
91
- } else {
92
- out.push(pl);
93
- }
94
- } else {
95
- buf += "\n" + pl;
96
- const opens = countUnescapedQuotes(buf.split("=").slice(1).join("="));
97
- if (opens % 2 === 0) {
98
- inDouble = false;
99
- out.push(buf);
100
- buf = "";
101
- }
102
- }
103
- }
104
- if (inDouble) throw new Error("ParseError: unterminated double-quoted value");
105
- return out;
106
- }
107
- function isValueStartDoubleQuoted(line) {
108
- const eq = line.indexOf("=");
109
- if (eq === -1) return false;
110
- const rest = line.slice(eq + 1).trimStart();
111
- return rest.startsWith('"') && !rest.endsWith('"');
112
- }
113
- function countUnescapedQuotes(s) {
114
- let n = 0;
115
- for (let i = 0; i < s.length; i++) {
116
- if (s[i] === '"' && s[i - 1] !== "\\") n++;
117
- }
118
- return n;
119
- }
120
- function parseValue(rest) {
121
- if (!rest) return "";
122
- if (rest.startsWith("'")) {
123
- const end = rest.indexOf("'", 1);
124
- if (end === -1) throw new Error("ParseError: unterminated single-quoted value");
125
- return rest.slice(1, end);
126
- }
127
- if (rest.startsWith('"')) {
128
- let i = 1;
129
- let val = "";
130
- while (i < rest.length) {
131
- const c = rest[i];
132
- if (c === "\\" && i + 1 < rest.length) {
133
- const n = rest[i + 1];
134
- if (n === "n") val += "\n";
135
- else if (n === "r") val += "\r";
136
- else if (n === "t") val += " ";
137
- else val += n;
138
- i += 2;
139
- continue;
140
- }
141
- if (c === '"') break;
142
- val += c;
143
- i++;
144
- }
145
- if (rest[i] !== '"') throw new Error("ParseError: unterminated double-quoted value");
146
- return val;
147
- }
148
- if (rest.startsWith("`")) throw new Error("ParseError: backtick values not supported");
149
- const hash = findCommentStart(rest);
150
- const v = (hash === -1 ? rest : rest.slice(0, hash)).trim();
151
- return v;
152
- }
153
- function findCommentStart(s) {
154
- for (let i = 0; i < s.length; i++) {
155
- if (s[i] === "#" && (i === 0 || /\s/.test(s[i - 1]))) return i;
156
- }
157
- return -1;
158
- }
159
- var init_env = __esm({
160
- "src/formats/env.ts"() {
161
- }
162
- });
163
-
164
- // src/formats/json.ts
165
- function parseJsonText(text, from = "json") {
166
- const stripped = text.charCodeAt(0) === 65279 ? text.slice(1) : text;
167
- if (!stripped.trim()) return {};
168
- try {
169
- return JSON.parse(stripped);
170
- } catch (e) {
171
- const err = e;
172
- throw new Error(`ParseError (${from}): ${err.message}`);
173
- }
174
- }
175
- var init_json = __esm({
176
- "src/formats/json.ts"() {
177
- }
178
- });
179
- function parseYamlText(text, from = "yaml") {
180
- const stripped = text.charCodeAt(0) === 65279 ? text.slice(1) : text;
181
- if (!stripped.trim()) return {};
182
- const docs = yaml.parseAllDocuments(stripped, {
183
- version: "1.2",
184
- uniqueKeys: true
185
- }).filter((d) => {
186
- if (d.errors.length > 0) return true;
187
- try {
188
- const v = d.toJS();
189
- return v !== null && v !== void 0;
190
- } catch {
191
- return true;
192
- }
193
- });
194
- if (docs.length === 0) return {};
195
- if (docs.length > 1) {
196
- throw new Error(`ParseError (${from}): multi-doc YAML not supported (got ${docs.length} documents)`);
197
- }
198
- const doc = docs[0];
199
- if (doc.errors.length > 0) {
200
- const first = doc.errors[0];
201
- const line = first.linePos?.[0]?.line ?? "?";
202
- throw new Error(`ParseError (${from}:${line}): ${first.message}`);
203
- }
204
- let value;
205
- try {
206
- value = doc.toJS();
207
- } catch (e) {
208
- throw new Error(`ParseError (${from}): ${e.message}`);
209
- }
210
- return value;
211
- }
212
- var init_yaml = __esm({
213
- "src/formats/yaml.ts"() {
214
- }
215
- });
216
- function parseTomlText(text, from = "toml") {
217
- const stripped = text.charCodeAt(0) === 65279 ? text.slice(1) : text;
218
- if (!stripped.trim()) return {};
219
- try {
220
- return smolToml.parse(stripped);
221
- } catch (e) {
222
- const err = e;
223
- throw new Error(`ParseError (${from}): ${err.message}`);
224
- }
225
- }
226
- var init_toml = __esm({
227
- "src/formats/toml.ts"() {
228
- }
229
- });
230
-
231
- // src/expand.ts
232
- function expandValue(input, lookup, opts) {
233
- let out = "";
234
- let i = 0;
235
- while (i < input.length) {
236
- const c = input[i];
237
- if (c === "$" && input[i + 1] === "$") {
238
- out += "$";
239
- i += 2;
240
- continue;
241
- }
242
- if (c === "\\" && input[i + 1] === "$") {
243
- out += "$";
244
- i += 2;
245
- continue;
246
- }
247
- if (c !== "$") {
248
- out += c;
249
- i++;
250
- continue;
251
- }
252
- const rest = input.slice(i);
253
- if (rest.startsWith("${")) {
254
- const parsed = parseBraced(input, i);
255
- if (!parsed) {
256
- out += "$";
257
- i++;
258
- continue;
259
- }
260
- const { name: name2, op, def, end } = parsed;
261
- if (op && op !== ":-" && op !== "-") {
262
- throw new ConfigError([
263
- { path: name2, from: opts?.from ?? "env", message: `E_BAD_OP: only :- and - supported, got ${op}` }
264
- ], "E_BAD_OP");
265
- }
266
- const val2 = lookup(name2);
267
- const missing = val2 === void 0 || op === ":-" && val2 === "";
268
- if (!missing) {
269
- out += val2;
270
- } else if (def !== void 0) {
271
- out += expandValue(def, lookup, opts);
272
- } else if (opts?.allowUnresolved) {
273
- out += input.slice(i, end);
274
- } else {
275
- throw new ConfigError([
276
- { path: name2, from: opts?.from ?? "env", message: `E_UNRESOLVED: ${name2} missing (expand)` }
277
- ], "E_UNRESOLVED");
278
- }
279
- i = end;
280
- continue;
281
- }
282
- const m = new RegExp(`^\\$(?<name>${NAME_RE})`).exec(rest);
283
- if (!m || !m.groups) {
284
- out += "$";
285
- i++;
286
- continue;
287
- }
288
- const name = m.groups["name"];
289
- const val = lookup(name);
290
- if (val === void 0) {
291
- if (opts?.allowUnresolved) {
292
- out += "$" + name;
293
- } else {
294
- throw new ConfigError([
295
- { path: name, from: opts?.from ?? "env", message: `E_UNRESOLVED: ${name} missing (expand)` }
296
- ], "E_UNRESOLVED");
297
- }
298
- } else {
299
- out += val;
300
- }
301
- i += 1 + name.length;
302
- }
303
- return out;
304
- }
305
- function parseBraced(input, start) {
306
- let i = start + 2;
307
- const nameMatch = new RegExp(`^(?<name>${NAME_RE})`).exec(input.slice(i));
308
- if (!nameMatch?.groups) return null;
309
- const name = nameMatch.groups["name"];
310
- i += name.length;
311
- if (input[i] === "}") return { name, end: i + 1 };
312
- if (input[i] === ":") {
313
- const two = input.slice(i, i + 2);
314
- if (two !== ":-") return { name, op: two[0] + (input[i + 1] ?? ""), def: "", end: input.length };
315
- i += 2;
316
- const { value, end } = readUntilCloseBrace(input, i);
317
- return { name, op: ":-", def: value, end };
318
- }
319
- if (input[i] === "-") {
320
- i += 1;
321
- const { value, end } = readUntilCloseBrace(input, i);
322
- return { name, op: "-", def: value, end };
323
- }
324
- return null;
325
- }
326
- function readUntilCloseBrace(input, start) {
327
- let depth = 0;
328
- let i = start;
329
- let val = "";
330
- while (i < input.length) {
331
- if (input[i] === "\\" && input[i + 1] === "}") {
332
- val += "}";
333
- i += 2;
334
- continue;
335
- }
336
- if (input[i] === "{") depth++;
337
- if (input[i] === "}") {
338
- if (depth === 0) return { value: val, end: i + 1 };
339
- depth--;
340
- }
341
- val += input[i];
342
- i++;
343
- }
344
- throw new Error("ParseError: unterminated ${}");
345
- }
346
- var NAME_RE;
347
- var init_expand = __esm({
348
- "src/expand.ts"() {
349
- init_errors();
350
- NAME_RE = "[A-Za-z_][A-Za-z0-9_]*";
351
- }
352
- });
353
-
354
- // src/coerce.ts
355
- function tryParseEnvValue(input) {
356
- return tryParse(input, true);
357
- }
358
- function tryParse(input, allowSplit) {
359
- if (typeof input !== "string") return input;
360
- const s = input;
361
- if (s === "") return "";
362
- const low = s.toLowerCase();
363
- if (low === "true" || low === "false") return low === "true";
364
- if (low === "null") return null;
365
- if (low === "undefined") return void 0;
366
- if (/^-?\d+$/.test(s)) {
367
- const n = Number(s);
368
- if (Number.isSafeInteger(n)) return n;
369
- return s;
370
- }
371
- if (/^-?(\d+\.\d*|\.\d+|\d+)(e[+-]?\d+)?$/i.test(s) && s !== "-" && s !== ".") {
372
- const n = Number(s);
373
- if (Number.isFinite(n)) return n;
374
- return s;
375
- }
376
- if (["yes", "y", "on"].includes(low)) return true;
377
- if (["no", "n", "off"].includes(low)) return false;
378
- const t = s.trim();
379
- if (t.startsWith("{") && t.endsWith("}") || t.startsWith("[") && t.endsWith("]")) {
380
- try {
381
- return JSON.parse(t);
382
- } catch {
383
- return input;
384
- }
385
- }
386
- if (allowSplit && s.includes(",")) {
387
- const parts = splitCsv(s);
388
- if (parts !== null) return parts.map((p) => tryParse(p, false));
389
- }
390
- return input;
391
- }
392
- function splitCsv(s) {
393
- const out = [];
394
- let cur = "";
395
- let quote = null;
396
- for (let i = 0; i < s.length; i++) {
397
- const c = s[i];
398
- if (quote) {
399
- if (c === "\\" && i + 1 < s.length) {
400
- cur += c + s[i + 1];
401
- i++;
402
- continue;
403
- }
404
- if (c === quote) {
405
- quote = null;
406
- cur += c;
407
- continue;
408
- }
409
- cur += c;
410
- continue;
411
- }
412
- if (c === '"' || c === "'") {
413
- quote = c;
414
- cur += c;
415
- continue;
416
- }
417
- if (c === "\\" && s[i + 1] === ",") {
418
- cur += ",";
419
- i++;
420
- continue;
421
- }
422
- if (c === ",") {
423
- out.push(cur.trim());
424
- cur = "";
425
- continue;
426
- }
427
- cur += c;
428
- }
429
- if (quote) return null;
430
- out.push(cur.trim());
431
- return out.map((p) => {
432
- if (p.length >= 2 && p.startsWith("'") && p.endsWith("'")) return p.slice(1, -1).replace(/\\,/g, ",");
433
- if (p.length >= 2 && p.startsWith('"') && p.endsWith('"')) return p.slice(1, -1);
434
- return p.replace(/\\,/g, ",");
435
- });
436
- }
437
- function coerceDeep(value) {
438
- if (typeof value === "string") return tryParseEnvValue(value);
439
- if (Array.isArray(value)) return value.map(coerceDeep);
440
- if (value && typeof value === "object") {
441
- const o = {};
442
- for (const [k, v] of Object.entries(value)) o[k] = coerceDeep(v);
443
- return o;
444
- }
445
- return value;
446
- }
447
- var init_coerce = __esm({
448
- "src/coerce.ts"() {
449
- }
450
- });
451
-
452
- // src/merge.ts
453
- function stripPrefix(key, prefix) {
454
- return key;
455
- }
456
- function expandKeys(flat, opts) {
457
- const out = {};
458
- const topKinds = /* @__PURE__ */ new Map();
459
- const kindOf = (top) => {
460
- let k = topKinds.get(top);
461
- if (!k) {
462
- k = { indexed: false, named: false, scalar: false };
463
- topKinds.set(top, k);
464
- }
465
- return k;
466
- };
467
- const lookupEnvMap = (rawKey) => {
468
- if (!opts?.envMap) return void 0;
469
- for (const cand of [rawKey, rawKey.toLowerCase(), rawKey.toUpperCase()]) {
470
- const hit = opts.envMap[cand];
471
- if (hit !== void 0) return hit;
472
- }
473
- return void 0;
474
- };
475
- for (const [rawKey, value] of Object.entries(flat)) {
476
- if (!/^[A-Za-z0-9_]+$/.test(rawKey)) continue;
477
- const escaped = lookupEnvMap(rawKey);
478
- const effective = escaped ?? rawKey;
479
- if (escaped !== void 0) {
480
- const k = effective.toLowerCase();
481
- if (FORBIDDEN.has(k)) throw new ConfigError([{ path: rawKey, from: "keys", message: "E_PROTO" }], "E_PROTO");
482
- out[k] = value;
483
- continue;
484
- }
485
- const stripped = stripPrefix(rawKey);
486
- if (stripped === null) continue;
487
- const useKey = stripped;
488
- if (useKey.includes("__")) {
489
- if (FORBIDDEN.has(useKey.toLowerCase())) throw new ConfigError([{ path: rawKey, from: "keys", message: "E_PROTO: forbidden key" }], "E_PROTO");
490
- const parts = useKey.split("__");
491
- for (const p of parts) {
492
- if (FORBIDDEN.has(p.toLowerCase())) throw new ConfigError([{ path: rawKey, from: "keys", message: "E_PROTO: forbidden key" }], "E_PROTO");
493
- if (!p) throw new ConfigError([{ path: rawKey, from: "keys", message: "E_EMPTY_SEGMENT" }], "E_EMPTY_SEGMENT");
494
- }
495
- const lowered = parts.map((p) => p.toLowerCase());
496
- const top = lowered[0];
497
- const kind = kindOf(top);
498
- const childIsIndex = lowered.length > 1 && INDEX_RE.test(lowered[1]);
499
- if (kind.scalar && childIsIndex) {
500
- throw new ConfigError(
501
- [{ path: rawKey, from: "keys", message: `E_ARRAY_MIX: '${top}' has both scalar/list and indexed (__0) values in the same layer` }],
502
- "E_ARRAY_MIX"
503
- );
504
- }
505
- if (childIsIndex) {
506
- if (kind.named) {
507
- throw new ConfigError(
508
- [{ path: rawKey, from: "keys", message: `E_ARRAY_MIX: '${top}' mixes indexed (__0) and named children in the same layer` }],
509
- "E_ARRAY_MIX"
510
- );
511
- }
512
- kind.indexed = true;
513
- } else if (lowered.length > 1) {
514
- if (kind.indexed) {
515
- throw new ConfigError(
516
- [{ path: rawKey, from: "keys", message: `E_ARRAY_MIX: '${top}' mixes named and indexed (__0) children in the same layer` }],
517
- "E_ARRAY_MIX"
518
- );
519
- }
520
- kind.named = true;
521
- }
522
- setPath(out, lowered, value);
523
- } else {
524
- const k = useKey.toLowerCase();
525
- if (FORBIDDEN.has(k)) throw new ConfigError([{ path: rawKey, from: "keys", message: "E_PROTO" }], "E_PROTO");
526
- const kind = kindOf(k);
527
- if (kind.indexed) {
528
- throw new ConfigError(
529
- [{ path: rawKey, from: "keys", message: `E_ARRAY_MIX: '${k}' has both indexed (__0) and scalar/list values in the same layer` }],
530
- "E_ARRAY_MIX"
531
- );
532
- }
533
- kind.scalar = true;
534
- out[k] = value;
535
- }
536
- }
537
- return out;
538
- }
539
- function normalizeIndexedObjects(value, path = "<root>") {
540
- if (Array.isArray(value)) return value.map((x, i) => normalizeIndexedObjects(x, `${path}[${i}]`));
541
- if (!isPlainObject(value)) return value;
542
- const entries = Object.entries(value);
543
- const normalized = {};
544
- for (const [k, v] of entries) {
545
- normalized[k] = normalizeIndexedObjects(v, path === "<root>" ? k : `${path}.${k}`);
546
- }
547
- if (entries.length > 0 && entries.every(([k]) => INDEX_RE.test(k))) {
548
- const idx = entries.map(([k]) => Number(k)).sort((a, b) => a - b);
549
- if (idx.length > 1024) {
550
- throw new ConfigError([{ path, from: "keys", message: "E_ARRAY_CAP: >1024 elements" }], "E_ARRAY_CAP");
551
- }
552
- for (let i = 0; i < idx.length; i++) {
553
- if (idx[i] !== i) {
554
- throw new ConfigError(
555
- [{ path, from: "keys", message: `E_SPARSE_ARRAY: indexes [${idx.join(",")}] are not dense 0..${idx.length - 1}` }],
556
- "E_SPARSE_ARRAY"
557
- );
558
- }
559
- }
560
- return idx.map((_, i) => normalized[String(i)]);
561
- }
562
- return normalized;
563
- }
564
- function setPath(root, parts, value) {
565
- let cur = root;
566
- for (let i = 0; i < parts.length - 1; i++) {
567
- const p = parts[i];
568
- const existing = cur[p];
569
- if (existing && typeof existing === "object" && !Array.isArray(existing)) {
570
- cur = existing;
571
- } else {
572
- const n = {};
573
- cur[p] = n;
574
- cur = n;
575
- }
576
- }
577
- cur[parts[parts.length - 1]] = value;
578
- }
579
- function isPlainObject(v) {
580
- if (!v || typeof v !== "object") return false;
581
- const proto = Object.getPrototypeOf(v);
582
- return proto === Object.prototype || proto === null;
583
- }
584
- function deepMerge(base, override, arrayStrategy = "replace") {
585
- if (override === void 0) return base;
586
- if (base === void 0) return override;
587
- if (override === null) return null;
588
- if (Array.isArray(base) && Array.isArray(override)) {
589
- if (arrayStrategy === "replace") return override;
590
- if (arrayStrategy === "concat") return [...base, ...override];
591
- const len = Math.max(base.length, override.length);
592
- if (len > 1024) throw new ConfigError([{ path: "<array>", from: "merge", message: "E_ARRAY_CAP: >1024" }], "E_ARRAY_CAP");
593
- const out = [];
594
- for (let i = 0; i < len; i++) {
595
- if (i in override) {
596
- out[i] = i in base ? deepMerge(base[i], override[i], arrayStrategy) : override[i];
597
- } else if (i in base) {
598
- out[i] = base[i];
599
- }
600
- }
601
- for (let i = 0; i < len; i++) {
602
- if (!(i in out)) {
603
- throw new ConfigError(
604
- [{ path: `<array>[${i}]`, from: "merge", message: "E_SPARSE_ARRAY: hole at index " + i }],
605
- "E_SPARSE_ARRAY"
606
- );
607
- }
608
- }
609
- return out;
610
- }
611
- if (isPlainObject(base) && isPlainObject(override)) {
612
- const out = { ...base };
613
- for (const [k, v] of Object.entries(override)) {
614
- if (FORBIDDEN.has(k)) throw new ConfigError([{ path: k, from: "merge", message: "E_PROTO" }], "E_PROTO");
615
- out[k] = k in out ? deepMerge(out[k], v, arrayStrategy) : v;
616
- }
617
- return out;
618
- }
619
- return override;
620
- }
621
- var FORBIDDEN, INDEX_RE;
622
- var init_merge = __esm({
623
- "src/merge.ts"() {
624
- init_errors();
625
- FORBIDDEN = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
626
- INDEX_RE = /^(0|[1-9][0-9]*)$/;
627
- }
628
- });
629
-
630
- // src/adapter.ts
631
- function normalizePath(path) {
632
- if (!path || path.length === 0) return "<root>";
633
- const parts = [];
634
- for (const seg of path) {
635
- if (seg !== null && typeof seg === "object" && "key" in seg) {
636
- parts.push(String(seg.key));
637
- } else {
638
- parts.push(String(seg));
639
- }
640
- }
641
- return parts.join(".");
642
- }
643
- function validateStandard(schema, input) {
644
- let r;
645
- try {
646
- r = schema["~standard"].validate(input);
647
- } catch (e) {
648
- const msg = e instanceof Error ? e.message : String(e);
649
- return { issues: [{ path: "<root>", message: msg }], async: false };
650
- }
651
- if (typeof r?.then === "function") {
652
- const p = r.then(
653
- (resolved) => normalizeResult(resolved),
654
- (e) => ({ ok: false, issues: [{ path: "<root>", message: e instanceof Error ? e.message : String(e) }] })
655
- );
656
- return { promise: p };
657
- }
658
- const n = normalizeResult(r);
659
- if (!n.ok) return { issues: n.issues, async: false };
660
- return { value: n.value };
661
- }
662
- function normalizeResult(r) {
663
- if (!r.issues || r.issues.length === 0) {
664
- return { ok: true, value: r.value };
665
- }
666
- return {
667
- ok: false,
668
- issues: r.issues.map((i) => ({ path: normalizePath(i.path), message: i.message }))
669
- };
670
- }
671
- var init_adapter = __esm({
672
- "src/adapter.ts"() {
673
- }
674
- });
675
-
676
- // src/index.ts
677
- var index_exports = {};
678
- __export(index_exports, {
679
- ConfigError: () => ConfigError,
680
- pickPublic: () => pickPublic,
681
- settings: () => settings,
682
- settingsAsync: () => settingsAsync,
683
- viteSettings: () => viteSettings,
684
- withOverrides: () => withOverrides
685
- });
686
- function getEnvSnapshot(injected) {
687
- if (injected) return injected;
688
- const g = globalThis;
689
- if (g.process?.env) return { ...g.process.env };
690
- return {};
691
- }
692
- function isSecretKey(key) {
693
- return /key|secret|token|password|private/i.test(key);
694
- }
695
- function withOverrides(map, fn) {
696
- const g = globalThis;
697
- const prev = g.process?.env ? { ...g.process.env } : void 0;
698
- const restore = () => {
699
- if (g.process?.env && prev) {
700
- for (const k of Object.keys(g.process.env)) delete g.process.env[k];
701
- Object.assign(g.process.env, prev);
702
- }
703
- };
704
- if (g.process?.env) {
705
- for (const [k, v] of Object.entries(map)) {
706
- if (v === void 0) delete g.process.env[k];
707
- else g.process.env[k] = v;
708
- }
709
- }
710
- let out;
711
- try {
712
- out = fn();
713
- } catch (e) {
714
- restore();
715
- throw e;
716
- }
717
- if (isThenable(out)) return out.finally(restore);
718
- restore();
719
- return out;
720
- }
721
- function pickPublic(cfg, keys) {
722
- const out = {};
723
- for (const k of keys) if (k in cfg) out[k] = cfg[k];
724
- return out;
725
- }
726
- function viteSettings(opts, metaEnv) {
727
- return settings({ ...opts, sources: [{ map: metaEnv }], env: {} });
728
- }
729
- function readFileSyncSafe(path, maxBytes = 2 * 1024 * 1024) {
730
- const getFs = () => {
731
- const injected = globalThis.__typedSettingsFs;
732
- if (injected) return injected;
733
- const g = globalThis;
734
- if (g.process) {
735
- const fn = new Function('return typeof require !== "undefined" ? require("node:fs") : null')();
736
- if (!fn) {
737
- throw new ConfigError(
738
- [{ path, from: path, message: "E_NO_FS: file sources need `typed-settings/node` under ESM (or pass { text }/{ map })" }],
739
- "E_NO_FS"
740
- );
741
- }
742
- return fn;
743
- }
744
- return null;
745
- };
746
- try {
747
- const fs = getFs();
748
- if (!fs) return void 0;
749
- const text = fs.readFileSync(path, "utf8");
750
- if (byteLengthUtf8(text) > maxBytes) {
751
- throw new ConfigError(
752
- [{ path, from: path, message: `E_FILE_TOO_LARGE: >${maxBytes} bytes` }],
753
- "E_FILE_TOO_LARGE"
754
- );
755
- }
756
- return text;
757
- } catch (e) {
758
- if (e instanceof ConfigError) throw e;
759
- const err = e;
760
- if (err?.code === "ENOENT") return void 0;
761
- throw e;
762
- }
763
- }
764
- function parseStructuredFile(path, text) {
765
- const lower = path.toLowerCase();
766
- try {
767
- if (lower.endsWith(".json")) return parseJsonText(text, path);
768
- if (lower.endsWith(".yaml") || lower.endsWith(".yml")) return parseYamlText(text, path);
769
- return parseTomlText(text, path);
770
- } catch (e) {
771
- const err = e;
772
- throw new ConfigError([{ path, from: path, message: err.message }], "E_PARSE");
773
- }
774
- }
775
- function stripFlatKey(key, effPrefix) {
776
- if (!effPrefix) return key;
777
- if (key.length <= effPrefix.length) return null;
778
- if (key.slice(0, effPrefix.length).toLowerCase() !== effPrefix.toLowerCase()) return null;
779
- return key.slice(effPrefix.length);
780
- }
781
- function assertAcyclic(value, label) {
782
- const visiting = /* @__PURE__ */ new Set();
783
- const visit = (v, path) => {
784
- if (!v || typeof v !== "object") return;
785
- if (visiting.has(v)) {
786
- throw new ConfigError(
787
- [{ path, from: label, message: `E_CYCLE: cyclic value at ${path} (from ${label})` }],
788
- "E_CYCLE"
789
- );
790
- }
791
- visiting.add(v);
792
- try {
793
- for (const [k, child] of Object.entries(v)) visit(child, path ? `${path}.${k}` : k);
794
- } finally {
795
- visiting.delete(v);
796
- }
797
- };
798
- visit(value, "");
799
- }
800
- function flatToLayer(m, label, srcPrefix, globalPrefix, opts, skipExpand) {
801
- assertAcyclic(m, label);
802
- const effPrefix = srcPrefix ?? globalPrefix;
803
- const stripped = {};
804
- for (const [k, v] of Object.entries(m)) {
805
- const s = stripFlatKey(k, effPrefix);
806
- if (s === null) continue;
807
- stripped[s] = v;
808
- }
809
- const node = normalizeIndexedObjects(
810
- expandKeys(stripped, { envMap: opts.envMap })
811
- );
812
- return { node, label, skipExpand };
813
- }
814
- function structuredToLayer(value, label, prefix) {
815
- assertAcyclic(value, label);
816
- if (!isPlainObject(value)) return { node: value ?? {}, label, skipExpand: false };
817
- const out = {};
818
- for (const [k, v] of Object.entries(value)) {
819
- if (["__proto__", "constructor", "prototype"].includes(k)) {
820
- throw new ConfigError([{ path: k, from: label, message: "E_PROTO: forbidden key" }], "E_PROTO");
821
- }
822
- if (prefix) {
823
- const s = stripFlatKey(k, prefix);
824
- if (s === null) continue;
825
- out[s] = v;
826
- } else {
827
- out[k] = v;
828
- }
829
- }
830
- return { node: out, label, skipExpand: false };
831
- }
832
- function recordLayerFrom(fromMap, layer) {
833
- const node = layer.node;
834
- if (node && typeof node === "object" && !Array.isArray(node)) {
835
- for (const k of Object.keys(node)) fromMap.set(k.toLowerCase(), layer.label);
836
- }
837
- }
838
- function isThenable(v) {
839
- return !!v && (typeof v === "object" || typeof v === "function") && typeof v.then === "function";
840
- }
841
- function asProvider(src) {
842
- if (!("provider" in src || "load" in src)) return null;
843
- const prov = "provider" in src ? src.provider : src;
844
- if (!prov || typeof prov.load !== "function") return null;
845
- return { load: prov.load, name: typeof prov.name === "string" ? prov.name : "<provider>" };
846
- }
847
- function timeoutError(name) {
848
- return new ConfigError([{ path: name, from: name, message: "E_TIMEOUT: provider load timed out" }], "E_TIMEOUT");
849
- }
850
- function collectSources(opts, envSnapshot) {
851
- const sources = opts.sources ?? [".env", "env"];
852
- const prefix = opts.prefix;
853
- const layers = [];
854
- const fromMap = /* @__PURE__ */ new Map();
855
- const maxBytes = opts.maxBytes ?? 2 * 1024 * 1024;
856
- const push = (layer) => {
857
- layers.push(layer);
858
- recordLayerFrom(fromMap, layer);
859
- };
860
- const parseEnv = (text, label) => {
861
- try {
862
- return parseEnvText(text);
863
- } catch (e) {
864
- const err = e;
865
- throw new ConfigError([{ path: label, from: label, message: err.message }], "E_PARSE");
866
- }
867
- };
868
- for (const src of sources) {
869
- if (src === "env") {
870
- push(flatToLayer({ ...envSnapshot }, "env", void 0, prefix, opts, false));
871
- } else if (src === ".env" || src === ".env.local") {
872
- const text = readFileSyncSafe(src, maxBytes);
873
- if (text === void 0) continue;
874
- push(flatToLayer(parseEnv(text, src), src, void 0, prefix, opts, false));
875
- } else if (typeof src === "string") {
876
- const text = readFileSyncSafe(src, maxBytes);
877
- if (text === void 0) continue;
878
- const lower = src.toLowerCase();
879
- if (lower.endsWith(".json") || lower.endsWith(".yaml") || lower.endsWith(".yml") || lower.endsWith(".toml")) {
880
- push(structuredToLayer(parseStructuredFile(src, text), src, prefix));
881
- } else {
882
- push(flatToLayer(parseEnv(text, src), src, void 0, prefix, opts, false));
883
- }
884
- } else if (src && typeof src === "object" && "text" in src) {
885
- push(flatToLayer(parseEnv(src.text, "text"), "text", void 0, prefix, opts, false));
886
- } else if (src && typeof src === "object" && "map" in src) {
887
- const m = src;
888
- push(flatToLayer(m.map ?? {}, "overrides", m.prefix, prefix, opts, false));
889
- } else if (src && typeof src === "object" && "file" in src) {
890
- const p = src.file;
891
- const text = readFileSyncSafe(p, maxBytes);
892
- if (text === void 0) continue;
893
- const lower = p.toLowerCase();
894
- if (lower.endsWith(".json") || lower.endsWith(".yaml") || lower.endsWith(".yml") || lower.endsWith(".toml")) {
895
- push(structuredToLayer(parseStructuredFile(p, text), p, prefix));
896
- } else {
897
- push(flatToLayer(parseEnv(text, p), p, void 0, prefix, opts, false));
898
- }
899
- } else if (src && typeof src === "object" && "dir" in src) {
900
- continue;
901
- } else if (src && typeof src === "object") {
902
- const prov = asProvider(src);
903
- if (prov) {
904
- const srcPrefix = "prefix" in src ? src.prefix : void 0;
905
- const loaded = prov.load();
906
- if (isThenable(loaded)) {
907
- throw new ConfigError(
908
- [{ path: "<provider>", from: prov.name, message: "USE_ASYNC: provider is async, use settingsAsync()" }],
909
- "USE_ASYNC"
910
- );
911
- }
912
- push(flatToLayer(loaded ?? {}, prov.name, srcPrefix, prefix, opts, !opts.expandSecrets));
913
- } else {
914
- push(flatToLayer(src, "overrides", void 0, prefix, opts, false));
915
- }
916
- }
917
- }
918
- return { layers, fromMap };
919
- }
920
- async function collectSourcesAsync(opts, envSnapshot) {
921
- const timeoutMs = opts.timeoutMs ?? 5e3;
922
- const needsAsync = (opts.sources ?? []).some((s) => s && typeof s === "object" && asProvider(s) !== null);
923
- if (!needsAsync) return collectSources(opts, envSnapshot);
924
- const sources = opts.sources;
925
- const prefix = opts.prefix;
926
- const layers = [];
927
- const fromMap = /* @__PURE__ */ new Map();
928
- const maxBytes = opts.maxBytes ?? 2 * 1024 * 1024;
929
- const push = (layer) => {
930
- layers.push(layer);
931
- recordLayerFrom(fromMap, layer);
932
- };
933
- const parseEnv = (text, label) => {
934
- try {
935
- return parseEnvText(text);
936
- } catch (e) {
937
- const err = e;
938
- throw new ConfigError([{ path: label, from: label, message: err.message }], "E_PARSE");
939
- }
940
- };
941
- const withTimeout = async (name, fn) => {
942
- let t;
943
- const timeout = new Promise((_, rej) => {
944
- t = setTimeout(() => rej(timeoutError(name)), timeoutMs);
945
- });
946
- const winner = await Promise.race([Promise.resolve().then(fn), timeout]).catch((e) => {
947
- clearTimeout(t);
948
- if (e instanceof ConfigError) throw e;
949
- const err = e;
950
- throw new ConfigError(
951
- [{ path: name, from: name, message: `E_PROVIDER: ${err?.message ?? String(e)}` }],
952
- "E_PROVIDER"
953
- );
954
- });
955
- clearTimeout(t);
956
- return winner;
957
- };
958
- for (const src of sources) {
959
- if (src === "env") {
960
- push(flatToLayer({ ...envSnapshot }, "env", void 0, prefix, opts, false));
961
- } else if (src === ".env" || src === ".env.local") {
962
- const text = readFileSyncSafe(src, maxBytes);
963
- if (text === void 0) continue;
964
- push(flatToLayer(parseEnv(text, src), src, void 0, prefix, opts, false));
965
- } else if (typeof src === "string") {
966
- const text = readFileSyncSafe(src, maxBytes);
967
- if (text === void 0) continue;
968
- const lower = src.toLowerCase();
969
- if (lower.endsWith(".json") || lower.endsWith(".yaml") || lower.endsWith(".yml") || lower.endsWith(".toml")) {
970
- push(structuredToLayer(parseStructuredFile(src, text), src, prefix));
971
- } else {
972
- push(flatToLayer(parseEnv(text, src), src, void 0, prefix, opts, false));
973
- }
974
- } else if (src && typeof src === "object" && "text" in src) {
975
- push(flatToLayer(parseEnv(src.text, "text"), "text", void 0, prefix, opts, false));
976
- } else if (src && typeof src === "object" && "map" in src) {
977
- const m = src;
978
- push(flatToLayer(m.map ?? {}, "overrides", m.prefix, prefix, opts, false));
979
- } else if (src && typeof src === "object" && "file" in src) {
980
- const p = src.file;
981
- const text = readFileSyncSafe(p, maxBytes);
982
- if (text === void 0) continue;
983
- const lower = p.toLowerCase();
984
- if (lower.endsWith(".json") || lower.endsWith(".yaml") || lower.endsWith(".yml") || lower.endsWith(".toml")) {
985
- push(structuredToLayer(parseStructuredFile(p, text), p, prefix));
986
- } else {
987
- push(flatToLayer(parseEnv(text, p), p, void 0, prefix, opts, false));
988
- }
989
- } else if (src && typeof src === "object" && "dir" in src) {
990
- continue;
991
- } else if (src && typeof src === "object") {
992
- const prov = asProvider(src);
993
- if (prov) {
994
- const srcPrefix = "prefix" in src ? src.prefix : void 0;
995
- const loaded = await withTimeout(prov.name, () => prov.load());
996
- push(flatToLayer(loaded ?? {}, prov.name, srcPrefix, prefix, opts, !opts.expandSecrets));
997
- } else {
998
- push(flatToLayer(src, "overrides", void 0, prefix, opts, false));
999
- }
1000
- }
1001
- }
1002
- return { layers, fromMap };
1003
- }
1004
- function buildConfigObject(opts, envSnapshot) {
1005
- const { layers, fromMap } = collectSources(opts, envSnapshot);
1006
- const arrayStrategy = opts.arrayStrategy ?? "replace";
1007
- let merged = {};
1008
- for (const layer of layers) {
1009
- merged = deepMerge(merged, layer.node, arrayStrategy);
1010
- }
1011
- const skipTops = new Set(
1012
- layers.filter((l) => l.skipExpand).flatMap((l) => Object.keys(l.node)).map((k) => k.toLowerCase())
1013
- );
1014
- if (opts.expand !== false) {
1015
- merged = expandDeepStrings(merged, makeLookup(merged, envSnapshot), {
1016
- allowUnresolved: opts.allowUnresolved,
1017
- fromMap,
1018
- skipTops
1019
- });
1020
- }
1021
- if (opts.coerce !== false) {
1022
- merged = coerceDeep(merged);
1023
- }
1024
- const fromFor = (path) => {
1025
- const top = path.split(".")[0].toLowerCase();
1026
- if (top === "<root>") return "schema";
1027
- return fromMap.get(top) ?? "defaults";
1028
- };
1029
- return { input: merged, fromFor };
1030
- }
1031
- function makeLookup(merged, envSnapshot) {
1032
- const rec = merged && typeof merged === "object" && !Array.isArray(merged) ? merged : {};
1033
- const ciKeys = new Map(Object.keys(rec).map((k) => [k.toLowerCase(), k]));
1034
- return (name) => {
1035
- const hit = ciKeys.get(name.toLowerCase());
1036
- if (hit !== void 0) {
1037
- const direct = rec[hit];
1038
- if (typeof direct === "string") return direct;
1039
- if (direct !== void 0 && direct !== null) return String(direct);
1040
- }
1041
- return envSnapshot[name] ?? envSnapshot[name.toUpperCase()] ?? envSnapshot[name.toLowerCase()];
1042
- };
1043
- }
1044
- function expandDeepStrings(obj, lookup, ctx, path = []) {
1045
- if (typeof obj === "string") {
1046
- const top = (path[0] ?? "<root>").toLowerCase();
1047
- return expandLeaf(obj, lookup, { ...ctx, from: ctx.fromMap.get(top) ?? "config" }, path.map((p) => p.toLowerCase()));
1048
- }
1049
- if (Array.isArray(obj)) return obj.map((x, i) => expandDeepStrings(x, lookup, ctx, [...path, String(i)]));
1050
- if (obj && typeof obj === "object") {
1051
- if (path.length === 0) {
1052
- const o2 = {};
1053
- for (const [k, v] of Object.entries(obj)) {
1054
- o2[k] = ctx.skipTops.has(k.toLowerCase()) ? v : expandDeepStrings(v, lookup, ctx, [k]);
1055
- }
1056
- return o2;
1057
- }
1058
- const o = {};
1059
- for (const [k, v] of Object.entries(obj)) o[k] = expandDeepStrings(v, lookup, ctx, [...path, k]);
1060
- return o;
1061
- }
1062
- return obj;
1063
- }
1064
- function expandLeaf(value, lookup, ctx, stack) {
1065
- return expandValue(
1066
- value,
1067
- (name) => {
1068
- const lower = name.toLowerCase();
1069
- if (stack.includes(lower)) {
1070
- throw new ConfigError(
1071
- [{ path: name, from: ctx.from, message: `E_CIRCULAR: $${[...stack, name].join("->$")}` }],
1072
- "E_CIRCULAR"
1073
- );
1074
- }
1075
- const raw = lookup(name);
1076
- if (raw === void 0) return void 0;
1077
- if (raw.includes("$")) return expandLeaf(raw, lookup, ctx, [...stack, lower]);
1078
- return raw;
1079
- },
1080
- { allowUnresolved: ctx.allowUnresolved, from: ctx.from }
1081
- );
1082
- }
1083
- function collectLeafPaths(v, prefix = "") {
1084
- if (Array.isArray(v)) {
1085
- const out = [];
1086
- v.forEach((x, i) => out.push(...collectLeafPaths(x, prefix ? `${prefix}.${i}` : `${i}`)));
1087
- return out;
1088
- }
1089
- if (isPlainObject(v)) {
1090
- const out = [];
1091
- for (const [k, val] of Object.entries(v)) {
1092
- const p = prefix ? `${prefix}.${k.toLowerCase()}` : k.toLowerCase();
1093
- if (isPlainObject(val) || Array.isArray(val)) out.push(...collectLeafPaths(val, p));
1094
- else out.push(p);
1095
- }
1096
- return out;
1097
- }
1098
- return prefix ? [prefix.toLowerCase()] : [];
1099
- }
1100
- function applyUnknownKeys(input, value, mode) {
1101
- if (mode === "strip" || mode === void 0) return value;
1102
- if (mode === "preserve") {
1103
- if (isPlainObject(input) && isPlainObject(value)) return deepMerge(input, value, "replace");
1104
- return value;
1105
- }
1106
- const inputPaths = new Set(collectLeafPaths(input));
1107
- const valuePaths = new Set(collectLeafPaths(value));
1108
- const unknown = [...inputPaths].filter((p) => !valuePaths.has(p));
1109
- if (unknown.length > 0) {
1110
- throw new ConfigError(
1111
- unknown.map((p) => ({ path: p, from: "schema", message: "E_UNKNOWN_KEY: unknown key (unknownKeys=reject)" })),
1112
- "E_UNKNOWN_KEY"
1113
- );
1114
- }
1115
- return value;
1116
- }
1117
- function freezeDeep(v) {
1118
- if (Array.isArray(v)) {
1119
- for (const x of v) freezeDeep(x);
1120
- return Object.freeze(v);
1121
- }
1122
- if (v && typeof v === "object") {
1123
- for (const k of Object.keys(v)) freezeDeep(v[k]);
1124
- return Object.freeze(v);
1125
- }
1126
- return v;
1127
- }
1128
- function settings(opts) {
1129
- const envSnapshot = getEnvSnapshot(opts.env);
1130
- const { input, fromFor } = buildConfigObject(opts, envSnapshot);
1131
- const r = validateStandard(opts.schema, input);
1132
- if ("promise" in r) {
1133
- throw new ConfigError(
1134
- [{ path: "<root>", from: "schema", message: "USE_ASYNC: schema is async, use settingsAsync()" }],
1135
- "USE_ASYNC"
1136
- );
1137
- }
1138
- if ("issues" in r) {
1139
- throw new ConfigError(
1140
- r.issues.map((i) => ({ path: i.path, from: fromFor(i.path), message: maskIfSecret(i.path, i.message, input) }))
1141
- );
1142
- }
1143
- const value = r.value;
1144
- const final = applyUnknownKeys(input, value, opts.unknownKeys ?? "strip");
1145
- return opts.freeze === false ? final : freezeDeep(final);
1146
- }
1147
- async function settingsAsync(opts) {
1148
- const timeoutMs = opts.timeoutMs ?? 5e3;
1149
- const envSnapshot = getEnvSnapshot(opts.env);
1150
- const { input, fromFor } = await buildConfigObjectAsync(opts, envSnapshot);
1151
- const r = validateStandard(opts.schema, input);
1152
- if ("promise" in r) {
1153
- const raced = await Promise.race([
1154
- r.promise,
1155
- new Promise((_, rej) => setTimeout(() => rej(new ConfigError([{ path: "<root>", from: "schema", message: "E_TIMEOUT" }], "E_TIMEOUT")), timeoutMs))
1156
- ]);
1157
- if (!raced.ok) {
1158
- throw new ConfigError(raced.issues.map((i) => ({ path: i.path, from: fromFor(i.path), message: maskIfSecret(i.path, i.message, input) })));
1159
- }
1160
- const value2 = raced.value;
1161
- const final2 = applyUnknownKeys(input, value2, opts.unknownKeys ?? "strip");
1162
- return opts.freeze === false ? final2 : freezeDeep(final2);
1163
- }
1164
- if ("issues" in r) {
1165
- throw new ConfigError(r.issues.map((i) => ({ path: i.path, from: fromFor(i.path), message: maskIfSecret(i.path, i.message, input) })));
1166
- }
1167
- const value = r.value;
1168
- const final = applyUnknownKeys(input, value, opts.unknownKeys ?? "strip");
1169
- return opts.freeze === false ? final : freezeDeep(final);
1170
- }
1171
- async function buildConfigObjectAsync(opts, envSnapshot) {
1172
- const { layers, fromMap } = await collectSourcesAsync(opts, envSnapshot);
1173
- const arrayStrategy = opts.arrayStrategy ?? "replace";
1174
- let merged = {};
1175
- for (const layer of layers) {
1176
- merged = deepMerge(merged, layer.node, arrayStrategy);
1177
- }
1178
- const skipTops = new Set(
1179
- layers.filter((l) => l.skipExpand).flatMap((l) => Object.keys(l.node)).map((k) => k.toLowerCase())
1180
- );
1181
- if (opts.expand !== false) {
1182
- merged = expandDeepStrings(merged, makeLookup(merged, envSnapshot), {
1183
- allowUnresolved: opts.allowUnresolved,
1184
- fromMap,
1185
- skipTops
1186
- });
1187
- }
1188
- if (opts.coerce !== false) merged = coerceDeep(merged);
1189
- const fromFor = (path) => {
1190
- const top = path.split(".")[0].toLowerCase();
1191
- if (top === "<root>") return "schema";
1192
- return fromMap.get(top) ?? "defaults";
1193
- };
1194
- return { input: merged, fromFor };
1195
- }
1196
- function getLeafByPath(input, path) {
1197
- const parts = path.split(".");
1198
- let cur = input;
1199
- for (const part of parts) {
1200
- if (cur === null || typeof cur !== "object") return void 0;
1201
- if (Array.isArray(cur)) {
1202
- const m = /\[(\d+)\]/.exec(part);
1203
- const idx = m ? Number(m[1]) : Number(part);
1204
- if (!Number.isInteger(idx)) return void 0;
1205
- cur = cur[idx];
1206
- continue;
1207
- }
1208
- const rec = cur;
1209
- const found = Object.keys(rec).find((k) => k.toLowerCase() === part.toLowerCase());
1210
- if (!found) return void 0;
1211
- cur = rec[found];
1212
- }
1213
- return cur;
1214
- }
1215
- function base64Of(s) {
1216
- try {
1217
- const g = globalThis;
1218
- if (g.btoa) return g.btoa(s);
1219
- if (g.Buffer) return g.Buffer.from(s, "utf8").toString("base64");
1220
- } catch {
1221
- }
1222
- return null;
1223
- }
1224
- function maskIfSecret(path, message, input) {
1225
- if (!isSecretKey(path)) return message;
1226
- let out = message;
1227
- const leaf = getLeafByPath(input, path);
1228
- if (typeof leaf === "string" && leaf.length > 0) {
1229
- const redacted = redactValue(path, leaf);
1230
- out = out.split(leaf).join(redacted);
1231
- const b64 = base64Of(leaf);
1232
- if (b64 && b64.length > 8) out = out.split(b64).join(redacted);
1233
- }
1234
- return `${out} (redacted)`;
1235
- }
1236
- var init_index = __esm({
1237
- "src/index.ts"() {
1238
- init_errors();
1239
- init_env();
1240
- init_json();
1241
- init_yaml();
1242
- init_toml();
1243
- init_expand();
1244
- init_coerce();
1245
- init_merge();
1246
- init_adapter();
1247
- init_errors();
1248
- }
1249
- });
1250
-
1251
- // src/cli/check.ts
1252
- init_index();
1253
- async function loadSchema(schemaPath, exportName) {
1254
- const abs = path.resolve(schemaPath);
1255
- let mod;
1256
- try {
1257
- const { createJiti } = await import('jiti');
1258
- const jiti = createJiti((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('main.cjs', document.baseURI).href)), { interopDefault: false, fsCache: false, moduleCache: false });
1259
- mod = await jiti.import(abs);
1260
- } catch (e) {
1261
- const err2 = e;
1262
- const wrapped = new Error(`SCHEMA_LOAD_ERROR: ${abs}: ${err2.message}`);
1263
- wrapped.code = "SCHEMA_LOAD_ERROR";
1264
- throw wrapped;
1265
- }
1266
- const pick = (name) => mod[name];
1267
- const isStandard = (v) => {
1268
- if (!v) return false;
1269
- if (typeof v !== "object" && typeof v !== "function") return false;
1270
- return "~standard" in v;
1271
- };
1272
- if (exportName) {
1273
- const picked = pick(exportName);
1274
- if (!isStandard(picked)) {
1275
- const err2 = new Error(
1276
- `SCHEMA_LOAD_ERROR: --schema-export ${JSON.stringify(exportName)} did not resolve to a Standard Schema in ${abs}`
1277
- );
1278
- err2.code = "SCHEMA_LOAD_ERROR";
1279
- throw err2;
1280
- }
1281
- return picked;
1282
- }
1283
- for (const cand of ["schema", "settingsSchema", "default"]) {
1284
- if (isStandard(pick(cand))) return pick(cand);
1285
- }
1286
- const first = Object.values(mod).find((v) => isStandard(v));
1287
- if (first) return first;
1288
- const err = new Error(`SCHEMA_LOAD_ERROR: no Standard Schema export in ${abs} (tried default/schema/settingsSchema)`);
1289
- err.code = "SCHEMA_LOAD_ERROR";
1290
- throw err;
1291
- }
1292
-
1293
- // src/cli/check.ts
1294
- async function runCheck(args) {
1295
- let schema;
1296
- try {
1297
- schema = await loadSchema(args.schema, args.schemaExport);
1298
- } catch (e) {
1299
- const err = e;
1300
- if (args.format === "json") console.log(JSON.stringify({ ok: false, error: err.message }));
1301
- else console.error(err.message);
1302
- return 2;
1303
- }
1304
- const sources = (args.config ?? ".env,env").split(",").map((s) => s.trim()).filter(Boolean);
1305
- try {
1306
- const cfg = settings({
1307
- schema,
1308
- sources: sources.length ? sources : [".env", "env"],
1309
- strict: void 0,
1310
- unknownKeys: args.strict ? "reject" : "strip",
1311
- expand: args.expand ?? true,
1312
- arrayStrategy: args.array ?? "replace",
1313
- prefix: args.prefix
1314
- });
1315
- if (args.format === "json") console.log(JSON.stringify({ ok: true, config: cfg }));
1316
- else console.log("OK: config valid");
1317
- return 0;
1318
- } catch (e) {
1319
- if (e instanceof ConfigError) {
1320
- if (args.format === "json") console.log(JSON.stringify({ ok: false, issues: e.issues }));
1321
- else {
1322
- console.error(e.message);
1323
- }
1324
- return 1;
1325
- }
1326
- const err = e;
1327
- if (args.format === "json") console.log(JSON.stringify({ ok: false, error: err.message }));
1328
- else console.error(`E_LOAD: ${err.message}`);
1329
- return 2;
1330
- }
1331
- }
1332
- var SETTINGS_TPL = {
1333
- zod: `import { z } from 'zod';
2
+ 'use strict';var yaml=require('yaml'),smolToml=require('smol-toml'),path=require('path'),util=require('util'),fs=require('fs'),child_process=require('child_process');var _documentCurrentScript=typeof document!=='undefined'?document.currentScript:null;var nn=Object.defineProperty;var v=(e,n)=>()=>(e&&(n=e(e=0)),n);var tn=(e,n)=>{for(var t in n)nn(e,t,{get:n[t],enumerable:true});};function T(e,n){if(rn.test(e))return true;if(n){for(let t of n)if(typeof t=="string"){if(t&&e.toLowerCase().includes(t.toLowerCase()))return true}else if(t instanceof RegExp){if(t.lastIndex=0,t.test(e))return true}else if(t!==null&&typeof t=="object"&&typeof t.test=="function"&&t.test(e))return true}return false}function I(e,n,t){return T(e,t)&&typeof n=="string"&&n.length>0?n.length<=8?"(redacted)":`(redacted: ${n.length} chars)`:String(n)}function Y(e){try{let n=globalThis;if(n.TextEncoder)return new n.TextEncoder().encode(e).length;if(n.Buffer)return n.Buffer.byteLength(e,"utf8")}catch{}return e.length}var rn,d,j=v(()=>{rn=/key|secret|token|password|private/i;d=class extends Error{code="E_INVALID_CONFIG";issues;static[Symbol.hasInstance](n){return typeof n=="object"&&n!==null&&n.name==="ConfigError"&&typeof n.code=="string"&&Array.isArray(n.issues)}constructor(n=[],t="E_INVALID_CONFIG"){let r=n.map(o=>`- ${o.path} (from ${o.from}): ${o.message}`);super(n.length===0?"Invalid config: unknown error (no issues attached)":`Invalid config (${n.length} issue${n.length===1?"":"s"}):
3
+ ${r.join(`
4
+ `)}`),this.name="ConfigError",this.code=t,this.issues=n;}};});function Z(e){let n={};e.charCodeAt(0)===65279&&(e=e.slice(1));let t=an(e);for(let r of t){let o=r.trim();if(!o||o.startsWith("#"))continue;o.startsWith("export ")&&(o=o.slice(7).trimStart());let s=o.indexOf("=");if(s===-1)throw new Error(`ParseError: bare key without '=': ${JSON.stringify(o)}`);let i=o.slice(0,s).trim(),c=o.slice(s+1).trimStart();if(!i)throw new Error("ParseError: empty key");let{value:f,quoted:a}=fn(c,o);n[i]=a&&!on(f)?sn(f):f;}return n}function on(e){let n=e.trim();return n.startsWith("{")&&n.endsWith("}")||n.startsWith("[")&&n.endsWith("]")}function sn(e){let n="";for(let t=0;t<e.length;t++){let r=e[t];if(r==="\\"&&t+1<e.length){n+=r+e[t+1],t++;continue}if(r===","){n+="\\,";continue}n+=r;}return n}function an(e){let n=e.split(/\r?\n/),t=[],r="",o=false;for(let s of n)o?(r+=`
5
+ `+s,he(r.split("=").slice(1).join("="))%2===0&&(o=false,t.push(r),r="")):he(s)%2===1&&cn(s)?(r=s,o=true):t.push(s);if(o)throw new Error("ParseError: unterminated double-quoted value");return t}function cn(e){let n=e.indexOf("=");if(n===-1)return false;let t=e.slice(n+1).trimStart();return t.startsWith('"')&&!t.endsWith('"')}function he(e){let n=0;for(let t=0;t<e.length;t++)e[t]==='"'&&e[t-1]!=="\\"&&n++;return n}function fn(e,n){if(!e)return {value:"",quoted:false};if(e.startsWith("'")){let o=e.indexOf("'",1);if(o===-1)throw new Error("ParseError: unterminated single-quoted value");return ye(e.slice(o+1),n),{value:e.slice(1,o),quoted:true}}if(e.startsWith('"')){let o=1,s="";for(;o<e.length;){let i=e[o];if(i==="\\"&&o+1<e.length){let c=e[o+1];c==="n"?s+=`
6
+ `:c==="r"?s+="\r":c==="t"?s+=" ":s+=c,o+=2;continue}if(i==='"')break;s+=i,o++;}if(e[o]!=='"')throw new Error("ParseError: unterminated double-quoted value");return ye(e.slice(o+1),n),{value:s,quoted:true}}if(e.startsWith("`"))throw new Error("ParseError: backtick values not supported");let t=un(e);return {value:(t===-1?e:e.slice(0,t)).trim(),quoted:false}}function ye(e,n){if(!/^\s*(#.*)?$/.test(e))throw new Error(`ParseError: trailing characters after quoted value: ${JSON.stringify(n)}`)}function un(e){for(let n=0;n<e.length;n++)if(e[n]==="#"&&(n===0||/\s/.test(e[n-1])))return n;return -1}var H=v(()=>{});function we(e,n="json"){let t=e.charCodeAt(0)===65279?e.slice(1):e;if(!t.trim())return {};try{return JSON.parse(t)}catch(r){let o=r;throw new Error(`ParseError (${n}): ${o.message}`)}}var Ee=v(()=>{});function ke(e,n="yaml"){let t=e.charCodeAt(0)===65279?e.slice(1):e;if(!t.trim())return {};let r=yaml.parseAllDocuments(t,{version:"1.2",uniqueKeys:true,maxAliasCount:100}).filter(i=>{if(i.errors.length>0)return true;try{let c=i.toJS();return c!=null}catch{return true}});if(r.length===0)return {};if(r.length>1)throw new Error(`ParseError (${n}): multi-doc YAML not supported (got ${r.length} documents)`);let o=r[0];if(o.errors.length>0){let i=o.errors[0],c=i.linePos?.[0]?.line??"?";throw new Error(`ParseError (${n}:${c}): ${i.message}`)}let s;try{s=o.toJS();}catch(i){throw new Error(`ParseError (${n}): ${i.message}`)}return s}var Se=v(()=>{});function be(e,n="toml"){let t=e.charCodeAt(0)===65279?e.slice(1):e;if(!t.trim())return {};try{return smolToml.parse(t)}catch(r){let o=r;throw new Error(`ParseError (${n}): ${o.message}`)}}var xe=v(()=>{});function X(e,n,t,r=0){if(r>_e)throw new d([{path:t?.leafPath??"<expand>",from:t?.from??"config",message:`E_DEPTH: \${} nesting too deep (>${_e})`}],"E_DEPTH");let o="",s=0;for(;s<e.length;){let i=e[s];if(i==="$"&&e[s+1]==="$"){o+="$",s+=2;continue}if(i==="\\"&&e[s+1]==="$"){o+="\\$",s+=2;continue}if(i!=="$"){o+=i,s++;continue}let c=e.slice(s);if(c.startsWith("${")){let l=gn(e,s,t);if(!l){o+="$",s++;continue}let{name:g,op:h,def:x,end:m}=l,S=t?.leafPath??g,w=t?.from??"config";if(h&&h!==":-"&&h!=="-")throw new d([{path:S,from:w,message:`E_BAD_OP: only :- and - supported, got ${h}`}],"E_BAD_OP");let p=n(g);if(!(p===void 0||h===":-"&&p===""))o+=p;else if(x!==void 0)o+=X(x,n,t,r+1);else if(t?.allowUnresolved)o+=e.slice(s,m);else throw new d([{path:S,from:w,message:`E_UNRESOLVED: ${g} missing (expand)`}],"E_UNRESOLVED");s=m;continue}let f=pn.exec(c);if(!f||!f.groups){o+="$",s++;continue}let a=f.groups.name,u=n(a);if(u===void 0)if(t?.allowUnresolved)o+="$"+a;else throw new d([{path:t?.leafPath??a,from:t?.from??"config",message:`E_UNRESOLVED: ${a} missing (expand)`}],"E_UNRESOLVED");else o+=u;s+=1+a.length;}return o}function gn(e,n,t){let r=n+2,o=mn.exec(e.slice(r));if(!o?.groups)return null;let s=o.groups.name;if(r+=s.length,e[r]==="}")return {name:s,end:r+1};if(r>=e.length)throw new d([{path:t?.leafPath??s,from:t?.from??"config",message:"E_EXPAND: unterminated ${}"}],"E_EXPAND");if(e[r]===":"){if(e.slice(r,r+2)!==":-"){let a=e.slice(r).split("}")[0].slice(0,12);return {name:s,op:a,def:"",end:e.length}}r+=2;let{value:c,end:f}=ve(e,r);return {name:s,op:":-",def:c,end:f}}if(e[r]==="-"){r+=1;let{value:i,end:c}=ve(e,r);return {name:s,op:"-",def:i,end:c}}return null}function ve(e,n){let t=0,r=n,o="";for(;r<e.length;){if(e[r]==="\\"&&e[r+1]==="}"){o+="}",r+=2;continue}if(e[r]==="{"&&t++,e[r]==="}"){if(t===0)return {value:o,end:r+1};t--;}o+=e[r],r++;}throw new d([{path:"<expand>",from:"expand",message:"E_EXPAND: unterminated ${}"}],"E_EXPAND")}var Ae,pn,mn,_e,Re=v(()=>{j();Ae="[A-Za-z_][A-Za-z0-9_]*",pn=new RegExp(`^\\$(?<name>${Ae})`),mn=new RegExp(`^(?<name>${Ae})`),_e=50;});function O(e){return e.toLowerCase()==="__proto__"}function hn(e,n){return e;}function Oe(e,n){let t={},r=new Map,o=f=>{let a=r.get(f);return a||(a={indexed:false,named:false},r.set(f,a)),a},s=new Map,i=f=>{if(!n?.envMap)return;let a=f.toLowerCase();for(let[u,l]of Object.entries(n.envMap))if(u.toLowerCase()===a)return l},c=(f,a,u)=>{throw new d([{path:f,from:"keys",message:`E_COLLISION: '${f}' ${u} (already claimed by '${s.get(a)}')`}],"E_COLLISION")};for(let[f,a]of Object.entries(e)){let u=i(f);if(u!==void 0){let m=u.toLowerCase();if(O(m))throw new d([{path:f,from:"keys",message:"E_PROTO: forbidden key"}],"E_PROTO");t[m]=a;continue}if(!/^[A-Za-z0-9_]+$/.test(f)){if(n?.tolerantKeys)continue;throw new d([{path:f,from:"keys",message:`E_BAD_KEY: '${f}' cannot be a config key (allowed: A-Z a-z 0-9 _, nesting with __) \u2014 bridge it with envMap`}],"E_BAD_KEY")}let l=hn(f);if(l===null)continue;let g=l;if(O(g))throw new d([{path:f,from:"keys",message:"E_PROTO: forbidden key"}],"E_PROTO");let h=g.split("__");if(h.length>1&&h.every(m=>m!=="")){let m=h.map(b=>b.toLowerCase()),S=m.join("."),w=m.slice(0,-1).join("."),p=m[0];if(s.get(S)!==void 0&&c(f,S,"duplicates a claimed path"),m.length===2&&s.has(p)&&Q.test(m[1]))throw new d([{path:f,from:"keys",message:`E_ARRAY_MIX: '${p}' has both scalar/list and indexed (__0) values in the same layer`}],"E_ARRAY_MIX");for(let[b]of s)(b.startsWith(`${S}.`)||S.startsWith(`${b}.`))&&c(f,b,"collides with a conflicting value at");let y=o(w);if(Q.test(m[m.length-1])){if(y.named)throw new d([{path:f,from:"keys",message:`E_ARRAY_MIX: '${w}' mixes indexed (__0) and named children in the same layer`}],"E_ARRAY_MIX");y.indexed=true;}else {if(y.indexed)throw new d([{path:f,from:"keys",message:`E_ARRAY_MIX: '${w}' mixes named and indexed (__0) children in the same layer`}],"E_ARRAY_MIX");y.named=true;}s.set(S,f),yn(t,m,a);}else {let m=g.toLowerCase();if(r.get(m)?.indexed)throw new d([{path:f,from:"keys",message:`E_ARRAY_MIX: '${m}' has both indexed (__0) and scalar/list values in the same layer`}],"E_ARRAY_MIX");s.get(m)!==void 0&&c(f,m,"duplicates a claimed path");for(let[w]of s)w.startsWith(`${m}.`)&&c(f,w,"collides with a conflicting value at");s.set(m,f),t[m]=a;}}return t}function C(e,n="<root>"){if(Array.isArray(e))return e.map((o,s)=>C(o,`${n}[${s}]`));if(!k(e))return e;let t=Object.entries(e),r={};for(let[o,s]of t)r[o]=C(s,n==="<root>"?o:`${n}.${o}`);if(t.length>0&&t.every(([o])=>Q.test(o))){let o=t.map(([s])=>Number(s)).sort((s,i)=>s-i);if(o.length>1024)throw new d([{path:n,from:"keys",message:"E_ARRAY_CAP: >1024 elements"}],"E_ARRAY_CAP");for(let s=0;s<o.length;s++)if(o[s]!==s)throw new d([{path:n,from:"keys",message:`E_SPARSE_ARRAY: indexes [${o.join(",")}] are not dense 0..${o[o.length-1]}`}],"E_SPARSE_ARRAY");return o.map((s,i)=>r[String(i)])}return r}function yn(e,n,t){let r=e;for(let o=0;o<n.length-1;o++){let s=n[o],i=r[s];if(i&&typeof i=="object"&&!Array.isArray(i))r=i;else {let c={};r[s]=c,r=c;}}r[n[n.length-1]]=t;}function k(e){if(!e||typeof e!="object")return false;let n=Object.getPrototypeOf(e);return n===Object.prototype||n===null}function te(e,n,t="replace"){return ne(n),ee(e,n,t)}function ee(e,n,t){if(n===void 0)return e;if(e===void 0)return n;if(n===null)return null;if(Array.isArray(e)!==Array.isArray(n)&&(k(e)||k(n))){let r=o=>o!=null&&typeof o=="object"&&(Array.isArray(o)?o.length===0:k(o)&&Object.keys(o).length===0);if(!r(e)&&!r(n))throw new d([{path:"<array>",from:"merge",message:`E_ARRAY_MIX: cannot merge object with array across layers (arrayStrategy '${t}' only merges arrays with arrays) \u2014 use matching shapes`}],"E_ARRAY_MIX")}if(Array.isArray(e)&&Array.isArray(n)){if(t==="replace")return n;if(t==="concat"){if(e.length+n.length>1024)throw new d([{path:"<array>",from:"merge",message:"E_ARRAY_CAP: concat would exceed 1024 elements"}],"E_ARRAY_CAP");return [...e,...n]}let r=Math.max(e.length,n.length);if(r>1024)throw new d([{path:"<array>",from:"merge",message:"E_ARRAY_CAP: >1024"}],"E_ARRAY_CAP");let o=[];for(let s=0;s<r;s++)s in n?o[s]=s in e?ee(e[s],n[s],t):n[s]:s in e&&(o[s]=e[s]);for(let s=0;s<r;s++)if(!(s in o))throw new d([{path:`<array>[${s}]`,from:"merge",message:"E_SPARSE_ARRAY: hole at index "+s}],"E_SPARSE_ARRAY");return o}if(k(e)&&k(n)){let r={...e};for(let[o,s]of Object.entries(n))r[o]=o in r?ee(r[o],s,t):s;return r}return n}function ne(e){if(Array.isArray(e)){for(let n of e)ne(n);return}if(e!==null&&typeof e=="object")for(let[n,t]of Object.entries(e)){if(O(n))throw new d([{path:n,from:"merge",message:"E_PROTO"}],"E_PROTO");ne(t);}}var Q,F=v(()=>{j();Q=/^(0|[1-9][0-9]*)$/;});function kn(e){return je(e,true)}function je(e,n){if(typeof e!="string")return e;let t=e;if(t==="")return "";let r=t.toLowerCase();if(r==="true"||r==="false")return r==="true";if(r==="null")return null;if(wn.test(t)){let s=Number(t);return Number.isSafeInteger(s)?s:t}if(En.test(t)&&t!=="-"&&t!=="."){let s=Number(t);return Number.isFinite(s)?s:t}let o=t.trim();if(o.startsWith("{")&&o.endsWith("}")||o.startsWith("[")&&o.endsWith("]"))try{return JSON.parse(o)}catch{return e}if(n&&t.includes(",")){if(!Sn(t))return t.replace(/\\,/g,",");let s=bn(t);if(s!==null)return s.map(i=>je(i,false))}return e}function Sn(e){let n=null;for(let t=0;t<e.length;t++){let r=e[t];if(n){if(r==="\\"&&t+1<e.length){t++;continue}r===n&&(n=null);continue}if(r==='"'||r==="'"){n=r;continue}if(r==="\\"&&e[t+1]===","){t++;continue}if(r===",")return true}return false}function bn(e){let n=[],t="",r=null;for(let o=0;o<e.length;o++){let s=e[o];if(r){if(s==="\\"&&o+1<e.length){t+=s+e[o+1],o++;continue}if(s===r){r=null,t+=s;continue}t+=s;continue}if(s==='"'||s==="'"){r=s,t+=s;continue}if(s==="\\"&&e[o+1]===","){t+=",",o++;continue}if(s===","){n.push(t.trim()),t="";continue}t+=s;}return r?null:(n.push(t.trim()),n.map(o=>o.length>=2&&o.startsWith("'")&&o.endsWith("'")?o.slice(1,-1).replace(/\\,/g,","):o.length>=2&&o.startsWith('"')&&o.endsWith('"')?o.slice(1,-1):o.replace(/\\,/g,",")))}function M(e){if(typeof e=="string")return kn(e);if(Array.isArray(e))return e.map(M);if(e&&typeof e=="object"){let n=Object.getPrototypeOf(e);if(n!==Object.prototype&&n!==null)return e;let t={};for(let[r,o]of Object.entries(e)){if(O(r))throw new d([{path:r,from:"coerce",message:"E_PROTO: forbidden key"}],"E_PROTO");t[r]=M(o);}return t}return e}var wn,En,$e=v(()=>{j();F();wn=/^-?\d+$/,En=/^-?(\d+\.\d*|\.\d+|\d+)(e[+-]?\d+)?$/i;});function xn(e){if(!e||e.length===0)return "<root>";let n=[];for(let t of e)t!==null&&typeof t=="object"&&"key"in t?n.push(String(t.key)):n.push(String(t));return n.join(".")}function re(e,n){let t;try{t=e["~standard"].validate(n);}catch(o){return {issues:[{path:"<root>",message:o instanceof Error?o.message:String(o)}],async:false}}if(typeof t?.then=="function")return {promise:t.then(s=>Te(s),s=>({ok:false,issues:[{path:"<root>",message:s instanceof Error?s.message:String(s)}]}))};let r=Te(t);return r.ok?{value:r.value}:{issues:r.issues,async:false}}function Te(e){return !e.issues||e.issues.length===0?{ok:true,value:e.value}:{ok:false,issues:e.issues.map(n=>({path:xn(n.path),message:n.message}))}}var oe=v(()=>{});function _n(e){if(e)return {...e};let n=globalThis;return n.process?.env?{...n.process.env}:{}}function se(e,n=2*1024*1024,t){let r=()=>{if(t)return t;let o=globalThis.__typedSettingsFs;if(o)return o;if(globalThis.process){let i;try{i=new Function('return typeof require !== "undefined" ? require("node:fs") : null')();}catch{i=null;}if(!i)throw new d([{path:"<root>",from:e,message:`E_NO_FS: cannot read '${e}' under ESM \u2014 import 'typed-settings/node', pass opts.fs, or use { text }/{ map }`}],"E_NO_FS");return i}return null};try{let o=r();if(!o)return;if(o.statSync)try{if(o.statSync(e).size>n)throw new d([{path:"<root>",from:e,message:`E_FILE_TOO_LARGE: '${e}' >${n} bytes \u2014 raise maxBytes or shrink the file`}],"E_FILE_TOO_LARGE")}catch(i){if(i instanceof d)throw i}let s=o.readFileSync(e,"utf8");if(Y(s)>n)throw new d([{path:"<root>",from:e,message:`E_FILE_TOO_LARGE: '${e}' >${n} bytes \u2014 raise maxBytes or shrink the file`}],"E_FILE_TOO_LARGE");return s}catch(o){if(o instanceof d)throw o;if(o?.code==="ENOENT")return;throw o}}function vn(e){if(e.maxBytes!==void 0&&(!Number.isFinite(e.maxBytes)||e.maxBytes<=0))throw new d([{path:"maxBytes",from:"options",message:"E_USAGE: maxBytes must be a positive finite number"}],"E_USAGE");if(e.timeoutMs!==void 0&&(!Number.isFinite(e.timeoutMs)||e.timeoutMs<=0))throw new d([{path:"timeoutMs",from:"options",message:"E_USAGE: timeoutMs must be a positive finite number"}],"E_USAGE")}function D(e,n){try{return n()}catch(t){throw t instanceof d?t:t instanceof RangeError&&/call stack|recursion|too much/i.test(t.message)?new d([{path:"<root>",from:e,message:"E_DEPTH: nesting too deep (possible hostile input)"}],"E_DEPTH"):t}}function Ce(e,n){let t=e.toLowerCase();try{return t.endsWith(".json")?we(n,e):t.endsWith(".yaml")||t.endsWith(".yml")?ke(n,e):be(n,e)}catch(r){let o=r;throw new d([{path:"<root>",from:e,message:o.message}],"E_PARSE")}}function Ne(e,n){if(!n)return e;if(e.length<=n.length||e.slice(0,n.length).toLowerCase()!==n.toLowerCase())return null;let t=e.slice(n.length);return /[A-Za-z0-9]$/.test(n)&&/^[A-Za-z0-9]/.test(t)?null:t}function Ie(e,n){let t=new Set,r=(o,s)=>{if(!(!o||typeof o!="object")){if(t.has(o))throw new d([{path:s,from:n,message:`E_CIRCULAR: cyclic value at '${s}' \u2014 remove the self-reference (shared DAG refs are fine, true cycles are not)`}],"E_CIRCULAR");t.add(o);try{for(let[i,c]of Object.entries(o))r(c,s?`${s}.${i}`:i);}finally{t.delete(o);}}};r(e,"");}function $(e,n,t,r,o,s,i=false){Ie(e,n);let c=t??r,f={};for(let[u,l]of Object.entries(e)){let g=Ne(u,c);if(g!==null){if(O(g))throw new d([{path:u,from:n,message:"E_PROTO: forbidden key"}],"E_PROTO");f[g]=l;}}return {node:C(Oe(f,{envMap:o.envMap,tolerantKeys:i})),label:n,skipExpand:s}}function Le(e,n,t){if(Ie(e,n),ie(e,n),!k(e))return {node:e??{},label:n,skipExpand:false};let r={};for(let[o,s]of Object.entries(e))if(t){let i=Ne(o,t);if(i===null)continue;if(O(i))throw new d([{path:o,from:n,message:"E_PROTO: forbidden key"}],"E_PROTO");r[i]=s;}else r[o]=s;return {node:C(r,n),label:n,skipExpand:false}}function ie(e,n){if(Array.isArray(e)){for(let t of e)ie(t,n);return}if(e&&typeof e=="object")for(let[t,r]of Object.entries(e)){if(O(t))throw new d([{path:t,from:n,message:"E_PROTO: forbidden key"}],"E_PROTO");ie(r,n);}}function An(e,n){let t=n.node;if(t&&typeof t=="object"&&!Array.isArray(t))for(let r of Object.keys(t))e.set(r.toLowerCase(),n.label);}function Rn(e){return !!e&&(typeof e=="object"||typeof e=="function")&&typeof e.then=="function"}function On(e){if(!("provider"in e||"load"in e))return null;let n="provider"in e?e.provider:e;return !n||typeof n.load!="function"?null:{load:n.load,name:typeof n.name=="string"?n.name:"<provider>"}}function jn(e,n){let t=e.sources??[".env","env"],r=e.prefix,o=[],s=new Map,i=e.maxBytes??2*1024*1024,c=a=>{o.push(a),An(s,a);},f=(a,u)=>{try{return Z(a)}catch(l){let g=l;throw new d([{path:"<root>",from:u,message:g.message}],"E_PARSE")}};for(let a of t)if(a==="env")c($({...n},"env",void 0,r,e,false,true));else if(a===".env"||a===".env.local"){let u=se(a,i,e.fs);if(u===void 0)continue;c($(f(u,a),a,void 0,r,e,false));}else if(typeof a=="string"){let u=se(a,i,e.fs);if(u===void 0)continue;let l=a.toLowerCase();l.endsWith(".json")||l.endsWith(".yaml")||l.endsWith(".yml")||l.endsWith(".toml")?c(Le(Ce(a,u),a,r)):c($(f(u,a),a,void 0,r,e,false));}else if(a&&typeof a=="object"&&"text"in a)c($(f(a.text,"text"),"text",void 0,r,e,false));else if(a&&typeof a=="object"&&"map"in a){let u=a;c($(u.map??{},"overrides",u.prefix,r,e,false));}else if(a&&typeof a=="object"&&"file"in a){let u=a.file,l=se(u,i,e.fs);if(l===void 0)continue;let g=u.toLowerCase();g.endsWith(".json")||g.endsWith(".yaml")||g.endsWith(".yml")||g.endsWith(".toml")?c(Le(Ce(u,l),u,r)):c($(f(l,u),u,void 0,r,e,false));}else {if(a&&typeof a=="object"&&"dir"in a)throw new d([{path:a.dir,from:"config",message:"E_USAGE: { dir } sources need loadSecretsDir() from typed-settings/node, passed back as { map }"}],"E_USAGE");if(a&&typeof a=="object"){let u=On(a);if(u){let l="prefix"in a?a.prefix:void 0,g;try{g=u.load();}catch(h){if(h instanceof d)throw h;let x=h;throw new d([{path:u.name,from:u.name,message:`E_PROVIDER: ${x?.message??String(h)}`}],"E_PROVIDER")}if(Rn(g))throw new d([{path:"<root>",from:u.name,message:`USE_ASYNC: provider '${u.name}' is async \u2014 switch to settingsAsync()`}],"USE_ASYNC");c($(g??{},u.name,l,r,e,!e.expandSecrets));}else c($(a,"overrides",void 0,r,e,false));}}return {layers:o,fromMap:s}}function $n(e){return new Set(e.filter(n=>n.skipExpand).flatMap(n=>Object.keys(n.node)).map(n=>n.toLowerCase()))}function Tn(e,n){let{layers:t,fromMap:r}=jn(e,n),o=e.arrayStrategy??"replace",s={};for(let f of t)s=te(s,f.node,o);let i=$n(t);return e.expand!==false&&(s=V(s,Pn(s,n),{allowUnresolved:e.allowUnresolved,fromMap:r,skipTops:i})),e.coerce!==false&&(s=M(s)),{input:s,fromFor:f=>{let a=f.split(".")[0].toLowerCase();return a==="<root>"?"schema":r.get(a)??"defaults"}}}function Pn(e,n){let t=e&&typeof e=="object"&&!Array.isArray(e)?e:{},r=new Map(Object.keys(t).map(s=>[s.toLowerCase(),s])),o=new Map;for(let[s,i]of Object.entries(n))o.set(s.toLowerCase(),i);return s=>{let i=r.get(s.toLowerCase());if(i!==void 0){let c=t[i];return typeof c=="string"?c:typeof c=="number"||typeof c=="boolean"||typeof c=="bigint"?String(c):c==null?n[s]??o.get(s.toLowerCase()):void 0}return n[s]??o.get(s.toLowerCase())}}function V(e,n,t,r=[]){if(typeof e=="string"){if(!e.includes("$"))return e;let o=(r[0]??"<root>").toLowerCase(),s=t.fromMap.get(o)??"config",i=r.map(c=>String(c).toLowerCase()).join(".")||"<root>";try{return Fe(e,n,{...t,from:s},[],i)}catch(c){if(s==="env"&&c instanceof d&&c.code==="E_UNRESOLVED")return e;throw c}}if(Array.isArray(e))return e.map((o,s)=>V(o,n,t,[...r,String(s)]));if(e&&typeof e=="object"){if(r.length===0){let s={};for(let[i,c]of Object.entries(e))s[i]=t.skipTops.has(i.toLowerCase())?c:V(c,n,t,[i]);return s}let o={};for(let[s,i]of Object.entries(e))o[s]=V(i,n,t,[...r,s]);return o}return e}function Fe(e,n,t,r,o){return X(e,s=>{let i=s.toLowerCase();if(r.includes(i))throw new d([{path:o,from:t.from,message:`E_CIRCULAR: $${[...r,s].join("->$")} reachable from '${o}' \u2014 unwind the $VAR references`}],"E_CIRCULAR");if(r.length>=Pe)throw new d([{path:o,from:t.from,message:`E_CIRCULAR: $VAR chain from '${o}' exceeded ${Pe} links \u2014 flatten the indirection`}],"E_CIRCULAR");let c=n(s);if(c!==void 0)return c.includes("$")?Fe(c,n,t,[...r,i],o):c},{allowUnresolved:t.allowUnresolved,from:t.from,leafPath:o})}function U(e,n=""){if(Array.isArray(e)){let t=[];return e.forEach((r,o)=>t.push(...U(r,n?`${n}.${o}`:`${o}`))),t}if(k(e)){let t=[];for(let[r,o]of Object.entries(e)){let s=n?`${n}.${r.toLowerCase()}`:r.toLowerCase();k(o)||Array.isArray(o)?t.push(...U(o,s)):t.push(s);}return t}return n?[n.toLowerCase()]:[]}function Cn(e,n,t,r){if(t==="strip"||t===void 0)return n;if(t==="preserve")return k(e)&&k(n)?te(e,n,"replace"):n;let o=new Set(U(e)),s=new Set(U(n)),i=[...o].filter(c=>!s.has(c));if(i.length>0)throw new d(i.map(c=>({path:c,from:r(c),message:`E_UNKNOWN_KEY: '${c}' is not in the schema \u2014 remove it, or use unknownKeys 'strip'/'preserve'`})),"E_UNKNOWN_KEY");return n}function ae(e){if(Array.isArray(e)){for(let n of e)ae(n);return Object.freeze(e)}if(e&&typeof e=="object"){for(let n of Object.keys(e))ae(e[n]);return Object.freeze(e)}return e}function L(e){vn(e);let n=e.secretKeys,t=_n(e.env),{input:r,fromFor:o}=D("config",()=>Tn(e,t)),s=D("schema",()=>re(e.schema,r));if("promise"in s)throw new d([{path:"<root>",from:"schema",message:"USE_ASYNC: schema is async, use settingsAsync()"}],"USE_ASYNC");if("issues"in s)throw new d(s.issues.map(f=>({path:f.path,from:o(f.path),message:In(f.path,f.message,r,n)})));let i=s.value,c=D("config",()=>Cn(r,i,e.unknownKeys??"strip",o));return e.freeze===false?c:D("config",()=>ae(c))}function Ln(e,n){let t=[];for(let o of n.split(".")){let s=/^([^\[\]]+)\[(\d+)\]$/.exec(o);s?t.push(s[1],Number(s[2])):t.push(o);}let r=e;for(let o of t){if(r===null||typeof r!="object")return;if(Array.isArray(r)){let c=typeof o=="number"?o:Number(o);if(!Number.isInteger(c))return;r=r[c];continue}let s=r,i=Object.keys(s).find(c=>c.toLowerCase()===String(o).toLowerCase());if(!i)return;r=s[i];}return r}function Nn(e){let n=globalThis;if(n.btoa)try{return n.btoa(e)}catch{}try{if(n.Buffer)return n.Buffer.from(e,"utf8").toString("base64")}catch{}return null}function In(e,n,t,r){if(!T(e,r))return n;let o=n,s=Ln(t,e),i=typeof s=="string"?s:typeof s=="number"||typeof s=="boolean"||typeof s=="bigint"?String(s):void 0;if(i!==void 0&&i.length>=4){let c=I(e,i,r);o=o.split(i).join(c);let f=Nn(i);f&&f.length>8&&(o=o.split(f).join(c));}return `${o} (redacted)`}var Pe,ce=v(()=>{j();H();Ee();Se();xe();Re();$e();F();oe();j();oe();Pe=50;});async function P(e,n){let t=path.resolve(e),r;try{let{createJiti:f}=await import('jiti');r=await f((typeof document === 'undefined' ? require('u' + 'rl').pathToFileURL(__filename).href : (_documentCurrentScript && _documentCurrentScript.tagName.toUpperCase() === 'SCRIPT' && _documentCurrentScript.src || new URL('main.cjs', document.baseURI).href)),{interopDefault:!1,fsCache:!1,moduleCache:!1}).import(t);}catch(f){let a=f,u=new Error(`SCHEMA_LOAD_ERROR: ${t}: ${a.message}`);throw u.code="SCHEMA_LOAD_ERROR",u}let o=f=>r[f],s=f=>!f||typeof f!="object"&&typeof f!="function"?false:"~standard"in f;if(n){let f=o(n);if(!s(f)){let a=new Error(`SCHEMA_LOAD_ERROR: --schema-export ${JSON.stringify(n)} did not resolve to a Standard Schema in ${t}`);throw a.code="SCHEMA_LOAD_ERROR",a}return f}for(let f of ["schema","settingsSchema","default"])if(s(o(f)))return o(f);let i=Object.values(r).filter(f=>s(f));if(i.length>1){let f=Object.entries(r).filter(([,u])=>s(u)).map(([u])=>u),a=new Error(`SCHEMA_LOAD_ERROR: ${i.length} Standard Schema exports in ${t} (${f.join(", ")}) \u2014 pass --schema-export NAME to pick one`);throw a.code="SCHEMA_LOAD_ERROR",a}if(i[0])return i[0];let c=new Error(`SCHEMA_LOAD_ERROR: no Standard Schema export in ${t} (tried default/schema/settingsSchema)`);throw c.code="SCHEMA_LOAD_ERROR",c}var W=v(()=>{});var Me={};tn(Me,{runCheck:()=>ue});function fe(e,n,t=""){if(Array.isArray(e))return e.map(r=>fe(r,n,t));if(e&&typeof e=="object"){let r={};for(let[o,s]of Object.entries(e)){let i=t?`${t}.${o}`:o,c=T(i,n)&&(typeof s=="string"&&s.length>0||typeof s=="number"||typeof s=="boolean");r[o]=c?typeof s=="string"?I(i,s,n):"(redacted)":fe(s,n,i);}return r}return e}async function ue(e){let n;try{n=await P(e.schema,e.schemaExport);}catch(r){let o=r,s=o.code;return e.format==="json"?console.log(JSON.stringify({ok:false,code:s,error:o.message})):console.error(o.message),2}let t=(e.config??".env,env").split(",").map(r=>r.trim()).filter(Boolean);try{let r=L({schema:n,sources:t.length?t:[".env","env"],unknownKeys:e.strict?"reject":"strip",expand:e.expand??!0,arrayStrategy:e.array??"replace",prefix:e.prefix,secretKeys:e.secretKeys});return e.format==="json"?console.log(JSON.stringify({ok:!0,config:fe(r,e.secretKeys)})):console.log("OK: config valid"),0}catch(r){if(r instanceof d)return e.format==="json"?console.log(JSON.stringify({ok:false,code:r.code,issues:r.issues})):console.error(r.message),Mn.has(r.code)?1:2;let o=r;return e.format==="json"?console.log(JSON.stringify({ok:false,code:"E_LOAD",error:o.message})):console.error(`E_LOAD: ${o.message}`),2}}var Mn,le=v(()=>{ce();j();W();Mn=new Set(["E_INVALID_CONFIG","E_UNKNOWN_KEY","E_UNRESOLVED","E_CIRCULAR","E_BAD_OP","E_EXPAND"]);});le();var de={zod:`import { z } from 'zod';
1334
7
  import { settings } from 'typed-settings';
8
+ import 'typed-settings/node';
1335
9
 
1336
- const schema = z.object({
10
+ export const schema = z.object({
1337
11
  port: z.coerce.number().default(3000),
1338
12
  });
1339
13
 
1340
14
  export const cfg = settings({ schema, sources: ['.env', 'env'], prefix: 'APP_' });
1341
- `,
1342
- valibot: `import * as v from 'valibot';
15
+ `,valibot:`import * as v from 'valibot';
1343
16
  import { settings } from 'typed-settings';
17
+ import 'typed-settings/node';
1344
18
 
1345
- const schema = v.object({ port: v.optional(v.pipe(v.unknown(), v.transform(Number)), 3000) });
19
+ export const schema = v.object({ port: v.optional(v.pipe(v.unknown(), v.transform(Number), v.number()), 3000) });
1346
20
 
1347
21
  export const cfg = settings({ schema: schema as never, sources: ['.env', 'env'], prefix: 'APP_' });
1348
- `,
1349
- arktype: `import { type } from 'arktype';
22
+ `,arktype:`import { type } from 'arktype';
1350
23
  import { settings } from 'typed-settings';
24
+ import 'typed-settings/node';
1351
25
 
1352
- const schema = type({ 'port?: string.integer.parse = 3000' });
26
+ export const schema = type({ port: 'number = 3000' });
1353
27
 
1354
28
  export const cfg = settings({ schema: schema as never, sources: ['.env', 'env'], prefix: 'APP_' });
1355
- `,
1356
- yup: `import * as yup from 'yup';
29
+ `,yup:`// npm install yup
30
+ import * as yup from 'yup';
1357
31
  import { settings } from 'typed-settings';
32
+ import 'typed-settings/node';
1358
33
  import { yupAdapter } from 'typed-settings/yup';
1359
34
 
1360
- const schema = yup.object({ port: yup.number().default(3000) });
35
+ export const schema = yup.object({ port: yup.number().default(3000) });
1361
36
 
1362
37
  export const cfg = settings({ schema: yupAdapter(schema) as never, sources: ['.env', 'env'], prefix: 'APP_' });
1363
- `,
1364
- joi: `import Joi from 'joi';
38
+ `,joi:`// npm install joi
39
+ import Joi from 'joi';
1365
40
  import { settings } from 'typed-settings';
41
+ import 'typed-settings/node';
1366
42
  import { joiAdapter } from 'typed-settings/joi';
1367
43
 
1368
- const schema = Joi.object({ port: Joi.number().default(3000) });
44
+ export const schema = Joi.object({ port: Joi.number().default(3000) });
1369
45
 
1370
46
  export const cfg = settings({ schema: joiAdapter(schema as never) as never, sources: ['.env', 'env'], prefix: 'APP_' });
1371
- `
1372
- };
1373
- var CONFIG_TPL = {
1374
- env: "# APP_PORT=3000\nAPP_PORT=3000\n",
1375
- yaml: "# config.yaml\nport: 3000\n",
1376
- toml: "# config.toml\nport = 3000\n"
1377
- };
1378
- async function runInit(args) {
1379
- const lib = args.lib ?? "zod";
1380
- const format = args.format ?? "env";
1381
- if (!(lib in SETTINGS_TPL)) {
1382
- console.error(`E_USAGE: --lib must be ${Object.keys(SETTINGS_TPL).join("|")} (got ${JSON.stringify(lib)})`);
1383
- return 2;
1384
- }
1385
- if (!(format in CONFIG_TPL)) {
1386
- console.error(`E_USAGE: --format must be ${Object.keys(CONFIG_TPL).join("|")} (got ${JSON.stringify(format)})`);
1387
- return 2;
1388
- }
1389
- const dir = path.resolve(args.dir ?? ".");
1390
- const settingsTpl = SETTINGS_TPL[lib];
1391
- const configName = format === "env" ? ".env.example" : `config.${format}`;
1392
- const files = [
1393
- { path: path.join(dir, "src", "settings.ts"), content: settingsTpl },
1394
- { path: path.join(dir, configName), content: CONFIG_TPL[format] }
1395
- ];
1396
- const currentOf = (p) => {
1397
- try {
1398
- return fs.readFileSync(p, "utf8");
1399
- } catch {
1400
- return null;
1401
- }
1402
- };
1403
- const drifted = files.filter((f) => currentOf(f.path) !== f.content);
1404
- if (args.dryRun || args.check) {
1405
- for (const f of files) {
1406
- const cur = currentOf(f.path);
1407
- console.log(`${cur === null ? "create" : cur === f.content ? "exists" : "overwrite"} ${f.path}`);
1408
- }
1409
- if (args.check && drifted.length > 0) return 2;
1410
- return 0;
1411
- }
1412
- let written = 0;
1413
- for (const f of files) {
1414
- if (currentOf(f.path) === f.content) {
1415
- continue;
1416
- }
1417
- if (fs.existsSync(f.path) && !args.force) {
1418
- continue;
1419
- }
1420
- fs.mkdirSync(path.dirname(f.path), { recursive: true });
1421
- fs.writeFileSync(f.path, f.content, { mode: 384 });
1422
- try {
1423
- fs.chmodSync(f.path, 384);
1424
- } catch {
1425
- }
1426
- written++;
1427
- }
1428
- console.log(`init: ${lib} + ${format} scaffolding ${written > 0 ? `written (${written} file${written === 1 ? "" : "s"})` : "already up to date"}`);
1429
- return 0;
1430
- }
1431
-
1432
- // src/cli/describe.ts
1433
- function getShape(schema) {
1434
- const s = schema;
1435
- if (s && typeof s.shape === "object" && s.shape !== null) return s.shape;
1436
- if (s && typeof s.shape === "function") {
1437
- try {
1438
- return s.shape();
1439
- } catch {
1440
- return null;
1441
- }
1442
- }
1443
- const d = s?._def?.shape;
1444
- if (typeof d === "function") {
1445
- try {
1446
- return d();
1447
- } catch {
1448
- return null;
1449
- }
1450
- }
1451
- if (d && typeof d === "object") return d;
1452
- return null;
1453
- }
1454
- function unwrapField(t) {
1455
- let cur = t;
1456
- let optional = false;
1457
- let def;
1458
- for (let i = 0; i < 10; i++) {
1459
- const c = cur;
1460
- const z4type = c?.type ?? c?.def?.type;
1461
- if (z4type === "optional") {
1462
- optional = true;
1463
- cur = c?.def?.innerType ?? (typeof c?.unwrap === "function" ? safeUnwrap(c.unwrap) : void 0) ?? cur;
1464
- if (cur === t) break;
1465
- t = cur;
1466
- continue;
1467
- }
1468
- if (z4type === "nullable") {
1469
- cur = c?.def?.innerType ?? (typeof c?.unwrap === "function" ? safeUnwrap(c.unwrap) : void 0) ?? cur;
1470
- if (cur === t) break;
1471
- t = cur;
1472
- continue;
1473
- }
1474
- if (z4type === "catch" || z4type === "prefault" || z4type === "pipe" || z4type === "brand" || z4type === "readonly") {
1475
- const inner = c?.def?.innerType ?? (typeof c?.unwrap === "function" ? safeUnwrap(c.unwrap) : void 0);
1476
- if (inner === void 0 || inner === cur) break;
1477
- cur = inner;
1478
- t = cur;
1479
- continue;
1480
- }
1481
- if (z4type === "default") {
1482
- const dv = c?.def?.defaultValue;
1483
- if (def === void 0) def = typeof dv === "function" ? safeCall(dv) : dv;
1484
- optional = true;
1485
- cur = c?.def?.innerType ?? (typeof c?.unwrap === "function" ? safeUnwrap(c.unwrap) : void 0) ?? cur;
1486
- continue;
1487
- }
1488
- if (z4type === "readonly" || z4type === "nonoptional" || z4type === "success") {
1489
- cur = c?.def?.innerType ?? cur;
1490
- continue;
1491
- }
1492
- const tn = c?._def?.typeName;
1493
- if (tn === "ZodOptional") {
1494
- optional = true;
1495
- cur = c?._def?.innerType;
1496
- continue;
1497
- }
1498
- if (tn === "ZodNullable") {
1499
- cur = c?._def?.innerType;
1500
- continue;
1501
- }
1502
- if (tn === "ZodDefault") {
1503
- if (def === void 0) {
1504
- const dv = c?._def?.defaultValue;
1505
- def = typeof dv === "function" ? safeCall(dv) : dv;
1506
- }
1507
- optional = true;
1508
- cur = c?._def?.innerType;
1509
- continue;
1510
- }
1511
- if (tn === "ZodReadonly") {
1512
- cur = c?._def?.innerType;
1513
- continue;
1514
- }
1515
- break;
1516
- }
1517
- const desc = cur?.description ?? cur?.def?.description ?? t?.description;
1518
- return { inner: cur, optional, def, desc };
1519
- }
1520
- function safeUnwrap(fn) {
1521
- try {
1522
- return fn();
1523
- } catch {
1524
- return void 0;
1525
- }
1526
- }
1527
- function safeCall(fn) {
1528
- try {
1529
- return fn();
1530
- } catch {
1531
- return void 0;
1532
- }
1533
- }
1534
- function enumMembers(def) {
1535
- const d = def;
1536
- if (Array.isArray(d?.values)) return d.values;
1537
- if (d?.entries && typeof d.entries === "object") return Object.values(d.entries);
1538
- return [];
1539
- }
1540
- function unwrapZod(t) {
1541
- return unwrapField(t);
1542
- }
1543
- function zodTypeName(t) {
1544
- const c = t;
1545
- const z4 = c?.type ?? c?.def?.type;
1546
- if (z4) {
1547
- switch (z4) {
1548
- case "string":
1549
- return "string";
1550
- case "number":
1551
- return "number";
1552
- case "boolean":
1553
- return "boolean";
1554
- case "array":
1555
- return "array";
1556
- case "object":
1557
- return "object";
1558
- // Zod 4 keeps enum members in `def.entries` (object); older shapes use `def.values`.
1559
- case "enum":
1560
- return `enum(${enumMembers(c?.def).join("|")})`;
1561
- case "literal":
1562
- return "literal";
1563
- case "union":
1564
- return "union";
1565
- default:
1566
- return z4;
1567
- }
1568
- }
1569
- const tn = c?._def?.typeName ?? "unknown";
1570
- switch (tn) {
1571
- case "ZodString":
1572
- return "string";
1573
- case "ZodNumber":
1574
- return "number";
1575
- case "ZodBoolean":
1576
- return "boolean";
1577
- case "ZodArray":
1578
- return "array";
1579
- case "ZodObject":
1580
- return "object";
1581
- case "ZodEnum":
1582
- return `enum(${(c?._def?.values ?? []).join("|")})`;
1583
- case "ZodLiteral":
1584
- return "literal";
1585
- case "ZodUnion":
1586
- return "union";
1587
- default:
1588
- return "string";
1589
- }
1590
- }
1591
- function walkZod(prefix, t, out) {
1592
- const { inner, optional, def, desc } = unwrapZod(t);
1593
- const shape = getShape(inner);
1594
- if (shape) {
1595
- for (const [k, v] of Object.entries(shape)) {
1596
- walkZod(prefix ? `${prefix}.${k}` : k, v, out);
1597
- }
1598
- return;
1599
- }
1600
- out.push({
1601
- path: prefix || "<root>",
1602
- type: zodTypeName(inner),
1603
- required: !optional && def === void 0,
1604
- default: def,
1605
- description: desc
1606
- });
1607
- }
1608
- function describeSchema(schema) {
1609
- try {
1610
- if (getShape(schema)) {
1611
- const out = [];
1612
- walkZod("", schema, out);
1613
- return { fields: out, bestEffort: false };
1614
- }
1615
- } catch {
1616
- }
1617
- try {
1618
- if (isValibotObject(schema)) {
1619
- const out = [];
1620
- walkValibot("", schema, out);
1621
- return { fields: out, bestEffort: false };
1622
- }
1623
- } catch {
1624
- }
1625
- try {
1626
- const j = arktypeJson(schema);
1627
- if (j && j.domain === "object") {
1628
- const out = [];
1629
- walkArktype(j, out);
1630
- return { fields: out, bestEffort: false };
1631
- }
1632
- } catch {
1633
- }
1634
- return { fields: [{ path: "<root>", type: "string", required: false, description: "GEN_BEST_EFFORT: unknown schema (Effect/others), fill manually" }], bestEffort: true };
1635
- }
1636
- function isValibotObject(schema) {
1637
- const s = schema;
1638
- return !!s && s.type === "object" && !!s.entries && typeof s.entries === "object";
1639
- }
1640
- function unwrapValibot(t) {
1641
- let cur = t;
1642
- let optional = false;
1643
- let def;
1644
- for (let i = 0; i < 10; i++) {
1645
- const c = cur;
1646
- const ty = c?.type;
1647
- if (ty === "optional" || ty === "nullish") {
1648
- optional = true;
1649
- if (def === void 0 && c?.default !== void 0) def = c.default;
1650
- if (!c?.wrapped) break;
1651
- cur = c.wrapped;
1652
- continue;
1653
- }
1654
- if (ty === "nullable") {
1655
- if (!c?.wrapped) break;
1656
- cur = c.wrapped;
1657
- continue;
1658
- }
1659
- if (ty === "non_optional" || ty === "non_nullable" || ty === "non_nullish") {
1660
- if (!c?.wrapped) break;
1661
- cur = c.wrapped;
1662
- continue;
1663
- }
1664
- break;
1665
- }
1666
- const leaf = cur;
1667
- if (def === void 0 && leaf?.default !== void 0) def = leaf.default;
1668
- return { inner: cur, optional, def, desc: leaf?.description };
1669
- }
1670
- function valibotTypeName(t) {
1671
- const c = t;
1672
- switch (c?.type) {
1673
- case "string":
1674
- return "string";
1675
- case "number":
1676
- return "number";
1677
- case "boolean":
1678
- return "boolean";
1679
- case "bigint":
1680
- return "bigint";
1681
- case "date":
1682
- return "date";
1683
- case "array":
1684
- return "array";
1685
- case "object":
1686
- return "object";
1687
- case "record":
1688
- return "object";
1689
- case "tuple":
1690
- return "array";
1691
- case "map":
1692
- return "object";
1693
- case "picklist":
1694
- case "enum_":
1695
- return `enum(${(c.options ?? []).map((o) => JSON.stringify(o)).join("|")})`;
1696
- case "literal":
1697
- return `literal(${JSON.stringify(c.literal)})`;
1698
- case "union":
1699
- case "variant":
1700
- case "intersect":
1701
- return c.type;
1702
- case "nan":
1703
- return "number";
1704
- default:
1705
- return typeof c?.type === "string" ? c.type : "string";
1706
- }
1707
- }
1708
- function walkValibot(prefix, t, out) {
1709
- const { inner, optional, def, desc } = unwrapValibot(t);
1710
- const c = inner;
1711
- if (c?.type === "object" && c.entries && typeof c.entries === "object") {
1712
- for (const [k, v] of Object.entries(c.entries)) {
1713
- walkValibot(prefix ? `${prefix}.${k}` : k, v, out);
1714
- }
1715
- return;
1716
- }
1717
- out.push({
1718
- path: prefix || "<root>",
1719
- type: valibotTypeName(inner),
1720
- required: !optional && def === void 0,
1721
- default: def,
1722
- description: desc
1723
- });
1724
- }
1725
- function arktypeJson(schema) {
1726
- const s = schema;
1727
- const j = s?.json;
1728
- if (typeof j === "function") {
1729
- try {
1730
- return j();
1731
- } catch {
1732
- return null;
1733
- }
1734
- }
1735
- return j ?? null;
1736
- }
1737
- function arktypeTypeName(v) {
1738
- if (typeof v === "string") return v;
1739
- if (Array.isArray(v)) return "union";
1740
- if (v && typeof v === "object") {
1741
- const o = v;
1742
- if ("sequence" in o) return "array";
1743
- if (o["domain"] === "object") return "object";
1744
- if (typeof o["proto"] === "string") return String(o["proto"]).toLowerCase();
1745
- }
1746
- return "string";
1747
- }
1748
- function walkArktype(node, out) {
1749
- const n = node;
1750
- if (n && n.domain === "object" && (Array.isArray(n.required) || Array.isArray(n.optional))) {
1751
- for (const r of n.required ?? []) walkArktypeValue(r.key, r.value, true, void 0, out);
1752
- for (const r of n.optional ?? []) walkArktypeValue(r.key, r.value, false, r.default, out);
1753
- return;
1754
- }
1755
- out.push({ path: "<root>", type: arktypeTypeName(node), required: true, default: void 0 });
1756
- }
1757
- function walkArktypeValue(path, value, required, def, out) {
1758
- if (value && typeof value === "object" && !Array.isArray(value) && value.domain === "object") {
1759
- const n = value;
1760
- if (Array.isArray(n.required) || Array.isArray(n.optional)) {
1761
- for (const r of n.required ?? []) walkArktypeValue(`${path}.${r.key}`, r.value, true, void 0, out);
1762
- for (const r of n.optional ?? []) walkArktypeValue(`${path}.${r.key}`, r.value, false, r.default, out);
1763
- return;
1764
- }
1765
- }
1766
- out.push({ path, type: arktypeTypeName(value), required: required && def === void 0, default: def });
1767
- }
1768
- function toEnvExample(fields, prefix = "") {
1769
- const lines = ["# Generated by typed-settings gen \u2014 edit values, keep keys"];
1770
- const sorted = [...fields].sort((a, b) => a.path.localeCompare(b.path));
1771
- for (const f of sorted) {
1772
- if (f.path === "<root>") {
1773
- lines.push(`# ${f.description ?? "no fields discovered \u2014 fill manually"}`);
1774
- continue;
1775
- }
1776
- const key = (prefix + f.path.replace(/\./g, "__")).toUpperCase();
1777
- const val = f.default !== void 0 && typeof f.default !== "object" ? String(f.default) : f.type === "number" ? "0" : f.type === "boolean" ? "false" : "";
1778
- const comment = f.required ? "required" : `default: ${f.default !== void 0 ? JSON.stringify(f.default) : "none"}`;
1779
- if (f.description) lines.push(`# ${f.description}`);
1780
- lines.push(`${key}=${val} # ${f.type} ${comment}`);
1781
- }
1782
- lines.push("");
1783
- return lines.join("\n");
1784
- }
1785
- function toMarkdownDocs(fields, prefix = "") {
1786
- const lines = ["# Configuration", "", "| Env | Path | Type | Required | Default |", "| --- | --- | --- | --- | --- |"];
1787
- for (const f of [...fields].sort((a, b) => a.path.localeCompare(b.path))) {
1788
- const env = (prefix + f.path.replace(/\./g, "__")).toUpperCase();
1789
- lines.push(`| \`${env}\` | \`${f.path}\` | ${f.type} | ${f.required} | ${f.default !== void 0 ? `\`${JSON.stringify(f.default)}\`` : "-"} |`);
1790
- }
1791
- lines.push("");
1792
- return lines.join("\n");
1793
- }
1794
-
1795
- // src/cli/gen.ts
1796
- async function runGen(args) {
1797
- let schema;
1798
- try {
1799
- schema = await loadSchema(args.schema, args.schemaExport);
1800
- } catch (e) {
1801
- console.error(e.message);
1802
- return 2;
1803
- }
1804
- const { fields, bestEffort } = describeSchema(schema);
1805
- if (bestEffort) console.error("GEN_BEST_EFFORT: non-Zod schema, output is a starting point \u2014 verify types manually");
1806
- const envText = toEnvExample(fields, args.prefix);
1807
- const mdText = toMarkdownDocs(fields, args.prefix);
1808
- const writeGuarded = (p, content) => {
1809
- if (fs.existsSync(p) && !args.force) {
1810
- console.error(`E_EXISTS: ${p} exists \u2014 pass --force to overwrite`);
1811
- return 2;
1812
- }
1813
- fs.mkdirSync(path.dirname(p), { recursive: true });
1814
- fs.writeFileSync(p, content, { mode: 384 });
1815
- console.log(`gen: wrote ${p}`);
1816
- return 0;
1817
- };
1818
- if (args.out) {
1819
- const code = writeGuarded(path.resolve(args.out), envText);
1820
- if (code !== 0) return code;
1821
- } else {
1822
- console.log(envText);
1823
- }
1824
- if (args.docs) {
1825
- const code = writeGuarded(path.resolve(args.docs), mdText);
1826
- if (code !== 0) return code;
1827
- } else if (!args.out) {
1828
- console.log(mdText);
1829
- }
1830
- return 0;
1831
- }
1832
-
1833
- // src/node.ts
1834
- init_env();
1835
- init_index();
1836
- globalThis.__typedSettingsFs ??= {
1837
- readFileSync: (p, e) => fs.readFileSync(p, e)
1838
- };
1839
- function extractWatchFiles(sources) {
1840
- const out = [];
1841
- for (const s of sources ?? []) {
1842
- if (s === "env") continue;
1843
- if (s === ".env" || s === ".env.local") out.push(path.resolve(s));
1844
- else if (typeof s === "string") {
1845
- const lower = s.toLowerCase();
1846
- if (lower.endsWith(".env") || s === ".env.local" || lower.endsWith(".json") || lower.endsWith(".yaml") || lower.endsWith(".yml") || lower.endsWith(".toml")) {
1847
- out.push(path.resolve(s));
1848
- } else if (!lower.endsWith(".env")) {
1849
- out.push(path.resolve(s));
1850
- }
1851
- } else if (s && typeof s === "object" && "file" in s) {
1852
- out.push(path.resolve(s.file));
1853
- }
1854
- }
1855
- return [...new Set(out)];
1856
- }
1857
- function hasPollSources(sources) {
1858
- return (sources ?? []).some(
1859
- (s) => s && typeof s === "object" && ("dir" in s || "provider" in s || "load" in s)
1860
- );
1861
- }
1862
- function diffLeafPaths(a, b, prefix = "") {
1863
- if (Array.isArray(a) && Array.isArray(b)) {
1864
- const out = [];
1865
- const len = Math.max(a.length, b.length);
1866
- for (let i = 0; i < len; i++) {
1867
- const p = prefix ? `${prefix}[${i}]` : `[${i}]`;
1868
- if (i >= a.length || i >= b.length) out.push(p);
1869
- else out.push(...diffLeafPaths(a[i], b[i], p));
1870
- }
1871
- return out;
1872
- }
1873
- if (a && typeof a === "object" && b && typeof b === "object" && !Array.isArray(a) && !Array.isArray(b)) {
1874
- const out = [];
1875
- const keys = /* @__PURE__ */ new Set([...Object.keys(a), ...Object.keys(b)]);
1876
- for (const k of keys) {
1877
- const p = prefix ? `${prefix}.${k}` : k;
1878
- if (!(k in a) || !(k in b)) out.push(p);
1879
- else out.push(...diffLeafPaths(a[k], b[k], p));
1880
- }
1881
- return out;
1882
- }
1883
- return JSON.stringify(a) === JSON.stringify(b) ? [] : [prefix || "<root>"];
1884
- }
1885
- async function stableSize(path, retries = 3) {
1886
- for (let i = 0; i < retries; i++) {
1887
- let s1 = null;
1888
- let s2 = null;
1889
- try {
1890
- const st = fs.statSync(path);
1891
- s1 = { size: st.size, mtimeMs: st.mtimeMs };
1892
- } catch {
1893
- return;
1894
- }
1895
- await new Promise((r) => setTimeout(r, 20));
1896
- try {
1897
- const st = fs.statSync(path);
1898
- s2 = { size: st.size, mtimeMs: st.mtimeMs };
1899
- } catch {
1900
- return;
1901
- }
1902
- if (s1.size === s2.size && s1.mtimeMs === s2.mtimeMs) return;
1903
- }
1904
- }
1905
- function watchSettings(opts, cb = {}) {
1906
- const debounceMs = cb.debounceMs ?? 100;
1907
- const refreshMs = cb.refreshMs ?? (hasPollSources(opts.sources) ? 6e4 : 0);
1908
- const pollMs = cb.pollMs ?? 0;
1909
- let current = settings(opts);
1910
- let version = 0;
1911
- let reloadId = 0;
1912
- let disposed = false;
1913
- let timer = null;
1914
- const watchers = [];
1915
- const intervals = [];
1916
- const watchedDirs = /* @__PURE__ */ new Set();
1917
- const handle = {
1918
- get: () => current,
1919
- reload: async () => {
1920
- await doReload();
1921
- },
1922
- dispose: async () => {
1923
- if (disposed) return;
1924
- disposed = true;
1925
- if (timer) clearTimeout(timer);
1926
- for (const iv of intervals) clearInterval(iv);
1927
- for (const w of watchers) {
1928
- try {
1929
- w.close();
1930
- } catch {
1931
- }
1932
- }
1933
- },
1934
- get version() {
1935
- return version;
1936
- }
1937
- };
1938
- async function doReload() {
1939
- const myId = ++reloadId;
1940
- ensureWatchers();
1941
- const files = extractWatchFiles(opts.sources);
1942
- await Promise.all(
1943
- files.map(
1944
- (f) => stableSize(f).catch(() => {
1945
- })
1946
- )
1947
- );
1948
- if (disposed || myId !== reloadId) return;
1949
- let next;
1950
- try {
1951
- next = settings(opts);
1952
- } catch (e) {
1953
- try {
1954
- cb.onError?.(e, { version });
1955
- } catch {
1956
- }
1957
- return;
1958
- }
1959
- if (disposed || myId !== reloadId) return;
1960
- const changed = diffLeafPaths(current, next);
1961
- current = next;
1962
- version++;
1963
- try {
1964
- cb.onUpdate?.(current, changed);
1965
- } catch {
1966
- }
1967
- }
1968
- function scheduleReload() {
1969
- if (disposed) return;
1970
- if (timer) clearTimeout(timer);
1971
- timer = setTimeout(() => {
1972
- timer = null;
1973
- void doReload();
1974
- }, debounceMs);
1975
- }
1976
- function ensureWatchers() {
1977
- for (const file of extractWatchFiles(opts.sources)) {
1978
- const dir = path.dirname(file);
1979
- const base = path.basename(file);
1980
- const key = dir + "\0" + base;
1981
- if (watchedDirs.has(key)) continue;
1982
- try {
1983
- const w = fs.watch(dir, (_event, filename) => {
1984
- const name = typeof filename === "string" ? filename : filename ? String(filename) : null;
1985
- if (name && name !== base) return;
1986
- scheduleReload();
1987
- });
1988
- w.on("error", () => {
1989
- });
1990
- watchers.push(w);
1991
- watchedDirs.add(key);
1992
- } catch {
1993
- }
1994
- }
1995
- }
1996
- ensureWatchers();
1997
- if (pollMs > 0) {
1998
- intervals.push(setInterval(scheduleReload, pollMs));
1999
- }
2000
- if (refreshMs > 0) {
2001
- intervals.push(setInterval(scheduleReload, refreshMs));
2002
- }
2003
- return handle;
2004
- }
2005
-
2006
- // src/cli/watch.ts
2007
- async function runWatch(args) {
2008
- if (!args.schema) {
2009
- console.error("Usage: watch -s schema.ts -c base.yaml,.env [-- cmd...]");
2010
- return 2;
2011
- }
2012
- const schema = await loadSchema(args.schema, args.schemaExport).catch((e) => {
2013
- console.error(e.message);
2014
- return null;
2015
- });
2016
- if (!schema) return 2;
2017
- const sources = (args.config ?? ".env,env").split(",").map((s) => s.trim()).filter(Boolean);
2018
- let child = null;
2019
- const startChild = () => {
2020
- if (!args.cmd?.length) return;
2021
- stopChild();
2022
- child = child_process.spawn(args.cmd[0], args.cmd.slice(1), { stdio: "inherit", shell: false });
2023
- child.on("error", (e) => {
2024
- console.error(`watch: child failed to start: ${e.message}`);
2025
- child = null;
2026
- });
2027
- child.on("exit", () => {
2028
- child = null;
2029
- });
2030
- };
2031
- const stopChild = () => {
2032
- try {
2033
- child?.kill();
2034
- } catch {
2035
- }
2036
- child = null;
2037
- };
2038
- if (args.once) {
2039
- if (args.cmd?.length) console.error("watch: -- cmd is ignored with --once (single validation, nothing to supervise)");
2040
- const { settings: settings2, ConfigError: ConfigError2 } = await Promise.resolve().then(() => (init_index(), index_exports));
2041
- try {
2042
- settings2({ schema, sources: sources.length ? sources : [".env", "env"], unknownKeys: args.strict ? "reject" : "strip", expand: args.expand ?? true, arrayStrategy: args.array ?? "replace", prefix: args.prefix });
2043
- console.log("OK: config valid");
2044
- return 0;
2045
- } catch (e) {
2046
- console.error(e.message);
2047
- return e instanceof ConfigError2 ? 1 : 2;
2048
- }
2049
- }
2050
- const sub = watchSettings(
2051
- // NOTE: no `env` override — inherit process.env exactly like --once/check do.
2052
- { schema, sources: sources.length ? sources : [".env", "env"], unknownKeys: args.strict ? "reject" : "strip", expand: args.expand ?? true, arrayStrategy: args.array ?? "replace", prefix: args.prefix },
2053
- {
2054
- onUpdate: (cfg, changed) => {
2055
- console.log(`reload: ok changed=[${changed.join(",")}]`);
2056
- if (args.cmd?.length) startChild();
2057
- },
2058
- onError: (e) => {
2059
- console.error(`reload: invalid, kept old
2060
- ${e.message}`);
2061
- if (args.exitOnError) {
2062
- void sub.dispose().then(() => {
2063
- stopChild();
2064
- process.exitCode = 1;
2065
- });
2066
- }
2067
- }
2068
- }
2069
- );
2070
- startChild();
2071
- const shutdown = () => {
2072
- void sub.dispose().then(() => {
2073
- stopChild();
2074
- });
2075
- };
2076
- process.once("SIGINT", shutdown);
2077
- process.once("SIGTERM", shutdown);
2078
- await new Promise((resolve5) => {
2079
- const t = setInterval(() => {
2080
- if ((process.exitCode ?? 0) !== 0) {
2081
- clearInterval(t);
2082
- resolve5();
2083
- }
2084
- }, 100);
2085
- process.once("SIGINT", () => {
2086
- clearInterval(t);
2087
- resolve5();
2088
- });
2089
- process.once("SIGTERM", () => {
2090
- clearInterval(t);
2091
- resolve5();
2092
- });
2093
- });
2094
- return Number(process.exitCode ?? 0);
2095
- }
2096
-
2097
- // src/cli/main.ts
2098
- async function main(argv = process.argv.slice(2)) {
2099
- const [cmd, ...rest] = argv;
2100
- if (!cmd || cmd === "--help" || cmd === "-h") {
2101
- console.log(`typed-settings <check|init|gen|watch>
2102
-
2103
- check -s schema.ts -c base.yaml,.env [--strict] [--no-expand] [--array replace|concat|mergeIndex] [--format human|json]
2104
- init --lib zod|valibot|arktype|yup|joi --format yaml|toml|env [--force|--dry-run|--check]
2105
- gen --schema src/config.ts --out .env.example --docs CONFIG.md
2106
- watch -s schema.ts -c base.yaml --once [--exit-on-error] [-- cmd...]`);
2107
- return 0;
2108
- }
2109
- try {
2110
- if (cmd === "check") {
2111
- const { values } = util.parseArgs({
2112
- args: rest,
2113
- // allowNegative enables the advertised `--no-expand` negation flag.
2114
- allowNegative: true,
2115
- options: {
2116
- schema: { type: "string", short: "s" },
2117
- config: { type: "string", short: "c" },
2118
- strict: { type: "boolean", default: false },
2119
- expand: { type: "boolean", default: true },
2120
- array: { type: "string", default: "replace" },
2121
- format: { type: "string", default: "human" },
2122
- "schema-export": { type: "string" },
2123
- prefix: { type: "string" }
2124
- }
2125
- });
2126
- if (!values.schema) {
2127
- console.error("Usage: check -s schema.ts -c base.yaml,.env");
2128
- return 2;
2129
- }
2130
- if (values.array !== void 0 && !["replace", "concat", "mergeIndex"].includes(values.array)) {
2131
- console.error(`E_USAGE: --array must be replace|concat|mergeIndex (got ${JSON.stringify(values.array)})`);
2132
- return 2;
2133
- }
2134
- if (values.format !== void 0 && !["human", "json"].includes(values.format)) {
2135
- console.error(`E_USAGE: --format must be human|json (got ${JSON.stringify(values.format)})`);
2136
- return 2;
2137
- }
2138
- return await runCheck({
2139
- schema: values.schema,
2140
- config: values.config,
2141
- strict: values.strict,
2142
- expand: values.expand,
2143
- array: values.array,
2144
- format: values.format,
2145
- schemaExport: values["schema-export"],
2146
- prefix: values.prefix
2147
- });
2148
- }
2149
- if (cmd === "init") {
2150
- const { values } = util.parseArgs({
2151
- args: rest,
2152
- options: {
2153
- lib: { type: "string", default: "zod" },
2154
- format: { type: "string", default: "env" },
2155
- dir: { type: "string", default: "." },
2156
- force: { type: "boolean", default: false },
2157
- "dry-run": { type: "boolean", default: false },
2158
- check: { type: "boolean", default: false }
2159
- }
2160
- });
2161
- return await runInit({
2162
- lib: values.lib,
2163
- format: values.format,
2164
- dir: values.dir,
2165
- force: values.force,
2166
- dryRun: values["dry-run"],
2167
- check: values.check
2168
- });
2169
- }
2170
- if (cmd === "gen") {
2171
- const { values } = util.parseArgs({
2172
- args: rest,
2173
- options: {
2174
- schema: { type: "string" },
2175
- "schema-export": { type: "string" },
2176
- out: { type: "string" },
2177
- docs: { type: "string" },
2178
- prefix: { type: "string" },
2179
- force: { type: "boolean", default: false }
2180
- }
2181
- });
2182
- if (!values.schema) {
2183
- console.error("Usage: gen --schema src/config.ts --out .env.example --docs CONFIG.md");
2184
- return 2;
2185
- }
2186
- return await runGen({
2187
- schema: values.schema,
2188
- schemaExport: values["schema-export"],
2189
- out: values.out,
2190
- docs: values.docs,
2191
- prefix: values.prefix,
2192
- force: values.force
2193
- });
2194
- }
2195
- if (cmd === "watch") {
2196
- const dashIdx = rest.indexOf("--");
2197
- const watchArgs = dashIdx === -1 ? rest : rest.slice(0, dashIdx);
2198
- const childCmd = dashIdx === -1 ? [] : rest.slice(dashIdx + 1);
2199
- const { values } = util.parseArgs({
2200
- args: watchArgs,
2201
- allowNegative: true,
2202
- options: {
2203
- schema: { type: "string", short: "s" },
2204
- config: { type: "string", short: "c" },
2205
- strict: { type: "boolean", default: false },
2206
- expand: { type: "boolean", default: true },
2207
- array: { type: "string", default: "replace" },
2208
- once: { type: "boolean", default: false },
2209
- "exit-on-error": { type: "boolean", default: false },
2210
- "schema-export": { type: "string" },
2211
- prefix: { type: "string" }
2212
- }
2213
- });
2214
- if (values.array !== void 0 && !["replace", "concat", "mergeIndex"].includes(values.array)) {
2215
- console.error(`E_USAGE: --array must be replace|concat|mergeIndex (got ${JSON.stringify(values.array)})`);
2216
- return 2;
2217
- }
2218
- return await runWatch({
2219
- schema: values.schema,
2220
- config: values.config,
2221
- schemaExport: values["schema-export"],
2222
- strict: values.strict,
2223
- expand: values.expand,
2224
- array: values.array,
2225
- prefix: values.prefix,
2226
- once: values.once,
2227
- exitOnError: values["exit-on-error"],
2228
- cmd: childCmd.length ? childCmd : void 0
2229
- });
2230
- }
2231
- console.error(`unknown command: ${cmd}`);
2232
- return 2;
2233
- } catch (e) {
2234
- console.error(e.message);
2235
- return 2;
2236
- }
2237
- }
2238
- var isDirect = process.argv[1]?.endsWith("main.js") || process.argv[1]?.endsWith("main.cjs");
2239
- if (isDirect) {
2240
- main().then((code) => {
2241
- process.exitCode = code;
2242
- });
2243
- }
2244
-
2245
- exports.main = main;
47
+ `},pe={env:`# APP_PORT=3000
48
+ APP_PORT=3000
49
+ `,yaml:`# config.yaml
50
+ port: 3000
51
+ `,toml:`# config.toml
52
+ port = 3000
53
+ `};async function Ve(e){let n=e.lib??"zod",t=e.format??"env";if(!Object.hasOwn(de,n))return console.error(`E_USAGE: --lib must be ${Object.keys(de).join("|")} (got ${JSON.stringify(n)})`),2;if(!Object.hasOwn(pe,t))return console.error(`E_USAGE: --format must be ${Object.keys(pe).join("|")} (got ${JSON.stringify(t)})`),2;let r=path.resolve(e.dir??"."),o=de[n],s=t==="env"?".env.example":`config.${t}`,i=[{path:path.join(r,"src","settings.ts"),content:o},{path:path.join(r,s),content:pe[t]}],c=l=>{try{return fs.readFileSync(l,"utf8")}catch{return null}},f=i.filter(l=>c(l.path)!==l.content);if(e.dryRun||e.check){for(let l of i){let g=c(l.path);console.log(`${g===null?"create":g===l.content?"exists":"overwrite"} ${l.path}`);}return e.check&&f.length>0?2:0}let a=0;for(let l of i){if(c(l.path)===l.content){continue}if(fs.existsSync(l.path)&&!e.force){continue}fs.mkdirSync(path.dirname(l.path),{recursive:true}),fs.writeFileSync(l.path,l.content,{mode:384});try{fs.chmodSync(l.path,384);}catch{}a++;}return console.log(`init: ${n} + ${t} scaffolding ${a>0?`written (${a} file${a===1?"":"s"})`:"already up to date"}`),t==="env"&&a>0&&console.log("hint: copy .env.example to .env and fill in real values (example files are never loaded)"),0}W();function We(e){let n=e;if(n&&typeof n.shape=="object"&&n.shape!==null)return n.shape;if(n&&typeof n.shape=="function")try{return n.shape()}catch{return null}let t=n?._def?.shape;if(typeof t=="function")try{return t()}catch{return null}return t&&typeof t=="object"?t:null}function Bn(e){let n=e,t=false,r;for(let s=0;s<10;s++){let i=n,c=i?.type??i?.def?.type;if(c==="optional"){if(t=true,n=i?.def?.innerType??(typeof i?.unwrap=="function"?G(i.unwrap):void 0)??n,n===e)break;e=n;continue}if(c==="nullable"){if(n=i?.def?.innerType??(typeof i?.unwrap=="function"?G(i.unwrap):void 0)??n,n===e)break;e=n;continue}if(c==="catch"||c==="prefault"||c==="pipe"||c==="brand"||c==="readonly"){let a=i?.def?.innerType??(typeof i?.unwrap=="function"?G(i.unwrap):void 0);if(a===void 0||a===n)break;n=a,e=n;continue}if(c==="default"){let a=i?.def?.defaultValue;r===void 0&&(r=typeof a=="function"?Ue(a):a),t=true,n=i?.def?.innerType??(typeof i?.unwrap=="function"?G(i.unwrap):void 0)??n;continue}if(c==="nonoptional"||c==="success"){let a=i?.def?.innerType;if(a===void 0||a===n)break;n=a,e=n;continue}let f=i?._def?.typeName;if(f==="ZodOptional"){t=true,n=i?._def?.innerType;continue}if(f==="ZodNullable"){n=i?._def?.innerType;continue}if(f==="ZodDefault"){if(r===void 0){let a=i?._def?.defaultValue;r=typeof a=="function"?Ue(a):a;}t=true,n=i?._def?.innerType;continue}if(f==="ZodReadonly"){n=i?._def?.innerType;continue}break}let o=n?.description??n?.def?.description??e?.description;return {inner:n,optional:t,def:r,desc:o}}function G(e){try{return e()}catch{return}}function Ue(e){try{return e()}catch{return}}function Jn(e){let n=e;return Array.isArray(n?.values)?n.values:n?.entries&&typeof n.entries=="object"?Object.values(n.entries):[]}function qn(e){return Bn(e)}function Yn(e){let n=e,t=n?.type??n?.def?.type;if(t)switch(t){case "string":return "string";case "number":return "number";case "boolean":return "boolean";case "array":return "array";case "object":return "object";case "enum":return `enum(${Jn(n?.def).join("|")})`;case "literal":return "literal";case "union":return "union";default:return t}switch(n?._def?.typeName??"unknown"){case "ZodString":return "string";case "ZodNumber":return "number";case "ZodBoolean":return "boolean";case "ZodBigInt":return "bigint";case "ZodDate":return "date";case "ZodNaN":return "number";case "ZodArray":return "array";case "ZodObject":return "object";case "ZodEnum":return `enum(${(n?._def?.values??[]).join("|")})`;case "ZodLiteral":return "literal";case "ZodUnion":return "union";default:return "string"}}function Ge(e,n,t,r=false){let{inner:o,optional:s,def:i,desc:c}=qn(n),f=r||s,a=We(o);if(a){for(let[u,l]of Object.entries(a))Ge(e?`${e}.${u}`:u,l,t,f);return}t.push({path:e||"<root>",type:Yn(o),required:!f&&i===void 0,default:i,description:c});}function ze(e){try{if(We(e)){let n=[];return Ge("",e,n),{fields:n,bestEffort:!1}}}catch{}try{if(Zn(e)){let n=[];return Ke("",e,n),{fields:n,bestEffort:!1}}}catch{}try{let n=Qn(e);if(n&&n.domain==="object"){let t=[];return et(n,t),{fields:t,bestEffort:!1}}}catch{}return {fields:[{path:"<root>",type:"string",required:false,description:"GEN_BEST_EFFORT: unknown schema (Effect/others), fill manually"}],bestEffort:true}}function Zn(e){let n=e;return !!n&&n.type==="object"&&!!n.entries&&typeof n.entries=="object"}function Hn(e){let n=e,t=false,r;for(let s=0;s<10;s++){let i=n,c=i?.type;if(c==="optional"||c==="nullish"){if(t=true,r===void 0&&i?.default!==void 0&&(r=i.default),!i?.wrapped)break;n=i.wrapped;continue}if(c==="nullable"){if(!i?.wrapped)break;n=i.wrapped;continue}if(c==="non_optional"||c==="non_nullable"||c==="non_nullish"){if(!i?.wrapped)break;n=i.wrapped;continue}break}let o=n;return r===void 0&&o?.default!==void 0&&(r=o.default),{inner:n,optional:t,def:r,desc:o?.description}}function Xn(e){let n=e;switch(n?.type){case "string":return "string";case "number":return "number";case "boolean":return "boolean";case "bigint":return "bigint";case "date":return "date";case "array":return "array";case "object":return "object";case "record":return "object";case "tuple":return "array";case "map":return "object";case "picklist":case "enum_":return `enum(${(n.options??[]).map(t=>JSON.stringify(t)).join("|")})`;case "literal":return `literal(${JSON.stringify(n.literal)})`;case "union":case "variant":case "intersect":return n.type;case "nan":return "number";default:return typeof n?.type=="string"?n.type:"string"}}function Ke(e,n,t,r=false){let{inner:o,optional:s,def:i,desc:c}=Hn(n),f=r||s,a=o;if(a?.type==="object"&&a.entries&&typeof a.entries=="object"){for(let[u,l]of Object.entries(a.entries))Ke(e?`${e}.${u}`:u,l,t,f);return}t.push({path:e||"<root>",type:Xn(o),required:!f&&i===void 0,default:i,description:c});}function Qn(e){let t=e?.json;if(typeof t=="function")try{return t()}catch{return null}return t??null}function Be(e){if(typeof e=="string")return e;if(Array.isArray(e))return "union";if(e&&typeof e=="object"){let n=e;if("sequence"in n)return "array";if(n.domain==="object")return "object";if(typeof n.proto=="string")return String(n.proto).toLowerCase()}return "string"}function et(e,n){let t=e;if(t&&t.domain==="object"&&(Array.isArray(t.required)||Array.isArray(t.optional))){for(let r of t.required??[])z(r.key,r.value,true,void 0,n);for(let r of t.optional??[])z(r.key,r.value,false,r.default,n);return}n.push({path:"<root>",type:Be(e),required:true,default:void 0});}function z(e,n,t,r,o){if(n&&typeof n=="object"&&!Array.isArray(n)&&n.domain==="object"){let s=n;if(Array.isArray(s.required)||Array.isArray(s.optional)){for(let i of s.required??[])z(`${e}.${i.key}`,i.value,true,void 0,o);for(let i of s.optional??[])z(`${e}.${i.key}`,i.value,false,i.default,o);return}}o.push({path:e,type:Be(n),required:t&&r===void 0,default:r});}function Je(e,n){return ((e&&!e.endsWith("_")?`${e}_`:e)+n.replace(/\./g,"__")).toUpperCase().replace(/[^A-Z0-9_]/g,"_")}function qe(e,n=""){let t=["# Generated by typed-settings gen \u2014 edit values, keep keys"],r=[...e].sort((o,s)=>o.path.localeCompare(s.path));for(let o of r){if(o.path==="<root>"){t.push(`# ${o.description??"no fields discovered \u2014 fill manually"}`);continue}let s=Je(n,o.path),i=o.default!==void 0&&typeof o.default!="object"?String(o.default):o.type==="number"?"0":o.type==="boolean"?"false":"",c=o.required?"required":`default: ${o.default!==void 0?JSON.stringify(o.default):"none"}`;o.description&&t.push(`# ${o.description}`),t.push(`${s}=${i} # ${o.type} ${c}`);}return t.push(""),t.join(`
54
+ `)}function Ye(e,n=""){let t=["# Configuration","","| Env | Path | Type | Required | Default |","| --- | --- | --- | --- | --- |"];for(let r of [...e].sort((o,s)=>o.path.localeCompare(s.path))){if(r.path==="<root>")continue;let o=Je(n,r.path);t.push(`| \`${o}\` | \`${r.path}\` | ${r.type} | ${r.required} | ${r.default!==void 0?`\`${JSON.stringify(r.default)}\``:"-"} |`);}return t.push(""),t.join(`
55
+ `)}function at(e){try{return fs.lstatSync(e).isSymbolicLink()}catch{return false}}async function He(e){let n;try{n=await P(e.schema,e.schemaExport);}catch(a){return console.error(a.message),2}let{fields:t,bestEffort:r}=ze(n);r&&console.error("GEN_BEST_EFFORT: non-Zod schema, output is a starting point \u2014 verify types manually");let o=qe(t,e.prefix),s=Ye(t,e.prefix),i=e.out?path.resolve(e.out):null,c=e.docs?path.resolve(e.docs):null;for(let a of [i,c])if(a){if(at(a))return console.error(`E_SYMLINK: ${a} is a symlink \u2014 refusing to write through it`),2;if(fs.existsSync(a)&&!e.force)return console.error(`E_EXISTS: ${a} exists \u2014 pass --force to overwrite`),2}let f=(a,u)=>{fs.mkdirSync(path.dirname(a),{recursive:true}),fs.writeFileSync(a,u,{mode:384});try{fs.chmodSync(a,384);}catch{}console.log(`gen: wrote ${a}`);};return i?f(i,o):console.log(o),c?f(c,s):i||(console.log("# ---- CONFIG.md below ----"),console.log(s)),0}H();F();ce();j();globalThis.__typedSettingsFs??={readFileSync:(e,n)=>fs.readFileSync(e,n),statSync:e=>fs.statSync(e)};function Xe(e){let n=[];for(let t of e??[])if(t!=="env")if(t===".env"||t===".env.local")n.push(path.resolve(t));else if(typeof t=="string"){let r=t.toLowerCase();r.endsWith(".env")||t===".env.local"||r.endsWith(".json")||r.endsWith(".yaml")||r.endsWith(".yml")||r.endsWith(".toml")?n.push(path.resolve(t)):r.endsWith(".env")||n.push(path.resolve(t));}else t&&typeof t=="object"&&"file"in t&&n.push(path.resolve(t.file));return [...new Set(n)]}function dt(e){return (e??[]).some(n=>n&&typeof n=="object"&&("provider"in n||"load"in n))}function pt(e,n){if(e===n||Object.is(e,n))return true;if(typeof e!=typeof n)return false;if(e&&n&&typeof e=="object")try{return JSON.stringify(e)===JSON.stringify(n)}catch{return false}return false}function mt(e,n,t=""){let r=[],o=[[e,n,t]];for(;o.length>0;){let[s,i,c]=o.pop();if(Array.isArray(s)&&Array.isArray(i)){let f=Math.max(s.length,i.length);for(let a=f-1;a>=0;a--){let u=c?`${c}[${a}]`:`[${a}]`;a>=s.length||a>=i.length?r.push(u):o.push([s[a],i[a],u]);}}else if(k(s)&&k(i)){let f=[...new Set([...Object.keys(s),...Object.keys(i)])];for(let a=f.length-1;a>=0;a--){let u=f[a],l=c?`${c}.${u}`:u;!(u in s)||!(u in i)?r.push(l):o.push([s[u],i[u],l]);}}else pt(s,i)||r.push(c||"<root>");}return r}async function gt(e,n=3){for(let t=0;t<n;t++){let r=null,o=null;try{let s=fs.statSync(e);r={size:s.size,mtimeMs:s.mtimeMs};}catch{return}await new Promise(s=>setTimeout(s,20));try{let s=fs.statSync(e);o={size:s.size,mtimeMs:s.mtimeMs};}catch{return}if(r.size===o.size&&r.mtimeMs===o.mtimeMs)return}}function Qe(e,n={}){let t=n.debounceMs??100,r=n.refreshMs??(dt(e.sources)?6e4:0),o=n.pollMs??0,s=L(e),i=0,a=0,u=false,l=null,g=[],h=[],x=new Set,m=new Map,S={get:()=>s,reload:async()=>{await w();},dispose:async()=>{if(!u){u=true,l&&(clearTimeout(l),l=null);for(let y of h)clearInterval(y);for(let y of g)try{y.close();}catch{}}},get version(){return i}};async function w(){let y=++a;if(u)return;E();let A=Xe(e.sources);if(await Promise.all(A.map(_=>gt(_).catch(()=>{}))),u||y!==a)return;let b;try{b=L(e);}catch(_){try{n.onError?.(_,{version:i});}catch{}return}if(u||y!==a)return;let R=mt(s,b);s=b,i++;try{n.onUpdate?.(s,R);}catch{}}function p(){u||(l&&clearTimeout(l),l=setTimeout(()=>{l=null,w();},t));}function E(){let y=new Map;for(let A of Xe(e.sources)){let b=path.dirname(A),R=path.basename(A),_=y.get(b)??[];_.push(R),y.set(b,_);}for(let[A,b]of y){let R=m.get(A);R||(R=new Set,m.set(A,R));for(let J of b)R.add(J);let _=A;if(!x.has(_))try{let J=R,q=fs.watch(A,(Et,N)=>{let ge=typeof N=="string"?N:N?String(N):null;ge&&!J.has(ge)||p();});q.on("error",()=>{x.delete(_),m.delete(_),g.splice(g.indexOf(q),1),setTimeout(()=>{u||E();},0);}),g.push(q),x.add(_);}catch{}}}return E(),o>0&&h.push(setInterval(()=>{w();},o)),r>0&&h.push(setInterval(()=>{w();},r)),S}W();async function en(e){if(!e.schema)return console.error("Usage: watch -s schema.ts -c base.yaml,.env [-- cmd...]"),2;let n=await P(e.schema,e.schemaExport).catch(p=>(console.error(p.message),null));if(!n)return 2;let t=(e.config??".env,env").split(",").map(p=>p.trim()).filter(Boolean),r=null,o=()=>{if(!e.cmd?.length)return;s();let p=child_process.spawn(e.cmd[0],e.cmd.slice(1),{stdio:"inherit",shell:false});r=p,p.on("error",E=>{console.error(`watch: child failed to start: ${E.message}`),r===p&&(r=null);}),p.on("exit",(E,y)=>{r===p&&(r=null,typeof E=="number"&&E!==0?(console.error(`watch: child exited with code ${E}`),e.exitOnChildError&&u(E)):typeof y=="string"&&(console.error(`watch: child exited on signal ${y}`),e.exitOnChildError&&u(1)));});},s=()=>{let p=r;if(r=null,!p)return;try{p.kill();}catch{}setTimeout(()=>{try{p.kill("SIGKILL");}catch{}},2e3).unref();};if(e.once){e.cmd?.length&&console.error("watch: -- cmd is ignored with --once (single validation, nothing to supervise)");let{runCheck:p}=await Promise.resolve().then(()=>(le(),Me));return p({schema:e.schema,config:e.config,schemaExport:e.schemaExport,strict:e.strict,expand:e.expand,array:e.array,prefix:e.prefix,format:e.format,secretKeys:e.secretKeys})}let i=Qe({schema:n,sources:t.length?t:[".env","env"],unknownKeys:e.strict?"reject":"strip",expand:e.expand??true,arrayStrategy:e.array??"replace",prefix:e.prefix},{onUpdate:(p,E)=>{E.length!==0&&(console.log(`reload: ok changed=[${E.join(",")}]`),e.cmd?.length&&o());},onError:p=>{console.error(`reload: invalid, kept old
56
+ ${p.message}`),e.exitOnError&&i.dispose().then(()=>{s(),process.exitCode=1,a(1);});}}),c,f=new Promise(p=>{c=p;}),a=p=>{process.removeListener("SIGINT",S),process.removeListener("SIGTERM",w),process.removeListener("SIGINT",m),process.removeListener("SIGTERM",m),clearInterval(x),c(p);},u=p=>{i.dispose().then(()=>{s(),process.exitCode=p,a(p);});};o();let l=null,g=new Promise(p=>{l=p;}),h=()=>{i.dispose().then(()=>{s(),l();});},x=setInterval(()=>{(process.exitCode??0)!==0&&a(Number(process.exitCode));},100),m=()=>{clearInterval(x),g.then(()=>a(Number(process.exitCode??0)));};function S(){h();}function w(){h();}return process.once("SIGINT",S),process.once("SIGTERM",w),process.once("SIGINT",m),process.once("SIGTERM",m),f}async function yt(e=process.argv.slice(2)){let[n,...t]=e;if(!n||n==="--help"||n==="-h")return console.log(`typed-settings <check|init|gen|watch>
57
+
58
+ check -s schema.ts -c base.yaml,.env [--strict] [--no-expand] [--array replace|concat|mergeIndex] [--format human|json] [--schema-export NAME] [--prefix PFX] [--secret-keys a,b]
59
+ init --lib zod|valibot|arktype|yup|joi --format yaml|toml|env [--dir .] [--force|--dry-run|--check]
60
+ gen --schema src/config.ts --out .env.example --docs CONFIG.md [--schema-export NAME] [--prefix PFX] [--force]
61
+ watch -s schema.ts -c base.yaml [--strict] [--no-expand] [--array ...] [--format human|json] [--schema-export NAME] [--prefix PFX] [--secret-keys a,b] [--once] [--exit-on-error] [--exit-on-child-error] [-- cmd...]`),0;try{if(n==="check"){let{values:r}=util.parseArgs({args:t,allowNegative:!0,options:{schema:{type:"string",short:"s"},config:{type:"string",short:"c"},strict:{type:"boolean",default:!1},expand:{type:"boolean",default:!0},array:{type:"string",default:"replace"},format:{type:"string",default:"human"},"schema-export":{type:"string"},prefix:{type:"string"},"secret-keys":{type:"string"}}});return r.schema?r.array!==void 0&&!["replace","concat","mergeIndex"].includes(r.array)?(console.error(`E_USAGE: --array must be replace|concat|mergeIndex (got ${JSON.stringify(r.array)})`),2):r.format!==void 0&&!["human","json"].includes(r.format)?(console.error(`E_USAGE: --format must be human|json (got ${JSON.stringify(r.format)})`),2):await ue({schema:r.schema,config:r.config,strict:r.strict,expand:r.expand,array:r.array,format:r.format,schemaExport:r["schema-export"],prefix:r.prefix,secretKeys:r["secret-keys"]?.split(",").map(o=>o.trim()).filter(Boolean)}):(console.error("E_USAGE: check -s schema.ts -c base.yaml,.env"),2)}if(n==="init"){let{values:r}=util.parseArgs({args:t,options:{lib:{type:"string",default:"zod"},format:{type:"string",default:"env"},dir:{type:"string",default:"."},force:{type:"boolean",default:!1},"dry-run":{type:"boolean",default:!1},check:{type:"boolean",default:!1}}});return await Ve({lib:r.lib,format:r.format,dir:r.dir,force:r.force,dryRun:r["dry-run"],check:r.check})}if(n==="gen"){let{values:r}=util.parseArgs({args:t,options:{schema:{type:"string",short:"s"},"schema-export":{type:"string"},out:{type:"string"},docs:{type:"string"},prefix:{type:"string"},force:{type:"boolean",default:!1}}});return r.schema?await He({schema:r.schema,schemaExport:r["schema-export"],out:r.out,docs:r.docs,prefix:r.prefix,force:r.force}):(console.error("E_USAGE: gen --schema src/config.ts --out .env.example --docs CONFIG.md"),2)}if(n==="watch"){let r=t.indexOf("--"),o=r===-1?t:t.slice(0,r),s=r===-1?[]:t.slice(r+1),{values:i}=util.parseArgs({args:o,allowNegative:!0,options:{schema:{type:"string",short:"s"},config:{type:"string",short:"c"},strict:{type:"boolean",default:!1},expand:{type:"boolean",default:!0},array:{type:"string",default:"replace"},format:{type:"string",default:"human"},once:{type:"boolean",default:!1},"exit-on-error":{type:"boolean",default:!1},"exit-on-child-error":{type:"boolean",default:!1},"schema-export":{type:"string"},prefix:{type:"string"},"secret-keys":{type:"string"}}});return i.array!==void 0&&!["replace","concat","mergeIndex"].includes(i.array)?(console.error(`E_USAGE: --array must be replace|concat|mergeIndex (got ${JSON.stringify(i.array)})`),2):i.format!==void 0&&!["human","json"].includes(i.format)?(console.error(`E_USAGE: --format must be human|json (got ${JSON.stringify(i.format)})`),2):await en({schema:i.schema,config:i.config,schemaExport:i["schema-export"],strict:i.strict,expand:i.expand,array:i.array,format:i.format,prefix:i.prefix,secretKeys:i["secret-keys"]?.split(",").map(c=>c.trim()).filter(Boolean),once:i.once,exitOnError:i["exit-on-error"],exitOnChildError:i["exit-on-child-error"],cmd:s.length?s:void 0})}return console.error(`E_USAGE: unknown command: ${n}`),2}catch(r){return console.error(`E_USAGE: ${r.message}`),2}}var wt=process.argv[1]?.endsWith("main.js")||process.argv[1]?.endsWith("main.cjs");wt&&yt().then(e=>{process.exitCode=e;}).catch(e=>{console.error(e?.message??e),process.exitCode=2;});exports.main=yt;