@optique/core 0.9.0-dev.184 → 0.9.0-dev.186

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
@@ -4,6 +4,7 @@ const require_constructs = require('./constructs.cjs');
4
4
  const require_doc = require('./doc.cjs');
5
5
  const require_completion = require('./completion.cjs');
6
6
  const require_modifiers = require('./modifiers.cjs');
7
+ const require_nonempty = require('./nonempty.cjs');
7
8
  const require_valueparser = require('./valueparser.cjs');
8
9
  const require_primitives = require('./primitives.cjs');
9
10
  const require_parser = require('./parser.cjs');
@@ -21,6 +22,7 @@ exports.commandLine = require_message.commandLine;
21
22
  exports.concat = require_constructs.concat;
22
23
  exports.conditional = require_constructs.conditional;
23
24
  exports.constant = require_primitives.constant;
25
+ exports.ensureNonEmptyString = require_nonempty.ensureNonEmptyString;
24
26
  exports.envVar = require_message.envVar;
25
27
  exports.extractArgumentMetavars = require_usage.extractArgumentMetavars;
26
28
  exports.extractCommandNames = require_usage.extractCommandNames;
@@ -35,6 +37,7 @@ exports.formatUsageTerm = require_usage.formatUsageTerm;
35
37
  exports.getDocPage = require_parser.getDocPage;
36
38
  exports.group = require_constructs.group;
37
39
  exports.integer = require_valueparser.integer;
40
+ exports.isNonEmptyString = require_nonempty.isNonEmptyString;
38
41
  exports.isValueParser = require_valueparser.isValueParser;
39
42
  exports.locale = require_valueparser.locale;
40
43
  exports.longestMatch = require_constructs.longestMatch;
package/dist/index.d.cts CHANGED
@@ -1,3 +1,4 @@
1
+ import { NonEmptyString, ensureNonEmptyString, isNonEmptyString } from "./nonempty.cjs";
1
2
  import { Message, MessageFormatOptions, MessageTerm, commandLine, envVar, formatMessage, message, metavar, optionName, optionNames, text, value, values } from "./message.cjs";
2
3
  import { OptionName, Usage, UsageFormatOptions, UsageTerm, UsageTermFormatOptions, extractArgumentMetavars, extractCommandNames, extractOptionNames, formatUsage, formatUsageTerm, normalizeUsage } from "./usage.cjs";
3
4
  import { DocEntry, DocFragment, DocFragments, DocPage, DocPageFormatOptions, DocSection, ShowDefaultOptions, formatDocPage } from "./doc.cjs";
@@ -8,4 +9,4 @@ import { DocState, InferValue, Parser, ParserContext, ParserResult, Result, Sugg
8
9
  import { ConditionalErrorOptions, ConditionalOptions, DuplicateOptionError, LongestMatchErrorOptions, LongestMatchOptions, MergeOptions, NoMatchContext, ObjectErrorOptions, ObjectOptions, OrErrorOptions, OrOptions, TupleOptions, concat, conditional, group, longestMatch, merge, object, or, tuple } from "./constructs.cjs";
9
10
  import { ShellCompletion, bash, fish, nu, pwsh, zsh } from "./completion.cjs";
10
11
  import { RunError, RunOptions, RunParserError, run, runParser } from "./facade.cjs";
11
- export { ArgumentErrorOptions, ArgumentOptions, ChoiceOptions, CommandErrorOptions, CommandOptions, ConditionalErrorOptions, ConditionalOptions, DocEntry, DocFragment, DocFragments, DocPage, DocPageFormatOptions, DocSection, DocState, DuplicateOptionError, FlagErrorOptions, FlagOptions, FloatOptions, InferValue, IntegerOptionsBigInt, IntegerOptionsNumber, LocaleOptions, LongestMatchErrorOptions, LongestMatchOptions, MergeOptions, Message, MessageFormatOptions, MessageTerm, MultipleErrorOptions, MultipleOptions, NoMatchContext, ObjectErrorOptions, ObjectOptions, OptionErrorOptions, OptionName, OptionOptions, OrErrorOptions, OrOptions, Parser, ParserContext, ParserResult, PassThroughFormat, PassThroughOptions, Result, RunError, RunOptions, RunParserError, ShellCompletion, ShowDefaultOptions, StringOptions, Suggestion, TupleOptions, UrlOptions, Usage, UsageFormatOptions, UsageTerm, UsageTermFormatOptions, Uuid, UuidOptions, ValueParser, ValueParserResult, WithDefaultError, WithDefaultOptions, argument, bash, choice, command, commandLine, concat, conditional, constant, envVar, extractArgumentMetavars, extractCommandNames, extractOptionNames, fish, flag, float, formatDocPage, formatMessage, formatUsage, formatUsageTerm, getDocPage, group, integer, isValueParser, locale, longestMatch, map, merge, message, metavar, multiple, normalizeUsage, nu, object, option, optionName, optionNames, optional, or, parse, passThrough, pwsh, run, runParser, string, suggest, text, tuple, url, uuid, value, values, withDefault, zsh };
12
+ export { ArgumentErrorOptions, ArgumentOptions, ChoiceOptions, CommandErrorOptions, CommandOptions, ConditionalErrorOptions, ConditionalOptions, DocEntry, DocFragment, DocFragments, DocPage, DocPageFormatOptions, DocSection, DocState, DuplicateOptionError, FlagErrorOptions, FlagOptions, FloatOptions, InferValue, IntegerOptionsBigInt, IntegerOptionsNumber, LocaleOptions, LongestMatchErrorOptions, LongestMatchOptions, MergeOptions, Message, MessageFormatOptions, MessageTerm, MultipleErrorOptions, MultipleOptions, NoMatchContext, NonEmptyString, ObjectErrorOptions, ObjectOptions, OptionErrorOptions, OptionName, OptionOptions, OrErrorOptions, OrOptions, Parser, ParserContext, ParserResult, PassThroughFormat, PassThroughOptions, Result, RunError, RunOptions, RunParserError, ShellCompletion, ShowDefaultOptions, StringOptions, Suggestion, TupleOptions, UrlOptions, Usage, UsageFormatOptions, UsageTerm, UsageTermFormatOptions, Uuid, UuidOptions, ValueParser, ValueParserResult, WithDefaultError, WithDefaultOptions, argument, bash, choice, command, commandLine, concat, conditional, constant, ensureNonEmptyString, envVar, extractArgumentMetavars, extractCommandNames, extractOptionNames, fish, flag, float, formatDocPage, formatMessage, formatUsage, formatUsageTerm, getDocPage, group, integer, isNonEmptyString, isValueParser, locale, longestMatch, map, merge, message, metavar, multiple, normalizeUsage, nu, object, option, optionName, optionNames, optional, or, parse, passThrough, pwsh, run, runParser, string, suggest, text, tuple, url, uuid, value, values, withDefault, zsh };
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { NonEmptyString, ensureNonEmptyString, isNonEmptyString } from "./nonempty.js";
1
2
  import { Message, MessageFormatOptions, MessageTerm, commandLine, envVar, formatMessage, message, metavar, optionName, optionNames, text, value, values } from "./message.js";
2
3
  import { OptionName, Usage, UsageFormatOptions, UsageTerm, UsageTermFormatOptions, extractArgumentMetavars, extractCommandNames, extractOptionNames, formatUsage, formatUsageTerm, normalizeUsage } from "./usage.js";
3
4
  import { DocEntry, DocFragment, DocFragments, DocPage, DocPageFormatOptions, DocSection, ShowDefaultOptions, formatDocPage } from "./doc.js";
@@ -8,4 +9,4 @@ import { DocState, InferValue, Parser, ParserContext, ParserResult, Result, Sugg
8
9
  import { ConditionalErrorOptions, ConditionalOptions, DuplicateOptionError, LongestMatchErrorOptions, LongestMatchOptions, MergeOptions, NoMatchContext, ObjectErrorOptions, ObjectOptions, OrErrorOptions, OrOptions, TupleOptions, concat, conditional, group, longestMatch, merge, object, or, tuple } from "./constructs.js";
9
10
  import { ShellCompletion, bash, fish, nu, pwsh, zsh } from "./completion.js";
10
11
  import { RunError, RunOptions, RunParserError, run, runParser } from "./facade.js";
11
- export { ArgumentErrorOptions, ArgumentOptions, ChoiceOptions, CommandErrorOptions, CommandOptions, ConditionalErrorOptions, ConditionalOptions, DocEntry, DocFragment, DocFragments, DocPage, DocPageFormatOptions, DocSection, DocState, DuplicateOptionError, FlagErrorOptions, FlagOptions, FloatOptions, InferValue, IntegerOptionsBigInt, IntegerOptionsNumber, LocaleOptions, LongestMatchErrorOptions, LongestMatchOptions, MergeOptions, Message, MessageFormatOptions, MessageTerm, MultipleErrorOptions, MultipleOptions, NoMatchContext, ObjectErrorOptions, ObjectOptions, OptionErrorOptions, OptionName, OptionOptions, OrErrorOptions, OrOptions, Parser, ParserContext, ParserResult, PassThroughFormat, PassThroughOptions, Result, RunError, RunOptions, RunParserError, ShellCompletion, ShowDefaultOptions, StringOptions, Suggestion, TupleOptions, UrlOptions, Usage, UsageFormatOptions, UsageTerm, UsageTermFormatOptions, Uuid, UuidOptions, ValueParser, ValueParserResult, WithDefaultError, WithDefaultOptions, argument, bash, choice, command, commandLine, concat, conditional, constant, envVar, extractArgumentMetavars, extractCommandNames, extractOptionNames, fish, flag, float, formatDocPage, formatMessage, formatUsage, formatUsageTerm, getDocPage, group, integer, isValueParser, locale, longestMatch, map, merge, message, metavar, multiple, normalizeUsage, nu, object, option, optionName, optionNames, optional, or, parse, passThrough, pwsh, run, runParser, string, suggest, text, tuple, url, uuid, value, values, withDefault, zsh };
12
+ export { ArgumentErrorOptions, ArgumentOptions, ChoiceOptions, CommandErrorOptions, CommandOptions, ConditionalErrorOptions, ConditionalOptions, DocEntry, DocFragment, DocFragments, DocPage, DocPageFormatOptions, DocSection, DocState, DuplicateOptionError, FlagErrorOptions, FlagOptions, FloatOptions, InferValue, IntegerOptionsBigInt, IntegerOptionsNumber, LocaleOptions, LongestMatchErrorOptions, LongestMatchOptions, MergeOptions, Message, MessageFormatOptions, MessageTerm, MultipleErrorOptions, MultipleOptions, NoMatchContext, NonEmptyString, ObjectErrorOptions, ObjectOptions, OptionErrorOptions, OptionName, OptionOptions, OrErrorOptions, OrOptions, Parser, ParserContext, ParserResult, PassThroughFormat, PassThroughOptions, Result, RunError, RunOptions, RunParserError, ShellCompletion, ShowDefaultOptions, StringOptions, Suggestion, TupleOptions, UrlOptions, Usage, UsageFormatOptions, UsageTerm, UsageTermFormatOptions, Uuid, UuidOptions, ValueParser, ValueParserResult, WithDefaultError, WithDefaultOptions, argument, bash, choice, command, commandLine, concat, conditional, constant, ensureNonEmptyString, envVar, extractArgumentMetavars, extractCommandNames, extractOptionNames, fish, flag, float, formatDocPage, formatMessage, formatUsage, formatUsageTerm, getDocPage, group, integer, isNonEmptyString, isValueParser, locale, longestMatch, map, merge, message, metavar, multiple, normalizeUsage, nu, object, option, optionName, optionNames, optional, or, parse, passThrough, pwsh, run, runParser, string, suggest, text, tuple, url, uuid, value, values, withDefault, zsh };
package/dist/index.js CHANGED
@@ -4,9 +4,10 @@ import { DuplicateOptionError, concat, conditional, group, longestMatch, merge,
4
4
  import { formatDocPage } from "./doc.js";
5
5
  import { bash, fish, nu, pwsh, zsh } from "./completion.js";
6
6
  import { WithDefaultError, map, multiple, optional, withDefault } from "./modifiers.js";
7
+ import { ensureNonEmptyString, isNonEmptyString } from "./nonempty.js";
7
8
  import { choice, float, integer, isValueParser, locale, string, url, uuid } from "./valueparser.js";
8
9
  import { argument, command, constant, flag, option, passThrough } from "./primitives.js";
9
10
  import { getDocPage, parse, suggest } from "./parser.js";
10
11
  import { RunError, RunParserError, run, runParser } from "./facade.js";
11
12
 
12
- export { DuplicateOptionError, RunError, RunParserError, WithDefaultError, argument, bash, choice, command, commandLine, concat, conditional, constant, envVar, extractArgumentMetavars, extractCommandNames, extractOptionNames, fish, flag, float, formatDocPage, formatMessage, formatUsage, formatUsageTerm, getDocPage, group, integer, isValueParser, locale, longestMatch, map, merge, message, metavar, multiple, normalizeUsage, nu, object, option, optionName, optionNames, optional, or, parse, passThrough, pwsh, run, runParser, string, suggest, text, tuple, url, uuid, value, values, withDefault, zsh };
13
+ export { DuplicateOptionError, RunError, RunParserError, WithDefaultError, argument, bash, choice, command, commandLine, concat, conditional, constant, ensureNonEmptyString, envVar, extractArgumentMetavars, extractCommandNames, extractOptionNames, fish, flag, float, formatDocPage, formatMessage, formatUsage, formatUsageTerm, getDocPage, group, integer, isNonEmptyString, isValueParser, locale, longestMatch, map, merge, message, metavar, multiple, normalizeUsage, nu, object, option, optionName, optionNames, optional, or, parse, passThrough, pwsh, run, runParser, string, suggest, text, tuple, url, uuid, value, values, withDefault, zsh };
@@ -1,4 +1,7 @@
1
+ import { NonEmptyString } from "./nonempty.cjs";
2
+
1
3
  //#region src/message.d.ts
4
+
2
5
  /**
3
6
  * Represents a single term in a message, which can be a text, an option
4
7
  * name, a list of option names, a metavariable, a value, or a list of
@@ -60,7 +63,7 @@ type MessageTerm =
60
63
  * The metavariable name, which is a string that represents
61
64
  * a variable in the message. For example, `"VALUE"` or `"ARG"`.
62
65
  */
63
- readonly metavar: string;
66
+ readonly metavar: NonEmptyString;
64
67
  }
65
68
  /**
66
69
  * A value term in the message, which can be a single value.
@@ -171,7 +174,7 @@ declare function optionNames(names: readonly string[]): MessageTerm;
171
174
  * `"ARG"`.
172
175
  * @returns A {@link MessageTerm} representing the metavariable.
173
176
  */
174
- declare function metavar(metavar: string): MessageTerm;
177
+ declare function metavar(metavar: NonEmptyString): MessageTerm;
175
178
  /**
176
179
  * Creates a {@link MessageTerm} for a single value. However, you usually
177
180
  * don't need to use this function directly, as {@link message} string template
package/dist/message.d.ts CHANGED
@@ -1,4 +1,7 @@
1
+ import { NonEmptyString } from "./nonempty.js";
2
+
1
3
  //#region src/message.d.ts
4
+
2
5
  /**
3
6
  * Represents a single term in a message, which can be a text, an option
4
7
  * name, a list of option names, a metavariable, a value, or a list of
@@ -60,7 +63,7 @@ type MessageTerm =
60
63
  * The metavariable name, which is a string that represents
61
64
  * a variable in the message. For example, `"VALUE"` or `"ARG"`.
62
65
  */
63
- readonly metavar: string;
66
+ readonly metavar: NonEmptyString;
64
67
  }
65
68
  /**
66
69
  * A value term in the message, which can be a single value.
@@ -171,7 +174,7 @@ declare function optionNames(names: readonly string[]): MessageTerm;
171
174
  * `"ARG"`.
172
175
  * @returns A {@link MessageTerm} representing the metavariable.
173
176
  */
174
- declare function metavar(metavar: string): MessageTerm;
177
+ declare function metavar(metavar: NonEmptyString): MessageTerm;
175
178
  /**
176
179
  * Creates a {@link MessageTerm} for a single value. However, you usually
177
180
  * don't need to use this function directly, as {@link message} string template
@@ -0,0 +1,26 @@
1
+
2
+ //#region src/nonempty.ts
3
+ /**
4
+ * Checks if a string is non-empty.
5
+ * Can be used as a type guard for type narrowing.
6
+ * @param value The string to check.
7
+ * @returns `true` if the string is non-empty, `false` otherwise.
8
+ * @since 0.9.0
9
+ */
10
+ function isNonEmptyString(value) {
11
+ return value !== "";
12
+ }
13
+ /**
14
+ * Asserts that a string is non-empty.
15
+ * Throws a `TypeError` if the string is empty.
16
+ * @param value The string to validate.
17
+ * @throws {TypeError} If the string is empty.
18
+ * @since 0.9.0
19
+ */
20
+ function ensureNonEmptyString(value) {
21
+ if (value === "") throw new TypeError("Expected a non-empty string.");
22
+ }
23
+
24
+ //#endregion
25
+ exports.ensureNonEmptyString = ensureNonEmptyString;
26
+ exports.isNonEmptyString = isNonEmptyString;
@@ -0,0 +1,29 @@
1
+ //#region src/nonempty.d.ts
2
+ /**
3
+ * A string type that guarantees at least one character.
4
+ * Used for `metavar` properties to ensure they are never empty.
5
+ *
6
+ * This type uses a template literal pattern that requires at least one
7
+ * character, providing compile-time rejection of empty string literals.
8
+ *
9
+ * @since 0.9.0
10
+ */
11
+ type NonEmptyString = `${any}${string}`;
12
+ /**
13
+ * Checks if a string is non-empty.
14
+ * Can be used as a type guard for type narrowing.
15
+ * @param value The string to check.
16
+ * @returns `true` if the string is non-empty, `false` otherwise.
17
+ * @since 0.9.0
18
+ */
19
+ declare function isNonEmptyString(value: string): value is NonEmptyString;
20
+ /**
21
+ * Asserts that a string is non-empty.
22
+ * Throws a `TypeError` if the string is empty.
23
+ * @param value The string to validate.
24
+ * @throws {TypeError} If the string is empty.
25
+ * @since 0.9.0
26
+ */
27
+ declare function ensureNonEmptyString(value: string): asserts value is NonEmptyString;
28
+ //#endregion
29
+ export { NonEmptyString, ensureNonEmptyString, isNonEmptyString };
@@ -0,0 +1,29 @@
1
+ //#region src/nonempty.d.ts
2
+ /**
3
+ * A string type that guarantees at least one character.
4
+ * Used for `metavar` properties to ensure they are never empty.
5
+ *
6
+ * This type uses a template literal pattern that requires at least one
7
+ * character, providing compile-time rejection of empty string literals.
8
+ *
9
+ * @since 0.9.0
10
+ */
11
+ type NonEmptyString = `${any}${string}`;
12
+ /**
13
+ * Checks if a string is non-empty.
14
+ * Can be used as a type guard for type narrowing.
15
+ * @param value The string to check.
16
+ * @returns `true` if the string is non-empty, `false` otherwise.
17
+ * @since 0.9.0
18
+ */
19
+ declare function isNonEmptyString(value: string): value is NonEmptyString;
20
+ /**
21
+ * Asserts that a string is non-empty.
22
+ * Throws a `TypeError` if the string is empty.
23
+ * @param value The string to validate.
24
+ * @throws {TypeError} If the string is empty.
25
+ * @since 0.9.0
26
+ */
27
+ declare function ensureNonEmptyString(value: string): asserts value is NonEmptyString;
28
+ //#endregion
29
+ export { NonEmptyString, ensureNonEmptyString, isNonEmptyString };
@@ -0,0 +1,24 @@
1
+ //#region src/nonempty.ts
2
+ /**
3
+ * Checks if a string is non-empty.
4
+ * Can be used as a type guard for type narrowing.
5
+ * @param value The string to check.
6
+ * @returns `true` if the string is non-empty, `false` otherwise.
7
+ * @since 0.9.0
8
+ */
9
+ function isNonEmptyString(value) {
10
+ return value !== "";
11
+ }
12
+ /**
13
+ * Asserts that a string is non-empty.
14
+ * Throws a `TypeError` if the string is empty.
15
+ * @param value The string to validate.
16
+ * @throws {TypeError} If the string is empty.
17
+ * @since 0.9.0
18
+ */
19
+ function ensureNonEmptyString(value) {
20
+ if (value === "") throw new TypeError("Expected a non-empty string.");
21
+ }
22
+
23
+ //#endregion
24
+ export { ensureNonEmptyString, isNonEmptyString };
package/dist/usage.d.cts CHANGED
@@ -1,4 +1,7 @@
1
+ import { NonEmptyString } from "./nonempty.cjs";
2
+
1
3
  //#region src/usage.d.ts
4
+
2
5
  /**
3
6
  * Represents the name of a command-line option. There are four types of
4
7
  * option syntax:
@@ -26,7 +29,7 @@ type UsageTerm =
26
29
  * The name of the argument, which is used to identify it in
27
30
  * the command-line usage.
28
31
  */
29
- readonly metavar: string;
32
+ readonly metavar: NonEmptyString;
30
33
  /**
31
34
  * When `true`, hides the argument from help text, shell completion
32
35
  * suggestions, and error suggestions.
@@ -51,7 +54,7 @@ type UsageTerm =
51
54
  * An optional metavariable name for the option, which is used
52
55
  * to indicate what value the option expects.
53
56
  */
54
- readonly metavar?: string;
57
+ readonly metavar?: NonEmptyString;
55
58
  /**
56
59
  * When `true`, hides the option from help text, shell completion
57
60
  * suggestions, and "Did you mean?" error suggestions.
package/dist/usage.d.ts CHANGED
@@ -1,4 +1,7 @@
1
+ import { NonEmptyString } from "./nonempty.js";
2
+
1
3
  //#region src/usage.d.ts
4
+
2
5
  /**
3
6
  * Represents the name of a command-line option. There are four types of
4
7
  * option syntax:
@@ -26,7 +29,7 @@ type UsageTerm =
26
29
  * The name of the argument, which is used to identify it in
27
30
  * the command-line usage.
28
31
  */
29
- readonly metavar: string;
32
+ readonly metavar: NonEmptyString;
30
33
  /**
31
34
  * When `true`, hides the argument from help text, shell completion
32
35
  * suggestions, and error suggestions.
@@ -51,7 +54,7 @@ type UsageTerm =
51
54
  * An optional metavariable name for the option, which is used
52
55
  * to indicate what value the option expects.
53
56
  */
54
- readonly metavar?: string;
57
+ readonly metavar?: NonEmptyString;
55
58
  /**
56
59
  * When `true`, hides the option from help text, shell completion
57
60
  * suggestions, and "Did you mean?" error suggestions.
@@ -1,4 +1,5 @@
1
1
  const require_message = require('./message.cjs');
2
+ const require_nonempty = require('./nonempty.cjs');
2
3
 
3
4
  //#region src/valueparser.ts
4
5
  /**
@@ -22,9 +23,11 @@ function isValueParser(object) {
22
23
  * specified values.
23
24
  */
24
25
  function choice(choices, options = {}) {
26
+ const metavar = options.metavar ?? "TYPE";
27
+ require_nonempty.ensureNonEmptyString(metavar);
25
28
  const normalizedValues = options.caseInsensitive ? choices.map((v) => v.toLowerCase()) : choices;
26
29
  return {
27
- metavar: options.metavar ?? "TYPE",
30
+ metavar,
28
31
  parse(input) {
29
32
  const normalizedInput = options.caseInsensitive ? input.toLowerCase() : input;
30
33
  const index = normalizedValues.indexOf(normalizedInput);
@@ -74,8 +77,10 @@ function choice(choices, options = {}) {
74
77
  * specified options.
75
78
  */
76
79
  function string(options = {}) {
80
+ const metavar = options.metavar ?? "STRING";
81
+ require_nonempty.ensureNonEmptyString(metavar);
77
82
  return {
78
- metavar: options.metavar ?? "STRING",
83
+ metavar,
79
84
  parse(input) {
80
85
  if (options.pattern != null && !options.pattern.test(input)) return {
81
86
  success: false,
@@ -125,38 +130,44 @@ function string(options = {}) {
125
130
  * integer type.
126
131
  */
127
132
  function integer(options) {
128
- if (options?.type === "bigint") return {
129
- metavar: options.metavar ?? "INTEGER",
130
- parse(input) {
131
- let value;
132
- try {
133
- value = BigInt(input);
134
- } catch (e) {
135
- if (e instanceof SyntaxError) return {
133
+ if (options?.type === "bigint") {
134
+ const metavar$1 = options.metavar ?? "INTEGER";
135
+ require_nonempty.ensureNonEmptyString(metavar$1);
136
+ return {
137
+ metavar: metavar$1,
138
+ parse(input) {
139
+ let value;
140
+ try {
141
+ value = BigInt(input);
142
+ } catch (e) {
143
+ if (e instanceof SyntaxError) return {
144
+ success: false,
145
+ error: options.errors?.invalidInteger ? typeof options.errors.invalidInteger === "function" ? options.errors.invalidInteger(input) : options.errors.invalidInteger : require_message.message`Expected a valid integer, but got ${input}.`
146
+ };
147
+ throw e;
148
+ }
149
+ if (options.min != null && value < options.min) return {
136
150
  success: false,
137
- error: options.errors?.invalidInteger ? typeof options.errors.invalidInteger === "function" ? options.errors.invalidInteger(input) : options.errors.invalidInteger : require_message.message`Expected a valid integer, but got ${input}.`
151
+ error: options.errors?.belowMinimum ? typeof options.errors.belowMinimum === "function" ? options.errors.belowMinimum(value, options.min) : options.errors.belowMinimum : require_message.message`Expected a value greater than or equal to ${require_message.text(options.min.toLocaleString("en"))}, but got ${input}.`
138
152
  };
139
- throw e;
153
+ else if (options.max != null && value > options.max) return {
154
+ success: false,
155
+ error: options.errors?.aboveMaximum ? typeof options.errors.aboveMaximum === "function" ? options.errors.aboveMaximum(value, options.max) : options.errors.aboveMaximum : require_message.message`Expected a value less than or equal to ${require_message.text(options.max.toLocaleString("en"))}, but got ${input}.`
156
+ };
157
+ return {
158
+ success: true,
159
+ value
160
+ };
161
+ },
162
+ format(value) {
163
+ return value.toString();
140
164
  }
141
- if (options.min != null && value < options.min) return {
142
- success: false,
143
- error: options.errors?.belowMinimum ? typeof options.errors.belowMinimum === "function" ? options.errors.belowMinimum(value, options.min) : options.errors.belowMinimum : require_message.message`Expected a value greater than or equal to ${require_message.text(options.min.toLocaleString("en"))}, but got ${input}.`
144
- };
145
- else if (options.max != null && value > options.max) return {
146
- success: false,
147
- error: options.errors?.aboveMaximum ? typeof options.errors.aboveMaximum === "function" ? options.errors.aboveMaximum(value, options.max) : options.errors.aboveMaximum : require_message.message`Expected a value less than or equal to ${require_message.text(options.max.toLocaleString("en"))}, but got ${input}.`
148
- };
149
- return {
150
- success: true,
151
- value
152
- };
153
- },
154
- format(value) {
155
- return value.toString();
156
- }
157
- };
165
+ };
166
+ }
167
+ const metavar = options?.metavar ?? "INTEGER";
168
+ require_nonempty.ensureNonEmptyString(metavar);
158
169
  return {
159
- metavar: options?.metavar ?? "INTEGER",
170
+ metavar,
160
171
  parse(input) {
161
172
  if (!input.match(/^-?\d+$/)) return {
162
173
  success: false,
@@ -192,8 +203,10 @@ function integer(options) {
192
203
  */
193
204
  function float(options = {}) {
194
205
  const floatRegex = /^[+-]?(?:(?:\d+\.?\d*)|(?:\d*\.\d+))(?:[eE][+-]?\d+)?$/;
206
+ const metavar = options.metavar ?? "NUMBER";
207
+ require_nonempty.ensureNonEmptyString(metavar);
195
208
  return {
196
- metavar: options.metavar ?? "NUMBER",
209
+ metavar,
197
210
  parse(input) {
198
211
  let value;
199
212
  const lowerInput = input.toLowerCase();
@@ -239,8 +252,10 @@ function float(options = {}) {
239
252
  */
240
253
  function url(options = {}) {
241
254
  const allowedProtocols = options.allowedProtocols?.map((p) => p.toLowerCase());
255
+ const metavar = options.metavar ?? "URL";
256
+ require_nonempty.ensureNonEmptyString(metavar);
242
257
  return {
243
- metavar: options.metavar ?? "URL",
258
+ metavar,
244
259
  parse(input) {
245
260
  if (!URL.canParse(input)) return {
246
261
  success: false,
@@ -281,8 +296,10 @@ function url(options = {}) {
281
296
  * objects.
282
297
  */
283
298
  function locale(options = {}) {
299
+ const metavar = options.metavar ?? "LOCALE";
300
+ require_nonempty.ensureNonEmptyString(metavar);
284
301
  return {
285
- metavar: options.metavar ?? "LOCALE",
302
+ metavar,
286
303
  parse(input) {
287
304
  let locale$1;
288
305
  try {
@@ -548,8 +565,10 @@ function locale(options = {}) {
548
565
  */
549
566
  function uuid(options = {}) {
550
567
  const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
568
+ const metavar = options.metavar ?? "UUID";
569
+ require_nonempty.ensureNonEmptyString(metavar);
551
570
  return {
552
- metavar: options.metavar ?? "UUID",
571
+ metavar,
553
572
  parse(input) {
554
573
  if (!uuidRegex.test(input)) return {
555
574
  success: false,
@@ -584,8 +603,10 @@ function uuid(options = {}) {
584
603
 
585
604
  //#endregion
586
605
  exports.choice = choice;
606
+ exports.ensureNonEmptyString = require_nonempty.ensureNonEmptyString;
587
607
  exports.float = float;
588
608
  exports.integer = integer;
609
+ exports.isNonEmptyString = require_nonempty.isNonEmptyString;
589
610
  exports.isValueParser = isValueParser;
590
611
  exports.locale = locale;
591
612
  exports.string = string;
@@ -1,3 +1,4 @@
1
+ import { NonEmptyString, ensureNonEmptyString, isNonEmptyString } from "./nonempty.cjs";
1
2
  import { Message } from "./message.cjs";
2
3
  import { Suggestion } from "./parser.cjs";
3
4
 
@@ -17,7 +18,7 @@ interface ValueParser<T> {
17
18
  * to indicate what kind of value this parser expects. Usually
18
19
  * a single word in uppercase, like `PORT` or `FILE`.
19
20
  */
20
- readonly metavar: string;
21
+ readonly metavar: NonEmptyString;
21
22
  /**
22
23
  * Parses a string input into a value of type {@link T}.
23
24
  *
@@ -75,7 +76,7 @@ interface StringOptions {
75
76
  * word in uppercase, like `HOST` or `NAME`.
76
77
  * @default `"STRING"`
77
78
  */
78
- readonly metavar?: string;
79
+ readonly metavar?: NonEmptyString;
79
80
  /**
80
81
  * Optional regular expression pattern that the string must match.
81
82
  *
@@ -111,7 +112,7 @@ interface ChoiceOptions {
111
112
  * word in uppercase, like `TYPE` or `MODE`.
112
113
  * @default `"TYPE"`
113
114
  */
114
- readonly metavar?: string;
115
+ readonly metavar?: NonEmptyString;
115
116
  /**
116
117
  * If `true`, the parser will perform case-insensitive matching
117
118
  * against the enumerated values. This means that input like "value",
@@ -185,7 +186,7 @@ interface IntegerOptionsNumber {
185
186
  * word in uppercase, like `PORT`.
186
187
  * @default `"INTEGER"`
187
188
  */
188
- readonly metavar?: string;
189
+ readonly metavar?: NonEmptyString;
189
190
  /**
190
191
  * Minimum allowed value (inclusive). If not specified,
191
192
  * no minimum is enforced.
@@ -236,7 +237,7 @@ interface IntegerOptionsBigInt {
236
237
  * word in uppercase, like `PORT`.
237
238
  * @default `"INTEGER"`
238
239
  */
239
- readonly metavar?: string;
240
+ readonly metavar?: NonEmptyString;
240
241
  /**
241
242
  * Minimum allowed value (inclusive). If not specified,
242
243
  * no minimum is enforced.
@@ -296,7 +297,7 @@ interface FloatOptions {
296
297
  * word in uppercase, like `RATE` or `PRICE`.
297
298
  * @default `"NUMBER"`
298
299
  */
299
- readonly metavar?: string;
300
+ readonly metavar?: NonEmptyString;
300
301
  /**
301
302
  * Minimum allowed value (inclusive). If not specified,
302
303
  * no minimum is enforced.
@@ -366,7 +367,7 @@ interface UrlOptions {
366
367
  * word in uppercase, like `URL` or `ENDPOINT`.
367
368
  * @default `"URL"`
368
369
  */
369
- readonly metavar?: string;
370
+ readonly metavar?: NonEmptyString;
370
371
  /**
371
372
  * List of allowed URL protocols (e.g., `["http:", "https:"]`).
372
373
  * If specified, the parsed URL must use one of these protocols.
@@ -413,7 +414,7 @@ interface LocaleOptions {
413
414
  * word in uppercase, like `LOCALE` or `LANG`.
414
415
  * @default `"LOCALE"`
415
416
  */
416
- readonly metavar?: string;
417
+ readonly metavar?: NonEmptyString;
417
418
  /**
418
419
  * Custom error messages for locale parsing failures.
419
420
  * @since 0.5.0
@@ -456,7 +457,7 @@ interface UuidOptions {
456
457
  * word in uppercase, like `UUID` or `ID`.
457
458
  * @default `"UUID"`
458
459
  */
459
- readonly metavar?: string;
460
+ readonly metavar?: NonEmptyString;
460
461
  /**
461
462
  * List of allowed UUID versions (e.g., `[4, 5]` for UUIDs version 4 and 5).
462
463
  * If specified, the parser will validate that the UUID matches one of the
@@ -496,4 +497,4 @@ interface UuidOptions {
496
497
  */
497
498
  declare function uuid(options?: UuidOptions): ValueParser<Uuid>;
498
499
  //#endregion
499
- export { ChoiceOptions, FloatOptions, IntegerOptionsBigInt, IntegerOptionsNumber, LocaleOptions, StringOptions, UrlOptions, Uuid, UuidOptions, ValueParser, ValueParserResult, choice, float, integer, isValueParser, locale, string, url, uuid };
500
+ export { ChoiceOptions, FloatOptions, IntegerOptionsBigInt, IntegerOptionsNumber, LocaleOptions, type NonEmptyString, StringOptions, UrlOptions, Uuid, UuidOptions, ValueParser, ValueParserResult, choice, ensureNonEmptyString, float, integer, isNonEmptyString, isValueParser, locale, string, url, uuid };
@@ -1,3 +1,4 @@
1
+ import { NonEmptyString, ensureNonEmptyString, isNonEmptyString } from "./nonempty.js";
1
2
  import { Message } from "./message.js";
2
3
  import { Suggestion } from "./parser.js";
3
4
 
@@ -17,7 +18,7 @@ interface ValueParser<T> {
17
18
  * to indicate what kind of value this parser expects. Usually
18
19
  * a single word in uppercase, like `PORT` or `FILE`.
19
20
  */
20
- readonly metavar: string;
21
+ readonly metavar: NonEmptyString;
21
22
  /**
22
23
  * Parses a string input into a value of type {@link T}.
23
24
  *
@@ -75,7 +76,7 @@ interface StringOptions {
75
76
  * word in uppercase, like `HOST` or `NAME`.
76
77
  * @default `"STRING"`
77
78
  */
78
- readonly metavar?: string;
79
+ readonly metavar?: NonEmptyString;
79
80
  /**
80
81
  * Optional regular expression pattern that the string must match.
81
82
  *
@@ -111,7 +112,7 @@ interface ChoiceOptions {
111
112
  * word in uppercase, like `TYPE` or `MODE`.
112
113
  * @default `"TYPE"`
113
114
  */
114
- readonly metavar?: string;
115
+ readonly metavar?: NonEmptyString;
115
116
  /**
116
117
  * If `true`, the parser will perform case-insensitive matching
117
118
  * against the enumerated values. This means that input like "value",
@@ -185,7 +186,7 @@ interface IntegerOptionsNumber {
185
186
  * word in uppercase, like `PORT`.
186
187
  * @default `"INTEGER"`
187
188
  */
188
- readonly metavar?: string;
189
+ readonly metavar?: NonEmptyString;
189
190
  /**
190
191
  * Minimum allowed value (inclusive). If not specified,
191
192
  * no minimum is enforced.
@@ -236,7 +237,7 @@ interface IntegerOptionsBigInt {
236
237
  * word in uppercase, like `PORT`.
237
238
  * @default `"INTEGER"`
238
239
  */
239
- readonly metavar?: string;
240
+ readonly metavar?: NonEmptyString;
240
241
  /**
241
242
  * Minimum allowed value (inclusive). If not specified,
242
243
  * no minimum is enforced.
@@ -296,7 +297,7 @@ interface FloatOptions {
296
297
  * word in uppercase, like `RATE` or `PRICE`.
297
298
  * @default `"NUMBER"`
298
299
  */
299
- readonly metavar?: string;
300
+ readonly metavar?: NonEmptyString;
300
301
  /**
301
302
  * Minimum allowed value (inclusive). If not specified,
302
303
  * no minimum is enforced.
@@ -366,7 +367,7 @@ interface UrlOptions {
366
367
  * word in uppercase, like `URL` or `ENDPOINT`.
367
368
  * @default `"URL"`
368
369
  */
369
- readonly metavar?: string;
370
+ readonly metavar?: NonEmptyString;
370
371
  /**
371
372
  * List of allowed URL protocols (e.g., `["http:", "https:"]`).
372
373
  * If specified, the parsed URL must use one of these protocols.
@@ -413,7 +414,7 @@ interface LocaleOptions {
413
414
  * word in uppercase, like `LOCALE` or `LANG`.
414
415
  * @default `"LOCALE"`
415
416
  */
416
- readonly metavar?: string;
417
+ readonly metavar?: NonEmptyString;
417
418
  /**
418
419
  * Custom error messages for locale parsing failures.
419
420
  * @since 0.5.0
@@ -456,7 +457,7 @@ interface UuidOptions {
456
457
  * word in uppercase, like `UUID` or `ID`.
457
458
  * @default `"UUID"`
458
459
  */
459
- readonly metavar?: string;
460
+ readonly metavar?: NonEmptyString;
460
461
  /**
461
462
  * List of allowed UUID versions (e.g., `[4, 5]` for UUIDs version 4 and 5).
462
463
  * If specified, the parser will validate that the UUID matches one of the
@@ -496,4 +497,4 @@ interface UuidOptions {
496
497
  */
497
498
  declare function uuid(options?: UuidOptions): ValueParser<Uuid>;
498
499
  //#endregion
499
- export { ChoiceOptions, FloatOptions, IntegerOptionsBigInt, IntegerOptionsNumber, LocaleOptions, StringOptions, UrlOptions, Uuid, UuidOptions, ValueParser, ValueParserResult, choice, float, integer, isValueParser, locale, string, url, uuid };
500
+ export { ChoiceOptions, FloatOptions, IntegerOptionsBigInt, IntegerOptionsNumber, LocaleOptions, type NonEmptyString, StringOptions, UrlOptions, Uuid, UuidOptions, ValueParser, ValueParserResult, choice, ensureNonEmptyString, float, integer, isNonEmptyString, isValueParser, locale, string, url, uuid };
@@ -1,4 +1,5 @@
1
1
  import { message, text } from "./message.js";
2
+ import { ensureNonEmptyString, isNonEmptyString } from "./nonempty.js";
2
3
 
3
4
  //#region src/valueparser.ts
4
5
  /**
@@ -22,9 +23,11 @@ function isValueParser(object) {
22
23
  * specified values.
23
24
  */
24
25
  function choice(choices, options = {}) {
26
+ const metavar = options.metavar ?? "TYPE";
27
+ ensureNonEmptyString(metavar);
25
28
  const normalizedValues = options.caseInsensitive ? choices.map((v) => v.toLowerCase()) : choices;
26
29
  return {
27
- metavar: options.metavar ?? "TYPE",
30
+ metavar,
28
31
  parse(input) {
29
32
  const normalizedInput = options.caseInsensitive ? input.toLowerCase() : input;
30
33
  const index = normalizedValues.indexOf(normalizedInput);
@@ -74,8 +77,10 @@ function choice(choices, options = {}) {
74
77
  * specified options.
75
78
  */
76
79
  function string(options = {}) {
80
+ const metavar = options.metavar ?? "STRING";
81
+ ensureNonEmptyString(metavar);
77
82
  return {
78
- metavar: options.metavar ?? "STRING",
83
+ metavar,
79
84
  parse(input) {
80
85
  if (options.pattern != null && !options.pattern.test(input)) return {
81
86
  success: false,
@@ -125,38 +130,44 @@ function string(options = {}) {
125
130
  * integer type.
126
131
  */
127
132
  function integer(options) {
128
- if (options?.type === "bigint") return {
129
- metavar: options.metavar ?? "INTEGER",
130
- parse(input) {
131
- let value;
132
- try {
133
- value = BigInt(input);
134
- } catch (e) {
135
- if (e instanceof SyntaxError) return {
133
+ if (options?.type === "bigint") {
134
+ const metavar$1 = options.metavar ?? "INTEGER";
135
+ ensureNonEmptyString(metavar$1);
136
+ return {
137
+ metavar: metavar$1,
138
+ parse(input) {
139
+ let value;
140
+ try {
141
+ value = BigInt(input);
142
+ } catch (e) {
143
+ if (e instanceof SyntaxError) return {
144
+ success: false,
145
+ error: options.errors?.invalidInteger ? typeof options.errors.invalidInteger === "function" ? options.errors.invalidInteger(input) : options.errors.invalidInteger : message`Expected a valid integer, but got ${input}.`
146
+ };
147
+ throw e;
148
+ }
149
+ if (options.min != null && value < options.min) return {
136
150
  success: false,
137
- error: options.errors?.invalidInteger ? typeof options.errors.invalidInteger === "function" ? options.errors.invalidInteger(input) : options.errors.invalidInteger : message`Expected a valid integer, but got ${input}.`
151
+ error: options.errors?.belowMinimum ? typeof options.errors.belowMinimum === "function" ? options.errors.belowMinimum(value, options.min) : options.errors.belowMinimum : message`Expected a value greater than or equal to ${text(options.min.toLocaleString("en"))}, but got ${input}.`
138
152
  };
139
- throw e;
153
+ else if (options.max != null && value > options.max) return {
154
+ success: false,
155
+ error: options.errors?.aboveMaximum ? typeof options.errors.aboveMaximum === "function" ? options.errors.aboveMaximum(value, options.max) : options.errors.aboveMaximum : message`Expected a value less than or equal to ${text(options.max.toLocaleString("en"))}, but got ${input}.`
156
+ };
157
+ return {
158
+ success: true,
159
+ value
160
+ };
161
+ },
162
+ format(value) {
163
+ return value.toString();
140
164
  }
141
- if (options.min != null && value < options.min) return {
142
- success: false,
143
- error: options.errors?.belowMinimum ? typeof options.errors.belowMinimum === "function" ? options.errors.belowMinimum(value, options.min) : options.errors.belowMinimum : message`Expected a value greater than or equal to ${text(options.min.toLocaleString("en"))}, but got ${input}.`
144
- };
145
- else if (options.max != null && value > options.max) return {
146
- success: false,
147
- error: options.errors?.aboveMaximum ? typeof options.errors.aboveMaximum === "function" ? options.errors.aboveMaximum(value, options.max) : options.errors.aboveMaximum : message`Expected a value less than or equal to ${text(options.max.toLocaleString("en"))}, but got ${input}.`
148
- };
149
- return {
150
- success: true,
151
- value
152
- };
153
- },
154
- format(value) {
155
- return value.toString();
156
- }
157
- };
165
+ };
166
+ }
167
+ const metavar = options?.metavar ?? "INTEGER";
168
+ ensureNonEmptyString(metavar);
158
169
  return {
159
- metavar: options?.metavar ?? "INTEGER",
170
+ metavar,
160
171
  parse(input) {
161
172
  if (!input.match(/^-?\d+$/)) return {
162
173
  success: false,
@@ -192,8 +203,10 @@ function integer(options) {
192
203
  */
193
204
  function float(options = {}) {
194
205
  const floatRegex = /^[+-]?(?:(?:\d+\.?\d*)|(?:\d*\.\d+))(?:[eE][+-]?\d+)?$/;
206
+ const metavar = options.metavar ?? "NUMBER";
207
+ ensureNonEmptyString(metavar);
195
208
  return {
196
- metavar: options.metavar ?? "NUMBER",
209
+ metavar,
197
210
  parse(input) {
198
211
  let value;
199
212
  const lowerInput = input.toLowerCase();
@@ -239,8 +252,10 @@ function float(options = {}) {
239
252
  */
240
253
  function url(options = {}) {
241
254
  const allowedProtocols = options.allowedProtocols?.map((p) => p.toLowerCase());
255
+ const metavar = options.metavar ?? "URL";
256
+ ensureNonEmptyString(metavar);
242
257
  return {
243
- metavar: options.metavar ?? "URL",
258
+ metavar,
244
259
  parse(input) {
245
260
  if (!URL.canParse(input)) return {
246
261
  success: false,
@@ -281,8 +296,10 @@ function url(options = {}) {
281
296
  * objects.
282
297
  */
283
298
  function locale(options = {}) {
299
+ const metavar = options.metavar ?? "LOCALE";
300
+ ensureNonEmptyString(metavar);
284
301
  return {
285
- metavar: options.metavar ?? "LOCALE",
302
+ metavar,
286
303
  parse(input) {
287
304
  let locale$1;
288
305
  try {
@@ -548,8 +565,10 @@ function locale(options = {}) {
548
565
  */
549
566
  function uuid(options = {}) {
550
567
  const uuidRegex = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
568
+ const metavar = options.metavar ?? "UUID";
569
+ ensureNonEmptyString(metavar);
551
570
  return {
552
- metavar: options.metavar ?? "UUID",
571
+ metavar,
553
572
  parse(input) {
554
573
  if (!uuidRegex.test(input)) return {
555
574
  success: false,
@@ -583,4 +602,4 @@ function uuid(options = {}) {
583
602
  }
584
603
 
585
604
  //#endregion
586
- export { choice, float, integer, isValueParser, locale, string, url, uuid };
605
+ export { choice, ensureNonEmptyString, float, integer, isNonEmptyString, isValueParser, locale, string, url, uuid };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@optique/core",
3
- "version": "0.9.0-dev.184+a94f89b9",
3
+ "version": "0.9.0-dev.186+976c1c1f",
4
4
  "description": "Type-safe combinatorial command-line interface parser",
5
5
  "keywords": [
6
6
  "CLI",
@@ -99,6 +99,14 @@
99
99
  "import": "./dist/modifiers.js",
100
100
  "require": "./dist/modifiers.cjs"
101
101
  },
102
+ "./nonempty": {
103
+ "types": {
104
+ "import": "./dist/nonempty.d.ts",
105
+ "require": "./dist/nonempty.d.cts"
106
+ },
107
+ "import": "./dist/nonempty.js",
108
+ "require": "./dist/nonempty.cjs"
109
+ },
102
110
  "./parser": {
103
111
  "types": {
104
112
  "import": "./dist/parser.d.ts",