@optique/core 1.0.0-dev.908 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (109) hide show
  1. package/dist/annotation-state.cjs +425 -0
  2. package/dist/annotation-state.d.cts +24 -0
  3. package/dist/annotation-state.d.ts +24 -0
  4. package/dist/annotation-state.js +414 -0
  5. package/dist/annotations.cjs +2 -248
  6. package/dist/annotations.d.cts +2 -137
  7. package/dist/annotations.d.ts +2 -137
  8. package/dist/annotations.js +2 -238
  9. package/dist/completion.cjs +611 -100
  10. package/dist/completion.d.cts +1 -1
  11. package/dist/completion.d.ts +1 -1
  12. package/dist/completion.js +611 -100
  13. package/dist/constructs.cjs +3338 -827
  14. package/dist/constructs.d.cts +48 -7
  15. package/dist/constructs.d.ts +48 -7
  16. package/dist/constructs.js +3338 -827
  17. package/dist/context.cjs +0 -23
  18. package/dist/context.d.cts +119 -53
  19. package/dist/context.d.ts +119 -53
  20. package/dist/context.js +0 -22
  21. package/dist/dependency-metadata.cjs +139 -0
  22. package/dist/dependency-metadata.d.cts +112 -0
  23. package/dist/dependency-metadata.d.ts +112 -0
  24. package/dist/dependency-metadata.js +138 -0
  25. package/dist/dependency-runtime.cjs +698 -0
  26. package/dist/dependency-runtime.d.cts +149 -0
  27. package/dist/dependency-runtime.d.ts +149 -0
  28. package/dist/dependency-runtime.js +687 -0
  29. package/dist/dependency.cjs +7 -928
  30. package/dist/dependency.d.cts +2 -794
  31. package/dist/dependency.d.ts +2 -794
  32. package/dist/dependency.js +2 -899
  33. package/dist/displaywidth.cjs +44 -0
  34. package/dist/displaywidth.js +43 -0
  35. package/dist/doc.cjs +285 -23
  36. package/dist/doc.d.cts +57 -2
  37. package/dist/doc.d.ts +57 -2
  38. package/dist/doc.js +283 -25
  39. package/dist/execution-context.cjs +56 -0
  40. package/dist/execution-context.js +53 -0
  41. package/dist/extension.cjs +87 -0
  42. package/dist/extension.d.cts +97 -0
  43. package/dist/extension.d.ts +97 -0
  44. package/dist/extension.js +76 -0
  45. package/dist/facade.cjs +718 -523
  46. package/dist/facade.d.cts +87 -18
  47. package/dist/facade.d.ts +87 -18
  48. package/dist/facade.js +718 -523
  49. package/dist/index.cjs +14 -29
  50. package/dist/index.d.cts +10 -10
  51. package/dist/index.d.ts +10 -10
  52. package/dist/index.js +7 -7
  53. package/dist/input-trace.cjs +56 -0
  54. package/dist/input-trace.d.cts +77 -0
  55. package/dist/input-trace.d.ts +77 -0
  56. package/dist/input-trace.js +55 -0
  57. package/dist/internal/annotations.cjs +316 -0
  58. package/dist/internal/annotations.d.cts +140 -0
  59. package/dist/internal/annotations.d.ts +140 -0
  60. package/dist/internal/annotations.js +306 -0
  61. package/dist/internal/dependency.cjs +984 -0
  62. package/dist/internal/dependency.d.cts +539 -0
  63. package/dist/internal/dependency.d.ts +539 -0
  64. package/dist/internal/dependency.js +964 -0
  65. package/dist/{mode-dispatch.cjs → internal/mode-dispatch.cjs} +1 -3
  66. package/dist/{mode-dispatch.d.cts → internal/mode-dispatch.d.cts} +3 -7
  67. package/dist/{mode-dispatch.d.ts → internal/mode-dispatch.d.ts} +3 -7
  68. package/dist/{mode-dispatch.js → internal/mode-dispatch.js} +1 -3
  69. package/dist/internal/parser.cjs +728 -0
  70. package/dist/internal/parser.d.cts +947 -0
  71. package/dist/internal/parser.d.ts +947 -0
  72. package/dist/internal/parser.js +711 -0
  73. package/dist/message.cjs +84 -26
  74. package/dist/message.d.cts +49 -9
  75. package/dist/message.d.ts +49 -9
  76. package/dist/message.js +84 -27
  77. package/dist/modifiers.cjs +1023 -240
  78. package/dist/modifiers.d.cts +42 -1
  79. package/dist/modifiers.d.ts +42 -1
  80. package/dist/modifiers.js +1023 -240
  81. package/dist/parser.cjs +11 -463
  82. package/dist/parser.d.cts +3 -537
  83. package/dist/parser.d.ts +3 -537
  84. package/dist/parser.js +2 -433
  85. package/dist/phase2-seed.cjs +59 -0
  86. package/dist/phase2-seed.js +56 -0
  87. package/dist/primitives.cjs +557 -208
  88. package/dist/primitives.d.cts +10 -14
  89. package/dist/primitives.d.ts +10 -14
  90. package/dist/primitives.js +557 -208
  91. package/dist/program.cjs +5 -1
  92. package/dist/program.d.cts +5 -3
  93. package/dist/program.d.ts +5 -3
  94. package/dist/program.js +6 -1
  95. package/dist/suggestion.cjs +22 -8
  96. package/dist/suggestion.js +22 -8
  97. package/dist/usage-internals.cjs +3 -2
  98. package/dist/usage-internals.js +4 -2
  99. package/dist/usage.cjs +195 -40
  100. package/dist/usage.d.cts +92 -11
  101. package/dist/usage.d.ts +92 -11
  102. package/dist/usage.js +194 -41
  103. package/dist/validate.cjs +170 -0
  104. package/dist/validate.js +164 -0
  105. package/dist/valueparser.cjs +1278 -191
  106. package/dist/valueparser.d.cts +330 -20
  107. package/dist/valueparser.d.ts +330 -20
  108. package/dist/valueparser.js +1277 -192
  109. package/package.json +9 -9
@@ -0,0 +1,964 @@
1
+ import { message } from "../message.js";
2
+
3
+ //#region src/internal/dependency.ts
4
+ /**
5
+ * A unique symbol used to identify dependency sources at compile time.
6
+ * This marker is used to distinguish {@link DependencySource} from regular
7
+ * {@link ValueParser} instances.
8
+ * @since 0.10.0
9
+ */
10
+ const dependencySourceMarker = Symbol.for("@optique/core/dependency/dependencySourceMarker");
11
+ /**
12
+ * A unique symbol used to identify derived value parsers at compile time.
13
+ * This marker is used to distinguish {@link DerivedValueParser} from regular
14
+ * {@link ValueParser} instances.
15
+ * @since 0.10.0
16
+ */
17
+ const derivedValueParserMarker = Symbol.for("@optique/core/dependency/derivedValueParserMarker");
18
+ /**
19
+ * A unique symbol used to store the dependency ID on value parsers.
20
+ * @since 0.10.0
21
+ */
22
+ const dependencyId = Symbol.for("@optique/core/dependency/dependencyId");
23
+ /**
24
+ * A unique symbol used to store multiple dependency IDs on derived parsers
25
+ * that depend on multiple sources (created via {@link deriveFrom}).
26
+ * @since 0.10.0
27
+ */
28
+ const dependencyIds = Symbol.for("@optique/core/dependency/dependencyIds");
29
+ /**
30
+ * A unique symbol used to store the default values function on derived parsers.
31
+ * This is used during partial dependency resolution to fill in missing values.
32
+ * @since 0.10.0
33
+ */
34
+ const defaultValues = Symbol.for("@optique/core/dependency/defaultValues");
35
+ /**
36
+ * A unique symbol used to store the single default value thunk on derived
37
+ * parsers created by {@link DependencySource.derive}. Unlike
38
+ * {@link defaultValues} (which `createDeferredParseState` only falls back to
39
+ * when no parse-time snapshot is available), this symbol is only read by the
40
+ * dependency-metadata bridge so that
41
+ * single-source defaults are accessible without double evaluation.
42
+ * @internal
43
+ */
44
+ const singleDefaultValue = Symbol.for("@optique/core/dependency/singleDefaultValue");
45
+ /**
46
+ * A unique symbol used to store the snapshotted default dependency values on
47
+ * a parse result produced by a derived parser's default path.
48
+ *
49
+ * @internal
50
+ */
51
+ const defaultDependencyValueSnapshot = Symbol.for("@optique/core/dependency/defaultDependencyValueSnapshot");
52
+ /**
53
+ * A unique symbol used to access the parseWithDependency method on derived parsers.
54
+ * @since 0.10.0
55
+ */
56
+ const parseWithDependency = Symbol.for("@optique/core/dependency/parseWithDependency");
57
+ /**
58
+ * A unique symbol used to access the suggestWithDependency method on derived parsers.
59
+ * This method generates suggestions using the provided dependency values instead of defaults.
60
+ * @since 0.10.0
61
+ */
62
+ const suggestWithDependency = Symbol.for("@optique/core/dependency/suggestWithDependency");
63
+ /**
64
+ * Creates a dependency source from a {@link ValueParser}.
65
+ *
66
+ * A dependency source wraps an existing value parser and enables creating
67
+ * derived parsers that depend on the parsed value. This is useful for
68
+ * scenarios where one option's valid values depend on another option's value.
69
+ *
70
+ * @template M The execution mode of the value parser.
71
+ * @template T The type of value the parser produces.
72
+ * @param parser The value parser to wrap as a dependency source.
73
+ * @returns A {@link DependencySource} that can be used to create
74
+ * derived parsers.
75
+ * @example
76
+ * ```typescript
77
+ * import { dependency } from "@optique/core/dependency";
78
+ * import { string } from "@optique/core/valueparser";
79
+ *
80
+ * // Create a dependency source for a directory path
81
+ * const cwdParser = dependency(string({ metavar: "DIR" }));
82
+ *
83
+ * // Create a derived parser that depends on the directory
84
+ * const branchParser = cwdParser.derive({
85
+ * metavar: "BRANCH",
86
+ * mode: "sync",
87
+ * factory: (dir) => gitBranch({ dir }),
88
+ * defaultValue: () => process.cwd(),
89
+ * });
90
+ * ```
91
+ * @since 0.10.0
92
+ */
93
+ function dependency(parser) {
94
+ const id = Symbol();
95
+ const result = {
96
+ ...parser,
97
+ [dependencySourceMarker]: true,
98
+ [dependencyId]: id,
99
+ derive(options) {
100
+ if (options.mode !== "sync" && options.mode !== "async") throw new TypeError("derive() requires an explicit mode field (\"sync\" or \"async\").");
101
+ return createDerivedValueParser(id, parser, options, options.mode);
102
+ },
103
+ deriveSync(options) {
104
+ if (parser.mode === "async") return createAsyncDerivedParserFromSyncFactory(id, options);
105
+ return createSyncDerivedParser(id, options);
106
+ },
107
+ deriveAsync(options) {
108
+ return createAsyncDerivedParserFromAsyncFactory(id, options);
109
+ }
110
+ };
111
+ return result;
112
+ }
113
+ /**
114
+ * Checks if a value parser is a {@link DependencySource}.
115
+ *
116
+ * @param parser The value parser to check.
117
+ * @returns `true` if the parser is a dependency source, `false` otherwise.
118
+ * @since 0.10.0
119
+ */
120
+ function isDependencySource(parser) {
121
+ return dependencySourceMarker in parser && parser[dependencySourceMarker] === true;
122
+ }
123
+ /**
124
+ * Checks if a value parser is a {@link DerivedValueParser}.
125
+ *
126
+ * @param parser The value parser to check.
127
+ * @returns `true` if the parser is a derived value parser, `false` otherwise.
128
+ * @since 0.10.0
129
+ */
130
+ function isDerivedValueParser(parser) {
131
+ return derivedValueParserMarker in parser && parser[derivedValueParserMarker] === true;
132
+ }
133
+ /**
134
+ * Creates a derived value parser from multiple dependency sources.
135
+ *
136
+ * This function allows creating a parser whose behavior depends on
137
+ * multiple other parsers' values. This is useful for scenarios where
138
+ * an option's valid values depend on a combination of other options.
139
+ *
140
+ * @template Deps A tuple of DependencySource types.
141
+ * @template T The type of value the derived parser produces.
142
+ * @param options Configuration for the derived parser.
143
+ * @returns A {@link DerivedValueParser} that depends on the given sources.
144
+ * @example
145
+ * ```typescript
146
+ * import { dependency, deriveFrom } from "@optique/core/dependency";
147
+ * import { string, choice } from "@optique/core/valueparser";
148
+ *
149
+ * const dirParser = dependency(string({ metavar: "DIR" }));
150
+ * const modeParser = dependency(choice(["dev", "prod"]));
151
+ *
152
+ * const configParser = deriveFrom({
153
+ * metavar: "CONFIG",
154
+ * mode: "sync",
155
+ * dependencies: [dirParser, modeParser] as const,
156
+ * factory: (dir, mode) =>
157
+ * choice(mode === "dev"
158
+ * ? [`${dir}/dev.json`, `${dir}/dev.yaml`]
159
+ * : [`${dir}/prod.json`, `${dir}/prod.yaml`]),
160
+ * defaultValues: () => ["/config", "dev"],
161
+ * });
162
+ * ```
163
+ * @throws {TypeError} If the `mode` field is missing or invalid.
164
+ * @since 0.10.0
165
+ */
166
+ function deriveFrom(options) {
167
+ if (options.mode !== "sync" && options.mode !== "async") throw new TypeError("deriveFrom() requires an explicit mode field (\"sync\" or \"async\").");
168
+ const depsAsync = options.dependencies.some((dep) => dep.mode === "async");
169
+ const sourceId = options.dependencies.length > 0 ? options.dependencies[0][dependencyId] : Symbol();
170
+ const factoryReturnsAsync = options.mode === "async";
171
+ const isAsync = depsAsync || factoryReturnsAsync;
172
+ if (isAsync) {
173
+ if (factoryReturnsAsync) return createAsyncDerivedFromParserFromAsyncFactory(sourceId, options);
174
+ return createAsyncDerivedFromParserFromSyncFactory(sourceId, options);
175
+ }
176
+ return createSyncDerivedFromParser(sourceId, options);
177
+ }
178
+ /**
179
+ * Creates a derived value parser from multiple dependency sources
180
+ * with a synchronous factory.
181
+ *
182
+ * This function allows creating a parser whose behavior depends on
183
+ * multiple other parsers' values. The factory explicitly returns
184
+ * a sync parser.
185
+ *
186
+ * @template Deps A tuple of DependencySource types.
187
+ * @template T The type of value the derived parser produces.
188
+ * @param options Configuration for the derived parser with sync factory.
189
+ * @returns A {@link DerivedValueParser} that depends on the given sources.
190
+ * @since 0.10.0
191
+ */
192
+ function deriveFromSync(options) {
193
+ const depsAsync = options.dependencies.some((dep) => dep.mode === "async");
194
+ const sourceId = options.dependencies.length > 0 ? options.dependencies[0][dependencyId] : Symbol();
195
+ if (depsAsync) return createAsyncDerivedFromParserFromSyncFactory(sourceId, options);
196
+ return createSyncDerivedFromParser(sourceId, options);
197
+ }
198
+ /**
199
+ * Creates a derived value parser from multiple dependency sources
200
+ * with an asynchronous factory.
201
+ *
202
+ * This function allows creating a parser whose behavior depends on
203
+ * multiple other parsers' values. The factory explicitly returns
204
+ * an async parser.
205
+ *
206
+ * @template Deps A tuple of DependencySource types.
207
+ * @template T The type of value the derived parser produces.
208
+ * @param options Configuration for the derived parser with async factory.
209
+ * @returns A {@link DerivedValueParser} that depends on the given sources.
210
+ * @since 0.10.0
211
+ */
212
+ function deriveFromAsync(options) {
213
+ const sourceId = options.dependencies.length > 0 ? options.dependencies[0][dependencyId] : Symbol();
214
+ return createAsyncDerivedFromParserFromAsyncFactory(sourceId, options);
215
+ }
216
+ function isAsyncModeParser(parser) {
217
+ return parser.mode === "async";
218
+ }
219
+ /**
220
+ * Shared helper for derived value parser `normalize()` implementations.
221
+ * Builds the inner parser from the factory and delegates to its
222
+ * `normalize()` if available, falling back to the original value on error.
223
+ */
224
+ function normalizeWithDerivedParser(value, getParser) {
225
+ let derivedParser;
226
+ try {
227
+ derivedParser = getParser();
228
+ } catch {
229
+ return value;
230
+ }
231
+ if (derivedParser && typeof derivedParser.normalize === "function") try {
232
+ return derivedParser.normalize(value);
233
+ } catch {
234
+ return value;
235
+ }
236
+ return value;
237
+ }
238
+ /**
239
+ * Attaches a default dependency snapshot to a derived parser's parse result.
240
+ *
241
+ * @param result The parse result to annotate.
242
+ * @param values The dependency values used for the default-path parse.
243
+ * @returns A cloned parse result with an internal snapshot attached.
244
+ * @internal
245
+ */
246
+ function snapshotDefaultDependencyValues(result, values) {
247
+ const snapshot = getSnapshottedDefaultDependencyValues(result) ?? values;
248
+ return attachDefaultDependencySnapshot(result, snapshot);
249
+ }
250
+ function attachDefaultDependencySnapshot(result, values) {
251
+ const annotated = Object.create(Object.getPrototypeOf(result), Object.getOwnPropertyDescriptors(result));
252
+ Object.defineProperty(annotated, defaultDependencyValueSnapshot, {
253
+ value: [...values],
254
+ configurable: true,
255
+ enumerable: false
256
+ });
257
+ return annotated;
258
+ }
259
+ /**
260
+ * Reads the snapshotted default dependency values from a parse result.
261
+ *
262
+ * @param result The parse result to inspect.
263
+ * @returns The snapshotted dependency values, if present.
264
+ * @internal
265
+ */
266
+ function getSnapshottedDefaultDependencyValues(result) {
267
+ return result[defaultDependencyValueSnapshot];
268
+ }
269
+ async function parseDerivedResultAsync(parser, input) {
270
+ return await parser.parse(input);
271
+ }
272
+ function parseDerivedResultSync(parser, input) {
273
+ const result = parser.parse(input);
274
+ if (isPromiseLike(result)) throw new TypeError("Sync derived parser parse() returned a promise-like result. Use an async derived parser instead.");
275
+ return result;
276
+ }
277
+ function isPromiseLike(value) {
278
+ return value != null && (typeof value === "object" || typeof value === "function") && "then" in value && typeof value.then === "function";
279
+ }
280
+ async function parseDerivedResultWithSnapshotAsync(parser, input, sourceValues) {
281
+ const snapshot = [...sourceValues];
282
+ return attachDefaultDependencySnapshot(await parseDerivedResultAsync(parser, input), snapshot);
283
+ }
284
+ function createSyncDerivedFromParser(sourceId, options) {
285
+ const alldependencyIds = options.dependencies.map((dep) => dep[dependencyId]);
286
+ return {
287
+ mode: "sync",
288
+ metavar: options.metavar,
289
+ get placeholder() {
290
+ try {
291
+ return options.factory(...options.defaultValues()).placeholder;
292
+ } catch {
293
+ return void 0;
294
+ }
295
+ },
296
+ [derivedValueParserMarker]: true,
297
+ [dependencyId]: sourceId,
298
+ [dependencyIds]: alldependencyIds,
299
+ [defaultValues]: options.defaultValues,
300
+ parse(input) {
301
+ let derivedParser;
302
+ let sourceValues;
303
+ try {
304
+ sourceValues = options.defaultValues();
305
+ derivedParser = options.factory(...sourceValues);
306
+ } catch (e) {
307
+ const msg = e instanceof Error ? e.message : String(e);
308
+ const failure = {
309
+ success: false,
310
+ error: message`Derived parser error: ${msg}`
311
+ };
312
+ return sourceValues == null ? failure : snapshotDefaultDependencyValues(failure, sourceValues);
313
+ }
314
+ if (isAsyncModeParser(derivedParser)) {
315
+ const failure = {
316
+ success: false,
317
+ error: message`Factory returned an async parser where a sync parser is required.`
318
+ };
319
+ return sourceValues == null ? failure : snapshotDefaultDependencyValues(failure, sourceValues);
320
+ }
321
+ const snapshot = [...sourceValues];
322
+ return attachDefaultDependencySnapshot(parseDerivedResultSync(derivedParser, input), snapshot);
323
+ },
324
+ [parseWithDependency](input, dependencyValue) {
325
+ let derivedParser;
326
+ try {
327
+ derivedParser = options.factory(...dependencyValue);
328
+ } catch (e) {
329
+ const msg = e instanceof Error ? e.message : String(e);
330
+ return {
331
+ success: false,
332
+ error: message`Factory error: ${msg}`
333
+ };
334
+ }
335
+ if (isAsyncModeParser(derivedParser)) {
336
+ const failure = {
337
+ success: false,
338
+ error: message`Factory returned an async parser where a sync parser is required.`
339
+ };
340
+ return failure;
341
+ }
342
+ return parseDerivedResultSync(derivedParser, input);
343
+ },
344
+ format(value) {
345
+ let derivedParser;
346
+ try {
347
+ const sourceValues = options.defaultValues();
348
+ derivedParser = options.factory(...sourceValues);
349
+ } catch {
350
+ return String(value);
351
+ }
352
+ return derivedParser.format(value);
353
+ },
354
+ *suggest(prefix) {
355
+ let derivedParser;
356
+ try {
357
+ const sourceValues = options.defaultValues();
358
+ derivedParser = options.factory(...sourceValues);
359
+ } catch {
360
+ return;
361
+ }
362
+ if (isAsyncModeParser(derivedParser) || !derivedParser.suggest) return;
363
+ yield* derivedParser.suggest(prefix);
364
+ },
365
+ normalize(value) {
366
+ return normalizeWithDerivedParser(value, () => options.factory(...options.defaultValues()));
367
+ },
368
+ *[suggestWithDependency](prefix, dependencyValue) {
369
+ let derivedParser;
370
+ try {
371
+ derivedParser = options.factory(...dependencyValue);
372
+ } catch {
373
+ try {
374
+ const sourceValues = options.defaultValues();
375
+ derivedParser = options.factory(...sourceValues);
376
+ } catch {
377
+ return;
378
+ }
379
+ }
380
+ if (isAsyncModeParser(derivedParser) || !derivedParser.suggest) return;
381
+ yield* derivedParser.suggest(prefix);
382
+ }
383
+ };
384
+ }
385
+ /**
386
+ * Creates an async derived parser from multiple dependencies when the
387
+ * factory returns an async parser.
388
+ */
389
+ function createAsyncDerivedFromParserFromAsyncFactory(sourceId, options) {
390
+ const alldependencyIds = options.dependencies.map((dep) => dep[dependencyId]);
391
+ return {
392
+ mode: "async",
393
+ metavar: options.metavar,
394
+ get placeholder() {
395
+ try {
396
+ return options.factory(...options.defaultValues()).placeholder;
397
+ } catch {
398
+ return void 0;
399
+ }
400
+ },
401
+ [derivedValueParserMarker]: true,
402
+ [dependencyId]: sourceId,
403
+ [dependencyIds]: alldependencyIds,
404
+ [defaultValues]: options.defaultValues,
405
+ async parse(input) {
406
+ let derivedParser;
407
+ let sourceValues;
408
+ try {
409
+ sourceValues = options.defaultValues();
410
+ derivedParser = options.factory(...sourceValues);
411
+ } catch (e) {
412
+ const msg = e instanceof Error ? e.message : String(e);
413
+ const failure = {
414
+ success: false,
415
+ error: message`Derived parser error: ${msg}`
416
+ };
417
+ return sourceValues == null ? failure : snapshotDefaultDependencyValues(failure, sourceValues);
418
+ }
419
+ return await parseDerivedResultWithSnapshotAsync(derivedParser, input, sourceValues);
420
+ },
421
+ async [parseWithDependency](input, dependencyValue) {
422
+ let derivedParser;
423
+ try {
424
+ derivedParser = options.factory(...dependencyValue);
425
+ } catch (e) {
426
+ const msg = e instanceof Error ? e.message : String(e);
427
+ return {
428
+ success: false,
429
+ error: message`Factory error: ${msg}`
430
+ };
431
+ }
432
+ return await parseDerivedResultAsync(derivedParser, input);
433
+ },
434
+ format(value) {
435
+ let derivedParser;
436
+ try {
437
+ const sourceValues = options.defaultValues();
438
+ derivedParser = options.factory(...sourceValues);
439
+ } catch {
440
+ return String(value);
441
+ }
442
+ return derivedParser.format(value);
443
+ },
444
+ normalize(value) {
445
+ return normalizeWithDerivedParser(value, () => options.factory(...options.defaultValues()));
446
+ },
447
+ async *suggest(prefix) {
448
+ let derivedParser;
449
+ try {
450
+ const sourceValues = options.defaultValues();
451
+ derivedParser = options.factory(...sourceValues);
452
+ } catch {
453
+ return;
454
+ }
455
+ if (derivedParser.suggest) for await (const suggestion of derivedParser.suggest(prefix)) yield suggestion;
456
+ },
457
+ async *[suggestWithDependency](prefix, dependencyValue) {
458
+ let derivedParser;
459
+ try {
460
+ derivedParser = options.factory(...dependencyValue);
461
+ } catch {
462
+ try {
463
+ const sourceValues = options.defaultValues();
464
+ derivedParser = options.factory(...sourceValues);
465
+ } catch {
466
+ return;
467
+ }
468
+ }
469
+ if (derivedParser.suggest) for await (const suggestion of derivedParser.suggest(prefix)) yield suggestion;
470
+ }
471
+ };
472
+ }
473
+ /**
474
+ * Creates an async derived parser from multiple dependencies when the
475
+ * sources are async but the factory returns a sync parser.
476
+ */
477
+ function createAsyncDerivedFromParserFromSyncFactory(sourceId, options) {
478
+ const alldependencyIds = options.dependencies.map((dep) => dep[dependencyId]);
479
+ return {
480
+ mode: "async",
481
+ metavar: options.metavar,
482
+ get placeholder() {
483
+ try {
484
+ return options.factory(...options.defaultValues()).placeholder;
485
+ } catch {
486
+ return void 0;
487
+ }
488
+ },
489
+ [derivedValueParserMarker]: true,
490
+ [dependencyId]: sourceId,
491
+ [dependencyIds]: alldependencyIds,
492
+ [defaultValues]: options.defaultValues,
493
+ async parse(input) {
494
+ let derivedParser;
495
+ let sourceValues;
496
+ try {
497
+ sourceValues = options.defaultValues();
498
+ derivedParser = options.factory(...sourceValues);
499
+ } catch (e) {
500
+ const msg = e instanceof Error ? e.message : String(e);
501
+ const failure = {
502
+ success: false,
503
+ error: message`Derived parser error: ${msg}`
504
+ };
505
+ return sourceValues == null ? failure : snapshotDefaultDependencyValues(failure, sourceValues);
506
+ }
507
+ return await parseDerivedResultWithSnapshotAsync(derivedParser, input, sourceValues);
508
+ },
509
+ async [parseWithDependency](input, dependencyValue) {
510
+ let derivedParser;
511
+ try {
512
+ derivedParser = options.factory(...dependencyValue);
513
+ } catch (e) {
514
+ const msg = e instanceof Error ? e.message : String(e);
515
+ return {
516
+ success: false,
517
+ error: message`Factory error: ${msg}`
518
+ };
519
+ }
520
+ return await parseDerivedResultAsync(derivedParser, input);
521
+ },
522
+ format(value) {
523
+ let derivedParser;
524
+ try {
525
+ const sourceValues = options.defaultValues();
526
+ derivedParser = options.factory(...sourceValues);
527
+ } catch {
528
+ return String(value);
529
+ }
530
+ return derivedParser.format(value);
531
+ },
532
+ normalize(value) {
533
+ return normalizeWithDerivedParser(value, () => options.factory(...options.defaultValues()));
534
+ },
535
+ async *suggest(prefix) {
536
+ let derivedParser;
537
+ try {
538
+ const sourceValues = options.defaultValues();
539
+ derivedParser = options.factory(...sourceValues);
540
+ } catch {
541
+ return;
542
+ }
543
+ if (derivedParser.suggest) yield* derivedParser.suggest(prefix);
544
+ },
545
+ *[suggestWithDependency](prefix, dependencyValue) {
546
+ let derivedParser;
547
+ try {
548
+ derivedParser = options.factory(...dependencyValue);
549
+ } catch {
550
+ try {
551
+ const sourceValues = options.defaultValues();
552
+ derivedParser = options.factory(...sourceValues);
553
+ } catch {
554
+ return;
555
+ }
556
+ }
557
+ if (derivedParser.suggest) yield* derivedParser.suggest(prefix);
558
+ }
559
+ };
560
+ }
561
+ function createDerivedValueParser(sourceId, sourceParser, options, factoryMode) {
562
+ const factoryReturnsAsync = factoryMode === "async";
563
+ const isAsync = sourceParser.mode === "async" || factoryReturnsAsync;
564
+ if (isAsync) {
565
+ if (factoryReturnsAsync) return createAsyncDerivedParserFromAsyncFactory(sourceId, options);
566
+ return createAsyncDerivedParserFromSyncFactory(sourceId, options);
567
+ }
568
+ return createSyncDerivedParser(sourceId, options);
569
+ }
570
+ function createSyncDerivedParser(sourceId, options) {
571
+ return {
572
+ mode: "sync",
573
+ metavar: options.metavar,
574
+ get placeholder() {
575
+ try {
576
+ return options.factory(options.defaultValue()).placeholder;
577
+ } catch {
578
+ return void 0;
579
+ }
580
+ },
581
+ [derivedValueParserMarker]: true,
582
+ [dependencyId]: sourceId,
583
+ [singleDefaultValue]: options.defaultValue,
584
+ parse(input) {
585
+ let derivedParser;
586
+ let hasSourceValue = false;
587
+ let sourceValue;
588
+ try {
589
+ sourceValue = options.defaultValue();
590
+ hasSourceValue = true;
591
+ derivedParser = options.factory(sourceValue);
592
+ } catch (e) {
593
+ const msg = e instanceof Error ? e.message : String(e);
594
+ const failure = {
595
+ success: false,
596
+ error: message`Derived parser error: ${msg}`
597
+ };
598
+ return hasSourceValue ? snapshotDefaultDependencyValues(failure, [sourceValue]) : failure;
599
+ }
600
+ if (isAsyncModeParser(derivedParser)) {
601
+ const failure = {
602
+ success: false,
603
+ error: message`Factory returned an async parser where a sync parser is required.`
604
+ };
605
+ return hasSourceValue ? snapshotDefaultDependencyValues(failure, [sourceValue]) : failure;
606
+ }
607
+ return attachDefaultDependencySnapshot(parseDerivedResultSync(derivedParser, input), [sourceValue]);
608
+ },
609
+ [parseWithDependency](input, dependencyValue) {
610
+ let derivedParser;
611
+ try {
612
+ derivedParser = options.factory(dependencyValue);
613
+ } catch (e) {
614
+ const msg = e instanceof Error ? e.message : String(e);
615
+ return {
616
+ success: false,
617
+ error: message`Factory error: ${msg}`
618
+ };
619
+ }
620
+ if (isAsyncModeParser(derivedParser)) return {
621
+ success: false,
622
+ error: message`Factory returned an async parser where a sync parser is required.`
623
+ };
624
+ return parseDerivedResultSync(derivedParser, input);
625
+ },
626
+ format(value) {
627
+ let derivedParser;
628
+ try {
629
+ const sourceValue = options.defaultValue();
630
+ derivedParser = options.factory(sourceValue);
631
+ } catch {
632
+ return String(value);
633
+ }
634
+ return derivedParser.format(value);
635
+ },
636
+ normalize(value) {
637
+ return normalizeWithDerivedParser(value, () => options.factory(options.defaultValue()));
638
+ },
639
+ *suggest(prefix) {
640
+ let derivedParser;
641
+ try {
642
+ const sourceValue = options.defaultValue();
643
+ derivedParser = options.factory(sourceValue);
644
+ } catch {
645
+ return;
646
+ }
647
+ if (isAsyncModeParser(derivedParser) || !derivedParser.suggest) return;
648
+ yield* derivedParser.suggest(prefix);
649
+ },
650
+ *[suggestWithDependency](prefix, dependencyValue) {
651
+ let derivedParser;
652
+ try {
653
+ derivedParser = options.factory(dependencyValue);
654
+ } catch {
655
+ try {
656
+ derivedParser = options.factory(options.defaultValue());
657
+ } catch {
658
+ return;
659
+ }
660
+ }
661
+ if (isAsyncModeParser(derivedParser) || !derivedParser.suggest) return;
662
+ yield* derivedParser.suggest(prefix);
663
+ }
664
+ };
665
+ }
666
+ /**
667
+ * Creates an async derived parser when the factory returns an async parser.
668
+ * The parse result is awaited since the factory returns an async parser.
669
+ */
670
+ function createAsyncDerivedParserFromAsyncFactory(sourceId, options) {
671
+ return {
672
+ mode: "async",
673
+ metavar: options.metavar,
674
+ get placeholder() {
675
+ try {
676
+ return options.factory(options.defaultValue()).placeholder;
677
+ } catch {
678
+ return void 0;
679
+ }
680
+ },
681
+ [derivedValueParserMarker]: true,
682
+ [dependencyId]: sourceId,
683
+ [singleDefaultValue]: options.defaultValue,
684
+ async parse(input) {
685
+ let derivedParser;
686
+ let hasSourceValue = false;
687
+ let sourceValue;
688
+ try {
689
+ sourceValue = options.defaultValue();
690
+ hasSourceValue = true;
691
+ derivedParser = options.factory(sourceValue);
692
+ } catch (e) {
693
+ const msg = e instanceof Error ? e.message : String(e);
694
+ const failure = {
695
+ success: false,
696
+ error: message`Derived parser error: ${msg}`
697
+ };
698
+ return hasSourceValue ? snapshotDefaultDependencyValues(failure, [sourceValue]) : failure;
699
+ }
700
+ return await parseDerivedResultWithSnapshotAsync(derivedParser, input, [sourceValue]);
701
+ },
702
+ async [parseWithDependency](input, dependencyValue) {
703
+ let derivedParser;
704
+ try {
705
+ derivedParser = options.factory(dependencyValue);
706
+ } catch (e) {
707
+ const msg = e instanceof Error ? e.message : String(e);
708
+ return {
709
+ success: false,
710
+ error: message`Factory error: ${msg}`
711
+ };
712
+ }
713
+ return await parseDerivedResultAsync(derivedParser, input);
714
+ },
715
+ format(value) {
716
+ let derivedParser;
717
+ try {
718
+ const sourceValue = options.defaultValue();
719
+ derivedParser = options.factory(sourceValue);
720
+ } catch {
721
+ return String(value);
722
+ }
723
+ return derivedParser.format(value);
724
+ },
725
+ normalize(value) {
726
+ return normalizeWithDerivedParser(value, () => options.factory(options.defaultValue()));
727
+ },
728
+ async *suggest(prefix) {
729
+ let derivedParser;
730
+ try {
731
+ const sourceValue = options.defaultValue();
732
+ derivedParser = options.factory(sourceValue);
733
+ } catch {
734
+ return;
735
+ }
736
+ if (derivedParser.suggest) for await (const suggestion of derivedParser.suggest(prefix)) yield suggestion;
737
+ },
738
+ async *[suggestWithDependency](prefix, dependencyValue) {
739
+ let derivedParser;
740
+ try {
741
+ derivedParser = options.factory(dependencyValue);
742
+ } catch {
743
+ try {
744
+ derivedParser = options.factory(options.defaultValue());
745
+ } catch {
746
+ return;
747
+ }
748
+ }
749
+ if (derivedParser.suggest) for await (const suggestion of derivedParser.suggest(prefix)) yield suggestion;
750
+ }
751
+ };
752
+ }
753
+ /**
754
+ * Creates an async derived parser when the source is async but the factory
755
+ * returns a sync parser. The sync result is wrapped in a Promise.
756
+ */
757
+ function createAsyncDerivedParserFromSyncFactory(sourceId, options) {
758
+ return {
759
+ mode: "async",
760
+ metavar: options.metavar,
761
+ get placeholder() {
762
+ try {
763
+ return options.factory(options.defaultValue()).placeholder;
764
+ } catch {
765
+ return void 0;
766
+ }
767
+ },
768
+ [derivedValueParserMarker]: true,
769
+ [dependencyId]: sourceId,
770
+ [singleDefaultValue]: options.defaultValue,
771
+ async parse(input) {
772
+ let derivedParser;
773
+ let hasSourceValue = false;
774
+ let sourceValue;
775
+ try {
776
+ sourceValue = options.defaultValue();
777
+ hasSourceValue = true;
778
+ derivedParser = options.factory(sourceValue);
779
+ } catch (e) {
780
+ const msg = e instanceof Error ? e.message : String(e);
781
+ const failure = {
782
+ success: false,
783
+ error: message`Derived parser error: ${msg}`
784
+ };
785
+ return hasSourceValue ? snapshotDefaultDependencyValues(failure, [sourceValue]) : failure;
786
+ }
787
+ return await parseDerivedResultWithSnapshotAsync(derivedParser, input, [sourceValue]);
788
+ },
789
+ async [parseWithDependency](input, dependencyValue) {
790
+ let derivedParser;
791
+ try {
792
+ derivedParser = options.factory(dependencyValue);
793
+ } catch (e) {
794
+ const msg = e instanceof Error ? e.message : String(e);
795
+ return {
796
+ success: false,
797
+ error: message`Factory error: ${msg}`
798
+ };
799
+ }
800
+ return await parseDerivedResultAsync(derivedParser, input);
801
+ },
802
+ format(value) {
803
+ let derivedParser;
804
+ try {
805
+ const sourceValue = options.defaultValue();
806
+ derivedParser = options.factory(sourceValue);
807
+ } catch {
808
+ return String(value);
809
+ }
810
+ return derivedParser.format(value);
811
+ },
812
+ normalize(value) {
813
+ return normalizeWithDerivedParser(value, () => options.factory(options.defaultValue()));
814
+ },
815
+ async *suggest(prefix) {
816
+ let derivedParser;
817
+ try {
818
+ const sourceValue = options.defaultValue();
819
+ derivedParser = options.factory(sourceValue);
820
+ } catch {
821
+ return;
822
+ }
823
+ if (derivedParser.suggest) yield* derivedParser.suggest(prefix);
824
+ },
825
+ *[suggestWithDependency](prefix, dependencyValue) {
826
+ let derivedParser;
827
+ try {
828
+ derivedParser = options.factory(dependencyValue);
829
+ } catch {
830
+ try {
831
+ derivedParser = options.factory(options.defaultValue());
832
+ } catch {
833
+ return;
834
+ }
835
+ }
836
+ if (derivedParser.suggest) yield* derivedParser.suggest(prefix);
837
+ }
838
+ };
839
+ }
840
+ /**
841
+ * A unique symbol used to identify deferred parse states.
842
+ * @since 0.10.0
843
+ */
844
+ const deferredParseMarker = Symbol.for("@optique/core/dependency/deferredParseMarker");
845
+ /**
846
+ * Checks if a value is a {@link DeferredParseState}.
847
+ *
848
+ * @param value The value to check.
849
+ * @returns `true` if the value is a deferred parse state, `false` otherwise.
850
+ * @since 0.10.0
851
+ */
852
+ function isDeferredParseState(value) {
853
+ return typeof value === "object" && value !== null && deferredParseMarker in value && value[deferredParseMarker] === true;
854
+ }
855
+ /**
856
+ * Gets all dependency IDs from a derived parser.
857
+ * If the parser was created with `deriveFrom` (multiple dependencies),
858
+ * returns the array of dependency IDs. Otherwise, returns an array
859
+ * containing the single dependency ID.
860
+ *
861
+ * @param parser The derived value parser to get dependency IDs from.
862
+ * @returns An array of dependency ID symbols.
863
+ * @internal
864
+ * @since 0.10.0
865
+ */
866
+ function getDependencyIds(parser) {
867
+ if (dependencyIds in parser) return parser[dependencyIds];
868
+ return [parser[dependencyId]];
869
+ }
870
+ /**
871
+ * Gets the default values function from a multi-source derived parser, if
872
+ * present.
873
+ *
874
+ * Single-source `derive()` defaults must stay lazy during suggestion-time
875
+ * replay so missing dependencies do not eagerly evaluate side-effectful
876
+ * `defaultValue()` thunks.
877
+ *
878
+ * @param parser The derived value parser to get the default values function from.
879
+ * @returns The default values function, or undefined if not available.
880
+ * @internal
881
+ * @since 0.10.0
882
+ */
883
+ function getDefaultValuesFunction(parser) {
884
+ if (Object.hasOwn(parser, defaultValues)) return parser[defaultValues];
885
+ return void 0;
886
+ }
887
+ /**
888
+ * A unique symbol used to identify dependency source parse states.
889
+ * @since 0.10.0
890
+ */
891
+ const dependencySourceStateMarker = Symbol.for("@optique/core/dependency/dependencySourceStateMarker");
892
+ /**
893
+ * Checks if a value is a {@link DependencySourceState}.
894
+ *
895
+ * @param value The value to check.
896
+ * @returns `true` if the value is a dependency source state, `false` otherwise.
897
+ * @since 0.10.0
898
+ */
899
+ function isDependencySourceState(value) {
900
+ return typeof value === "object" && value !== null && dependencySourceStateMarker in value && value[dependencySourceStateMarker] === true;
901
+ }
902
+ /**
903
+ * Creates a dependency source state from a parse result.
904
+ *
905
+ * @template T The type of value the state contains.
906
+ * @param result The parse result.
907
+ * @param depId The dependency ID.
908
+ * @returns A DependencySourceState object.
909
+ * @since 0.10.0
910
+ */
911
+ function createDependencySourceState(result, depId) {
912
+ return {
913
+ [dependencySourceStateMarker]: true,
914
+ [dependencyId]: depId,
915
+ result
916
+ };
917
+ }
918
+ /**
919
+ * A unique symbol used to identify pending dependency source states.
920
+ * @since 0.10.0
921
+ */
922
+ const pendingDependencySourceStateMarker = Symbol.for("@optique/core/dependency/pendingDependencySourceStateMarker");
923
+ /**
924
+ * Checks if a value is a {@link PendingDependencySourceState}.
925
+ *
926
+ * @param value The value to check.
927
+ * @returns `true` if the value is a pending dependency source state.
928
+ * @since 0.10.0
929
+ */
930
+ function isPendingDependencySourceState(value) {
931
+ return typeof value === "object" && value !== null && pendingDependencySourceStateMarker in value && value[pendingDependencySourceStateMarker] === true;
932
+ }
933
+ /**
934
+ * A unique symbol used to identify parsers that wrap a dependency source.
935
+ * This is used by withDefault to indicate it contains an inner parser
936
+ * with a PendingDependencySourceState initialState.
937
+ * @since 0.10.0
938
+ */
939
+ const wrappedDependencySourceMarker = Symbol.for("@optique/core/dependency/wrappedDependencySourceMarker");
940
+ /**
941
+ * A unique symbol used to indicate that a wrapper transforms the dependency
942
+ * source value. This is used by withDefault to determine whether its default
943
+ * value should be registered as the dependency value.
944
+ *
945
+ * When a wrapper has this marker set to `true`, it means the wrapper transforms
946
+ * the dependency source value (e.g., via map()), so the wrapper's output is NOT
947
+ * a valid dependency source value.
948
+ *
949
+ * @since 0.10.0
950
+ */
951
+ const transformsDependencyValueMarker = Symbol.for("@optique/core/dependency/transformsDependencyValueMarker");
952
+ /**
953
+ * Checks if a parser wraps a dependency source (has wrappedDependencySourceMarker).
954
+ *
955
+ * @param parser The parser to check.
956
+ * @returns `true` if the parser wraps a dependency source.
957
+ * @since 0.10.0
958
+ */
959
+ function isWrappedDependencySource(parser) {
960
+ return typeof parser === "object" && parser !== null && wrappedDependencySourceMarker in parser;
961
+ }
962
+
963
+ //#endregion
964
+ export { createDependencySourceState, defaultValues, dependency, dependencyId, dependencyIds, deriveFrom, deriveFromAsync, deriveFromSync, getDefaultValuesFunction, getDependencyIds, getSnapshottedDefaultDependencyValues, isDeferredParseState, isDependencySource, isDependencySourceState, isDerivedValueParser, isPendingDependencySourceState, isWrappedDependencySource, parseWithDependency, singleDefaultValue, suggestWithDependency, wrappedDependencySourceMarker };