Tous les articles
TypeScriptBackendDatabase

Prisma 6: TypedSQL, Multi-Schema Support, and the omit API

//
·7 min de lecture

Prisma 6 ships TypedSQL for fully type-safe raw queries, multi-schema support for PlanetScale and Supabase, the omit API for excluding sensitive fields at the query level, and query extensions for reusable logic.

Prisma 6 released on November 11, 2024 alongside a rebrand from “Prisma ORM” to just “Prisma”. The release promotes TypedSQL from Preview to Generally Available, adds multi-schema support for multi-tenant and multi-database platforms, and ships the omit API for fine-grained field exclusion.

>TypedSQL — type-safe raw queries

TypedSQL lets you write raw SQL in .sql files and automatically generates fully typed TypeScript functions from them.

bash
# Enable in schema.prisma
generator client {
  provider        = "prisma-client-js"
  previewFeatures = []  # TypedSQL is GA — no preview flag needed in Prisma 6
}

# Create a SQL file
mkdir -p prisma/sql
touch prisma/sql/getUsersWithRevenue.sql

# Regenerate client after adding SQL files
npx prisma generate --sql
SQL
-- prisma/sql/getUsersWithRevenue.sql
SELECT
  u.id,
  u.name,
  u.email,
  COALESCE(SUM(o.total), 0)::int AS total_revenue
FROM users u
LEFT JOIN orders o ON o.user_id = u.id
WHERE u.created_at > $1
GROUP BY u.id
ORDER BY total_revenue DESC
LIMIT $2;
TypeScript
// Generated function — fully typed, no any
import { PrismaClient } from '@prisma/client';
import { getUsersWithRevenue } from '@prisma/client/sql';

const prisma = new PrismaClient();

const result = await prisma.$queryRawTyped(
  getUsersWithRevenue(new Date('2024-01-01'), 10),
);
// result: Array<{ id: string; name: string; email: string; total_revenue: number }>

>omit — exclude sensitive fields

TypeScript
// Exclude password globally in the client
const prisma = new PrismaClient().$extends({
  result: {
    user: {
      password: { needs: {}, compute: () => undefined },
    },
  },
});

// Or per-query
const user = await prisma.user.findUnique({
  where: { id },
  omit: { password: true, internalNotes: true },
});
// user.password is undefined — TypeScript knows this too

// In a findMany
const users = await prisma.user.findMany({
  omit: { password: true },
});

>Multi-schema support (GA)

prisma
// schema.prisma
generator client {
  provider        = "prisma-client-js"
  previewFeatures = ["multiSchema"]
}

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
  schemas  = ["public", "auth", "billing"]
}

model User {
  id    String @id @default(uuid())
  email String @unique
  @@schema("public")
}

model Subscription {
  id     String @id @default(uuid())
  plan   Plan
  userId String
  @@schema("billing")
}

>Query extensions — reusable query logic

TypeScript
const prisma = new PrismaClient().$extends({
  model: {
    $allModels: {
      // Add a findOrCreate method to every model
      async findOrCreate<T>(
        this: T,
        args: { where: object; create: object },
      ) {
        const ctx = Prisma.getExtensionContext(this) as any;
        return (
          (await ctx.findFirst({ where: args.where })) ??
          (await ctx.create({ data: args.create }))
        );
      },
    },
  },
});

// Works on any model
const tag = await prisma.tag.findOrCreate({
  where:  { slug: 'typescript' },
  create: { slug: 'typescript', label: 'TypeScript' },
});

>Breaking changes in Prisma 6

bash
npm install prisma@6 @prisma/client@6

# After upgrading, run:
npx prisma generate

NOTEThe rejectOnNotFound option was removed. Replace with findUniqueOrThrow() / findFirstOrThrow(). The jsonProtocol preview feature is now the default and the flag can be removed.