CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-yeoman-environment

Handles the lifecycle and bootstrapping of generators in a specific environment

Overview
Eval results
Files

cli.mddocs/

Command Line Interface

CLI command creation and management with Commander.js integration for generator commands and environment interaction.

Capabilities

YeomanCommand Class

Extended Commander class with Yeoman-specific functionality for handling generator options and arguments.

/**
 * Extended Commander class with Yeoman-specific functionality
 */
class YeomanCommand extends Command {
  /** Environment instance associated with this command */
  env?: BaseEnvironment;

  /**
   * Create sub-command with YeomanCommand type
   * @param name - Optional command name
   * @returns New YeomanCommand instance
   */
  createCommand(name?: string): YeomanCommand;

  /**
   * Add option with automatic negative alternative creation
   * @param option - Commander Option instance
   * @returns This command for chaining
   */
  addOption(option: Option): YeomanCommand;

  /**
   * Register generator options and arguments with the command
   * @param generator - Generator instance with _options and _arguments
   * @returns This command for chaining
   */
  registerGenerator(generator: any): YeomanCommand;

  /**
   * Add generator arguments to command
   * @param generatorArgs - Array of generator argument definitions
   * @returns This command for chaining
   */
  addGeneratorArguments(generatorArgs: any[]): YeomanCommand;

  /**
   * Add generator options to command
   * @param options - Object mapping option names to definitions
   * @returns This command for chaining
   */
  addGeneratorOptions(options: Record<string, any>): YeomanCommand;
}

Usage Examples:

import { YeomanCommand } from "yeoman-environment";

// Create command with Yeoman extensions
const command = new YeomanCommand("generate");

// Add environment-aware options
command.option("--skip-install", "Skip dependency installation");

// Register generator options
const generator = await env.get("webapp:app");
command.registerGenerator(generator);

// Create sub-command
const subCommand = command
  .createCommand("component")
  .description("Generate a component");

Environment Options

Add standard environment options to any command.

/**
 * Add standard environment options to a command
 * @param command - Command to add options to (defaults to new YeomanCommand)
 * @returns Command with environment options added
 */
function addEnvironmentOptions(command?: YeomanCommand): YeomanCommand;

Usage Examples:

import { addEnvironmentOptions, YeomanCommand } from "yeoman-environment";

// Add to existing command
const command = new YeomanCommand("generate");
addEnvironmentOptions(command);

// Create new command with options
const envCommand = addEnvironmentOptions();

// Chain with other options
const fullCommand = addEnvironmentOptions(new YeomanCommand("build"))
  .option("--production", "Build for production")
  .option("--watch", "Watch for changes");

Standard Environment Options Added:

  • --cwd - Path to use as current directory
  • --skip-install - Do not automatically install dependencies
  • --skip-cache - Do not remember prompt answers
  • --local-config-only - Generate .yo-rc-global.json locally
  • --ask-answered - Show prompts for already configured options
  • --force - Override every file
  • --dry-run - Print conflicts without applying
  • --whitespace - Whitespace changes will not trigger conflicts
  • --bail - Fail on first conflict
  • --skip-yo-resolve - Ignore .yo-resolve files

Command Preparation

Prepare Commander instances for CLI support with generator integration.

/**
 * Prepare a commander instance for CLI support with generator integration
 * @param options - Command preparation configuration
 * @returns Configured YeomanCommand instance
 */
function prepareGeneratorCommand(options: CommandPreparation): Promise<YeomanCommand>;

/**
 * Prepare a commander instance for CLI support
 * @param options - Command preparation configuration
 * @returns Configured YeomanCommand instance
 */
function prepareCommand(options: CommandPreparation): Promise<YeomanCommand>;

interface CommandPreparation {
  /** Generator file path or module path */
  resolved?: string;
  /** Command instance to configure */
  command?: YeomanCommand;
  /** Generator constructor to use */
  generator?: BaseGeneratorConstructor;
  /** Generator namespace */
  namespace?: string;
}

Usage Examples:

import { prepareCommand, prepareGeneratorCommand } from "yeoman-environment";

// Prepare command for specific generator
const command1 = await prepareGeneratorCommand({
  resolved: "./generators/app/index.js",
  namespace: "myapp:app"
});

// Prepare with generator constructor
const command2 = await prepareGeneratorCommand({
  generator: MyGeneratorClass,
  namespace: "myapp:component"
});

// Prepare basic command
const command3 = await prepareCommand({
  resolved: "generator-webapp/generators/app",
  namespace: "webapp:app"
});

// Use prepared command
command1.action(async function() {
  console.log("Running generator with args:", this.args);
  console.log("Running generator with options:", this.opts());
});

Built-in CLI Binary

The package includes a yoe CLI binary for direct generator interaction.

yoe Commands

# Run a generator
yoe run <namespace> [generator-options]

# Find installed generators
yoe find

# List available generators
yoe list

# Get help
yoe --help

Examples:

# Run webapp generator
yoe run webapp:app MyProject --skip-install

# Run with environment options
yoe run angular:component UserCard --force --dry-run

# Find all installed generators
yoe find

# List registered generators
yoe list

CLI Integration Example

Complete example of CLI integration with custom commands:

import { Command } from "commander";
import { 
  createEnv, 
  addEnvironmentOptions, 
  YeomanCommand,
  prepareGeneratorCommand 
} from "yeoman-environment";

// Create main program
const program = new YeomanCommand();
program.version("1.0.0");

// Add generate command
const generateCommand = addEnvironmentOptions(
  program
    .command("generate <type>")
    .description("Generate code")
    .argument("<type>", "Type of code to generate")
);

generateCommand.action(async function(type, options) {
  const env = createEnv({ ...options, command: this });
  
  this.env = env;
  await env.lookupLocalPackages();
  
  // Execute generator based on type
  await env.execute(`myapp:${type}`, this.args.slice(1));
});

// Add generator-specific commands
const componentCommand = await prepareGeneratorCommand({
  resolved: "./generators/component/index.js",
  namespace: "myapp:component"
});

program.addCommand(componentCommand.name("component"));

// Parse arguments
await program.parseAsync(process.argv);

Advanced CLI Patterns

Dynamic Command Registration

import { createEnv, YeomanCommand, addEnvironmentOptions } from "yeoman-environment";

async function createDynamicCLI() {
  const env = createEnv();
  const program = new YeomanCommand();
  
  // Discover generators
  const generators = await env.lookup();
  
  // Create commands for each generator
  for (const meta of generators) {
    const command = addEnvironmentOptions(
      program
        .command(meta.namespace.replace(":", "-"))
        .description(`Run ${meta.namespace} generator`)
    );
    
    command.action(async function() {
      await env.execute(meta.namespace, this.args);
    });
  }
  
  return program;
}

// Usage
const cli = await createDynamicCLI();
await cli.parseAsync(process.argv);

Custom Environment Integration

import { YeomanCommand, createEnv } from "yeoman-environment";

class CustomCommand extends YeomanCommand {
  constructor() {
    super();
    this.env = createEnv({
      // Custom environment options
      skipInstall: true,
      adapter: myCustomAdapter
    });
  }
  
  async executeGenerator(namespace: string, args: string[]) {
    await this.env!.lookup();
    return this.env!.execute(namespace, args);
  }
}

const customCLI = new CustomCommand()
  .command("build <generator>")
  .action(async function(generator, options) {
    await this.executeGenerator(`myapp:${generator}`, this.args.slice(1));
  });

CLI Configuration Types

interface CommandPreparation {
  /** Generator file path or module path */
  resolved?: string;
  /** Command instance to configure */
  command?: YeomanCommand;
  /** Generator constructor to use */
  generator?: BaseGeneratorConstructor;
  /** Generator namespace */
  namespace?: string;
}

interface GeneratorOptionDefinition {
  /** Option description */
  description: string;
  /** Option type (String, Boolean, Array, etc.) */
  type: any;
  /** Default value */
  default?: any;
  /** Short alias */
  alias?: string;
  /** Whether option is required */
  required?: boolean;
  /** Hide from help */
  hide?: boolean;
}

interface GeneratorArgumentDefinition {
  /** Argument name */
  name: string;
  /** Argument type */
  type: any;
  /** Whether argument is required */
  required: boolean;
  /** Argument description */
  description?: string;
}

Install with Tessl CLI

npx tessl i tessl/npm-yeoman-environment

docs

cli.md

environment.md

filesystem.md

generator-discovery.md

generator-management.md

index.md

module-lookup.md

tile.json