CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-plop

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

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

generator-api.mddocs/

Generator API

Plop provides a comprehensive programmatic API for creating, configuring, and executing code generators. This API is primarily provided by the node-plop package that plop re-exports.

Capabilities

NodePlopAPI Creation

Create a new plop API instance for programmatic generator management.

/**
 * 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>;

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

Usage Examples:

import { nodePlop } from "plop";

// Create instance without plopfile
const plop = await nodePlop();

// Create instance with specific plopfile
const plop = await nodePlop('/path/to/plopfile.js');

// Create instance with configuration
const plop = await nodePlop('./plopfile.js', {
  force: true,
  destBasePath: './output'
});

Generator Management

Create and manage code generators programmatically.

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

/**
 * Retrieve a registered generator by name
 * @param name - Generator name
 * @returns PlopGenerator instance or undefined
 */
getGenerator(name: string): PlopGenerator;

/**
 * Get list of all registered generators
 * @returns Array of generator info objects
 */
getGeneratorList(): { name: string; description: string }[];

Generator Configuration:

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

type Prompts = DynamicPromptsFunction | PromptQuestion[];
type Actions = DynamicActionsFunction | ActionType[];

Usage Examples:

import { nodePlop } from "plop";

const plop = await nodePlop();

// Register a component generator
const componentGen = plop.setGenerator('component', {
  description: 'React component generator',
  prompts: [
    {
      type: 'input',
      name: 'name',
      message: 'Component name:'
    },
    {
      type: 'list',
      name: 'type',
      message: 'Component type:',
      choices: ['functional', 'class']
    }
  ],
  actions: [
    {
      type: 'add',
      path: 'src/components/{{name}}.jsx',
      templateFile: 'templates/component.hbs'
    }
  ]
});

// Get generator by name
const gen = plop.getGenerator('component');

// List all generators
const generators = plop.getGeneratorList();
console.log(generators);
// [{ name: 'component', description: 'React component generator' }]

Generator Execution

Execute generators programmatically with prompt handling and action processing.

interface PlopGenerator extends PlopGeneratorConfig {
  /**
   * Run generator prompts and collect user input
   * @param bypassArr - Optional array to bypass prompts with pre-filled answers
   * @returns Promise resolving to user answers
   */
  runPrompts(bypassArr?: string[]): Promise<any>;
  
  /**
   * Execute generator actions with provided answers
   * @param answers - Answers from prompts or provided data
   * @param hooks - Optional lifecycle hooks
   * @returns Promise resolving to execution results
   */
  runActions(answers: Answers, hooks?: PlopActionHooks): Promise<{
    changes: PlopActionHooksChanges[];
    failures: PlopActionHooksFailures[];
  }>;
}

Action Hooks Interface:

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

interface PlopActionHooksChanges {
  type: string;             // Action type that succeeded
  path: string;             // File path that was changed
}

interface PlopActionHooksFailures {
  type: string;             // Action type that failed
  path: string;             // File path that failed
  error: string;            // Error message
  message: string;          // Human-readable message
}

Usage Examples:

const plop = await nodePlop('./plopfile.js');
const generator = plop.getGenerator('component');

// Run with interactive prompts
const answers = await generator.runPrompts();

// Run with bypass data (skip prompts)
const answers = await generator.runPrompts(['MyComponent', 'functional']);

// Execute actions with hooks
const results = await generator.runActions(answers, {
  onSuccess: (change) => console.log(`✅ ${change.type}: ${change.path}`),
  onFailure: (failure) => console.error(`❌ ${failure.type}: ${failure.error}`),
  onComment: (msg) => console.log(`💬 ${msg}`)
});

console.log(`${results.changes.length} files changed`);
console.log(`${results.failures.length} failures`);

Dynamic Configuration

Use functions to dynamically configure prompts and actions based on runtime conditions.

/**
 * Function that returns prompts dynamically
 * @param inquirer - Inquirer instance for advanced prompt handling
 * @returns Promise resolving to prompt answers
 */
type DynamicPromptsFunction = (inquirer: Inquirer) => Promise<Answers>;

/**
 * Function that returns actions dynamically based on answers
 * @param data - Answers from prompts
 * @returns Array of actions to execute
 */
type DynamicActionsFunction = (data?: Answers) => ActionType[];

Usage Examples:

plop.setGenerator('advanced', {
  description: 'Advanced generator with dynamic configuration',
  
  // Dynamic prompts based on conditions
  prompts: async (inquirer) => {
    const answers = {};
    
    // Conditional prompting
    answers.type = await inquirer.prompt({
      type: 'list',
      name: 'type',
      choices: ['api', 'ui', 'test']
    });
    
    if (answers.type === 'api') {
      answers.methods = await inquirer.prompt({
        type: 'checkbox',
        name: 'methods',
        choices: ['GET', 'POST', 'PUT', 'DELETE']
      });
    }
    
    return answers;
  },
  
  // Dynamic actions based on answers
  actions: (data) => {
    const actions = [
      {
        type: 'add',
        path: `src/${data.type}/{{name}}.js`,
        templateFile: `templates/${data.type}.hbs`
      }
    ];
    
    if (data.type === 'api' && data.methods.includes('POST')) {
      actions.push({
        type: 'add',
        path: `src/${data.type}/{{name}}.test.js`,
        templateFile: 'templates/api-test.hbs'
      });
    }
    
    return actions;
  }
});

Path Management

Control file system paths and destination handling.

/**
 * Set the path to the plopfile for this instance
 * @param filePath - Absolute path to plopfile
 */
setPlopfilePath(filePath: string): void;

/**
 * Get the current plopfile path
 * @returns Current plopfile path
 */
getPlopfilePath(): string;

/**
 * Get the base destination path for file operations
 * @returns Base destination path
 */
getDestBasePath(): string;

Template Rendering

Render Handlebars templates with data outside of action context.

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

Usage Examples:

const plop = await nodePlop();

// Render template with data
const template = 'Hello {{name}}, welcome to {{project}}!';
const rendered = plop.renderString(template, {
  name: 'Alice',
  project: 'My App'
});
console.log(rendered); // "Hello Alice, welcome to My App!"

// Use with path templates
const pathTemplate = 'src/components/{{kebabCase name}}/{{pascalCase name}}.jsx';
const path = plop.renderString(pathTemplate, { name: 'MyComponent' });
console.log(path); // "src/components/my-component/MyComponent.jsx"

Install with Tessl CLI

npx tessl i tessl/npm-plop

docs

action-system.md

cli.md

console.md

generator-api.md

index.md

programmatic.md

template-system.md

tile.json