Comprehensive internal utility library for Prisma's CLI operations, schema management, generator handling, and engine interactions
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
The binary resolution domain provides engine binary path resolution and platform-specific operations, ensuring Prisma engines can be located and executed correctly across different platforms and deployment environments.
resolveBinary(name, proposedPath?)Resolves the path to a Prisma engine binary, handling various installation scenarios and platform-specific requirements.
function resolveBinary(
name: BinaryType,
proposedPath?: string
): Promise<string>Parameters:
name: BinaryType - Type of binary to resolve (QueryEngine, SchemaEngine, etc.)proposedPath?: string - Optional proposed path to check firstReturns: Promise<string> - Resolved absolute path to the binary
Example:
import { resolveBinary, BinaryType } from '@prisma/internals'
// Resolve query engine binary
const queryEnginePath = await resolveBinary(BinaryType.QueryEngine)
console.log('Query Engine:', queryEnginePath)
// Resolve with proposed path
const schemaEnginePath = await resolveBinary(
BinaryType.SchemaEngine,
'/custom/path/to/schema-engine'
)
console.log('Schema Engine:', schemaEnginePath)
// Resolve all engine binaries
const engines = [
BinaryType.QueryEngine,
BinaryType.SchemaEngine
]
for (const engine of engines) {
try {
const path = await resolveBinary(engine)
console.log(`${engine}: ${path}`)
} catch (error) {
console.error(`Failed to resolve ${engine}:`, error.message)
}
}BinaryTypeEnumeration of available Prisma engine binary types.
enum BinaryType {
QueryEngine = 'query-engine',
SchemaEngine = 'schema-engine',
LibqueryEngine = 'libquery-engine',
MigrationEngine = 'migration-engine' // Legacy
}Binary Type Descriptions:
QueryEngine - Main query execution engineSchemaEngine - Schema operations and migrationsLibqueryEngine - Query engine library (for library mode)MigrationEngine - Legacy migration engine (deprecated)engineEnvVarMapMapping of engine types to their corresponding environment variable names for custom binary paths.
const engineEnvVarMap: {
[BinaryType.QueryEngine]: 'PRISMA_QUERY_ENGINE_BINARY'
[BinaryType.SchemaEngine]: 'PRISMA_SCHEMA_ENGINE_BINARY'
[BinaryType.LibqueryEngine]: 'PRISMA_LIBQUERY_ENGINE_BINARY'
[BinaryType.MigrationEngine]: 'PRISMA_MIGRATION_ENGINE_BINARY'
}Usage:
import { engineEnvVarMap, BinaryType } from '@prisma/internals'
// Get environment variable name for query engine
const queryEngineEnvVar = engineEnvVarMap[BinaryType.QueryEngine]
console.log(queryEngineEnvVar) // 'PRISMA_QUERY_ENGINE_BINARY'
// Check if custom binary path is set
const customPath = process.env[queryEngineEnvVar]
if (customPath) {
console.log('Custom query engine path:', customPath)
}getBinaryTargetForCurrentPlatform()Detects the binary target identifier for the current platform and architecture.
function getBinaryTargetForCurrentPlatform(): BinaryTargetReturns: BinaryTarget - Platform-specific binary target identifier
Example Platform Targets:
linux-musl - Linux with musl libclinux-openssl-1.1.x - Linux with OpenSSL 1.1.xlinux-openssl-3.0.x - Linux with OpenSSL 3.0.xdarwin - macOS Inteldarwin-arm64 - macOS Apple Siliconwindows - Windowsdebian-openssl-1.1.x - Debian-based systemsrhel-openssl-1.0.x - Red Hat Enterprise LinuxgetNodeAPIName()Gets the Node.js API name for the current platform and Node.js version.
function getNodeAPIName(): stringReturns: string - Node.js API identifier (e.g., 'node-api')
BinaryTargetType representing supported binary target platforms.
type BinaryTarget =
| 'native'
| 'linux-musl'
| 'linux-openssl-1.0.x'
| 'linux-openssl-1.1.x'
| 'linux-openssl-3.0.x'
| 'debian-openssl-1.0.x'
| 'debian-openssl-1.1.x'
| 'debian-openssl-3.0.x'
| 'rhel-openssl-1.0.x'
| 'rhel-openssl-1.1.x'
| 'rhel-openssl-3.0.x'
| 'linux-arm64-openssl-1.0.x'
| 'linux-arm64-openssl-1.1.x'
| 'linux-arm64-openssl-3.0.x'
| 'linux-arm-openssl-1.0.x'
| 'linux-arm-openssl-1.1.x'
| 'linux-arm-openssl-3.0.x'
| 'linux-musl-openssl-3.0.x'
| 'linux-nixos'
| 'darwin'
| 'darwin-arm64'
| 'windows'
| 'freebsd11'
| 'freebsd12'
| 'freebsd13'
| 'freebsd14'
| 'freebsd15'
| 'openbsd'
| 'netbsd'
| 'arm'import {
resolveBinary,
BinaryType,
getBinaryTargetForCurrentPlatform,
getNodeAPIName,
engineEnvVarMap
} from '@prisma/internals'
interface EngineConfig {
queryEngine: string
schemaEngine: string
libqueryEngine?: string
}
async function setupEngineConfiguration(): Promise<EngineConfig> {
console.log('Setting up Prisma engines...')
// Detect current platform
const platform = getBinaryTargetForCurrentPlatform()
const nodeAPI = getNodeAPIName()
console.log(`Platform: ${platform}`)
console.log(`Node API: ${nodeAPI}`)
// Check for custom engine paths from environment
const customPaths: Partial<Record<BinaryType, string>> = {}
for (const [binaryType, envVar] of Object.entries(engineEnvVarMap)) {
const customPath = process.env[envVar]
if (customPath) {
customPaths[binaryType as BinaryType] = customPath
console.log(`Custom ${binaryType} path: ${customPath}`)
}
}
// Resolve all required engine binaries
const [queryEngine, schemaEngine] = await Promise.all([
resolveBinary(BinaryType.QueryEngine, customPaths[BinaryType.QueryEngine]),
resolveBinary(BinaryType.SchemaEngine, customPaths[BinaryType.SchemaEngine])
])
// Optionally resolve library engine
let libqueryEngine: string | undefined
try {
libqueryEngine = await resolveBinary(
BinaryType.LibqueryEngine,
customPaths[BinaryType.LibqueryEngine]
)
} catch (error) {
console.warn('Library query engine not available:', error.message)
}
const config: EngineConfig = {
queryEngine,
schemaEngine,
libqueryEngine
}
console.log('Engine configuration:')
console.log(`Query Engine: ${config.queryEngine}`)
console.log(`Schema Engine: ${config.schemaEngine}`)
if (config.libqueryEngine) {
console.log(`Library Query Engine: ${config.libqueryEngine}`)
}
return config
}import {
getBinaryTargetForCurrentPlatform,
BinaryType,
type BinaryTarget
} from '@prisma/internals'
interface PlatformInfo {
target: BinaryTarget
isLinux: boolean
isMacOS: boolean
isWindows: boolean
isARM: boolean
openSSLVersion?: string
supportsLibraryMode: boolean
}
function analyzePlatform(): PlatformInfo {
const target = getBinaryTargetForCurrentPlatform()
const info: PlatformInfo = {
target,
isLinux: target.startsWith('linux') || target.startsWith('debian') || target.startsWith('rhel'),
isMacOS: target.startsWith('darwin'),
isWindows: target === 'windows',
isARM: target.includes('arm64') || target.includes('arm'),
supportsLibraryMode: !target.includes('musl') // musl doesn't support library mode well
}
// Extract OpenSSL version from target
const openSSLMatch = target.match(/openssl-(\d+\.\d+\.x)/)
if (openSSLMatch) {
info.openSSLVersion = openSSLMatch[1]
}
return info
}
async function setupPlatformSpecificEngines() {
const platformInfo = analyzePlatform()
console.log('Platform Analysis:')
console.log(`Target: ${platformInfo.target}`)
console.log(`Linux: ${platformInfo.isLinux}`)
console.log(`macOS: ${platformInfo.isMacOS}`)
console.log(`Windows: ${platformInfo.isWindows}`)
console.log(`ARM Architecture: ${platformInfo.isARM}`)
console.log(`OpenSSL Version: ${platformInfo.openSSLVersion || 'Not detected'}`)
console.log(`Library Mode Support: ${platformInfo.supportsLibraryMode}`)
// Always resolve query and schema engines
const requiredEngines = [BinaryType.QueryEngine, BinaryType.SchemaEngine]
const enginePaths: Record<string, string> = {}
for (const engineType of requiredEngines) {
try {
const path = await resolveBinary(engineType)
enginePaths[engineType] = path
console.log(`✓ ${engineType}: ${path}`)
} catch (error) {
console.error(`✗ Failed to resolve ${engineType}: ${error.message}`)
throw new Error(`Required engine ${engineType} not available`)
}
}
// Conditionally resolve library engine based on platform support
if (platformInfo.supportsLibraryMode) {
try {
const libPath = await resolveBinary(BinaryType.LibqueryEngine)
enginePaths[BinaryType.LibqueryEngine] = libPath
console.log(`✓ ${BinaryType.LibqueryEngine}: ${libPath}`)
} catch (error) {
console.warn(`⚠ Library engine not available: ${error.message}`)
}
} else {
console.log(`ℹ Library mode not supported on ${platformInfo.target}`)
}
return { platformInfo, enginePaths }
}import {
engineEnvVarMap,
BinaryType,
resolveBinary
} from '@prisma/internals'
class EnginePathManager {
private customPaths: Map<BinaryType, string> = new Map()
/**
* Load custom engine paths from environment variables
*/
loadFromEnvironment(): void {
console.log('Loading custom engine paths from environment...')
for (const [binaryType, envVar] of Object.entries(engineEnvVarMap)) {
const customPath = process.env[envVar]
if (customPath) {
this.customPaths.set(binaryType as BinaryType, customPath)
console.log(`${binaryType}: ${customPath} (from ${envVar})`)
}
}
if (this.customPaths.size === 0) {
console.log('No custom engine paths configured')
}
}
/**
* Set custom path for specific engine
*/
setCustomPath(engine: BinaryType, path: string): void {
this.customPaths.set(engine, path)
console.log(`Set custom ${engine} path: ${path}`)
}
/**
* Get custom path for engine, if configured
*/
getCustomPath(engine: BinaryType): string | undefined {
return this.customPaths.get(engine)
}
/**
* Resolve engine binary with custom path consideration
*/
async resolve(engine: BinaryType): Promise<string> {
const customPath = this.getCustomPath(engine)
return await resolveBinary(engine, customPath)
}
/**
* Resolve all engines
*/
async resolveAll(): Promise<Record<BinaryType, string>> {
const engines = Object.values(BinaryType)
const results: Partial<Record<BinaryType, string>> = {}
await Promise.all(
engines.map(async (engine) => {
try {
results[engine] = await this.resolve(engine)
} catch (error) {
console.warn(`Could not resolve ${engine}: ${error.message}`)
}
})
)
return results as Record<BinaryType, string>
}
/**
* Generate environment variable export commands
*/
generateEnvExports(): string[] {
const exports: string[] = []
for (const [engine, path] of this.customPaths) {
const envVar = engineEnvVarMap[engine]
exports.push(`export ${envVar}="${path}"`)
}
return exports
}
}
// Usage
async function manageEngineConfiguration() {
const manager = new EnginePathManager()
// Load from environment
manager.loadFromEnvironment()
// Set custom paths programmatically
manager.setCustomPath(BinaryType.QueryEngine, '/opt/prisma/query-engine')
manager.setCustomPath(BinaryType.SchemaEngine, '/opt/prisma/schema-engine')
// Resolve all engines
const enginePaths = await manager.resolveAll()
console.log('Resolved engine paths:', enginePaths)
// Generate export commands for deployment
const exports = manager.generateEnvExports()
console.log('\nEnvironment exports for deployment:')
exports.forEach(exp => console.log(exp))
}import {
resolveBinary,
BinaryType,
getBinaryTargetForCurrentPlatform
} from '@prisma/internals'
import { execFile } from 'child_process'
import { promisify } from 'util'
import { access, constants } from 'fs'
const execFileAsync = promisify(execFile)
const accessAsync = promisify(access)
interface BinaryHealthStatus {
engine: BinaryType
path: string
exists: boolean
executable: boolean
version?: string
error?: string
}
async function checkBinaryHealth(engine: BinaryType): Promise<BinaryHealthStatus> {
const status: BinaryHealthStatus = {
engine,
path: '',
exists: false,
executable: false
}
try {
// Resolve binary path
status.path = await resolveBinary(engine)
// Check if file exists
try {
await accessAsync(status.path, constants.F_OK)
status.exists = true
} catch {
status.exists = false
status.error = 'Binary file not found'
return status
}
// Check if executable
try {
await accessAsync(status.path, constants.X_OK)
status.executable = true
} catch {
status.executable = false
status.error = 'Binary not executable'
return status
}
// Get version information
try {
const { stdout } = await execFileAsync(status.path, ['--version'], {
timeout: 5000
})
status.version = stdout.trim()
} catch (error) {
status.error = `Version check failed: ${error.message}`
}
} catch (error) {
status.error = `Resolution failed: ${error.message}`
}
return status
}
async function performEngineHealthCheck(): Promise<void> {
console.log('Performing Prisma Engine Health Check...')
console.log(`Platform: ${getBinaryTargetForCurrentPlatform()}`)
console.log('=' .repeat(60))
const engines = [BinaryType.QueryEngine, BinaryType.SchemaEngine]
const results: BinaryHealthStatus[] = []
for (const engine of engines) {
const status = await checkBinaryHealth(engine)
results.push(status)
const icon = status.exists && status.executable && !status.error ? '✓' : '✗'
console.log(`${icon} ${engine}`)
console.log(` Path: ${status.path || 'Not resolved'}`)
console.log(` Exists: ${status.exists}`)
console.log(` Executable: ${status.executable}`)
if (status.version) {
console.log(` Version: ${status.version}`)
}
if (status.error) {
console.log(` Error: ${status.error}`)
}
console.log()
}
// Summary
const healthy = results.filter(r => r.exists && r.executable && !r.error)
const total = results.length
console.log('=' .repeat(60))
console.log(`Health Check Summary: ${healthy.length}/${total} engines healthy`)
if (healthy.length < total) {
const issues = results.filter(r => !r.exists || !r.executable || r.error)
console.log('\nIssues found:')
issues.forEach(issue => {
console.log(`- ${issue.engine}: ${issue.error || 'Unknown issue'}`)
})
process.exit(1)
}
console.log('All engines are healthy and ready!')
}Install with Tessl CLI
npx tessl i tessl/npm-prisma--internals