@o3co/ts.hocon 1.5.2 → 1.6.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/dist/{config-BwjvKeZ5.d.cts → config-CjSkQ4_l.d.cts} +2 -0
- package/dist/{config-BwjvKeZ5.d.ts → config-CjSkQ4_l.d.ts} +2 -0
- package/dist/index.cjs +167 -36
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +167 -36
- package/dist/zod.cjs +167 -36
- package/dist/zod.d.cts +1 -1
- package/dist/zod.d.ts +1 -1
- package/dist/zod.js +167 -36
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -299,7 +299,7 @@ function stringSegmentsToKey(segments) {
|
|
|
299
299
|
}).join(".");
|
|
300
300
|
}
|
|
301
301
|
function containsSelfRef(v, fullKey) {
|
|
302
|
-
if (isSubst(v)) return substFullKey(v) === fullKey;
|
|
302
|
+
if (isSubst(v)) return !v.knownAbsent && substFullKey(v) === fullKey;
|
|
303
303
|
if (isConcat(v)) return v.nodes.some((n) => containsSelfRef(n, fullKey));
|
|
304
304
|
if (isAppend(v)) {
|
|
305
305
|
return containsSelfRef(v.existing, fullKey) || containsSelfRef(v.elem, fullKey);
|
|
@@ -366,15 +366,75 @@ function foldSelfRef(v, fullKey, replacement) {
|
|
|
366
366
|
}
|
|
367
367
|
function foldOrSkipPrior(prior, fullKey, old) {
|
|
368
368
|
if (!containsSelfRef(prior, fullKey)) return cloneResolverValue(prior);
|
|
369
|
-
if (old === void 0) return
|
|
369
|
+
if (old === void 0) return foldOptionalSelfRefAbsent(prior, fullKey);
|
|
370
370
|
return foldSelfRef(prior, fullKey, old);
|
|
371
371
|
}
|
|
372
|
+
function foldOptionalSelfRefAbsent(v, fullKey) {
|
|
373
|
+
if (isSubst(v) && substFullKey(v) === fullKey) {
|
|
374
|
+
if (!v.optional) return void 0;
|
|
375
|
+
return {
|
|
376
|
+
_kind: "subst-placeholder",
|
|
377
|
+
segments: v.segments.map((seg) => ({ text: seg.text, line: seg.line, col: seg.col })),
|
|
378
|
+
optional: v.optional,
|
|
379
|
+
knownAbsent: true,
|
|
380
|
+
listSuffix: v.listSuffix,
|
|
381
|
+
line: v.line,
|
|
382
|
+
col: v.col,
|
|
383
|
+
prefixLen: v.prefixLen
|
|
384
|
+
};
|
|
385
|
+
}
|
|
386
|
+
if (isConcat(v)) {
|
|
387
|
+
const nodes = [];
|
|
388
|
+
for (const node of v.nodes) {
|
|
389
|
+
const folded = foldOptionalSelfRefAbsent(node, fullKey);
|
|
390
|
+
if (folded === void 0) return void 0;
|
|
391
|
+
nodes.push(folded);
|
|
392
|
+
}
|
|
393
|
+
return { _kind: "concat-placeholder", nodes, line: v.line, col: v.col };
|
|
394
|
+
}
|
|
395
|
+
if (isAppend(v)) {
|
|
396
|
+
const existing = foldOptionalSelfRefAbsent(v.existing, fullKey);
|
|
397
|
+
const elem = foldOptionalSelfRefAbsent(v.elem, fullKey);
|
|
398
|
+
if (existing === void 0 || elem === void 0) return void 0;
|
|
399
|
+
return { _kind: "append-placeholder", existing, elem };
|
|
400
|
+
}
|
|
401
|
+
if (isResObj(v)) {
|
|
402
|
+
const fields = /* @__PURE__ */ new Map();
|
|
403
|
+
for (const [key, value] of v.fields) {
|
|
404
|
+
const folded = foldOptionalSelfRefAbsent(value, fullKey);
|
|
405
|
+
if (folded === void 0) return void 0;
|
|
406
|
+
fields.set(key, folded);
|
|
407
|
+
}
|
|
408
|
+
return { _kind: "res-obj", fields, priorValues: new Map(v.priorValues) };
|
|
409
|
+
}
|
|
410
|
+
const hv = v;
|
|
411
|
+
if (hv.kind === "array") {
|
|
412
|
+
const items = [];
|
|
413
|
+
for (const item of hv.items) {
|
|
414
|
+
const folded = foldOptionalSelfRefAbsent(item, fullKey);
|
|
415
|
+
if (folded === void 0) return void 0;
|
|
416
|
+
items.push(folded);
|
|
417
|
+
}
|
|
418
|
+
return { kind: "array", items };
|
|
419
|
+
}
|
|
420
|
+
if (hv.kind === "object") {
|
|
421
|
+
const fields = /* @__PURE__ */ new Map();
|
|
422
|
+
for (const [key, value] of hv.fields) {
|
|
423
|
+
const folded = foldOptionalSelfRefAbsent(value, fullKey);
|
|
424
|
+
if (folded === void 0) return void 0;
|
|
425
|
+
fields.set(key, folded);
|
|
426
|
+
}
|
|
427
|
+
return { kind: "object", fields };
|
|
428
|
+
}
|
|
429
|
+
return cloneResolverValue(v);
|
|
430
|
+
}
|
|
372
431
|
function cloneResolverValue(v) {
|
|
373
432
|
if (isSubst(v)) {
|
|
374
433
|
return {
|
|
375
434
|
_kind: "subst-placeholder",
|
|
376
435
|
segments: v.segments.map((seg) => ({ text: seg.text, line: seg.line, col: seg.col })),
|
|
377
436
|
optional: v.optional,
|
|
437
|
+
knownAbsent: v.knownAbsent,
|
|
378
438
|
listSuffix: v.listSuffix,
|
|
379
439
|
line: v.line,
|
|
380
440
|
col: v.col,
|
|
@@ -439,7 +499,7 @@ function foldNestedSelfRefs(v, pathPrefix) {
|
|
|
439
499
|
return { _kind: "res-obj", fields: newFields, priorValues: new Map(v.priorValues) };
|
|
440
500
|
}
|
|
441
501
|
function containsSubstByPath(v, target) {
|
|
442
|
-
if (isSubst(v)) return segmentsTextEqual(v.segments, target);
|
|
502
|
+
if (isSubst(v)) return !v.knownAbsent && segmentsTextEqual(v.segments, target);
|
|
443
503
|
if (isConcat(v)) return v.nodes.some((n) => containsSubstByPath(n, target));
|
|
444
504
|
if (isAppend(v)) {
|
|
445
505
|
return containsSubstByPath(v.existing, target) || containsSubstByPath(v.elem, target);
|
|
@@ -606,6 +666,11 @@ var Lexer = class {
|
|
|
606
666
|
this.line = 1;
|
|
607
667
|
this.col = 1;
|
|
608
668
|
this.hadSpace = false;
|
|
669
|
+
// Accumulates literal whitespace chars consumed between tokens. Reset on every
|
|
670
|
+
// token push. Used so the parser can preserve path-expression whitespace
|
|
671
|
+
// (xx.hocon#42, E13) — e.g. tab vs space adjacent to dots in key paths.
|
|
672
|
+
// Comment text is NOT accumulated; only the actual WS chars.
|
|
673
|
+
this.whitespaceBuffer = "";
|
|
609
674
|
this.tokens = [];
|
|
610
675
|
if (input.charCodeAt(0) === 65279) this.input = input.slice(1);
|
|
611
676
|
}
|
|
@@ -621,6 +686,7 @@ var Lexer = class {
|
|
|
621
686
|
continue;
|
|
622
687
|
}
|
|
623
688
|
if (isHoconWhitespace(ch)) {
|
|
689
|
+
this.whitespaceBuffer += ch;
|
|
624
690
|
this.advance();
|
|
625
691
|
this.hadSpace = true;
|
|
626
692
|
continue;
|
|
@@ -712,7 +778,7 @@ var Lexer = class {
|
|
|
712
778
|
}
|
|
713
779
|
throw new ParseError(`unexpected character: ${JSON.stringify(ch)}`, sl, sc);
|
|
714
780
|
}
|
|
715
|
-
this.tokens.push({ kind: "eof", value: "", line: this.line, col: this.col, isQuoted: false, precedingSpace: false });
|
|
781
|
+
this.tokens.push({ kind: "eof", value: "", line: this.line, col: this.col, isQuoted: false, precedingSpace: false, precedingWhitespace: "" });
|
|
716
782
|
return this.tokens;
|
|
717
783
|
}
|
|
718
784
|
peek(offset = 0) {
|
|
@@ -729,12 +795,14 @@ var Lexer = class {
|
|
|
729
795
|
return ch;
|
|
730
796
|
}
|
|
731
797
|
push(kind, value, l, c, isQuoted = false) {
|
|
732
|
-
this.tokens.push({ kind, value, line: l, col: c, isQuoted, precedingSpace: this.hadSpace });
|
|
798
|
+
this.tokens.push({ kind, value, line: l, col: c, isQuoted, precedingSpace: this.hadSpace, precedingWhitespace: this.whitespaceBuffer });
|
|
733
799
|
this.hadSpace = false;
|
|
800
|
+
this.whitespaceBuffer = "";
|
|
734
801
|
}
|
|
735
802
|
pushSubst(payload, value, l, c) {
|
|
736
|
-
this.tokens.push({ kind: "subst", value, line: l, col: c, isQuoted: false, precedingSpace: this.hadSpace, subst: payload });
|
|
803
|
+
this.tokens.push({ kind: "subst", value, line: l, col: c, isQuoted: false, precedingSpace: this.hadSpace, precedingWhitespace: this.whitespaceBuffer, subst: payload });
|
|
737
804
|
this.hadSpace = false;
|
|
805
|
+
this.whitespaceBuffer = "";
|
|
738
806
|
}
|
|
739
807
|
/**
|
|
740
808
|
* Read body of a quoted string. Opening `"` must already be consumed.
|
|
@@ -980,7 +1048,7 @@ function isUnquotedContinue(ch, nextFn) {
|
|
|
980
1048
|
}
|
|
981
1049
|
|
|
982
1050
|
// src/internal/parser/parser.ts
|
|
983
|
-
var EOF_TOKEN = { kind: "eof", value: "", line: 0, col: 0, isQuoted: false, precedingSpace: false, subst: void 0 };
|
|
1051
|
+
var EOF_TOKEN = { kind: "eof", value: "", line: 0, col: 0, isQuoted: false, precedingSpace: false, precedingWhitespace: "", subst: void 0 };
|
|
984
1052
|
var Parser = class {
|
|
985
1053
|
constructor(tokens) {
|
|
986
1054
|
this.tokens = tokens;
|
|
@@ -1093,13 +1161,17 @@ var Parser = class {
|
|
|
1093
1161
|
let trailingDot = false;
|
|
1094
1162
|
let firstWasQuoted = false;
|
|
1095
1163
|
let spaceConcat = false;
|
|
1164
|
+
let postDotPrefix = "";
|
|
1096
1165
|
while (true) {
|
|
1097
1166
|
const t = this.peek();
|
|
1098
1167
|
if (t.kind === "string") {
|
|
1099
1168
|
this.advance();
|
|
1100
1169
|
if (segments.length === 0) firstWasQuoted = true;
|
|
1101
1170
|
if (spaceConcat) {
|
|
1102
|
-
segments[segments.length - 1] = `${segments[segments.length - 1]}
|
|
1171
|
+
segments[segments.length - 1] = `${segments[segments.length - 1]}${t.precedingWhitespace}${t.value}`;
|
|
1172
|
+
} else if (postDotPrefix !== "") {
|
|
1173
|
+
segments.push(`${postDotPrefix}${t.value}`);
|
|
1174
|
+
postDotPrefix = "";
|
|
1103
1175
|
} else {
|
|
1104
1176
|
segments.push(t.value);
|
|
1105
1177
|
}
|
|
@@ -1109,24 +1181,23 @@ var Parser = class {
|
|
|
1109
1181
|
const raw = t.value.startsWith(".") && segments.length > 0 && !t.precedingSpace ? t.value.slice(1) : t.value;
|
|
1110
1182
|
const parts = raw.split(".");
|
|
1111
1183
|
const filtered = parts.filter((s) => s.length > 0);
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
const after = seg.length >= 2 ? JSON.stringify(seg[1]) : "EOF";
|
|
1115
|
-
throw new ParseError(
|
|
1116
|
-
`unquoted key segment cannot begin with '-' unless followed by a digit (got '-' then ${after} in ${JSON.stringify(seg)}, HOCON.md L270-276)`,
|
|
1117
|
-
t.line,
|
|
1118
|
-
t.col
|
|
1119
|
-
);
|
|
1120
|
-
}
|
|
1121
|
-
}
|
|
1122
|
-
if (spaceConcat && filtered.length > 0) {
|
|
1184
|
+
if (spaceConcat) {
|
|
1185
|
+
segments[segments.length - 1] = `${segments[segments.length - 1]}${t.precedingWhitespace}`;
|
|
1123
1186
|
if (raw.startsWith(".")) {
|
|
1124
1187
|
segments.push(...filtered);
|
|
1125
|
-
} else {
|
|
1188
|
+
} else if (filtered.length > 0) {
|
|
1126
1189
|
const [head, ...tail] = filtered;
|
|
1127
|
-
segments[segments.length - 1] = `${segments[segments.length - 1]}
|
|
1190
|
+
segments[segments.length - 1] = `${segments[segments.length - 1]}${head}`;
|
|
1128
1191
|
segments.push(...tail);
|
|
1129
1192
|
}
|
|
1193
|
+
} else if (postDotPrefix !== "" && raw.startsWith(".")) {
|
|
1194
|
+
segments.push(postDotPrefix);
|
|
1195
|
+
postDotPrefix = "";
|
|
1196
|
+
segments.push(...filtered);
|
|
1197
|
+
} else if (postDotPrefix !== "" && filtered.length > 0) {
|
|
1198
|
+
const [head, ...tail] = filtered;
|
|
1199
|
+
segments.push(`${postDotPrefix}${head}`, ...tail);
|
|
1200
|
+
postDotPrefix = "";
|
|
1130
1201
|
} else {
|
|
1131
1202
|
segments.push(...filtered);
|
|
1132
1203
|
}
|
|
@@ -1136,11 +1207,23 @@ var Parser = class {
|
|
|
1136
1207
|
break;
|
|
1137
1208
|
}
|
|
1138
1209
|
spaceConcat = false;
|
|
1139
|
-
if (trailingDot)
|
|
1210
|
+
if (trailingDot) {
|
|
1211
|
+
const next2 = this.peek();
|
|
1212
|
+
if ((next2.kind === "unquoted" || next2.kind === "string") && next2.precedingWhitespace.length > 0) {
|
|
1213
|
+
postDotPrefix = next2.precedingWhitespace;
|
|
1214
|
+
} else {
|
|
1215
|
+
postDotPrefix = "";
|
|
1216
|
+
}
|
|
1217
|
+
continue;
|
|
1218
|
+
}
|
|
1140
1219
|
const next = this.peek();
|
|
1141
1220
|
if (next.kind === "unquoted" && next.value === "." && !next.precedingSpace) {
|
|
1142
1221
|
this.advance();
|
|
1143
1222
|
trailingDot = true;
|
|
1223
|
+
const afterDot = this.peek();
|
|
1224
|
+
if ((afterDot.kind === "unquoted" || afterDot.kind === "string") && afterDot.precedingWhitespace.length > 0) {
|
|
1225
|
+
postDotPrefix = afterDot.precedingWhitespace;
|
|
1226
|
+
}
|
|
1144
1227
|
continue;
|
|
1145
1228
|
}
|
|
1146
1229
|
if (next.kind === "unquoted" && next.value.startsWith(".") && !next.precedingSpace) {
|
|
@@ -1153,6 +1236,14 @@ var Parser = class {
|
|
|
1153
1236
|
}
|
|
1154
1237
|
break;
|
|
1155
1238
|
}
|
|
1239
|
+
if (trailingDot) {
|
|
1240
|
+
const here = this.peek();
|
|
1241
|
+
throw new ParseError(
|
|
1242
|
+
`path has a trailing period '.' \u2014 empty key segment not allowed (HOCON.md path rules)`,
|
|
1243
|
+
here.line,
|
|
1244
|
+
here.col
|
|
1245
|
+
);
|
|
1246
|
+
}
|
|
1156
1247
|
return { segments, firstWasQuoted };
|
|
1157
1248
|
}
|
|
1158
1249
|
parseInclude() {
|
|
@@ -1325,7 +1416,8 @@ var Parser = class {
|
|
|
1325
1416
|
break;
|
|
1326
1417
|
}
|
|
1327
1418
|
if (hadSpace) {
|
|
1328
|
-
|
|
1419
|
+
const sep = t.precedingWhitespace.length > 0 ? t.precedingWhitespace : " ";
|
|
1420
|
+
parts.push({ kind: "scalar", raw: sep, valueType: "string", pos: { line: t.line, col: t.col }, _separator: true });
|
|
1329
1421
|
}
|
|
1330
1422
|
parts.push(node);
|
|
1331
1423
|
}
|
|
@@ -1786,9 +1878,9 @@ var StructureBuilder = class _StructureBuilder {
|
|
|
1786
1878
|
const existing = obj.fields.get(head);
|
|
1787
1879
|
const newVal = this.astToResolverValue(field.value, childPrefix);
|
|
1788
1880
|
if (existing !== void 0) {
|
|
1789
|
-
const exFolded = foldNestedSelfRefs(existing, childPrefix);
|
|
1790
1881
|
const oldPrior = obj.priorValues.get(head);
|
|
1791
|
-
const
|
|
1882
|
+
const priorInput = isResObj(existing) ? foldNestedSelfRefs(existing, childPrefix) : existing;
|
|
1883
|
+
const prior = foldOrSkipPrior(priorInput, fullKey, oldPrior);
|
|
1792
1884
|
if (prior !== void 0) obj.priorValues.set(head, prior);
|
|
1793
1885
|
}
|
|
1794
1886
|
if (existing !== void 0 && isResObj(existing) && isResObj(newVal)) {
|
|
@@ -1840,9 +1932,9 @@ var StructureBuilder = class _StructureBuilder {
|
|
|
1840
1932
|
const existing = obj.fields.get(head);
|
|
1841
1933
|
const newVal = await this.astToResolverValueAsync(field.value, childPrefix);
|
|
1842
1934
|
if (existing !== void 0) {
|
|
1843
|
-
const exFolded = foldNestedSelfRefs(existing, childPrefix);
|
|
1844
1935
|
const oldPrior = obj.priorValues.get(head);
|
|
1845
|
-
const
|
|
1936
|
+
const priorInput = isResObj(existing) ? foldNestedSelfRefs(existing, childPrefix) : existing;
|
|
1937
|
+
const prior = foldOrSkipPrior(priorInput, fullKey, oldPrior);
|
|
1846
1938
|
if (prior !== void 0) obj.priorValues.set(head, prior);
|
|
1847
1939
|
}
|
|
1848
1940
|
if (existing !== void 0 && isResObj(existing) && isResObj(newVal)) {
|
|
@@ -1865,7 +1957,7 @@ var StructureBuilder = class _StructureBuilder {
|
|
|
1865
1957
|
return inner;
|
|
1866
1958
|
}
|
|
1867
1959
|
case "subst":
|
|
1868
|
-
return { _kind: "subst-placeholder", segments: ast.segments, optional: ast.optional, listSuffix: ast.listSuffix, line: ast.pos.line, col: ast.pos.col, prefixLen: 0 };
|
|
1960
|
+
return { _kind: "subst-placeholder", segments: ast.segments, optional: ast.optional, knownAbsent: false, listSuffix: ast.listSuffix, line: ast.pos.line, col: ast.pos.col, prefixLen: 0 };
|
|
1869
1961
|
case "concat":
|
|
1870
1962
|
return { _kind: "concat-placeholder", nodes: ast.nodes.map((n) => this.astToResolverValue(n, pathPrefix)), line: ast.pos.line, col: ast.pos.col };
|
|
1871
1963
|
case "include":
|
|
@@ -1889,7 +1981,7 @@ var StructureBuilder = class _StructureBuilder {
|
|
|
1889
1981
|
case "object":
|
|
1890
1982
|
return await this.buildAsync(ast, pathPrefix);
|
|
1891
1983
|
case "subst":
|
|
1892
|
-
return { _kind: "subst-placeholder", segments: ast.segments, optional: ast.optional, listSuffix: ast.listSuffix, line: ast.pos.line, col: ast.pos.col, prefixLen: 0 };
|
|
1984
|
+
return { _kind: "subst-placeholder", segments: ast.segments, optional: ast.optional, knownAbsent: false, listSuffix: ast.listSuffix, line: ast.pos.line, col: ast.pos.col, prefixLen: 0 };
|
|
1893
1985
|
case "concat": {
|
|
1894
1986
|
const nodes = [];
|
|
1895
1987
|
for (const n of ast.nodes) {
|
|
@@ -2007,6 +2099,8 @@ var SubstitutionResolver = class {
|
|
|
2007
2099
|
const result = /* @__PURE__ */ new Map();
|
|
2008
2100
|
for (const [key, val] of obj.fields) {
|
|
2009
2101
|
this.resolvingFieldPath.push(key);
|
|
2102
|
+
const fullCacheKey = stringSegmentsToKey(this.resolvingFieldPath);
|
|
2103
|
+
this.cache.delete(fullCacheKey);
|
|
2010
2104
|
let resolved;
|
|
2011
2105
|
try {
|
|
2012
2106
|
resolved = this.resolveVal(val, obj);
|
|
@@ -2019,28 +2113,42 @@ var SubstitutionResolver = class {
|
|
|
2019
2113
|
if (prior !== void 0) {
|
|
2020
2114
|
const priorResolved = this.resolveVal(prior, obj);
|
|
2021
2115
|
if (priorResolved !== void 0 && priorResolved.kind === "object") {
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
priorResolved,
|
|
2026
|
-
resolved
|
|
2027
|
-
)
|
|
2116
|
+
const finalValue = deepMergeHoconValues(
|
|
2117
|
+
priorResolved,
|
|
2118
|
+
resolved
|
|
2028
2119
|
);
|
|
2120
|
+
result.set(key, finalValue);
|
|
2121
|
+
this.cache.set(fullCacheKey, finalValue);
|
|
2122
|
+
this.cacheDescendants(fullCacheKey, finalValue);
|
|
2029
2123
|
continue;
|
|
2030
2124
|
}
|
|
2031
2125
|
}
|
|
2032
2126
|
}
|
|
2033
2127
|
result.set(key, resolved);
|
|
2128
|
+
this.cache.set(fullCacheKey, resolved);
|
|
2129
|
+
this.cacheDescendants(fullCacheKey, resolved);
|
|
2034
2130
|
} else {
|
|
2035
2131
|
const prior = obj.priorValues.get(key);
|
|
2036
2132
|
if (prior !== void 0) {
|
|
2037
2133
|
const priorResolved = this.resolveVal(prior, obj);
|
|
2038
|
-
if (priorResolved !== void 0)
|
|
2134
|
+
if (priorResolved !== void 0) {
|
|
2135
|
+
result.set(key, priorResolved);
|
|
2136
|
+
this.cache.set(fullCacheKey, priorResolved);
|
|
2137
|
+
this.cacheDescendants(fullCacheKey, priorResolved);
|
|
2138
|
+
}
|
|
2039
2139
|
}
|
|
2040
2140
|
}
|
|
2041
2141
|
}
|
|
2042
2142
|
return { kind: "object", fields: result };
|
|
2043
2143
|
}
|
|
2144
|
+
cacheDescendants(prefix, value) {
|
|
2145
|
+
if (value.kind !== "object") return;
|
|
2146
|
+
for (const [key, child] of value.fields) {
|
|
2147
|
+
const childKey = `${prefix}.${stringSegmentsToKey([key])}`;
|
|
2148
|
+
this.cache.set(childKey, child);
|
|
2149
|
+
this.cacheDescendants(childKey, child);
|
|
2150
|
+
}
|
|
2151
|
+
}
|
|
2044
2152
|
resolveVal(v, scope) {
|
|
2045
2153
|
if (isSubst(v)) return this.resolveSubst(v, scope);
|
|
2046
2154
|
if (isConcat(v)) {
|
|
@@ -2066,6 +2174,7 @@ var SubstitutionResolver = class {
|
|
|
2066
2174
|
return hv;
|
|
2067
2175
|
}
|
|
2068
2176
|
resolveSubst(s, scope) {
|
|
2177
|
+
if (s.knownAbsent) return void 0;
|
|
2069
2178
|
const key = s.listSuffix ? `${segmentsToKey(s.segments)}[]` : segmentsToKey(s.segments);
|
|
2070
2179
|
if (this.cache.has(key)) return this.cache.get(key);
|
|
2071
2180
|
if (this.resolving.has(key)) {
|
|
@@ -2158,6 +2267,28 @@ var SubstitutionResolver = class {
|
|
|
2158
2267
|
if (result !== void 0) this.cache.set(key, result);
|
|
2159
2268
|
return result;
|
|
2160
2269
|
}
|
|
2270
|
+
if (s.prefixLen > 0 && s.segments.length > s.prefixLen) {
|
|
2271
|
+
const originalSegments = s.segments.slice(s.prefixLen);
|
|
2272
|
+
const fallbackFound = lookupPath(this.root, originalSegments);
|
|
2273
|
+
if (fallbackFound !== void 0) {
|
|
2274
|
+
let result = this.resolveVal(fallbackFound, scope);
|
|
2275
|
+
if (originalSegments.length === 1 && result !== void 0 && result.kind === "object") {
|
|
2276
|
+
const rootSeg = originalSegments[0]?.text ?? "";
|
|
2277
|
+
const prior = this.root.priorValues.get(rootSeg);
|
|
2278
|
+
if (prior !== void 0) {
|
|
2279
|
+
const priorResolved = this.resolveVal(prior, scope);
|
|
2280
|
+
if (priorResolved !== void 0 && priorResolved.kind === "object") {
|
|
2281
|
+
result = deepMergeHoconValues(
|
|
2282
|
+
priorResolved,
|
|
2283
|
+
result
|
|
2284
|
+
);
|
|
2285
|
+
}
|
|
2286
|
+
}
|
|
2287
|
+
}
|
|
2288
|
+
if (result !== void 0) this.cache.set(key, result);
|
|
2289
|
+
return result;
|
|
2290
|
+
}
|
|
2291
|
+
}
|
|
2161
2292
|
if (s.listSuffix && this.opts.useSystemEnvironment !== false) {
|
|
2162
2293
|
const result = this.resolveEnvList(s);
|
|
2163
2294
|
if (result !== void 0) {
|