@optique/core 0.10.0-dev.290 → 0.10.0-dev.292
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 +71 -2
- package/dist/constructs.js +71 -2
- package/dist/dependency.cjs +383 -0
- package/dist/dependency.d.cts +457 -0
- package/dist/dependency.d.ts +457 -0
- package/dist/dependency.js +367 -0
- package/dist/facade.cjs +1 -1
- package/dist/facade.js +1 -1
- package/dist/index.cjs +18 -1
- package/dist/index.d.cts +4 -3
- package/dist/index.d.ts +4 -3
- package/dist/index.js +3 -2
- package/dist/parser.d.cts +3 -3
- package/dist/parser.d.ts +3 -3
- package/dist/primitives.cjs +60 -12
- package/dist/primitives.d.cts +8 -2
- package/dist/primitives.d.ts +8 -2
- package/dist/primitives.js +60 -12
- package/package.json +9 -1
package/dist/constructs.cjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const require_message = require('./message.cjs');
|
|
2
|
+
const require_dependency = require('./dependency.cjs');
|
|
2
3
|
const require_usage = require('./usage.cjs');
|
|
3
4
|
const require_suggestion = require('./suggestion.cjs');
|
|
4
5
|
|
|
@@ -531,6 +532,72 @@ async function* suggestObjectAsync(context, prefix, parserPairs) {
|
|
|
531
532
|
}
|
|
532
533
|
yield* require_suggestion.deduplicateSuggestions(suggestions);
|
|
533
534
|
}
|
|
535
|
+
/**
|
|
536
|
+
* Resolves deferred parse states in an object's field states.
|
|
537
|
+
* This function builds a dependency registry from DependencySourceState fields
|
|
538
|
+
* and re-parses DeferredParseState fields using the actual dependency values.
|
|
539
|
+
*
|
|
540
|
+
* @param fieldStates A record of field names to their state values
|
|
541
|
+
* @returns The field states with deferred states resolved to their actual values
|
|
542
|
+
* @internal
|
|
543
|
+
*/
|
|
544
|
+
function resolveDeferredParseStates(fieldStates) {
|
|
545
|
+
const registry = new require_dependency.DependencyRegistry();
|
|
546
|
+
for (const key of Reflect.ownKeys(fieldStates)) {
|
|
547
|
+
const fieldState = fieldStates[key];
|
|
548
|
+
if (require_dependency.isDependencySourceState(fieldState)) {
|
|
549
|
+
const depId = fieldState[require_dependency.DependencyId];
|
|
550
|
+
const result = fieldState.result;
|
|
551
|
+
if (result.success) registry.set(depId, result.value);
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
const resolvedStates = { ...fieldStates };
|
|
555
|
+
for (const key of Reflect.ownKeys(fieldStates)) {
|
|
556
|
+
const fieldState = fieldStates[key];
|
|
557
|
+
if (require_dependency.isDeferredParseState(fieldState)) {
|
|
558
|
+
const deferredState = fieldState;
|
|
559
|
+
const depId = deferredState.dependencyId;
|
|
560
|
+
if (registry.has(depId)) {
|
|
561
|
+
const dependencyValue = registry.get(depId);
|
|
562
|
+
const parser = deferredState.parser;
|
|
563
|
+
const reParseResult = parser[require_dependency.ParseWithDependency](deferredState.rawInput, dependencyValue);
|
|
564
|
+
if (reParseResult instanceof Promise) resolvedStates[key] = deferredState.preliminaryResult;
|
|
565
|
+
else resolvedStates[key] = reParseResult;
|
|
566
|
+
} else resolvedStates[key] = deferredState.preliminaryResult;
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
return resolvedStates;
|
|
570
|
+
}
|
|
571
|
+
/**
|
|
572
|
+
* Async version of resolveDeferredParseStates for async parsers.
|
|
573
|
+
* @internal
|
|
574
|
+
*/
|
|
575
|
+
async function resolveDeferredParseStatesAsync(fieldStates) {
|
|
576
|
+
const registry = new require_dependency.DependencyRegistry();
|
|
577
|
+
for (const key of Reflect.ownKeys(fieldStates)) {
|
|
578
|
+
const fieldState = fieldStates[key];
|
|
579
|
+
if (require_dependency.isDependencySourceState(fieldState)) {
|
|
580
|
+
const depId = fieldState[require_dependency.DependencyId];
|
|
581
|
+
const result = fieldState.result;
|
|
582
|
+
if (result.success) registry.set(depId, result.value);
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
const resolvedStates = { ...fieldStates };
|
|
586
|
+
for (const key of Reflect.ownKeys(fieldStates)) {
|
|
587
|
+
const fieldState = fieldStates[key];
|
|
588
|
+
if (require_dependency.isDeferredParseState(fieldState)) {
|
|
589
|
+
const deferredState = fieldState;
|
|
590
|
+
const depId = deferredState.dependencyId;
|
|
591
|
+
if (registry.has(depId)) {
|
|
592
|
+
const dependencyValue = registry.get(depId);
|
|
593
|
+
const parser = deferredState.parser;
|
|
594
|
+
const reParseResult = parser[require_dependency.ParseWithDependency](deferredState.rawInput, dependencyValue);
|
|
595
|
+
resolvedStates[key] = await Promise.resolve(reParseResult);
|
|
596
|
+
} else resolvedStates[key] = deferredState.preliminaryResult;
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
return resolvedStates;
|
|
600
|
+
}
|
|
534
601
|
function object(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
|
|
535
602
|
const label = typeof labelOrParsers === "string" ? labelOrParsers : void 0;
|
|
536
603
|
let parsers;
|
|
@@ -689,10 +756,11 @@ function object(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
|
|
|
689
756
|
return parseSync(context);
|
|
690
757
|
},
|
|
691
758
|
complete(state) {
|
|
759
|
+
const resolvedState = isAsync ? state : resolveDeferredParseStates(state);
|
|
692
760
|
if (!isAsync) {
|
|
693
761
|
const result = {};
|
|
694
762
|
for (const field of parserKeys) {
|
|
695
|
-
const valueResult = parsers[field].complete(
|
|
763
|
+
const valueResult = parsers[field].complete(resolvedState[field]);
|
|
696
764
|
if (valueResult.success) result[field] = valueResult.value;
|
|
697
765
|
else return {
|
|
698
766
|
success: false,
|
|
@@ -705,9 +773,10 @@ function object(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
|
|
|
705
773
|
};
|
|
706
774
|
}
|
|
707
775
|
return (async () => {
|
|
776
|
+
const resolvedState$1 = await resolveDeferredParseStatesAsync(state);
|
|
708
777
|
const result = {};
|
|
709
778
|
for (const field of parserKeys) {
|
|
710
|
-
const valueResult = await parsers[field].complete(
|
|
779
|
+
const valueResult = await parsers[field].complete(resolvedState$1[field]);
|
|
711
780
|
if (valueResult.success) result[field] = valueResult.value;
|
|
712
781
|
else return {
|
|
713
782
|
success: false,
|
package/dist/constructs.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { message, optionName, values } from "./message.js";
|
|
2
|
+
import { DependencyId, DependencyRegistry, ParseWithDependency, isDeferredParseState, isDependencySourceState } from "./dependency.js";
|
|
2
3
|
import { extractArgumentMetavars, extractCommandNames, extractOptionNames } from "./usage.js";
|
|
3
4
|
import { createErrorWithSuggestions, deduplicateSuggestions } from "./suggestion.js";
|
|
4
5
|
|
|
@@ -531,6 +532,72 @@ async function* suggestObjectAsync(context, prefix, parserPairs) {
|
|
|
531
532
|
}
|
|
532
533
|
yield* deduplicateSuggestions(suggestions);
|
|
533
534
|
}
|
|
535
|
+
/**
|
|
536
|
+
* Resolves deferred parse states in an object's field states.
|
|
537
|
+
* This function builds a dependency registry from DependencySourceState fields
|
|
538
|
+
* and re-parses DeferredParseState fields using the actual dependency values.
|
|
539
|
+
*
|
|
540
|
+
* @param fieldStates A record of field names to their state values
|
|
541
|
+
* @returns The field states with deferred states resolved to their actual values
|
|
542
|
+
* @internal
|
|
543
|
+
*/
|
|
544
|
+
function resolveDeferredParseStates(fieldStates) {
|
|
545
|
+
const registry = new DependencyRegistry();
|
|
546
|
+
for (const key of Reflect.ownKeys(fieldStates)) {
|
|
547
|
+
const fieldState = fieldStates[key];
|
|
548
|
+
if (isDependencySourceState(fieldState)) {
|
|
549
|
+
const depId = fieldState[DependencyId];
|
|
550
|
+
const result = fieldState.result;
|
|
551
|
+
if (result.success) registry.set(depId, result.value);
|
|
552
|
+
}
|
|
553
|
+
}
|
|
554
|
+
const resolvedStates = { ...fieldStates };
|
|
555
|
+
for (const key of Reflect.ownKeys(fieldStates)) {
|
|
556
|
+
const fieldState = fieldStates[key];
|
|
557
|
+
if (isDeferredParseState(fieldState)) {
|
|
558
|
+
const deferredState = fieldState;
|
|
559
|
+
const depId = deferredState.dependencyId;
|
|
560
|
+
if (registry.has(depId)) {
|
|
561
|
+
const dependencyValue = registry.get(depId);
|
|
562
|
+
const parser = deferredState.parser;
|
|
563
|
+
const reParseResult = parser[ParseWithDependency](deferredState.rawInput, dependencyValue);
|
|
564
|
+
if (reParseResult instanceof Promise) resolvedStates[key] = deferredState.preliminaryResult;
|
|
565
|
+
else resolvedStates[key] = reParseResult;
|
|
566
|
+
} else resolvedStates[key] = deferredState.preliminaryResult;
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
return resolvedStates;
|
|
570
|
+
}
|
|
571
|
+
/**
|
|
572
|
+
* Async version of resolveDeferredParseStates for async parsers.
|
|
573
|
+
* @internal
|
|
574
|
+
*/
|
|
575
|
+
async function resolveDeferredParseStatesAsync(fieldStates) {
|
|
576
|
+
const registry = new DependencyRegistry();
|
|
577
|
+
for (const key of Reflect.ownKeys(fieldStates)) {
|
|
578
|
+
const fieldState = fieldStates[key];
|
|
579
|
+
if (isDependencySourceState(fieldState)) {
|
|
580
|
+
const depId = fieldState[DependencyId];
|
|
581
|
+
const result = fieldState.result;
|
|
582
|
+
if (result.success) registry.set(depId, result.value);
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
const resolvedStates = { ...fieldStates };
|
|
586
|
+
for (const key of Reflect.ownKeys(fieldStates)) {
|
|
587
|
+
const fieldState = fieldStates[key];
|
|
588
|
+
if (isDeferredParseState(fieldState)) {
|
|
589
|
+
const deferredState = fieldState;
|
|
590
|
+
const depId = deferredState.dependencyId;
|
|
591
|
+
if (registry.has(depId)) {
|
|
592
|
+
const dependencyValue = registry.get(depId);
|
|
593
|
+
const parser = deferredState.parser;
|
|
594
|
+
const reParseResult = parser[ParseWithDependency](deferredState.rawInput, dependencyValue);
|
|
595
|
+
resolvedStates[key] = await Promise.resolve(reParseResult);
|
|
596
|
+
} else resolvedStates[key] = deferredState.preliminaryResult;
|
|
597
|
+
}
|
|
598
|
+
}
|
|
599
|
+
return resolvedStates;
|
|
600
|
+
}
|
|
534
601
|
function object(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
|
|
535
602
|
const label = typeof labelOrParsers === "string" ? labelOrParsers : void 0;
|
|
536
603
|
let parsers;
|
|
@@ -689,10 +756,11 @@ function object(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
|
|
|
689
756
|
return parseSync(context);
|
|
690
757
|
},
|
|
691
758
|
complete(state) {
|
|
759
|
+
const resolvedState = isAsync ? state : resolveDeferredParseStates(state);
|
|
692
760
|
if (!isAsync) {
|
|
693
761
|
const result = {};
|
|
694
762
|
for (const field of parserKeys) {
|
|
695
|
-
const valueResult = parsers[field].complete(
|
|
763
|
+
const valueResult = parsers[field].complete(resolvedState[field]);
|
|
696
764
|
if (valueResult.success) result[field] = valueResult.value;
|
|
697
765
|
else return {
|
|
698
766
|
success: false,
|
|
@@ -705,9 +773,10 @@ function object(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
|
|
|
705
773
|
};
|
|
706
774
|
}
|
|
707
775
|
return (async () => {
|
|
776
|
+
const resolvedState$1 = await resolveDeferredParseStatesAsync(state);
|
|
708
777
|
const result = {};
|
|
709
778
|
for (const field of parserKeys) {
|
|
710
|
-
const valueResult = await parsers[field].complete(
|
|
779
|
+
const valueResult = await parsers[field].complete(resolvedState$1[field]);
|
|
711
780
|
if (valueResult.success) result[field] = valueResult.value;
|
|
712
781
|
else return {
|
|
713
782
|
success: false,
|
|
@@ -0,0 +1,383 @@
|
|
|
1
|
+
|
|
2
|
+
//#region src/dependency.ts
|
|
3
|
+
/**
|
|
4
|
+
* A unique symbol used to identify dependency sources at compile time.
|
|
5
|
+
* This marker is used to distinguish {@link DependencySource} from regular
|
|
6
|
+
* {@link ValueParser} instances.
|
|
7
|
+
* @since 0.10.0
|
|
8
|
+
*/
|
|
9
|
+
const DependencySourceMarker = Symbol.for("@optique/core/dependency/DependencySourceMarker");
|
|
10
|
+
/**
|
|
11
|
+
* A unique symbol used to identify derived value parsers at compile time.
|
|
12
|
+
* This marker is used to distinguish {@link DerivedValueParser} from regular
|
|
13
|
+
* {@link ValueParser} instances.
|
|
14
|
+
* @since 0.10.0
|
|
15
|
+
*/
|
|
16
|
+
const DerivedValueParserMarker = Symbol.for("@optique/core/dependency/DerivedValueParserMarker");
|
|
17
|
+
/**
|
|
18
|
+
* A unique symbol used to store the dependency ID on value parsers.
|
|
19
|
+
* @since 0.10.0
|
|
20
|
+
*/
|
|
21
|
+
const DependencyId = Symbol.for("@optique/core/dependency/DependencyId");
|
|
22
|
+
/**
|
|
23
|
+
* A unique symbol used to access the parseWithDependency method on derived parsers.
|
|
24
|
+
* @since 0.10.0
|
|
25
|
+
*/
|
|
26
|
+
const ParseWithDependency = Symbol.for("@optique/core/dependency/ParseWithDependency");
|
|
27
|
+
/**
|
|
28
|
+
* Creates a dependency source from a {@link ValueParser}.
|
|
29
|
+
*
|
|
30
|
+
* A dependency source wraps an existing value parser and enables creating
|
|
31
|
+
* derived parsers that depend on the parsed value. This is useful for
|
|
32
|
+
* scenarios where one option's valid values depend on another option's value.
|
|
33
|
+
*
|
|
34
|
+
* @template M The execution mode of the value parser.
|
|
35
|
+
* @template T The type of value the parser produces.
|
|
36
|
+
* @param parser The value parser to wrap as a dependency source.
|
|
37
|
+
* @returns A {@link DependencySource} that can be used to create
|
|
38
|
+
* derived parsers.
|
|
39
|
+
* @example
|
|
40
|
+
* ```typescript
|
|
41
|
+
* import { dependency } from "@optique/core/dependency";
|
|
42
|
+
* import { string } from "@optique/core/valueparser";
|
|
43
|
+
*
|
|
44
|
+
* // Create a dependency source for a directory path
|
|
45
|
+
* const cwdParser = dependency(string({ metavar: "DIR" }));
|
|
46
|
+
*
|
|
47
|
+
* // Create a derived parser that depends on the directory
|
|
48
|
+
* const branchParser = cwdParser.derive({
|
|
49
|
+
* metavar: "BRANCH",
|
|
50
|
+
* factory: (dir) => gitBranch({ dir }),
|
|
51
|
+
* defaultValue: () => process.cwd(),
|
|
52
|
+
* });
|
|
53
|
+
* ```
|
|
54
|
+
* @since 0.10.0
|
|
55
|
+
*/
|
|
56
|
+
function dependency(parser) {
|
|
57
|
+
const id = Symbol();
|
|
58
|
+
return {
|
|
59
|
+
...parser,
|
|
60
|
+
[DependencySourceMarker]: true,
|
|
61
|
+
[DependencyId]: id,
|
|
62
|
+
derive(options) {
|
|
63
|
+
return createDerivedValueParser(id, parser, options);
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Checks if a value parser is a {@link DependencySource}.
|
|
69
|
+
*
|
|
70
|
+
* @param parser The value parser to check.
|
|
71
|
+
* @returns `true` if the parser is a dependency source, `false` otherwise.
|
|
72
|
+
* @since 0.10.0
|
|
73
|
+
*/
|
|
74
|
+
function isDependencySource(parser) {
|
|
75
|
+
return DependencySourceMarker in parser && parser[DependencySourceMarker] === true;
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Checks if a value parser is a {@link DerivedValueParser}.
|
|
79
|
+
*
|
|
80
|
+
* @param parser The value parser to check.
|
|
81
|
+
* @returns `true` if the parser is a derived value parser, `false` otherwise.
|
|
82
|
+
* @since 0.10.0
|
|
83
|
+
*/
|
|
84
|
+
function isDerivedValueParser(parser) {
|
|
85
|
+
return DerivedValueParserMarker in parser && parser[DerivedValueParserMarker] === true;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Creates a derived value parser from multiple dependency sources.
|
|
89
|
+
*
|
|
90
|
+
* This function allows creating a parser whose behavior depends on
|
|
91
|
+
* multiple other parsers' values. This is useful for scenarios where
|
|
92
|
+
* an option's valid values depend on a combination of other options.
|
|
93
|
+
*
|
|
94
|
+
* @template Deps A tuple of DependencySource types.
|
|
95
|
+
* @template T The type of value the derived parser produces.
|
|
96
|
+
* @param options Configuration for the derived parser.
|
|
97
|
+
* @returns A {@link DerivedValueParser} that depends on the given sources.
|
|
98
|
+
* @example
|
|
99
|
+
* ```typescript
|
|
100
|
+
* import { dependency, deriveFrom } from "@optique/core/dependency";
|
|
101
|
+
* import { string, choice } from "@optique/core/valueparser";
|
|
102
|
+
*
|
|
103
|
+
* const dirParser = dependency(string({ metavar: "DIR" }));
|
|
104
|
+
* const modeParser = dependency(choice(["dev", "prod"]));
|
|
105
|
+
*
|
|
106
|
+
* const configParser = deriveFrom({
|
|
107
|
+
* metavar: "CONFIG",
|
|
108
|
+
* dependencies: [dirParser, modeParser] as const,
|
|
109
|
+
* factory: (dir, mode) =>
|
|
110
|
+
* choice(mode === "dev"
|
|
111
|
+
* ? [`${dir}/dev.json`, `${dir}/dev.yaml`]
|
|
112
|
+
* : [`${dir}/prod.json`, `${dir}/prod.yaml`]),
|
|
113
|
+
* defaultValues: () => ["/config", "dev"],
|
|
114
|
+
* });
|
|
115
|
+
* ```
|
|
116
|
+
* @since 0.10.0
|
|
117
|
+
*/
|
|
118
|
+
function deriveFrom(options) {
|
|
119
|
+
const isAsync = options.dependencies.some((dep) => dep.$mode === "async");
|
|
120
|
+
const sourceId = options.dependencies.length > 0 ? options.dependencies[0][DependencyId] : Symbol();
|
|
121
|
+
if (isAsync) return createAsyncDerivedFromParser(sourceId, options);
|
|
122
|
+
return createSyncDerivedFromParser(sourceId, options);
|
|
123
|
+
}
|
|
124
|
+
function createSyncDerivedFromParser(sourceId, options) {
|
|
125
|
+
return {
|
|
126
|
+
$mode: "sync",
|
|
127
|
+
metavar: options.metavar,
|
|
128
|
+
[DerivedValueParserMarker]: true,
|
|
129
|
+
[DependencyId]: sourceId,
|
|
130
|
+
parse(input) {
|
|
131
|
+
const sourceValues = options.defaultValues();
|
|
132
|
+
const derivedParser = options.factory(...sourceValues);
|
|
133
|
+
return derivedParser.parse(input);
|
|
134
|
+
},
|
|
135
|
+
[ParseWithDependency](input, dependencyValue) {
|
|
136
|
+
const derivedParser = options.factory(...dependencyValue);
|
|
137
|
+
return derivedParser.parse(input);
|
|
138
|
+
},
|
|
139
|
+
format(value) {
|
|
140
|
+
const sourceValues = options.defaultValues();
|
|
141
|
+
const derivedParser = options.factory(...sourceValues);
|
|
142
|
+
return derivedParser.format(value);
|
|
143
|
+
},
|
|
144
|
+
*suggest(prefix) {
|
|
145
|
+
const sourceValues = options.defaultValues();
|
|
146
|
+
const derivedParser = options.factory(...sourceValues);
|
|
147
|
+
if (derivedParser.suggest) yield* derivedParser.suggest(prefix);
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
function createAsyncDerivedFromParser(sourceId, options) {
|
|
152
|
+
return {
|
|
153
|
+
$mode: "async",
|
|
154
|
+
metavar: options.metavar,
|
|
155
|
+
[DerivedValueParserMarker]: true,
|
|
156
|
+
[DependencyId]: sourceId,
|
|
157
|
+
parse(input) {
|
|
158
|
+
const sourceValues = options.defaultValues();
|
|
159
|
+
const derivedParser = options.factory(...sourceValues);
|
|
160
|
+
return Promise.resolve(derivedParser.parse(input));
|
|
161
|
+
},
|
|
162
|
+
[ParseWithDependency](input, dependencyValue) {
|
|
163
|
+
const derivedParser = options.factory(...dependencyValue);
|
|
164
|
+
return Promise.resolve(derivedParser.parse(input));
|
|
165
|
+
},
|
|
166
|
+
format(value) {
|
|
167
|
+
const sourceValues = options.defaultValues();
|
|
168
|
+
const derivedParser = options.factory(...sourceValues);
|
|
169
|
+
return derivedParser.format(value);
|
|
170
|
+
},
|
|
171
|
+
async *suggest(prefix) {
|
|
172
|
+
const sourceValues = options.defaultValues();
|
|
173
|
+
const derivedParser = options.factory(...sourceValues);
|
|
174
|
+
if (derivedParser.suggest) yield* derivedParser.suggest(prefix);
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
function createDerivedValueParser(sourceId, sourceParser, options) {
|
|
179
|
+
if (sourceParser.$mode === "async") return createAsyncDerivedParser(sourceId, options);
|
|
180
|
+
return createSyncDerivedParser(sourceId, options);
|
|
181
|
+
}
|
|
182
|
+
function createSyncDerivedParser(sourceId, options) {
|
|
183
|
+
return {
|
|
184
|
+
$mode: "sync",
|
|
185
|
+
metavar: options.metavar,
|
|
186
|
+
[DerivedValueParserMarker]: true,
|
|
187
|
+
[DependencyId]: sourceId,
|
|
188
|
+
parse(input) {
|
|
189
|
+
const sourceValue = options.defaultValue();
|
|
190
|
+
const derivedParser = options.factory(sourceValue);
|
|
191
|
+
return derivedParser.parse(input);
|
|
192
|
+
},
|
|
193
|
+
[ParseWithDependency](input, dependencyValue) {
|
|
194
|
+
const derivedParser = options.factory(dependencyValue);
|
|
195
|
+
return derivedParser.parse(input);
|
|
196
|
+
},
|
|
197
|
+
format(value) {
|
|
198
|
+
const sourceValue = options.defaultValue();
|
|
199
|
+
const derivedParser = options.factory(sourceValue);
|
|
200
|
+
return derivedParser.format(value);
|
|
201
|
+
},
|
|
202
|
+
*suggest(prefix) {
|
|
203
|
+
const sourceValue = options.defaultValue();
|
|
204
|
+
const derivedParser = options.factory(sourceValue);
|
|
205
|
+
if (derivedParser.suggest) yield* derivedParser.suggest(prefix);
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
function createAsyncDerivedParser(sourceId, options) {
|
|
210
|
+
return {
|
|
211
|
+
$mode: "async",
|
|
212
|
+
metavar: options.metavar,
|
|
213
|
+
[DerivedValueParserMarker]: true,
|
|
214
|
+
[DependencyId]: sourceId,
|
|
215
|
+
parse(input) {
|
|
216
|
+
const sourceValue = options.defaultValue();
|
|
217
|
+
const derivedParser = options.factory(sourceValue);
|
|
218
|
+
return Promise.resolve(derivedParser.parse(input));
|
|
219
|
+
},
|
|
220
|
+
[ParseWithDependency](input, dependencyValue) {
|
|
221
|
+
const derivedParser = options.factory(dependencyValue);
|
|
222
|
+
return Promise.resolve(derivedParser.parse(input));
|
|
223
|
+
},
|
|
224
|
+
format(value) {
|
|
225
|
+
const sourceValue = options.defaultValue();
|
|
226
|
+
const derivedParser = options.factory(sourceValue);
|
|
227
|
+
return derivedParser.format(value);
|
|
228
|
+
},
|
|
229
|
+
async *suggest(prefix) {
|
|
230
|
+
const sourceValue = options.defaultValue();
|
|
231
|
+
const derivedParser = options.factory(sourceValue);
|
|
232
|
+
if (derivedParser.suggest) yield* derivedParser.suggest(prefix);
|
|
233
|
+
}
|
|
234
|
+
};
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* A unique symbol used to identify deferred parse states.
|
|
238
|
+
* @since 0.10.0
|
|
239
|
+
*/
|
|
240
|
+
const DeferredParseMarker = Symbol.for("@optique/core/dependency/DeferredParseMarker");
|
|
241
|
+
/**
|
|
242
|
+
* Checks if a value is a {@link DeferredParseState}.
|
|
243
|
+
*
|
|
244
|
+
* @param value The value to check.
|
|
245
|
+
* @returns `true` if the value is a deferred parse state, `false` otherwise.
|
|
246
|
+
* @since 0.10.0
|
|
247
|
+
*/
|
|
248
|
+
function isDeferredParseState(value) {
|
|
249
|
+
return typeof value === "object" && value !== null && DeferredParseMarker in value && value[DeferredParseMarker] === true;
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Creates a deferred parse state for a DerivedValueParser.
|
|
253
|
+
*
|
|
254
|
+
* @template T The type of value the parser will produce.
|
|
255
|
+
* @template S The type of the source dependency value.
|
|
256
|
+
* @param rawInput The raw input string to be parsed.
|
|
257
|
+
* @param parser The DerivedValueParser that will parse the input.
|
|
258
|
+
* @param preliminaryResult The parse result using default dependency value.
|
|
259
|
+
* @returns A DeferredParseState object.
|
|
260
|
+
* @since 0.10.0
|
|
261
|
+
*/
|
|
262
|
+
function createDeferredParseState(rawInput, parser, preliminaryResult) {
|
|
263
|
+
return {
|
|
264
|
+
[DeferredParseMarker]: true,
|
|
265
|
+
rawInput,
|
|
266
|
+
parser,
|
|
267
|
+
dependencyId: parser[DependencyId],
|
|
268
|
+
preliminaryResult
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* A unique symbol used to identify dependency source parse states.
|
|
273
|
+
* @since 0.10.0
|
|
274
|
+
*/
|
|
275
|
+
const DependencySourceStateMarker = Symbol.for("@optique/core/dependency/DependencySourceStateMarker");
|
|
276
|
+
/**
|
|
277
|
+
* Checks if a value is a {@link DependencySourceState}.
|
|
278
|
+
*
|
|
279
|
+
* @param value The value to check.
|
|
280
|
+
* @returns `true` if the value is a dependency source state, `false` otherwise.
|
|
281
|
+
* @since 0.10.0
|
|
282
|
+
*/
|
|
283
|
+
function isDependencySourceState(value) {
|
|
284
|
+
return typeof value === "object" && value !== null && DependencySourceStateMarker in value && value[DependencySourceStateMarker] === true;
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Creates a dependency source state from a parse result.
|
|
288
|
+
*
|
|
289
|
+
* @template T The type of value the state contains.
|
|
290
|
+
* @param result The parse result.
|
|
291
|
+
* @param dependencyId The dependency ID.
|
|
292
|
+
* @returns A DependencySourceState object.
|
|
293
|
+
* @since 0.10.0
|
|
294
|
+
*/
|
|
295
|
+
function createDependencySourceState(result, dependencyId) {
|
|
296
|
+
return {
|
|
297
|
+
[DependencySourceStateMarker]: true,
|
|
298
|
+
[DependencyId]: dependencyId,
|
|
299
|
+
result
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
/**
|
|
303
|
+
* A registry for storing resolved dependency values during parsing.
|
|
304
|
+
* This is used to pass dependency values from DependencySource options
|
|
305
|
+
* to DerivedValueParser options.
|
|
306
|
+
* @since 0.10.0
|
|
307
|
+
*/
|
|
308
|
+
var DependencyRegistry = class DependencyRegistry {
|
|
309
|
+
values = /* @__PURE__ */ new Map();
|
|
310
|
+
/**
|
|
311
|
+
* Registers a resolved dependency value.
|
|
312
|
+
* @param id The dependency ID.
|
|
313
|
+
* @param value The resolved value.
|
|
314
|
+
*/
|
|
315
|
+
set(id, value) {
|
|
316
|
+
this.values.set(id, value);
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* Gets a resolved dependency value.
|
|
320
|
+
* @param id The dependency ID.
|
|
321
|
+
* @returns The resolved value, or undefined if not found.
|
|
322
|
+
*/
|
|
323
|
+
get(id) {
|
|
324
|
+
return this.values.get(id);
|
|
325
|
+
}
|
|
326
|
+
/**
|
|
327
|
+
* Checks if a dependency has been resolved.
|
|
328
|
+
* @param id The dependency ID.
|
|
329
|
+
* @returns `true` if the dependency has been resolved.
|
|
330
|
+
*/
|
|
331
|
+
has(id) {
|
|
332
|
+
return this.values.has(id);
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* Creates a copy of the registry.
|
|
336
|
+
*/
|
|
337
|
+
clone() {
|
|
338
|
+
const copy = new DependencyRegistry();
|
|
339
|
+
for (const [id, value] of this.values) copy.values.set(id, value);
|
|
340
|
+
return copy;
|
|
341
|
+
}
|
|
342
|
+
};
|
|
343
|
+
/**
|
|
344
|
+
* Formats a {@link DependencyError} into a human-readable {@link Message}.
|
|
345
|
+
*
|
|
346
|
+
* @param error The dependency error to format.
|
|
347
|
+
* @returns A Message describing the error.
|
|
348
|
+
* @since 0.10.0
|
|
349
|
+
*/
|
|
350
|
+
function formatDependencyError(error) {
|
|
351
|
+
switch (error.kind) {
|
|
352
|
+
case "duplicate": return [{
|
|
353
|
+
type: "text",
|
|
354
|
+
text: `Dependency used in multiple locations: ${error.locations.join(", ")}.`
|
|
355
|
+
}];
|
|
356
|
+
case "unresolved": return [{
|
|
357
|
+
type: "text",
|
|
358
|
+
text: `Unresolved dependency for ${error.derivedParserMetavar}: the dependency was not provided.`
|
|
359
|
+
}];
|
|
360
|
+
case "circular": return [{
|
|
361
|
+
type: "text",
|
|
362
|
+
text: `Circular dependency detected.`
|
|
363
|
+
}];
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
//#endregion
|
|
368
|
+
exports.DeferredParseMarker = DeferredParseMarker;
|
|
369
|
+
exports.DependencyId = DependencyId;
|
|
370
|
+
exports.DependencyRegistry = DependencyRegistry;
|
|
371
|
+
exports.DependencySourceMarker = DependencySourceMarker;
|
|
372
|
+
exports.DependencySourceStateMarker = DependencySourceStateMarker;
|
|
373
|
+
exports.DerivedValueParserMarker = DerivedValueParserMarker;
|
|
374
|
+
exports.ParseWithDependency = ParseWithDependency;
|
|
375
|
+
exports.createDeferredParseState = createDeferredParseState;
|
|
376
|
+
exports.createDependencySourceState = createDependencySourceState;
|
|
377
|
+
exports.dependency = dependency;
|
|
378
|
+
exports.deriveFrom = deriveFrom;
|
|
379
|
+
exports.formatDependencyError = formatDependencyError;
|
|
380
|
+
exports.isDeferredParseState = isDeferredParseState;
|
|
381
|
+
exports.isDependencySource = isDependencySource;
|
|
382
|
+
exports.isDependencySourceState = isDependencySourceState;
|
|
383
|
+
exports.isDerivedValueParser = isDerivedValueParser;
|