@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.
Files changed (151) hide show
  1. package/LICENSE.md +18 -0
  2. package/README.md +84 -0
  3. package/dist/ParsingError.d.ts +4 -0
  4. package/dist/ParsingError.js +11 -0
  5. package/dist/ParsingError.js.map +1 -0
  6. package/dist/ValidationError.d.ts +4 -0
  7. package/dist/ValidationError.js +16 -0
  8. package/dist/ValidationError.js.map +1 -0
  9. package/dist/internals/Checker.d.ts +13 -0
  10. package/dist/internals/Checker.js +118 -0
  11. package/dist/internals/Checker.js.map +1 -0
  12. package/dist/internals/CommandScope.d.ts +14 -0
  13. package/dist/internals/CommandScope.js +48 -0
  14. package/dist/internals/CommandScope.js.map +1 -0
  15. package/dist/internals/OptionScope.d.ts +14 -0
  16. package/dist/internals/OptionScope.js +87 -0
  17. package/dist/internals/OptionScope.js.map +1 -0
  18. package/dist/internals/castValue.d.ts +7 -0
  19. package/dist/internals/castValue.js +25 -0
  20. package/dist/internals/castValue.js.map +1 -0
  21. package/dist/internals/commandToArguments.d.ts +7 -0
  22. package/dist/internals/commandToArguments.js +21 -0
  23. package/dist/internals/commandToArguments.js.map +1 -0
  24. package/dist/internals/createOptionShortNameMap.d.ts +2 -0
  25. package/dist/internals/createOptionShortNameMap.js +11 -0
  26. package/dist/internals/createOptionShortNameMap.js.map +1 -0
  27. package/dist/internals/expandArguments.d.ts +8 -0
  28. package/dist/internals/expandArguments.js +21 -0
  29. package/dist/internals/expandArguments.js.map +1 -0
  30. package/dist/internals/isCommand.d.ts +8 -0
  31. package/dist/internals/isCommand.js +11 -0
  32. package/dist/internals/isCommand.js.map +1 -0
  33. package/dist/internals/isFalseString.d.ts +6 -0
  34. package/dist/internals/isFalseString.js +10 -0
  35. package/dist/internals/isFalseString.js.map +1 -0
  36. package/dist/internals/isLongOption.d.ts +7 -0
  37. package/dist/internals/isLongOption.js +11 -0
  38. package/dist/internals/isLongOption.js.map +1 -0
  39. package/dist/internals/isOptionLike.d.ts +7 -0
  40. package/dist/internals/isOptionLike.js +11 -0
  41. package/dist/internals/isOptionLike.js.map +1 -0
  42. package/dist/internals/isShortOption.d.ts +7 -0
  43. package/dist/internals/isShortOption.js +11 -0
  44. package/dist/internals/isShortOption.js.map +1 -0
  45. package/dist/internals/isShortOptionsGroup.d.ts +8 -0
  46. package/dist/internals/isShortOptionsGroup.js +11 -0
  47. package/dist/internals/isShortOptionsGroup.js.map +1 -0
  48. package/dist/internals/isTrueString.d.ts +6 -0
  49. package/dist/internals/isTrueString.js +10 -0
  50. package/dist/internals/isTrueString.js.map +1 -0
  51. package/dist/internals.d.ts +14 -0
  52. package/dist/internals.js +16 -0
  53. package/dist/internals.js.map +1 -0
  54. package/dist/main.d.ts +4 -0
  55. package/dist/main.js +6 -0
  56. package/dist/main.js.map +1 -0
  57. package/dist/parseArguments.d.ts +10 -0
  58. package/dist/parseArguments.js +244 -0
  59. package/dist/parseArguments.js.map +1 -0
  60. package/dist/types/Arguments.d.ts +22 -0
  61. package/dist/types/Arguments.js +3 -0
  62. package/dist/types/Arguments.js.map +1 -0
  63. package/dist/types/ArgumentsCommand.d.ts +3 -0
  64. package/dist/types/ArgumentsCommand.js +3 -0
  65. package/dist/types/ArgumentsCommand.js.map +1 -0
  66. package/dist/types/ArgumentsOptions.d.ts +14 -0
  67. package/dist/types/ArgumentsOptions.js +3 -0
  68. package/dist/types/ArgumentsOptions.js.map +1 -0
  69. package/dist/types/ArgumentsParameters.d.ts +91 -0
  70. package/dist/types/ArgumentsParameters.js +3 -0
  71. package/dist/types/ArgumentsParameters.js.map +1 -0
  72. package/dist/types/ArgumentsUnknownOptions.d.ts +3 -0
  73. package/dist/types/ArgumentsUnknownOptions.js +3 -0
  74. package/dist/types/ArgumentsUnknownOptions.js.map +1 -0
  75. package/dist/types/Argv.d.ts +2 -0
  76. package/dist/types/Argv.js +3 -0
  77. package/dist/types/Argv.js.map +1 -0
  78. package/dist/types/CommandConfig.d.ts +2 -0
  79. package/dist/types/CommandConfig.js +3 -0
  80. package/dist/types/CommandConfig.js.map +1 -0
  81. package/dist/types/CommandsConfig.d.ts +3 -0
  82. package/dist/types/CommandsConfig.js +3 -0
  83. package/dist/types/CommandsConfig.js.map +1 -0
  84. package/dist/types/LongOptionName.d.ts +2 -0
  85. package/dist/types/LongOptionName.js +3 -0
  86. package/dist/types/LongOptionName.js.map +1 -0
  87. package/dist/types/NormalizedCommandConfig.d.ts +5 -0
  88. package/dist/types/NormalizedCommandConfig.js +3 -0
  89. package/dist/types/NormalizedCommandConfig.js.map +1 -0
  90. package/dist/types/NormalizedCommandsConfig.d.ts +3 -0
  91. package/dist/types/NormalizedCommandsConfig.js +3 -0
  92. package/dist/types/NormalizedCommandsConfig.js.map +1 -0
  93. package/dist/types/OptionConfig.d.ts +220 -0
  94. package/dist/types/OptionConfig.js +3 -0
  95. package/dist/types/OptionConfig.js.map +1 -0
  96. package/dist/types/OptionsConfig.d.ts +3 -0
  97. package/dist/types/OptionsConfig.js +3 -0
  98. package/dist/types/OptionsConfig.js.map +1 -0
  99. package/dist/types/ParameterConfig.d.ts +74 -0
  100. package/dist/types/ParameterConfig.js +3 -0
  101. package/dist/types/ParameterConfig.js.map +1 -0
  102. package/dist/types/ParametersConfig.d.ts +10 -0
  103. package/dist/types/ParametersConfig.js +3 -0
  104. package/dist/types/ParametersConfig.js.map +1 -0
  105. package/dist/types/ParserConfig.d.ts +16 -0
  106. package/dist/types/ParserConfig.js +3 -0
  107. package/dist/types/ParserConfig.js.map +1 -0
  108. package/dist/types/ShortOptionName.d.ts +2 -0
  109. package/dist/types/ShortOptionName.js +3 -0
  110. package/dist/types/ShortOptionName.js.map +1 -0
  111. package/dist/types.d.ts +17 -0
  112. package/dist/types.js +19 -0
  113. package/dist/types.js.map +1 -0
  114. package/package.json +42 -0
  115. package/src/ParsingError.ts +11 -0
  116. package/src/ValidationError.ts +22 -0
  117. package/src/internals/Checker.ts +145 -0
  118. package/src/internals/CommandScope.ts +61 -0
  119. package/src/internals/OptionScope.ts +101 -0
  120. package/src/internals/castValue.ts +36 -0
  121. package/src/internals/commandToArguments.ts +22 -0
  122. package/src/internals/createOptionShortNameMap.ts +13 -0
  123. package/src/internals/expandArguments.ts +22 -0
  124. package/src/internals/isCommand.ts +11 -0
  125. package/src/internals/isFalseString.ts +10 -0
  126. package/src/internals/isLongOption.ts +11 -0
  127. package/src/internals/isOptionLike.ts +11 -0
  128. package/src/internals/isShortOption.ts +11 -0
  129. package/src/internals/isShortOptionsGroup.ts +11 -0
  130. package/src/internals/isTrueString.ts +10 -0
  131. package/src/internals.ts +14 -0
  132. package/src/main.ts +4 -0
  133. package/src/parseArguments.ts +358 -0
  134. package/src/types/Arguments.ts +28 -0
  135. package/src/types/ArgumentsCommand.ts +8 -0
  136. package/src/types/ArgumentsOptions.ts +89 -0
  137. package/src/types/ArgumentsParameters.ts +158 -0
  138. package/src/types/ArgumentsUnknownOptions.ts +6 -0
  139. package/src/types/Argv.ts +2 -0
  140. package/src/types/CommandConfig.ts +2 -0
  141. package/src/types/CommandsConfig.ts +4 -0
  142. package/src/types/LongOptionName.ts +2 -0
  143. package/src/types/NormalizedCommandConfig.ts +5 -0
  144. package/src/types/NormalizedCommandsConfig.ts +4 -0
  145. package/src/types/OptionConfig.ts +279 -0
  146. package/src/types/OptionsConfig.ts +4 -0
  147. package/src/types/ParameterConfig.ts +100 -0
  148. package/src/types/ParametersConfig.ts +17 -0
  149. package/src/types/ParserConfig.ts +21 -0
  150. package/src/types/ShortOptionName.ts +54 -0
  151. 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']>>;
@@ -0,0 +1,6 @@
1
+ import {type ParserConfig} from './ParserConfig.js';
2
+
3
+ /** Unknown options. Unknown options are always parsed as strings. */
4
+ export type ArgumentsUnknownOptions<O extends ParserConfig> = O['allowUnknownOptions'] extends true
5
+ ? Record<string, unknown>
6
+ : null;
@@ -0,0 +1,2 @@
1
+ /** Unparsed arguments. */
2
+ export type Argv = string[];
@@ -0,0 +1,2 @@
1
+ /** A type representing parser's command configuration. */
2
+ export type CommandConfig = string;
@@ -0,0 +1,4 @@
1
+ import {type CommandConfig} from './CommandConfig.js';
2
+
3
+ /** A type representing parser's commands configuration. */
4
+ export type CommandsConfig = readonly CommandConfig[];
@@ -0,0 +1,2 @@
1
+ /** Long option name. */
2
+ export type LongOptionName = string;
@@ -0,0 +1,5 @@
1
+ /** A type representing parser's normalized command configuration. */
2
+ export type NormalizedCommandConfig = {
3
+ command: string;
4
+ args: string[];
5
+ };
@@ -0,0 +1,4 @@
1
+ import {type NormalizedCommandConfig} from './NormalizedCommandConfig.js';
2
+
3
+ /** A type representing parser's normalized commands configuration. */
4
+ export type NormalizedCommandsConfig = NormalizedCommandConfig[];