ClassFile.ts•3.55 kB
import crypto from 'node:crypto'
import path from 'node:path'
import { GetPrismaClientConfig } from '@prisma/client-common'
import { getClientEngineType, pathToPosix } from '@prisma/internals'
import * as ts from '@prisma/ts-builders'
import ciInfo from 'ci-info'
import { buildDebugInitialization } from '../../utils/buildDebugInitialization'
import { buildRuntimeDataModel } from '../../utils/buildDMMF'
import { buildInjectableEdgeEnv } from '../../utils/buildInjectableEdgeEnv'
import { buildInlineDatasources } from '../../utils/buildInlineDatasources'
import { buildGetWasmModule } from '../../utils/wasm'
import { GenerateContext } from '../GenerateContext'
import { PrismaClientClass } from '../PrismaClient'
import { TSClientOptions } from '../TSClient'
const jsDocHeader = `/*
 * WARNING: This is an internal file that is subject to change!
 *
 * 🛑 Under no circumstances should you import this file directly! 🛑
 *
 * Please import the \`PrismaClient\` class from the \`client.ts\` file instead.
 */
`
export function createClassFile(context: GenerateContext, options: TSClientOptions): string {
  const imports: ts.BasicBuilder[] = [
    ts.moduleImport(context.runtimeImport).asNamespace('runtime'),
    ts.moduleImport(context.importFileName(`./prismaNamespace`)).asNamespace('Prisma').typeOnly(),
  ]
  const stringifiedImports = imports.map((i) => ts.stringify(i))
  const prismaClientClass = new PrismaClientClass(context, options.runtimeName)
  return `${jsDocHeader}
${stringifiedImports.join('\n')}
${clientConfig(context, options)}
${prismaClientClass.toTS()}
export function getPrismaClientClass(dirname: string): PrismaClientConstructor {
  config.dirname = dirname
  return runtime.getPrismaClient(config) as unknown as PrismaClientConstructor
}
`
}
function clientConfig(context: GenerateContext, options: TSClientOptions) {
  const {
    edge,
    generator,
    outputDir,
    datamodel: inlineSchema,
    runtimeBase,
    runtimeName,
    datasources,
    copyEngine = true,
    target,
    activeProvider,
    moduleFormat,
  } = options
  // This ensures that any engine override is propagated to the generated clients config
  const clientEngineType = getClientEngineType(generator)
  generator.config.engineType = clientEngineType
  const inlineSchemaHash = crypto
    .createHash('sha256')
    .update(Buffer.from(inlineSchema, 'utf8').toString('base64'))
    .digest('hex')
  const datasourceFilePath = datasources[0].sourceFilePath
  const config: GetPrismaClientConfig = {
    generator,
    relativePath: pathToPosix(path.relative(outputDir, path.dirname(datasourceFilePath))),
    clientVersion: options.clientVersion,
    engineVersion: options.engineVersion,
    datasourceNames: datasources.map((d) => d.name),
    activeProvider: options.activeProvider,
    postinstall: options.postinstall,
    ciName: ciInfo.name ?? undefined,
    inlineDatasources: buildInlineDatasources(datasources),
    inlineSchema,
    inlineSchemaHash,
    copyEngine,
    runtimeDataModel: { models: {}, enums: {}, types: {} },
    dirname: '',
  }
  return `
const config: runtime.GetPrismaClientConfig = ${JSON.stringify(config, null, 2)}
${buildRuntimeDataModel(context.dmmf.datamodel, runtimeName)}
${buildGetWasmModule({ component: 'engine', runtimeBase, runtimeName, target, activeProvider, moduleFormat })}
${buildGetWasmModule({ component: 'compiler', runtimeBase, runtimeName, target, activeProvider, moduleFormat })}
${buildInjectableEdgeEnv(edge, datasources)}
${buildDebugInitialization(edge)}
`
}