@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.
- package/dist/constructs.cjs +754 -0
- package/dist/constructs.d.cts +1100 -0
- package/dist/constructs.d.ts +1100 -0
- package/dist/constructs.js +748 -0
- package/dist/facade.cjs +29 -26
- package/dist/facade.js +4 -1
- package/dist/index.cjs +20 -17
- package/dist/index.d.cts +5 -2
- package/dist/index.d.ts +5 -2
- package/dist/index.js +4 -1
- package/dist/modifiers.cjs +300 -0
- package/dist/modifiers.d.cts +192 -0
- package/dist/modifiers.d.ts +192 -0
- package/dist/modifiers.js +296 -0
- package/dist/parser.cjs +20 -1581
- package/dist/parser.d.cts +6 -1279
- package/dist/parser.d.ts +6 -1279
- package/dist/parser.js +4 -1565
- package/dist/primitives.cjs +595 -0
- package/dist/primitives.d.cts +274 -0
- package/dist/primitives.d.ts +274 -0
- package/dist/primitives.js +591 -0
- package/dist/valueparser.cjs +28 -28
- package/dist/valueparser.d.cts +144 -0
- package/dist/valueparser.d.ts +144 -0
- package/dist/valueparser.js +28 -28
- package/package.json +25 -1
|
@@ -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 };
|