wip
This commit is contained in:
@@ -0,0 +1,151 @@
|
||||
# Prisma Accelerate Users
|
||||
|
||||
Special migration instructions for users of Prisma Accelerate or Prisma Postgres with `prisma://` or `prisma+postgres://` URLs.
|
||||
|
||||
## Important
|
||||
|
||||
**Do NOT pass Accelerate URLs to driver adapters.**
|
||||
|
||||
Driver adapters (like `PrismaPg`) expect direct database connection strings. They will fail with `prisma://` or `prisma+postgres://` URLs.
|
||||
|
||||
## Correct v7 Setup for Accelerate
|
||||
|
||||
### 1. Keep your Accelerate URL
|
||||
|
||||
```env
|
||||
# .env
|
||||
DATABASE_URL="prisma://accelerate.prisma-data.net/?api_key=..."
|
||||
# or
|
||||
DATABASE_URL="prisma+postgres://accelerate.prisma-data.net/..."
|
||||
```
|
||||
|
||||
### 2. Install Accelerate extension
|
||||
|
||||
```bash
|
||||
npm install @prisma/extension-accelerate
|
||||
```
|
||||
|
||||
### 3. Configure prisma.config.ts
|
||||
|
||||
```typescript
|
||||
import 'dotenv/config'
|
||||
import { defineConfig, env } from 'prisma/config'
|
||||
|
||||
export default defineConfig({
|
||||
schema: 'prisma/schema.prisma',
|
||||
datasource: {
|
||||
url: env('DATABASE_URL'), // Accelerate URL works here
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
### 4. Instantiate client with accelerateUrl
|
||||
|
||||
```typescript
|
||||
import { PrismaClient } from '../generated/client'
|
||||
import { withAccelerate } from '@prisma/extension-accelerate'
|
||||
|
||||
// Use accelerateUrl instead of adapter
|
||||
export const prisma = new PrismaClient({
|
||||
accelerateUrl: process.env.DATABASE_URL,
|
||||
}).$extends(withAccelerate())
|
||||
```
|
||||
|
||||
## What NOT to Do
|
||||
|
||||
```typescript
|
||||
// ❌ WRONG - Don't use adapter with Accelerate URL
|
||||
import { PrismaPg } from '@prisma/adapter-pg'
|
||||
|
||||
const adapter = new PrismaPg({
|
||||
connectionString: process.env.DATABASE_URL // This will fail with prisma://
|
||||
})
|
||||
```
|
||||
|
||||
## Migrations with Accelerate
|
||||
|
||||
For migrations, you may need a direct database connection:
|
||||
|
||||
### Option 1: Use Accelerate URL for everything
|
||||
|
||||
Accelerate URLs work with Prisma CLI commands:
|
||||
|
||||
```bash
|
||||
# Works with Accelerate URL
|
||||
prisma migrate deploy
|
||||
prisma db push
|
||||
```
|
||||
|
||||
### Option 2: Use direct URL for migrations
|
||||
|
||||
```env
|
||||
DATABASE_URL="prisma+postgres://..." # For app
|
||||
DIRECT_DATABASE_URL="postgresql://..." # For migrations
|
||||
```
|
||||
|
||||
```typescript
|
||||
// prisma.config.ts
|
||||
export default defineConfig({
|
||||
datasource: {
|
||||
url: env('DIRECT_DATABASE_URL'), // Direct URL for CLI
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
## Prisma Postgres (Cloud)
|
||||
|
||||
If using Prisma Postgres cloud database:
|
||||
|
||||
### Same approach
|
||||
|
||||
```typescript
|
||||
import { PrismaClient } from '../generated/client'
|
||||
import { withAccelerate } from '@prisma/extension-accelerate'
|
||||
|
||||
export const prisma = new PrismaClient({
|
||||
accelerateUrl: process.env.DATABASE_URL, // prisma+postgres:// URL
|
||||
}).$extends(withAccelerate())
|
||||
```
|
||||
|
||||
## Switching Away from Accelerate
|
||||
|
||||
If you later switch to direct TCP connection:
|
||||
|
||||
```typescript
|
||||
// Change from accelerateUrl to adapter
|
||||
import { PrismaClient } from '../generated/client'
|
||||
import { PrismaPg } from '@prisma/adapter-pg'
|
||||
|
||||
const adapter = new PrismaPg({
|
||||
connectionString: process.env.DATABASE_URL // Direct postgres:// URL
|
||||
})
|
||||
|
||||
export const prisma = new PrismaClient({ adapter })
|
||||
```
|
||||
|
||||
## Caching with Accelerate
|
||||
|
||||
The extension enables caching:
|
||||
|
||||
```typescript
|
||||
const users = await prisma.user.findMany({
|
||||
cacheStrategy: {
|
||||
ttl: 60, // Cache for 60 seconds
|
||||
swr: 120, // Stale-while-revalidate for 120 seconds
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
## Edge Runtime
|
||||
|
||||
Accelerate works great in edge runtimes:
|
||||
|
||||
```typescript
|
||||
// Works in Vercel Edge, Cloudflare Workers, etc.
|
||||
import { PrismaClient } from '../generated/client'
|
||||
import { withAccelerate } from '@prisma/extension-accelerate'
|
||||
|
||||
export const prisma = new PrismaClient({
|
||||
accelerateUrl: process.env.DATABASE_URL,
|
||||
}).$extends(withAccelerate())
|
||||
```
|
||||
@@ -0,0 +1,267 @@
|
||||
# Driver Adapters
|
||||
|
||||
Prisma v7 requires driver adapters for SQL database connections. This is the standard SQL execution path in current Prisma releases.
|
||||
|
||||
MongoDB should not follow this path. There is no published MongoDB `@prisma/adapter-*` package, and MongoDB projects should remain on the latest Prisma 6.x release instead of trying to fit into the Prisma 7 SQL adapter model.
|
||||
|
||||
## Why Driver Adapters?
|
||||
|
||||
- No native engine binary in the Prisma Client SQL path
|
||||
- Smaller bundle size
|
||||
- Better serverless/edge compatibility
|
||||
- Uses native Node.js database drivers
|
||||
- More control over connection pooling
|
||||
|
||||
## Available Adapters
|
||||
|
||||
| Database | Adapter Package | Underlying Driver |
|
||||
|----------|-----------------|-------------------|
|
||||
| PostgreSQL | `@prisma/adapter-pg` | `pg` |
|
||||
| MySQL / MariaDB | `@prisma/adapter-mariadb` | `mariadb` |
|
||||
| SQLite | `@prisma/adapter-better-sqlite3` | `better-sqlite3` |
|
||||
| Prisma Postgres (Node.js) | `@prisma/adapter-pg` | `pg` |
|
||||
| Prisma Postgres (edge/serverless) | `@prisma/adapter-ppg` | `@prisma/ppg` |
|
||||
| SQL Server | `@prisma/adapter-mssql` | `mssql` |
|
||||
| Neon | `@prisma/adapter-neon` | `@neondatabase/serverless` |
|
||||
| PlanetScale | `@prisma/adapter-planetscale` | `@planetscale/database` |
|
||||
| Turso/libSQL | `@prisma/adapter-libsql` | `@libsql/client` |
|
||||
| D1 (Cloudflare) | `@prisma/adapter-d1` | Cloudflare D1 |
|
||||
|
||||
## Installation
|
||||
|
||||
### PostgreSQL
|
||||
|
||||
```bash
|
||||
npm install @prisma/adapter-pg
|
||||
```
|
||||
|
||||
### MySQL
|
||||
|
||||
```bash
|
||||
npm install @prisma/adapter-mariadb mariadb
|
||||
```
|
||||
|
||||
### SQLite
|
||||
|
||||
```bash
|
||||
npm install @prisma/adapter-better-sqlite3
|
||||
```
|
||||
|
||||
### Prisma Postgres
|
||||
|
||||
```bash
|
||||
npm install @prisma/adapter-pg pg
|
||||
```
|
||||
|
||||
### SQL Server
|
||||
|
||||
```bash
|
||||
npm install @prisma/adapter-mssql mssql
|
||||
```
|
||||
|
||||
## Configuration
|
||||
|
||||
### PostgreSQL
|
||||
|
||||
```typescript
|
||||
import { PrismaClient } from '../generated/client'
|
||||
import { PrismaPg } from '@prisma/adapter-pg'
|
||||
|
||||
const adapter = new PrismaPg({
|
||||
connectionString: process.env.DATABASE_URL
|
||||
})
|
||||
|
||||
const prisma = new PrismaClient({ adapter })
|
||||
```
|
||||
|
||||
### MySQL
|
||||
|
||||
```typescript
|
||||
import { PrismaClient } from '../generated/client'
|
||||
import { PrismaMariaDb } from '@prisma/adapter-mariadb'
|
||||
|
||||
const adapter = new PrismaMariaDb({
|
||||
host: 'localhost',
|
||||
port: 3306,
|
||||
connectionLimit: 5,
|
||||
user: process.env.MYSQL_USER,
|
||||
password: process.env.MYSQL_PASSWORD,
|
||||
database: process.env.MYSQL_DATABASE,
|
||||
})
|
||||
|
||||
const prisma = new PrismaClient({ adapter })
|
||||
```
|
||||
|
||||
### SQLite
|
||||
|
||||
```typescript
|
||||
import { PrismaClient } from '../generated/client'
|
||||
import { PrismaBetterSqlite3 } from '@prisma/adapter-better-sqlite3'
|
||||
|
||||
const adapter = new PrismaBetterSqlite3({
|
||||
url: process.env.DATABASE_URL || 'file:./dev.db'
|
||||
})
|
||||
|
||||
const prisma = new PrismaClient({ adapter })
|
||||
```
|
||||
|
||||
### Neon (Serverless PostgreSQL)
|
||||
|
||||
```typescript
|
||||
import { PrismaClient } from '../generated/client'
|
||||
import { PrismaNeon } from '@prisma/adapter-neon'
|
||||
|
||||
const adapter = new PrismaNeon({
|
||||
connectionString: process.env.DATABASE_URL
|
||||
})
|
||||
|
||||
const prisma = new PrismaClient({ adapter })
|
||||
```
|
||||
|
||||
### Prisma Postgres
|
||||
|
||||
```typescript
|
||||
import { PrismaClient } from '../generated/client'
|
||||
import { PrismaPg } from '@prisma/adapter-pg'
|
||||
|
||||
const adapter = new PrismaPg({
|
||||
connectionString: process.env.DATABASE_URL,
|
||||
})
|
||||
|
||||
const prisma = new PrismaClient({ adapter })
|
||||
```
|
||||
|
||||
### Prisma Postgres serverless driver
|
||||
|
||||
```typescript
|
||||
import { PrismaClient } from '../generated/client'
|
||||
import { PrismaPostgresAdapter } from '@prisma/adapter-ppg'
|
||||
|
||||
const prisma = new PrismaClient({
|
||||
adapter: new PrismaPostgresAdapter({
|
||||
connectionString: process.env.PRISMA_DIRECT_TCP_URL,
|
||||
}),
|
||||
})
|
||||
```
|
||||
|
||||
### SQL Server
|
||||
|
||||
```typescript
|
||||
import { PrismaClient } from '../generated/client'
|
||||
import { PrismaMssql } from '@prisma/adapter-mssql'
|
||||
|
||||
const adapter = new PrismaMssql({
|
||||
server: 'localhost',
|
||||
port: 1433,
|
||||
database: 'mydb',
|
||||
user: process.env.SQLSERVER_USER,
|
||||
password: process.env.SQLSERVER_PASSWORD,
|
||||
options: {
|
||||
encrypt: true,
|
||||
trustServerCertificate: true,
|
||||
},
|
||||
})
|
||||
|
||||
const prisma = new PrismaClient({ adapter })
|
||||
```
|
||||
|
||||
## Connection Pool Configuration
|
||||
|
||||
Driver adapters use the underlying driver's pool settings, which differ from v6 defaults.
|
||||
|
||||
### PostgreSQL with custom pool
|
||||
|
||||
```typescript
|
||||
import { PrismaPg } from '@prisma/adapter-pg'
|
||||
|
||||
const adapter = new PrismaPg({
|
||||
connectionString: process.env.DATABASE_URL,
|
||||
// Pool configuration
|
||||
max: 10, // Maximum connections
|
||||
idleTimeoutMillis: 30000, // Close idle connections after 30s
|
||||
connectionTimeoutMillis: 5000, // Connection timeout (v6 default was 5s)
|
||||
})
|
||||
```
|
||||
|
||||
### Matching v6 behavior
|
||||
|
||||
```typescript
|
||||
const adapter = new PrismaPg({
|
||||
connectionString: process.env.DATABASE_URL,
|
||||
connectionTimeoutMillis: 5000, // v6 used 5 second timeout
|
||||
})
|
||||
```
|
||||
|
||||
## SSL Configuration
|
||||
|
||||
### Accept self-signed certificates
|
||||
|
||||
```typescript
|
||||
const adapter = new PrismaPg({
|
||||
connectionString: process.env.DATABASE_URL,
|
||||
ssl: {
|
||||
rejectUnauthorized: false // Accept self-signed certs
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
### Proper SSL configuration
|
||||
|
||||
```typescript
|
||||
const adapter = new PrismaPg({
|
||||
connectionString: process.env.DATABASE_URL,
|
||||
ssl: {
|
||||
ca: fs.readFileSync('/path/to/ca-cert.pem'),
|
||||
rejectUnauthorized: true
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
## Migration from v6
|
||||
|
||||
### Before (v6)
|
||||
|
||||
```typescript
|
||||
import { PrismaClient } from '@prisma/client'
|
||||
|
||||
const prisma = new PrismaClient({
|
||||
datasources: {
|
||||
db: { url: process.env.DATABASE_URL }
|
||||
}
|
||||
})
|
||||
```
|
||||
|
||||
### After (v7)
|
||||
|
||||
```typescript
|
||||
import { PrismaClient } from '../generated/client'
|
||||
import { PrismaPg } from '@prisma/adapter-pg'
|
||||
|
||||
const adapter = new PrismaPg({
|
||||
connectionString: process.env.DATABASE_URL
|
||||
})
|
||||
|
||||
const prisma = new PrismaClient({ adapter })
|
||||
```
|
||||
|
||||
## Singleton Pattern
|
||||
|
||||
```typescript
|
||||
// lib/prisma.ts
|
||||
import { PrismaClient } from '../generated/client'
|
||||
import { PrismaPg } from '@prisma/adapter-pg'
|
||||
|
||||
const globalForPrisma = globalThis as unknown as {
|
||||
prisma: PrismaClient | undefined
|
||||
}
|
||||
|
||||
const adapter = new PrismaPg({
|
||||
connectionString: process.env.DATABASE_URL!
|
||||
})
|
||||
|
||||
export const prisma = globalForPrisma.prisma ?? new PrismaClient({ adapter })
|
||||
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
globalForPrisma.prisma = prisma
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,161 @@
|
||||
# Environment Variables
|
||||
|
||||
Prisma v7 no longer automatically loads environment variables. You must load them explicitly.
|
||||
|
||||
## The Change
|
||||
|
||||
### v6 Behavior
|
||||
|
||||
Prisma CLI automatically loaded `.env` files.
|
||||
|
||||
### v7 Behavior
|
||||
|
||||
You must manually load environment variables using `dotenv` or similar.
|
||||
|
||||
## Setup
|
||||
|
||||
### 1. Install dotenv
|
||||
|
||||
```bash
|
||||
npm install dotenv
|
||||
```
|
||||
|
||||
### 2. Import in prisma.config.ts
|
||||
|
||||
```typescript
|
||||
import 'dotenv/config' // Must be first import
|
||||
import { defineConfig, env } from 'prisma/config'
|
||||
|
||||
export default defineConfig({
|
||||
datasource: {
|
||||
url: env('DATABASE_URL'),
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
## Bun Users
|
||||
|
||||
Bun automatically loads `.env` files. No additional setup needed:
|
||||
|
||||
```typescript
|
||||
// prisma.config.ts (Bun)
|
||||
import { defineConfig, env } from 'prisma/config'
|
||||
|
||||
export default defineConfig({
|
||||
datasource: {
|
||||
url: env('DATABASE_URL'),
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
## Multiple .env Files
|
||||
|
||||
### Using dotenv-cli
|
||||
|
||||
```bash
|
||||
npm install -D dotenv-cli
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"scripts": {
|
||||
"db:migrate": "dotenv -e .env.local -- prisma migrate dev",
|
||||
"db:push": "dotenv -e .env.development -- prisma db push"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Using dotenv with path
|
||||
|
||||
```typescript
|
||||
// prisma.config.ts
|
||||
import { config } from 'dotenv'
|
||||
import path from 'path'
|
||||
|
||||
// Load specific .env file
|
||||
config({ path: path.join(__dirname, '.env.local') })
|
||||
|
||||
import { defineConfig, env } from 'prisma/config'
|
||||
|
||||
export default defineConfig({
|
||||
datasource: {
|
||||
url: env('DATABASE_URL'),
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
## Application Code
|
||||
|
||||
For your application, load env vars at startup:
|
||||
|
||||
### Entry point
|
||||
|
||||
```typescript
|
||||
// index.ts
|
||||
import 'dotenv/config'
|
||||
|
||||
import { PrismaClient } from '../generated/client'
|
||||
import { PrismaPg } from '@prisma/adapter-pg'
|
||||
|
||||
const adapter = new PrismaPg({
|
||||
connectionString: process.env.DATABASE_URL!
|
||||
})
|
||||
|
||||
const prisma = new PrismaClient({ adapter })
|
||||
```
|
||||
|
||||
### Or use dotenv explicitly
|
||||
|
||||
```typescript
|
||||
import { config } from 'dotenv'
|
||||
config()
|
||||
|
||||
// Now process.env.DATABASE_URL is available
|
||||
```
|
||||
|
||||
## Removed Environment Variables
|
||||
|
||||
These Prisma-specific env vars are removed in v7:
|
||||
|
||||
| Removed Variable | Alternative |
|
||||
|-----------------|-------------|
|
||||
| `PRISMA_CLI_QUERY_ENGINE_TYPE` | Not needed (no engines) |
|
||||
| `PRISMA_CLIENT_ENGINE_TYPE` | Not needed (no engines) |
|
||||
| `PRISMA_QUERY_ENGINE_BINARY` | Not needed |
|
||||
| `PRISMA_QUERY_ENGINE_LIBRARY` | Not needed |
|
||||
| `PRISMA_GENERATE_SKIP_AUTOINSTALL` | Not needed |
|
||||
| `PRISMA_SKIP_POSTINSTALL_GENERATE` | Not needed |
|
||||
| `PRISMA_GENERATE_IN_POSTINSTALL` | Not needed |
|
||||
| `PRISMA_GENERATE_DATAPROXY` | Migrate to `prisma-client` with driver adapters |
|
||||
| `PRISMA_GENERATE_NO_ENGINE` | Migrate to `prisma-client` with driver adapters |
|
||||
| `PRISMA_CLIENT_NO_RETRY` | Configure on adapter |
|
||||
| `PRISMA_MIGRATE_SKIP_GENERATE` | Not needed (auto-generate removed) |
|
||||
| `PRISMA_MIGRATE_SKIP_SEED` | Not needed (auto-seed removed) |
|
||||
|
||||
## TypeScript env() Helper
|
||||
|
||||
The `env()` function from `prisma/config` provides type safety:
|
||||
|
||||
```typescript
|
||||
import { env } from 'prisma/config'
|
||||
|
||||
// Type-safe environment variable access
|
||||
const url = env('DATABASE_URL') // string
|
||||
```
|
||||
|
||||
Note: This only works within `prisma.config.ts`, not in your application code.
|
||||
|
||||
## CI/CD Considerations
|
||||
|
||||
Ensure environment variables are set in your CI environment:
|
||||
|
||||
```yaml
|
||||
# GitHub Actions
|
||||
env:
|
||||
DATABASE_URL: ${{ secrets.DATABASE_URL }}
|
||||
|
||||
steps:
|
||||
- run: npx prisma migrate deploy
|
||||
```
|
||||
|
||||
No need for dotenv in CI if variables are set directly.
|
||||
@@ -0,0 +1,128 @@
|
||||
# ESM and CommonJS Support
|
||||
|
||||
Prisma ORM v7 is ESM-first, but the `prisma-client` generator can target either ESM or CommonJS. Use ESM by default, and opt into CommonJS with `moduleFormat = "cjs"` if your project still needs it.
|
||||
|
||||
## ESM Projects
|
||||
|
||||
Add `"type": "module"` to `package.json` and use an ESM-compatible `tsconfig.json`:
|
||||
|
||||
```json
|
||||
{
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"start": "node dist/index.js"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```json
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "bundler",
|
||||
"target": "ES2023",
|
||||
"strict": true,
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
"outDir": "dist"
|
||||
},
|
||||
"include": ["src/**/*", "prisma/**/*"]
|
||||
}
|
||||
```
|
||||
|
||||
## CommonJS Projects
|
||||
|
||||
If the rest of your app is still CommonJS, keep that setup and make the generated Prisma Client CommonJS too:
|
||||
|
||||
```json
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "CommonJS",
|
||||
"moduleResolution": "node",
|
||||
"target": "ES2022",
|
||||
"esModuleInterop": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
```prisma
|
||||
generator client {
|
||||
provider = "prisma-client"
|
||||
output = "../generated/prisma"
|
||||
moduleFormat = "cjs"
|
||||
}
|
||||
```
|
||||
|
||||
## Generator Fields That Matter
|
||||
|
||||
- `moduleFormat`: `esm` or `cjs`
|
||||
- `runtime`: `nodejs`, `bun`, `deno`, `workerd`, `vercel-edge`, `react-native`
|
||||
- `generatedFileExtension`: `ts`, `mts`, or `cts`
|
||||
- `importFileExtension`: `ts`, `mts`, `cts`, `js`, `mjs`, `cjs`, or empty
|
||||
|
||||
Example:
|
||||
|
||||
```prisma
|
||||
generator client {
|
||||
provider = "prisma-client"
|
||||
output = "../generated/prisma"
|
||||
runtime = "nodejs"
|
||||
moduleFormat = "esm"
|
||||
generatedFileExtension = "ts"
|
||||
importFileExtension = "ts"
|
||||
}
|
||||
```
|
||||
|
||||
## Import Paths
|
||||
|
||||
### Server Code
|
||||
|
||||
```typescript
|
||||
import { PrismaClient } from '../generated/prisma/client'
|
||||
```
|
||||
|
||||
### Browser-Safe Types
|
||||
|
||||
```typescript
|
||||
import { Prisma } from '../generated/prisma/browser'
|
||||
import { Role } from '../generated/prisma/enums'
|
||||
import type { UserModel } from '../generated/prisma/models/User'
|
||||
```
|
||||
|
||||
## File Extensions
|
||||
|
||||
With `moduleResolution: "Node16"` or `"NodeNext"`, use `.js`/`.mjs`/`.cjs` extensions that match your emitted files.
|
||||
|
||||
With `moduleResolution: "bundler"`, bare relative imports are usually fine.
|
||||
|
||||
## Minimum Versions
|
||||
|
||||
| Requirement | Minimum Version |
|
||||
|-------------|-----------------|
|
||||
| Node.js | 20.19.0 |
|
||||
| TypeScript | 5.4.0 |
|
||||
|
||||
## Framework Considerations
|
||||
|
||||
### Next.js
|
||||
|
||||
Next.js works well with the default ESM output. If you need generated types in client components, import them from `browser`, `models`, or `enums`, not from `client`.
|
||||
|
||||
### Bun
|
||||
|
||||
Bun loads `.env` files automatically, so ESM plus `env()` is the smoothest default. You can still choose `moduleFormat = "cjs"` if the rest of your project requires it.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### "ERR_REQUIRE_ESM"
|
||||
|
||||
Your generated client is ESM, but your app is requiring it as CommonJS. Either switch the project to ESM or set `moduleFormat = "cjs"` and regenerate.
|
||||
|
||||
### "Cannot use import statement outside a module"
|
||||
|
||||
Your app is still being executed as CommonJS. Add `"type": "module"` or use `moduleFormat = "cjs"` instead.
|
||||
|
||||
### TypeScript compilation errors
|
||||
|
||||
Ensure `module`, `moduleResolution`, and your generator's `moduleFormat` agree with one another.
|
||||
@@ -0,0 +1,203 @@
|
||||
# Prisma Config
|
||||
|
||||
Prisma v7 introduces `prisma.config.ts` as the central configuration file for the Prisma CLI.
|
||||
|
||||
## Location
|
||||
|
||||
Place `prisma.config.ts` at your project root (next to `package.json`).
|
||||
|
||||
## Basic Configuration
|
||||
|
||||
```typescript
|
||||
import 'dotenv/config'
|
||||
import { defineConfig, env } from 'prisma/config'
|
||||
|
||||
export default defineConfig({
|
||||
schema: 'prisma/schema.prisma',
|
||||
migrations: {
|
||||
path: 'prisma/migrations',
|
||||
},
|
||||
datasource: {
|
||||
url: env('DATABASE_URL'),
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
## Configuration Options
|
||||
|
||||
### schema
|
||||
|
||||
Path to your Prisma schema file:
|
||||
|
||||
```typescript
|
||||
schema: 'prisma/schema.prisma'
|
||||
```
|
||||
|
||||
### datasource.url
|
||||
|
||||
Database connection URL:
|
||||
|
||||
```typescript
|
||||
datasource: {
|
||||
url: env('DATABASE_URL'),
|
||||
}
|
||||
```
|
||||
|
||||
### datasource.directUrl
|
||||
|
||||
Direct connection URL (bypassing connection pooler):
|
||||
|
||||
```typescript
|
||||
datasource: {
|
||||
url: env('DATABASE_URL'),
|
||||
directUrl: env('DIRECT_DATABASE_URL'),
|
||||
}
|
||||
```
|
||||
|
||||
### datasource.shadowDatabaseUrl
|
||||
|
||||
Shadow database for migrations:
|
||||
|
||||
```typescript
|
||||
datasource: {
|
||||
url: env('DATABASE_URL'),
|
||||
shadowDatabaseUrl: env('SHADOW_DATABASE_URL'),
|
||||
}
|
||||
```
|
||||
|
||||
### migrations.path
|
||||
|
||||
Directory for migration files:
|
||||
|
||||
```typescript
|
||||
migrations: {
|
||||
path: 'prisma/migrations',
|
||||
}
|
||||
```
|
||||
|
||||
### migrations.seed
|
||||
|
||||
Seed command for `prisma db seed`:
|
||||
|
||||
```typescript
|
||||
migrations: {
|
||||
path: 'prisma/migrations',
|
||||
seed: 'tsx prisma/seed.ts',
|
||||
}
|
||||
```
|
||||
|
||||
## Full Example
|
||||
|
||||
```typescript
|
||||
import 'dotenv/config'
|
||||
import { defineConfig, env } from 'prisma/config'
|
||||
|
||||
export default defineConfig({
|
||||
// Schema location
|
||||
schema: 'prisma/schema.prisma',
|
||||
|
||||
// Migration configuration
|
||||
migrations: {
|
||||
path: 'prisma/migrations',
|
||||
seed: 'tsx prisma/seed.ts',
|
||||
},
|
||||
|
||||
// Database connection
|
||||
datasource: {
|
||||
url: env('DATABASE_URL'),
|
||||
directUrl: env('DIRECT_DATABASE_URL'),
|
||||
shadowDatabaseUrl: env('SHADOW_DATABASE_URL'),
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
## Environment Variables
|
||||
|
||||
### The env() helper
|
||||
|
||||
Use `env()` to reference environment variables:
|
||||
|
||||
```typescript
|
||||
import { env } from 'prisma/config'
|
||||
|
||||
datasource: {
|
||||
url: env('DATABASE_URL'),
|
||||
}
|
||||
```
|
||||
|
||||
This provides type safety but does NOT load .env files automatically.
|
||||
|
||||
### Loading .env files
|
||||
|
||||
Install and import dotenv:
|
||||
|
||||
```bash
|
||||
npm install dotenv
|
||||
```
|
||||
|
||||
```typescript
|
||||
import 'dotenv/config' // Must be first import
|
||||
import { defineConfig, env } from 'prisma/config'
|
||||
```
|
||||
|
||||
## Migrating from v6
|
||||
|
||||
### Before (v6) - schema.prisma
|
||||
|
||||
```prisma
|
||||
datasource db {
|
||||
provider = "postgresql"
|
||||
url = env("DATABASE_URL")
|
||||
directUrl = env("DIRECT_URL")
|
||||
}
|
||||
```
|
||||
|
||||
### After (v7) - prisma.config.ts
|
||||
|
||||
```typescript
|
||||
import 'dotenv/config'
|
||||
import { defineConfig, env } from 'prisma/config'
|
||||
|
||||
export default defineConfig({
|
||||
schema: 'prisma/schema.prisma',
|
||||
datasource: {
|
||||
url: env('DATABASE_URL'),
|
||||
directUrl: env('DIRECT_URL'),
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
And update schema.prisma:
|
||||
|
||||
```prisma
|
||||
datasource db {
|
||||
provider = "postgresql"
|
||||
// URLs now in prisma.config.ts
|
||||
}
|
||||
```
|
||||
|
||||
## Custom Config Path
|
||||
|
||||
Use `--config` flag with CLI commands:
|
||||
|
||||
```bash
|
||||
prisma migrate dev --config ./config/prisma.config.ts
|
||||
```
|
||||
|
||||
## Monorepo Configuration
|
||||
|
||||
```typescript
|
||||
import 'dotenv/config'
|
||||
import { defineConfig, env } from 'prisma/config'
|
||||
import path from 'path'
|
||||
|
||||
export default defineConfig({
|
||||
schema: path.join(__dirname, 'packages/database/prisma/schema.prisma'),
|
||||
migrations: {
|
||||
path: path.join(__dirname, 'packages/database/prisma/migrations'),
|
||||
},
|
||||
datasource: {
|
||||
url: env('DATABASE_URL'),
|
||||
},
|
||||
})
|
||||
```
|
||||
@@ -0,0 +1,230 @@
|
||||
# Removed Features
|
||||
|
||||
Several features have been removed in Prisma v7. Here's how to migrate.
|
||||
|
||||
## Client Middleware
|
||||
|
||||
### Removed
|
||||
|
||||
```typescript
|
||||
// ❌ No longer works in v7
|
||||
prisma.$use(async (params, next) => {
|
||||
const before = Date.now()
|
||||
const result = await next(params)
|
||||
const after = Date.now()
|
||||
console.log(`Query took ${after - before}ms`)
|
||||
return result
|
||||
})
|
||||
```
|
||||
|
||||
### Use Client Extensions Instead
|
||||
|
||||
```typescript
|
||||
// ✅ v7 approach
|
||||
const prisma = new PrismaClient({ adapter }).$extends({
|
||||
query: {
|
||||
$allModels: {
|
||||
async $allOperations({ operation, model, args, query }) {
|
||||
const before = Date.now()
|
||||
const result = await query(args)
|
||||
const after = Date.now()
|
||||
console.log(`${model}.${operation} took ${after - before}ms`)
|
||||
return result
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
### Common Middleware Patterns
|
||||
|
||||
#### Soft delete
|
||||
|
||||
```typescript
|
||||
const prisma = new PrismaClient({ adapter }).$extends({
|
||||
query: {
|
||||
user: {
|
||||
async delete({ args, query }) {
|
||||
// Convert delete to soft delete
|
||||
return prisma.user.update({
|
||||
where: args.where,
|
||||
data: { deletedAt: new Date() },
|
||||
})
|
||||
},
|
||||
async findMany({ args, query }) {
|
||||
// Filter out soft-deleted records
|
||||
args.where = { ...args.where, deletedAt: null }
|
||||
return query(args)
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
#### Logging
|
||||
|
||||
```typescript
|
||||
const prisma = new PrismaClient({ adapter }).$extends({
|
||||
query: {
|
||||
$allModels: {
|
||||
async $allOperations({ operation, model, args, query }) {
|
||||
console.log(`${model}.${operation}`, JSON.stringify(args))
|
||||
return query(args)
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
## Metrics
|
||||
|
||||
### Removed
|
||||
|
||||
The Metrics preview feature has been removed.
|
||||
|
||||
```typescript
|
||||
// ❌ No longer works
|
||||
const metrics = await prisma.$metrics.json()
|
||||
```
|
||||
|
||||
### Alternatives
|
||||
|
||||
#### Custom counter with extensions
|
||||
|
||||
```typescript
|
||||
let totalQueries = 0
|
||||
|
||||
const prisma = new PrismaClient({ adapter }).$extends({
|
||||
client: {
|
||||
async $totalQueries() {
|
||||
return totalQueries
|
||||
},
|
||||
},
|
||||
query: {
|
||||
$allModels: {
|
||||
async $allOperations({ query, args }) {
|
||||
totalQueries += 1
|
||||
return query(args)
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
// Usage
|
||||
const count = await prisma.$totalQueries()
|
||||
```
|
||||
|
||||
#### Use driver-level metrics
|
||||
|
||||
Access metrics from the underlying driver adapter.
|
||||
|
||||
## CLI Flags Removed
|
||||
|
||||
### --skip-generate
|
||||
|
||||
Removed from `migrate dev` and `db push`.
|
||||
|
||||
```bash
|
||||
# v6
|
||||
prisma migrate dev --skip-generate
|
||||
|
||||
# v7 - generate is not run automatically
|
||||
prisma migrate dev
|
||||
prisma generate # Run explicitly if needed
|
||||
```
|
||||
|
||||
Local verification with Prisma `7.6.0` showed no generated client files emitted by `migrate dev` or `db push`, even though some CLI help text still says `migrate dev` "trigger[s] generators".
|
||||
|
||||
### --skip-seed
|
||||
|
||||
Removed from `migrate dev`. More importantly, Prisma v7 no longer auto-runs seeds during `migrate dev` or `migrate reset`, so seed explicitly when you need it.
|
||||
|
||||
```bash
|
||||
# v6
|
||||
prisma migrate dev --skip-seed
|
||||
|
||||
# v7 - seed is not run automatically
|
||||
prisma migrate dev
|
||||
prisma db seed # Run explicitly if needed
|
||||
```
|
||||
|
||||
### --schema and --url from db execute
|
||||
|
||||
```bash
|
||||
# v6
|
||||
prisma db execute --file ./script.sql --url "$DATABASE_URL"
|
||||
|
||||
# v7 - configure in prisma.config.ts
|
||||
prisma db execute --file ./script.sql
|
||||
```
|
||||
|
||||
## migrate diff Options
|
||||
|
||||
| Removed | Replacement |
|
||||
|---------|-------------|
|
||||
| `--from-url` | `--from-config-datasource` |
|
||||
| `--to-url` | `--to-config-datasource` |
|
||||
| `--from-schema-datasource` | `--from-config-datasource` |
|
||||
| `--to-schema-datasource` | `--to-config-datasource` |
|
||||
| `--shadow-database-url` | Configure in `prisma.config.ts` |
|
||||
|
||||
### Example
|
||||
|
||||
```bash
|
||||
# v6
|
||||
prisma migrate diff --from-url "$DATABASE_URL" --to-schema schema.prisma
|
||||
|
||||
# v7
|
||||
prisma migrate diff --from-config-datasource --to-schema schema.prisma
|
||||
```
|
||||
|
||||
## Automatic Behaviors Removed
|
||||
|
||||
### Auto-generate after migrate
|
||||
|
||||
```bash
|
||||
# v7 workflow
|
||||
prisma migrate dev --name add_field
|
||||
prisma generate # Must run explicitly
|
||||
```
|
||||
|
||||
### Auto-seed after migrate
|
||||
|
||||
```bash
|
||||
# v7 workflow
|
||||
prisma migrate reset --force
|
||||
prisma db seed # Must run explicitly
|
||||
```
|
||||
|
||||
## Prisma.validator
|
||||
|
||||
The `prisma-client` generator no longer exposes `Prisma.validator`. Use TypeScript's `satisfies` operator instead.
|
||||
|
||||
```typescript
|
||||
import { Prisma } from '../generated/prisma/client'
|
||||
|
||||
const userSelect = {
|
||||
id: true,
|
||||
email: true,
|
||||
} satisfies Prisma.UserSelect
|
||||
```
|
||||
|
||||
## rejectOnNotFound
|
||||
|
||||
Removed in v5.0.0 (already deprecated).
|
||||
|
||||
```typescript
|
||||
// ❌ Removed
|
||||
const prisma = new PrismaClient({
|
||||
rejectOnNotFound: true,
|
||||
})
|
||||
|
||||
// ✅ Use OrThrow methods
|
||||
const user = await prisma.user.findUniqueOrThrow({
|
||||
where: { id: 1 },
|
||||
})
|
||||
|
||||
const user = await prisma.user.findFirstOrThrow({
|
||||
where: { email: 'test@example.com' },
|
||||
})
|
||||
```
|
||||
@@ -0,0 +1,164 @@
|
||||
# Schema Changes
|
||||
|
||||
Prisma v7 promotes `prisma-client` to the default generator. Update your generator block, output path, and imports accordingly.
|
||||
|
||||
This guide is for projects that are actually migrating to Prisma 7. Do not apply these schema changes to MongoDB projects; keep those on Prisma 6.x.
|
||||
|
||||
## Generator Block (v7)
|
||||
|
||||
```prisma
|
||||
generator client {
|
||||
provider = "prisma-client"
|
||||
output = "../generated/prisma"
|
||||
}
|
||||
```
|
||||
|
||||
## Key Changes
|
||||
|
||||
### 1. Provider name
|
||||
|
||||
Use `prisma-client` in Prisma v7. The older `prisma-client-js` generator still exists in the repo for legacy setups, but `prisma-client` is the default path for current projects.
|
||||
|
||||
### 2. Output is required
|
||||
|
||||
The `output` field is mandatory when using `prisma-client`. Prisma Client no longer generates to `node_modules` with this generator.
|
||||
|
||||
```prisma
|
||||
generator client {
|
||||
provider = "prisma-client"
|
||||
output = "../generated/prisma"
|
||||
}
|
||||
```
|
||||
|
||||
### 3. engineType changed
|
||||
|
||||
Legacy Rust engine settings are gone. With `prisma-client`, the relevant value is `engineType = "client"` if you want to state it explicitly, although it is typically inferred and can be omitted.
|
||||
|
||||
```prisma
|
||||
generator client {
|
||||
provider = "prisma-client"
|
||||
output = "../generated/prisma"
|
||||
engineType = "client"
|
||||
}
|
||||
```
|
||||
|
||||
### 4. moduleFormat is explicit when needed
|
||||
|
||||
If you must stay on CommonJS:
|
||||
|
||||
```prisma
|
||||
generator client {
|
||||
provider = "prisma-client"
|
||||
output = "../generated/prisma"
|
||||
moduleFormat = "cjs"
|
||||
}
|
||||
```
|
||||
|
||||
## Example Output Paths
|
||||
|
||||
### Standard project
|
||||
|
||||
```prisma
|
||||
output = "../generated/prisma"
|
||||
```
|
||||
|
||||
Creates files like:
|
||||
|
||||
```text
|
||||
generated/prisma/
|
||||
client.ts
|
||||
browser.ts
|
||||
enums.ts
|
||||
models.ts
|
||||
models/
|
||||
```
|
||||
|
||||
### Monorepo
|
||||
|
||||
```prisma
|
||||
output = "../../packages/database/generated/prisma"
|
||||
```
|
||||
|
||||
### Same directory as schema
|
||||
|
||||
```prisma
|
||||
output = "./generated/prisma"
|
||||
```
|
||||
|
||||
Creates: `prisma/generated/prisma/client.ts`
|
||||
|
||||
## Datasource Block
|
||||
|
||||
The `url`, `directUrl`, and `shadowDatabaseUrl` fields in the `datasource` block are deprecated in Prisma v7. Move them to `prisma.config.ts` and keep only the provider in `schema.prisma`:
|
||||
|
||||
```prisma
|
||||
datasource db {
|
||||
provider = "postgresql"
|
||||
}
|
||||
```
|
||||
|
||||
```typescript
|
||||
export default defineConfig({
|
||||
datasource: {
|
||||
url: env('DATABASE_URL'),
|
||||
directUrl: env('DIRECT_URL'),
|
||||
shadowDatabaseUrl: env('SHADOW_DATABASE_URL'),
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
## After Schema Changes
|
||||
|
||||
1. Run `prisma generate`:
|
||||
```bash
|
||||
npx prisma generate
|
||||
```
|
||||
|
||||
2. Update imports throughout your codebase:
|
||||
```typescript
|
||||
import { PrismaClient } from '../generated/prisma/client'
|
||||
```
|
||||
|
||||
3. Update `.gitignore` if you manage this manually:
|
||||
```
|
||||
/generated/prisma
|
||||
```
|
||||
|
||||
4. Replace `Prisma.validator()` with TypeScript `satisfies` when using `prisma-client`:
|
||||
```typescript
|
||||
import { Prisma } from '../generated/prisma/client'
|
||||
|
||||
const userSelect = {
|
||||
id: true,
|
||||
email: true,
|
||||
} satisfies Prisma.UserSelect
|
||||
```
|
||||
|
||||
## Generated Entrypoints
|
||||
|
||||
- `client` - server-side Prisma Client and Prisma namespace
|
||||
- `browser` - browser-safe types and enums without a real `PrismaClient`
|
||||
- `enums` - slim enum-only entrypoint
|
||||
- `models` - model types and derived helper types
|
||||
|
||||
## Preview Features
|
||||
|
||||
Preview features still work as before:
|
||||
|
||||
```prisma
|
||||
generator client {
|
||||
provider = "prisma-client"
|
||||
output = "../generated/prisma"
|
||||
previewFeatures = ["relationJoins", "fullTextSearch"]
|
||||
}
|
||||
```
|
||||
|
||||
Recent preview-feature examples also include `partialIndexes` for PostgreSQL, SQLite, SQL Server, and CockroachDB:
|
||||
|
||||
```prisma
|
||||
generator client {
|
||||
provider = "prisma-client"
|
||||
output = "../generated/prisma"
|
||||
previewFeatures = ["partialIndexes"]
|
||||
}
|
||||
```
|
||||
Reference in New Issue
Block a user