@optique/core 1.0.0-dev.1536 → 1.0.0-dev.1553

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.
@@ -9,6 +9,43 @@ const require_suggestion = require('./suggestion.cjs');
9
9
  const require_usage_internals = require('./usage-internals.cjs');
10
10
 
11
11
  //#region src/constructs.ts
12
+ /**
13
+ * A shared empty set used as the `leadingNames` value for parsers that
14
+ * do not match any specific name at the first buffer position.
15
+ */
16
+ const EMPTY_LEADING_NAMES = /* @__PURE__ */ new Set();
17
+ /**
18
+ * Computes the union of `leadingNames` from all given parsers.
19
+ * Used for alternative combinators (`or()`, `longestMatch()`) where all
20
+ * branches compete independently.
21
+ */
22
+ function unionLeadingNames(parsers) {
23
+ const names = /* @__PURE__ */ new Set();
24
+ for (const p of parsers) for (const name of p.leadingNames) names.add(name);
25
+ return names.size === 0 ? EMPTY_LEADING_NAMES : names;
26
+ }
27
+ /**
28
+ * Computes `leadingNames` for shared-buffer compositions (`tuple()`,
29
+ * `object()`, `merge()`, `concat()`).
30
+ *
31
+ * Children are processed in descending priority order (matching the
32
+ * round-robin parse loop). Once a child with `acceptingAnyToken` is
33
+ * encountered, no lower-priority children can match at position 0, so
34
+ * their names are excluded.
35
+ */
36
+ function sharedBufferLeadingNames(parsers) {
37
+ const sorted = parsers.toSorted((a, b) => b.priority - a.priority);
38
+ const names = /* @__PURE__ */ new Set();
39
+ let positionalBlocked = false;
40
+ for (const p of sorted) {
41
+ if (p.leadingNames) for (const name of p.leadingNames) {
42
+ if (positionalBlocked && !name.startsWith("-")) continue;
43
+ names.add(name);
44
+ }
45
+ if (p.acceptingAnyToken) positionalBlocked = true;
46
+ }
47
+ return names.size === 0 ? EMPTY_LEADING_NAMES : names;
48
+ }
12
49
  const inheritParentAnnotationsKey = Symbol.for("@optique/core/inheritParentAnnotations");
13
50
  /**
14
51
  * Internal symbol for exposing field-level parser pairs from `object()`
@@ -454,7 +491,7 @@ function or(...args) {
454
491
  success: false
455
492
  };
456
493
  };
457
- return {
494
+ const singleResult = {
458
495
  $mode: combinedMode,
459
496
  $valueType: [],
460
497
  $stateType: [],
@@ -463,6 +500,8 @@ function or(...args) {
463
500
  type: "exclusive",
464
501
  terms: parsers.map((p) => p.usage)
465
502
  }],
503
+ leadingNames: unionLeadingNames(parsers),
504
+ acceptingAnyToken: parsers.some((p) => p.acceptingAnyToken),
466
505
  initialState: void 0,
467
506
  complete: createExclusiveComplete(parsers, options, noMatchContext, combinedMode),
468
507
  parse(context) {
@@ -496,6 +535,7 @@ function or(...args) {
496
535
  };
497
536
  }
498
537
  };
538
+ return singleResult;
499
539
  }
500
540
  /**
501
541
  * @since 0.5.0
@@ -591,7 +631,7 @@ function longestMatch(...args) {
591
631
  success: false
592
632
  };
593
633
  };
594
- return {
634
+ const multiResult = {
595
635
  $mode: combinedMode,
596
636
  $valueType: [],
597
637
  $stateType: [],
@@ -600,6 +640,8 @@ function longestMatch(...args) {
600
640
  type: "exclusive",
601
641
  terms: parsers.map((p) => p.usage)
602
642
  }],
643
+ leadingNames: unionLeadingNames(parsers),
644
+ acceptingAnyToken: parsers.some((p) => p.acceptingAnyToken),
603
645
  initialState: void 0,
604
646
  complete: createExclusiveComplete(parsers, options, noMatchContext, combinedMode),
605
647
  parse(context) {
@@ -640,6 +682,7 @@ function longestMatch(...args) {
640
682
  };
641
683
  }
642
684
  };
685
+ return multiResult;
643
686
  }
644
687
  /**
645
688
  * Internal sync helper for object suggest functionality.
@@ -1178,13 +1221,15 @@ function object(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
1178
1221
  success: false
1179
1222
  };
1180
1223
  };
1181
- return {
1224
+ const objectParser = {
1182
1225
  $mode: combinedMode,
1183
1226
  $valueType: [],
1184
1227
  $stateType: [],
1185
1228
  [fieldParsersKey]: parserPairs,
1186
1229
  priority: Math.max(...parserKeys.map((k) => parsers[k].priority)),
1187
1230
  usage: applyHiddenToUsage(parserPairs.flatMap(([_, p]) => p.usage), options.hidden),
1231
+ leadingNames: sharedBufferLeadingNames(parserPairs.map(([_, p]) => p)),
1232
+ acceptingAnyToken: parserPairs.some(([_, p]) => p.acceptingAnyToken),
1188
1233
  get initialState() {
1189
1234
  return createInitialState();
1190
1235
  },
@@ -1380,6 +1425,28 @@ function object(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
1380
1425
  })) };
1381
1426
  }
1382
1427
  };
1428
+ const fieldNormalizers = [];
1429
+ for (const [key, fieldParser] of parserPairs) if (typeof fieldParser.normalizeValue === "function") fieldNormalizers.push([key, fieldParser.normalizeValue.bind(fieldParser)]);
1430
+ if (fieldNormalizers.length > 0) Object.defineProperty(objectParser, "normalizeValue", {
1431
+ value(obj) {
1432
+ if (typeof obj !== "object" || obj == null) return obj;
1433
+ let changed = false;
1434
+ let result;
1435
+ for (const [key, normalize] of fieldNormalizers) if (Object.hasOwn(obj, key)) try {
1436
+ const original = obj[key];
1437
+ const normalized = normalize(original);
1438
+ if (normalized !== original) {
1439
+ if (!result) result = { ...obj };
1440
+ result[key] = normalized;
1441
+ changed = true;
1442
+ }
1443
+ } catch {}
1444
+ return changed ? result : obj;
1445
+ },
1446
+ configurable: true,
1447
+ enumerable: false
1448
+ });
1449
+ return objectParser;
1383
1450
  }
1384
1451
  function suggestTupleSync(context, prefix, parsers) {
1385
1452
  const suggestions = [];
@@ -1551,11 +1618,13 @@ function tuple(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
1551
1618
  consumed: allConsumed
1552
1619
  };
1553
1620
  };
1554
- return {
1621
+ const tupleParser = {
1555
1622
  $mode: combinedMode,
1556
1623
  $valueType: [],
1557
1624
  $stateType: [],
1558
1625
  usage: parsers.toSorted((a, b) => b.priority - a.priority).flatMap((p) => p.usage),
1626
+ leadingNames: sharedBufferLeadingNames(parsers),
1627
+ acceptingAnyToken: parsers.some((p) => p.acceptingAnyToken),
1559
1628
  priority: parsers.length > 0 ? Math.max(...parsers.map((p) => p.priority)) : 0,
1560
1629
  initialState: parsers.map((parser) => parser.initialState),
1561
1630
  parse(context) {
@@ -1723,6 +1792,31 @@ function tuple(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
1723
1792
  return label ? `tuple(${JSON.stringify(label)}, ${parsersStr})` : `tuple(${parsersStr})`;
1724
1793
  }
1725
1794
  };
1795
+ const tupleNormalizers = [];
1796
+ for (let i = 0; i < parsers.length; i++) {
1797
+ const p = parsers[i];
1798
+ if (typeof p.normalizeValue === "function") tupleNormalizers.push([i, p.normalizeValue.bind(p)]);
1799
+ }
1800
+ if (tupleNormalizers.length > 0) Object.defineProperty(tupleParser, "normalizeValue", {
1801
+ value(arr) {
1802
+ if (!Array.isArray(arr)) return arr;
1803
+ let changed = false;
1804
+ let result;
1805
+ for (const [idx, normalize] of tupleNormalizers) if (idx < arr.length && Object.hasOwn(arr, idx)) try {
1806
+ const original = arr[idx];
1807
+ const normalized = normalize(original);
1808
+ if (normalized !== original) {
1809
+ if (!result) result = [...arr];
1810
+ result[idx] = normalized;
1811
+ changed = true;
1812
+ }
1813
+ } catch {}
1814
+ return changed ? result : arr;
1815
+ },
1816
+ configurable: true,
1817
+ enumerable: false
1818
+ });
1819
+ return tupleParser;
1726
1820
  }
1727
1821
  function merge(...args) {
1728
1822
  const label = typeof args[0] === "string" ? args[0] : void 0;
@@ -1870,13 +1964,15 @@ function merge(...args) {
1870
1964
  };
1871
1965
  };
1872
1966
  const mergedFieldParsers = collectChildFieldParsers(parsers);
1873
- return {
1967
+ const mergeParser = {
1874
1968
  $mode: combinedMode,
1875
1969
  $valueType: [],
1876
1970
  $stateType: [],
1877
1971
  [fieldParsersKey]: mergedFieldParsers,
1878
1972
  priority: Math.max(...parsers.map((p) => p.priority)),
1879
1973
  usage: applyHiddenToUsage(parsers.flatMap((p) => p.usage), options.hidden),
1974
+ leadingNames: sharedBufferLeadingNames(parsers),
1975
+ acceptingAnyToken: parsers.some((p) => p.acceptingAnyToken),
1880
1976
  initialState,
1881
1977
  parse(context) {
1882
1978
  if (isAsync) return parseAsync(context);
@@ -2087,6 +2183,7 @@ function merge(...args) {
2087
2183
  };
2088
2184
  }
2089
2185
  };
2186
+ return mergeParser;
2090
2187
  }
2091
2188
  /**
2092
2189
  * Builds a dependency registry from the pre-parsed context state and returns
@@ -2415,6 +2512,8 @@ function concat(...parsers) {
2415
2512
  $stateType: [],
2416
2513
  priority: parsers.length > 0 ? Math.max(...parsers.map((p) => p.priority)) : 0,
2417
2514
  usage: parsers.flatMap((p) => p.usage),
2515
+ leadingNames: sharedBufferLeadingNames(parsers),
2516
+ acceptingAnyToken: parsers.some((p) => p.acceptingAnyToken),
2418
2517
  initialState,
2419
2518
  parse(context) {
2420
2519
  if (isAsync) return parseAsync(context);
@@ -2492,6 +2591,8 @@ function group(label, parser, options = {}) {
2492
2591
  $stateType: parser.$stateType,
2493
2592
  priority: parser.priority,
2494
2593
  usage: applyHiddenToUsage(parser.usage, options.hidden),
2594
+ leadingNames: parser.leadingNames,
2595
+ acceptingAnyToken: parser.acceptingAnyToken,
2495
2596
  initialState: parser.initialState,
2496
2597
  ...fieldParsersKey in parser ? { [fieldParsersKey]: parser[fieldParsersKey] } : {},
2497
2598
  ...typeof parser.shouldDeferCompletion === "function" ? { shouldDeferCompletion: parser.shouldDeferCompletion.bind(parser) } : {},
@@ -2546,6 +2647,11 @@ function group(label, parser, options = {}) {
2546
2647
  configurable: true,
2547
2648
  enumerable: false
2548
2649
  });
2650
+ if (typeof parser.normalizeValue === "function") Object.defineProperty(groupParser, "normalizeValue", {
2651
+ value: parser.normalizeValue.bind(parser),
2652
+ configurable: true,
2653
+ enumerable: false
2654
+ });
2549
2655
  return groupParser;
2550
2656
  }
2551
2657
  /**
@@ -2976,6 +3082,8 @@ function conditional(discriminator, branches, defaultBranch, options) {
2976
3082
  $stateType: [],
2977
3083
  priority: maxPriority,
2978
3084
  usage,
3085
+ leadingNames: defaultBranch ? unionLeadingNames([discriminator, defaultBranch]) : discriminator.leadingNames,
3086
+ acceptingAnyToken: defaultBranch?.acceptingAnyToken ?? false,
2979
3087
  initialState,
2980
3088
  parse(context) {
2981
3089
  if (isAsync) return parseAsync(context);
@@ -9,6 +9,43 @@ import { DEFAULT_FIND_SIMILAR_OPTIONS, createErrorWithSuggestions, createSuggest
9
9
  import { collectLeadingCandidates } from "./usage-internals.js";
10
10
 
11
11
  //#region src/constructs.ts
12
+ /**
13
+ * A shared empty set used as the `leadingNames` value for parsers that
14
+ * do not match any specific name at the first buffer position.
15
+ */
16
+ const EMPTY_LEADING_NAMES = /* @__PURE__ */ new Set();
17
+ /**
18
+ * Computes the union of `leadingNames` from all given parsers.
19
+ * Used for alternative combinators (`or()`, `longestMatch()`) where all
20
+ * branches compete independently.
21
+ */
22
+ function unionLeadingNames(parsers) {
23
+ const names = /* @__PURE__ */ new Set();
24
+ for (const p of parsers) for (const name of p.leadingNames) names.add(name);
25
+ return names.size === 0 ? EMPTY_LEADING_NAMES : names;
26
+ }
27
+ /**
28
+ * Computes `leadingNames` for shared-buffer compositions (`tuple()`,
29
+ * `object()`, `merge()`, `concat()`).
30
+ *
31
+ * Children are processed in descending priority order (matching the
32
+ * round-robin parse loop). Once a child with `acceptingAnyToken` is
33
+ * encountered, no lower-priority children can match at position 0, so
34
+ * their names are excluded.
35
+ */
36
+ function sharedBufferLeadingNames(parsers) {
37
+ const sorted = parsers.toSorted((a, b) => b.priority - a.priority);
38
+ const names = /* @__PURE__ */ new Set();
39
+ let positionalBlocked = false;
40
+ for (const p of sorted) {
41
+ if (p.leadingNames) for (const name of p.leadingNames) {
42
+ if (positionalBlocked && !name.startsWith("-")) continue;
43
+ names.add(name);
44
+ }
45
+ if (p.acceptingAnyToken) positionalBlocked = true;
46
+ }
47
+ return names.size === 0 ? EMPTY_LEADING_NAMES : names;
48
+ }
12
49
  const inheritParentAnnotationsKey = Symbol.for("@optique/core/inheritParentAnnotations");
13
50
  /**
14
51
  * Internal symbol for exposing field-level parser pairs from `object()`
@@ -454,7 +491,7 @@ function or(...args) {
454
491
  success: false
455
492
  };
456
493
  };
457
- return {
494
+ const singleResult = {
458
495
  $mode: combinedMode,
459
496
  $valueType: [],
460
497
  $stateType: [],
@@ -463,6 +500,8 @@ function or(...args) {
463
500
  type: "exclusive",
464
501
  terms: parsers.map((p) => p.usage)
465
502
  }],
503
+ leadingNames: unionLeadingNames(parsers),
504
+ acceptingAnyToken: parsers.some((p) => p.acceptingAnyToken),
466
505
  initialState: void 0,
467
506
  complete: createExclusiveComplete(parsers, options, noMatchContext, combinedMode),
468
507
  parse(context) {
@@ -496,6 +535,7 @@ function or(...args) {
496
535
  };
497
536
  }
498
537
  };
538
+ return singleResult;
499
539
  }
500
540
  /**
501
541
  * @since 0.5.0
@@ -591,7 +631,7 @@ function longestMatch(...args) {
591
631
  success: false
592
632
  };
593
633
  };
594
- return {
634
+ const multiResult = {
595
635
  $mode: combinedMode,
596
636
  $valueType: [],
597
637
  $stateType: [],
@@ -600,6 +640,8 @@ function longestMatch(...args) {
600
640
  type: "exclusive",
601
641
  terms: parsers.map((p) => p.usage)
602
642
  }],
643
+ leadingNames: unionLeadingNames(parsers),
644
+ acceptingAnyToken: parsers.some((p) => p.acceptingAnyToken),
603
645
  initialState: void 0,
604
646
  complete: createExclusiveComplete(parsers, options, noMatchContext, combinedMode),
605
647
  parse(context) {
@@ -640,6 +682,7 @@ function longestMatch(...args) {
640
682
  };
641
683
  }
642
684
  };
685
+ return multiResult;
643
686
  }
644
687
  /**
645
688
  * Internal sync helper for object suggest functionality.
@@ -1178,13 +1221,15 @@ function object(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
1178
1221
  success: false
1179
1222
  };
1180
1223
  };
1181
- return {
1224
+ const objectParser = {
1182
1225
  $mode: combinedMode,
1183
1226
  $valueType: [],
1184
1227
  $stateType: [],
1185
1228
  [fieldParsersKey]: parserPairs,
1186
1229
  priority: Math.max(...parserKeys.map((k) => parsers[k].priority)),
1187
1230
  usage: applyHiddenToUsage(parserPairs.flatMap(([_, p]) => p.usage), options.hidden),
1231
+ leadingNames: sharedBufferLeadingNames(parserPairs.map(([_, p]) => p)),
1232
+ acceptingAnyToken: parserPairs.some(([_, p]) => p.acceptingAnyToken),
1188
1233
  get initialState() {
1189
1234
  return createInitialState();
1190
1235
  },
@@ -1380,6 +1425,28 @@ function object(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
1380
1425
  })) };
1381
1426
  }
1382
1427
  };
1428
+ const fieldNormalizers = [];
1429
+ for (const [key, fieldParser] of parserPairs) if (typeof fieldParser.normalizeValue === "function") fieldNormalizers.push([key, fieldParser.normalizeValue.bind(fieldParser)]);
1430
+ if (fieldNormalizers.length > 0) Object.defineProperty(objectParser, "normalizeValue", {
1431
+ value(obj) {
1432
+ if (typeof obj !== "object" || obj == null) return obj;
1433
+ let changed = false;
1434
+ let result;
1435
+ for (const [key, normalize] of fieldNormalizers) if (Object.hasOwn(obj, key)) try {
1436
+ const original = obj[key];
1437
+ const normalized = normalize(original);
1438
+ if (normalized !== original) {
1439
+ if (!result) result = { ...obj };
1440
+ result[key] = normalized;
1441
+ changed = true;
1442
+ }
1443
+ } catch {}
1444
+ return changed ? result : obj;
1445
+ },
1446
+ configurable: true,
1447
+ enumerable: false
1448
+ });
1449
+ return objectParser;
1383
1450
  }
1384
1451
  function suggestTupleSync(context, prefix, parsers) {
1385
1452
  const suggestions = [];
@@ -1551,11 +1618,13 @@ function tuple(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
1551
1618
  consumed: allConsumed
1552
1619
  };
1553
1620
  };
1554
- return {
1621
+ const tupleParser = {
1555
1622
  $mode: combinedMode,
1556
1623
  $valueType: [],
1557
1624
  $stateType: [],
1558
1625
  usage: parsers.toSorted((a, b) => b.priority - a.priority).flatMap((p) => p.usage),
1626
+ leadingNames: sharedBufferLeadingNames(parsers),
1627
+ acceptingAnyToken: parsers.some((p) => p.acceptingAnyToken),
1559
1628
  priority: parsers.length > 0 ? Math.max(...parsers.map((p) => p.priority)) : 0,
1560
1629
  initialState: parsers.map((parser) => parser.initialState),
1561
1630
  parse(context) {
@@ -1723,6 +1792,31 @@ function tuple(labelOrParsers, maybeParsersOrOptions, maybeOptions) {
1723
1792
  return label ? `tuple(${JSON.stringify(label)}, ${parsersStr})` : `tuple(${parsersStr})`;
1724
1793
  }
1725
1794
  };
1795
+ const tupleNormalizers = [];
1796
+ for (let i = 0; i < parsers.length; i++) {
1797
+ const p = parsers[i];
1798
+ if (typeof p.normalizeValue === "function") tupleNormalizers.push([i, p.normalizeValue.bind(p)]);
1799
+ }
1800
+ if (tupleNormalizers.length > 0) Object.defineProperty(tupleParser, "normalizeValue", {
1801
+ value(arr) {
1802
+ if (!Array.isArray(arr)) return arr;
1803
+ let changed = false;
1804
+ let result;
1805
+ for (const [idx, normalize] of tupleNormalizers) if (idx < arr.length && Object.hasOwn(arr, idx)) try {
1806
+ const original = arr[idx];
1807
+ const normalized = normalize(original);
1808
+ if (normalized !== original) {
1809
+ if (!result) result = [...arr];
1810
+ result[idx] = normalized;
1811
+ changed = true;
1812
+ }
1813
+ } catch {}
1814
+ return changed ? result : arr;
1815
+ },
1816
+ configurable: true,
1817
+ enumerable: false
1818
+ });
1819
+ return tupleParser;
1726
1820
  }
1727
1821
  function merge(...args) {
1728
1822
  const label = typeof args[0] === "string" ? args[0] : void 0;
@@ -1870,13 +1964,15 @@ function merge(...args) {
1870
1964
  };
1871
1965
  };
1872
1966
  const mergedFieldParsers = collectChildFieldParsers(parsers);
1873
- return {
1967
+ const mergeParser = {
1874
1968
  $mode: combinedMode,
1875
1969
  $valueType: [],
1876
1970
  $stateType: [],
1877
1971
  [fieldParsersKey]: mergedFieldParsers,
1878
1972
  priority: Math.max(...parsers.map((p) => p.priority)),
1879
1973
  usage: applyHiddenToUsage(parsers.flatMap((p) => p.usage), options.hidden),
1974
+ leadingNames: sharedBufferLeadingNames(parsers),
1975
+ acceptingAnyToken: parsers.some((p) => p.acceptingAnyToken),
1880
1976
  initialState,
1881
1977
  parse(context) {
1882
1978
  if (isAsync) return parseAsync(context);
@@ -2087,6 +2183,7 @@ function merge(...args) {
2087
2183
  };
2088
2184
  }
2089
2185
  };
2186
+ return mergeParser;
2090
2187
  }
2091
2188
  /**
2092
2189
  * Builds a dependency registry from the pre-parsed context state and returns
@@ -2415,6 +2512,8 @@ function concat(...parsers) {
2415
2512
  $stateType: [],
2416
2513
  priority: parsers.length > 0 ? Math.max(...parsers.map((p) => p.priority)) : 0,
2417
2514
  usage: parsers.flatMap((p) => p.usage),
2515
+ leadingNames: sharedBufferLeadingNames(parsers),
2516
+ acceptingAnyToken: parsers.some((p) => p.acceptingAnyToken),
2418
2517
  initialState,
2419
2518
  parse(context) {
2420
2519
  if (isAsync) return parseAsync(context);
@@ -2492,6 +2591,8 @@ function group(label, parser, options = {}) {
2492
2591
  $stateType: parser.$stateType,
2493
2592
  priority: parser.priority,
2494
2593
  usage: applyHiddenToUsage(parser.usage, options.hidden),
2594
+ leadingNames: parser.leadingNames,
2595
+ acceptingAnyToken: parser.acceptingAnyToken,
2495
2596
  initialState: parser.initialState,
2496
2597
  ...fieldParsersKey in parser ? { [fieldParsersKey]: parser[fieldParsersKey] } : {},
2497
2598
  ...typeof parser.shouldDeferCompletion === "function" ? { shouldDeferCompletion: parser.shouldDeferCompletion.bind(parser) } : {},
@@ -2546,6 +2647,11 @@ function group(label, parser, options = {}) {
2546
2647
  configurable: true,
2547
2648
  enumerable: false
2548
2649
  });
2650
+ if (typeof parser.normalizeValue === "function") Object.defineProperty(groupParser, "normalizeValue", {
2651
+ value: parser.normalizeValue.bind(parser),
2652
+ configurable: true,
2653
+ enumerable: false
2654
+ });
2549
2655
  return groupParser;
2550
2656
  }
2551
2657
  /**
@@ -2976,6 +3082,8 @@ function conditional(discriminator, branches, defaultBranch, options) {
2976
3082
  $stateType: [],
2977
3083
  priority: maxPriority,
2978
3084
  usage,
3085
+ leadingNames: defaultBranch ? unionLeadingNames([discriminator, defaultBranch]) : discriminator.leadingNames,
3086
+ acceptingAnyToken: defaultBranch?.acceptingAnyToken ?? false,
2979
3087
  initialState,
2980
3088
  parse(context) {
2981
3089
  if (isAsync) return parseAsync(context);
@@ -199,6 +199,25 @@ function deriveFromAsync(options) {
199
199
  function isAsyncModeParser(parser) {
200
200
  return parser.$mode === "async";
201
201
  }
202
+ /**
203
+ * Shared helper for derived value parser `normalize()` implementations.
204
+ * Builds the inner parser from the factory and delegates to its
205
+ * `normalize()` if available, falling back to the original value on error.
206
+ */
207
+ function normalizeWithDerivedParser(value, getParser) {
208
+ let derivedParser;
209
+ try {
210
+ derivedParser = getParser();
211
+ } catch {
212
+ return value;
213
+ }
214
+ if (derivedParser && typeof derivedParser.normalize === "function") try {
215
+ return derivedParser.normalize(value);
216
+ } catch {
217
+ return value;
218
+ }
219
+ return value;
220
+ }
202
221
  function createSyncDerivedFromParser(sourceId, options) {
203
222
  const alldependencyIds = options.dependencies.map((dep) => dep[dependencyId]);
204
223
  return {
@@ -271,6 +290,9 @@ function createSyncDerivedFromParser(sourceId, options) {
271
290
  if (isAsyncModeParser(derivedParser) || !derivedParser.suggest) return;
272
291
  yield* derivedParser.suggest(prefix);
273
292
  },
293
+ normalize(value) {
294
+ return normalizeWithDerivedParser(value, () => options.factory(...options.defaultValues()));
295
+ },
274
296
  *[suggestWithDependency](prefix, dependencyValue) {
275
297
  let derivedParser;
276
298
  try {
@@ -345,6 +367,9 @@ function createAsyncDerivedFromParserFromAsyncFactory(sourceId, options) {
345
367
  }
346
368
  return derivedParser.format(value);
347
369
  },
370
+ normalize(value) {
371
+ return normalizeWithDerivedParser(value, () => options.factory(...options.defaultValues()));
372
+ },
348
373
  async *suggest(prefix) {
349
374
  let derivedParser;
350
375
  try {
@@ -428,6 +453,9 @@ function createAsyncDerivedFromParserFromSyncFactory(sourceId, options) {
428
453
  }
429
454
  return derivedParser.format(value);
430
455
  },
456
+ normalize(value) {
457
+ return normalizeWithDerivedParser(value, () => options.factory(...options.defaultValues()));
458
+ },
431
459
  async *suggest(prefix) {
432
460
  let derivedParser;
433
461
  try {
@@ -521,6 +549,9 @@ function createSyncDerivedParser(sourceId, options) {
521
549
  }
522
550
  return derivedParser.format(value);
523
551
  },
552
+ normalize(value) {
553
+ return normalizeWithDerivedParser(value, () => options.factory(options.defaultValue()));
554
+ },
524
555
  *suggest(prefix) {
525
556
  let derivedParser;
526
557
  try {
@@ -681,6 +712,9 @@ function createAsyncDerivedParserFromSyncFactory(sourceId, options) {
681
712
  }
682
713
  return derivedParser.format(value);
683
714
  },
715
+ normalize(value) {
716
+ return normalizeWithDerivedParser(value, () => options.factory(options.defaultValue()));
717
+ },
684
718
  async *suggest(prefix) {
685
719
  let derivedParser;
686
720
  try {
@@ -199,6 +199,25 @@ function deriveFromAsync(options) {
199
199
  function isAsyncModeParser(parser) {
200
200
  return parser.$mode === "async";
201
201
  }
202
+ /**
203
+ * Shared helper for derived value parser `normalize()` implementations.
204
+ * Builds the inner parser from the factory and delegates to its
205
+ * `normalize()` if available, falling back to the original value on error.
206
+ */
207
+ function normalizeWithDerivedParser(value, getParser) {
208
+ let derivedParser;
209
+ try {
210
+ derivedParser = getParser();
211
+ } catch {
212
+ return value;
213
+ }
214
+ if (derivedParser && typeof derivedParser.normalize === "function") try {
215
+ return derivedParser.normalize(value);
216
+ } catch {
217
+ return value;
218
+ }
219
+ return value;
220
+ }
202
221
  function createSyncDerivedFromParser(sourceId, options) {
203
222
  const alldependencyIds = options.dependencies.map((dep) => dep[dependencyId]);
204
223
  return {
@@ -271,6 +290,9 @@ function createSyncDerivedFromParser(sourceId, options) {
271
290
  if (isAsyncModeParser(derivedParser) || !derivedParser.suggest) return;
272
291
  yield* derivedParser.suggest(prefix);
273
292
  },
293
+ normalize(value) {
294
+ return normalizeWithDerivedParser(value, () => options.factory(...options.defaultValues()));
295
+ },
274
296
  *[suggestWithDependency](prefix, dependencyValue) {
275
297
  let derivedParser;
276
298
  try {
@@ -345,6 +367,9 @@ function createAsyncDerivedFromParserFromAsyncFactory(sourceId, options) {
345
367
  }
346
368
  return derivedParser.format(value);
347
369
  },
370
+ normalize(value) {
371
+ return normalizeWithDerivedParser(value, () => options.factory(...options.defaultValues()));
372
+ },
348
373
  async *suggest(prefix) {
349
374
  let derivedParser;
350
375
  try {
@@ -428,6 +453,9 @@ function createAsyncDerivedFromParserFromSyncFactory(sourceId, options) {
428
453
  }
429
454
  return derivedParser.format(value);
430
455
  },
456
+ normalize(value) {
457
+ return normalizeWithDerivedParser(value, () => options.factory(...options.defaultValues()));
458
+ },
431
459
  async *suggest(prefix) {
432
460
  let derivedParser;
433
461
  try {
@@ -521,6 +549,9 @@ function createSyncDerivedParser(sourceId, options) {
521
549
  }
522
550
  return derivedParser.format(value);
523
551
  },
552
+ normalize(value) {
553
+ return normalizeWithDerivedParser(value, () => options.factory(options.defaultValue()));
554
+ },
524
555
  *suggest(prefix) {
525
556
  let derivedParser;
526
557
  try {
@@ -681,6 +712,9 @@ function createAsyncDerivedParserFromSyncFactory(sourceId, options) {
681
712
  }
682
713
  return derivedParser.format(value);
683
714
  },
715
+ normalize(value) {
716
+ return normalizeWithDerivedParser(value, () => options.factory(options.defaultValue()));
717
+ },
684
718
  async *suggest(prefix) {
685
719
  let derivedParser;
686
720
  try {
package/dist/facade.cjs CHANGED
@@ -196,6 +196,8 @@ function combineWithHelpVersion(originalParser, helpParsers, versionParsers, com
196
196
  $stateType: [],
197
197
  priority: 200,
198
198
  usage: helpParsers.helpOption.usage,
199
+ leadingNames: helpParsers.helpOption.leadingNames,
200
+ acceptingAnyToken: false,
199
201
  initialState: null,
200
202
  parse(context) {
201
203
  const { buffer, optionsTerminated } = context;
@@ -275,6 +277,8 @@ function combineWithHelpVersion(originalParser, helpParsers, versionParsers, com
275
277
  $stateType: [],
276
278
  priority: 200,
277
279
  usage: versionParsers.versionOption.usage,
280
+ leadingNames: versionParsers.versionOption.leadingNames,
281
+ acceptingAnyToken: false,
278
282
  initialState: null,
279
283
  parse(context) {
280
284
  const { buffer, optionsTerminated } = context;
@@ -620,9 +624,7 @@ function runParser(parserOrProgram, programNameOrArgs, argsOrOptions, optionsPar
620
624
  completionCommandNames
621
625
  ]);
622
626
  require_validate.validateMetaNameCollisions({
623
- leadingOptions: require_usage.extractLeadingOptionNames(parser.usage, true),
624
- leadingCommands: require_usage.extractLeadingCommandNames(parser.usage, true),
625
- leadingLiterals: require_usage.extractLeadingLiteralValues(parser.usage),
627
+ leadingNames: parser.leadingNames,
626
628
  allOptions: require_usage.extractOptionNames(parser.usage, true),
627
629
  allCommands: require_usage.extractCommandNames(parser.usage, true),
628
630
  allLiterals: require_usage.extractLiteralValues(parser.usage)