or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

action-system.mdcli.mdconsole.mdgenerator-api.mdindex.mdprogrammatic.mdtemplate-system.md
tile.json

tessl/npm-plop

Micro-generator framework that makes it easy for an entire team to create files with a level of uniformity

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/plop@4.0.x

To install, run

npx @tessl/cli install tessl/npm-plop@4.0.0

index.mddocs/

Plop

Plop is a micro-generator framework that makes it easy for development teams to create files with consistent patterns and structures. It combines interactive command-line prompts with Handlebars templates to automate the generation of boilerplate code, components, routes, controllers, and other repetitive file structures. By codifying file creation patterns, Plop helps maintain coding standards and best practices across teams.

Package Information

  • Package Name: plop
  • Package Type: npm
  • Language: JavaScript (Node.js)
  • Installation: npm install -g plop or npm install --save-dev plop

Core Imports

For CLI programmatic usage:

import { Plop, run } from "plop";

For advanced programmatic usage (direct node-plop access):

import { nodePlop } from "plop";
// or
import nodePlop from "node-plop";

For CommonJS:

const { Plop, run } = require("plop");
const { nodePlop } = require("plop");

For CLI usage, no imports needed - use the plop command directly.

Basic Usage

CLI Usage

# Install globally
npm install -g plop

# Run plop (shows generator list)
plop

# Run specific generator
plop component

# Run generator with bypass data
plop component "MyComponent"

Programmatic Usage

import { Plop, run } from "plop";
import path from "node:path";

// Prepare and execute plop programmatically
Plop.prepare({
  cwd: process.cwd(),
  configPath: path.join(__dirname, 'plopfile.js'),
}, env => Plop.execute(env, run));

Architecture

Plop is built around several key components:

  • CLI Interface: Primary user interaction through terminal commands with argument parsing and help system
  • Liftoff Integration: Configuration file discovery and environment setup for finding plopfiles
  • Generator System: Integration with node-plop for executing generators with prompts and actions
  • Progress Feedback: Visual progress indicators using Ora spinners during file generation
  • Bypass System: Allows skipping prompts by providing values directly via CLI arguments

Capabilities

Command Line Interface

Full-featured CLI for running generators interactively or with bypass data. Includes help system, version information, and initialization commands.

// CLI entry point from bin/plop.js
import { Plop, run } from "../src/plop.js";

Plop.prepare(options, function (env) {
  Plop.execute(env, run);
});

Command Line Interface

Programmatic Execution

Core execution functions for embedding Plop functionality in custom tools and workflows.

/**
 * Main execution function for plop generators
 * @param env - Environment object from Liftoff containing configuration
 * @param _ - Unused parameter for compatibility
 * @param passArgsBeforeDashes - Optional boolean to merge CLI and generator args
 * @returns Promise resolving to plop instance
 */
async function run(env, _, passArgsBeforeDashes);

/**
 * Liftoff instance configured for plop
 */
const Plop: Liftoff;

/**
 * Ora spinner instance for progress indication
 */
const progressSpinner: ora.Ora;

Programmatic Usage

Generator Management API

Comprehensive programmatic API for creating, configuring, and executing code generators through the node-plop package.

/**
 * Create a new NodePlopAPI instance
 * @param plopfilePath - Optional absolute path to plopfile
 * @param plopCfg - Optional configuration object
 * @returns Promise resolving to NodePlopAPI instance
 */
function nodePlop(plopfilePath?: string, plopCfg?: PlopCfg): Promise<NodePlopAPI>;

/**
 * Register a new generator
 * @param name - Unique generator name
 * @param config - Generator configuration
 * @returns PlopGenerator instance
 */
setGenerator(name: string, config: Partial<PlopGeneratorConfig>): PlopGenerator;

/**
 * Execute generator prompts and actions
 * @param bypassArr - Optional array to bypass prompts
 * @returns Promise resolving to user answers
 */
runPrompts(bypassArr?: string[]): Promise<any>;

Generator Management

Template System

Handlebars templating with built-in helpers, custom helpers, and partials for flexible file generation.

/**
 * Register a custom Handlebars helper
 * @param name - Helper name for use in templates
 * @param fn - Helper function
 */
setHelper(name: string, fn: HelperFunction): void;

/**
 * Register a Handlebars partial
 * @param name - Partial name for use in templates
 * @param str - Partial template string
 */
setPartial(name: string, str: string): void;

/**
 * Render a Handlebars template string with data
 * @param template - Handlebars template string
 * @param data - Data object for template rendering
 * @returns Rendered string
 */
renderString(template: string, data: any): string;

Template System

Action System

Built-in file operations (add, addMany, modify, append) and support for custom actions.

/**
 * Register a custom action type
 * @param name - Action type name
 * @param fn - Action function
 */
setActionType(name: string, fn: CustomActionFunction): void;

// Built-in action configuration interfaces
interface AddActionConfig extends ActionConfig {
  type: "add";
  path: string;
  skipIfExists?: boolean;
} & TemplateStrOrFile;

interface ModifyActionConfig extends ActionConfig {
  type: "modify";
  path: string;
  pattern: string | RegExp;
} & TemplateStrOrFile;

Action System

Console Output and User Interface

User interface functions for displaying help, selecting generators, and creating initial plopfiles.

/**
 * Display generator selection list to user
 * @param plopList - Array of available generators
 * @param message - Optional custom selection message
 * @returns Promise resolving to selected generator name
 */
async function chooseOptionFromList(plopList, message);

/**
 * Display help screen with usage information
 */
function displayHelpScreen();

/**
 * Create initial plopfile.js or plopfile.ts
 * @param force - Overwrite existing plopfile if present
 * @param useTypescript - Generate TypeScript plopfile
 */
function createInitPlopfile(force, useTypescript);

Console Interface

Types

// Core configuration types
interface PlopCfg {
  force?: boolean;           // Force overwrite existing files
  destBasePath?: string;     // Base path for file operations
}

interface PlopGeneratorConfig {
  description: string;       // Human-readable description
  prompts: Prompts;         // Inquirer prompts or function
  actions: Actions;         // Actions to perform or function
}

// Generator and API interfaces
interface NodePlopAPI {
  setGenerator(name: string, config: Partial<PlopGeneratorConfig>): PlopGenerator;
  getGenerator(name: string): PlopGenerator;
  getGeneratorList(): { name: string; description: string }[];
  setHelper(name: string, fn: HelperFunction): void;
  setPartial(name: string, str: string): void;
  setActionType(name: string, fn: CustomActionFunction): void;
  renderString(template: string, data: any): string;
}

interface PlopGenerator extends PlopGeneratorConfig {
  runPrompts(bypassArr?: string[]): Promise<any>;
  runActions(answers: Answers, hooks?: PlopActionHooks): Promise<{
    changes: PlopActionHooksChanges[];
    failures: PlopActionHooksFailures[];
  }>;
}

// Action configuration types
interface ActionConfig {
  type: string;             // Action type name
  force?: boolean;          // Force overwrite
  data?: object;            // Additional template data
  abortOnFail?: boolean;    // Abort on action failure
  skip?: Function;          // Conditional skip function
}

interface AddActionConfig extends ActionConfig {
  type: "add";
  path: string;
  skipIfExists?: boolean;
} & TemplateStrOrFile;

interface AddManyActionConfig extends ActionConfig {
  type: "addMany";
  destination: string;
  base: string;
  templateFiles: string | string[];
  stripExtensions?: string[];
  globOptions?: GlobOptions;
  verbose?: boolean;
}

interface ModifyActionConfig extends ActionConfig {
  type: "modify";
  path: string;
  pattern: string | RegExp;
} & TemplateStrOrFile;

interface AppendActionConfig extends ActionConfig {
  type: "append";
  path: string;
  pattern: string | RegExp;
  unique?: boolean;
  separator?: string;
} & TemplateStrOrFile;

// Template and prompt types
interface TemplateStrOrFile {
  template?: string;        // Inline template string
  templateFile?: string;    // Path to template file
}

type Prompts = DynamicPromptsFunction | PromptQuestion[];
type Actions = DynamicActionsFunction | ActionType[];
type ActionType = AddActionConfig | AddManyActionConfig | ModifyActionConfig | AppendActionConfig | CustomActionConfig<string>;

type DynamicPromptsFunction = (inquirer: Inquirer) => Promise<Answers>;
type DynamicActionsFunction = (data?: Answers) => ActionType[];
type CustomActionFunction = (
  answers: Answers,
  config: CustomActionConfig<string>,
  plopfileApi: NodePlopAPI,
) => Promise<string> | string;

// Hook system types
interface PlopActionHooks {
  onComment?: (msg: string) => void;
  onSuccess?: (change: PlopActionHooksChanges) => void;
  onFailure?: (failure: PlopActionHooksFailures) => void;
}

interface PlopActionHooksChanges {
  type: string;
  path: string;
}

interface PlopActionHooksFailures {
  type: string;
  path: string;
  error: string;
  message: string;
}

// CLI and environment types
interface EnvironmentOptions {
  cwd?: string;
  preload?: string[];
  configPath?: string;
  completion?: any;
}

interface GeneratorInfo {
  name: string;
  description?: string;
}

// External library types
interface Liftoff {
  prepare(options: PrepareOptions, callback: (env: LiftoffEnvironment) => void): void;
  execute(env: LiftoffEnvironment, run: Function): any;
}

interface PrepareOptions {
  cwd?: string;
  preload?: string[];
  configPath?: string;
  completion?: any;
}

interface LiftoffEnvironment {
  configPath: string;
  cwd: string;
  require: Function;
  configName: string;
  configBase: string;
  configNameSearch: string[];
  modulePackage: object;
  modules: object;
}

interface Ora {
  start(): Ora;
  stop(): Ora;
  succeed(text?: string): Ora;
  fail(text?: string): Ora;
  info(text?: string): Ora;
}