import { Message } from "./message.js"; import { Mode, Parser } from "./internal/parser.js"; //#region src/modifiers.d.ts /** * Creates a parser that makes another parser optional, allowing it to succeed * without consuming input if the wrapped parser fails to match. * If the wrapped parser succeeds, this returns its value. * If the wrapped parser fails, this returns `undefined` without consuming input. * @template M The execution mode of the parser. * @template TValue The type of the value returned by the wrapped parser. * @template TState The type of the state used by the wrapped parser. * @param parser The {@link Parser} to make optional. * @returns A {@link Parser} that produces either the result of the wrapped parser * or `undefined` if the wrapped parser fails to match. */ declare function optional(parser: Parser): Parser; /** * Options for the {@link withDefault} parser. */ interface WithDefaultOptions { /** * Custom message to display in help output instead of the formatted default value. * This allows showing descriptive text like "SERVICE_URL environment variable" * instead of the actual default value. * * @example * ```typescript * withDefault( * option("--url", url()), * process.env["SERVICE_URL"], * { message: message`${envVar("SERVICE_URL")} environment variable` } * ) * ``` */ readonly message?: Message; } /** * Error type for structured error messages in {@link withDefault} default value callbacks. * Unlike regular errors that only support string messages, this error type accepts * a {@link Message} object that supports rich formatting, colors, and structured content. * * @example * ```typescript * withDefault(option("--url", url()), () => { * if (!process.env.INSTANCE_URL) { * throw new WithDefaultError( * message`Environment variable ${envVar("INSTANCE_URL")} is not set.` * ); * } * return new URL(process.env.INSTANCE_URL); * }) * ``` * * @since 0.5.0 */ declare class WithDefaultError extends Error { /** * The structured message associated with this error. */ readonly errorMessage: Message; /** * Creates a new WithDefaultError with a structured message. * @param message The structured {@link Message} describing the error. */ constructor(message: Message); } /** * Creates a parser that makes another parser use a default value when it fails * to match or consume input. This is similar to {@link optional}, but instead * of returning `undefined` when the wrapped parser doesn't match, it returns * a specified default value. * @template M The execution mode of the parser. * @template TValue The type of the value returned by the wrapped parser. * @template TState The type of the state used by the wrapped parser. * @template TDefault The type of the default value. * @param parser The {@link Parser} to wrap with default behavior. * @param defaultValue The default value to return when the wrapped parser * doesn't match or consume input. Can be a value of type * {@link TDefault} or a function that returns such a value. * @returns A {@link Parser} that produces either the result of the wrapped parser * or the default value if the wrapped parser fails to match * (union type {@link TValue} | {@link TDefault}). */ declare function withDefault(parser: Parser, defaultValue: TDefault | (() => TDefault)): Parser; /** * Creates a parser that makes another parser use a default value when it fails * to match or consume input. This is similar to {@link optional}, but instead * of returning `undefined` when the wrapped parser doesn't match, it returns * a specified default value. * @template M The execution mode of the parser. * @template TValue The type of the value returned by the wrapped parser. * @template TState The type of the state used by the wrapped parser. * @template TDefault The type of the default value. * @param parser The {@link Parser} to wrap with default behavior. * @param defaultValue The default value to return when the wrapped parser * doesn't match or consume input. Can be a value of type * {@link TDefault} or a function that returns such a value. * @param options Optional configuration including custom help display message. * @returns A {@link Parser} that produces either the result of the wrapped parser * or the default value if the wrapped parser fails to match * (union type {@link TValue} | {@link TDefault}). * @since 0.5.0 */ declare function withDefault(parser: Parser, defaultValue: TDefault | (() => TDefault), options?: WithDefaultOptions): Parser; /** * Creates a parser that transforms the result value of another parser using * a mapping function. This enables value transformation while preserving * the original parser's parsing logic and state management. * * The `map()` function is useful for: * - Converting parsed values to different types * - Applying transformations like string formatting or boolean inversion * - Computing derived values from parsed input * - Creating reusable transformations that can be applied to any parser * * @template M The execution mode of the parser. * @template T The type of the value produced by the original parser. * @template U The type of the value produced by the mapping function. * @template TState The type of the state used by the original parser. * @param parser The {@link Parser} whose result will be transformed. * @param transform A function that transforms the parsed value from type T to type U. * @returns A {@link Parser} that produces the transformed value of type U * while preserving the original parser's state type and parsing behavior. * @throws Any exception thrown by `transform` when completing a non-deferred * value. Errors from deferred placeholder transforms are caught and the * mapped result falls back to `undefined` with `deferred: true`. * * ### Deferred prompt interaction * * During two-phase parsing, `map()` propagates the `deferred` flag from * inner results but intentionally drops per-field `deferredKeys`. The * inner key set describes the *input* shape, but `transform` produces an * arbitrary *output* shape where keys may be renamed, dropped, or reused * with different semantics. For `object()` results that are *not* * wrapped in `map()`, per-field deferred stripping works normally. * * Because the `deferred` flag is propagated conservatively, mapped scalar * results are treated as missing (`undefined`) during phase-two context * collection—even when `transform` only used non-deferred fields. * For example, `map(object({ apiKey: prompt(...), mode: option(...) }), * v => v.mode)` makes phase-two contexts see `undefined` instead of the * real `mode` value. This is the intentional trade-off: the alternative * (not propagating `deferred`) would leak placeholder values into context * resolution when `transform` *does* use deferred fields. The final * parse always produces the correct result regardless. * * If the transform throws on a deferred placeholder value, the mapped * result falls back to `undefined` with `deferred: true`, so the first * pass does not abort. * * ### Transform purity * * The `transform` function must not mutate its input. Object and array * values may be shared placeholder references during deferred prompt * resolution, and in-place mutations would corrupt the placeholder for * subsequent parses. Always return a new value: * * ```typescript * // ✅ Correct — creates a new object * map(parser, v => ({ ...v, host: "override" })) * * // ❌ Wrong — mutates the input in place * map(parser, v => { v.host = "override"; return v; }) * ``` * * @example * ```typescript * // Transform boolean flag to its inverse * const parser = object({ * disallow: map(option("--allow"), b => !b) * }); * * // Transform string to uppercase * const upperParser = map(argument(string()), s => s.toUpperCase()); * * // Transform number to formatted string * const prefixedParser = map(option("-n", integer()), n => `value: ${n}`); * ``` */ declare function map(parser: Parser, transform: (value: T) => U): Parser; /** * Options for the {@link multiple} parser. */ interface MultipleOptions { /** * The minimum number of occurrences required for the parser to succeed. * If the number of occurrences is less than this value, * the parser will fail with an error. * @default `0` */ readonly min?: number; /** * The maximum number of occurrences allowed for the parser. * If the number of occurrences exceeds this value, * the parser will fail with an error. * @default `Infinity` */ readonly max?: number; /** * Error messages customization. * @since 0.5.0 */ readonly errors?: MultipleErrorOptions; } /** * Options for customizing error messages in the {@link multiple} parser. * @since 0.5.0 */ interface MultipleErrorOptions { /** * Error message when fewer than the minimum number of values are provided. */ readonly tooFew?: Message | ((min: number, actual: number) => Message); /** * Error message when more than the maximum number of values are provided. */ readonly tooMany?: Message | ((max: number, actual: number) => Message); } /** * Creates a parser that allows multiple occurrences of a given parser. * This parser can be used to parse multiple values of the same type, * such as multiple command-line arguments or options. * @template M The execution mode of the parser. * @template TValue The type of the value that the parser produces. * @template TState The type of the state used by the parser. * @param parser The {@link Parser} to apply multiple times. * @param options Optional configuration for the parser, * allowing you to specify the minimum and maximum number of * occurrences allowed. * @returns A {@link Parser} that produces an array of values * of type {@link TValue} and an array of states * of type {@link TState}. */ declare function multiple(parser: Parser, options?: MultipleOptions): Parser; /** * Creates a parser that requires the wrapped parser to consume at least one * input token to succeed. If the wrapped parser succeeds without consuming * any tokens, this parser fails with an error. * * This modifier is useful with `longestMatch()` for implementing conditional * default values. When used together, `nonEmpty()` prevents a parser with * only default values from matching when no input is provided, allowing * another branch (like a help command) to match instead. * * @template M The execution mode of the parser. * @template T The type of value produced by the wrapped parser. * @template TState The type of state used by the wrapped parser. * @param parser The {@link Parser} that must consume input to succeed. * @returns A {@link Parser} that fails if the wrapped parser consumes no input. * * @example * ```typescript * // Without nonEmpty(): activeParser always wins (consumes 0 tokens) * // With nonEmpty(): helpParser wins when no options are provided * const activeParser = nonEmpty(object({ * cwd: withDefault(option("--cwd", string()), "./default"), * key: optional(option("--key", string())), * })); * * const helpParser = object({ * mode: constant("help"), * }); * * const parser = longestMatch(activeParser, helpParser); * * // cli → helpParser matches (activeParser fails with nonEmpty) * // cli --key foo → activeParser matches (consumes tokens) * ``` * * @since 0.10.0 */ declare function nonEmpty(parser: Parser): Parser; //#endregion export { MultipleErrorOptions, MultipleOptions, WithDefaultError, WithDefaultOptions, map, multiple, nonEmpty, optional, withDefault };