@optique/core 1.1.0-dev.2096 → 1.1.0-dev.2148
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/annotation-state.cjs +26 -26
- package/dist/annotation-state.d.cts +133 -1
- package/dist/annotation-state.d.ts +133 -1
- package/dist/annotations.cjs +2 -2
- package/dist/constructs.cjs +141 -73
- package/dist/constructs.js +70 -2
- package/dist/dependency-metadata.cjs +12 -12
- package/dist/dependency-metadata.d.cts +34 -3
- package/dist/dependency-metadata.d.ts +34 -3
- package/dist/dependency-runtime.cjs +37 -13
- package/dist/dependency-runtime.d.cts +197 -2
- package/dist/dependency-runtime.d.ts +197 -2
- package/dist/dependency-runtime.js +22 -1
- package/dist/dependency.cjs +7 -7
- package/dist/displaywidth.d.cts +12 -0
- package/dist/displaywidth.d.ts +12 -0
- package/dist/execution-context.d.cts +23 -0
- package/dist/execution-context.d.ts +23 -0
- package/dist/extension.cjs +14 -14
- package/dist/facade.cjs +46 -36
- package/dist/facade.js +31 -21
- package/dist/index.cjs +22 -21
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +3 -3
- package/dist/input-trace.d.cts +2 -1
- package/dist/input-trace.d.ts +2 -1
- package/dist/internal/annotations.cjs +3 -0
- package/dist/internal/annotations.d.cts +47 -5
- package/dist/internal/annotations.d.ts +47 -5
- package/dist/internal/annotations.js +1 -1
- package/dist/internal/command-alias.cjs +16 -0
- package/dist/internal/command-alias.js +14 -0
- package/dist/internal/dependency.cjs +131 -0
- package/dist/internal/dependency.d.cts +311 -2
- package/dist/internal/dependency.d.ts +311 -2
- package/dist/internal/dependency.js +119 -1
- package/dist/internal/parser.cjs +35 -13
- package/dist/internal/parser.d.cts +44 -3
- package/dist/internal/parser.d.ts +44 -3
- package/dist/internal/parser.js +28 -6
- package/dist/modifiers.cjs +41 -41
- package/dist/parser.cjs +11 -11
- package/dist/phase2-seed.cjs +2 -2
- package/dist/phase2-seed.d.cts +50 -0
- package/dist/phase2-seed.d.ts +50 -0
- package/dist/primitives.cjs +74 -33
- package/dist/primitives.d.cts +10 -0
- package/dist/primitives.d.ts +10 -0
- package/dist/primitives.js +54 -13
- package/dist/suggestion.cjs +72 -2
- package/dist/suggestion.d.cts +188 -0
- package/dist/suggestion.d.ts +188 -0
- package/dist/suggestion.js +71 -3
- package/dist/usage-internals.cjs +5 -1
- package/dist/usage-internals.js +5 -1
- package/dist/usage.cjs +9 -1
- package/dist/usage.d.cts +14 -0
- package/dist/usage.d.ts +14 -0
- package/dist/usage.js +9 -1
- package/dist/validate.cjs +1 -0
- package/dist/validate.d.cts +99 -0
- package/dist/validate.d.ts +99 -0
- package/dist/validate.js +1 -1
- package/dist/valueparser.cjs +333 -79
- package/dist/valueparser.d.cts +197 -1
- package/dist/valueparser.d.ts +197 -1
- package/dist/valueparser.js +334 -81
- package/package.json +19 -4
package/dist/constructs.js
CHANGED
|
@@ -8,9 +8,10 @@ import { createDependencySourceState, dependencyId, isDependencySourceState, isP
|
|
|
8
8
|
import { buildRuntimeNodesFromArray, buildRuntimeNodesFromPairs, collectExplicitSourceValues, collectExplicitSourceValuesAsync, collectSourcesFromState, createDependencyRuntimeContext, fillMissingSourceDefaults, fillMissingSourceDefaultsAsync, resolveStateWithRuntime, resolveStateWithRuntimeAsync } from "./dependency-runtime.js";
|
|
9
9
|
import { defineInheritedAnnotationParser, getParserSuggestRuntimeNodes, unmatchedNonCliDependencySourceStateMarker } from "./internal/parser.js";
|
|
10
10
|
import { annotationViewTargets, getWrappedChildParseState, getWrappedChildState, reconcileObjectChildState, unwrapAnnotationView } from "./annotation-state.js";
|
|
11
|
+
import { allowDuplicateLeadingCommandNamesKey } from "./internal/command-alias.js";
|
|
11
12
|
import { mergeChildExec, withChildContext, withChildExecPath } from "./execution-context.js";
|
|
12
13
|
import { completeOrExtractPhase2Seed, extractPhase2Seed, extractPhase2SeedKey, phase2SeedFromValueResult } from "./phase2-seed.js";
|
|
13
|
-
import { DEFAULT_FIND_SIMILAR_OPTIONS, createErrorWithSuggestions, createSuggestionMessage, deduplicateSuggestions, findSimilar } from "./suggestion.js";
|
|
14
|
+
import { DEFAULT_FIND_SIMILAR_OPTIONS, createErrorWithSuggestions, createSuggestionMessage, deduplicateSuggestions, expandCommandAliasSuggestions, findSimilar } from "./suggestion.js";
|
|
14
15
|
import { collectLeadingCandidates } from "./usage-internals.js";
|
|
15
16
|
|
|
16
17
|
//#region src/constructs.ts
|
|
@@ -301,7 +302,12 @@ function createUnexpectedInputErrorWithScopedSuggestions(baseError, invalidInput
|
|
|
301
302
|
for (const parser of parsers) collectLeadingCandidates(parser.usage, options, commands);
|
|
302
303
|
const candidates = new Set([...options, ...commands]);
|
|
303
304
|
const suggestions = findSimilar(invalidInput, candidates, DEFAULT_FIND_SIMILAR_OPTIONS);
|
|
304
|
-
const
|
|
305
|
+
const aliasUsage = [{
|
|
306
|
+
type: "exclusive",
|
|
307
|
+
terms: parsers.map((parser) => parser.usage)
|
|
308
|
+
}];
|
|
309
|
+
const displaySuggestions = expandCommandAliasSuggestions(aliasUsage, suggestions);
|
|
310
|
+
const suggestionMsg = customFormatter ? customFormatter(displaySuggestions) : createSuggestionMessage(displaySuggestions);
|
|
305
311
|
return suggestionMsg.length > 0 ? [
|
|
306
312
|
...baseError,
|
|
307
313
|
text("\n\n"),
|
|
@@ -457,6 +463,18 @@ var DuplicateOptionError = class extends Error {
|
|
|
457
463
|
}
|
|
458
464
|
};
|
|
459
465
|
/**
|
|
466
|
+
* Error class thrown when duplicate command names or aliases are detected
|
|
467
|
+
* during parser construction. This is a programmer error, not a user error.
|
|
468
|
+
*/
|
|
469
|
+
var DuplicateCommandNameError = class extends TypeError {
|
|
470
|
+
constructor(commandName, sources) {
|
|
471
|
+
const sourceNames = sources.map((s) => typeof s === "symbol" ? s.description ?? s.toString() : s);
|
|
472
|
+
super(`Duplicate command name "${commandName}" found in parsers: ${sourceNames.join(", ")}. Each command name or alias must be unique within active parser alternatives.`);
|
|
473
|
+
this.commandName = commandName;
|
|
474
|
+
this.sources = sources;
|
|
475
|
+
}
|
|
476
|
+
};
|
|
477
|
+
/**
|
|
460
478
|
* Checks for duplicate option names across parser sources and throws an error
|
|
461
479
|
* if duplicates are found. This should be called at construction time.
|
|
462
480
|
* @param parserSources Array of [source, usage] tuples
|
|
@@ -473,6 +491,48 @@ function checkDuplicateOptionNames(parserSources) {
|
|
|
473
491
|
}
|
|
474
492
|
for (const [name, sources] of optionNameSources) if (sources.length > 1) throw new DuplicateOptionError(name, sources);
|
|
475
493
|
}
|
|
494
|
+
function checkDuplicateLeadingCommandNames(parserSources) {
|
|
495
|
+
const commandNameSources = /* @__PURE__ */ new Map();
|
|
496
|
+
for (const [source, parser] of parserSources) {
|
|
497
|
+
const commandNames = extractCommandNames(parser.usage, true);
|
|
498
|
+
for (const name of parser.leadingNames) {
|
|
499
|
+
if (!commandNames.has(name)) continue;
|
|
500
|
+
const sources = commandNameSources.get(name);
|
|
501
|
+
commandNameSources.set(name, sources == null ? [source] : [...sources, source]);
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
for (const [name, sources] of commandNameSources) if (sources.length > 1) throw new DuplicateCommandNameError(name, sources);
|
|
505
|
+
}
|
|
506
|
+
function checkDuplicateReachableLeadingCommandNames(parserSources) {
|
|
507
|
+
const commandNameSources = /* @__PURE__ */ new Map();
|
|
508
|
+
const sortedSources = [...parserSources].sort(([, parserA], [, parserB]) => parserB.priority - parserA.priority);
|
|
509
|
+
const blockedNames = /* @__PURE__ */ new Set();
|
|
510
|
+
let positionalBlocked = false;
|
|
511
|
+
for (let i = 0; i < sortedSources.length;) {
|
|
512
|
+
const priority = sortedSources[i][1].priority;
|
|
513
|
+
const priorityGroup = [];
|
|
514
|
+
while (i < sortedSources.length && sortedSources[i][1].priority === priority) {
|
|
515
|
+
priorityGroup.push(sortedSources[i]);
|
|
516
|
+
i++;
|
|
517
|
+
}
|
|
518
|
+
const groupNames = /* @__PURE__ */ new Set();
|
|
519
|
+
let groupAcceptsAnyToken = false;
|
|
520
|
+
for (const [source, parser] of priorityGroup) {
|
|
521
|
+
if (parser.acceptingAnyToken) groupAcceptsAnyToken = true;
|
|
522
|
+
const commandNames = extractCommandNames(parser.usage, true);
|
|
523
|
+
for (const name of parser.leadingNames) {
|
|
524
|
+
if (!commandNames.has(name)) continue;
|
|
525
|
+
if (positionalBlocked || blockedNames.has(name)) continue;
|
|
526
|
+
groupNames.add(name);
|
|
527
|
+
const sources = commandNameSources.get(name);
|
|
528
|
+
commandNameSources.set(name, sources == null ? [source] : [...sources, source]);
|
|
529
|
+
}
|
|
530
|
+
}
|
|
531
|
+
for (const name of groupNames) blockedNames.add(name);
|
|
532
|
+
if (groupAcceptsAnyToken) positionalBlocked = true;
|
|
533
|
+
}
|
|
534
|
+
for (const [name, sources] of commandNameSources) if (sources.length > 1) throw new DuplicateCommandNameError(name, sources);
|
|
535
|
+
}
|
|
476
536
|
/**
|
|
477
537
|
* Extracts option names that participate in CLI syntax.
|
|
478
538
|
*
|
|
@@ -737,6 +797,7 @@ function or(...args) {
|
|
|
737
797
|
}
|
|
738
798
|
if (parsers.length < 1) throw new TypeError("or() requires at least one parser argument.");
|
|
739
799
|
assertParsers(parsers, "or()");
|
|
800
|
+
checkDuplicateLeadingCommandNames(parsers.map((parser, index) => [String(index), parser]));
|
|
740
801
|
const noMatchContext = analyzeNoMatchContext(parsers);
|
|
741
802
|
const combinedMode = parsers.some((p) => p.mode === "async") ? "async" : "sync";
|
|
742
803
|
const syncParsers = parsers;
|
|
@@ -1212,6 +1273,9 @@ function or(...args) {
|
|
|
1212
1273
|
* @since 0.5.0
|
|
1213
1274
|
*/
|
|
1214
1275
|
function longestMatch(...args) {
|
|
1276
|
+
return createLongestMatch(...args);
|
|
1277
|
+
}
|
|
1278
|
+
function createLongestMatch(...args) {
|
|
1215
1279
|
let parsers;
|
|
1216
1280
|
let options;
|
|
1217
1281
|
if (args.length > 0 && args[args.length - 1] && typeof args[args.length - 1] === "object" && !("$valueType" in args[args.length - 1])) {
|
|
@@ -1223,6 +1287,8 @@ function longestMatch(...args) {
|
|
|
1223
1287
|
}
|
|
1224
1288
|
if (parsers.length < 1) throw new TypeError("longestMatch() requires at least one parser argument.");
|
|
1225
1289
|
assertParsers(parsers, "longestMatch()");
|
|
1290
|
+
const allowDuplicateLeadingCommandNames = options?.[allowDuplicateLeadingCommandNamesKey] === true;
|
|
1291
|
+
if (!allowDuplicateLeadingCommandNames) checkDuplicateLeadingCommandNames(parsers.map((parser, index) => [String(index), parser]));
|
|
1226
1292
|
const noMatchContext = analyzeNoMatchContext(parsers);
|
|
1227
1293
|
const combinedMode = parsers.some((p) => p.mode === "async") ? "async" : "sync";
|
|
1228
1294
|
const syncParsers = parsers;
|
|
@@ -1768,6 +1834,7 @@ function object(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
|
|
|
1768
1834
|
};
|
|
1769
1835
|
};
|
|
1770
1836
|
if (!options.allowDuplicates) checkDuplicateOptionNames(parserPairs.map(([field, parser]) => [field, parser.usage]));
|
|
1837
|
+
checkDuplicateReachableLeadingCommandNames(parserPairs.map(([field, parser]) => [field, parser]));
|
|
1771
1838
|
const noMatchContext = analyzeNoMatchContext(parserKeys.map((k) => parsers[k]));
|
|
1772
1839
|
const combinedMode = parserKeys.some((k) => parsers[k].mode === "async") ? "async" : "sync";
|
|
1773
1840
|
const getInitialError = (context) => ({
|
|
@@ -3651,6 +3718,7 @@ function merge(...args) {
|
|
|
3651
3718
|
const syncSorted = syncWithIndex.toSorted(([a], [b]) => b.priority - a.priority);
|
|
3652
3719
|
const syncParsers = syncSorted.map(([p]) => p);
|
|
3653
3720
|
if (!options.allowDuplicates) checkDuplicateOptionNames(sorted.map(([parser, originalIndex]) => [String(originalIndex), parser.usage]));
|
|
3721
|
+
checkDuplicateReachableLeadingCommandNames(sorted.map(([parser, originalIndex]) => [String(originalIndex), parser]));
|
|
3654
3722
|
const mergedFieldParsers = collectChildFieldParsers(parsers);
|
|
3655
3723
|
const duplicateOutputFieldNames = collectDuplicateFieldNames(mergedFieldParsers);
|
|
3656
3724
|
const parserStateKey = (index) => `__parser_${index}`;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
const
|
|
1
|
+
const require_internal_dependency = require('./internal/dependency.cjs');
|
|
2
2
|
|
|
3
3
|
//#region src/dependency-metadata.ts
|
|
4
4
|
/**
|
|
@@ -14,27 +14,27 @@ const require_dependency = require('./internal/dependency.cjs');
|
|
|
14
14
|
* @since 1.0.0
|
|
15
15
|
*/
|
|
16
16
|
function extractDependencyMetadata(valueParser) {
|
|
17
|
-
if (
|
|
17
|
+
if (require_internal_dependency.isDependencySource(valueParser)) return { source: {
|
|
18
18
|
kind: "source",
|
|
19
|
-
sourceId: valueParser[
|
|
19
|
+
sourceId: valueParser[require_internal_dependency.dependencyId],
|
|
20
20
|
extractSourceValue: extractFromBareState,
|
|
21
21
|
preservesSourceValue: true
|
|
22
22
|
} };
|
|
23
|
-
if (
|
|
24
|
-
const isMultiSource =
|
|
25
|
-
const allIds = isMultiSource ? valueParser[
|
|
23
|
+
if (require_internal_dependency.isDerivedValueParser(valueParser)) {
|
|
24
|
+
const isMultiSource = require_internal_dependency.dependencyIds in valueParser && valueParser[require_internal_dependency.dependencyIds] != null;
|
|
25
|
+
const allIds = isMultiSource ? valueParser[require_internal_dependency.dependencyIds] : [valueParser[require_internal_dependency.dependencyId]];
|
|
26
26
|
let defaultValuesFn;
|
|
27
|
-
if (
|
|
28
|
-
else if (
|
|
29
|
-
const singleFn = valueParser[
|
|
27
|
+
if (require_internal_dependency.defaultValues in valueParser && valueParser[require_internal_dependency.defaultValues] != null) defaultValuesFn = valueParser[require_internal_dependency.defaultValues];
|
|
28
|
+
else if (require_internal_dependency.singleDefaultValue in valueParser && valueParser[require_internal_dependency.singleDefaultValue] != null) {
|
|
29
|
+
const singleFn = valueParser[require_internal_dependency.singleDefaultValue];
|
|
30
30
|
defaultValuesFn = () => [singleFn()];
|
|
31
31
|
}
|
|
32
32
|
const parser = valueParser;
|
|
33
33
|
const replayParse = (rawInput, depValues) => {
|
|
34
34
|
const depArg = isMultiSource ? depValues : depValues[0];
|
|
35
|
-
return parser[
|
|
35
|
+
return parser[require_internal_dependency.parseWithDependency](rawInput, depArg);
|
|
36
36
|
};
|
|
37
|
-
const suggestFn =
|
|
37
|
+
const suggestFn = require_internal_dependency.suggestWithDependency in parser ? parser[require_internal_dependency.suggestWithDependency] : void 0;
|
|
38
38
|
const replaySuggest = suggestFn != null ? (prefix, depValues) => {
|
|
39
39
|
const depArg = isMultiSource ? depValues : depValues[0];
|
|
40
40
|
return suggestFn(prefix, depArg);
|
|
@@ -58,7 +58,7 @@ function extractDependencyMetadata(valueParser) {
|
|
|
58
58
|
* dependency sources.
|
|
59
59
|
*/
|
|
60
60
|
function extractFromBareState(state) {
|
|
61
|
-
if (
|
|
61
|
+
if (require_internal_dependency.isDependencySourceState(state)) return state.result;
|
|
62
62
|
if (state != null && typeof state === "object" && Object.hasOwn(state, "success") && typeof state.success === "boolean" && (state.success && Object.hasOwn(state, "value") || !state.success && Object.hasOwn(state, "error"))) return state;
|
|
63
63
|
return void 0;
|
|
64
64
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ValueParserResult } from "./valueparser.cjs";
|
|
2
|
-
import { Suggestion } from "./internal/parser.cjs";
|
|
1
|
+
import { ValueParser, ValueParserResult } from "./valueparser.cjs";
|
|
2
|
+
import { Mode, Suggestion } from "./internal/parser.cjs";
|
|
3
3
|
|
|
4
4
|
//#region src/dependency-metadata.d.ts
|
|
5
5
|
|
|
@@ -108,5 +108,36 @@ interface ParserDependencyMetadata {
|
|
|
108
108
|
* @internal
|
|
109
109
|
* @since 1.0.0
|
|
110
110
|
*/
|
|
111
|
+
declare function extractDependencyMetadata<M extends Mode, T>(valueParser: ValueParser<M, T>): ParserDependencyMetadata | undefined;
|
|
112
|
+
/**
|
|
113
|
+
* Options for `composeDependencyMetadata` when the wrapper kind is
|
|
114
|
+
* `"withDefault"`.
|
|
115
|
+
*
|
|
116
|
+
* @internal
|
|
117
|
+
* @since 1.0.0
|
|
118
|
+
*/
|
|
119
|
+
interface WithDefaultCompositionOptions {
|
|
120
|
+
/** Thunk returning the default value as a `ValueParserResult`. */
|
|
121
|
+
readonly defaultValue: () => ValueParserResult<unknown> | Promise<ValueParserResult<unknown>>;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Composes dependency metadata through a modifier wrapper.
|
|
125
|
+
*
|
|
126
|
+
* - `"optional"`: composes `extractSourceValue` with array unwrapping.
|
|
127
|
+
* - `"withDefault"`: adds `getMissingSourceValue` if the inner parser
|
|
128
|
+
* preserves a dependency source.
|
|
129
|
+
* - `"map"`: sets `transformsSourceValue` and clears
|
|
130
|
+
* `preservesSourceValue`.
|
|
131
|
+
*
|
|
132
|
+
* Returns `undefined` if `inner` is `undefined`.
|
|
133
|
+
*
|
|
134
|
+
* @param inner The inner parser's metadata.
|
|
135
|
+
* @param wrapperKind The type of modifier being applied.
|
|
136
|
+
* @param options Additional options for certain wrapper kinds.
|
|
137
|
+
* @returns Composed metadata, or `undefined`.
|
|
138
|
+
* @internal
|
|
139
|
+
* @since 1.0.0
|
|
140
|
+
*/
|
|
141
|
+
declare function composeDependencyMetadata(inner: ParserDependencyMetadata | undefined, wrapperKind: "optional" | "withDefault" | "map", options?: WithDefaultCompositionOptions): ParserDependencyMetadata | undefined;
|
|
111
142
|
//#endregion
|
|
112
|
-
export { ParserDependencyMetadata };
|
|
143
|
+
export { DependencySourceCapability, DependencyTransformCapability, DerivedDependencyCapability, ParserDependencyMetadata, WithDefaultCompositionOptions, composeDependencyMetadata, extractDependencyMetadata };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ValueParserResult } from "./valueparser.js";
|
|
2
|
-
import { Suggestion } from "./internal/parser.js";
|
|
1
|
+
import { ValueParser, ValueParserResult } from "./valueparser.js";
|
|
2
|
+
import { Mode, Suggestion } from "./internal/parser.js";
|
|
3
3
|
|
|
4
4
|
//#region src/dependency-metadata.d.ts
|
|
5
5
|
|
|
@@ -108,5 +108,36 @@ interface ParserDependencyMetadata {
|
|
|
108
108
|
* @internal
|
|
109
109
|
* @since 1.0.0
|
|
110
110
|
*/
|
|
111
|
+
declare function extractDependencyMetadata<M extends Mode, T>(valueParser: ValueParser<M, T>): ParserDependencyMetadata | undefined;
|
|
112
|
+
/**
|
|
113
|
+
* Options for `composeDependencyMetadata` when the wrapper kind is
|
|
114
|
+
* `"withDefault"`.
|
|
115
|
+
*
|
|
116
|
+
* @internal
|
|
117
|
+
* @since 1.0.0
|
|
118
|
+
*/
|
|
119
|
+
interface WithDefaultCompositionOptions {
|
|
120
|
+
/** Thunk returning the default value as a `ValueParserResult`. */
|
|
121
|
+
readonly defaultValue: () => ValueParserResult<unknown> | Promise<ValueParserResult<unknown>>;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Composes dependency metadata through a modifier wrapper.
|
|
125
|
+
*
|
|
126
|
+
* - `"optional"`: composes `extractSourceValue` with array unwrapping.
|
|
127
|
+
* - `"withDefault"`: adds `getMissingSourceValue` if the inner parser
|
|
128
|
+
* preserves a dependency source.
|
|
129
|
+
* - `"map"`: sets `transformsSourceValue` and clears
|
|
130
|
+
* `preservesSourceValue`.
|
|
131
|
+
*
|
|
132
|
+
* Returns `undefined` if `inner` is `undefined`.
|
|
133
|
+
*
|
|
134
|
+
* @param inner The inner parser's metadata.
|
|
135
|
+
* @param wrapperKind The type of modifier being applied.
|
|
136
|
+
* @param options Additional options for certain wrapper kinds.
|
|
137
|
+
* @returns Composed metadata, or `undefined`.
|
|
138
|
+
* @internal
|
|
139
|
+
* @since 1.0.0
|
|
140
|
+
*/
|
|
141
|
+
declare function composeDependencyMetadata(inner: ParserDependencyMetadata | undefined, wrapperKind: "optional" | "withDefault" | "map", options?: WithDefaultCompositionOptions): ParserDependencyMetadata | undefined;
|
|
111
142
|
//#endregion
|
|
112
|
-
export { ParserDependencyMetadata };
|
|
143
|
+
export { DependencySourceCapability, DependencyTransformCapability, DerivedDependencyCapability, ParserDependencyMetadata, WithDefaultCompositionOptions, composeDependencyMetadata, extractDependencyMetadata };
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
const require_message = require('./message.cjs');
|
|
2
|
-
const
|
|
3
|
-
const
|
|
2
|
+
const require_internal_dependency = require('./internal/dependency.cjs');
|
|
3
|
+
const require_internal_parser = require('./internal/parser.cjs');
|
|
4
4
|
|
|
5
5
|
//#region src/dependency-runtime.ts
|
|
6
6
|
const symbolIds = /* @__PURE__ */ new WeakMap();
|
|
@@ -457,6 +457,27 @@ async function replayDerivedParserAsync(node, rawInput, runtime) {
|
|
|
457
457
|
return result;
|
|
458
458
|
}
|
|
459
459
|
/**
|
|
460
|
+
* Extracts `rawInput` from a parser state that may contain a
|
|
461
|
+
* {@link DeferredParseState}. During the transition period, primitives
|
|
462
|
+
* still produce `DeferredParseState` with `rawInput`.
|
|
463
|
+
*
|
|
464
|
+
* Handles direct `DeferredParseState` and array-wrapped
|
|
465
|
+
* `[DeferredParseState]` (from optional/withDefault wrappers).
|
|
466
|
+
*
|
|
467
|
+
* @param state The parser state to inspect.
|
|
468
|
+
* @returns The raw input string, or `undefined` if the state does not
|
|
469
|
+
* contain a `DeferredParseState`.
|
|
470
|
+
* @internal
|
|
471
|
+
* @since 1.0.0
|
|
472
|
+
*/
|
|
473
|
+
function extractRawInputFromState(state) {
|
|
474
|
+
if (state == null) return void 0;
|
|
475
|
+
if (typeof state !== "object") return void 0;
|
|
476
|
+
if (require_internal_dependency.isDeferredParseState(state)) return state.rawInput;
|
|
477
|
+
if (Array.isArray(state) && state.length === 1 && require_internal_dependency.isDeferredParseState(state[0])) return state[0].rawInput;
|
|
478
|
+
return void 0;
|
|
479
|
+
}
|
|
480
|
+
/**
|
|
460
481
|
* Checks if a value is a plain object (not a class instance) for the
|
|
461
482
|
* purpose of recursive state traversal.
|
|
462
483
|
*/
|
|
@@ -481,7 +502,7 @@ function resolveSingleDeferred(deferred, runtime) {
|
|
|
481
502
|
if (resolution.kind !== "resolved") return deferred.preliminaryResult;
|
|
482
503
|
if (resolution.usedDefaults.every((d) => d)) return deferred.preliminaryResult;
|
|
483
504
|
const depValue = isMultiDep ? resolution.values : resolution.values[0];
|
|
484
|
-
const result = deferred.parser[
|
|
505
|
+
const result = deferred.parser[require_internal_dependency.parseWithDependency](deferred.rawInput, depValue);
|
|
485
506
|
if (isPromiseLike(result)) throw new TypeError("resolveStateWithRuntime() received an async parseWithDependency() result. Use resolveStateWithRuntimeAsync() instead.");
|
|
486
507
|
return result;
|
|
487
508
|
}
|
|
@@ -495,7 +516,7 @@ function resolveSingleDeferredAsync(deferred, runtime) {
|
|
|
495
516
|
if (resolution.kind !== "resolved") return Promise.resolve(deferred.preliminaryResult);
|
|
496
517
|
if (resolution.usedDefaults.every((d) => d)) return Promise.resolve(deferred.preliminaryResult);
|
|
497
518
|
const depValue = isMultiDep ? resolution.values : resolution.values[0];
|
|
498
|
-
return Promise.resolve(deferred.parser[
|
|
519
|
+
return Promise.resolve(deferred.parser[require_internal_dependency.parseWithDependency](deferred.rawInput, depValue));
|
|
499
520
|
}
|
|
500
521
|
/**
|
|
501
522
|
* Recursively collects dependency source values from {@link DependencySourceState}
|
|
@@ -514,14 +535,14 @@ function collectSourcesFromState(state, runtime, visited = /* @__PURE__ */ new W
|
|
|
514
535
|
if (state == null || typeof state !== "object") return;
|
|
515
536
|
if (visited.has(state)) return;
|
|
516
537
|
visited.add(state);
|
|
517
|
-
if (
|
|
518
|
-
const depId = state[
|
|
538
|
+
if (require_internal_dependency.isDependencySourceState(state)) {
|
|
539
|
+
const depId = state[require_internal_dependency.dependencyId];
|
|
519
540
|
const result = state.result;
|
|
520
541
|
if (depId != null && result.success) runtime.registerSource(depId, result.value, "cli");
|
|
521
542
|
else if (depId != null) runtime.markSourceFailed(depId);
|
|
522
543
|
return;
|
|
523
544
|
}
|
|
524
|
-
if (
|
|
545
|
+
if (require_internal_dependency.isDeferredParseState(state)) return;
|
|
525
546
|
if (Array.isArray(state)) {
|
|
526
547
|
for (const item of state) collectSourcesFromState(item, runtime, visited);
|
|
527
548
|
return;
|
|
@@ -559,14 +580,14 @@ function resolveStateWithRuntime(state, runtime) {
|
|
|
559
580
|
/** Pass 2 helper: recursively replace DeferredParseState with resolved values. */
|
|
560
581
|
function resolveDeferredInState(state, runtime, visited = /* @__PURE__ */ new WeakSet(), deferredCache = /* @__PURE__ */ new WeakMap()) {
|
|
561
582
|
if (state == null) return state;
|
|
562
|
-
if (
|
|
583
|
+
if (require_internal_dependency.isDeferredParseState(state)) {
|
|
563
584
|
const cached = deferredCache.get(state);
|
|
564
585
|
if (cached !== void 0) return cached;
|
|
565
586
|
const resolved = resolveSingleDeferred(state, runtime);
|
|
566
587
|
deferredCache.set(state, resolved);
|
|
567
588
|
return resolved;
|
|
568
589
|
}
|
|
569
|
-
if (
|
|
590
|
+
if (require_internal_dependency.isDependencySourceState(state)) return state;
|
|
570
591
|
if (typeof state === "object") {
|
|
571
592
|
if (visited.has(state)) return state;
|
|
572
593
|
visited.add(state);
|
|
@@ -601,14 +622,14 @@ function resolveStateWithRuntimeAsync(state, runtime) {
|
|
|
601
622
|
/** Async pass 2 helper. */
|
|
602
623
|
async function resolveDeferredInStateAsync(state, runtime, visited = /* @__PURE__ */ new WeakSet(), deferredCache = /* @__PURE__ */ new WeakMap()) {
|
|
603
624
|
if (state == null) return state;
|
|
604
|
-
if (
|
|
625
|
+
if (require_internal_dependency.isDeferredParseState(state)) {
|
|
605
626
|
const cached = deferredCache.get(state);
|
|
606
627
|
if (cached !== void 0) return cached;
|
|
607
628
|
const resolved = resolveSingleDeferredAsync(state, runtime);
|
|
608
629
|
deferredCache.set(state, resolved);
|
|
609
630
|
return resolved;
|
|
610
631
|
}
|
|
611
|
-
if (
|
|
632
|
+
if (require_internal_dependency.isDependencySourceState(state)) return state;
|
|
612
633
|
if (typeof state === "object") {
|
|
613
634
|
if (visited.has(state)) return state;
|
|
614
635
|
visited.add(state);
|
|
@@ -636,8 +657,8 @@ async function resolveDeferredInStateAsync(state, runtime, visited = /* @__PURE_
|
|
|
636
657
|
function isMatchedState(fieldState, parser) {
|
|
637
658
|
if (fieldState === void 0) return false;
|
|
638
659
|
const innerState = Array.isArray(fieldState) && fieldState.length === 1 ? fieldState[0] : fieldState;
|
|
639
|
-
if (
|
|
640
|
-
if (parser[
|
|
660
|
+
if (require_internal_dependency.isPendingDependencySourceState(innerState)) return false;
|
|
661
|
+
if (parser[require_internal_parser.unmatchedNonCliDependencySourceStateMarker] === true && innerState != null && typeof innerState === "object" && Object.hasOwn(innerState, "hasCliValue") && innerState.hasCliValue === false) return false;
|
|
641
662
|
if (fieldState === parser.initialState) return false;
|
|
642
663
|
return true;
|
|
643
664
|
}
|
|
@@ -701,7 +722,10 @@ exports.buildRuntimeNodesFromPairs = buildRuntimeNodesFromPairs;
|
|
|
701
722
|
exports.collectExplicitSourceValues = collectExplicitSourceValues;
|
|
702
723
|
exports.collectExplicitSourceValuesAsync = collectExplicitSourceValuesAsync;
|
|
703
724
|
exports.collectSourcesFromState = collectSourcesFromState;
|
|
725
|
+
exports.createDependencyFingerprint = createDependencyFingerprint;
|
|
704
726
|
exports.createDependencyRuntimeContext = createDependencyRuntimeContext;
|
|
727
|
+
exports.createReplayKey = createReplayKey;
|
|
728
|
+
exports.extractRawInputFromState = extractRawInputFromState;
|
|
705
729
|
exports.fillMissingSourceDefaults = fillMissingSourceDefaults;
|
|
706
730
|
exports.fillMissingSourceDefaultsAsync = fillMissingSourceDefaultsAsync;
|
|
707
731
|
exports.replayDerivedParser = replayDerivedParser;
|
|
@@ -49,7 +49,14 @@ interface DependencyResolution {
|
|
|
49
49
|
* @internal
|
|
50
50
|
* @since 1.0.0
|
|
51
51
|
*/
|
|
52
|
-
|
|
52
|
+
interface SourceDefaultFailure {
|
|
53
|
+
/** The source that failed. */
|
|
54
|
+
readonly sourceId: symbol;
|
|
55
|
+
/** The path of the node. */
|
|
56
|
+
readonly path: readonly PropertyKey[];
|
|
57
|
+
/** The failed result or error message. */
|
|
58
|
+
readonly error: ValueParserResult<unknown>;
|
|
59
|
+
}
|
|
53
60
|
/**
|
|
54
61
|
* A key for caching replayed parse results.
|
|
55
62
|
*
|
|
@@ -145,5 +152,193 @@ interface DependencyRuntimeContext {
|
|
|
145
152
|
* @internal
|
|
146
153
|
* @since 1.0.0
|
|
147
154
|
*/
|
|
155
|
+
declare function createDependencyRuntimeContext(registry?: DependencyRegistryLike): DependencyRuntimeContext;
|
|
156
|
+
/**
|
|
157
|
+
* Creates a stable fingerprint from dependency values.
|
|
158
|
+
*
|
|
159
|
+
* @param values The dependency values to fingerprint.
|
|
160
|
+
* @returns A string fingerprint.
|
|
161
|
+
* @internal
|
|
162
|
+
* @since 1.0.0
|
|
163
|
+
*/
|
|
164
|
+
declare function createDependencyFingerprint(values: readonly unknown[]): string;
|
|
165
|
+
declare function createReplayKey(path: readonly PropertyKey[], rawInput: string, dependencyValues: readonly unknown[], replayParse?: Function): ReplayKey;
|
|
166
|
+
/**
|
|
167
|
+
* Collects explicit source values from parser states and registers them
|
|
168
|
+
* in the runtime context.
|
|
169
|
+
*
|
|
170
|
+
* @param nodes The runtime nodes to inspect.
|
|
171
|
+
* @param runtime The dependency runtime context.
|
|
172
|
+
* @throws Propagates synchronous errors thrown by `extractSourceValue()`.
|
|
173
|
+
* @throws {TypeError} If `extractSourceValue()` returns a promise-like result.
|
|
174
|
+
* Use {@link collectExplicitSourceValuesAsync} when async source
|
|
175
|
+
* extraction is expected.
|
|
176
|
+
* @internal
|
|
177
|
+
* @since 1.0.0
|
|
178
|
+
*/
|
|
179
|
+
declare function collectExplicitSourceValues(nodes: readonly RuntimeNode[], runtime: DependencyRuntimeContext): void;
|
|
180
|
+
/**
|
|
181
|
+
* Async version of {@link collectExplicitSourceValues}.
|
|
182
|
+
* Awaits async `extractSourceValue` results instead of rejecting
|
|
183
|
+
* promise-like values as the synchronous variant does.
|
|
184
|
+
*
|
|
185
|
+
* @param nodes The runtime nodes to inspect.
|
|
186
|
+
* @param runtime The dependency runtime context.
|
|
187
|
+
* @throws Propagates errors thrown or rejected by `extractSourceValue()`.
|
|
188
|
+
* @internal
|
|
189
|
+
* @since 1.0.0
|
|
190
|
+
*/
|
|
191
|
+
declare function collectExplicitSourceValuesAsync(nodes: readonly RuntimeNode[], runtime: DependencyRuntimeContext): Promise<void>;
|
|
192
|
+
/**
|
|
193
|
+
* Fills missing source defaults for source parsers whose state is
|
|
194
|
+
* unpopulated.
|
|
195
|
+
*
|
|
196
|
+
* Returns an array of failures for sources whose default evaluation
|
|
197
|
+
* failed (either threw or returned `{ success: false }`). The caller
|
|
198
|
+
* should propagate these so that dependent parsers see the real error
|
|
199
|
+
* instead of silently treating the source as absent.
|
|
200
|
+
*
|
|
201
|
+
* @param nodes The runtime nodes to inspect.
|
|
202
|
+
* @param runtime The dependency runtime context.
|
|
203
|
+
* @returns Failures from default evaluation (empty if all succeeded).
|
|
204
|
+
* @throws {TypeError} If `getMissingSourceValue()` returns a promise-like
|
|
205
|
+
* result. Use {@link fillMissingSourceDefaultsAsync} when async
|
|
206
|
+
* default extraction is expected.
|
|
207
|
+
* @internal
|
|
208
|
+
* @since 1.0.0
|
|
209
|
+
*/
|
|
210
|
+
declare function fillMissingSourceDefaults(nodes: readonly RuntimeNode[], runtime: DependencyRuntimeContext): readonly SourceDefaultFailure[];
|
|
211
|
+
/**
|
|
212
|
+
* Async version of {@link fillMissingSourceDefaults}.
|
|
213
|
+
* Awaits async `getMissingSourceValue` results.
|
|
214
|
+
*
|
|
215
|
+
* @param nodes The runtime nodes to inspect.
|
|
216
|
+
* @param runtime The dependency runtime context.
|
|
217
|
+
* @returns Failures from default evaluation (empty if all succeeded).
|
|
218
|
+
* @internal
|
|
219
|
+
* @since 1.0.0
|
|
220
|
+
*/
|
|
221
|
+
declare function fillMissingSourceDefaultsAsync(nodes: readonly RuntimeNode[], runtime: DependencyRuntimeContext): Promise<readonly SourceDefaultFailure[]>;
|
|
222
|
+
/**
|
|
223
|
+
* Replays a derived parser with resolved dependency values (sync).
|
|
224
|
+
*
|
|
225
|
+
* Returns `undefined` if dependencies cannot be resolved.
|
|
226
|
+
*
|
|
227
|
+
* @param node The runtime node with derived metadata.
|
|
228
|
+
* @param rawInput The raw input to replay.
|
|
229
|
+
* @param runtime The dependency runtime context.
|
|
230
|
+
* @returns The replay result, or `undefined`.
|
|
231
|
+
* @throws {TypeError} If `replayParse()` returns a promise-like result.
|
|
232
|
+
* Use {@link replayDerivedParserAsync} for async replay.
|
|
233
|
+
* @internal
|
|
234
|
+
* @since 1.0.0
|
|
235
|
+
*/
|
|
236
|
+
declare function replayDerivedParser(node: RuntimeNode, rawInput: string, runtime: DependencyRuntimeContext): ValueParserResult<unknown> | undefined;
|
|
237
|
+
/**
|
|
238
|
+
* Replays a derived parser with resolved dependency values (async).
|
|
239
|
+
*
|
|
240
|
+
* Returns `undefined` if dependencies cannot be resolved.
|
|
241
|
+
*
|
|
242
|
+
* @param node The runtime node with derived metadata.
|
|
243
|
+
* @param rawInput The raw input to replay.
|
|
244
|
+
* @param runtime The dependency runtime context.
|
|
245
|
+
* @returns The replay result, or `undefined`.
|
|
246
|
+
* @internal
|
|
247
|
+
* @since 1.0.0
|
|
248
|
+
*/
|
|
249
|
+
declare function replayDerivedParserAsync(node: RuntimeNode, rawInput: string, runtime: DependencyRuntimeContext): Promise<ValueParserResult<unknown> | undefined>;
|
|
250
|
+
/**
|
|
251
|
+
* Extracts `rawInput` from a parser state that may contain a
|
|
252
|
+
* {@link DeferredParseState}. During the transition period, primitives
|
|
253
|
+
* still produce `DeferredParseState` with `rawInput`.
|
|
254
|
+
*
|
|
255
|
+
* Handles direct `DeferredParseState` and array-wrapped
|
|
256
|
+
* `[DeferredParseState]` (from optional/withDefault wrappers).
|
|
257
|
+
*
|
|
258
|
+
* @param state The parser state to inspect.
|
|
259
|
+
* @returns The raw input string, or `undefined` if the state does not
|
|
260
|
+
* contain a `DeferredParseState`.
|
|
261
|
+
* @internal
|
|
262
|
+
* @since 1.0.0
|
|
263
|
+
*/
|
|
264
|
+
declare function extractRawInputFromState(state: unknown): string | undefined;
|
|
265
|
+
/**
|
|
266
|
+
* Recursively collects dependency source values from {@link DependencySourceState}
|
|
267
|
+
* objects found in the state tree and registers them in the runtime.
|
|
268
|
+
*
|
|
269
|
+
* This must run BEFORE deferred resolution so that all source values
|
|
270
|
+
* are available when replaying derived parsers.
|
|
271
|
+
*
|
|
272
|
+
* @param state The state tree to traverse.
|
|
273
|
+
* @param runtime The dependency runtime context to populate.
|
|
274
|
+
* @param visited Cycle guard for recursive traversal.
|
|
275
|
+
* @param excludedFields Optional property keys to skip at the current level.
|
|
276
|
+
* This exclusion set is not propagated recursively.
|
|
277
|
+
*/
|
|
278
|
+
declare function collectSourcesFromState(state: unknown, runtime: DependencyRuntimeContext, visited?: WeakSet<object>, excludedFields?: ReadonlySet<PropertyKey>): void;
|
|
279
|
+
/**
|
|
280
|
+
* Recursively resolves all {@link DeferredParseState} objects in a state
|
|
281
|
+
* tree using the dependency runtime (sync).
|
|
282
|
+
*
|
|
283
|
+
* Performs a two-pass traversal:
|
|
284
|
+
* 1. Collect all {@link DependencySourceState} values into the runtime.
|
|
285
|
+
* 2. Resolve all {@link DeferredParseState} using the populated runtime.
|
|
286
|
+
*
|
|
287
|
+
* This replaces the old `resolveDeferredParseStates` with runtime-based
|
|
288
|
+
* resolution. Only traverses plain objects and arrays; class instances
|
|
289
|
+
* and primitives are returned as-is.
|
|
290
|
+
*
|
|
291
|
+
* @param state The state tree to resolve.
|
|
292
|
+
* @param runtime The dependency runtime context.
|
|
293
|
+
* @returns The resolved state tree.
|
|
294
|
+
* @throws {TypeError} If a deferred parser returns a promise-like result from
|
|
295
|
+
* `parseWithDependency()`. Use {@link resolveStateWithRuntimeAsync}
|
|
296
|
+
* for async resolution.
|
|
297
|
+
* @internal
|
|
298
|
+
* @since 1.0.0
|
|
299
|
+
*/
|
|
300
|
+
declare function resolveStateWithRuntime(state: unknown, runtime: DependencyRuntimeContext): unknown;
|
|
301
|
+
/**
|
|
302
|
+
* Async version of {@link resolveStateWithRuntime}.
|
|
303
|
+
*
|
|
304
|
+
* @param state The state tree to resolve.
|
|
305
|
+
* @param runtime The dependency runtime context.
|
|
306
|
+
* @returns The resolved state tree.
|
|
307
|
+
* @internal
|
|
308
|
+
* @since 1.0.0
|
|
309
|
+
*/
|
|
310
|
+
declare function resolveStateWithRuntimeAsync(state: unknown, runtime: DependencyRuntimeContext): Promise<unknown>;
|
|
311
|
+
/**
|
|
312
|
+
* Builds {@link RuntimeNode}s from field→parser pairs and a state record.
|
|
313
|
+
*
|
|
314
|
+
* Used by `object()` and `merge()` constructs.
|
|
315
|
+
*
|
|
316
|
+
* @param pairs Field→parser pairs.
|
|
317
|
+
* @param state The state record keyed by field name.
|
|
318
|
+
* @param parentPath Optional parent path prefix.
|
|
319
|
+
* @returns An array of runtime nodes.
|
|
320
|
+
* @internal
|
|
321
|
+
* @since 1.0.0
|
|
322
|
+
*/
|
|
323
|
+
declare function buildRuntimeNodesFromPairs(pairs: ReadonlyArray<readonly [PropertyKey, {
|
|
324
|
+
readonly dependencyMetadata?: ParserDependencyMetadata;
|
|
325
|
+
readonly initialState?: unknown;
|
|
326
|
+
}]>, state: Record<PropertyKey, unknown>, parentPath?: readonly PropertyKey[]): readonly RuntimeNode[];
|
|
327
|
+
/**
|
|
328
|
+
* Builds {@link RuntimeNode}s from a parser array and a state array.
|
|
329
|
+
*
|
|
330
|
+
* Used by `tuple()` and `concat()` constructs.
|
|
331
|
+
*
|
|
332
|
+
* @param parsers The child parsers.
|
|
333
|
+
* @param stateArray The state array (one element per parser).
|
|
334
|
+
* @param parentPath Optional parent path prefix.
|
|
335
|
+
* @returns An array of runtime nodes.
|
|
336
|
+
* @internal
|
|
337
|
+
* @since 1.0.0
|
|
338
|
+
*/
|
|
339
|
+
declare function buildRuntimeNodesFromArray(parsers: ReadonlyArray<{
|
|
340
|
+
readonly dependencyMetadata?: ParserDependencyMetadata;
|
|
341
|
+
readonly initialState?: unknown;
|
|
342
|
+
}>, stateArray: readonly unknown[], parentPath?: readonly PropertyKey[]): readonly RuntimeNode[];
|
|
148
343
|
//#endregion
|
|
149
|
-
export { DependencyRuntimeContext, RuntimeNode };
|
|
344
|
+
export { DependencyRequest, DependencyResolution, DependencyRuntimeContext, DependencyValueOrigin, ReplayKey, RuntimeNode, SourceDefaultFailure, buildRuntimeNodesFromArray, buildRuntimeNodesFromPairs, collectExplicitSourceValues, collectExplicitSourceValuesAsync, collectSourcesFromState, createDependencyFingerprint, createDependencyRuntimeContext, createReplayKey, extractRawInputFromState, fillMissingSourceDefaults, fillMissingSourceDefaultsAsync, replayDerivedParser, replayDerivedParserAsync, resolveStateWithRuntime, resolveStateWithRuntimeAsync };
|