0
# Generator System and Management
1
2
The generator system domain provides comprehensive generator lifecycle management including initialization, execution, cleanup, and registry management for both JSON-RPC and in-process generators.
3
4
## Classes
5
6
### Abstract Generator Base Class
7
8
#### `Generator`
9
10
Abstract base class for all generator implementations providing common interface and lifecycle management.
11
12
```typescript { .api }
13
abstract class Generator {
14
abstract init(): Promise<void>
15
abstract generate(): Promise<void>
16
abstract setOptions(options: GeneratorOptions): void
17
abstract setBinaryPaths(binaryPaths: BinaryPaths): void
18
abstract getPrettyName(): string
19
abstract getProvider(): string
20
abstract stop(): void
21
}
22
```
23
24
**Methods:**
25
- `init(): Promise<void>` - Initialize the generator
26
- `generate(): Promise<void>` - Execute generation process
27
- `setOptions(options: GeneratorOptions): void` - Set generator options
28
- `setBinaryPaths(binaryPaths: BinaryPaths): void` - Set binary paths for engines
29
- `getPrettyName(): string` - Get display name for UI
30
- `getProvider(): string` - Get provider name/identifier
31
- `stop(): void` - Stop and cleanup the generator
32
33
### JSON-RPC Generator Implementation
34
35
#### `JsonRpcGenerator`
36
37
Generator implementation for JSON-RPC based external generators that communicate via process IPC.
38
39
```typescript { .api }
40
class JsonRpcGenerator extends Generator {
41
constructor(
42
executablePath: string,
43
config: GeneratorConfig,
44
isNode?: boolean
45
)
46
}
47
```
48
49
**Constructor Parameters:**
50
- `executablePath: string` - Path to the generator executable
51
- `config: GeneratorConfig` - Generator configuration
52
- `isNode?: boolean` - Whether the generator is a Node.js process
53
54
**Example:**
55
```typescript
56
const generator = new JsonRpcGenerator(
57
'/path/to/prisma-client-generator',
58
{
59
name: 'client',
60
provider: 'prisma-client-js',
61
output: './node_modules/.prisma/client',
62
config: {},
63
binaryTargets: ['native']
64
},
65
true // is Node.js
66
)
67
68
await generator.init()
69
await generator.generate()
70
generator.stop()
71
```
72
73
### In-Process Generator Implementation
74
75
#### `InProcessGenerator`
76
77
Generator implementation for in-process generators that run directly within the same Node.js process.
78
79
```typescript { .api }
80
class InProcessGenerator extends Generator {
81
constructor(config: GeneratorConfig, generator: IGenerator)
82
}
83
```
84
85
**Constructor Parameters:**
86
- `config: GeneratorConfig` - Generator configuration
87
- `generator: IGenerator` - Generator implementation interface
88
89
**Example:**
90
```typescript
91
const inProcessGen = new InProcessGenerator(
92
config,
93
{
94
onManifest: () => Promise.resolve(manifest),
95
onGenerate: (options) => Promise.resolve()
96
}
97
)
98
```
99
100
## Functions
101
102
### Generator Factory Functions
103
104
#### `getGenerators(options)`
105
106
Factory function that creates and initializes all generators from schema configuration.
107
108
```typescript { .api }
109
function getGenerators(options: GetGeneratorOptions): Promise<Generator[]>
110
```
111
112
**GetGeneratorOptions:**
113
```typescript { .api }
114
interface GetGeneratorOptions {
115
schemaPath?: string // Path to schema file
116
cwd?: string // Current working directory
117
schemaContent?: string // Schema content (alternative to schemaPath)
118
generators?: GeneratorConfig[] // Explicit generator configurations
119
generatorRegistry?: GeneratorRegistry // Registry of available generators
120
skipDownload?: boolean // Skip binary downloads
121
printDownloadProgress?: boolean // Show download progress
122
version?: string // Prisma version
123
engineVersion?: string // Engine version
124
}
125
```
126
127
**Returns:** `Promise<Generator[]>` - Array of initialized generators
128
129
**Example:**
130
```typescript
131
const generators = await getGenerators({
132
schemaPath: './prisma/schema.prisma',
133
cwd: process.cwd(),
134
printDownloadProgress: true,
135
skipDownload: false
136
})
137
138
console.log(`Initialized ${generators.length} generators`)
139
140
// Run all generators
141
for (const generator of generators) {
142
await generator.generate()
143
console.log(`✓ ${generator.getPrettyName()}`)
144
}
145
146
// Cleanup
147
generators.forEach(gen => gen.stop())
148
```
149
150
#### `getGenerator(options)`
151
152
Shortcut function for getting a single generator instance (useful for testing and single-generator scenarios).
153
154
```typescript { .api }
155
function getGenerator(options: GetGeneratorOptions): Promise<Generator>
156
```
157
158
**Parameters:** Same as `getGenerators`
159
160
**Returns:** `Promise<Generator>` - Single generator instance
161
162
**Example:**
163
```typescript
164
const generator = await getGenerator({
165
schemaContent: `
166
generator client {
167
provider = "prisma-client-js"
168
output = "./generated/client"
169
}
170
`,
171
cwd: process.cwd()
172
})
173
174
await generator.generate()
175
```
176
177
### Generator Utility Functions
178
179
#### `fixBinaryTargets(schemaBinaryTargets, runtimeBinaryTarget)`
180
181
Fixes binary targets by adding native or runtime target as needed to ensure generators can run properly.
182
183
```typescript { .api }
184
function fixBinaryTargets(
185
schemaBinaryTargets: BinaryTargetsEnvValue[],
186
runtimeBinaryTarget: BinaryTarget | string
187
): BinaryTargetsEnvValue[]
188
```
189
190
**Parameters:**
191
- `schemaBinaryTargets: BinaryTargetsEnvValue[]` - Binary targets from schema
192
- `runtimeBinaryTarget: BinaryTarget | string` - Runtime binary target
193
194
**Returns:** `BinaryTargetsEnvValue[]` - Fixed binary targets including necessary runtime targets
195
196
**Example:**
197
```typescript
198
import { fixBinaryTargets, getBinaryTargetForCurrentPlatform } from '@prisma/internals'
199
200
const schemaBinaryTargets = [{ fromEnvVar: null, value: 'linux-musl' }]
201
const runtimeTarget = getBinaryTargetForCurrentPlatform()
202
203
const fixedTargets = fixBinaryTargets(schemaBinaryTargets, runtimeTarget)
204
console.log('Fixed binary targets:', fixedTargets)
205
// Ensures current platform is included if not already specified
206
```
207
208
#### `printGeneratorConfig(config)`
209
210
Formats generator configuration as a readable string for debugging and logging.
211
212
```typescript { .api }
213
function printGeneratorConfig(config: GeneratorConfig): string
214
```
215
216
**Parameters:**
217
- `config: GeneratorConfig` - Generator configuration to format
218
219
**Returns:** `string` - Formatted configuration string
220
221
**Example:**
222
```typescript
223
const config: GeneratorConfig = {
224
name: 'client',
225
provider: 'prisma-client-js',
226
output: './generated/client',
227
config: { engineType: 'binary' },
228
binaryTargets: ['native', 'linux-musl']
229
}
230
231
console.log(printGeneratorConfig(config))
232
// Output:
233
// generator client {
234
// provider = "prisma-client-js"
235
// output = "./generated/client"
236
// engineType = "binary"
237
// binaryTargets = ["native", "linux-musl"]
238
// }
239
```
240
241
## Types and Interfaces
242
243
### Registry Types
244
245
#### `GeneratorRegistry`
246
247
Registry mapping generator providers to their implementations.
248
249
```typescript { .api }
250
type GeneratorRegistry = Record<string, GeneratorRegistryEntry>
251
```
252
253
#### `GeneratorRegistryEntry`
254
255
Union type for registry entries supporting both RPC and in-process generators.
256
257
```typescript { .api }
258
type GeneratorRegistryEntry =
259
| {
260
type: 'rpc'
261
generatorPath: string
262
isNode?: boolean
263
}
264
| {
265
type: 'in-process'
266
generator: IGenerator
267
}
268
```
269
270
**RPC Registry Entry:**
271
- `type: 'rpc'` - Indicates JSON-RPC generator
272
- `generatorPath: string` - Path to generator executable
273
- `isNode?: boolean` - Whether generator is Node.js based
274
275
**In-Process Registry Entry:**
276
- `type: 'in-process'` - Indicates in-process generator
277
- `generator: IGenerator` - Generator implementation
278
279
**Example:**
280
```typescript
281
const registry: GeneratorRegistry = {
282
'prisma-client-js': {
283
type: 'rpc',
284
generatorPath: './node_modules/.prisma/client/generator-build/index.js',
285
isNode: true
286
},
287
'custom-generator': {
288
type: 'in-process',
289
generator: {
290
onManifest: () => Promise.resolve(customManifest),
291
onGenerate: (options) => customGenerate(options)
292
}
293
}
294
}
295
```
296
297
### Generator Interface Types
298
299
#### `IGenerator`
300
301
Interface for in-process generator implementations.
302
303
```typescript { .api }
304
interface IGenerator {
305
onManifest(config: GeneratorConfig): Promise<GeneratorManifest>
306
onGenerate(options: GeneratorOptions): Promise<void>
307
}
308
```
309
310
**Methods:**
311
- `onManifest(config: GeneratorConfig): Promise<GeneratorManifest>` - Return generator manifest
312
- `onGenerate(options: GeneratorOptions): Promise<void>` - Execute generation
313
314
#### `GeneratorManifest`
315
316
Manifest describing generator capabilities and requirements.
317
318
```typescript { .api }
319
interface GeneratorManifest {
320
prettyName?: string // Display name
321
defaultOutput?: string // Default output directory
322
denylist?: string[] // Unsupported features
323
requiresGenerators?: string[] // Required other generators
324
requiresEngines?: string[] // Required engine binaries
325
version: string // Generator version
326
}
327
```
328
329
#### `BinaryPaths`
330
331
Paths to engine binaries required by generators.
332
333
```typescript { .api }
334
interface BinaryPaths {
335
queryEngine?: string // Query engine binary path
336
schemaEngine?: string // Schema engine binary path
337
libqueryEngine?: string // Query engine library path
338
migrationEngine?: string // Migration engine binary path (legacy)
339
}
340
```
341
342
## Examples
343
344
### Complete Generator Lifecycle Management
345
346
```typescript
347
import {
348
getGenerators,
349
printGeneratorConfig,
350
fixBinaryTargets,
351
getBinaryTargetForCurrentPlatform
352
} from '@prisma/internals'
353
354
async function runGenerationPipeline() {
355
try {
356
// Get all generators from schema
357
const generators = await getGenerators({
358
schemaPath: './prisma/schema.prisma',
359
cwd: process.cwd(),
360
printDownloadProgress: true
361
})
362
363
console.log(`Found ${generators.length} generators`)
364
365
// Initialize all generators
366
for (const generator of generators) {
367
console.log(`Initializing ${generator.getPrettyName()}...`)
368
await generator.init()
369
}
370
371
// Set binary paths for all generators
372
const binaryPaths = {
373
queryEngine: '/path/to/query-engine',
374
schemaEngine: '/path/to/schema-engine'
375
}
376
377
generators.forEach(gen => {
378
gen.setBinaryPaths(binaryPaths)
379
})
380
381
// Generate with each generator
382
for (const generator of generators) {
383
const startTime = Date.now()
384
385
console.log(`Generating ${generator.getPrettyName()}...`)
386
await generator.generate()
387
388
const duration = Date.now() - startTime
389
console.log(`✓ Generated ${generator.getPrettyName()} (${duration}ms)`)
390
}
391
392
console.log('All generators completed successfully')
393
394
} catch (error) {
395
console.error('Generation failed:', error)
396
throw error
397
} finally {
398
// Always cleanup generators
399
if (generators) {
400
generators.forEach(gen => {
401
try {
402
gen.stop()
403
} catch (stopError) {
404
console.warn(`Failed to stop generator: ${stopError.message}`)
405
}
406
})
407
}
408
}
409
}
410
```
411
412
### Custom In-Process Generator
413
414
```typescript
415
import { InProcessGenerator, type IGenerator, type GeneratorManifest } from '@prisma/internals'
416
417
// Define custom generator
418
const customGenerator: IGenerator = {
419
async onManifest(config): Promise<GeneratorManifest> {
420
return {
421
prettyName: 'Custom TypeScript Generator',
422
defaultOutput: './generated/custom',
423
version: '1.0.0',
424
requiresEngines: ['queryEngine']
425
}
426
},
427
428
async onGenerate(options) {
429
console.log('Generating custom TypeScript files...')
430
431
// Access DMMF for model information
432
const models = options.dmmf.datamodel.models
433
434
for (const model of models) {
435
// Generate custom TypeScript interfaces
436
const interfaceCode = generateInterface(model)
437
438
// Write to output directory
439
const outputPath = path.join(options.generator.output!, `${model.name}.ts`)
440
await fs.writeFile(outputPath, interfaceCode)
441
}
442
443
console.log(`Generated files for ${models.length} models`)
444
}
445
}
446
447
// Create generator config
448
const config: GeneratorConfig = {
449
name: 'custom',
450
provider: 'custom-ts-generator',
451
output: './generated/custom',
452
config: {},
453
binaryTargets: ['native']
454
}
455
456
// Create and use generator
457
const generator = new InProcessGenerator(config, customGenerator)
458
459
await generator.init()
460
await generator.generate()
461
generator.stop()
462
```
463
464
### Generator Registry Management
465
466
```typescript
467
import {
468
getGenerators,
469
type GeneratorRegistry,
470
type GeneratorRegistryEntry
471
} from '@prisma/internals'
472
473
// Create custom registry
474
const customRegistry: GeneratorRegistry = {
475
// Built-in Prisma generators
476
'prisma-client-js': {
477
type: 'rpc',
478
generatorPath: require.resolve('@prisma/client/generator-build/index.js'),
479
isNode: true
480
},
481
482
// Custom external generator
483
'custom-external': {
484
type: 'rpc',
485
generatorPath: './custom-generators/external-gen',
486
isNode: false
487
},
488
489
// Custom in-process generator
490
'custom-internal': {
491
type: 'in-process',
492
generator: customGenerator
493
}
494
}
495
496
// Use generators with custom registry
497
async function runWithCustomRegistry() {
498
const generators = await getGenerators({
499
schemaContent: `
500
generator client {
501
provider = "prisma-client-js"
502
output = "./generated/client"
503
}
504
505
generator custom {
506
provider = "custom-internal"
507
output = "./generated/custom"
508
}
509
`,
510
generatorRegistry: customRegistry,
511
cwd: process.cwd()
512
})
513
514
// Process generators
515
for (const gen of generators) {
516
console.log(`Processing: ${gen.getProvider()}`)
517
await gen.init()
518
await gen.generate()
519
}
520
521
// Cleanup
522
generators.forEach(gen => gen.stop())
523
}
524
```
525
526
### Binary Target Management
527
528
```typescript
529
import {
530
fixBinaryTargets,
531
getBinaryTargetForCurrentPlatform,
532
type BinaryTargetsEnvValue
533
} from '@prisma/internals'
534
535
function manageBinaryTargets(generatorConfig: GeneratorConfig) {
536
// Get current platform
537
const currentPlatform = getBinaryTargetForCurrentPlatform()
538
console.log('Current platform:', currentPlatform)
539
540
// Convert string array to BinaryTargetsEnvValue format
541
const schemaBinaryTargets: BinaryTargetsEnvValue[] =
542
generatorConfig.binaryTargets.map(target => ({
543
fromEnvVar: null,
544
value: target
545
}))
546
547
// Fix binary targets to ensure current platform is included
548
const fixedTargets = fixBinaryTargets(schemaBinaryTargets, currentPlatform)
549
550
// Update generator config
551
const updatedConfig: GeneratorConfig = {
552
...generatorConfig,
553
binaryTargets: fixedTargets.map(t => t.value)
554
}
555
556
console.log('Original targets:', generatorConfig.binaryTargets)
557
console.log('Fixed targets:', updatedConfig.binaryTargets)
558
559
return updatedConfig
560
}
561
```