@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.js
CHANGED
|
@@ -37,13 +37,22 @@ function coerceNumber(value) {
|
|
|
37
37
|
return Number(value);
|
|
38
38
|
}
|
|
39
39
|
var DURATION_UNITS = {
|
|
40
|
+
// S19.1–S19.3: the bare nano/micro/milli (+plural) aliases are part of the
|
|
41
|
+
// spec's unit lists (HOCON.md L1307–L1309) and accepted by Lightbend
|
|
42
|
+
// (typesafe-config 1.4.6 probe, 2026-08-18); they were missing here.
|
|
40
43
|
ns: 1e-6,
|
|
44
|
+
nano: 1e-6,
|
|
45
|
+
nanos: 1e-6,
|
|
41
46
|
nanosecond: 1e-6,
|
|
42
47
|
nanoseconds: 1e-6,
|
|
43
48
|
us: 1e-3,
|
|
49
|
+
micro: 1e-3,
|
|
50
|
+
micros: 1e-3,
|
|
44
51
|
microsecond: 1e-3,
|
|
45
52
|
microseconds: 1e-3,
|
|
46
53
|
ms: 1,
|
|
54
|
+
milli: 1,
|
|
55
|
+
millis: 1,
|
|
47
56
|
millisecond: 1,
|
|
48
57
|
milliseconds: 1,
|
|
49
58
|
s: 1e3,
|
|
@@ -95,37 +104,76 @@ function parseDuration(value, outputUnit = "ms") {
|
|
|
95
104
|
return ms / divisor;
|
|
96
105
|
}
|
|
97
106
|
var BYTE_UNITS = {
|
|
107
|
+
// S21.1–S21.4 — the EXACT Lightbend/typesafe-config unit set (1.4.6 probe,
|
|
108
|
+
// 2026-08-18). Multi-letter units are case-sensitive: the SI decimal short
|
|
109
|
+
// form is `kB` (NOT `KB`/`kb` — Lightbend rejects both), higher decimals
|
|
110
|
+
// are `MB`…`YB`, binary prefixes are `Ki`/`KiB`…`Yi`/`YiB` with capital
|
|
111
|
+
// first letter, and long forms are lowercase only (`kilobyte`, never
|
|
112
|
+
// `Kilobyte`). Only the bare byte unit (`B`/`b`) and the single-letter
|
|
113
|
+
// -Xmx forms accept both cases. The old case-insensitive fallback and the
|
|
114
|
+
// lowercase alias rows accepted spellings Lightbend rejects — removed.
|
|
98
115
|
B: 1,
|
|
116
|
+
b: 1,
|
|
99
117
|
byte: 1,
|
|
100
118
|
bytes: 1,
|
|
101
|
-
|
|
119
|
+
kB: 1e3,
|
|
102
120
|
kilobyte: 1e3,
|
|
103
121
|
kilobytes: 1e3,
|
|
104
|
-
KiB: 1024,
|
|
105
|
-
kibibyte: 1024,
|
|
106
|
-
kibibytes: 1024,
|
|
107
122
|
MB: 1e6,
|
|
108
123
|
megabyte: 1e6,
|
|
109
124
|
megabytes: 1e6,
|
|
110
|
-
MiB: 1048576,
|
|
111
|
-
mebibyte: 1048576,
|
|
112
|
-
mebibytes: 1048576,
|
|
113
125
|
GB: 1e9,
|
|
114
126
|
gigabyte: 1e9,
|
|
115
127
|
gigabytes: 1e9,
|
|
116
|
-
GiB: 1073741824,
|
|
117
|
-
gibibyte: 1073741824,
|
|
118
|
-
gibibytes: 1073741824,
|
|
119
128
|
TB: 1e12,
|
|
120
129
|
terabyte: 1e12,
|
|
121
130
|
terabytes: 1e12,
|
|
131
|
+
PB: 1e15,
|
|
132
|
+
petabyte: 1e15,
|
|
133
|
+
petabytes: 1e15,
|
|
134
|
+
EB: 1e18,
|
|
135
|
+
exabyte: 1e18,
|
|
136
|
+
exabytes: 1e18,
|
|
137
|
+
ZB: 1e21,
|
|
138
|
+
zettabyte: 1e21,
|
|
139
|
+
zettabytes: 1e21,
|
|
140
|
+
YB: 1e24,
|
|
141
|
+
yottabyte: 1e24,
|
|
142
|
+
yottabytes: 1e24,
|
|
143
|
+
Ki: 1024,
|
|
144
|
+
KiB: 1024,
|
|
145
|
+
kibibyte: 1024,
|
|
146
|
+
kibibytes: 1024,
|
|
147
|
+
Mi: 1048576,
|
|
148
|
+
MiB: 1048576,
|
|
149
|
+
mebibyte: 1048576,
|
|
150
|
+
mebibytes: 1048576,
|
|
151
|
+
Gi: 1073741824,
|
|
152
|
+
GiB: 1073741824,
|
|
153
|
+
gibibyte: 1073741824,
|
|
154
|
+
gibibytes: 1073741824,
|
|
155
|
+
Ti: 1099511627776,
|
|
122
156
|
TiB: 1099511627776,
|
|
123
157
|
tebibyte: 1099511627776,
|
|
124
158
|
tebibytes: 1099511627776,
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
159
|
+
Pi: 1024 ** 5,
|
|
160
|
+
PiB: 1024 ** 5,
|
|
161
|
+
pebibyte: 1024 ** 5,
|
|
162
|
+
pebibytes: 1024 ** 5,
|
|
163
|
+
Ei: 1024 ** 6,
|
|
164
|
+
EiB: 1024 ** 6,
|
|
165
|
+
exbibyte: 1024 ** 6,
|
|
166
|
+
exbibytes: 1024 ** 6,
|
|
167
|
+
Zi: 1024 ** 7,
|
|
168
|
+
ZiB: 1024 ** 7,
|
|
169
|
+
zebibyte: 1024 ** 7,
|
|
170
|
+
zebibytes: 1024 ** 7,
|
|
171
|
+
Yi: 1024 ** 8,
|
|
172
|
+
YiB: 1024 ** 8,
|
|
173
|
+
yobibyte: 1024 ** 8,
|
|
174
|
+
yobibytes: 1024 ** 8,
|
|
175
|
+
// S21.4 — single-letter abbreviations → powers of two (java -Xmx
|
|
176
|
+
// convention); Lightbend accepts BOTH cases here, through the full ladder.
|
|
129
177
|
K: 1024,
|
|
130
178
|
k: 1024,
|
|
131
179
|
M: 1024 ** 2,
|
|
@@ -138,16 +186,10 @@ var BYTE_UNITS = {
|
|
|
138
186
|
p: 1024 ** 5,
|
|
139
187
|
E: 1024 ** 6,
|
|
140
188
|
e: 1024 ** 6,
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
mb: 1e6,
|
|
146
|
-
mib: 1048576,
|
|
147
|
-
gb: 1e9,
|
|
148
|
-
gib: 1073741824,
|
|
149
|
-
tb: 1e12,
|
|
150
|
-
tib: 1099511627776
|
|
189
|
+
Z: 1024 ** 7,
|
|
190
|
+
z: 1024 ** 7,
|
|
191
|
+
Y: 1024 ** 8,
|
|
192
|
+
y: 1024 ** 8
|
|
151
193
|
};
|
|
152
194
|
var OUTPUT_BYTE_UNITS = {
|
|
153
195
|
B: 1,
|
|
@@ -185,10 +227,7 @@ function parseBytes(value, outputUnit = "B") {
|
|
|
185
227
|
}
|
|
186
228
|
return bytes2 / divisor;
|
|
187
229
|
}
|
|
188
|
-
|
|
189
|
-
if (mult === void 0) {
|
|
190
|
-
mult = BYTE_UNITS[unit.toLowerCase()];
|
|
191
|
-
}
|
|
230
|
+
const mult = BYTE_UNITS[unit];
|
|
192
231
|
if (mult === void 0) return NaN;
|
|
193
232
|
const bytes = num * mult;
|
|
194
233
|
if (Math.abs(bytes) > Number.MAX_SAFE_INTEGER) {
|
|
@@ -235,35 +274,114 @@ function stringSegmentsToKey(segments) {
|
|
|
235
274
|
return t;
|
|
236
275
|
}).join(".");
|
|
237
276
|
}
|
|
277
|
+
function prefixSelfRefRemainder(s, fullKey) {
|
|
278
|
+
const texts = s.segments.map((seg) => seg.text);
|
|
279
|
+
if (!stringSegmentsToKey(texts).startsWith(fullKey + ".")) return null;
|
|
280
|
+
for (let n = 1; n < texts.length; n++) {
|
|
281
|
+
if (stringSegmentsToKey(texts.slice(0, n)) === fullKey) return texts.slice(n);
|
|
282
|
+
}
|
|
283
|
+
return null;
|
|
284
|
+
}
|
|
285
|
+
function navigateResolverValue(v, remainder) {
|
|
286
|
+
let cur = v;
|
|
287
|
+
for (const seg of remainder) {
|
|
288
|
+
if (isSubst(cur) || isConcat(cur)) return null;
|
|
289
|
+
if (isResObj(cur)) {
|
|
290
|
+
const next = cur.fields.get(seg);
|
|
291
|
+
if (next === void 0) return void 0;
|
|
292
|
+
cur = next;
|
|
293
|
+
continue;
|
|
294
|
+
}
|
|
295
|
+
const hv = cur;
|
|
296
|
+
if (hv.kind === "object") {
|
|
297
|
+
const next = hv.fields.get(seg);
|
|
298
|
+
if (next === void 0) return void 0;
|
|
299
|
+
cur = next;
|
|
300
|
+
continue;
|
|
301
|
+
}
|
|
302
|
+
return void 0;
|
|
303
|
+
}
|
|
304
|
+
return cur;
|
|
305
|
+
}
|
|
306
|
+
function foldPrefixSelfRef(s, replacement, remainder) {
|
|
307
|
+
const navigated = navigateResolverValue(replacement, remainder);
|
|
308
|
+
if (navigated === null) return s;
|
|
309
|
+
if (navigated === void 0) {
|
|
310
|
+
return {
|
|
311
|
+
_kind: "subst-placeholder",
|
|
312
|
+
segments: s.segments.map((seg) => ({ text: seg.text, line: seg.line, col: seg.col })),
|
|
313
|
+
optional: s.optional,
|
|
314
|
+
knownAbsent: true,
|
|
315
|
+
listSuffix: s.listSuffix,
|
|
316
|
+
line: s.line,
|
|
317
|
+
col: s.col,
|
|
318
|
+
prefixLen: s.prefixLen
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
return cloneResolverValue(navigated);
|
|
322
|
+
}
|
|
323
|
+
function mergeResObjLayers(base, top) {
|
|
324
|
+
const fields = new Map(base.fields);
|
|
325
|
+
for (const [k, tv] of top.fields) {
|
|
326
|
+
const bv = fields.get(k);
|
|
327
|
+
if (bv !== void 0 && isResObj(bv) && isResObj(tv)) {
|
|
328
|
+
fields.set(k, mergeResObjLayers(bv, tv));
|
|
329
|
+
} else {
|
|
330
|
+
fields.set(k, tv);
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
const priorValues = new Map(base.priorValues);
|
|
334
|
+
for (const [k, pv] of top.priorValues) priorValues.set(k, pv);
|
|
335
|
+
const resetKeys = new Set(base.resetKeys);
|
|
336
|
+
for (const k of top.resetKeys) resetKeys.add(k);
|
|
337
|
+
return {
|
|
338
|
+
_kind: "res-obj",
|
|
339
|
+
fields,
|
|
340
|
+
priorValues,
|
|
341
|
+
resetKeys
|
|
342
|
+
};
|
|
343
|
+
}
|
|
238
344
|
function containsSelfRef(v, fullKey) {
|
|
239
|
-
|
|
240
|
-
|
|
345
|
+
return containsSelfRefInner(v, fullKey, true);
|
|
346
|
+
}
|
|
347
|
+
function containsSelfRefInner(v, fullKey, allowPrefix) {
|
|
348
|
+
if (isSubst(v))
|
|
349
|
+
return !v.knownAbsent && (substFullKey(v) === fullKey || allowPrefix && prefixSelfRefRemainder(v, fullKey) !== null);
|
|
350
|
+
if (isConcat(v)) return v.nodes.some((n) => containsSelfRefInner(n, fullKey, allowPrefix));
|
|
241
351
|
if (isResObj(v)) {
|
|
242
352
|
for (const f of v.fields.values()) {
|
|
243
|
-
if (
|
|
353
|
+
if (containsSelfRefInner(f, fullKey, false)) return true;
|
|
244
354
|
}
|
|
245
355
|
return false;
|
|
246
356
|
}
|
|
247
357
|
const hv = v;
|
|
248
358
|
if (hv.kind === "array") {
|
|
249
|
-
return hv.items.some((item) =>
|
|
359
|
+
return hv.items.some((item) => containsSelfRefInner(item, fullKey, allowPrefix));
|
|
250
360
|
}
|
|
251
361
|
if (hv.kind === "object") {
|
|
252
362
|
for (const f of hv.fields.values()) {
|
|
253
|
-
if (
|
|
363
|
+
if (containsSelfRefInner(f, fullKey, false)) return true;
|
|
254
364
|
}
|
|
255
365
|
return false;
|
|
256
366
|
}
|
|
257
367
|
return false;
|
|
258
368
|
}
|
|
259
369
|
function foldSelfRef(v, fullKey, replacement) {
|
|
370
|
+
return foldSelfRefInner(v, fullKey, replacement, true);
|
|
371
|
+
}
|
|
372
|
+
function foldSelfRefInner(v, fullKey, replacement, allowPrefix) {
|
|
260
373
|
if (isSubst(v)) {
|
|
261
|
-
|
|
374
|
+
if (substFullKey(v) === fullKey) return replacement;
|
|
375
|
+
if (allowPrefix) {
|
|
376
|
+
const remainder = prefixSelfRefRemainder(v, fullKey);
|
|
377
|
+
if (remainder !== null) return foldPrefixSelfRef(v, replacement, remainder);
|
|
378
|
+
}
|
|
379
|
+
return v;
|
|
262
380
|
}
|
|
263
381
|
if (isConcat(v)) {
|
|
264
382
|
return {
|
|
265
383
|
_kind: "concat-placeholder",
|
|
266
|
-
nodes: v.nodes.map((n) =>
|
|
384
|
+
nodes: v.nodes.map((n) => foldSelfRefInner(n, fullKey, replacement, allowPrefix)),
|
|
267
385
|
line: v.line,
|
|
268
386
|
col: v.col
|
|
269
387
|
};
|
|
@@ -271,7 +389,7 @@ function foldSelfRef(v, fullKey, replacement) {
|
|
|
271
389
|
if (isResObj(v)) {
|
|
272
390
|
const newFields = /* @__PURE__ */ new Map();
|
|
273
391
|
for (const [k, val] of v.fields) {
|
|
274
|
-
newFields.set(k,
|
|
392
|
+
newFields.set(k, foldSelfRefInner(val, fullKey, replacement, false));
|
|
275
393
|
}
|
|
276
394
|
return { _kind: "res-obj", fields: newFields, priorValues: new Map(v.priorValues), resetKeys: new Set(v.resetKeys) };
|
|
277
395
|
}
|
|
@@ -279,13 +397,15 @@ function foldSelfRef(v, fullKey, replacement) {
|
|
|
279
397
|
if (hv.kind === "array") {
|
|
280
398
|
return {
|
|
281
399
|
kind: "array",
|
|
282
|
-
items: hv.items.map(
|
|
400
|
+
items: hv.items.map(
|
|
401
|
+
(item) => foldSelfRefInner(item, fullKey, replacement, allowPrefix)
|
|
402
|
+
)
|
|
283
403
|
};
|
|
284
404
|
}
|
|
285
405
|
if (hv.kind === "object") {
|
|
286
406
|
const newFields = /* @__PURE__ */ new Map();
|
|
287
407
|
for (const [k, val] of hv.fields) {
|
|
288
|
-
newFields.set(k,
|
|
408
|
+
newFields.set(k, foldSelfRefInner(val, fullKey, replacement, false));
|
|
289
409
|
}
|
|
290
410
|
return { kind: "object", fields: newFields };
|
|
291
411
|
}
|
|
@@ -294,10 +414,26 @@ function foldSelfRef(v, fullKey, replacement) {
|
|
|
294
414
|
function foldOrSkipPrior(prior, fullKey, old) {
|
|
295
415
|
if (!containsSelfRef(prior, fullKey)) return cloneResolverValue(prior);
|
|
296
416
|
if (old === void 0) return foldOptionalSelfRefAbsent(prior, fullKey);
|
|
417
|
+
if (isSubst(prior)) {
|
|
418
|
+
const remainder = prefixSelfRefRemainder(prior, fullKey);
|
|
419
|
+
if (remainder !== null) {
|
|
420
|
+
const navigated = navigateResolverValue(old, remainder);
|
|
421
|
+
if (navigated === void 0 && prior.optional) return cloneResolverValue(old);
|
|
422
|
+
if (navigated !== null && navigated !== void 0 && isResObj(navigated) && isResObj(old)) {
|
|
423
|
+
return mergeResObjLayers(
|
|
424
|
+
cloneResolverValue(old),
|
|
425
|
+
cloneResolverValue(navigated)
|
|
426
|
+
);
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
}
|
|
297
430
|
return foldSelfRef(prior, fullKey, old);
|
|
298
431
|
}
|
|
299
432
|
function foldOptionalSelfRefAbsent(v, fullKey) {
|
|
300
|
-
|
|
433
|
+
return foldOptionalSelfRefAbsentInner(v, fullKey, true);
|
|
434
|
+
}
|
|
435
|
+
function foldOptionalSelfRefAbsentInner(v, fullKey, allowPrefix) {
|
|
436
|
+
if (isSubst(v) && (substFullKey(v) === fullKey || allowPrefix && prefixSelfRefRemainder(v, fullKey) !== null)) {
|
|
301
437
|
if (!v.optional) return void 0;
|
|
302
438
|
return {
|
|
303
439
|
_kind: "subst-placeholder",
|
|
@@ -313,7 +449,7 @@ function foldOptionalSelfRefAbsent(v, fullKey) {
|
|
|
313
449
|
if (isConcat(v)) {
|
|
314
450
|
const nodes = [];
|
|
315
451
|
for (const node of v.nodes) {
|
|
316
|
-
const folded =
|
|
452
|
+
const folded = foldOptionalSelfRefAbsentInner(node, fullKey, allowPrefix);
|
|
317
453
|
if (folded === void 0) return void 0;
|
|
318
454
|
nodes.push(folded);
|
|
319
455
|
}
|
|
@@ -322,7 +458,7 @@ function foldOptionalSelfRefAbsent(v, fullKey) {
|
|
|
322
458
|
if (isResObj(v)) {
|
|
323
459
|
const fields = /* @__PURE__ */ new Map();
|
|
324
460
|
for (const [key, value] of v.fields) {
|
|
325
|
-
const folded =
|
|
461
|
+
const folded = foldOptionalSelfRefAbsentInner(value, fullKey, false);
|
|
326
462
|
if (folded === void 0) return void 0;
|
|
327
463
|
fields.set(key, folded);
|
|
328
464
|
}
|
|
@@ -332,7 +468,7 @@ function foldOptionalSelfRefAbsent(v, fullKey) {
|
|
|
332
468
|
if (hv.kind === "array") {
|
|
333
469
|
const items = [];
|
|
334
470
|
for (const item of hv.items) {
|
|
335
|
-
const folded =
|
|
471
|
+
const folded = foldOptionalSelfRefAbsentInner(item, fullKey, allowPrefix);
|
|
336
472
|
if (folded === void 0) return void 0;
|
|
337
473
|
items.push(folded);
|
|
338
474
|
}
|
|
@@ -341,7 +477,7 @@ function foldOptionalSelfRefAbsent(v, fullKey) {
|
|
|
341
477
|
if (hv.kind === "object") {
|
|
342
478
|
const fields = /* @__PURE__ */ new Map();
|
|
343
479
|
for (const [key, value] of hv.fields) {
|
|
344
|
-
const folded =
|
|
480
|
+
const folded = foldOptionalSelfRefAbsentInner(value, fullKey, false);
|
|
345
481
|
if (folded === void 0) return void 0;
|
|
346
482
|
fields.set(key, folded);
|
|
347
483
|
}
|
|
@@ -523,6 +659,27 @@ function stripBom(input) {
|
|
|
523
659
|
return input.charCodeAt(0) === 65279 ? input.slice(1) : input;
|
|
524
660
|
}
|
|
525
661
|
|
|
662
|
+
// src/internal/depth.ts
|
|
663
|
+
function guardStackDepth(fn, wrap) {
|
|
664
|
+
try {
|
|
665
|
+
return fn();
|
|
666
|
+
} catch (e) {
|
|
667
|
+
if (!isStackOverflow(e)) throw e;
|
|
668
|
+
throw wrap(STACK_MESSAGE);
|
|
669
|
+
}
|
|
670
|
+
}
|
|
671
|
+
var STACK_MESSAGE = "input is nested too deeply for this engine's stack, or contains a cycle (flatten the document, or break the cycle)";
|
|
672
|
+
function isStackOverflow(e) {
|
|
673
|
+
if (!(e instanceof RangeError)) return false;
|
|
674
|
+
const m = e.message.toLowerCase();
|
|
675
|
+
return m.includes("call stack") || // V8: "Maximum call stack size exceeded"
|
|
676
|
+
m.includes("recursion") || // SpiderMonkey: "too much recursion"
|
|
677
|
+
m.includes("stack overflow");
|
|
678
|
+
}
|
|
679
|
+
function depthError(message) {
|
|
680
|
+
return new ConfigError(message, "");
|
|
681
|
+
}
|
|
682
|
+
|
|
526
683
|
// src/value/numeric-array.ts
|
|
527
684
|
function numericObjectToArray(value) {
|
|
528
685
|
if (value.kind !== "object") return null;
|
|
@@ -577,6 +734,12 @@ var SubstitutionResolver = class {
|
|
|
577
734
|
// Cross-impl with rs.hocon v1.5.1's resolving_field_path (same purpose,
|
|
578
735
|
// same prefix-match semantics).
|
|
579
736
|
this.resolvingFieldPath = [];
|
|
737
|
+
// S13a.12 recursion guard: field keys whose prior is currently being
|
|
738
|
+
// resolved through the prefix-self-ref branch. Saved priors are
|
|
739
|
+
// prefix-self-ref-free by the fold invariant, so re-entry only happens on
|
|
740
|
+
// a shape the fold could not see through (a live subst mid-navigation) —
|
|
741
|
+
// report it as a cycle instead of recursing forever.
|
|
742
|
+
this.resolvingPrefixPriors = /* @__PURE__ */ new Set();
|
|
580
743
|
}
|
|
581
744
|
/** Returns a prefix for error messages, including origin info when set. */
|
|
582
745
|
originPrefix() {
|
|
@@ -591,46 +754,57 @@ var SubstitutionResolver = class {
|
|
|
591
754
|
this.resolvingFieldPath.push(key);
|
|
592
755
|
const fullCacheKey = stringSegmentsToKey(this.resolvingFieldPath);
|
|
593
756
|
this.cache.delete(fullCacheKey);
|
|
594
|
-
let resolved;
|
|
595
757
|
try {
|
|
596
|
-
resolved = this.resolveVal(val, obj);
|
|
597
|
-
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
758
|
+
const resolved = this.resolveVal(val, obj);
|
|
759
|
+
if (resolved !== void 0) {
|
|
760
|
+
if (resolved.kind === "object") {
|
|
761
|
+
const prior = obj.priorValues.get(key);
|
|
762
|
+
if (prior !== void 0) {
|
|
763
|
+
const priorResolved = this.resolveVal(prior, obj);
|
|
764
|
+
if (priorResolved !== void 0 && priorResolved.kind === "object") {
|
|
765
|
+
const finalValue = deepMergeHoconValues(
|
|
766
|
+
priorResolved,
|
|
767
|
+
resolved
|
|
768
|
+
);
|
|
769
|
+
result.set(key, finalValue);
|
|
770
|
+
this.cache.set(fullCacheKey, finalValue);
|
|
771
|
+
this.cacheDescendants(fullCacheKey, finalValue);
|
|
772
|
+
continue;
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
}
|
|
776
|
+
result.set(key, resolved);
|
|
777
|
+
this.cache.set(fullCacheKey, resolved);
|
|
778
|
+
this.cacheDescendants(fullCacheKey, resolved);
|
|
779
|
+
} else {
|
|
602
780
|
const prior = obj.priorValues.get(key);
|
|
603
781
|
if (prior !== void 0) {
|
|
604
782
|
const priorResolved = this.resolveVal(prior, obj);
|
|
605
|
-
if (priorResolved !== void 0
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
);
|
|
610
|
-
result.set(key, finalValue);
|
|
611
|
-
this.cache.set(fullCacheKey, finalValue);
|
|
612
|
-
this.cacheDescendants(fullCacheKey, finalValue);
|
|
613
|
-
continue;
|
|
783
|
+
if (priorResolved !== void 0) {
|
|
784
|
+
result.set(key, priorResolved);
|
|
785
|
+
this.cache.set(fullCacheKey, priorResolved);
|
|
786
|
+
this.cacheDescendants(fullCacheKey, priorResolved);
|
|
614
787
|
}
|
|
615
788
|
}
|
|
616
789
|
}
|
|
617
|
-
|
|
618
|
-
this.
|
|
619
|
-
this.cacheDescendants(fullCacheKey, resolved);
|
|
620
|
-
} else {
|
|
621
|
-
const prior = obj.priorValues.get(key);
|
|
622
|
-
if (prior !== void 0) {
|
|
623
|
-
const priorResolved = this.resolveVal(prior, obj);
|
|
624
|
-
if (priorResolved !== void 0) {
|
|
625
|
-
result.set(key, priorResolved);
|
|
626
|
-
this.cache.set(fullCacheKey, priorResolved);
|
|
627
|
-
this.cacheDescendants(fullCacheKey, priorResolved);
|
|
628
|
-
}
|
|
629
|
-
}
|
|
790
|
+
} finally {
|
|
791
|
+
this.resolvingFieldPath.pop();
|
|
630
792
|
}
|
|
631
793
|
}
|
|
632
794
|
return { kind: "object", fields: result };
|
|
633
795
|
}
|
|
796
|
+
/** S13a.12: walk resolved-object fields by segment text. A missing segment
|
|
797
|
+
* or a walk into a scalar/array is path-absent → undefined. */
|
|
798
|
+
navigateResolved(v, remainder) {
|
|
799
|
+
let cur = v;
|
|
800
|
+
for (const seg of remainder) {
|
|
801
|
+
if (cur.kind !== "object") return void 0;
|
|
802
|
+
const next = cur.fields.get(seg);
|
|
803
|
+
if (next === void 0) return void 0;
|
|
804
|
+
cur = next;
|
|
805
|
+
}
|
|
806
|
+
return cur;
|
|
807
|
+
}
|
|
634
808
|
cacheDescendants(prefix, value) {
|
|
635
809
|
if (value.kind !== "object") return;
|
|
636
810
|
for (const [key, child] of value.fields) {
|
|
@@ -653,17 +827,59 @@ var SubstitutionResolver = class {
|
|
|
653
827
|
if (isResObj(v)) return this.resolveResObj(v);
|
|
654
828
|
const hv = v;
|
|
655
829
|
if (hv.kind === "array") {
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
660
|
-
)
|
|
661
|
-
}
|
|
830
|
+
const items = [];
|
|
831
|
+
for (const item of hv.items) {
|
|
832
|
+
const resolved = this.resolveVal(item, scope);
|
|
833
|
+
if (resolved === void 0) continue;
|
|
834
|
+
items.push(resolved);
|
|
835
|
+
}
|
|
836
|
+
return { kind: "array", items };
|
|
662
837
|
}
|
|
663
838
|
return hv;
|
|
664
839
|
}
|
|
665
840
|
resolveSubst(s, scope) {
|
|
666
|
-
if (s.knownAbsent)
|
|
841
|
+
if (s.knownAbsent) {
|
|
842
|
+
if (!s.optional) {
|
|
843
|
+
if (this.opts.allowUnresolved) return s;
|
|
844
|
+
const k = s.listSuffix ? `${segmentsToKey(s.segments)}[]` : segmentsToKey(s.segments);
|
|
845
|
+
throw new ResolveError(
|
|
846
|
+
`${this.originPrefix()}could not resolve substitution: \${${k}}`,
|
|
847
|
+
k,
|
|
848
|
+
s.line,
|
|
849
|
+
s.col
|
|
850
|
+
);
|
|
851
|
+
}
|
|
852
|
+
return void 0;
|
|
853
|
+
}
|
|
854
|
+
{
|
|
855
|
+
const rfp = this.resolvingFieldPath;
|
|
856
|
+
const sTexts = s.segments.map((seg) => seg.text);
|
|
857
|
+
if (rfp.length > 0 && rfp.length < sTexts.length && stringSegmentsToKey(sTexts.slice(0, rfp.length)) === stringSegmentsToKey(rfp)) {
|
|
858
|
+
const guardKey = stringSegmentsToKey(rfp);
|
|
859
|
+
const prior = scope.priorValues.get(rfp[rfp.length - 1]);
|
|
860
|
+
if (prior !== void 0 && !this.resolvingPrefixPriors.has(guardKey)) {
|
|
861
|
+
this.resolvingPrefixPriors.add(guardKey);
|
|
862
|
+
try {
|
|
863
|
+
const priorResolved = this.resolveVal(prior, scope);
|
|
864
|
+
if (priorResolved !== void 0) {
|
|
865
|
+
const navigated = this.navigateResolved(priorResolved, sTexts.slice(rfp.length));
|
|
866
|
+
if (navigated !== void 0) return navigated;
|
|
867
|
+
}
|
|
868
|
+
} finally {
|
|
869
|
+
this.resolvingPrefixPriors.delete(guardKey);
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
if (s.optional) return void 0;
|
|
873
|
+
if (this.opts.allowUnresolved) return s;
|
|
874
|
+
const k = s.listSuffix ? `${segmentsToKey(s.segments)}[]` : segmentsToKey(s.segments);
|
|
875
|
+
throw new ResolveError(
|
|
876
|
+
`${this.originPrefix()}could not resolve substitution: \${${k}}`,
|
|
877
|
+
k,
|
|
878
|
+
s.line,
|
|
879
|
+
s.col
|
|
880
|
+
);
|
|
881
|
+
}
|
|
882
|
+
}
|
|
667
883
|
const key = s.listSuffix ? `${segmentsToKey(s.segments)}[]` : segmentsToKey(s.segments);
|
|
668
884
|
if (this.cache.has(key)) return this.cache.get(key);
|
|
669
885
|
if (this.resolving.has(key)) {
|
|
@@ -983,6 +1199,121 @@ function hoconValueToResObj2(value) {
|
|
|
983
1199
|
return obj;
|
|
984
1200
|
}
|
|
985
1201
|
|
|
1202
|
+
// src/render-hocon.ts
|
|
1203
|
+
function renderHoconFromRoot(root) {
|
|
1204
|
+
const out = [];
|
|
1205
|
+
renderObjectBody(out, root, 0);
|
|
1206
|
+
return out.join("");
|
|
1207
|
+
}
|
|
1208
|
+
function renderObjectBody(out, o, depth) {
|
|
1209
|
+
const indent = " ".repeat(depth);
|
|
1210
|
+
for (const [k, v] of o.fields) {
|
|
1211
|
+
out.push(indent, renderKey(k));
|
|
1212
|
+
if (v.kind === "object") {
|
|
1213
|
+
out.push(" {");
|
|
1214
|
+
if (v.fields.size === 0) {
|
|
1215
|
+
out.push("}\n");
|
|
1216
|
+
continue;
|
|
1217
|
+
}
|
|
1218
|
+
out.push("\n");
|
|
1219
|
+
renderObjectBody(out, v, depth + 1);
|
|
1220
|
+
out.push(indent, "}\n");
|
|
1221
|
+
} else {
|
|
1222
|
+
out.push(" = ");
|
|
1223
|
+
renderValue(out, v, depth);
|
|
1224
|
+
out.push("\n");
|
|
1225
|
+
}
|
|
1226
|
+
}
|
|
1227
|
+
}
|
|
1228
|
+
function renderValue(out, v, depth) {
|
|
1229
|
+
switch (v.kind) {
|
|
1230
|
+
case "object": {
|
|
1231
|
+
if (v.fields.size === 0) {
|
|
1232
|
+
out.push("{}");
|
|
1233
|
+
return;
|
|
1234
|
+
}
|
|
1235
|
+
out.push("{\n");
|
|
1236
|
+
renderObjectBody(out, v, depth + 1);
|
|
1237
|
+
out.push(" ".repeat(depth), "}");
|
|
1238
|
+
return;
|
|
1239
|
+
}
|
|
1240
|
+
case "array":
|
|
1241
|
+
renderArray(out, v, depth);
|
|
1242
|
+
return;
|
|
1243
|
+
case "scalar":
|
|
1244
|
+
out.push(renderScalar(v));
|
|
1245
|
+
return;
|
|
1246
|
+
default:
|
|
1247
|
+
throw new ConfigError(
|
|
1248
|
+
"renderHocon: unrenderable value (config must be resolved data)",
|
|
1249
|
+
""
|
|
1250
|
+
);
|
|
1251
|
+
}
|
|
1252
|
+
}
|
|
1253
|
+
function renderArray(out, a, depth) {
|
|
1254
|
+
if (a.items.length === 0) {
|
|
1255
|
+
out.push("[]");
|
|
1256
|
+
return;
|
|
1257
|
+
}
|
|
1258
|
+
const inner = " ".repeat(depth + 1);
|
|
1259
|
+
out.push("[\n");
|
|
1260
|
+
for (const e of a.items) {
|
|
1261
|
+
out.push(inner);
|
|
1262
|
+
renderValue(out, e, depth + 1);
|
|
1263
|
+
out.push("\n");
|
|
1264
|
+
}
|
|
1265
|
+
out.push(" ".repeat(depth), "]");
|
|
1266
|
+
}
|
|
1267
|
+
function renderScalar(s) {
|
|
1268
|
+
switch (s.valueType) {
|
|
1269
|
+
case "null":
|
|
1270
|
+
return "null";
|
|
1271
|
+
case "boolean":
|
|
1272
|
+
case "number":
|
|
1273
|
+
return s.raw;
|
|
1274
|
+
case "string":
|
|
1275
|
+
return renderString(s.raw);
|
|
1276
|
+
}
|
|
1277
|
+
}
|
|
1278
|
+
var SAFE_UNQUOTED_KEY = /^[A-Za-z0-9_-]+$/;
|
|
1279
|
+
function renderKey(k) {
|
|
1280
|
+
if (k === "include") return quoteString(k);
|
|
1281
|
+
return SAFE_UNQUOTED_KEY.test(k) ? k : quoteString(k);
|
|
1282
|
+
}
|
|
1283
|
+
var SAFE_BARE_STRING = /^[A-Za-z][A-Za-z0-9_-]*$/;
|
|
1284
|
+
var STRING_KEYWORDS = /* @__PURE__ */ new Set(["true", "false", "null", "yes", "no", "on", "off"]);
|
|
1285
|
+
function renderString(s) {
|
|
1286
|
+
return SAFE_BARE_STRING.test(s) && !STRING_KEYWORDS.has(s.toLowerCase()) ? s : quoteString(s);
|
|
1287
|
+
}
|
|
1288
|
+
function quoteString(s) {
|
|
1289
|
+
if (s.includes("\n") && !s.includes("\r") && !s.includes('"""') && !s.endsWith('"')) {
|
|
1290
|
+
return `"""${s}"""`;
|
|
1291
|
+
}
|
|
1292
|
+
let b = '"';
|
|
1293
|
+
for (const ch of s) {
|
|
1294
|
+
switch (ch) {
|
|
1295
|
+
case '"':
|
|
1296
|
+
b += '\\"';
|
|
1297
|
+
break;
|
|
1298
|
+
case "\\":
|
|
1299
|
+
b += "\\\\";
|
|
1300
|
+
break;
|
|
1301
|
+
case "\n":
|
|
1302
|
+
b += "\\n";
|
|
1303
|
+
break;
|
|
1304
|
+
case "\r":
|
|
1305
|
+
b += "\\r";
|
|
1306
|
+
break;
|
|
1307
|
+
case " ":
|
|
1308
|
+
b += "\\t";
|
|
1309
|
+
break;
|
|
1310
|
+
default:
|
|
1311
|
+
b += ch;
|
|
1312
|
+
}
|
|
1313
|
+
}
|
|
1314
|
+
return b + '"';
|
|
1315
|
+
}
|
|
1316
|
+
|
|
986
1317
|
// src/config.ts
|
|
987
1318
|
var Config = class _Config {
|
|
988
1319
|
constructor(root, opts) {
|
|
@@ -1288,6 +1619,36 @@ var Config = class _Config {
|
|
|
1288
1619
|
toObject(opts) {
|
|
1289
1620
|
return hoconToJs(this.root, opts?.nullPrototype === true);
|
|
1290
1621
|
}
|
|
1622
|
+
/**
|
|
1623
|
+
* Renders this resolved Config as HOCON text (E18; lockstep with go.hocon's
|
|
1624
|
+
* `Config.RenderHOCON`, v1.11.0).
|
|
1625
|
+
*
|
|
1626
|
+
* The output round-trips: parsing it back yields the same value tree. That
|
|
1627
|
+
* is the correctness contract, not byte-for-byte formatting — a scalar is
|
|
1628
|
+
* quoted whenever leaving it bare would re-parse as a different type (a
|
|
1629
|
+
* string `"8080"` becomes `"8080"`, not `8080`), and left bare only when it
|
|
1630
|
+
* provably cannot.
|
|
1631
|
+
*
|
|
1632
|
+
* The Config must be resolved and hold only data (objects, arrays, string /
|
|
1633
|
+
* number / boolean / null scalars) — exactly what {@link fromMap} and the
|
|
1634
|
+
* format adapters produce. An unresolved placeholder throws
|
|
1635
|
+
* {@link ConfigError}; substitutions have no textual round trip through a
|
|
1636
|
+
* value tree.
|
|
1637
|
+
*
|
|
1638
|
+
* The root object's fields are emitted without enclosing braces, nested
|
|
1639
|
+
* objects as `key { … }`, arrays as newline-separated `[ … ]`, indented two
|
|
1640
|
+
* spaces. Source comments are not represented — a value tree does not carry
|
|
1641
|
+
* them.
|
|
1642
|
+
*/
|
|
1643
|
+
renderHocon() {
|
|
1644
|
+
if (!this._resolved) {
|
|
1645
|
+
throw new ConfigError(
|
|
1646
|
+
"renderHocon: unrenderable unresolved substitution (config must be resolved data)",
|
|
1647
|
+
""
|
|
1648
|
+
);
|
|
1649
|
+
}
|
|
1650
|
+
return renderHoconFromRoot(this.root);
|
|
1651
|
+
}
|
|
1291
1652
|
/**
|
|
1292
1653
|
* @internal Test-only: renders this resolved Config's value tree as canonical
|
|
1293
1654
|
* JSON (sorted keys, no whitespace). Used by Layer-2 fixture tests to compare
|
|
@@ -1501,7 +1862,10 @@ function normalizeLeadingZeroNumber(raw) {
|
|
|
1501
1862
|
|
|
1502
1863
|
// src/value-factory.ts
|
|
1503
1864
|
function fromMap(values, originDescription) {
|
|
1504
|
-
const fields =
|
|
1865
|
+
const fields = guardStackDepth(
|
|
1866
|
+
() => coerceObject(values, ""),
|
|
1867
|
+
(msg) => depthError(`fromMap: ${msg}`)
|
|
1868
|
+
);
|
|
1505
1869
|
const root = { kind: "object", fields };
|
|
1506
1870
|
return Config._fromResolvedValue(root, { originDescription });
|
|
1507
1871
|
}
|
|
@@ -1578,11 +1942,14 @@ function parseYaml(input, originDescription) {
|
|
|
1578
1942
|
if (doc.errors.length > 0) {
|
|
1579
1943
|
throw new ConfigError(`yaml: ${doc.errors[0]?.message ?? "parse error"}`, "");
|
|
1580
1944
|
}
|
|
1581
|
-
return fromYamlValue(doc.toJS({ mapAsMap:
|
|
1945
|
+
return fromYamlValue(doc.toJS({ mapAsMap: true }), originDescription);
|
|
1582
1946
|
}
|
|
1583
1947
|
function fromYamlValue(value, originDescription) {
|
|
1584
1948
|
if (value === null || value === void 0) return fromMap({}, originDescription);
|
|
1585
|
-
const normalized =
|
|
1949
|
+
const normalized = guardStackDepth(
|
|
1950
|
+
() => convert(value, ""),
|
|
1951
|
+
(msg) => depthError(`yaml: ${msg}`)
|
|
1952
|
+
);
|
|
1586
1953
|
if (typeof normalized !== "object" || normalized === null || Array.isArray(normalized)) {
|
|
1587
1954
|
throw new ConfigError(
|
|
1588
1955
|
`yaml: document root is ${Array.isArray(normalized) ? "an array" : typeof normalized}, but a config root must be an object (spec F0.3)`,
|
|
@@ -1598,6 +1965,7 @@ function convert(v, atPath) {
|
|
|
1598
1965
|
}
|
|
1599
1966
|
if (v instanceof Map) {
|
|
1600
1967
|
const entries = [];
|
|
1968
|
+
const seen = /* @__PURE__ */ new Map();
|
|
1601
1969
|
for (const [k, e] of v) {
|
|
1602
1970
|
if (k !== null && typeof k === "object") {
|
|
1603
1971
|
throw new ConfigError(
|
|
@@ -1606,6 +1974,13 @@ function convert(v, atPath) {
|
|
|
1606
1974
|
);
|
|
1607
1975
|
}
|
|
1608
1976
|
const key = String(k);
|
|
1977
|
+
if (seen.has(key)) {
|
|
1978
|
+
throw new ConfigError(
|
|
1979
|
+
`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)`,
|
|
1980
|
+
atPath
|
|
1981
|
+
);
|
|
1982
|
+
}
|
|
1983
|
+
seen.set(key, k);
|
|
1609
1984
|
entries.push([key, convert(e, atPath === "" ? key : `${atPath}.${key}`)]);
|
|
1610
1985
|
}
|
|
1611
1986
|
return Object.fromEntries(entries);
|
|
@@ -1639,6 +2014,10 @@ function bytesToBase64(bytes) {
|
|
|
1639
2014
|
}
|
|
1640
2015
|
return btoa(binary);
|
|
1641
2016
|
}
|
|
2017
|
+
function keyForm(k) {
|
|
2018
|
+
if (typeof k === "string") return JSON.stringify(k);
|
|
2019
|
+
return `${String(k)} (${k === null ? "null" : typeof k})`;
|
|
2020
|
+
}
|
|
1642
2021
|
var MAX_SAFE = BigInt(Number.MAX_SAFE_INTEGER);
|
|
1643
2022
|
var MIN_SAFE = BigInt(Number.MIN_SAFE_INTEGER);
|
|
1644
2023
|
function isSafeIntegerBigInt(v) {
|