Skip to main content
Glama

Prisma MCP Server

Official
by prisma
Apache 2.0
4
44,213
  • Linux
  • Apple
setupTestSuiteClient.ts12.5 kB
import type { D1Database } from '@cloudflare/workers-types' import { generateClient as generateClientLegacy, type GenerateClientOptions as GenerateClientLegacyOptions, } from '@prisma/client-generator-js' import { generateClient as generateClientESM, type GenerateClientOptions as GenerateClientESMOptions, } from '@prisma/client-generator-ts' import { SqlQueryOutput } from '@prisma/generator' import { getDMMF, inferDirectoryConfig, parseEnvValue, processSchemaResult } from '@prisma/internals' import path from 'path' import { fetch, WebSocket } from 'undici' import { introspectSql } from '../../../../cli/src/generate/introspectSql' import { PrismaClientOptions } from '../../../src/runtime/getPrismaClient' import type { NamedTestSuiteConfig } from './getTestSuiteInfo' import { getTestSuiteFolderPath, getTestSuitePreviewFeatures, getTestSuiteSchema, getTestSuiteSchemaPath, testSuiteHasTypedSql, } from './getTestSuiteInfo' import { AdapterProviders, GeneratorTypes } from './providers' import { DatasourceInfo, setupTestSuiteDatabase, setupTestSuiteFiles, setupTestSuiteSchema } from './setupTestSuiteEnv' import type { TestSuiteMeta } from './setupTestSuiteMatrix' import { AlterStatementCallback, ClientMeta, ClientRuntime, CliMeta } from './types' const runtimeBase = path.join(__dirname, '..', '..', '..', 'runtime') /** * Does the necessary setup to get a test suite client ready to run. * @param suiteMeta * @param suiteConfig * @returns tuple of loaded client folder + loaded sql folder */ export async function setupTestSuiteClient({ generatorType, cliMeta, suiteMeta, suiteConfig, datasourceInfo, clientMeta, skipDb, alterStatementCallback, cfWorkerBindings, }: { generatorType: GeneratorTypes cliMeta: CliMeta suiteMeta: TestSuiteMeta suiteConfig: NamedTestSuiteConfig datasourceInfo: DatasourceInfo clientMeta: ClientMeta skipDb?: boolean alterStatementCallback?: AlterStatementCallback cfWorkerBindings?: Record<string, unknown> }) { const suiteFolderPath = getTestSuiteFolderPath({ suiteMeta, suiteConfig }) const schemaPath = getTestSuiteSchemaPath({ suiteMeta, suiteConfig }) const schema = getTestSuiteSchema({ cliMeta, suiteMeta, matrixOptions: suiteConfig.matrixOptions }) const previewFeatures = getTestSuitePreviewFeatures(schema) const dmmf = await getDMMF({ datamodel: [[schemaPath, schema]], previewFeatures }) const schemaContext = await processSchemaResult({ schemaResult: { schemas: [[schemaPath, schema]], schemaPath, schemaRootDir: path.dirname(schemaPath) }, // Only TypedSQL tests strictly require env vars in the schema to resolveSome tests. (see below) // We also have some tests that verify error messages when env vars in the schema are not resolvable. // => We do not resolve env vars in the schema here and hence ignore potential errors at this point. ignoreEnvVarErrors: true, }) const generator = schemaContext.generators.find((g) => ['prisma-client-js', 'prisma-client-ts'].includes(parseEnvValue(g.provider)), )! const directoryConfig = inferDirectoryConfig(schemaContext) const hasTypedSql = await testSuiteHasTypedSql(suiteMeta) await setupTestSuiteFiles({ suiteMeta, suiteConfig }) await setupTestSuiteSchema({ suiteMeta, suiteConfig, schema }) process.env[datasourceInfo.directEnvVarName] = datasourceInfo.databaseUrl process.env[datasourceInfo.envVarName] = datasourceInfo.databaseUrl if (skipDb !== true) { await setupTestSuiteDatabase({ suiteMeta, suiteConfig, alterStatementCallback, cfWorkerBindings }) } let typedSql: SqlQueryOutput[] | undefined if (hasTypedSql) { const schemaContextIntrospect = await processSchemaResult({ schemaResult: { schemas: [[schemaPath, schema]], schemaPath, schemaRootDir: path.dirname(schemaPath) }, // TypedSQL requires a connection to the database => ENV vars in the schema must be resolved for the test to work. ignoreEnvVarErrors: false, }) typedSql = await introspectSql(directoryConfig, schemaContextIntrospect) } if (datasourceInfo.accelerateUrl !== undefined) { process.env[datasourceInfo.envVarName] = datasourceInfo.accelerateUrl } else { process.env[datasourceInfo.envVarName] = datasourceInfo.databaseUrl } const outputPath = generatorType === 'prisma-client-ts' ? 'generated/prisma' : 'generated/prisma/client' const clientGenOptions: GenerateClientLegacyOptions & GenerateClientESMOptions = { datamodel: schema, schemaPath, binaryPaths: { libqueryEngine: {}, queryEngine: {} }, datasources: schemaContext.datasources, outputDir: path.join(suiteFolderPath, outputPath), copyRuntime: false, dmmf: dmmf, generator: generator, engineVersion: '0000000000000000000000000000000000000000', clientVersion: '0.0.0', testMode: true, activeProvider: suiteConfig.matrixOptions.provider, runtimeBase, runtimeSourcePath: path.join(__dirname, '../../../runtime'), copyEngine: !clientMeta.dataProxy, typedSql, target: 'nodejs', generatedFileExtension: 'ts', importFileExtension: '', moduleFormat: 'cjs', tsNoCheckPreamble: false, } if (generatorType === 'prisma-client-ts') { await generateClientESM(clientGenOptions) } else { await generateClientLegacy(clientGenOptions) } const clientPathForRuntime: Record<ClientRuntime, { client: string; sql: string }> = { node: { client: 'generated/prisma/client', sql: path.join(outputPath, 'sql'), }, edge: { client: generatorType === 'prisma-client-ts' ? 'generated/prisma/client' : 'generated/prisma/client/edge', sql: path.join(outputPath, 'sql', 'index.edge.js'), }, 'wasm-engine-edge': { client: generatorType === 'prisma-client-ts' ? 'generated/prisma/client' : 'generated/prisma/client/wasm', sql: path.join(outputPath, 'sql', 'index.edge.js'), }, 'wasm-compiler-edge': { client: generatorType === 'prisma-client-ts' ? 'generated/prisma/client' : 'generated/prisma/client/wasm', sql: path.join(outputPath, 'sql', 'index.wasm-compiler-edge.js'), }, client: { client: 'generated/prisma/client', sql: path.join(outputPath, 'sql'), }, } const clientModule = require(path.join(suiteFolderPath, clientPathForRuntime[clientMeta.runtime].client)) let sqlModule = undefined if (hasTypedSql) { sqlModule = require(path.join(suiteFolderPath, clientPathForRuntime[clientMeta.runtime].sql)) } return [clientModule, sqlModule] } /** * Automatically loads the driver adapter for the test suite client. */ export function setupTestSuiteClientDriverAdapter({ suiteConfig, datasourceInfo, clientMeta, cfWorkerBindings, }: { suiteConfig: NamedTestSuiteConfig datasourceInfo: DatasourceInfo clientMeta: ClientMeta cfWorkerBindings?: Record<string, unknown> }) { const driverAdapter = suiteConfig.matrixOptions.driverAdapter if (clientMeta.driverAdapter !== true) return {} if (driverAdapter === undefined) { throw new Error(`Missing Driver Adapter`) } if (driverAdapter === AdapterProviders.JS_PG || driverAdapter === AdapterProviders.JS_PG_COCKROACHDB) { const { PrismaPg } = require('@prisma/adapter-pg') as typeof import('@prisma/adapter-pg') return { adapter: new PrismaPg({ connectionString: datasourceInfo.databaseUrl, }), } } if (driverAdapter === AdapterProviders.JS_NEON) { const { neonConfig } = require('@neondatabase/serverless') as typeof import('@neondatabase/serverless') const { PrismaNeon } = require('@prisma/adapter-neon') as typeof import('@prisma/adapter-neon') neonConfig.wsProxy = () => `127.0.0.1:5488/v1` neonConfig.webSocketConstructor = WebSocket neonConfig.useSecureWebSocket = false // disable tls neonConfig.pipelineConnect = false return { adapter: new PrismaNeon({ connectionString: datasourceInfo.databaseUrl, }), } } if (driverAdapter === AdapterProviders.JS_PLANETSCALE) { const { PrismaPlanetScale } = require('@prisma/adapter-planetscale') as typeof import('@prisma/adapter-planetscale') const url = new URL('http://root:root@127.0.0.1:8085') url.pathname = new URL(datasourceInfo.databaseUrl).pathname return { adapter: new PrismaPlanetScale({ url: url.toString(), fetch, // TODO remove when Node 16 is deprecated }), } } if (driverAdapter === AdapterProviders.JS_LIBSQL) { const { PrismaLibSQL } = require('@prisma/adapter-libsql') as typeof import('@prisma/adapter-libsql') return { adapter: new PrismaLibSQL({ url: datasourceInfo.databaseUrl, intMode: 'bigint', }), } } if (driverAdapter === AdapterProviders.JS_D1) { const { PrismaD1 } = require('@prisma/adapter-d1') as typeof import('@prisma/adapter-d1') const d1Client = cfWorkerBindings!.MY_DATABASE as D1Database return { adapter: new PrismaD1(d1Client) } } if (driverAdapter === AdapterProviders.JS_BETTER_SQLITE3) { const { PrismaBetterSQLite3 } = require('@prisma/adapter-better-sqlite3') as typeof import('@prisma/adapter-better-sqlite3') return { adapter: new PrismaBetterSQLite3({ // Workaround to avoid the Prisma validation error: // ``` // Error validating datasource `db`: the URL must start with the protocol `file:` // ``` url: datasourceInfo.databaseUrl.replace('file:', ''), }), } } if (driverAdapter === AdapterProviders.JS_MSSQL) { const { PrismaMssql } = require('@prisma/adapter-mssql') as typeof import('@prisma/adapter-mssql') const [, server, port, database, user, password] = datasourceInfo.databaseUrl.match( /^sqlserver:\/\/([^:;]+):(\d+);database=([^;]+);user=([^;]+);password=([^;]+);/, ) || [] return { adapter: new PrismaMssql({ user, password, database, server, port: Number(port), options: { trustServerCertificate: true, }, }), } } if (driverAdapter === 'js_mariadb') { const { PrismaMariaDb } = require('@prisma/adapter-mariadb') as typeof import('@prisma/adapter-mariadb') const url = new URL(datasourceInfo.databaseUrl) const { username: user, password, hostname: host, port } = url const database = url.pathname && url.pathname.slice(1) return { adapter: new PrismaMariaDb({ user, password, database, host, port: Number(port), connectionLimit: 4, // avoid running out of connections, some tests create multiple clients }), } } throw new Error(`No Driver Adapter support for ${driverAdapter}`) } /** * Constructs the `__internal` argument of `PrismaClient` that contains configuration overrides * specific to the test environment. */ export function getPrismaClientInternalArgs({ suiteConfig, clientMeta, }: { suiteConfig: NamedTestSuiteConfig clientMeta: ClientMeta }) { const provider = suiteConfig.matrixOptions.provider const __internal: PrismaClientOptions['__internal'] = {} if (clientMeta.runtime === 'wasm-engine-edge') { __internal.configOverride = (config) => { config.engineWasm = { getRuntime: () => Promise.resolve(require(path.join(runtimeBase, `query_engine_bg.${provider}.js`))), getQueryEngineWasmModule: () => { const queryEngineWasmFilePath = path.join(runtimeBase, `query_engine_bg.${provider}.wasm-base64.js`) const wasmBase64: string = require(queryEngineWasmFilePath).wasm return Promise.resolve(new WebAssembly.Module(Buffer.from(wasmBase64, 'base64'))) }, } return config } } else if (clientMeta.runtime === 'client' || clientMeta.runtime === 'wasm-compiler-edge') { __internal.configOverride = (config) => { config.compilerWasm = { getRuntime: () => Promise.resolve(require(path.join(runtimeBase, `query_compiler_bg.${provider}.js`))), getQueryCompilerWasmModule: () => { const queryCompilerWasmFilePath = path.join(runtimeBase, `query_compiler_bg.${provider}.wasm-base64.js`) const wasmBase64: string = require(queryCompilerWasmFilePath).wasm return Promise.resolve(new WebAssembly.Module(Buffer.from(wasmBase64, 'base64'))) }, } return config } } return { __internal } }

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/prisma/prisma'

If you have feedback or need assistance with the MCP directory API, please join our Discord server