@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.
Files changed (2) hide show
  1. package/lib/index.js +169 -200
  2. 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, keyPaths, formalize, plugins } from '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: async (schema, options = { }) => {
208
-
209
- options.command = options.command || command;
213
+ options: (schema, validationOptions = { }) => {
210
214
 
211
- schema = formalize(schema);
215
+ validationOptions.command = validationOptions.command || command;
212
216
 
213
- let nonOptions;
214
- let nonOptionsIndex = args.indexOf('--');
217
+ Object.assign(
218
+ options.validationOptions,
219
+ validationOptions);
215
220
 
216
- if (nonOptionsIndex > -1) {
217
- nonOptions = args.slice(nonOptionsIndex + 1).join(' ');
218
- args = args.slice(0, nonOptionsIndex);
219
- }
221
+ options.schema = merge(
222
+ options.schema)
223
+ .with(schema);
220
224
 
221
- const allKeyPaths = keyPaths(schema)
222
- .all()
223
- .filter((keyPath) => keyPath);
225
+ return result;
224
226
 
225
- if (allKeyPaths.length) {
226
- helpUsage.push(`${opening}${strings?.options?.help?.placeholder || 'options'}${closing}`);
227
- }
227
+ },
228
+ help(error) {
229
+ printHelp(error);
230
+ },
231
+ then: (...resultArguments) => {
232
+ return (async () => {
228
233
 
229
- if (typeof options.usage === 'string') {
230
- helpUsage.push(options.usage);
231
- }
234
+ checkHelp();
232
235
 
233
- let shortOptions = {};
236
+ let nonOptions;
237
+ let nonOptionsIndex = args.indexOf('--');
234
238
 
235
- allKeyPaths
236
- .forEach((keyPath) => {
239
+ if (nonOptionsIndex > -1) {
240
+ nonOptions = args.slice(nonOptionsIndex + 1).join(' ');
241
+ args = args.slice(0, nonOptionsIndex);
242
+ }
237
243
 
238
- const keyPathSchema = keyPaths(schema).get(keyPath);
244
+ const allKeyPaths = keyPaths(options.schema)
245
+ .all()
246
+ .filter((keyPath) => keyPath);
239
247
 
240
- if (keyPathSchema.short) {
248
+ if (allKeyPaths.length) {
249
+ helpUsage.push(`${opening}${strings?.options?.help?.placeholder || 'options'}${closing}`);
250
+ }
241
251
 
242
- if (shortOptions[keyPathSchema.short]) {
243
- throw new Error(`Short option "${keyPathSchema.short}" already used.`);
244
- }
252
+ if (typeof options.validationOptions.usage === 'string') {
253
+ helpUsage.push(options.validationOptions.usage);
254
+ }
245
255
 
246
- shortOptions[keyPath] = keyPathSchema.short;
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
- shortOptions = Object.fromEntries(
253
- Object.entries(shortOptions)
254
- .map(([key, value]) => [value, key]));
263
+ if (keyPathSchema.short) {
255
264
 
256
- if (allKeyPaths.length) {
265
+ if (shortOptions[keyPathSchema.short]) {
266
+ throw new Error(`Short option "${keyPathSchema.short}" already used.`);
267
+ }
257
268
 
258
- helpOptions = () => {
269
+ shortOptions[keyPath] = keyPathSchema.short;
259
270
 
260
- print();
261
- print(strings?.options?.help?.title || 'Options:');
262
- print();
271
+ }
263
272
 
264
- list(print, Object.fromEntries(allKeyPaths
265
- .map((keyPath) => {
273
+ });
266
274
 
267
- const keyPathSchema = keyPaths(schema).get(keyPath);
275
+ shortOptions = Object.fromEntries(
276
+ Object.entries(shortOptions)
277
+ .map(([key, value]) => [value, key]));
268
278
 
269
- let optionKeys = [`--${caseit(keyPath, 'kebab')}`];
270
- let description = [keyPathSchema.description || 'No description'];
279
+ if (allKeyPaths.length) {
271
280
 
272
- if (shortOptions[keyPath]) {
273
- optionKeys.push(`-${shortOptions[keyPath]}`);
274
- }
281
+ helpOptions = () => {
275
282
 
276
- if (typeof keyPathSchema.enum !== 'undefined') {
277
- description.push(`(${opening}${keyPath}${closing}: ${Object.keys(keyPathSchema.enum).map((value) => `\`${value}\``).join(', ')})`);
278
- }
283
+ print();
284
+ print(strings?.options?.help?.title || 'Options:');
285
+ print();
279
286
 
280
- if (keyPathSchema.type === Array) {
281
- description.push(`${strings?.options?.help?.allowsMultiple || '(allows multiple)'}`);
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
- let defaultDescription;
290
+ const keyPathSchema = keyPaths(options.schema).get(keyPath);
287
291
 
288
- if (keyPathSchema.secret === true) {
289
- defaultDescription = '`********`';
290
- } else {
292
+ let optionKeys = [`--${caseit(keyPath, 'kebab')}`];
293
+ let description = [keyPathSchema.description || 'No description'];
291
294
 
292
- if (keyPathSchema.type === Boolean) {
293
- defaultDescription = keyPathSchema.default === true ? 'enabled' : 'disabled';
294
- } else {
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
- description.push(`${(strings?.options?.help?.default || '(default: <default>)')
301
- .replace('<default>', defaultDescription)}`);
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
- if (keyPathSchema.hints?.length) {
306
- description = description.concat(keyPathSchema.hints);
307
- }
311
+ if (keyPathSchema.secret === true) {
312
+ defaultDescription = '`********`';
313
+ } else {
308
314
 
309
- let option = optionKeys.reverse().join(', ');
315
+ if (keyPathSchema.type === Boolean) {
316
+ defaultDescription = keyPathSchema.default === true ? 'enabled' : 'disabled';
317
+ } else {
318
+ defaultDescription = `\`${keyPathSchema.defaultDescription ?? keyPathSchema.default}\``;
319
+ }
310
320
 
311
- if (keyPathSchema.type !== Boolean) {
312
- option += ` ${strings?.options?.help?.argument || `${opening}${caseit(keyPath, 'kebab')}${closing}`}`;
313
- }
321
+ }
314
322
 
315
- return [option, description];
323
+ description.push(`${(strings?.options?.help?.default || '(default: <default>)')
324
+ .replace('<default>', defaultDescription)}`);
316
325
 
317
- })), true);
326
+ }
318
327
 
319
- };
320
- }
328
+ if (keyPathSchema.hints?.length) {
329
+ description = description.concat(keyPathSchema.hints);
330
+ }
321
331
 
322
- checkHelp();
332
+ let option = optionKeys.reverse().join(', ');
323
333
 
324
- let data = {};
325
- let rest = [];
334
+ if (keyPathSchema.type !== Boolean) {
335
+ option += ` ${strings?.options?.help?.argument || `${opening}${caseit(keyPath, 'kebab')}${closing}`}`;
336
+ }
326
337
 
327
- let idx;
338
+ return [option, description];
328
339
 
329
- for (idx = 0 ; idx < args.length ; idx++) {
340
+ })), true);
330
341
 
331
- if (args[idx].slice(0, 1) !== '-') {
332
- rest.push(args[idx]);
333
- continue;
342
+ };
334
343
  }
335
344
 
336
- let key = args[idx].slice(1);
345
+ let rest = [];
337
346
 
338
- if (args[idx].slice(1, 2) === '-') {
339
- key = caseit(args[idx].slice(2));
340
- } else if (shortOptions[key]) {
341
- key = caseit(shortOptions[key]);
342
- }
347
+ let idx;
343
348
 
344
- if (!keyPaths(schema).all().includes(key)) {
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
- if (keyPaths(schema).get(key).type === Boolean) {
354
- value = true;
355
- } else {
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
- if (typeof data[key] === 'undefined') {
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
- if (rest.length) {
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?.empty?.help?.errors?.unexpected || 'Unexpected argument: <argument>.')
386
- .replace('<argument>', args[0])));
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
- allKeyPaths
436
- .forEach((keyPath, idx) => {
371
+ let value;
437
372
 
438
- const schema = schemaKeyPaths.get(keyPath);
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 (schema.required && idx > lastNonRequiredIndex + 1) {
441
- throw new Error('Required arguments must come first.');
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
- if (schema.type !== String) {
445
- throw new Error('Schema must be an object of strings.');
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
- helpUsage = helpUsage.concat([`${opening}${caseit(keyPath, 'kebab')}${closing}`]);
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
- checkHelp();
419
+ try {
420
+ data = await isvalid(options.data, options.schema, {
421
+ aggregatedErrors: 'flatten'
422
+ });
423
+ } catch (error) {
424
+ printHelp(error);
425
+ }
453
426
 
454
- try {
455
- return await isvalid(Object.fromEntries(
456
- allKeyPaths.map((keyPath, idx) => [keyPath, args[idx]])), schema);
457
- } catch (error) {
458
- return printHelp(error);
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
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trenskow/arguments-parser",
3
- "version": "0.3.86",
3
+ "version": "0.3.87",
4
4
  "description": "Yet another arguments parser.",
5
5
  "main": "index.js",
6
6
  "type": "module",