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