CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-prisma--internals

Comprehensive internal utility library for Prisma's CLI operations, schema management, generator handling, and engine interactions

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

generators.mddocs/

Generator System and Management

The generator system domain provides comprehensive generator lifecycle management including initialization, execution, cleanup, and registry management for both JSON-RPC and in-process generators.

Classes

Abstract Generator Base Class

Generator

Abstract base class for all generator implementations providing common interface and lifecycle management.

abstract class Generator {
  abstract init(): Promise<void>
  abstract generate(): Promise<void>
  abstract setOptions(options: GeneratorOptions): void
  abstract setBinaryPaths(binaryPaths: BinaryPaths): void
  abstract getPrettyName(): string
  abstract getProvider(): string
  abstract stop(): void
}

Methods:

  • init(): Promise<void> - Initialize the generator
  • generate(): Promise<void> - Execute generation process
  • setOptions(options: GeneratorOptions): void - Set generator options
  • setBinaryPaths(binaryPaths: BinaryPaths): void - Set binary paths for engines
  • getPrettyName(): string - Get display name for UI
  • getProvider(): string - Get provider name/identifier
  • stop(): void - Stop and cleanup the generator

JSON-RPC Generator Implementation

JsonRpcGenerator

Generator implementation for JSON-RPC based external generators that communicate via process IPC.

class JsonRpcGenerator extends Generator {
  constructor(
    executablePath: string,
    config: GeneratorConfig,
    isNode?: boolean
  )
}

Constructor Parameters:

  • executablePath: string - Path to the generator executable
  • config: GeneratorConfig - Generator configuration
  • isNode?: boolean - Whether the generator is a Node.js process

Example:

const generator = new JsonRpcGenerator(
  '/path/to/prisma-client-generator',
  {
    name: 'client',
    provider: 'prisma-client-js',
    output: './node_modules/.prisma/client',
    config: {},
    binaryTargets: ['native']
  },
  true // is Node.js
)

await generator.init()
await generator.generate()
generator.stop()

In-Process Generator Implementation

InProcessGenerator

Generator implementation for in-process generators that run directly within the same Node.js process.

class InProcessGenerator extends Generator {
  constructor(config: GeneratorConfig, generator: IGenerator)
}

Constructor Parameters:

  • config: GeneratorConfig - Generator configuration
  • generator: IGenerator - Generator implementation interface

Example:

const inProcessGen = new InProcessGenerator(
  config,
  {
    onManifest: () => Promise.resolve(manifest),
    onGenerate: (options) => Promise.resolve()
  }
)

Functions

Generator Factory Functions

getGenerators(options)

Factory function that creates and initializes all generators from schema configuration.

function getGenerators(options: GetGeneratorOptions): Promise<Generator[]>

GetGeneratorOptions:

interface GetGeneratorOptions {
  schemaPath?: string                    // Path to schema file
  cwd?: string                          // Current working directory
  schemaContent?: string                // Schema content (alternative to schemaPath)
  generators?: GeneratorConfig[]        // Explicit generator configurations
  generatorRegistry?: GeneratorRegistry // Registry of available generators
  skipDownload?: boolean               // Skip binary downloads
  printDownloadProgress?: boolean      // Show download progress
  version?: string                     // Prisma version
  engineVersion?: string               // Engine version
}

Returns: Promise<Generator[]> - Array of initialized generators

Example:

const generators = await getGenerators({
  schemaPath: './prisma/schema.prisma',
  cwd: process.cwd(),
  printDownloadProgress: true,
  skipDownload: false
})

console.log(`Initialized ${generators.length} generators`)

// Run all generators
for (const generator of generators) {
  await generator.generate()
  console.log(`✓ ${generator.getPrettyName()}`)
}

// Cleanup
generators.forEach(gen => gen.stop())

getGenerator(options)

Shortcut function for getting a single generator instance (useful for testing and single-generator scenarios).

function getGenerator(options: GetGeneratorOptions): Promise<Generator>

Parameters: Same as getGenerators

Returns: Promise<Generator> - Single generator instance

Example:

const generator = await getGenerator({
  schemaContent: `
    generator client {
      provider = "prisma-client-js"
      output   = "./generated/client"
    }
  `,
  cwd: process.cwd()
})

await generator.generate()

Generator Utility Functions

fixBinaryTargets(schemaBinaryTargets, runtimeBinaryTarget)

Fixes binary targets by adding native or runtime target as needed to ensure generators can run properly.

function fixBinaryTargets(
  schemaBinaryTargets: BinaryTargetsEnvValue[],
  runtimeBinaryTarget: BinaryTarget | string
): BinaryTargetsEnvValue[]

Parameters:

  • schemaBinaryTargets: BinaryTargetsEnvValue[] - Binary targets from schema
  • runtimeBinaryTarget: BinaryTarget | string - Runtime binary target

Returns: BinaryTargetsEnvValue[] - Fixed binary targets including necessary runtime targets

Example:

import { fixBinaryTargets, getBinaryTargetForCurrentPlatform } from '@prisma/internals'

const schemaBinaryTargets = [{ fromEnvVar: null, value: 'linux-musl' }]
const runtimeTarget = getBinaryTargetForCurrentPlatform()

const fixedTargets = fixBinaryTargets(schemaBinaryTargets, runtimeTarget)
console.log('Fixed binary targets:', fixedTargets)
// Ensures current platform is included if not already specified

printGeneratorConfig(config)

Formats generator configuration as a readable string for debugging and logging.

function printGeneratorConfig(config: GeneratorConfig): string

Parameters:

  • config: GeneratorConfig - Generator configuration to format

Returns: string - Formatted configuration string

Example:

const config: GeneratorConfig = {
  name: 'client',
  provider: 'prisma-client-js',
  output: './generated/client',
  config: { engineType: 'binary' },
  binaryTargets: ['native', 'linux-musl']
}

console.log(printGeneratorConfig(config))
// Output:
// generator client {
//   provider      = "prisma-client-js"
//   output        = "./generated/client" 
//   engineType    = "binary"
//   binaryTargets = ["native", "linux-musl"]
// }

Types and Interfaces

Registry Types

GeneratorRegistry

Registry mapping generator providers to their implementations.

type GeneratorRegistry = Record<string, GeneratorRegistryEntry>

GeneratorRegistryEntry

Union type for registry entries supporting both RPC and in-process generators.

type GeneratorRegistryEntry = 
  | {
      type: 'rpc'
      generatorPath: string
      isNode?: boolean
    }
  | {
      type: 'in-process'
      generator: IGenerator
    }

RPC Registry Entry:

  • type: 'rpc' - Indicates JSON-RPC generator
  • generatorPath: string - Path to generator executable
  • isNode?: boolean - Whether generator is Node.js based

In-Process Registry Entry:

  • type: 'in-process' - Indicates in-process generator
  • generator: IGenerator - Generator implementation

Example:

const registry: GeneratorRegistry = {
  'prisma-client-js': {
    type: 'rpc',
    generatorPath: './node_modules/.prisma/client/generator-build/index.js',
    isNode: true
  },
  'custom-generator': {
    type: 'in-process',
    generator: {
      onManifest: () => Promise.resolve(customManifest),
      onGenerate: (options) => customGenerate(options)
    }
  }
}

Generator Interface Types

IGenerator

Interface for in-process generator implementations.

interface IGenerator {
  onManifest(config: GeneratorConfig): Promise<GeneratorManifest>
  onGenerate(options: GeneratorOptions): Promise<void>
}

Methods:

  • onManifest(config: GeneratorConfig): Promise<GeneratorManifest> - Return generator manifest
  • onGenerate(options: GeneratorOptions): Promise<void> - Execute generation

GeneratorManifest

Manifest describing generator capabilities and requirements.

interface GeneratorManifest {
  prettyName?: string           // Display name
  defaultOutput?: string        // Default output directory
  denylist?: string[]          // Unsupported features
  requiresGenerators?: string[] // Required other generators
  requiresEngines?: string[]    // Required engine binaries
  version: string              // Generator version
}

BinaryPaths

Paths to engine binaries required by generators.

interface BinaryPaths {
  queryEngine?: string         // Query engine binary path
  schemaEngine?: string        // Schema engine binary path
  libqueryEngine?: string      // Query engine library path
  migrationEngine?: string     // Migration engine binary path (legacy)
}

Examples

Complete Generator Lifecycle Management

import { 
  getGenerators, 
  printGeneratorConfig,
  fixBinaryTargets,
  getBinaryTargetForCurrentPlatform 
} from '@prisma/internals'

async function runGenerationPipeline() {
  try {
    // Get all generators from schema
    const generators = await getGenerators({
      schemaPath: './prisma/schema.prisma',
      cwd: process.cwd(),
      printDownloadProgress: true
    })
    
    console.log(`Found ${generators.length} generators`)
    
    // Initialize all generators
    for (const generator of generators) {
      console.log(`Initializing ${generator.getPrettyName()}...`)
      await generator.init()
    }
    
    // Set binary paths for all generators
    const binaryPaths = {
      queryEngine: '/path/to/query-engine',
      schemaEngine: '/path/to/schema-engine'
    }
    
    generators.forEach(gen => {
      gen.setBinaryPaths(binaryPaths)
    })
    
    // Generate with each generator
    for (const generator of generators) {
      const startTime = Date.now()
      
      console.log(`Generating ${generator.getPrettyName()}...`)
      await generator.generate()
      
      const duration = Date.now() - startTime
      console.log(`✓ Generated ${generator.getPrettyName()} (${duration}ms)`)
    }
    
    console.log('All generators completed successfully')
    
  } catch (error) {
    console.error('Generation failed:', error)
    throw error
  } finally {
    // Always cleanup generators
    if (generators) {
      generators.forEach(gen => {
        try {
          gen.stop()
        } catch (stopError) {
          console.warn(`Failed to stop generator: ${stopError.message}`)
        }
      })
    }
  }
}

Custom In-Process Generator

import { InProcessGenerator, type IGenerator, type GeneratorManifest } from '@prisma/internals'

// Define custom generator
const customGenerator: IGenerator = {
  async onManifest(config): Promise<GeneratorManifest> {
    return {
      prettyName: 'Custom TypeScript Generator',
      defaultOutput: './generated/custom',
      version: '1.0.0',
      requiresEngines: ['queryEngine']
    }
  },
  
  async onGenerate(options) {
    console.log('Generating custom TypeScript files...')
    
    // Access DMMF for model information
    const models = options.dmmf.datamodel.models
    
    for (const model of models) {
      // Generate custom TypeScript interfaces
      const interfaceCode = generateInterface(model)
      
      // Write to output directory
      const outputPath = path.join(options.generator.output!, `${model.name}.ts`)
      await fs.writeFile(outputPath, interfaceCode)
    }
    
    console.log(`Generated files for ${models.length} models`)
  }
}

// Create generator config
const config: GeneratorConfig = {
  name: 'custom',
  provider: 'custom-ts-generator',
  output: './generated/custom',
  config: {},
  binaryTargets: ['native']
}

// Create and use generator
const generator = new InProcessGenerator(config, customGenerator)

await generator.init()
await generator.generate()
generator.stop()

Generator Registry Management

import { 
  getGenerators, 
  type GeneratorRegistry,
  type GeneratorRegistryEntry 
} from '@prisma/internals'

// Create custom registry
const customRegistry: GeneratorRegistry = {
  // Built-in Prisma generators
  'prisma-client-js': {
    type: 'rpc',
    generatorPath: require.resolve('@prisma/client/generator-build/index.js'),
    isNode: true
  },
  
  // Custom external generator  
  'custom-external': {
    type: 'rpc',
    generatorPath: './custom-generators/external-gen',
    isNode: false
  },
  
  // Custom in-process generator
  'custom-internal': {
    type: 'in-process',
    generator: customGenerator
  }
}

// Use generators with custom registry
async function runWithCustomRegistry() {
  const generators = await getGenerators({
    schemaContent: `
      generator client {
        provider = "prisma-client-js"
        output   = "./generated/client"
      }
      
      generator custom {
        provider = "custom-internal"
        output   = "./generated/custom"
      }
    `,
    generatorRegistry: customRegistry,
    cwd: process.cwd()
  })
  
  // Process generators
  for (const gen of generators) {
    console.log(`Processing: ${gen.getProvider()}`)
    await gen.init()
    await gen.generate()
  }
  
  // Cleanup
  generators.forEach(gen => gen.stop())
}

Binary Target Management

import { 
  fixBinaryTargets, 
  getBinaryTargetForCurrentPlatform,
  type BinaryTargetsEnvValue 
} from '@prisma/internals'

function manageBinaryTargets(generatorConfig: GeneratorConfig) {
  // Get current platform
  const currentPlatform = getBinaryTargetForCurrentPlatform()
  console.log('Current platform:', currentPlatform)
  
  // Convert string array to BinaryTargetsEnvValue format
  const schemaBinaryTargets: BinaryTargetsEnvValue[] = 
    generatorConfig.binaryTargets.map(target => ({
      fromEnvVar: null,
      value: target
    }))
  
  // Fix binary targets to ensure current platform is included
  const fixedTargets = fixBinaryTargets(schemaBinaryTargets, currentPlatform)
  
  // Update generator config
  const updatedConfig: GeneratorConfig = {
    ...generatorConfig,
    binaryTargets: fixedTargets.map(t => t.value)
  }
  
  console.log('Original targets:', generatorConfig.binaryTargets)
  console.log('Fixed targets:', updatedConfig.binaryTargets)
  
  return updatedConfig
}

Install with Tessl CLI

npx tessl i tessl/npm-prisma--internals

docs

binary-resolution.md

cli-utilities.md

database-operations.md

engine-commands.md

error-handling.md

generators.md

index.md

syntax-highlighting.md

tracing.md

utilities.md

tile.json