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

generator-utilities.mddocs/

Generator Utilities

Core utilities for generator development including project management, plop integration, and workspace operations.

Capabilities

Project Management

Utilities for working with Turborepo project instances and configuration.

Project Instance

/**
 * Get Turborepo project instance from repository root
 * @param args - Project configuration
 * @returns Promise with Project instance for the repository
 */
function getProject(args: { root?: string }): Promise<Project>;

Usage Examples:

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

// Get project from current directory
const project = await getProject({});

// Get project from specific root
const project = await getProject({
  root: "/path/to/turborepo"
});

Update Notifications

Check for package updates and notify users.

/**
 * Check for package updates and display notification
 * @returns Promise that resolves when update check is complete
 */
function notifyUpdate(): Promise<void>;

Usage Examples:

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

// Check for updates (typically called after command completion)
await notifyUpdate();

Error Handling

Specialized error types for generator operations.

/**
 * Custom error class for generator operations
 */
class GeneratorError extends Error {
  public type: GenerateErrorType;
  
  constructor(message: string, opts?: GeneratorErrorOptions);
}

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

interface GeneratorErrorOptions {
  type?: GenerateErrorType;
}

Usage Examples:

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

// Throw specific error type
throw new GeneratorError("Generator not found", {
  type: "plop_generator_not_found"
});

// Catch and handle generator errors
try {
  await runCustomGenerator(args);
} catch (error) {
  if (error instanceof GeneratorError) {
    console.error(`Generator error (${error.type}): ${error.message}`);
  }
}

Plop Integration Utilities

Advanced utilities for working with node-plop and custom generators.

Plop API Access

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

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

/**
 * Execute a custom generator with optional 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>;

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

Usage Examples:

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

const project = await getProject({});

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

if (plop) {
  // Access plop directly for custom operations
  const generator = plop.getGenerator("component");
  await plop.runGenerator(generator, { name: "MyComponent" });
}

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

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

if (componentGenerator) {
  // Run the generator
  await runCustomGenerator({
    project,
    generator: "component",
    bypassArgs: ["Button", "ui/components"]
  });
}

Workspace Utilities

Utilities for analyzing and working with workspace structures in monorepos.

Workspace Analysis

/**
 * Analyze workspace structure in the monorepo
 * @param args - Project instance
 * @returns Detailed workspace structure information
 */
function getWorkspaceStructure(args: {
  project: Project;
}): WorkspaceStructure;

interface WorkspaceStructure {
  hasRootApps: boolean;
  hasRootPackages: boolean;
  workspacesByGroup: Record<string, Array<Workspace>>;
  nonAppWorkspaces: Array<Workspace>;
}

/**
 * Get group name for a workspace based on its location
 * @param args - Project and workspace
 * @returns Group name for the workspace
 */
function getGroupFromWorkspace(args: {
  project: Project;
  workspace: Workspace;
}): string;

Workspace Listing

/**
 * Get filtered list of workspaces for selection or processing
 * @param args - Project and filtering options
 * @returns Array of workspaces or separators for UI
 */
function getWorkspaceList(args: {
  project: Project;
  type: WorkspaceType;
  showAllDependencies?: boolean;
}): Array<Workspace | Separator>;

type WorkspaceType = "app" | "package";

Workspace Roots

/**
 * Get workspace root directories from project configuration
 * @param args - Project instance
 * @returns Array of workspace root directory paths
 */
function getWorkspaceRoots(args: {
  project: Project;
}): Array<string>;

Usage Examples:

import { 
  getWorkspaceStructure, 
  getGroupFromWorkspace,
  getWorkspaceList,
  getWorkspaceRoots 
} from "@turbo/gen/dist/utils";

const project = await getProject({});

// Analyze workspace structure
const structure = getWorkspaceStructure({ project });
console.log("Has root apps:", structure.hasRootApps);
console.log("Workspaces by group:", structure.workspacesByGroup);

// Get group for specific workspace
const workspace = structure.workspacesByGroup["packages"][0];
const group = getGroupFromWorkspace({ project, workspace });
console.log("Workspace group:", group);

// Get filtered workspace list
const packages = getWorkspaceList({
  project,
  type: "package",
  showAllDependencies: false
});

// Get workspace roots
const roots = getWorkspaceRoots({ project });
console.log("Workspace roots:", roots); // ["apps", "packages", "tools"]

Template and Setup Utilities

Utilities for generator template setup and configuration.

Template Setup

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

const project = await getProject({});

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

// This creates:
// - turbo/generators/ directory
// - turbo/generators/config.ts
// - turbo/generators/templates/
// - turbo/generators/package.json

Requirement Gathering

/**
 * Gather all requirements for workspace creation including interactive prompts
 * @param args - Generator arguments
 * @returns Promise with collected workspace requirements
 */
function gatherAddRequirements(args: TurboGeneratorArguments): Promise<{
  type: WorkspaceType;
  name: string;
  location: { absolute: string; relative: string };
  source: Workspace | undefined;
  dependencies: DependencyGroups;
}>;

interface TurboGeneratorArguments {
  project: Project;
  opts: TurboGeneratorOptions;
}

interface DependencyGroups {
  dependencies: string[];
  devDependencies: string[];
  peerDependencies: string[];
}

Usage Examples:

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

const project = await getProject({});

const requirements = await gatherAddRequirements({
  project,
  opts: {
    name: "my-package",
    type: "package",
    method: "empty",
    copy: { type: "internal", source: "" },
    showAllDependencies: false
  }
});

console.log("Workspace name:", requirements.name);
console.log("Location:", requirements.location);
console.log("Dependencies:", requirements.dependencies);

Advanced Usage Patterns

Custom Generator Development

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

// Set up a new generator project
const project = await getProject({});

// Initialize generator template
await setupFromTemplate({
  project,
  template: "ts"
});

// Get plop instance for custom generator registration
const plop = getPlop({
  project,
  configPath: "./turbo/generators/config.ts"
});

if (plop) {
  // Register custom helper
  plop.setHelper("capitalize", (text: string) => 
    text.charAt(0).toUpperCase() + text.slice(1)
  );
  
  // Add custom action type
  plop.setActionType("custom-action", (answers, config) => {
    // Custom action implementation
    return "Custom action completed";
  });
}

Workspace Operations

import { 
  getProject,
  getWorkspaceStructure,
  getWorkspaceList,
  generate 
} from "@turbo/gen/dist/utils";

const project = await getProject({});

// Analyze current workspace structure
const structure = getWorkspaceStructure({ project });

// Find available packages to copy from
const availablePackages = getWorkspaceList({
  project,
  type: "package",
  showAllDependencies: false
});

// Create new workspace based on existing one
if (availablePackages.length > 0) {
  const sourceWorkspace = availablePackages[0];
  
  await generate({
    project,
    opts: {
      name: "new-package",
      type: "package",
      method: "copy",
      copy: {
        type: "internal",
        source: sourceWorkspace.name
      },
      showAllDependencies: false
    }
  });
}

Error Handling Best Practices

import { GeneratorError } from "@turbo/gen/dist/utils/error";
import { runCustomGenerator } from "@turbo/gen/dist/utils/plop";

async function safeGeneratorExecution() {
  try {
    const project = await getProject({});
    
    await runCustomGenerator({
      project,
      generator: "component",
      configPath: "./turbo/generators/config.js"
    });
    
  } catch (error) {
    if (error instanceof GeneratorError) {
      switch (error.type) {
        case "plop_generator_not_found":
          console.error("Generator not found. Check your config file.");
          break;
        case "plop_unable_to_load_config":
          console.error("Unable to load generator config. Check file path and syntax.");
          break;
        case "plop_error_running_generator":
          console.error("Error during generator execution:", error.message);
          break;
        default:
          console.error("Unknown generator error:", error.message);
      }
    } else {
      console.error("Unexpected error:", error);
    }
  }
}

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