CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-turbo--gen

Extend a Turborepo with code generation utilities for creating workspaces and custom generators

Pending
Overview
Eval results
Files

custom-generators.mddocs/

Custom Generators

System for running custom plop-based generators with Turborepo integration, supporting both TypeScript and JavaScript generator configurations.

Capabilities

Run Function

Main function for executing custom generators programmatically.

/**
 * Execute a custom generator
 * @param generator - Name of the generator to run (undefined for interactive selection)
 * @param opts - Custom generator options
 * @returns Promise that resolves when generator execution is complete
 */
function run(generator: string | undefined, opts: CustomGeneratorCLIOptions): Promise<void>;

interface CustomGeneratorCLIOptions {
  /** Generator configuration file path */
  config?: string;
  /** Repository root directory */
  root?: string;
  /** Arguments passed directly to generator */
  args?: Array<string>;
}

Usage Examples:

import { run } from "@turbo/gen/dist/commands";

// Run with interactive generator selection
await run(undefined, {
  config: "./turbo/generators/config.js"
});

// Run specific generator
await run("my-component", {
  config: "./turbo/generators/config.js",
  args: ["name=Button", "type=component"]
});

// Run with custom config
await run("api-route", {
  config: "./custom-generators/config.ts",
  root: "/path/to/project"
});

Custom Generator Function

Low-level function for custom generator execution.

/**
 * Execute custom generator with detailed arguments
 * @param args - Custom generator arguments
 * @returns Promise that resolves when generation is complete
 */
function generate(args: CustomGeneratorArguments): Promise<void>;

interface CustomGeneratorArguments {
  generator: string | undefined;
  project: Project;
  opts: CustomGeneratorCLIOptions;
}

Usage Examples:

import { generate as customGenerate } from "@turbo/gen/dist/generators/custom";
import { getProject } from "@turbo/gen/dist/utils/getProject";

const project = await getProject({ root: process.cwd() });

await customGenerate({
  generator: "component",
  project,
  opts: {
    config: "./turbo/generators/config.js",
    args: ["name=MyComponent", "directory=components"]
  }
});

Plop Integration

Plop API Access

Get access to the underlying node-plop API for advanced generator operations.

/**
 * Get NodePlopAPI instance for direct plop operations
 * @param args - Plop configuration
 * @returns NodePlopAPI instance or undefined if config not found
 */
function getPlop(args: {
  project: Project;
  configPath?: string;
}): NodePlopAPI | undefined;

Generator Discovery

Find and list available custom generators.

/**
 * Get list of all available custom generators
 * @param args - Generator discovery configuration
 * @returns Array of generators or separators for UI display
 */
function getCustomGenerators(args: {
  project: Project;
  configPath?: string;
}): Array<Generator | Separator>;

/**
 * Get specific generator by name
 * @param args - Generator lookup configuration
 * @returns Generator name or undefined if not found
 */
function getCustomGenerator(args: {
  project: Project;
  generator: string;
  configPath?: string;
}): string | undefined;

type Generator = PlopGenerator & {
  basePath: string;
  name: string;
};

Generator Execution

Direct generator execution utilities.

/**
 * Run a custom generator with bypass arguments
 * @param args - Generator execution configuration
 * @returns Promise that resolves when generator completes
 */
function runCustomGenerator(args: {
  project: Project;
  generator: string;
  bypassArgs?: Array<string>;
  configPath?: string;
}): Promise<void>;

Usage Examples:

import { 
  getPlop, 
  getCustomGenerators, 
  getCustomGenerator,
  runCustomGenerator 
} from "@turbo/gen/dist/utils/plop";

// Get plop instance
const plop = getPlop({
  project,
  configPath: "./turbo/generators/config.js"
});

// Get all generators
const generators = getCustomGenerators({
  project,
  configPath: "./turbo/generators/config.js"
});

// Find specific generator
const generator = getCustomGenerator({
  project,
  generator: "component",
  configPath: "./turbo/generators/config.js"
});

// Run generator with arguments
await runCustomGenerator({
  project,
  generator: "component",
  bypassArgs: ["Button", "components/ui"],
  configPath: "./turbo/generators/config.js"
});

Template Setup

Template Initialization

Set up generator templates for new projects.

/**
 * Set up generator configuration from built-in templates
 * @param args - Template setup configuration
 * @returns Promise that resolves when template is set up
 */
function setupFromTemplate(args: {
  project: Project;
  template: "ts" | "js";
}): Promise<void>;

Usage Examples:

import { setupFromTemplate } from "@turbo/gen/dist/utils/setupFromTemplate";

// Set up TypeScript generator template
await setupFromTemplate({
  project,
  template: "ts"
});

// Set up JavaScript generator template
await setupFromTemplate({
  project,
  template: "js"
});

Interactive Prompts

Programmatic access to generator selection and setup prompts.

Generator Selection

/**
 * Prompt for generator selection from available generators
 * @param args - Generator selection configuration
 * @returns Promise with selected generator name
 */
function customGenerators(args: {
  generators: Array<Generator | Separator>;
  generator?: string;
}): Promise<{ selectedGenerator: string }>;

Template Choice

/**
 * Prompt for generator template language choice
 * @returns Promise with selected template type
 */
function chooseGeneratorTemplate(): Promise<{ answer: "ts" | "js" }>;

Confirmation Prompt

/**
 * Display confirmation prompt to user
 * @param args - Confirmation prompt configuration
 * @returns Promise with user's boolean response
 */
function confirm(args: { message: string }): Promise<{ answer: boolean }>;

Usage Examples:

import { 
  customGenerators, 
  chooseGeneratorTemplate, 
  confirm 
} from "@turbo/gen/dist/commands/run/prompts";

// Select generator
const generators = getCustomGenerators({ project });
const selection = await customGenerators({
  generators,
  generator: undefined
});

// Choose template type
const template = await chooseGeneratorTemplate();

// Confirm action
const confirmation = await confirm({
  message: "Are you sure you want to create this generator?"
});

Generator Configuration

Configuration File Structure

Custom generators are configured using node-plop configuration files:

TypeScript Configuration (turbo/generators/config.ts):

import type { PlopTypes } from "@turbo/gen";

const config: PlopTypes.PlopConfig = {
  generator: {
    description: "Create a new component",
    prompts: [
      {
        type: "input",
        name: "name",
        message: "Component name:",
        validate: (input: string) => input.length > 0
      }
    ],
    actions: [
      {
        type: "add",
        path: "{{ turbo.paths.root }}/packages/ui/src/{{ dashCase name }}.tsx",
        templateFile: "templates/component.hbs"
      }
    ]
  }
};

export default config;

JavaScript Configuration (turbo/generators/config.js):

module.exports = {
  generator: {
    description: "Create a new component",
    prompts: [
      {
        type: "input",
        name: "name",
        message: "Component name:"
      }
    ],
    actions: [
      {
        type: "add",
        path: "{{ turbo.paths.root }}/packages/ui/src/{{ dashCase name }}.tsx",
        templateFile: "templates/component.hbs"
      }
    ]
  }
};

Built-in Template Files

Turbo Gen includes built-in templates for generator setup:

  • TypeScript template: dist/templates/simple-ts/

    • config.ts - TypeScript generator configuration
    • templates/turborepo-generators.hbs - Handlebars template
    • package.json - Package metadata
  • JavaScript template: dist/templates/simple-js/

    • config.js - JavaScript generator configuration
    • templates/turborepo-generators.hbs - Handlebars template
    • package.json - Package metadata

Turbo-Specific Variables

Custom generators have access to Turbo-specific template variables:

{{ turbo.paths.root }} - Repository root path
{{ turbo.paths.workspace }} - Current workspace path
{{ turbo.generator.name }} - Generator name

Usage in Templates:

// Component template (component.hbs)
import React from 'react';

interface {{ pascalCase name }}Props {
  children?: React.ReactNode;
}

export const {{ pascalCase name }}: React.FC<{{ pascalCase name }}Props> = ({ children }) => {
  return <div className="{{ dashCase name }}">{children}</div>;
};

export default {{ pascalCase name }};

Error Handling

Custom generator operations can throw specific error types:

type GenerateErrorType =
  | "plop_error_running_generator"
  | "plop_unable_to_load_config"
  | "plop_generator_not_found"
  | "plop_no_config"
  | "config_directory_already_exists"
  | "unknown";

class GeneratorError extends Error {
  public type: GenerateErrorType;
  constructor(message: string, opts?: GeneratorErrorOptions);
}

interface GeneratorErrorOptions {
  type?: GenerateErrorType;
}

Common error scenarios:

  • Generator configuration file not found or invalid
  • Selected generator doesn't exist in configuration
  • Plop execution errors during file generation
  • Permission issues when creating files
  • Template file not found or malformed

Install with Tessl CLI

npx tessl i tessl/npm-turbo--gen

docs

cli-commands.md

custom-generators.md

generator-utilities.md

index.md

workspace-generation.md

tile.json