@optique/core 1.0.0-dev.1495 → 1.0.0-dev.1500

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.
@@ -2,7 +2,6 @@ const require_annotations = require('./annotations.cjs');
2
2
  const require_message = require('./message.cjs');
3
3
  const require_dependency = require('./dependency.cjs');
4
4
  const require_mode_dispatch = require('./mode-dispatch.cjs');
5
- const require_context = require('./context.cjs');
6
5
 
7
6
  //#region src/modifiers.ts
8
7
  /**
@@ -123,6 +122,7 @@ function optional(parser) {
123
122
  $mode: parser.$mode,
124
123
  $valueType: [],
125
124
  $stateType: [],
125
+ placeholder: void 0,
126
126
  priority: parser.priority,
127
127
  usage: [{
128
128
  type: "optional",
@@ -237,7 +237,7 @@ function withDefault(parser, defaultValue, options) {
237
237
  }
238
238
  const innerInitialState = syncParser.initialState;
239
239
  const wrappedDependencyMarker = require_dependency.isPendingDependencySourceState(innerInitialState) ? { [require_dependency.wrappedDependencySourceMarker]: innerInitialState } : require_dependency.isWrappedDependencySource(parser) ? { [require_dependency.wrappedDependencySourceMarker]: parser[require_dependency.wrappedDependencySourceMarker] } : {};
240
- return {
240
+ const withDefaultParser = {
241
241
  $mode: parser.$mode,
242
242
  $valueType: [],
243
243
  $stateType: [],
@@ -386,6 +386,14 @@ function withDefault(parser, defaultValue, options) {
386
386
  return fragments;
387
387
  }
388
388
  };
389
+ if ("placeholder" in parser) Object.defineProperty(withDefaultParser, "placeholder", {
390
+ get() {
391
+ return parser.placeholder;
392
+ },
393
+ configurable: true,
394
+ enumerable: false
395
+ });
396
+ return withDefaultParser;
389
397
  }
390
398
  /**
391
399
  * Creates a parser that transforms the result value of another parser using
@@ -406,6 +414,47 @@ function withDefault(parser, defaultValue, options) {
406
414
  * @param transform A function that transforms the parsed value from type T to type U.
407
415
  * @returns A {@link Parser} that produces the transformed value of type U
408
416
  * while preserving the original parser's state type and parsing behavior.
417
+ * @throws Any exception thrown by `transform` when completing a non-deferred
418
+ * value. Errors from deferred placeholder transforms are caught and the
419
+ * mapped result falls back to `undefined` with `deferred: true`.
420
+ *
421
+ * ### Deferred prompt interaction
422
+ *
423
+ * During two-phase parsing, `map()` propagates the `deferred` flag from
424
+ * inner results but intentionally drops per-field `deferredKeys`. The
425
+ * inner key set describes the *input* shape, but `transform` produces an
426
+ * arbitrary *output* shape where keys may be renamed, dropped, or reused
427
+ * with different semantics. For `object()` results that are *not*
428
+ * wrapped in `map()`, per-field deferred stripping works normally.
429
+ *
430
+ * Because the `deferred` flag is propagated conservatively, mapped scalar
431
+ * results are treated as missing (`undefined`) during phase-two context
432
+ * collection — even when `transform` only used non-deferred fields.
433
+ * For example, `map(object({ apiKey: prompt(...), mode: option(...) }),
434
+ * v => v.mode)` makes phase-two contexts see `undefined` instead of the
435
+ * real `mode` value. This is the intentional trade-off: the alternative
436
+ * (not propagating `deferred`) would leak placeholder values into context
437
+ * resolution when `transform` *does* use deferred fields. The final
438
+ * parse always produces the correct result regardless.
439
+ *
440
+ * If the transform throws on a deferred placeholder value, the mapped
441
+ * result falls back to `undefined` with `deferred: true`, so the first
442
+ * pass does not abort.
443
+ *
444
+ * ### Transform purity
445
+ *
446
+ * The `transform` function must not mutate its input. Object and array
447
+ * values may be shared placeholder references during deferred prompt
448
+ * resolution, and in-place mutations would corrupt the placeholder for
449
+ * subsequent parses. Always return a new value:
450
+ *
451
+ * ```typescript
452
+ * // ✅ Correct — creates a new object
453
+ * map(parser, v => ({ ...v, host: "override" }))
454
+ *
455
+ * // ❌ Wrong — mutates the input in place
456
+ * map(parser, v => { v.host = "override"; return v; })
457
+ * ```
409
458
  *
410
459
  * @example
411
460
  * ```typescript
@@ -423,16 +472,32 @@ function withDefault(parser, defaultValue, options) {
423
472
  */
424
473
  function map(parser, transform) {
425
474
  const complete = (state) => {
426
- return require_mode_dispatch.mapModeValue(parser.$mode, parser.complete(state), (result) => result.success ? require_context.isPlaceholderValue(result.value) ? result : {
427
- success: true,
428
- value: transform(result.value)
429
- } : result);
475
+ return require_mode_dispatch.mapModeValue(parser.$mode, parser.complete(state), (result) => {
476
+ if (!result.success) return result;
477
+ if (result.deferred) try {
478
+ return {
479
+ success: true,
480
+ value: transform(result.value),
481
+ deferred: true
482
+ };
483
+ } catch {
484
+ return {
485
+ success: true,
486
+ value: void 0,
487
+ deferred: true
488
+ };
489
+ }
490
+ return {
491
+ success: true,
492
+ value: transform(result.value)
493
+ };
494
+ });
430
495
  };
431
496
  const dependencyMarkers = require_dependency.isWrappedDependencySource(parser) ? {
432
497
  [require_dependency.wrappedDependencySourceMarker]: parser[require_dependency.wrappedDependencySourceMarker],
433
498
  [require_dependency.transformsDependencyValueMarker]: true
434
499
  } : {};
435
- return {
500
+ const mappedParser = {
436
501
  ...parser,
437
502
  $valueType: [],
438
503
  complete,
@@ -441,6 +506,18 @@ function map(parser, transform) {
441
506
  return parser.getDocFragments(state, void 0);
442
507
  }
443
508
  };
509
+ if ("placeholder" in parser) Object.defineProperty(mappedParser, "placeholder", {
510
+ get() {
511
+ try {
512
+ return transform(parser.placeholder);
513
+ } catch {
514
+ return void 0;
515
+ }
516
+ },
517
+ configurable: true,
518
+ enumerable: false
519
+ });
520
+ return mappedParser;
444
521
  }
445
522
  /**
446
523
  * Creates a parser that allows multiple occurrences of a given parser.
@@ -580,24 +657,41 @@ function multiple(parser, options = {}) {
580
657
  complete(state) {
581
658
  return require_mode_dispatch.dispatchByMode(parser.$mode, () => {
582
659
  const result = [];
583
- for (const s of state) {
584
- const valueResult = completeSyncWithUnwrappedFallback(s);
585
- if (valueResult.success) result.push(unwrapInjectedWrapper(valueResult.value));
586
- else return {
660
+ const deferredIndices = /* @__PURE__ */ new Map();
661
+ let hasDeferred = false;
662
+ for (let i = 0; i < state.length; i++) {
663
+ const valueResult = completeSyncWithUnwrappedFallback(state[i]);
664
+ if (valueResult.success) {
665
+ const unwrappedValue = unwrapInjectedWrapper(valueResult.value);
666
+ result.push(unwrappedValue);
667
+ if (valueResult.deferred) if (valueResult.deferredKeys) deferredIndices.set(i, valueResult.deferredKeys);
668
+ else if (unwrappedValue == null || typeof unwrappedValue !== "object") deferredIndices.set(i, null);
669
+ else hasDeferred = true;
670
+ } else return {
587
671
  success: false,
588
672
  error: valueResult.error
589
673
  };
590
674
  }
591
- return validateMultipleResult(result);
675
+ return validateMultipleResult(result, deferredIndices, hasDeferred);
592
676
  }, async () => {
593
677
  const results = await Promise.all(state.map((s) => completeAsyncWithUnwrappedFallback(s)));
594
678
  const values = [];
595
- for (const valueResult of results) if (valueResult.success) values.push(unwrapInjectedWrapper(valueResult.value));
596
- else return {
597
- success: false,
598
- error: valueResult.error
599
- };
600
- return validateMultipleResult(values);
679
+ const deferredIndices = /* @__PURE__ */ new Map();
680
+ let hasDeferred = false;
681
+ for (let i = 0; i < results.length; i++) {
682
+ const valueResult = results[i];
683
+ if (valueResult.success) {
684
+ const unwrappedValue = unwrapInjectedWrapper(valueResult.value);
685
+ values.push(unwrappedValue);
686
+ if (valueResult.deferred) if (valueResult.deferredKeys) deferredIndices.set(i, valueResult.deferredKeys);
687
+ else if (unwrappedValue == null || typeof unwrappedValue !== "object") deferredIndices.set(i, null);
688
+ else hasDeferred = true;
689
+ } else return {
690
+ success: false,
691
+ error: valueResult.error
692
+ };
693
+ }
694
+ return validateMultipleResult(values, deferredIndices, hasDeferred);
601
695
  });
602
696
  },
603
697
  suggest(context, prefix) {
@@ -694,7 +788,7 @@ function multiple(parser, options = {}) {
694
788
  return syncParser.getDocFragments(innerState, defaultValue != null && defaultValue.length > 0 ? defaultValue[0] : void 0);
695
789
  }
696
790
  };
697
- function validateMultipleResult(result) {
791
+ function validateMultipleResult(result, deferredIndices, hasDeferred = false) {
698
792
  if (result.length < min) {
699
793
  const customMessage = options.errors?.tooFew;
700
794
  return {
@@ -708,11 +802,26 @@ function multiple(parser, options = {}) {
708
802
  error: customMessage ? typeof customMessage === "function" ? customMessage(max, result.length) : customMessage : require_message.message`Expected at most ${require_message.text(max.toLocaleString("en"))} values, but got ${require_message.text(result.length.toLocaleString("en"))}.`
709
803
  };
710
804
  }
805
+ const isDeferred = deferredIndices.size > 0 || hasDeferred;
711
806
  return {
712
807
  success: true,
713
- value: result
808
+ value: result,
809
+ ...isDeferred ? {
810
+ deferred: true,
811
+ ...deferredIndices.size > 0 ? { deferredKeys: deferredIndices } : {}
812
+ } : {}
714
813
  };
715
814
  }
815
+ Object.defineProperty(resultParser, "placeholder", {
816
+ get() {
817
+ try {
818
+ if (min > 0 && "placeholder" in parser) return Array.from({ length: min }, () => parser.placeholder);
819
+ } catch {}
820
+ return [];
821
+ },
822
+ configurable: true,
823
+ enumerable: false
824
+ });
716
825
  return resultParser;
717
826
  }
718
827
  /**
@@ -771,13 +880,14 @@ function nonEmpty(parser) {
771
880
  const result = await parser.parse(context);
772
881
  return processNonEmptyResult(result);
773
882
  };
774
- return {
883
+ const nonEmptyParser = {
775
884
  $mode: parser.$mode,
776
885
  $valueType: parser.$valueType,
777
886
  $stateType: parser.$stateType,
778
887
  priority: parser.priority,
779
888
  usage: parser.usage,
780
889
  initialState: parser.initialState,
890
+ ...typeof parser.shouldDeferCompletion === "function" ? { shouldDeferCompletion: parser.shouldDeferCompletion.bind(parser) } : {},
781
891
  parse(context) {
782
892
  return require_mode_dispatch.dispatchByMode(parser.$mode, () => parseSync(context), () => parseAsync(context));
783
893
  },
@@ -791,6 +901,14 @@ function nonEmpty(parser) {
791
901
  return syncParser.getDocFragments(state, defaultValue);
792
902
  }
793
903
  };
904
+ if ("placeholder" in parser) Object.defineProperty(nonEmptyParser, "placeholder", {
905
+ get() {
906
+ return parser.placeholder;
907
+ },
908
+ configurable: true,
909
+ enumerable: false
910
+ });
911
+ return nonEmptyParser;
794
912
  }
795
913
 
796
914
  //#endregion
@@ -123,6 +123,47 @@ declare function withDefault<M extends Mode, TValue, TState, const TDefault = TV
123
123
  * @param transform A function that transforms the parsed value from type T to type U.
124
124
  * @returns A {@link Parser} that produces the transformed value of type U
125
125
  * while preserving the original parser's state type and parsing behavior.
126
+ * @throws Any exception thrown by `transform` when completing a non-deferred
127
+ * value. Errors from deferred placeholder transforms are caught and the
128
+ * mapped result falls back to `undefined` with `deferred: true`.
129
+ *
130
+ * ### Deferred prompt interaction
131
+ *
132
+ * During two-phase parsing, `map()` propagates the `deferred` flag from
133
+ * inner results but intentionally drops per-field `deferredKeys`. The
134
+ * inner key set describes the *input* shape, but `transform` produces an
135
+ * arbitrary *output* shape where keys may be renamed, dropped, or reused
136
+ * with different semantics. For `object()` results that are *not*
137
+ * wrapped in `map()`, per-field deferred stripping works normally.
138
+ *
139
+ * Because the `deferred` flag is propagated conservatively, mapped scalar
140
+ * results are treated as missing (`undefined`) during phase-two context
141
+ * collection — even when `transform` only used non-deferred fields.
142
+ * For example, `map(object({ apiKey: prompt(...), mode: option(...) }),
143
+ * v => v.mode)` makes phase-two contexts see `undefined` instead of the
144
+ * real `mode` value. This is the intentional trade-off: the alternative
145
+ * (not propagating `deferred`) would leak placeholder values into context
146
+ * resolution when `transform` *does* use deferred fields. The final
147
+ * parse always produces the correct result regardless.
148
+ *
149
+ * If the transform throws on a deferred placeholder value, the mapped
150
+ * result falls back to `undefined` with `deferred: true`, so the first
151
+ * pass does not abort.
152
+ *
153
+ * ### Transform purity
154
+ *
155
+ * The `transform` function must not mutate its input. Object and array
156
+ * values may be shared placeholder references during deferred prompt
157
+ * resolution, and in-place mutations would corrupt the placeholder for
158
+ * subsequent parses. Always return a new value:
159
+ *
160
+ * ```typescript
161
+ * // ✅ Correct — creates a new object
162
+ * map(parser, v => ({ ...v, host: "override" }))
163
+ *
164
+ * // ❌ Wrong — mutates the input in place
165
+ * map(parser, v => { v.host = "override"; return v; })
166
+ * ```
126
167
  *
127
168
  * @example
128
169
  * ```typescript
@@ -123,6 +123,47 @@ declare function withDefault<M extends Mode, TValue, TState, const TDefault = TV
123
123
  * @param transform A function that transforms the parsed value from type T to type U.
124
124
  * @returns A {@link Parser} that produces the transformed value of type U
125
125
  * while preserving the original parser's state type and parsing behavior.
126
+ * @throws Any exception thrown by `transform` when completing a non-deferred
127
+ * value. Errors from deferred placeholder transforms are caught and the
128
+ * mapped result falls back to `undefined` with `deferred: true`.
129
+ *
130
+ * ### Deferred prompt interaction
131
+ *
132
+ * During two-phase parsing, `map()` propagates the `deferred` flag from
133
+ * inner results but intentionally drops per-field `deferredKeys`. The
134
+ * inner key set describes the *input* shape, but `transform` produces an
135
+ * arbitrary *output* shape where keys may be renamed, dropped, or reused
136
+ * with different semantics. For `object()` results that are *not*
137
+ * wrapped in `map()`, per-field deferred stripping works normally.
138
+ *
139
+ * Because the `deferred` flag is propagated conservatively, mapped scalar
140
+ * results are treated as missing (`undefined`) during phase-two context
141
+ * collection — even when `transform` only used non-deferred fields.
142
+ * For example, `map(object({ apiKey: prompt(...), mode: option(...) }),
143
+ * v => v.mode)` makes phase-two contexts see `undefined` instead of the
144
+ * real `mode` value. This is the intentional trade-off: the alternative
145
+ * (not propagating `deferred`) would leak placeholder values into context
146
+ * resolution when `transform` *does* use deferred fields. The final
147
+ * parse always produces the correct result regardless.
148
+ *
149
+ * If the transform throws on a deferred placeholder value, the mapped
150
+ * result falls back to `undefined` with `deferred: true`, so the first
151
+ * pass does not abort.
152
+ *
153
+ * ### Transform purity
154
+ *
155
+ * The `transform` function must not mutate its input. Object and array
156
+ * values may be shared placeholder references during deferred prompt
157
+ * resolution, and in-place mutations would corrupt the placeholder for
158
+ * subsequent parses. Always return a new value:
159
+ *
160
+ * ```typescript
161
+ * // ✅ Correct — creates a new object
162
+ * map(parser, v => ({ ...v, host: "override" }))
163
+ *
164
+ * // ❌ Wrong — mutates the input in place
165
+ * map(parser, v => { v.host = "override"; return v; })
166
+ * ```
126
167
  *
127
168
  * @example
128
169
  * ```typescript
package/dist/modifiers.js CHANGED
@@ -2,7 +2,6 @@ import { annotateFreshArray, getAnnotations, inheritAnnotations, isInjectedAnnot
2
2
  import { formatMessage, message, text } from "./message.js";
3
3
  import { createDependencySourceState, dependencyId, isDependencySourceState, isPendingDependencySourceState, isWrappedDependencySource, transformsDependencyValue, transformsDependencyValueMarker, wrappedDependencySourceMarker } from "./dependency.js";
4
4
  import { dispatchByMode, dispatchIterableByMode, mapModeValue } from "./mode-dispatch.js";
5
- import { isPlaceholderValue } from "./context.js";
6
5
 
7
6
  //#region src/modifiers.ts
8
7
  /**
@@ -123,6 +122,7 @@ function optional(parser) {
123
122
  $mode: parser.$mode,
124
123
  $valueType: [],
125
124
  $stateType: [],
125
+ placeholder: void 0,
126
126
  priority: parser.priority,
127
127
  usage: [{
128
128
  type: "optional",
@@ -237,7 +237,7 @@ function withDefault(parser, defaultValue, options) {
237
237
  }
238
238
  const innerInitialState = syncParser.initialState;
239
239
  const wrappedDependencyMarker = isPendingDependencySourceState(innerInitialState) ? { [wrappedDependencySourceMarker]: innerInitialState } : isWrappedDependencySource(parser) ? { [wrappedDependencySourceMarker]: parser[wrappedDependencySourceMarker] } : {};
240
- return {
240
+ const withDefaultParser = {
241
241
  $mode: parser.$mode,
242
242
  $valueType: [],
243
243
  $stateType: [],
@@ -386,6 +386,14 @@ function withDefault(parser, defaultValue, options) {
386
386
  return fragments;
387
387
  }
388
388
  };
389
+ if ("placeholder" in parser) Object.defineProperty(withDefaultParser, "placeholder", {
390
+ get() {
391
+ return parser.placeholder;
392
+ },
393
+ configurable: true,
394
+ enumerable: false
395
+ });
396
+ return withDefaultParser;
389
397
  }
390
398
  /**
391
399
  * Creates a parser that transforms the result value of another parser using
@@ -406,6 +414,47 @@ function withDefault(parser, defaultValue, options) {
406
414
  * @param transform A function that transforms the parsed value from type T to type U.
407
415
  * @returns A {@link Parser} that produces the transformed value of type U
408
416
  * while preserving the original parser's state type and parsing behavior.
417
+ * @throws Any exception thrown by `transform` when completing a non-deferred
418
+ * value. Errors from deferred placeholder transforms are caught and the
419
+ * mapped result falls back to `undefined` with `deferred: true`.
420
+ *
421
+ * ### Deferred prompt interaction
422
+ *
423
+ * During two-phase parsing, `map()` propagates the `deferred` flag from
424
+ * inner results but intentionally drops per-field `deferredKeys`. The
425
+ * inner key set describes the *input* shape, but `transform` produces an
426
+ * arbitrary *output* shape where keys may be renamed, dropped, or reused
427
+ * with different semantics. For `object()` results that are *not*
428
+ * wrapped in `map()`, per-field deferred stripping works normally.
429
+ *
430
+ * Because the `deferred` flag is propagated conservatively, mapped scalar
431
+ * results are treated as missing (`undefined`) during phase-two context
432
+ * collection — even when `transform` only used non-deferred fields.
433
+ * For example, `map(object({ apiKey: prompt(...), mode: option(...) }),
434
+ * v => v.mode)` makes phase-two contexts see `undefined` instead of the
435
+ * real `mode` value. This is the intentional trade-off: the alternative
436
+ * (not propagating `deferred`) would leak placeholder values into context
437
+ * resolution when `transform` *does* use deferred fields. The final
438
+ * parse always produces the correct result regardless.
439
+ *
440
+ * If the transform throws on a deferred placeholder value, the mapped
441
+ * result falls back to `undefined` with `deferred: true`, so the first
442
+ * pass does not abort.
443
+ *
444
+ * ### Transform purity
445
+ *
446
+ * The `transform` function must not mutate its input. Object and array
447
+ * values may be shared placeholder references during deferred prompt
448
+ * resolution, and in-place mutations would corrupt the placeholder for
449
+ * subsequent parses. Always return a new value:
450
+ *
451
+ * ```typescript
452
+ * // ✅ Correct — creates a new object
453
+ * map(parser, v => ({ ...v, host: "override" }))
454
+ *
455
+ * // ❌ Wrong — mutates the input in place
456
+ * map(parser, v => { v.host = "override"; return v; })
457
+ * ```
409
458
  *
410
459
  * @example
411
460
  * ```typescript
@@ -423,16 +472,32 @@ function withDefault(parser, defaultValue, options) {
423
472
  */
424
473
  function map(parser, transform) {
425
474
  const complete = (state) => {
426
- return mapModeValue(parser.$mode, parser.complete(state), (result) => result.success ? isPlaceholderValue(result.value) ? result : {
427
- success: true,
428
- value: transform(result.value)
429
- } : result);
475
+ return mapModeValue(parser.$mode, parser.complete(state), (result) => {
476
+ if (!result.success) return result;
477
+ if (result.deferred) try {
478
+ return {
479
+ success: true,
480
+ value: transform(result.value),
481
+ deferred: true
482
+ };
483
+ } catch {
484
+ return {
485
+ success: true,
486
+ value: void 0,
487
+ deferred: true
488
+ };
489
+ }
490
+ return {
491
+ success: true,
492
+ value: transform(result.value)
493
+ };
494
+ });
430
495
  };
431
496
  const dependencyMarkers = isWrappedDependencySource(parser) ? {
432
497
  [wrappedDependencySourceMarker]: parser[wrappedDependencySourceMarker],
433
498
  [transformsDependencyValueMarker]: true
434
499
  } : {};
435
- return {
500
+ const mappedParser = {
436
501
  ...parser,
437
502
  $valueType: [],
438
503
  complete,
@@ -441,6 +506,18 @@ function map(parser, transform) {
441
506
  return parser.getDocFragments(state, void 0);
442
507
  }
443
508
  };
509
+ if ("placeholder" in parser) Object.defineProperty(mappedParser, "placeholder", {
510
+ get() {
511
+ try {
512
+ return transform(parser.placeholder);
513
+ } catch {
514
+ return void 0;
515
+ }
516
+ },
517
+ configurable: true,
518
+ enumerable: false
519
+ });
520
+ return mappedParser;
444
521
  }
445
522
  /**
446
523
  * Creates a parser that allows multiple occurrences of a given parser.
@@ -580,24 +657,41 @@ function multiple(parser, options = {}) {
580
657
  complete(state) {
581
658
  return dispatchByMode(parser.$mode, () => {
582
659
  const result = [];
583
- for (const s of state) {
584
- const valueResult = completeSyncWithUnwrappedFallback(s);
585
- if (valueResult.success) result.push(unwrapInjectedWrapper(valueResult.value));
586
- else return {
660
+ const deferredIndices = /* @__PURE__ */ new Map();
661
+ let hasDeferred = false;
662
+ for (let i = 0; i < state.length; i++) {
663
+ const valueResult = completeSyncWithUnwrappedFallback(state[i]);
664
+ if (valueResult.success) {
665
+ const unwrappedValue = unwrapInjectedWrapper(valueResult.value);
666
+ result.push(unwrappedValue);
667
+ if (valueResult.deferred) if (valueResult.deferredKeys) deferredIndices.set(i, valueResult.deferredKeys);
668
+ else if (unwrappedValue == null || typeof unwrappedValue !== "object") deferredIndices.set(i, null);
669
+ else hasDeferred = true;
670
+ } else return {
587
671
  success: false,
588
672
  error: valueResult.error
589
673
  };
590
674
  }
591
- return validateMultipleResult(result);
675
+ return validateMultipleResult(result, deferredIndices, hasDeferred);
592
676
  }, async () => {
593
677
  const results = await Promise.all(state.map((s) => completeAsyncWithUnwrappedFallback(s)));
594
678
  const values = [];
595
- for (const valueResult of results) if (valueResult.success) values.push(unwrapInjectedWrapper(valueResult.value));
596
- else return {
597
- success: false,
598
- error: valueResult.error
599
- };
600
- return validateMultipleResult(values);
679
+ const deferredIndices = /* @__PURE__ */ new Map();
680
+ let hasDeferred = false;
681
+ for (let i = 0; i < results.length; i++) {
682
+ const valueResult = results[i];
683
+ if (valueResult.success) {
684
+ const unwrappedValue = unwrapInjectedWrapper(valueResult.value);
685
+ values.push(unwrappedValue);
686
+ if (valueResult.deferred) if (valueResult.deferredKeys) deferredIndices.set(i, valueResult.deferredKeys);
687
+ else if (unwrappedValue == null || typeof unwrappedValue !== "object") deferredIndices.set(i, null);
688
+ else hasDeferred = true;
689
+ } else return {
690
+ success: false,
691
+ error: valueResult.error
692
+ };
693
+ }
694
+ return validateMultipleResult(values, deferredIndices, hasDeferred);
601
695
  });
602
696
  },
603
697
  suggest(context, prefix) {
@@ -694,7 +788,7 @@ function multiple(parser, options = {}) {
694
788
  return syncParser.getDocFragments(innerState, defaultValue != null && defaultValue.length > 0 ? defaultValue[0] : void 0);
695
789
  }
696
790
  };
697
- function validateMultipleResult(result) {
791
+ function validateMultipleResult(result, deferredIndices, hasDeferred = false) {
698
792
  if (result.length < min) {
699
793
  const customMessage = options.errors?.tooFew;
700
794
  return {
@@ -708,11 +802,26 @@ function multiple(parser, options = {}) {
708
802
  error: customMessage ? typeof customMessage === "function" ? customMessage(max, result.length) : customMessage : message`Expected at most ${text(max.toLocaleString("en"))} values, but got ${text(result.length.toLocaleString("en"))}.`
709
803
  };
710
804
  }
805
+ const isDeferred = deferredIndices.size > 0 || hasDeferred;
711
806
  return {
712
807
  success: true,
713
- value: result
808
+ value: result,
809
+ ...isDeferred ? {
810
+ deferred: true,
811
+ ...deferredIndices.size > 0 ? { deferredKeys: deferredIndices } : {}
812
+ } : {}
714
813
  };
715
814
  }
815
+ Object.defineProperty(resultParser, "placeholder", {
816
+ get() {
817
+ try {
818
+ if (min > 0 && "placeholder" in parser) return Array.from({ length: min }, () => parser.placeholder);
819
+ } catch {}
820
+ return [];
821
+ },
822
+ configurable: true,
823
+ enumerable: false
824
+ });
716
825
  return resultParser;
717
826
  }
718
827
  /**
@@ -771,13 +880,14 @@ function nonEmpty(parser) {
771
880
  const result = await parser.parse(context);
772
881
  return processNonEmptyResult(result);
773
882
  };
774
- return {
883
+ const nonEmptyParser = {
775
884
  $mode: parser.$mode,
776
885
  $valueType: parser.$valueType,
777
886
  $stateType: parser.$stateType,
778
887
  priority: parser.priority,
779
888
  usage: parser.usage,
780
889
  initialState: parser.initialState,
890
+ ...typeof parser.shouldDeferCompletion === "function" ? { shouldDeferCompletion: parser.shouldDeferCompletion.bind(parser) } : {},
781
891
  parse(context) {
782
892
  return dispatchByMode(parser.$mode, () => parseSync(context), () => parseAsync(context));
783
893
  },
@@ -791,6 +901,14 @@ function nonEmpty(parser) {
791
901
  return syncParser.getDocFragments(state, defaultValue);
792
902
  }
793
903
  };
904
+ if ("placeholder" in parser) Object.defineProperty(nonEmptyParser, "placeholder", {
905
+ get() {
906
+ return parser.placeholder;
907
+ },
908
+ configurable: true,
909
+ enumerable: false
910
+ });
911
+ return nonEmptyParser;
794
912
  }
795
913
 
796
914
  //#endregion
package/dist/parser.cjs CHANGED
@@ -60,7 +60,9 @@ function parseSync(parser, args, options) {
60
60
  const endResult = parser.complete(context.state);
61
61
  return endResult.success ? {
62
62
  success: true,
63
- value: shouldUnwrapAnnotatedValue ? require_annotations.unwrapInjectedAnnotationWrapper(endResult.value) : endResult.value
63
+ value: shouldUnwrapAnnotatedValue ? require_annotations.unwrapInjectedAnnotationWrapper(endResult.value) : endResult.value,
64
+ ...endResult.deferred ? { deferred: true } : {},
65
+ ...endResult.deferredKeys ? { deferredKeys: endResult.deferredKeys } : {}
64
66
  } : {
65
67
  success: false,
66
68
  error: endResult.error
@@ -110,7 +112,9 @@ async function parseAsync(parser, args, options) {
110
112
  const endResult = await parser.complete(context.state);
111
113
  return endResult.success ? {
112
114
  success: true,
113
- value: shouldUnwrapAnnotatedValue ? require_annotations.unwrapInjectedAnnotationWrapper(endResult.value) : endResult.value
115
+ value: shouldUnwrapAnnotatedValue ? require_annotations.unwrapInjectedAnnotationWrapper(endResult.value) : endResult.value,
116
+ ...endResult.deferred ? { deferred: true } : {},
117
+ ...endResult.deferredKeys ? { deferredKeys: endResult.deferredKeys } : {}
114
118
  } : {
115
119
  success: false,
116
120
  error: endResult.error