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