@trenskow/arguments-parser 0.3.85 → 0.3.87
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/.vscode/settings.json +8 -0
- package/lib/index.js +185 -206
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
import { basename } from 'path';
|
|
10
10
|
|
|
11
11
|
import caseit from '@trenskow/caseit';
|
|
12
|
-
import { default as isvalid,
|
|
12
|
+
import { default as isvalid, merge, keyPaths, plugins } from 'isvalid';
|
|
13
13
|
import print from '@trenskow/print';
|
|
14
14
|
|
|
15
15
|
plugins.use('argumentsParser.default', () => ({
|
|
@@ -54,7 +54,12 @@ const argumentsParser = (
|
|
|
54
54
|
help: {
|
|
55
55
|
usage: helpUsage,
|
|
56
56
|
options: helpOptions,
|
|
57
|
-
} = {}
|
|
57
|
+
} = {},
|
|
58
|
+
options = {
|
|
59
|
+
schema: {},
|
|
60
|
+
data: {},
|
|
61
|
+
validationOptions: {}
|
|
62
|
+
}
|
|
58
63
|
} = {}
|
|
59
64
|
) => {
|
|
60
65
|
|
|
@@ -114,9 +119,23 @@ const argumentsParser = (
|
|
|
114
119
|
}
|
|
115
120
|
|
|
116
121
|
if (error) {
|
|
122
|
+
|
|
117
123
|
print();
|
|
118
|
-
|
|
119
|
-
|
|
124
|
+
|
|
125
|
+
(error.errors || [error])
|
|
126
|
+
.forEach((error) => {
|
|
127
|
+
|
|
128
|
+
let message = error.message;
|
|
129
|
+
|
|
130
|
+
if (error.keyPath?.[0]) {
|
|
131
|
+
message = `${caseit(error.keyPath[0], 'kebab')}: ${message}`;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
print.bold((strings?.commands?.help?.error || 'Error: <message>')
|
|
135
|
+
.replace('<message>', message));
|
|
136
|
+
|
|
137
|
+
});
|
|
138
|
+
|
|
120
139
|
}
|
|
121
140
|
|
|
122
141
|
print();
|
|
@@ -180,7 +199,8 @@ const argumentsParser = (
|
|
|
180
199
|
onCommand,
|
|
181
200
|
placeholder,
|
|
182
201
|
command: commands[tool],
|
|
183
|
-
strings
|
|
202
|
+
strings,
|
|
203
|
+
options
|
|
184
204
|
})
|
|
185
205
|
});
|
|
186
206
|
|
|
@@ -190,274 +210,233 @@ const argumentsParser = (
|
|
|
190
210
|
}
|
|
191
211
|
|
|
192
212
|
},
|
|
193
|
-
options:
|
|
213
|
+
options: (schema, validationOptions = { }) => {
|
|
194
214
|
|
|
195
|
-
|
|
215
|
+
validationOptions.command = validationOptions.command || command;
|
|
196
216
|
|
|
197
|
-
|
|
217
|
+
Object.assign(
|
|
218
|
+
options.validationOptions,
|
|
219
|
+
validationOptions);
|
|
198
220
|
|
|
199
|
-
|
|
200
|
-
|
|
221
|
+
options.schema = merge(
|
|
222
|
+
options.schema)
|
|
223
|
+
.with(schema);
|
|
201
224
|
|
|
202
|
-
|
|
203
|
-
nonOptions = args.slice(nonOptionsIndex + 1).join(' ');
|
|
204
|
-
args = args.slice(0, nonOptionsIndex);
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
const allKeyPaths = keyPaths(schema)
|
|
208
|
-
.all()
|
|
209
|
-
.filter((keyPath) => keyPath);
|
|
225
|
+
return result;
|
|
210
226
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
227
|
+
},
|
|
228
|
+
help(error) {
|
|
229
|
+
printHelp(error);
|
|
230
|
+
},
|
|
231
|
+
then: (...resultArguments) => {
|
|
232
|
+
return (async () => {
|
|
214
233
|
|
|
215
|
-
|
|
216
|
-
helpUsage.push(options.usage);
|
|
217
|
-
}
|
|
234
|
+
checkHelp();
|
|
218
235
|
|
|
219
|
-
|
|
236
|
+
let nonOptions;
|
|
237
|
+
let nonOptionsIndex = args.indexOf('--');
|
|
220
238
|
|
|
221
|
-
|
|
222
|
-
|
|
239
|
+
if (nonOptionsIndex > -1) {
|
|
240
|
+
nonOptions = args.slice(nonOptionsIndex + 1).join(' ');
|
|
241
|
+
args = args.slice(0, nonOptionsIndex);
|
|
242
|
+
}
|
|
223
243
|
|
|
224
|
-
|
|
244
|
+
const allKeyPaths = keyPaths(options.schema)
|
|
245
|
+
.all()
|
|
246
|
+
.filter((keyPath) => keyPath);
|
|
225
247
|
|
|
226
|
-
|
|
248
|
+
if (allKeyPaths.length) {
|
|
249
|
+
helpUsage.push(`${opening}${strings?.options?.help?.placeholder || 'options'}${closing}`);
|
|
250
|
+
}
|
|
227
251
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
252
|
+
if (typeof options.validationOptions.usage === 'string') {
|
|
253
|
+
helpUsage.push(options.validationOptions.usage);
|
|
254
|
+
}
|
|
231
255
|
|
|
232
|
-
|
|
256
|
+
let shortOptions = {};
|
|
233
257
|
|
|
234
|
-
|
|
258
|
+
allKeyPaths
|
|
259
|
+
.forEach((keyPath) => {
|
|
235
260
|
|
|
236
|
-
|
|
261
|
+
const keyPathSchema = keyPaths(options.schema).get(keyPath);
|
|
237
262
|
|
|
238
|
-
|
|
239
|
-
Object.entries(shortOptions)
|
|
240
|
-
.map(([key, value]) => [value, key]));
|
|
263
|
+
if (keyPathSchema.short) {
|
|
241
264
|
|
|
242
|
-
|
|
265
|
+
if (shortOptions[keyPathSchema.short]) {
|
|
266
|
+
throw new Error(`Short option "${keyPathSchema.short}" already used.`);
|
|
267
|
+
}
|
|
243
268
|
|
|
244
|
-
|
|
269
|
+
shortOptions[keyPath] = keyPathSchema.short;
|
|
245
270
|
|
|
246
|
-
|
|
247
|
-
print(strings?.options?.help?.title || 'Options:');
|
|
248
|
-
print();
|
|
271
|
+
}
|
|
249
272
|
|
|
250
|
-
|
|
251
|
-
.map((keyPath) => {
|
|
273
|
+
});
|
|
252
274
|
|
|
253
|
-
|
|
275
|
+
shortOptions = Object.fromEntries(
|
|
276
|
+
Object.entries(shortOptions)
|
|
277
|
+
.map(([key, value]) => [value, key]));
|
|
254
278
|
|
|
255
|
-
|
|
256
|
-
let description = [keyPathSchema.description || 'No description'];
|
|
279
|
+
if (allKeyPaths.length) {
|
|
257
280
|
|
|
258
|
-
|
|
259
|
-
optionKeys.push(`-${shortOptions[keyPath]}`);
|
|
260
|
-
}
|
|
281
|
+
helpOptions = () => {
|
|
261
282
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
283
|
+
print();
|
|
284
|
+
print(strings?.options?.help?.title || 'Options:');
|
|
285
|
+
print();
|
|
265
286
|
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
} else if (keyPathSchema.required === true) {
|
|
269
|
-
description.push(`${strings?.options?.help?.required || '(required)'}`);
|
|
270
|
-
} else if (typeof keyPathSchema.default !== 'undefined') {
|
|
287
|
+
list(print, Object.fromEntries(allKeyPaths
|
|
288
|
+
.map((keyPath) => {
|
|
271
289
|
|
|
272
|
-
|
|
290
|
+
const keyPathSchema = keyPaths(options.schema).get(keyPath);
|
|
273
291
|
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
} else {
|
|
292
|
+
let optionKeys = [`--${caseit(keyPath, 'kebab')}`];
|
|
293
|
+
let description = [keyPathSchema.description || 'No description'];
|
|
277
294
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
defaultDescription = `\`${keyPathSchema.defaultDescription ?? keyPathSchema.default}\``;
|
|
282
|
-
}
|
|
295
|
+
if (shortOptions[keyPath]) {
|
|
296
|
+
optionKeys.push(`-${shortOptions[keyPath]}`);
|
|
297
|
+
}
|
|
283
298
|
|
|
299
|
+
if (typeof keyPathSchema.enum !== 'undefined') {
|
|
300
|
+
description.push(`(${opening}${keyPath}${closing}: ${Object.keys(keyPathSchema.enum).map((value) => `\`${value}\``).join(', ')})`);
|
|
284
301
|
}
|
|
285
302
|
|
|
286
|
-
|
|
287
|
-
.
|
|
303
|
+
if (keyPathSchema.type === Array) {
|
|
304
|
+
description.push(`${strings?.options?.help?.allowsMultiple || '(allows multiple)'}`);
|
|
305
|
+
} else if (keyPathSchema.required === true) {
|
|
306
|
+
description.push(`${strings?.options?.help?.required || '(required)'}`);
|
|
307
|
+
} else if (typeof keyPathSchema.default !== 'undefined') {
|
|
288
308
|
|
|
289
|
-
|
|
309
|
+
let defaultDescription;
|
|
290
310
|
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
311
|
+
if (keyPathSchema.secret === true) {
|
|
312
|
+
defaultDescription = '`********`';
|
|
313
|
+
} else {
|
|
294
314
|
|
|
295
|
-
|
|
315
|
+
if (keyPathSchema.type === Boolean) {
|
|
316
|
+
defaultDescription = keyPathSchema.default === true ? 'enabled' : 'disabled';
|
|
317
|
+
} else {
|
|
318
|
+
defaultDescription = `\`${keyPathSchema.defaultDescription ?? keyPathSchema.default}\``;
|
|
319
|
+
}
|
|
296
320
|
|
|
297
|
-
|
|
298
|
-
option += ` ${strings?.options?.help?.argument || `${opening}${caseit(keyPath, 'kebab')}${closing}`}`;
|
|
299
|
-
}
|
|
321
|
+
}
|
|
300
322
|
|
|
301
|
-
|
|
323
|
+
description.push(`${(strings?.options?.help?.default || '(default: <default>)')
|
|
324
|
+
.replace('<default>', defaultDescription)}`);
|
|
302
325
|
|
|
303
|
-
|
|
326
|
+
}
|
|
304
327
|
|
|
305
|
-
|
|
306
|
-
|
|
328
|
+
if (keyPathSchema.hints?.length) {
|
|
329
|
+
description = description.concat(keyPathSchema.hints);
|
|
330
|
+
}
|
|
307
331
|
|
|
308
|
-
|
|
332
|
+
let option = optionKeys.reverse().join(', ');
|
|
309
333
|
|
|
310
|
-
|
|
311
|
-
|
|
334
|
+
if (keyPathSchema.type !== Boolean) {
|
|
335
|
+
option += ` ${strings?.options?.help?.argument || `${opening}${caseit(keyPath, 'kebab')}${closing}`}`;
|
|
336
|
+
}
|
|
312
337
|
|
|
313
|
-
|
|
338
|
+
return [option, description];
|
|
314
339
|
|
|
315
|
-
|
|
340
|
+
})), true);
|
|
316
341
|
|
|
317
|
-
|
|
318
|
-
rest.push(args[idx]);
|
|
319
|
-
continue;
|
|
342
|
+
};
|
|
320
343
|
}
|
|
321
344
|
|
|
322
|
-
let
|
|
345
|
+
let rest = [];
|
|
323
346
|
|
|
324
|
-
|
|
325
|
-
key = caseit(args[idx].slice(2));
|
|
326
|
-
} else if (shortOptions[key]) {
|
|
327
|
-
key = caseit(shortOptions[key]);
|
|
328
|
-
}
|
|
347
|
+
let idx;
|
|
329
348
|
|
|
330
|
-
|
|
331
|
-
printHelp(
|
|
332
|
-
new Error(
|
|
333
|
-
(strings?.options?.help?.errors?.unknownOption || 'Unknown option: <option>.')
|
|
334
|
-
.replace('<option>', args[idx])));
|
|
335
|
-
}
|
|
349
|
+
for (idx = 0 ; idx < args.length ; idx++) {
|
|
336
350
|
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
value = true;
|
|
341
|
-
} else {
|
|
342
|
-
if (args.length <= idx + 1 || args[idx + 1].slice(0, 2) === '--') {
|
|
343
|
-
printHelp(
|
|
344
|
-
new Error(
|
|
345
|
-
(strings?.options?.help?.errors?.missingArgument || 'Argument missing for option: <option>.')
|
|
346
|
-
.replace('<option>', args[idx])));
|
|
351
|
+
if (args[idx].slice(0, 1) !== '-') {
|
|
352
|
+
rest.push(args[idx]);
|
|
353
|
+
continue;
|
|
347
354
|
}
|
|
348
|
-
value = args[++idx];
|
|
349
|
-
}
|
|
350
355
|
|
|
351
|
-
|
|
352
|
-
data[key] = value;
|
|
353
|
-
} else if (Array.isArray(data[key])) {
|
|
354
|
-
data[key].push(value);
|
|
355
|
-
} else {
|
|
356
|
-
data[key] = [data[key], value];
|
|
357
|
-
}
|
|
356
|
+
let key = args[idx].slice(1);
|
|
358
357
|
|
|
359
|
-
|
|
358
|
+
if (args[idx].slice(1, 2) === '-') {
|
|
359
|
+
key = caseit(args[idx].slice(2));
|
|
360
|
+
} else if (shortOptions[key]) {
|
|
361
|
+
key = caseit(shortOptions[key]);
|
|
362
|
+
}
|
|
360
363
|
|
|
361
|
-
|
|
362
|
-
switch (options.variadic || 'deny') {
|
|
363
|
-
case 'allow':
|
|
364
|
-
break;
|
|
365
|
-
case 'ignore':
|
|
366
|
-
rest = [];
|
|
367
|
-
break;
|
|
368
|
-
default:
|
|
364
|
+
if (!keyPaths(options.schema).all().includes(key)) {
|
|
369
365
|
printHelp(
|
|
370
366
|
new Error(
|
|
371
|
-
(strings?.
|
|
372
|
-
.replace('<
|
|
373
|
-
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
try {
|
|
377
|
-
data = await isvalid(data, schema, {
|
|
378
|
-
aggregatedErrors: 'flatten'
|
|
379
|
-
});
|
|
380
|
-
} catch (error) {
|
|
381
|
-
let message = error.message;
|
|
382
|
-
if (error.keyPath?.[0]) {
|
|
383
|
-
message = `${caseit(error.keyPath[0], 'kebab')}: ${message}`;
|
|
384
|
-
}
|
|
385
|
-
printHelp(new Error(message));
|
|
386
|
-
}
|
|
387
|
-
|
|
388
|
-
return Object.assign({}, data, {
|
|
389
|
-
onError: (error) => {
|
|
390
|
-
print.err(error.message);
|
|
391
|
-
process.exit(1);
|
|
392
|
-
},
|
|
393
|
-
rest,
|
|
394
|
-
nonOptions
|
|
395
|
-
});
|
|
396
|
-
|
|
397
|
-
},
|
|
398
|
-
empty: async () => {
|
|
399
|
-
|
|
400
|
-
checkHelp();
|
|
401
|
-
|
|
402
|
-
if (args.length > 0) {
|
|
403
|
-
printHelp(
|
|
404
|
-
new Error(
|
|
405
|
-
(strings?.empty?.help?.errors?.unexpected || 'Unexpected argument: <argument>.')
|
|
406
|
-
.replace('<argument>', args[0])));
|
|
407
|
-
}
|
|
408
|
-
|
|
409
|
-
},
|
|
410
|
-
values: async (schema) => {
|
|
411
|
-
|
|
412
|
-
schema = formalize(schema);
|
|
413
|
-
|
|
414
|
-
if (schema.type !== Object) {
|
|
415
|
-
throw new Error('Schema must be an object.');
|
|
416
|
-
}
|
|
417
|
-
|
|
418
|
-
const schemaKeyPaths = keyPaths(schema);
|
|
419
|
-
|
|
420
|
-
const allKeyPaths = schemaKeyPaths.all({ maxDepth: 2 })
|
|
421
|
-
.filter((keyPath) => keyPath);
|
|
422
|
-
|
|
423
|
-
let lastNonRequiredIndex = -1;
|
|
367
|
+
(strings?.options?.help?.errors?.unknownOption || 'Unknown option: <option>.')
|
|
368
|
+
.replace('<option>', args[idx])));
|
|
369
|
+
}
|
|
424
370
|
|
|
425
|
-
|
|
426
|
-
.forEach((keyPath, idx) => {
|
|
371
|
+
let value;
|
|
427
372
|
|
|
428
|
-
|
|
373
|
+
if (keyPaths(options.schema).get(key).type === Boolean) {
|
|
374
|
+
value = true;
|
|
375
|
+
} else {
|
|
376
|
+
if (args.length <= idx + 1 || args[idx + 1].slice(0, 2) === '--') {
|
|
377
|
+
printHelp(
|
|
378
|
+
new Error(
|
|
379
|
+
(strings?.options?.help?.errors?.missingArgument || 'Argument missing for option: <option>.')
|
|
380
|
+
.replace('<option>', args[idx])));
|
|
381
|
+
}
|
|
382
|
+
value = args[++idx];
|
|
383
|
+
}
|
|
429
384
|
|
|
430
|
-
if (
|
|
431
|
-
|
|
385
|
+
if (typeof options.data[key] === 'undefined') {
|
|
386
|
+
options.data[key] = value;
|
|
387
|
+
} else if (Array.isArray(options.data[key])) {
|
|
388
|
+
options.data[key].push(value);
|
|
389
|
+
} else {
|
|
390
|
+
options.data[key] = [options.data[key], value];
|
|
432
391
|
}
|
|
433
392
|
|
|
434
|
-
|
|
435
|
-
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
if (rest.length) {
|
|
396
|
+
switch (options.validationOptions.variadic || 'deny') {
|
|
397
|
+
case 'allow':
|
|
398
|
+
break;
|
|
399
|
+
case 'ignore':
|
|
400
|
+
rest = [];
|
|
401
|
+
break;
|
|
402
|
+
default:
|
|
403
|
+
printHelp(
|
|
404
|
+
new Error(
|
|
405
|
+
(strings?.empty?.help?.errors?.unexpected || 'Unexpected argument: <argument>.')
|
|
406
|
+
.replace('<argument>', args[0])));
|
|
436
407
|
}
|
|
408
|
+
}
|
|
437
409
|
|
|
438
|
-
|
|
410
|
+
if (args.length > 0) {
|
|
411
|
+
printHelp(
|
|
412
|
+
new Error(
|
|
413
|
+
(strings?.empty?.help?.errors?.unexpected || 'Unexpected argument: <argument>.')
|
|
414
|
+
.replace('<argument>', args[0])));
|
|
415
|
+
}
|
|
439
416
|
|
|
440
|
-
}
|
|
417
|
+
let data = {};
|
|
441
418
|
|
|
442
|
-
|
|
419
|
+
try {
|
|
420
|
+
data = await isvalid(options.data, options.schema, {
|
|
421
|
+
aggregatedErrors: 'flatten'
|
|
422
|
+
});
|
|
423
|
+
} catch (error) {
|
|
424
|
+
printHelp(error);
|
|
425
|
+
}
|
|
443
426
|
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
427
|
+
return Object.assign({}, data, {
|
|
428
|
+
onError: (error) => {
|
|
429
|
+
print.err(error.message);
|
|
430
|
+
process.exit(1);
|
|
431
|
+
},
|
|
432
|
+
rest,
|
|
433
|
+
nonOptions
|
|
434
|
+
});
|
|
450
435
|
|
|
451
|
-
|
|
452
|
-
help(error) {
|
|
453
|
-
printHelp(error);
|
|
436
|
+
})().then(...resultArguments);
|
|
454
437
|
}
|
|
455
438
|
};
|
|
456
439
|
|
|
457
|
-
result.then = (...args) => {
|
|
458
|
-
return result.empty().then(...args);
|
|
459
|
-
};
|
|
460
|
-
|
|
461
440
|
return result;
|
|
462
441
|
|
|
463
442
|
};
|