or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

binary-resolution.mdcli-utilities.mddatabase-operations.mdengine-commands.mderror-handling.mdgenerators.mdindex.mdsyntax-highlighting.mdtracing.mdutilities.md

binary-resolution.mddocs/

0

# Binary Resolution and Platform Utilities

1

2

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.

3

4

## Functions

5

6

### Binary Resolution

7

8

#### `resolveBinary(name, proposedPath?)`

9

10

Resolves the path to a Prisma engine binary, handling various installation scenarios and platform-specific requirements.

11

12

```typescript { .api }

13

function resolveBinary(

14

name: BinaryType,

15

proposedPath?: string

16

): Promise<string>

17

```

18

19

**Parameters:**

20

- `name: BinaryType` - Type of binary to resolve (QueryEngine, SchemaEngine, etc.)

21

- `proposedPath?: string` - Optional proposed path to check first

22

23

**Returns:** `Promise<string>` - Resolved absolute path to the binary

24

25

**Example:**

26

```typescript

27

import { resolveBinary, BinaryType } from '@prisma/internals'

28

29

// Resolve query engine binary

30

const queryEnginePath = await resolveBinary(BinaryType.QueryEngine)

31

console.log('Query Engine:', queryEnginePath)

32

33

// Resolve with proposed path

34

const schemaEnginePath = await resolveBinary(

35

BinaryType.SchemaEngine,

36

'/custom/path/to/schema-engine'

37

)

38

console.log('Schema Engine:', schemaEnginePath)

39

40

// Resolve all engine binaries

41

const engines = [

42

BinaryType.QueryEngine,

43

BinaryType.SchemaEngine

44

]

45

46

for (const engine of engines) {

47

try {

48

const path = await resolveBinary(engine)

49

console.log(`${engine}: ${path}`)

50

} catch (error) {

51

console.error(`Failed to resolve ${engine}:`, error.message)

52

}

53

}

54

```

55

56

## Types and Enums

57

58

### Binary Types

59

60

#### `BinaryType`

61

62

Enumeration of available Prisma engine binary types.

63

64

```typescript { .api }

65

enum BinaryType {

66

QueryEngine = 'query-engine',

67

SchemaEngine = 'schema-engine',

68

LibqueryEngine = 'libquery-engine',

69

MigrationEngine = 'migration-engine' // Legacy

70

}

71

```

72

73

**Binary Type Descriptions:**

74

- `QueryEngine` - Main query execution engine

75

- `SchemaEngine` - Schema operations and migrations

76

- `LibqueryEngine` - Query engine library (for library mode)

77

- `MigrationEngine` - Legacy migration engine (deprecated)

78

79

## Constants

80

81

### Environment Variable Mapping

82

83

#### `engineEnvVarMap`

84

85

Mapping of engine types to their corresponding environment variable names for custom binary paths.

86

87

```typescript { .api }

88

const engineEnvVarMap: {

89

[BinaryType.QueryEngine]: 'PRISMA_QUERY_ENGINE_BINARY'

90

[BinaryType.SchemaEngine]: 'PRISMA_SCHEMA_ENGINE_BINARY'

91

[BinaryType.LibqueryEngine]: 'PRISMA_LIBQUERY_ENGINE_BINARY'

92

[BinaryType.MigrationEngine]: 'PRISMA_MIGRATION_ENGINE_BINARY'

93

}

94

```

95

96

**Usage:**

97

```typescript

98

import { engineEnvVarMap, BinaryType } from '@prisma/internals'

99

100

// Get environment variable name for query engine

101

const queryEngineEnvVar = engineEnvVarMap[BinaryType.QueryEngine]

102

console.log(queryEngineEnvVar) // 'PRISMA_QUERY_ENGINE_BINARY'

103

104

// Check if custom binary path is set

105

const customPath = process.env[queryEngineEnvVar]

106

if (customPath) {

107

console.log('Custom query engine path:', customPath)

108

}

109

```

110

111

## Platform Detection Functions

112

113

### Platform Information

114

115

#### `getBinaryTargetForCurrentPlatform()`

116

117

Detects the binary target identifier for the current platform and architecture.

118

119

```typescript { .api }

120

function getBinaryTargetForCurrentPlatform(): BinaryTarget

121

```

122

123

**Returns:** `BinaryTarget` - Platform-specific binary target identifier

124

125

**Example Platform Targets:**

126

- `linux-musl` - Linux with musl libc

127

- `linux-openssl-1.1.x` - Linux with OpenSSL 1.1.x

128

- `linux-openssl-3.0.x` - Linux with OpenSSL 3.0.x

129

- `darwin` - macOS Intel

130

- `darwin-arm64` - macOS Apple Silicon

131

- `windows` - Windows

132

- `debian-openssl-1.1.x` - Debian-based systems

133

- `rhel-openssl-1.0.x` - Red Hat Enterprise Linux

134

135

#### `getNodeAPIName()`

136

137

Gets the Node.js API name for the current platform and Node.js version.

138

139

```typescript { .api }

140

function getNodeAPIName(): string

141

```

142

143

**Returns:** `string` - Node.js API identifier (e.g., 'node-api')

144

145

## Types

146

147

### Platform Types

148

149

#### `BinaryTarget`

150

151

Type representing supported binary target platforms.

152

153

```typescript { .api }

154

type BinaryTarget =

155

| 'native'

156

| 'linux-musl'

157

| 'linux-openssl-1.0.x'

158

| 'linux-openssl-1.1.x'

159

| 'linux-openssl-3.0.x'

160

| 'debian-openssl-1.0.x'

161

| 'debian-openssl-1.1.x'

162

| 'debian-openssl-3.0.x'

163

| 'rhel-openssl-1.0.x'

164

| 'rhel-openssl-1.1.x'

165

| 'rhel-openssl-3.0.x'

166

| 'linux-arm64-openssl-1.0.x'

167

| 'linux-arm64-openssl-1.1.x'

168

| 'linux-arm64-openssl-3.0.x'

169

| 'linux-arm-openssl-1.0.x'

170

| 'linux-arm-openssl-1.1.x'

171

| 'linux-arm-openssl-3.0.x'

172

| 'linux-musl-openssl-3.0.x'

173

| 'linux-nixos'

174

| 'darwin'

175

| 'darwin-arm64'

176

| 'windows'

177

| 'freebsd11'

178

| 'freebsd12'

179

| 'freebsd13'

180

| 'freebsd14'

181

| 'freebsd15'

182

| 'openbsd'

183

| 'netbsd'

184

| 'arm'

185

```

186

187

## Examples

188

189

### Complete Binary Resolution Setup

190

191

```typescript

192

import {

193

resolveBinary,

194

BinaryType,

195

getBinaryTargetForCurrentPlatform,

196

getNodeAPIName,

197

engineEnvVarMap

198

} from '@prisma/internals'

199

200

interface EngineConfig {

201

queryEngine: string

202

schemaEngine: string

203

libqueryEngine?: string

204

}

205

206

async function setupEngineConfiguration(): Promise<EngineConfig> {

207

console.log('Setting up Prisma engines...')

208

209

// Detect current platform

210

const platform = getBinaryTargetForCurrentPlatform()

211

const nodeAPI = getNodeAPIName()

212

213

console.log(`Platform: ${platform}`)

214

console.log(`Node API: ${nodeAPI}`)

215

216

// Check for custom engine paths from environment

217

const customPaths: Partial<Record<BinaryType, string>> = {}

218

219

for (const [binaryType, envVar] of Object.entries(engineEnvVarMap)) {

220

const customPath = process.env[envVar]

221

if (customPath) {

222

customPaths[binaryType as BinaryType] = customPath

223

console.log(`Custom ${binaryType} path: ${customPath}`)

224

}

225

}

226

227

// Resolve all required engine binaries

228

const [queryEngine, schemaEngine] = await Promise.all([

229

resolveBinary(BinaryType.QueryEngine, customPaths[BinaryType.QueryEngine]),

230

resolveBinary(BinaryType.SchemaEngine, customPaths[BinaryType.SchemaEngine])

231

])

232

233

// Optionally resolve library engine

234

let libqueryEngine: string | undefined

235

try {

236

libqueryEngine = await resolveBinary(

237

BinaryType.LibqueryEngine,

238

customPaths[BinaryType.LibqueryEngine]

239

)

240

} catch (error) {

241

console.warn('Library query engine not available:', error.message)

242

}

243

244

const config: EngineConfig = {

245

queryEngine,

246

schemaEngine,

247

libqueryEngine

248

}

249

250

console.log('Engine configuration:')

251

console.log(`Query Engine: ${config.queryEngine}`)

252

console.log(`Schema Engine: ${config.schemaEngine}`)

253

if (config.libqueryEngine) {

254

console.log(`Library Query Engine: ${config.libqueryEngine}`)

255

}

256

257

return config

258

}

259

```

260

261

### Platform-Specific Binary Management

262

263

```typescript

264

import {

265

getBinaryTargetForCurrentPlatform,

266

BinaryType,

267

type BinaryTarget

268

} from '@prisma/internals'

269

270

interface PlatformInfo {

271

target: BinaryTarget

272

isLinux: boolean

273

isMacOS: boolean

274

isWindows: boolean

275

isARM: boolean

276

openSSLVersion?: string

277

supportsLibraryMode: boolean

278

}

279

280

function analyzePlatform(): PlatformInfo {

281

const target = getBinaryTargetForCurrentPlatform()

282

283

const info: PlatformInfo = {

284

target,

285

isLinux: target.startsWith('linux') || target.startsWith('debian') || target.startsWith('rhel'),

286

isMacOS: target.startsWith('darwin'),

287

isWindows: target === 'windows',

288

isARM: target.includes('arm64') || target.includes('arm'),

289

supportsLibraryMode: !target.includes('musl') // musl doesn't support library mode well

290

}

291

292

// Extract OpenSSL version from target

293

const openSSLMatch = target.match(/openssl-(\d+\.\d+\.x)/)

294

if (openSSLMatch) {

295

info.openSSLVersion = openSSLMatch[1]

296

}

297

298

return info

299

}

300

301

async function setupPlatformSpecificEngines() {

302

const platformInfo = analyzePlatform()

303

304

console.log('Platform Analysis:')

305

console.log(`Target: ${platformInfo.target}`)

306

console.log(`Linux: ${platformInfo.isLinux}`)

307

console.log(`macOS: ${platformInfo.isMacOS}`)

308

console.log(`Windows: ${platformInfo.isWindows}`)

309

console.log(`ARM Architecture: ${platformInfo.isARM}`)

310

console.log(`OpenSSL Version: ${platformInfo.openSSLVersion || 'Not detected'}`)

311

console.log(`Library Mode Support: ${platformInfo.supportsLibraryMode}`)

312

313

// Always resolve query and schema engines

314

const requiredEngines = [BinaryType.QueryEngine, BinaryType.SchemaEngine]

315

const enginePaths: Record<string, string> = {}

316

317

for (const engineType of requiredEngines) {

318

try {

319

const path = await resolveBinary(engineType)

320

enginePaths[engineType] = path

321

console.log(`✓ ${engineType}: ${path}`)

322

} catch (error) {

323

console.error(`✗ Failed to resolve ${engineType}: ${error.message}`)

324

throw new Error(`Required engine ${engineType} not available`)

325

}

326

}

327

328

// Conditionally resolve library engine based on platform support

329

if (platformInfo.supportsLibraryMode) {

330

try {

331

const libPath = await resolveBinary(BinaryType.LibqueryEngine)

332

enginePaths[BinaryType.LibqueryEngine] = libPath

333

console.log(`✓ ${BinaryType.LibqueryEngine}: ${libPath}`)

334

} catch (error) {

335

console.warn(`⚠ Library engine not available: ${error.message}`)

336

}

337

} else {

338

console.log(`ℹ Library mode not supported on ${platformInfo.target}`)

339

}

340

341

return { platformInfo, enginePaths }

342

}

343

```

344

345

### Environment Variable Configuration

346

347

```typescript

348

import {

349

engineEnvVarMap,

350

BinaryType,

351

resolveBinary

352

} from '@prisma/internals'

353

354

class EnginePathManager {

355

private customPaths: Map<BinaryType, string> = new Map()

356

357

/**

358

* Load custom engine paths from environment variables

359

*/

360

loadFromEnvironment(): void {

361

console.log('Loading custom engine paths from environment...')

362

363

for (const [binaryType, envVar] of Object.entries(engineEnvVarMap)) {

364

const customPath = process.env[envVar]

365

if (customPath) {

366

this.customPaths.set(binaryType as BinaryType, customPath)

367

console.log(`${binaryType}: ${customPath} (from ${envVar})`)

368

}

369

}

370

371

if (this.customPaths.size === 0) {

372

console.log('No custom engine paths configured')

373

}

374

}

375

376

/**

377

* Set custom path for specific engine

378

*/

379

setCustomPath(engine: BinaryType, path: string): void {

380

this.customPaths.set(engine, path)

381

console.log(`Set custom ${engine} path: ${path}`)

382

}

383

384

/**

385

* Get custom path for engine, if configured

386

*/

387

getCustomPath(engine: BinaryType): string | undefined {

388

return this.customPaths.get(engine)

389

}

390

391

/**

392

* Resolve engine binary with custom path consideration

393

*/

394

async resolve(engine: BinaryType): Promise<string> {

395

const customPath = this.getCustomPath(engine)

396

return await resolveBinary(engine, customPath)

397

}

398

399

/**

400

* Resolve all engines

401

*/

402

async resolveAll(): Promise<Record<BinaryType, string>> {

403

const engines = Object.values(BinaryType)

404

const results: Partial<Record<BinaryType, string>> = {}

405

406

await Promise.all(

407

engines.map(async (engine) => {

408

try {

409

results[engine] = await this.resolve(engine)

410

} catch (error) {

411

console.warn(`Could not resolve ${engine}: ${error.message}`)

412

}

413

})

414

)

415

416

return results as Record<BinaryType, string>

417

}

418

419

/**

420

* Generate environment variable export commands

421

*/

422

generateEnvExports(): string[] {

423

const exports: string[] = []

424

425

for (const [engine, path] of this.customPaths) {

426

const envVar = engineEnvVarMap[engine]

427

exports.push(`export ${envVar}="${path}"`)

428

}

429

430

return exports

431

}

432

}

433

434

// Usage

435

async function manageEngineConfiguration() {

436

const manager = new EnginePathManager()

437

438

// Load from environment

439

manager.loadFromEnvironment()

440

441

// Set custom paths programmatically

442

manager.setCustomPath(BinaryType.QueryEngine, '/opt/prisma/query-engine')

443

manager.setCustomPath(BinaryType.SchemaEngine, '/opt/prisma/schema-engine')

444

445

// Resolve all engines

446

const enginePaths = await manager.resolveAll()

447

console.log('Resolved engine paths:', enginePaths)

448

449

// Generate export commands for deployment

450

const exports = manager.generateEnvExports()

451

console.log('\nEnvironment exports for deployment:')

452

exports.forEach(exp => console.log(exp))

453

}

454

```

455

456

### Binary Validation and Health Check

457

458

```typescript

459

import {

460

resolveBinary,

461

BinaryType,

462

getBinaryTargetForCurrentPlatform

463

} from '@prisma/internals'

464

import { execFile } from 'child_process'

465

import { promisify } from 'util'

466

import { access, constants } from 'fs'

467

468

const execFileAsync = promisify(execFile)

469

const accessAsync = promisify(access)

470

471

interface BinaryHealthStatus {

472

engine: BinaryType

473

path: string

474

exists: boolean

475

executable: boolean

476

version?: string

477

error?: string

478

}

479

480

async function checkBinaryHealth(engine: BinaryType): Promise<BinaryHealthStatus> {

481

const status: BinaryHealthStatus = {

482

engine,

483

path: '',

484

exists: false,

485

executable: false

486

}

487

488

try {

489

// Resolve binary path

490

status.path = await resolveBinary(engine)

491

492

// Check if file exists

493

try {

494

await accessAsync(status.path, constants.F_OK)

495

status.exists = true

496

} catch {

497

status.exists = false

498

status.error = 'Binary file not found'

499

return status

500

}

501

502

// Check if executable

503

try {

504

await accessAsync(status.path, constants.X_OK)

505

status.executable = true

506

} catch {

507

status.executable = false

508

status.error = 'Binary not executable'

509

return status

510

}

511

512

// Get version information

513

try {

514

const { stdout } = await execFileAsync(status.path, ['--version'], {

515

timeout: 5000

516

})

517

status.version = stdout.trim()

518

} catch (error) {

519

status.error = `Version check failed: ${error.message}`

520

}

521

522

} catch (error) {

523

status.error = `Resolution failed: ${error.message}`

524

}

525

526

return status

527

}

528

529

async function performEngineHealthCheck(): Promise<void> {

530

console.log('Performing Prisma Engine Health Check...')

531

console.log(`Platform: ${getBinaryTargetForCurrentPlatform()}`)

532

console.log('=' .repeat(60))

533

534

const engines = [BinaryType.QueryEngine, BinaryType.SchemaEngine]

535

const results: BinaryHealthStatus[] = []

536

537

for (const engine of engines) {

538

const status = await checkBinaryHealth(engine)

539

results.push(status)

540

541

const icon = status.exists && status.executable && !status.error ? '✓' : '✗'

542

543

console.log(`${icon} ${engine}`)

544

console.log(` Path: ${status.path || 'Not resolved'}`)

545

console.log(` Exists: ${status.exists}`)

546

console.log(` Executable: ${status.executable}`)

547

548

if (status.version) {

549

console.log(` Version: ${status.version}`)

550

}

551

552

if (status.error) {

553

console.log(` Error: ${status.error}`)

554

}

555

556

console.log()

557

}

558

559

// Summary

560

const healthy = results.filter(r => r.exists && r.executable && !r.error)

561

const total = results.length

562

563

console.log('=' .repeat(60))

564

console.log(`Health Check Summary: ${healthy.length}/${total} engines healthy`)

565

566

if (healthy.length < total) {

567

const issues = results.filter(r => !r.exists || !r.executable || r.error)

568

console.log('\nIssues found:')

569

issues.forEach(issue => {

570

console.log(`- ${issue.engine}: ${issue.error || 'Unknown issue'}`)

571

})

572

573

process.exit(1)

574

}

575

576

console.log('All engines are healthy and ready!')

577

}

578

```