@optique/core 0.5.0-dev.79 → 0.5.0-dev.80

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.
@@ -0,0 +1,192 @@
1
+ import { Message } from "./message.cjs";
2
+ import { Parser } from "./parser.cjs";
3
+
4
+ //#region src/modifiers.d.ts
5
+
6
+ /**
7
+ * Creates a parser that makes another parser optional, allowing it to succeed
8
+ * without consuming input if the wrapped parser fails to match.
9
+ * If the wrapped parser succeeds, this returns its value.
10
+ * If the wrapped parser fails, this returns `undefined` without consuming input.
11
+ * @template TValue The type of the value returned by the wrapped parser.
12
+ * @template TState The type of the state used by the wrapped parser.
13
+ * @param parser The {@link Parser} to make optional.
14
+ * @returns A {@link Parser} that produces either the result of the wrapped parser
15
+ * or `undefined` if the wrapped parser fails to match.
16
+ */
17
+ declare function optional<TValue, TState>(parser: Parser<TValue, TState>): Parser<TValue | undefined, [TState] | undefined>;
18
+ /**
19
+ * Options for the {@link withDefault} parser.
20
+ */
21
+ interface WithDefaultOptions {
22
+ /**
23
+ * Custom message to display in help output instead of the formatted default value.
24
+ * This allows showing descriptive text like "SERVICE_URL environment variable"
25
+ * instead of the actual default value.
26
+ *
27
+ * @example
28
+ * ```typescript
29
+ * withDefault(
30
+ * option("--url", url()),
31
+ * process.env["SERVICE_URL"],
32
+ * { message: message`${envVar("SERVICE_URL")} environment variable` }
33
+ * )
34
+ * ```
35
+ */
36
+ readonly message?: Message;
37
+ }
38
+ /**
39
+ * Error type for structured error messages in {@link withDefault} default value callbacks.
40
+ * Unlike regular errors that only support string messages, this error type accepts
41
+ * a {@link Message} object that supports rich formatting, colors, and structured content.
42
+ *
43
+ * @example
44
+ * ```typescript
45
+ * withDefault(option("--url", url()), () => {
46
+ * if (!process.env.INSTANCE_URL) {
47
+ * throw new WithDefaultError(
48
+ * message`Environment variable ${envVar("INSTANCE_URL")} is not set.`
49
+ * );
50
+ * }
51
+ * return new URL(process.env.INSTANCE_URL);
52
+ * })
53
+ * ```
54
+ *
55
+ * @since 0.5.0
56
+ */
57
+ declare class WithDefaultError extends Error {
58
+ /**
59
+ * The structured message associated with this error.
60
+ */
61
+ readonly errorMessage: Message;
62
+ /**
63
+ * Creates a new WithDefaultError with a structured message.
64
+ * @param message The structured {@link Message} describing the error.
65
+ */
66
+ constructor(message: Message);
67
+ }
68
+ /**
69
+ * Creates a parser that makes another parser use a default value when it fails
70
+ * to match or consume input. This is similar to {@link optional}, but instead
71
+ * of returning `undefined` when the wrapped parser doesn't match, it returns
72
+ * a specified default value.
73
+ * @template TValue The type of the value returned by the wrapped parser.
74
+ * @template TState The type of the state used by the wrapped parser.
75
+ * @template TDefault The type of the default value.
76
+ * @param parser The {@link Parser} to wrap with default behavior.
77
+ * @param defaultValue The default value to return when the wrapped parser
78
+ * doesn't match or consume input. Can be a value of type
79
+ * {@link TDefault} or a function that returns such a value.
80
+ * @returns A {@link Parser} that produces either the result of the wrapped parser
81
+ * or the default value if the wrapped parser fails to match
82
+ * (union type {@link TValue} | {@link TDefault}).
83
+ */
84
+ declare function withDefault<TValue, TState, TDefault = TValue>(parser: Parser<TValue, TState>, defaultValue: TDefault | (() => TDefault)): Parser<TValue | TDefault, [TState] | undefined>;
85
+ /**
86
+ * Creates a parser that makes another parser use a default value when it fails
87
+ * to match or consume input. This is similar to {@link optional}, but instead
88
+ * of returning `undefined` when the wrapped parser doesn't match, it returns
89
+ * a specified default value.
90
+ * @template TValue The type of the value returned by the wrapped parser.
91
+ * @template TState The type of the state used by the wrapped parser.
92
+ * @template TDefault The type of the default value.
93
+ * @param parser The {@link Parser} to wrap with default behavior.
94
+ * @param defaultValue The default value to return when the wrapped parser
95
+ * doesn't match or consume input. Can be a value of type
96
+ * {@link TDefault} or a function that returns such a value.
97
+ * @param options Optional configuration including custom help display message.
98
+ * @returns A {@link Parser} that produces either the result of the wrapped parser
99
+ * or the default value if the wrapped parser fails to match
100
+ * (union type {@link TValue} | {@link TDefault}).
101
+ * @since 0.5.0
102
+ */
103
+ declare function withDefault<TValue, TState, TDefault = TValue>(parser: Parser<TValue, TState>, defaultValue: TDefault | (() => TDefault), options?: WithDefaultOptions): Parser<TValue | TDefault, [TState] | undefined>;
104
+ /**
105
+ * Creates a parser that transforms the result value of another parser using
106
+ * a mapping function. This enables value transformation while preserving
107
+ * the original parser's parsing logic and state management.
108
+ *
109
+ * The `map()` function is useful for:
110
+ * - Converting parsed values to different types
111
+ * - Applying transformations like string formatting or boolean inversion
112
+ * - Computing derived values from parsed input
113
+ * - Creating reusable transformations that can be applied to any parser
114
+ *
115
+ * @template T The type of the value produced by the original parser.
116
+ * @template U The type of the value produced by the mapping function.
117
+ * @template TState The type of the state used by the original parser.
118
+ * @param parser The {@link Parser} whose result will be transformed.
119
+ * @param transform A function that transforms the parsed value from type T to type U.
120
+ * @returns A {@link Parser} that produces the transformed value of type U
121
+ * while preserving the original parser's state type and parsing behavior.
122
+ *
123
+ * @example
124
+ * ```typescript
125
+ * // Transform boolean flag to its inverse
126
+ * const parser = object({
127
+ * disallow: map(option("--allow"), b => !b)
128
+ * });
129
+ *
130
+ * // Transform string to uppercase
131
+ * const upperParser = map(argument(string()), s => s.toUpperCase());
132
+ *
133
+ * // Transform number to formatted string
134
+ * const prefixedParser = map(option("-n", integer()), n => `value: ${n}`);
135
+ * ```
136
+ */
137
+ declare function map<T, U, TState>(parser: Parser<T, TState>, transform: (value: T) => U): Parser<U, TState>;
138
+ /**
139
+ * Options for the {@link multiple} parser.
140
+ */
141
+ interface MultipleOptions {
142
+ /**
143
+ * The minimum number of occurrences required for the parser to succeed.
144
+ * If the number of occurrences is less than this value,
145
+ * the parser will fail with an error.
146
+ * @default `0`
147
+ */
148
+ readonly min?: number;
149
+ /**
150
+ * The maximum number of occurrences allowed for the parser.
151
+ * If the number of occurrences exceeds this value,
152
+ * the parser will fail with an error.
153
+ * @default `Infinity`
154
+ */
155
+ readonly max?: number;
156
+ /**
157
+ * Error messages customization.
158
+ * @since 0.5.0
159
+ */
160
+ readonly errors?: MultipleErrorOptions;
161
+ }
162
+ /**
163
+ * Options for customizing error messages in the {@link multiple} parser.
164
+ * @since 0.5.0
165
+ */
166
+ interface MultipleErrorOptions {
167
+ /**
168
+ * Error message when fewer than the minimum number of values are provided.
169
+ */
170
+ readonly tooFew?: Message | ((min: number, actual: number) => Message);
171
+ /**
172
+ * Error message when more than the maximum number of values are provided.
173
+ */
174
+ readonly tooMany?: Message | ((max: number, actual: number) => Message);
175
+ }
176
+ /**
177
+ * Creates a parser that allows multiple occurrences of a given parser.
178
+ * This parser can be used to parse multiple values of the same type,
179
+ * such as multiple command-line arguments or options.
180
+ * @template TValue The type of the value that the parser produces.
181
+ * @template TState The type of the state used by the parser.
182
+ * @param parser The {@link Parser} to apply multiple times.
183
+ * @param options Optional configuration for the parser,
184
+ * allowing you to specify the minimum and maximum number of
185
+ * occurrences allowed.
186
+ * @returns A {@link Parser} that produces an array of values
187
+ * of type {@link TValue} and an array of states
188
+ * of type {@link TState}.
189
+ */
190
+ declare function multiple<TValue, TState>(parser: Parser<TValue, TState>, options?: MultipleOptions): Parser<readonly TValue[], readonly TState[]>;
191
+ //#endregion
192
+ export { MultipleErrorOptions, MultipleOptions, WithDefaultError, WithDefaultOptions, map, multiple, optional, withDefault };
@@ -0,0 +1,192 @@
1
+ import { Message } from "./message.js";
2
+ import { Parser } from "./parser.js";
3
+
4
+ //#region src/modifiers.d.ts
5
+
6
+ /**
7
+ * Creates a parser that makes another parser optional, allowing it to succeed
8
+ * without consuming input if the wrapped parser fails to match.
9
+ * If the wrapped parser succeeds, this returns its value.
10
+ * If the wrapped parser fails, this returns `undefined` without consuming input.
11
+ * @template TValue The type of the value returned by the wrapped parser.
12
+ * @template TState The type of the state used by the wrapped parser.
13
+ * @param parser The {@link Parser} to make optional.
14
+ * @returns A {@link Parser} that produces either the result of the wrapped parser
15
+ * or `undefined` if the wrapped parser fails to match.
16
+ */
17
+ declare function optional<TValue, TState>(parser: Parser<TValue, TState>): Parser<TValue | undefined, [TState] | undefined>;
18
+ /**
19
+ * Options for the {@link withDefault} parser.
20
+ */
21
+ interface WithDefaultOptions {
22
+ /**
23
+ * Custom message to display in help output instead of the formatted default value.
24
+ * This allows showing descriptive text like "SERVICE_URL environment variable"
25
+ * instead of the actual default value.
26
+ *
27
+ * @example
28
+ * ```typescript
29
+ * withDefault(
30
+ * option("--url", url()),
31
+ * process.env["SERVICE_URL"],
32
+ * { message: message`${envVar("SERVICE_URL")} environment variable` }
33
+ * )
34
+ * ```
35
+ */
36
+ readonly message?: Message;
37
+ }
38
+ /**
39
+ * Error type for structured error messages in {@link withDefault} default value callbacks.
40
+ * Unlike regular errors that only support string messages, this error type accepts
41
+ * a {@link Message} object that supports rich formatting, colors, and structured content.
42
+ *
43
+ * @example
44
+ * ```typescript
45
+ * withDefault(option("--url", url()), () => {
46
+ * if (!process.env.INSTANCE_URL) {
47
+ * throw new WithDefaultError(
48
+ * message`Environment variable ${envVar("INSTANCE_URL")} is not set.`
49
+ * );
50
+ * }
51
+ * return new URL(process.env.INSTANCE_URL);
52
+ * })
53
+ * ```
54
+ *
55
+ * @since 0.5.0
56
+ */
57
+ declare class WithDefaultError extends Error {
58
+ /**
59
+ * The structured message associated with this error.
60
+ */
61
+ readonly errorMessage: Message;
62
+ /**
63
+ * Creates a new WithDefaultError with a structured message.
64
+ * @param message The structured {@link Message} describing the error.
65
+ */
66
+ constructor(message: Message);
67
+ }
68
+ /**
69
+ * Creates a parser that makes another parser use a default value when it fails
70
+ * to match or consume input. This is similar to {@link optional}, but instead
71
+ * of returning `undefined` when the wrapped parser doesn't match, it returns
72
+ * a specified default value.
73
+ * @template TValue The type of the value returned by the wrapped parser.
74
+ * @template TState The type of the state used by the wrapped parser.
75
+ * @template TDefault The type of the default value.
76
+ * @param parser The {@link Parser} to wrap with default behavior.
77
+ * @param defaultValue The default value to return when the wrapped parser
78
+ * doesn't match or consume input. Can be a value of type
79
+ * {@link TDefault} or a function that returns such a value.
80
+ * @returns A {@link Parser} that produces either the result of the wrapped parser
81
+ * or the default value if the wrapped parser fails to match
82
+ * (union type {@link TValue} | {@link TDefault}).
83
+ */
84
+ declare function withDefault<TValue, TState, TDefault = TValue>(parser: Parser<TValue, TState>, defaultValue: TDefault | (() => TDefault)): Parser<TValue | TDefault, [TState] | undefined>;
85
+ /**
86
+ * Creates a parser that makes another parser use a default value when it fails
87
+ * to match or consume input. This is similar to {@link optional}, but instead
88
+ * of returning `undefined` when the wrapped parser doesn't match, it returns
89
+ * a specified default value.
90
+ * @template TValue The type of the value returned by the wrapped parser.
91
+ * @template TState The type of the state used by the wrapped parser.
92
+ * @template TDefault The type of the default value.
93
+ * @param parser The {@link Parser} to wrap with default behavior.
94
+ * @param defaultValue The default value to return when the wrapped parser
95
+ * doesn't match or consume input. Can be a value of type
96
+ * {@link TDefault} or a function that returns such a value.
97
+ * @param options Optional configuration including custom help display message.
98
+ * @returns A {@link Parser} that produces either the result of the wrapped parser
99
+ * or the default value if the wrapped parser fails to match
100
+ * (union type {@link TValue} | {@link TDefault}).
101
+ * @since 0.5.0
102
+ */
103
+ declare function withDefault<TValue, TState, TDefault = TValue>(parser: Parser<TValue, TState>, defaultValue: TDefault | (() => TDefault), options?: WithDefaultOptions): Parser<TValue | TDefault, [TState] | undefined>;
104
+ /**
105
+ * Creates a parser that transforms the result value of another parser using
106
+ * a mapping function. This enables value transformation while preserving
107
+ * the original parser's parsing logic and state management.
108
+ *
109
+ * The `map()` function is useful for:
110
+ * - Converting parsed values to different types
111
+ * - Applying transformations like string formatting or boolean inversion
112
+ * - Computing derived values from parsed input
113
+ * - Creating reusable transformations that can be applied to any parser
114
+ *
115
+ * @template T The type of the value produced by the original parser.
116
+ * @template U The type of the value produced by the mapping function.
117
+ * @template TState The type of the state used by the original parser.
118
+ * @param parser The {@link Parser} whose result will be transformed.
119
+ * @param transform A function that transforms the parsed value from type T to type U.
120
+ * @returns A {@link Parser} that produces the transformed value of type U
121
+ * while preserving the original parser's state type and parsing behavior.
122
+ *
123
+ * @example
124
+ * ```typescript
125
+ * // Transform boolean flag to its inverse
126
+ * const parser = object({
127
+ * disallow: map(option("--allow"), b => !b)
128
+ * });
129
+ *
130
+ * // Transform string to uppercase
131
+ * const upperParser = map(argument(string()), s => s.toUpperCase());
132
+ *
133
+ * // Transform number to formatted string
134
+ * const prefixedParser = map(option("-n", integer()), n => `value: ${n}`);
135
+ * ```
136
+ */
137
+ declare function map<T, U, TState>(parser: Parser<T, TState>, transform: (value: T) => U): Parser<U, TState>;
138
+ /**
139
+ * Options for the {@link multiple} parser.
140
+ */
141
+ interface MultipleOptions {
142
+ /**
143
+ * The minimum number of occurrences required for the parser to succeed.
144
+ * If the number of occurrences is less than this value,
145
+ * the parser will fail with an error.
146
+ * @default `0`
147
+ */
148
+ readonly min?: number;
149
+ /**
150
+ * The maximum number of occurrences allowed for the parser.
151
+ * If the number of occurrences exceeds this value,
152
+ * the parser will fail with an error.
153
+ * @default `Infinity`
154
+ */
155
+ readonly max?: number;
156
+ /**
157
+ * Error messages customization.
158
+ * @since 0.5.0
159
+ */
160
+ readonly errors?: MultipleErrorOptions;
161
+ }
162
+ /**
163
+ * Options for customizing error messages in the {@link multiple} parser.
164
+ * @since 0.5.0
165
+ */
166
+ interface MultipleErrorOptions {
167
+ /**
168
+ * Error message when fewer than the minimum number of values are provided.
169
+ */
170
+ readonly tooFew?: Message | ((min: number, actual: number) => Message);
171
+ /**
172
+ * Error message when more than the maximum number of values are provided.
173
+ */
174
+ readonly tooMany?: Message | ((max: number, actual: number) => Message);
175
+ }
176
+ /**
177
+ * Creates a parser that allows multiple occurrences of a given parser.
178
+ * This parser can be used to parse multiple values of the same type,
179
+ * such as multiple command-line arguments or options.
180
+ * @template TValue The type of the value that the parser produces.
181
+ * @template TState The type of the state used by the parser.
182
+ * @param parser The {@link Parser} to apply multiple times.
183
+ * @param options Optional configuration for the parser,
184
+ * allowing you to specify the minimum and maximum number of
185
+ * occurrences allowed.
186
+ * @returns A {@link Parser} that produces an array of values
187
+ * of type {@link TValue} and an array of states
188
+ * of type {@link TState}.
189
+ */
190
+ declare function multiple<TValue, TState>(parser: Parser<TValue, TState>, options?: MultipleOptions): Parser<readonly TValue[], readonly TState[]>;
191
+ //#endregion
192
+ export { MultipleErrorOptions, MultipleOptions, WithDefaultError, WithDefaultOptions, map, multiple, optional, withDefault };
@@ -0,0 +1,296 @@
1
+ import { formatMessage, message, text } from "./message.js";
2
+
3
+ //#region src/modifiers.ts
4
+ /**
5
+ * Creates a parser that makes another parser optional, allowing it to succeed
6
+ * without consuming input if the wrapped parser fails to match.
7
+ * If the wrapped parser succeeds, this returns its value.
8
+ * If the wrapped parser fails, this returns `undefined` without consuming input.
9
+ * @template TValue The type of the value returned by the wrapped parser.
10
+ * @template TState The type of the state used by the wrapped parser.
11
+ * @param parser The {@link Parser} to make optional.
12
+ * @returns A {@link Parser} that produces either the result of the wrapped parser
13
+ * or `undefined` if the wrapped parser fails to match.
14
+ */
15
+ function optional(parser) {
16
+ return {
17
+ $valueType: [],
18
+ $stateType: [],
19
+ priority: parser.priority,
20
+ usage: [{
21
+ type: "optional",
22
+ terms: parser.usage
23
+ }],
24
+ initialState: void 0,
25
+ parse(context) {
26
+ const result = parser.parse({
27
+ ...context,
28
+ state: typeof context.state === "undefined" ? parser.initialState : context.state[0]
29
+ });
30
+ if (result.success) return {
31
+ success: true,
32
+ next: {
33
+ ...result.next,
34
+ state: [result.next.state]
35
+ },
36
+ consumed: result.consumed
37
+ };
38
+ return result;
39
+ },
40
+ complete(state) {
41
+ if (typeof state === "undefined") return {
42
+ success: true,
43
+ value: void 0
44
+ };
45
+ return parser.complete(state[0]);
46
+ },
47
+ getDocFragments(state, defaultValue) {
48
+ const innerState = state.kind === "unavailable" ? { kind: "unavailable" } : state.state === void 0 ? { kind: "unavailable" } : {
49
+ kind: "available",
50
+ state: state.state[0]
51
+ };
52
+ return parser.getDocFragments(innerState, defaultValue);
53
+ }
54
+ };
55
+ }
56
+ /**
57
+ * Error type for structured error messages in {@link withDefault} default value callbacks.
58
+ * Unlike regular errors that only support string messages, this error type accepts
59
+ * a {@link Message} object that supports rich formatting, colors, and structured content.
60
+ *
61
+ * @example
62
+ * ```typescript
63
+ * withDefault(option("--url", url()), () => {
64
+ * if (!process.env.INSTANCE_URL) {
65
+ * throw new WithDefaultError(
66
+ * message`Environment variable ${envVar("INSTANCE_URL")} is not set.`
67
+ * );
68
+ * }
69
+ * return new URL(process.env.INSTANCE_URL);
70
+ * })
71
+ * ```
72
+ *
73
+ * @since 0.5.0
74
+ */
75
+ var WithDefaultError = class extends Error {
76
+ /**
77
+ * The structured message associated with this error.
78
+ */
79
+ errorMessage;
80
+ /**
81
+ * Creates a new WithDefaultError with a structured message.
82
+ * @param message The structured {@link Message} describing the error.
83
+ */
84
+ constructor(message$1) {
85
+ super(formatMessage(message$1));
86
+ this.errorMessage = message$1;
87
+ this.name = "WithDefaultError";
88
+ }
89
+ };
90
+ function withDefault(parser, defaultValue, options) {
91
+ return {
92
+ $valueType: [],
93
+ $stateType: [],
94
+ priority: parser.priority,
95
+ usage: [{
96
+ type: "optional",
97
+ terms: parser.usage
98
+ }],
99
+ initialState: void 0,
100
+ parse(context) {
101
+ const result = parser.parse({
102
+ ...context,
103
+ state: typeof context.state === "undefined" ? parser.initialState : context.state[0]
104
+ });
105
+ if (result.success) return {
106
+ success: true,
107
+ next: {
108
+ ...result.next,
109
+ state: [result.next.state]
110
+ },
111
+ consumed: result.consumed
112
+ };
113
+ return result;
114
+ },
115
+ complete(state) {
116
+ if (typeof state === "undefined") try {
117
+ const value = typeof defaultValue === "function" ? defaultValue() : defaultValue;
118
+ return {
119
+ success: true,
120
+ value
121
+ };
122
+ } catch (error) {
123
+ return {
124
+ success: false,
125
+ error: error instanceof WithDefaultError ? error.errorMessage : message`${text(String(error))}`
126
+ };
127
+ }
128
+ return parser.complete(state[0]);
129
+ },
130
+ getDocFragments(state, upperDefaultValue) {
131
+ const innerState = state.kind === "unavailable" ? { kind: "unavailable" } : state.state === void 0 ? { kind: "unavailable" } : {
132
+ kind: "available",
133
+ state: state.state[0]
134
+ };
135
+ const actualDefaultValue = upperDefaultValue != null ? upperDefaultValue : typeof defaultValue === "function" ? defaultValue() : defaultValue;
136
+ const fragments = parser.getDocFragments(innerState, actualDefaultValue);
137
+ if (options?.message) {
138
+ const modifiedFragments = fragments.fragments.map((fragment) => {
139
+ if (fragment.type === "entry") return {
140
+ ...fragment,
141
+ default: options.message
142
+ };
143
+ return fragment;
144
+ });
145
+ return {
146
+ ...fragments,
147
+ fragments: modifiedFragments
148
+ };
149
+ }
150
+ return fragments;
151
+ }
152
+ };
153
+ }
154
+ /**
155
+ * Creates a parser that transforms the result value of another parser using
156
+ * a mapping function. This enables value transformation while preserving
157
+ * the original parser's parsing logic and state management.
158
+ *
159
+ * The `map()` function is useful for:
160
+ * - Converting parsed values to different types
161
+ * - Applying transformations like string formatting or boolean inversion
162
+ * - Computing derived values from parsed input
163
+ * - Creating reusable transformations that can be applied to any parser
164
+ *
165
+ * @template T The type of the value produced by the original parser.
166
+ * @template U The type of the value produced by the mapping function.
167
+ * @template TState The type of the state used by the original parser.
168
+ * @param parser The {@link Parser} whose result will be transformed.
169
+ * @param transform A function that transforms the parsed value from type T to type U.
170
+ * @returns A {@link Parser} that produces the transformed value of type U
171
+ * while preserving the original parser's state type and parsing behavior.
172
+ *
173
+ * @example
174
+ * ```typescript
175
+ * // Transform boolean flag to its inverse
176
+ * const parser = object({
177
+ * disallow: map(option("--allow"), b => !b)
178
+ * });
179
+ *
180
+ * // Transform string to uppercase
181
+ * const upperParser = map(argument(string()), s => s.toUpperCase());
182
+ *
183
+ * // Transform number to formatted string
184
+ * const prefixedParser = map(option("-n", integer()), n => `value: ${n}`);
185
+ * ```
186
+ */
187
+ function map(parser, transform) {
188
+ return {
189
+ $valueType: [],
190
+ $stateType: parser.$stateType,
191
+ priority: parser.priority,
192
+ usage: parser.usage,
193
+ initialState: parser.initialState,
194
+ parse: parser.parse.bind(parser),
195
+ complete(state) {
196
+ const result = parser.complete(state);
197
+ if (result.success) return {
198
+ success: true,
199
+ value: transform(result.value)
200
+ };
201
+ return result;
202
+ },
203
+ getDocFragments(state, _defaultValue) {
204
+ return parser.getDocFragments(state, void 0);
205
+ }
206
+ };
207
+ }
208
+ /**
209
+ * Creates a parser that allows multiple occurrences of a given parser.
210
+ * This parser can be used to parse multiple values of the same type,
211
+ * such as multiple command-line arguments or options.
212
+ * @template TValue The type of the value that the parser produces.
213
+ * @template TState The type of the state used by the parser.
214
+ * @param parser The {@link Parser} to apply multiple times.
215
+ * @param options Optional configuration for the parser,
216
+ * allowing you to specify the minimum and maximum number of
217
+ * occurrences allowed.
218
+ * @returns A {@link Parser} that produces an array of values
219
+ * of type {@link TValue} and an array of states
220
+ * of type {@link TState}.
221
+ */
222
+ function multiple(parser, options = {}) {
223
+ const { min = 0, max = Infinity } = options;
224
+ return {
225
+ $valueType: [],
226
+ $stateType: [],
227
+ priority: parser.priority,
228
+ usage: [{
229
+ type: "multiple",
230
+ terms: parser.usage,
231
+ min
232
+ }],
233
+ initialState: [],
234
+ parse(context) {
235
+ let added = context.state.length < 1;
236
+ let result = parser.parse({
237
+ ...context,
238
+ state: context.state.at(-1) ?? parser.initialState
239
+ });
240
+ if (!result.success) if (!added) {
241
+ result = parser.parse({
242
+ ...context,
243
+ state: parser.initialState
244
+ });
245
+ if (!result.success) return result;
246
+ added = true;
247
+ } else return result;
248
+ return {
249
+ success: true,
250
+ next: {
251
+ ...result.next,
252
+ state: [...added ? context.state : context.state.slice(0, -1), result.next.state]
253
+ },
254
+ consumed: result.consumed
255
+ };
256
+ },
257
+ complete(state) {
258
+ const result = [];
259
+ for (const s of state) {
260
+ const valueResult = parser.complete(s);
261
+ if (valueResult.success) result.push(valueResult.value);
262
+ else return {
263
+ success: false,
264
+ error: valueResult.error
265
+ };
266
+ }
267
+ if (result.length < min) {
268
+ const customMessage = options.errors?.tooFew;
269
+ return {
270
+ success: false,
271
+ error: customMessage ? typeof customMessage === "function" ? customMessage(min, result.length) : customMessage : message`Expected at least ${text(min.toLocaleString("en"))} values, but got only ${text(result.length.toLocaleString("en"))}.`
272
+ };
273
+ } else if (result.length > max) {
274
+ const customMessage = options.errors?.tooMany;
275
+ return {
276
+ success: false,
277
+ error: customMessage ? typeof customMessage === "function" ? customMessage(max, result.length) : customMessage : message`Expected at most ${text(max.toLocaleString("en"))} values, but got ${text(result.length.toLocaleString("en"))}.`
278
+ };
279
+ }
280
+ return {
281
+ success: true,
282
+ value: result
283
+ };
284
+ },
285
+ getDocFragments(state, defaultValue) {
286
+ const innerState = state.kind === "unavailable" ? { kind: "unavailable" } : state.state.length > 0 ? {
287
+ kind: "available",
288
+ state: state.state.at(-1)
289
+ } : { kind: "unavailable" };
290
+ return parser.getDocFragments(innerState, defaultValue != null && defaultValue.length > 0 ? defaultValue[0] : void 0);
291
+ }
292
+ };
293
+ }
294
+
295
+ //#endregion
296
+ export { WithDefaultError, map, multiple, optional, withDefault };