@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/zod.js
CHANGED
|
@@ -303,7 +303,7 @@ function stringSegmentsToKey(segments) {
|
|
|
303
303
|
}).join(".");
|
|
304
304
|
}
|
|
305
305
|
function containsSelfRef(v, fullKey) {
|
|
306
|
-
if (isSubst(v)) return substFullKey(v) === fullKey;
|
|
306
|
+
if (isSubst(v)) return !v.knownAbsent && substFullKey(v) === fullKey;
|
|
307
307
|
if (isConcat(v)) return v.nodes.some((n) => containsSelfRef(n, fullKey));
|
|
308
308
|
if (isAppend(v)) {
|
|
309
309
|
return containsSelfRef(v.existing, fullKey) || containsSelfRef(v.elem, fullKey);
|
|
@@ -370,15 +370,75 @@ function foldSelfRef(v, fullKey, replacement) {
|
|
|
370
370
|
}
|
|
371
371
|
function foldOrSkipPrior(prior, fullKey, old) {
|
|
372
372
|
if (!containsSelfRef(prior, fullKey)) return cloneResolverValue(prior);
|
|
373
|
-
if (old === void 0) return
|
|
373
|
+
if (old === void 0) return foldOptionalSelfRefAbsent(prior, fullKey);
|
|
374
374
|
return foldSelfRef(prior, fullKey, old);
|
|
375
375
|
}
|
|
376
|
+
function foldOptionalSelfRefAbsent(v, fullKey) {
|
|
377
|
+
if (isSubst(v) && substFullKey(v) === fullKey) {
|
|
378
|
+
if (!v.optional) return void 0;
|
|
379
|
+
return {
|
|
380
|
+
_kind: "subst-placeholder",
|
|
381
|
+
segments: v.segments.map((seg) => ({ text: seg.text, line: seg.line, col: seg.col })),
|
|
382
|
+
optional: v.optional,
|
|
383
|
+
knownAbsent: true,
|
|
384
|
+
listSuffix: v.listSuffix,
|
|
385
|
+
line: v.line,
|
|
386
|
+
col: v.col,
|
|
387
|
+
prefixLen: v.prefixLen
|
|
388
|
+
};
|
|
389
|
+
}
|
|
390
|
+
if (isConcat(v)) {
|
|
391
|
+
const nodes = [];
|
|
392
|
+
for (const node of v.nodes) {
|
|
393
|
+
const folded = foldOptionalSelfRefAbsent(node, fullKey);
|
|
394
|
+
if (folded === void 0) return void 0;
|
|
395
|
+
nodes.push(folded);
|
|
396
|
+
}
|
|
397
|
+
return { _kind: "concat-placeholder", nodes, line: v.line, col: v.col };
|
|
398
|
+
}
|
|
399
|
+
if (isAppend(v)) {
|
|
400
|
+
const existing = foldOptionalSelfRefAbsent(v.existing, fullKey);
|
|
401
|
+
const elem = foldOptionalSelfRefAbsent(v.elem, fullKey);
|
|
402
|
+
if (existing === void 0 || elem === void 0) return void 0;
|
|
403
|
+
return { _kind: "append-placeholder", existing, elem };
|
|
404
|
+
}
|
|
405
|
+
if (isResObj(v)) {
|
|
406
|
+
const fields = /* @__PURE__ */ new Map();
|
|
407
|
+
for (const [key, value] of v.fields) {
|
|
408
|
+
const folded = foldOptionalSelfRefAbsent(value, fullKey);
|
|
409
|
+
if (folded === void 0) return void 0;
|
|
410
|
+
fields.set(key, folded);
|
|
411
|
+
}
|
|
412
|
+
return { _kind: "res-obj", fields, priorValues: new Map(v.priorValues) };
|
|
413
|
+
}
|
|
414
|
+
const hv = v;
|
|
415
|
+
if (hv.kind === "array") {
|
|
416
|
+
const items = [];
|
|
417
|
+
for (const item of hv.items) {
|
|
418
|
+
const folded = foldOptionalSelfRefAbsent(item, fullKey);
|
|
419
|
+
if (folded === void 0) return void 0;
|
|
420
|
+
items.push(folded);
|
|
421
|
+
}
|
|
422
|
+
return { kind: "array", items };
|
|
423
|
+
}
|
|
424
|
+
if (hv.kind === "object") {
|
|
425
|
+
const fields = /* @__PURE__ */ new Map();
|
|
426
|
+
for (const [key, value] of hv.fields) {
|
|
427
|
+
const folded = foldOptionalSelfRefAbsent(value, fullKey);
|
|
428
|
+
if (folded === void 0) return void 0;
|
|
429
|
+
fields.set(key, folded);
|
|
430
|
+
}
|
|
431
|
+
return { kind: "object", fields };
|
|
432
|
+
}
|
|
433
|
+
return cloneResolverValue(v);
|
|
434
|
+
}
|
|
376
435
|
function cloneResolverValue(v) {
|
|
377
436
|
if (isSubst(v)) {
|
|
378
437
|
return {
|
|
379
438
|
_kind: "subst-placeholder",
|
|
380
439
|
segments: v.segments.map((seg) => ({ text: seg.text, line: seg.line, col: seg.col })),
|
|
381
440
|
optional: v.optional,
|
|
441
|
+
knownAbsent: v.knownAbsent,
|
|
382
442
|
listSuffix: v.listSuffix,
|
|
383
443
|
line: v.line,
|
|
384
444
|
col: v.col,
|
|
@@ -443,7 +503,7 @@ function foldNestedSelfRefs(v, pathPrefix) {
|
|
|
443
503
|
return { _kind: "res-obj", fields: newFields, priorValues: new Map(v.priorValues) };
|
|
444
504
|
}
|
|
445
505
|
function containsSubstByPath(v, target) {
|
|
446
|
-
if (isSubst(v)) return segmentsTextEqual(v.segments, target);
|
|
506
|
+
if (isSubst(v)) return !v.knownAbsent && segmentsTextEqual(v.segments, target);
|
|
447
507
|
if (isConcat(v)) return v.nodes.some((n) => containsSubstByPath(n, target));
|
|
448
508
|
if (isAppend(v)) {
|
|
449
509
|
return containsSubstByPath(v.existing, target) || containsSubstByPath(v.elem, target);
|
|
@@ -610,6 +670,11 @@ var Lexer = class {
|
|
|
610
670
|
this.line = 1;
|
|
611
671
|
this.col = 1;
|
|
612
672
|
this.hadSpace = false;
|
|
673
|
+
// Accumulates literal whitespace chars consumed between tokens. Reset on every
|
|
674
|
+
// token push. Used so the parser can preserve path-expression whitespace
|
|
675
|
+
// (xx.hocon#42, E13) — e.g. tab vs space adjacent to dots in key paths.
|
|
676
|
+
// Comment text is NOT accumulated; only the actual WS chars.
|
|
677
|
+
this.whitespaceBuffer = "";
|
|
613
678
|
this.tokens = [];
|
|
614
679
|
if (input.charCodeAt(0) === 65279) this.input = input.slice(1);
|
|
615
680
|
}
|
|
@@ -625,6 +690,7 @@ var Lexer = class {
|
|
|
625
690
|
continue;
|
|
626
691
|
}
|
|
627
692
|
if (isHoconWhitespace(ch)) {
|
|
693
|
+
this.whitespaceBuffer += ch;
|
|
628
694
|
this.advance();
|
|
629
695
|
this.hadSpace = true;
|
|
630
696
|
continue;
|
|
@@ -716,7 +782,7 @@ var Lexer = class {
|
|
|
716
782
|
}
|
|
717
783
|
throw new ParseError(`unexpected character: ${JSON.stringify(ch)}`, sl, sc);
|
|
718
784
|
}
|
|
719
|
-
this.tokens.push({ kind: "eof", value: "", line: this.line, col: this.col, isQuoted: false, precedingSpace: false });
|
|
785
|
+
this.tokens.push({ kind: "eof", value: "", line: this.line, col: this.col, isQuoted: false, precedingSpace: false, precedingWhitespace: "" });
|
|
720
786
|
return this.tokens;
|
|
721
787
|
}
|
|
722
788
|
peek(offset = 0) {
|
|
@@ -733,12 +799,14 @@ var Lexer = class {
|
|
|
733
799
|
return ch;
|
|
734
800
|
}
|
|
735
801
|
push(kind, value, l, c, isQuoted = false) {
|
|
736
|
-
this.tokens.push({ kind, value, line: l, col: c, isQuoted, precedingSpace: this.hadSpace });
|
|
802
|
+
this.tokens.push({ kind, value, line: l, col: c, isQuoted, precedingSpace: this.hadSpace, precedingWhitespace: this.whitespaceBuffer });
|
|
737
803
|
this.hadSpace = false;
|
|
804
|
+
this.whitespaceBuffer = "";
|
|
738
805
|
}
|
|
739
806
|
pushSubst(payload, value, l, c) {
|
|
740
|
-
this.tokens.push({ kind: "subst", value, line: l, col: c, isQuoted: false, precedingSpace: this.hadSpace, subst: payload });
|
|
807
|
+
this.tokens.push({ kind: "subst", value, line: l, col: c, isQuoted: false, precedingSpace: this.hadSpace, precedingWhitespace: this.whitespaceBuffer, subst: payload });
|
|
741
808
|
this.hadSpace = false;
|
|
809
|
+
this.whitespaceBuffer = "";
|
|
742
810
|
}
|
|
743
811
|
/**
|
|
744
812
|
* Read body of a quoted string. Opening `"` must already be consumed.
|
|
@@ -984,7 +1052,7 @@ function isUnquotedContinue(ch, nextFn) {
|
|
|
984
1052
|
}
|
|
985
1053
|
|
|
986
1054
|
// src/internal/parser/parser.ts
|
|
987
|
-
var EOF_TOKEN = { kind: "eof", value: "", line: 0, col: 0, isQuoted: false, precedingSpace: false, subst: void 0 };
|
|
1055
|
+
var EOF_TOKEN = { kind: "eof", value: "", line: 0, col: 0, isQuoted: false, precedingSpace: false, precedingWhitespace: "", subst: void 0 };
|
|
988
1056
|
var Parser = class {
|
|
989
1057
|
constructor(tokens) {
|
|
990
1058
|
this.tokens = tokens;
|
|
@@ -1097,13 +1165,17 @@ var Parser = class {
|
|
|
1097
1165
|
let trailingDot = false;
|
|
1098
1166
|
let firstWasQuoted = false;
|
|
1099
1167
|
let spaceConcat = false;
|
|
1168
|
+
let postDotPrefix = "";
|
|
1100
1169
|
while (true) {
|
|
1101
1170
|
const t = this.peek();
|
|
1102
1171
|
if (t.kind === "string") {
|
|
1103
1172
|
this.advance();
|
|
1104
1173
|
if (segments.length === 0) firstWasQuoted = true;
|
|
1105
1174
|
if (spaceConcat) {
|
|
1106
|
-
segments[segments.length - 1] = `${segments[segments.length - 1]}
|
|
1175
|
+
segments[segments.length - 1] = `${segments[segments.length - 1]}${t.precedingWhitespace}${t.value}`;
|
|
1176
|
+
} else if (postDotPrefix !== "") {
|
|
1177
|
+
segments.push(`${postDotPrefix}${t.value}`);
|
|
1178
|
+
postDotPrefix = "";
|
|
1107
1179
|
} else {
|
|
1108
1180
|
segments.push(t.value);
|
|
1109
1181
|
}
|
|
@@ -1113,24 +1185,23 @@ var Parser = class {
|
|
|
1113
1185
|
const raw = t.value.startsWith(".") && segments.length > 0 && !t.precedingSpace ? t.value.slice(1) : t.value;
|
|
1114
1186
|
const parts = raw.split(".");
|
|
1115
1187
|
const filtered = parts.filter((s) => s.length > 0);
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
const after = seg.length >= 2 ? JSON.stringify(seg[1]) : "EOF";
|
|
1119
|
-
throw new ParseError(
|
|
1120
|
-
`unquoted key segment cannot begin with '-' unless followed by a digit (got '-' then ${after} in ${JSON.stringify(seg)}, HOCON.md L270-276)`,
|
|
1121
|
-
t.line,
|
|
1122
|
-
t.col
|
|
1123
|
-
);
|
|
1124
|
-
}
|
|
1125
|
-
}
|
|
1126
|
-
if (spaceConcat && filtered.length > 0) {
|
|
1188
|
+
if (spaceConcat) {
|
|
1189
|
+
segments[segments.length - 1] = `${segments[segments.length - 1]}${t.precedingWhitespace}`;
|
|
1127
1190
|
if (raw.startsWith(".")) {
|
|
1128
1191
|
segments.push(...filtered);
|
|
1129
|
-
} else {
|
|
1192
|
+
} else if (filtered.length > 0) {
|
|
1130
1193
|
const [head, ...tail] = filtered;
|
|
1131
|
-
segments[segments.length - 1] = `${segments[segments.length - 1]}
|
|
1194
|
+
segments[segments.length - 1] = `${segments[segments.length - 1]}${head}`;
|
|
1132
1195
|
segments.push(...tail);
|
|
1133
1196
|
}
|
|
1197
|
+
} else if (postDotPrefix !== "" && raw.startsWith(".")) {
|
|
1198
|
+
segments.push(postDotPrefix);
|
|
1199
|
+
postDotPrefix = "";
|
|
1200
|
+
segments.push(...filtered);
|
|
1201
|
+
} else if (postDotPrefix !== "" && filtered.length > 0) {
|
|
1202
|
+
const [head, ...tail] = filtered;
|
|
1203
|
+
segments.push(`${postDotPrefix}${head}`, ...tail);
|
|
1204
|
+
postDotPrefix = "";
|
|
1134
1205
|
} else {
|
|
1135
1206
|
segments.push(...filtered);
|
|
1136
1207
|
}
|
|
@@ -1140,11 +1211,23 @@ var Parser = class {
|
|
|
1140
1211
|
break;
|
|
1141
1212
|
}
|
|
1142
1213
|
spaceConcat = false;
|
|
1143
|
-
if (trailingDot)
|
|
1214
|
+
if (trailingDot) {
|
|
1215
|
+
const next2 = this.peek();
|
|
1216
|
+
if ((next2.kind === "unquoted" || next2.kind === "string") && next2.precedingWhitespace.length > 0) {
|
|
1217
|
+
postDotPrefix = next2.precedingWhitespace;
|
|
1218
|
+
} else {
|
|
1219
|
+
postDotPrefix = "";
|
|
1220
|
+
}
|
|
1221
|
+
continue;
|
|
1222
|
+
}
|
|
1144
1223
|
const next = this.peek();
|
|
1145
1224
|
if (next.kind === "unquoted" && next.value === "." && !next.precedingSpace) {
|
|
1146
1225
|
this.advance();
|
|
1147
1226
|
trailingDot = true;
|
|
1227
|
+
const afterDot = this.peek();
|
|
1228
|
+
if ((afterDot.kind === "unquoted" || afterDot.kind === "string") && afterDot.precedingWhitespace.length > 0) {
|
|
1229
|
+
postDotPrefix = afterDot.precedingWhitespace;
|
|
1230
|
+
}
|
|
1148
1231
|
continue;
|
|
1149
1232
|
}
|
|
1150
1233
|
if (next.kind === "unquoted" && next.value.startsWith(".") && !next.precedingSpace) {
|
|
@@ -1157,6 +1240,14 @@ var Parser = class {
|
|
|
1157
1240
|
}
|
|
1158
1241
|
break;
|
|
1159
1242
|
}
|
|
1243
|
+
if (trailingDot) {
|
|
1244
|
+
const here = this.peek();
|
|
1245
|
+
throw new ParseError(
|
|
1246
|
+
`path has a trailing period '.' \u2014 empty key segment not allowed (HOCON.md path rules)`,
|
|
1247
|
+
here.line,
|
|
1248
|
+
here.col
|
|
1249
|
+
);
|
|
1250
|
+
}
|
|
1160
1251
|
return { segments, firstWasQuoted };
|
|
1161
1252
|
}
|
|
1162
1253
|
parseInclude() {
|
|
@@ -1329,7 +1420,8 @@ var Parser = class {
|
|
|
1329
1420
|
break;
|
|
1330
1421
|
}
|
|
1331
1422
|
if (hadSpace) {
|
|
1332
|
-
|
|
1423
|
+
const sep = t.precedingWhitespace.length > 0 ? t.precedingWhitespace : " ";
|
|
1424
|
+
parts.push({ kind: "scalar", raw: sep, valueType: "string", pos: { line: t.line, col: t.col }, _separator: true });
|
|
1333
1425
|
}
|
|
1334
1426
|
parts.push(node);
|
|
1335
1427
|
}
|
|
@@ -1790,9 +1882,9 @@ var StructureBuilder = class _StructureBuilder {
|
|
|
1790
1882
|
const existing = obj.fields.get(head);
|
|
1791
1883
|
const newVal = this.astToResolverValue(field.value, childPrefix);
|
|
1792
1884
|
if (existing !== void 0) {
|
|
1793
|
-
const exFolded = foldNestedSelfRefs(existing, childPrefix);
|
|
1794
1885
|
const oldPrior = obj.priorValues.get(head);
|
|
1795
|
-
const
|
|
1886
|
+
const priorInput = isResObj(existing) ? foldNestedSelfRefs(existing, childPrefix) : existing;
|
|
1887
|
+
const prior = foldOrSkipPrior(priorInput, fullKey, oldPrior);
|
|
1796
1888
|
if (prior !== void 0) obj.priorValues.set(head, prior);
|
|
1797
1889
|
}
|
|
1798
1890
|
if (existing !== void 0 && isResObj(existing) && isResObj(newVal)) {
|
|
@@ -1844,9 +1936,9 @@ var StructureBuilder = class _StructureBuilder {
|
|
|
1844
1936
|
const existing = obj.fields.get(head);
|
|
1845
1937
|
const newVal = await this.astToResolverValueAsync(field.value, childPrefix);
|
|
1846
1938
|
if (existing !== void 0) {
|
|
1847
|
-
const exFolded = foldNestedSelfRefs(existing, childPrefix);
|
|
1848
1939
|
const oldPrior = obj.priorValues.get(head);
|
|
1849
|
-
const
|
|
1940
|
+
const priorInput = isResObj(existing) ? foldNestedSelfRefs(existing, childPrefix) : existing;
|
|
1941
|
+
const prior = foldOrSkipPrior(priorInput, fullKey, oldPrior);
|
|
1850
1942
|
if (prior !== void 0) obj.priorValues.set(head, prior);
|
|
1851
1943
|
}
|
|
1852
1944
|
if (existing !== void 0 && isResObj(existing) && isResObj(newVal)) {
|
|
@@ -1869,7 +1961,7 @@ var StructureBuilder = class _StructureBuilder {
|
|
|
1869
1961
|
return inner;
|
|
1870
1962
|
}
|
|
1871
1963
|
case "subst":
|
|
1872
|
-
return { _kind: "subst-placeholder", segments: ast.segments, optional: ast.optional, listSuffix: ast.listSuffix, line: ast.pos.line, col: ast.pos.col, prefixLen: 0 };
|
|
1964
|
+
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 };
|
|
1873
1965
|
case "concat":
|
|
1874
1966
|
return { _kind: "concat-placeholder", nodes: ast.nodes.map((n) => this.astToResolverValue(n, pathPrefix)), line: ast.pos.line, col: ast.pos.col };
|
|
1875
1967
|
case "include":
|
|
@@ -1893,7 +1985,7 @@ var StructureBuilder = class _StructureBuilder {
|
|
|
1893
1985
|
case "object":
|
|
1894
1986
|
return await this.buildAsync(ast, pathPrefix);
|
|
1895
1987
|
case "subst":
|
|
1896
|
-
return { _kind: "subst-placeholder", segments: ast.segments, optional: ast.optional, listSuffix: ast.listSuffix, line: ast.pos.line, col: ast.pos.col, prefixLen: 0 };
|
|
1988
|
+
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 };
|
|
1897
1989
|
case "concat": {
|
|
1898
1990
|
const nodes = [];
|
|
1899
1991
|
for (const n of ast.nodes) {
|
|
@@ -2011,6 +2103,8 @@ var SubstitutionResolver = class {
|
|
|
2011
2103
|
const result = /* @__PURE__ */ new Map();
|
|
2012
2104
|
for (const [key, val] of obj.fields) {
|
|
2013
2105
|
this.resolvingFieldPath.push(key);
|
|
2106
|
+
const fullCacheKey = stringSegmentsToKey(this.resolvingFieldPath);
|
|
2107
|
+
this.cache.delete(fullCacheKey);
|
|
2014
2108
|
let resolved;
|
|
2015
2109
|
try {
|
|
2016
2110
|
resolved = this.resolveVal(val, obj);
|
|
@@ -2023,28 +2117,42 @@ var SubstitutionResolver = class {
|
|
|
2023
2117
|
if (prior !== void 0) {
|
|
2024
2118
|
const priorResolved = this.resolveVal(prior, obj);
|
|
2025
2119
|
if (priorResolved !== void 0 && priorResolved.kind === "object") {
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
priorResolved,
|
|
2030
|
-
resolved
|
|
2031
|
-
)
|
|
2120
|
+
const finalValue = deepMergeHoconValues(
|
|
2121
|
+
priorResolved,
|
|
2122
|
+
resolved
|
|
2032
2123
|
);
|
|
2124
|
+
result.set(key, finalValue);
|
|
2125
|
+
this.cache.set(fullCacheKey, finalValue);
|
|
2126
|
+
this.cacheDescendants(fullCacheKey, finalValue);
|
|
2033
2127
|
continue;
|
|
2034
2128
|
}
|
|
2035
2129
|
}
|
|
2036
2130
|
}
|
|
2037
2131
|
result.set(key, resolved);
|
|
2132
|
+
this.cache.set(fullCacheKey, resolved);
|
|
2133
|
+
this.cacheDescendants(fullCacheKey, resolved);
|
|
2038
2134
|
} else {
|
|
2039
2135
|
const prior = obj.priorValues.get(key);
|
|
2040
2136
|
if (prior !== void 0) {
|
|
2041
2137
|
const priorResolved = this.resolveVal(prior, obj);
|
|
2042
|
-
if (priorResolved !== void 0)
|
|
2138
|
+
if (priorResolved !== void 0) {
|
|
2139
|
+
result.set(key, priorResolved);
|
|
2140
|
+
this.cache.set(fullCacheKey, priorResolved);
|
|
2141
|
+
this.cacheDescendants(fullCacheKey, priorResolved);
|
|
2142
|
+
}
|
|
2043
2143
|
}
|
|
2044
2144
|
}
|
|
2045
2145
|
}
|
|
2046
2146
|
return { kind: "object", fields: result };
|
|
2047
2147
|
}
|
|
2148
|
+
cacheDescendants(prefix, value) {
|
|
2149
|
+
if (value.kind !== "object") return;
|
|
2150
|
+
for (const [key, child] of value.fields) {
|
|
2151
|
+
const childKey = `${prefix}.${stringSegmentsToKey([key])}`;
|
|
2152
|
+
this.cache.set(childKey, child);
|
|
2153
|
+
this.cacheDescendants(childKey, child);
|
|
2154
|
+
}
|
|
2155
|
+
}
|
|
2048
2156
|
resolveVal(v, scope) {
|
|
2049
2157
|
if (isSubst(v)) return this.resolveSubst(v, scope);
|
|
2050
2158
|
if (isConcat(v)) {
|
|
@@ -2070,6 +2178,7 @@ var SubstitutionResolver = class {
|
|
|
2070
2178
|
return hv;
|
|
2071
2179
|
}
|
|
2072
2180
|
resolveSubst(s, scope) {
|
|
2181
|
+
if (s.knownAbsent) return void 0;
|
|
2073
2182
|
const key = s.listSuffix ? `${segmentsToKey(s.segments)}[]` : segmentsToKey(s.segments);
|
|
2074
2183
|
if (this.cache.has(key)) return this.cache.get(key);
|
|
2075
2184
|
if (this.resolving.has(key)) {
|
|
@@ -2162,6 +2271,28 @@ var SubstitutionResolver = class {
|
|
|
2162
2271
|
if (result !== void 0) this.cache.set(key, result);
|
|
2163
2272
|
return result;
|
|
2164
2273
|
}
|
|
2274
|
+
if (s.prefixLen > 0 && s.segments.length > s.prefixLen) {
|
|
2275
|
+
const originalSegments = s.segments.slice(s.prefixLen);
|
|
2276
|
+
const fallbackFound = lookupPath(this.root, originalSegments);
|
|
2277
|
+
if (fallbackFound !== void 0) {
|
|
2278
|
+
let result = this.resolveVal(fallbackFound, scope);
|
|
2279
|
+
if (originalSegments.length === 1 && result !== void 0 && result.kind === "object") {
|
|
2280
|
+
const rootSeg = originalSegments[0]?.text ?? "";
|
|
2281
|
+
const prior = this.root.priorValues.get(rootSeg);
|
|
2282
|
+
if (prior !== void 0) {
|
|
2283
|
+
const priorResolved = this.resolveVal(prior, scope);
|
|
2284
|
+
if (priorResolved !== void 0 && priorResolved.kind === "object") {
|
|
2285
|
+
result = deepMergeHoconValues(
|
|
2286
|
+
priorResolved,
|
|
2287
|
+
result
|
|
2288
|
+
);
|
|
2289
|
+
}
|
|
2290
|
+
}
|
|
2291
|
+
}
|
|
2292
|
+
if (result !== void 0) this.cache.set(key, result);
|
|
2293
|
+
return result;
|
|
2294
|
+
}
|
|
2295
|
+
}
|
|
2165
2296
|
if (s.listSuffix && this.opts.useSystemEnvironment !== false) {
|
|
2166
2297
|
const result = this.resolveEnvList(s);
|
|
2167
2298
|
if (result !== void 0) {
|