Skip to main content
Glama

Prisma MCP Server

Official
by prisma
PrismaClient.ts22.9 kB
import { capitalize, NonModelOperation, Operation, uncapitalize } from '@prisma/client-common' import type * as DMMF from '@prisma/dmmf' import type { DataSource } from '@prisma/generator' import { assertNever } from '@prisma/internals' import * as ts from '@prisma/ts-builders' import indent from 'indent-string' import { extArgsParam, getAggregateName, getCountAggregateOutputName, getFieldRefsTypeName, getGroupByName, getModelArgName, getPayloadName, } from '../utils' import { runtimeImportedType } from '../utils/runtimeImport' import { TAB_SIZE } from './constants' import type { Generable } from './Generable' import { GenerateContext } from './GenerateContext' import { globalOmitConfig } from './globalOmit' import { TSClientOptions } from './TSClient' import { getModelActions } from './utils/getModelActions' import * as tsx from './utils/type-builders' function clientTypeMapModelsDefinition(context: GenerateContext) { const meta = ts.objectType() const modelNames = context.dmmf.datamodel.models.map((m) => m.name) // `modelNames` can be empty if `generate --allow-no-models` is used. if (modelNames.length === 0) { meta.add(ts.property('modelProps', ts.neverType)) } else { meta.add(ts.property('modelProps', ts.unionType(modelNames.map((name) => ts.stringLiteral(uncapitalize(name)))))) } const isolationLevel = context.dmmf.hasEnumInNamespace('TransactionIsolationLevel', 'prisma') ? ts.namedType('Prisma.TransactionIsolationLevel') : ts.neverType meta.add(ts.property('txIsolationLevel', isolationLevel)) const model = ts.objectType() model.addMultiple( modelNames.map((modelName) => { const entry = ts.objectType() entry.add( ts.property('payload', ts.namedType(getPayloadName(modelName)).addGenericArgument(extArgsParam.toArgument())), ) entry.add(ts.property('fields', ts.namedType(`Prisma.${getFieldRefsTypeName(modelName)}`))) const actions = getModelActions(context.dmmf, modelName) const operations = ts.objectType() operations.addMultiple( actions.map((action) => { const operationType = ts.objectType() const argsType = `Prisma.${getModelArgName(modelName, action)}` operationType.add(ts.property('args', ts.namedType(argsType).addGenericArgument(extArgsParam.toArgument()))) operationType.add(ts.property('result', clientTypeMapModelsResultDefinition(modelName, action))) return ts.property(action, operationType) }), ) entry.add(ts.property('operations', operations)) return ts.property(modelName, entry) }), ) return ts .objectType() .add(ts.property('globalOmitOptions', ts.objectType().add(ts.property('omit', ts.namedType('GlobalOmitOptions'))))) .add(ts.property('meta', meta)) .add(ts.property('model', model)) } function clientTypeMapModelsResultDefinition( modelName: string, action: Exclude<Operation, `$${string}`>, ): ts.TypeBuilder { if (action === 'count') return ts.unionType([tsx.optional(ts.namedType(getCountAggregateOutputName(modelName))), ts.numberType]) if (action === 'groupBy') return ts.array(tsx.optional(ts.namedType(getGroupByName(modelName)))) if (action === 'aggregate') return tsx.optional(ts.namedType(getAggregateName(modelName))) if (action === 'findRaw') return ts.namedType('JsonObject') if (action === 'aggregateRaw') return ts.namedType('JsonObject') if (action === 'deleteMany') return ts.namedType('BatchPayload') if (action === 'createMany') return ts.namedType('BatchPayload') if (action === 'createManyAndReturn') return ts.array(payloadToResult(modelName)) if (action === 'updateMany') return ts.namedType('BatchPayload') if (action === 'updateManyAndReturn') return ts.array(payloadToResult(modelName)) if (action === 'findMany') return ts.array(payloadToResult(modelName)) if (action === 'findFirst') return ts.unionType([payloadToResult(modelName), ts.nullType]) if (action === 'findUnique') return ts.unionType([payloadToResult(modelName), ts.nullType]) if (action === 'findFirstOrThrow') return payloadToResult(modelName) if (action === 'findUniqueOrThrow') return payloadToResult(modelName) if (action === 'create') return payloadToResult(modelName) if (action === 'update') return payloadToResult(modelName) if (action === 'upsert') return payloadToResult(modelName) if (action === 'delete') return payloadToResult(modelName) assertNever(action, `Unknown action: ${action}`) } function payloadToResult(modelName: string) { return ts.namedType('$Utils.PayloadToResult').addGenericArgument(ts.namedType(getPayloadName(modelName))) } function clientTypeMapOthersDefinition(context: GenerateContext) { const otherOperationsNames = context.dmmf.getOtherOperationNames().flatMap((name) => { const results = [`$${name}`] if (name === 'executeRaw' || name === 'queryRaw') { results.push(`$${name}Unsafe`) } if (name === 'queryRaw' && context.isPreviewFeatureOn('typedSql')) { results.push(`$queryRawTyped`) } return results }) const argsResultMap = { $executeRaw: { args: '[query: TemplateStringsArray | Prisma.Sql, ...values: any[]]', result: 'any' }, $queryRaw: { args: '[query: TemplateStringsArray | Prisma.Sql, ...values: any[]]', result: 'any' }, $executeRawUnsafe: { args: '[query: string, ...values: any[]]', result: 'any' }, $queryRawUnsafe: { args: '[query: string, ...values: any[]]', result: 'any' }, $runCommandRaw: { args: 'Prisma.InputJsonObject', result: 'Prisma.JsonObject' }, $queryRawTyped: { args: 'runtime.UnknownTypedSql', result: 'Prisma.JsonObject' }, } satisfies Record<NonModelOperation, { args: string; result: string }> return `{ other: { payload: any operations: {${otherOperationsNames.reduce((acc, action) => { return `${acc} ${action}: { args: ${argsResultMap[action].args}, result: ${argsResultMap[action].result} }` }, '')} } } }` } function clientTypeMapDefinition(context: GenerateContext) { const typeMap = `${ts.stringify(clientTypeMapModelsDefinition(context))} & ${clientTypeMapOthersDefinition(context)}` return ` interface TypeMapCb<ClientOptions = {}> extends $Utils.Fn<{extArgs: $Extensions.InternalArgs }, $Utils.Record<string, any>> { returns: Prisma.TypeMap<this['params']['extArgs'], ClientOptions extends { omit: infer OmitOptions } ? OmitOptions : {}> } export type TypeMap<ExtArgs extends $Extensions.InternalArgs = $Extensions.DefaultArgs, GlobalOmitOptions = {}> = ${typeMap}` } function clientExtensionsDefinitions(context: GenerateContext) { const typeMap = clientTypeMapDefinition(context) const define = ts.moduleExport( ts.constDeclaration( 'defineExtension', ts .namedType('$Extensions.ExtendsHook') .addGenericArgument(ts.stringLiteral('define')) .addGenericArgument(ts.namedType('Prisma.TypeMapCb')) .addGenericArgument(ts.namedType('$Extensions.DefaultArgs')), ), ) return [typeMap, ts.stringify(define)].join('\n') } function extendsPropertyDefinition() { const extendsDefinition = ts .namedType('$Extensions.ExtendsHook') .addGenericArgument(ts.stringLiteral('extends')) .addGenericArgument(ts.namedType('Prisma.TypeMapCb').addGenericArgument(ts.namedType('ClientOptions'))) .addGenericArgument(ts.namedType('ExtArgs')) .addGenericArgument( ts .namedType('$Utils.Call') .addGenericArgument(ts.namedType('Prisma.TypeMapCb').addGenericArgument(ts.namedType('ClientOptions'))) .addGenericArgument(ts.objectType().add(ts.property('extArgs', ts.namedType('ExtArgs')))), ) return ts.stringify(ts.property('$extends', extendsDefinition), { indentLevel: 1 }) } function batchingTransactionDefinition(context: GenerateContext) { const method = ts .method('$transaction') .setDocComment( ts.docComment` Allows the running of a sequence of read/write operations that are guaranteed to either succeed or fail as a whole. @example \`\`\` const [george, bob, alice] = await prisma.$transaction([ prisma.user.create({ data: { name: 'George' } }), prisma.user.create({ data: { name: 'Bob' } }), prisma.user.create({ data: { name: 'Alice' } }), ]) \`\`\` Read more in our [docs](https://www.prisma.io/docs/concepts/components/prisma-client/transactions). `, ) .addGenericParameter(ts.genericParameter('P').extends(ts.array(tsx.prismaPromise(ts.anyType)))) .addParameter(ts.parameter('arg', ts.arraySpread(ts.namedType('P')))) .setReturnType(tsx.promise(ts.namedType('runtime.Types.Utils.UnwrapTuple').addGenericArgument(ts.namedType('P')))) if (context.dmmf.hasEnumInNamespace('TransactionIsolationLevel', 'prisma')) { const options = ts .objectType() .formatInline() .add(ts.property('isolationLevel', ts.namedType('Prisma.TransactionIsolationLevel')).optional()) method.addParameter(ts.parameter('options', options).optional()) } return ts.stringify(method, { indentLevel: 1, newLine: 'leading' }) } function interactiveTransactionDefinition(context: GenerateContext) { const options = ts .objectType() .formatInline() .add(ts.property('maxWait', ts.numberType).optional()) .add(ts.property('timeout', ts.numberType).optional()) if (context.dmmf.hasEnumInNamespace('TransactionIsolationLevel', 'prisma')) { const isolationLevel = ts.property('isolationLevel', ts.namedType('Prisma.TransactionIsolationLevel')).optional() options.add(isolationLevel) } const returnType = tsx.promise(ts.namedType('R')) const callbackType = ts .functionType() .addParameter( ts.parameter('prisma', ts.omit(ts.namedType('PrismaClient'), ts.namedType('runtime.ITXClientDenyList'))), ) .setReturnType(returnType) const method = ts .method('$transaction') .addGenericParameter(ts.genericParameter('R')) .addParameter(ts.parameter('fn', callbackType)) .addParameter(ts.parameter('options', options).optional()) .setReturnType(returnType) return ts.stringify(method, { indentLevel: 1, newLine: 'leading' }) } function queryRawDefinition(context: GenerateContext) { // we do not generate `$queryRaw...` definitions if not supported if (!context.dmmf.mappings.otherOperations.write.includes('queryRaw')) { return '' // https://github.com/prisma/prisma/issues/8189 } return ` /** * Performs a prepared raw query and returns the \`SELECT\` data. * @example * \`\`\` * const result = await prisma.$queryRaw\`SELECT * FROM User WHERE id = \${1} OR email = \${'user@email.com'};\` * \`\`\` * * Read more in our [docs](https://www.prisma.io/docs/reference/tools-and-interfaces/prisma-client/raw-database-access). */ $queryRaw<T = unknown>(query: TemplateStringsArray | Prisma.Sql, ...values: any[]): Prisma.PrismaPromise<T>; /** * Performs a raw query and returns the \`SELECT\` data. * Susceptible to SQL injections, see documentation. * @example * \`\`\` * const result = await prisma.$queryRawUnsafe('SELECT * FROM User WHERE id = $1 OR email = $2;', 1, 'user@email.com') * \`\`\` * * Read more in our [docs](https://www.prisma.io/docs/reference/tools-and-interfaces/prisma-client/raw-database-access). */ $queryRawUnsafe<T = unknown>(query: string, ...values: any[]): Prisma.PrismaPromise<T>;` } function executeRawDefinition(context: GenerateContext) { // we do not generate `$executeRaw...` definitions if not supported if (!context.dmmf.mappings.otherOperations.write.includes('executeRaw')) { return '' // https://github.com/prisma/prisma/issues/8189 } return ` /** * Executes a prepared raw query and returns the number of affected rows. * @example * \`\`\` * const result = await prisma.$executeRaw\`UPDATE User SET cool = \${true} WHERE email = \${'user@email.com'};\` * \`\`\` * * Read more in our [docs](https://www.prisma.io/docs/reference/tools-and-interfaces/prisma-client/raw-database-access). */ $executeRaw<T = unknown>(query: TemplateStringsArray | Prisma.Sql, ...values: any[]): Prisma.PrismaPromise<number>; /** * Executes a raw query and returns the number of affected rows. * Susceptible to SQL injections, see documentation. * @example * \`\`\` * const result = await prisma.$executeRawUnsafe('UPDATE User SET cool = $1 WHERE email = $2 ;', true, 'user@email.com') * \`\`\` * * Read more in our [docs](https://www.prisma.io/docs/reference/tools-and-interfaces/prisma-client/raw-database-access). */ $executeRawUnsafe<T = unknown>(query: string, ...values: any[]): Prisma.PrismaPromise<number>;` } function queryRawTypedDefinition(context: GenerateContext) { if (!context.isPreviewFeatureOn('typedSql')) { return '' } if (!context.dmmf.mappings.otherOperations.write.includes('queryRaw')) { return '' } const param = ts.genericParameter('T') const method = ts .method('$queryRawTyped') .setDocComment( ts.docComment` Executes a typed SQL query and returns a typed result @example \`\`\` import { myQuery } from '@prisma/client/sql' const result = await prisma.$queryRawTyped(myQuery()) \`\`\` `, ) .addGenericParameter(param) .addParameter( ts.parameter( 'typedSql', runtimeImportedType('TypedSql') .addGenericArgument(ts.array(ts.unknownType)) .addGenericArgument(param.toArgument()), ), ) .setReturnType(tsx.prismaPromise(ts.array(param.toArgument()))) return ts.stringify(method, { indentLevel: 1, newLine: 'leading' }) } function runCommandRawDefinition(context: GenerateContext) { // we do not generate `$runCommandRaw` definitions if not supported if (!context.dmmf.mappings.otherOperations.write.includes('runCommandRaw')) { return '' // https://github.com/prisma/prisma/issues/8189 } const method = ts .method('$runCommandRaw') .addParameter(ts.parameter('command', ts.namedType('Prisma.InputJsonObject'))) .setReturnType(tsx.prismaPromise(ts.namedType('Prisma.JsonObject'))).setDocComment(ts.docComment` Executes a raw MongoDB command and returns the result of it. @example \`\`\` const user = await prisma.$runCommandRaw({ aggregate: 'User', pipeline: [{ $match: { name: 'Bob' } }, { $project: { email: true, _id: false } }], explain: false, }) \`\`\` Read more in our [docs](https://www.prisma.io/docs/reference/tools-and-interfaces/prisma-client/raw-database-access). `) return ts.stringify(method, { indentLevel: 1, newLine: 'leading' }) } export class PrismaClientClass implements Generable { constructor( protected readonly context: GenerateContext, protected readonly internalDatasources: DataSource[], protected readonly outputDir: string, protected readonly runtimeName: TSClientOptions['runtimeName'], protected readonly browser?: boolean, ) {} private get jsDoc(): string { const { dmmf } = this.context let example: DMMF.ModelMapping if (dmmf.mappings.modelOperations.length) { example = dmmf.mappings.modelOperations[0] } else { // because generator models is empty we need to create a fake example example = { model: 'User', plural: 'users', } } return `/** * ## Prisma Client ʲˢ * * Type-safe database client for TypeScript & Node.js * @example * \`\`\` * const prisma = new PrismaClient() * // Fetch zero or more ${capitalize(example.plural)} * const ${uncapitalize(example.plural)} = await prisma.${uncapitalize(example.model)}.findMany() * \`\`\` * * * Read more in our [docs](https://www.prisma.io/docs/reference/tools-and-interfaces/prisma-client). */` } public toTSWithoutNamespace(): string { const { dmmf } = this.context return `${this.jsDoc} export class PrismaClient< ClientOptions extends Prisma.PrismaClientOptions = Prisma.PrismaClientOptions, const U = 'log' extends keyof ClientOptions ? ClientOptions['log'] extends Array<Prisma.LogLevel | Prisma.LogDefinition> ? Prisma.GetEvents<ClientOptions['log']> : never : never, ExtArgs extends $Extensions.InternalArgs = $Extensions.DefaultArgs > { [K: symbol]: { types: Prisma.TypeMap<ExtArgs>['other'] } ${indent(this.jsDoc, TAB_SIZE)} constructor(optionsArg ?: Prisma.Subset<ClientOptions, Prisma.PrismaClientOptions>); $on<V extends U>(eventType: V, callback: (event: V extends 'query' ? Prisma.QueryEvent : Prisma.LogEvent) => void): PrismaClient; /** * Connect with the database */ $connect(): $Utils.JsPromise<void>; /** * Disconnect from the database */ $disconnect(): $Utils.JsPromise<void>; ${[ executeRawDefinition(this.context), queryRawDefinition(this.context), queryRawTypedDefinition(this.context), batchingTransactionDefinition(this.context), interactiveTransactionDefinition(this.context), runCommandRawDefinition(this.context), extendsPropertyDefinition(), ] .filter((d) => d !== null) .join('\n') .trim()} ${indent( dmmf.mappings.modelOperations .filter((m) => m.findMany) .map((m) => { let methodName = uncapitalize(m.model) if (methodName === 'constructor') { methodName = '["constructor"]' } const generics = ['ExtArgs', 'ClientOptions'] return `\ /** * \`prisma.${methodName}\`: Exposes CRUD operations for the **${m.model}** model. * Example usage: * \`\`\`ts * // Fetch zero or more ${capitalize(m.plural)} * const ${uncapitalize(m.plural)} = await prisma.${methodName}.findMany() * \`\`\` */ get ${methodName}(): Prisma.${m.model}Delegate<${generics.join(', ')}>;` }) .join('\n\n'), 2, )} }` } public toTS(): string { const clientOptions = this.buildClientOptions() return `${clientExtensionsDefinitions(this.context)} export type DefaultPrismaClient = PrismaClient export type ErrorFormat = 'pretty' | 'colorless' | 'minimal' ${ts.stringify(ts.moduleExport(clientOptions))} ${ts.stringify(globalOmitConfig(this.context.dmmf))} /* Types for Logging */ export type LogLevel = 'info' | 'query' | 'warn' | 'error' export type LogDefinition = { level: LogLevel emit: 'stdout' | 'event' } export type CheckIsLogLevel<T> = T extends LogLevel ? T : never; export type GetLogType<T> = CheckIsLogLevel< T extends LogDefinition ? T['level'] : T >; export type GetEvents<T extends any[]> = T extends Array<LogLevel | LogDefinition> ? GetLogType<T[number]> : never; 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 */ export type PrismaAction = | 'findUnique' | 'findUniqueOrThrow' | 'findMany' | 'findFirst' | 'findFirstOrThrow' | 'create' | 'createMany' | 'createManyAndReturn' | 'update' | 'updateMany' | 'updateManyAndReturn' | 'upsert' | 'delete' | 'deleteMany' | 'executeRaw' | 'queryRaw' | 'aggregate' | 'count' | 'runCommandRaw' | 'findRaw' | 'groupBy' // tested in getLogLevel.test.ts export function getLogLevel(log: Array<LogLevel | LogDefinition>): LogLevel | undefined; /** * \`PrismaClient\` proxy available in interactive transactions. */ export type TransactionClient = Omit<Prisma.DefaultPrismaClient, runtime.ITXClientDenyList> ` } private buildClientOptions() { const clientOptions = ts .interfaceDeclaration('PrismaClientOptions') .add( ts .property('errorFormat', ts.namedType('ErrorFormat')) .optional() .setDocComment(ts.docComment('@default "colorless"')), ) .add( ts.property('log', ts.array(ts.unionType([ts.namedType('LogLevel'), ts.namedType('LogDefinition')]))).optional() .setDocComment(ts.docComment` @example \`\`\` // Shorthand for \`emit: 'stdout'\` log: ['query', 'info', 'warn', 'error'] // Emit as events only log: [ { emit: 'event', level: 'query' }, { emit: 'event', level: 'info' }, { emit: 'event', level: 'warn' } { emit: 'event', level: 'error' } ] // Emit as events and log to stdout log: [ { emit: 'stdout', level: 'query' }, { emit: 'stdout', level: 'info' }, { emit: 'stdout', level: 'warn' } { emit: 'stdout', level: 'error' } ] \`\`\` Read more in our [docs](https://www.prisma.io/docs/reference/tools-and-interfaces/prisma-client/logging#the-log-option). `), ) const transactionOptions = ts .objectType() .add(ts.property('maxWait', ts.numberType).optional()) .add(ts.property('timeout', ts.numberType).optional()) if (this.context.dmmf.hasEnumInNamespace('TransactionIsolationLevel', 'prisma')) { transactionOptions.add(ts.property('isolationLevel', ts.namedType('Prisma.TransactionIsolationLevel')).optional()) } clientOptions.add( ts.property('transactionOptions', transactionOptions).optional().setDocComment(ts.docComment` The default values for transactionOptions maxWait ?= 2000 timeout ?= 5000 `), ) if ( // We don't support a custom adapter with MongoDB for now. this.internalDatasources.some((d) => d.provider !== 'mongodb') ) { clientOptions.add( ts .property('adapter', ts.namedType('runtime.SqlDriverAdapterFactory')) .optional() .setDocComment( ts.docComment('Instance of a Driver Adapter, e.g., like one provided by `@prisma/adapter-planetscale`'), ), ) } clientOptions.add( ts .property('accelerateUrl', ts.stringType) .optional() .setDocComment( ts.docComment( 'Prisma Accelerate URL allowing the client to connect through Accelerate instead of a direct database.', ), ), ) clientOptions.add( ts.property('omit', ts.namedType('Prisma.GlobalOmitConfig')).optional().setDocComment(ts.docComment` Global configuration for omitting model fields by default. @example \`\`\` const prisma = new PrismaClient({ omit: { user: { password: true } } }) \`\`\` `), ) return clientOptions } }

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