@optique/core 0.10.7 → 1.0.0-dev.1116

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 (56) hide show
  1. package/README.md +4 -6
  2. package/dist/annotations.cjs +209 -1
  3. package/dist/annotations.d.cts +78 -1
  4. package/dist/annotations.d.ts +78 -1
  5. package/dist/annotations.js +201 -1
  6. package/dist/completion.cjs +194 -52
  7. package/dist/completion.js +194 -52
  8. package/dist/constructs.cjs +310 -78
  9. package/dist/constructs.d.cts +525 -644
  10. package/dist/constructs.d.ts +525 -644
  11. package/dist/constructs.js +311 -79
  12. package/dist/context.cjs +43 -3
  13. package/dist/context.d.cts +113 -5
  14. package/dist/context.d.ts +113 -5
  15. package/dist/context.js +41 -3
  16. package/dist/dependency.cjs +172 -66
  17. package/dist/dependency.d.cts +22 -2
  18. package/dist/dependency.d.ts +22 -2
  19. package/dist/dependency.js +172 -66
  20. package/dist/doc.cjs +46 -1
  21. package/dist/doc.d.cts +24 -0
  22. package/dist/doc.d.ts +24 -0
  23. package/dist/doc.js +46 -1
  24. package/dist/facade.cjs +702 -322
  25. package/dist/facade.d.cts +124 -190
  26. package/dist/facade.d.ts +124 -190
  27. package/dist/facade.js +703 -323
  28. package/dist/index.cjs +5 -0
  29. package/dist/index.d.cts +5 -5
  30. package/dist/index.d.ts +5 -5
  31. package/dist/index.js +3 -3
  32. package/dist/message.cjs +7 -4
  33. package/dist/message.js +7 -4
  34. package/dist/mode-dispatch.cjs +23 -1
  35. package/dist/mode-dispatch.d.cts +55 -0
  36. package/dist/mode-dispatch.d.ts +55 -0
  37. package/dist/mode-dispatch.js +21 -1
  38. package/dist/modifiers.cjs +210 -55
  39. package/dist/modifiers.js +211 -56
  40. package/dist/parser.cjs +80 -47
  41. package/dist/parser.d.cts +18 -3
  42. package/dist/parser.d.ts +18 -3
  43. package/dist/parser.js +82 -50
  44. package/dist/primitives.cjs +102 -37
  45. package/dist/primitives.d.cts +81 -24
  46. package/dist/primitives.d.ts +81 -24
  47. package/dist/primitives.js +103 -39
  48. package/dist/usage.cjs +88 -6
  49. package/dist/usage.d.cts +51 -13
  50. package/dist/usage.d.ts +51 -13
  51. package/dist/usage.js +85 -7
  52. package/dist/valueparser.cjs +391 -106
  53. package/dist/valueparser.d.cts +62 -10
  54. package/dist/valueparser.d.ts +62 -10
  55. package/dist/valueparser.js +391 -106
  56. package/package.json +10 -1
@@ -66,6 +66,7 @@ const suggestWithDependency = Symbol.for("@optique/core/dependency/suggestWithDe
66
66
  * // Create a derived parser that depends on the directory
67
67
  * const branchParser = cwdParser.derive({
68
68
  * metavar: "BRANCH",
69
+ * mode: "sync",
69
70
  * factory: (dir) => gitBranch({ dir }),
70
71
  * defaultValue: () => process.cwd(),
71
72
  * });
@@ -79,14 +80,15 @@ function dependency(parser) {
79
80
  [dependencySourceMarker]: true,
80
81
  [dependencyId]: id,
81
82
  derive(options) {
82
- return createDerivedValueParser(id, parser, options);
83
+ if (options.mode !== "sync" && options.mode !== "async") throw new TypeError("derive() requires an explicit mode field (\"sync\" or \"async\").");
84
+ return createDerivedValueParser(id, parser, options, options.mode);
83
85
  },
84
86
  deriveSync(options) {
85
87
  if (parser.$mode === "async") return createAsyncDerivedParserFromSyncFactory(id, options);
86
88
  return createSyncDerivedParser(id, options);
87
89
  },
88
90
  deriveAsync(options) {
89
- return createDerivedValueParser(id, parser, options);
91
+ return createAsyncDerivedParserFromAsyncFactory(id, options);
90
92
  }
91
93
  };
92
94
  return result;
@@ -132,6 +134,7 @@ function isDerivedValueParser(parser) {
132
134
  *
133
135
  * const configParser = deriveFrom({
134
136
  * metavar: "CONFIG",
137
+ * mode: "sync",
135
138
  * dependencies: [dirParser, modeParser] as const,
136
139
  * factory: (dir, mode) =>
137
140
  * choice(mode === "dev"
@@ -140,12 +143,14 @@ function isDerivedValueParser(parser) {
140
143
  * defaultValues: () => ["/config", "dev"],
141
144
  * });
142
145
  * ```
146
+ * @throws {TypeError} If the `mode` field is missing or invalid.
143
147
  * @since 0.10.0
144
148
  */
145
149
  function deriveFrom(options) {
150
+ if (options.mode !== "sync" && options.mode !== "async") throw new TypeError("deriveFrom() requires an explicit mode field (\"sync\" or \"async\").");
146
151
  const depsAsync = options.dependencies.some((dep) => dep.$mode === "async");
147
- const factoryReturnsAsync = determineFactoryModeForDeriveFrom(options);
148
152
  const sourceId = options.dependencies.length > 0 ? options.dependencies[0][dependencyId] : Symbol();
153
+ const factoryReturnsAsync = options.mode === "async";
149
154
  const isAsync = depsAsync || factoryReturnsAsync;
150
155
  if (isAsync) {
151
156
  if (factoryReturnsAsync) return createAsyncDerivedFromParserFromAsyncFactory(sourceId, options);
@@ -191,14 +196,6 @@ function deriveFromAsync(options) {
191
196
  const sourceId = options.dependencies.length > 0 ? options.dependencies[0][dependencyId] : Symbol();
192
197
  return createAsyncDerivedFromParserFromAsyncFactory(sourceId, options);
193
198
  }
194
- /**
195
- * Determines if the factory returns an async parser for deriveFrom options.
196
- */
197
- function determineFactoryModeForDeriveFrom(options) {
198
- const defaultValues$1 = options.defaultValues();
199
- const parser = options.factory(...defaultValues$1);
200
- return parser.$mode === "async";
201
- }
202
199
  function isAsyncModeParser(parser) {
203
200
  return parser.$mode === "async";
204
201
  }
@@ -212,8 +209,17 @@ function createSyncDerivedFromParser(sourceId, options) {
212
209
  [dependencyIds]: alldependencyIds,
213
210
  [defaultValues]: options.defaultValues,
214
211
  parse(input) {
215
- const sourceValues = options.defaultValues();
216
- const derivedParser = options.factory(...sourceValues);
212
+ let derivedParser;
213
+ try {
214
+ const sourceValues = options.defaultValues();
215
+ derivedParser = options.factory(...sourceValues);
216
+ } catch (e) {
217
+ const msg = e instanceof Error ? e.message : String(e);
218
+ return {
219
+ success: false,
220
+ error: require_message.message`Derived parser error: ${msg}`
221
+ };
222
+ }
217
223
  if (isAsyncModeParser(derivedParser)) return {
218
224
  success: false,
219
225
  error: require_message.message`Factory returned an async parser where a sync parser is required.`
@@ -238,14 +244,25 @@ function createSyncDerivedFromParser(sourceId, options) {
238
244
  return derivedParser.parse(input);
239
245
  },
240
246
  format(value) {
241
- const sourceValues = options.defaultValues();
242
- const derivedParser = options.factory(...sourceValues);
247
+ let derivedParser;
248
+ try {
249
+ const sourceValues = options.defaultValues();
250
+ derivedParser = options.factory(...sourceValues);
251
+ } catch {
252
+ return String(value);
253
+ }
243
254
  return derivedParser.format(value);
244
255
  },
245
256
  *suggest(prefix) {
246
- const sourceValues = options.defaultValues();
247
- const derivedParser = options.factory(...sourceValues);
248
- if (derivedParser.suggest) yield* derivedParser.suggest(prefix);
257
+ let derivedParser;
258
+ try {
259
+ const sourceValues = options.defaultValues();
260
+ derivedParser = options.factory(...sourceValues);
261
+ } catch {
262
+ return;
263
+ }
264
+ if (isAsyncModeParser(derivedParser) || !derivedParser.suggest) return;
265
+ yield* derivedParser.suggest(prefix);
249
266
  },
250
267
  *[suggestWithDependency](prefix, dependencyValue) {
251
268
  let derivedParser;
@@ -259,7 +276,8 @@ function createSyncDerivedFromParser(sourceId, options) {
259
276
  return;
260
277
  }
261
278
  }
262
- if (derivedParser.suggest) yield* derivedParser.suggest(prefix);
279
+ if (isAsyncModeParser(derivedParser) || !derivedParser.suggest) return;
280
+ yield* derivedParser.suggest(prefix);
263
281
  }
264
282
  };
265
283
  }
@@ -277,9 +295,18 @@ function createAsyncDerivedFromParserFromAsyncFactory(sourceId, options) {
277
295
  [dependencyIds]: alldependencyIds,
278
296
  [defaultValues]: options.defaultValues,
279
297
  parse(input) {
280
- const sourceValues = options.defaultValues();
281
- const derivedParser = options.factory(...sourceValues);
282
- return derivedParser.parse(input);
298
+ let derivedParser;
299
+ try {
300
+ const sourceValues = options.defaultValues();
301
+ derivedParser = options.factory(...sourceValues);
302
+ } catch (e) {
303
+ const msg = e instanceof Error ? e.message : String(e);
304
+ return Promise.resolve({
305
+ success: false,
306
+ error: require_message.message`Derived parser error: ${msg}`
307
+ });
308
+ }
309
+ return Promise.resolve(derivedParser.parse(input));
283
310
  },
284
311
  [parseWithDependency](input, dependencyValue) {
285
312
  let derivedParser;
@@ -292,16 +319,26 @@ function createAsyncDerivedFromParserFromAsyncFactory(sourceId, options) {
292
319
  error: require_message.message`Factory error: ${msg}`
293
320
  });
294
321
  }
295
- return derivedParser.parse(input);
322
+ return Promise.resolve(derivedParser.parse(input));
296
323
  },
297
324
  format(value) {
298
- const sourceValues = options.defaultValues();
299
- const derivedParser = options.factory(...sourceValues);
325
+ let derivedParser;
326
+ try {
327
+ const sourceValues = options.defaultValues();
328
+ derivedParser = options.factory(...sourceValues);
329
+ } catch {
330
+ return String(value);
331
+ }
300
332
  return derivedParser.format(value);
301
333
  },
302
334
  async *suggest(prefix) {
303
- const sourceValues = options.defaultValues();
304
- const derivedParser = options.factory(...sourceValues);
335
+ let derivedParser;
336
+ try {
337
+ const sourceValues = options.defaultValues();
338
+ derivedParser = options.factory(...sourceValues);
339
+ } catch {
340
+ return;
341
+ }
305
342
  if (derivedParser.suggest) for await (const suggestion of derivedParser.suggest(prefix)) yield suggestion;
306
343
  },
307
344
  async *[suggestWithDependency](prefix, dependencyValue) {
@@ -334,8 +371,17 @@ function createAsyncDerivedFromParserFromSyncFactory(sourceId, options) {
334
371
  [dependencyIds]: alldependencyIds,
335
372
  [defaultValues]: options.defaultValues,
336
373
  parse(input) {
337
- const sourceValues = options.defaultValues();
338
- const derivedParser = options.factory(...sourceValues);
374
+ let derivedParser;
375
+ try {
376
+ const sourceValues = options.defaultValues();
377
+ derivedParser = options.factory(...sourceValues);
378
+ } catch (e) {
379
+ const msg = e instanceof Error ? e.message : String(e);
380
+ return Promise.resolve({
381
+ success: false,
382
+ error: require_message.message`Derived parser error: ${msg}`
383
+ });
384
+ }
339
385
  return Promise.resolve(derivedParser.parse(input));
340
386
  },
341
387
  [parseWithDependency](input, dependencyValue) {
@@ -352,13 +398,23 @@ function createAsyncDerivedFromParserFromSyncFactory(sourceId, options) {
352
398
  return Promise.resolve(derivedParser.parse(input));
353
399
  },
354
400
  format(value) {
355
- const sourceValues = options.defaultValues();
356
- const derivedParser = options.factory(...sourceValues);
401
+ let derivedParser;
402
+ try {
403
+ const sourceValues = options.defaultValues();
404
+ derivedParser = options.factory(...sourceValues);
405
+ } catch {
406
+ return String(value);
407
+ }
357
408
  return derivedParser.format(value);
358
409
  },
359
410
  async *suggest(prefix) {
360
- const sourceValues = options.defaultValues();
361
- const derivedParser = options.factory(...sourceValues);
411
+ let derivedParser;
412
+ try {
413
+ const sourceValues = options.defaultValues();
414
+ derivedParser = options.factory(...sourceValues);
415
+ } catch {
416
+ return;
417
+ }
362
418
  if (derivedParser.suggest) yield* derivedParser.suggest(prefix);
363
419
  },
364
420
  *[suggestWithDependency](prefix, dependencyValue) {
@@ -377,8 +433,8 @@ function createAsyncDerivedFromParserFromSyncFactory(sourceId, options) {
377
433
  }
378
434
  };
379
435
  }
380
- function createDerivedValueParser(sourceId, sourceParser, options) {
381
- const factoryReturnsAsync = determineFactoryMode(options);
436
+ function createDerivedValueParser(sourceId, sourceParser, options, factoryMode) {
437
+ const factoryReturnsAsync = factoryMode === "async";
382
438
  const isAsync = sourceParser.$mode === "async" || factoryReturnsAsync;
383
439
  if (isAsync) {
384
440
  if (factoryReturnsAsync) return createAsyncDerivedParserFromAsyncFactory(sourceId, options);
@@ -386,15 +442,6 @@ function createDerivedValueParser(sourceId, sourceParser, options) {
386
442
  }
387
443
  return createSyncDerivedParser(sourceId, options);
388
444
  }
389
- /**
390
- * Determines if the factory returns an async parser by calling it with
391
- * the default value and checking the mode.
392
- */
393
- function determineFactoryMode(options) {
394
- const defaultValue = options.defaultValue();
395
- const parser = options.factory(defaultValue);
396
- return parser.$mode === "async";
397
- }
398
445
  function createSyncDerivedParser(sourceId, options) {
399
446
  return {
400
447
  $mode: "sync",
@@ -402,8 +449,17 @@ function createSyncDerivedParser(sourceId, options) {
402
449
  [derivedValueParserMarker]: true,
403
450
  [dependencyId]: sourceId,
404
451
  parse(input) {
405
- const sourceValue = options.defaultValue();
406
- const derivedParser = options.factory(sourceValue);
452
+ let derivedParser;
453
+ try {
454
+ const sourceValue = options.defaultValue();
455
+ derivedParser = options.factory(sourceValue);
456
+ } catch (e) {
457
+ const msg = e instanceof Error ? e.message : String(e);
458
+ return {
459
+ success: false,
460
+ error: require_message.message`Derived parser error: ${msg}`
461
+ };
462
+ }
407
463
  if (isAsyncModeParser(derivedParser)) return {
408
464
  success: false,
409
465
  error: require_message.message`Factory returned an async parser where a sync parser is required.`
@@ -428,14 +484,25 @@ function createSyncDerivedParser(sourceId, options) {
428
484
  return derivedParser.parse(input);
429
485
  },
430
486
  format(value) {
431
- const sourceValue = options.defaultValue();
432
- const derivedParser = options.factory(sourceValue);
487
+ let derivedParser;
488
+ try {
489
+ const sourceValue = options.defaultValue();
490
+ derivedParser = options.factory(sourceValue);
491
+ } catch {
492
+ return String(value);
493
+ }
433
494
  return derivedParser.format(value);
434
495
  },
435
496
  *suggest(prefix) {
436
- const sourceValue = options.defaultValue();
437
- const derivedParser = options.factory(sourceValue);
438
- if (derivedParser.suggest) yield* derivedParser.suggest(prefix);
497
+ let derivedParser;
498
+ try {
499
+ const sourceValue = options.defaultValue();
500
+ derivedParser = options.factory(sourceValue);
501
+ } catch {
502
+ return;
503
+ }
504
+ if (isAsyncModeParser(derivedParser) || !derivedParser.suggest) return;
505
+ yield* derivedParser.suggest(prefix);
439
506
  },
440
507
  *[suggestWithDependency](prefix, dependencyValue) {
441
508
  let derivedParser;
@@ -448,7 +515,8 @@ function createSyncDerivedParser(sourceId, options) {
448
515
  return;
449
516
  }
450
517
  }
451
- if (derivedParser.suggest) yield* derivedParser.suggest(prefix);
518
+ if (isAsyncModeParser(derivedParser) || !derivedParser.suggest) return;
519
+ yield* derivedParser.suggest(prefix);
452
520
  }
453
521
  };
454
522
  }
@@ -463,9 +531,18 @@ function createAsyncDerivedParserFromAsyncFactory(sourceId, options) {
463
531
  [derivedValueParserMarker]: true,
464
532
  [dependencyId]: sourceId,
465
533
  parse(input) {
466
- const sourceValue = options.defaultValue();
467
- const derivedParser = options.factory(sourceValue);
468
- return derivedParser.parse(input);
534
+ let derivedParser;
535
+ try {
536
+ const sourceValue = options.defaultValue();
537
+ derivedParser = options.factory(sourceValue);
538
+ } catch (e) {
539
+ const msg = e instanceof Error ? e.message : String(e);
540
+ return Promise.resolve({
541
+ success: false,
542
+ error: require_message.message`Derived parser error: ${msg}`
543
+ });
544
+ }
545
+ return Promise.resolve(derivedParser.parse(input));
469
546
  },
470
547
  [parseWithDependency](input, dependencyValue) {
471
548
  let derivedParser;
@@ -478,16 +555,26 @@ function createAsyncDerivedParserFromAsyncFactory(sourceId, options) {
478
555
  error: require_message.message`Factory error: ${msg}`
479
556
  });
480
557
  }
481
- return derivedParser.parse(input);
558
+ return Promise.resolve(derivedParser.parse(input));
482
559
  },
483
560
  format(value) {
484
- const sourceValue = options.defaultValue();
485
- const derivedParser = options.factory(sourceValue);
561
+ let derivedParser;
562
+ try {
563
+ const sourceValue = options.defaultValue();
564
+ derivedParser = options.factory(sourceValue);
565
+ } catch {
566
+ return String(value);
567
+ }
486
568
  return derivedParser.format(value);
487
569
  },
488
570
  async *suggest(prefix) {
489
- const sourceValue = options.defaultValue();
490
- const derivedParser = options.factory(sourceValue);
571
+ let derivedParser;
572
+ try {
573
+ const sourceValue = options.defaultValue();
574
+ derivedParser = options.factory(sourceValue);
575
+ } catch {
576
+ return;
577
+ }
491
578
  if (derivedParser.suggest) for await (const suggestion of derivedParser.suggest(prefix)) yield suggestion;
492
579
  },
493
580
  async *[suggestWithDependency](prefix, dependencyValue) {
@@ -516,8 +603,17 @@ function createAsyncDerivedParserFromSyncFactory(sourceId, options) {
516
603
  [derivedValueParserMarker]: true,
517
604
  [dependencyId]: sourceId,
518
605
  parse(input) {
519
- const sourceValue = options.defaultValue();
520
- const derivedParser = options.factory(sourceValue);
606
+ let derivedParser;
607
+ try {
608
+ const sourceValue = options.defaultValue();
609
+ derivedParser = options.factory(sourceValue);
610
+ } catch (e) {
611
+ const msg = e instanceof Error ? e.message : String(e);
612
+ return Promise.resolve({
613
+ success: false,
614
+ error: require_message.message`Derived parser error: ${msg}`
615
+ });
616
+ }
521
617
  return Promise.resolve(derivedParser.parse(input));
522
618
  },
523
619
  [parseWithDependency](input, dependencyValue) {
@@ -534,13 +630,23 @@ function createAsyncDerivedParserFromSyncFactory(sourceId, options) {
534
630
  return Promise.resolve(derivedParser.parse(input));
535
631
  },
536
632
  format(value) {
537
- const sourceValue = options.defaultValue();
538
- const derivedParser = options.factory(sourceValue);
633
+ let derivedParser;
634
+ try {
635
+ const sourceValue = options.defaultValue();
636
+ derivedParser = options.factory(sourceValue);
637
+ } catch {
638
+ return String(value);
639
+ }
539
640
  return derivedParser.format(value);
540
641
  },
541
642
  async *suggest(prefix) {
542
- const sourceValue = options.defaultValue();
543
- const derivedParser = options.factory(sourceValue);
643
+ let derivedParser;
644
+ try {
645
+ const sourceValue = options.defaultValue();
646
+ derivedParser = options.factory(sourceValue);
647
+ } catch {
648
+ return;
649
+ }
544
650
  if (derivedParser.suggest) yield* derivedParser.suggest(prefix);
545
651
  },
546
652
  *[suggestWithDependency](prefix, dependencyValue) {
@@ -77,7 +77,7 @@ interface DeriveOptions<S, T, FM extends Mode = Mode> {
77
77
  * @param sourceValue The value parsed from the dependency source.
78
78
  * @returns A {@link ValueParser} for the derived value.
79
79
  */
80
- readonly factory: (sourceValue: S) => ValueParser<FM, T>;
80
+ readonly factory: (sourceValue: S) => ValueParser<NoInfer<FM>, T>;
81
81
  /**
82
82
  * Default value to use when the dependency source is not provided.
83
83
  * This allows the derived parser to work even when the dependency
@@ -86,6 +86,14 @@ interface DeriveOptions<S, T, FM extends Mode = Mode> {
86
86
  * @returns The default value for the dependency source.
87
87
  */
88
88
  readonly defaultValue: () => S;
89
+ /**
90
+ * The execution mode of the factory's returned parser. This tells the
91
+ * runtime whether the factory returns a sync or async parser, avoiding
92
+ * the need to call the factory during parser construction.
93
+ *
94
+ * @since 1.0.0
95
+ */
96
+ readonly mode: FM;
89
97
  }
90
98
  /**
91
99
  * Options for creating a derived value parser with a synchronous factory.
@@ -165,6 +173,7 @@ interface DependencySource<M extends Mode = "sync", T = unknown> extends ValuePa
165
173
  * @template FM The mode of the factory's returned parser.
166
174
  * @param options Configuration for the derived parser.
167
175
  * @returns A {@link DerivedValueParser} that depends on this source.
176
+ * @throws {TypeError} If the `mode` field is missing or invalid.
168
177
  */
169
178
  derive<U, FM extends Mode = "sync">(options: DeriveOptions<T, U, FM>): DerivedValueParser<CombineMode<M, FM>, U, T>;
170
179
  /**
@@ -247,7 +256,7 @@ interface DeriveFromOptions<Deps extends readonly AnyDependencySource[], T, FM e
247
256
  * @param values The values parsed from the dependency sources (in order).
248
257
  * @returns A {@link ValueParser} for the derived value.
249
258
  */
250
- readonly factory: (...values: DependencyValues<Deps>) => ValueParser<FM, T>;
259
+ readonly factory: (...values: DependencyValues<Deps>) => ValueParser<NoInfer<FM>, T>;
251
260
  /**
252
261
  * Default values to use when the dependency sources are not provided.
253
262
  * Must return a tuple with the same length and types as the dependencies.
@@ -255,6 +264,14 @@ interface DeriveFromOptions<Deps extends readonly AnyDependencySource[], T, FM e
255
264
  * @returns A tuple of default values for each dependency source.
256
265
  */
257
266
  readonly defaultValues: () => DependencyValues<Deps>;
267
+ /**
268
+ * The execution mode of the factory's returned parser. This tells the
269
+ * runtime whether the factory returns a sync or async parser, avoiding
270
+ * the need to call the factory during parser construction.
271
+ *
272
+ * @since 1.0.0
273
+ */
274
+ readonly mode: FM;
258
275
  }
259
276
  /**
260
277
  * Options for creating a derived value parser from multiple dependencies
@@ -390,6 +407,7 @@ interface DerivedValueParser<M extends Mode = "sync", T = unknown, S = unknown>
390
407
  * // Create a derived parser that depends on the directory
391
408
  * const branchParser = cwdParser.derive({
392
409
  * metavar: "BRANCH",
410
+ * mode: "sync",
393
411
  * factory: (dir) => gitBranch({ dir }),
394
412
  * defaultValue: () => process.cwd(),
395
413
  * });
@@ -434,6 +452,7 @@ declare function isDerivedValueParser<M extends Mode, T>(parser: ValueParser<M,
434
452
  *
435
453
  * const configParser = deriveFrom({
436
454
  * metavar: "CONFIG",
455
+ * mode: "sync",
437
456
  * dependencies: [dirParser, modeParser] as const,
438
457
  * factory: (dir, mode) =>
439
458
  * choice(mode === "dev"
@@ -442,6 +461,7 @@ declare function isDerivedValueParser<M extends Mode, T>(parser: ValueParser<M,
442
461
  * defaultValues: () => ["/config", "dev"],
443
462
  * });
444
463
  * ```
464
+ * @throws {TypeError} If the `mode` field is missing or invalid.
445
465
  * @since 0.10.0
446
466
  */
447
467
  declare function deriveFrom<Deps extends readonly AnyDependencySource[], T, FM extends Mode = "sync">(options: DeriveFromOptions<Deps, T, FM>): DerivedValueParser<CombineMode<CombinedDependencyMode<Deps>, FM>, T, DependencyValues<Deps>>;
@@ -77,7 +77,7 @@ interface DeriveOptions<S, T, FM extends Mode = Mode> {
77
77
  * @param sourceValue The value parsed from the dependency source.
78
78
  * @returns A {@link ValueParser} for the derived value.
79
79
  */
80
- readonly factory: (sourceValue: S) => ValueParser<FM, T>;
80
+ readonly factory: (sourceValue: S) => ValueParser<NoInfer<FM>, T>;
81
81
  /**
82
82
  * Default value to use when the dependency source is not provided.
83
83
  * This allows the derived parser to work even when the dependency
@@ -86,6 +86,14 @@ interface DeriveOptions<S, T, FM extends Mode = Mode> {
86
86
  * @returns The default value for the dependency source.
87
87
  */
88
88
  readonly defaultValue: () => S;
89
+ /**
90
+ * The execution mode of the factory's returned parser. This tells the
91
+ * runtime whether the factory returns a sync or async parser, avoiding
92
+ * the need to call the factory during parser construction.
93
+ *
94
+ * @since 1.0.0
95
+ */
96
+ readonly mode: FM;
89
97
  }
90
98
  /**
91
99
  * Options for creating a derived value parser with a synchronous factory.
@@ -165,6 +173,7 @@ interface DependencySource<M extends Mode = "sync", T = unknown> extends ValuePa
165
173
  * @template FM The mode of the factory's returned parser.
166
174
  * @param options Configuration for the derived parser.
167
175
  * @returns A {@link DerivedValueParser} that depends on this source.
176
+ * @throws {TypeError} If the `mode` field is missing or invalid.
168
177
  */
169
178
  derive<U, FM extends Mode = "sync">(options: DeriveOptions<T, U, FM>): DerivedValueParser<CombineMode<M, FM>, U, T>;
170
179
  /**
@@ -247,7 +256,7 @@ interface DeriveFromOptions<Deps extends readonly AnyDependencySource[], T, FM e
247
256
  * @param values The values parsed from the dependency sources (in order).
248
257
  * @returns A {@link ValueParser} for the derived value.
249
258
  */
250
- readonly factory: (...values: DependencyValues<Deps>) => ValueParser<FM, T>;
259
+ readonly factory: (...values: DependencyValues<Deps>) => ValueParser<NoInfer<FM>, T>;
251
260
  /**
252
261
  * Default values to use when the dependency sources are not provided.
253
262
  * Must return a tuple with the same length and types as the dependencies.
@@ -255,6 +264,14 @@ interface DeriveFromOptions<Deps extends readonly AnyDependencySource[], T, FM e
255
264
  * @returns A tuple of default values for each dependency source.
256
265
  */
257
266
  readonly defaultValues: () => DependencyValues<Deps>;
267
+ /**
268
+ * The execution mode of the factory's returned parser. This tells the
269
+ * runtime whether the factory returns a sync or async parser, avoiding
270
+ * the need to call the factory during parser construction.
271
+ *
272
+ * @since 1.0.0
273
+ */
274
+ readonly mode: FM;
258
275
  }
259
276
  /**
260
277
  * Options for creating a derived value parser from multiple dependencies
@@ -390,6 +407,7 @@ interface DerivedValueParser<M extends Mode = "sync", T = unknown, S = unknown>
390
407
  * // Create a derived parser that depends on the directory
391
408
  * const branchParser = cwdParser.derive({
392
409
  * metavar: "BRANCH",
410
+ * mode: "sync",
393
411
  * factory: (dir) => gitBranch({ dir }),
394
412
  * defaultValue: () => process.cwd(),
395
413
  * });
@@ -434,6 +452,7 @@ declare function isDerivedValueParser<M extends Mode, T>(parser: ValueParser<M,
434
452
  *
435
453
  * const configParser = deriveFrom({
436
454
  * metavar: "CONFIG",
455
+ * mode: "sync",
437
456
  * dependencies: [dirParser, modeParser] as const,
438
457
  * factory: (dir, mode) =>
439
458
  * choice(mode === "dev"
@@ -442,6 +461,7 @@ declare function isDerivedValueParser<M extends Mode, T>(parser: ValueParser<M,
442
461
  * defaultValues: () => ["/config", "dev"],
443
462
  * });
444
463
  * ```
464
+ * @throws {TypeError} If the `mode` field is missing or invalid.
445
465
  * @since 0.10.0
446
466
  */
447
467
  declare function deriveFrom<Deps extends readonly AnyDependencySource[], T, FM extends Mode = "sync">(options: DeriveFromOptions<Deps, T, FM>): DerivedValueParser<CombineMode<CombinedDependencyMode<Deps>, FM>, T, DependencyValues<Deps>>;