@vexify-org/yaggs 3.2.0 → 5.0.0

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 (3) hide show
  1. package/index.js +12 -0
  2. package/lib/parser.js +76 -15
  3. package/package.json +1 -1
package/index.js CHANGED
@@ -133,6 +133,18 @@ class Yaggs {
133
133
  return this;
134
134
  }
135
135
 
136
+ env(name, envVar) {
137
+ if (this.parser.options[name]) {
138
+ this.parser.options[name].env = envVar;
139
+ }
140
+ return this;
141
+ }
142
+
143
+ config(filePath) {
144
+ this.parser.loadConfig(filePath);
145
+ return this;
146
+ }
147
+
136
148
  parse(argv = process.argv.slice(2)) {
137
149
  const result = this.parser.parse(argv);
138
150
 
package/lib/parser.js CHANGED
@@ -12,6 +12,8 @@ class ArgumentParser {
12
12
  this.scriptName = options.scriptName || process.argv[1] || 'yaggs';
13
13
  this.helpFunction = options.helpFunction || null;
14
14
  this.errorHandler = options.errorHandler || null;
15
+ this.configFile = options.configFile || null;
16
+ this.config = {};
15
17
  }
16
18
 
17
19
  option(name, config) {
@@ -87,12 +89,37 @@ class ArgumentParser {
87
89
  aliases: config.aliases || [],
88
90
  hidden: config.hidden || false,
89
91
  strict: config.strict || false,
92
+ group: config.group || 'Commands',
90
93
  ...config
91
94
  };
92
95
 
93
96
  return this;
94
97
  }
95
98
 
99
+ loadConfig(filePath) {
100
+ const fs = require('fs');
101
+ const path = require('path');
102
+
103
+ try {
104
+ const fullPath = path.resolve(filePath);
105
+ if (!fs.existsSync(fullPath)) {
106
+ return this;
107
+ }
108
+
109
+ const ext = path.extname(filePath).toLowerCase();
110
+ if (ext === '.json') {
111
+ this.config = JSON.parse(fs.readFileSync(fullPath, 'utf8'));
112
+ } else if (ext === '.js') {
113
+ this.config = require(fullPath);
114
+ }
115
+
116
+ return this;
117
+ } catch (error) {
118
+ this._handleError(`Failed to load config file: ${error.message}`);
119
+ return this;
120
+ }
121
+ }
122
+
96
123
  parse(argv = process.argv.slice(2)) {
97
124
  const result = {
98
125
  _: [],
@@ -138,7 +165,7 @@ class ArgumentParser {
138
165
  const arg = argv[i];
139
166
 
140
167
  if (inOption) {
141
- if (arg.startsWith('-') || this.commands[arg]) {
168
+ if (arg.startsWith('-') || this.commands[arg] || this._resolveCommandAlias(arg)) {
142
169
  this._assignOption(result, inOption, optionAccumulator);
143
170
  inOption = null;
144
171
  optionAccumulator = [];
@@ -235,9 +262,10 @@ class ArgumentParser {
235
262
  }
236
263
  }
237
264
  } else {
238
- if (!currentCommand && this.commands[arg]) {
239
- currentCommand = arg;
240
- commandChain.push(arg);
265
+ if (!currentCommand && (this.commands[arg] || this._resolveCommandAlias(arg))) {
266
+ const resolvedCommand = this._resolveCommandAlias(arg) || arg;
267
+ currentCommand = resolvedCommand;
268
+ commandChain.push(resolvedCommand);
241
269
  } else {
242
270
  result._.push(arg);
243
271
  }
@@ -276,6 +304,12 @@ class ArgumentParser {
276
304
  }
277
305
  }
278
306
 
307
+ for (const [key, value] of Object.entries(this.config)) {
308
+ if (result[key] === undefined) {
309
+ result[key] = value;
310
+ }
311
+ }
312
+
279
313
  this._applyTypeConversion(result);
280
314
  this._validateOptions(result);
281
315
  this._validatePositionals(result);
@@ -296,6 +330,13 @@ class ArgumentParser {
296
330
  return;
297
331
  }
298
332
 
333
+ if (opt.env && !result[name]) {
334
+ const envValue = process.env[opt.env];
335
+ if (envValue !== undefined) {
336
+ result[name] = envValue;
337
+ }
338
+ }
339
+
299
340
  if (opt.array) {
300
341
  if (!result[name]) result[name] = [];
301
342
  result[name].push(...values);
@@ -421,6 +462,15 @@ class ArgumentParser {
421
462
  }
422
463
  }
423
464
 
465
+ _resolveCommandAlias(arg) {
466
+ for (const [name, cmd] of Object.entries(this.commands)) {
467
+ if (cmd.aliases && cmd.aliases.includes(arg)) {
468
+ return name;
469
+ }
470
+ }
471
+ return null;
472
+ }
473
+
424
474
  getHelp() {
425
475
  let help = `\u001b[36m${this.scriptName}\u001b[0m`;
426
476
 
@@ -458,21 +508,32 @@ class ArgumentParser {
458
508
 
459
509
  const visibleCommands = Object.entries(this.commands).filter(([, cmd]) => !cmd.hidden);
460
510
  if (visibleCommands.length > 0) {
461
- help += '\n\n\u001b[33mCommands:\u001b[0m';
462
-
463
- const maxLen = Math.max(...visibleCommands.map(([name]) => name.length)) + 4;
464
-
511
+ const groupedCommands = {};
465
512
  for (const [name, cmd] of visibleCommands) {
466
- let line = ` ${name}`;
467
-
468
- if (cmd.aliases && cmd.aliases.length > 0) {
469
- line += ` (${cmd.aliases.join(', ')})`;
513
+ const group = cmd.group || 'Commands';
514
+ if (!groupedCommands[group]) {
515
+ groupedCommands[group] = [];
470
516
  }
517
+ groupedCommands[group].push({ name, cmd });
518
+ }
519
+
520
+ for (const [groupName, commands] of Object.entries(groupedCommands)) {
521
+ help += `\n\n\u001b[33m${groupName}:\u001b[0m`;
471
522
 
472
- line = line.padEnd(maxLen);
473
- line += cmd.description;
523
+ const maxLen = Math.max(...commands.map(({ name }) => name.length)) + 4;
474
524
 
475
- help += `\n${line}`;
525
+ for (const { name, cmd } of commands) {
526
+ let line = ` ${name}`;
527
+
528
+ if (cmd.aliases && cmd.aliases.length > 0) {
529
+ line += ` (${cmd.aliases.join(', ')})`;
530
+ }
531
+
532
+ line = line.padEnd(maxLen);
533
+ line += cmd.description;
534
+
535
+ help += `\n${line}`;
536
+ }
476
537
  }
477
538
  }
478
539
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vexify-org/yaggs",
3
- "version": "3.2.0",
3
+ "version": "5.0.0",
4
4
  "description": "A powerful CLI argument parser, better than yargs",
5
5
  "main": "index.js",
6
6
  "scripts": {