@optique/core 1.2.0-dev.2234 → 1.2.0-dev.2236

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.
@@ -913,10 +913,60 @@ function makeFallbackDeferredValue(fallback, memoize) {
913
913
  };
914
914
  return brandDeferredValue(call, "fallback");
915
915
  }
916
+ /**
917
+ * Wraps a parser so its value is resolved by the command handler instead of
918
+ * during parsing.
919
+ *
920
+ * The parsed field becomes a {@link DeferredValue}: a value-producing function.
921
+ * When the wrapped parser produced a value, calling the function returns that
922
+ * value and {@link DeferredValue.source} is `"specified"`. A value resolved
923
+ * from a source such as `bindEnv()`/`bindConfig()` counts as produced. When
924
+ * the wrapped parser did not produce a value, calling the function runs
925
+ * `fallback` and `source` is `"fallback"`. Because a missing value is reported
926
+ * as `undefined`, a wrapped parser that yields `undefined` is treated as having
927
+ * produced no value and selects the fallback. The fallback runs at handler
928
+ * time, so its errors are handler errors rather than parser errors. A value
929
+ * that is specified but invalid still fails during parsing.
930
+ *
931
+ * Like {@link optional}, the wrapped parser keeps its place in usage and help;
932
+ * only the result type changes. The fallback context type `C` is inferred from
933
+ * the `fallback` parameter.
934
+ *
935
+ * @example
936
+ * ```typescript
937
+ * const parser = object({
938
+ * serviceName: option("--service-name", string()),
939
+ * apiToken: deferredValue(
940
+ * option("--api-token", string()),
941
+ * ({ serviceName }: { readonly serviceName: string }) =>
942
+ * promptForApiToken(serviceName),
943
+ * ),
944
+ * });
945
+ *
946
+ * const parsed = parse(parser, argv);
947
+ * // The prompt only runs if this branch is reached.
948
+ * const apiToken = await parsed.apiToken({
949
+ * serviceName: parsed.serviceName,
950
+ * });
951
+ * ```
952
+ *
953
+ * @template M The execution mode of the wrapped parser.
954
+ * @template T The resolved value type.
955
+ * @template S The state type of the wrapped parser.
956
+ * @template C The handler-time context type, inferred from `fallback`. A
957
+ * fallback without a parameter yields a no-argument
958
+ * {@link DeferredValue}; one whose parameter is optional or includes
959
+ * `undefined` stays callable with no argument.
960
+ * @param parser The parser that reads the CLI value.
961
+ * @param fallback A resolver run at handler time when no value was specified.
962
+ * @param options Optional {@link DeferredValueOptions}.
963
+ * @returns A parser whose value is a {@link DeferredValue}.
964
+ * @since 1.2.0
965
+ */
916
966
  function deferredValue(parser, fallback, options) {
917
967
  const memoize = options?.memoize ?? false;
918
968
  const base = optional(parser);
919
- const complete = (state, exec) => require_mode_dispatch.mapModeValue(base.mode, base.complete(state, exec), (result) => {
969
+ const complete = (state, exec) => require_mode_dispatch.wrapForMode(base.mode, require_mode_dispatch.mapModeValue(base.mode, base.complete(state, exec), (result) => {
920
970
  if (!result.success) return result;
921
971
  const value = result.value === void 0 ? makeFallbackDeferredValue(fallback, memoize) : makeSpecifiedDeferredValue(result.value);
922
972
  return result.deferred ? {
@@ -927,7 +977,7 @@ function deferredValue(parser, fallback, options) {
927
977
  success: true,
928
978
  value
929
979
  };
930
- });
980
+ }));
931
981
  const descriptors = Object.getOwnPropertyDescriptors(base);
932
982
  descriptors.complete = {
933
983
  value: complete,
@@ -266,14 +266,17 @@ interface DeferredValueOptions {
266
266
  * @template M The execution mode of the wrapped parser.
267
267
  * @template T The resolved value type.
268
268
  * @template S The state type of the wrapped parser.
269
+ * @template C The handler-time context type, inferred from `fallback`. A
270
+ * fallback without a parameter yields a no-argument
271
+ * {@link DeferredValue}; one whose parameter is optional or includes
272
+ * `undefined` stays callable with no argument.
269
273
  * @param parser The parser that reads the CLI value.
270
274
  * @param fallback A resolver run at handler time when no value was specified.
271
275
  * @param options Optional {@link DeferredValueOptions}.
272
276
  * @returns A parser whose value is a {@link DeferredValue}.
273
277
  * @since 1.2.0
274
278
  */
275
- declare function deferredValue<M extends Mode, T, S>(parser: Parser<M, T, S>, fallback: () => T | Promise<T>, options?: DeferredValueOptions): FluentParser<M, DeferredValue<T>, [S] | undefined>;
276
- declare function deferredValue<M extends Mode, T, S, C>(parser: Parser<M, T, S>, fallback: (ctx: C) => T | Promise<T>, options?: DeferredValueOptions): FluentParser<M, DeferredValue<T, C>, [S] | undefined>;
279
+ declare function deferredValue<M extends Mode, T, S, C = void>(parser: Parser<M, T, S>, fallback: (ctx: C) => T | Promise<T>, options?: DeferredValueOptions): FluentParser<M, DeferredValue<T, C>, [S] | undefined>;
277
280
  /**
278
281
  * Checks whether a value is a {@link DeferredValue} produced by
279
282
  * {@link deferredValue}.
@@ -416,13 +419,13 @@ interface ParserModifiers<M extends Mode = "sync", TValue = unknown, TState = un
416
419
  /**
417
420
  * Defers this parser's value so the command handler resolves it.
418
421
  *
422
+ * @template C The handler-time context type, inferred from `fallback`.
419
423
  * @param fallback A resolver run at handler time when no value was specified.
420
424
  * @param options Optional {@link DeferredValueOptions}.
421
425
  * @returns A parser whose value is a {@link DeferredValue}.
422
426
  * @since 1.2.0
423
427
  */
424
- deferredValue(fallback: () => TValue | Promise<TValue>, options?: DeferredValueOptions): FluentParser<M, DeferredValue<TValue>, [TState] | undefined>;
425
- deferredValue<C>(fallback: (ctx: C) => TValue | Promise<TValue>, options?: DeferredValueOptions): FluentParser<M, DeferredValue<TValue, C>, [TState] | undefined>;
428
+ deferredValue<C = void>(fallback: (ctx: C) => TValue | Promise<TValue>, options?: DeferredValueOptions): FluentParser<M, DeferredValue<TValue, C>, [TState] | undefined>;
426
429
  /**
427
430
  * Allows this parser to match multiple times.
428
431
  *
@@ -266,14 +266,17 @@ interface DeferredValueOptions {
266
266
  * @template M The execution mode of the wrapped parser.
267
267
  * @template T The resolved value type.
268
268
  * @template S The state type of the wrapped parser.
269
+ * @template C The handler-time context type, inferred from `fallback`. A
270
+ * fallback without a parameter yields a no-argument
271
+ * {@link DeferredValue}; one whose parameter is optional or includes
272
+ * `undefined` stays callable with no argument.
269
273
  * @param parser The parser that reads the CLI value.
270
274
  * @param fallback A resolver run at handler time when no value was specified.
271
275
  * @param options Optional {@link DeferredValueOptions}.
272
276
  * @returns A parser whose value is a {@link DeferredValue}.
273
277
  * @since 1.2.0
274
278
  */
275
- declare function deferredValue<M extends Mode, T, S>(parser: Parser<M, T, S>, fallback: () => T | Promise<T>, options?: DeferredValueOptions): FluentParser<M, DeferredValue<T>, [S] | undefined>;
276
- declare function deferredValue<M extends Mode, T, S, C>(parser: Parser<M, T, S>, fallback: (ctx: C) => T | Promise<T>, options?: DeferredValueOptions): FluentParser<M, DeferredValue<T, C>, [S] | undefined>;
279
+ declare function deferredValue<M extends Mode, T, S, C = void>(parser: Parser<M, T, S>, fallback: (ctx: C) => T | Promise<T>, options?: DeferredValueOptions): FluentParser<M, DeferredValue<T, C>, [S] | undefined>;
277
280
  /**
278
281
  * Checks whether a value is a {@link DeferredValue} produced by
279
282
  * {@link deferredValue}.
@@ -416,13 +419,13 @@ interface ParserModifiers<M extends Mode = "sync", TValue = unknown, TState = un
416
419
  /**
417
420
  * Defers this parser's value so the command handler resolves it.
418
421
  *
422
+ * @template C The handler-time context type, inferred from `fallback`.
419
423
  * @param fallback A resolver run at handler time when no value was specified.
420
424
  * @param options Optional {@link DeferredValueOptions}.
421
425
  * @returns A parser whose value is a {@link DeferredValue}.
422
426
  * @since 1.2.0
423
427
  */
424
- deferredValue(fallback: () => TValue | Promise<TValue>, options?: DeferredValueOptions): FluentParser<M, DeferredValue<TValue>, [TState] | undefined>;
425
- deferredValue<C>(fallback: (ctx: C) => TValue | Promise<TValue>, options?: DeferredValueOptions): FluentParser<M, DeferredValue<TValue, C>, [TState] | undefined>;
428
+ deferredValue<C = void>(fallback: (ctx: C) => TValue | Promise<TValue>, options?: DeferredValueOptions): FluentParser<M, DeferredValue<TValue, C>, [TState] | undefined>;
426
429
  /**
427
430
  * Allows this parser to match multiple times.
428
431
  *
package/dist/modifiers.js CHANGED
@@ -913,10 +913,60 @@ function makeFallbackDeferredValue(fallback, memoize) {
913
913
  };
914
914
  return brandDeferredValue(call, "fallback");
915
915
  }
916
+ /**
917
+ * Wraps a parser so its value is resolved by the command handler instead of
918
+ * during parsing.
919
+ *
920
+ * The parsed field becomes a {@link DeferredValue}: a value-producing function.
921
+ * When the wrapped parser produced a value, calling the function returns that
922
+ * value and {@link DeferredValue.source} is `"specified"`. A value resolved
923
+ * from a source such as `bindEnv()`/`bindConfig()` counts as produced. When
924
+ * the wrapped parser did not produce a value, calling the function runs
925
+ * `fallback` and `source` is `"fallback"`. Because a missing value is reported
926
+ * as `undefined`, a wrapped parser that yields `undefined` is treated as having
927
+ * produced no value and selects the fallback. The fallback runs at handler
928
+ * time, so its errors are handler errors rather than parser errors. A value
929
+ * that is specified but invalid still fails during parsing.
930
+ *
931
+ * Like {@link optional}, the wrapped parser keeps its place in usage and help;
932
+ * only the result type changes. The fallback context type `C` is inferred from
933
+ * the `fallback` parameter.
934
+ *
935
+ * @example
936
+ * ```typescript
937
+ * const parser = object({
938
+ * serviceName: option("--service-name", string()),
939
+ * apiToken: deferredValue(
940
+ * option("--api-token", string()),
941
+ * ({ serviceName }: { readonly serviceName: string }) =>
942
+ * promptForApiToken(serviceName),
943
+ * ),
944
+ * });
945
+ *
946
+ * const parsed = parse(parser, argv);
947
+ * // The prompt only runs if this branch is reached.
948
+ * const apiToken = await parsed.apiToken({
949
+ * serviceName: parsed.serviceName,
950
+ * });
951
+ * ```
952
+ *
953
+ * @template M The execution mode of the wrapped parser.
954
+ * @template T The resolved value type.
955
+ * @template S The state type of the wrapped parser.
956
+ * @template C The handler-time context type, inferred from `fallback`. A
957
+ * fallback without a parameter yields a no-argument
958
+ * {@link DeferredValue}; one whose parameter is optional or includes
959
+ * `undefined` stays callable with no argument.
960
+ * @param parser The parser that reads the CLI value.
961
+ * @param fallback A resolver run at handler time when no value was specified.
962
+ * @param options Optional {@link DeferredValueOptions}.
963
+ * @returns A parser whose value is a {@link DeferredValue}.
964
+ * @since 1.2.0
965
+ */
916
966
  function deferredValue(parser, fallback, options) {
917
967
  const memoize = options?.memoize ?? false;
918
968
  const base = optional(parser);
919
- const complete = (state, exec) => mapModeValue(base.mode, base.complete(state, exec), (result) => {
969
+ const complete = (state, exec) => wrapForMode(base.mode, mapModeValue(base.mode, base.complete(state, exec), (result) => {
920
970
  if (!result.success) return result;
921
971
  const value = result.value === void 0 ? makeFallbackDeferredValue(fallback, memoize) : makeSpecifiedDeferredValue(result.value);
922
972
  return result.deferred ? {
@@ -927,7 +977,7 @@ function deferredValue(parser, fallback, options) {
927
977
  success: true,
928
978
  value
929
979
  };
930
- });
980
+ }));
931
981
  const descriptors = Object.getOwnPropertyDescriptors(base);
932
982
  descriptors.complete = {
933
983
  value: complete,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@optique/core",
3
- "version": "1.2.0-dev.2234",
3
+ "version": "1.2.0-dev.2236",
4
4
  "description": "Type-safe combinatorial command-line interface parser",
5
5
  "keywords": [
6
6
  "CLI",
@@ -208,7 +208,7 @@
208
208
  "fast-check": "^4.7.0",
209
209
  "tsdown": "^0.13.0",
210
210
  "typescript": "^5.8.3",
211
- "@optique/env": "1.2.0-dev.2234+763fcd3e"
211
+ "@optique/env": "1.2.0-dev.2236+88a40b64"
212
212
  },
213
213
  "scripts": {
214
214
  "build": "tsdown",