Handles the lifecycle and bootstrapping of generators in a specific environment
CLI command creation and management with Commander.js integration for generator commands and environment interaction.
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");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 filesPrepare 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());
});The package includes a yoe CLI binary for direct generator interaction.
# Run a generator
yoe run <namespace> [generator-options]
# Find installed generators
yoe find
# List available generators
yoe list
# Get help
yoe --helpExamples:
# 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 listComplete 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);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);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));
});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