Skip to main content
Glama

Prisma MCP Server

Official
by prisma
Apache 2.0
4
44,192
  • Linux
  • Apple
getPrismaClient.ts33.7 kB
import type { Context } from '@opentelemetry/api' import { GetPrismaClientConfig, RuntimeDataModel } from '@prisma/client-common' import { clearLogs, Debug } from '@prisma/debug' import type { SqlDriverAdapterFactory } from '@prisma/driver-adapter-utils' import { version as enginesVersion } from '@prisma/engines-version/package.json' import { ExtendedSpanOptions, logger, TracingHelper, tryLoadEnvs } from '@prisma/internals' import { AsyncResource } from 'async_hooks' import { EventEmitter } from 'events' import fs from 'fs' import path from 'path' import { RawValue, Sql } from 'sql-template-tag' import { PrismaClientInitializationError, PrismaClientKnownRequestError, PrismaClientUnknownRequestError, PrismaClientValidationError, } from '.' import { addProperty, createCompositeProxy, removeProperties } from './core/compositeProxy' import { BatchTransactionOptions, Engine, EngineConfig, Options } from './core/engines' import { AccelerateEngineConfig } from './core/engines/accelerate/AccelerateEngine' import { AccelerateExtensionFetchDecorator } from './core/engines/common/Engine' import { EngineEvent, LogEmitter } from './core/engines/common/types/Events' import type * as Transaction from './core/engines/common/types/Transaction' import { getBatchRequestPayload } from './core/engines/common/utils/getBatchRequestPayload' import { prettyPrintArguments } from './core/errorRendering/prettyPrintArguments' import { prismaGraphQLToJSError } from './core/errors/utils/prismaGraphQLToJSError' import { $extends } from './core/extensions/$extends' import { applyAllResultExtensions } from './core/extensions/applyAllResultExtensions' import { applyQueryExtensions } from './core/extensions/applyQueryExtensions' import { MergedExtensionsList } from './core/extensions/MergedExtensionsList' import { checkPlatformCaching } from './core/init/checkPlatformCaching' import { getDatasourceOverrides } from './core/init/getDatasourceOverrides' import { getEngineInstance } from './core/init/getEngineInstance' import { getPreviewFeatures } from './core/init/getPreviewFeatures' import { resolveDatasourceUrl } from './core/init/resolveDatasourceUrl' import { GlobalOmitOptions, serializeJsonQuery } from './core/jsonProtocol/serializeJsonQuery' import { MetricsClient } from './core/metrics/MetricsClient' import { applyModelsAndClientExtensions, unApplyModelsAndClientExtensions, } from './core/model/applyModelsAndClientExtensions' import { rawCommandArgsMapper } from './core/raw-query/rawCommandArgsMapper' import { checkAlter, rawQueryArgsMapper, sqlMiddlewareArgsMapper, templateStringMiddlewareArgsMapper, } from './core/raw-query/rawQueryArgsMapper' import { createPrismaPromiseFactory } from './core/request/createPrismaPromise' import { PrismaPromise, PrismaPromiseInteractiveTransaction, PrismaPromiseTransaction, } from './core/request/PrismaPromise' import { UserArgs } from './core/request/UserArgs' import { getTracingHelper } from './core/tracing/TracingHelper' import { getLockCountPromise } from './core/transaction/utils/createLockCountPromise' import { itxClientDenyList } from './core/types/exported/itxClientDenyList' import { JsInputValue } from './core/types/exported/JsApi' import { RawQueryArgs } from './core/types/exported/RawQueryArgs' import { UnknownTypedSql } from './core/types/exported/TypedSql' import { getLogLevel } from './getLogLevel' import type { QueryMiddlewareParams } from './QueryMiddlewareParams' import { RequestHandler } from './RequestHandler' import { CallSite, getCallSite } from './utils/CallSite' import { clientVersion } from './utils/clientVersion' import { validatePrismaClientOptions } from './utils/validatePrismaClientOptions' import { waitForBatch } from './utils/waitForBatch' const debug = Debug('prisma:client') declare global { // eslint-disable-next-line no-var var NODE_CLIENT: true const TARGET_BUILD_TYPE: | 'binary' | 'library' | 'edge' | 'wasm-engine-edge' | 'wasm-compiler-edge' | 'react-native' | 'client' } // used by esbuild for tree-shaking typeof globalThis === 'object' ? (globalThis.NODE_CLIENT = true) : 0 export type ErrorFormat = 'pretty' | 'colorless' | 'minimal' export type Datasource = { url?: string } export type Datasources = { [name in string]: Datasource } export type PrismaClientOptions = { /** * Overwrites the primary datasource url from your schema.prisma file */ datasourceUrl?: string /** * Instance of a Driver Adapter, e.g., like one provided by `@prisma/adapter-planetscale. */ adapter?: SqlDriverAdapterFactory | null /** * Overwrites the datasource url from your schema.prisma file */ datasources?: Datasources /** * @default "colorless" */ errorFormat?: ErrorFormat /** * The default values for Transaction options * maxWait ?= 2000 * timeout ?= 5000 */ transactionOptions?: Transaction.Options /** * @example * \`\`\` * // Defaults to stdout * log: ['query', 'info', 'warn'] * * // Emit as events * log: [ * { emit: 'stdout', level: 'query' }, * { emit: 'stdout', level: 'info' }, * { emit: 'stdout', level: 'warn' } * ] * \`\`\` * Read more in our [docs](https://www.prisma.io/docs/reference/tools-and-interfaces/prisma-client/logging#the-log-option). */ log?: Array<LogLevel | LogDefinition> omit?: GlobalOmitOptions /** * @internal * You probably don't want to use this. \`__internal\` is used by internal tooling. */ __internal?: { debug?: boolean engine?: { cwd?: string binaryPath?: string endpoint?: string allowTriggerPanic?: boolean } /** This can be used for testing purposes */ configOverride?: (config: GetPrismaClientConfig) => GetPrismaClientConfig } } export type Unpacker = (data: any) => any export type InternalRequestParams = { /** * The original client method being called. * Even though the rootField / operation can be changed, * this method stays as it is, as it's what the user's * code looks like */ clientMethod: string // TODO what is this /** * Name of js model that triggered the request. Might be used * for warnings or error messages */ jsModelName?: string // Extra headers for data proxy. callsite?: CallSite transaction?: PrismaPromiseTransaction unpacker?: Unpacker // TODO what is this otelParentCtx?: Context /** Used to "desugar" a user input into an "expanded" one */ argsMapper?: (args?: UserArgs) => UserArgs /** Used to convert args for middleware and back */ middlewareArgsMapper?: MiddlewareArgsMapper<unknown, unknown> /** Used for Accelerate client extension via Data Proxy */ customDataProxyFetch?: AccelerateExtensionFetchDecorator } & Omit<QueryMiddlewareParams, 'runInTransaction'> export type MiddlewareArgsMapper<RequestArgs, MiddlewareArgs> = { requestArgsToMiddlewareArgs(requestArgs: RequestArgs): MiddlewareArgs middlewareArgsToRequestArgs(middlewareArgs: MiddlewareArgs): RequestArgs } const noopMiddlewareArgsMapper: MiddlewareArgsMapper<unknown, unknown> = { requestArgsToMiddlewareArgs: (param) => param, middlewareArgsToRequestArgs: (param) => param, } /* Types for Logging */ export type LogLevel = 'info' | 'query' | 'warn' | 'error' export type LogDefinition = { level: LogLevel emit: 'stdout' | 'event' } export type QueryEvent = { timestamp: Date query: string params: string duration: number target: string } export type LogEvent = { timestamp: Date message: string target: string } /* End Types for Logging */ type ExtendedEventType = LogLevel | 'beforeExit' type EventCallback<E extends ExtendedEventType> = [E] extends ['beforeExit'] ? () => Promise<void> : [E] extends [LogLevel] ? (event: EngineEvent<E>) => void : never const TX_ID = Symbol.for('prisma.client.transaction.id') const BatchTxIdCounter = { id: 0, nextId() { return ++this.id }, } export type Client = ReturnType<typeof getPrismaClient> extends new () => infer T ? T : never export function getPrismaClient(config: GetPrismaClientConfig) { class PrismaClient { _originalClient = this _runtimeDataModel: RuntimeDataModel _requestHandler: RequestHandler _connectionPromise?: Promise<any> _disconnectionPromise?: Promise<any> _engineConfig: EngineConfig _accelerateEngineConfig: AccelerateEngineConfig _clientVersion: string _errorFormat: ErrorFormat _tracingHelper: TracingHelper _previewFeatures: string[] _activeProvider: string _globalOmit?: GlobalOmitOptions _extensions: MergedExtensionsList /** * @remarks This is used internally by Policy, do not rename or remove */ _engine: Engine /** * A fully constructed/applied Client that references the parent * PrismaClient. This is used for Client extensions only. */ _appliedParent: PrismaClient _createPrismaPromise = createPrismaPromiseFactory() constructor(optionsArg?: PrismaClientOptions) { config = optionsArg?.__internal?.configOverride?.(config) ?? config checkPlatformCaching(config) if (optionsArg) { validatePrismaClientOptions(optionsArg, config) } // prevents unhandled error events when users do not explicitly listen to them const logEmitter = new EventEmitter().on('error', () => {}) as LogEmitter this._extensions = MergedExtensionsList.empty() this._previewFeatures = getPreviewFeatures(config) this._clientVersion = config.clientVersion ?? clientVersion this._activeProvider = config.activeProvider this._globalOmit = optionsArg?.omit this._tracingHelper = getTracingHelper() const envPaths = config.relativeEnvPaths && { rootEnvPath: config.relativeEnvPaths.rootEnvPath && path.resolve(config.dirname, config.relativeEnvPaths.rootEnvPath), schemaEnvPath: config.relativeEnvPaths.schemaEnvPath && path.resolve(config.dirname, config.relativeEnvPaths.schemaEnvPath), } /** * Initialise and validate the Driver Adapter, if provided. */ let adapter: SqlDriverAdapterFactory | undefined if (optionsArg?.adapter) { adapter = optionsArg.adapter // Note: // - `getConfig(..).datasources[0].provider` can be `postgresql`, `postgres`, `mysql`, or other known providers // - `getConfig(..).datasources[0].activeProvider`, stored in `config.activeProvider`, can be `postgresql`, `mysql`, or other known providers // - `adapter.provider` can be `postgres`, `mysql`, or `sqlite`, and changing this requires changes to Rust as well, // see https://github.com/prisma/prisma-engines/blob/d116c37d7d27aee74fdd840fc85ab2b45407e5ce/query-engine/driver-adapters/src/types.rs#L22-L23. // // TODO: Normalize these provider names once and for all in Prisma 6. const expectedDriverAdapterProvider = config.activeProvider === 'postgresql' ? 'postgres' : // CockroachDB is only accessible through Postgres driver adapters config.activeProvider === 'cockroachdb' ? 'postgres' : config.activeProvider if (adapter.provider !== expectedDriverAdapterProvider) { throw new PrismaClientInitializationError( `The Driver Adapter \`${adapter.adapterName}\`, based on \`${adapter.provider}\`, is not compatible with the provider \`${expectedDriverAdapterProvider}\` specified in the Prisma schema.`, this._clientVersion, ) } if (optionsArg.datasources || optionsArg.datasourceUrl !== undefined) { throw new PrismaClientInitializationError( `Custom datasource configuration is not compatible with Prisma Driver Adapters. Please define the database connection string directly in the Driver Adapter configuration.`, this._clientVersion, ) } } const loadedEnv = // for node we load the env from files, for edge only via env injections (NODE_CLIENT && !adapter && envPaths && tryLoadEnvs(envPaths, { conflictCheck: 'none' })) || config.injectableEdgeEnv?.() try { const options: PrismaClientOptions = optionsArg ?? {} const internal = options.__internal ?? {} const useDebug = internal.debug === true if (useDebug) { Debug.enable('prisma:client') } let cwd = path.resolve(config.dirname, config.relativePath) // TODO this logic should not be needed anymore #findSync if (!fs.existsSync(cwd)) { cwd = config.dirname } debug('dirname', config.dirname) debug('relativePath', config.relativePath) debug('cwd', cwd) const engineConfig = internal.engine || {} if (options.errorFormat) { this._errorFormat = options.errorFormat } else if (process.env.NODE_ENV === 'production') { this._errorFormat = 'minimal' } else if (process.env.NO_COLOR) { this._errorFormat = 'colorless' } else { this._errorFormat = 'colorless' // default errorFormat } this._runtimeDataModel = config.runtimeDataModel this._engineConfig = { cwd, dirname: config.dirname, enableDebugLogs: useDebug, allowTriggerPanic: engineConfig.allowTriggerPanic, prismaPath: engineConfig.binaryPath ?? undefined, engineEndpoint: engineConfig.endpoint, generator: config.generator, showColors: this._errorFormat === 'pretty', logLevel: options.log && (getLogLevel(options.log) as any), // TODO logQueries: options.log && Boolean( typeof options.log === 'string' ? options.log === 'query' : options.log.find((o) => (typeof o === 'string' ? o === 'query' : o.level === 'query')), ), env: loadedEnv?.parsed ?? {}, flags: [], engineWasm: config.engineWasm, compilerWasm: config.compilerWasm, clientVersion: config.clientVersion, engineVersion: config.engineVersion, previewFeatures: this._previewFeatures, activeProvider: config.activeProvider, inlineSchema: config.inlineSchema, overrideDatasources: getDatasourceOverrides(options, config.datasourceNames), inlineDatasources: config.inlineDatasources, inlineSchemaHash: config.inlineSchemaHash, tracingHelper: this._tracingHelper, transactionOptions: { maxWait: options.transactionOptions?.maxWait ?? 2000, timeout: options.transactionOptions?.timeout ?? 5000, isolationLevel: options.transactionOptions?.isolationLevel, }, logEmitter, isBundled: config.isBundled, adapter, } this._accelerateEngineConfig = { ...this._engineConfig, // share runtime utils to accelerate accelerateUtils: { resolveDatasourceUrl, getBatchRequestPayload, prismaGraphQLToJSError, PrismaClientUnknownRequestError, PrismaClientInitializationError, PrismaClientKnownRequestError, debug: Debug('prisma:client:accelerateEngine'), engineVersion: enginesVersion, clientVersion: config.clientVersion, }, } debug('clientVersion', config.clientVersion) this._engine = getEngineInstance(config, this._engineConfig) this._requestHandler = new RequestHandler(this, logEmitter) if (options.log) { for (const log of options.log) { const level = typeof log === 'string' ? log : log.emit === 'stdout' ? log.level : null if (level) { this.$on(level, (event) => { logger.log(`${logger.tags[level] ?? ''}`, (event as LogEvent).message || (event as QueryEvent).query) }) } } } } catch (e: any) { e.clientVersion = this._clientVersion throw e } // the first client has no parent so it is its own parent client // this is used for extensions to reference their parent client return (this._appliedParent = applyModelsAndClientExtensions(this)) // this applied client is also a custom constructor return value } get [Symbol.toStringTag]() { return 'PrismaClient' } $on<E extends ExtendedEventType>(eventType: E, callback: EventCallback<E>): PrismaClient { if (eventType === 'beforeExit') { this._engine.onBeforeExit(callback as EventCallback<'beforeExit'>) } else if (eventType) { this._engineConfig.logEmitter.on(eventType, callback as EventCallback<LogLevel>) } return this } $connect() { try { return this._engine.start() } catch (e: any) { e.clientVersion = this._clientVersion throw e } } /** * Disconnect from the database */ async $disconnect() { try { await this._engine.stop() } catch (e: any) { e.clientVersion = this._clientVersion throw e } finally { // Debug module keeps a list of last 100 logs regardless of environment // variables. This can cause a memory leak. It's especially bad in jest // environment where keeping an error in this list prevents jest sandbox // from being GCed. Clearing logs on disconnect helps to avoid that clearLogs() } } /** * Executes a raw query and always returns a number */ $executeRawInternal( transaction: PrismaPromiseTransaction | undefined, clientMethod: string, args: RawQueryArgs, middlewareArgsMapper?: MiddlewareArgsMapper<unknown, unknown>, ): Promise<number> { const activeProvider = this._activeProvider return this._request({ action: 'executeRaw', args, transaction, clientMethod, argsMapper: rawQueryArgsMapper({ clientMethod, activeProvider }), callsite: getCallSite(this._errorFormat), dataPath: [], middlewareArgsMapper, }) } /** * Executes a raw query provided through a safe tag function * @see https://github.com/prisma/prisma/issues/7142 * * @param query * @param values * @returns */ $executeRaw(query: TemplateStringsArray | Sql, ...values: any[]) { return this._createPrismaPromise((transaction) => { if ((query as TemplateStringsArray).raw !== undefined || (query as Sql).sql !== undefined) { const [sql, argsMapper] = toSql(query, values) checkAlter( this._activeProvider, sql.text, sql.values, Array.isArray(query) ? 'prisma.$executeRaw`<SQL>`' : 'prisma.$executeRaw(sql`<SQL>`)', ) return this.$executeRawInternal(transaction, '$executeRaw', sql, argsMapper) } throw new PrismaClientValidationError( `\`$executeRaw\` is a tag function, please use it like the following: \`\`\` const result = await prisma.$executeRaw\`UPDATE User SET cool = \${true} WHERE email = \${'user@email.com'};\` \`\`\` Or read our docs at https://www.prisma.io/docs/concepts/components/prisma-client/raw-database-access#executeraw `, { clientVersion: this._clientVersion }, ) }) } /** * Unsafe counterpart of `$executeRaw` that is susceptible to SQL injections * @see https://github.com/prisma/prisma/issues/7142 * * @param query * @param values * @returns */ $executeRawUnsafe(query: string, ...values: RawValue[]) { return this._createPrismaPromise((transaction) => { checkAlter(this._activeProvider, query, values, 'prisma.$executeRawUnsafe(<SQL>, [...values])') return this.$executeRawInternal(transaction, '$executeRawUnsafe', [query, ...values]) }) } /** * Executes a raw command only for MongoDB * * @param command * @returns */ $runCommandRaw(command: Record<string, JsInputValue>) { if (config.activeProvider !== 'mongodb') { throw new PrismaClientValidationError( `The ${config.activeProvider} provider does not support $runCommandRaw. Use the mongodb provider.`, { clientVersion: this._clientVersion }, ) } return this._createPrismaPromise((transaction) => { return this._request({ args: command, clientMethod: '$runCommandRaw', dataPath: [], action: 'runCommandRaw', argsMapper: rawCommandArgsMapper, callsite: getCallSite(this._errorFormat), transaction: transaction, }) }) } /** * Executes a raw query and returns selected data */ async $queryRawInternal( transaction: PrismaPromiseTransaction | undefined, clientMethod: string, args: RawQueryArgs, middlewareArgsMapper?: MiddlewareArgsMapper<unknown, unknown>, ) { const activeProvider = this._activeProvider return this._request({ action: 'queryRaw', args, transaction, clientMethod, argsMapper: rawQueryArgsMapper({ clientMethod, activeProvider }), callsite: getCallSite(this._errorFormat), dataPath: [], middlewareArgsMapper, }) } /** * Executes a raw query provided through a safe tag function * @see https://github.com/prisma/prisma/issues/7142 * * @param query * @param values * @returns */ $queryRaw(query: TemplateStringsArray | Sql, ...values: any[]) { return this._createPrismaPromise((transaction) => { if ((query as TemplateStringsArray).raw !== undefined || (query as Sql).sql !== undefined) { return this.$queryRawInternal(transaction, '$queryRaw', ...toSql(query, values)) } throw new PrismaClientValidationError( `\`$queryRaw\` is a tag function, please use it like the following: \`\`\` const result = await prisma.$queryRaw\`SELECT * FROM User WHERE id = \${1} OR email = \${'user@email.com'};\` \`\`\` Or read our docs at https://www.prisma.io/docs/concepts/components/prisma-client/raw-database-access#queryraw `, { clientVersion: this._clientVersion }, ) }) } /** * Counterpart to $queryRaw, that returns strongly typed results * @param typedSql */ $queryRawTyped(typedSql: UnknownTypedSql) { return this._createPrismaPromise((transaction) => { if (!this._hasPreviewFlag('typedSql')) { throw new PrismaClientValidationError( '`typedSql` preview feature must be enabled in order to access $queryRawTyped API', { clientVersion: this._clientVersion }, ) } return this.$queryRawInternal(transaction, '$queryRawTyped', typedSql) }) } /** * Unsafe counterpart of `$queryRaw` that is susceptible to SQL injections * @see https://github.com/prisma/prisma/issues/7142 * * @param query * @param values * @returns */ $queryRawUnsafe(query: string, ...values: RawValue[]) { return this._createPrismaPromise((transaction) => { return this.$queryRawInternal(transaction, '$queryRawUnsafe', [query, ...values]) }) } /** * Execute a batch of requests in a transaction * @param requests * @param options */ _transactionWithArray({ promises, options, }: { promises: Array<PrismaPromise<any>> options?: BatchTransactionOptions }): Promise<any> { const id = BatchTxIdCounter.nextId() const lock = getLockCountPromise(promises.length) const requests = promises.map((request, index) => { if (request?.[Symbol.toStringTag] !== 'PrismaPromise') { throw new Error( `All elements of the array need to be Prisma Client promises. Hint: Please make sure you are not awaiting the Prisma client calls you intended to pass in the $transaction function.`, ) } const isolationLevel = options?.isolationLevel ?? this._engineConfig.transactionOptions.isolationLevel const transaction = { kind: 'batch', id, index, isolationLevel, lock } as const return request.requestTransaction?.(transaction) ?? request }) return waitForBatch(requests) } /** * Perform a long-running transaction * @param callback * @param options * @returns */ async _transactionWithCallback({ callback, options, }: { callback: (client: Client) => Promise<unknown> options?: Options }) { const headers = { traceparent: this._tracingHelper.getTraceParent() } const optionsWithDefaults: Options = { maxWait: options?.maxWait ?? this._engineConfig.transactionOptions.maxWait, timeout: options?.timeout ?? this._engineConfig.transactionOptions.timeout, isolationLevel: options?.isolationLevel ?? this._engineConfig.transactionOptions.isolationLevel, } const info = await this._engine.transaction('start', headers, optionsWithDefaults) let result: unknown try { // execute user logic with a proxied the client const transaction = { kind: 'itx', ...info } as const result = await callback(this._createItxClient(transaction)) // it went well, then we commit the transaction await this._engine.transaction('commit', headers, info) } catch (e: any) { // it went bad, then we rollback the transaction await this._engine.transaction('rollback', headers, info).catch(() => {}) throw e // silent rollback, throw original error } return result } _createItxClient(transaction: PrismaPromiseInteractiveTransaction): Client { return createCompositeProxy( applyModelsAndClientExtensions( createCompositeProxy(unApplyModelsAndClientExtensions(this), [ addProperty('_appliedParent', () => this._appliedParent._createItxClient(transaction)), addProperty('_createPrismaPromise', () => createPrismaPromiseFactory(transaction)), addProperty(TX_ID, () => transaction.id), ]), ), [removeProperties(itxClientDenyList)], ) } /** * Execute queries within a transaction * @param input a callback or a query list * @param options to set timeouts (callback) * @returns */ $transaction(input: any, options?: any) { let callback: () => Promise<any> // iTx - Interactive transaction if (typeof input === 'function') { if (this._engineConfig.adapter?.adapterName === '@prisma/adapter-d1') { callback = () => { throw new Error( 'Cloudflare D1 does not support interactive transactions. We recommend you to refactor your queries with that limitation in mind, and use batch transactions with `prisma.$transactions([])` where applicable.', ) } } else { callback = () => this._transactionWithCallback({ callback: input, options }) } } else { // Batch transaction callback = () => this._transactionWithArray({ promises: input, options }) } const spanOptions = { name: 'transaction', attributes: { method: '$transaction' }, } return this._tracingHelper.runInChildSpan(spanOptions, callback) } /** * Runs the middlewares over params before executing a request * @param internalParams * @returns */ _request(internalParams: InternalRequestParams): Promise<any> { // this is the otel context that is active at the callsite internalParams.otelParentCtx = this._tracingHelper.getActiveContext() const middlewareArgsMapper = internalParams.middlewareArgsMapper ?? noopMiddlewareArgsMapper // make sure that we don't leak extra properties to users const params: QueryMiddlewareParams = { args: middlewareArgsMapper.requestArgsToMiddlewareArgs(internalParams.args), dataPath: internalParams.dataPath, runInTransaction: Boolean(internalParams.transaction), action: internalParams.action, model: internalParams.model, } // span options for opentelemetry instrumentation const spanOptions = { operation: { name: 'operation', attributes: { method: params.action, model: params.model, name: params.model ? `${params.model}.${params.action}` : params.action, }, } as ExtendedSpanOptions, } // prepare recursive fn that will pipe params through middlewares const consumer = async (changedMiddlewareParams: QueryMiddlewareParams) => { // we proceed with request execution // before we send the execution request, we use the changed params const { runInTransaction, args, ...changedRequestParams } = changedMiddlewareParams const requestParams = { ...internalParams, ...changedRequestParams, } if (args) { requestParams.args = middlewareArgsMapper.middlewareArgsToRequestArgs(args) } // if middleware switched off `runInTransaction`, unset `transaction` // property on request as well so it will be executed outside of the tx if (internalParams.transaction !== undefined && runInTransaction === false) { delete requestParams.transaction // client extensions check for this } const result = await applyQueryExtensions(this, requestParams) // also executes the query if (!requestParams.model) { return result } return applyAllResultExtensions({ result, modelName: requestParams.model, args: requestParams.args, extensions: this._extensions, runtimeDataModel: this._runtimeDataModel, globalOmit: this._globalOmit, }) } return this._tracingHelper.runInChildSpan(spanOptions.operation, () => { if (NODE_CLIENT) { // https://github.com/prisma/prisma/issues/3148 not for edge client const asyncRes = new AsyncResource('prisma-client-request') return asyncRes.runInAsyncScope(() => consumer(params)) } return consumer(params) }) } async _executeRequest({ args, clientMethod, dataPath, callsite, action, model, argsMapper, transaction, unpacker, otelParentCtx, customDataProxyFetch, }: InternalRequestParams) { try { // execute argument transformation before execution args = argsMapper ? argsMapper(args) : args const spanOptions: ExtendedSpanOptions = { name: 'serialize', } const message = this._tracingHelper.runInChildSpan(spanOptions, () => serializeJsonQuery({ modelName: model, runtimeDataModel: this._runtimeDataModel, action, args, clientMethod, callsite, extensions: this._extensions, errorFormat: this._errorFormat, clientVersion: this._clientVersion, previewFeatures: this._previewFeatures, globalOmit: this._globalOmit, }), ) // as prettyPrintArguments takes a bit of compute // we only want to do it, if debug is enabled for 'prisma-client' if (Debug.enabled('prisma:client')) { debug(`Prisma Client call:`) debug(`prisma.${clientMethod}(${prettyPrintArguments(args)})`) debug(`Generated request:`) debug(JSON.stringify(message, null, 2) + '\n') } if (transaction?.kind === 'batch') { /** @see {@link getLockCountPromise} */ await transaction.lock } return this._requestHandler.request({ protocolQuery: message, modelName: model, action, clientMethod, dataPath, callsite, args, extensions: this._extensions, transaction, unpacker, otelParentCtx, otelChildCtx: this._tracingHelper.getActiveContext(), globalOmit: this._globalOmit, customDataProxyFetch, }) } catch (e) { e.clientVersion = this._clientVersion throw e } } $metrics = new MetricsClient(this) /** * Shortcut for checking a preview flag * @param feature preview flag * @returns */ _hasPreviewFlag(feature: string) { return !!this._engineConfig.previewFeatures?.includes(feature) } $applyPendingMigrations(): Promise<void> { return this._engine.applyPendingMigrations() } $extends = $extends } return PrismaClient } function toSql(query: TemplateStringsArray | Sql, values: unknown[]): [Sql, MiddlewareArgsMapper<unknown, unknown>] { if (isTemplateStringArray(query)) { return [new Sql(query, values), templateStringMiddlewareArgsMapper] } return [query, sqlMiddlewareArgsMapper] } function isTemplateStringArray(value: unknown): value is TemplateStringsArray { return Array.isArray(value) && Array.isArray(value['raw']) }

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