CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-sade

Smooth CLI operator for building command-line applications with subcommands, options, and automated help text generation.

Pending
Overview
Eval results
Files

action-execution.mddocs/

Action Execution

Action handler system for command execution, argument parsing, and lazy evaluation support.

Capabilities

Action Method

Attach callback handlers to commands that execute when the command is invoked.

/**
 * Attach callback handler to current command
 * @param {function} handler - Command handler function
 * @returns {Sade} Chainable instance
 */
action(handler);

/**
 * Command handler function signature
 * @param {...*} args - Positional arguments based on command usage pattern
 * @param {object} opts - Parsed options and flags
 */
type Handler = (...args: any[], opts: object) => any;

Parameters:

  • handler (function, required): Callback function executed when command runs
    • Receives positional arguments based on command usage pattern
    • Final parameter is always an options object with parsed flags
    • Optional arguments may be undefined if not provided

Usage Examples:

// Basic command handler
prog.command('greet <name>')
  .action((name, opts) => {
    console.log(`Hello, ${name}!`);
  });

// Handler with optional arguments
prog.command('serve [dir] [port]')
  .option('-w, --watch', 'Watch for changes')
  .action((dir = '.', port = 3000, opts) => {
    console.log(`Serving ${dir} on port ${port}`);
    if (opts.watch) console.log('Watching for changes...');
  });

// Handler with multiple required arguments
prog.command('copy <src> <dest>')
  .option('-f, --force', 'Overwrite existing files')
  .action((src, dest, opts) => {
    console.log(`Copying ${src} to ${dest}`);
    console.log('Options:', opts);
    // opts = { _: [], force: true/false, f: true/false }
  });

Parse Method

Parse command line arguments and execute the appropriate command handler.

/**
 * Parse command line arguments and execute appropriate handler
 * @param {string[]} arr - Command line arguments (typically process.argv)
 * @param {object} [opts] - Parsing configuration options
 * @returns {void|LazyOutput} Void (executes handler) or LazyOutput if opts.lazy = true
 */
parse(arr, opts);

interface ParseOptions {
  /** Return execution info instead of running handler */
  lazy?: boolean;
  /** Additional flag aliases */
  alias?: Record<string, string | string[]>;
  /** Additional default values */
  default?: Record<string, any>;
  /** Handler for unknown flags */
  unknown?: (flag: string) => string | void;
}

interface LazyOutput {
  /** Command name that was matched */
  name: string;
  /** Handler function to execute */
  handler: Handler;
  /** Arguments array to pass to handler */
  args: any[];
}

Parameters:

  • arr (string[], required): Command line arguments array (usually process.argv)
  • opts (object, optional): Parsing configuration options

Basic Usage:

// Standard usage - executes handler immediately
prog.parse(process.argv);

// With custom arguments (for testing)
prog.parse(['node', 'script.js', 'build', 'src', 'dist', '--watch']);

Lazy Execution

Use lazy parsing to defer command execution and gain control over when handlers run.

Usage Examples:

// Get execution information without running
const result = prog.parse(process.argv, { lazy: true });

console.log('Command:', result.name);
console.log('Arguments:', result.args);

// Execute later (optionally modify args first)
result.handler.apply(null, result.args);

// Or with modified arguments
const modifiedArgs = result.args.map(arg => 
  typeof arg === 'string' ? arg.toUpperCase() : arg
);
result.handler.apply(null, modifiedArgs);

Parse Options Override

Override or extend option parsing behavior with custom configuration.

Alias Override:

prog.command('build')
  .option('-f, --force', 'Force build');

// Override aliases at parse time
prog.parse(process.argv, {
  alias: {
    f: ['foo', 'fizz'],  // -f now maps to --foo and --fizz instead of --force
    v: ['verbose']       // Add new -v -> --verbose alias
  }
});

Default Value Override:

prog.command('start')
  .option('-p, --port', 'Server port', 3000);

// Override defaults at parse time
prog.parse(process.argv, {
  default: {
    port: 8080,          // Override default port
    env: 'development'   // Add new default value
  }
});

Unknown Flag Handling:

prog.parse(process.argv, {
  unknown: (flag) => {
    if (flag.startsWith('--experimental-')) {
      return; // Allow experimental flags without error
    }
    return `Unknown flag: ${flag}. Did you mean --help?`;
  }
});

// Example output:
// $ my-cli build --typo
// ERROR: Unknown flag: --typo. Did you mean --help?

Argument Parsing Behavior

Sade follows specific rules for parsing arguments and options.

Argument Order and Types:

prog.command('deploy <env> [version] [region]')
  .option('-f, --force', 'Force deployment')
  .option('--timeout', 'Deployment timeout', 300)
  .action((env, version, region, opts) => {
    // env: always provided (required)
    // version: string or undefined (optional)
    // region: string or undefined (optional)  
    // opts: { force: boolean, timeout: number, ... }
  });

// Examples:
// $ my-cli deploy prod
//   → env='prod', version=undefined, region=undefined
// $ my-cli deploy prod v1.2.0
//   → env='prod', version='v1.2.0', region=undefined
// $ my-cli deploy prod v1.2.0 us-east-1 --force
//   → env='prod', version='v1.2.0', region='us-east-1', opts.force=true

Options Object Structure:

prog.command('build')
  .option('-w, --watch', 'Watch mode')
  .option('-o, --output', 'Output file', 'dist.js')
  .action((opts) => {
    console.log(opts);
    // {
    //   _: [],                    // Remaining arguments
    //   w: true,                  // Short flag alias
    //   watch: true,              // Long flag name
    //   o: 'custom.js',          // Short flag alias with value
    //   output: 'custom.js'       // Long flag name with value
    // }
  });

Error Handling

Parse method handles various error conditions and provides helpful error messages.

Common Errors:

  • Insufficient arguments: Required arguments not provided
  • Invalid command: Command name not found
  • Unknown options: Unrecognized flags (unless handled by unknown option)
  • No command specified: Multi-command CLI called without a command

Error Examples:

// Insufficient arguments
// $ my-cli copy file1
// ERROR: Insufficient arguments!
// Run `$ my-cli copy --help` for more info.

// Invalid command  
// $ my-cli invalid-command
// ERROR: Invalid command: invalid-command
// Run `$ my-cli --help` for more info.

// No command (multi-command mode)
// $ my-cli
// ERROR: No command specified.
// Run `$ my-cli --help` for more info.

Execution Flow

The parse method follows a specific execution flow:

  1. Parse arguments using mri library
  2. Detect command from positional arguments
  3. Resolve aliases to actual command names
  4. Validate arguments against command usage pattern
  5. Merge options (global + command + parse-time)
  6. Execute action or return lazy output
  7. Handle help/version flags automatically

Install with Tessl CLI

npx tessl i tessl/npm-sade

docs

action-execution.md

command-definition.md

help-system.md

index.md

options-configuration.md

program-creation.md

tile.json