Initial commit
This commit is contained in:
513
skills/commander-patterns/examples/advanced-option-class.md
Normal file
513
skills/commander-patterns/examples/advanced-option-class.md
Normal file
@@ -0,0 +1,513 @@
|
||||
# Advanced Option Class Usage
|
||||
|
||||
Comprehensive examples of the Option class for advanced option handling.
|
||||
|
||||
## Basic Option Class
|
||||
|
||||
```typescript
|
||||
import { Command, Option } from 'commander';
|
||||
|
||||
const program = new Command();
|
||||
|
||||
program
|
||||
.command('deploy')
|
||||
.addOption(
|
||||
new Option('-e, --env <environment>', 'target environment')
|
||||
.choices(['dev', 'staging', 'prod'])
|
||||
.default('dev')
|
||||
)
|
||||
.action((options) => {
|
||||
console.log('Environment:', options.env);
|
||||
});
|
||||
|
||||
program.parse();
|
||||
```
|
||||
|
||||
## Option with Choices
|
||||
|
||||
```typescript
|
||||
import { Command, Option } from 'commander';
|
||||
|
||||
program
|
||||
.command('log')
|
||||
.addOption(
|
||||
new Option('-l, --level <level>', 'log level')
|
||||
.choices(['debug', 'info', 'warn', 'error'])
|
||||
.default('info')
|
||||
)
|
||||
.addOption(
|
||||
new Option('-f, --format <format>', 'output format')
|
||||
.choices(['json', 'yaml', 'table'])
|
||||
.default('table')
|
||||
)
|
||||
.action((options) => {
|
||||
console.log(`Logging at ${options.level} level in ${options.format} format`);
|
||||
});
|
||||
```
|
||||
|
||||
Usage:
|
||||
```bash
|
||||
mycli log --level debug --format json
|
||||
mycli log --level invalid # Error: invalid choice
|
||||
```
|
||||
|
||||
## Mandatory Options
|
||||
|
||||
```typescript
|
||||
import { Command, Option } from 'commander';
|
||||
|
||||
program
|
||||
.command('deploy')
|
||||
.addOption(
|
||||
new Option('-t, --token <token>', 'API token')
|
||||
.makeOptionMandatory()
|
||||
)
|
||||
.addOption(
|
||||
new Option('-e, --env <environment>', 'environment')
|
||||
.choices(['dev', 'staging', 'prod'])
|
||||
.makeOptionMandatory()
|
||||
)
|
||||
.action((options) => {
|
||||
console.log('Deploying with token:', options.token);
|
||||
console.log('Environment:', options.env);
|
||||
});
|
||||
```
|
||||
|
||||
Usage:
|
||||
```bash
|
||||
mycli deploy # Error: required option missing
|
||||
mycli deploy --token abc --env prod # ✓ Works
|
||||
```
|
||||
|
||||
## Options from Environment Variables
|
||||
|
||||
```typescript
|
||||
import { Command, Option } from 'commander';
|
||||
|
||||
program
|
||||
.command('deploy')
|
||||
.addOption(
|
||||
new Option('-t, --token <token>', 'API token')
|
||||
.env('API_TOKEN')
|
||||
.makeOptionMandatory()
|
||||
)
|
||||
.addOption(
|
||||
new Option('-u, --api-url <url>', 'API URL')
|
||||
.env('API_URL')
|
||||
.default('https://api.example.com')
|
||||
)
|
||||
.action((options) => {
|
||||
console.log('Token:', options.token);
|
||||
console.log('API URL:', options.apiUrl);
|
||||
});
|
||||
```
|
||||
|
||||
Usage:
|
||||
```bash
|
||||
export API_TOKEN=abc123
|
||||
export API_URL=https://custom-api.com
|
||||
|
||||
mycli deploy # Uses environment variables
|
||||
mycli deploy --token xyz # CLI arg overrides env var
|
||||
```
|
||||
|
||||
## Custom Argument Parsers
|
||||
|
||||
```typescript
|
||||
import { Command, Option } from 'commander';
|
||||
|
||||
program
|
||||
.command('scale')
|
||||
.addOption(
|
||||
new Option('-r, --replicas <count>', 'number of replicas')
|
||||
.argParser((value) => {
|
||||
const count = parseInt(value, 10);
|
||||
if (isNaN(count) || count < 1 || count > 100) {
|
||||
throw new Error('Replicas must be between 1 and 100');
|
||||
}
|
||||
return count;
|
||||
})
|
||||
.default(3)
|
||||
)
|
||||
.addOption(
|
||||
new Option('-m, --memory <size>', 'memory limit')
|
||||
.argParser((value) => {
|
||||
// Parse sizes like "512M", "2G"
|
||||
const match = value.match(/^(\d+)([MG])$/i);
|
||||
if (!match) {
|
||||
throw new Error('Invalid memory format (use 512M or 2G)');
|
||||
}
|
||||
const [, num, unit] = match;
|
||||
const mb = parseInt(num) * (unit.toUpperCase() === 'G' ? 1024 : 1);
|
||||
return mb;
|
||||
})
|
||||
.default(512)
|
||||
)
|
||||
.action((options) => {
|
||||
console.log('Replicas:', options.replicas);
|
||||
console.log('Memory:', options.memory, 'MB');
|
||||
});
|
||||
```
|
||||
|
||||
Usage:
|
||||
```bash
|
||||
mycli scale --replicas 5 --memory 2G
|
||||
# Replicas: 5
|
||||
# Memory: 2048 MB
|
||||
```
|
||||
|
||||
## Conflicting Options
|
||||
|
||||
```typescript
|
||||
import { Command, Option } from 'commander';
|
||||
|
||||
program
|
||||
.command('build')
|
||||
.addOption(
|
||||
new Option('--cache', 'enable caching')
|
||||
.conflicts('noCache')
|
||||
)
|
||||
.addOption(
|
||||
new Option('--no-cache', 'disable caching')
|
||||
.conflicts('cache')
|
||||
)
|
||||
.addOption(
|
||||
new Option('--watch', 'watch mode')
|
||||
.conflicts('production')
|
||||
)
|
||||
.addOption(
|
||||
new Option('--production', 'production build')
|
||||
.conflicts('watch')
|
||||
)
|
||||
.action((options) => {
|
||||
console.log('Cache:', options.cache);
|
||||
console.log('Watch:', options.watch);
|
||||
console.log('Production:', options.production);
|
||||
});
|
||||
```
|
||||
|
||||
Usage:
|
||||
```bash
|
||||
mycli build --cache # ✓ Works
|
||||
mycli build --no-cache # ✓ Works
|
||||
mycli build --cache --no-cache # ✗ Error: conflicting options
|
||||
mycli build --watch --production # ✗ Error: conflicting options
|
||||
```
|
||||
|
||||
## Option Implies
|
||||
|
||||
```typescript
|
||||
import { Command, Option } from 'commander';
|
||||
|
||||
program
|
||||
.command('server')
|
||||
.addOption(
|
||||
new Option('--ssl', 'enable SSL')
|
||||
.implies({ sslCert: './cert.pem', sslKey: './key.pem' })
|
||||
)
|
||||
.addOption(
|
||||
new Option('--ssl-cert <path>', 'SSL certificate path')
|
||||
)
|
||||
.addOption(
|
||||
new Option('--ssl-key <path>', 'SSL key path')
|
||||
)
|
||||
.addOption(
|
||||
new Option('--secure', 'secure mode')
|
||||
.implies({ ssl: true, httpsOnly: true })
|
||||
)
|
||||
.addOption(
|
||||
new Option('--https-only', 'enforce HTTPS')
|
||||
)
|
||||
.action((options) => {
|
||||
console.log('SSL:', options.ssl);
|
||||
console.log('SSL Cert:', options.sslCert);
|
||||
console.log('SSL Key:', options.sslKey);
|
||||
console.log('HTTPS Only:', options.httpsOnly);
|
||||
});
|
||||
```
|
||||
|
||||
Usage:
|
||||
```bash
|
||||
mycli server --ssl
|
||||
# SSL: true
|
||||
# SSL Cert: ./cert.pem
|
||||
# SSL Key: ./key.pem
|
||||
|
||||
mycli server --secure
|
||||
# SSL: true
|
||||
# HTTPS Only: true
|
||||
```
|
||||
|
||||
## Preset Configurations
|
||||
|
||||
```typescript
|
||||
import { Command, Option } from 'commander';
|
||||
|
||||
program
|
||||
.command('deploy')
|
||||
.addOption(
|
||||
new Option('--preset <preset>', 'use preset configuration')
|
||||
.choices(['minimal', 'standard', 'enterprise'])
|
||||
.argParser((value) => {
|
||||
const presets = {
|
||||
minimal: {
|
||||
replicas: 1,
|
||||
memory: '256M',
|
||||
cpu: '0.25',
|
||||
autoScaling: false,
|
||||
},
|
||||
standard: {
|
||||
replicas: 3,
|
||||
memory: '512M',
|
||||
cpu: '0.5',
|
||||
autoScaling: true,
|
||||
},
|
||||
enterprise: {
|
||||
replicas: 10,
|
||||
memory: '2G',
|
||||
cpu: '2',
|
||||
autoScaling: true,
|
||||
loadBalancer: true,
|
||||
monitoring: true,
|
||||
},
|
||||
};
|
||||
return presets[value as keyof typeof presets];
|
||||
})
|
||||
)
|
||||
.action((options) => {
|
||||
if (options.preset) {
|
||||
console.log('Using preset configuration:');
|
||||
console.log(JSON.stringify(options.preset, null, 2));
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
Usage:
|
||||
```bash
|
||||
mycli deploy --preset enterprise
|
||||
# Using preset configuration:
|
||||
# {
|
||||
# "replicas": 10,
|
||||
# "memory": "2G",
|
||||
# "cpu": "2",
|
||||
# "autoScaling": true,
|
||||
# "loadBalancer": true,
|
||||
# "monitoring": true
|
||||
# }
|
||||
```
|
||||
|
||||
## Hidden Options (Debug/Internal)
|
||||
|
||||
```typescript
|
||||
import { Command, Option } from 'commander';
|
||||
|
||||
program
|
||||
.command('build')
|
||||
.option('-p, --production', 'production build')
|
||||
.addOption(
|
||||
new Option('--debug', 'enable debug mode')
|
||||
.hideHelp()
|
||||
)
|
||||
.addOption(
|
||||
new Option('--internal-api', 'use internal API')
|
||||
.hideHelp()
|
||||
.default(false)
|
||||
)
|
||||
.action((options) => {
|
||||
if (options.debug) {
|
||||
console.log('Debug mode enabled');
|
||||
console.log('All options:', options);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
## Complex Validation
|
||||
|
||||
```typescript
|
||||
import { Command, Option } from 'commander';
|
||||
|
||||
program
|
||||
.command('backup')
|
||||
.addOption(
|
||||
new Option('-s, --schedule <cron>', 'backup schedule (cron format)')
|
||||
.argParser((value) => {
|
||||
// Validate cron expression
|
||||
const cronRegex = /^(\*|([0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9])|\*\/([0-9]|1[0-9]|2[0-9]|3[0-9]|4[0-9]|5[0-9])) (\*|([0-9]|1[0-9]|2[0-3])|\*\/([0-9]|1[0-9]|2[0-3])) (\*|([1-9]|1[0-9]|2[0-9]|3[0-1])|\*\/([1-9]|1[0-9]|2[0-9]|3[0-1])) (\*|([1-9]|1[0-2])|\*\/([1-9]|1[0-2])) (\*|([0-6])|\*\/([0-6]))$/;
|
||||
|
||||
if (!cronRegex.test(value)) {
|
||||
throw new Error('Invalid cron expression');
|
||||
}
|
||||
return value;
|
||||
})
|
||||
)
|
||||
.addOption(
|
||||
new Option('-r, --retention <days>', 'backup retention in days')
|
||||
.argParser((value) => {
|
||||
const days = parseInt(value, 10);
|
||||
if (isNaN(days) || days < 1 || days > 365) {
|
||||
throw new Error('Retention must be between 1 and 365 days');
|
||||
}
|
||||
return days;
|
||||
})
|
||||
.default(30)
|
||||
)
|
||||
.action((options) => {
|
||||
console.log('Schedule:', options.schedule);
|
||||
console.log('Retention:', options.retention, 'days');
|
||||
});
|
||||
```
|
||||
|
||||
Usage:
|
||||
```bash
|
||||
mycli backup --schedule "0 2 * * *" --retention 90
|
||||
# Schedule: 0 2 * * *
|
||||
# Retention: 90 days
|
||||
```
|
||||
|
||||
## Cumulative Options
|
||||
|
||||
```typescript
|
||||
import { Command, Option } from 'commander';
|
||||
|
||||
program
|
||||
.command('log')
|
||||
.addOption(
|
||||
new Option('-v, --verbose', 'increase verbosity')
|
||||
.argParser((value, previous) => {
|
||||
return previous + 1;
|
||||
})
|
||||
.default(0)
|
||||
)
|
||||
.action((options) => {
|
||||
console.log('Verbosity level:', options.verbose);
|
||||
// 0 = normal
|
||||
// 1 = verbose (-v)
|
||||
// 2 = very verbose (-vv)
|
||||
// 3 = debug (-vvv)
|
||||
});
|
||||
```
|
||||
|
||||
Usage:
|
||||
```bash
|
||||
mycli log # verbosity: 0
|
||||
mycli log -v # verbosity: 1
|
||||
mycli log -vv # verbosity: 2
|
||||
mycli log -vvv # verbosity: 3
|
||||
```
|
||||
|
||||
## Complete Example
|
||||
|
||||
```typescript
|
||||
#!/usr/bin/env node
|
||||
import { Command, Option } from 'commander';
|
||||
import chalk from 'chalk';
|
||||
|
||||
const program = new Command();
|
||||
|
||||
program
|
||||
.name('deploy-cli')
|
||||
.version('1.0.0');
|
||||
|
||||
program
|
||||
.command('deploy')
|
||||
.description('Deploy application with advanced options')
|
||||
|
||||
// Required with choices
|
||||
.addOption(
|
||||
new Option('-e, --env <environment>', 'deployment environment')
|
||||
.choices(['dev', 'staging', 'prod'])
|
||||
.makeOptionMandatory()
|
||||
)
|
||||
|
||||
// Environment variable with validation
|
||||
.addOption(
|
||||
new Option('-t, --token <token>', 'API token')
|
||||
.env('DEPLOY_TOKEN')
|
||||
.makeOptionMandatory()
|
||||
.argParser((value) => {
|
||||
if (value.length < 32) {
|
||||
throw new Error('Token must be at least 32 characters');
|
||||
}
|
||||
return value;
|
||||
})
|
||||
)
|
||||
|
||||
// Custom parser with unit conversion
|
||||
.addOption(
|
||||
new Option('-m, --memory <size>', 'memory allocation')
|
||||
.argParser((value) => {
|
||||
const match = value.match(/^(\d+)([MG])$/i);
|
||||
if (!match) {
|
||||
throw new Error('Memory must be in format: 512M or 2G');
|
||||
}
|
||||
const [, num, unit] = match;
|
||||
return parseInt(num) * (unit.toUpperCase() === 'G' ? 1024 : 1);
|
||||
})
|
||||
.default(512)
|
||||
)
|
||||
|
||||
// Conflicting options
|
||||
.addOption(
|
||||
new Option('--fast', 'fast deployment (skip tests)')
|
||||
.conflicts('safe')
|
||||
)
|
||||
.addOption(
|
||||
new Option('--safe', 'safe deployment (full tests)')
|
||||
.conflicts('fast')
|
||||
.default(true)
|
||||
)
|
||||
|
||||
// Implies relationship
|
||||
.addOption(
|
||||
new Option('--production-mode', 'enable production optimizations')
|
||||
.implies({ env: 'prod', safe: true, monitoring: true })
|
||||
)
|
||||
.addOption(
|
||||
new Option('--monitoring', 'enable monitoring')
|
||||
)
|
||||
|
||||
// Hidden debug option
|
||||
.addOption(
|
||||
new Option('--debug', 'debug mode')
|
||||
.hideHelp()
|
||||
)
|
||||
|
||||
.action((options) => {
|
||||
console.log(chalk.blue('Deployment Configuration:'));
|
||||
console.log('Environment:', chalk.yellow(options.env));
|
||||
console.log('Token:', options.token ? chalk.green('***set***') : chalk.red('missing'));
|
||||
console.log('Memory:', `${options.memory}MB`);
|
||||
console.log('Mode:', options.fast ? 'fast' : 'safe');
|
||||
console.log('Production Mode:', options.productionMode || false);
|
||||
console.log('Monitoring:', options.monitoring || false);
|
||||
|
||||
if (options.debug) {
|
||||
console.log(chalk.gray('\nDebug - All options:'));
|
||||
console.log(chalk.gray(JSON.stringify(options, null, 2)));
|
||||
}
|
||||
|
||||
console.log(chalk.green('\n✓ Deployment started'));
|
||||
});
|
||||
|
||||
program.parse();
|
||||
```
|
||||
|
||||
Usage:
|
||||
```bash
|
||||
export DEPLOY_TOKEN=abc123xyz789abc123xyz789abc12345
|
||||
|
||||
# Basic deployment
|
||||
deploy-cli deploy --env staging
|
||||
|
||||
# Custom memory
|
||||
deploy-cli deploy --env prod --memory 4G
|
||||
|
||||
# Fast mode
|
||||
deploy-cli deploy --env dev --fast
|
||||
|
||||
# Production mode (implies multiple settings)
|
||||
deploy-cli deploy --production-mode
|
||||
|
||||
# Debug
|
||||
deploy-cli deploy --env dev --debug
|
||||
```
|
||||
284
skills/commander-patterns/examples/basic-usage.md
Normal file
284
skills/commander-patterns/examples/basic-usage.md
Normal file
@@ -0,0 +1,284 @@
|
||||
# Basic Commander.js Usage
|
||||
|
||||
Simple examples demonstrating core Commander.js features.
|
||||
|
||||
## Example 1: Simple CLI with Commands
|
||||
|
||||
```typescript
|
||||
import { Command } from 'commander';
|
||||
|
||||
const program = new Command();
|
||||
|
||||
program
|
||||
.name('mycli')
|
||||
.description('My CLI tool')
|
||||
.version('1.0.0');
|
||||
|
||||
// Command without options
|
||||
program
|
||||
.command('init')
|
||||
.description('Initialize project')
|
||||
.action(() => {
|
||||
console.log('Initializing project...');
|
||||
});
|
||||
|
||||
// Command with options
|
||||
program
|
||||
.command('build')
|
||||
.description('Build project')
|
||||
.option('-w, --watch', 'watch mode')
|
||||
.action((options) => {
|
||||
console.log('Building...');
|
||||
if (options.watch) {
|
||||
console.log('Watch mode enabled');
|
||||
}
|
||||
});
|
||||
|
||||
program.parse();
|
||||
```
|
||||
|
||||
**Usage:**
|
||||
```bash
|
||||
mycli init
|
||||
mycli build
|
||||
mycli build --watch
|
||||
mycli --help
|
||||
mycli --version
|
||||
```
|
||||
|
||||
## Example 2: Command with Arguments
|
||||
|
||||
```typescript
|
||||
import { Command } from 'commander';
|
||||
|
||||
const program = new Command();
|
||||
|
||||
program
|
||||
.name('mycli')
|
||||
.version('1.0.0');
|
||||
|
||||
program
|
||||
.command('greet <name>')
|
||||
.description('Greet someone')
|
||||
.action((name) => {
|
||||
console.log(`Hello, ${name}!`);
|
||||
});
|
||||
|
||||
program
|
||||
.command('add <a> <b>')
|
||||
.description('Add two numbers')
|
||||
.action((a, b) => {
|
||||
const sum = parseInt(a) + parseInt(b);
|
||||
console.log(`${a} + ${b} = ${sum}`);
|
||||
});
|
||||
|
||||
program.parse();
|
||||
```
|
||||
|
||||
**Usage:**
|
||||
```bash
|
||||
mycli greet Alice
|
||||
# Output: Hello, Alice!
|
||||
|
||||
mycli add 5 3
|
||||
# Output: 5 + 3 = 8
|
||||
```
|
||||
|
||||
## Example 3: Options with Different Types
|
||||
|
||||
```typescript
|
||||
import { Command } from 'commander';
|
||||
|
||||
const program = new Command();
|
||||
|
||||
program
|
||||
.name('mycli')
|
||||
.version('1.0.0');
|
||||
|
||||
program
|
||||
.command('serve')
|
||||
.description('Start development server')
|
||||
// Boolean flag
|
||||
.option('-o, --open', 'open browser', false)
|
||||
// Option with value
|
||||
.option('-p, --port <port>', 'port number', '3000')
|
||||
// Option with default
|
||||
.option('-h, --host <host>', 'hostname', 'localhost')
|
||||
// Negatable option
|
||||
.option('--no-color', 'disable colors')
|
||||
.action((options) => {
|
||||
console.log(`Server running at http://${options.host}:${options.port}`);
|
||||
console.log('Open browser:', options.open);
|
||||
console.log('Colors:', options.color);
|
||||
});
|
||||
|
||||
program.parse();
|
||||
```
|
||||
|
||||
**Usage:**
|
||||
```bash
|
||||
mycli serve
|
||||
# Uses defaults
|
||||
|
||||
mycli serve --port 8080
|
||||
# Uses custom port
|
||||
|
||||
mycli serve --open --no-color
|
||||
# Opens browser and disables colors
|
||||
```
|
||||
|
||||
## Example 4: Global Options
|
||||
|
||||
```typescript
|
||||
import { Command } from 'commander';
|
||||
|
||||
const program = new Command();
|
||||
|
||||
program
|
||||
.name('mycli')
|
||||
.version('1.0.0')
|
||||
// Global options
|
||||
.option('-v, --verbose', 'verbose output')
|
||||
.option('-c, --config <path>', 'config file path');
|
||||
|
||||
program
|
||||
.command('deploy')
|
||||
.action((options, command) => {
|
||||
const globalOpts = command.parent?.opts();
|
||||
console.log('Deploying...');
|
||||
if (globalOpts?.verbose) {
|
||||
console.log('Verbose mode enabled');
|
||||
console.log('Config:', globalOpts.config);
|
||||
}
|
||||
});
|
||||
|
||||
program.parse();
|
||||
```
|
||||
|
||||
**Usage:**
|
||||
```bash
|
||||
mycli deploy
|
||||
# Normal output
|
||||
|
||||
mycli --verbose deploy
|
||||
# Verbose output
|
||||
|
||||
mycli --verbose --config ./config.json deploy
|
||||
# Verbose with custom config
|
||||
```
|
||||
|
||||
## Example 5: Multiple Commands
|
||||
|
||||
```typescript
|
||||
import { Command } from 'commander';
|
||||
import chalk from 'chalk';
|
||||
|
||||
const program = new Command();
|
||||
|
||||
program.name('mycli').version('1.0.0');
|
||||
|
||||
program
|
||||
.command('init')
|
||||
.description('Initialize new project')
|
||||
.action(() => {
|
||||
console.log(chalk.green('✓ Project initialized'));
|
||||
});
|
||||
|
||||
program
|
||||
.command('build')
|
||||
.description('Build project')
|
||||
.action(() => {
|
||||
console.log(chalk.blue('Building...'));
|
||||
console.log(chalk.green('✓ Build complete'));
|
||||
});
|
||||
|
||||
program
|
||||
.command('test')
|
||||
.description('Run tests')
|
||||
.action(() => {
|
||||
console.log(chalk.blue('Running tests...'));
|
||||
console.log(chalk.green('✓ All tests passed'));
|
||||
});
|
||||
|
||||
program
|
||||
.command('deploy')
|
||||
.description('Deploy to production')
|
||||
.action(() => {
|
||||
console.log(chalk.yellow('Deploying...'));
|
||||
console.log(chalk.green('✓ Deployed'));
|
||||
});
|
||||
|
||||
program.parse();
|
||||
```
|
||||
|
||||
**Usage:**
|
||||
```bash
|
||||
mycli init
|
||||
mycli build
|
||||
mycli test
|
||||
mycli deploy
|
||||
mycli --help # Shows all commands
|
||||
```
|
||||
|
||||
## Running the Examples
|
||||
|
||||
### Setup
|
||||
|
||||
1. Create a new project:
|
||||
```bash
|
||||
mkdir my-cli
|
||||
cd my-cli
|
||||
npm init -y
|
||||
```
|
||||
|
||||
2. Install dependencies:
|
||||
```bash
|
||||
npm install commander chalk
|
||||
npm install -D typescript @types/node tsx
|
||||
```
|
||||
|
||||
3. Configure TypeScript:
|
||||
```bash
|
||||
npx tsc --init --target ES2022 --module ESNext
|
||||
```
|
||||
|
||||
4. Create `src/index.ts` with any example above
|
||||
|
||||
5. Run with tsx:
|
||||
```bash
|
||||
npx tsx src/index.ts --help
|
||||
```
|
||||
|
||||
### Building for Production
|
||||
|
||||
```bash
|
||||
# Build TypeScript
|
||||
npx tsc
|
||||
|
||||
# Run compiled version
|
||||
node dist/index.js
|
||||
```
|
||||
|
||||
### Making it Executable
|
||||
|
||||
Add to `package.json`:
|
||||
```json
|
||||
{
|
||||
"bin": {
|
||||
"mycli": "./dist/index.js"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Add shebang to top of source file:
|
||||
```typescript
|
||||
#!/usr/bin/env node
|
||||
import { Command } from 'commander';
|
||||
// ... rest of code
|
||||
```
|
||||
|
||||
Install globally for testing:
|
||||
```bash
|
||||
npm link
|
||||
mycli --help
|
||||
```
|
||||
558
skills/commander-patterns/examples/nested-commands-demo.md
Normal file
558
skills/commander-patterns/examples/nested-commands-demo.md
Normal file
@@ -0,0 +1,558 @@
|
||||
# Nested Commands Demo
|
||||
|
||||
Examples of building multi-level command hierarchies with Commander.js.
|
||||
|
||||
## Basic Nested Commands
|
||||
|
||||
```typescript
|
||||
import { Command } from 'commander';
|
||||
|
||||
const program = new Command();
|
||||
|
||||
program.name('mycli').version('1.0.0');
|
||||
|
||||
// Create parent command
|
||||
const config = program.command('config').description('Configuration management');
|
||||
|
||||
// Add subcommands
|
||||
config
|
||||
.command('get <key>')
|
||||
.description('Get config value')
|
||||
.action((key) => {
|
||||
console.log(`Getting ${key}...`);
|
||||
});
|
||||
|
||||
config
|
||||
.command('set <key> <value>')
|
||||
.description('Set config value')
|
||||
.action((key, value) => {
|
||||
console.log(`Setting ${key} = ${value}`);
|
||||
});
|
||||
|
||||
config
|
||||
.command('list')
|
||||
.description('List all config')
|
||||
.action(() => {
|
||||
console.log('Listing config...');
|
||||
});
|
||||
|
||||
program.parse();
|
||||
```
|
||||
|
||||
Usage:
|
||||
```bash
|
||||
mycli config get api-key
|
||||
mycli config set api-key abc123
|
||||
mycli config list
|
||||
mycli config --help # Shows subcommands
|
||||
```
|
||||
|
||||
## Multiple Command Groups
|
||||
|
||||
```typescript
|
||||
import { Command } from 'commander';
|
||||
import chalk from 'chalk';
|
||||
|
||||
const program = new Command();
|
||||
program.name('mycli').version('1.0.0');
|
||||
|
||||
// Database commands
|
||||
const db = program.command('db').description('Database operations');
|
||||
|
||||
db.command('migrate')
|
||||
.description('Run migrations')
|
||||
.option('-d, --dry-run', 'show migrations')
|
||||
.action((options) => {
|
||||
console.log(chalk.blue('Running migrations...'));
|
||||
});
|
||||
|
||||
db.command('seed')
|
||||
.description('Seed database')
|
||||
.option('-e, --env <env>', 'environment', 'dev')
|
||||
.action((options) => {
|
||||
console.log(chalk.blue(`Seeding ${options.env} database...`));
|
||||
});
|
||||
|
||||
db.command('reset')
|
||||
.description('Reset database')
|
||||
.option('-f, --force', 'skip confirmation')
|
||||
.action((options) => {
|
||||
if (!options.force) {
|
||||
console.log(chalk.red('Use --force to confirm'));
|
||||
return;
|
||||
}
|
||||
console.log(chalk.yellow('Resetting database...'));
|
||||
});
|
||||
|
||||
// User commands
|
||||
const user = program.command('user').description('User management');
|
||||
|
||||
user
|
||||
.command('list')
|
||||
.description('List users')
|
||||
.option('-p, --page <page>', 'page number', '1')
|
||||
.action((options) => {
|
||||
console.log(`Listing users (page ${options.page})`);
|
||||
});
|
||||
|
||||
user
|
||||
.command('create <username> <email>')
|
||||
.description('Create user')
|
||||
.action((username, email) => {
|
||||
console.log(chalk.green(`Created user: ${username} (${email})`));
|
||||
});
|
||||
|
||||
user
|
||||
.command('delete <userId>')
|
||||
.description('Delete user')
|
||||
.option('-f, --force', 'skip confirmation')
|
||||
.action((userId, options) => {
|
||||
console.log(chalk.red(`Deleted user: ${userId}`));
|
||||
});
|
||||
|
||||
// Cache commands
|
||||
const cache = program.command('cache').description('Cache management');
|
||||
|
||||
cache
|
||||
.command('clear')
|
||||
.description('Clear cache')
|
||||
.option('-a, --all', 'clear all caches')
|
||||
.action((options) => {
|
||||
console.log('Clearing cache...');
|
||||
});
|
||||
|
||||
cache
|
||||
.command('stats')
|
||||
.description('Show cache statistics')
|
||||
.action(() => {
|
||||
console.log('Cache stats:');
|
||||
console.log(' Size: 1.2 GB');
|
||||
console.log(' Hits: 89%');
|
||||
});
|
||||
|
||||
program.parse();
|
||||
```
|
||||
|
||||
Usage:
|
||||
```bash
|
||||
mycli db migrate --dry-run
|
||||
mycli db seed --env prod
|
||||
mycli db reset --force
|
||||
|
||||
mycli user list --page 2
|
||||
mycli user create john john@example.com
|
||||
mycli user delete 123 --force
|
||||
|
||||
mycli cache clear --all
|
||||
mycli cache stats
|
||||
```
|
||||
|
||||
## Three-Level Nesting
|
||||
|
||||
```typescript
|
||||
import { Command } from 'commander';
|
||||
|
||||
const program = new Command();
|
||||
program.name('mycli').version('1.0.0');
|
||||
|
||||
// Level 1: Cloud
|
||||
const cloud = program.command('cloud').description('Cloud operations');
|
||||
|
||||
// Level 2: AWS
|
||||
const aws = cloud.command('aws').description('AWS operations');
|
||||
|
||||
// Level 3: EC2
|
||||
const ec2 = aws.command('ec2').description('EC2 operations');
|
||||
|
||||
ec2
|
||||
.command('list')
|
||||
.description('List EC2 instances')
|
||||
.action(() => {
|
||||
console.log('Listing EC2 instances...');
|
||||
});
|
||||
|
||||
ec2
|
||||
.command('start <instanceId>')
|
||||
.description('Start EC2 instance')
|
||||
.action((instanceId) => {
|
||||
console.log(`Starting instance ${instanceId}...`);
|
||||
});
|
||||
|
||||
ec2
|
||||
.command('stop <instanceId>')
|
||||
.description('Stop EC2 instance')
|
||||
.action((instanceId) => {
|
||||
console.log(`Stopping instance ${instanceId}...`);
|
||||
});
|
||||
|
||||
// Level 3: S3
|
||||
const s3 = aws.command('s3').description('S3 operations');
|
||||
|
||||
s3.command('list')
|
||||
.description('List S3 buckets')
|
||||
.action(() => {
|
||||
console.log('Listing S3 buckets...');
|
||||
});
|
||||
|
||||
s3.command('upload <file> <bucket>')
|
||||
.description('Upload to S3')
|
||||
.action((file, bucket) => {
|
||||
console.log(`Uploading ${file} to ${bucket}...`);
|
||||
});
|
||||
|
||||
// Level 2: Azure
|
||||
const azure = cloud.command('azure').description('Azure operations');
|
||||
|
||||
azure
|
||||
.command('vm-list')
|
||||
.description('List VMs')
|
||||
.action(() => {
|
||||
console.log('Listing Azure VMs...');
|
||||
});
|
||||
|
||||
program.parse();
|
||||
```
|
||||
|
||||
Usage:
|
||||
```bash
|
||||
mycli cloud aws ec2 list
|
||||
mycli cloud aws ec2 start i-123456
|
||||
mycli cloud aws s3 list
|
||||
mycli cloud aws s3 upload file.txt my-bucket
|
||||
mycli cloud azure vm-list
|
||||
```
|
||||
|
||||
## CRUD Pattern
|
||||
|
||||
```typescript
|
||||
import { Command } from 'commander';
|
||||
import chalk from 'chalk';
|
||||
|
||||
const program = new Command();
|
||||
program.name('api-cli').version('1.0.0');
|
||||
|
||||
function createResourceCommands(name: string) {
|
||||
const resource = program.command(name).description(`${name} management`);
|
||||
|
||||
resource
|
||||
.command('list')
|
||||
.description(`List all ${name}`)
|
||||
.option('-p, --page <page>', 'page number', '1')
|
||||
.option('-l, --limit <limit>', 'items per page', '10')
|
||||
.action((options) => {
|
||||
console.log(chalk.blue(`Listing ${name}...`));
|
||||
console.log(`Page ${options.page}, Limit ${options.limit}`);
|
||||
});
|
||||
|
||||
resource
|
||||
.command('get <id>')
|
||||
.description(`Get ${name} by ID`)
|
||||
.action((id) => {
|
||||
console.log(chalk.blue(`Getting ${name} ${id}...`));
|
||||
});
|
||||
|
||||
resource
|
||||
.command('create')
|
||||
.description(`Create new ${name}`)
|
||||
.option('-d, --data <json>', 'JSON data')
|
||||
.action((options) => {
|
||||
console.log(chalk.green(`Creating ${name}...`));
|
||||
console.log('Data:', options.data);
|
||||
});
|
||||
|
||||
resource
|
||||
.command('update <id>')
|
||||
.description(`Update ${name}`)
|
||||
.option('-d, --data <json>', 'JSON data')
|
||||
.action((id, options) => {
|
||||
console.log(chalk.yellow(`Updating ${name} ${id}...`));
|
||||
console.log('Data:', options.data);
|
||||
});
|
||||
|
||||
resource
|
||||
.command('delete <id>')
|
||||
.description(`Delete ${name}`)
|
||||
.option('-f, --force', 'skip confirmation')
|
||||
.action((id, options) => {
|
||||
if (!options.force) {
|
||||
console.log(chalk.red('Use --force to confirm deletion'));
|
||||
return;
|
||||
}
|
||||
console.log(chalk.red(`Deleted ${name} ${id}`));
|
||||
});
|
||||
|
||||
return resource;
|
||||
}
|
||||
|
||||
// Create CRUD commands for different resources
|
||||
createResourceCommands('users');
|
||||
createResourceCommands('posts');
|
||||
createResourceCommands('comments');
|
||||
|
||||
program.parse();
|
||||
```
|
||||
|
||||
Usage:
|
||||
```bash
|
||||
# Users
|
||||
api-cli users list --page 2
|
||||
api-cli users get 123
|
||||
api-cli users create --data '{"name":"John"}'
|
||||
api-cli users update 123 --data '{"email":"new@example.com"}'
|
||||
api-cli users delete 123 --force
|
||||
|
||||
# Posts
|
||||
api-cli posts list
|
||||
api-cli posts get 456
|
||||
api-cli posts create --data '{"title":"Hello"}'
|
||||
|
||||
# Comments
|
||||
api-cli comments list
|
||||
```
|
||||
|
||||
## Modular Command Structure
|
||||
|
||||
Split commands into separate files for better organization:
|
||||
|
||||
**src/commands/config.ts**
|
||||
```typescript
|
||||
import { Command } from 'commander';
|
||||
|
||||
export function createConfigCommand(): Command {
|
||||
const config = new Command('config').description('Configuration management');
|
||||
|
||||
config
|
||||
.command('get <key>')
|
||||
.description('Get config value')
|
||||
.action((key) => {
|
||||
console.log(`Getting ${key}...`);
|
||||
});
|
||||
|
||||
config
|
||||
.command('set <key> <value>')
|
||||
.description('Set config value')
|
||||
.action((key, value) => {
|
||||
console.log(`Setting ${key} = ${value}`);
|
||||
});
|
||||
|
||||
return config;
|
||||
}
|
||||
```
|
||||
|
||||
**src/commands/user.ts**
|
||||
```typescript
|
||||
import { Command } from 'commander';
|
||||
|
||||
export function createUserCommand(): Command {
|
||||
const user = new Command('user').description('User management');
|
||||
|
||||
user
|
||||
.command('list')
|
||||
.description('List users')
|
||||
.action(() => {
|
||||
console.log('Listing users...');
|
||||
});
|
||||
|
||||
user
|
||||
.command('create <username>')
|
||||
.description('Create user')
|
||||
.action((username) => {
|
||||
console.log(`Creating user: ${username}`);
|
||||
});
|
||||
|
||||
return user;
|
||||
}
|
||||
```
|
||||
|
||||
**src/index.ts**
|
||||
```typescript
|
||||
import { Command } from 'commander';
|
||||
import { createConfigCommand } from './commands/config';
|
||||
import { createUserCommand } from './commands/user';
|
||||
|
||||
const program = new Command();
|
||||
|
||||
program
|
||||
.name('mycli')
|
||||
.version('1.0.0')
|
||||
.description('My CLI tool');
|
||||
|
||||
// Add command groups
|
||||
program.addCommand(createConfigCommand());
|
||||
program.addCommand(createUserCommand());
|
||||
|
||||
program.parse();
|
||||
```
|
||||
|
||||
## Nested Commands with Shared Options
|
||||
|
||||
```typescript
|
||||
import { Command } from 'commander';
|
||||
|
||||
const program = new Command();
|
||||
program.name('deploy-cli').version('1.0.0');
|
||||
|
||||
// Parent deploy command with shared options
|
||||
const deploy = program
|
||||
.command('deploy')
|
||||
.description('Deployment operations')
|
||||
.option('-e, --env <environment>', 'environment', 'dev')
|
||||
.option('-v, --verbose', 'verbose output');
|
||||
|
||||
// Subcommands inherit parent context
|
||||
deploy
|
||||
.command('start')
|
||||
.description('Start deployment')
|
||||
.option('-f, --force', 'force deployment')
|
||||
.action((options, command) => {
|
||||
const parentOpts = command.parent?.opts();
|
||||
console.log('Environment:', parentOpts?.env);
|
||||
console.log('Verbose:', parentOpts?.verbose);
|
||||
console.log('Force:', options.force);
|
||||
});
|
||||
|
||||
deploy
|
||||
.command('status')
|
||||
.description('Check deployment status')
|
||||
.action((options, command) => {
|
||||
const parentOpts = command.parent?.opts();
|
||||
console.log(`Checking ${parentOpts?.env} status...`);
|
||||
});
|
||||
|
||||
deploy
|
||||
.command('rollback [version]')
|
||||
.description('Rollback deployment')
|
||||
.action((version, options, command) => {
|
||||
const parentOpts = command.parent?.opts();
|
||||
console.log(`Rolling back ${parentOpts?.env}...`);
|
||||
});
|
||||
|
||||
program.parse();
|
||||
```
|
||||
|
||||
Usage:
|
||||
```bash
|
||||
deploy-cli deploy --env prod start --force
|
||||
deploy-cli deploy --env staging status
|
||||
deploy-cli deploy --verbose rollback v1.0.0
|
||||
```
|
||||
|
||||
## Command Aliases
|
||||
|
||||
```typescript
|
||||
import { Command } from 'commander';
|
||||
|
||||
const program = new Command();
|
||||
program.name('mycli').version('1.0.0');
|
||||
|
||||
const db = program.command('database').alias('db').description('Database ops');
|
||||
|
||||
db.command('migrate')
|
||||
.alias('m')
|
||||
.description('Run migrations')
|
||||
.action(() => {
|
||||
console.log('Running migrations...');
|
||||
});
|
||||
|
||||
db.command('seed')
|
||||
.alias('s')
|
||||
.description('Seed database')
|
||||
.action(() => {
|
||||
console.log('Seeding...');
|
||||
});
|
||||
|
||||
program.parse();
|
||||
```
|
||||
|
||||
Usage (all equivalent):
|
||||
```bash
|
||||
mycli database migrate
|
||||
mycli db migrate
|
||||
mycli db m
|
||||
|
||||
mycli database seed
|
||||
mycli db seed
|
||||
mycli db s
|
||||
```
|
||||
|
||||
## Complete CLI Example
|
||||
|
||||
```typescript
|
||||
#!/usr/bin/env node
|
||||
import { Command } from 'commander';
|
||||
import chalk from 'chalk';
|
||||
|
||||
const program = new Command();
|
||||
|
||||
program
|
||||
.name('project-cli')
|
||||
.version('1.0.0')
|
||||
.description('Project management CLI');
|
||||
|
||||
// Project commands
|
||||
const project = program.command('project').alias('p').description('Project operations');
|
||||
|
||||
project
|
||||
.command('init <name>')
|
||||
.description('Initialize new project')
|
||||
.option('-t, --template <type>', 'template', 'basic')
|
||||
.action((name, options) => {
|
||||
console.log(chalk.green(`✓ Initialized ${name} with ${options.template} template`));
|
||||
});
|
||||
|
||||
project
|
||||
.command('build')
|
||||
.description('Build project')
|
||||
.action(() => {
|
||||
console.log(chalk.blue('Building...'));
|
||||
});
|
||||
|
||||
// Environment commands
|
||||
const env = program.command('env').alias('e').description('Environment management');
|
||||
|
||||
env
|
||||
.command('list')
|
||||
.alias('ls')
|
||||
.description('List environments')
|
||||
.action(() => {
|
||||
console.log('dev, staging, prod');
|
||||
});
|
||||
|
||||
env
|
||||
.command('create <name>')
|
||||
.description('Create environment')
|
||||
.action((name) => {
|
||||
console.log(chalk.green(`✓ Created environment: ${name}`));
|
||||
});
|
||||
|
||||
// Deploy commands
|
||||
const deploy = program.command('deploy').alias('d').description('Deployment operations');
|
||||
|
||||
deploy
|
||||
.command('start <env>')
|
||||
.description('Start deployment')
|
||||
.action((env) => {
|
||||
console.log(chalk.blue(`Deploying to ${env}...`));
|
||||
});
|
||||
|
||||
deploy
|
||||
.command('status [env]')
|
||||
.description('Check status')
|
||||
.action((env) => {
|
||||
console.log(`Status of ${env || 'all'}:`);
|
||||
});
|
||||
|
||||
program.parse();
|
||||
```
|
||||
|
||||
Usage:
|
||||
```bash
|
||||
project-cli project init my-app --template advanced
|
||||
project-cli p build
|
||||
|
||||
project-cli env list
|
||||
project-cli e create staging
|
||||
|
||||
project-cli deploy start prod
|
||||
project-cli d status
|
||||
```
|
||||
406
skills/commander-patterns/examples/options-arguments-demo.md
Normal file
406
skills/commander-patterns/examples/options-arguments-demo.md
Normal file
@@ -0,0 +1,406 @@
|
||||
# Commander.js Options and Arguments Demo
|
||||
|
||||
Comprehensive examples of option and argument patterns.
|
||||
|
||||
## Option Patterns
|
||||
|
||||
### 1. Boolean Flags
|
||||
|
||||
```typescript
|
||||
program
|
||||
.command('build')
|
||||
.option('-w, --watch', 'watch for changes')
|
||||
.option('-m, --minify', 'minify output')
|
||||
.option('-v, --verbose', 'verbose logging')
|
||||
.action((options) => {
|
||||
console.log('Watch:', options.watch); // true or undefined
|
||||
console.log('Minify:', options.minify);
|
||||
console.log('Verbose:', options.verbose);
|
||||
});
|
||||
```
|
||||
|
||||
Usage:
|
||||
```bash
|
||||
mycli build --watch --minify
|
||||
```
|
||||
|
||||
### 2. Options with Required Values
|
||||
|
||||
```typescript
|
||||
program
|
||||
.command('deploy')
|
||||
.option('-e, --env <environment>', 'deployment environment')
|
||||
.option('-r, --region <region>', 'AWS region')
|
||||
.action((options) => {
|
||||
console.log('Environment:', options.env);
|
||||
console.log('Region:', options.region);
|
||||
});
|
||||
```
|
||||
|
||||
Usage:
|
||||
```bash
|
||||
mycli deploy --env production --region us-west-2
|
||||
```
|
||||
|
||||
### 3. Options with Optional Values
|
||||
|
||||
```typescript
|
||||
program
|
||||
.command('log')
|
||||
.option('-f, --file [path]', 'log file path')
|
||||
.action((options) => {
|
||||
if (options.file === true) {
|
||||
console.log('Using default log file');
|
||||
} else if (options.file) {
|
||||
console.log('Log file:', options.file);
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
Usage:
|
||||
```bash
|
||||
mycli log --file # file = true
|
||||
mycli log --file custom.log # file = 'custom.log'
|
||||
mycli log # file = undefined
|
||||
```
|
||||
|
||||
### 4. Options with Defaults
|
||||
|
||||
```typescript
|
||||
program
|
||||
.command('serve')
|
||||
.option('-p, --port <port>', 'port number', '3000')
|
||||
.option('-h, --host <host>', 'hostname', 'localhost')
|
||||
.action((options) => {
|
||||
console.log(`http://${options.host}:${options.port}`);
|
||||
});
|
||||
```
|
||||
|
||||
Usage:
|
||||
```bash
|
||||
mycli serve # Uses defaults
|
||||
mycli serve --port 8080 # Custom port
|
||||
```
|
||||
|
||||
### 5. Negatable Options
|
||||
|
||||
```typescript
|
||||
program
|
||||
.command('build')
|
||||
.option('--cache', 'enable cache')
|
||||
.option('--no-cache', 'disable cache')
|
||||
.option('--color', 'enable colors')
|
||||
.option('--no-color', 'disable colors')
|
||||
.action((options) => {
|
||||
console.log('Cache:', options.cache); // undefined, true, or false
|
||||
console.log('Color:', options.color);
|
||||
});
|
||||
```
|
||||
|
||||
Usage:
|
||||
```bash
|
||||
mycli build # cache & color = undefined
|
||||
mycli build --cache # cache = true
|
||||
mycli build --no-cache # cache = false
|
||||
mycli build --no-color # color = false
|
||||
```
|
||||
|
||||
### 6. Variadic Options
|
||||
|
||||
```typescript
|
||||
program
|
||||
.command('tag')
|
||||
.option('-t, --tags <tags...>', 'multiple tags')
|
||||
.action((options) => {
|
||||
console.log('Tags:', options.tags); // Array
|
||||
});
|
||||
```
|
||||
|
||||
Usage:
|
||||
```bash
|
||||
mycli tag --tags v1.0 production stable
|
||||
# Tags: ['v1.0', 'production', 'stable']
|
||||
```
|
||||
|
||||
### 7. Options with Custom Parsers
|
||||
|
||||
```typescript
|
||||
program
|
||||
.command('scale')
|
||||
.option('-r, --replicas <count>', 'replica count', parseInt)
|
||||
.option('-m, --memory <mb>', 'memory in MB', parseFloat)
|
||||
.option('-t, --timeout <sec>', 'timeout', (value) => {
|
||||
return parseInt(value) * 1000; // Convert to ms
|
||||
})
|
||||
.action((options) => {
|
||||
console.log('Replicas:', options.replicas); // Number
|
||||
console.log('Memory:', options.memory); // Number
|
||||
console.log('Timeout:', options.timeout); // Number (ms)
|
||||
});
|
||||
```
|
||||
|
||||
Usage:
|
||||
```bash
|
||||
mycli scale --replicas 5 --memory 512.5 --timeout 30
|
||||
```
|
||||
|
||||
## Argument Patterns
|
||||
|
||||
### 1. Required Arguments
|
||||
|
||||
```typescript
|
||||
program
|
||||
.command('deploy <environment>')
|
||||
.description('Deploy to environment')
|
||||
.action((environment) => {
|
||||
console.log('Deploying to:', environment);
|
||||
});
|
||||
```
|
||||
|
||||
Usage:
|
||||
```bash
|
||||
mycli deploy production # ✓ Works
|
||||
mycli deploy # ✗ Error: missing required argument
|
||||
```
|
||||
|
||||
### 2. Optional Arguments
|
||||
|
||||
```typescript
|
||||
program
|
||||
.command('create <name> [description]')
|
||||
.description('Create item')
|
||||
.action((name, description) => {
|
||||
console.log('Name:', name);
|
||||
console.log('Description:', description || 'No description');
|
||||
});
|
||||
```
|
||||
|
||||
Usage:
|
||||
```bash
|
||||
mycli create "My Item"
|
||||
mycli create "My Item" "A detailed description"
|
||||
```
|
||||
|
||||
### 3. Variadic Arguments
|
||||
|
||||
```typescript
|
||||
program
|
||||
.command('add <items...>')
|
||||
.description('Add multiple items')
|
||||
.action((items) => {
|
||||
console.log('Items:', items); // Array
|
||||
items.forEach((item, i) => {
|
||||
console.log(` ${i + 1}. ${item}`);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
Usage:
|
||||
```bash
|
||||
mycli add item1 item2 item3
|
||||
# Items: ['item1', 'item2', 'item3']
|
||||
```
|
||||
|
||||
### 4. Mixed Required and Optional
|
||||
|
||||
```typescript
|
||||
program
|
||||
.command('copy <source> <destination> [options]')
|
||||
.description('Copy files')
|
||||
.action((source, destination, options) => {
|
||||
console.log('Source:', source);
|
||||
console.log('Destination:', destination);
|
||||
console.log('Options:', options || 'none');
|
||||
});
|
||||
```
|
||||
|
||||
### 5. Arguments with Descriptions
|
||||
|
||||
```typescript
|
||||
program
|
||||
.command('deploy <environment>')
|
||||
.argument('<environment>', 'target environment (dev, staging, prod)')
|
||||
.argument('[region]', 'deployment region', 'us-east-1')
|
||||
.action((environment, region) => {
|
||||
console.log(`Deploying to ${environment} in ${region}`);
|
||||
});
|
||||
```
|
||||
|
||||
### 6. Arguments with Custom Parsers
|
||||
|
||||
```typescript
|
||||
program
|
||||
.command('wait <seconds>')
|
||||
.argument('<seconds>', 'seconds to wait', parseFloat)
|
||||
.action(async (seconds) => {
|
||||
console.log(`Waiting ${seconds} seconds...`);
|
||||
await new Promise((resolve) => setTimeout(resolve, seconds * 1000));
|
||||
console.log('Done!');
|
||||
});
|
||||
```
|
||||
|
||||
Usage:
|
||||
```bash
|
||||
mycli wait 2.5 # Waits 2.5 seconds
|
||||
```
|
||||
|
||||
### 7. Arguments with Validation
|
||||
|
||||
```typescript
|
||||
program
|
||||
.command('set-port <port>')
|
||||
.argument('<port>', 'port number', (value) => {
|
||||
const port = parseInt(value, 10);
|
||||
if (isNaN(port)) {
|
||||
throw new Error('Port must be a number');
|
||||
}
|
||||
if (port < 1 || port > 65535) {
|
||||
throw new Error('Port must be between 1 and 65535');
|
||||
}
|
||||
return port;
|
||||
})
|
||||
.action((port) => {
|
||||
console.log('Port set to:', port);
|
||||
});
|
||||
```
|
||||
|
||||
## Combined Patterns
|
||||
|
||||
### Arguments + Options
|
||||
|
||||
```typescript
|
||||
program
|
||||
.command('deploy <environment>')
|
||||
.argument('<environment>', 'deployment environment')
|
||||
.option('-f, --force', 'force deployment')
|
||||
.option('-d, --dry-run', 'simulate deployment')
|
||||
.option('-t, --tag <tag>', 'deployment tag', 'latest')
|
||||
.action((environment, options) => {
|
||||
console.log('Environment:', environment);
|
||||
console.log('Force:', options.force);
|
||||
console.log('Dry run:', options.dryRun);
|
||||
console.log('Tag:', options.tag);
|
||||
});
|
||||
```
|
||||
|
||||
Usage:
|
||||
```bash
|
||||
mycli deploy production --force --tag v1.2.3
|
||||
```
|
||||
|
||||
### Variadic Arguments + Options
|
||||
|
||||
```typescript
|
||||
program
|
||||
.command('compile <files...>')
|
||||
.argument('<files...>', 'files to compile')
|
||||
.option('-o, --output <dir>', 'output directory', './dist')
|
||||
.option('-m, --minify', 'minify output')
|
||||
.action((files, options) => {
|
||||
console.log('Files:', files);
|
||||
console.log('Output:', options.output);
|
||||
console.log('Minify:', options.minify);
|
||||
});
|
||||
```
|
||||
|
||||
Usage:
|
||||
```bash
|
||||
mycli compile src/a.ts src/b.ts --output build --minify
|
||||
```
|
||||
|
||||
### Multiple Option Types
|
||||
|
||||
```typescript
|
||||
program
|
||||
.command('start')
|
||||
.option('-p, --port <port>', 'port', '3000')
|
||||
.option('-h, --host <host>', 'host', 'localhost')
|
||||
.option('-o, --open', 'open browser')
|
||||
.option('--no-color', 'disable colors')
|
||||
.option('-e, --env <vars...>', 'environment variables')
|
||||
.action((options) => {
|
||||
console.log('Server:', `http://${options.host}:${options.port}`);
|
||||
console.log('Open:', options.open);
|
||||
console.log('Color:', options.color);
|
||||
console.log('Env:', options.env);
|
||||
});
|
||||
```
|
||||
|
||||
Usage:
|
||||
```bash
|
||||
mycli start --port 8080 --open --env NODE_ENV=production DEBUG=true
|
||||
```
|
||||
|
||||
## Complete Example
|
||||
|
||||
```typescript
|
||||
#!/usr/bin/env node
|
||||
import { Command } from 'commander';
|
||||
import chalk from 'chalk';
|
||||
|
||||
const program = new Command();
|
||||
|
||||
program.name('deploy-cli').version('1.0.0');
|
||||
|
||||
program
|
||||
.command('deploy <environment> [region]')
|
||||
.description('Deploy application')
|
||||
.argument('<environment>', 'target environment (dev, staging, prod)')
|
||||
.argument('[region]', 'deployment region', 'us-east-1')
|
||||
.option('-f, --force', 'skip confirmations', false)
|
||||
.option('-d, --dry-run', 'simulate deployment', false)
|
||||
.option('-t, --tag <tag>', 'deployment tag', 'latest')
|
||||
.option('-r, --replicas <count>', 'replica count', parseInt, 3)
|
||||
.option('--env <vars...>', 'environment variables')
|
||||
.option('--no-rollback', 'disable auto-rollback')
|
||||
.action((environment, region, options) => {
|
||||
console.log(chalk.blue('Deployment Configuration:'));
|
||||
console.log('Environment:', chalk.yellow(environment));
|
||||
console.log('Region:', region);
|
||||
console.log('Tag:', options.tag);
|
||||
console.log('Replicas:', options.replicas);
|
||||
console.log('Force:', options.force);
|
||||
console.log('Dry run:', options.dryRun);
|
||||
console.log('Rollback:', options.rollback);
|
||||
|
||||
if (options.env) {
|
||||
console.log('Environment variables:');
|
||||
options.env.forEach((v) => console.log(` ${v}`));
|
||||
}
|
||||
|
||||
if (options.dryRun) {
|
||||
console.log(chalk.yellow('\n🔍 Dry run - no actual deployment'));
|
||||
return;
|
||||
}
|
||||
|
||||
console.log(chalk.green('\n✓ Deployment complete!'));
|
||||
});
|
||||
|
||||
program.parse();
|
||||
```
|
||||
|
||||
Usage examples:
|
||||
```bash
|
||||
# Basic
|
||||
deploy-cli deploy production
|
||||
|
||||
# With region
|
||||
deploy-cli deploy staging us-west-2
|
||||
|
||||
# With options
|
||||
deploy-cli deploy prod --force --replicas 5
|
||||
|
||||
# With environment variables
|
||||
deploy-cli deploy prod --env NODE_ENV=production API_KEY=xyz
|
||||
|
||||
# Dry run
|
||||
deploy-cli deploy prod --dry-run --no-rollback
|
||||
|
||||
# All together
|
||||
deploy-cli deploy production us-west-2 \
|
||||
--force \
|
||||
--tag v2.0.0 \
|
||||
--replicas 10 \
|
||||
--env NODE_ENV=production DEBUG=false \
|
||||
--no-rollback
|
||||
```
|
||||
Reference in New Issue
Block a user