@optique/core 1.0.0-dev.1608 → 1.0.0-dev.1611
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/constructs.cjs +91 -14
- package/dist/constructs.js +91 -14
- package/dist/parser.d.cts +19 -0
- package/dist/parser.d.ts +19 -0
- package/package.json +1 -1
package/dist/constructs.cjs
CHANGED
|
@@ -879,6 +879,31 @@ async function completeDependencySourceDefaultsAsync(context, parserPairs, regis
|
|
|
879
879
|
* mappings from its child `object()` (or nested `merge()`) parsers.
|
|
880
880
|
* @internal
|
|
881
881
|
*/
|
|
882
|
+
/**
|
|
883
|
+
* Removes entries for duplicate field names from a pre-completed results
|
|
884
|
+
* map. When a child construct's field-parser pairs contain the same field
|
|
885
|
+
* name more than once (e.g., inner merges with overlapping output keys),
|
|
886
|
+
* the flat map collapses branch-specific results. This function strips
|
|
887
|
+
* only the ambiguous entries, preserving cached results for unique fields.
|
|
888
|
+
*
|
|
889
|
+
* Returns `undefined` if the filtered map is empty (no cacheable fields).
|
|
890
|
+
*
|
|
891
|
+
* @see https://github.com/dahlia/optique/issues/762
|
|
892
|
+
* @internal
|
|
893
|
+
*/
|
|
894
|
+
function filterDuplicateKeys(preCompleted, pairs) {
|
|
895
|
+
const counts = /* @__PURE__ */ new Map();
|
|
896
|
+
for (const [field] of pairs) counts.set(field, (counts.get(field) ?? 0) + 1);
|
|
897
|
+
let hasDuplicates = false;
|
|
898
|
+
for (const count of counts.values()) if (count > 1) {
|
|
899
|
+
hasDuplicates = true;
|
|
900
|
+
break;
|
|
901
|
+
}
|
|
902
|
+
if (!hasDuplicates) return preCompleted;
|
|
903
|
+
const filtered = /* @__PURE__ */ new Map();
|
|
904
|
+
for (const [field, value] of preCompleted) if ((counts.get(field) ?? 0) <= 1) filtered.set(field, value);
|
|
905
|
+
return filtered.size > 0 ? filtered : void 0;
|
|
906
|
+
}
|
|
882
907
|
function collectChildFieldParsers(parsers) {
|
|
883
908
|
const pairs = [];
|
|
884
909
|
for (const parser of parsers) if (fieldParsersKey in parser) pairs.push(...parser[fieldParsersKey]);
|
|
@@ -901,7 +926,14 @@ function collectChildFieldParsers(parsers) {
|
|
|
901
926
|
*/
|
|
902
927
|
function preCompleteAndRegisterDependencies(state, fieldParserPairs, registry, exec) {
|
|
903
928
|
const preCompleted = /* @__PURE__ */ new Map();
|
|
929
|
+
const parentResults = exec?.preCompletedByParser;
|
|
904
930
|
for (const [field, fieldParser] of fieldParserPairs) {
|
|
931
|
+
const cached = parentResults?.get(field);
|
|
932
|
+
if (cached !== void 0) {
|
|
933
|
+
preCompleted.set(field, cached);
|
|
934
|
+
registerCompletedDependency(cached, registry);
|
|
935
|
+
continue;
|
|
936
|
+
}
|
|
905
937
|
const fieldState = state[field];
|
|
906
938
|
if (Array.isArray(fieldState) && fieldState.length === 1 && require_dependency.isPendingDependencySourceState(fieldState[0])) {
|
|
907
939
|
const completed = fieldParser.complete(fieldState, exec);
|
|
@@ -932,7 +964,14 @@ function preCompleteAndRegisterDependencies(state, fieldParserPairs, registry, e
|
|
|
932
964
|
*/
|
|
933
965
|
async function preCompleteAndRegisterDependenciesAsync(state, fieldParserPairs, registry, exec) {
|
|
934
966
|
const preCompleted = /* @__PURE__ */ new Map();
|
|
967
|
+
const parentResults = exec?.preCompletedByParser;
|
|
935
968
|
for (const [field, fieldParser] of fieldParserPairs) {
|
|
969
|
+
const cached = parentResults?.get(field);
|
|
970
|
+
if (cached !== void 0) {
|
|
971
|
+
preCompleted.set(field, cached);
|
|
972
|
+
registerCompletedDependency(cached, registry);
|
|
973
|
+
continue;
|
|
974
|
+
}
|
|
936
975
|
const fieldState = state[field];
|
|
937
976
|
if (Array.isArray(fieldState) && fieldState.length === 1 && require_dependency.isPendingDependencySourceState(fieldState[0])) {
|
|
938
977
|
const completed = await fieldParser.complete(fieldState, exec);
|
|
@@ -1304,7 +1343,12 @@ function object(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
|
|
|
1304
1343
|
...exec,
|
|
1305
1344
|
dependencyRuntime: runtime
|
|
1306
1345
|
};
|
|
1307
|
-
const
|
|
1346
|
+
const typedParserPairs = parserPairs;
|
|
1347
|
+
const preCompleted = preCompleteAndRegisterDependencies(state, typedParserPairs, runtime.registry, childExec);
|
|
1348
|
+
const phase3Exec = {
|
|
1349
|
+
...childExec,
|
|
1350
|
+
preCompletedByParser: void 0
|
|
1351
|
+
};
|
|
1308
1352
|
const getFieldState = createFieldStateGetter(state);
|
|
1309
1353
|
const annotatedState = {};
|
|
1310
1354
|
for (const field of parserKeys) {
|
|
@@ -1324,7 +1368,7 @@ function object(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
|
|
|
1324
1368
|
if (preCompletedResult !== void 0) valueResult = unwrapCompleteResult(preCompletedResult);
|
|
1325
1369
|
else {
|
|
1326
1370
|
const fieldState = resolvedFieldStates[fieldKey];
|
|
1327
|
-
valueResult = unwrapCompleteResult(fieldParser.complete(fieldState,
|
|
1371
|
+
valueResult = unwrapCompleteResult(fieldParser.complete(fieldState, phase3Exec));
|
|
1328
1372
|
}
|
|
1329
1373
|
if (valueResult.success) {
|
|
1330
1374
|
result[fieldKey] = valueResult.value;
|
|
@@ -1351,7 +1395,12 @@ function object(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
|
|
|
1351
1395
|
...exec,
|
|
1352
1396
|
dependencyRuntime: runtime
|
|
1353
1397
|
};
|
|
1354
|
-
const
|
|
1398
|
+
const asyncParserPairs = parserPairs;
|
|
1399
|
+
const preCompleted = await preCompleteAndRegisterDependenciesAsync(state, asyncParserPairs, runtime.registry, childExec);
|
|
1400
|
+
const phase3Exec = {
|
|
1401
|
+
...childExec,
|
|
1402
|
+
preCompletedByParser: void 0
|
|
1403
|
+
};
|
|
1355
1404
|
const getFieldState = createFieldStateGetter(state);
|
|
1356
1405
|
const annotatedState = {};
|
|
1357
1406
|
for (const field of parserKeys) {
|
|
@@ -1371,7 +1420,7 @@ function object(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
|
|
|
1371
1420
|
if (preCompletedResult !== void 0) valueResult = unwrapCompleteResult(preCompletedResult);
|
|
1372
1421
|
else {
|
|
1373
1422
|
const fieldState = resolvedFieldStates[fieldKey];
|
|
1374
|
-
valueResult = unwrapCompleteResult(await fieldParser.complete(fieldState,
|
|
1423
|
+
valueResult = unwrapCompleteResult(await fieldParser.complete(fieldState, phase3Exec));
|
|
1375
1424
|
}
|
|
1376
1425
|
if (valueResult.success) {
|
|
1377
1426
|
result[fieldKey] = valueResult.value;
|
|
@@ -1644,6 +1693,10 @@ function tuple(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
|
|
|
1644
1693
|
const tuplePairs = syncParsers.map((p, i) => [String(i), p]);
|
|
1645
1694
|
const tupleState = Object.fromEntries(stateArray.map((s, i) => [String(i), s]));
|
|
1646
1695
|
const preCompleted = preCompleteAndRegisterDependencies(tupleState, tuplePairs, runtime.registry, childExec);
|
|
1696
|
+
const phase3Exec = {
|
|
1697
|
+
...childExec,
|
|
1698
|
+
preCompletedByParser: void 0
|
|
1699
|
+
};
|
|
1647
1700
|
const resolvedArray = require_dependency_runtime.resolveStateWithRuntime(stateArray, runtime);
|
|
1648
1701
|
const result = [];
|
|
1649
1702
|
const deferredKeys = /* @__PURE__ */ new Map();
|
|
@@ -1655,7 +1708,7 @@ function tuple(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
|
|
|
1655
1708
|
if (preCompletedResult !== void 0) valueResult = unwrapCompleteResult(preCompletedResult);
|
|
1656
1709
|
else {
|
|
1657
1710
|
const elementState = prepareStateForCompletion(resolvedArray[i], elementParser);
|
|
1658
|
-
valueResult = unwrapCompleteResult(elementParser.complete(elementState,
|
|
1711
|
+
valueResult = unwrapCompleteResult(elementParser.complete(elementState, phase3Exec));
|
|
1659
1712
|
}
|
|
1660
1713
|
if (valueResult.success) {
|
|
1661
1714
|
result[i] = valueResult.value;
|
|
@@ -1686,6 +1739,10 @@ function tuple(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
|
|
|
1686
1739
|
const tuplePairs = parsers.map((p, i) => [String(i), p]);
|
|
1687
1740
|
const tupleState = Object.fromEntries(stateArray.map((s, i) => [String(i), s]));
|
|
1688
1741
|
const preCompleted = await preCompleteAndRegisterDependenciesAsync(tupleState, tuplePairs, runtime.registry, childExec);
|
|
1742
|
+
const phase3Exec = {
|
|
1743
|
+
...childExec,
|
|
1744
|
+
preCompletedByParser: void 0
|
|
1745
|
+
};
|
|
1689
1746
|
const resolvedArray = await require_dependency_runtime.resolveStateWithRuntimeAsync(stateArray, runtime);
|
|
1690
1747
|
const result = [];
|
|
1691
1748
|
const deferredKeys = /* @__PURE__ */ new Map();
|
|
@@ -1697,7 +1754,7 @@ function tuple(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
|
|
|
1697
1754
|
if (preCompletedResult !== void 0) valueResult = unwrapCompleteResult(preCompletedResult);
|
|
1698
1755
|
else {
|
|
1699
1756
|
const elementState = prepareStateForCompletion(resolvedArray[i], elementParser);
|
|
1700
|
-
valueResult = unwrapCompleteResult(await elementParser.complete(elementState,
|
|
1757
|
+
valueResult = unwrapCompleteResult(await elementParser.complete(elementState, phase3Exec));
|
|
1701
1758
|
}
|
|
1702
1759
|
if (valueResult.success) {
|
|
1703
1760
|
result[i] = valueResult.value;
|
|
@@ -1963,8 +2020,14 @@ function merge(...args) {
|
|
|
1963
2020
|
...exec,
|
|
1964
2021
|
dependencyRuntime: runtime
|
|
1965
2022
|
};
|
|
1966
|
-
const
|
|
1967
|
-
|
|
2023
|
+
const perChildCache = syncParsers.map((parser) => {
|
|
2024
|
+
if (fieldParsersKey in parser) {
|
|
2025
|
+
const pairs = parser[fieldParsersKey];
|
|
2026
|
+
const preCompleted = preCompleteAndRegisterDependencies(state, pairs, runtime.registry, childExec);
|
|
2027
|
+
return filterDuplicateKeys(preCompleted, pairs);
|
|
2028
|
+
}
|
|
2029
|
+
return void 0;
|
|
2030
|
+
});
|
|
1968
2031
|
const resolvedState = require_dependency_runtime.resolveStateWithRuntime(state, runtime);
|
|
1969
2032
|
const object$1 = {};
|
|
1970
2033
|
const deferredKeys = /* @__PURE__ */ new Map();
|
|
@@ -1972,7 +2035,11 @@ function merge(...args) {
|
|
|
1972
2035
|
for (let i = 0; i < syncParsers.length; i++) {
|
|
1973
2036
|
const parser = syncParsers[i];
|
|
1974
2037
|
const parserState = extractCompleteState(parser, resolvedState, i);
|
|
1975
|
-
const
|
|
2038
|
+
const cache = perChildCache[i];
|
|
2039
|
+
const result = unwrapCompleteResult(parser.complete(parserState, {
|
|
2040
|
+
...childExec,
|
|
2041
|
+
preCompletedByParser: cache
|
|
2042
|
+
}));
|
|
1976
2043
|
if (!result.success) return result;
|
|
1977
2044
|
const resultValue = result.value;
|
|
1978
2045
|
for (const field in resultValue) {
|
|
@@ -1998,8 +2065,12 @@ function merge(...args) {
|
|
|
1998
2065
|
...exec,
|
|
1999
2066
|
dependencyRuntime: runtime
|
|
2000
2067
|
};
|
|
2001
|
-
const
|
|
2002
|
-
|
|
2068
|
+
const perChildCache = [];
|
|
2069
|
+
for (const parser of parsers) if (fieldParsersKey in parser) {
|
|
2070
|
+
const pairs = parser[fieldParsersKey];
|
|
2071
|
+
const preCompleted = await preCompleteAndRegisterDependenciesAsync(state, pairs, runtime.registry, childExec);
|
|
2072
|
+
perChildCache.push(filterDuplicateKeys(preCompleted, pairs));
|
|
2073
|
+
} else perChildCache.push(void 0);
|
|
2003
2074
|
const resolvedState = await require_dependency_runtime.resolveStateWithRuntimeAsync(state, runtime);
|
|
2004
2075
|
const object$1 = {};
|
|
2005
2076
|
const deferredKeys = /* @__PURE__ */ new Map();
|
|
@@ -2007,7 +2078,11 @@ function merge(...args) {
|
|
|
2007
2078
|
for (let i = 0; i < parsers.length; i++) {
|
|
2008
2079
|
const parser = parsers[i];
|
|
2009
2080
|
const parserState = extractCompleteState(parser, resolvedState, i);
|
|
2010
|
-
const
|
|
2081
|
+
const asyncCache = perChildCache[i];
|
|
2082
|
+
const result = unwrapCompleteResult(await parser.complete(parserState, {
|
|
2083
|
+
...childExec,
|
|
2084
|
+
preCompletedByParser: asyncCache
|
|
2085
|
+
}));
|
|
2011
2086
|
if (!result.success) return result;
|
|
2012
2087
|
const resultValue = result.value;
|
|
2013
2088
|
for (const field in resultValue) {
|
|
@@ -2400,7 +2475,8 @@ function concat(...parsers) {
|
|
|
2400
2475
|
const runtime = exec?.dependencyRuntime ?? require_dependency_runtime.createDependencyRuntimeContext(exec?.dependencyRegistry);
|
|
2401
2476
|
const childExec = {
|
|
2402
2477
|
...exec,
|
|
2403
|
-
dependencyRuntime: runtime
|
|
2478
|
+
dependencyRuntime: runtime,
|
|
2479
|
+
preCompletedByParser: void 0
|
|
2404
2480
|
};
|
|
2405
2481
|
const resolvedArray = require_dependency_runtime.resolveStateWithRuntime(stateArray, runtime);
|
|
2406
2482
|
const results = [];
|
|
@@ -2442,7 +2518,8 @@ function concat(...parsers) {
|
|
|
2442
2518
|
const runtime = exec?.dependencyRuntime ?? require_dependency_runtime.createDependencyRuntimeContext(exec?.dependencyRegistry);
|
|
2443
2519
|
const childExec = {
|
|
2444
2520
|
...exec,
|
|
2445
|
-
dependencyRuntime: runtime
|
|
2521
|
+
dependencyRuntime: runtime,
|
|
2522
|
+
preCompletedByParser: void 0
|
|
2446
2523
|
};
|
|
2447
2524
|
const resolvedArray = await require_dependency_runtime.resolveStateWithRuntimeAsync(stateArray, runtime);
|
|
2448
2525
|
const results = [];
|
package/dist/constructs.js
CHANGED
|
@@ -879,6 +879,31 @@ async function completeDependencySourceDefaultsAsync(context, parserPairs, regis
|
|
|
879
879
|
* mappings from its child `object()` (or nested `merge()`) parsers.
|
|
880
880
|
* @internal
|
|
881
881
|
*/
|
|
882
|
+
/**
|
|
883
|
+
* Removes entries for duplicate field names from a pre-completed results
|
|
884
|
+
* map. When a child construct's field-parser pairs contain the same field
|
|
885
|
+
* name more than once (e.g., inner merges with overlapping output keys),
|
|
886
|
+
* the flat map collapses branch-specific results. This function strips
|
|
887
|
+
* only the ambiguous entries, preserving cached results for unique fields.
|
|
888
|
+
*
|
|
889
|
+
* Returns `undefined` if the filtered map is empty (no cacheable fields).
|
|
890
|
+
*
|
|
891
|
+
* @see https://github.com/dahlia/optique/issues/762
|
|
892
|
+
* @internal
|
|
893
|
+
*/
|
|
894
|
+
function filterDuplicateKeys(preCompleted, pairs) {
|
|
895
|
+
const counts = /* @__PURE__ */ new Map();
|
|
896
|
+
for (const [field] of pairs) counts.set(field, (counts.get(field) ?? 0) + 1);
|
|
897
|
+
let hasDuplicates = false;
|
|
898
|
+
for (const count of counts.values()) if (count > 1) {
|
|
899
|
+
hasDuplicates = true;
|
|
900
|
+
break;
|
|
901
|
+
}
|
|
902
|
+
if (!hasDuplicates) return preCompleted;
|
|
903
|
+
const filtered = /* @__PURE__ */ new Map();
|
|
904
|
+
for (const [field, value] of preCompleted) if ((counts.get(field) ?? 0) <= 1) filtered.set(field, value);
|
|
905
|
+
return filtered.size > 0 ? filtered : void 0;
|
|
906
|
+
}
|
|
882
907
|
function collectChildFieldParsers(parsers) {
|
|
883
908
|
const pairs = [];
|
|
884
909
|
for (const parser of parsers) if (fieldParsersKey in parser) pairs.push(...parser[fieldParsersKey]);
|
|
@@ -901,7 +926,14 @@ function collectChildFieldParsers(parsers) {
|
|
|
901
926
|
*/
|
|
902
927
|
function preCompleteAndRegisterDependencies(state, fieldParserPairs, registry, exec) {
|
|
903
928
|
const preCompleted = /* @__PURE__ */ new Map();
|
|
929
|
+
const parentResults = exec?.preCompletedByParser;
|
|
904
930
|
for (const [field, fieldParser] of fieldParserPairs) {
|
|
931
|
+
const cached = parentResults?.get(field);
|
|
932
|
+
if (cached !== void 0) {
|
|
933
|
+
preCompleted.set(field, cached);
|
|
934
|
+
registerCompletedDependency(cached, registry);
|
|
935
|
+
continue;
|
|
936
|
+
}
|
|
905
937
|
const fieldState = state[field];
|
|
906
938
|
if (Array.isArray(fieldState) && fieldState.length === 1 && isPendingDependencySourceState(fieldState[0])) {
|
|
907
939
|
const completed = fieldParser.complete(fieldState, exec);
|
|
@@ -932,7 +964,14 @@ function preCompleteAndRegisterDependencies(state, fieldParserPairs, registry, e
|
|
|
932
964
|
*/
|
|
933
965
|
async function preCompleteAndRegisterDependenciesAsync(state, fieldParserPairs, registry, exec) {
|
|
934
966
|
const preCompleted = /* @__PURE__ */ new Map();
|
|
967
|
+
const parentResults = exec?.preCompletedByParser;
|
|
935
968
|
for (const [field, fieldParser] of fieldParserPairs) {
|
|
969
|
+
const cached = parentResults?.get(field);
|
|
970
|
+
if (cached !== void 0) {
|
|
971
|
+
preCompleted.set(field, cached);
|
|
972
|
+
registerCompletedDependency(cached, registry);
|
|
973
|
+
continue;
|
|
974
|
+
}
|
|
936
975
|
const fieldState = state[field];
|
|
937
976
|
if (Array.isArray(fieldState) && fieldState.length === 1 && isPendingDependencySourceState(fieldState[0])) {
|
|
938
977
|
const completed = await fieldParser.complete(fieldState, exec);
|
|
@@ -1304,7 +1343,12 @@ function object(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
|
|
|
1304
1343
|
...exec,
|
|
1305
1344
|
dependencyRuntime: runtime
|
|
1306
1345
|
};
|
|
1307
|
-
const
|
|
1346
|
+
const typedParserPairs = parserPairs;
|
|
1347
|
+
const preCompleted = preCompleteAndRegisterDependencies(state, typedParserPairs, runtime.registry, childExec);
|
|
1348
|
+
const phase3Exec = {
|
|
1349
|
+
...childExec,
|
|
1350
|
+
preCompletedByParser: void 0
|
|
1351
|
+
};
|
|
1308
1352
|
const getFieldState = createFieldStateGetter(state);
|
|
1309
1353
|
const annotatedState = {};
|
|
1310
1354
|
for (const field of parserKeys) {
|
|
@@ -1324,7 +1368,7 @@ function object(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
|
|
|
1324
1368
|
if (preCompletedResult !== void 0) valueResult = unwrapCompleteResult(preCompletedResult);
|
|
1325
1369
|
else {
|
|
1326
1370
|
const fieldState = resolvedFieldStates[fieldKey];
|
|
1327
|
-
valueResult = unwrapCompleteResult(fieldParser.complete(fieldState,
|
|
1371
|
+
valueResult = unwrapCompleteResult(fieldParser.complete(fieldState, phase3Exec));
|
|
1328
1372
|
}
|
|
1329
1373
|
if (valueResult.success) {
|
|
1330
1374
|
result[fieldKey] = valueResult.value;
|
|
@@ -1351,7 +1395,12 @@ function object(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
|
|
|
1351
1395
|
...exec,
|
|
1352
1396
|
dependencyRuntime: runtime
|
|
1353
1397
|
};
|
|
1354
|
-
const
|
|
1398
|
+
const asyncParserPairs = parserPairs;
|
|
1399
|
+
const preCompleted = await preCompleteAndRegisterDependenciesAsync(state, asyncParserPairs, runtime.registry, childExec);
|
|
1400
|
+
const phase3Exec = {
|
|
1401
|
+
...childExec,
|
|
1402
|
+
preCompletedByParser: void 0
|
|
1403
|
+
};
|
|
1355
1404
|
const getFieldState = createFieldStateGetter(state);
|
|
1356
1405
|
const annotatedState = {};
|
|
1357
1406
|
for (const field of parserKeys) {
|
|
@@ -1371,7 +1420,7 @@ function object(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
|
|
|
1371
1420
|
if (preCompletedResult !== void 0) valueResult = unwrapCompleteResult(preCompletedResult);
|
|
1372
1421
|
else {
|
|
1373
1422
|
const fieldState = resolvedFieldStates[fieldKey];
|
|
1374
|
-
valueResult = unwrapCompleteResult(await fieldParser.complete(fieldState,
|
|
1423
|
+
valueResult = unwrapCompleteResult(await fieldParser.complete(fieldState, phase3Exec));
|
|
1375
1424
|
}
|
|
1376
1425
|
if (valueResult.success) {
|
|
1377
1426
|
result[fieldKey] = valueResult.value;
|
|
@@ -1644,6 +1693,10 @@ function tuple(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
|
|
|
1644
1693
|
const tuplePairs = syncParsers.map((p, i) => [String(i), p]);
|
|
1645
1694
|
const tupleState = Object.fromEntries(stateArray.map((s, i) => [String(i), s]));
|
|
1646
1695
|
const preCompleted = preCompleteAndRegisterDependencies(tupleState, tuplePairs, runtime.registry, childExec);
|
|
1696
|
+
const phase3Exec = {
|
|
1697
|
+
...childExec,
|
|
1698
|
+
preCompletedByParser: void 0
|
|
1699
|
+
};
|
|
1647
1700
|
const resolvedArray = resolveStateWithRuntime(stateArray, runtime);
|
|
1648
1701
|
const result = [];
|
|
1649
1702
|
const deferredKeys = /* @__PURE__ */ new Map();
|
|
@@ -1655,7 +1708,7 @@ function tuple(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
|
|
|
1655
1708
|
if (preCompletedResult !== void 0) valueResult = unwrapCompleteResult(preCompletedResult);
|
|
1656
1709
|
else {
|
|
1657
1710
|
const elementState = prepareStateForCompletion(resolvedArray[i], elementParser);
|
|
1658
|
-
valueResult = unwrapCompleteResult(elementParser.complete(elementState,
|
|
1711
|
+
valueResult = unwrapCompleteResult(elementParser.complete(elementState, phase3Exec));
|
|
1659
1712
|
}
|
|
1660
1713
|
if (valueResult.success) {
|
|
1661
1714
|
result[i] = valueResult.value;
|
|
@@ -1686,6 +1739,10 @@ function tuple(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
|
|
|
1686
1739
|
const tuplePairs = parsers.map((p, i) => [String(i), p]);
|
|
1687
1740
|
const tupleState = Object.fromEntries(stateArray.map((s, i) => [String(i), s]));
|
|
1688
1741
|
const preCompleted = await preCompleteAndRegisterDependenciesAsync(tupleState, tuplePairs, runtime.registry, childExec);
|
|
1742
|
+
const phase3Exec = {
|
|
1743
|
+
...childExec,
|
|
1744
|
+
preCompletedByParser: void 0
|
|
1745
|
+
};
|
|
1689
1746
|
const resolvedArray = await resolveStateWithRuntimeAsync(stateArray, runtime);
|
|
1690
1747
|
const result = [];
|
|
1691
1748
|
const deferredKeys = /* @__PURE__ */ new Map();
|
|
@@ -1697,7 +1754,7 @@ function tuple(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
|
|
|
1697
1754
|
if (preCompletedResult !== void 0) valueResult = unwrapCompleteResult(preCompletedResult);
|
|
1698
1755
|
else {
|
|
1699
1756
|
const elementState = prepareStateForCompletion(resolvedArray[i], elementParser);
|
|
1700
|
-
valueResult = unwrapCompleteResult(await elementParser.complete(elementState,
|
|
1757
|
+
valueResult = unwrapCompleteResult(await elementParser.complete(elementState, phase3Exec));
|
|
1701
1758
|
}
|
|
1702
1759
|
if (valueResult.success) {
|
|
1703
1760
|
result[i] = valueResult.value;
|
|
@@ -1963,8 +2020,14 @@ function merge(...args) {
|
|
|
1963
2020
|
...exec,
|
|
1964
2021
|
dependencyRuntime: runtime
|
|
1965
2022
|
};
|
|
1966
|
-
const
|
|
1967
|
-
|
|
2023
|
+
const perChildCache = syncParsers.map((parser) => {
|
|
2024
|
+
if (fieldParsersKey in parser) {
|
|
2025
|
+
const pairs = parser[fieldParsersKey];
|
|
2026
|
+
const preCompleted = preCompleteAndRegisterDependencies(state, pairs, runtime.registry, childExec);
|
|
2027
|
+
return filterDuplicateKeys(preCompleted, pairs);
|
|
2028
|
+
}
|
|
2029
|
+
return void 0;
|
|
2030
|
+
});
|
|
1968
2031
|
const resolvedState = resolveStateWithRuntime(state, runtime);
|
|
1969
2032
|
const object$1 = {};
|
|
1970
2033
|
const deferredKeys = /* @__PURE__ */ new Map();
|
|
@@ -1972,7 +2035,11 @@ function merge(...args) {
|
|
|
1972
2035
|
for (let i = 0; i < syncParsers.length; i++) {
|
|
1973
2036
|
const parser = syncParsers[i];
|
|
1974
2037
|
const parserState = extractCompleteState(parser, resolvedState, i);
|
|
1975
|
-
const
|
|
2038
|
+
const cache = perChildCache[i];
|
|
2039
|
+
const result = unwrapCompleteResult(parser.complete(parserState, {
|
|
2040
|
+
...childExec,
|
|
2041
|
+
preCompletedByParser: cache
|
|
2042
|
+
}));
|
|
1976
2043
|
if (!result.success) return result;
|
|
1977
2044
|
const resultValue = result.value;
|
|
1978
2045
|
for (const field in resultValue) {
|
|
@@ -1998,8 +2065,12 @@ function merge(...args) {
|
|
|
1998
2065
|
...exec,
|
|
1999
2066
|
dependencyRuntime: runtime
|
|
2000
2067
|
};
|
|
2001
|
-
const
|
|
2002
|
-
|
|
2068
|
+
const perChildCache = [];
|
|
2069
|
+
for (const parser of parsers) if (fieldParsersKey in parser) {
|
|
2070
|
+
const pairs = parser[fieldParsersKey];
|
|
2071
|
+
const preCompleted = await preCompleteAndRegisterDependenciesAsync(state, pairs, runtime.registry, childExec);
|
|
2072
|
+
perChildCache.push(filterDuplicateKeys(preCompleted, pairs));
|
|
2073
|
+
} else perChildCache.push(void 0);
|
|
2003
2074
|
const resolvedState = await resolveStateWithRuntimeAsync(state, runtime);
|
|
2004
2075
|
const object$1 = {};
|
|
2005
2076
|
const deferredKeys = /* @__PURE__ */ new Map();
|
|
@@ -2007,7 +2078,11 @@ function merge(...args) {
|
|
|
2007
2078
|
for (let i = 0; i < parsers.length; i++) {
|
|
2008
2079
|
const parser = parsers[i];
|
|
2009
2080
|
const parserState = extractCompleteState(parser, resolvedState, i);
|
|
2010
|
-
const
|
|
2081
|
+
const asyncCache = perChildCache[i];
|
|
2082
|
+
const result = unwrapCompleteResult(await parser.complete(parserState, {
|
|
2083
|
+
...childExec,
|
|
2084
|
+
preCompletedByParser: asyncCache
|
|
2085
|
+
}));
|
|
2011
2086
|
if (!result.success) return result;
|
|
2012
2087
|
const resultValue = result.value;
|
|
2013
2088
|
for (const field in resultValue) {
|
|
@@ -2400,7 +2475,8 @@ function concat(...parsers) {
|
|
|
2400
2475
|
const runtime = exec?.dependencyRuntime ?? createDependencyRuntimeContext(exec?.dependencyRegistry);
|
|
2401
2476
|
const childExec = {
|
|
2402
2477
|
...exec,
|
|
2403
|
-
dependencyRuntime: runtime
|
|
2478
|
+
dependencyRuntime: runtime,
|
|
2479
|
+
preCompletedByParser: void 0
|
|
2404
2480
|
};
|
|
2405
2481
|
const resolvedArray = resolveStateWithRuntime(stateArray, runtime);
|
|
2406
2482
|
const results = [];
|
|
@@ -2442,7 +2518,8 @@ function concat(...parsers) {
|
|
|
2442
2518
|
const runtime = exec?.dependencyRuntime ?? createDependencyRuntimeContext(exec?.dependencyRegistry);
|
|
2443
2519
|
const childExec = {
|
|
2444
2520
|
...exec,
|
|
2445
|
-
dependencyRuntime: runtime
|
|
2521
|
+
dependencyRuntime: runtime,
|
|
2522
|
+
preCompletedByParser: void 0
|
|
2446
2523
|
};
|
|
2447
2524
|
const resolvedArray = await resolveStateWithRuntimeAsync(stateArray, runtime);
|
|
2448
2525
|
const results = [];
|
package/dist/parser.d.cts
CHANGED
|
@@ -325,6 +325,25 @@ interface ExecutionContext {
|
|
|
325
325
|
* @since 1.0.0
|
|
326
326
|
*/
|
|
327
327
|
readonly dependencyRuntime?: DependencyRuntimeContext;
|
|
328
|
+
/**
|
|
329
|
+
* Immutable map of pre-completed results from the parent construct's
|
|
330
|
+
* Phase 1, keyed by field name. Each construct passes its own
|
|
331
|
+
* `preCompleteAndRegisterDependencies` results directly to children
|
|
332
|
+
* in Phase 3. Children read it in their own Phase 1 to avoid
|
|
333
|
+
* re-evaluating non-idempotent default thunks, but never write to
|
|
334
|
+
* it — this prevents sibling completions from leaking into each
|
|
335
|
+
* other.
|
|
336
|
+
*
|
|
337
|
+
* Field-name keying naturally handles parser reuse across different
|
|
338
|
+
* fields (e.g., `merge(object({a: shared}), object({b: shared}))`)
|
|
339
|
+
* because each field maps to its own result regardless of whether
|
|
340
|
+
* the underlying parser instance is the same.
|
|
341
|
+
*
|
|
342
|
+
* @see https://github.com/dahlia/optique/issues/762
|
|
343
|
+
* @internal
|
|
344
|
+
* @since 1.0.0
|
|
345
|
+
*/
|
|
346
|
+
readonly preCompletedByParser?: ReadonlyMap<string | symbol, unknown>;
|
|
328
347
|
}
|
|
329
348
|
/**
|
|
330
349
|
* The context of the parser, which includes the input buffer and the state.
|
package/dist/parser.d.ts
CHANGED
|
@@ -325,6 +325,25 @@ interface ExecutionContext {
|
|
|
325
325
|
* @since 1.0.0
|
|
326
326
|
*/
|
|
327
327
|
readonly dependencyRuntime?: DependencyRuntimeContext;
|
|
328
|
+
/**
|
|
329
|
+
* Immutable map of pre-completed results from the parent construct's
|
|
330
|
+
* Phase 1, keyed by field name. Each construct passes its own
|
|
331
|
+
* `preCompleteAndRegisterDependencies` results directly to children
|
|
332
|
+
* in Phase 3. Children read it in their own Phase 1 to avoid
|
|
333
|
+
* re-evaluating non-idempotent default thunks, but never write to
|
|
334
|
+
* it — this prevents sibling completions from leaking into each
|
|
335
|
+
* other.
|
|
336
|
+
*
|
|
337
|
+
* Field-name keying naturally handles parser reuse across different
|
|
338
|
+
* fields (e.g., `merge(object({a: shared}), object({b: shared}))`)
|
|
339
|
+
* because each field maps to its own result regardless of whether
|
|
340
|
+
* the underlying parser instance is the same.
|
|
341
|
+
*
|
|
342
|
+
* @see https://github.com/dahlia/optique/issues/762
|
|
343
|
+
* @internal
|
|
344
|
+
* @since 1.0.0
|
|
345
|
+
*/
|
|
346
|
+
readonly preCompletedByParser?: ReadonlyMap<string | symbol, unknown>;
|
|
328
347
|
}
|
|
329
348
|
/**
|
|
330
349
|
* The context of the parser, which includes the input buffer and the state.
|