@o3co/ts.hocon 1.11.0 → 1.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.ja.md +7 -5
- package/README.md +19 -10
- package/dist/adapters/env.cjs +471 -82
- package/dist/adapters/env.d.cts +1 -1
- package/dist/adapters/env.d.ts +1 -1
- package/dist/adapters/env.js +471 -82
- package/dist/adapters/json5.cjs +2450 -0
- package/dist/adapters/json5.d.cts +47 -0
- package/dist/adapters/json5.d.ts +47 -0
- package/dist/adapters/json5.js +2413 -0
- package/dist/adapters/jsonc.cjs +448 -81
- package/dist/adapters/jsonc.d.cts +13 -2
- package/dist/adapters/jsonc.d.ts +13 -2
- package/dist/adapters/jsonc.js +448 -81
- package/dist/adapters/properties.cjs +457 -81
- package/dist/adapters/properties.d.cts +1 -1
- package/dist/adapters/properties.d.ts +1 -1
- package/dist/adapters/properties.js +457 -81
- package/dist/adapters/toml.cjs +451 -81
- package/dist/adapters/toml.d.cts +3 -2
- package/dist/adapters/toml.d.ts +3 -2
- package/dist/adapters/toml.js +451 -81
- package/dist/adapters/yaml.cjs +461 -82
- package/dist/adapters/yaml.d.cts +3 -2
- package/dist/adapters/yaml.d.ts +3 -2
- package/dist/adapters/yaml.js +461 -82
- package/dist/{config-Dlq6rF3w.d.cts → config-6sApTEMM.d.cts} +22 -0
- package/dist/{config-Dlq6rF3w.d.ts → config-6sApTEMM.d.ts} +22 -0
- package/dist/index.cjs +491 -97
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +491 -97
- package/dist/zod.cjs +486 -91
- package/dist/zod.d.cts +1 -1
- package/dist/zod.d.ts +1 -1
- package/dist/zod.js +486 -91
- package/package.json +12 -2
package/dist/adapters/yaml.cjs
CHANGED
|
@@ -72,13 +72,22 @@ function coerceNumber(value) {
|
|
|
72
72
|
return Number(value);
|
|
73
73
|
}
|
|
74
74
|
var DURATION_UNITS = {
|
|
75
|
+
// S19.1–S19.3: the bare nano/micro/milli (+plural) aliases are part of the
|
|
76
|
+
// spec's unit lists (HOCON.md L1307–L1309) and accepted by Lightbend
|
|
77
|
+
// (typesafe-config 1.4.6 probe, 2026-08-18); they were missing here.
|
|
75
78
|
ns: 1e-6,
|
|
79
|
+
nano: 1e-6,
|
|
80
|
+
nanos: 1e-6,
|
|
76
81
|
nanosecond: 1e-6,
|
|
77
82
|
nanoseconds: 1e-6,
|
|
78
83
|
us: 1e-3,
|
|
84
|
+
micro: 1e-3,
|
|
85
|
+
micros: 1e-3,
|
|
79
86
|
microsecond: 1e-3,
|
|
80
87
|
microseconds: 1e-3,
|
|
81
88
|
ms: 1,
|
|
89
|
+
milli: 1,
|
|
90
|
+
millis: 1,
|
|
82
91
|
millisecond: 1,
|
|
83
92
|
milliseconds: 1,
|
|
84
93
|
s: 1e3,
|
|
@@ -130,37 +139,76 @@ function parseDuration(value, outputUnit = "ms") {
|
|
|
130
139
|
return ms / divisor;
|
|
131
140
|
}
|
|
132
141
|
var BYTE_UNITS = {
|
|
142
|
+
// S21.1–S21.4 — the EXACT Lightbend/typesafe-config unit set (1.4.6 probe,
|
|
143
|
+
// 2026-08-18). Multi-letter units are case-sensitive: the SI decimal short
|
|
144
|
+
// form is `kB` (NOT `KB`/`kb` — Lightbend rejects both), higher decimals
|
|
145
|
+
// are `MB`…`YB`, binary prefixes are `Ki`/`KiB`…`Yi`/`YiB` with capital
|
|
146
|
+
// first letter, and long forms are lowercase only (`kilobyte`, never
|
|
147
|
+
// `Kilobyte`). Only the bare byte unit (`B`/`b`) and the single-letter
|
|
148
|
+
// -Xmx forms accept both cases. The old case-insensitive fallback and the
|
|
149
|
+
// lowercase alias rows accepted spellings Lightbend rejects — removed.
|
|
133
150
|
B: 1,
|
|
151
|
+
b: 1,
|
|
134
152
|
byte: 1,
|
|
135
153
|
bytes: 1,
|
|
136
|
-
|
|
154
|
+
kB: 1e3,
|
|
137
155
|
kilobyte: 1e3,
|
|
138
156
|
kilobytes: 1e3,
|
|
139
|
-
KiB: 1024,
|
|
140
|
-
kibibyte: 1024,
|
|
141
|
-
kibibytes: 1024,
|
|
142
157
|
MB: 1e6,
|
|
143
158
|
megabyte: 1e6,
|
|
144
159
|
megabytes: 1e6,
|
|
145
|
-
MiB: 1048576,
|
|
146
|
-
mebibyte: 1048576,
|
|
147
|
-
mebibytes: 1048576,
|
|
148
160
|
GB: 1e9,
|
|
149
161
|
gigabyte: 1e9,
|
|
150
162
|
gigabytes: 1e9,
|
|
151
|
-
GiB: 1073741824,
|
|
152
|
-
gibibyte: 1073741824,
|
|
153
|
-
gibibytes: 1073741824,
|
|
154
163
|
TB: 1e12,
|
|
155
164
|
terabyte: 1e12,
|
|
156
165
|
terabytes: 1e12,
|
|
166
|
+
PB: 1e15,
|
|
167
|
+
petabyte: 1e15,
|
|
168
|
+
petabytes: 1e15,
|
|
169
|
+
EB: 1e18,
|
|
170
|
+
exabyte: 1e18,
|
|
171
|
+
exabytes: 1e18,
|
|
172
|
+
ZB: 1e21,
|
|
173
|
+
zettabyte: 1e21,
|
|
174
|
+
zettabytes: 1e21,
|
|
175
|
+
YB: 1e24,
|
|
176
|
+
yottabyte: 1e24,
|
|
177
|
+
yottabytes: 1e24,
|
|
178
|
+
Ki: 1024,
|
|
179
|
+
KiB: 1024,
|
|
180
|
+
kibibyte: 1024,
|
|
181
|
+
kibibytes: 1024,
|
|
182
|
+
Mi: 1048576,
|
|
183
|
+
MiB: 1048576,
|
|
184
|
+
mebibyte: 1048576,
|
|
185
|
+
mebibytes: 1048576,
|
|
186
|
+
Gi: 1073741824,
|
|
187
|
+
GiB: 1073741824,
|
|
188
|
+
gibibyte: 1073741824,
|
|
189
|
+
gibibytes: 1073741824,
|
|
190
|
+
Ti: 1099511627776,
|
|
157
191
|
TiB: 1099511627776,
|
|
158
192
|
tebibyte: 1099511627776,
|
|
159
193
|
tebibytes: 1099511627776,
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
194
|
+
Pi: 1024 ** 5,
|
|
195
|
+
PiB: 1024 ** 5,
|
|
196
|
+
pebibyte: 1024 ** 5,
|
|
197
|
+
pebibytes: 1024 ** 5,
|
|
198
|
+
Ei: 1024 ** 6,
|
|
199
|
+
EiB: 1024 ** 6,
|
|
200
|
+
exbibyte: 1024 ** 6,
|
|
201
|
+
exbibytes: 1024 ** 6,
|
|
202
|
+
Zi: 1024 ** 7,
|
|
203
|
+
ZiB: 1024 ** 7,
|
|
204
|
+
zebibyte: 1024 ** 7,
|
|
205
|
+
zebibytes: 1024 ** 7,
|
|
206
|
+
Yi: 1024 ** 8,
|
|
207
|
+
YiB: 1024 ** 8,
|
|
208
|
+
yobibyte: 1024 ** 8,
|
|
209
|
+
yobibytes: 1024 ** 8,
|
|
210
|
+
// S21.4 — single-letter abbreviations → powers of two (java -Xmx
|
|
211
|
+
// convention); Lightbend accepts BOTH cases here, through the full ladder.
|
|
164
212
|
K: 1024,
|
|
165
213
|
k: 1024,
|
|
166
214
|
M: 1024 ** 2,
|
|
@@ -173,16 +221,10 @@ var BYTE_UNITS = {
|
|
|
173
221
|
p: 1024 ** 5,
|
|
174
222
|
E: 1024 ** 6,
|
|
175
223
|
e: 1024 ** 6,
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
mb: 1e6,
|
|
181
|
-
mib: 1048576,
|
|
182
|
-
gb: 1e9,
|
|
183
|
-
gib: 1073741824,
|
|
184
|
-
tb: 1e12,
|
|
185
|
-
tib: 1099511627776
|
|
224
|
+
Z: 1024 ** 7,
|
|
225
|
+
z: 1024 ** 7,
|
|
226
|
+
Y: 1024 ** 8,
|
|
227
|
+
y: 1024 ** 8
|
|
186
228
|
};
|
|
187
229
|
var OUTPUT_BYTE_UNITS = {
|
|
188
230
|
B: 1,
|
|
@@ -220,10 +262,7 @@ function parseBytes(value, outputUnit = "B") {
|
|
|
220
262
|
}
|
|
221
263
|
return bytes2 / divisor;
|
|
222
264
|
}
|
|
223
|
-
|
|
224
|
-
if (mult === void 0) {
|
|
225
|
-
mult = BYTE_UNITS[unit.toLowerCase()];
|
|
226
|
-
}
|
|
265
|
+
const mult = BYTE_UNITS[unit];
|
|
227
266
|
if (mult === void 0) return NaN;
|
|
228
267
|
const bytes = num * mult;
|
|
229
268
|
if (Math.abs(bytes) > Number.MAX_SAFE_INTEGER) {
|
|
@@ -270,35 +309,114 @@ function stringSegmentsToKey(segments) {
|
|
|
270
309
|
return t;
|
|
271
310
|
}).join(".");
|
|
272
311
|
}
|
|
312
|
+
function prefixSelfRefRemainder(s, fullKey) {
|
|
313
|
+
const texts = s.segments.map((seg) => seg.text);
|
|
314
|
+
if (!stringSegmentsToKey(texts).startsWith(fullKey + ".")) return null;
|
|
315
|
+
for (let n = 1; n < texts.length; n++) {
|
|
316
|
+
if (stringSegmentsToKey(texts.slice(0, n)) === fullKey) return texts.slice(n);
|
|
317
|
+
}
|
|
318
|
+
return null;
|
|
319
|
+
}
|
|
320
|
+
function navigateResolverValue(v, remainder) {
|
|
321
|
+
let cur = v;
|
|
322
|
+
for (const seg of remainder) {
|
|
323
|
+
if (isSubst(cur) || isConcat(cur)) return null;
|
|
324
|
+
if (isResObj(cur)) {
|
|
325
|
+
const next = cur.fields.get(seg);
|
|
326
|
+
if (next === void 0) return void 0;
|
|
327
|
+
cur = next;
|
|
328
|
+
continue;
|
|
329
|
+
}
|
|
330
|
+
const hv = cur;
|
|
331
|
+
if (hv.kind === "object") {
|
|
332
|
+
const next = hv.fields.get(seg);
|
|
333
|
+
if (next === void 0) return void 0;
|
|
334
|
+
cur = next;
|
|
335
|
+
continue;
|
|
336
|
+
}
|
|
337
|
+
return void 0;
|
|
338
|
+
}
|
|
339
|
+
return cur;
|
|
340
|
+
}
|
|
341
|
+
function foldPrefixSelfRef(s, replacement, remainder) {
|
|
342
|
+
const navigated = navigateResolverValue(replacement, remainder);
|
|
343
|
+
if (navigated === null) return s;
|
|
344
|
+
if (navigated === void 0) {
|
|
345
|
+
return {
|
|
346
|
+
_kind: "subst-placeholder",
|
|
347
|
+
segments: s.segments.map((seg) => ({ text: seg.text, line: seg.line, col: seg.col })),
|
|
348
|
+
optional: s.optional,
|
|
349
|
+
knownAbsent: true,
|
|
350
|
+
listSuffix: s.listSuffix,
|
|
351
|
+
line: s.line,
|
|
352
|
+
col: s.col,
|
|
353
|
+
prefixLen: s.prefixLen
|
|
354
|
+
};
|
|
355
|
+
}
|
|
356
|
+
return cloneResolverValue(navigated);
|
|
357
|
+
}
|
|
358
|
+
function mergeResObjLayers(base, top) {
|
|
359
|
+
const fields = new Map(base.fields);
|
|
360
|
+
for (const [k, tv] of top.fields) {
|
|
361
|
+
const bv = fields.get(k);
|
|
362
|
+
if (bv !== void 0 && isResObj(bv) && isResObj(tv)) {
|
|
363
|
+
fields.set(k, mergeResObjLayers(bv, tv));
|
|
364
|
+
} else {
|
|
365
|
+
fields.set(k, tv);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
const priorValues = new Map(base.priorValues);
|
|
369
|
+
for (const [k, pv] of top.priorValues) priorValues.set(k, pv);
|
|
370
|
+
const resetKeys = new Set(base.resetKeys);
|
|
371
|
+
for (const k of top.resetKeys) resetKeys.add(k);
|
|
372
|
+
return {
|
|
373
|
+
_kind: "res-obj",
|
|
374
|
+
fields,
|
|
375
|
+
priorValues,
|
|
376
|
+
resetKeys
|
|
377
|
+
};
|
|
378
|
+
}
|
|
273
379
|
function containsSelfRef(v, fullKey) {
|
|
274
|
-
|
|
275
|
-
|
|
380
|
+
return containsSelfRefInner(v, fullKey, true);
|
|
381
|
+
}
|
|
382
|
+
function containsSelfRefInner(v, fullKey, allowPrefix) {
|
|
383
|
+
if (isSubst(v))
|
|
384
|
+
return !v.knownAbsent && (substFullKey(v) === fullKey || allowPrefix && prefixSelfRefRemainder(v, fullKey) !== null);
|
|
385
|
+
if (isConcat(v)) return v.nodes.some((n) => containsSelfRefInner(n, fullKey, allowPrefix));
|
|
276
386
|
if (isResObj(v)) {
|
|
277
387
|
for (const f of v.fields.values()) {
|
|
278
|
-
if (
|
|
388
|
+
if (containsSelfRefInner(f, fullKey, false)) return true;
|
|
279
389
|
}
|
|
280
390
|
return false;
|
|
281
391
|
}
|
|
282
392
|
const hv = v;
|
|
283
393
|
if (hv.kind === "array") {
|
|
284
|
-
return hv.items.some((item) =>
|
|
394
|
+
return hv.items.some((item) => containsSelfRefInner(item, fullKey, allowPrefix));
|
|
285
395
|
}
|
|
286
396
|
if (hv.kind === "object") {
|
|
287
397
|
for (const f of hv.fields.values()) {
|
|
288
|
-
if (
|
|
398
|
+
if (containsSelfRefInner(f, fullKey, false)) return true;
|
|
289
399
|
}
|
|
290
400
|
return false;
|
|
291
401
|
}
|
|
292
402
|
return false;
|
|
293
403
|
}
|
|
294
404
|
function foldSelfRef(v, fullKey, replacement) {
|
|
405
|
+
return foldSelfRefInner(v, fullKey, replacement, true);
|
|
406
|
+
}
|
|
407
|
+
function foldSelfRefInner(v, fullKey, replacement, allowPrefix) {
|
|
295
408
|
if (isSubst(v)) {
|
|
296
|
-
|
|
409
|
+
if (substFullKey(v) === fullKey) return replacement;
|
|
410
|
+
if (allowPrefix) {
|
|
411
|
+
const remainder = prefixSelfRefRemainder(v, fullKey);
|
|
412
|
+
if (remainder !== null) return foldPrefixSelfRef(v, replacement, remainder);
|
|
413
|
+
}
|
|
414
|
+
return v;
|
|
297
415
|
}
|
|
298
416
|
if (isConcat(v)) {
|
|
299
417
|
return {
|
|
300
418
|
_kind: "concat-placeholder",
|
|
301
|
-
nodes: v.nodes.map((n) =>
|
|
419
|
+
nodes: v.nodes.map((n) => foldSelfRefInner(n, fullKey, replacement, allowPrefix)),
|
|
302
420
|
line: v.line,
|
|
303
421
|
col: v.col
|
|
304
422
|
};
|
|
@@ -306,7 +424,7 @@ function foldSelfRef(v, fullKey, replacement) {
|
|
|
306
424
|
if (isResObj(v)) {
|
|
307
425
|
const newFields = /* @__PURE__ */ new Map();
|
|
308
426
|
for (const [k, val] of v.fields) {
|
|
309
|
-
newFields.set(k,
|
|
427
|
+
newFields.set(k, foldSelfRefInner(val, fullKey, replacement, false));
|
|
310
428
|
}
|
|
311
429
|
return { _kind: "res-obj", fields: newFields, priorValues: new Map(v.priorValues), resetKeys: new Set(v.resetKeys) };
|
|
312
430
|
}
|
|
@@ -314,13 +432,15 @@ function foldSelfRef(v, fullKey, replacement) {
|
|
|
314
432
|
if (hv.kind === "array") {
|
|
315
433
|
return {
|
|
316
434
|
kind: "array",
|
|
317
|
-
items: hv.items.map(
|
|
435
|
+
items: hv.items.map(
|
|
436
|
+
(item) => foldSelfRefInner(item, fullKey, replacement, allowPrefix)
|
|
437
|
+
)
|
|
318
438
|
};
|
|
319
439
|
}
|
|
320
440
|
if (hv.kind === "object") {
|
|
321
441
|
const newFields = /* @__PURE__ */ new Map();
|
|
322
442
|
for (const [k, val] of hv.fields) {
|
|
323
|
-
newFields.set(k,
|
|
443
|
+
newFields.set(k, foldSelfRefInner(val, fullKey, replacement, false));
|
|
324
444
|
}
|
|
325
445
|
return { kind: "object", fields: newFields };
|
|
326
446
|
}
|
|
@@ -329,10 +449,26 @@ function foldSelfRef(v, fullKey, replacement) {
|
|
|
329
449
|
function foldOrSkipPrior(prior, fullKey, old) {
|
|
330
450
|
if (!containsSelfRef(prior, fullKey)) return cloneResolverValue(prior);
|
|
331
451
|
if (old === void 0) return foldOptionalSelfRefAbsent(prior, fullKey);
|
|
452
|
+
if (isSubst(prior)) {
|
|
453
|
+
const remainder = prefixSelfRefRemainder(prior, fullKey);
|
|
454
|
+
if (remainder !== null) {
|
|
455
|
+
const navigated = navigateResolverValue(old, remainder);
|
|
456
|
+
if (navigated === void 0 && prior.optional) return cloneResolverValue(old);
|
|
457
|
+
if (navigated !== null && navigated !== void 0 && isResObj(navigated) && isResObj(old)) {
|
|
458
|
+
return mergeResObjLayers(
|
|
459
|
+
cloneResolverValue(old),
|
|
460
|
+
cloneResolverValue(navigated)
|
|
461
|
+
);
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
}
|
|
332
465
|
return foldSelfRef(prior, fullKey, old);
|
|
333
466
|
}
|
|
334
467
|
function foldOptionalSelfRefAbsent(v, fullKey) {
|
|
335
|
-
|
|
468
|
+
return foldOptionalSelfRefAbsentInner(v, fullKey, true);
|
|
469
|
+
}
|
|
470
|
+
function foldOptionalSelfRefAbsentInner(v, fullKey, allowPrefix) {
|
|
471
|
+
if (isSubst(v) && (substFullKey(v) === fullKey || allowPrefix && prefixSelfRefRemainder(v, fullKey) !== null)) {
|
|
336
472
|
if (!v.optional) return void 0;
|
|
337
473
|
return {
|
|
338
474
|
_kind: "subst-placeholder",
|
|
@@ -348,7 +484,7 @@ function foldOptionalSelfRefAbsent(v, fullKey) {
|
|
|
348
484
|
if (isConcat(v)) {
|
|
349
485
|
const nodes = [];
|
|
350
486
|
for (const node of v.nodes) {
|
|
351
|
-
const folded =
|
|
487
|
+
const folded = foldOptionalSelfRefAbsentInner(node, fullKey, allowPrefix);
|
|
352
488
|
if (folded === void 0) return void 0;
|
|
353
489
|
nodes.push(folded);
|
|
354
490
|
}
|
|
@@ -357,7 +493,7 @@ function foldOptionalSelfRefAbsent(v, fullKey) {
|
|
|
357
493
|
if (isResObj(v)) {
|
|
358
494
|
const fields = /* @__PURE__ */ new Map();
|
|
359
495
|
for (const [key, value] of v.fields) {
|
|
360
|
-
const folded =
|
|
496
|
+
const folded = foldOptionalSelfRefAbsentInner(value, fullKey, false);
|
|
361
497
|
if (folded === void 0) return void 0;
|
|
362
498
|
fields.set(key, folded);
|
|
363
499
|
}
|
|
@@ -367,7 +503,7 @@ function foldOptionalSelfRefAbsent(v, fullKey) {
|
|
|
367
503
|
if (hv.kind === "array") {
|
|
368
504
|
const items = [];
|
|
369
505
|
for (const item of hv.items) {
|
|
370
|
-
const folded =
|
|
506
|
+
const folded = foldOptionalSelfRefAbsentInner(item, fullKey, allowPrefix);
|
|
371
507
|
if (folded === void 0) return void 0;
|
|
372
508
|
items.push(folded);
|
|
373
509
|
}
|
|
@@ -376,7 +512,7 @@ function foldOptionalSelfRefAbsent(v, fullKey) {
|
|
|
376
512
|
if (hv.kind === "object") {
|
|
377
513
|
const fields = /* @__PURE__ */ new Map();
|
|
378
514
|
for (const [key, value] of hv.fields) {
|
|
379
|
-
const folded =
|
|
515
|
+
const folded = foldOptionalSelfRefAbsentInner(value, fullKey, false);
|
|
380
516
|
if (folded === void 0) return void 0;
|
|
381
517
|
fields.set(key, folded);
|
|
382
518
|
}
|
|
@@ -558,6 +694,27 @@ function stripBom(input) {
|
|
|
558
694
|
return input.charCodeAt(0) === 65279 ? input.slice(1) : input;
|
|
559
695
|
}
|
|
560
696
|
|
|
697
|
+
// src/internal/depth.ts
|
|
698
|
+
function guardStackDepth(fn, wrap) {
|
|
699
|
+
try {
|
|
700
|
+
return fn();
|
|
701
|
+
} catch (e) {
|
|
702
|
+
if (!isStackOverflow(e)) throw e;
|
|
703
|
+
throw wrap(STACK_MESSAGE);
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
var STACK_MESSAGE = "input is nested too deeply for this engine's stack, or contains a cycle (flatten the document, or break the cycle)";
|
|
707
|
+
function isStackOverflow(e) {
|
|
708
|
+
if (!(e instanceof RangeError)) return false;
|
|
709
|
+
const m = e.message.toLowerCase();
|
|
710
|
+
return m.includes("call stack") || // V8: "Maximum call stack size exceeded"
|
|
711
|
+
m.includes("recursion") || // SpiderMonkey: "too much recursion"
|
|
712
|
+
m.includes("stack overflow");
|
|
713
|
+
}
|
|
714
|
+
function depthError(message) {
|
|
715
|
+
return new ConfigError(message, "");
|
|
716
|
+
}
|
|
717
|
+
|
|
561
718
|
// src/value/numeric-array.ts
|
|
562
719
|
function numericObjectToArray(value) {
|
|
563
720
|
if (value.kind !== "object") return null;
|
|
@@ -612,6 +769,12 @@ var SubstitutionResolver = class {
|
|
|
612
769
|
// Cross-impl with rs.hocon v1.5.1's resolving_field_path (same purpose,
|
|
613
770
|
// same prefix-match semantics).
|
|
614
771
|
this.resolvingFieldPath = [];
|
|
772
|
+
// S13a.12 recursion guard: field keys whose prior is currently being
|
|
773
|
+
// resolved through the prefix-self-ref branch. Saved priors are
|
|
774
|
+
// prefix-self-ref-free by the fold invariant, so re-entry only happens on
|
|
775
|
+
// a shape the fold could not see through (a live subst mid-navigation) —
|
|
776
|
+
// report it as a cycle instead of recursing forever.
|
|
777
|
+
this.resolvingPrefixPriors = /* @__PURE__ */ new Set();
|
|
615
778
|
}
|
|
616
779
|
/** Returns a prefix for error messages, including origin info when set. */
|
|
617
780
|
originPrefix() {
|
|
@@ -626,46 +789,57 @@ var SubstitutionResolver = class {
|
|
|
626
789
|
this.resolvingFieldPath.push(key);
|
|
627
790
|
const fullCacheKey = stringSegmentsToKey(this.resolvingFieldPath);
|
|
628
791
|
this.cache.delete(fullCacheKey);
|
|
629
|
-
let resolved;
|
|
630
792
|
try {
|
|
631
|
-
resolved = this.resolveVal(val, obj);
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
793
|
+
const resolved = this.resolveVal(val, obj);
|
|
794
|
+
if (resolved !== void 0) {
|
|
795
|
+
if (resolved.kind === "object") {
|
|
796
|
+
const prior = obj.priorValues.get(key);
|
|
797
|
+
if (prior !== void 0) {
|
|
798
|
+
const priorResolved = this.resolveVal(prior, obj);
|
|
799
|
+
if (priorResolved !== void 0 && priorResolved.kind === "object") {
|
|
800
|
+
const finalValue = deepMergeHoconValues(
|
|
801
|
+
priorResolved,
|
|
802
|
+
resolved
|
|
803
|
+
);
|
|
804
|
+
result.set(key, finalValue);
|
|
805
|
+
this.cache.set(fullCacheKey, finalValue);
|
|
806
|
+
this.cacheDescendants(fullCacheKey, finalValue);
|
|
807
|
+
continue;
|
|
808
|
+
}
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
result.set(key, resolved);
|
|
812
|
+
this.cache.set(fullCacheKey, resolved);
|
|
813
|
+
this.cacheDescendants(fullCacheKey, resolved);
|
|
814
|
+
} else {
|
|
637
815
|
const prior = obj.priorValues.get(key);
|
|
638
816
|
if (prior !== void 0) {
|
|
639
817
|
const priorResolved = this.resolveVal(prior, obj);
|
|
640
|
-
if (priorResolved !== void 0
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
);
|
|
645
|
-
result.set(key, finalValue);
|
|
646
|
-
this.cache.set(fullCacheKey, finalValue);
|
|
647
|
-
this.cacheDescendants(fullCacheKey, finalValue);
|
|
648
|
-
continue;
|
|
818
|
+
if (priorResolved !== void 0) {
|
|
819
|
+
result.set(key, priorResolved);
|
|
820
|
+
this.cache.set(fullCacheKey, priorResolved);
|
|
821
|
+
this.cacheDescendants(fullCacheKey, priorResolved);
|
|
649
822
|
}
|
|
650
823
|
}
|
|
651
824
|
}
|
|
652
|
-
|
|
653
|
-
this.
|
|
654
|
-
this.cacheDescendants(fullCacheKey, resolved);
|
|
655
|
-
} else {
|
|
656
|
-
const prior = obj.priorValues.get(key);
|
|
657
|
-
if (prior !== void 0) {
|
|
658
|
-
const priorResolved = this.resolveVal(prior, obj);
|
|
659
|
-
if (priorResolved !== void 0) {
|
|
660
|
-
result.set(key, priorResolved);
|
|
661
|
-
this.cache.set(fullCacheKey, priorResolved);
|
|
662
|
-
this.cacheDescendants(fullCacheKey, priorResolved);
|
|
663
|
-
}
|
|
664
|
-
}
|
|
825
|
+
} finally {
|
|
826
|
+
this.resolvingFieldPath.pop();
|
|
665
827
|
}
|
|
666
828
|
}
|
|
667
829
|
return { kind: "object", fields: result };
|
|
668
830
|
}
|
|
831
|
+
/** S13a.12: walk resolved-object fields by segment text. A missing segment
|
|
832
|
+
* or a walk into a scalar/array is path-absent → undefined. */
|
|
833
|
+
navigateResolved(v, remainder) {
|
|
834
|
+
let cur = v;
|
|
835
|
+
for (const seg of remainder) {
|
|
836
|
+
if (cur.kind !== "object") return void 0;
|
|
837
|
+
const next = cur.fields.get(seg);
|
|
838
|
+
if (next === void 0) return void 0;
|
|
839
|
+
cur = next;
|
|
840
|
+
}
|
|
841
|
+
return cur;
|
|
842
|
+
}
|
|
669
843
|
cacheDescendants(prefix, value) {
|
|
670
844
|
if (value.kind !== "object") return;
|
|
671
845
|
for (const [key, child] of value.fields) {
|
|
@@ -688,17 +862,59 @@ var SubstitutionResolver = class {
|
|
|
688
862
|
if (isResObj(v)) return this.resolveResObj(v);
|
|
689
863
|
const hv = v;
|
|
690
864
|
if (hv.kind === "array") {
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
)
|
|
696
|
-
}
|
|
865
|
+
const items = [];
|
|
866
|
+
for (const item of hv.items) {
|
|
867
|
+
const resolved = this.resolveVal(item, scope);
|
|
868
|
+
if (resolved === void 0) continue;
|
|
869
|
+
items.push(resolved);
|
|
870
|
+
}
|
|
871
|
+
return { kind: "array", items };
|
|
697
872
|
}
|
|
698
873
|
return hv;
|
|
699
874
|
}
|
|
700
875
|
resolveSubst(s, scope) {
|
|
701
|
-
if (s.knownAbsent)
|
|
876
|
+
if (s.knownAbsent) {
|
|
877
|
+
if (!s.optional) {
|
|
878
|
+
if (this.opts.allowUnresolved) return s;
|
|
879
|
+
const k = s.listSuffix ? `${segmentsToKey(s.segments)}[]` : segmentsToKey(s.segments);
|
|
880
|
+
throw new ResolveError(
|
|
881
|
+
`${this.originPrefix()}could not resolve substitution: \${${k}}`,
|
|
882
|
+
k,
|
|
883
|
+
s.line,
|
|
884
|
+
s.col
|
|
885
|
+
);
|
|
886
|
+
}
|
|
887
|
+
return void 0;
|
|
888
|
+
}
|
|
889
|
+
{
|
|
890
|
+
const rfp = this.resolvingFieldPath;
|
|
891
|
+
const sTexts = s.segments.map((seg) => seg.text);
|
|
892
|
+
if (rfp.length > 0 && rfp.length < sTexts.length && stringSegmentsToKey(sTexts.slice(0, rfp.length)) === stringSegmentsToKey(rfp)) {
|
|
893
|
+
const guardKey = stringSegmentsToKey(rfp);
|
|
894
|
+
const prior = scope.priorValues.get(rfp[rfp.length - 1]);
|
|
895
|
+
if (prior !== void 0 && !this.resolvingPrefixPriors.has(guardKey)) {
|
|
896
|
+
this.resolvingPrefixPriors.add(guardKey);
|
|
897
|
+
try {
|
|
898
|
+
const priorResolved = this.resolveVal(prior, scope);
|
|
899
|
+
if (priorResolved !== void 0) {
|
|
900
|
+
const navigated = this.navigateResolved(priorResolved, sTexts.slice(rfp.length));
|
|
901
|
+
if (navigated !== void 0) return navigated;
|
|
902
|
+
}
|
|
903
|
+
} finally {
|
|
904
|
+
this.resolvingPrefixPriors.delete(guardKey);
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
if (s.optional) return void 0;
|
|
908
|
+
if (this.opts.allowUnresolved) return s;
|
|
909
|
+
const k = s.listSuffix ? `${segmentsToKey(s.segments)}[]` : segmentsToKey(s.segments);
|
|
910
|
+
throw new ResolveError(
|
|
911
|
+
`${this.originPrefix()}could not resolve substitution: \${${k}}`,
|
|
912
|
+
k,
|
|
913
|
+
s.line,
|
|
914
|
+
s.col
|
|
915
|
+
);
|
|
916
|
+
}
|
|
917
|
+
}
|
|
702
918
|
const key = s.listSuffix ? `${segmentsToKey(s.segments)}[]` : segmentsToKey(s.segments);
|
|
703
919
|
if (this.cache.has(key)) return this.cache.get(key);
|
|
704
920
|
if (this.resolving.has(key)) {
|
|
@@ -1018,6 +1234,121 @@ function hoconValueToResObj2(value) {
|
|
|
1018
1234
|
return obj;
|
|
1019
1235
|
}
|
|
1020
1236
|
|
|
1237
|
+
// src/render-hocon.ts
|
|
1238
|
+
function renderHoconFromRoot(root) {
|
|
1239
|
+
const out = [];
|
|
1240
|
+
renderObjectBody(out, root, 0);
|
|
1241
|
+
return out.join("");
|
|
1242
|
+
}
|
|
1243
|
+
function renderObjectBody(out, o, depth) {
|
|
1244
|
+
const indent = " ".repeat(depth);
|
|
1245
|
+
for (const [k, v] of o.fields) {
|
|
1246
|
+
out.push(indent, renderKey(k));
|
|
1247
|
+
if (v.kind === "object") {
|
|
1248
|
+
out.push(" {");
|
|
1249
|
+
if (v.fields.size === 0) {
|
|
1250
|
+
out.push("}\n");
|
|
1251
|
+
continue;
|
|
1252
|
+
}
|
|
1253
|
+
out.push("\n");
|
|
1254
|
+
renderObjectBody(out, v, depth + 1);
|
|
1255
|
+
out.push(indent, "}\n");
|
|
1256
|
+
} else {
|
|
1257
|
+
out.push(" = ");
|
|
1258
|
+
renderValue(out, v, depth);
|
|
1259
|
+
out.push("\n");
|
|
1260
|
+
}
|
|
1261
|
+
}
|
|
1262
|
+
}
|
|
1263
|
+
function renderValue(out, v, depth) {
|
|
1264
|
+
switch (v.kind) {
|
|
1265
|
+
case "object": {
|
|
1266
|
+
if (v.fields.size === 0) {
|
|
1267
|
+
out.push("{}");
|
|
1268
|
+
return;
|
|
1269
|
+
}
|
|
1270
|
+
out.push("{\n");
|
|
1271
|
+
renderObjectBody(out, v, depth + 1);
|
|
1272
|
+
out.push(" ".repeat(depth), "}");
|
|
1273
|
+
return;
|
|
1274
|
+
}
|
|
1275
|
+
case "array":
|
|
1276
|
+
renderArray(out, v, depth);
|
|
1277
|
+
return;
|
|
1278
|
+
case "scalar":
|
|
1279
|
+
out.push(renderScalar(v));
|
|
1280
|
+
return;
|
|
1281
|
+
default:
|
|
1282
|
+
throw new ConfigError(
|
|
1283
|
+
"renderHocon: unrenderable value (config must be resolved data)",
|
|
1284
|
+
""
|
|
1285
|
+
);
|
|
1286
|
+
}
|
|
1287
|
+
}
|
|
1288
|
+
function renderArray(out, a, depth) {
|
|
1289
|
+
if (a.items.length === 0) {
|
|
1290
|
+
out.push("[]");
|
|
1291
|
+
return;
|
|
1292
|
+
}
|
|
1293
|
+
const inner = " ".repeat(depth + 1);
|
|
1294
|
+
out.push("[\n");
|
|
1295
|
+
for (const e of a.items) {
|
|
1296
|
+
out.push(inner);
|
|
1297
|
+
renderValue(out, e, depth + 1);
|
|
1298
|
+
out.push("\n");
|
|
1299
|
+
}
|
|
1300
|
+
out.push(" ".repeat(depth), "]");
|
|
1301
|
+
}
|
|
1302
|
+
function renderScalar(s) {
|
|
1303
|
+
switch (s.valueType) {
|
|
1304
|
+
case "null":
|
|
1305
|
+
return "null";
|
|
1306
|
+
case "boolean":
|
|
1307
|
+
case "number":
|
|
1308
|
+
return s.raw;
|
|
1309
|
+
case "string":
|
|
1310
|
+
return renderString(s.raw);
|
|
1311
|
+
}
|
|
1312
|
+
}
|
|
1313
|
+
var SAFE_UNQUOTED_KEY = /^[A-Za-z0-9_-]+$/;
|
|
1314
|
+
function renderKey(k) {
|
|
1315
|
+
if (k === "include") return quoteString(k);
|
|
1316
|
+
return SAFE_UNQUOTED_KEY.test(k) ? k : quoteString(k);
|
|
1317
|
+
}
|
|
1318
|
+
var SAFE_BARE_STRING = /^[A-Za-z][A-Za-z0-9_-]*$/;
|
|
1319
|
+
var STRING_KEYWORDS = /* @__PURE__ */ new Set(["true", "false", "null", "yes", "no", "on", "off"]);
|
|
1320
|
+
function renderString(s) {
|
|
1321
|
+
return SAFE_BARE_STRING.test(s) && !STRING_KEYWORDS.has(s.toLowerCase()) ? s : quoteString(s);
|
|
1322
|
+
}
|
|
1323
|
+
function quoteString(s) {
|
|
1324
|
+
if (s.includes("\n") && !s.includes("\r") && !s.includes('"""') && !s.endsWith('"')) {
|
|
1325
|
+
return `"""${s}"""`;
|
|
1326
|
+
}
|
|
1327
|
+
let b = '"';
|
|
1328
|
+
for (const ch of s) {
|
|
1329
|
+
switch (ch) {
|
|
1330
|
+
case '"':
|
|
1331
|
+
b += '\\"';
|
|
1332
|
+
break;
|
|
1333
|
+
case "\\":
|
|
1334
|
+
b += "\\\\";
|
|
1335
|
+
break;
|
|
1336
|
+
case "\n":
|
|
1337
|
+
b += "\\n";
|
|
1338
|
+
break;
|
|
1339
|
+
case "\r":
|
|
1340
|
+
b += "\\r";
|
|
1341
|
+
break;
|
|
1342
|
+
case " ":
|
|
1343
|
+
b += "\\t";
|
|
1344
|
+
break;
|
|
1345
|
+
default:
|
|
1346
|
+
b += ch;
|
|
1347
|
+
}
|
|
1348
|
+
}
|
|
1349
|
+
return b + '"';
|
|
1350
|
+
}
|
|
1351
|
+
|
|
1021
1352
|
// src/config.ts
|
|
1022
1353
|
var Config = class _Config {
|
|
1023
1354
|
constructor(root, opts) {
|
|
@@ -1323,6 +1654,36 @@ var Config = class _Config {
|
|
|
1323
1654
|
toObject(opts) {
|
|
1324
1655
|
return hoconToJs(this.root, opts?.nullPrototype === true);
|
|
1325
1656
|
}
|
|
1657
|
+
/**
|
|
1658
|
+
* Renders this resolved Config as HOCON text (E18; lockstep with go.hocon's
|
|
1659
|
+
* `Config.RenderHOCON`, v1.11.0).
|
|
1660
|
+
*
|
|
1661
|
+
* The output round-trips: parsing it back yields the same value tree. That
|
|
1662
|
+
* is the correctness contract, not byte-for-byte formatting — a scalar is
|
|
1663
|
+
* quoted whenever leaving it bare would re-parse as a different type (a
|
|
1664
|
+
* string `"8080"` becomes `"8080"`, not `8080`), and left bare only when it
|
|
1665
|
+
* provably cannot.
|
|
1666
|
+
*
|
|
1667
|
+
* The Config must be resolved and hold only data (objects, arrays, string /
|
|
1668
|
+
* number / boolean / null scalars) — exactly what {@link fromMap} and the
|
|
1669
|
+
* format adapters produce. An unresolved placeholder throws
|
|
1670
|
+
* {@link ConfigError}; substitutions have no textual round trip through a
|
|
1671
|
+
* value tree.
|
|
1672
|
+
*
|
|
1673
|
+
* The root object's fields are emitted without enclosing braces, nested
|
|
1674
|
+
* objects as `key { … }`, arrays as newline-separated `[ … ]`, indented two
|
|
1675
|
+
* spaces. Source comments are not represented — a value tree does not carry
|
|
1676
|
+
* them.
|
|
1677
|
+
*/
|
|
1678
|
+
renderHocon() {
|
|
1679
|
+
if (!this._resolved) {
|
|
1680
|
+
throw new ConfigError(
|
|
1681
|
+
"renderHocon: unrenderable unresolved substitution (config must be resolved data)",
|
|
1682
|
+
""
|
|
1683
|
+
);
|
|
1684
|
+
}
|
|
1685
|
+
return renderHoconFromRoot(this.root);
|
|
1686
|
+
}
|
|
1326
1687
|
/**
|
|
1327
1688
|
* @internal Test-only: renders this resolved Config's value tree as canonical
|
|
1328
1689
|
* JSON (sorted keys, no whitespace). Used by Layer-2 fixture tests to compare
|
|
@@ -1536,7 +1897,10 @@ function normalizeLeadingZeroNumber(raw) {
|
|
|
1536
1897
|
|
|
1537
1898
|
// src/value-factory.ts
|
|
1538
1899
|
function fromMap(values, originDescription) {
|
|
1539
|
-
const fields =
|
|
1900
|
+
const fields = guardStackDepth(
|
|
1901
|
+
() => coerceObject(values, ""),
|
|
1902
|
+
(msg) => depthError(`fromMap: ${msg}`)
|
|
1903
|
+
);
|
|
1540
1904
|
const root = { kind: "object", fields };
|
|
1541
1905
|
return Config._fromResolvedValue(root, { originDescription });
|
|
1542
1906
|
}
|
|
@@ -1613,11 +1977,14 @@ function parseYaml(input, originDescription) {
|
|
|
1613
1977
|
if (doc.errors.length > 0) {
|
|
1614
1978
|
throw new ConfigError(`yaml: ${doc.errors[0]?.message ?? "parse error"}`, "");
|
|
1615
1979
|
}
|
|
1616
|
-
return fromYamlValue(doc.toJS({ mapAsMap:
|
|
1980
|
+
return fromYamlValue(doc.toJS({ mapAsMap: true }), originDescription);
|
|
1617
1981
|
}
|
|
1618
1982
|
function fromYamlValue(value, originDescription) {
|
|
1619
1983
|
if (value === null || value === void 0) return fromMap({}, originDescription);
|
|
1620
|
-
const normalized =
|
|
1984
|
+
const normalized = guardStackDepth(
|
|
1985
|
+
() => convert(value, ""),
|
|
1986
|
+
(msg) => depthError(`yaml: ${msg}`)
|
|
1987
|
+
);
|
|
1621
1988
|
if (typeof normalized !== "object" || normalized === null || Array.isArray(normalized)) {
|
|
1622
1989
|
throw new ConfigError(
|
|
1623
1990
|
`yaml: document root is ${Array.isArray(normalized) ? "an array" : typeof normalized}, but a config root must be an object (spec F0.3)`,
|
|
@@ -1633,6 +2000,7 @@ function convert(v, atPath) {
|
|
|
1633
2000
|
}
|
|
1634
2001
|
if (v instanceof Map) {
|
|
1635
2002
|
const entries = [];
|
|
2003
|
+
const seen = /* @__PURE__ */ new Map();
|
|
1636
2004
|
for (const [k, e] of v) {
|
|
1637
2005
|
if (k !== null && typeof k === "object") {
|
|
1638
2006
|
throw new ConfigError(
|
|
@@ -1641,6 +2009,13 @@ function convert(v, atPath) {
|
|
|
1641
2009
|
);
|
|
1642
2010
|
}
|
|
1643
2011
|
const key = String(k);
|
|
2012
|
+
if (seen.has(key)) {
|
|
2013
|
+
throw new ConfigError(
|
|
2014
|
+
`yaml: sibling mapping keys ${keyForm(seen.get(key))} and ${keyForm(k)} both give the key "${key}"${atPath === "" ? "" : ` at "${atPath}"`}; rename one of them, because one of the two values would otherwise be lost. Quoting a non-string key helps only where that changes the key text, as 0x10 does and 1 does not (spec F5.3)`,
|
|
2015
|
+
atPath
|
|
2016
|
+
);
|
|
2017
|
+
}
|
|
2018
|
+
seen.set(key, k);
|
|
1644
2019
|
entries.push([key, convert(e, atPath === "" ? key : `${atPath}.${key}`)]);
|
|
1645
2020
|
}
|
|
1646
2021
|
return Object.fromEntries(entries);
|
|
@@ -1674,6 +2049,10 @@ function bytesToBase64(bytes) {
|
|
|
1674
2049
|
}
|
|
1675
2050
|
return btoa(binary);
|
|
1676
2051
|
}
|
|
2052
|
+
function keyForm(k) {
|
|
2053
|
+
if (typeof k === "string") return JSON.stringify(k);
|
|
2054
|
+
return `${String(k)} (${k === null ? "null" : typeof k})`;
|
|
2055
|
+
}
|
|
1677
2056
|
var MAX_SAFE = BigInt(Number.MAX_SAFE_INTEGER);
|
|
1678
2057
|
var MIN_SAFE = BigInt(Number.MIN_SAFE_INTEGER);
|
|
1679
2058
|
function isSafeIntegerBigInt(v) {
|