@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.
@@ -0,0 +1,8 @@
1
+ {
2
+ "cSpell.words": [
3
+ "caseit",
4
+ "isvalid",
5
+ "Kristian",
6
+ "trenskow"
7
+ ]
8
+ }
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
 
@@ -114,9 +119,23 @@ const argumentsParser = (
114
119
  }
115
120
 
116
121
  if (error) {
122
+
117
123
  print();
118
- print.bold((strings?.commands?.help?.error || 'Error: <message>')
119
- .replace('<message>', error.message));
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: async (schema, options = { }) => {
213
+ options: (schema, validationOptions = { }) => {
194
214
 
195
- options.command = options.command || command;
215
+ validationOptions.command = validationOptions.command || command;
196
216
 
197
- schema = formalize(schema);
217
+ Object.assign(
218
+ options.validationOptions,
219
+ validationOptions);
198
220
 
199
- let nonOptions;
200
- let nonOptionsIndex = args.indexOf('--');
221
+ options.schema = merge(
222
+ options.schema)
223
+ .with(schema);
201
224
 
202
- if (nonOptionsIndex > -1) {
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
- if (allKeyPaths.length) {
212
- helpUsage.push(`${opening}${strings?.options?.help?.placeholder || 'options'}${closing}`);
213
- }
227
+ },
228
+ help(error) {
229
+ printHelp(error);
230
+ },
231
+ then: (...resultArguments) => {
232
+ return (async () => {
214
233
 
215
- if (typeof options.usage === 'string') {
216
- helpUsage.push(options.usage);
217
- }
234
+ checkHelp();
218
235
 
219
- let shortOptions = {};
236
+ let nonOptions;
237
+ let nonOptionsIndex = args.indexOf('--');
220
238
 
221
- allKeyPaths
222
- .forEach((keyPath) => {
239
+ if (nonOptionsIndex > -1) {
240
+ nonOptions = args.slice(nonOptionsIndex + 1).join(' ');
241
+ args = args.slice(0, nonOptionsIndex);
242
+ }
223
243
 
224
- const keyPathSchema = keyPaths(schema).get(keyPath);
244
+ const allKeyPaths = keyPaths(options.schema)
245
+ .all()
246
+ .filter((keyPath) => keyPath);
225
247
 
226
- if (keyPathSchema.short) {
248
+ if (allKeyPaths.length) {
249
+ helpUsage.push(`${opening}${strings?.options?.help?.placeholder || 'options'}${closing}`);
250
+ }
227
251
 
228
- if (shortOptions[keyPathSchema.short]) {
229
- throw new Error(`Short option "${keyPathSchema.short}" already used.`);
230
- }
252
+ if (typeof options.validationOptions.usage === 'string') {
253
+ helpUsage.push(options.validationOptions.usage);
254
+ }
231
255
 
232
- shortOptions[keyPath] = keyPathSchema.short;
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
- shortOptions = Object.fromEntries(
239
- Object.entries(shortOptions)
240
- .map(([key, value]) => [value, key]));
263
+ if (keyPathSchema.short) {
241
264
 
242
- if (allKeyPaths.length) {
265
+ if (shortOptions[keyPathSchema.short]) {
266
+ throw new Error(`Short option "${keyPathSchema.short}" already used.`);
267
+ }
243
268
 
244
- helpOptions = () => {
269
+ shortOptions[keyPath] = keyPathSchema.short;
245
270
 
246
- print();
247
- print(strings?.options?.help?.title || 'Options:');
248
- print();
271
+ }
249
272
 
250
- list(print, Object.fromEntries(allKeyPaths
251
- .map((keyPath) => {
273
+ });
252
274
 
253
- const keyPathSchema = keyPaths(schema).get(keyPath);
275
+ shortOptions = Object.fromEntries(
276
+ Object.entries(shortOptions)
277
+ .map(([key, value]) => [value, key]));
254
278
 
255
- let optionKeys = [`--${caseit(keyPath, 'kebab')}`];
256
- let description = [keyPathSchema.description || 'No description'];
279
+ if (allKeyPaths.length) {
257
280
 
258
- if (shortOptions[keyPath]) {
259
- optionKeys.push(`-${shortOptions[keyPath]}`);
260
- }
281
+ helpOptions = () => {
261
282
 
262
- if (typeof keyPathSchema.enum !== 'undefined') {
263
- description.push(`(${opening}${keyPath}${closing}: ${Object.keys(keyPathSchema.enum).map((value) => `\`${value}\``).join(', ')})`);
264
- }
283
+ print();
284
+ print(strings?.options?.help?.title || 'Options:');
285
+ print();
265
286
 
266
- if (keyPathSchema.type === Array) {
267
- description.push(`${strings?.options?.help?.allowsMultple || '(allows multiple)'}`);
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
- let defaultDescription;
290
+ const keyPathSchema = keyPaths(options.schema).get(keyPath);
273
291
 
274
- if (keyPathSchema.secret === true) {
275
- defaultDescription = '`********`';
276
- } else {
292
+ let optionKeys = [`--${caseit(keyPath, 'kebab')}`];
293
+ let description = [keyPathSchema.description || 'No description'];
277
294
 
278
- if (keyPathSchema.type === Boolean) {
279
- defaultDescription = keyPathSchema.default === true ? 'enabled' : 'disabled';
280
- } else {
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
- description.push(`${(strings?.options?.help?.default || '(default: <default>)')
287
- .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') {
288
308
 
289
- }
309
+ let defaultDescription;
290
310
 
291
- if (keyPathSchema.hints?.length) {
292
- description = description.concat(keyPathSchema.hints);
293
- }
311
+ if (keyPathSchema.secret === true) {
312
+ defaultDescription = '`********`';
313
+ } else {
294
314
 
295
- 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
+ }
296
320
 
297
- if (keyPathSchema.type !== Boolean) {
298
- option += ` ${strings?.options?.help?.argument || `${opening}${caseit(keyPath, 'kebab')}${closing}`}`;
299
- }
321
+ }
300
322
 
301
- return [option, description];
323
+ description.push(`${(strings?.options?.help?.default || '(default: <default>)')
324
+ .replace('<default>', defaultDescription)}`);
302
325
 
303
- })), true);
326
+ }
304
327
 
305
- };
306
- }
328
+ if (keyPathSchema.hints?.length) {
329
+ description = description.concat(keyPathSchema.hints);
330
+ }
307
331
 
308
- checkHelp();
332
+ let option = optionKeys.reverse().join(', ');
309
333
 
310
- let data = {};
311
- let rest = [];
334
+ if (keyPathSchema.type !== Boolean) {
335
+ option += ` ${strings?.options?.help?.argument || `${opening}${caseit(keyPath, 'kebab')}${closing}`}`;
336
+ }
312
337
 
313
- let idx;
338
+ return [option, description];
314
339
 
315
- for (idx = 0 ; idx < args.length ; idx++) {
340
+ })), true);
316
341
 
317
- if (args[idx].slice(0, 1) !== '-') {
318
- rest.push(args[idx]);
319
- continue;
342
+ };
320
343
  }
321
344
 
322
- let key = args[idx].slice(1);
345
+ let rest = [];
323
346
 
324
- if (args[idx].slice(1, 2) === '-') {
325
- key = caseit(args[idx].slice(2));
326
- } else if (shortOptions[key]) {
327
- key = caseit(shortOptions[key]);
328
- }
347
+ let idx;
329
348
 
330
- if (!keyPaths(schema).all().includes(key)) {
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
- let value;
338
-
339
- if (keyPaths(schema).get(key).type === Boolean) {
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
- if (typeof data[key] === 'undefined') {
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
- if (rest.length) {
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?.empty?.help?.errors?.unexpected || 'Unexpected argument: <argument>.')
372
- .replace('<argument>', args[0])));
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
- allKeyPaths
426
- .forEach((keyPath, idx) => {
371
+ let value;
427
372
 
428
- 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
+ }
429
384
 
430
- if (schema.required && idx > lastNonRequiredIndex + 1) {
431
- 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];
432
391
  }
433
392
 
434
- if (schema.type !== String) {
435
- 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])));
436
407
  }
408
+ }
437
409
 
438
- 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
+ }
439
416
 
440
- });
417
+ let data = {};
441
418
 
442
- checkHelp();
419
+ try {
420
+ data = await isvalid(options.data, options.schema, {
421
+ aggregatedErrors: 'flatten'
422
+ });
423
+ } catch (error) {
424
+ printHelp(error);
425
+ }
443
426
 
444
- try {
445
- return await isvalid(Object.fromEntries(
446
- allKeyPaths.map((keyPath, idx) => [keyPath, args[idx]])), schema);
447
- } catch (error) {
448
- return printHelp(error);
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
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trenskow/arguments-parser",
3
- "version": "0.3.85",
3
+ "version": "0.3.87",
4
4
  "description": "Yet another arguments parser.",
5
5
  "main": "index.js",
6
6
  "type": "module",