Initial commit
This commit is contained in:
261
skills/yargs-patterns/SKILL.md
Normal file
261
skills/yargs-patterns/SKILL.md
Normal file
@@ -0,0 +1,261 @@
|
||||
---
|
||||
name: yargs-patterns
|
||||
description: Advanced yargs patterns for Node.js CLI argument parsing with subcommands, options, middleware, and validation
|
||||
tags: [nodejs, cli, yargs, argument-parsing, validation]
|
||||
---
|
||||
|
||||
# yargs Patterns Skill
|
||||
|
||||
Comprehensive patterns and templates for building CLI applications with yargs, the modern Node.js argument parsing library.
|
||||
|
||||
## Overview
|
||||
|
||||
yargs is a powerful argument parsing library for Node.js that provides:
|
||||
- Automatic help generation
|
||||
- Rich command syntax (positional args, options, flags)
|
||||
- Type coercion and validation
|
||||
- Subcommands with isolated option namespaces
|
||||
- Middleware for preprocessing
|
||||
- Completion scripts for bash/zsh
|
||||
|
||||
## Quick Reference
|
||||
|
||||
### Basic Setup
|
||||
|
||||
```javascript
|
||||
#!/usr/bin/env node
|
||||
const yargs = require('yargs/yargs');
|
||||
const { hideBin } = require('yargs/helpers');
|
||||
|
||||
yargs(hideBin(process.argv))
|
||||
.command('* <name>', 'greet someone', (yargs) => {
|
||||
yargs.positional('name', {
|
||||
describe: 'Name to greet',
|
||||
type: 'string'
|
||||
});
|
||||
}, (argv) => {
|
||||
console.log(`Hello, ${argv.name}!`);
|
||||
})
|
||||
.parse();
|
||||
```
|
||||
|
||||
### Subcommands
|
||||
|
||||
```javascript
|
||||
yargs(hideBin(process.argv))
|
||||
.command('init <project>', 'initialize a new project', (yargs) => {
|
||||
yargs
|
||||
.positional('project', {
|
||||
describe: 'Project name',
|
||||
type: 'string'
|
||||
})
|
||||
.option('template', {
|
||||
alias: 't',
|
||||
describe: 'Project template',
|
||||
choices: ['basic', 'advanced', 'minimal'],
|
||||
default: 'basic'
|
||||
});
|
||||
}, (argv) => {
|
||||
console.log(`Initializing ${argv.project} with ${argv.template} template`);
|
||||
})
|
||||
.command('build [entry]', 'build the project', (yargs) => {
|
||||
yargs
|
||||
.positional('entry', {
|
||||
describe: 'Entry point file',
|
||||
type: 'string',
|
||||
default: 'index.js'
|
||||
})
|
||||
.option('output', {
|
||||
alias: 'o',
|
||||
describe: 'Output directory',
|
||||
type: 'string',
|
||||
default: 'dist'
|
||||
})
|
||||
.option('minify', {
|
||||
describe: 'Minify output',
|
||||
type: 'boolean',
|
||||
default: false
|
||||
});
|
||||
}, (argv) => {
|
||||
console.log(`Building from ${argv.entry} to ${argv.output}`);
|
||||
})
|
||||
.parse();
|
||||
```
|
||||
|
||||
### Options and Flags
|
||||
|
||||
```javascript
|
||||
yargs(hideBin(process.argv))
|
||||
.option('verbose', {
|
||||
alias: 'v',
|
||||
type: 'boolean',
|
||||
description: 'Run with verbose logging',
|
||||
default: false
|
||||
})
|
||||
.option('config', {
|
||||
alias: 'c',
|
||||
type: 'string',
|
||||
description: 'Path to config file',
|
||||
demandOption: true // Required option
|
||||
})
|
||||
.option('port', {
|
||||
alias: 'p',
|
||||
type: 'number',
|
||||
description: 'Port number',
|
||||
default: 3000
|
||||
})
|
||||
.option('env', {
|
||||
alias: 'e',
|
||||
type: 'string',
|
||||
choices: ['development', 'staging', 'production'],
|
||||
description: 'Environment'
|
||||
})
|
||||
.parse();
|
||||
```
|
||||
|
||||
### Validation
|
||||
|
||||
```javascript
|
||||
yargs(hideBin(process.argv))
|
||||
.command('deploy <service>', 'deploy a service', (yargs) => {
|
||||
yargs
|
||||
.positional('service', {
|
||||
describe: 'Service name',
|
||||
type: 'string'
|
||||
})
|
||||
.option('version', {
|
||||
describe: 'Version to deploy',
|
||||
type: 'string',
|
||||
coerce: (arg) => {
|
||||
// Custom validation
|
||||
if (!/^\d+\.\d+\.\d+$/.test(arg)) {
|
||||
throw new Error('Version must be in format X.Y.Z');
|
||||
}
|
||||
return arg;
|
||||
}
|
||||
})
|
||||
.option('replicas', {
|
||||
describe: 'Number of replicas',
|
||||
type: 'number',
|
||||
default: 1
|
||||
})
|
||||
.check((argv) => {
|
||||
// Cross-field validation
|
||||
if (argv.replicas > 10 && argv.env === 'development') {
|
||||
throw new Error('Cannot deploy more than 10 replicas in development');
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}, (argv) => {
|
||||
console.log(`Deploying ${argv.service} v${argv.version} with ${argv.replicas} replicas`);
|
||||
})
|
||||
.parse();
|
||||
```
|
||||
|
||||
### Middleware
|
||||
|
||||
```javascript
|
||||
yargs(hideBin(process.argv))
|
||||
.middleware((argv) => {
|
||||
// Preprocessing middleware
|
||||
if (argv.verbose) {
|
||||
console.log('Running in verbose mode');
|
||||
console.log('Arguments:', argv);
|
||||
}
|
||||
})
|
||||
.middleware((argv) => {
|
||||
// Load config file
|
||||
if (argv.config) {
|
||||
const config = require(path.resolve(argv.config));
|
||||
return { ...argv, ...config };
|
||||
}
|
||||
})
|
||||
.command('run', 'run the application', {}, (argv) => {
|
||||
console.log('Application running with config:', argv);
|
||||
})
|
||||
.parse();
|
||||
```
|
||||
|
||||
### Advanced Features
|
||||
|
||||
#### Conflicts and Implies
|
||||
|
||||
```javascript
|
||||
yargs(hideBin(process.argv))
|
||||
.option('json', {
|
||||
describe: 'Output as JSON',
|
||||
type: 'boolean'
|
||||
})
|
||||
.option('yaml', {
|
||||
describe: 'Output as YAML',
|
||||
type: 'boolean'
|
||||
})
|
||||
.conflicts('json', 'yaml') // Can't use both
|
||||
.option('output', {
|
||||
describe: 'Output file',
|
||||
type: 'string'
|
||||
})
|
||||
.option('format', {
|
||||
describe: 'Output format',
|
||||
choices: ['json', 'yaml'],
|
||||
implies: 'output' // format requires output
|
||||
})
|
||||
.parse();
|
||||
```
|
||||
|
||||
#### Array Options
|
||||
|
||||
```javascript
|
||||
yargs(hideBin(process.argv))
|
||||
.option('include', {
|
||||
describe: 'Files to include',
|
||||
type: 'array',
|
||||
default: []
|
||||
})
|
||||
.option('exclude', {
|
||||
describe: 'Files to exclude',
|
||||
type: 'array',
|
||||
default: []
|
||||
})
|
||||
.parse();
|
||||
|
||||
// Usage: cli --include file1.js file2.js --exclude test.js
|
||||
```
|
||||
|
||||
#### Count Options
|
||||
|
||||
```javascript
|
||||
yargs(hideBin(process.argv))
|
||||
.option('verbose', {
|
||||
alias: 'v',
|
||||
describe: 'Verbosity level',
|
||||
type: 'count' // -v, -vv, -vvv
|
||||
})
|
||||
.parse();
|
||||
```
|
||||
|
||||
## Templates
|
||||
|
||||
See `templates/` directory for:
|
||||
- `basic-cli.js` - Simple CLI with commands
|
||||
- `advanced-cli.js` - Full-featured CLI with validation
|
||||
- `config-cli.js` - CLI with configuration file support
|
||||
- `interactive-cli.js` - CLI with prompts
|
||||
- `plugin-cli.js` - Plugin-based CLI architecture
|
||||
|
||||
## Scripts
|
||||
|
||||
See `scripts/` directory for:
|
||||
- `generate-completion.sh` - Generate bash/zsh completion
|
||||
- `validate-args.js` - Argument validation helper
|
||||
- `test-cli.sh` - CLI testing script
|
||||
|
||||
## Examples
|
||||
|
||||
See `examples/` directory for complete working examples.
|
||||
|
||||
## Resources
|
||||
|
||||
- [yargs Documentation](https://yargs.js.org/)
|
||||
- [yargs GitHub](https://github.com/yargs/yargs)
|
||||
- [yargs Best Practices](https://github.com/yargs/yargs/blob/main/docs/tricks.md)
|
||||
Reference in New Issue
Block a user