@optique/core 1.1.0-dev.2152 → 1.1.0-dev.2160

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.
package/dist/index.cjs CHANGED
@@ -74,6 +74,7 @@ exports.isSuggestionHidden = require_usage.isSuggestionHidden;
74
74
  exports.isUsageHidden = require_usage.isUsageHidden;
75
75
  exports.isValueParser = require_valueparser.isValueParser;
76
76
  exports.json = require_valueparser.json;
77
+ exports.keyValue = require_valueparser.keyValue;
77
78
  exports.lineBreak = require_message.lineBreak;
78
79
  exports.link = require_message.link;
79
80
  exports.locale = require_valueparser.locale;
package/dist/index.d.cts CHANGED
@@ -3,7 +3,7 @@ import { NonEmptyString, ensureNonEmptyString, isNonEmptyString } from "./nonemp
3
3
  import { Message, MessageFormatOptions, MessageTerm, ValueSetOptions, commandLine, envVar, formatMessage, lineBreak, link, message, metavar, optionName, optionNames, text, value, valueSet, values } from "./message.cjs";
4
4
  import { HiddenVisibility, OptionName, Usage, UsageFormatOptions, UsageTerm, UsageTermFormatOptions, cloneUsage, cloneUsageTerm, extractArgumentMetavars, extractCommandNames, extractLiteralValues, extractOptionNames, formatUsage, formatUsageTerm, isDocHidden, isSuggestionHidden, isUsageHidden, mergeHidden, normalizeUsage } from "./usage.cjs";
5
5
  import { DocEntry, DocFragment, DocFragments, DocPage, DocPageFormatOptions, DocSection, ShowChoicesOptions, ShowDefaultOptions, cloneDocEntry, deduplicateDocEntries, deduplicateDocFragments, formatDocPage, isDocEntryHidden } from "./doc.cjs";
6
- import { ChoiceOptions, ChoiceOptionsBase, ChoiceOptionsNumber, ChoiceOptionsString, CidrOptions, CidrValue, Color, ColorFormat, ColorOptions, DeferredMap, DomainOptions, EmailOptions, FileSizeOptions, FileSizeOptionsBigInt, FileSizeOptionsNumber, FileSizeUnit, FirstOfOptions, FloatOptions, HostnameOptions, IntegerOptionsBigInt, IntegerOptionsNumber, IpOptions, Ipv4Options, Ipv6Options, Json, JsonOptions, LocaleOptions, MacAddressOptions, PortOptionsBigInt, PortOptionsNumber, PortRangeOptionsBigInt, PortRangeOptionsNumber, PortRangeValueBigInt, PortRangeValueNumber, SemVer, SemVerOptionsObject, SemVerOptionsString, SemVerString, SocketAddressOptions, SocketAddressValue, StringOptions, UrlOptions, Uuid, UuidOptions, ValueParser, ValueParserResult, checkBooleanOption, checkEnumOption, choice, cidr, color, domain, email, fileSize, firstOf, float, hostname, integer, ip, ipv4, ipv6, isValueParser, json, locale, macAddress, port, portRange, semVer, socketAddress, string, url, uuid } from "./valueparser.cjs";
6
+ import { ChoiceOptions, ChoiceOptionsBase, ChoiceOptionsNumber, ChoiceOptionsString, CidrOptions, CidrValue, Color, ColorFormat, ColorOptions, DeferredMap, DomainOptions, EmailOptions, FileSizeOptions, FileSizeOptionsBigInt, FileSizeOptionsNumber, FileSizeUnit, FirstOfOptions, FloatOptions, HostnameOptions, IntegerOptionsBigInt, IntegerOptionsNumber, IpOptions, Ipv4Options, Ipv6Options, Json, JsonOptions, KeyValueOptions, LocaleOptions, MacAddressOptions, PortOptionsBigInt, PortOptionsNumber, PortRangeOptionsBigInt, PortRangeOptionsNumber, PortRangeValueBigInt, PortRangeValueNumber, SemVer, SemVerOptionsObject, SemVerOptionsString, SemVerString, SocketAddressOptions, SocketAddressValue, StringOptions, UrlOptions, Uuid, UuidOptions, ValueParser, ValueParserResult, checkBooleanOption, checkEnumOption, choice, cidr, color, domain, email, fileSize, firstOf, float, hostname, integer, ip, ipv4, ipv6, isValueParser, json, keyValue, locale, macAddress, port, portRange, semVer, socketAddress, string, url, uuid } from "./valueparser.cjs";
7
7
  import { CombineModes, DocState, ExecutionContext, ExecutionPhase, InferMode, InferValue, Mode, ModeIterable, ModeValue, ParseFrame, Parser, ParserContext, ParserResult, Result, Suggestion, createParserContext, getDocPage, getDocPageAsync, getDocPageSync, parse, parseAsync, parseSync, suggest, suggestAsync, suggestSync } from "./internal/parser.cjs";
8
8
  import { ShellCompletion, bash, fish, nu, pwsh, zsh } from "./completion.cjs";
9
9
  import { ConditionalErrorOptions, ConditionalOptions, DuplicateOptionError, GroupOptions, LongestMatchErrorOptions, LongestMatchOptions, MergeOptions, NoMatchContext, ObjectErrorOptions, ObjectOptions, OrErrorOptions, OrOptions, SeqOptions, TupleOptions, concat, conditional, group, longestMatch, merge, object, or, seq, tuple } from "./constructs.cjs";
@@ -12,4 +12,4 @@ import { AnyDependencySource, CombineMode, CombinedDependencyMode, DependencyMod
12
12
  import { CommandSubConfig, ContextOptionsParam, ExtractRequiredOptions, OptionSubConfig, RunOptions, RunParserError, RunWithOptions, SubstituteParserValue, runParser, runParserAsync, runParserSync, runWith, runWithAsync, runWithSync } from "./facade.cjs";
13
13
  import { MultipleErrorOptions, MultipleOptions, WithDefaultError, WithDefaultOptions, map, multiple, nonEmpty, optional, withDefault } from "./modifiers.cjs";
14
14
  import { ArgumentErrorOptions, ArgumentOptions, CommandErrorOptions, CommandOptions, FlagErrorOptions, FlagOptions, NegatableFlagErrorOptions, NegatableFlagNameList, NegatableFlagNames, NegatableFlagOptions, NegatableFlagState, OptionErrorOptions, OptionOptions, OptionState, PassThroughFormat, PassThroughOptions, argument, command, constant, fail, flag, negatableFlag, option, passThrough } from "./primitives.cjs";
15
- export { type Annotations, AnyDependencySource, ArgumentErrorOptions, ArgumentOptions, ChoiceOptions, ChoiceOptionsBase, ChoiceOptionsNumber, ChoiceOptionsString, CidrOptions, CidrValue, Color, ColorFormat, ColorOptions, CombineMode, CombineModes, CombinedDependencyMode, CommandErrorOptions, CommandOptions, CommandSubConfig, ConditionalErrorOptions, ConditionalOptions, ContextOptionsParam, DeferredMap, DependencyMode, DependencySource, DependencyValue, DependencyValues, DeriveAsyncOptions, DeriveFromAsyncOptions, DeriveFromOptions, DeriveFromSyncOptions, DeriveOptions, DeriveSyncOptions, DerivedValueParser, DocEntry, DocFragment, DocFragments, DocPage, DocPageFormatOptions, DocSection, DocState, DomainOptions, DuplicateOptionError, EmailOptions, ExecutionContext, ExecutionPhase, ExtractRequiredOptions, FileSizeOptions, FileSizeOptionsBigInt, FileSizeOptionsNumber, FileSizeUnit, FirstOfOptions, FlagErrorOptions, FlagOptions, FloatOptions, GroupOptions, HiddenVisibility, HostnameOptions, InferMode, InferValue, IntegerOptionsBigInt, IntegerOptionsNumber, IpOptions, Ipv4Options, Ipv6Options, Json, JsonOptions, LocaleOptions, LongestMatchErrorOptions, LongestMatchOptions, MacAddressOptions, MergeOptions, type Message, type MessageFormatOptions, type MessageTerm, Mode, ModeIterable, ModeValue, MultipleErrorOptions, MultipleOptions, NegatableFlagErrorOptions, NegatableFlagNameList, NegatableFlagNames, NegatableFlagOptions, NegatableFlagState, NoMatchContext, NonEmptyString, ObjectErrorOptions, ObjectOptions, OptionErrorOptions, OptionName, OptionOptions, OptionState, OptionSubConfig, OrErrorOptions, OrOptions, ParseFrame, type ParseOptions, Parser, ParserContext, ParserResult, ParserValuePlaceholder, PassThroughFormat, PassThroughOptions, PortOptionsBigInt, PortOptionsNumber, PortRangeOptionsBigInt, PortRangeOptionsNumber, PortRangeValueBigInt, PortRangeValueNumber, Result, RunOptions, RunParserError, RunWithOptions, SemVer, SemVerOptionsObject, SemVerOptionsString, SemVerString, SeqOptions, ShellCompletion, ShowChoicesOptions, ShowDefaultOptions, SocketAddressOptions, SocketAddressValue, SourceContext, SourceContextRequest, StringOptions, SubstituteParserValue, Suggestion, TupleOptions, UrlOptions, Usage, UsageFormatOptions, UsageTerm, UsageTermFormatOptions, Uuid, UuidOptions, ValueParser, ValueParserResult, type ValueSetOptions, WithDefaultError, WithDefaultOptions, argument, bash, checkBooleanOption, checkEnumOption, choice, cidr, cloneDocEntry, cloneUsage, cloneUsageTerm, color, command, commandLine, concat, conditional, constant, createParserContext, deduplicateDocEntries, deduplicateDocFragments, dependency, deriveFrom, deriveFromAsync, deriveFromSync, domain, email, ensureNonEmptyString, envVar, extractArgumentMetavars, extractCommandNames, extractLiteralValues, extractOptionNames, fail, fileSize, firstOf, fish, flag, float, formatDocPage, formatMessage, formatUsage, formatUsageTerm, getAnnotations, getDocPage, getDocPageAsync, getDocPageSync, group, hostname, integer, ip, ipv4, ipv6, isDependencySource, isDerivedValueParser, isDocEntryHidden, isDocHidden, isNonEmptyString, isSuggestionHidden, isUsageHidden, isValueParser, json, lineBreak, link, locale, longestMatch, macAddress, map, merge, mergeHidden, message, metavar, multiple, negatableFlag, nonEmpty, normalizeUsage, nu, object, option, optionName, optionNames, optional, or, parse, parseAsync, parseSync, passThrough, port, portRange, pwsh, runParser, runParserAsync, runParserSync, runWith, runWithAsync, runWithSync, semVer, seq, socketAddress, string, suggest, suggestAsync, suggestSync, text, tuple, url, uuid, value, valueSet, values, withDefault, zsh };
15
+ export { type Annotations, AnyDependencySource, ArgumentErrorOptions, ArgumentOptions, ChoiceOptions, ChoiceOptionsBase, ChoiceOptionsNumber, ChoiceOptionsString, CidrOptions, CidrValue, Color, ColorFormat, ColorOptions, CombineMode, CombineModes, CombinedDependencyMode, CommandErrorOptions, CommandOptions, CommandSubConfig, ConditionalErrorOptions, ConditionalOptions, ContextOptionsParam, DeferredMap, DependencyMode, DependencySource, DependencyValue, DependencyValues, DeriveAsyncOptions, DeriveFromAsyncOptions, DeriveFromOptions, DeriveFromSyncOptions, DeriveOptions, DeriveSyncOptions, DerivedValueParser, DocEntry, DocFragment, DocFragments, DocPage, DocPageFormatOptions, DocSection, DocState, DomainOptions, DuplicateOptionError, EmailOptions, ExecutionContext, ExecutionPhase, ExtractRequiredOptions, FileSizeOptions, FileSizeOptionsBigInt, FileSizeOptionsNumber, FileSizeUnit, FirstOfOptions, FlagErrorOptions, FlagOptions, FloatOptions, GroupOptions, HiddenVisibility, HostnameOptions, InferMode, InferValue, IntegerOptionsBigInt, IntegerOptionsNumber, IpOptions, Ipv4Options, Ipv6Options, Json, JsonOptions, KeyValueOptions, LocaleOptions, LongestMatchErrorOptions, LongestMatchOptions, MacAddressOptions, MergeOptions, type Message, type MessageFormatOptions, type MessageTerm, Mode, ModeIterable, ModeValue, MultipleErrorOptions, MultipleOptions, NegatableFlagErrorOptions, NegatableFlagNameList, NegatableFlagNames, NegatableFlagOptions, NegatableFlagState, NoMatchContext, NonEmptyString, ObjectErrorOptions, ObjectOptions, OptionErrorOptions, OptionName, OptionOptions, OptionState, OptionSubConfig, OrErrorOptions, OrOptions, ParseFrame, type ParseOptions, Parser, ParserContext, ParserResult, ParserValuePlaceholder, PassThroughFormat, PassThroughOptions, PortOptionsBigInt, PortOptionsNumber, PortRangeOptionsBigInt, PortRangeOptionsNumber, PortRangeValueBigInt, PortRangeValueNumber, Result, RunOptions, RunParserError, RunWithOptions, SemVer, SemVerOptionsObject, SemVerOptionsString, SemVerString, SeqOptions, ShellCompletion, ShowChoicesOptions, ShowDefaultOptions, SocketAddressOptions, SocketAddressValue, SourceContext, SourceContextRequest, StringOptions, SubstituteParserValue, Suggestion, TupleOptions, UrlOptions, Usage, UsageFormatOptions, UsageTerm, UsageTermFormatOptions, Uuid, UuidOptions, ValueParser, ValueParserResult, type ValueSetOptions, WithDefaultError, WithDefaultOptions, argument, bash, checkBooleanOption, checkEnumOption, choice, cidr, cloneDocEntry, cloneUsage, cloneUsageTerm, color, command, commandLine, concat, conditional, constant, createParserContext, deduplicateDocEntries, deduplicateDocFragments, dependency, deriveFrom, deriveFromAsync, deriveFromSync, domain, email, ensureNonEmptyString, envVar, extractArgumentMetavars, extractCommandNames, extractLiteralValues, extractOptionNames, fail, fileSize, firstOf, fish, flag, float, formatDocPage, formatMessage, formatUsage, formatUsageTerm, getAnnotations, getDocPage, getDocPageAsync, getDocPageSync, group, hostname, integer, ip, ipv4, ipv6, isDependencySource, isDerivedValueParser, isDocEntryHidden, isDocHidden, isNonEmptyString, isSuggestionHidden, isUsageHidden, isValueParser, json, keyValue, lineBreak, link, locale, longestMatch, macAddress, map, merge, mergeHidden, message, metavar, multiple, negatableFlag, nonEmpty, normalizeUsage, nu, object, option, optionName, optionNames, optional, or, parse, parseAsync, parseSync, passThrough, port, portRange, pwsh, runParser, runParserAsync, runParserSync, runWith, runWithAsync, runWithSync, semVer, seq, socketAddress, string, suggest, suggestAsync, suggestSync, text, tuple, url, uuid, value, valueSet, values, withDefault, zsh };
package/dist/index.d.ts CHANGED
@@ -3,7 +3,7 @@ import { NonEmptyString, ensureNonEmptyString, isNonEmptyString } from "./nonemp
3
3
  import { Message, MessageFormatOptions, MessageTerm, ValueSetOptions, commandLine, envVar, formatMessage, lineBreak, link, message, metavar, optionName, optionNames, text, value, valueSet, values } from "./message.js";
4
4
  import { HiddenVisibility, OptionName, Usage, UsageFormatOptions, UsageTerm, UsageTermFormatOptions, cloneUsage, cloneUsageTerm, extractArgumentMetavars, extractCommandNames, extractLiteralValues, extractOptionNames, formatUsage, formatUsageTerm, isDocHidden, isSuggestionHidden, isUsageHidden, mergeHidden, normalizeUsage } from "./usage.js";
5
5
  import { DocEntry, DocFragment, DocFragments, DocPage, DocPageFormatOptions, DocSection, ShowChoicesOptions, ShowDefaultOptions, cloneDocEntry, deduplicateDocEntries, deduplicateDocFragments, formatDocPage, isDocEntryHidden } from "./doc.js";
6
- import { ChoiceOptions, ChoiceOptionsBase, ChoiceOptionsNumber, ChoiceOptionsString, CidrOptions, CidrValue, Color, ColorFormat, ColorOptions, DeferredMap, DomainOptions, EmailOptions, FileSizeOptions, FileSizeOptionsBigInt, FileSizeOptionsNumber, FileSizeUnit, FirstOfOptions, FloatOptions, HostnameOptions, IntegerOptionsBigInt, IntegerOptionsNumber, IpOptions, Ipv4Options, Ipv6Options, Json, JsonOptions, LocaleOptions, MacAddressOptions, PortOptionsBigInt, PortOptionsNumber, PortRangeOptionsBigInt, PortRangeOptionsNumber, PortRangeValueBigInt, PortRangeValueNumber, SemVer, SemVerOptionsObject, SemVerOptionsString, SemVerString, SocketAddressOptions, SocketAddressValue, StringOptions, UrlOptions, Uuid, UuidOptions, ValueParser, ValueParserResult, checkBooleanOption, checkEnumOption, choice, cidr, color, domain, email, fileSize, firstOf, float, hostname, integer, ip, ipv4, ipv6, isValueParser, json, locale, macAddress, port, portRange, semVer, socketAddress, string, url, uuid } from "./valueparser.js";
6
+ import { ChoiceOptions, ChoiceOptionsBase, ChoiceOptionsNumber, ChoiceOptionsString, CidrOptions, CidrValue, Color, ColorFormat, ColorOptions, DeferredMap, DomainOptions, EmailOptions, FileSizeOptions, FileSizeOptionsBigInt, FileSizeOptionsNumber, FileSizeUnit, FirstOfOptions, FloatOptions, HostnameOptions, IntegerOptionsBigInt, IntegerOptionsNumber, IpOptions, Ipv4Options, Ipv6Options, Json, JsonOptions, KeyValueOptions, LocaleOptions, MacAddressOptions, PortOptionsBigInt, PortOptionsNumber, PortRangeOptionsBigInt, PortRangeOptionsNumber, PortRangeValueBigInt, PortRangeValueNumber, SemVer, SemVerOptionsObject, SemVerOptionsString, SemVerString, SocketAddressOptions, SocketAddressValue, StringOptions, UrlOptions, Uuid, UuidOptions, ValueParser, ValueParserResult, checkBooleanOption, checkEnumOption, choice, cidr, color, domain, email, fileSize, firstOf, float, hostname, integer, ip, ipv4, ipv6, isValueParser, json, keyValue, locale, macAddress, port, portRange, semVer, socketAddress, string, url, uuid } from "./valueparser.js";
7
7
  import { CombineModes, DocState, ExecutionContext, ExecutionPhase, InferMode, InferValue, Mode, ModeIterable, ModeValue, ParseFrame, Parser, ParserContext, ParserResult, Result, Suggestion, createParserContext, getDocPage, getDocPageAsync, getDocPageSync, parse, parseAsync, parseSync, suggest, suggestAsync, suggestSync } from "./internal/parser.js";
8
8
  import { ShellCompletion, bash, fish, nu, pwsh, zsh } from "./completion.js";
9
9
  import { ConditionalErrorOptions, ConditionalOptions, DuplicateOptionError, GroupOptions, LongestMatchErrorOptions, LongestMatchOptions, MergeOptions, NoMatchContext, ObjectErrorOptions, ObjectOptions, OrErrorOptions, OrOptions, SeqOptions, TupleOptions, concat, conditional, group, longestMatch, merge, object, or, seq, tuple } from "./constructs.js";
@@ -12,4 +12,4 @@ import { AnyDependencySource, CombineMode, CombinedDependencyMode, DependencyMod
12
12
  import { CommandSubConfig, ContextOptionsParam, ExtractRequiredOptions, OptionSubConfig, RunOptions, RunParserError, RunWithOptions, SubstituteParserValue, runParser, runParserAsync, runParserSync, runWith, runWithAsync, runWithSync } from "./facade.js";
13
13
  import { MultipleErrorOptions, MultipleOptions, WithDefaultError, WithDefaultOptions, map, multiple, nonEmpty, optional, withDefault } from "./modifiers.js";
14
14
  import { ArgumentErrorOptions, ArgumentOptions, CommandErrorOptions, CommandOptions, FlagErrorOptions, FlagOptions, NegatableFlagErrorOptions, NegatableFlagNameList, NegatableFlagNames, NegatableFlagOptions, NegatableFlagState, OptionErrorOptions, OptionOptions, OptionState, PassThroughFormat, PassThroughOptions, argument, command, constant, fail, flag, negatableFlag, option, passThrough } from "./primitives.js";
15
- export { type Annotations, AnyDependencySource, ArgumentErrorOptions, ArgumentOptions, ChoiceOptions, ChoiceOptionsBase, ChoiceOptionsNumber, ChoiceOptionsString, CidrOptions, CidrValue, Color, ColorFormat, ColorOptions, CombineMode, CombineModes, CombinedDependencyMode, CommandErrorOptions, CommandOptions, CommandSubConfig, ConditionalErrorOptions, ConditionalOptions, ContextOptionsParam, DeferredMap, DependencyMode, DependencySource, DependencyValue, DependencyValues, DeriveAsyncOptions, DeriveFromAsyncOptions, DeriveFromOptions, DeriveFromSyncOptions, DeriveOptions, DeriveSyncOptions, DerivedValueParser, DocEntry, DocFragment, DocFragments, DocPage, DocPageFormatOptions, DocSection, DocState, DomainOptions, DuplicateOptionError, EmailOptions, ExecutionContext, ExecutionPhase, ExtractRequiredOptions, FileSizeOptions, FileSizeOptionsBigInt, FileSizeOptionsNumber, FileSizeUnit, FirstOfOptions, FlagErrorOptions, FlagOptions, FloatOptions, GroupOptions, HiddenVisibility, HostnameOptions, InferMode, InferValue, IntegerOptionsBigInt, IntegerOptionsNumber, IpOptions, Ipv4Options, Ipv6Options, Json, JsonOptions, LocaleOptions, LongestMatchErrorOptions, LongestMatchOptions, MacAddressOptions, MergeOptions, type Message, type MessageFormatOptions, type MessageTerm, Mode, ModeIterable, ModeValue, MultipleErrorOptions, MultipleOptions, NegatableFlagErrorOptions, NegatableFlagNameList, NegatableFlagNames, NegatableFlagOptions, NegatableFlagState, NoMatchContext, NonEmptyString, ObjectErrorOptions, ObjectOptions, OptionErrorOptions, OptionName, OptionOptions, OptionState, OptionSubConfig, OrErrorOptions, OrOptions, ParseFrame, type ParseOptions, Parser, ParserContext, ParserResult, ParserValuePlaceholder, PassThroughFormat, PassThroughOptions, PortOptionsBigInt, PortOptionsNumber, PortRangeOptionsBigInt, PortRangeOptionsNumber, PortRangeValueBigInt, PortRangeValueNumber, Result, RunOptions, RunParserError, RunWithOptions, SemVer, SemVerOptionsObject, SemVerOptionsString, SemVerString, SeqOptions, ShellCompletion, ShowChoicesOptions, ShowDefaultOptions, SocketAddressOptions, SocketAddressValue, SourceContext, SourceContextRequest, StringOptions, SubstituteParserValue, Suggestion, TupleOptions, UrlOptions, Usage, UsageFormatOptions, UsageTerm, UsageTermFormatOptions, Uuid, UuidOptions, ValueParser, ValueParserResult, type ValueSetOptions, WithDefaultError, WithDefaultOptions, argument, bash, checkBooleanOption, checkEnumOption, choice, cidr, cloneDocEntry, cloneUsage, cloneUsageTerm, color, command, commandLine, concat, conditional, constant, createParserContext, deduplicateDocEntries, deduplicateDocFragments, dependency, deriveFrom, deriveFromAsync, deriveFromSync, domain, email, ensureNonEmptyString, envVar, extractArgumentMetavars, extractCommandNames, extractLiteralValues, extractOptionNames, fail, fileSize, firstOf, fish, flag, float, formatDocPage, formatMessage, formatUsage, formatUsageTerm, getAnnotations, getDocPage, getDocPageAsync, getDocPageSync, group, hostname, integer, ip, ipv4, ipv6, isDependencySource, isDerivedValueParser, isDocEntryHidden, isDocHidden, isNonEmptyString, isSuggestionHidden, isUsageHidden, isValueParser, json, lineBreak, link, locale, longestMatch, macAddress, map, merge, mergeHidden, message, metavar, multiple, negatableFlag, nonEmpty, normalizeUsage, nu, object, option, optionName, optionNames, optional, or, parse, parseAsync, parseSync, passThrough, port, portRange, pwsh, runParser, runParserAsync, runParserSync, runWith, runWithAsync, runWithSync, semVer, seq, socketAddress, string, suggest, suggestAsync, suggestSync, text, tuple, url, uuid, value, valueSet, values, withDefault, zsh };
15
+ export { type Annotations, AnyDependencySource, ArgumentErrorOptions, ArgumentOptions, ChoiceOptions, ChoiceOptionsBase, ChoiceOptionsNumber, ChoiceOptionsString, CidrOptions, CidrValue, Color, ColorFormat, ColorOptions, CombineMode, CombineModes, CombinedDependencyMode, CommandErrorOptions, CommandOptions, CommandSubConfig, ConditionalErrorOptions, ConditionalOptions, ContextOptionsParam, DeferredMap, DependencyMode, DependencySource, DependencyValue, DependencyValues, DeriveAsyncOptions, DeriveFromAsyncOptions, DeriveFromOptions, DeriveFromSyncOptions, DeriveOptions, DeriveSyncOptions, DerivedValueParser, DocEntry, DocFragment, DocFragments, DocPage, DocPageFormatOptions, DocSection, DocState, DomainOptions, DuplicateOptionError, EmailOptions, ExecutionContext, ExecutionPhase, ExtractRequiredOptions, FileSizeOptions, FileSizeOptionsBigInt, FileSizeOptionsNumber, FileSizeUnit, FirstOfOptions, FlagErrorOptions, FlagOptions, FloatOptions, GroupOptions, HiddenVisibility, HostnameOptions, InferMode, InferValue, IntegerOptionsBigInt, IntegerOptionsNumber, IpOptions, Ipv4Options, Ipv6Options, Json, JsonOptions, KeyValueOptions, LocaleOptions, LongestMatchErrorOptions, LongestMatchOptions, MacAddressOptions, MergeOptions, type Message, type MessageFormatOptions, type MessageTerm, Mode, ModeIterable, ModeValue, MultipleErrorOptions, MultipleOptions, NegatableFlagErrorOptions, NegatableFlagNameList, NegatableFlagNames, NegatableFlagOptions, NegatableFlagState, NoMatchContext, NonEmptyString, ObjectErrorOptions, ObjectOptions, OptionErrorOptions, OptionName, OptionOptions, OptionState, OptionSubConfig, OrErrorOptions, OrOptions, ParseFrame, type ParseOptions, Parser, ParserContext, ParserResult, ParserValuePlaceholder, PassThroughFormat, PassThroughOptions, PortOptionsBigInt, PortOptionsNumber, PortRangeOptionsBigInt, PortRangeOptionsNumber, PortRangeValueBigInt, PortRangeValueNumber, Result, RunOptions, RunParserError, RunWithOptions, SemVer, SemVerOptionsObject, SemVerOptionsString, SemVerString, SeqOptions, ShellCompletion, ShowChoicesOptions, ShowDefaultOptions, SocketAddressOptions, SocketAddressValue, SourceContext, SourceContextRequest, StringOptions, SubstituteParserValue, Suggestion, TupleOptions, UrlOptions, Usage, UsageFormatOptions, UsageTerm, UsageTermFormatOptions, Uuid, UuidOptions, ValueParser, ValueParserResult, type ValueSetOptions, WithDefaultError, WithDefaultOptions, argument, bash, checkBooleanOption, checkEnumOption, choice, cidr, cloneDocEntry, cloneUsage, cloneUsageTerm, color, command, commandLine, concat, conditional, constant, createParserContext, deduplicateDocEntries, deduplicateDocFragments, dependency, deriveFrom, deriveFromAsync, deriveFromSync, domain, email, ensureNonEmptyString, envVar, extractArgumentMetavars, extractCommandNames, extractLiteralValues, extractOptionNames, fail, fileSize, firstOf, fish, flag, float, formatDocPage, formatMessage, formatUsage, formatUsageTerm, getAnnotations, getDocPage, getDocPageAsync, getDocPageSync, group, hostname, integer, ip, ipv4, ipv6, isDependencySource, isDerivedValueParser, isDocEntryHidden, isDocHidden, isNonEmptyString, isSuggestionHidden, isUsageHidden, isValueParser, json, keyValue, lineBreak, link, locale, longestMatch, macAddress, map, merge, mergeHidden, message, metavar, multiple, negatableFlag, nonEmpty, normalizeUsage, nu, object, option, optionName, optionNames, optional, or, parse, parseAsync, parseSync, passThrough, port, portRange, pwsh, runParser, runParserAsync, runParserSync, runWith, runWithAsync, runWithSync, semVer, seq, socketAddress, string, suggest, suggestAsync, suggestSync, text, tuple, url, uuid, value, valueSet, values, withDefault, zsh };
package/dist/index.js CHANGED
@@ -8,8 +8,8 @@ import { bash, fish, nu, pwsh, zsh } from "./completion.js";
8
8
  import { DuplicateOptionError, concat, conditional, group, longestMatch, merge, object, or, seq, tuple } from "./constructs.js";
9
9
  import { WithDefaultError, map, multiple, nonEmpty, optional, withDefault } from "./modifiers.js";
10
10
  import { ensureNonEmptyString, isNonEmptyString } from "./nonempty.js";
11
- import { checkBooleanOption, checkEnumOption, choice, cidr, color, domain, email, fileSize, firstOf, float, hostname, integer, ip, ipv4, ipv6, isValueParser, json, locale, macAddress, port, portRange, semVer, socketAddress, string, url, uuid } from "./valueparser.js";
11
+ import { checkBooleanOption, checkEnumOption, choice, cidr, color, domain, email, fileSize, firstOf, float, hostname, integer, ip, ipv4, ipv6, isValueParser, json, keyValue, locale, macAddress, port, portRange, semVer, socketAddress, string, url, uuid } from "./valueparser.js";
12
12
  import { argument, command, constant, fail, flag, negatableFlag, option, passThrough } from "./primitives.js";
13
13
  import { RunParserError, runParser, runParserAsync, runParserSync, runWith, runWithAsync, runWithSync } from "./facade.js";
14
14
 
15
- export { DuplicateOptionError, RunParserError, WithDefaultError, argument, bash, checkBooleanOption, checkEnumOption, choice, cidr, cloneDocEntry, cloneUsage, cloneUsageTerm, color, command, commandLine, concat, conditional, constant, createParserContext, deduplicateDocEntries, deduplicateDocFragments, dependency, deriveFrom, deriveFromAsync, deriveFromSync, domain, email, ensureNonEmptyString, envVar, extractArgumentMetavars, extractCommandNames, extractLiteralValues, extractOptionNames, fail, fileSize, firstOf, fish, flag, float, formatDocPage, formatMessage, formatUsage, formatUsageTerm, getAnnotations, getDocPage, getDocPageAsync, getDocPageSync, group, hostname, integer, ip, ipv4, ipv6, isDependencySource, isDerivedValueParser, isDocEntryHidden, isDocHidden, isNonEmptyString, isSuggestionHidden, isUsageHidden, isValueParser, json, lineBreak, link, locale, longestMatch, macAddress, map, merge, mergeHidden, message, metavar, multiple, negatableFlag, nonEmpty, normalizeUsage, nu, object, option, optionName, optionNames, optional, or, parse, parseAsync, parseSync, passThrough, port, portRange, pwsh, runParser, runParserAsync, runParserSync, runWith, runWithAsync, runWithSync, semVer, seq, socketAddress, string, suggest, suggestAsync, suggestSync, text, tuple, url, uuid, value, valueSet, values, withDefault, zsh };
15
+ export { DuplicateOptionError, RunParserError, WithDefaultError, argument, bash, checkBooleanOption, checkEnumOption, choice, cidr, cloneDocEntry, cloneUsage, cloneUsageTerm, color, command, commandLine, concat, conditional, constant, createParserContext, deduplicateDocEntries, deduplicateDocFragments, dependency, deriveFrom, deriveFromAsync, deriveFromSync, domain, email, ensureNonEmptyString, envVar, extractArgumentMetavars, extractCommandNames, extractLiteralValues, extractOptionNames, fail, fileSize, firstOf, fish, flag, float, formatDocPage, formatMessage, formatUsage, formatUsageTerm, getAnnotations, getDocPage, getDocPageAsync, getDocPageSync, group, hostname, integer, ip, ipv4, ipv6, isDependencySource, isDerivedValueParser, isDocEntryHidden, isDocHidden, isNonEmptyString, isSuggestionHidden, isUsageHidden, isValueParser, json, keyValue, lineBreak, link, locale, longestMatch, macAddress, map, merge, mergeHidden, message, metavar, multiple, negatableFlag, nonEmpty, normalizeUsage, nu, object, option, optionName, optionNames, optional, or, parse, parseAsync, parseSync, passThrough, port, portRange, pwsh, runParser, runParserAsync, runParserSync, runWith, runWithAsync, runWithSync, semVer, seq, socketAddress, string, suggest, suggestAsync, suggestSync, text, tuple, url, uuid, value, valueSet, values, withDefault, zsh };
@@ -327,6 +327,323 @@ function string(options = {}) {
327
327
  }
328
328
  };
329
329
  }
330
+ function keyValue(options = {}) {
331
+ const separator = options.separator ?? "=";
332
+ if (typeof separator !== "string") throw new TypeError(`Expected separator to be a string, but got ${typeof separator}: ${String(separator)}.`);
333
+ require_nonempty.ensureNonEmptyString(separator);
334
+ checkBooleanOption(options, "allowEmptyKey");
335
+ checkBooleanOption(options, "allowEmptyValue");
336
+ checkEnumOption(options, "split", ["first", "last"]);
337
+ const split = options.split ?? "first";
338
+ const allowEmptyKey = options.allowEmptyKey ?? false;
339
+ const allowEmptyValue = options.allowEmptyValue ?? true;
340
+ const metavar$1 = options.metavar ?? `KEY${separator}VALUE`;
341
+ require_nonempty.ensureNonEmptyString(metavar$1);
342
+ const rawKeyParser = options.key ?? string({ placeholder: "KEY" });
343
+ const rawValueParser = options.value ?? string({ placeholder: allowEmptyValue ? "" : "VALUE" });
344
+ checkKeyValueChildParser("key", rawKeyParser);
345
+ checkKeyValueChildParser("value", rawValueParser);
346
+ const keyParser = rawKeyParser;
347
+ const valueParser = rawValueParser;
348
+ const hasNormalize = typeof keyParser.normalize === "function" || typeof valueParser.normalize === "function";
349
+ const hasSuggest = typeof keyParser.suggest === "function" || typeof valueParser.suggest === "function";
350
+ function findSeparator(input) {
351
+ return split === "last" ? input.lastIndexOf(separator) : input.indexOf(separator);
352
+ }
353
+ function emptyKeyError(input) {
354
+ const custom = options.errors?.emptyKey;
355
+ if (custom != null) return typeof custom === "function" ? custom(input) : custom;
356
+ return require_message.message`Expected a non-empty key in ${input}.`;
357
+ }
358
+ function emptyValueError(input) {
359
+ const custom = options.errors?.emptyValue;
360
+ if (custom != null) return typeof custom === "function" ? custom(input) : custom;
361
+ return require_message.message`Expected a non-empty value in ${input}.`;
362
+ }
363
+ function missingSeparatorError(input) {
364
+ const custom = options.errors?.missingSeparator;
365
+ if (custom != null) return typeof custom === "function" ? custom(input, separator) : custom;
366
+ return require_message.message`Expected ${separator} in ${input}.`;
367
+ }
368
+ function invalidKeyError(error) {
369
+ const custom = options.errors?.invalidKey;
370
+ if (custom != null) return typeof custom === "function" ? custom(error) : custom;
371
+ return [require_message.text("Invalid key: "), ...require_message.cloneMessage(error)];
372
+ }
373
+ function invalidValueError(error) {
374
+ const custom = options.errors?.invalidValue;
375
+ if (custom != null) return typeof custom === "function" ? custom(error) : custom;
376
+ return [require_message.text("Invalid value: "), ...require_message.cloneMessage(error)];
377
+ }
378
+ function validateParts(input, key, value) {
379
+ if (!allowEmptyKey && key === "") return {
380
+ success: false,
381
+ error: emptyKeyError(input)
382
+ };
383
+ if (!allowEmptyValue && value === "") return {
384
+ success: false,
385
+ error: emptyValueError(input)
386
+ };
387
+ const keyResult = keyParser.parse(key);
388
+ if (!keyResult.success) return {
389
+ success: false,
390
+ error: invalidKeyError(keyResult.error)
391
+ };
392
+ const valueResult = valueParser.parse(value);
393
+ if (!valueResult.success) return {
394
+ success: false,
395
+ error: invalidValueError(valueResult.error)
396
+ };
397
+ return validateResultParts(input, keyResult, valueResult);
398
+ }
399
+ function validateKeyForSuggestion(key) {
400
+ if (!allowEmptyKey && key === "") return false;
401
+ if (!partsRoundTrip(key, "")) return false;
402
+ const keyResult = keyParser.parse(key);
403
+ if (!keyResult.success) return false;
404
+ if (!allowEmptyKey && keyResult.value === "") return false;
405
+ const formattedKeyResult = formatValueParserValue(keyParser, keyResult.value);
406
+ if (!formattedKeyResult.success) return false;
407
+ const formattedKey = formattedKeyResult.value;
408
+ return formattedKey == null || partsRoundTrip(formattedKey, "");
409
+ }
410
+ function validateKeyPatternForSuggestion(key) {
411
+ if (!allowEmptyKey && key === "") return false;
412
+ return partsRoundTrip(key, "");
413
+ }
414
+ function fallbackInput(key, value) {
415
+ return `${typeof key === "string" ? key : ""}${separator}${typeof value === "string" ? value : ""}`;
416
+ }
417
+ function partsRoundTrip(key, value) {
418
+ const input = `${key}${separator}${value}`;
419
+ const index = findSeparator(input);
420
+ if (index < 0) return false;
421
+ return input.slice(0, index) === key && input.slice(index + separator.length) === value;
422
+ }
423
+ function validateResultParts(input, keyResult, valueResult) {
424
+ if (!allowEmptyKey && keyResult.value === "") return {
425
+ success: false,
426
+ error: emptyKeyError(input)
427
+ };
428
+ if (!allowEmptyValue && valueResult.value === "") return {
429
+ success: false,
430
+ error: emptyValueError(input)
431
+ };
432
+ const formattedKeyResult = formatValueParserValue(keyParser, keyResult.value);
433
+ if (!formattedKeyResult.success) return {
434
+ success: false,
435
+ error: invalidKeyError(formattedKeyResult.error)
436
+ };
437
+ const formattedValueResult = formatValueParserValue(valueParser, valueResult.value);
438
+ if (!formattedValueResult.success) return {
439
+ success: false,
440
+ error: invalidValueError(formattedValueResult.error)
441
+ };
442
+ const formattedKey = formattedKeyResult.value;
443
+ const formattedValue = formattedValueResult.value;
444
+ if (!allowEmptyKey && formattedKey === "") return {
445
+ success: false,
446
+ error: emptyKeyError(input)
447
+ };
448
+ if (!allowEmptyValue && formattedValue === "") return {
449
+ success: false,
450
+ error: emptyValueError(input)
451
+ };
452
+ if (split === "first" && formattedKey != null && formattedKey.includes(separator)) return {
453
+ success: false,
454
+ error: invalidKeyError(require_message.message`Expected a key without ${separator}, but got ${formattedKey}.`)
455
+ };
456
+ if (split === "last" && formattedValue != null && formattedValue.includes(separator)) return {
457
+ success: false,
458
+ error: invalidValueError(require_message.message`Expected a value without ${separator}, but got ${formattedValue}.`)
459
+ };
460
+ if (formattedKey != null && formattedValue != null) {
461
+ if (!partsRoundTrip(formattedKey, formattedValue)) return split === "first" ? {
462
+ success: false,
463
+ error: invalidKeyError(require_message.message`Expected a key that round-trips with ${separator}, but got ${formattedKey}.`)
464
+ } : {
465
+ success: false,
466
+ error: invalidValueError(require_message.message`Expected a value that round-trips with ${separator}, but got ${formattedValue}.`)
467
+ };
468
+ }
469
+ return makeKeyValueSuccess(keyResult, valueResult);
470
+ }
471
+ function validateTuple(value) {
472
+ if (!allowEmptyKey && value[0] === "") return {
473
+ success: false,
474
+ error: emptyKeyError(fallbackInput(value[0], value[1]))
475
+ };
476
+ if (!allowEmptyValue && value[1] === "") return {
477
+ success: false,
478
+ error: emptyValueError(fallbackInput(value[0], value[1]))
479
+ };
480
+ const keyResult = validateValueParserValue(keyParser, value[0]);
481
+ if (!keyResult.success) return {
482
+ success: false,
483
+ error: invalidKeyError(keyResult.error)
484
+ };
485
+ const valueResult = validateValueParserValue(valueParser, value[1]);
486
+ if (!valueResult.success) return {
487
+ success: false,
488
+ error: invalidValueError(valueResult.error)
489
+ };
490
+ return validateResultParts(fallbackInput(value[0], value[1]), keyResult, valueResult);
491
+ }
492
+ return {
493
+ mode: "sync",
494
+ metavar: metavar$1,
495
+ placeholder: [keyParser.placeholder, valueParser.placeholder],
496
+ parse(input) {
497
+ const index = findSeparator(input);
498
+ if (index < 0) return {
499
+ success: false,
500
+ error: missingSeparatorError(input)
501
+ };
502
+ const key = input.slice(0, index);
503
+ const value = input.slice(index + separator.length);
504
+ return validateParts(input, key, value);
505
+ },
506
+ format(value) {
507
+ return `${keyParser.format(value[0])}${separator}${valueParser.format(value[1])}`;
508
+ },
509
+ validate(value) {
510
+ if (!isKeyValueTuple(value)) return {
511
+ success: false,
512
+ error: require_message.message`Expected a key-value tuple.`
513
+ };
514
+ return validateTuple(value);
515
+ },
516
+ ...hasNormalize ? { normalize(value) {
517
+ if (!isKeyValueTuple(value)) return value;
518
+ const normalized = [typeof keyParser.normalize === "function" ? keyParser.normalize(value[0]) : value[0], typeof valueParser.normalize === "function" ? valueParser.normalize(value[1]) : value[1]];
519
+ return validateTuple(normalized).success ? normalized : value;
520
+ } } : {},
521
+ ...hasSuggest ? { *suggest(prefix) {
522
+ const index = findSeparator(prefix);
523
+ const suggestions = [];
524
+ if (index < 0 || split === "last") {
525
+ if (typeof keyParser.suggest === "function") for (const suggestion of keyParser.suggest(prefix)) {
526
+ const key = suggestionTextValue(suggestion);
527
+ if (suggestion.kind === "literal" ? !validateKeyForSuggestion(key) : !validateKeyPatternForSuggestion(key)) continue;
528
+ suggestions.push(prefixKeyValueSuggestion(suggestion, "", separator));
529
+ }
530
+ }
531
+ if (index < 0) {
532
+ yield* require_suggestion.deduplicateSuggestions(suggestions);
533
+ return;
534
+ }
535
+ if (typeof valueParser.suggest === "function") {
536
+ const key = prefix.slice(0, index);
537
+ if (!validateKeyForSuggestion(key)) {
538
+ yield* require_suggestion.deduplicateSuggestions(suggestions);
539
+ return;
540
+ }
541
+ const valuePrefix = prefix.slice(index + separator.length);
542
+ for (const suggestion of valueParser.suggest(valuePrefix)) {
543
+ const value = suggestionTextValue(suggestion);
544
+ if (!partsRoundTrip(key, value)) continue;
545
+ if (suggestion.kind === "literal" && !validateParts(`${key}${separator}${value}`, key, value).success) continue;
546
+ suggestions.push(prefixKeyValueSuggestion(suggestion, `${key}${separator}`));
547
+ }
548
+ }
549
+ yield* require_suggestion.deduplicateSuggestions(suggestions);
550
+ } } : {}
551
+ };
552
+ }
553
+ function checkKeyValueChildParser(role, parser) {
554
+ if (!isValueParser(parser)) throw new TypeError(`The ${role} option for keyValue() must be a value parser.`);
555
+ if (parser.mode !== "sync") throw new TypeError(`keyValue() only supports sync ${role} parsers, but an async one was given.`);
556
+ if (require_internal_dependency.isDerivedValueParser(parser)) throw new TypeError(`keyValue() does not support dependency-derived ${role} parsers (created via deriveFrom() or dependency().derive()); pass the derived parser directly to option() or argument() instead.`);
557
+ }
558
+ function validateValueParserValue(parser, value) {
559
+ if (typeof parser.validate === "function") return parser.validate(value);
560
+ let formatted;
561
+ try {
562
+ formatted = parser.format(value);
563
+ } catch {
564
+ return {
565
+ success: true,
566
+ value
567
+ };
568
+ }
569
+ if (typeof formatted !== "string") return {
570
+ success: false,
571
+ error: stringFormatError()
572
+ };
573
+ return parser.parse(formatted);
574
+ }
575
+ function formatValueParserValue(parser, value) {
576
+ let formatted;
577
+ try {
578
+ formatted = parser.format(value);
579
+ } catch {
580
+ return {
581
+ success: true,
582
+ value: void 0
583
+ };
584
+ }
585
+ if (typeof formatted !== "string") return {
586
+ success: false,
587
+ error: stringFormatError()
588
+ };
589
+ return {
590
+ success: true,
591
+ value: formatted
592
+ };
593
+ }
594
+ function stringFormatError() {
595
+ return require_message.message`Expected a value formatted as a string.`;
596
+ }
597
+ function suggestionTextValue(suggestion) {
598
+ return suggestion.kind === "literal" ? suggestion.text : suggestion.pattern ?? "";
599
+ }
600
+ function prefixKeyValueSuggestion(suggestion, prefix, suffix = "") {
601
+ const textValue = suggestionTextValue(suggestion);
602
+ const text$1 = `${prefix}${textValue}${suffix}`;
603
+ if (suggestion.kind === "file" && suffix === "") return {
604
+ ...suggestion,
605
+ pattern: text$1
606
+ };
607
+ return suggestion.description == null ? {
608
+ kind: "literal",
609
+ text: text$1
610
+ } : {
611
+ kind: "literal",
612
+ text: text$1,
613
+ description: suggestion.description
614
+ };
615
+ }
616
+ function isKeyValueTuple(value) {
617
+ return Array.isArray(value) && value.length === 2 && 0 in value && 1 in value;
618
+ }
619
+ function makeKeyValueSuccess(keyResult, valueResult) {
620
+ const deferredKeys = /* @__PURE__ */ new Map();
621
+ let hasDeferred = false;
622
+ collectKeyValueDeferredKeys(deferredKeys, 0, keyResult, () => {
623
+ hasDeferred = true;
624
+ });
625
+ collectKeyValueDeferredKeys(deferredKeys, 1, valueResult, () => {
626
+ hasDeferred = true;
627
+ });
628
+ return {
629
+ success: true,
630
+ value: [keyResult.value, valueResult.value],
631
+ ...hasDeferred ? {
632
+ deferred: true,
633
+ ...deferredKeys.size > 0 ? { deferredKeys } : {}
634
+ } : {}
635
+ };
636
+ }
637
+ function collectKeyValueDeferredKeys(deferredKeys, index, result, markDeferred) {
638
+ if (result.deferredKeys != null) {
639
+ markDeferred();
640
+ deferredKeys.set(index, result.deferredKeys);
641
+ return;
642
+ }
643
+ if (result.deferred !== true) return;
644
+ markDeferred();
645
+ deferredKeys.set(index, null);
646
+ }
330
647
  /**
331
648
  * Creates a ValueParser for parsing integer values from strings.
332
649
  *
@@ -5799,6 +6116,7 @@ exports.ipv6 = ipv6;
5799
6116
  exports.isNonEmptyString = require_nonempty.isNonEmptyString;
5800
6117
  exports.isValueParser = isValueParser;
5801
6118
  exports.json = json;
6119
+ exports.keyValue = keyValue;
5802
6120
  exports.locale = locale;
5803
6121
  exports.macAddress = macAddress;
5804
6122
  exports.port = port;
@@ -385,6 +385,130 @@ declare function checkEnumOption<T extends object>(options: T | undefined, key:
385
385
  * `RegExp` instance.
386
386
  */
387
387
  declare function string(options?: StringOptions): ValueParser<"sync", string>;
388
+ interface KeyValueOptionsBase {
389
+ /**
390
+ * The metavariable name for this parser. Used in help messages to
391
+ * indicate the expected key–value shape.
392
+ * @default `"KEY=VALUE"` with the configured separator.
393
+ */
394
+ readonly metavar?: NonEmptyString;
395
+ /**
396
+ * The separator between key and value.
397
+ * @default `"="`
398
+ */
399
+ readonly separator?: string;
400
+ /**
401
+ * If `true`, accepts an empty key before the separator.
402
+ * @default `false`
403
+ */
404
+ readonly allowEmptyKey?: boolean;
405
+ /**
406
+ * If `true`, accepts an empty value after the separator.
407
+ * @default `true`
408
+ */
409
+ readonly allowEmptyValue?: boolean;
410
+ /**
411
+ * Chooses which separator occurrence is used when input contains the
412
+ * separator more than once.
413
+ * @default `"first"`
414
+ */
415
+ readonly split?: "first" | "last";
416
+ /**
417
+ * Custom error messages for key–value parsing failures.
418
+ * @since 1.1.0
419
+ */
420
+ readonly errors?: {
421
+ /**
422
+ * Custom error when the input does not contain the separator.
423
+ */
424
+ readonly missingSeparator?: Message | ((input: string, separator: string) => Message);
425
+ /**
426
+ * Custom error when the key side is empty and empty keys are disabled.
427
+ */
428
+ readonly emptyKey?: Message | ((input: string) => Message);
429
+ /**
430
+ * Custom error when the value side is empty and empty values are disabled.
431
+ */
432
+ readonly emptyValue?: Message | ((input: string) => Message);
433
+ /**
434
+ * Custom error wrapper for key parser failures.
435
+ */
436
+ readonly invalidKey?: Message | ((error: Message) => Message);
437
+ /**
438
+ * Custom error wrapper for value parser failures.
439
+ */
440
+ readonly invalidValue?: Message | ((error: Message) => Message);
441
+ };
442
+ }
443
+ type IsDefaultString<T> = [T] extends [string] ? [string] extends [T] ? true : false : false;
444
+ type KeyValueKeyOption<K> = IsDefaultString<K> extends true ? {
445
+ /**
446
+ * Parser used to validate and transform the key side.
447
+ * @default `string({ placeholder: "KEY" })`
448
+ */
449
+ readonly key?: ValueParser<"sync", K>;
450
+ } : {
451
+ /**
452
+ * Parser used to validate and transform the key side.
453
+ * @default `string({ placeholder: "KEY" })`
454
+ */
455
+ readonly key: ValueParser<"sync", K>;
456
+ };
457
+ type KeyValueValueOption<V> = IsDefaultString<V> extends true ? {
458
+ /**
459
+ * Parser used to validate and transform the value side.
460
+ * @default `string()`
461
+ */
462
+ readonly value?: ValueParser<"sync", V>;
463
+ } : {
464
+ /**
465
+ * Parser used to validate and transform the value side.
466
+ * @default `string()`
467
+ */
468
+ readonly value: ValueParser<"sync", V>;
469
+ };
470
+ /**
471
+ * Options for creating a {@link keyValue} parser.
472
+ *
473
+ * The default key and value parsers produce strings. If {@link K} or
474
+ * {@link V} is anything other than the default `string` type, the
475
+ * corresponding child parser is required so the option object cannot promise
476
+ * a type that the default parser would not produce.
477
+ *
478
+ * @template K The parsed key type.
479
+ * @template V The parsed value type.
480
+ * @since 1.1.0
481
+ */
482
+ type KeyValueOptions<K = string, V = string> = KeyValueOptionsBase & KeyValueKeyOption<K> & KeyValueValueOption<V>;
483
+ type KeyValueOptionsInput = KeyValueOptionsBase & {
484
+ readonly key?: ValueParser<"sync", unknown>;
485
+ readonly value?: ValueParser<"sync", unknown>;
486
+ };
487
+ type KeyValueKeyType<Options> = Options extends {
488
+ readonly key: ValueParser<"sync", infer K>;
489
+ } ? K : string;
490
+ type KeyValueValueType<Options> = Options extends {
491
+ readonly value: ValueParser<"sync", infer V>;
492
+ } ? V : string;
493
+ type KeyValueResultType<Options> = Options extends KeyValueOptionsInput ? readonly [KeyValueKeyType<Options>, KeyValueValueType<Options>] : readonly [string, string];
494
+ /**
495
+ * Creates a value parser for strings shaped like `KEY=VALUE`.
496
+ *
497
+ * The default parser splits on the first `=`, rejects empty keys, allows
498
+ * empty values, and returns a readonly `[key, value]` tuple. Custom key and
499
+ * value parsers can narrow or transform either side while preserving the
500
+ * inferred tuple type.
501
+ *
502
+ * @template Options The option object type used to infer child parser results.
503
+ * @param options Configuration options for the key–value parser.
504
+ * @returns A sync value parser producing readonly key–value tuples.
505
+ * @throws {TypeError} If `separator` or `metavar` is empty, if
506
+ * `allowEmptyKey` or `allowEmptyValue` is not a boolean, if `split` is not
507
+ * `"first"` or `"last"`, or if `key` or `value` is not a sync value parser.
508
+ * @since 1.1.0
509
+ */
510
+ declare function keyValue(): ValueParser<"sync", readonly [string, string]>;
511
+ declare function keyValue<const Options extends KeyValueOptionsInput | undefined>(options: Options): ValueParser<"sync", KeyValueResultType<Options>>;
388
512
  /**
389
513
  * Options for creating an integer parser that returns a JavaScript `number`.
390
514
  *
@@ -2934,4 +3058,4 @@ declare function firstOf<const TParsers extends readonly [ValueParser<"sync", un
2934
3058
  */
2935
3059
  declare function firstOf<const TParsers extends readonly ValueParser<"sync", unknown>[]>(parsers: TParsers, options?: FirstOfOptions): ValueParser<"sync", ValueParserValue<TParsers[number]>>;
2936
3060
  //#endregion
2937
- export { ChoiceOptions, ChoiceOptionsBase, ChoiceOptionsNumber, ChoiceOptionsString, CidrOptions, CidrValue, Color, ColorFormat, ColorOptions, DeferredMap, DomainOptions, EmailOptions, FileSizeOptions, FileSizeOptionsBigInt, FileSizeOptionsNumber, FileSizeUnit, FirstOfOptions, FloatOptions, HostnameOptions, IntegerOptionsBigInt, IntegerOptionsNumber, IpOptions, Ipv4Options, Ipv6Options, Json, JsonOptions, LocaleOptions, MacAddressOptions, type Mode, type ModeIterable, type ModeValue, type NonEmptyString, PortOptionsBigInt, PortOptionsNumber, PortRangeOptionsBigInt, PortRangeOptionsNumber, PortRangeValueBigInt, PortRangeValueNumber, SemVer, SemVerOptionsObject, SemVerOptionsString, SemVerString, SocketAddressOptions, SocketAddressValue, StringOptions, UrlOptions, Uuid, UuidOptions, ValueParser, ValueParserResult, checkBooleanOption, checkEnumOption, choice, cidr, color, domain, email, ensureNonEmptyString, fileSize, firstOf, float, hostname, integer, ip, ipv4, ipv6, isNonEmptyString, isValueParser, json, locale, macAddress, port, portRange, semVer, socketAddress, string, url, uuid };
3061
+ export { ChoiceOptions, ChoiceOptionsBase, ChoiceOptionsNumber, ChoiceOptionsString, CidrOptions, CidrValue, Color, ColorFormat, ColorOptions, DeferredMap, DomainOptions, EmailOptions, FileSizeOptions, FileSizeOptionsBigInt, FileSizeOptionsNumber, FileSizeUnit, FirstOfOptions, FloatOptions, HostnameOptions, IntegerOptionsBigInt, IntegerOptionsNumber, IpOptions, Ipv4Options, Ipv6Options, Json, JsonOptions, KeyValueOptions, LocaleOptions, MacAddressOptions, type Mode, type ModeIterable, type ModeValue, type NonEmptyString, PortOptionsBigInt, PortOptionsNumber, PortRangeOptionsBigInt, PortRangeOptionsNumber, PortRangeValueBigInt, PortRangeValueNumber, SemVer, SemVerOptionsObject, SemVerOptionsString, SemVerString, SocketAddressOptions, SocketAddressValue, StringOptions, UrlOptions, Uuid, UuidOptions, ValueParser, ValueParserResult, checkBooleanOption, checkEnumOption, choice, cidr, color, domain, email, ensureNonEmptyString, fileSize, firstOf, float, hostname, integer, ip, ipv4, ipv6, isNonEmptyString, isValueParser, json, keyValue, locale, macAddress, port, portRange, semVer, socketAddress, string, url, uuid };
@@ -385,6 +385,130 @@ declare function checkEnumOption<T extends object>(options: T | undefined, key:
385
385
  * `RegExp` instance.
386
386
  */
387
387
  declare function string(options?: StringOptions): ValueParser<"sync", string>;
388
+ interface KeyValueOptionsBase {
389
+ /**
390
+ * The metavariable name for this parser. Used in help messages to
391
+ * indicate the expected key–value shape.
392
+ * @default `"KEY=VALUE"` with the configured separator.
393
+ */
394
+ readonly metavar?: NonEmptyString;
395
+ /**
396
+ * The separator between key and value.
397
+ * @default `"="`
398
+ */
399
+ readonly separator?: string;
400
+ /**
401
+ * If `true`, accepts an empty key before the separator.
402
+ * @default `false`
403
+ */
404
+ readonly allowEmptyKey?: boolean;
405
+ /**
406
+ * If `true`, accepts an empty value after the separator.
407
+ * @default `true`
408
+ */
409
+ readonly allowEmptyValue?: boolean;
410
+ /**
411
+ * Chooses which separator occurrence is used when input contains the
412
+ * separator more than once.
413
+ * @default `"first"`
414
+ */
415
+ readonly split?: "first" | "last";
416
+ /**
417
+ * Custom error messages for key–value parsing failures.
418
+ * @since 1.1.0
419
+ */
420
+ readonly errors?: {
421
+ /**
422
+ * Custom error when the input does not contain the separator.
423
+ */
424
+ readonly missingSeparator?: Message | ((input: string, separator: string) => Message);
425
+ /**
426
+ * Custom error when the key side is empty and empty keys are disabled.
427
+ */
428
+ readonly emptyKey?: Message | ((input: string) => Message);
429
+ /**
430
+ * Custom error when the value side is empty and empty values are disabled.
431
+ */
432
+ readonly emptyValue?: Message | ((input: string) => Message);
433
+ /**
434
+ * Custom error wrapper for key parser failures.
435
+ */
436
+ readonly invalidKey?: Message | ((error: Message) => Message);
437
+ /**
438
+ * Custom error wrapper for value parser failures.
439
+ */
440
+ readonly invalidValue?: Message | ((error: Message) => Message);
441
+ };
442
+ }
443
+ type IsDefaultString<T> = [T] extends [string] ? [string] extends [T] ? true : false : false;
444
+ type KeyValueKeyOption<K> = IsDefaultString<K> extends true ? {
445
+ /**
446
+ * Parser used to validate and transform the key side.
447
+ * @default `string({ placeholder: "KEY" })`
448
+ */
449
+ readonly key?: ValueParser<"sync", K>;
450
+ } : {
451
+ /**
452
+ * Parser used to validate and transform the key side.
453
+ * @default `string({ placeholder: "KEY" })`
454
+ */
455
+ readonly key: ValueParser<"sync", K>;
456
+ };
457
+ type KeyValueValueOption<V> = IsDefaultString<V> extends true ? {
458
+ /**
459
+ * Parser used to validate and transform the value side.
460
+ * @default `string()`
461
+ */
462
+ readonly value?: ValueParser<"sync", V>;
463
+ } : {
464
+ /**
465
+ * Parser used to validate and transform the value side.
466
+ * @default `string()`
467
+ */
468
+ readonly value: ValueParser<"sync", V>;
469
+ };
470
+ /**
471
+ * Options for creating a {@link keyValue} parser.
472
+ *
473
+ * The default key and value parsers produce strings. If {@link K} or
474
+ * {@link V} is anything other than the default `string` type, the
475
+ * corresponding child parser is required so the option object cannot promise
476
+ * a type that the default parser would not produce.
477
+ *
478
+ * @template K The parsed key type.
479
+ * @template V The parsed value type.
480
+ * @since 1.1.0
481
+ */
482
+ type KeyValueOptions<K = string, V = string> = KeyValueOptionsBase & KeyValueKeyOption<K> & KeyValueValueOption<V>;
483
+ type KeyValueOptionsInput = KeyValueOptionsBase & {
484
+ readonly key?: ValueParser<"sync", unknown>;
485
+ readonly value?: ValueParser<"sync", unknown>;
486
+ };
487
+ type KeyValueKeyType<Options> = Options extends {
488
+ readonly key: ValueParser<"sync", infer K>;
489
+ } ? K : string;
490
+ type KeyValueValueType<Options> = Options extends {
491
+ readonly value: ValueParser<"sync", infer V>;
492
+ } ? V : string;
493
+ type KeyValueResultType<Options> = Options extends KeyValueOptionsInput ? readonly [KeyValueKeyType<Options>, KeyValueValueType<Options>] : readonly [string, string];
494
+ /**
495
+ * Creates a value parser for strings shaped like `KEY=VALUE`.
496
+ *
497
+ * The default parser splits on the first `=`, rejects empty keys, allows
498
+ * empty values, and returns a readonly `[key, value]` tuple. Custom key and
499
+ * value parsers can narrow or transform either side while preserving the
500
+ * inferred tuple type.
501
+ *
502
+ * @template Options The option object type used to infer child parser results.
503
+ * @param options Configuration options for the key–value parser.
504
+ * @returns A sync value parser producing readonly key–value tuples.
505
+ * @throws {TypeError} If `separator` or `metavar` is empty, if
506
+ * `allowEmptyKey` or `allowEmptyValue` is not a boolean, if `split` is not
507
+ * `"first"` or `"last"`, or if `key` or `value` is not a sync value parser.
508
+ * @since 1.1.0
509
+ */
510
+ declare function keyValue(): ValueParser<"sync", readonly [string, string]>;
511
+ declare function keyValue<const Options extends KeyValueOptionsInput | undefined>(options: Options): ValueParser<"sync", KeyValueResultType<Options>>;
388
512
  /**
389
513
  * Options for creating an integer parser that returns a JavaScript `number`.
390
514
  *
@@ -2934,4 +3058,4 @@ declare function firstOf<const TParsers extends readonly [ValueParser<"sync", un
2934
3058
  */
2935
3059
  declare function firstOf<const TParsers extends readonly ValueParser<"sync", unknown>[]>(parsers: TParsers, options?: FirstOfOptions): ValueParser<"sync", ValueParserValue<TParsers[number]>>;
2936
3060
  //#endregion
2937
- export { ChoiceOptions, ChoiceOptionsBase, ChoiceOptionsNumber, ChoiceOptionsString, CidrOptions, CidrValue, Color, ColorFormat, ColorOptions, DeferredMap, DomainOptions, EmailOptions, FileSizeOptions, FileSizeOptionsBigInt, FileSizeOptionsNumber, FileSizeUnit, FirstOfOptions, FloatOptions, HostnameOptions, IntegerOptionsBigInt, IntegerOptionsNumber, IpOptions, Ipv4Options, Ipv6Options, Json, JsonOptions, LocaleOptions, MacAddressOptions, type Mode, type ModeIterable, type ModeValue, type NonEmptyString, PortOptionsBigInt, PortOptionsNumber, PortRangeOptionsBigInt, PortRangeOptionsNumber, PortRangeValueBigInt, PortRangeValueNumber, SemVer, SemVerOptionsObject, SemVerOptionsString, SemVerString, SocketAddressOptions, SocketAddressValue, StringOptions, UrlOptions, Uuid, UuidOptions, ValueParser, ValueParserResult, checkBooleanOption, checkEnumOption, choice, cidr, color, domain, email, ensureNonEmptyString, fileSize, firstOf, float, hostname, integer, ip, ipv4, ipv6, isNonEmptyString, isValueParser, json, locale, macAddress, port, portRange, semVer, socketAddress, string, url, uuid };
3061
+ export { ChoiceOptions, ChoiceOptionsBase, ChoiceOptionsNumber, ChoiceOptionsString, CidrOptions, CidrValue, Color, ColorFormat, ColorOptions, DeferredMap, DomainOptions, EmailOptions, FileSizeOptions, FileSizeOptionsBigInt, FileSizeOptionsNumber, FileSizeUnit, FirstOfOptions, FloatOptions, HostnameOptions, IntegerOptionsBigInt, IntegerOptionsNumber, IpOptions, Ipv4Options, Ipv6Options, Json, JsonOptions, KeyValueOptions, LocaleOptions, MacAddressOptions, type Mode, type ModeIterable, type ModeValue, type NonEmptyString, PortOptionsBigInt, PortOptionsNumber, PortRangeOptionsBigInt, PortRangeOptionsNumber, PortRangeValueBigInt, PortRangeValueNumber, SemVer, SemVerOptionsObject, SemVerOptionsString, SemVerString, SocketAddressOptions, SocketAddressValue, StringOptions, UrlOptions, Uuid, UuidOptions, ValueParser, ValueParserResult, checkBooleanOption, checkEnumOption, choice, cidr, color, domain, email, ensureNonEmptyString, fileSize, firstOf, float, hostname, integer, ip, ipv4, ipv6, isNonEmptyString, isValueParser, json, keyValue, locale, macAddress, port, portRange, semVer, socketAddress, string, url, uuid };
@@ -327,6 +327,323 @@ function string(options = {}) {
327
327
  }
328
328
  };
329
329
  }
330
+ function keyValue(options = {}) {
331
+ const separator = options.separator ?? "=";
332
+ if (typeof separator !== "string") throw new TypeError(`Expected separator to be a string, but got ${typeof separator}: ${String(separator)}.`);
333
+ ensureNonEmptyString(separator);
334
+ checkBooleanOption(options, "allowEmptyKey");
335
+ checkBooleanOption(options, "allowEmptyValue");
336
+ checkEnumOption(options, "split", ["first", "last"]);
337
+ const split = options.split ?? "first";
338
+ const allowEmptyKey = options.allowEmptyKey ?? false;
339
+ const allowEmptyValue = options.allowEmptyValue ?? true;
340
+ const metavar$1 = options.metavar ?? `KEY${separator}VALUE`;
341
+ ensureNonEmptyString(metavar$1);
342
+ const rawKeyParser = options.key ?? string({ placeholder: "KEY" });
343
+ const rawValueParser = options.value ?? string({ placeholder: allowEmptyValue ? "" : "VALUE" });
344
+ checkKeyValueChildParser("key", rawKeyParser);
345
+ checkKeyValueChildParser("value", rawValueParser);
346
+ const keyParser = rawKeyParser;
347
+ const valueParser = rawValueParser;
348
+ const hasNormalize = typeof keyParser.normalize === "function" || typeof valueParser.normalize === "function";
349
+ const hasSuggest = typeof keyParser.suggest === "function" || typeof valueParser.suggest === "function";
350
+ function findSeparator(input) {
351
+ return split === "last" ? input.lastIndexOf(separator) : input.indexOf(separator);
352
+ }
353
+ function emptyKeyError(input) {
354
+ const custom = options.errors?.emptyKey;
355
+ if (custom != null) return typeof custom === "function" ? custom(input) : custom;
356
+ return message`Expected a non-empty key in ${input}.`;
357
+ }
358
+ function emptyValueError(input) {
359
+ const custom = options.errors?.emptyValue;
360
+ if (custom != null) return typeof custom === "function" ? custom(input) : custom;
361
+ return message`Expected a non-empty value in ${input}.`;
362
+ }
363
+ function missingSeparatorError(input) {
364
+ const custom = options.errors?.missingSeparator;
365
+ if (custom != null) return typeof custom === "function" ? custom(input, separator) : custom;
366
+ return message`Expected ${separator} in ${input}.`;
367
+ }
368
+ function invalidKeyError(error) {
369
+ const custom = options.errors?.invalidKey;
370
+ if (custom != null) return typeof custom === "function" ? custom(error) : custom;
371
+ return [text("Invalid key: "), ...cloneMessage(error)];
372
+ }
373
+ function invalidValueError(error) {
374
+ const custom = options.errors?.invalidValue;
375
+ if (custom != null) return typeof custom === "function" ? custom(error) : custom;
376
+ return [text("Invalid value: "), ...cloneMessage(error)];
377
+ }
378
+ function validateParts(input, key, value) {
379
+ if (!allowEmptyKey && key === "") return {
380
+ success: false,
381
+ error: emptyKeyError(input)
382
+ };
383
+ if (!allowEmptyValue && value === "") return {
384
+ success: false,
385
+ error: emptyValueError(input)
386
+ };
387
+ const keyResult = keyParser.parse(key);
388
+ if (!keyResult.success) return {
389
+ success: false,
390
+ error: invalidKeyError(keyResult.error)
391
+ };
392
+ const valueResult = valueParser.parse(value);
393
+ if (!valueResult.success) return {
394
+ success: false,
395
+ error: invalidValueError(valueResult.error)
396
+ };
397
+ return validateResultParts(input, keyResult, valueResult);
398
+ }
399
+ function validateKeyForSuggestion(key) {
400
+ if (!allowEmptyKey && key === "") return false;
401
+ if (!partsRoundTrip(key, "")) return false;
402
+ const keyResult = keyParser.parse(key);
403
+ if (!keyResult.success) return false;
404
+ if (!allowEmptyKey && keyResult.value === "") return false;
405
+ const formattedKeyResult = formatValueParserValue(keyParser, keyResult.value);
406
+ if (!formattedKeyResult.success) return false;
407
+ const formattedKey = formattedKeyResult.value;
408
+ return formattedKey == null || partsRoundTrip(formattedKey, "");
409
+ }
410
+ function validateKeyPatternForSuggestion(key) {
411
+ if (!allowEmptyKey && key === "") return false;
412
+ return partsRoundTrip(key, "");
413
+ }
414
+ function fallbackInput(key, value) {
415
+ return `${typeof key === "string" ? key : ""}${separator}${typeof value === "string" ? value : ""}`;
416
+ }
417
+ function partsRoundTrip(key, value) {
418
+ const input = `${key}${separator}${value}`;
419
+ const index = findSeparator(input);
420
+ if (index < 0) return false;
421
+ return input.slice(0, index) === key && input.slice(index + separator.length) === value;
422
+ }
423
+ function validateResultParts(input, keyResult, valueResult) {
424
+ if (!allowEmptyKey && keyResult.value === "") return {
425
+ success: false,
426
+ error: emptyKeyError(input)
427
+ };
428
+ if (!allowEmptyValue && valueResult.value === "") return {
429
+ success: false,
430
+ error: emptyValueError(input)
431
+ };
432
+ const formattedKeyResult = formatValueParserValue(keyParser, keyResult.value);
433
+ if (!formattedKeyResult.success) return {
434
+ success: false,
435
+ error: invalidKeyError(formattedKeyResult.error)
436
+ };
437
+ const formattedValueResult = formatValueParserValue(valueParser, valueResult.value);
438
+ if (!formattedValueResult.success) return {
439
+ success: false,
440
+ error: invalidValueError(formattedValueResult.error)
441
+ };
442
+ const formattedKey = formattedKeyResult.value;
443
+ const formattedValue = formattedValueResult.value;
444
+ if (!allowEmptyKey && formattedKey === "") return {
445
+ success: false,
446
+ error: emptyKeyError(input)
447
+ };
448
+ if (!allowEmptyValue && formattedValue === "") return {
449
+ success: false,
450
+ error: emptyValueError(input)
451
+ };
452
+ if (split === "first" && formattedKey != null && formattedKey.includes(separator)) return {
453
+ success: false,
454
+ error: invalidKeyError(message`Expected a key without ${separator}, but got ${formattedKey}.`)
455
+ };
456
+ if (split === "last" && formattedValue != null && formattedValue.includes(separator)) return {
457
+ success: false,
458
+ error: invalidValueError(message`Expected a value without ${separator}, but got ${formattedValue}.`)
459
+ };
460
+ if (formattedKey != null && formattedValue != null) {
461
+ if (!partsRoundTrip(formattedKey, formattedValue)) return split === "first" ? {
462
+ success: false,
463
+ error: invalidKeyError(message`Expected a key that round-trips with ${separator}, but got ${formattedKey}.`)
464
+ } : {
465
+ success: false,
466
+ error: invalidValueError(message`Expected a value that round-trips with ${separator}, but got ${formattedValue}.`)
467
+ };
468
+ }
469
+ return makeKeyValueSuccess(keyResult, valueResult);
470
+ }
471
+ function validateTuple(value) {
472
+ if (!allowEmptyKey && value[0] === "") return {
473
+ success: false,
474
+ error: emptyKeyError(fallbackInput(value[0], value[1]))
475
+ };
476
+ if (!allowEmptyValue && value[1] === "") return {
477
+ success: false,
478
+ error: emptyValueError(fallbackInput(value[0], value[1]))
479
+ };
480
+ const keyResult = validateValueParserValue(keyParser, value[0]);
481
+ if (!keyResult.success) return {
482
+ success: false,
483
+ error: invalidKeyError(keyResult.error)
484
+ };
485
+ const valueResult = validateValueParserValue(valueParser, value[1]);
486
+ if (!valueResult.success) return {
487
+ success: false,
488
+ error: invalidValueError(valueResult.error)
489
+ };
490
+ return validateResultParts(fallbackInput(value[0], value[1]), keyResult, valueResult);
491
+ }
492
+ return {
493
+ mode: "sync",
494
+ metavar: metavar$1,
495
+ placeholder: [keyParser.placeholder, valueParser.placeholder],
496
+ parse(input) {
497
+ const index = findSeparator(input);
498
+ if (index < 0) return {
499
+ success: false,
500
+ error: missingSeparatorError(input)
501
+ };
502
+ const key = input.slice(0, index);
503
+ const value = input.slice(index + separator.length);
504
+ return validateParts(input, key, value);
505
+ },
506
+ format(value) {
507
+ return `${keyParser.format(value[0])}${separator}${valueParser.format(value[1])}`;
508
+ },
509
+ validate(value) {
510
+ if (!isKeyValueTuple(value)) return {
511
+ success: false,
512
+ error: message`Expected a key-value tuple.`
513
+ };
514
+ return validateTuple(value);
515
+ },
516
+ ...hasNormalize ? { normalize(value) {
517
+ if (!isKeyValueTuple(value)) return value;
518
+ const normalized = [typeof keyParser.normalize === "function" ? keyParser.normalize(value[0]) : value[0], typeof valueParser.normalize === "function" ? valueParser.normalize(value[1]) : value[1]];
519
+ return validateTuple(normalized).success ? normalized : value;
520
+ } } : {},
521
+ ...hasSuggest ? { *suggest(prefix) {
522
+ const index = findSeparator(prefix);
523
+ const suggestions = [];
524
+ if (index < 0 || split === "last") {
525
+ if (typeof keyParser.suggest === "function") for (const suggestion of keyParser.suggest(prefix)) {
526
+ const key = suggestionTextValue(suggestion);
527
+ if (suggestion.kind === "literal" ? !validateKeyForSuggestion(key) : !validateKeyPatternForSuggestion(key)) continue;
528
+ suggestions.push(prefixKeyValueSuggestion(suggestion, "", separator));
529
+ }
530
+ }
531
+ if (index < 0) {
532
+ yield* deduplicateSuggestions(suggestions);
533
+ return;
534
+ }
535
+ if (typeof valueParser.suggest === "function") {
536
+ const key = prefix.slice(0, index);
537
+ if (!validateKeyForSuggestion(key)) {
538
+ yield* deduplicateSuggestions(suggestions);
539
+ return;
540
+ }
541
+ const valuePrefix = prefix.slice(index + separator.length);
542
+ for (const suggestion of valueParser.suggest(valuePrefix)) {
543
+ const value = suggestionTextValue(suggestion);
544
+ if (!partsRoundTrip(key, value)) continue;
545
+ if (suggestion.kind === "literal" && !validateParts(`${key}${separator}${value}`, key, value).success) continue;
546
+ suggestions.push(prefixKeyValueSuggestion(suggestion, `${key}${separator}`));
547
+ }
548
+ }
549
+ yield* deduplicateSuggestions(suggestions);
550
+ } } : {}
551
+ };
552
+ }
553
+ function checkKeyValueChildParser(role, parser) {
554
+ if (!isValueParser(parser)) throw new TypeError(`The ${role} option for keyValue() must be a value parser.`);
555
+ if (parser.mode !== "sync") throw new TypeError(`keyValue() only supports sync ${role} parsers, but an async one was given.`);
556
+ if (isDerivedValueParser(parser)) throw new TypeError(`keyValue() does not support dependency-derived ${role} parsers (created via deriveFrom() or dependency().derive()); pass the derived parser directly to option() or argument() instead.`);
557
+ }
558
+ function validateValueParserValue(parser, value) {
559
+ if (typeof parser.validate === "function") return parser.validate(value);
560
+ let formatted;
561
+ try {
562
+ formatted = parser.format(value);
563
+ } catch {
564
+ return {
565
+ success: true,
566
+ value
567
+ };
568
+ }
569
+ if (typeof formatted !== "string") return {
570
+ success: false,
571
+ error: stringFormatError()
572
+ };
573
+ return parser.parse(formatted);
574
+ }
575
+ function formatValueParserValue(parser, value) {
576
+ let formatted;
577
+ try {
578
+ formatted = parser.format(value);
579
+ } catch {
580
+ return {
581
+ success: true,
582
+ value: void 0
583
+ };
584
+ }
585
+ if (typeof formatted !== "string") return {
586
+ success: false,
587
+ error: stringFormatError()
588
+ };
589
+ return {
590
+ success: true,
591
+ value: formatted
592
+ };
593
+ }
594
+ function stringFormatError() {
595
+ return message`Expected a value formatted as a string.`;
596
+ }
597
+ function suggestionTextValue(suggestion) {
598
+ return suggestion.kind === "literal" ? suggestion.text : suggestion.pattern ?? "";
599
+ }
600
+ function prefixKeyValueSuggestion(suggestion, prefix, suffix = "") {
601
+ const textValue = suggestionTextValue(suggestion);
602
+ const text$1 = `${prefix}${textValue}${suffix}`;
603
+ if (suggestion.kind === "file" && suffix === "") return {
604
+ ...suggestion,
605
+ pattern: text$1
606
+ };
607
+ return suggestion.description == null ? {
608
+ kind: "literal",
609
+ text: text$1
610
+ } : {
611
+ kind: "literal",
612
+ text: text$1,
613
+ description: suggestion.description
614
+ };
615
+ }
616
+ function isKeyValueTuple(value) {
617
+ return Array.isArray(value) && value.length === 2 && 0 in value && 1 in value;
618
+ }
619
+ function makeKeyValueSuccess(keyResult, valueResult) {
620
+ const deferredKeys = /* @__PURE__ */ new Map();
621
+ let hasDeferred = false;
622
+ collectKeyValueDeferredKeys(deferredKeys, 0, keyResult, () => {
623
+ hasDeferred = true;
624
+ });
625
+ collectKeyValueDeferredKeys(deferredKeys, 1, valueResult, () => {
626
+ hasDeferred = true;
627
+ });
628
+ return {
629
+ success: true,
630
+ value: [keyResult.value, valueResult.value],
631
+ ...hasDeferred ? {
632
+ deferred: true,
633
+ ...deferredKeys.size > 0 ? { deferredKeys } : {}
634
+ } : {}
635
+ };
636
+ }
637
+ function collectKeyValueDeferredKeys(deferredKeys, index, result, markDeferred) {
638
+ if (result.deferredKeys != null) {
639
+ markDeferred();
640
+ deferredKeys.set(index, result.deferredKeys);
641
+ return;
642
+ }
643
+ if (result.deferred !== true) return;
644
+ markDeferred();
645
+ deferredKeys.set(index, null);
646
+ }
330
647
  /**
331
648
  * Creates a ValueParser for parsing integer values from strings.
332
649
  *
@@ -5780,4 +6097,4 @@ function plainObjectsEqual(a, b) {
5780
6097
  }
5781
6098
 
5782
6099
  //#endregion
5783
- export { checkBooleanOption, checkEnumOption, choice, cidr, color, domain, email, ensureNonEmptyString, fileSize, firstOf, float, hostname, integer, ip, ipv4, ipv6, isNonEmptyString, isValueParser, json, locale, macAddress, port, portRange, semVer, socketAddress, string, url, uuid };
6100
+ export { checkBooleanOption, checkEnumOption, choice, cidr, color, domain, email, ensureNonEmptyString, fileSize, firstOf, float, hostname, integer, ip, ipv4, ipv6, isNonEmptyString, isValueParser, json, keyValue, locale, macAddress, port, portRange, semVer, socketAddress, string, url, uuid };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@optique/core",
3
- "version": "1.1.0-dev.2152",
3
+ "version": "1.1.0-dev.2160",
4
4
  "description": "Type-safe combinatorial command-line interface parser",
5
5
  "keywords": [
6
6
  "CLI",
@@ -200,7 +200,7 @@
200
200
  "fast-check": "^4.7.0",
201
201
  "tsdown": "^0.13.0",
202
202
  "typescript": "^5.8.3",
203
- "@optique/env": "1.1.0-dev.2152+cc0a0741"
203
+ "@optique/env": "1.1.0-dev.2160+4b3b85cc"
204
204
  },
205
205
  "scripts": {
206
206
  "build": "tsdown",