@optique/core 1.3.0-dev.2398 → 1.3.0-dev.2401

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.
@@ -13,6 +13,16 @@ import { Mode, Suggestion } from "./parser.cjs";
13
13
  * @since 0.10.0
14
14
  */
15
15
  declare const dependencySourceMarker: unique symbol;
16
+ /**
17
+ * A unique symbol used to store a dependency source's own identity.
18
+ *
19
+ * This is distinct from {@link dependencyId}, which stores an upstream
20
+ * reference on a derived parser. A parser wrapped with `dependency()` after
21
+ * derivation carries both values.
22
+ * @internal
23
+ * @since 1.3.0
24
+ */
25
+ declare const dependencySourceId: unique symbol;
16
26
  /**
17
27
  * A unique symbol used to identify derived value parsers at compile time.
18
28
  * This marker is used to distinguish {@link DerivedValueParser} from regular
@@ -176,7 +186,7 @@ interface DependencySource<M extends Mode = "sync", T = unknown> extends ValuePa
176
186
  * Unique identifier for this dependency source.
177
187
  * @internal
178
188
  */
179
- readonly [dependencyId]: symbol;
189
+ readonly [dependencySourceId]: symbol;
180
190
  /**
181
191
  * Creates a derived value parser whose behavior depends on this
182
192
  * dependency source's value.
@@ -255,7 +265,7 @@ type CombinedDependencyMode<T extends readonly unknown[]> = "async" extends { [K
255
265
  */
256
266
  interface AnyDependencySource<M extends Mode = Mode> {
257
267
  readonly [dependencySourceMarker]: true;
258
- readonly [dependencyId]: symbol;
268
+ readonly [dependencySourceId]: symbol;
259
269
  readonly mode: M;
260
270
  }
261
271
  /**
@@ -355,9 +365,6 @@ interface DeriveFromAsyncOptions<Deps extends readonly AnyDependencySource[], T>
355
365
  /**
356
366
  * A value parser that depends on another parser's value.
357
367
  *
358
- * A derived value parser cannot be nested (i.e., you cannot call
359
- * {@link DependencySource.derive} on a {@link DerivedValueParser}).
360
- *
361
368
  * @template M The execution mode of the parser (`"sync"` or `"async"`).
362
369
  * @template T The type of value this parser produces.
363
370
  * @template S The type of the source dependency value.
@@ -424,6 +431,8 @@ interface DerivedValueParser<M extends Mode = "sync", T = unknown, S = unknown>
424
431
  * A dependency source wraps an existing value parser and enables creating
425
432
  * derived parsers that depend on the parsed value. This is useful for
426
433
  * scenarios where one option's valid values depend on another option's value.
434
+ * A derived parser can itself become a source by wrapping it with
435
+ * `dependency()`, allowing dependency chains of any depth.
427
436
  *
428
437
  * @template M The execution mode of the value parser.
429
438
  * @template T The type of value the parser produces.
@@ -445,6 +454,14 @@ interface DerivedValueParser<M extends Mode = "sync", T = unknown, S = unknown>
445
454
  * factory: (dir) => gitBranch({ dir }),
446
455
  * defaultValue: () => process.cwd(),
447
456
  * });
457
+ *
458
+ * // A derived parser can provide the next dependency level.
459
+ * const branchSource = dependency(branchParser);
460
+ * const commitParser = branchSource.deriveSync({
461
+ * metavar: "COMMIT",
462
+ * factory: (branch) => gitCommit({ branch }),
463
+ * defaultValue: () => "main",
464
+ * });
448
465
  * ```
449
466
  * @since 0.10.0
450
467
  */
@@ -845,4 +862,4 @@ type DependencyError = {
845
862
  */
846
863
  declare function formatDependencyError(error: DependencyError): Message;
847
864
  //#endregion
848
- export { AnyDependencySource, CombineMode, CombinedDependencyMode, DeferredParseState, DependencyError, DependencyMode, DependencyRegistry, DependencySource, DependencySourceState, DependencyValue, DependencyValues, DeriveAsyncOptions, DeriveFromAsyncOptions, DeriveFromOptions, DeriveFromSyncOptions, DeriveOptions, DeriveSyncOptions, DerivedValueParser, PendingDependencySourceState, ResolvedDependency, createDeferredParseState, createDependencySourceState, createPendingDependencySourceState, defaultDependencyValueSnapshot, defaultValues, deferredParseMarker, dependency, dependencyId, dependencyIds, dependencySourceMarker, dependencySourceStateMarker, deriveFrom, deriveFromAsync, deriveFromSync, derivedValueParserMarker, formatDependencyError, getDefaultValuesFunction, getDependencyIds, getSnapshottedDefaultDependencyValues, isDeferredParseState, isDependencySource, isDependencySourceState, isDerivedValueParser, isPendingDependencySourceState, isWrappedDependencySource, parseWithDependency, pendingDependencySourceStateMarker, singleDefaultValue, snapshotDefaultDependencyValues, suggestWithDependency, transformsDependencyValue, transformsDependencyValueMarker, wrappedDependencySourceMarker };
865
+ export { AnyDependencySource, CombineMode, CombinedDependencyMode, DeferredParseState, DependencyError, DependencyMode, DependencyRegistry, DependencySource, DependencySourceState, DependencyValue, DependencyValues, DeriveAsyncOptions, DeriveFromAsyncOptions, DeriveFromOptions, DeriveFromSyncOptions, DeriveOptions, DeriveSyncOptions, DerivedValueParser, PendingDependencySourceState, ResolvedDependency, createDeferredParseState, createDependencySourceState, createPendingDependencySourceState, defaultDependencyValueSnapshot, defaultValues, deferredParseMarker, dependency, dependencyId, dependencyIds, dependencySourceId, dependencySourceMarker, dependencySourceStateMarker, deriveFrom, deriveFromAsync, deriveFromSync, derivedValueParserMarker, formatDependencyError, getDefaultValuesFunction, getDependencyIds, getSnapshottedDefaultDependencyValues, isDeferredParseState, isDependencySource, isDependencySourceState, isDerivedValueParser, isPendingDependencySourceState, isWrappedDependencySource, parseWithDependency, pendingDependencySourceStateMarker, singleDefaultValue, snapshotDefaultDependencyValues, suggestWithDependency, transformsDependencyValue, transformsDependencyValueMarker, wrappedDependencySourceMarker };
@@ -13,6 +13,16 @@ import { Mode, Suggestion } from "./parser.js";
13
13
  * @since 0.10.0
14
14
  */
15
15
  declare const dependencySourceMarker: unique symbol;
16
+ /**
17
+ * A unique symbol used to store a dependency source's own identity.
18
+ *
19
+ * This is distinct from {@link dependencyId}, which stores an upstream
20
+ * reference on a derived parser. A parser wrapped with `dependency()` after
21
+ * derivation carries both values.
22
+ * @internal
23
+ * @since 1.3.0
24
+ */
25
+ declare const dependencySourceId: unique symbol;
16
26
  /**
17
27
  * A unique symbol used to identify derived value parsers at compile time.
18
28
  * This marker is used to distinguish {@link DerivedValueParser} from regular
@@ -176,7 +186,7 @@ interface DependencySource<M extends Mode = "sync", T = unknown> extends ValuePa
176
186
  * Unique identifier for this dependency source.
177
187
  * @internal
178
188
  */
179
- readonly [dependencyId]: symbol;
189
+ readonly [dependencySourceId]: symbol;
180
190
  /**
181
191
  * Creates a derived value parser whose behavior depends on this
182
192
  * dependency source's value.
@@ -255,7 +265,7 @@ type CombinedDependencyMode<T extends readonly unknown[]> = "async" extends { [K
255
265
  */
256
266
  interface AnyDependencySource<M extends Mode = Mode> {
257
267
  readonly [dependencySourceMarker]: true;
258
- readonly [dependencyId]: symbol;
268
+ readonly [dependencySourceId]: symbol;
259
269
  readonly mode: M;
260
270
  }
261
271
  /**
@@ -355,9 +365,6 @@ interface DeriveFromAsyncOptions<Deps extends readonly AnyDependencySource[], T>
355
365
  /**
356
366
  * A value parser that depends on another parser's value.
357
367
  *
358
- * A derived value parser cannot be nested (i.e., you cannot call
359
- * {@link DependencySource.derive} on a {@link DerivedValueParser}).
360
- *
361
368
  * @template M The execution mode of the parser (`"sync"` or `"async"`).
362
369
  * @template T The type of value this parser produces.
363
370
  * @template S The type of the source dependency value.
@@ -424,6 +431,8 @@ interface DerivedValueParser<M extends Mode = "sync", T = unknown, S = unknown>
424
431
  * A dependency source wraps an existing value parser and enables creating
425
432
  * derived parsers that depend on the parsed value. This is useful for
426
433
  * scenarios where one option's valid values depend on another option's value.
434
+ * A derived parser can itself become a source by wrapping it with
435
+ * `dependency()`, allowing dependency chains of any depth.
427
436
  *
428
437
  * @template M The execution mode of the value parser.
429
438
  * @template T The type of value the parser produces.
@@ -445,6 +454,14 @@ interface DerivedValueParser<M extends Mode = "sync", T = unknown, S = unknown>
445
454
  * factory: (dir) => gitBranch({ dir }),
446
455
  * defaultValue: () => process.cwd(),
447
456
  * });
457
+ *
458
+ * // A derived parser can provide the next dependency level.
459
+ * const branchSource = dependency(branchParser);
460
+ * const commitParser = branchSource.deriveSync({
461
+ * metavar: "COMMIT",
462
+ * factory: (branch) => gitCommit({ branch }),
463
+ * defaultValue: () => "main",
464
+ * });
448
465
  * ```
449
466
  * @since 0.10.0
450
467
  */
@@ -845,4 +862,4 @@ type DependencyError = {
845
862
  */
846
863
  declare function formatDependencyError(error: DependencyError): Message;
847
864
  //#endregion
848
- export { AnyDependencySource, CombineMode, CombinedDependencyMode, DeferredParseState, DependencyError, DependencyMode, DependencyRegistry, DependencySource, DependencySourceState, DependencyValue, DependencyValues, DeriveAsyncOptions, DeriveFromAsyncOptions, DeriveFromOptions, DeriveFromSyncOptions, DeriveOptions, DeriveSyncOptions, DerivedValueParser, PendingDependencySourceState, ResolvedDependency, createDeferredParseState, createDependencySourceState, createPendingDependencySourceState, defaultDependencyValueSnapshot, defaultValues, deferredParseMarker, dependency, dependencyId, dependencyIds, dependencySourceMarker, dependencySourceStateMarker, deriveFrom, deriveFromAsync, deriveFromSync, derivedValueParserMarker, formatDependencyError, getDefaultValuesFunction, getDependencyIds, getSnapshottedDefaultDependencyValues, isDeferredParseState, isDependencySource, isDependencySourceState, isDerivedValueParser, isPendingDependencySourceState, isWrappedDependencySource, parseWithDependency, pendingDependencySourceStateMarker, singleDefaultValue, snapshotDefaultDependencyValues, suggestWithDependency, transformsDependencyValue, transformsDependencyValueMarker, wrappedDependencySourceMarker };
865
+ export { AnyDependencySource, CombineMode, CombinedDependencyMode, DeferredParseState, DependencyError, DependencyMode, DependencyRegistry, DependencySource, DependencySourceState, DependencyValue, DependencyValues, DeriveAsyncOptions, DeriveFromAsyncOptions, DeriveFromOptions, DeriveFromSyncOptions, DeriveOptions, DeriveSyncOptions, DerivedValueParser, PendingDependencySourceState, ResolvedDependency, createDeferredParseState, createDependencySourceState, createPendingDependencySourceState, defaultDependencyValueSnapshot, defaultValues, deferredParseMarker, dependency, dependencyId, dependencyIds, dependencySourceId, dependencySourceMarker, dependencySourceStateMarker, deriveFrom, deriveFromAsync, deriveFromSync, derivedValueParserMarker, formatDependencyError, getDefaultValuesFunction, getDependencyIds, getSnapshottedDefaultDependencyValues, isDeferredParseState, isDependencySource, isDependencySourceState, isDerivedValueParser, isPendingDependencySourceState, isWrappedDependencySource, parseWithDependency, pendingDependencySourceStateMarker, singleDefaultValue, snapshotDefaultDependencyValues, suggestWithDependency, transformsDependencyValue, transformsDependencyValueMarker, wrappedDependencySourceMarker };
@@ -9,6 +9,16 @@ import { message } from "../message.js";
9
9
  */
10
10
  const dependencySourceMarker = Symbol.for("@optique/core/dependency/dependencySourceMarker");
11
11
  /**
12
+ * A unique symbol used to store a dependency source's own identity.
13
+ *
14
+ * This is distinct from {@link dependencyId}, which stores an upstream
15
+ * reference on a derived parser. A parser wrapped with `dependency()` after
16
+ * derivation carries both values.
17
+ * @internal
18
+ * @since 1.3.0
19
+ */
20
+ const dependencySourceId = Symbol.for("@optique/core/dependency/dependencySourceId");
21
+ /**
12
22
  * A unique symbol used to identify derived value parsers at compile time.
13
23
  * This marker is used to distinguish {@link DerivedValueParser} from regular
14
24
  * {@link ValueParser} instances.
@@ -66,6 +76,8 @@ const suggestWithDependency = Symbol.for("@optique/core/dependency/suggestWithDe
66
76
  * A dependency source wraps an existing value parser and enables creating
67
77
  * derived parsers that depend on the parsed value. This is useful for
68
78
  * scenarios where one option's valid values depend on another option's value.
79
+ * A derived parser can itself become a source by wrapping it with
80
+ * `dependency()`, allowing dependency chains of any depth.
69
81
  *
70
82
  * @template M The execution mode of the value parser.
71
83
  * @template T The type of value the parser produces.
@@ -87,15 +99,23 @@ const suggestWithDependency = Symbol.for("@optique/core/dependency/suggestWithDe
87
99
  * factory: (dir) => gitBranch({ dir }),
88
100
  * defaultValue: () => process.cwd(),
89
101
  * });
102
+ *
103
+ * // A derived parser can provide the next dependency level.
104
+ * const branchSource = dependency(branchParser);
105
+ * const commitParser = branchSource.deriveSync({
106
+ * metavar: "COMMIT",
107
+ * factory: (branch) => gitCommit({ branch }),
108
+ * defaultValue: () => "main",
109
+ * });
90
110
  * ```
91
111
  * @since 0.10.0
92
112
  */
93
113
  function dependency(parser) {
94
114
  const id = Symbol();
95
- const result = {
96
- ...parser,
115
+ const result = Object.create(Object.getPrototypeOf(parser), Object.getOwnPropertyDescriptors(parser));
116
+ Object.defineProperties(result, Object.getOwnPropertyDescriptors({
97
117
  [dependencySourceMarker]: true,
98
- [dependencyId]: id,
118
+ [dependencySourceId]: id,
99
119
  derive(options) {
100
120
  if (options.mode !== "sync" && options.mode !== "async") throw new TypeError("derive() requires an explicit mode field (\"sync\" or \"async\").");
101
121
  return createDerivedValueParser(id, parser, options, options.mode);
@@ -107,7 +127,7 @@ function dependency(parser) {
107
127
  deriveAsync(options) {
108
128
  return createAsyncDerivedParserFromAsyncFactory(id, options);
109
129
  }
110
- };
130
+ }));
111
131
  return result;
112
132
  }
113
133
  /**
@@ -166,7 +186,7 @@ function isDerivedValueParser(parser) {
166
186
  function deriveFrom(options) {
167
187
  if (options.mode !== "sync" && options.mode !== "async") throw new TypeError("deriveFrom() requires an explicit mode field (\"sync\" or \"async\").");
168
188
  const depsAsync = options.dependencies.some((dep) => dep.mode === "async");
169
- const sourceId = options.dependencies.length > 0 ? options.dependencies[0][dependencyId] : Symbol();
189
+ const sourceId = options.dependencies.length > 0 ? options.dependencies[0][dependencySourceId] : Symbol();
170
190
  const factoryReturnsAsync = options.mode === "async";
171
191
  const isAsync = depsAsync || factoryReturnsAsync;
172
192
  if (isAsync) {
@@ -191,7 +211,7 @@ function deriveFrom(options) {
191
211
  */
192
212
  function deriveFromSync(options) {
193
213
  const depsAsync = options.dependencies.some((dep) => dep.mode === "async");
194
- const sourceId = options.dependencies.length > 0 ? options.dependencies[0][dependencyId] : Symbol();
214
+ const sourceId = options.dependencies.length > 0 ? options.dependencies[0][dependencySourceId] : Symbol();
195
215
  if (depsAsync) return createAsyncDerivedFromParserFromSyncFactory(sourceId, options);
196
216
  return createSyncDerivedFromParser(sourceId, options);
197
217
  }
@@ -210,7 +230,7 @@ function deriveFromSync(options) {
210
230
  * @since 0.10.0
211
231
  */
212
232
  function deriveFromAsync(options) {
213
- const sourceId = options.dependencies.length > 0 ? options.dependencies[0][dependencyId] : Symbol();
233
+ const sourceId = options.dependencies.length > 0 ? options.dependencies[0][dependencySourceId] : Symbol();
214
234
  return createAsyncDerivedFromParserFromAsyncFactory(sourceId, options);
215
235
  }
216
236
  function isAsyncModeParser(parser) {
@@ -282,7 +302,7 @@ async function parseDerivedResultWithSnapshotAsync(parser, input, sourceValues)
282
302
  return attachDefaultDependencySnapshot(await parseDerivedResultAsync(parser, input), snapshot);
283
303
  }
284
304
  function createSyncDerivedFromParser(sourceId, options) {
285
- const alldependencyIds = options.dependencies.map((dep) => dep[dependencyId]);
305
+ const alldependencyIds = options.dependencies.map((dep) => dep[dependencySourceId]);
286
306
  return {
287
307
  mode: "sync",
288
308
  metavar: options.metavar,
@@ -387,7 +407,7 @@ function createSyncDerivedFromParser(sourceId, options) {
387
407
  * factory returns an async parser.
388
408
  */
389
409
  function createAsyncDerivedFromParserFromAsyncFactory(sourceId, options) {
390
- const alldependencyIds = options.dependencies.map((dep) => dep[dependencyId]);
410
+ const alldependencyIds = options.dependencies.map((dep) => dep[dependencySourceId]);
391
411
  return {
392
412
  mode: "async",
393
413
  metavar: options.metavar,
@@ -475,7 +495,7 @@ function createAsyncDerivedFromParserFromAsyncFactory(sourceId, options) {
475
495
  * sources are async but the factory returns a sync parser.
476
496
  */
477
497
  function createAsyncDerivedFromParserFromSyncFactory(sourceId, options) {
478
- const alldependencyIds = options.dependencies.map((dep) => dep[dependencyId]);
498
+ const alldependencyIds = options.dependencies.map((dep) => dep[dependencySourceId]);
479
499
  return {
480
500
  mode: "async",
481
501
  metavar: options.metavar,
@@ -1079,4 +1099,4 @@ function formatDependencyError(error) {
1079
1099
  }
1080
1100
 
1081
1101
  //#endregion
1082
- export { DependencyRegistry, createDeferredParseState, createDependencySourceState, createPendingDependencySourceState, defaultDependencyValueSnapshot, defaultValues, deferredParseMarker, dependency, dependencyId, dependencyIds, dependencySourceMarker, dependencySourceStateMarker, deriveFrom, deriveFromAsync, deriveFromSync, derivedValueParserMarker, formatDependencyError, getDefaultValuesFunction, getDependencyIds, getSnapshottedDefaultDependencyValues, isDeferredParseState, isDependencySource, isDependencySourceState, isDerivedValueParser, isPendingDependencySourceState, isWrappedDependencySource, parseWithDependency, pendingDependencySourceStateMarker, singleDefaultValue, snapshotDefaultDependencyValues, suggestWithDependency, transformsDependencyValue, transformsDependencyValueMarker, wrappedDependencySourceMarker };
1102
+ export { DependencyRegistry, createDeferredParseState, createDependencySourceState, createPendingDependencySourceState, defaultDependencyValueSnapshot, defaultValues, deferredParseMarker, dependency, dependencyId, dependencyIds, dependencySourceId, dependencySourceMarker, dependencySourceStateMarker, deriveFrom, deriveFromAsync, deriveFromSync, derivedValueParserMarker, formatDependencyError, getDefaultValuesFunction, getDependencyIds, getSnapshottedDefaultDependencyValues, isDeferredParseState, isDependencySource, isDependencySourceState, isDerivedValueParser, isPendingDependencySourceState, isWrappedDependencySource, parseWithDependency, pendingDependencySourceStateMarker, singleDefaultValue, snapshotDefaultDependencyValues, suggestWithDependency, transformsDependencyValue, transformsDependencyValueMarker, wrappedDependencySourceMarker };
@@ -36,7 +36,8 @@ function isTerminalValueState(state) {
36
36
  * execution trace.
37
37
  * @internal
38
38
  */
39
- function createOptionParseState(parseResult) {
39
+ function createOptionParseState(parseResult, rawInput, valueParser) {
40
+ if (require_internal_dependency.isDerivedValueParser(valueParser)) require_dependency_runtime.recordDerivedRawInput(parseResult, rawInput);
40
41
  return parseResult;
41
42
  }
42
43
  function buildTraceEntry(kind, rawInput, consumed, valueParser, parseResult, optionNames$1) {
@@ -88,6 +89,11 @@ function resolveDerivedCompletionSync(derivedMetadata, state, exec) {
88
89
  }, traceEntry.rawInput, exec.dependencyRuntime);
89
90
  return replayed ?? traceEntry.preliminaryResult ?? state;
90
91
  }
92
+ function includeDependencyFailureChain(error, dependencyMetadata, exec) {
93
+ const sourceId = dependencyMetadata?.source?.sourceId;
94
+ if (sourceId == null || exec?.dependencyRuntime == null) return error;
95
+ return require_dependency_runtime.includeSourceFailureChain(error, sourceId, exec.dependencyRuntime);
96
+ }
91
97
  async function resolveDerivedCompletionAsync(derivedMetadata, state, exec) {
92
98
  if (derivedMetadata?.derived == null || exec?.dependencyRuntime == null) return state;
93
99
  const traceEntry = exec.trace?.get(exec.path);
@@ -499,7 +505,7 @@ function option(...args) {
499
505
  success: true,
500
506
  next: {
501
507
  ...next,
502
- state: createOptionParseState(parseResult),
508
+ state: createOptionParseState(parseResult, rawInput, syncValueParser),
503
509
  buffer: context.buffer.slice(2)
504
510
  },
505
511
  consumed: context.buffer.slice(0, 2)
@@ -511,7 +517,7 @@ function option(...args) {
511
517
  success: true,
512
518
  next: {
513
519
  ...next,
514
- state: createOptionParseState(parseResult),
520
+ state: createOptionParseState(parseResult, rawInput, valueParser),
515
521
  buffer: context.buffer.slice(2)
516
522
  },
517
523
  consumed: context.buffer.slice(0, 2)
@@ -542,7 +548,7 @@ function option(...args) {
542
548
  success: true,
543
549
  next: {
544
550
  ...next,
545
- state: createOptionParseState(parseResult),
551
+ state: createOptionParseState(parseResult, rawInput, syncValueParser),
546
552
  buffer: context.buffer.slice(1)
547
553
  },
548
554
  consumed: context.buffer.slice(0, 1)
@@ -554,7 +560,7 @@ function option(...args) {
554
560
  success: true,
555
561
  next: {
556
562
  ...next,
557
- state: createOptionParseState(parseResult),
563
+ state: createOptionParseState(parseResult, rawInput, valueParser),
558
564
  buffer: context.buffer.slice(1)
559
565
  },
560
566
  consumed: context.buffer.slice(0, 1)
@@ -616,7 +622,7 @@ function option(...args) {
616
622
  const resolvedState = valueParser != null && dependencyMetadata?.derived != null ? resolveDerivedCompletionSync(dependencyMetadata, state, exec) : state;
617
623
  return resolvedState.success ? resolvedState : {
618
624
  success: false,
619
- error: formatInvalidValueError(resolvedState.error)
625
+ error: formatInvalidValueError(includeDependencyFailureChain(resolvedState.error, dependencyMetadata, exec))
620
626
  };
621
627
  };
622
628
  const completeAsync = async () => {
@@ -625,7 +631,7 @@ function option(...args) {
625
631
  const resolved = await resolveDerivedCompletionAsync(dependencyMetadata, state, exec);
626
632
  return resolved.success ? resolved : {
627
633
  success: false,
628
- error: formatInvalidValueError(resolved.error)
634
+ error: formatInvalidValueError(includeDependencyFailureChain(resolved.error, dependencyMetadata, exec))
629
635
  };
630
636
  };
631
637
  return require_mode_dispatch.dispatchByMode(mode, completeSync, completeAsync);
@@ -1242,7 +1248,7 @@ function argument(valueParser, options = {}) {
1242
1248
  next: {
1243
1249
  ...next,
1244
1250
  buffer: context.buffer.slice(i + 1),
1245
- state: createOptionParseState(parseResult),
1251
+ state: createOptionParseState(parseResult, rawInput, syncValueParser),
1246
1252
  optionsTerminated
1247
1253
  },
1248
1254
  consumed: context.buffer.slice(0, i + 1)
@@ -1255,7 +1261,7 @@ function argument(valueParser, options = {}) {
1255
1261
  next: {
1256
1262
  ...next,
1257
1263
  buffer: context.buffer.slice(i + 1),
1258
- state: createOptionParseState(parseResult),
1264
+ state: createOptionParseState(parseResult, rawInput, valueParser),
1259
1265
  optionsTerminated
1260
1266
  },
1261
1267
  consumed: context.buffer.slice(0, i + 1)
@@ -1272,7 +1278,7 @@ function argument(valueParser, options = {}) {
1272
1278
  const resolvedState = dependencyMetadata?.derived != null ? resolveDerivedCompletionSync(dependencyMetadata, state, exec) : state;
1273
1279
  return resolvedState.success ? resolvedState : {
1274
1280
  success: false,
1275
- error: formatInvalidValueError(resolvedState.error)
1281
+ error: formatInvalidValueError(includeDependencyFailureChain(resolvedState.error, dependencyMetadata, exec))
1276
1282
  };
1277
1283
  };
1278
1284
  const completeAsync = async () => {
@@ -1281,7 +1287,7 @@ function argument(valueParser, options = {}) {
1281
1287
  const resolved = await resolveDerivedCompletionAsync(dependencyMetadata, state, exec);
1282
1288
  return resolved.success ? resolved : {
1283
1289
  success: false,
1284
- error: formatInvalidValueError(resolved.error)
1290
+ error: formatInvalidValueError(includeDependencyFailureChain(resolved.error, dependencyMetadata, exec))
1285
1291
  };
1286
1292
  };
1287
1293
  return require_mode_dispatch.dispatchByMode(valueParser.mode, completeSync, completeAsync);
@@ -4,7 +4,7 @@ import { validateCommandNames, validateOptionNames } from "./validate.js";
4
4
  import { extractOptionNames, isDocHidden, isSuggestionHidden } from "./usage.js";
5
5
  import { dispatchByMode, dispatchIterableByMode, wrapForMode } from "./internal/mode-dispatch.js";
6
6
  import { getDefaultValuesFunction, getDependencyIds, getSnapshottedDefaultDependencyValues, isDerivedValueParser, suggestWithDependency } from "./internal/dependency.js";
7
- import { effectfulSchedulingNodesKey, replayDerivedParser, replayDerivedParserAsync, sourceCollectionExpansionKey, staticSourceScopeKey } from "./dependency-runtime.js";
7
+ import { effectfulSchedulingNodesKey, includeSourceFailureChain, recordDerivedRawInput, replayDerivedParser, replayDerivedParserAsync, sourceCollectionExpansionKey, staticSourceScopeKey } from "./dependency-runtime.js";
8
8
  import { getWrappedChildParseState, getWrappedChildState, isAnnotationWrappedInitialState, normalizeInjectedAnnotationState } from "./annotation-state.js";
9
9
  import { hiddenCommandAliasesKey } from "./internal/command-alias.js";
10
10
  import { mergeChildExec, withChildContext, withChildExecPath } from "./execution-context.js";
@@ -36,7 +36,8 @@ function isTerminalValueState(state) {
36
36
  * execution trace.
37
37
  * @internal
38
38
  */
39
- function createOptionParseState(parseResult) {
39
+ function createOptionParseState(parseResult, rawInput, valueParser) {
40
+ if (isDerivedValueParser(valueParser)) recordDerivedRawInput(parseResult, rawInput);
40
41
  return parseResult;
41
42
  }
42
43
  function buildTraceEntry(kind, rawInput, consumed, valueParser, parseResult, optionNames$1) {
@@ -88,6 +89,11 @@ function resolveDerivedCompletionSync(derivedMetadata, state, exec) {
88
89
  }, traceEntry.rawInput, exec.dependencyRuntime);
89
90
  return replayed ?? traceEntry.preliminaryResult ?? state;
90
91
  }
92
+ function includeDependencyFailureChain(error, dependencyMetadata, exec) {
93
+ const sourceId = dependencyMetadata?.source?.sourceId;
94
+ if (sourceId == null || exec?.dependencyRuntime == null) return error;
95
+ return includeSourceFailureChain(error, sourceId, exec.dependencyRuntime);
96
+ }
91
97
  async function resolveDerivedCompletionAsync(derivedMetadata, state, exec) {
92
98
  if (derivedMetadata?.derived == null || exec?.dependencyRuntime == null) return state;
93
99
  const traceEntry = exec.trace?.get(exec.path);
@@ -499,7 +505,7 @@ function option(...args) {
499
505
  success: true,
500
506
  next: {
501
507
  ...next,
502
- state: createOptionParseState(parseResult),
508
+ state: createOptionParseState(parseResult, rawInput, syncValueParser),
503
509
  buffer: context.buffer.slice(2)
504
510
  },
505
511
  consumed: context.buffer.slice(0, 2)
@@ -511,7 +517,7 @@ function option(...args) {
511
517
  success: true,
512
518
  next: {
513
519
  ...next,
514
- state: createOptionParseState(parseResult),
520
+ state: createOptionParseState(parseResult, rawInput, valueParser),
515
521
  buffer: context.buffer.slice(2)
516
522
  },
517
523
  consumed: context.buffer.slice(0, 2)
@@ -542,7 +548,7 @@ function option(...args) {
542
548
  success: true,
543
549
  next: {
544
550
  ...next,
545
- state: createOptionParseState(parseResult),
551
+ state: createOptionParseState(parseResult, rawInput, syncValueParser),
546
552
  buffer: context.buffer.slice(1)
547
553
  },
548
554
  consumed: context.buffer.slice(0, 1)
@@ -554,7 +560,7 @@ function option(...args) {
554
560
  success: true,
555
561
  next: {
556
562
  ...next,
557
- state: createOptionParseState(parseResult),
563
+ state: createOptionParseState(parseResult, rawInput, valueParser),
558
564
  buffer: context.buffer.slice(1)
559
565
  },
560
566
  consumed: context.buffer.slice(0, 1)
@@ -616,7 +622,7 @@ function option(...args) {
616
622
  const resolvedState = valueParser != null && dependencyMetadata?.derived != null ? resolveDerivedCompletionSync(dependencyMetadata, state, exec) : state;
617
623
  return resolvedState.success ? resolvedState : {
618
624
  success: false,
619
- error: formatInvalidValueError(resolvedState.error)
625
+ error: formatInvalidValueError(includeDependencyFailureChain(resolvedState.error, dependencyMetadata, exec))
620
626
  };
621
627
  };
622
628
  const completeAsync = async () => {
@@ -625,7 +631,7 @@ function option(...args) {
625
631
  const resolved = await resolveDerivedCompletionAsync(dependencyMetadata, state, exec);
626
632
  return resolved.success ? resolved : {
627
633
  success: false,
628
- error: formatInvalidValueError(resolved.error)
634
+ error: formatInvalidValueError(includeDependencyFailureChain(resolved.error, dependencyMetadata, exec))
629
635
  };
630
636
  };
631
637
  return dispatchByMode(mode, completeSync, completeAsync);
@@ -1242,7 +1248,7 @@ function argument(valueParser, options = {}) {
1242
1248
  next: {
1243
1249
  ...next,
1244
1250
  buffer: context.buffer.slice(i + 1),
1245
- state: createOptionParseState(parseResult),
1251
+ state: createOptionParseState(parseResult, rawInput, syncValueParser),
1246
1252
  optionsTerminated
1247
1253
  },
1248
1254
  consumed: context.buffer.slice(0, i + 1)
@@ -1255,7 +1261,7 @@ function argument(valueParser, options = {}) {
1255
1261
  next: {
1256
1262
  ...next,
1257
1263
  buffer: context.buffer.slice(i + 1),
1258
- state: createOptionParseState(parseResult),
1264
+ state: createOptionParseState(parseResult, rawInput, valueParser),
1259
1265
  optionsTerminated
1260
1266
  },
1261
1267
  consumed: context.buffer.slice(0, i + 1)
@@ -1272,7 +1278,7 @@ function argument(valueParser, options = {}) {
1272
1278
  const resolvedState = dependencyMetadata?.derived != null ? resolveDerivedCompletionSync(dependencyMetadata, state, exec) : state;
1273
1279
  return resolvedState.success ? resolvedState : {
1274
1280
  success: false,
1275
- error: formatInvalidValueError(resolvedState.error)
1281
+ error: formatInvalidValueError(includeDependencyFailureChain(resolvedState.error, dependencyMetadata, exec))
1276
1282
  };
1277
1283
  };
1278
1284
  const completeAsync = async () => {
@@ -1281,7 +1287,7 @@ function argument(valueParser, options = {}) {
1281
1287
  const resolved = await resolveDerivedCompletionAsync(dependencyMetadata, state, exec);
1282
1288
  return resolved.success ? resolved : {
1283
1289
  success: false,
1284
- error: formatInvalidValueError(resolved.error)
1290
+ error: formatInvalidValueError(includeDependencyFailureChain(resolved.error, dependencyMetadata, exec))
1285
1291
  };
1286
1292
  };
1287
1293
  return dispatchByMode(valueParser.mode, completeSync, completeAsync);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@optique/core",
3
- "version": "1.3.0-dev.2398",
3
+ "version": "1.3.0-dev.2401",
4
4
  "description": "Type-safe combinatorial command-line interface parser",
5
5
  "keywords": [
6
6
  "CLI",
@@ -221,7 +221,7 @@
221
221
  },
222
222
  "sideEffects": false,
223
223
  "devDependencies": {
224
- "@optique/env": "1.3.0-dev.2398+ee974c3d",
224
+ "@optique/env": "1.3.0-dev.2401+fb69ad83",
225
225
  "@types/node": "^24.0.0",
226
226
  "fast-check": "^4.7.0",
227
227
  "tsdown": "^0.13.0",
@@ -52,6 +52,10 @@ Core rules
52
52
  - Async value parsers make the containing parser async. If you use packages
53
53
  such as *@optique/git*, remember to `await run(...)`, `await parse(...)`, or
54
54
  `await runParser(...)` as appropriate.
55
+ - Use `dependency()` when one value parser controls another's valid values.
56
+ For a multi-level chain, wrap the middle derivation too:
57
+ `dependency(source.deriveSync(...))`. Optique resolves such chains by
58
+ dependency order, independently of object/tuple field order.
55
59
  - Build subcommands with `command()` combined by `or()`. Put a literal field
56
60
  such as `command: constant("serve")` in each branch when you want a
57
61
  discriminated union.
@@ -228,6 +232,9 @@ Common mistakes checklist
228
232
  `message` values.
229
233
  - Do not forget to register source contexts when using `bindEnv()`,
230
234
  `bindConfig()`, or `bindDerivedDefault()`.
235
+ - Do not flatten a multi-level dependency graph into duplicated one-level
236
+ factories. Wrap each derived value that becomes a later source with
237
+ `dependency()` and derive the next parser from it.
231
238
  - Do not probe runtime capabilities eagerly before constructing a prompt
232
239
  parser. Put synchronous or asynchronous checks in the prompt config's
233
240
  `when` field and provide a typed `otherwise` value. The check then runs