@jakubmazanec/args 1.0.0-de51f16
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/LICENSE.md +18 -0
- package/README.md +84 -0
- package/dist/ParsingError.d.ts +4 -0
- package/dist/ParsingError.js +11 -0
- package/dist/ParsingError.js.map +1 -0
- package/dist/ValidationError.d.ts +4 -0
- package/dist/ValidationError.js +16 -0
- package/dist/ValidationError.js.map +1 -0
- package/dist/internals/Checker.d.ts +13 -0
- package/dist/internals/Checker.js +118 -0
- package/dist/internals/Checker.js.map +1 -0
- package/dist/internals/CommandScope.d.ts +14 -0
- package/dist/internals/CommandScope.js +48 -0
- package/dist/internals/CommandScope.js.map +1 -0
- package/dist/internals/OptionScope.d.ts +14 -0
- package/dist/internals/OptionScope.js +87 -0
- package/dist/internals/OptionScope.js.map +1 -0
- package/dist/internals/castValue.d.ts +7 -0
- package/dist/internals/castValue.js +25 -0
- package/dist/internals/castValue.js.map +1 -0
- package/dist/internals/commandToArguments.d.ts +7 -0
- package/dist/internals/commandToArguments.js +21 -0
- package/dist/internals/commandToArguments.js.map +1 -0
- package/dist/internals/createOptionShortNameMap.d.ts +2 -0
- package/dist/internals/createOptionShortNameMap.js +11 -0
- package/dist/internals/createOptionShortNameMap.js.map +1 -0
- package/dist/internals/expandArguments.d.ts +8 -0
- package/dist/internals/expandArguments.js +21 -0
- package/dist/internals/expandArguments.js.map +1 -0
- package/dist/internals/isCommand.d.ts +8 -0
- package/dist/internals/isCommand.js +11 -0
- package/dist/internals/isCommand.js.map +1 -0
- package/dist/internals/isFalseString.d.ts +6 -0
- package/dist/internals/isFalseString.js +10 -0
- package/dist/internals/isFalseString.js.map +1 -0
- package/dist/internals/isLongOption.d.ts +7 -0
- package/dist/internals/isLongOption.js +11 -0
- package/dist/internals/isLongOption.js.map +1 -0
- package/dist/internals/isOptionLike.d.ts +7 -0
- package/dist/internals/isOptionLike.js +11 -0
- package/dist/internals/isOptionLike.js.map +1 -0
- package/dist/internals/isShortOption.d.ts +7 -0
- package/dist/internals/isShortOption.js +11 -0
- package/dist/internals/isShortOption.js.map +1 -0
- package/dist/internals/isShortOptionsGroup.d.ts +8 -0
- package/dist/internals/isShortOptionsGroup.js +11 -0
- package/dist/internals/isShortOptionsGroup.js.map +1 -0
- package/dist/internals/isTrueString.d.ts +6 -0
- package/dist/internals/isTrueString.js +10 -0
- package/dist/internals/isTrueString.js.map +1 -0
- package/dist/internals.d.ts +14 -0
- package/dist/internals.js +16 -0
- package/dist/internals.js.map +1 -0
- package/dist/main.d.ts +4 -0
- package/dist/main.js +6 -0
- package/dist/main.js.map +1 -0
- package/dist/parseArguments.d.ts +10 -0
- package/dist/parseArguments.js +244 -0
- package/dist/parseArguments.js.map +1 -0
- package/dist/types/Arguments.d.ts +22 -0
- package/dist/types/Arguments.js +3 -0
- package/dist/types/Arguments.js.map +1 -0
- package/dist/types/ArgumentsCommand.d.ts +3 -0
- package/dist/types/ArgumentsCommand.js +3 -0
- package/dist/types/ArgumentsCommand.js.map +1 -0
- package/dist/types/ArgumentsOptions.d.ts +14 -0
- package/dist/types/ArgumentsOptions.js +3 -0
- package/dist/types/ArgumentsOptions.js.map +1 -0
- package/dist/types/ArgumentsParameters.d.ts +91 -0
- package/dist/types/ArgumentsParameters.js +3 -0
- package/dist/types/ArgumentsParameters.js.map +1 -0
- package/dist/types/ArgumentsUnknownOptions.d.ts +3 -0
- package/dist/types/ArgumentsUnknownOptions.js +3 -0
- package/dist/types/ArgumentsUnknownOptions.js.map +1 -0
- package/dist/types/Argv.d.ts +2 -0
- package/dist/types/Argv.js +3 -0
- package/dist/types/Argv.js.map +1 -0
- package/dist/types/CommandConfig.d.ts +2 -0
- package/dist/types/CommandConfig.js +3 -0
- package/dist/types/CommandConfig.js.map +1 -0
- package/dist/types/CommandsConfig.d.ts +3 -0
- package/dist/types/CommandsConfig.js +3 -0
- package/dist/types/CommandsConfig.js.map +1 -0
- package/dist/types/LongOptionName.d.ts +2 -0
- package/dist/types/LongOptionName.js +3 -0
- package/dist/types/LongOptionName.js.map +1 -0
- package/dist/types/NormalizedCommandConfig.d.ts +5 -0
- package/dist/types/NormalizedCommandConfig.js +3 -0
- package/dist/types/NormalizedCommandConfig.js.map +1 -0
- package/dist/types/NormalizedCommandsConfig.d.ts +3 -0
- package/dist/types/NormalizedCommandsConfig.js +3 -0
- package/dist/types/NormalizedCommandsConfig.js.map +1 -0
- package/dist/types/OptionConfig.d.ts +220 -0
- package/dist/types/OptionConfig.js +3 -0
- package/dist/types/OptionConfig.js.map +1 -0
- package/dist/types/OptionsConfig.d.ts +3 -0
- package/dist/types/OptionsConfig.js +3 -0
- package/dist/types/OptionsConfig.js.map +1 -0
- package/dist/types/ParameterConfig.d.ts +74 -0
- package/dist/types/ParameterConfig.js +3 -0
- package/dist/types/ParameterConfig.js.map +1 -0
- package/dist/types/ParametersConfig.d.ts +10 -0
- package/dist/types/ParametersConfig.js +3 -0
- package/dist/types/ParametersConfig.js.map +1 -0
- package/dist/types/ParserConfig.d.ts +16 -0
- package/dist/types/ParserConfig.js +3 -0
- package/dist/types/ParserConfig.js.map +1 -0
- package/dist/types/ShortOptionName.d.ts +2 -0
- package/dist/types/ShortOptionName.js +3 -0
- package/dist/types/ShortOptionName.js.map +1 -0
- package/dist/types.d.ts +17 -0
- package/dist/types.js +19 -0
- package/dist/types.js.map +1 -0
- package/package.json +42 -0
- package/src/ParsingError.ts +11 -0
- package/src/ValidationError.ts +22 -0
- package/src/internals/Checker.ts +145 -0
- package/src/internals/CommandScope.ts +61 -0
- package/src/internals/OptionScope.ts +101 -0
- package/src/internals/castValue.ts +36 -0
- package/src/internals/commandToArguments.ts +22 -0
- package/src/internals/createOptionShortNameMap.ts +13 -0
- package/src/internals/expandArguments.ts +22 -0
- package/src/internals/isCommand.ts +11 -0
- package/src/internals/isFalseString.ts +10 -0
- package/src/internals/isLongOption.ts +11 -0
- package/src/internals/isOptionLike.ts +11 -0
- package/src/internals/isShortOption.ts +11 -0
- package/src/internals/isShortOptionsGroup.ts +11 -0
- package/src/internals/isTrueString.ts +10 -0
- package/src/internals.ts +14 -0
- package/src/main.ts +4 -0
- package/src/parseArguments.ts +358 -0
- package/src/types/Arguments.ts +28 -0
- package/src/types/ArgumentsCommand.ts +8 -0
- package/src/types/ArgumentsOptions.ts +89 -0
- package/src/types/ArgumentsParameters.ts +158 -0
- package/src/types/ArgumentsUnknownOptions.ts +6 -0
- package/src/types/Argv.ts +2 -0
- package/src/types/CommandConfig.ts +2 -0
- package/src/types/CommandsConfig.ts +4 -0
- package/src/types/LongOptionName.ts +2 -0
- package/src/types/NormalizedCommandConfig.ts +5 -0
- package/src/types/NormalizedCommandsConfig.ts +4 -0
- package/src/types/OptionConfig.ts +279 -0
- package/src/types/OptionsConfig.ts +4 -0
- package/src/types/ParameterConfig.ts +100 -0
- package/src/types/ParametersConfig.ts +17 -0
- package/src/types/ParserConfig.ts +21 -0
- package/src/types/ShortOptionName.ts +54 -0
- package/src/types.ts +17 -0
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
import {
|
|
2
|
+
castValue,
|
|
3
|
+
Checker,
|
|
4
|
+
CommandScope,
|
|
5
|
+
commandToArguments,
|
|
6
|
+
createOptionShortNameMap,
|
|
7
|
+
expandArguments,
|
|
8
|
+
isFalseString,
|
|
9
|
+
isLongOption,
|
|
10
|
+
isOptionLike,
|
|
11
|
+
isShortOption,
|
|
12
|
+
isTrueString,
|
|
13
|
+
OptionScope,
|
|
14
|
+
} from './internals.js';
|
|
15
|
+
import {ParsingError} from './ParsingError.js';
|
|
16
|
+
import {
|
|
17
|
+
type Arguments,
|
|
18
|
+
type ArgumentsCommand,
|
|
19
|
+
type ArgumentsOptions,
|
|
20
|
+
type ArgumentsParameters,
|
|
21
|
+
type ArgumentsUnknownOptions,
|
|
22
|
+
type Argv,
|
|
23
|
+
type NormalizedCommandsConfig,
|
|
24
|
+
type ParameterConfig,
|
|
25
|
+
type ParserConfig,
|
|
26
|
+
} from './types.js';
|
|
27
|
+
|
|
28
|
+
/* eslint-disable no-param-reassign -- we need to add properties to the `parsedOption` object */
|
|
29
|
+
function commitOptionScope(optionScope: OptionScope, parsedOptions: Record<string, unknown>) {
|
|
30
|
+
let optionValue = optionScope.getValue();
|
|
31
|
+
|
|
32
|
+
parsedOptions[optionScope.name] = optionValue;
|
|
33
|
+
|
|
34
|
+
if (optionScope.config.validate) {
|
|
35
|
+
optionScope.config.validate(parsedOptions[optionScope.name] as never); // type assertion needed to make TypeScript happy
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/* eslint-enable no-param-reassign */
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Parse a list of command line arguments into an arguments object. Based on provided parser config, raw arguments can be parsed as commands, options and parameters.
|
|
42
|
+
*
|
|
43
|
+
* @param argv Raw arguments to be parsed.
|
|
44
|
+
* @param parserConfig Parser configuration.
|
|
45
|
+
* @return Parsed arguments.
|
|
46
|
+
*
|
|
47
|
+
*/
|
|
48
|
+
// TODO: refactor
|
|
49
|
+
// eslint-disable-next-line complexity -- TODO
|
|
50
|
+
export function parseArguments<const O extends ParserConfig>(
|
|
51
|
+
argv: Argv,
|
|
52
|
+
parserConfig: O,
|
|
53
|
+
): Arguments<O> {
|
|
54
|
+
// create separate configs for commands, parameters and options
|
|
55
|
+
let commandsConfig = parserConfig.commands ?? [];
|
|
56
|
+
let parametersConfig = parserConfig.parameters ?? [];
|
|
57
|
+
let optionsConfig = parserConfig.options ?? {};
|
|
58
|
+
|
|
59
|
+
// check if parser config is valid
|
|
60
|
+
let checker = new Checker();
|
|
61
|
+
|
|
62
|
+
checker.checkCommandsConfig(commandsConfig);
|
|
63
|
+
checker.checkParametersConfig(parametersConfig);
|
|
64
|
+
checker.checkOptionsConfig(optionsConfig);
|
|
65
|
+
|
|
66
|
+
// normalize some configs
|
|
67
|
+
let normalizedCommandsConfig: NormalizedCommandsConfig = commandsConfig.map((command) => ({
|
|
68
|
+
command: command.toLowerCase(),
|
|
69
|
+
args: commandToArguments(command.toLowerCase()),
|
|
70
|
+
}));
|
|
71
|
+
let commandFirstArguments = normalizedCommandsConfig.map(
|
|
72
|
+
(commandConfig) => commandConfig.args[0],
|
|
73
|
+
);
|
|
74
|
+
let optionShortNameMap = parserConfig.options
|
|
75
|
+
? createOptionShortNameMap(parserConfig.options)
|
|
76
|
+
: {};
|
|
77
|
+
|
|
78
|
+
// variables for keeping track of the parsing
|
|
79
|
+
let parsedCommand: string | undefined;
|
|
80
|
+
let parsedParameters: unknown[] = [];
|
|
81
|
+
let parsedOptions: Record<string, unknown> = {};
|
|
82
|
+
let parsedUnknownOptions: Record<string, unknown> = {};
|
|
83
|
+
let restArgs: string[] = [];
|
|
84
|
+
let optionScope: OptionScope | null = null;
|
|
85
|
+
let commandScope: CommandScope | null = null;
|
|
86
|
+
|
|
87
|
+
//
|
|
88
|
+
let args = expandArguments(argv);
|
|
89
|
+
|
|
90
|
+
for (let [i, arg] of args.entries()) {
|
|
91
|
+
// extract rest arguments
|
|
92
|
+
if (arg === '--') {
|
|
93
|
+
restArgs.push(...args.slice(i + 1));
|
|
94
|
+
|
|
95
|
+
break;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
try {
|
|
99
|
+
if (isOptionLike(arg)) {
|
|
100
|
+
// first let's handle options
|
|
101
|
+
|
|
102
|
+
if (optionScope) {
|
|
103
|
+
commitOptionScope(
|
|
104
|
+
optionScope,
|
|
105
|
+
optionsConfig[optionScope.name] ? parsedOptions : parsedUnknownOptions,
|
|
106
|
+
);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// if there is still unhandled `commandScope`, let's handle its args as parameters...
|
|
110
|
+
if (commandScope) {
|
|
111
|
+
let unhandledArgs = commandScope.getArgs();
|
|
112
|
+
|
|
113
|
+
for (let unhandledArg of unhandledArgs) {
|
|
114
|
+
if (parserConfig.allowUnknownParameters) {
|
|
115
|
+
// let's handle other parameter
|
|
116
|
+
parsedParameters.push(unhandledArg);
|
|
117
|
+
} else {
|
|
118
|
+
checker.addError(
|
|
119
|
+
new ParsingError('UNKNOWN_PARAMETER', {messageParameters: [unhandledArg]}),
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
optionScope = null;
|
|
126
|
+
commandScope = null;
|
|
127
|
+
|
|
128
|
+
let optionName = arg;
|
|
129
|
+
let optionValue;
|
|
130
|
+
|
|
131
|
+
// Extract option name and value
|
|
132
|
+
if (optionName.includes('=')) {
|
|
133
|
+
let result = optionName.split('=', 2);
|
|
134
|
+
|
|
135
|
+
if (result[0] && result[1]) {
|
|
136
|
+
[optionName, optionValue] = result;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (isShortOption(optionName)) {
|
|
141
|
+
let fullOptionName = optionShortNameMap[optionName.slice(1)];
|
|
142
|
+
|
|
143
|
+
if (typeof fullOptionName === 'string') {
|
|
144
|
+
optionName = fullOptionName;
|
|
145
|
+
}
|
|
146
|
+
} else if (isLongOption(optionName)) {
|
|
147
|
+
optionName = optionName.slice(2);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
let newOptionScope = new OptionScope(
|
|
151
|
+
optionName,
|
|
152
|
+
optionsConfig,
|
|
153
|
+
parserConfig.allowUnknownOptions,
|
|
154
|
+
);
|
|
155
|
+
|
|
156
|
+
if (typeof parsedOptions[newOptionScope.name] !== 'undefined') {
|
|
157
|
+
if (newOptionScope.config.multiple) {
|
|
158
|
+
newOptionScope.previousParsedValue = parsedOptions[newOptionScope.name];
|
|
159
|
+
} else if (newOptionScope.config.type === 'number' && newOptionScope.config.count) {
|
|
160
|
+
newOptionScope.previousParsedValue = parsedOptions[newOptionScope.name];
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
if (typeof optionValue !== 'undefined') {
|
|
165
|
+
newOptionScope.captureArg(optionValue);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
if (newOptionScope.isComplete()) {
|
|
169
|
+
commitOptionScope(
|
|
170
|
+
newOptionScope,
|
|
171
|
+
optionsConfig[newOptionScope.name] ? parsedOptions : parsedUnknownOptions,
|
|
172
|
+
);
|
|
173
|
+
|
|
174
|
+
optionScope = null;
|
|
175
|
+
} else {
|
|
176
|
+
optionScope = newOptionScope;
|
|
177
|
+
}
|
|
178
|
+
} else if (
|
|
179
|
+
optionScope &&
|
|
180
|
+
!(optionScope.config.type === 'boolean' && !optionScope.config.multiple)
|
|
181
|
+
) {
|
|
182
|
+
// let's handle adding more values to previous option, but not if it's signle boolean option
|
|
183
|
+
|
|
184
|
+
optionScope.captureArg(arg);
|
|
185
|
+
|
|
186
|
+
if (optionScope.isComplete()) {
|
|
187
|
+
commitOptionScope(
|
|
188
|
+
optionScope,
|
|
189
|
+
optionsConfig[optionScope.name] ? parsedOptions : parsedUnknownOptions,
|
|
190
|
+
);
|
|
191
|
+
|
|
192
|
+
optionScope = null;
|
|
193
|
+
}
|
|
194
|
+
} else if (
|
|
195
|
+
optionScope &&
|
|
196
|
+
optionScope.config.type === 'boolean' &&
|
|
197
|
+
!optionScope.config.multiple &&
|
|
198
|
+
(isFalseString(arg) || isTrueString(arg))
|
|
199
|
+
) {
|
|
200
|
+
// we're adding value to a single boolean option only if the value is "false" or "true" string
|
|
201
|
+
optionScope.captureArg(arg);
|
|
202
|
+
|
|
203
|
+
if (optionScope.isComplete()) {
|
|
204
|
+
commitOptionScope(
|
|
205
|
+
optionScope,
|
|
206
|
+
optionsConfig[optionScope.name] ? parsedOptions : parsedUnknownOptions,
|
|
207
|
+
);
|
|
208
|
+
|
|
209
|
+
optionScope = null;
|
|
210
|
+
}
|
|
211
|
+
} else if (commandScope) {
|
|
212
|
+
// let's handle rest of the command
|
|
213
|
+
|
|
214
|
+
commandScope.captureArg(arg);
|
|
215
|
+
|
|
216
|
+
if (commandScope.isComplete()) {
|
|
217
|
+
parsedCommand = commandScope.getValue();
|
|
218
|
+
commandScope = null;
|
|
219
|
+
} else if (commandScope.isDone()) {
|
|
220
|
+
let unhandledArgs = commandScope.getArgs();
|
|
221
|
+
|
|
222
|
+
for (let unhandledArg of unhandledArgs) {
|
|
223
|
+
if (parserConfig.allowUnknownParameters) {
|
|
224
|
+
// let's handle other parameter
|
|
225
|
+
parsedParameters.push(unhandledArg);
|
|
226
|
+
} else {
|
|
227
|
+
checker.addError(
|
|
228
|
+
new ParsingError('UNKNOWN_PARAMETER', {messageParameters: [unhandledArg]}),
|
|
229
|
+
);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
commandScope = null;
|
|
234
|
+
}
|
|
235
|
+
} else if (
|
|
236
|
+
typeof parsedCommand === 'undefined' &&
|
|
237
|
+
commandFirstArguments.includes(arg.toLowerCase())
|
|
238
|
+
) {
|
|
239
|
+
// let's handle command
|
|
240
|
+
|
|
241
|
+
let newCommandScope = new CommandScope(arg, normalizedCommandsConfig);
|
|
242
|
+
|
|
243
|
+
if (newCommandScope.isComplete()) {
|
|
244
|
+
parsedCommand = newCommandScope.getValue();
|
|
245
|
+
commandScope = null;
|
|
246
|
+
} else {
|
|
247
|
+
commandScope = newCommandScope;
|
|
248
|
+
}
|
|
249
|
+
} else if (parametersConfig[parsedParameters.length]) {
|
|
250
|
+
// let's handle configured parameter
|
|
251
|
+
let parameterConfig = parametersConfig[parsedParameters.length] as ParameterConfig;
|
|
252
|
+
let parameterValue = castValue(arg, parameterConfig.type);
|
|
253
|
+
|
|
254
|
+
if (
|
|
255
|
+
parameterConfig.type !== 'boolean' &&
|
|
256
|
+
typeof parameterConfig.choices !== 'undefined' &&
|
|
257
|
+
!parameterConfig.choices.includes(parameterValue as never) // during runtime `parameterValue` has correct type
|
|
258
|
+
) {
|
|
259
|
+
throw new ParsingError('INVALID_PARAMETER', {
|
|
260
|
+
messageParameters: [
|
|
261
|
+
parameterValue,
|
|
262
|
+
parameterConfig.label ?? parsedParameters.length,
|
|
263
|
+
parameterConfig.choices.map((choice) => `"${choice}"`).join(', '),
|
|
264
|
+
],
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
parsedParameters.push(parameterValue);
|
|
269
|
+
|
|
270
|
+
if (parameterConfig.validate) {
|
|
271
|
+
parameterConfig.validate(parameterValue as never); // during runtime `parameterValue` has correct type
|
|
272
|
+
}
|
|
273
|
+
} else if (parserConfig.allowUnknownParameters) {
|
|
274
|
+
// let's handle other parameter
|
|
275
|
+
parsedParameters.push(arg);
|
|
276
|
+
} else {
|
|
277
|
+
throw new ParsingError('UNKNOWN_PARAMETER', {messageParameters: [arg]});
|
|
278
|
+
}
|
|
279
|
+
} catch (error: unknown) {
|
|
280
|
+
optionScope = null;
|
|
281
|
+
commandScope = null;
|
|
282
|
+
|
|
283
|
+
checker.addError(error as Error);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
try {
|
|
288
|
+
if (optionScope) {
|
|
289
|
+
commitOptionScope(
|
|
290
|
+
optionScope,
|
|
291
|
+
optionsConfig[optionScope.name] ? parsedOptions : parsedUnknownOptions,
|
|
292
|
+
);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// if there is still unhandled `commandScope`, let's handle its args as parameters...
|
|
296
|
+
if (commandScope) {
|
|
297
|
+
let unhandledArgs = commandScope.getArgs();
|
|
298
|
+
|
|
299
|
+
for (let unhandledArg of unhandledArgs) {
|
|
300
|
+
if (parserConfig.allowUnknownParameters) {
|
|
301
|
+
// let's handle other parameter
|
|
302
|
+
parsedParameters.push(unhandledArg);
|
|
303
|
+
} else {
|
|
304
|
+
checker.addError(
|
|
305
|
+
new ParsingError('UNKNOWN_PARAMETER', {messageParameters: [unhandledArg]}),
|
|
306
|
+
);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// if there are missing parsed parameters, add undefined
|
|
312
|
+
for (let [i] of parametersConfig.entries()) {
|
|
313
|
+
if (typeof parsedParameters[i] === 'undefined') {
|
|
314
|
+
parsedParameters[i] = undefined;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// handle default option values...
|
|
319
|
+
for (let [optionName, optionConfig] of Object.entries(optionsConfig)) {
|
|
320
|
+
if (
|
|
321
|
+
typeof parsedOptions[optionName] === 'undefined' &&
|
|
322
|
+
typeof optionConfig.defaultValue !== 'undefined'
|
|
323
|
+
) {
|
|
324
|
+
parsedOptions[optionName] = optionConfig.defaultValue;
|
|
325
|
+
} else if (typeof parsedOptions[optionName] === 'undefined') {
|
|
326
|
+
parsedOptions[optionName] = undefined;
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
// handle default parameters values...
|
|
331
|
+
for (let [i, parameterConfig] of parametersConfig.entries()) {
|
|
332
|
+
if (
|
|
333
|
+
typeof parsedParameters[i] === 'undefined' &&
|
|
334
|
+
typeof parameterConfig.defaultValue !== 'undefined'
|
|
335
|
+
) {
|
|
336
|
+
parsedParameters[i] = parameterConfig.defaultValue;
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
} catch (error: unknown) {
|
|
340
|
+
checker.addError(error as Error);
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
checker.checkParsedParameters(parametersConfig, parsedParameters);
|
|
344
|
+
checker.checkParsedOptions(optionsConfig, parsedOptions);
|
|
345
|
+
|
|
346
|
+
return {
|
|
347
|
+
command: (normalizedCommandsConfig.length ? parsedCommand : null) as ArgumentsCommand<O>,
|
|
348
|
+
parameters: (parametersConfig.length || parserConfig.allowUnknownParameters
|
|
349
|
+
? parsedParameters
|
|
350
|
+
: null) as ArgumentsParameters<O>,
|
|
351
|
+
options: (Object.keys(optionsConfig).length ? parsedOptions : null) as ArgumentsOptions<O>,
|
|
352
|
+
unknownOptions: (parserConfig.allowUnknownOptions
|
|
353
|
+
? parsedUnknownOptions
|
|
354
|
+
: null) as ArgumentsUnknownOptions<O>,
|
|
355
|
+
rest: restArgs,
|
|
356
|
+
errors: checker.errors,
|
|
357
|
+
};
|
|
358
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import {type ArgumentsCommand} from './ArgumentsCommand.js';
|
|
2
|
+
import {type ArgumentsOptions} from './ArgumentsOptions.js';
|
|
3
|
+
import {type ArgumentsParameters} from './ArgumentsParameters.js';
|
|
4
|
+
import {type ArgumentsUnknownOptions} from './ArgumentsUnknownOptions.js';
|
|
5
|
+
import {type ParserConfig} from './ParserConfig.js';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Parsed arguments.
|
|
9
|
+
*/
|
|
10
|
+
export type Arguments<T extends ParserConfig> = {
|
|
11
|
+
/** Parsed command. */
|
|
12
|
+
readonly command: ArgumentsCommand<T>;
|
|
13
|
+
|
|
14
|
+
/** Parsed parameters. */
|
|
15
|
+
readonly parameters: ArgumentsParameters<T>;
|
|
16
|
+
|
|
17
|
+
/** Parsed options. */
|
|
18
|
+
readonly options: ArgumentsOptions<T>;
|
|
19
|
+
|
|
20
|
+
/** Unconfigured options. */
|
|
21
|
+
readonly unknownOptions: ArgumentsUnknownOptions<T>;
|
|
22
|
+
|
|
23
|
+
/** Arguments that appear after "--". */
|
|
24
|
+
readonly rest: string[];
|
|
25
|
+
|
|
26
|
+
/** Parsing and validation rrors */
|
|
27
|
+
readonly errors: Error[];
|
|
28
|
+
};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import {type ParserConfig} from './ParserConfig.js';
|
|
2
|
+
|
|
3
|
+
/** Parsed command. */
|
|
4
|
+
export type ArgumentsCommand<O extends ParserConfig> = Omit<O, 'commands'> extends O
|
|
5
|
+
? null
|
|
6
|
+
: O['commands'] extends undefined
|
|
7
|
+
? null
|
|
8
|
+
: Lowercase<NonNullable<O['commands']>[number]> | undefined;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import {type TupleToUnion} from '@jakubmazanec/ts-utils';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
type CountOptionConfig,
|
|
5
|
+
type BooleansOptionConfig,
|
|
6
|
+
type NumbersOptionConfig,
|
|
7
|
+
type StringsOptionConfig,
|
|
8
|
+
type OptionConfig,
|
|
9
|
+
type BooleanOptionConfig,
|
|
10
|
+
type NumberOptionConfig,
|
|
11
|
+
type StringOptionConfig,
|
|
12
|
+
} from './OptionConfig.js';
|
|
13
|
+
import {type OptionsConfig} from './OptionsConfig.js';
|
|
14
|
+
import {type ParserConfig} from './ParserConfig.js';
|
|
15
|
+
|
|
16
|
+
type BooleanOptionConfigToArgumentsOption<O extends BooleanOptionConfig | BooleansOptionConfig> =
|
|
17
|
+
O extends BooleanOptionConfig
|
|
18
|
+
? O['defaultValue'] extends boolean
|
|
19
|
+
? boolean
|
|
20
|
+
: boolean | undefined
|
|
21
|
+
: O extends BooleansOptionConfig
|
|
22
|
+
? O['defaultValue'] extends readonly boolean[]
|
|
23
|
+
? boolean[]
|
|
24
|
+
: boolean[] | undefined
|
|
25
|
+
: never;
|
|
26
|
+
|
|
27
|
+
type NumberOptionConfigToArgumentsOption<
|
|
28
|
+
O extends CountOptionConfig | NumberOptionConfig | NumbersOptionConfig,
|
|
29
|
+
> = O extends NumbersOptionConfig
|
|
30
|
+
? O['choices'] extends readonly number[]
|
|
31
|
+
? O['defaultValue'] extends readonly number[]
|
|
32
|
+
? Array<TupleToUnion<O['choices']>>
|
|
33
|
+
: Array<TupleToUnion<O['choices']>> | undefined
|
|
34
|
+
: O['defaultValue'] extends readonly number[]
|
|
35
|
+
? number[]
|
|
36
|
+
: number[] | undefined
|
|
37
|
+
: O extends NumberOptionConfig
|
|
38
|
+
? O['choices'] extends readonly number[]
|
|
39
|
+
? O['defaultValue'] extends number
|
|
40
|
+
? TupleToUnion<O['choices']>
|
|
41
|
+
: TupleToUnion<O['choices']> | undefined
|
|
42
|
+
: O['defaultValue'] extends number
|
|
43
|
+
? number
|
|
44
|
+
: number | undefined
|
|
45
|
+
: O extends CountOptionConfig
|
|
46
|
+
? O['defaultValue'] extends number
|
|
47
|
+
? number
|
|
48
|
+
: number | undefined
|
|
49
|
+
: never;
|
|
50
|
+
|
|
51
|
+
type StringOptionConfigToArgumentsOption<O extends StringOptionConfig | StringsOptionConfig> =
|
|
52
|
+
O extends StringsOptionConfig
|
|
53
|
+
? O['choices'] extends readonly string[]
|
|
54
|
+
? O['defaultValue'] extends readonly string[]
|
|
55
|
+
? Array<TupleToUnion<O['choices']>>
|
|
56
|
+
: Array<TupleToUnion<O['choices']>> | undefined
|
|
57
|
+
: O['defaultValue'] extends readonly string[]
|
|
58
|
+
? string[]
|
|
59
|
+
: string[] | undefined
|
|
60
|
+
: O extends StringOptionConfig
|
|
61
|
+
? O['choices'] extends readonly string[]
|
|
62
|
+
? O['defaultValue'] extends string
|
|
63
|
+
? TupleToUnion<O['choices']>
|
|
64
|
+
: TupleToUnion<O['choices']> | undefined
|
|
65
|
+
: O['defaultValue'] extends string
|
|
66
|
+
? string
|
|
67
|
+
: string | undefined
|
|
68
|
+
: never;
|
|
69
|
+
|
|
70
|
+
type OptionConfigToArgumentOption<O extends OptionConfig> = O extends
|
|
71
|
+
| BooleanOptionConfig
|
|
72
|
+
| BooleansOptionConfig
|
|
73
|
+
? BooleanOptionConfigToArgumentsOption<O>
|
|
74
|
+
: O extends CountOptionConfig | NumberOptionConfig | NumbersOptionConfig
|
|
75
|
+
? NumberOptionConfigToArgumentsOption<O>
|
|
76
|
+
: O extends StringOptionConfig | StringsOptionConfig
|
|
77
|
+
? StringOptionConfigToArgumentsOption<O>
|
|
78
|
+
: never;
|
|
79
|
+
|
|
80
|
+
type OptionsConfigToArgumentsOptions<O extends OptionsConfig> = {
|
|
81
|
+
[K in keyof O]: OptionConfigToArgumentOption<O[K]>;
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
/** Parsed options. */
|
|
85
|
+
export type ArgumentsOptions<O extends ParserConfig> = Omit<O, 'options'> extends O
|
|
86
|
+
? null
|
|
87
|
+
: O['options'] extends undefined
|
|
88
|
+
? null
|
|
89
|
+
: OptionsConfigToArgumentsOptions<NonNullable<O['options']>>;
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import {type TupleToUnion} from '@jakubmazanec/ts-utils';
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
type ParameterConfig,
|
|
5
|
+
type BooleanParameterConfig,
|
|
6
|
+
type NumberParameterConfig,
|
|
7
|
+
type StringParameterConfig,
|
|
8
|
+
} from './ParameterConfig.js';
|
|
9
|
+
import {type ParametersConfig} from './ParametersConfig.js';
|
|
10
|
+
import {type ParserConfig} from './ParserConfig.js';
|
|
11
|
+
|
|
12
|
+
type NumberParameterConfigToArgumentsParameter<O extends NumberParameterConfig> =
|
|
13
|
+
O['choices'] extends readonly number[]
|
|
14
|
+
? O['defaultValue'] extends number
|
|
15
|
+
? TupleToUnion<O['choices']>
|
|
16
|
+
: TupleToUnion<O['choices']> | undefined
|
|
17
|
+
: O['defaultValue'] extends number
|
|
18
|
+
? number
|
|
19
|
+
: number | undefined;
|
|
20
|
+
|
|
21
|
+
type StringParameterConfigToArgumentsParameter<O extends StringParameterConfig> =
|
|
22
|
+
O['choices'] extends readonly string[]
|
|
23
|
+
? O['defaultValue'] extends string
|
|
24
|
+
? TupleToUnion<O['choices']>
|
|
25
|
+
: TupleToUnion<O['choices']> | undefined
|
|
26
|
+
: O['defaultValue'] extends string
|
|
27
|
+
? string
|
|
28
|
+
: string | undefined;
|
|
29
|
+
|
|
30
|
+
type BooleanParameterConfigToArgumentsParameter<O extends BooleanParameterConfig> =
|
|
31
|
+
O['defaultValue'] extends boolean ? boolean : boolean | undefined;
|
|
32
|
+
|
|
33
|
+
type ParameterConfigToArgumentsParameter<O extends ParameterConfig> =
|
|
34
|
+
O extends NumberParameterConfig
|
|
35
|
+
? NumberParameterConfigToArgumentsParameter<O>
|
|
36
|
+
: O extends StringParameterConfig
|
|
37
|
+
? StringParameterConfigToArgumentsParameter<O>
|
|
38
|
+
: O extends BooleanParameterConfig
|
|
39
|
+
? BooleanParameterConfigToArgumentsParameter<O>
|
|
40
|
+
: never;
|
|
41
|
+
|
|
42
|
+
type ParametersConfigToArgumentsParameters<O extends ParametersConfig> = O extends readonly [
|
|
43
|
+
ParameterConfig,
|
|
44
|
+
ParameterConfig,
|
|
45
|
+
ParameterConfig,
|
|
46
|
+
ParameterConfig,
|
|
47
|
+
ParameterConfig,
|
|
48
|
+
ParameterConfig,
|
|
49
|
+
]
|
|
50
|
+
? readonly [
|
|
51
|
+
ParameterConfigToArgumentsParameter<O[0]>,
|
|
52
|
+
ParameterConfigToArgumentsParameter<O[1]>,
|
|
53
|
+
ParameterConfigToArgumentsParameter<O[2]>,
|
|
54
|
+
ParameterConfigToArgumentsParameter<O[3]>,
|
|
55
|
+
ParameterConfigToArgumentsParameter<O[4]>,
|
|
56
|
+
ParameterConfigToArgumentsParameter<O[5]>,
|
|
57
|
+
]
|
|
58
|
+
: O extends readonly [
|
|
59
|
+
ParameterConfig,
|
|
60
|
+
ParameterConfig,
|
|
61
|
+
ParameterConfig,
|
|
62
|
+
ParameterConfig,
|
|
63
|
+
ParameterConfig,
|
|
64
|
+
]
|
|
65
|
+
? readonly [
|
|
66
|
+
ParameterConfigToArgumentsParameter<O[0]>,
|
|
67
|
+
ParameterConfigToArgumentsParameter<O[1]>,
|
|
68
|
+
ParameterConfigToArgumentsParameter<O[2]>,
|
|
69
|
+
ParameterConfigToArgumentsParameter<O[3]>,
|
|
70
|
+
ParameterConfigToArgumentsParameter<O[4]>,
|
|
71
|
+
]
|
|
72
|
+
: O extends readonly [ParameterConfig, ParameterConfig, ParameterConfig, ParameterConfig]
|
|
73
|
+
? readonly [
|
|
74
|
+
ParameterConfigToArgumentsParameter<O[0]>,
|
|
75
|
+
ParameterConfigToArgumentsParameter<O[1]>,
|
|
76
|
+
ParameterConfigToArgumentsParameter<O[2]>,
|
|
77
|
+
ParameterConfigToArgumentsParameter<O[3]>,
|
|
78
|
+
]
|
|
79
|
+
: O extends readonly [ParameterConfig, ParameterConfig, ParameterConfig]
|
|
80
|
+
? readonly [
|
|
81
|
+
ParameterConfigToArgumentsParameter<O[0]>,
|
|
82
|
+
ParameterConfigToArgumentsParameter<O[1]>,
|
|
83
|
+
ParameterConfigToArgumentsParameter<O[2]>,
|
|
84
|
+
]
|
|
85
|
+
: O extends readonly [ParameterConfig, ParameterConfig]
|
|
86
|
+
? readonly [ParameterConfigToArgumentsParameter<O[0]>, ParameterConfigToArgumentsParameter<O[1]>]
|
|
87
|
+
: O extends readonly [ParameterConfig]
|
|
88
|
+
? readonly [ParameterConfigToArgumentsParameter<O[0]>]
|
|
89
|
+
: never;
|
|
90
|
+
|
|
91
|
+
type ParametersConfigToVariadicArgumentsParameters<O extends ParametersConfig> =
|
|
92
|
+
O extends readonly [
|
|
93
|
+
ParameterConfig,
|
|
94
|
+
ParameterConfig,
|
|
95
|
+
ParameterConfig,
|
|
96
|
+
ParameterConfig,
|
|
97
|
+
ParameterConfig,
|
|
98
|
+
ParameterConfig,
|
|
99
|
+
]
|
|
100
|
+
? readonly [
|
|
101
|
+
ParameterConfigToArgumentsParameter<O[0]>,
|
|
102
|
+
ParameterConfigToArgumentsParameter<O[1]>,
|
|
103
|
+
ParameterConfigToArgumentsParameter<O[2]>,
|
|
104
|
+
ParameterConfigToArgumentsParameter<O[3]>,
|
|
105
|
+
ParameterConfigToArgumentsParameter<O[4]>,
|
|
106
|
+
ParameterConfigToArgumentsParameter<O[5]>,
|
|
107
|
+
...(readonly string[]),
|
|
108
|
+
]
|
|
109
|
+
: O extends readonly [
|
|
110
|
+
ParameterConfig,
|
|
111
|
+
ParameterConfig,
|
|
112
|
+
ParameterConfig,
|
|
113
|
+
ParameterConfig,
|
|
114
|
+
ParameterConfig,
|
|
115
|
+
]
|
|
116
|
+
? readonly [
|
|
117
|
+
ParameterConfigToArgumentsParameter<O[0]>,
|
|
118
|
+
ParameterConfigToArgumentsParameter<O[1]>,
|
|
119
|
+
ParameterConfigToArgumentsParameter<O[2]>,
|
|
120
|
+
ParameterConfigToArgumentsParameter<O[3]>,
|
|
121
|
+
ParameterConfigToArgumentsParameter<O[4]>,
|
|
122
|
+
...(readonly string[]),
|
|
123
|
+
]
|
|
124
|
+
: O extends readonly [ParameterConfig, ParameterConfig, ParameterConfig, ParameterConfig]
|
|
125
|
+
? readonly [
|
|
126
|
+
ParameterConfigToArgumentsParameter<O[0]>,
|
|
127
|
+
ParameterConfigToArgumentsParameter<O[1]>,
|
|
128
|
+
ParameterConfigToArgumentsParameter<O[2]>,
|
|
129
|
+
ParameterConfigToArgumentsParameter<O[3]>,
|
|
130
|
+
...(readonly string[]),
|
|
131
|
+
]
|
|
132
|
+
: O extends readonly [ParameterConfig, ParameterConfig, ParameterConfig]
|
|
133
|
+
? readonly [
|
|
134
|
+
ParameterConfigToArgumentsParameter<O[0]>,
|
|
135
|
+
ParameterConfigToArgumentsParameter<O[1]>,
|
|
136
|
+
ParameterConfigToArgumentsParameter<O[2]>,
|
|
137
|
+
...(readonly string[]),
|
|
138
|
+
]
|
|
139
|
+
: O extends readonly [ParameterConfig, ParameterConfig]
|
|
140
|
+
? readonly [
|
|
141
|
+
ParameterConfigToArgumentsParameter<O[0]>,
|
|
142
|
+
ParameterConfigToArgumentsParameter<O[1]>,
|
|
143
|
+
...(readonly string[]),
|
|
144
|
+
]
|
|
145
|
+
: O extends readonly [ParameterConfig]
|
|
146
|
+
? readonly [ParameterConfigToArgumentsParameter<O[0]>, ...(readonly string[])]
|
|
147
|
+
: readonly [...(readonly string[])];
|
|
148
|
+
|
|
149
|
+
/** Parsed parameters. */
|
|
150
|
+
export type ArgumentsParameters<O extends ParserConfig> = Omit<O, 'parameters'> extends O
|
|
151
|
+
? O['allowUnknownParameters'] extends true
|
|
152
|
+
? [...string[]]
|
|
153
|
+
: null
|
|
154
|
+
: O['parameters'] extends undefined
|
|
155
|
+
? null
|
|
156
|
+
: O['allowUnknownParameters'] extends true
|
|
157
|
+
? ParametersConfigToVariadicArgumentsParameters<NonNullable<O['parameters']>>
|
|
158
|
+
: ParametersConfigToArgumentsParameters<NonNullable<O['parameters']>>;
|