or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

cli-commands.mdcustom-generators.mdgenerator-utilities.mdindex.mdworkspace-generation.md

custom-generators.mddocs/

0

# Custom Generators

1

2

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

3

4

## Capabilities

5

6

### Run Function

7

8

Main function for executing custom generators programmatically.

9

10

```typescript { .api }

11

/**

12

* Execute a custom generator

13

* @param generator - Name of the generator to run (undefined for interactive selection)

14

* @param opts - Custom generator options

15

* @returns Promise that resolves when generator execution is complete

16

*/

17

function run(generator: string | undefined, opts: CustomGeneratorCLIOptions): Promise<void>;

18

19

interface CustomGeneratorCLIOptions {

20

/** Generator configuration file path */

21

config?: string;

22

/** Repository root directory */

23

root?: string;

24

/** Arguments passed directly to generator */

25

args?: Array<string>;

26

}

27

```

28

29

**Usage Examples:**

30

31

```typescript

32

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

33

34

// Run with interactive generator selection

35

await run(undefined, {

36

config: "./turbo/generators/config.js"

37

});

38

39

// Run specific generator

40

await run("my-component", {

41

config: "./turbo/generators/config.js",

42

args: ["name=Button", "type=component"]

43

});

44

45

// Run with custom config

46

await run("api-route", {

47

config: "./custom-generators/config.ts",

48

root: "/path/to/project"

49

});

50

```

51

52

### Custom Generator Function

53

54

Low-level function for custom generator execution.

55

56

```typescript { .api }

57

/**

58

* Execute custom generator with detailed arguments

59

* @param args - Custom generator arguments

60

* @returns Promise that resolves when generation is complete

61

*/

62

function generate(args: CustomGeneratorArguments): Promise<void>;

63

64

interface CustomGeneratorArguments {

65

generator: string | undefined;

66

project: Project;

67

opts: CustomGeneratorCLIOptions;

68

}

69

```

70

71

**Usage Examples:**

72

73

```typescript

74

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

75

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

76

77

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

78

79

await customGenerate({

80

generator: "component",

81

project,

82

opts: {

83

config: "./turbo/generators/config.js",

84

args: ["name=MyComponent", "directory=components"]

85

}

86

});

87

```

88

89

## Plop Integration

90

91

### Plop API Access

92

93

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

94

95

```typescript { .api }

96

/**

97

* Get NodePlopAPI instance for direct plop operations

98

* @param args - Plop configuration

99

* @returns NodePlopAPI instance or undefined if config not found

100

*/

101

function getPlop(args: {

102

project: Project;

103

configPath?: string;

104

}): NodePlopAPI | undefined;

105

```

106

107

### Generator Discovery

108

109

Find and list available custom generators.

110

111

```typescript { .api }

112

/**

113

* Get list of all available custom generators

114

* @param args - Generator discovery configuration

115

* @returns Array of generators or separators for UI display

116

*/

117

function getCustomGenerators(args: {

118

project: Project;

119

configPath?: string;

120

}): Array<Generator | Separator>;

121

122

/**

123

* Get specific generator by name

124

* @param args - Generator lookup configuration

125

* @returns Generator name or undefined if not found

126

*/

127

function getCustomGenerator(args: {

128

project: Project;

129

generator: string;

130

configPath?: string;

131

}): string | undefined;

132

133

type Generator = PlopGenerator & {

134

basePath: string;

135

name: string;

136

};

137

```

138

139

### Generator Execution

140

141

Direct generator execution utilities.

142

143

```typescript { .api }

144

/**

145

* Run a custom generator with bypass arguments

146

* @param args - Generator execution configuration

147

* @returns Promise that resolves when generator completes

148

*/

149

function runCustomGenerator(args: {

150

project: Project;

151

generator: string;

152

bypassArgs?: Array<string>;

153

configPath?: string;

154

}): Promise<void>;

155

```

156

157

**Usage Examples:**

158

159

```typescript

160

import {

161

getPlop,

162

getCustomGenerators,

163

getCustomGenerator,

164

runCustomGenerator

165

} from "@turbo/gen/dist/utils/plop";

166

167

// Get plop instance

168

const plop = getPlop({

169

project,

170

configPath: "./turbo/generators/config.js"

171

});

172

173

// Get all generators

174

const generators = getCustomGenerators({

175

project,

176

configPath: "./turbo/generators/config.js"

177

});

178

179

// Find specific generator

180

const generator = getCustomGenerator({

181

project,

182

generator: "component",

183

configPath: "./turbo/generators/config.js"

184

});

185

186

// Run generator with arguments

187

await runCustomGenerator({

188

project,

189

generator: "component",

190

bypassArgs: ["Button", "components/ui"],

191

configPath: "./turbo/generators/config.js"

192

});

193

```

194

195

## Template Setup

196

197

### Template Initialization

198

199

Set up generator templates for new projects.

200

201

```typescript { .api }

202

/**

203

* Set up generator configuration from built-in templates

204

* @param args - Template setup configuration

205

* @returns Promise that resolves when template is set up

206

*/

207

function setupFromTemplate(args: {

208

project: Project;

209

template: "ts" | "js";

210

}): Promise<void>;

211

```

212

213

**Usage Examples:**

214

215

```typescript

216

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

217

218

// Set up TypeScript generator template

219

await setupFromTemplate({

220

project,

221

template: "ts"

222

});

223

224

// Set up JavaScript generator template

225

await setupFromTemplate({

226

project,

227

template: "js"

228

});

229

```

230

231

## Interactive Prompts

232

233

Programmatic access to generator selection and setup prompts.

234

235

### Generator Selection

236

237

```typescript { .api }

238

/**

239

* Prompt for generator selection from available generators

240

* @param args - Generator selection configuration

241

* @returns Promise with selected generator name

242

*/

243

function customGenerators(args: {

244

generators: Array<Generator | Separator>;

245

generator?: string;

246

}): Promise<{ selectedGenerator: string }>;

247

```

248

249

### Template Choice

250

251

```typescript { .api }

252

/**

253

* Prompt for generator template language choice

254

* @returns Promise with selected template type

255

*/

256

function chooseGeneratorTemplate(): Promise<{ answer: "ts" | "js" }>;

257

```

258

259

### Confirmation Prompt

260

261

```typescript { .api }

262

/**

263

* Display confirmation prompt to user

264

* @param args - Confirmation prompt configuration

265

* @returns Promise with user's boolean response

266

*/

267

function confirm(args: { message: string }): Promise<{ answer: boolean }>;

268

```

269

270

**Usage Examples:**

271

272

```typescript

273

import {

274

customGenerators,

275

chooseGeneratorTemplate,

276

confirm

277

} from "@turbo/gen/dist/commands/run/prompts";

278

279

// Select generator

280

const generators = getCustomGenerators({ project });

281

const selection = await customGenerators({

282

generators,

283

generator: undefined

284

});

285

286

// Choose template type

287

const template = await chooseGeneratorTemplate();

288

289

// Confirm action

290

const confirmation = await confirm({

291

message: "Are you sure you want to create this generator?"

292

});

293

```

294

295

## Generator Configuration

296

297

### Configuration File Structure

298

299

Custom generators are configured using node-plop configuration files:

300

301

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

302

303

```typescript

304

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

305

306

const config: PlopTypes.PlopConfig = {

307

generator: {

308

description: "Create a new component",

309

prompts: [

310

{

311

type: "input",

312

name: "name",

313

message: "Component name:",

314

validate: (input: string) => input.length > 0

315

}

316

],

317

actions: [

318

{

319

type: "add",

320

path: "{{ turbo.paths.root }}/packages/ui/src/{{ dashCase name }}.tsx",

321

templateFile: "templates/component.hbs"

322

}

323

]

324

}

325

};

326

327

export default config;

328

```

329

330

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

331

332

```javascript

333

module.exports = {

334

generator: {

335

description: "Create a new component",

336

prompts: [

337

{

338

type: "input",

339

name: "name",

340

message: "Component name:"

341

}

342

],

343

actions: [

344

{

345

type: "add",

346

path: "{{ turbo.paths.root }}/packages/ui/src/{{ dashCase name }}.tsx",

347

templateFile: "templates/component.hbs"

348

}

349

]

350

}

351

};

352

```

353

354

### Built-in Template Files

355

356

Turbo Gen includes built-in templates for generator setup:

357

358

- **TypeScript template**: `dist/templates/simple-ts/`

359

- `config.ts` - TypeScript generator configuration

360

- `templates/turborepo-generators.hbs` - Handlebars template

361

- `package.json` - Package metadata

362

363

- **JavaScript template**: `dist/templates/simple-js/`

364

- `config.js` - JavaScript generator configuration

365

- `templates/turborepo-generators.hbs` - Handlebars template

366

- `package.json` - Package metadata

367

368

### Turbo-Specific Variables

369

370

Custom generators have access to Turbo-specific template variables:

371

372

```handlebars

373

{{ turbo.paths.root }} - Repository root path

374

{{ turbo.paths.workspace }} - Current workspace path

375

{{ turbo.generator.name }} - Generator name

376

```

377

378

**Usage in Templates:**

379

380

```handlebars

381

// Component template (component.hbs)

382

import React from 'react';

383

384

interface {{ pascalCase name }}Props {

385

children?: React.ReactNode;

386

}

387

388

export const {{ pascalCase name }}: React.FC<{{ pascalCase name }}Props> = ({ children }) => {

389

return <div className="{{ dashCase name }}">{children}</div>;

390

};

391

392

export default {{ pascalCase name }};

393

```

394

395

## Error Handling

396

397

Custom generator operations can throw specific error types:

398

399

```typescript { .api }

400

type GenerateErrorType =

401

| "plop_error_running_generator"

402

| "plop_unable_to_load_config"

403

| "plop_generator_not_found"

404

| "plop_no_config"

405

| "config_directory_already_exists"

406

| "unknown";

407

408

class GeneratorError extends Error {

409

public type: GenerateErrorType;

410

constructor(message: string, opts?: GeneratorErrorOptions);

411

}

412

413

interface GeneratorErrorOptions {

414

type?: GenerateErrorType;

415

}

416

```

417

418

Common error scenarios:

419

- Generator configuration file not found or invalid

420

- Selected generator doesn't exist in configuration

421

- Plop execution errors during file generation

422

- Permission issues when creating files

423

- Template file not found or malformed