Extend a Turborepo with code generation utilities for creating workspaces and custom generators
—
Core utilities for generator development including project management, plop integration, and workspace operations.
Utilities for working with Turborepo project instances and configuration.
/**
* 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"
});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();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}`);
}
}Advanced utilities for working with node-plop and custom generators.
/**
* 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;/**
* 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"]
});
}Utilities for analyzing and working with workspace structures in monorepos.
/**
* 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;/**
* 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";/**
* 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"]Utilities for generator template setup and configuration.
/**
* 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/**
* 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);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";
});
}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
}
});
}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