Skip to main content
Glama

Prisma MCP Server

Official
by prisma
Apache 2.0
4
44,213
  • Linux
  • Apple
itx.ts9.32 kB
import { faker } from '@faker-js/faker' import { copycat } from '@snaplet/copycat' import { expectTypeOf } from 'expect-type' import { AdapterProviders, Providers } from '../_utils/providers' import testMatrix from './_matrix' // @ts-ignore import type { Prisma as PrismaNamespace, PrismaClient } from './generated/prisma/client' declare let prisma: PrismaClient declare let Prisma: typeof PrismaNamespace const email = faker.internet.email() testMatrix.setupTestSuite( ({ provider }, _suiteMeta, _clientMeta) => { beforeEach(async () => { await prisma.post.deleteMany() await prisma.user.deleteMany() const { id: userId } = await prisma.user.create({ data: { email, firstName: 'John', lastName: 'Smith', }, }) await prisma.post.create({ data: { user: { connect: { id: userId } }, }, }) }) test('client is extended in itx', async () => { const xprisma = prisma.$extends({ result: { user: { fullName: { needs: { firstName: true, lastName: true }, compute(user) { return `${user.firstName} ${user.lastName}` }, }, }, }, }) await xprisma.$transaction(async (tx) => { const user = await tx.user.findFirst({}) expect(user?.fullName).toBe('John Smith') expectTypeOf(user?.fullName).toEqualTypeOf<string | undefined>() }) }) test('extended client in itx can rollback via normal call', async () => { const xprisma = prisma.$extends({ result: { user: { fullName: { needs: { firstName: true, lastName: true }, compute(user) { return `${user.firstName} ${user.lastName}` }, }, }, }, }) const result = xprisma.$transaction(async (tx) => { const userA = await tx.user.create({ data: { id: copycat.uuid(0).replaceAll('-', '').slice(-24), email: 'jane@smith.com', firstName: 'Jane', lastName: 'Smith', }, }) await tx.user.create({ data: { id: copycat.uuid(1).replaceAll('-', '').slice(-24), email: 'jane@smith.com', firstName: 'Jane', lastName: 'Smith', }, }) expectTypeOf(userA?.fullName).toEqualTypeOf<string>() }) await expect(result).rejects.toMatchPrismaErrorSnapshot() const users = await prisma.user.findMany({ where: { email: 'jane@smith.com' } }) expect(users).toHaveLength(0) }) test('extended client in itx works via normal call', async () => { const xprisma = prisma.$extends({ result: { user: { fullName: { needs: { firstName: true, lastName: true }, compute(user) { return `${user.firstName} ${user.lastName}` }, }, }, }, }) await xprisma.$transaction(async (tx) => { const userA = await tx.user.create({ data: { email: 'jane@smith.com', firstName: 'Jane', lastName: 'Smith', }, }) expectTypeOf(userA?.fullName).toEqualTypeOf<string>() }) const users = await prisma.user.findMany({ where: { email: 'jane@smith.com' } }) expect(users).toHaveLength(1) }) test('extended client in itx can rollback via custom call', async () => { const xprisma = prisma .$extends({ result: { user: { fullName: { needs: { firstName: true, lastName: true }, compute(user) { return `${user.firstName} ${user.lastName}` }, }, }, }, }) .$extends({ model: { $allModels: { createAlt(args: any) { return (this as any).create(args) }, }, }, }) const result = xprisma.$transaction(async (tx) => { await tx.user.createAlt({ data: { id: copycat.uuid(0).replaceAll('-', '').slice(-24), email: 'jane@smith.com', firstName: 'Jane', lastName: 'Smith', }, }) await tx.user.createAlt({ data: { id: copycat.uuid(1).replaceAll('-', '').slice(-24), email: 'jane@smith.com', firstName: 'Jane', lastName: 'Smith', }, }) }) await expect(result).rejects.toMatchPrismaErrorSnapshot() const users = await prisma.user.findMany({ where: { email: 'jane@smith.com' } }) expect(users).toHaveLength(0) }) test('extended client in itx works via custom call', async () => { const xprisma = prisma .$extends({ result: { user: { fullName: { needs: { firstName: true, lastName: true }, compute(user) { return `${user.firstName} ${user.lastName}` }, }, }, }, }) .$extends({ model: { $allModels: { createAlt(args: any) { return (this as any).create(args) }, }, }, }) await xprisma.$transaction(async (tx) => { await tx.user.createAlt({ data: { email: 'jane@smith.com', firstName: 'Jane', lastName: 'Smith', }, }) }) const users = await prisma.user.findMany({ where: { email: 'jane@smith.com' } }) expect(users).toHaveLength(1) }) testIf(provider !== Providers.MONGODB)('itx works with extended client + queryRawUnsafe', async () => { const xprisma = prisma.$extends({}) await expect( xprisma.$transaction((tx) => { // @ts-test-if: provider !== Providers.MONGODB return tx.$queryRawUnsafe('SELECT 1') }), ).resolves.not.toThrow() }) test('client component is available within itx callback', async () => { const helper = jest.fn() const xprisma = prisma.$extends({ client: { helper, }, }) await xprisma.$transaction((tx) => { tx.helper() return Promise.resolve() }) expect(helper).toHaveBeenCalled() }) test('methods from itx client denylist are optional within client extensions', async () => { expect.assertions(10) const xprisma = prisma.$extends({ client: { testContextMethods(isTransaction: boolean) { const ctx = Prisma.getExtensionContext(this) // eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents expectTypeOf(ctx.$connect).toEqualTypeOf<typeof prisma.$connect | undefined>() // eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents expectTypeOf(ctx.$disconnect).toEqualTypeOf<typeof prisma.$disconnect | undefined>() expectTypeOf(ctx.$transaction).toMatchTypeOf<Function | undefined>() // eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents expectTypeOf(ctx.$extends).toEqualTypeOf<typeof prisma.$extends | undefined>() expectTypeOf(ctx).not.toHaveProperty('$on') expect(ctx['$on']).toBeUndefined() if (isTransaction) { expect(ctx.$connect).toBeUndefined() expect(ctx.$disconnect).toBeUndefined() expect(ctx.$transaction).toBeUndefined() expect(ctx.$extends).toBeUndefined() } else { expect(ctx.$connect).toBeDefined() expect(ctx.$disconnect).toBeDefined() expect(ctx.$transaction).toBeDefined() expect(ctx.$extends).toBeDefined() } }, }, model: { user: { helper() {}, }, }, }) xprisma.testContextMethods(false) await xprisma.$transaction((tx) => { tx.testContextMethods(true) return Promise.resolve() }) }) test('isolation level is properly reflected in extended client', () => { ;async () => { const xprisma = prisma.$extends({}) // @ts-test-if: provider !== Providers.MONGODB const data = await xprisma.$transaction( () => { return Promise.resolve(42) }, { isolationLevel: 'Serializable', }, ) // @ts-test-if: provider !== Providers.MONGODB expectTypeOf(data).toEqualTypeOf<number>() } }) }, { skipDriverAdapter: { from: [AdapterProviders.JS_D1, AdapterProviders.JS_LIBSQL], reason: 'js_d1: iTx are not possible. There is no Transaction API for D1 yet: https://github.com/cloudflare/workers-sdk/issues/2733; ' + 'js_libsql: SIGABRT due to panic in libsql (not yet implemented: array)', // TODO: ORM-867 }, }, )

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