Compare commits
9 Commits
main
...
feat-3.5.0
| Author | SHA1 | Date | |
|---|---|---|---|
| c090675255 | |||
| 83a90407b0 | |||
| a3c70bf1a7 | |||
| 69ec885803 | |||
| 48c45ada89 | |||
| d30cf25890 | |||
| 8827110f2f | |||
| e6ded00a4c | |||
| 63a6993276 |
@@ -0,0 +1,27 @@
|
|||||||
|
# 构建产物必须在目标 Linux 平台重新生成。
|
||||||
|
**/node_modules
|
||||||
|
**/.pnpm-store
|
||||||
|
**/dist
|
||||||
|
**/dist-test
|
||||||
|
**/coverage
|
||||||
|
**/*.tsbuildinfo
|
||||||
|
apps/server/src/generated
|
||||||
|
**/.git
|
||||||
|
**/.DS_Store
|
||||||
|
**/*.log
|
||||||
|
# 真实密钥、备份与资源报告禁止进入镜像;仅保留示例配置。
|
||||||
|
**/.env
|
||||||
|
**/.env.*
|
||||||
|
!**/.env.example
|
||||||
|
**/server.env
|
||||||
|
**/server.env.*
|
||||||
|
!**/server.env.example
|
||||||
|
deploy/data
|
||||||
|
deploy/backups
|
||||||
|
**/*.dump
|
||||||
|
**/*.tar
|
||||||
|
**/*.tar.gz
|
||||||
|
packages/asset-sync/reports
|
||||||
|
.agents
|
||||||
|
.codex
|
||||||
|
docs
|
||||||
+1
-1
@@ -4,6 +4,6 @@ root = true
|
|||||||
charset = utf-8
|
charset = utf-8
|
||||||
end_of_line = lf
|
end_of_line = lf
|
||||||
indent_style = space
|
indent_style = space
|
||||||
indent_size = 2
|
indent_size = 4
|
||||||
insert_final_newline = true
|
insert_final_newline = true
|
||||||
trim_trailing_whitespace = true
|
trim_trailing_whitespace = true
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
# 仅用于本地 Docker Compose,命令从 doodle-store 根目录执行。
|
||||||
|
POSTGRES_PORT=5434
|
||||||
|
POSTGRES_DB=doodle_dev
|
||||||
|
POSTGRES_USER=doodle_dev
|
||||||
|
# 本地开发专用;复制为 .env 后替换,真实密码不要提交仓库。
|
||||||
|
POSTGRES_PASSWORD=change-me-local-only
|
||||||
@@ -5,9 +5,13 @@ dist-test/
|
|||||||
coverage/
|
coverage/
|
||||||
*.tsbuildinfo
|
*.tsbuildinfo
|
||||||
*.log
|
*.log
|
||||||
|
/apps/server/src/generated/
|
||||||
.DS_Store
|
.DS_Store
|
||||||
.env
|
.env
|
||||||
.env.*
|
.env.*
|
||||||
!.env.example
|
!.env.example
|
||||||
/deploy/data/
|
/deploy/data/
|
||||||
/deploy/backups/
|
/deploy/backups/
|
||||||
|
/deploy/server.env
|
||||||
|
/deploy/server.env.*
|
||||||
|
!/deploy/server.env.example
|
||||||
|
|||||||
@@ -4,3 +4,6 @@ dist
|
|||||||
dist-test
|
dist-test
|
||||||
coverage
|
coverage
|
||||||
pnpm-lock.yaml
|
pnpm-lock.yaml
|
||||||
|
apps/server/src/generated
|
||||||
|
|
||||||
|
packages/asset-sync/reports
|
||||||
|
|||||||
+4
-2
@@ -1,4 +1,6 @@
|
|||||||
{
|
{
|
||||||
"singleQuote": true,
|
"tabWidth": 4,
|
||||||
"trailingComma": "all"
|
"useTabs": false,
|
||||||
|
"singleQuote": true,
|
||||||
|
"trailingComma": "all"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
# 项目编码约定
|
||||||
|
|
||||||
|
- 使用 4 个空格缩进,不使用 Tab;遵循项目 EditorConfig 与 Prettier 配置。
|
||||||
|
- 新增或修改代码时添加适当的中文注释。公共类、服务方法和接入接口说明职责与使用前提;复杂逻辑说明设计原因、处理顺序、边界条件及异常行为。
|
||||||
|
- 配置校验、鉴权与权限、事务与幂等、第三方服务接入、日志脱敏等关键逻辑应有注释。临时占位实现要说明当前行为和后续替换位置。
|
||||||
|
- 注释保持简洁,避免逐行复述代码或给显而易见的操作添加无意义注释;修改逻辑时同步更新相关注释。
|
||||||
@@ -1,18 +1,23 @@
|
|||||||
# Doodle Store
|
# Doodle Store
|
||||||
|
|
||||||
|
当前进度、旧线上服务保留约束、验证结果及下一步任务见 [开发交接文档](docs/v3.5/开发交接文档.md)(2026-10-19)。
|
||||||
|
|
||||||
独立于 `doodle-mini` 的 pnpm Monorepo,用于维护统一业务后端、后续管理后台和用户 Web 网站。小程序源码与 CloudBase 兼容函数仍在 `doodle-mini`,两个项目通过 HTTPS API 协作。
|
独立于 `doodle-mini` 的 pnpm Monorepo,用于维护统一业务后端、后续管理后台和用户 Web 网站。小程序源码与 CloudBase 兼容函数仍在 `doodle-mini`,两个项目通过 HTTPS API 协作。
|
||||||
|
|
||||||
## 当前范围
|
## 当前范围
|
||||||
|
|
||||||
本次仅初始化工程,不开发具体业务:
|
当前已完成基础工程、本地数据库、小程序登录鉴权及分类服务:
|
||||||
|
|
||||||
- `apps/server`:可运行的 NestJS 服务,只有进程健康检查。
|
- `apps/server`:可运行的 NestJS 服务,已接入日志、中间件、Swagger、微信静默登录、JWT 与真实账户检查,提供本人摘要、分类查询/管理、题型列表/详情与组合筛选和数据库就绪接口。
|
||||||
- `packages/contracts`:基础成功响应与健康检查类型,不包含业务字段或私有实现。
|
- `packages/contracts`:公开响应、登录请求/结果、本人摘要、分类与安全错误类型,不包含数据库模型或私有实现。
|
||||||
|
- `packages/asset-sync`:本地云存储备份同步七牛的独立 Node.js 工具,支持预演、校验、重试,头像与其他资源共用公开空间。
|
||||||
- `apps/admin`、`apps/web`:仅预留目录与说明,尚未选择或安装前端框架。
|
- `apps/admin`、`apps/web`:仅预留目录与说明,尚未选择或安装前端框架。
|
||||||
- 数据库、Prisma、微信登录、七牛、定时任务、业务接口与生产部署尚未接入。
|
- 本地 PostgreSQL 18.6 Docker 开发环境已启动,13 张表及初始配置已创建,并于 2026-10-15 与最新 SQL 复核一致;Prisma 与微信登录已接入,七牛、其他业务及生产部署待实施。
|
||||||
|
|
||||||
## 本地使用
|
## 本地使用
|
||||||
|
|
||||||
|
先按 [本地数据库说明](infra/README.md) 配置根 `.env`,执行 `pnpm infra:up`。默认数据库地址为 `127.0.0.1:5434`,开发库为 `doodle_dev`。图片等资源直接使用七牛,本地仅启动 PostgreSQL。生产与按需测试的安排见 [v3.5 开发与部署环境方案](docs/v3.5/开发与部署环境方案.md)。
|
||||||
|
|
||||||
使用 Node.js **24.20.0** 与 pnpm **11.24.0**。如使用 fnm,可在本目录执行 `fnm use --install-if-missing`。
|
使用 Node.js **24.20.0** 与 pnpm **11.24.0**。如使用 fnm,可在本目录执行 `fnm use --install-if-missing`。
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@@ -21,12 +26,19 @@ pnpm build
|
|||||||
pnpm dev
|
pnpm dev
|
||||||
```
|
```
|
||||||
|
|
||||||
默认地址为 `http://127.0.0.1:3000/api/v1/health`。该接口只证明服务进程可以处理 HTTP 请求,不代表数据库、文件存储或业务系统已经可用。
|
默认地址为 `http://127.0.0.1:8800/api/v1/health`。该接口只证明服务进程可以处理 HTTP 请求,不代表数据库、文件存储或业务系统已经可用。
|
||||||
|
|
||||||
|
`pnpm dev` 在服务监听成功后显示完整 Swagger 地址(默认 `http://127.0.0.1:8800/api-docs`),并使用系统默认浏览器自动打开一次。热更新不会重复打开;关闭 Swagger 时不打开。链接按实际 HOST/PORT 生成,建议使用输出的 IP 地址,避免 `localhost` 解析到其他项目。
|
||||||
|
|
||||||
可在 `apps/server/.env` 中配置 `PORT`、`HOST`,变量示例见 `apps/server/.env.example`。未配置时使用安全的本地默认值。不要提交真实 `.env` 或密钥。
|
可在 `apps/server/.env` 中配置 `PORT`、`HOST`,变量示例见 `apps/server/.env.example`。未配置时使用安全的本地默认值。不要提交真实 `.env` 或密钥。
|
||||||
|
|
||||||
|
JWT_SECRET 必须配置为至少 32 字节的独立密钥,本机开发密钥已生成。Swagger 默认开发开启:`http://127.0.0.1:8800/api-docs`,生产未显式配置时关闭;其他设置与账户查询接入边界见 [Server 基础设置](docs/v3.5/Server基础设置.md)。
|
||||||
|
|
||||||
|
微信小程序配置在 `apps/server/.env` 中填写 `WECHAT_MINI_APP_ID` 和 `WECHAT_MINI_APP_SECRET`。两项均为启动必填;DATABASE_URL 同样必须配置。真实 AppSecret 仅由服务端持有,不提交仓库。
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pnpm check # 格式、代码检查、类型检查、构建与测试
|
pnpm check # 格式、代码检查、类型检查、构建与测试
|
||||||
|
pnpm test:db # 独立临时数据库中的登录/鉴权/分类测试,结束后清理
|
||||||
pnpm build # 按工作区依赖顺序构建
|
pnpm build # 按工作区依赖顺序构建
|
||||||
pnpm start # 运行已构建的服务端
|
pnpm start # 运行已构建的服务端
|
||||||
pnpm format # 格式化源码与配置
|
pnpm format # 格式化源码与配置
|
||||||
@@ -40,8 +52,10 @@ apps/
|
|||||||
admin/ 后续管理后台,当前仅占位
|
admin/ 后续管理后台,当前仅占位
|
||||||
web/ 后续用户网站,当前仅占位
|
web/ 后续用户网站,当前仅占位
|
||||||
packages/
|
packages/
|
||||||
|
asset-sync/ 云存储备份同步七牛的独立脚本
|
||||||
contracts/ 可公开的接口类型
|
contracts/ 可公开的接口类型
|
||||||
deploy/ 后续部署说明,当前未部署
|
deploy/ 后续部署说明,当前未部署
|
||||||
|
infra/ 本地 PostgreSQL Docker 配置
|
||||||
docs/ 工程初始化与接入边界说明
|
docs/ 工程初始化与接入边界说明
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -49,4 +63,53 @@ docs/ 工程初始化与接入边界说明
|
|||||||
|
|
||||||
数据库模型、密钥和未来私有生成/绘制逻辑只能由服务端持有,不能放进公共契约包供前端导入。小程序不直接依赖本仓库源码或本地工作区包。
|
数据库模型、密钥和未来私有生成/绘制逻辑只能由服务端持有,不能放进公共契约包供前端导入。小程序不直接依赖本仓库源码或本地工作区包。
|
||||||
|
|
||||||
|
登录请求、恢复错误码、数据库基线及联调边界见 [服务端登录接入说明](docs/v3.5/服务端登录接入说明.md)。
|
||||||
|
|
||||||
|
分类公开/管理 API、本地导入工具及本批 6 条分类的导入结果见 [分类接口与数据导入](docs/v3.5/分类接口与数据导入.md)。
|
||||||
|
|
||||||
|
51 条旧题型数据已导入本地库,预览文件仍待迁移;导入工具、异常年级和计数对账见 [题型数据导入说明](docs/v3.5/题型数据导入说明.md)。
|
||||||
|
|
||||||
|
题型查询支持分类、审核年级、年龄段、Tag、最新/热门、运营标记和分页,见 [题型查询接口说明](docs/v3.5/题型查询接口说明.md)。
|
||||||
|
|
||||||
现有功能迁移的权威方案见 [docs/云服务端迁移方案.md](docs/云服务端迁移方案.md),小程序产品规划与历史设计仍保留在 `doodle-mini`。本仓库的初始化说明见 [docs/初始化说明.md](docs/初始化说明.md)。
|
现有功能迁移的权威方案见 [docs/云服务端迁移方案.md](docs/云服务端迁移方案.md),小程序产品规划与历史设计仍保留在 `doodle-mini`。本仓库的初始化说明见 [docs/初始化说明.md](docs/初始化说明.md)。
|
||||||
|
|
||||||
|
## 云存储备份同步七牛
|
||||||
|
|
||||||
|
独立脚本项目位于 [packages/asset-sync](packages/asset-sync/README.md),配置入口为该目录的 `.env`,已填写本地 cloud_backup 源目录。`pnpm assets:sync` 默认只预演;填写七牛 AK/SK 与 bucket 后,使用 `pnpm assets:sync --apply --only assets/previews` 同步题型预览。支持保留相对路径、同内容跳过、冲突保护、有限重试和报告;头像与其他资源共用 QINIU_BUCKET 公开空间。该工具不修改业务数据库或自动替换旧 cloud 引用。
|
||||||
|
|
||||||
|
### 服务端资源地址配置
|
||||||
|
|
||||||
|
`apps/server/.env` 与 asset-sync 使用同一组公开配置;服务端无需配置七牛 AK/SK:
|
||||||
|
|
||||||
|
```dotenv
|
||||||
|
QINIU_PUBLIC_DOMAIN=https://cdn.joeyone.cn
|
||||||
|
QINIU_KEY_PREFIX=doodle-assets/
|
||||||
|
QINIU_BUCKET=doodle-cn
|
||||||
|
```
|
||||||
|
|
||||||
|
地址规则为「域名 / 对象 key」。字体等固定资源由 `publicResourceUrl(config, 'assets/fonts/ToneOZ-Pinyin-Regular.ttf')` 补上前缀,得到 `https://cdn.joeyone.cn/doodle-assets/assets/fonts/ToneOZ-Pinyin-Regular.ttf`。支持空前缀;域名仅接受 HTTPS origin,不包含目录。修改配置后重启 server。
|
||||||
|
|
||||||
|
数据库 `assets.object_key` 存完整 key,例如 `doodle-assets/assets/previews/math/example.jpg`,返回预览时直接拼域名,不再次添加前缀。`QINIU_BUCKET` 是对象所属空间,不拼进 URL,也不会自动修改资产记录。图片上传成功后仍需根据同步报告回填资产的 key、bucket、摘要等字段并标记 ready;pending 资产继续返回空预览,配置域名不会自动宣布迁移完成。
|
||||||
|
|
||||||
|
资源上传后,可将成功同步报告映射回本地 `assets`,保留原资源 ID 与业务表外键:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 预演:重新核对本地文件与七牛对象,仅允许本机 doodle_dev
|
||||||
|
pnpm assets:map --report /绝对路径/成功同步报告.json
|
||||||
|
# 核对通过后,整批事务写入并记录迁移审计
|
||||||
|
pnpm assets:map --report /绝对路径/成功同步报告.json --apply
|
||||||
|
```
|
||||||
|
|
||||||
|
当前工具处理已有 cloud 来源的题型预览:根据原文件相对路径匹配,回填 bucket、完整 objectKey、MIME、大小和 SHA-256,设置 ready。重复执行同一映射会跳过,已就绪但映射不同的资产会拒绝覆盖;有缺失或核对失败则整批不写入。不创建用户头像记录、不猜测头像归属。
|
||||||
|
|
||||||
|
业务表(例如 worksheets.preview_asset_id、users.avatar_asset_id)仅保存资源 ID;assets 保存文件定位和元数据,不保存七牛完整访问 URL。固定字体未作为业务记录入库,小程序通过 `miniprogram/config/assets.ts` 统一配置域名和前缀;接口提供的图片地址直接使用,不在小程序重复拼接。
|
||||||
|
|
||||||
|
### 微信登录上游失败排查
|
||||||
|
|
||||||
|
`503 / AUTH_UPSTREAM_UNAVAILABLE` 表示服务端兑换微信 code 未成功。查看同一 requestId 的 `wechat_exchange_failed` 日志:只记录失败阶段、HTTP 状态和微信数值错误码,不输出 AppSecret、code、完整请求 URL 或微信 errmsg。
|
||||||
|
|
||||||
|
若 `wechat_errcode=40164`,且有 `egress_ip`,表示微信拒绝当前服务器公网出口 IP。登录对应 AppID 的微信公众平台,在服务端接口调用的 IP 白名单中添加该出口 IP(与代码上传白名单分别核对),保存后在小程序重新触发登录。换网络或代理出口后需重新核对 IP;上线时使用实际服务器的固定出口 IP。仅修改本站后端 `.env` 无法解除微信侧白名单限制。
|
||||||
|
|
||||||
|
### 小程序业务接口迁移
|
||||||
|
|
||||||
|
除微信预拉取外,用户资料、头像、收藏、下载记录、年龄推荐、动态首页兜底和各管理页已迁至本站 API;详见 [小程序云接口迁移清单](docs/v3.5/小程序云接口迁移清单.md)。上传凭据仅由服务端持有,本地已沿用 asset-sync 的七牛配置。`20261019000000_member_assets` 已在本地应用;云端历史用户及关联记录仍需单独导入。管理功能要求数据库当前角色为 admin,不自动授权开发者账户。
|
||||||
|
|||||||
@@ -0,0 +1,267 @@
|
|||||||
|
---
|
||||||
|
name: prisma-cli
|
||||||
|
description: Prisma ORM 7 CLI reference for existing Prisma 7 applications or explicitly selected Prisma 7 workflows. Covers prisma init, generate, migrate, db, dev, studio, and mcp. For setup, connection repair, or Prisma 8, use prisma-orm-setup; not the Prisma Platform CLI.
|
||||||
|
license: MIT
|
||||||
|
metadata:
|
||||||
|
author: prisma
|
||||||
|
version: "7.9.1"
|
||||||
|
---
|
||||||
|
|
||||||
|
# Prisma ORM 7 CLI reference
|
||||||
|
|
||||||
|
These commands and examples apply to **Prisma ORM 7** only. For setup, connection repair, or a Prisma 8 application, load [prisma-orm-setup](../prisma-orm-setup/SKILL.md).
|
||||||
|
|
||||||
|
Use the project's version-matched CLI. Do not install a floating `prisma@latest` to run these commands.
|
||||||
|
|
||||||
|
## Boundary: Platform and Compute
|
||||||
|
|
||||||
|
Do not confuse the stable ORM command (`prisma`) with the public-beta Platform package (`@prisma/cli`, binary `prisma-cli`). Use `prisma-compute` for Compute apps and workspace auth, and `prisma-postgres-setup` for Platform projects and databases.
|
||||||
|
|
||||||
|
## When to Apply
|
||||||
|
|
||||||
|
Reference this skill when:
|
||||||
|
- Setting up an explicitly selected Prisma 7 project (`prisma init`)
|
||||||
|
- Generating Prisma Client (`prisma generate`)
|
||||||
|
- Running database migrations (`prisma migrate`)
|
||||||
|
- Managing database state (`prisma db push/pull`)
|
||||||
|
- Using local development database (`prisma dev`)
|
||||||
|
- Debugging Prisma issues (`prisma debug`)
|
||||||
|
- Generating shell completions (`prisma complete`)
|
||||||
|
|
||||||
|
## Rule Categories by Priority
|
||||||
|
|
||||||
|
| Priority | Category | Impact | Prefix |
|
||||||
|
|----------|----------|--------|--------|
|
||||||
|
| 1 | Setup | HIGH | `init` |
|
||||||
|
| 2 | Generation | HIGH | `generate` |
|
||||||
|
| 3 | Development | HIGH | `dev` |
|
||||||
|
| 4 | Database | HIGH | `db-` |
|
||||||
|
| 5 | Migrations | CRITICAL | `migrate-` |
|
||||||
|
| 6 | Utility | MEDIUM | `complete`, `studio`, `validate`, `format`, `debug`, `mcp` |
|
||||||
|
|
||||||
|
## Command Categories
|
||||||
|
|
||||||
|
| Category | Commands | Purpose |
|
||||||
|
|----------|----------|---------|
|
||||||
|
| Setup | `init` | Initialize a Prisma project |
|
||||||
|
| Generation | `generate` | Generate Prisma Client |
|
||||||
|
| Validation | `validate`, `format` | Schema validation and formatting |
|
||||||
|
| Development | `dev` | Local Prisma Postgres for development |
|
||||||
|
| Database | `db pull`, `db push`, `db seed`, `db execute` | Direct database operations |
|
||||||
|
| Migrations | `migrate dev`, `migrate deploy`, `migrate reset`, `migrate status`, `migrate diff`, `migrate resolve` | Schema migrations |
|
||||||
|
| Utility | `complete`, `studio`, `mcp`, `version`, `debug` | Shell, development, and AI tooling |
|
||||||
|
|
||||||
|
## Quick Reference
|
||||||
|
|
||||||
|
### Project Setup
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Initialize new project (creates prisma/ folder and prisma.config.ts)
|
||||||
|
prisma init
|
||||||
|
|
||||||
|
# Initialize with specific database
|
||||||
|
prisma init --datasource-provider postgresql
|
||||||
|
prisma init --datasource-provider mysql
|
||||||
|
prisma init --datasource-provider sqlite
|
||||||
|
|
||||||
|
# Initialize with Prisma Postgres (cloud)
|
||||||
|
prisma init --db
|
||||||
|
|
||||||
|
# Initialize with an example model
|
||||||
|
prisma init --with-model
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
### Client Generation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Generate Prisma Client
|
||||||
|
prisma generate
|
||||||
|
|
||||||
|
# Watch mode for development
|
||||||
|
prisma generate --watch
|
||||||
|
|
||||||
|
# Generate specific generator only
|
||||||
|
prisma generate --generator client
|
||||||
|
```
|
||||||
|
|
||||||
|
### Bun Runtime
|
||||||
|
|
||||||
|
When using Bun, always add the `--bun` flag so Prisma runs with the Bun runtime (otherwise it falls back to Node.js because of the CLI shebang):
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bunx --bun prisma init
|
||||||
|
bunx --bun prisma generate
|
||||||
|
```
|
||||||
|
|
||||||
|
### Local Development Database
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Start local Prisma Postgres
|
||||||
|
prisma dev
|
||||||
|
|
||||||
|
# Start with specific name
|
||||||
|
prisma dev --name myproject
|
||||||
|
|
||||||
|
# Start in background (detached)
|
||||||
|
prisma dev --detach
|
||||||
|
|
||||||
|
# List all local instances
|
||||||
|
prisma dev ls
|
||||||
|
|
||||||
|
# Stop instance
|
||||||
|
prisma dev stop myproject
|
||||||
|
|
||||||
|
# Remove instance data
|
||||||
|
prisma dev rm myproject
|
||||||
|
```
|
||||||
|
|
||||||
|
### Database Operations
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Pull schema from existing database
|
||||||
|
prisma db pull
|
||||||
|
|
||||||
|
# Push schema to database (no migrations)
|
||||||
|
prisma db push
|
||||||
|
|
||||||
|
# Seed database
|
||||||
|
prisma db seed
|
||||||
|
|
||||||
|
# Execute raw SQL
|
||||||
|
prisma db execute --file ./script.sql
|
||||||
|
```
|
||||||
|
|
||||||
|
### Migrations (Development)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Create and apply migration
|
||||||
|
prisma migrate dev
|
||||||
|
|
||||||
|
# Create migration with name
|
||||||
|
prisma migrate dev --name add_users_table
|
||||||
|
|
||||||
|
# Create migration without applying
|
||||||
|
prisma migrate dev --create-only
|
||||||
|
|
||||||
|
# Reset database and apply all migrations
|
||||||
|
prisma migrate reset
|
||||||
|
```
|
||||||
|
|
||||||
|
### Migrations (Production)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Apply pending migrations (CI/CD)
|
||||||
|
prisma migrate deploy
|
||||||
|
|
||||||
|
# Check migration status
|
||||||
|
prisma migrate status
|
||||||
|
|
||||||
|
# Compare schemas and generate diff
|
||||||
|
prisma migrate diff --from-config-datasource --to-schema schema.prisma --script
|
||||||
|
```
|
||||||
|
|
||||||
|
### Utility Commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Open Prisma Studio (database GUI)
|
||||||
|
prisma studio
|
||||||
|
|
||||||
|
# Start Prisma's MCP server for AI tools
|
||||||
|
prisma mcp
|
||||||
|
|
||||||
|
# Show version info
|
||||||
|
prisma version
|
||||||
|
prisma -v
|
||||||
|
|
||||||
|
# Debug information
|
||||||
|
prisma debug
|
||||||
|
|
||||||
|
# Validate schema
|
||||||
|
prisma validate
|
||||||
|
|
||||||
|
# Format schema
|
||||||
|
prisma format
|
||||||
|
|
||||||
|
# Generate shell completion code
|
||||||
|
prisma complete zsh
|
||||||
|
```
|
||||||
|
|
||||||
|
## AI Safety Checkpoint
|
||||||
|
|
||||||
|
Prisma blocks destructive commands when it detects an AI agent until the agent has obtained explicit user consent. This covers `migrate reset`, `db push --force-reset`, and `db push --accept-data-loss`.
|
||||||
|
|
||||||
|
- Explain the exact data-loss impact and ask for consent immediately before running the command.
|
||||||
|
- Do not infer consent from earlier or unrelated messages.
|
||||||
|
- If automation needs the consent variable, set `PRISMA_USER_CONSENT_FOR_DANGEROUS_AI_ACTION` to the user's exact consent message. Do not invent the text.
|
||||||
|
- The Prisma MCP server deliberately has no `migrate-reset` tool.
|
||||||
|
|
||||||
|
Read `references/agent-safety.md` before any destructive Prisma command.
|
||||||
|
|
||||||
|
## Current Prisma CLI Setup
|
||||||
|
|
||||||
|
### New Configuration File
|
||||||
|
|
||||||
|
Use `prisma.config.ts` for CLI configuration:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import 'dotenv/config'
|
||||||
|
import { defineConfig, env } from 'prisma/config'
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
schema: 'prisma/schema.prisma',
|
||||||
|
migrations: {
|
||||||
|
path: 'prisma/migrations',
|
||||||
|
seed: 'tsx prisma/seed.ts',
|
||||||
|
},
|
||||||
|
datasource: {
|
||||||
|
url: env('DATABASE_URL'),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Current Command Behavior
|
||||||
|
|
||||||
|
- Run `prisma generate` explicitly after `migrate dev`, `db push`, or other schema syncs when you need fresh client output
|
||||||
|
- Run `prisma db seed` explicitly after `migrate dev` or `migrate reset` when you need seed data
|
||||||
|
- Use `prisma db execute --file ...` for raw SQL scripts
|
||||||
|
|
||||||
|
### Environment Variables
|
||||||
|
|
||||||
|
Load environment variables explicitly in `prisma.config.ts`, commonly with `dotenv`:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// prisma.config.ts
|
||||||
|
import 'dotenv/config'
|
||||||
|
```
|
||||||
|
|
||||||
|
## Rule Files
|
||||||
|
|
||||||
|
See individual rule files for detailed command documentation:
|
||||||
|
|
||||||
|
```
|
||||||
|
references/init.md - Project initialization
|
||||||
|
references/generate.md - Client generation
|
||||||
|
references/dev.md - Local development database
|
||||||
|
references/db-pull.md - Database introspection
|
||||||
|
references/db-push.md - Schema push
|
||||||
|
references/db-seed.md - Database seeding
|
||||||
|
references/db-execute.md - Raw SQL execution
|
||||||
|
references/migrate-dev.md - Development migrations
|
||||||
|
references/migrate-deploy.md - Production migrations
|
||||||
|
references/migrate-reset.md - Database reset
|
||||||
|
references/migrate-status.md - Migration status
|
||||||
|
references/migrate-resolve.md - Migration resolution
|
||||||
|
references/migrate-diff.md - Schema diffing
|
||||||
|
references/studio.md - Database GUI
|
||||||
|
references/mcp.md - Prisma MCP server
|
||||||
|
references/complete.md - Shell completion generation
|
||||||
|
references/agent-safety.md - AI consent checkpoint for destructive commands
|
||||||
|
references/validate.md - Schema validation
|
||||||
|
references/format.md - Schema formatting
|
||||||
|
references/debug.md - Debug info
|
||||||
|
```
|
||||||
|
|
||||||
|
## How to Use
|
||||||
|
|
||||||
|
Use the command categories above for navigation, then open the specific command reference file you need.
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
# AI safety checkpoint for destructive commands
|
||||||
|
|
||||||
|
Prisma detects common AI-agent environments and blocks these commands until the user gives explicit consent:
|
||||||
|
|
||||||
|
- `prisma migrate reset`
|
||||||
|
- `prisma db push --force-reset`
|
||||||
|
- `prisma db push --accept-data-loss`
|
||||||
|
|
||||||
|
## Required workflow
|
||||||
|
|
||||||
|
1. Inspect the target database/config and explain exactly what can be deleted or reset.
|
||||||
|
2. Ask the user for explicit consent immediately before the action.
|
||||||
|
3. Run the command only after that consent.
|
||||||
|
|
||||||
|
For an agent-run subprocess, Prisma accepts the exact consent text through:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
PRISMA_USER_CONSENT_FOR_DANGEROUS_AI_ACTION='<exact user consent message>' prisma migrate reset --force
|
||||||
|
```
|
||||||
|
|
||||||
|
The value must match the user's message exactly and must not contain added quotes or newlines. Never fabricate consent, reuse an old unrelated approval, or bypass the checkpoint by hiding agent-detection environment variables.
|
||||||
|
|
||||||
|
The MCP server has no `migrate-reset` tool. Use the shell command only after consent.
|
||||||
|
|
||||||
|
## Reference
|
||||||
|
|
||||||
|
- [Prisma ORM 7.9.0 release](https://github.com/prisma/prisma/releases/tag/7.9.0)
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
# prisma complete
|
||||||
|
|
||||||
|
Prints a shell completion script.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma complete zsh
|
||||||
|
prisma complete bash
|
||||||
|
prisma complete fish
|
||||||
|
prisma complete powershell
|
||||||
|
```
|
||||||
|
|
||||||
|
For a direct global CLI installation, load the output using the shell's normal startup mechanism. For example, in zsh:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
source <(prisma complete zsh)
|
||||||
|
```
|
||||||
|
|
||||||
|
Prisma also integrates with supported package-manager completion flows. `npx` and `bunx` do not themselves provide completion; invoke the installed binary or the package manager's supported execution form such as `npm exec` or `bun x`.
|
||||||
|
|
||||||
|
## Reference
|
||||||
|
|
||||||
|
- [Prisma ORM 7.9.0 release](https://github.com/prisma/prisma/releases/tag/7.9.0)
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
# prisma db execute
|
||||||
|
|
||||||
|
Execute native commands (SQL) to your database.
|
||||||
|
|
||||||
|
## Command
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma db execute [options]
|
||||||
|
```
|
||||||
|
|
||||||
|
## What It Does
|
||||||
|
|
||||||
|
- Connects to your database using the configured datasource
|
||||||
|
- Executes a script provided via file (`--file`) or stdin (`--stdin`)
|
||||||
|
- Useful for running raw SQL, maintenance tasks, or applying diffs from `migrate diff`
|
||||||
|
- Not supported on MongoDB
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
| Option | Description |
|
||||||
|
|--------|-------------|
|
||||||
|
| `--file` | Path to a file containing the script to execute |
|
||||||
|
| `--stdin` | Use terminal standard input as the script |
|
||||||
|
| `--config` | Custom path to your Prisma config file |
|
||||||
|
|
||||||
|
## Current Option Surface
|
||||||
|
|
||||||
|
`prisma db execute` uses the datasource configured in `prisma.config.ts`. Use `--config` if you need a separate config file for another environment.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### Execute from file
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma db execute --file ./script.sql
|
||||||
|
```
|
||||||
|
|
||||||
|
### Execute from stdin
|
||||||
|
|
||||||
|
```bash
|
||||||
|
echo "TRUNCATE TABLE User;" | prisma db execute --stdin
|
||||||
|
```
|
||||||
|
|
||||||
|
### Execute `migrate diff` output
|
||||||
|
|
||||||
|
Pipe the output of `migrate diff` directly to the database:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma migrate diff \
|
||||||
|
--from-empty \
|
||||||
|
--to-schema prisma/schema.prisma \
|
||||||
|
--script \
|
||||||
|
| prisma db execute --stdin
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
Uses `datasource` from `prisma.config.ts`:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
export default defineConfig({
|
||||||
|
datasource: {
|
||||||
|
url: env('DATABASE_URL'),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## Use Cases
|
||||||
|
|
||||||
|
- **Manual Migrations**: Applying raw SQL changes
|
||||||
|
- **Data Maintenance**: Truncating tables, cleaning up data
|
||||||
|
- **Schema Synchronization**: Applying `migrate diff` scripts
|
||||||
|
- **Debugging**: Running test queries (though typically not for fetching data)
|
||||||
|
|
||||||
|
## Limitations
|
||||||
|
|
||||||
|
- **No Data Return**: The command reports success/failure, not query results (rows). Use Prisma Client or `prisma studio` to view data.
|
||||||
|
- **SQL Only**: Primarily for SQL databases.
|
||||||
@@ -0,0 +1,185 @@
|
|||||||
|
# prisma db pull
|
||||||
|
|
||||||
|
Introspects an existing database and updates your Prisma schema to reflect its structure.
|
||||||
|
|
||||||
|
## Command
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma db pull [options]
|
||||||
|
```
|
||||||
|
|
||||||
|
## What It Does
|
||||||
|
|
||||||
|
- Connects to your database
|
||||||
|
- Reads the database schema (tables, columns, relations, indexes)
|
||||||
|
- Updates `schema.prisma` with corresponding Prisma models
|
||||||
|
- For MongoDB, samples data to infer schema
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
| Option | Description |
|
||||||
|
|--------|-------------|
|
||||||
|
| `--force` | Ignore current Prisma schema file |
|
||||||
|
| `--print` | Print the introspected Prisma schema to stdout |
|
||||||
|
| `--schema` | Custom path to your Prisma schema |
|
||||||
|
| `--config` | Custom path to your Prisma config file |
|
||||||
|
| `--url` | Override the datasource URL from the Prisma config file |
|
||||||
|
| `--composite-type-depth` | Specify the depth for introspecting composite types (default: -1 for infinite, 0 = off) |
|
||||||
|
| `--schemas` | Specify the database schemas to introspect |
|
||||||
|
| `--local-d1` | Generate a Prisma schema from a local Cloudflare D1 database |
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### Basic introspection
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma db pull
|
||||||
|
```
|
||||||
|
|
||||||
|
### Preview without writing
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma db pull --print
|
||||||
|
```
|
||||||
|
|
||||||
|
Outputs schema to terminal for review.
|
||||||
|
|
||||||
|
### Force overwrite
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma db pull --force
|
||||||
|
```
|
||||||
|
|
||||||
|
Replaces schema file, losing any manual customizations.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
Configure database connection in `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'),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## Workflow
|
||||||
|
|
||||||
|
### Starting from existing database
|
||||||
|
|
||||||
|
1. Initialize Prisma:
|
||||||
|
```bash
|
||||||
|
prisma init
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Configure database URL
|
||||||
|
|
||||||
|
3. Pull schema:
|
||||||
|
```bash
|
||||||
|
prisma db pull
|
||||||
|
```
|
||||||
|
|
||||||
|
4. Review and customize generated schema
|
||||||
|
|
||||||
|
5. Generate client:
|
||||||
|
```bash
|
||||||
|
prisma generate
|
||||||
|
```
|
||||||
|
|
||||||
|
### Syncing changes from database
|
||||||
|
|
||||||
|
When database changes are made outside Prisma:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma db pull
|
||||||
|
prisma generate
|
||||||
|
```
|
||||||
|
|
||||||
|
## Generated Schema Example
|
||||||
|
|
||||||
|
Database tables become Prisma models:
|
||||||
|
|
||||||
|
```sql
|
||||||
|
-- Database tables
|
||||||
|
CREATE TABLE users (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
email VARCHAR(255) UNIQUE NOT NULL,
|
||||||
|
name VARCHAR(100)
|
||||||
|
);
|
||||||
|
|
||||||
|
CREATE TABLE posts (
|
||||||
|
id SERIAL PRIMARY KEY,
|
||||||
|
title VARCHAR(255) NOT NULL,
|
||||||
|
author_id INTEGER REFERENCES users(id)
|
||||||
|
);
|
||||||
|
```
|
||||||
|
|
||||||
|
Becomes:
|
||||||
|
|
||||||
|
```prisma
|
||||||
|
model users {
|
||||||
|
id Int @id @default(autoincrement())
|
||||||
|
email String @unique @db.VarChar(255)
|
||||||
|
name String? @db.VarChar(100)
|
||||||
|
posts posts[]
|
||||||
|
}
|
||||||
|
|
||||||
|
model posts {
|
||||||
|
id Int @id @default(autoincrement())
|
||||||
|
title String @db.VarChar(255)
|
||||||
|
author_id Int?
|
||||||
|
users users? @relation(fields: [author_id], references: [id])
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Post-Introspection Cleanup
|
||||||
|
|
||||||
|
After `db pull`, consider:
|
||||||
|
|
||||||
|
1. **Rename models** to PascalCase:
|
||||||
|
```prisma
|
||||||
|
model User { // Was: users
|
||||||
|
@@map("users")
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Rename fields** to camelCase:
|
||||||
|
```prisma
|
||||||
|
authorId Int? @map("author_id")
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Add relation names** for clarity:
|
||||||
|
```prisma
|
||||||
|
author User? @relation("PostAuthor", fields: [authorId], references: [id])
|
||||||
|
```
|
||||||
|
|
||||||
|
4. **Add documentation**:
|
||||||
|
```prisma
|
||||||
|
/// User account information
|
||||||
|
model User {
|
||||||
|
/// Primary email for authentication
|
||||||
|
email String @unique
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## MongoDB Introspection
|
||||||
|
|
||||||
|
For MongoDB, `db pull` samples documents to infer schema:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma db pull
|
||||||
|
```
|
||||||
|
|
||||||
|
May require manual refinement since MongoDB is schemaless.
|
||||||
|
|
||||||
|
## Warning
|
||||||
|
|
||||||
|
`db pull` overwrites your schema file. Always:
|
||||||
|
- Commit current schema before pulling
|
||||||
|
- Use `--print` to preview first
|
||||||
|
- Backup customizations you want to keep
|
||||||
@@ -0,0 +1,150 @@
|
|||||||
|
# prisma db push
|
||||||
|
|
||||||
|
Pushes schema changes directly to database without creating migrations. Ideal for prototyping.
|
||||||
|
|
||||||
|
## Command
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma db push [options]
|
||||||
|
```
|
||||||
|
|
||||||
|
## What It Does
|
||||||
|
|
||||||
|
- Syncs your Prisma schema to the database
|
||||||
|
- Creates database if it doesn't exist
|
||||||
|
- Does NOT create migration files
|
||||||
|
- Does NOT track migration history
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
| Option | Description |
|
||||||
|
|--------|-------------|
|
||||||
|
| `--force-reset` | Force a reset of the database before push |
|
||||||
|
| `--accept-data-loss` | Ignore data loss warnings |
|
||||||
|
| `--schema` | Custom path to your Prisma schema |
|
||||||
|
| `--config` | Custom path to your Prisma config file |
|
||||||
|
| `--url` | Override the datasource URL from the Prisma config file |
|
||||||
|
|
||||||
|
When Prisma detects an AI agent, `--force-reset` and `--accept-data-loss` require explicit user consent. Follow `agent-safety.md`; never infer or fabricate the consent text.
|
||||||
|
|
||||||
|
### Follow-up Command
|
||||||
|
|
||||||
|
- Run `prisma generate` explicitly when you need refreshed client output
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### Basic push
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma db push
|
||||||
|
```
|
||||||
|
|
||||||
|
### Accept data loss
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma db push --accept-data-loss
|
||||||
|
```
|
||||||
|
|
||||||
|
Required when changes would delete data (dropping columns, etc.)
|
||||||
|
|
||||||
|
### Force reset
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma db push --force-reset
|
||||||
|
```
|
||||||
|
|
||||||
|
Completely resets database and applies schema.
|
||||||
|
|
||||||
|
### Full workflow
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma db push
|
||||||
|
prisma generate
|
||||||
|
```
|
||||||
|
|
||||||
|
## When to Use
|
||||||
|
|
||||||
|
- **Prototyping** - Rapid schema iteration
|
||||||
|
- **Local development** - Quick schema changes
|
||||||
|
- **MongoDB** - Primary workflow (migrations not supported)
|
||||||
|
- **Testing** - Setting up test databases
|
||||||
|
|
||||||
|
## When NOT to Use
|
||||||
|
|
||||||
|
- **Production** - Use `migrate deploy`
|
||||||
|
- **Team collaboration** - Use migrations for trackable changes
|
||||||
|
- **When you need rollback** - Migrations provide history
|
||||||
|
|
||||||
|
## Comparison with migrate dev
|
||||||
|
|
||||||
|
| Feature | db push | migrate dev |
|
||||||
|
|---------|---------|-------------|
|
||||||
|
| Creates migration files | No | Yes |
|
||||||
|
| Tracks history | No | Yes |
|
||||||
|
| Requires shadow database | No | Yes |
|
||||||
|
| Speed | Faster | Slower |
|
||||||
|
| Rollback capability | No | Yes |
|
||||||
|
| Best for | Prototyping | Development |
|
||||||
|
|
||||||
|
## MongoDB Workflow
|
||||||
|
|
||||||
|
MongoDB doesn't support migrations. Use `db push` exclusively:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Schema changes for MongoDB
|
||||||
|
prisma db push
|
||||||
|
prisma generate
|
||||||
|
```
|
||||||
|
|
||||||
|
## Common Patterns
|
||||||
|
|
||||||
|
### Prototyping workflow
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Make schema changes
|
||||||
|
# ...
|
||||||
|
|
||||||
|
# Push to database
|
||||||
|
prisma db push
|
||||||
|
|
||||||
|
# Generate client
|
||||||
|
prisma generate
|
||||||
|
|
||||||
|
# Test your changes
|
||||||
|
# Repeat as needed
|
||||||
|
```
|
||||||
|
|
||||||
|
### Reset and start fresh
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma db push --force-reset
|
||||||
|
prisma db seed
|
||||||
|
```
|
||||||
|
|
||||||
|
### Handling conflicts
|
||||||
|
|
||||||
|
If `db push` can't apply changes safely:
|
||||||
|
|
||||||
|
```
|
||||||
|
Error: The following changes cannot be applied:
|
||||||
|
- Removing field `email` would cause data loss
|
||||||
|
|
||||||
|
Use --accept-data-loss to proceed
|
||||||
|
```
|
||||||
|
|
||||||
|
Decide whether data loss is acceptable, then:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma db push --accept-data-loss
|
||||||
|
```
|
||||||
|
|
||||||
|
## Transition to Migrations
|
||||||
|
|
||||||
|
When ready for production, switch to migrations:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Create baseline migration from current schema
|
||||||
|
prisma migrate dev --name init
|
||||||
|
```
|
||||||
|
|
||||||
|
Then use `migrate dev` for future changes.
|
||||||
@@ -0,0 +1,188 @@
|
|||||||
|
# prisma db seed
|
||||||
|
|
||||||
|
Runs your database seed script to populate data.
|
||||||
|
|
||||||
|
## Command
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma db seed [options]
|
||||||
|
```
|
||||||
|
|
||||||
|
## What It Does
|
||||||
|
|
||||||
|
- Executes your configured seed script
|
||||||
|
- Populates database with initial/test data
|
||||||
|
- Runs independently (not auto-run by migrations in v7)
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
| Option | Description |
|
||||||
|
|--------|-------------|
|
||||||
|
| `--config` | Custom path to your Prisma config file |
|
||||||
|
| `--` | Pass custom arguments to seed script |
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
Configure seed script in `prisma.config.ts`:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import 'dotenv/config'
|
||||||
|
import { defineConfig, env } from 'prisma/config'
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
schema: 'prisma/schema.prisma',
|
||||||
|
migrations: {
|
||||||
|
path: 'prisma/migrations',
|
||||||
|
seed: 'tsx prisma/seed.ts', // Your seed command
|
||||||
|
},
|
||||||
|
datasource: {
|
||||||
|
url: env('DATABASE_URL'),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Common seed commands
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// TypeScript with tsx
|
||||||
|
seed: 'tsx prisma/seed.ts'
|
||||||
|
|
||||||
|
// TypeScript with ts-node
|
||||||
|
seed: 'ts-node prisma/seed.ts'
|
||||||
|
|
||||||
|
// JavaScript
|
||||||
|
seed: 'node prisma/seed.js'
|
||||||
|
```
|
||||||
|
|
||||||
|
## Seed Script Example
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// prisma/seed.ts
|
||||||
|
import { PrismaClient } from '../generated/client'
|
||||||
|
|
||||||
|
const prisma = new PrismaClient()
|
||||||
|
|
||||||
|
async function main() {
|
||||||
|
// Create users
|
||||||
|
const alice = await prisma.user.upsert({
|
||||||
|
where: { email: 'alice@prisma.io' },
|
||||||
|
update: {},
|
||||||
|
create: {
|
||||||
|
email: 'alice@prisma.io',
|
||||||
|
name: 'Alice',
|
||||||
|
posts: {
|
||||||
|
create: {
|
||||||
|
title: 'Hello World',
|
||||||
|
published: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
const bob = await prisma.user.upsert({
|
||||||
|
where: { email: 'bob@prisma.io' },
|
||||||
|
update: {},
|
||||||
|
create: {
|
||||||
|
email: 'bob@prisma.io',
|
||||||
|
name: 'Bob',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
console.log({ alice, bob })
|
||||||
|
}
|
||||||
|
|
||||||
|
main()
|
||||||
|
.then(async () => {
|
||||||
|
await prisma.$disconnect()
|
||||||
|
})
|
||||||
|
.catch(async (e) => {
|
||||||
|
console.error(e)
|
||||||
|
await prisma.$disconnect()
|
||||||
|
process.exit(1)
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### Run seed
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma db seed
|
||||||
|
```
|
||||||
|
|
||||||
|
### With custom arguments
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma db seed -- --environment development
|
||||||
|
```
|
||||||
|
|
||||||
|
Arguments after `--` are passed to your seed script.
|
||||||
|
|
||||||
|
## Current Workflow
|
||||||
|
|
||||||
|
Run seeding explicitly after migrations when you need seed data:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma migrate dev --name init
|
||||||
|
prisma generate
|
||||||
|
prisma db seed # Must run explicitly
|
||||||
|
```
|
||||||
|
|
||||||
|
## Idempotent Seeding
|
||||||
|
|
||||||
|
Use `upsert` to make seeds re-runnable:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Good: Can run multiple times
|
||||||
|
await prisma.user.upsert({
|
||||||
|
where: { email: 'alice@prisma.io' },
|
||||||
|
update: {}, // Don't change existing
|
||||||
|
create: { email: 'alice@prisma.io', name: 'Alice' },
|
||||||
|
})
|
||||||
|
|
||||||
|
// Bad: Fails on second run
|
||||||
|
await prisma.user.create({
|
||||||
|
data: { email: 'alice@prisma.io', name: 'Alice' },
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## Common Patterns
|
||||||
|
|
||||||
|
### Development reset
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma migrate reset --force
|
||||||
|
prisma db seed
|
||||||
|
```
|
||||||
|
|
||||||
|
### Conditional seeding
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// prisma/seed.ts
|
||||||
|
const count = await prisma.user.count()
|
||||||
|
if (count === 0) {
|
||||||
|
// Only seed if empty
|
||||||
|
await seedUsers()
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Environment-specific seeds
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// prisma/seed.ts
|
||||||
|
const env = process.env.NODE_ENV || 'development'
|
||||||
|
|
||||||
|
if (env === 'development') {
|
||||||
|
await seedDevData()
|
||||||
|
} else if (env === 'test') {
|
||||||
|
await seedTestData()
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Best Practices
|
||||||
|
|
||||||
|
1. Use `upsert` for idempotent seeds
|
||||||
|
2. Keep seeds focused and minimal
|
||||||
|
3. Use realistic but fake data
|
||||||
|
4. Document required seed data
|
||||||
|
5. Version control your seed scripts
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
# prisma debug
|
||||||
|
|
||||||
|
Prints information helpful for debugging and bug reports.
|
||||||
|
|
||||||
|
## Command
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma debug [options]
|
||||||
|
```
|
||||||
|
|
||||||
|
## What It Does
|
||||||
|
|
||||||
|
Outputs details about your Prisma environment, including:
|
||||||
|
- Prisma CLI version
|
||||||
|
- Prisma Client version (if installed)
|
||||||
|
- Engine binaries (Query Engine, Migration Engine, etc.)
|
||||||
|
- Platform information (OS, Architecture)
|
||||||
|
- Node.js version
|
||||||
|
- Configured datasource provider
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
| Option | Description |
|
||||||
|
|--------|-------------|
|
||||||
|
| `--schema` | Path to schema file |
|
||||||
|
| `--config` | Custom path to your Prisma config file |
|
||||||
|
|
||||||
|
## Example Output
|
||||||
|
|
||||||
|
```
|
||||||
|
prisma : 7.3.0
|
||||||
|
@prisma/client : 7.3.0
|
||||||
|
Operating System : darwin
|
||||||
|
Architecture : arm64
|
||||||
|
Node.js : v20.10.0
|
||||||
|
TypeScript : 5.3.3
|
||||||
|
Query Compiler : enabled
|
||||||
|
PSL : ...
|
||||||
|
Schema Engine : ...
|
||||||
|
```
|
||||||
|
|
||||||
|
## When to Use
|
||||||
|
|
||||||
|
- **Troubleshooting**: Checking version mismatches
|
||||||
|
- **Reporting Issues**: Including environment info in GitHub issues
|
||||||
|
- **Verifying Installation**: Ensuring correct binaries are downloaded
|
||||||
@@ -0,0 +1,157 @@
|
|||||||
|
# prisma dev
|
||||||
|
|
||||||
|
Starts a local Prisma Postgres database for development. Provides a PostgreSQL-compatible database that runs entirely on your machine.
|
||||||
|
|
||||||
|
## Command
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma dev [options]
|
||||||
|
```
|
||||||
|
|
||||||
|
## What It Does
|
||||||
|
|
||||||
|
- Starts a local PostgreSQL-compatible database
|
||||||
|
- Runs in your terminal or as a background process
|
||||||
|
- Perfect for development and testing
|
||||||
|
- Easy migration to Prisma Postgres cloud in production
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
| Option | Description | Default |
|
||||||
|
|--------|-------------|---------|
|
||||||
|
| `--name` / `-n` | Name for the database instance | `default` |
|
||||||
|
| `--port` / `-p` | HTTP server port | `51213` |
|
||||||
|
| `--db-port` / `-P` | Database server port | `51214` |
|
||||||
|
| `--shadow-db-port` | Shadow database port (for migrations) | `51215` |
|
||||||
|
| `--detach` / `-d` | Run in background | `false` |
|
||||||
|
| `--debug` | Enable debug logging | `false` |
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### Start local database
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma dev
|
||||||
|
```
|
||||||
|
|
||||||
|
Interactive mode with keyboard shortcuts:
|
||||||
|
- `q` - Quit
|
||||||
|
- `h` - Show HTTP URL
|
||||||
|
- `t` - Show TCP URLs
|
||||||
|
|
||||||
|
### Named instance
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma dev --name myproject
|
||||||
|
```
|
||||||
|
|
||||||
|
Useful for multiple projects.
|
||||||
|
|
||||||
|
### Background mode
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma dev --detach
|
||||||
|
```
|
||||||
|
|
||||||
|
Frees your terminal for other commands.
|
||||||
|
|
||||||
|
### Custom ports
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma dev --port 5000 --db-port 5432
|
||||||
|
```
|
||||||
|
|
||||||
|
## Instance Management
|
||||||
|
|
||||||
|
### List all instances
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma dev ls
|
||||||
|
```
|
||||||
|
|
||||||
|
Shows all local Prisma Postgres instances with status.
|
||||||
|
|
||||||
|
### Start existing instance
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma dev start myproject
|
||||||
|
```
|
||||||
|
|
||||||
|
Starts a previously created instance in background.
|
||||||
|
|
||||||
|
### Stop instance
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma dev stop myproject
|
||||||
|
```
|
||||||
|
|
||||||
|
### Stop with glob pattern
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma dev stop "myproject*"
|
||||||
|
```
|
||||||
|
|
||||||
|
Stops all instances matching pattern.
|
||||||
|
|
||||||
|
### Remove instance
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma dev rm myproject
|
||||||
|
```
|
||||||
|
|
||||||
|
Removes instance data from filesystem.
|
||||||
|
|
||||||
|
### Force remove (stops first)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma dev rm myproject --force
|
||||||
|
```
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
Configure your `prisma.config.ts` to use local Prisma Postgres:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import 'dotenv/config'
|
||||||
|
import { defineConfig, env } from 'prisma/config'
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
schema: 'prisma/schema.prisma',
|
||||||
|
migrations: {
|
||||||
|
path: 'prisma/migrations',
|
||||||
|
},
|
||||||
|
datasource: {
|
||||||
|
// Local Prisma Postgres URL (from prisma dev output)
|
||||||
|
url: env('DATABASE_URL'),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## Workflow
|
||||||
|
|
||||||
|
1. Start local database:
|
||||||
|
```bash
|
||||||
|
prisma dev
|
||||||
|
```
|
||||||
|
|
||||||
|
2. In another terminal, run migrations:
|
||||||
|
```bash
|
||||||
|
prisma migrate dev
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Generate client:
|
||||||
|
```bash
|
||||||
|
prisma generate
|
||||||
|
```
|
||||||
|
|
||||||
|
4. Run your application
|
||||||
|
|
||||||
|
## Production Migration
|
||||||
|
|
||||||
|
When ready for production, switch to Prisma Postgres cloud:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma init --db
|
||||||
|
```
|
||||||
|
|
||||||
|
Update your `DATABASE_URL` to the cloud connection string.
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
# prisma format
|
||||||
|
|
||||||
|
Formats your Prisma schema file.
|
||||||
|
|
||||||
|
## Command
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma format [options]
|
||||||
|
```
|
||||||
|
|
||||||
|
## What It Does
|
||||||
|
|
||||||
|
- Fixes formatting (indentation, spacing)
|
||||||
|
- Adds missing back-relations (e.g., adds the other side of a relation)
|
||||||
|
- Adds missing relation arguments (e.g., `fields`, `references`)
|
||||||
|
- Sorts fields and attributes (opinionated)
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
| Option | Description |
|
||||||
|
|--------|-------------|
|
||||||
|
| `--schema` | Path to schema file |
|
||||||
|
| `--config` | Custom path to your Prisma config file |
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### Format default schema
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma format
|
||||||
|
```
|
||||||
|
|
||||||
|
### Format specific schema
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma format --schema=./custom/schema.prisma
|
||||||
|
```
|
||||||
|
|
||||||
|
## Behavior
|
||||||
|
|
||||||
|
`prisma format` modifies the file in place. It is equivalent to "Prettier for Prisma schemas" but also has semantic understanding to fix/add missing schema definitions.
|
||||||
|
|
||||||
|
## Use in Editor
|
||||||
|
|
||||||
|
Most Prisma editor extensions (VS Code, WebStorm) run `prisma format` automatically on save. This command is useful for:
|
||||||
|
- CI pipelines (check formatting)
|
||||||
|
- CLI-based workflows
|
||||||
|
- Fixing large schema refactors
|
||||||
@@ -0,0 +1,173 @@
|
|||||||
|
# prisma generate
|
||||||
|
|
||||||
|
Generates assets based on the generator blocks in your Prisma schema, most commonly Prisma Client.
|
||||||
|
|
||||||
|
## Command
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma generate [options]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Bun Runtime
|
||||||
|
|
||||||
|
If you're using Bun, run Prisma with `bunx --bun` so it doesn't fall back to Node.js:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bunx --bun prisma generate
|
||||||
|
```
|
||||||
|
|
||||||
|
## What It Does
|
||||||
|
|
||||||
|
1. Reads your `schema.prisma` file
|
||||||
|
2. Generates a customized Prisma Client based on your models
|
||||||
|
3. Outputs to the directory specified in the generator block
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
| Option | Description |
|
||||||
|
|--------|-------------|
|
||||||
|
| `--schema` | Custom path to your Prisma schema |
|
||||||
|
| `--config` | Custom path to your Prisma config file |
|
||||||
|
| `--sql` | Generate typed sql module |
|
||||||
|
| `--watch` | Watch the Prisma schema and rerun after a change |
|
||||||
|
| `--generator` | Generator to use (may be provided multiple times) |
|
||||||
|
| `--no-hints` | Hides the hint messages but still outputs errors and warnings |
|
||||||
|
| `--require-models` | Do not allow generating a client without models |
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### Basic generation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma generate
|
||||||
|
```
|
||||||
|
|
||||||
|
### Watch mode (development)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma generate --watch
|
||||||
|
```
|
||||||
|
|
||||||
|
Auto-regenerates when `schema.prisma` changes.
|
||||||
|
|
||||||
|
### Specific generator
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma generate --generator client
|
||||||
|
```
|
||||||
|
|
||||||
|
### Multiple generators
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma generate --generator client --generator zod_schemas
|
||||||
|
```
|
||||||
|
|
||||||
|
### Typed SQL generation
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma generate --sql
|
||||||
|
```
|
||||||
|
|
||||||
|
## Schema Configuration
|
||||||
|
|
||||||
|
```prisma
|
||||||
|
generator client {
|
||||||
|
provider = "prisma-client"
|
||||||
|
output = "../generated"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Current Generator Behavior
|
||||||
|
|
||||||
|
- `prisma-client` is the standard generator
|
||||||
|
- `output` is required when using `prisma-client`
|
||||||
|
- `prisma-client` supports both ESM and CommonJS via `moduleFormat`
|
||||||
|
- `compilerBuild` supports `fast` and `small` query compiler artifacts
|
||||||
|
- Use TypeScript `satisfies` for typed query fragments with `prisma-client`
|
||||||
|
- Import Prisma Client from your generated output path, for example:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { PrismaClient } from '../generated/prisma/client'
|
||||||
|
```
|
||||||
|
|
||||||
|
### Compiler Build Tuning
|
||||||
|
|
||||||
|
Use `compilerBuild` when you need to trade artifact size against the default build:
|
||||||
|
|
||||||
|
```prisma
|
||||||
|
generator client {
|
||||||
|
provider = "prisma-client"
|
||||||
|
output = "../generated"
|
||||||
|
compilerBuild = "small"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- `fast` is the default build for most targets
|
||||||
|
- `small` is useful for size-constrained targets
|
||||||
|
- Prisma defaults `vercel-edge` targets to `small`
|
||||||
|
|
||||||
|
## Common Patterns
|
||||||
|
|
||||||
|
### After schema changes
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma migrate dev --name my_migration
|
||||||
|
prisma generate
|
||||||
|
```
|
||||||
|
|
||||||
|
Run `prisma generate` whenever you need refreshed client code after schema-changing commands.
|
||||||
|
|
||||||
|
### CI/CD pipeline
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma generate
|
||||||
|
```
|
||||||
|
|
||||||
|
Run before building your application.
|
||||||
|
|
||||||
|
### Multiple generators
|
||||||
|
|
||||||
|
```prisma
|
||||||
|
generator client {
|
||||||
|
provider = "prisma-client"
|
||||||
|
output = "../generated"
|
||||||
|
}
|
||||||
|
|
||||||
|
generator zod {
|
||||||
|
provider = "zod-prisma-types"
|
||||||
|
output = "../generated/zod"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma generate # Runs all generators
|
||||||
|
```
|
||||||
|
|
||||||
|
## Output Structure
|
||||||
|
|
||||||
|
After running `prisma generate`, your output directory contains:
|
||||||
|
|
||||||
|
```
|
||||||
|
generated/
|
||||||
|
├── browser.ts
|
||||||
|
├── client.ts
|
||||||
|
├── commonInputTypes.ts
|
||||||
|
├── models/
|
||||||
|
├── enums.ts
|
||||||
|
├── models.ts
|
||||||
|
└── ...
|
||||||
|
```
|
||||||
|
|
||||||
|
Import the client:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { PrismaClient, Prisma } from '../generated/prisma/client'
|
||||||
|
```
|
||||||
|
|
||||||
|
Import browser-safe types:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { Prisma } from '../generated/prisma/browser'
|
||||||
|
import { Role } from '../generated/prisma/enums'
|
||||||
|
import type { UserModel } from '../generated/prisma/models/User'
|
||||||
|
```
|
||||||
@@ -0,0 +1,139 @@
|
|||||||
|
# prisma init
|
||||||
|
|
||||||
|
Bootstraps a fresh Prisma ORM project in the current directory.
|
||||||
|
|
||||||
|
## Command
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma init [options]
|
||||||
|
```
|
||||||
|
|
||||||
|
## Bun Runtime
|
||||||
|
|
||||||
|
If you're using Bun, run Prisma with `bunx --bun` so it doesn't fall back to Node.js:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bunx --bun prisma init
|
||||||
|
```
|
||||||
|
|
||||||
|
## What It Creates
|
||||||
|
|
||||||
|
- `prisma/schema.prisma` - Your Prisma schema file
|
||||||
|
- `prisma.config.ts` - TypeScript configuration for Prisma CLI
|
||||||
|
- `.env` - Environment variables (DATABASE_URL)
|
||||||
|
- `.gitignore` - Ensures `.env` is ignored and appends the generated client path
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
| Option | Description | Default |
|
||||||
|
|--------|-------------|---------|
|
||||||
|
| `--datasource-provider` | Database provider: `postgresql`, `mysql`, `sqlite`, `sqlserver`, `mongodb`, `cockroachdb` | `postgresql` |
|
||||||
|
| `--db` | Provisions a fully managed Prisma Postgres database on the Prisma Data Platform | - |
|
||||||
|
| `--url` | Define a custom datasource url | - |
|
||||||
|
| `--generator-provider` | Define the generator provider to use | `prisma-client` |
|
||||||
|
| `--output` | Define Prisma Client generator output path to use | - |
|
||||||
|
| `--preview-feature` | Define a preview feature to use | - |
|
||||||
|
| `--with-model` | Add example model to created schema file | - |
|
||||||
|
| `--no-skills` | Skip the best-effort installation of Prisma agent skills | - |
|
||||||
|
|
||||||
|
`prisma init` attempts to install `prisma/skills` for detected agents. This is best-effort and does not make project initialization fail. Use `--no-skills` in minimal or controlled environments.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### Basic initialization
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma init
|
||||||
|
```
|
||||||
|
|
||||||
|
Creates a PostgreSQL project setup.
|
||||||
|
|
||||||
|
### SQLite project
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma init --datasource-provider sqlite
|
||||||
|
```
|
||||||
|
|
||||||
|
### MySQL with custom URL
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma init --datasource-provider mysql --url "mysql://user:password@localhost:3306/mydb"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Prisma Postgres (cloud)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma init --db
|
||||||
|
```
|
||||||
|
|
||||||
|
Opens browser for authentication, creates cloud database instance.
|
||||||
|
|
||||||
|
### Add an example model
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma init --with-model
|
||||||
|
```
|
||||||
|
|
||||||
|
Adds a starter model to the generated schema.
|
||||||
|
|
||||||
|
### With preview features
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma init --preview-feature relationJoins --preview-feature fullTextSearch
|
||||||
|
```
|
||||||
|
|
||||||
|
## Generated Schema
|
||||||
|
|
||||||
|
```prisma
|
||||||
|
generator client {
|
||||||
|
provider = "prisma-client"
|
||||||
|
output = "../generated/prisma"
|
||||||
|
}
|
||||||
|
|
||||||
|
datasource db {
|
||||||
|
provider = "postgresql"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Generated Config (Node.js default)
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// prisma.config.ts
|
||||||
|
import "dotenv/config";
|
||||||
|
import { defineConfig } from 'prisma/config'
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
schema: 'prisma/schema.prisma',
|
||||||
|
migrations: {
|
||||||
|
path: 'prisma/migrations',
|
||||||
|
},
|
||||||
|
datasource: {
|
||||||
|
url: process.env['DATABASE_URL'],
|
||||||
|
},
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## Generated Config (Bun)
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { defineConfig, env } from 'prisma/config'
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
schema: 'prisma/schema.prisma',
|
||||||
|
migrations: {
|
||||||
|
path: 'prisma/migrations',
|
||||||
|
},
|
||||||
|
datasource: {
|
||||||
|
url: env('DATABASE_URL'),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## Next Steps After Init
|
||||||
|
|
||||||
|
1. Configure `DATABASE_URL` in `.env` (and let `prisma.config.ts` read it)
|
||||||
|
2. Define your models in `prisma/schema.prisma`
|
||||||
|
3. Run `prisma dev` for local development or connect to remote DB
|
||||||
|
4. Run `prisma migrate dev` to create migrations
|
||||||
|
5. Run `prisma generate` to generate Prisma Client
|
||||||
|
6. Run `prisma db seed` explicitly if you want seed data
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
# prisma mcp
|
||||||
|
|
||||||
|
Starts Prisma's MCP server for AI development tools.
|
||||||
|
|
||||||
|
## Command
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma mcp
|
||||||
|
```
|
||||||
|
|
||||||
|
## What It Does
|
||||||
|
|
||||||
|
- Starts a Model Context Protocol (MCP) server for your Prisma project
|
||||||
|
- Exposes Prisma schema and database context to compatible AI tools
|
||||||
|
- Helps AI assistants understand models, generate queries, and suggest migrations
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma mcp
|
||||||
|
```
|
||||||
|
|
||||||
|
## Typical Use Cases
|
||||||
|
|
||||||
|
- Connect Prisma to ChatGPT, Claude, or other MCP-aware tools
|
||||||
|
- Give an AI assistant access to your Prisma schema structure
|
||||||
|
- Help an agent propose queries, schema updates, and migration steps with project context
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- Run this from the project that contains your Prisma schema and `prisma.config.ts`
|
||||||
|
- The command is separate from Prisma Studio and does not open a browser UI
|
||||||
|
- The MCP server exposes `migrate-status`, `migrate-dev`, and Prisma Studio tooling. It does not expose the destructive `migrate-reset` tool; do not claim it is available or try to bypass that safety boundary.
|
||||||
|
- For destructive shell commands, follow `agent-safety.md` and obtain explicit user consent.
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- [Prisma CLI `mcp` command](https://docs.prisma.io/docs/cli/mcp)
|
||||||
|
- [Prisma MCP Server](https://www.prisma.io/docs/ai/tools/chatgpt)
|
||||||
@@ -0,0 +1,127 @@
|
|||||||
|
# prisma migrate deploy
|
||||||
|
|
||||||
|
Applies pending migrations in production/staging environments.
|
||||||
|
|
||||||
|
## Command
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma migrate deploy
|
||||||
|
```
|
||||||
|
|
||||||
|
## What It Does
|
||||||
|
|
||||||
|
- Applies all pending migrations from `prisma/migrations/`
|
||||||
|
- Updates `_prisma_migrations` table
|
||||||
|
- Does NOT generate new migrations
|
||||||
|
- Does NOT run seed scripts
|
||||||
|
- Safe for CI/CD and production
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
| Option | Description |
|
||||||
|
|--------|-------------|
|
||||||
|
| `--schema` | Custom path to your Prisma schema |
|
||||||
|
| `--config` | Custom path to your Prisma config file |
|
||||||
|
|
||||||
|
## When to Use
|
||||||
|
|
||||||
|
- Production deployments
|
||||||
|
- Staging environments
|
||||||
|
- CI/CD pipelines
|
||||||
|
- Any non-development environment
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### Basic deployment
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma migrate deploy
|
||||||
|
```
|
||||||
|
|
||||||
|
### In CI/CD pipeline
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# GitHub Actions example
|
||||||
|
- name: Apply migrations
|
||||||
|
run: npx prisma migrate deploy
|
||||||
|
env:
|
||||||
|
DATABASE_URL: ${{ secrets.DATABASE_URL }}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Docker deployment
|
||||||
|
|
||||||
|
```dockerfile
|
||||||
|
# Run migrations before starting app
|
||||||
|
CMD npx prisma migrate deploy && node dist/index.js
|
||||||
|
```
|
||||||
|
|
||||||
|
## Comparison with migrate dev
|
||||||
|
|
||||||
|
| Feature | migrate dev | migrate deploy |
|
||||||
|
|---------|-------------|----------------|
|
||||||
|
| Creates migrations | Yes | No |
|
||||||
|
| Applies migrations | Yes | Yes |
|
||||||
|
| Detects drift | Yes | No |
|
||||||
|
| Prompts for input | Yes | No |
|
||||||
|
| Uses shadow database | Yes | No |
|
||||||
|
| Safe for production | No | Yes |
|
||||||
|
| Resets on issues | Prompts | Fails |
|
||||||
|
|
||||||
|
## Production Workflow
|
||||||
|
|
||||||
|
1. **Development**: Create migrations locally
|
||||||
|
```bash
|
||||||
|
prisma migrate dev --name add_feature
|
||||||
|
```
|
||||||
|
|
||||||
|
2. **Commit**: Include migration files in version control
|
||||||
|
```bash
|
||||||
|
git add prisma/migrations
|
||||||
|
git commit -m "Add feature migration"
|
||||||
|
```
|
||||||
|
|
||||||
|
3. **Deploy**: Apply in production
|
||||||
|
```bash
|
||||||
|
prisma migrate deploy
|
||||||
|
```
|
||||||
|
|
||||||
|
## Error Handling
|
||||||
|
|
||||||
|
### Failed migration
|
||||||
|
|
||||||
|
If a migration fails, `migrate deploy` exits with error. The failed migration is marked as failed in `_prisma_migrations`.
|
||||||
|
|
||||||
|
To fix:
|
||||||
|
1. Resolve the issue (fix SQL, database state, etc.)
|
||||||
|
2. Mark as resolved: `prisma migrate resolve --applied <migration_name>`
|
||||||
|
3. Re-run: `prisma migrate deploy`
|
||||||
|
|
||||||
|
### Check status first
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma migrate status
|
||||||
|
```
|
||||||
|
|
||||||
|
Shows pending and applied migrations before deploying.
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
Ensure `prisma.config.ts` has the production database URL:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import 'dotenv/config'
|
||||||
|
import { defineConfig, env } from 'prisma/config'
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
datasource: {
|
||||||
|
url: env('DATABASE_URL'),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## Best Practices
|
||||||
|
|
||||||
|
1. Always run `migrate status` before `migrate deploy` in CI
|
||||||
|
2. Have a rollback plan (backup before migrations)
|
||||||
|
3. Test migrations in staging first
|
||||||
|
4. Never use `migrate dev` in production
|
||||||
@@ -0,0 +1,145 @@
|
|||||||
|
# prisma migrate dev
|
||||||
|
|
||||||
|
Creates and applies migrations during development. Requires a shadow database.
|
||||||
|
|
||||||
|
## Command
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma migrate dev [options]
|
||||||
|
```
|
||||||
|
|
||||||
|
## What It Does
|
||||||
|
|
||||||
|
1. Runs existing migrations in shadow database to detect drift
|
||||||
|
2. Applies any pending migrations
|
||||||
|
3. Generates new migration from schema changes
|
||||||
|
4. Applies new migration to development database
|
||||||
|
5. Updates `_prisma_migrations` table
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
| Option | Description |
|
||||||
|
|--------|-------------|
|
||||||
|
| `--name` / `-n` | Name the migration |
|
||||||
|
| `--create-only` | Create a new migration but do not apply it |
|
||||||
|
| `--schema` | Custom path to your Prisma schema |
|
||||||
|
| `--config` | Custom path to your Prisma config file |
|
||||||
|
| `--url` | Override the datasource URL from the Prisma config file |
|
||||||
|
|
||||||
|
### Follow-up Commands
|
||||||
|
|
||||||
|
- Run `prisma generate` explicitly when you need refreshed client output
|
||||||
|
- Run `prisma db seed` explicitly when you need seed data
|
||||||
|
|
||||||
|
Run `prisma generate` as an explicit follow-up when you need refreshed generated artifacts. Do not rely on historical CLI help that described generators as part of `migrate dev`.
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### Create and apply migration
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma migrate dev
|
||||||
|
```
|
||||||
|
|
||||||
|
Prompts for migration name if schema changed.
|
||||||
|
|
||||||
|
### Named migration
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma migrate dev --name add_users_table
|
||||||
|
```
|
||||||
|
|
||||||
|
### Create without applying
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma migrate dev --create-only
|
||||||
|
```
|
||||||
|
|
||||||
|
Useful for reviewing migration SQL before applying.
|
||||||
|
|
||||||
|
### Full workflow
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma migrate dev --name my_migration
|
||||||
|
prisma generate
|
||||||
|
prisma db seed
|
||||||
|
```
|
||||||
|
|
||||||
|
## Migration Files
|
||||||
|
|
||||||
|
Created in `prisma/migrations/`:
|
||||||
|
|
||||||
|
```
|
||||||
|
prisma/migrations/
|
||||||
|
├── 20240115120000_add_users_table/
|
||||||
|
│ └── migration.sql
|
||||||
|
├── 20240116090000_add_posts/
|
||||||
|
│ └── migration.sql
|
||||||
|
└── migration_lock.toml
|
||||||
|
```
|
||||||
|
|
||||||
|
## Schema Drift Detection
|
||||||
|
|
||||||
|
If `migrate dev` detects drift (manual database changes or edited migrations), it prompts to reset:
|
||||||
|
|
||||||
|
```
|
||||||
|
Drift detected: Your database schema is not in sync.
|
||||||
|
|
||||||
|
Do you want to reset your database? All data will be lost.
|
||||||
|
```
|
||||||
|
|
||||||
|
## When to Use
|
||||||
|
|
||||||
|
- Local development
|
||||||
|
- Adding new models/fields
|
||||||
|
- Changing relations
|
||||||
|
- Creating indexes
|
||||||
|
|
||||||
|
## When NOT to Use
|
||||||
|
|
||||||
|
- Production deployments (use `migrate deploy`)
|
||||||
|
- CI/CD pipelines (use `migrate deploy`)
|
||||||
|
- MongoDB (use `db push` instead)
|
||||||
|
|
||||||
|
## Common Patterns
|
||||||
|
|
||||||
|
### After schema changes
|
||||||
|
|
||||||
|
```prisma
|
||||||
|
// schema.prisma - Add new field
|
||||||
|
model User {
|
||||||
|
id Int @id @default(autoincrement())
|
||||||
|
email String @unique
|
||||||
|
name String?
|
||||||
|
createdAt DateTime @default(now()) // New field
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma migrate dev --name add_created_at
|
||||||
|
```
|
||||||
|
|
||||||
|
### Handling data loss warnings
|
||||||
|
|
||||||
|
When a migration would cause data loss:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma migrate dev --name remove_field
|
||||||
|
# Warning: You are about to delete data...
|
||||||
|
# Accept with: --accept-data-loss
|
||||||
|
```
|
||||||
|
|
||||||
|
## Shadow Database
|
||||||
|
|
||||||
|
`migrate dev` requires a shadow database for drift detection. Configure in `prisma.config.ts`:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
export default defineConfig({
|
||||||
|
datasource: {
|
||||||
|
url: env('DATABASE_URL'),
|
||||||
|
shadowDatabaseUrl: env('SHADOW_DATABASE_URL'),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
For local Prisma Postgres (`prisma dev`), shadow database is handled automatically.
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
# prisma migrate diff
|
||||||
|
|
||||||
|
Compares database schemas and generates diffs (SQL or summary).
|
||||||
|
|
||||||
|
## Command
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma migrate diff [options]
|
||||||
|
```
|
||||||
|
|
||||||
|
## What It Does
|
||||||
|
|
||||||
|
- Compares two sources (`--from-...` and `--to-...`)
|
||||||
|
- Sources can be:
|
||||||
|
- Empty (`empty`)
|
||||||
|
- Schema file (`schema`)
|
||||||
|
- Migrations directory (`migrations`)
|
||||||
|
- Database URL (`url`) or Configured Datasource (`config-datasource`)
|
||||||
|
- Outputs the difference:
|
||||||
|
- Human-readable summary (default)
|
||||||
|
- SQL script (`--script`)
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
| Option | Description |
|
||||||
|
|--------|-------------|
|
||||||
|
| `--script` | Render SQL script to stdout |
|
||||||
|
| `--exit-code` | Exit 2 if changes detected, 0 if empty, 1 if error |
|
||||||
|
| `--config` | Custom path to your Prisma config file |
|
||||||
|
|
||||||
|
### Sources (Must provide one `from` and one `to`)
|
||||||
|
|
||||||
|
- `--from-empty`, `--to-empty`
|
||||||
|
- `--from-schema <path>`, `--to-schema <path>`
|
||||||
|
- `--from-migrations <path>`, `--to-migrations <path>`
|
||||||
|
- `--from-url <url>`, `--to-url <url>`
|
||||||
|
- `--from-config-datasource`, `--to-config-datasource` (uses `prisma.config.ts`)
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### Generate SQL for a schema change
|
||||||
|
|
||||||
|
Compare current production DB to your local schema:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma migrate diff \
|
||||||
|
--from-url "$PROD_DB_URL" \
|
||||||
|
--to-schema ./prisma/schema.prisma \
|
||||||
|
--script
|
||||||
|
```
|
||||||
|
|
||||||
|
### Review pending migrations
|
||||||
|
|
||||||
|
Compare database state to migrations directory:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma migrate diff \
|
||||||
|
--from-config-datasource \
|
||||||
|
--to-migrations ./prisma/migrations
|
||||||
|
```
|
||||||
|
|
||||||
|
### Create baseline migration
|
||||||
|
|
||||||
|
Compare empty state to current schema:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma migrate diff \
|
||||||
|
--from-empty \
|
||||||
|
--to-schema ./prisma/schema.prisma \
|
||||||
|
--script > prisma/migrations/0_init/migration.sql
|
||||||
|
```
|
||||||
|
|
||||||
|
### Check for drift (CI)
|
||||||
|
|
||||||
|
Check if database matches schema:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma migrate diff \
|
||||||
|
--from-config-datasource \
|
||||||
|
--to-schema ./prisma/schema.prisma \
|
||||||
|
--exit-code
|
||||||
|
```
|
||||||
|
|
||||||
|
## Use Cases
|
||||||
|
|
||||||
|
- **Forward-generating migrations**: Creating SQL without `migrate dev`.
|
||||||
|
- **Drift detection**: Checking if DB is in sync.
|
||||||
|
- **Baselining**: Creating initial migration from existing DB.
|
||||||
|
- **Debugging**: Understanding what `migrate dev` would do.
|
||||||
@@ -0,0 +1,80 @@
|
|||||||
|
# prisma migrate reset
|
||||||
|
|
||||||
|
Resets your database and re-applies all migrations.
|
||||||
|
|
||||||
|
## Command
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma migrate reset [options]
|
||||||
|
```
|
||||||
|
|
||||||
|
## What It Does
|
||||||
|
|
||||||
|
1. **Drops** the database (if possible) or deletes all data/tables
|
||||||
|
2. **Re-creates** the database
|
||||||
|
3. **Applies** all migrations from `prisma/migrations/`
|
||||||
|
4. Stops there - run seed and generate explicitly if needed
|
||||||
|
|
||||||
|
**Warning: All data will be lost.**
|
||||||
|
|
||||||
|
When Prisma detects an AI agent, this command is blocked until the user gives explicit consent. Follow `agent-safety.md`; `--force` skips the ordinary prompt but does not constitute user consent for an agent.
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
| Option | Description |
|
||||||
|
|--------|-------------|
|
||||||
|
| `--force` / `-f` | Skip confirmation prompt |
|
||||||
|
| `--schema` | Path to schema file |
|
||||||
|
| `--config` | Custom path to your Prisma config file |
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### Basic reset
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma migrate reset
|
||||||
|
```
|
||||||
|
|
||||||
|
Prompts for confirmation in interactive terminals.
|
||||||
|
|
||||||
|
### Force reset (CI/Automation)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma migrate reset --force
|
||||||
|
```
|
||||||
|
|
||||||
|
### With custom schema
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma migrate reset --schema=./custom/schema.prisma
|
||||||
|
```
|
||||||
|
|
||||||
|
## When to Use
|
||||||
|
|
||||||
|
- **Development**: When you want a fresh start
|
||||||
|
- **Testing**: Resetting test database before suites
|
||||||
|
- **Drift Recovery**: When the database is out of sync and you can't migrate
|
||||||
|
|
||||||
|
## Follow-up Steps
|
||||||
|
|
||||||
|
Run `prisma generate` and `prisma db seed` explicitly when you need refreshed client output or seed data after a reset.
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
Configure the seed script in `prisma.config.ts`, then run it explicitly after reset:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
export default defineConfig({
|
||||||
|
migrations: {
|
||||||
|
seed: 'tsx prisma/seed.ts',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
Typical workflow:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma migrate reset --force
|
||||||
|
prisma generate
|
||||||
|
prisma db seed
|
||||||
|
```
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
# prisma migrate resolve
|
||||||
|
|
||||||
|
Resolves issues with database migrations, such as failed migrations or baselining.
|
||||||
|
|
||||||
|
## Command
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma migrate resolve [options]
|
||||||
|
```
|
||||||
|
|
||||||
|
## What It Does
|
||||||
|
|
||||||
|
Updates the `_prisma_migrations` table to manually change the state of a migration. This is a recovery tool.
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
You must provide exactly one of `--applied` or `--rolled-back`.
|
||||||
|
|
||||||
|
| Option | Description |
|
||||||
|
|--------|-------------|
|
||||||
|
| `--applied <name>` | Mark a migration as **applied** (success) |
|
||||||
|
| `--rolled-back <name>` | Mark a migration as **rolled back** (ignored/failed) |
|
||||||
|
| `--schema` | Path to schema file |
|
||||||
|
| `--config` | Custom path to your Prisma config file |
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### Mark as Applied (Baselining)
|
||||||
|
|
||||||
|
If you have existing tables and want to initialize migrations without running the SQL:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma migrate resolve --applied 20240101000000_initial_migration
|
||||||
|
```
|
||||||
|
|
||||||
|
This tells Prisma "Assume this migration has already run".
|
||||||
|
|
||||||
|
### Mark as Rolled Back (Fixing Failures)
|
||||||
|
|
||||||
|
If a migration failed (e.g., syntax error) and you fixed the SQL or want to retry:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma migrate resolve --rolled-back 20240115120000_failed_migration
|
||||||
|
```
|
||||||
|
|
||||||
|
This tells Prisma "Forget this migration run, let me try applying it again".
|
||||||
|
|
||||||
|
## Use Cases
|
||||||
|
|
||||||
|
1. **Baselining**: Adopting Prisma Migrate on an existing production database.
|
||||||
|
2. **Failed Migrations**: Recovering from a failed `migrate deploy` in production.
|
||||||
|
3. **Hotfixes**: reconciling manual database changes (rare).
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- [Baselining](https://www.prisma.io/docs/guides/database/developing-with-prisma-migrate/baselining)
|
||||||
|
- [Troubleshooting](https://www.prisma.io/docs/guides/database/production-troubleshooting)
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
# prisma migrate status
|
||||||
|
|
||||||
|
Checks the status of your database migrations.
|
||||||
|
|
||||||
|
## Command
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma migrate status [options]
|
||||||
|
```
|
||||||
|
|
||||||
|
## What It Does
|
||||||
|
|
||||||
|
- Connects to the database
|
||||||
|
- Checks the `_prisma_migrations` table
|
||||||
|
- Compares applied migrations with local migration files
|
||||||
|
- Reports:
|
||||||
|
- **Status**: Database is up-to-date or behind
|
||||||
|
- **Unapplied migrations**: Count of pending migrations
|
||||||
|
- **Missing migrations**: Migrations present in DB but missing locally
|
||||||
|
- **Failed migrations**: Any migrations that failed to apply
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
| Option | Description |
|
||||||
|
|--------|-------------|
|
||||||
|
| `--schema` | Path to schema file |
|
||||||
|
| `--config` | Custom path to your Prisma config file |
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### Check status
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma migrate status
|
||||||
|
```
|
||||||
|
|
||||||
|
Output example (Up to date):
|
||||||
|
```
|
||||||
|
Database schema is up to date!
|
||||||
|
```
|
||||||
|
|
||||||
|
Output example (Pending):
|
||||||
|
```
|
||||||
|
Following migration have not yet been applied:
|
||||||
|
20240115120000_add_user
|
||||||
|
|
||||||
|
To apply migrations in development, run:
|
||||||
|
prisma migrate dev
|
||||||
|
|
||||||
|
To apply migrations in production, run:
|
||||||
|
prisma migrate deploy
|
||||||
|
```
|
||||||
|
|
||||||
|
## When to Use
|
||||||
|
|
||||||
|
- **Debugging**: Why is `migrate dev` complaining about drift?
|
||||||
|
- **CI/CD**: Verify database state before deploying
|
||||||
|
- **Production**: Check if migrations are needed (`migrate deploy`) or if a deployment failed
|
||||||
|
|
||||||
|
## Exit Codes
|
||||||
|
|
||||||
|
- `0`: Success (may have pending migrations, but command ran successfully)
|
||||||
|
- `1`: Error
|
||||||
|
|
||||||
|
To check for pending migrations programmatically, you might need to parse the output or use `migrate diff` with exit code flags.
|
||||||
@@ -0,0 +1,137 @@
|
|||||||
|
# prisma studio
|
||||||
|
|
||||||
|
Opens a visual database browser for viewing and editing data.
|
||||||
|
|
||||||
|
## Command
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma studio [options]
|
||||||
|
```
|
||||||
|
|
||||||
|
## What It Does
|
||||||
|
|
||||||
|
- Starts a web-based database GUI
|
||||||
|
- View all your models and records
|
||||||
|
- Create, update, and delete records
|
||||||
|
- Filter and sort data
|
||||||
|
- Navigate relations
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
| Option | Description | Default |
|
||||||
|
|--------|-------------|---------|
|
||||||
|
| `--port` / `-p` | Port to start Studio on | `5555` |
|
||||||
|
| `--browser` / `-b` | Browser to open Studio in | System default |
|
||||||
|
| `--config` | Custom path to your Prisma config file | - |
|
||||||
|
| `--url` | Database connection string (overrides the one in your Prisma config) | - |
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### Open Studio
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma studio
|
||||||
|
```
|
||||||
|
|
||||||
|
Opens at http://localhost:5555
|
||||||
|
|
||||||
|
### Custom port
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma studio --port 3000
|
||||||
|
```
|
||||||
|
|
||||||
|
### Specific browser
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma studio --browser firefox
|
||||||
|
```
|
||||||
|
|
||||||
|
### Don't open browser
|
||||||
|
|
||||||
|
```bash
|
||||||
|
BROWSER=none prisma studio
|
||||||
|
```
|
||||||
|
|
||||||
|
Useful for remote servers.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
### View Records
|
||||||
|
|
||||||
|
- See all records in table format
|
||||||
|
- Pagination for large datasets
|
||||||
|
- Column sorting
|
||||||
|
|
||||||
|
### Filter Data
|
||||||
|
|
||||||
|
- Filter by any field
|
||||||
|
- Multiple conditions
|
||||||
|
- Relation filtering
|
||||||
|
|
||||||
|
### Edit Records
|
||||||
|
|
||||||
|
- Click to edit inline
|
||||||
|
- Add new records
|
||||||
|
- Delete records (with confirmation)
|
||||||
|
|
||||||
|
### Navigate Relations
|
||||||
|
|
||||||
|
- Click relations to view related records
|
||||||
|
- See counts of related items
|
||||||
|
- Follow relation links
|
||||||
|
|
||||||
|
## Recent Studio Capabilities
|
||||||
|
|
||||||
|
Recent Prisma Studio releases added richer editor workflows:
|
||||||
|
|
||||||
|
- multi-cell selection and editing
|
||||||
|
- full-table search and more intuitive filtering
|
||||||
|
- command palette shortcuts
|
||||||
|
- dark mode
|
||||||
|
- copy selections as Markdown
|
||||||
|
- back-relation navigation
|
||||||
|
- SQL workflows including raw SQL queries
|
||||||
|
|
||||||
|
Some recent builds also expose AI-assisted SQL authoring. Treat these as interactive Studio features rather than a replacement for checked-in migrations or application queries.
|
||||||
|
|
||||||
|
## Use Cases
|
||||||
|
|
||||||
|
- **Development**: Quick data inspection
|
||||||
|
- **Debugging**: Check data state
|
||||||
|
- **Testing**: Verify seed data
|
||||||
|
- **Demo**: Show data to stakeholders
|
||||||
|
|
||||||
|
## Limitations
|
||||||
|
|
||||||
|
- Development tool only
|
||||||
|
- Not for production use
|
||||||
|
- Limited to configured database
|
||||||
|
- Prisma Studio in Prisma 7 currently targets PostgreSQL, MySQL, and SQLite first
|
||||||
|
- For reproducible application logic, prefer Prisma Client and checked-in SQL scripts
|
||||||
|
|
||||||
|
## Common Workflow
|
||||||
|
|
||||||
|
1. Run migrations:
|
||||||
|
```bash
|
||||||
|
prisma migrate dev
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Seed data:
|
||||||
|
```bash
|
||||||
|
prisma db seed
|
||||||
|
```
|
||||||
|
|
||||||
|
3. Open Studio to verify:
|
||||||
|
```bash
|
||||||
|
prisma studio
|
||||||
|
```
|
||||||
|
|
||||||
|
4. Make manual edits if needed
|
||||||
|
|
||||||
|
## Security Note
|
||||||
|
|
||||||
|
Studio provides direct database access. Only run on:
|
||||||
|
- Local development machines
|
||||||
|
- Secure internal networks
|
||||||
|
- Never expose publicly
|
||||||
@@ -0,0 +1,53 @@
|
|||||||
|
# prisma validate
|
||||||
|
|
||||||
|
Validates your Prisma schema file.
|
||||||
|
|
||||||
|
## Command
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma validate [options]
|
||||||
|
```
|
||||||
|
|
||||||
|
## What It Does
|
||||||
|
|
||||||
|
- Parses the `schema.prisma` file
|
||||||
|
- Checks for syntax errors
|
||||||
|
- Validates model definitions, relations, and types
|
||||||
|
- Reports any errors or warnings without generating code
|
||||||
|
|
||||||
|
## Options
|
||||||
|
|
||||||
|
| Option | Description |
|
||||||
|
|--------|-------------|
|
||||||
|
| `--schema` | Path to schema file |
|
||||||
|
| `--config` | Custom path to your Prisma config file |
|
||||||
|
|
||||||
|
## Examples
|
||||||
|
|
||||||
|
### Validate default schema
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma validate
|
||||||
|
```
|
||||||
|
|
||||||
|
### Validate specific schema
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma validate --schema=./custom/schema.prisma
|
||||||
|
```
|
||||||
|
|
||||||
|
### Use in CI
|
||||||
|
|
||||||
|
Run `validate` in your CI pipeline to catch schema errors early:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: Validate Schema
|
||||||
|
run: npx prisma validate
|
||||||
|
```
|
||||||
|
|
||||||
|
## Common Errors
|
||||||
|
|
||||||
|
- Missing `@relation` fields
|
||||||
|
- Invalid types
|
||||||
|
- Duplicate model names
|
||||||
|
- Syntax errors (missing braces, etc.)
|
||||||
@@ -0,0 +1,216 @@
|
|||||||
|
---
|
||||||
|
name: prisma-client-api
|
||||||
|
description: Prisma Client API reference covering model queries, filters, operators, and client methods. Use when writing database queries, using CRUD operations, filtering data, or configuring Prisma Client. Triggers on "prisma query", "findMany", "create", "update", "delete", "$transaction".
|
||||||
|
license: MIT
|
||||||
|
metadata:
|
||||||
|
author: prisma
|
||||||
|
version: "7.9.1"
|
||||||
|
---
|
||||||
|
|
||||||
|
# Prisma Client API Reference
|
||||||
|
|
||||||
|
Complete API reference for Prisma Client. This skill provides guidance on model queries, filtering, relations, and client methods for current Prisma projects.
|
||||||
|
|
||||||
|
## When to Apply
|
||||||
|
|
||||||
|
Reference this skill when:
|
||||||
|
- Writing database queries with Prisma Client
|
||||||
|
- Performing CRUD operations (create, read, update, delete)
|
||||||
|
- Filtering and sorting data
|
||||||
|
- Working with relations
|
||||||
|
- Using transactions
|
||||||
|
- Configuring client options
|
||||||
|
|
||||||
|
## Rule Categories by Priority
|
||||||
|
|
||||||
|
| Priority | Category | Impact | Prefix |
|
||||||
|
|----------|----------|--------|--------|
|
||||||
|
| 1 | Client Construction | HIGH | `constructor` |
|
||||||
|
| 2 | Model Queries | CRITICAL | `model-queries` |
|
||||||
|
| 3 | Query Shape | HIGH | `query-options` |
|
||||||
|
| 4 | Filtering | HIGH | `filters` |
|
||||||
|
| 5 | Relations | HIGH | `relations` |
|
||||||
|
| 6 | Transactions | CRITICAL | `transactions` |
|
||||||
|
| 7 | Raw SQL | CRITICAL | `raw-queries` |
|
||||||
|
| 8 | Client Methods | MEDIUM | `client-methods` |
|
||||||
|
|
||||||
|
## Quick Reference
|
||||||
|
|
||||||
|
- `constructor` - `PrismaClient` setup, adapter wiring, logging, and SQL commenter plugins
|
||||||
|
- `model-queries` - CRUD operations and bulk operations
|
||||||
|
- `query-options` - `select`, `include`, `omit`, sort, pagination
|
||||||
|
- `filters` - scalar and logical filter operators
|
||||||
|
- `relations` - relation reads and nested writes
|
||||||
|
- `transactions` - array and interactive transaction patterns
|
||||||
|
- `raw-queries` - `$queryRaw` and `$executeRaw` safety
|
||||||
|
- `client-methods` - lifecycle methods, extensions, and `satisfies` patterns for `prisma-client`
|
||||||
|
|
||||||
|
## Client Instantiation
|
||||||
|
|
||||||
|
```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 })
|
||||||
|
```
|
||||||
|
|
||||||
|
## Model Query Methods
|
||||||
|
|
||||||
|
| Method | Description |
|
||||||
|
|--------|-------------|
|
||||||
|
| `findUnique()` | Find one record by unique field |
|
||||||
|
| `findUniqueOrThrow()` | Find one or throw error |
|
||||||
|
| `findFirst()` | Find first matching record |
|
||||||
|
| `findFirstOrThrow()` | Find first or throw error |
|
||||||
|
| `findMany()` | Find multiple records |
|
||||||
|
| `create()` | Create a new record |
|
||||||
|
| `createMany()` | Create multiple records |
|
||||||
|
| `createManyAndReturn()` | Create multiple and return them |
|
||||||
|
| `update()` | Update one record |
|
||||||
|
| `updateMany()` | Update multiple records |
|
||||||
|
| `updateManyAndReturn()` | Update multiple and return them |
|
||||||
|
| `upsert()` | Update or create record |
|
||||||
|
| `delete()` | Delete one record |
|
||||||
|
| `deleteMany()` | Delete multiple records |
|
||||||
|
| `count()` | Count matching records |
|
||||||
|
| `aggregate()` | Aggregate values (sum, avg, etc.) |
|
||||||
|
| `groupBy()` | Group and aggregate |
|
||||||
|
|
||||||
|
## Query Options
|
||||||
|
|
||||||
|
| Option | Description |
|
||||||
|
|--------|-------------|
|
||||||
|
| `where` | Filter conditions |
|
||||||
|
| `select` | Fields to include |
|
||||||
|
| `include` | Relations to load |
|
||||||
|
| `omit` | Fields to exclude |
|
||||||
|
| `orderBy` | Sort order |
|
||||||
|
| `take` | Limit results |
|
||||||
|
| `skip` | Skip results (pagination) |
|
||||||
|
| `cursor` | Cursor-based pagination |
|
||||||
|
| `distinct` | Unique values only |
|
||||||
|
|
||||||
|
## Client Methods
|
||||||
|
|
||||||
|
| Method | Description |
|
||||||
|
|--------|-------------|
|
||||||
|
| `$connect()` | Explicitly connect to database |
|
||||||
|
| `$disconnect()` | Disconnect from database |
|
||||||
|
| `$transaction()` | Execute transaction |
|
||||||
|
| `$queryRaw()` | Execute raw SQL query |
|
||||||
|
| `$executeRaw()` | Execute raw SQL command |
|
||||||
|
| `$on()` | Subscribe to events |
|
||||||
|
| `$extends()` | Add extensions |
|
||||||
|
|
||||||
|
## Quick Examples
|
||||||
|
|
||||||
|
### Find records
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Find by unique field
|
||||||
|
const user = await prisma.user.findUnique({
|
||||||
|
where: { email: 'alice@prisma.io' }
|
||||||
|
})
|
||||||
|
|
||||||
|
// Find with filter
|
||||||
|
const users = await prisma.user.findMany({
|
||||||
|
where: { role: 'ADMIN' },
|
||||||
|
orderBy: { createdAt: 'desc' },
|
||||||
|
take: 10
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Create records
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const user = await prisma.user.create({
|
||||||
|
data: {
|
||||||
|
email: 'alice@prisma.io',
|
||||||
|
name: 'Alice',
|
||||||
|
posts: {
|
||||||
|
create: { title: 'Hello World' }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
include: { posts: true }
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Update records
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const user = await prisma.user.update({
|
||||||
|
where: { id: 1 },
|
||||||
|
data: { name: 'Alice Smith' }
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Delete records
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
await prisma.user.delete({
|
||||||
|
where: { id: 1 }
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Transactions
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const [user, post] = await prisma.$transaction([
|
||||||
|
prisma.user.create({ data: { email: 'alice@prisma.io' } }),
|
||||||
|
prisma.post.create({ data: { title: 'Hello', authorId: 1 } })
|
||||||
|
])
|
||||||
|
```
|
||||||
|
|
||||||
|
## Rule Files
|
||||||
|
|
||||||
|
Detailed API documentation:
|
||||||
|
|
||||||
|
```
|
||||||
|
references/constructor.md - PrismaClient constructor options
|
||||||
|
references/model-queries.md - CRUD operations
|
||||||
|
references/query-options.md - select, include, omit, where, orderBy
|
||||||
|
references/filters.md - Filter conditions and operators
|
||||||
|
references/relations.md - Relation queries and nested operations
|
||||||
|
references/transactions.md - Transaction API
|
||||||
|
references/raw-queries.md - $queryRaw, $executeRaw
|
||||||
|
references/client-methods.md - $connect, $disconnect, $on, $extends
|
||||||
|
```
|
||||||
|
|
||||||
|
## Filter Operators
|
||||||
|
|
||||||
|
| Operator | Description |
|
||||||
|
|----------|-------------|
|
||||||
|
| `equals` | Exact match |
|
||||||
|
| `not` | Not equal |
|
||||||
|
| `in` | In array |
|
||||||
|
| `notIn` | Not in array |
|
||||||
|
| `lt`, `lte` | Less than |
|
||||||
|
| `gt`, `gte` | Greater than |
|
||||||
|
| `contains` | String contains |
|
||||||
|
| `startsWith` | String starts with |
|
||||||
|
| `endsWith` | String ends with |
|
||||||
|
| `mode` | Case sensitivity |
|
||||||
|
|
||||||
|
## Relation Filters
|
||||||
|
|
||||||
|
| Operator | Description |
|
||||||
|
|----------|-------------|
|
||||||
|
| `some` | At least one related record matches |
|
||||||
|
| `every` | All related records match |
|
||||||
|
| `none` | No related records match |
|
||||||
|
| `is` | Related record matches (1-to-1) |
|
||||||
|
| `isNot` | Related record doesn't match |
|
||||||
|
|
||||||
|
## Resources
|
||||||
|
|
||||||
|
- [Prisma Client API Reference](https://www.prisma.io/docs/orm/reference/prisma-client-reference)
|
||||||
|
- [CRUD Operations](https://www.prisma.io/docs/orm/prisma-client/queries/crud)
|
||||||
|
- [Filtering and Sorting](https://www.prisma.io/docs/orm/prisma-client/queries/filtering-and-sorting)
|
||||||
|
|
||||||
|
## How to Use
|
||||||
|
|
||||||
|
Pick the category from the table above, then open the matching reference file for implementation details and examples.
|
||||||
@@ -0,0 +1,223 @@
|
|||||||
|
# Client Methods
|
||||||
|
|
||||||
|
Prisma Client instance methods.
|
||||||
|
|
||||||
|
## $connect()
|
||||||
|
|
||||||
|
Explicitly connect to the database:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const prisma = new PrismaClient({ adapter })
|
||||||
|
|
||||||
|
// Explicit connection
|
||||||
|
await prisma.$connect()
|
||||||
|
```
|
||||||
|
|
||||||
|
### When to use
|
||||||
|
|
||||||
|
Usually not needed - Prisma connects automatically on first query. Use for:
|
||||||
|
- Fail fast on startup
|
||||||
|
- Health checks
|
||||||
|
- Pre-warming connections
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
async function main() {
|
||||||
|
try {
|
||||||
|
await prisma.$connect()
|
||||||
|
console.log('Database connected')
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Failed to connect:', e)
|
||||||
|
process.exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## $disconnect()
|
||||||
|
|
||||||
|
Close database connection:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
await prisma.$disconnect()
|
||||||
|
```
|
||||||
|
|
||||||
|
### Graceful shutdown
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
process.on('beforeExit', async () => {
|
||||||
|
await prisma.$disconnect()
|
||||||
|
})
|
||||||
|
|
||||||
|
// Or with SIGTERM
|
||||||
|
process.on('SIGTERM', async () => {
|
||||||
|
await prisma.$disconnect()
|
||||||
|
process.exit(0)
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### In tests
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
afterAll(async () => {
|
||||||
|
await prisma.$disconnect()
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## $on()
|
||||||
|
|
||||||
|
Subscribe to events:
|
||||||
|
|
||||||
|
### Query events
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const prisma = new PrismaClient({
|
||||||
|
adapter,
|
||||||
|
log: [{ level: 'query', emit: 'event' }]
|
||||||
|
})
|
||||||
|
|
||||||
|
prisma.$on('query', (e) => {
|
||||||
|
console.log('Query:', e.query)
|
||||||
|
console.log('Params:', e.params)
|
||||||
|
console.log('Duration:', e.duration, 'ms')
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Log events
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const prisma = new PrismaClient({
|
||||||
|
adapter,
|
||||||
|
log: [
|
||||||
|
{ level: 'info', emit: 'event' },
|
||||||
|
{ level: 'warn', emit: 'event' },
|
||||||
|
{ level: 'error', emit: 'event' }
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
|
prisma.$on('info', (e) => console.log(e.message))
|
||||||
|
prisma.$on('warn', (e) => console.warn(e.message))
|
||||||
|
prisma.$on('error', (e) => console.error(e.message))
|
||||||
|
```
|
||||||
|
|
||||||
|
## $extends()
|
||||||
|
|
||||||
|
Add extensions for custom behavior:
|
||||||
|
|
||||||
|
### Add custom methods
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const prisma = new PrismaClient({ adapter }).$extends({
|
||||||
|
client: {
|
||||||
|
$log: (message: string) => console.log(message)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
prisma.$log('Hello!')
|
||||||
|
```
|
||||||
|
|
||||||
|
### Add model methods
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const prisma = new PrismaClient({ adapter }).$extends({
|
||||||
|
model: {
|
||||||
|
user: {
|
||||||
|
async findByEmail(email: string) {
|
||||||
|
return prisma.user.findUnique({ where: { email } })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const user = await prisma.user.findByEmail('alice@prisma.io')
|
||||||
|
```
|
||||||
|
|
||||||
|
### Query extensions
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const prisma = new PrismaClient({ adapter }).$extends({
|
||||||
|
query: {
|
||||||
|
user: {
|
||||||
|
async findMany({ args, query }) {
|
||||||
|
// Add default filter
|
||||||
|
args.where = { ...args.where, deletedAt: null }
|
||||||
|
return query(args)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Result extensions
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const prisma = new PrismaClient({ adapter }).$extends({
|
||||||
|
result: {
|
||||||
|
user: {
|
||||||
|
fullName: {
|
||||||
|
needs: { firstName: true, lastName: true },
|
||||||
|
compute(user) {
|
||||||
|
return `${user.firstName} ${user.lastName}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const user = await prisma.user.findFirst()
|
||||||
|
console.log(user.fullName) // Computed field
|
||||||
|
```
|
||||||
|
|
||||||
|
### Chain extensions
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const prisma = new PrismaClient({ adapter })
|
||||||
|
.$extends(loggingExtension)
|
||||||
|
.$extends(softDeleteExtension)
|
||||||
|
.$extends(computedFieldsExtension)
|
||||||
|
```
|
||||||
|
|
||||||
|
## $transaction()
|
||||||
|
|
||||||
|
See `transactions.md` for details.
|
||||||
|
|
||||||
|
## $queryRaw() / $executeRaw()
|
||||||
|
|
||||||
|
See `raw-queries.md` for details.
|
||||||
|
|
||||||
|
## Type utilities
|
||||||
|
|
||||||
|
### Prisma namespace
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { Prisma } from '../generated/client'
|
||||||
|
|
||||||
|
// Input types
|
||||||
|
type UserCreateInput = Prisma.UserCreateInput
|
||||||
|
type UserWhereInput = Prisma.UserWhereInput
|
||||||
|
|
||||||
|
// Output types
|
||||||
|
type User = Prisma.UserGetPayload<{}>
|
||||||
|
type UserWithPosts = Prisma.UserGetPayload<{
|
||||||
|
include: { posts: true }
|
||||||
|
}>
|
||||||
|
```
|
||||||
|
|
||||||
|
### Type-safe query fragments with satisfies
|
||||||
|
|
||||||
|
Type-safe query fragments:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { Prisma } from '../generated/client'
|
||||||
|
|
||||||
|
const userSelect = {
|
||||||
|
id: true,
|
||||||
|
email: true,
|
||||||
|
name: true
|
||||||
|
} satisfies Prisma.UserSelect
|
||||||
|
|
||||||
|
const user = await prisma.user.findUnique({
|
||||||
|
where: { id: 1 },
|
||||||
|
select: userSelect
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
With the `prisma-client` generator, use TypeScript `satisfies` for typed query fragments. You may still see older examples that use `Prisma.validator()` with `prisma-client-js`.
|
||||||
@@ -0,0 +1,221 @@
|
|||||||
|
# PrismaClient Constructor
|
||||||
|
|
||||||
|
Configure Prisma Client when instantiating.
|
||||||
|
|
||||||
|
## Basic Instantiation
|
||||||
|
|
||||||
|
```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 })
|
||||||
|
```
|
||||||
|
|
||||||
|
## Constructor Options
|
||||||
|
|
||||||
|
### adapter (Required for the SQL provider workflow)
|
||||||
|
|
||||||
|
Driver adapter instance:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { PrismaPg } from '@prisma/adapter-pg'
|
||||||
|
|
||||||
|
const adapter = new PrismaPg({
|
||||||
|
connectionString: process.env.DATABASE_URL
|
||||||
|
})
|
||||||
|
|
||||||
|
const prisma = new PrismaClient({ adapter })
|
||||||
|
```
|
||||||
|
|
||||||
|
### accelerateUrl (For Accelerate users)
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { withAccelerate } from '@prisma/extension-accelerate'
|
||||||
|
|
||||||
|
const prisma = new PrismaClient({
|
||||||
|
accelerateUrl: process.env.DATABASE_URL, // prisma:// URL
|
||||||
|
}).$extends(withAccelerate())
|
||||||
|
```
|
||||||
|
|
||||||
|
### log
|
||||||
|
|
||||||
|
Configure logging:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const prisma = new PrismaClient({
|
||||||
|
adapter,
|
||||||
|
log: ['query', 'info', 'warn', 'error'],
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Log levels
|
||||||
|
|
||||||
|
| Level | Description |
|
||||||
|
|-------|-------------|
|
||||||
|
| `query` | All SQL queries |
|
||||||
|
| `info` | Informational messages |
|
||||||
|
| `warn` | Warnings |
|
||||||
|
| `error` | Errors |
|
||||||
|
|
||||||
|
#### Log to events
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const prisma = new PrismaClient({
|
||||||
|
adapter,
|
||||||
|
log: [
|
||||||
|
{ level: 'query', emit: 'event' },
|
||||||
|
{ level: 'error', emit: 'stdout' },
|
||||||
|
],
|
||||||
|
})
|
||||||
|
|
||||||
|
prisma.$on('query', (e) => {
|
||||||
|
console.log('Query:', e.query)
|
||||||
|
console.log('Duration:', e.duration, 'ms')
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### errorFormat
|
||||||
|
|
||||||
|
Control error formatting:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const prisma = new PrismaClient({
|
||||||
|
adapter,
|
||||||
|
errorFormat: 'pretty', // 'pretty' | 'colorless' | 'minimal'
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### comments
|
||||||
|
|
||||||
|
Attach SQL commenter plugins for observability, tracing, or query insights:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { PrismaClient } from '../generated/client'
|
||||||
|
import { PrismaPg } from '@prisma/adapter-pg'
|
||||||
|
import { prismaQueryInsights } from '@prisma/sqlcommenter-query-insights'
|
||||||
|
import { queryTags, withQueryTags } from '@prisma/sqlcommenter-query-tags'
|
||||||
|
import { traceContext } from '@prisma/sqlcommenter-trace-context'
|
||||||
|
|
||||||
|
const prisma = new PrismaClient({
|
||||||
|
adapter: new PrismaPg(process.env.DATABASE_URL!),
|
||||||
|
comments: [prismaQueryInsights(), traceContext(), queryTags()],
|
||||||
|
})
|
||||||
|
|
||||||
|
await withQueryTags({ route: '/api/users', requestId: 'req-123' }, () =>
|
||||||
|
prisma.user.findMany(),
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
Use `comments` only for SQL providers. This is the clean way to add trace or query-shape metadata without changing your query calls.
|
||||||
|
|
||||||
|
### transactionOptions
|
||||||
|
|
||||||
|
Default transaction settings:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const prisma = new PrismaClient({
|
||||||
|
adapter,
|
||||||
|
transactionOptions: {
|
||||||
|
maxWait: 5000, // Max wait to acquire transaction (ms)
|
||||||
|
timeout: 10000, // Max transaction duration (ms)
|
||||||
|
isolationLevel: 'Serializable',
|
||||||
|
},
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### queryPlanCacheMaxSize
|
||||||
|
|
||||||
|
Use `queryPlanCacheMaxSize` to limit the in-memory query-plan cache:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const prisma = new PrismaClient({
|
||||||
|
adapter,
|
||||||
|
queryPlanCacheMaxSize: 2_000,
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
The value must be a non-negative integer. Set it to `0` to disable query-plan caching; omit it to use Prisma's default. Treat this as a process-local memory/performance control, not a database prepared-statement setting.
|
||||||
|
|
||||||
|
## Singleton Pattern
|
||||||
|
|
||||||
|
Prevent multiple client instances in development:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// lib/prisma.ts
|
||||||
|
import { PrismaClient } from '../generated/client'
|
||||||
|
import { PrismaPg } from '@prisma/adapter-pg'
|
||||||
|
|
||||||
|
const globalForPrisma = globalThis as unknown as {
|
||||||
|
prisma: PrismaClient | undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
function createPrismaClient() {
|
||||||
|
const adapter = new PrismaPg({
|
||||||
|
connectionString: process.env.DATABASE_URL!
|
||||||
|
})
|
||||||
|
return new PrismaClient({ adapter })
|
||||||
|
}
|
||||||
|
|
||||||
|
export const prisma = globalForPrisma.prisma ?? createPrismaClient()
|
||||||
|
|
||||||
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
|
globalForPrisma.prisma = prisma
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Next.js Pattern
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// lib/prisma.ts
|
||||||
|
import { PrismaClient } from '@/generated/client'
|
||||||
|
import { PrismaPg } from '@prisma/adapter-pg'
|
||||||
|
|
||||||
|
const createAdapter = () => new PrismaPg({
|
||||||
|
connectionString: process.env.DATABASE_URL!
|
||||||
|
})
|
||||||
|
|
||||||
|
const prismaClientSingleton = () => {
|
||||||
|
return new PrismaClient({ adapter: createAdapter() })
|
||||||
|
}
|
||||||
|
|
||||||
|
declare const globalThis: {
|
||||||
|
prismaGlobal: ReturnType<typeof prismaClientSingleton>
|
||||||
|
} & typeof global
|
||||||
|
|
||||||
|
const prisma = globalThis.prismaGlobal ?? prismaClientSingleton()
|
||||||
|
|
||||||
|
export default prisma
|
||||||
|
|
||||||
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
|
globalThis.prismaGlobal = prisma
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Query Events
|
||||||
|
|
||||||
|
Listen to query events:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const prisma = new PrismaClient({
|
||||||
|
adapter,
|
||||||
|
log: [{ level: 'query', emit: 'event' }],
|
||||||
|
})
|
||||||
|
|
||||||
|
prisma.$on('query', (e) => {
|
||||||
|
console.log('Query:', e.query)
|
||||||
|
console.log('Params:', e.params)
|
||||||
|
console.log('Duration:', e.duration)
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## Log Events
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
prisma.$on('info', (e) => console.log(e.message))
|
||||||
|
prisma.$on('warn', (e) => console.warn(e.message))
|
||||||
|
prisma.$on('error', (e) => console.error(e.message))
|
||||||
|
```
|
||||||
@@ -0,0 +1,256 @@
|
|||||||
|
# Filter Conditions and Operators
|
||||||
|
|
||||||
|
Filter operators for the `where` clause.
|
||||||
|
|
||||||
|
## Equality
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Exact match (implicit)
|
||||||
|
where: { email: 'alice@prisma.io' }
|
||||||
|
|
||||||
|
// Explicit equals
|
||||||
|
where: { email: { equals: 'alice@prisma.io' } }
|
||||||
|
|
||||||
|
// Not equal
|
||||||
|
where: { email: { not: 'alice@prisma.io' } }
|
||||||
|
```
|
||||||
|
|
||||||
|
## Comparison
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Greater than
|
||||||
|
where: { age: { gt: 18 } }
|
||||||
|
|
||||||
|
// Greater than or equal
|
||||||
|
where: { age: { gte: 18 } }
|
||||||
|
|
||||||
|
// Less than
|
||||||
|
where: { age: { lt: 65 } }
|
||||||
|
|
||||||
|
// Less than or equal
|
||||||
|
where: { age: { lte: 65 } }
|
||||||
|
|
||||||
|
// Combined
|
||||||
|
where: { age: { gte: 18, lte: 65 } }
|
||||||
|
```
|
||||||
|
|
||||||
|
## Lists
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// In array
|
||||||
|
where: { role: { in: ['ADMIN', 'MODERATOR'] } }
|
||||||
|
|
||||||
|
// Not in array
|
||||||
|
where: { role: { notIn: ['GUEST', 'BANNED'] } }
|
||||||
|
```
|
||||||
|
|
||||||
|
## String Filters
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Contains
|
||||||
|
where: { email: { contains: 'prisma' } }
|
||||||
|
|
||||||
|
// Starts with
|
||||||
|
where: { email: { startsWith: 'alice' } }
|
||||||
|
|
||||||
|
// Ends with
|
||||||
|
where: { email: { endsWith: '@prisma.io' } }
|
||||||
|
|
||||||
|
// Case-insensitive (default for some databases)
|
||||||
|
where: {
|
||||||
|
email: {
|
||||||
|
contains: 'PRISMA',
|
||||||
|
mode: 'insensitive'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Null Checks
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Is null
|
||||||
|
where: { deletedAt: null }
|
||||||
|
|
||||||
|
// Is not null
|
||||||
|
where: { deletedAt: { not: null } }
|
||||||
|
|
||||||
|
// Using isSet (for optional fields)
|
||||||
|
where: { middleName: { isSet: true } }
|
||||||
|
```
|
||||||
|
|
||||||
|
## Logical Operators
|
||||||
|
|
||||||
|
### AND (implicit)
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Multiple conditions = AND
|
||||||
|
where: {
|
||||||
|
email: { contains: '@prisma.io' },
|
||||||
|
role: 'ADMIN'
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### AND (explicit)
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
where: {
|
||||||
|
AND: [
|
||||||
|
{ email: { contains: '@prisma.io' } },
|
||||||
|
{ role: 'ADMIN' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### OR
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
where: {
|
||||||
|
OR: [
|
||||||
|
{ email: { contains: '@gmail.com' } },
|
||||||
|
{ email: { contains: '@prisma.io' } }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### NOT
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
where: {
|
||||||
|
NOT: {
|
||||||
|
role: 'GUEST'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Multiple NOT conditions
|
||||||
|
where: {
|
||||||
|
NOT: [
|
||||||
|
{ role: 'GUEST' },
|
||||||
|
{ verified: false }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Combined
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
where: {
|
||||||
|
AND: [
|
||||||
|
{ verified: true },
|
||||||
|
{
|
||||||
|
OR: [
|
||||||
|
{ role: 'ADMIN' },
|
||||||
|
{ role: 'MODERATOR' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
NOT: { deletedAt: { not: null } }
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Relation Filters
|
||||||
|
|
||||||
|
### some
|
||||||
|
|
||||||
|
At least one related record matches:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Users with at least one published post
|
||||||
|
where: {
|
||||||
|
posts: {
|
||||||
|
some: { published: true }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### every
|
||||||
|
|
||||||
|
All related records match:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Users where all posts are published
|
||||||
|
where: {
|
||||||
|
posts: {
|
||||||
|
every: { published: true }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### none
|
||||||
|
|
||||||
|
No related records match:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Users with no published posts
|
||||||
|
where: {
|
||||||
|
posts: {
|
||||||
|
none: { published: true }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### is / isNot (1-to-1)
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Users with profile in specific country
|
||||||
|
where: {
|
||||||
|
profile: {
|
||||||
|
is: { country: 'USA' }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Users without profile
|
||||||
|
where: {
|
||||||
|
profile: {
|
||||||
|
isNot: null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Array Field Filters
|
||||||
|
|
||||||
|
For fields like `String[]`:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Has element
|
||||||
|
where: { tags: { has: 'typescript' } }
|
||||||
|
|
||||||
|
// Has some elements
|
||||||
|
where: { tags: { hasSome: ['typescript', 'javascript'] } }
|
||||||
|
|
||||||
|
// Has every element
|
||||||
|
where: { tags: { hasEvery: ['typescript', 'prisma'] } }
|
||||||
|
|
||||||
|
// Is empty
|
||||||
|
where: { tags: { isEmpty: true } }
|
||||||
|
```
|
||||||
|
|
||||||
|
## JSON Filters
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Path-based filter
|
||||||
|
where: {
|
||||||
|
metadata: {
|
||||||
|
path: ['settings', 'theme'],
|
||||||
|
equals: 'dark'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// String contains in JSON
|
||||||
|
where: {
|
||||||
|
metadata: {
|
||||||
|
path: ['bio'],
|
||||||
|
string_contains: 'developer'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Full-Text Search
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Requires @@fulltext index
|
||||||
|
where: {
|
||||||
|
content: {
|
||||||
|
search: 'prisma database'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
@@ -0,0 +1,281 @@
|
|||||||
|
# Model Queries
|
||||||
|
|
||||||
|
CRUD operations for your Prisma models.
|
||||||
|
|
||||||
|
## Read Operations
|
||||||
|
|
||||||
|
### findUnique
|
||||||
|
|
||||||
|
Find a single record by unique field:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const user = await prisma.user.findUnique({
|
||||||
|
where: { id: 1 }
|
||||||
|
})
|
||||||
|
|
||||||
|
const user = await prisma.user.findUnique({
|
||||||
|
where: { email: 'alice@prisma.io' }
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
#### With composite unique key
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Model with @@unique([firstName, lastName])
|
||||||
|
const user = await prisma.user.findUnique({
|
||||||
|
where: {
|
||||||
|
firstName_lastName: {
|
||||||
|
firstName: 'Alice',
|
||||||
|
lastName: 'Smith'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### findUniqueOrThrow
|
||||||
|
|
||||||
|
Same as findUnique but throws if not found:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const user = await prisma.user.findUniqueOrThrow({
|
||||||
|
where: { id: 1 }
|
||||||
|
})
|
||||||
|
// Throws PrismaClientKnownRequestError if not found
|
||||||
|
```
|
||||||
|
|
||||||
|
### findFirst
|
||||||
|
|
||||||
|
Find first matching record:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const user = await prisma.user.findFirst({
|
||||||
|
where: { role: 'ADMIN' },
|
||||||
|
orderBy: { createdAt: 'desc' }
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### findFirstOrThrow
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const user = await prisma.user.findFirstOrThrow({
|
||||||
|
where: { role: 'ADMIN' }
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### findMany
|
||||||
|
|
||||||
|
Find multiple records:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const users = await prisma.user.findMany({
|
||||||
|
where: { role: 'USER' },
|
||||||
|
orderBy: { name: 'asc' },
|
||||||
|
take: 10,
|
||||||
|
skip: 0
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## Create Operations
|
||||||
|
|
||||||
|
### create
|
||||||
|
|
||||||
|
Create a single record:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const user = await prisma.user.create({
|
||||||
|
data: {
|
||||||
|
email: 'alice@prisma.io',
|
||||||
|
name: 'Alice'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
#### With relations
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const user = await prisma.user.create({
|
||||||
|
data: {
|
||||||
|
email: 'alice@prisma.io',
|
||||||
|
posts: {
|
||||||
|
create: [
|
||||||
|
{ title: 'First Post' },
|
||||||
|
{ title: 'Second Post' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
include: { posts: true }
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### createMany
|
||||||
|
|
||||||
|
Create multiple records:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const result = await prisma.user.createMany({
|
||||||
|
data: [
|
||||||
|
{ email: 'alice@prisma.io', name: 'Alice' },
|
||||||
|
{ email: 'bob@prisma.io', name: 'Bob' }
|
||||||
|
],
|
||||||
|
skipDuplicates: true // Skip records with duplicate unique fields
|
||||||
|
})
|
||||||
|
// Returns { count: 2 }
|
||||||
|
```
|
||||||
|
|
||||||
|
### createManyAndReturn
|
||||||
|
|
||||||
|
Create multiple and return them:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const users = await prisma.user.createManyAndReturn({
|
||||||
|
data: [
|
||||||
|
{ email: 'alice@prisma.io', name: 'Alice' },
|
||||||
|
{ email: 'bob@prisma.io', name: 'Bob' }
|
||||||
|
]
|
||||||
|
})
|
||||||
|
// Returns array of created users
|
||||||
|
```
|
||||||
|
|
||||||
|
## Update Operations
|
||||||
|
|
||||||
|
### update
|
||||||
|
|
||||||
|
Update a single record:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const user = await prisma.user.update({
|
||||||
|
where: { id: 1 },
|
||||||
|
data: { name: 'Alice Smith' }
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Atomic operations
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const post = await prisma.post.update({
|
||||||
|
where: { id: 1 },
|
||||||
|
data: {
|
||||||
|
views: { increment: 1 },
|
||||||
|
likes: { decrement: 1 },
|
||||||
|
score: { multiply: 2 },
|
||||||
|
rating: { divide: 2 },
|
||||||
|
version: { set: 5 }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### updateMany
|
||||||
|
|
||||||
|
Update multiple records:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const result = await prisma.user.updateMany({
|
||||||
|
where: { role: 'USER' },
|
||||||
|
data: { verified: true }
|
||||||
|
})
|
||||||
|
// Returns { count: 42 }
|
||||||
|
```
|
||||||
|
|
||||||
|
### updateManyAndReturn
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const users = await prisma.user.updateManyAndReturn({
|
||||||
|
where: { role: 'USER' },
|
||||||
|
data: { verified: true }
|
||||||
|
})
|
||||||
|
// Returns array of updated users
|
||||||
|
```
|
||||||
|
|
||||||
|
### upsert
|
||||||
|
|
||||||
|
Update or create:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const user = await prisma.user.upsert({
|
||||||
|
where: { email: 'alice@prisma.io' },
|
||||||
|
update: { name: 'Alice Smith' },
|
||||||
|
create: { email: 'alice@prisma.io', name: 'Alice' }
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## Delete Operations
|
||||||
|
|
||||||
|
### delete
|
||||||
|
|
||||||
|
Delete a single record:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const user = await prisma.user.delete({
|
||||||
|
where: { id: 1 }
|
||||||
|
})
|
||||||
|
// Returns deleted record
|
||||||
|
```
|
||||||
|
|
||||||
|
### deleteMany
|
||||||
|
|
||||||
|
Delete multiple records:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const result = await prisma.user.deleteMany({
|
||||||
|
where: { role: 'GUEST' }
|
||||||
|
})
|
||||||
|
// Returns { count: 5 }
|
||||||
|
|
||||||
|
// Delete all
|
||||||
|
const result = await prisma.user.deleteMany({})
|
||||||
|
```
|
||||||
|
|
||||||
|
## Aggregation Operations
|
||||||
|
|
||||||
|
### count
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const count = await prisma.user.count({
|
||||||
|
where: { role: 'ADMIN' }
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### aggregate
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const result = await prisma.post.aggregate({
|
||||||
|
_avg: { views: true },
|
||||||
|
_sum: { views: true },
|
||||||
|
_min: { views: true },
|
||||||
|
_max: { views: true },
|
||||||
|
_count: { _all: true }
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### groupBy
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const groups = await prisma.user.groupBy({
|
||||||
|
by: ['country'],
|
||||||
|
_count: { _all: true },
|
||||||
|
_avg: { age: true },
|
||||||
|
having: {
|
||||||
|
age: { _avg: { gt: 30 } }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## Return Types
|
||||||
|
|
||||||
|
| Method | Returns |
|
||||||
|
|--------|---------|
|
||||||
|
| `findUnique` | Record \| null |
|
||||||
|
| `findUniqueOrThrow` | Record (throws if not found) |
|
||||||
|
| `findFirst` | Record \| null |
|
||||||
|
| `findFirstOrThrow` | Record (throws if not found) |
|
||||||
|
| `findMany` | Record[] |
|
||||||
|
| `create` | Record |
|
||||||
|
| `createMany` | { count: number } |
|
||||||
|
| `createManyAndReturn` | Record[] |
|
||||||
|
| `update` | Record |
|
||||||
|
| `updateMany` | { count: number } |
|
||||||
|
| `delete` | Record |
|
||||||
|
| `deleteMany` | { count: number } |
|
||||||
|
| `count` | number |
|
||||||
|
| `aggregate` | Aggregate result |
|
||||||
|
| `groupBy` | Group result[] |
|
||||||
@@ -0,0 +1,276 @@
|
|||||||
|
# Query Options
|
||||||
|
|
||||||
|
Options for controlling query behavior.
|
||||||
|
|
||||||
|
## select
|
||||||
|
|
||||||
|
Choose specific fields to return:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const user = await prisma.user.findUnique({
|
||||||
|
where: { id: 1 },
|
||||||
|
select: {
|
||||||
|
id: true,
|
||||||
|
name: true,
|
||||||
|
email: true,
|
||||||
|
// password: false (excluded by not including)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// Returns: { id: 1, name: 'Alice', email: 'alice@prisma.io' }
|
||||||
|
```
|
||||||
|
|
||||||
|
### Select relations
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const user = await prisma.user.findUnique({
|
||||||
|
where: { id: 1 },
|
||||||
|
select: {
|
||||||
|
name: true,
|
||||||
|
posts: {
|
||||||
|
select: {
|
||||||
|
title: true,
|
||||||
|
published: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Select with include inside
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const user = await prisma.user.findMany({
|
||||||
|
select: {
|
||||||
|
name: true,
|
||||||
|
posts: {
|
||||||
|
include: {
|
||||||
|
comments: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Select relation count
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const users = await prisma.user.findMany({
|
||||||
|
select: {
|
||||||
|
name: true,
|
||||||
|
_count: {
|
||||||
|
select: { posts: true }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// Returns: { name: 'Alice', _count: { posts: 5 } }
|
||||||
|
```
|
||||||
|
|
||||||
|
## include
|
||||||
|
|
||||||
|
Include related records:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const user = await prisma.user.findUnique({
|
||||||
|
where: { id: 1 },
|
||||||
|
include: {
|
||||||
|
posts: true,
|
||||||
|
profile: true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Filtered include
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const user = await prisma.user.findUnique({
|
||||||
|
where: { id: 1 },
|
||||||
|
include: {
|
||||||
|
posts: {
|
||||||
|
where: { published: true },
|
||||||
|
orderBy: { createdAt: 'desc' },
|
||||||
|
take: 5
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Nested include
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const user = await prisma.user.findUnique({
|
||||||
|
where: { id: 1 },
|
||||||
|
include: {
|
||||||
|
posts: {
|
||||||
|
include: {
|
||||||
|
comments: {
|
||||||
|
include: {
|
||||||
|
author: true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Include relation count
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const users = await prisma.user.findMany({
|
||||||
|
include: {
|
||||||
|
_count: {
|
||||||
|
select: { posts: true, followers: true }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## omit
|
||||||
|
|
||||||
|
Exclude specific fields:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const user = await prisma.user.findUnique({
|
||||||
|
where: { id: 1 },
|
||||||
|
omit: {
|
||||||
|
password: true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// Returns all fields except password
|
||||||
|
```
|
||||||
|
|
||||||
|
### Omit in relations
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const users = await prisma.user.findMany({
|
||||||
|
omit: { password: true },
|
||||||
|
include: {
|
||||||
|
posts: {
|
||||||
|
omit: { content: true }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
**Note:** Cannot use `select` and `omit` together.
|
||||||
|
|
||||||
|
## where
|
||||||
|
|
||||||
|
Filter records:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const users = await prisma.user.findMany({
|
||||||
|
where: {
|
||||||
|
email: { contains: '@prisma.io' },
|
||||||
|
role: 'ADMIN'
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
See `filters.md` for detailed filter operators.
|
||||||
|
|
||||||
|
## orderBy
|
||||||
|
|
||||||
|
Sort results:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Single field
|
||||||
|
const users = await prisma.user.findMany({
|
||||||
|
orderBy: { name: 'asc' }
|
||||||
|
})
|
||||||
|
|
||||||
|
// Multiple fields
|
||||||
|
const users = await prisma.user.findMany({
|
||||||
|
orderBy: [
|
||||||
|
{ role: 'desc' },
|
||||||
|
{ name: 'asc' }
|
||||||
|
]
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Order by relation
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const users = await prisma.user.findMany({
|
||||||
|
orderBy: {
|
||||||
|
posts: { _count: 'desc' }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Null handling
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const users = await prisma.user.findMany({
|
||||||
|
orderBy: {
|
||||||
|
name: { sort: 'asc', nulls: 'last' }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## take & skip
|
||||||
|
|
||||||
|
Pagination:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// First page
|
||||||
|
const users = await prisma.user.findMany({
|
||||||
|
take: 10,
|
||||||
|
skip: 0
|
||||||
|
})
|
||||||
|
|
||||||
|
// Second page
|
||||||
|
const users = await prisma.user.findMany({
|
||||||
|
take: 10,
|
||||||
|
skip: 10
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Negative take (reverse)
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const lastUsers = await prisma.user.findMany({
|
||||||
|
take: -10,
|
||||||
|
orderBy: { id: 'asc' }
|
||||||
|
})
|
||||||
|
// Returns last 10 users
|
||||||
|
```
|
||||||
|
|
||||||
|
## cursor
|
||||||
|
|
||||||
|
Cursor-based pagination:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// First page
|
||||||
|
const firstPage = await prisma.user.findMany({
|
||||||
|
take: 10,
|
||||||
|
orderBy: { id: 'asc' }
|
||||||
|
})
|
||||||
|
|
||||||
|
// Next page using cursor
|
||||||
|
const nextPage = await prisma.user.findMany({
|
||||||
|
take: 10,
|
||||||
|
skip: 1, // Skip the cursor record
|
||||||
|
cursor: { id: firstPage[firstPage.length - 1].id },
|
||||||
|
orderBy: { id: 'asc' }
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## distinct
|
||||||
|
|
||||||
|
Return unique values:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const cities = await prisma.user.findMany({
|
||||||
|
distinct: ['city'],
|
||||||
|
select: { city: true }
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Multiple distinct fields
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const locations = await prisma.user.findMany({
|
||||||
|
distinct: ['city', 'country']
|
||||||
|
})
|
||||||
|
```
|
||||||
@@ -0,0 +1,198 @@
|
|||||||
|
# Raw Queries
|
||||||
|
|
||||||
|
Execute raw SQL when Prisma's query API isn't sufficient.
|
||||||
|
|
||||||
|
## $queryRaw
|
||||||
|
|
||||||
|
Execute SELECT queries and get typed results:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const users = await prisma.$queryRaw`
|
||||||
|
SELECT * FROM "User" WHERE email LIKE ${'%@prisma.io'}
|
||||||
|
`
|
||||||
|
```
|
||||||
|
|
||||||
|
### With type
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
type User = { id: number; email: string; name: string | null }
|
||||||
|
|
||||||
|
const users = await prisma.$queryRaw<User[]>`
|
||||||
|
SELECT id, email, name FROM "User" WHERE role = ${'ADMIN'}
|
||||||
|
`
|
||||||
|
```
|
||||||
|
|
||||||
|
### Dynamic table/column names
|
||||||
|
|
||||||
|
Use `Prisma.raw()` for identifiers (not safe for user input):
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { Prisma } from '../generated/client'
|
||||||
|
|
||||||
|
const column = 'email'
|
||||||
|
const users = await prisma.$queryRaw`
|
||||||
|
SELECT ${Prisma.raw(column)} FROM "User"
|
||||||
|
`
|
||||||
|
```
|
||||||
|
|
||||||
|
### With Prisma.sql
|
||||||
|
|
||||||
|
Build queries dynamically:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { Prisma } from '../generated/client'
|
||||||
|
|
||||||
|
const email = 'alice@prisma.io'
|
||||||
|
const query = Prisma.sql`SELECT * FROM "User" WHERE email = ${email}`
|
||||||
|
const users = await prisma.$queryRaw(query)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Join multiple SQL fragments
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { Prisma } from '../generated/client'
|
||||||
|
|
||||||
|
const conditions = [
|
||||||
|
Prisma.sql`role = ${'ADMIN'}`,
|
||||||
|
Prisma.sql`verified = ${true}`
|
||||||
|
]
|
||||||
|
|
||||||
|
const users = await prisma.$queryRaw`
|
||||||
|
SELECT * FROM "User"
|
||||||
|
WHERE ${Prisma.join(conditions, ' AND ')}
|
||||||
|
`
|
||||||
|
```
|
||||||
|
|
||||||
|
## $executeRaw
|
||||||
|
|
||||||
|
Execute INSERT, UPDATE, DELETE (returns affected count):
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const count = await prisma.$executeRaw`
|
||||||
|
UPDATE "User" SET verified = true WHERE email LIKE ${'%@prisma.io'}
|
||||||
|
`
|
||||||
|
console.log(`Updated ${count} users`)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Delete example
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const deleted = await prisma.$executeRaw`
|
||||||
|
DELETE FROM "User" WHERE "deletedAt" < ${thirtyDaysAgo}
|
||||||
|
`
|
||||||
|
```
|
||||||
|
|
||||||
|
### Insert example
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const inserted = await prisma.$executeRaw`
|
||||||
|
INSERT INTO "Log" (message, level, timestamp)
|
||||||
|
VALUES (${message}, ${level}, ${new Date()})
|
||||||
|
`
|
||||||
|
```
|
||||||
|
|
||||||
|
## $queryRawUnsafe / $executeRawUnsafe
|
||||||
|
|
||||||
|
For fully dynamic queries (use with caution!):
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// ⚠️ SQL injection risk - only use with trusted input
|
||||||
|
const table = 'User'
|
||||||
|
const users = await prisma.$queryRawUnsafe(
|
||||||
|
`SELECT * FROM "${table}" WHERE id = $1`,
|
||||||
|
userId
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Parameterized unsafe query
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const result = await prisma.$executeRawUnsafe(
|
||||||
|
'UPDATE "User" SET name = $1 WHERE id = $2',
|
||||||
|
'Alice',
|
||||||
|
1
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
## SQL Injection Prevention
|
||||||
|
|
||||||
|
### Safe (parameterized)
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// ✅ User input is parameterized
|
||||||
|
const email = userInput
|
||||||
|
const users = await prisma.$queryRaw`
|
||||||
|
SELECT * FROM "User" WHERE email = ${email}
|
||||||
|
`
|
||||||
|
```
|
||||||
|
|
||||||
|
### Unsafe (concatenation)
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// ❌ SQL injection vulnerability!
|
||||||
|
const email = userInput
|
||||||
|
const users = await prisma.$queryRawUnsafe(
|
||||||
|
`SELECT * FROM "User" WHERE email = '${email}'`
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Database-Specific Features
|
||||||
|
|
||||||
|
### PostgreSQL
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Array operations
|
||||||
|
const users = await prisma.$queryRaw`
|
||||||
|
SELECT * FROM "User" WHERE 'admin' = ANY(roles)
|
||||||
|
`
|
||||||
|
|
||||||
|
// JSON operations
|
||||||
|
const users = await prisma.$queryRaw`
|
||||||
|
SELECT * FROM "User" WHERE metadata->>'theme' = 'dark'
|
||||||
|
`
|
||||||
|
```
|
||||||
|
|
||||||
|
### MySQL
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Full-text search
|
||||||
|
const posts = await prisma.$queryRaw`
|
||||||
|
SELECT * FROM Post WHERE MATCH(title, content) AGAINST(${searchTerm})
|
||||||
|
`
|
||||||
|
```
|
||||||
|
|
||||||
|
## Transactions with Raw Queries
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
await prisma.$transaction(async (tx) => {
|
||||||
|
await tx.$executeRaw`UPDATE "Account" SET balance = balance - ${amount} WHERE id = ${senderId}`
|
||||||
|
await tx.$executeRaw`UPDATE "Account" SET balance = balance + ${amount} WHERE id = ${recipientId}`
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## Handling Results
|
||||||
|
|
||||||
|
### BigInt handling
|
||||||
|
|
||||||
|
PostgreSQL returns BigInt for COUNT:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const result = await prisma.$queryRaw<[{ count: bigint }]>`
|
||||||
|
SELECT COUNT(*) as count FROM "User"
|
||||||
|
`
|
||||||
|
const count = Number(result[0].count)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Date handling
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
type Result = { createdAt: Date }
|
||||||
|
const users = await prisma.$queryRaw<Result[]>`
|
||||||
|
SELECT "createdAt" FROM "User"
|
||||||
|
`
|
||||||
|
// createdAt is already a Date object
|
||||||
|
```
|
||||||
|
|
||||||
|
Invalid JavaScript `Date` values passed to raw queries fail validation instead of being silently serialized as `null`. Validate date input at the application boundary; do not rely on `new Date(badValue)` reaching the database.
|
||||||
|
|
||||||
|
When a driver adapter returns an unmapped database-specific error, Prisma surfaces `P2039` with the adapter's preserved original code/message. If those details are missing, fix the adapter mapping rather than parsing rendered error text.
|
||||||
@@ -0,0 +1,308 @@
|
|||||||
|
# Relation Queries
|
||||||
|
|
||||||
|
Query and modify related records.
|
||||||
|
|
||||||
|
## Include Relations
|
||||||
|
|
||||||
|
Load related records:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const user = await prisma.user.findUnique({
|
||||||
|
where: { id: 1 },
|
||||||
|
include: {
|
||||||
|
posts: true,
|
||||||
|
profile: true
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Filtered include
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const user = await prisma.user.findUnique({
|
||||||
|
where: { id: 1 },
|
||||||
|
include: {
|
||||||
|
posts: {
|
||||||
|
where: { published: true },
|
||||||
|
orderBy: { createdAt: 'desc' },
|
||||||
|
take: 5,
|
||||||
|
select: { id: true, title: true }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Nested include
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const user = await prisma.user.findUnique({
|
||||||
|
where: { id: 1 },
|
||||||
|
include: {
|
||||||
|
posts: {
|
||||||
|
include: {
|
||||||
|
comments: {
|
||||||
|
include: { author: true }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## Select Relations
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const user = await prisma.user.findUnique({
|
||||||
|
where: { id: 1 },
|
||||||
|
select: {
|
||||||
|
name: true,
|
||||||
|
posts: {
|
||||||
|
select: { title: true }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## Nested Writes
|
||||||
|
|
||||||
|
### Create with relations
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const user = await prisma.user.create({
|
||||||
|
data: {
|
||||||
|
email: 'alice@prisma.io',
|
||||||
|
posts: {
|
||||||
|
create: [
|
||||||
|
{ title: 'Post 1' },
|
||||||
|
{ title: 'Post 2' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
profile: {
|
||||||
|
create: { bio: 'Hello!' }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Create or connect
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const post = await prisma.post.create({
|
||||||
|
data: {
|
||||||
|
title: 'New Post',
|
||||||
|
author: {
|
||||||
|
connectOrCreate: {
|
||||||
|
where: { email: 'alice@prisma.io' },
|
||||||
|
create: { email: 'alice@prisma.io', name: 'Alice' }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Connect existing
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const post = await prisma.post.create({
|
||||||
|
data: {
|
||||||
|
title: 'New Post',
|
||||||
|
author: {
|
||||||
|
connect: { id: 1 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Shorthand for foreign key
|
||||||
|
const post = await prisma.post.create({
|
||||||
|
data: {
|
||||||
|
title: 'New Post',
|
||||||
|
authorId: 1
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## Update Relations
|
||||||
|
|
||||||
|
### Update related records
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const user = await prisma.user.update({
|
||||||
|
where: { id: 1 },
|
||||||
|
data: {
|
||||||
|
posts: {
|
||||||
|
update: {
|
||||||
|
where: { id: 1 },
|
||||||
|
data: { title: 'Updated Title' }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Update many related
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const user = await prisma.user.update({
|
||||||
|
where: { id: 1 },
|
||||||
|
data: {
|
||||||
|
posts: {
|
||||||
|
updateMany: {
|
||||||
|
where: { published: false },
|
||||||
|
data: { published: true }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Upsert related
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const user = await prisma.user.update({
|
||||||
|
where: { id: 1 },
|
||||||
|
data: {
|
||||||
|
profile: {
|
||||||
|
upsert: {
|
||||||
|
create: { bio: 'New bio' },
|
||||||
|
update: { bio: 'Updated bio' }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Disconnect
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// 1-to-1 optional
|
||||||
|
const user = await prisma.user.update({
|
||||||
|
where: { id: 1 },
|
||||||
|
data: {
|
||||||
|
profile: { disconnect: true }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Many-to-many
|
||||||
|
const post = await prisma.post.update({
|
||||||
|
where: { id: 1 },
|
||||||
|
data: {
|
||||||
|
tags: {
|
||||||
|
disconnect: [{ id: 1 }, { id: 2 }]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Delete related
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const user = await prisma.user.update({
|
||||||
|
where: { id: 1 },
|
||||||
|
data: {
|
||||||
|
posts: {
|
||||||
|
delete: { id: 1 }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Delete many
|
||||||
|
const user = await prisma.user.update({
|
||||||
|
where: { id: 1 },
|
||||||
|
data: {
|
||||||
|
posts: {
|
||||||
|
deleteMany: { published: false }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Set (replace all)
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Replace all related records
|
||||||
|
const post = await prisma.post.update({
|
||||||
|
where: { id: 1 },
|
||||||
|
data: {
|
||||||
|
tags: {
|
||||||
|
set: [{ id: 1 }, { id: 2 }]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## Relation Filters
|
||||||
|
|
||||||
|
### some
|
||||||
|
|
||||||
|
At least one matches:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const users = await prisma.user.findMany({
|
||||||
|
where: {
|
||||||
|
posts: { some: { published: true } }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### every
|
||||||
|
|
||||||
|
All match:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const users = await prisma.user.findMany({
|
||||||
|
where: {
|
||||||
|
posts: { every: { published: true } }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### none
|
||||||
|
|
||||||
|
None match:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const users = await prisma.user.findMany({
|
||||||
|
where: {
|
||||||
|
posts: { none: { published: true } }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### is / isNot (1-to-1)
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const users = await prisma.user.findMany({
|
||||||
|
where: {
|
||||||
|
profile: { is: { country: 'USA' } }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## Count Relations
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const users = await prisma.user.findMany({
|
||||||
|
select: {
|
||||||
|
name: true,
|
||||||
|
_count: {
|
||||||
|
select: { posts: true, followers: true }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
// { name: 'Alice', _count: { posts: 5, followers: 100 } }
|
||||||
|
```
|
||||||
|
|
||||||
|
### Filter counted relations
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const users = await prisma.user.findMany({
|
||||||
|
select: {
|
||||||
|
name: true,
|
||||||
|
_count: {
|
||||||
|
select: {
|
||||||
|
posts: { where: { published: true } }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
@@ -0,0 +1,184 @@
|
|||||||
|
# Transactions
|
||||||
|
|
||||||
|
Execute multiple operations atomically.
|
||||||
|
|
||||||
|
## Sequential Transactions
|
||||||
|
|
||||||
|
Array of operations executed in order:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
const [user, post] = await prisma.$transaction([
|
||||||
|
prisma.user.create({ data: { email: 'alice@prisma.io' } }),
|
||||||
|
prisma.post.create({ data: { title: 'Hello', authorId: 1 } })
|
||||||
|
])
|
||||||
|
```
|
||||||
|
|
||||||
|
### All or nothing
|
||||||
|
|
||||||
|
If any operation fails, all are rolled back:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
try {
|
||||||
|
await prisma.$transaction([
|
||||||
|
prisma.user.create({ data: { email: 'alice@prisma.io' } }),
|
||||||
|
prisma.user.create({ data: { email: 'alice@prisma.io' } }) // Duplicate!
|
||||||
|
])
|
||||||
|
} catch (e) {
|
||||||
|
// Both operations rolled back
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Interactive Transactions
|
||||||
|
|
||||||
|
For complex logic and dependent operations:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
await prisma.$transaction(async (tx) => {
|
||||||
|
// Decrement sender balance
|
||||||
|
const sender = await tx.account.update({
|
||||||
|
where: { id: senderId },
|
||||||
|
data: { balance: { decrement: amount } }
|
||||||
|
})
|
||||||
|
|
||||||
|
// Check balance
|
||||||
|
if (sender.balance < 0) {
|
||||||
|
throw new Error('Insufficient funds')
|
||||||
|
}
|
||||||
|
|
||||||
|
// Increment recipient balance
|
||||||
|
await tx.account.update({
|
||||||
|
where: { id: recipientId },
|
||||||
|
data: { balance: { increment: amount } }
|
||||||
|
})
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Transaction options
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
await prisma.$transaction(
|
||||||
|
async (tx) => {
|
||||||
|
// operations
|
||||||
|
},
|
||||||
|
{
|
||||||
|
maxWait: 5000, // Max wait to acquire lock (ms)
|
||||||
|
timeout: 10000, // Max transaction duration (ms)
|
||||||
|
isolationLevel: 'Serializable' // Isolation level
|
||||||
|
}
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
### Isolation levels
|
||||||
|
|
||||||
|
| Level | Description |
|
||||||
|
|-------|-------------|
|
||||||
|
| `ReadUncommitted` | Lowest isolation, can read uncommitted changes |
|
||||||
|
| `ReadCommitted` | Only read committed changes |
|
||||||
|
| `RepeatableRead` | Consistent reads within transaction |
|
||||||
|
| `Serializable` | Highest isolation, serialized execution |
|
||||||
|
|
||||||
|
## Nested Writes
|
||||||
|
|
||||||
|
Automatic transactions for nested operations:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// This is automatically a transaction
|
||||||
|
const user = await prisma.user.create({
|
||||||
|
data: {
|
||||||
|
email: 'alice@prisma.io',
|
||||||
|
posts: {
|
||||||
|
create: [
|
||||||
|
{ title: 'Post 1' },
|
||||||
|
{ title: 'Post 2' }
|
||||||
|
]
|
||||||
|
},
|
||||||
|
profile: {
|
||||||
|
create: { bio: 'Hello!' }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## Transaction Client
|
||||||
|
|
||||||
|
The `tx` parameter is a Prisma Client scoped to the transaction:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
await prisma.$transaction(async (tx) => {
|
||||||
|
// Use tx instead of prisma
|
||||||
|
await tx.user.create({ ... })
|
||||||
|
await tx.post.create({ ... })
|
||||||
|
|
||||||
|
// Can call methods
|
||||||
|
const count = await tx.user.count()
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## OrThrow in Transactions
|
||||||
|
|
||||||
|
Use with interactive transactions:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
await prisma.$transaction(async (tx) => {
|
||||||
|
// If not found, throws and rolls back entire transaction
|
||||||
|
const user = await tx.user.findUniqueOrThrow({
|
||||||
|
where: { id: 1 }
|
||||||
|
})
|
||||||
|
|
||||||
|
await tx.post.create({
|
||||||
|
data: { title: 'New Post', authorId: user.id }
|
||||||
|
})
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## Best Practices
|
||||||
|
|
||||||
|
### Keep transactions short
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Good - only DB operations in transaction
|
||||||
|
const data = prepareData() // Outside transaction
|
||||||
|
await prisma.$transaction(async (tx) => {
|
||||||
|
await tx.user.create({ data })
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Handle errors
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
try {
|
||||||
|
await prisma.$transaction(async (tx) => {
|
||||||
|
// operations
|
||||||
|
})
|
||||||
|
} catch (e) {
|
||||||
|
if (e.code === 'P2002') {
|
||||||
|
// Handle unique constraint violation
|
||||||
|
}
|
||||||
|
throw e
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Use appropriate isolation
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Default is fine for most cases
|
||||||
|
await prisma.$transaction(async (tx) => {
|
||||||
|
// operations
|
||||||
|
})
|
||||||
|
|
||||||
|
// Use Serializable for strict consistency
|
||||||
|
await prisma.$transaction(
|
||||||
|
async (tx) => { /* operations */ },
|
||||||
|
{ isolationLevel: 'Serializable' }
|
||||||
|
)
|
||||||
|
```
|
||||||
|
|
||||||
|
## Sequential vs Interactive
|
||||||
|
|
||||||
|
| Feature | Sequential | Interactive |
|
||||||
|
|---------|------------|-------------|
|
||||||
|
| Syntax | Array | Async function |
|
||||||
|
| Dependent ops | No | Yes |
|
||||||
|
| Conditional logic | No | Yes |
|
||||||
|
| Performance | Better | More flexible |
|
||||||
|
| Use case | Simple batch | Complex logic |
|
||||||
@@ -0,0 +1,172 @@
|
|||||||
|
---
|
||||||
|
name: prisma-compute
|
||||||
|
description: Deploy and operate apps on Prisma Compute with the Prisma 8 CLI. Use whenever the user mentions Prisma Compute, deploying or hosting a Prisma app, `prisma deploy`, `prisma dev module.ts`, Prisma Composer apps (`module.ts`, `compute()`, the `composer` section of `prisma.config.ts`), preview stages, deploy on push (`prisma git connect`, `prisma/cloud-deploy-action`), `prisma service` logs, versions, rollback, or custom domains, `project env`, `PRISMA_SERVICE_TOKEN`, regions, 504s, sleeping instances, or `waitUntil`; also when a project still uses the removed `@prisma/cli app deploy`, `prisma.compute.ts`, `defineComputeConfig`, `compute:deploy`, or `build logs` surface.
|
||||||
|
license: MIT
|
||||||
|
metadata:
|
||||||
|
author: prisma
|
||||||
|
version: "2.0.0"
|
||||||
|
---
|
||||||
|
|
||||||
|
# Prisma Compute
|
||||||
|
|
||||||
|
Deploy TypeScript apps to Prisma Compute and operate them afterwards. Every deploy goes through a Prisma Composer app (a `module.ts` root module) and the Prisma 8 CLI, `prisma`.
|
||||||
|
|
||||||
|
Verified against `prisma` 8.0.0-rc.21 (published identically as `@prisma/cli`), `@prisma/composer` and `@prisma/composer-prisma-cloud` 0.28.0, `@prisma/compute` 0.1.0-beta.0, and `create-prisma` 0.14.1. Re-checked against `prisma` 8.0.0-rc.23, whose command surface matches rc.21, and Composer 0.30.0, which adds `node()`'s `dependencies` option (0.29.0) and narrows the supported Node.js versions. The CLI moves fast: run `npx prisma <group> --help` before using a flag this skill does not show.
|
||||||
|
|
||||||
|
## Version-Matched Skills
|
||||||
|
|
||||||
|
The installed packages ship their own agent skills, matched to the installed version:
|
||||||
|
|
||||||
|
- `prisma-platform-core-concepts`, inside `prisma`: projects, branches, services, versions, env vars, deploy on push.
|
||||||
|
- `prisma-composer-core-concepts`, inside `@prisma/composer`: declaring services, modules, databases, and builds; `dev`, `deploy`, and teardown.
|
||||||
|
|
||||||
|
`npx prisma skills sync` copies them into the agent skill directories (`.claude/skills`, `.cursor/skills`, `.agents/skills`, `.devin/skills`), and `npx prisma skills list` shows what is installed. `npx prisma init` does the same and adds a `postinstall` hook that keeps them current. When those skills are installed, use them for API details. This skill covers the deploy and operations workflow and its pitfalls.
|
||||||
|
|
||||||
|
## Removed Surface
|
||||||
|
|
||||||
|
The Compute CLI from before Composer is gone. Its commands fail with `CLI.UNKNOWN_COMMAND` (removed flags with `CLI.INVALID_ARGUMENTS`), its config files are not read, and its environment variables are ignored:
|
||||||
|
|
||||||
|
| Removed | Use instead |
|
||||||
|
|---------|-------------|
|
||||||
|
| `@prisma/cli app deploy`, `app build`, `app run` | Your own build script, then `npx prisma deploy module.ts`; `npx prisma dev module.ts` to run locally |
|
||||||
|
| `prisma.compute.ts`, `prisma.compute.json`, `defineComputeConfig` | `module.ts`, a `service.ts` per server declared with `compute()`, and the `composer` section of `prisma.config.ts` |
|
||||||
|
| `init` writing a compute config | `npx prisma init` now writes a `prisma.config.ts` with only a `skills` section, adds `prisma` as a dev dependency, and syncs skills. Add the `composer` section yourself |
|
||||||
|
| `compute:deploy` script | `npx prisma deploy module.ts`, or the `deploy` script current `create-prisma` generates |
|
||||||
|
| `app deploy --branch <name>` | `npx prisma deploy module.ts --stage <name>` |
|
||||||
|
| `app deploy --prod`, `--no-promote`, `app promote` | No `--stage` deploys production; `service version promote <version-id>` |
|
||||||
|
| `app show`, `app open`, `app list-deploys`, `app show-deploy` | `service show <service>`, `service open <service>`, `service version list <service>`, `service version show <version-id>` |
|
||||||
|
| `app logs` | `service logs <service>` |
|
||||||
|
| `app rollback --to <id> --yes` | `service version rollback <service> --to <id> --confirm <id>` |
|
||||||
|
| `app domain ...` | `service domain ... --service <service>` |
|
||||||
|
| `app remove` | Remove the `provision()` from `module.ts` and deploy, or `service delete <service> --confirm <service>` |
|
||||||
|
| `build logs <build-id>` | The GitHub Actions run log or the Console; `GET /v1/builds/{buildId}` for state and failing step |
|
||||||
|
| `database ...` | `postgres ...` |
|
||||||
|
| `project env remove` | `project env delete` |
|
||||||
|
| `auth logout --workspace <id>` | `auth workspace logout <id>` |
|
||||||
|
| `agent install`, `agent update`, `agent status` | `npx skills add prisma/skills --skill prisma-compute`; `npx prisma skills sync` for package skills |
|
||||||
|
| `PRISMA_PROJECT_ID`, `PRISMA_APP_ID`, `PRISMA_SERVICE_ID` | `--project <id-or-name>`, the service as a positional argument, and `.prisma/local.json` from `project link` |
|
||||||
|
| `/v1/apps` REST endpoints | `/v1/services` (the `/v1/apps` paths are deprecated) |
|
||||||
|
|
||||||
|
A repository with `prisma.compute.ts` or a `compute:deploy` script was set up for the removed flow. Port it to Composer ([`app-composer-setup.md`](references/app-composer-setup.md)) instead of running the old commands.
|
||||||
|
|
||||||
|
## When to Apply
|
||||||
|
|
||||||
|
- Deploying a new or existing app to Prisma Compute
|
||||||
|
- Porting a project that uses `prisma.compute.ts`, `compute:deploy`, or `@prisma/cli app deploy`
|
||||||
|
- Setting up preview stages, deploy on push, or CI deploys
|
||||||
|
- Reading service logs, listing versions, promoting, or rolling back
|
||||||
|
- Managing env vars, custom domains, Prisma Postgres databases, or buckets in a Compute project
|
||||||
|
- Debugging a failed deploy, an unreachable service, a `504`, or work that stops when an instance sleeps
|
||||||
|
|
||||||
|
## Rule Categories by Priority
|
||||||
|
|
||||||
|
| Priority | Category | Impact | Prefix |
|
||||||
|
|----------|----------|--------|--------|
|
||||||
|
| 1 | CLI surface | CRITICAL | `cli-` |
|
||||||
|
| 2 | App declaration | CRITICAL | `app-` |
|
||||||
|
| 3 | Runtime | CRITICAL | `runtime-` |
|
||||||
|
| 4 | Deploy | HIGH | `deploy-` |
|
||||||
|
| 5 | Operations | HIGH | `ops-` |
|
||||||
|
| 6 | Debugging | HIGH | `debug-` |
|
||||||
|
| 7 | Automation | MEDIUM | `automation-` |
|
||||||
|
|
||||||
|
## Quick Reference
|
||||||
|
|
||||||
|
### 1. CLI surface (CRITICAL)
|
||||||
|
|
||||||
|
- `cli-prisma-8-binary` - Platform and deploy commands exist only in the Prisma 8 CLI. In a Prisma 6 or 7 project, `npx prisma` runs that version's ORM CLI, which has no `auth`, `project`, `service`, or `deploy`; Prisma 7's `dev` starts a local database instead. Check `npx prisma --version`; outside a Prisma 8 project use `npx @prisma/cli@latest <command>`.
|
||||||
|
- `cli-help-first` - Command groups are `auth`, `project` (with `project env`), `postgres`, `bucket`, `branch`, `git`, and `service` (with `service version` and `service domain`), plus `deploy`, `dev`, `init`, `skills`, and `feedback`. Read `--help` before using a flag.
|
||||||
|
- `cli-json` - Pass `--json`, and `--no-interactive` in scripts. Branch on `error.code` (`NAMESPACE.SUBCODE`) and follow `nextActions`; do not parse messages.
|
||||||
|
- `cli-explicit-targets` - Name the service as the first argument, the project with `--project` (or link the directory), and a preview with `--branch`. Without `--branch` a command targets the production branch; the CLI does not read the current Git branch.
|
||||||
|
- `cli-consent-tokens` - Destructive commands need `--confirm <token>` with an exact id, name, or hostname. `--yes` cannot grant consent. Run them only when the user asked for that action.
|
||||||
|
|
||||||
|
### 2. App declaration (CRITICAL)
|
||||||
|
|
||||||
|
- `app-composer-required` - A deployable app has `module.ts` (default export `module(name, ...)`), a `service.ts` per server (`compute({ name, deps, build })`), and a `composer` section in `prisma.config.ts` with `prismaCloud()`, `nodeBuild()` (plus `nextjsBuild()` for Next.js), and `state: prismaState()`.
|
||||||
|
- `app-build-adapter` - `node({ module: import.meta.url, entry })` for one self-contained bundle, `node({ module, dir, entry })` for a built directory, `nextjs({ module, appDir })` for Next.js standalone. Add `dependencies: "external"` to `node()` when the build leaves packages as imports. See [`app-framework-builds.md`](references/app-framework-builds.md).
|
||||||
|
- `app-region` - The first deploy creates the project and needs a region: `prismaCloud({ region: "eu-central-1" })` or `PRISMA_REGION`. The region cannot change later.
|
||||||
|
- `app-databases` - `rawPostgres()` (package root) delivers `{ url }`; `postgres(contract)` from `@prisma/composer-prisma-cloud/orm` adds a typed client and applies committed migrations on deploy. Read both through `service.load()`, not `process.env.DATABASE_URL`.
|
||||||
|
- `app-names` - Provision ids and service names allow `[A-Za-z0-9]` only, and the platform rejects ids shorter than three characters. The root module name becomes the project name.
|
||||||
|
|
||||||
|
### 3. Runtime (CRITICAL)
|
||||||
|
|
||||||
|
- `runtime-bind-all-interfaces` - Listen on `service.port()` (also exported as `PORT`, default 3000) and bind `0.0.0.0`. A loopback listener is unreachable.
|
||||||
|
- `runtime-bun` - Services run on Bun. By default (`dependencies: "bundled"`) a deploy ships only the build output, never the project's `node_modules`, so the build must inline every dependency except runtime built-ins. A build that leaves packages as imports (`tsc`, Astro's Node adapter) sets `dependencies: "external"` on `node()`, and the deploy stages the installed packages its entry imports.
|
||||||
|
- `runtime-first-byte-60s` - A request that sends no bytes for 60 seconds gets `504 Gateway Time-out` and is cancelled. Respond first, then continue under `waitUntil` or from a queue.
|
||||||
|
- `runtime-sleep` - Idle instances are snapshotted and resumed. Timers and floating promises can stall. `waitUntil` and `KeepAwakeGuard` from `@prisma/compute` keep an instance awake on a best-effort basis; they do not make work durable.
|
||||||
|
- `runtime-no-websockets` - WebSocket servers are not supported.
|
||||||
|
|
||||||
|
### 4. Deploy (HIGH)
|
||||||
|
|
||||||
|
- `deploy-build-first` - `deploy` and `dev` do not build. Run the build, then `npx prisma deploy module.ts`.
|
||||||
|
- `deploy-dev-first` - `npx prisma dev module.ts` runs the whole app locally with no credentials. Verify each local URL before deploying.
|
||||||
|
- `deploy-production-intent` - A deploy without `--stage`, and a push to the default branch of a connected repository, change production. Get the user's go-ahead first; use `--stage <name>` for previews.
|
||||||
|
- `deploy-auth` - On a workstation the user runs `npx prisma auth login` (browser). In CI set `PRISMA_SERVICE_TOKEN` and `PRISMA_WORKSPACE_ID`. Check `npx prisma auth whoami --json` (`envelope.result.authenticated`, `envelope.result.workspace`) before deploying.
|
||||||
|
- `deploy-link-after` - `deploy` finds or creates the project by the root module name (or `--name`) and does not write `.prisma/local.json`. Run `npx prisma project link <app-name>` afterwards, or pass `--project`, before `service`, `git`, or `project env` commands.
|
||||||
|
- `deploy-on-push` - Deploy on push needs both `npx prisma git connect` (interactive) and a workflow running `prisma/cloud-deploy-action@v1`. Connecting alone deploys nothing.
|
||||||
|
- `deploy-verify-url` - Take each service URL from the deploy output (`--json` result or `--report <path>`) and request it.
|
||||||
|
|
||||||
|
### 5. Operations (HIGH)
|
||||||
|
|
||||||
|
- `ops-logs` - `service logs <service>` reads the live version; `--version-id <id>` reads another, `--follow` streams. Build output lives in the CI log or the Console, not the CLI.
|
||||||
|
- `ops-versions` - `service version promote <version-id>` rebuilds with production env vars. `service version rollback <service> --to <id> --confirm <id>` switches back without a rebuild.
|
||||||
|
- `ops-env-write-only` - `project env add|update|list|delete` with `--role production`, `--role preview`, or `--branch <name>`. Values are never returned and apply on the next deploy.
|
||||||
|
- `ops-domains` - `service domain add <hostname> --service <service>`, create the CNAME it reports, then `service domain wait`. Production branch only.
|
||||||
|
- `ops-secrets-once` - `postgres create`, `postgres connection create|rotate`, and `bucket key create` print credentials once. Store them; never echo them.
|
||||||
|
|
||||||
|
### 6. Debugging (HIGH)
|
||||||
|
|
||||||
|
- `debug-error-code-first` - Read `error.code` and `nextActions` from `--json` output, or `failure.code` from the `--report` file, before changing anything.
|
||||||
|
- `debug-public-url` - Test the printed public URL, not `localhost`. A deploy that converged but does not answer is usually host binding, the port, or a crash at boot; read `service logs`.
|
||||||
|
- `debug-report-cli-bugs` - Report unresolvable CLI failures with `npx prisma feedback "<message>"` without secrets.
|
||||||
|
|
||||||
|
### 7. Automation (MEDIUM)
|
||||||
|
|
||||||
|
- `automation-create-prisma` - `create-prisma` scaffolds a new Prisma 8 project that is already a Composer app. Its `--json` mode deploys unless `--no-deploy` is passed.
|
||||||
|
- `automation-control-api` - `@prisma/composer/control` exposes `deploy`, `destroy`, `dev`, and `log`. Teardown of a stage is `destroy`; it reads only `PRISMA_SERVICE_TOKEN` and `PRISMA_WORKSPACE_ID`.
|
||||||
|
- `automation-rest-api` - Use `/v1/services`, `/v1/deployments/{deploymentId}/logs`, and `/v1/builds` from `https://api.prisma.io/v1/doc`. Do not build new deploy tooling on `@prisma/compute-sdk`.
|
||||||
|
|
||||||
|
## Preferred Workflow
|
||||||
|
|
||||||
|
1. Inspect `package.json` (is `prisma` 8.x a dev dependency, are `@prisma/composer` and `@prisma/composer-prisma-cloud` installed?), `module.ts`, `prisma.config.ts`, the build script, and leftovers from the removed flow (`prisma.compute.ts`, `compute:deploy`).
|
||||||
|
2. Install what is missing and sync the package skills:
|
||||||
|
```bash
|
||||||
|
npm install @prisma/composer @prisma/composer-prisma-cloud
|
||||||
|
npm install -D prisma
|
||||||
|
npx prisma skills sync
|
||||||
|
```
|
||||||
|
3. Declare or port the app: [`app-composer-setup.md`](references/app-composer-setup.md) and [`app-framework-builds.md`](references/app-framework-builds.md).
|
||||||
|
4. Build, run `npx prisma dev module.ts`, and request each local URL it prints.
|
||||||
|
5. Run `npx prisma auth whoami --json`. If `envelope.result.authenticated` is `false`, ask the user to run `npx prisma auth login`.
|
||||||
|
6. Deploy a preview with `npm run build && npx prisma deploy module.ts --stage <name> --json`, or production without `--stage` once the user confirms. A new project needs a region.
|
||||||
|
7. Request each printed URL, then `npx prisma project link <app-name>` and `npx prisma service list --json` (add `--branch <stage>` for a preview).
|
||||||
|
8. Report the app name, stage, service ids, URLs, and database ids. Never report secret values.
|
||||||
|
|
||||||
|
## Avoid
|
||||||
|
|
||||||
|
- Do not run `@prisma/cli app ...`, `build logs`, or `database ...`, and do not create `prisma.compute.ts`.
|
||||||
|
- Do not run platform commands through a Prisma 6 or 7 `prisma` binary.
|
||||||
|
- Do not read the port or connection strings from `process.env` in a Composer service.
|
||||||
|
- Do not expect `deploy` to build, to migrate a `rawPostgres()` database, or to copy production data into a stage.
|
||||||
|
- Do not pass `--yes` to destructive commands; it cannot grant consent.
|
||||||
|
- Do not run `auth login` or `git connect` non-interactively; both need a person at a browser.
|
||||||
|
- Do not push to the default branch of a connected repository without the user's go-ahead; it deploys production.
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- [`cli-command-map.md`](references/cli-command-map.md): every verified command, global flags, JSON envelope, targeting, consent tokens
|
||||||
|
- [`app-composer-setup.md`](references/app-composer-setup.md): the minimum declaration, region, databases, config and secrets, porting from `prisma.compute.ts`
|
||||||
|
- [`app-framework-builds.md`](references/app-framework-builds.md): build output and `build:` adapter per framework
|
||||||
|
- [`runtime-requirements.md`](references/runtime-requirements.md): Bun, host and port, 60-second first byte, sleep, keep-awake, regions
|
||||||
|
- [`deploy-cli-and-ci.md`](references/deploy-cli-and-ci.md): `prisma deploy`, stages, credentials, output, CI, teardown
|
||||||
|
- [`deploy-on-push.md`](references/deploy-on-push.md): GitHub connection and the `prisma/cloud-deploy-action` workflow
|
||||||
|
- [`ops-services-and-config.md`](references/ops-services-and-config.md): services, versions, logs, domains, env vars, databases, buckets
|
||||||
|
- [`debug-deploy-failures.md`](references/debug-deploy-failures.md): symptoms, causes, and fixes
|
||||||
|
- [`automation-create-prisma.md`](references/automation-create-prisma.md): scaffolding a new Composer app
|
||||||
|
- [`automation-rest-api.md`](references/automation-rest-api.md): REST API paths, the control API, and the status of `@prisma/compute-sdk`
|
||||||
|
|
||||||
|
Docs: [Compute](https://www.prisma.io/docs/compute), [Deploy your first app](https://www.prisma.io/docs/prisma-compute/deploy), [Composer](https://www.prisma.io/docs/composer), [CLI reference](https://www.prisma.io/docs/cli).
|
||||||
|
|
||||||
|
## Feedback
|
||||||
|
|
||||||
|
`npx prisma feedback "<message>"` sends anonymous feedback to the CLI team with the CLI version, Node.js version, and OS platform. Add `--email <address>` for a reply. Never include tokens, connection URLs, or user data.
|
||||||
@@ -0,0 +1,189 @@
|
|||||||
|
# app-composer-setup
|
||||||
|
|
||||||
|
Compute deploys only Prisma Composer apps: a root module, one service declaration per server, and a `composer` section in `prisma.config.ts`.
|
||||||
|
|
||||||
|
## Priority
|
||||||
|
|
||||||
|
CRITICAL
|
||||||
|
|
||||||
|
## Why It Matters
|
||||||
|
|
||||||
|
`prisma deploy` takes a module file, not a framework name or a config file. Without `module.ts`, a `compute()` service, and the `composer` config section, there is nothing to deploy. This file covers the minimum an agent needs. For contracts between services, input schemas, modules, and testing, use the `prisma-composer-core-concepts` skill and the [Composer docs](https://www.prisma.io/docs/composer).
|
||||||
|
|
||||||
|
## Requirements
|
||||||
|
|
||||||
|
- Node.js 22.18 or newer on the 22 line, 24.11 or newer on the 24 line, or 26 or newer (`engines.node` is `^22.18.0 || ^24.11.0 || >=26.0.0` since Composer 0.30.0). Composer loads the `.ts` entry directly; older versions stop at `ERR_UNKNOWN_FILE_EXTENSION`.
|
||||||
|
- Bun. Deployed services run on Bun, and `bun build --target=bun` is the simplest way to produce the single-file entry a service needs.
|
||||||
|
- The packages:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install @prisma/composer @prisma/composer-prisma-cloud
|
||||||
|
npm install -D prisma
|
||||||
|
npx prisma skills sync
|
||||||
|
```
|
||||||
|
|
||||||
|
`@prisma/composer` pins its own `effect` version; do not add a different `effect` to the app. See [`debug-deploy-failures.md`](debug-deploy-failures.md) if `prisma.config.ts` fails to evaluate.
|
||||||
|
|
||||||
|
## The Four Files
|
||||||
|
|
||||||
|
```ts
|
||||||
|
// src/server.ts
|
||||||
|
import service from "./service.ts";
|
||||||
|
|
||||||
|
Bun.serve({
|
||||||
|
port: service.port(),
|
||||||
|
hostname: "0.0.0.0",
|
||||||
|
fetch: () => new Response("ok"),
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
```ts
|
||||||
|
// src/service.ts
|
||||||
|
import node from "@prisma/composer/node";
|
||||||
|
import { compute } from "@prisma/composer-prisma-cloud";
|
||||||
|
|
||||||
|
export default compute({
|
||||||
|
name: "web",
|
||||||
|
deps: {},
|
||||||
|
build: node({ module: import.meta.url, entry: "../dist/server.mjs" }),
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
```ts
|
||||||
|
// module.ts
|
||||||
|
import { module } from "@prisma/composer";
|
||||||
|
import web from "./src/service.ts";
|
||||||
|
|
||||||
|
export default module("my-app", ({ provision }) => {
|
||||||
|
provision(web);
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
```ts
|
||||||
|
// prisma.config.ts
|
||||||
|
import { defineConfig as composer } from "@prisma/composer/config";
|
||||||
|
import { nodeBuild } from "@prisma/composer/node/control";
|
||||||
|
import { prismaCloud, prismaState } from "@prisma/composer-prisma-cloud/control";
|
||||||
|
import { definePrismaConfig } from "prisma/config";
|
||||||
|
|
||||||
|
export default definePrismaConfig({
|
||||||
|
composer: composer({
|
||||||
|
extensions: [prismaCloud({ region: "us-east-1" }), nodeBuild()],
|
||||||
|
state: prismaState(),
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
And a build script in `package.json` that produces the file `entry` points at:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"scripts": {
|
||||||
|
"build": "bun build src/server.ts --target=bun --outfile dist/server.mjs"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Rules:
|
||||||
|
|
||||||
|
- `entry` and `dir` resolve relative to the service module (`module: import.meta.url`), not the project root.
|
||||||
|
- The `composer` section accepts only `extensions` and `state`. Add `nextjsBuild()` from `@prisma/composer/nextjs/control` when a service uses the `nextjs` adapter.
|
||||||
|
- `prisma.config.ts` is read by the CLI only; app code never imports it. A separate `prisma-composer.config.ts` is refused.
|
||||||
|
- Inside the module graph, write relative imports with explicit `.ts` extensions and enable `allowImportingTsExtensions` in `tsconfig.json`.
|
||||||
|
|
||||||
|
## Region
|
||||||
|
|
||||||
|
The first deploy creates the project and needs a region. Set `prismaCloud({ region })` or `PRISMA_REGION`; the config value wins when both are set. Without either, the deploy stops with `project "<name>" does not exist yet and no deploy region is configured`. Once the project exists it keeps its region, and stages inherit it.
|
||||||
|
|
||||||
|
Region ids: `us-east-1`, `us-west-1`, `eu-west-3`, `eu-central-1`, `ap-northeast-1`, `ap-southeast-1`.
|
||||||
|
|
||||||
|
## Names
|
||||||
|
|
||||||
|
- The root module name (`module("my-app", ...)`) becomes the project name and may contain hyphens. `deploy --name <name>` overrides it.
|
||||||
|
- `compute({ name })` and `provision()` ids allow `[A-Za-z0-9]` only. A hyphenated id passes `tsc` and then fails at load. The platform rejects provision ids shorter than three characters, so name a database `database`, not `db`.
|
||||||
|
|
||||||
|
## Databases
|
||||||
|
|
||||||
|
Declare the database as a dependency of the service and provision it in the module that owns it. The service reads the value with `service.load()`.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
// src/service.ts
|
||||||
|
import node from "@prisma/composer/node";
|
||||||
|
import { compute, rawPostgres } from "@prisma/composer-prisma-cloud";
|
||||||
|
|
||||||
|
export default compute({
|
||||||
|
name: "api",
|
||||||
|
deps: { db: rawPostgres() },
|
||||||
|
build: node({ module: import.meta.url, entry: "../dist/server.mjs" }),
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
```ts
|
||||||
|
// module.ts
|
||||||
|
import { module } from "@prisma/composer";
|
||||||
|
import { rawPostgres } from "@prisma/composer-prisma-cloud";
|
||||||
|
import api from "./src/service.ts";
|
||||||
|
|
||||||
|
export default module("my-app", ({ provision }) => {
|
||||||
|
const db = provision(rawPostgres({ name: "database" }));
|
||||||
|
provision(api, { deps: { db } });
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
```ts
|
||||||
|
// src/server.ts
|
||||||
|
import { SQL } from "bun";
|
||||||
|
import service from "./service.ts";
|
||||||
|
|
||||||
|
const { db } = service.load();
|
||||||
|
const sql = new SQL({ url: db.url, max: 1, idleTimeout: 10 });
|
||||||
|
```
|
||||||
|
|
||||||
|
- `rawPostgres()` comes from the package root and delivers `{ url }`. You own the client and the schema; the deploy runs no migrations for it.
|
||||||
|
- `postgres(contract)` comes from `@prisma/composer-prisma-cloud/orm`, together with `dataContract`. It delivers `{ url, client }` with a client typed by your Prisma ORM data contract, and the deploy applies the committed `migrations/` before the service starts. Every schema change goes through `prisma contract emit` and `prisma migration plan` first. See [Databases](https://www.prisma.io/docs/composer/databases).
|
||||||
|
- `postgres` is not exported from the package root in 0.28.0, and `postgres()` with no argument does not declare a plain database. Use `rawPostgres()` for that.
|
||||||
|
- Each stage gets its own empty databases. Production data is never copied.
|
||||||
|
|
||||||
|
Buckets work the same way: `bucket()` from the package root, delivering `{ url, bucket, accessKeyId, secretAccessKey }`.
|
||||||
|
|
||||||
|
## Configuration and Secrets
|
||||||
|
|
||||||
|
Composer services do not read `process.env`. Declare the service's configuration as an input schema, and bind each field at `provision()` to a literal, `envParam("NAME")`, or `envSecret("NAME")`. The named values live in the stage's platform environment variables (`project env`). A deploy copies a missing name from the deploying shell and fails early, naming the variable, when neither has it. See [Service input](https://www.prisma.io/docs/composer/service-input).
|
||||||
|
|
||||||
|
## Porting From `prisma.compute.ts`
|
||||||
|
|
||||||
|
| `prisma.compute.ts` field | Composer equivalent |
|
||||||
|
|---------------------------|---------------------|
|
||||||
|
| `app.name` / `apps.<key>` | `compute({ name })`; the root module name is the project name |
|
||||||
|
| `framework`, `build.command` | Your own `build` script, run before `deploy` |
|
||||||
|
| `entry`, `build.outputDirectory`, `build.entrypoint` | `node({ module, entry })` or `node({ module, dir, entry })` pointing at built output, or `nextjs({ module, appDir })` |
|
||||||
|
| `httpPort` | Removed. Listen on `service.port()` |
|
||||||
|
| `env` file | Platform env vars through `project env add --file`, bound with `envParam`/`envSecret`; a database becomes a declared dependency |
|
||||||
|
| `region` | `prismaCloud({ region })`, used only when the first deploy creates the project |
|
||||||
|
| `apps` (monorepo) | One `compute()` per deployable app, all provisioned in one `module.ts` |
|
||||||
|
| `--branch <name>` on deploy | `deploy --stage <name>` |
|
||||||
|
|
||||||
|
Then delete `prisma.compute.ts`, the `compute:deploy` script, and the `@prisma/compute-sdk` dev dependency if nothing else imports it. `.prisma/cli/state.json` from the old CLI is no longer used.
|
||||||
|
|
||||||
|
## Bad
|
||||||
|
|
||||||
|
```ts
|
||||||
|
// prisma.compute.ts
|
||||||
|
import { defineComputeConfig } from "@prisma/compute-sdk/config";
|
||||||
|
|
||||||
|
export default defineComputeConfig({
|
||||||
|
app: { framework: "hono", entry: "src/index.ts", httpPort: 8080 },
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
No current command reads this file.
|
||||||
|
|
||||||
|
## Good
|
||||||
|
|
||||||
|
`module.ts`, `src/service.ts`, and the `composer` section of `prisma.config.ts` as shown above, with a build script that writes the file `entry` names.
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- [Deploy your first app](https://www.prisma.io/docs/prisma-compute/deploy)
|
||||||
|
- [Port an existing app](https://www.prisma.io/docs/composer/porting-an-app)
|
||||||
|
- [Composer getting started](https://www.prisma.io/docs/composer/getting-started)
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
# app-framework-builds
|
||||||
|
|
||||||
|
Each framework deploys through a build adapter in its `service.ts` that points at the output your own build produced.
|
||||||
|
|
||||||
|
## Priority
|
||||||
|
|
||||||
|
CRITICAL
|
||||||
|
|
||||||
|
## Why It Matters
|
||||||
|
|
||||||
|
Neither `prisma deploy` nor the deploy action detects a framework or runs a build. The service declaration names the built output, and a mismatch between it and what the build writes fails at assemble time or at boot. There are no framework keys any more (`--framework nextjs` and similar belonged to the removed CLI).
|
||||||
|
|
||||||
|
## Adapters
|
||||||
|
|
||||||
|
| Adapter | Import | Use for |
|
||||||
|
|---------|--------|---------|
|
||||||
|
| `node({ module: import.meta.url, entry })` | `@prisma/composer/node` | One self-contained ESM file with every dependency inlined except runtime built-ins (`bun`, `bun:*`, `node:*`) |
|
||||||
|
| `node({ module: import.meta.url, dir, entry })` | `@prisma/composer/node` | A built directory copied as-is; `entry` is a file inside `dir` |
|
||||||
|
| `nextjs({ module: import.meta.url, appDir })` | `@prisma/composer/nextjs` | A Next.js app built with `output: "standalone"`; add `nextjsBuild()` to the `composer` extensions |
|
||||||
|
| `dependencies: "external"` on either `node()` form | `@prisma/composer/node` | A build that leaves packages as imports. The deploy traces `entry` and stages the installed packages it imports, which can take minutes. Composer 0.29.0 and later |
|
||||||
|
|
||||||
|
Paths are relative to the service module. With the default `dependencies: "bundled"`, the deploy copies only what the build produced and never ships the project's `node_modules`, for a single file and for a `dir` build alike, so a package left as an import fails at boot with `Cannot find package`. Bundle it, or set `dependencies: "external"`. A `dir` tree must contain no symlinks and `entry` must not leave `dir`. Two services in one package need two separate builds, one per entry.
|
||||||
|
|
||||||
|
## Per Framework
|
||||||
|
|
||||||
|
The shapes `create-prisma` 0.14.1 generates, with `service.ts` at the project root:
|
||||||
|
|
||||||
|
| Framework | Build script | `build:` in `service.ts` | Requirements |
|
||||||
|
|-----------|--------------|--------------------------|--------------|
|
||||||
|
| Hono, Elysia, NestJS, plain server | Bundle to one file (`bun build src/index.ts --target=bun --outfile dist/server.mjs`, or tsdown bundling every non-built-in dependency) | `node({ module: import.meta.url, entry: "./dist/server.mjs" })` | The entry starts the HTTP server itself |
|
||||||
|
| Next.js | `next build` | `nextjs({ module: import.meta.url, appDir: "." })` | `output: "standalone"` in `next.config.*`; `nextjsBuild()` in `prisma.config.ts` |
|
||||||
|
| Nuxt | `nuxt build` | `node({ module: import.meta.url, dir: "./.output", entry: "server/index.mjs" })` | Default Nitro Node server preset |
|
||||||
|
| TanStack Start | `vite build` | `node({ module: import.meta.url, dir: "./.output", entry: "server/index.mjs" })` | `nitro()` from `nitro/vite` in the Vite plugins |
|
||||||
|
| Astro | `astro build` | `node({ module: import.meta.url, dir: "./dist", entry: "server/entry.mjs", dependencies: "external" })` | `output: "server"`, `adapter: node({ mode: "standalone" })` from `@astrojs/node`. The adapter leaves packages as imports, so Composer 0.29.0 and later need `dependencies: "external"`; `create-prisma` 0.14.x pins Composer 0.28.0 and omits it |
|
||||||
|
| SvelteKit | `vite build` | `node({ module: import.meta.url, dir: "./build", entry: "index.js" })` | `@sveltejs/adapter-node`, with `ssr: { noExternal: true }` in `vite.config.ts` so the build inlines packages; without it, add `dependencies: "external"` |
|
||||||
|
| Turborepo | `turbo run build` | `node({ module: import.meta.url, entry: "./apps/server/dist/server.mjs" })` | One `compute()` per deployable app |
|
||||||
|
|
||||||
|
Verify the actual output path after a local build before writing `entry` or `dir`.
|
||||||
|
|
||||||
|
## Host and Port
|
||||||
|
|
||||||
|
The runtime exports the reserved port as `PORT` and sets `HOST` to `0.0.0.0` when it is unset. Code you write reads `service.port()` and binds `0.0.0.0`. Framework servers that read `PORT` themselves (Next.js standalone, Nitro, Astro's Node adapter, SvelteKit's Node adapter) work without changes. Never set `HOST` or `HOSTNAME` to `localhost` or `127.0.0.1` in deploy env.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
// Elysia
|
||||||
|
app.listen({ port: service.port(), hostname: "0.0.0.0" });
|
||||||
|
|
||||||
|
// NestJS
|
||||||
|
await app.listen(service.port(), "0.0.0.0");
|
||||||
|
```
|
||||||
|
|
||||||
|
## Next.js Pages That Read the Service
|
||||||
|
|
||||||
|
A page, route handler, or server action that calls `service.load()` or `service.input()` needs `export const dynamic = "force-dynamic"`. The runtime environment does not exist at build time, and Next.js does not re-read it for prerendered routes.
|
||||||
|
|
||||||
|
## Bad
|
||||||
|
|
||||||
|
```ts
|
||||||
|
build: node({ module: import.meta.url, entry: "./src/index.ts" }),
|
||||||
|
```
|
||||||
|
|
||||||
|
The entry is source, not a self-contained build. Imports from `node_modules` fail at boot.
|
||||||
|
|
||||||
|
## Good
|
||||||
|
|
||||||
|
```ts
|
||||||
|
build: node({ module: import.meta.url, entry: "./dist/server.mjs" }),
|
||||||
|
```
|
||||||
|
|
||||||
|
with `"build": "bun build src/index.ts --target=bun --outfile dist/server.mjs"`.
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- [Port an existing app](https://www.prisma.io/docs/composer/porting-an-app)
|
||||||
|
- [Framework guides](https://www.prisma.io/docs/guides)
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
# automation-create-prisma
|
||||||
|
|
||||||
|
`create-prisma` scaffolds a new Prisma 8 project that is already a Composer app, and can deploy it once.
|
||||||
|
|
||||||
|
## Priority
|
||||||
|
|
||||||
|
MEDIUM
|
||||||
|
|
||||||
|
## Why It Matters
|
||||||
|
|
||||||
|
`create-prisma` writes a working Composer app in one command, but only for new projects, and its `--json` mode deploys by default. Older versions generated `prisma.compute.ts` and a `compute:deploy` script; current versions generate `module.ts`, `service.ts`, and a `composer` section instead.
|
||||||
|
|
||||||
|
Verified with `create-prisma` 0.14.1.
|
||||||
|
|
||||||
|
## Commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx create-prisma@latest --help
|
||||||
|
```
|
||||||
|
|
||||||
|
| Flag | Meaning |
|
||||||
|
|------|---------|
|
||||||
|
| `[project-name]`, `--name` | Project directory and root module name |
|
||||||
|
| `--template` | `minimal`, `hono`, `elysia`, `nest`, `next`, `turborepo`, `svelte`, `astro`, `nuxt`, `tanstack-start` |
|
||||||
|
| `--provider` | `postgres` or `mongo` |
|
||||||
|
| `--authoring` | `psl` or `typescript` for the data contract |
|
||||||
|
| `--package-manager` | `npm`, `pnpm`, `yarn`, `bun`, `deno` |
|
||||||
|
| `--deploy` | Build and deploy after scaffolding |
|
||||||
|
| `--workspace` | Workspace id or name to deploy into |
|
||||||
|
| `--skills` | Agents to install package skills for (`claude,cursor,agents,devin`), or `none` |
|
||||||
|
| `--yes` | Accept defaults; does not deploy |
|
||||||
|
| `--json` | One JSON result, non-interactive; deploys unless `--no-deploy` |
|
||||||
|
|
||||||
|
When to deploy:
|
||||||
|
|
||||||
|
| Invocation | Deploys |
|
||||||
|
|------------|---------|
|
||||||
|
| `--deploy` | Yes |
|
||||||
|
| `--json` without `--no-deploy` | Yes |
|
||||||
|
| `--yes` without `--deploy` or `--json` | No |
|
||||||
|
| Interactive | Asks |
|
||||||
|
| `--package-manager deno` | Never; no Composer files are generated |
|
||||||
|
|
||||||
|
For an unattended scaffold with no deploy, pass both:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx create-prisma@latest my-api --template hono --provider postgres --yes --json --no-deploy
|
||||||
|
```
|
||||||
|
|
||||||
|
## What It Generates
|
||||||
|
|
||||||
|
- `module.ts` provisioning one service named `app`. With `--provider postgres`, it also provisions `postgres({ name: "database", contract, config: "./prisma.config.ts" })` from `@prisma/composer-prisma-cloud/orm`, so the deploy applies the generated migrations. With `--provider mongo`, it binds `envSecret("MONGODB_URL")` to the service input.
|
||||||
|
- `service.ts` with the build adapter for the template; see [`app-framework-builds.md`](app-framework-builds.md).
|
||||||
|
- `prisma.config.ts` with `orm`, `skills`, and `composer` sections. The `composer` section uses `prismaCloud({ region: "us-east-1" })`; change the region before the first deploy if the app belongs elsewhere.
|
||||||
|
- Scripts: `composer:dev` (`prisma dev module.ts`), `composer:deploy` (`prisma deploy module.ts`), `dev:composer` (build, then `composer:dev`), and `deploy` (build, then `composer:deploy`). The `deploy` script targets production; pass a stage with `npx prisma deploy module.ts --stage <name>` instead.
|
||||||
|
- `/.prisma-composer` in `.gitignore`.
|
||||||
|
|
||||||
|
## Deploy Flow
|
||||||
|
|
||||||
|
With deploy enabled, `create-prisma` runs `prisma auth whoami`, selects the workspace, checks that no project already has the app's name, runs the build script, and runs `prisma deploy module.ts --report <tmp>`. Without a session it signs in interactively in a terminal; in `--json` mode or without a TTY it stops with `not_authenticated`, keeps the scaffold, and tells the user to sign in and run the `deploy` script.
|
||||||
|
|
||||||
|
## Rules
|
||||||
|
|
||||||
|
- Do not run `create-prisma` inside an existing app to deploy it. Port the app ([`app-composer-setup.md`](app-composer-setup.md)) and use `prisma deploy`.
|
||||||
|
- Use the scripts the scaffold actually wrote; read `package.json` rather than reconstructing them.
|
||||||
|
- A scaffold's first deploy is production. Ask the user before using `--deploy` or `--json` without `--no-deploy`.
|
||||||
|
|
||||||
|
## Bad
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx create-prisma@latest my-api --template hono --yes --json
|
||||||
|
```
|
||||||
|
|
||||||
|
This deploys to production without anyone deciding to.
|
||||||
|
|
||||||
|
## Good
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx create-prisma@latest my-api --template hono --provider postgres --yes --json --no-deploy
|
||||||
|
cd my-api
|
||||||
|
npm run dev:composer
|
||||||
|
```
|
||||||
|
|
||||||
|
Verify locally, then deploy a stage with `npm run build && npx prisma deploy module.ts --stage preview`.
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- [create-prisma on npm](https://www.npmjs.com/package/create-prisma)
|
||||||
|
- [Deploy your first app](https://www.prisma.io/docs/prisma-compute/deploy)
|
||||||
@@ -0,0 +1,99 @@
|
|||||||
|
# automation-rest-api
|
||||||
|
|
||||||
|
Programmatic access to Compute: the Management REST API, the Composer control API, and what became of `@prisma/compute-sdk`.
|
||||||
|
|
||||||
|
## Priority
|
||||||
|
|
||||||
|
MEDIUM
|
||||||
|
|
||||||
|
## Why It Matters
|
||||||
|
|
||||||
|
Deploys now go through Composer, so low-level deploy clients from the earlier flow create resources that no `module.ts` declares. Use the CLI or the control API to deploy, and the REST API to read state, stream logs, and integrate with other tools.
|
||||||
|
|
||||||
|
## Choose the Surface
|
||||||
|
|
||||||
|
| Goal | Use |
|
||||||
|
|------|-----|
|
||||||
|
| Deploy or tear down an app | `prisma deploy`, or `deploy`/`destroy` from `@prisma/composer/control` |
|
||||||
|
| Deploy from GitHub | `prisma/cloud-deploy-action` ([`deploy-on-push.md`](deploy-on-push.md)) |
|
||||||
|
| Read services, versions, builds, logs from your own tool | REST API |
|
||||||
|
| A coding agent with its own credential and approval policy | [Agent enrollment](https://www.prisma.io/docs/prisma-compute/agent-enrollment) (REST API) |
|
||||||
|
|
||||||
|
## REST API
|
||||||
|
|
||||||
|
Base URL `https://api.prisma.io/v1`. The current OpenAPI document is at `https://api.prisma.io/v1/doc`; read it for exact payloads instead of copying shapes from memory. Authenticate with `Authorization: Bearer <workspace service token>` or an OAuth token. The Compute endpoints are marked experimental and can change.
|
||||||
|
|
||||||
|
| Resource | Paths |
|
||||||
|
|----------|-------|
|
||||||
|
| Projects | `GET/POST /v1/projects`, `GET/PATCH/DELETE /v1/projects/{id}` |
|
||||||
|
| Branches | `GET/POST /v1/projects/{projectId}/branches` (`gitName` filter), `GET/PATCH/DELETE /v1/branches/{branchId}` |
|
||||||
|
| Services | `GET/POST /v1/services` (filter by `projectId`, `branchId`, `branchGitName`), `GET/PATCH/DELETE /v1/services/{serviceId}` |
|
||||||
|
| Versions (deployments) | `GET/POST /v1/services/{serviceId}/deployments`, `GET/DELETE /v1/deployments/{deploymentId}`, `POST /v1/deployments/{deploymentId}/start`, `POST /v1/deployments/{deploymentId}/stop` |
|
||||||
|
| Promote and rollback | `POST /v1/services/{serviceId}/promote`, `POST /v1/services/{serviceId}/rollback` |
|
||||||
|
| Logs | `GET /v1/deployments/{deploymentId}/logs` |
|
||||||
|
| Builds | `GET/POST /v1/builds` (filter by `projectId`, `branchId`, `state`), `GET/PATCH /v1/builds/{buildId}` |
|
||||||
|
| Domains | `GET/POST /v1/services/{serviceId}/domains`, `GET/DELETE /v1/domains/{domainId}`, `POST /v1/domains/{domainId}/retry` |
|
||||||
|
| Environment variables | `GET/POST /v1/environment-variables` (filter by `projectId`, `class`, `key`, `branchId`), `GET/PATCH/DELETE /v1/environment-variables/{envVarId}` |
|
||||||
|
|
||||||
|
The `/v1/apps` paths (`/v1/apps`, `/v1/apps/{appId}/deployments`, `/promote`, `/rollback`, `/domains`) are deprecated. Use the `/v1/services` equivalents.
|
||||||
|
|
||||||
|
### Logs
|
||||||
|
|
||||||
|
`GET /v1/deployments/{deploymentId}/logs` takes `tail`, `from_start`, or `cursor`. A plain GET returns newline-delimited JSON: `type: "log"` records, then a `type: "terminal"` record carrying the cursor for the next page. Send `Upgrade: websocket` to follow live; a live segment ends after 10 minutes with the same terminal record, so reconnect with the cursor.
|
||||||
|
|
||||||
|
### Builds
|
||||||
|
|
||||||
|
A build record is what a deploy reports about itself: the deploy action and `prisma deploy` both write to it. `GET /v1/builds/{buildId}` returns its `state`, `failingStep`, `errorMessage`, `externalLogUrl` (for example the GitHub Actions run), and `deployedUrl`. There is no build log endpoint; the log lives at `externalLogUrl` or in the terminal that ran the deploy. `prisma deploy --build-id <id>` joins a build record your CI created with `POST /v1/builds`.
|
||||||
|
|
||||||
|
### Secrets
|
||||||
|
|
||||||
|
Environment variable values are write-only: no endpoint returns them. Do not log tokens, connection URLs, or env values.
|
||||||
|
|
||||||
|
## Control API
|
||||||
|
|
||||||
|
`@prisma/composer/control` runs the CLI's operations in-process and returns `{ ok: true, value }` or `{ ok: false, failure }` with a dotted `failure.code`:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { deploy } from "@prisma/composer/control";
|
||||||
|
import prismaConfig from "./prisma.config.ts";
|
||||||
|
|
||||||
|
const result = await deploy({
|
||||||
|
entry: "module.ts",
|
||||||
|
config: { value: prismaConfig.composer, file: "prisma.config.ts" },
|
||||||
|
stage: "pr-42",
|
||||||
|
});
|
||||||
|
if (!result.ok) throw new Error(`${result.failure.code}: ${result.failure.message}`);
|
||||||
|
```
|
||||||
|
|
||||||
|
- Operations: `deploy`, `destroy`, `dev`, `log`. `config` is required in 0.28.0.
|
||||||
|
- `deploy` and `destroy` read only `PRISMA_SERVICE_TOKEN` and `PRISMA_WORKSPACE_ID`, never the `auth login` session. Without them they fail with `environment variable PRISMA_WORKSPACE_ID is required`.
|
||||||
|
- `log` tails a locally running `prisma dev` app; it is not a platform log reader.
|
||||||
|
- The engine's own output still streams to stdio.
|
||||||
|
|
||||||
|
## `@prisma/compute-sdk`
|
||||||
|
|
||||||
|
`@prisma/compute-sdk` 0.43.0 is still on npm, and the CLI uses it internally for service operations and log streaming. Its `deploy()` build strategies and `defineComputeConfig` belong to the removed flow: no CLI command reads `prisma.compute.ts`, and its app client calls the deprecated `/v1/apps` endpoints. Do not start new deploy automation on it, and remove it from projects that used it only for `defineComputeConfig`.
|
||||||
|
|
||||||
|
## Bad
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { ComputeClient, PreBuilt } from "@prisma/compute-sdk";
|
||||||
|
|
||||||
|
await new ComputeClient(apiClient).deploy({
|
||||||
|
strategy: new PreBuilt({ appPath: "./dist", entrypoint: "index.js" }),
|
||||||
|
projectId: "proj_abc",
|
||||||
|
appName: "my-app",
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
This creates an app outside any Composer declaration, through deprecated endpoints.
|
||||||
|
|
||||||
|
## Good
|
||||||
|
|
||||||
|
Deploy with `prisma deploy module.ts` or the control API, and read the result back with `GET /v1/services?projectId=...` and `GET /v1/deployments/{deploymentId}/logs`.
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- [REST API](https://www.prisma.io/docs/rest-api)
|
||||||
|
- [OpenAPI document](https://api.prisma.io/v1/doc)
|
||||||
|
- [`deploy` command and control API](https://www.prisma.io/docs/cli/deploy)
|
||||||
@@ -0,0 +1,137 @@
|
|||||||
|
# cli-command-map
|
||||||
|
|
||||||
|
The Prisma 8 CLI commands an agent uses to deploy and operate a Compute app, with the flags, output, and targeting rules that matter.
|
||||||
|
|
||||||
|
## Priority
|
||||||
|
|
||||||
|
CRITICAL
|
||||||
|
|
||||||
|
## Why It Matters
|
||||||
|
|
||||||
|
Agents trained on the earlier Compute CLI reach for `@prisma/cli app deploy`, `build logs`, and `database ...`, which no longer exist. The current CLI also refuses to guess: it needs explicit targets, exact consent tokens for destructive actions, and the Prisma 8 binary.
|
||||||
|
|
||||||
|
Verified with `prisma` 8.0.0-rc.21 and `@prisma/cli` 8.0.0-rc.21 (same commands; the `@prisma/cli` binary is named `prisma-cli`).
|
||||||
|
|
||||||
|
## Which Binary Runs
|
||||||
|
|
||||||
|
| Situation | Run |
|
||||||
|
|-----------|-----|
|
||||||
|
| Composer app with `prisma` 8.x in `devDependencies` | `npx prisma <command>` (or `bunx prisma`, `pnpm exec prisma`) |
|
||||||
|
| No local `prisma`, or a Prisma 6/7 project | `npx @prisma/cli@latest <command>` |
|
||||||
|
|
||||||
|
A Prisma 6 or 7 `prisma` binary has no `auth`, `project`, `service`, `branch`, `git`, or `deploy` commands. In Prisma 7, `dev` starts a local Prisma Postgres server and `postgres` only links an existing database. `npx prisma --version` prints the version; in a non-terminal it prints a JSON envelope with `result.version`.
|
||||||
|
|
||||||
|
## Commands
|
||||||
|
|
||||||
|
| Command | Subcommands and flags | Notes |
|
||||||
|
|---------|-----------------------|-------|
|
||||||
|
| `auth` | `login`, `logout`, `whoami`, `workspace list`, `workspace use [id-or-name]`, `workspace logout <id-or-name>` | `login` opens a browser. `logout` ends every stored session |
|
||||||
|
| `project` | `list`, `show [id-or-name]`, `create <name> [--region]`, `link [id-or-name]`, `rename <name>`, `delete <id-or-name>`, `transfer <id-or-name>` | `create` and `link` write `.prisma/local.json` and gitignore it |
|
||||||
|
| `project env` | `add [KEY=VALUE\|KEY]`, `update`, `list`, `delete <key>`; scope with `--role production\|preview` or `--branch <git-name>`; `--file <dotenv>` for `add`/`update` | Values are write-only |
|
||||||
|
| `postgres` | `list`, `show`, `create <name> [--region] [--branch]`, `usage`, `delete`, `backup list\|restore`, `connection list\|create\|rotate\|delete` | Connection URLs print once |
|
||||||
|
| `bucket` | `list`, `create [--name] [--branch]`, `delete <bucket-id>`, `key list\|create\|delete` | Keys print once |
|
||||||
|
| `branch` | `list` | No create or delete |
|
||||||
|
| `git` | `connect [git-url]`, `disconnect` | `connect` needs an interactive terminal |
|
||||||
|
| `service` | `list`, `create <name> [--region] [--branch]`, `show <service>`, `open <service>`, `logs <service>`, `delete <service>` | `--project`, `--branch` on each |
|
||||||
|
| `service version` | `list <service>`, `show <id>`, `promote <id>`, `rollback <service> [--to <id>]`, `start <id>`, `stop <id>`, `delete <id>` | Version ids look like `cpv_...` |
|
||||||
|
| `service domain` | `add`, `show`, `wait [--timeout]`, `retry`, `delete`, each `<hostname> --service <service>` | Production branch only |
|
||||||
|
| `deploy <entry>` | `--name`, `--stage`, `--report <path>`, `--build-id <id>` | Composer app; does not build |
|
||||||
|
| `dev <entry>` | `--name`, `--fresh` | Composer app, local, no credentials |
|
||||||
|
| `init` | `--skills <agents>`, `--postinstall/--no-postinstall` | Local only; never edits an existing `prisma.config.ts` |
|
||||||
|
| `skills` | `sync [--disable\|--enable]`, `list` | Copies package-shipped skills |
|
||||||
|
| `feedback <message>` | `--email <address>` | Anonymous unless `--email` |
|
||||||
|
|
||||||
|
`contract`, `db`, `migration`, `orm`, `lsp`, and `telemetry` belong to Prisma ORM and the CLI itself; they are outside this skill. There is no `destroy`, `log`, `app`, `build`, `database`, `agent`, or `compute` command.
|
||||||
|
|
||||||
|
## Global Flags
|
||||||
|
|
||||||
|
Every command accepts these:
|
||||||
|
|
||||||
|
- `--json` (same as `--format json`), or `--format human|json|markdown`
|
||||||
|
- `--interactive` / `--no-interactive`
|
||||||
|
- `--yes`: accept prompt defaults; it cannot grant consent
|
||||||
|
- `--confirm <token>`: grant one consent prompt; repeat for several
|
||||||
|
- `--config <path>`: read another config file instead of `./prisma.config.ts`
|
||||||
|
- `--log-level error|warn|info|verbose`, `-v`, `-q`, `--color/--no-color`
|
||||||
|
|
||||||
|
When stdout is not a terminal the CLI already writes JSON; pass `--json` anyway so the intent is explicit. When `CI` is set (and not `false`), prompts are off.
|
||||||
|
|
||||||
|
## JSON Output
|
||||||
|
|
||||||
|
Each command prints one envelope:
|
||||||
|
|
||||||
|
```json
|
||||||
|
{"kind":"result","envelope":{"ok":false,"commandId":"","error":{"code":"CLI.UNKNOWN_COMMAND","summary":"No command registered for `app`","nextActions":[{"kind":"run-command","command":"prisma --help"}]},"nextActions":[]}}
|
||||||
|
```
|
||||||
|
|
||||||
|
On success, `envelope.ok` is `true` and `envelope.result` holds the data. On failure, branch on `envelope.error.code`; codes are a stable contract and messages are not. Codes you will meet:
|
||||||
|
|
||||||
|
| Code | Meaning |
|
||||||
|
|------|---------|
|
||||||
|
| `CLI.UNKNOWN_COMMAND` | The command does not exist in this CLI version |
|
||||||
|
| `CLI.INVALID_ARGUMENTS` | Unknown flag or bad argument |
|
||||||
|
| `CLI.CONSENT_REQUIRED` | A destructive action needs `--confirm <token>` |
|
||||||
|
| `CLI.INTERACTION_REQUIRED` | The command needs an interactive terminal (`git connect`, `auth login`) |
|
||||||
|
| `CLI.CREDENTIALS_REQUIRED` | No stored session and no `PRISMA_SERVICE_TOKEN` |
|
||||||
|
| `PROJECT.SETUP_REQUIRED` | No `--project` and no `.prisma/local.json` link |
|
||||||
|
| `SERVICE.TARGET_REQUIRED` | The service argument is missing |
|
||||||
|
| `SERVICE.NO_PREVIOUS_VERSION` | `rollback` without `--to` found nothing to roll back to |
|
||||||
|
| `CLI.CONFIG_UNREADABLE` | `prisma.config.ts` failed to evaluate (often an `effect` version conflict) |
|
||||||
|
|
||||||
|
`deploy --json` also emits step events and ends with `envelope.result.summary.nodes[].entities[]`, where each entity has `kind` (`compute-service`, `postgres-database`), `id`, and, for services, `url`.
|
||||||
|
|
||||||
|
## Targeting
|
||||||
|
|
||||||
|
- **Project:** `--project <id-or-name>`, else the `.prisma/local.json` link, else `PROJECT.SETUP_REQUIRED`. Only `project create` and `project link` write the link; `deploy` does not.
|
||||||
|
- **Branch:** `--branch <git-name>`. Without it, commands target the project's default branch, which is production. The current Git branch is not consulted.
|
||||||
|
- **Service:** the first positional argument. There is no picker and no environment fallback.
|
||||||
|
- **Version:** version ids are globally unique, so `service version show|promote|start|stop|delete <id>` need no other scope.
|
||||||
|
|
||||||
|
Environment variables the CLI reads for the Platform: `PRISMA_SERVICE_TOKEN` (overrides stored sessions; a set-but-empty value is an error), `PRISMA_WORKSPACE_ID` (the workspace for a service token), `PRISMA_REGION` (region for a project the first deploy creates), and `PRISMA_COMPOSER_REPORT_FILE` (same as `--report`). `PRISMA_SKILLS_CHECK=0` silences the out-of-date skills notice. It does not read `PRISMA_PROJECT_ID`, `PRISMA_APP_ID`, or `PRISMA_SERVICE_ID`.
|
||||||
|
|
||||||
|
## Consent Tokens
|
||||||
|
|
||||||
|
These commands stop at a consent prompt. In a non-interactive run, pass the token with `--confirm`; `--yes` fails with `CLI.CONSENT_REQUIRED`.
|
||||||
|
|
||||||
|
| Command | Token |
|
||||||
|
|---------|-------|
|
||||||
|
| `project delete <project>` | Project id |
|
||||||
|
| `project transfer <project>` | Project id |
|
||||||
|
| `postgres delete <database>` | Database id |
|
||||||
|
| `postgres backup restore <database> --backup <id>` | Target database id |
|
||||||
|
| `postgres connection rotate <connection-id>` | Connection id |
|
||||||
|
| `postgres connection delete <connection-id>` | Connection id |
|
||||||
|
| `bucket delete <bucket-id>` | Bucket id |
|
||||||
|
| `service delete <service>` | Service name |
|
||||||
|
| `service version delete <version-id>` | Version id |
|
||||||
|
| `service version rollback <service> --to <version-id>` | Target version id |
|
||||||
|
| `service domain delete <hostname>` | Hostname |
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx prisma service version rollback api --project my-app --to cpv_123 --confirm cpv_123 --json
|
||||||
|
```
|
||||||
|
|
||||||
|
Run a consent-gated command only when the user asked for that specific action.
|
||||||
|
|
||||||
|
## Bad
|
||||||
|
|
||||||
|
```bash
|
||||||
|
bunx @prisma/cli@latest app deploy --prod --yes --env .env
|
||||||
|
npx prisma service delete api --yes
|
||||||
|
```
|
||||||
|
|
||||||
|
`app deploy` fails with `CLI.UNKNOWN_COMMAND`, and `--yes` cannot answer the consent prompt for `service delete`.
|
||||||
|
|
||||||
|
## Good
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run build
|
||||||
|
npx prisma deploy module.ts --stage feat-search --json
|
||||||
|
npx prisma service delete api --branch feat-search --confirm api --json
|
||||||
|
```
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- [CLI reference](https://www.prisma.io/docs/cli)
|
||||||
|
- [Global flags](https://www.prisma.io/docs/cli/global-flags)
|
||||||
|
- [Error reference](https://www.prisma.io/docs/cli/error-reference)
|
||||||
@@ -0,0 +1,121 @@
|
|||||||
|
# debug-deploy-failures
|
||||||
|
|
||||||
|
Diagnose Compute failures from the error code first, then the symptom.
|
||||||
|
|
||||||
|
## Priority
|
||||||
|
|
||||||
|
HIGH
|
||||||
|
|
||||||
|
## Why It Matters
|
||||||
|
|
||||||
|
Most failures carry a structured code and a `nextActions` list that names the fix. Guessing from the message, or retrying commands from the removed CLI, wastes the user's time and can deploy into the wrong place.
|
||||||
|
|
||||||
|
## First Checks
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx prisma --version
|
||||||
|
npx prisma auth whoami --json
|
||||||
|
npx prisma project show --json
|
||||||
|
ls module.ts prisma.config.ts
|
||||||
|
node --version
|
||||||
|
test -f .env && sed 's/=.*/=<redacted>/' .env
|
||||||
|
```
|
||||||
|
|
||||||
|
Re-run the failing command with `--json` (and `--report deploy-report.json` for `deploy`) and read `error.code`, `error.why`, and `nextActions`. Never print token or connection-string values.
|
||||||
|
|
||||||
|
## CLI and Setup
|
||||||
|
|
||||||
|
| Symptom | Cause | Fix |
|
||||||
|
|---------|-------|-----|
|
||||||
|
| `CLI.UNKNOWN_COMMAND` for `app`, `build`, `database`, `agent`, `destroy`, `compute` | The command was removed | Use the replacement in the SKILL.md table |
|
||||||
|
| `Unknown command "auth"` or `"deploy"`, or `prisma dev` starts a database server | A Prisma 6 or 7 `prisma` binary | Install `prisma` 8.x as a dev dependency, or use `npx @prisma/cli@latest` |
|
||||||
|
| `ERR_UNKNOWN_FILE_EXTENSION` | Node.js too old to load `module.ts`. Composer supports 22.18 or newer on the 22 line, 24.11 or newer on the 24 line, or 26 or newer | Upgrade Node.js |
|
||||||
|
| `CLI.CONFIG_UNREADABLE` with a module error from `effect` | Another `effect` version hoisted over the one `@prisma/composer` pins | Match the app's `effect` to `@prisma/composer`'s `dependencies.effect`, or force it with `overrides` (npm), `pnpm.overrides` or `pnpm-workspace.yaml` `overrides` (pnpm), `resolutions` (Yarn); reinstall |
|
||||||
|
| `CLI.CONFIG_SECTION_INVALID` with `CONFIG.SECTION_MISSING` | No `composer` section in `prisma.config.ts` | Add the section ([`app-composer-setup.md`](app-composer-setup.md)) |
|
||||||
|
| `CONFIG.FILE_RETIRED` or `CONFIG.FIELD_RETIRED` | A `prisma-composer.config.ts` or `configPath` from an older Composer | Move `extensions` and `state` into the `composer` section and delete the old file |
|
||||||
|
| `ASSEMBLE.EXTENSION_MISSING` | A service uses `nextjs()` but `nextjsBuild()` is not in `extensions` | Add `nextjsBuild()` from `@prisma/composer/nextjs/control` |
|
||||||
|
| `COMPOSE.GRAPH_INVALID` naming an id | A provision id or service name with a hyphen or other non-alphanumeric character | Use `[A-Za-z0-9]` only; at least three characters for provision ids |
|
||||||
|
| Bun APIs fail while the CLI loads `module.ts` | The `prisma` bin runs under Node | `bun node_modules/.bin/prisma deploy module.ts` |
|
||||||
|
|
||||||
|
## Auth and Project
|
||||||
|
|
||||||
|
| Symptom | Cause | Fix |
|
||||||
|
|---------|-------|-----|
|
||||||
|
| `CLI.CREDENTIALS_REQUIRED` | No session and no service token | Ask the user to run `npx prisma auth login`; in CI set `PRISMA_SERVICE_TOKEN` and `PRISMA_WORKSPACE_ID` |
|
||||||
|
| Error about a blank `PRISMA_SERVICE_TOKEN` | The variable is set but empty | Unset it or provide a token |
|
||||||
|
| Commands act in the wrong workspace | Another stored session is current, or a service token overrides it | `auth workspace list --json`, then `auth workspace use <id>`; unset `PRISMA_SERVICE_TOKEN` to use sessions |
|
||||||
|
| `PROJECT.SETUP_REQUIRED` after a successful deploy | `deploy` does not link the directory | `npx prisma project link <app-name>` or pass `--project` |
|
||||||
|
| `project "<name>" does not exist yet and no deploy region is configured` | First deploy without a region | `prismaCloud({ region })` or `PRISMA_REGION` |
|
||||||
|
| Deploy refuses an existing project name (`HostedStateBootstrapError`, or `a project with this name already exists`) | A project with the module's name exists that this module did not create | `deploy --name <unique-name>`, or rename the module |
|
||||||
|
| Deploy fails immediately naming another holder | Another deploy of the same environment holds the state lease | Wait for it; a crashed deploy's lease expires after about a minute |
|
||||||
|
|
||||||
|
## Deploy Pipeline
|
||||||
|
|
||||||
|
| Symptom | Cause | Fix |
|
||||||
|
|---------|-------|-----|
|
||||||
|
| `ASSEMBLE.BUILD_FAILED` | The built entry or directory is missing or invalid (no build, wrong path, symlinks in a `dir` build) | Run the build and check that `entry`/`dir` match its output, relative to `service.ts` |
|
||||||
|
| `ASSEMBLE.SERVICE_MISSING` | The module provisions no service | Provision at least one `compute()` service |
|
||||||
|
| `DEPLOY.STAGE_INVALID` | The stage is not a valid Git ref name | Rename the stage |
|
||||||
|
| A connection input "declares param ..., but its producer ... did not supply it" | An authored connection or extension does not supply a declared value | Fix the producer's outputs; mark the param optional only if absent is valid |
|
||||||
|
| Deploy fails early naming a missing variable | An `envParam`/`envSecret` name is unset on the stage and in the shell | Export it in the deploying shell or set it with `project env add` |
|
||||||
|
| `MIGRATION_PATH_NOT_FOUND` | A `postgres(contract)` schema change has no committed migration | `prisma contract emit`, `prisma migration plan --name <slug>`, commit `migrations/` |
|
||||||
|
| `DEPLOY.ENGINE_FAILED` | The deploy engine or the platform rejected the generated stack | Read the engine lines in the error; it names `.prisma-composer/alchemy.run.ts` and a command that reproduces the failure |
|
||||||
|
| `DEPLOY.BUILD_REQUIRED` from `destroy` | `destroy` packages the built app too | Build, then destroy |
|
||||||
|
|
||||||
|
## Deployed but Not Working
|
||||||
|
|
||||||
|
| Symptom | Cause | Fix |
|
||||||
|
|---------|-------|-----|
|
||||||
|
| Public URL times out or returns 502 at once | Listener on `localhost`, wrong port, or a crash at boot | Bind `0.0.0.0` on `service.port()`; read `npx prisma service logs <service>` |
|
||||||
|
| `Cannot find package`, `Cannot find module`, or `ENOENT while resolving package` in logs | The build left a package as an import, and the default `dependencies: "bundled"` ships only the build output | Bundle every dependency (`bun build --target=bun`), or set `dependencies: "external"` on `node()` so the deploy stages the installed packages |
|
||||||
|
| 502s in a loop after the app was idle | A database client dies when idle connections close | Small reconnect-friendly pool; log `uncaughtException` and `unhandledRejection` instead of exiting |
|
||||||
|
| `504 Gateway Time-out` with an `openresty` body after about 60 seconds | The handler sent nothing for 60 seconds | Respond first, continue under `waitUntil`, or queue the work |
|
||||||
|
| Background work stops or never finishes | The instance slept | `waitUntil` or `KeepAwakeGuard` from `@prisma/compute`; persist progress |
|
||||||
|
| `401` from a deployed `/rpc/<method>` | Composer's service-key check; only wired consumers may call | Test through a consumer or locally; not a deploy failure |
|
||||||
|
| `RUNTIME.TEMPORAL_UNAVAILABLE` or a failure on the first timestamp read | No global `Temporal` on the runtime | Import a Temporal polyfill at the server entry, or use string column types |
|
||||||
|
| Next.js page shows build-time or missing values from `service.load()` | The route was prerendered | `export const dynamic = "force-dynamic"` |
|
||||||
|
| `ECONNRESET` calling another service | The callee was cold-starting | Retry |
|
||||||
|
| A changed env var has no effect | Values resolve at deploy time | Redeploy (or promote) |
|
||||||
|
| A resource disappeared after a deploy | Its `provision()` was removed from `module.ts` | Restore the declaration and redeploy |
|
||||||
|
| A preview's database is empty | Stages get their own empty databases | Seed it; production data is never copied |
|
||||||
|
|
||||||
|
## Deploy on Push
|
||||||
|
|
||||||
|
| Symptom | Cause | Fix |
|
||||||
|
|---------|-------|-----|
|
||||||
|
| Push builds nothing, no error | No workflow on the pushed branch | Add `.github/workflows/prisma-deploy.yml` ([`deploy-on-push.md`](deploy-on-push.md)) |
|
||||||
|
| Green run with `skipped-no-credential` | Repository not connected, no `id-token: write`, or a fork | `npx prisma git connect`, add the permission |
|
||||||
|
| `CLI.UNKNOWN_COMMAND` inside the action | Action release v1.5.0 or older | Use `prisma/cloud-deploy-action@v1` (v1.9.0 or later) |
|
||||||
|
| Install step fails on pnpm or Yarn | The action auto-detects npm and Bun only | Set `install-command` |
|
||||||
|
|
||||||
|
## Custom Domains
|
||||||
|
|
||||||
|
`npx prisma service domain show <hostname> --service <service> --json` prints the state and the DNS record it expects. `SERVICE.DOMAIN_DNS_NOT_CONFIGURED` means the CNAME is not visible yet; create it, then run `add` again. After fixing DNS on a `failed` domain, run `service domain retry`. `SERVICE.BRANCH_NOT_DEPLOYABLE` means a preview branch was targeted; domains are production only.
|
||||||
|
|
||||||
|
## Local Development
|
||||||
|
|
||||||
|
- `dev` lists services from other apps: the emulators are shared machine-wide daemons. Ignore names not in your `module.ts`.
|
||||||
|
- `dev --fresh` fails for an app with a database in this release. Follow the reset steps in [Local development](https://www.prisma.io/docs/composer/local-development#whats-local-vs-whats-real).
|
||||||
|
- Windows is not supported for the local stack.
|
||||||
|
|
||||||
|
## Report CLI Bugs
|
||||||
|
|
||||||
|
When a failure survives these checks or the CLI reports an internal error, send it to the CLI team without secrets:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx prisma feedback "deploy failed with DEPLOY.UNEXPECTED: <first error line>"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Bad
|
||||||
|
|
||||||
|
Retrying `bunx @prisma/cli@latest app deploy --prod --yes` after `CLI.UNKNOWN_COMMAND`, or editing code before reading `error.code`.
|
||||||
|
|
||||||
|
## Good
|
||||||
|
|
||||||
|
Re-run with `--json --report deploy-report.json`, read `error.code` or `failure.code`, apply the fix this table names, rebuild, and deploy again.
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- [Deploying](https://www.prisma.io/docs/composer/deploying)
|
||||||
|
- [Request timeout](https://www.prisma.io/docs/compute/request-timeout)
|
||||||
|
- [CLI error reference](https://www.prisma.io/docs/cli/error-reference)
|
||||||
@@ -0,0 +1,138 @@
|
|||||||
|
# deploy-cli-and-ci
|
||||||
|
|
||||||
|
Deploy a Composer app with `prisma deploy`: production or a stage, from a workstation or from CI.
|
||||||
|
|
||||||
|
## Priority
|
||||||
|
|
||||||
|
HIGH
|
||||||
|
|
||||||
|
## Why It Matters
|
||||||
|
|
||||||
|
`deploy` does not build, chooses the project by the app's name rather than the directory link, and targets production unless told otherwise. Getting any of these wrong ships stale code, deploys into the wrong project, or changes production by accident.
|
||||||
|
|
||||||
|
## Commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx prisma deploy module.ts --help
|
||||||
|
npx prisma dev module.ts --help
|
||||||
|
```
|
||||||
|
|
||||||
|
| You want to | Run |
|
||||||
|
|-------------|-----|
|
||||||
|
| Run the app locally, no credentials | `npm run build && npx prisma dev module.ts` |
|
||||||
|
| Deploy a preview | `npm run build && npx prisma deploy module.ts --stage <name>` |
|
||||||
|
| Deploy production | `npm run build && npx prisma deploy module.ts` |
|
||||||
|
| Deploy under another app name | `npx prisma deploy module.ts --name <name>` |
|
||||||
|
| Write the outcome as JSON | `npx prisma deploy module.ts --report deploy-report.json` |
|
||||||
|
|
||||||
|
`<entry>` is the file whose default export is the root module, usually `module.ts`.
|
||||||
|
|
||||||
|
## Before Deploying
|
||||||
|
|
||||||
|
1. Build. `deploy` and `dev` package what the build already produced.
|
||||||
|
2. Run `npx prisma dev module.ts` and request each local URL it prints. It runs the same pipeline against local emulators, with a real local Postgres, and needs no account. `Ctrl-C` leaves local data in place.
|
||||||
|
3. Check auth: `npx prisma auth whoami --json`. If no one is signed in, ask the user to run `npx prisma auth login`; it opens a browser and cannot be done by an agent.
|
||||||
|
4. For a new project, set a region: `prismaCloud({ region })` in `prisma.config.ts` or `PRISMA_REGION`.
|
||||||
|
5. Decide the target with the user. No `--stage` changes production.
|
||||||
|
|
||||||
|
## Production and Stages
|
||||||
|
|
||||||
|
- No `--stage`: production. In platform terms the app is a project named after the root module, and production is its default branch.
|
||||||
|
- `--stage <name>`: a complete, isolated copy of the app as a preview branch of the same project, with its own services, databases, and configuration. Only the code is shared. The name must be a valid Git ref name; an invalid one fails the deploy.
|
||||||
|
- Redeploying is idempotent: the deploy compares the module with the recorded deploy state and applies the difference. Removing a `provision()` from the module deletes that resource on the next deploy. A deploy never deletes the last service, the project, or a branch.
|
||||||
|
- Deploy state lives on the platform, per branch, so a workstation and CI see the same state. Concurrent deploys of one environment take turns through a lease; a second deploy fails while the first holds it, and a crashed deploy's lease expires after about a minute.
|
||||||
|
|
||||||
|
## Which Project
|
||||||
|
|
||||||
|
The deploy finds the project in the workspace by the root module name (or `--name`) and creates it if none exists. It does not read or write `.prisma/local.json`, and it has no `--project` flag.
|
||||||
|
|
||||||
|
- A project with the same name that this module did not create can stop the deploy. Deploy with `--name <unique-name>` or rename the module.
|
||||||
|
- After the first deploy, link the directory so other commands target the project: `npx prisma project link <app-name>`. Otherwise pass `--project <app-name>` to `service`, `git`, and `project env` commands.
|
||||||
|
|
||||||
|
## Credentials
|
||||||
|
|
||||||
|
| Where | How |
|
||||||
|
|-------|-----|
|
||||||
|
| Workstation | `npx prisma auth login` once; later commands, including an agent's, reuse the stored session |
|
||||||
|
| CI or headless | `PRISMA_SERVICE_TOKEN` (a workspace service token from Console settings) and `PRISMA_WORKSPACE_ID` |
|
||||||
|
| GitHub Actions on a connected repository | OIDC through `prisma/cloud-deploy-action`; no stored secret. See [`deploy-on-push.md`](deploy-on-push.md) |
|
||||||
|
|
||||||
|
A non-empty `PRISMA_SERVICE_TOKEN` takes priority over stored sessions. A set-but-empty value is an error. Never print the token; check presence with `test -n "${PRISMA_SERVICE_TOKEN:-}"`.
|
||||||
|
|
||||||
|
Input fields bound with `envParam`/`envSecret` are stored per stage. A fresh stage starts with none, so CI must export those values; the first deploy copies missing names from the shell to the stage.
|
||||||
|
|
||||||
|
## Output
|
||||||
|
|
||||||
|
A deploy prints each step and ends with the app tree: every authored name, the platform resource it became, and public URLs.
|
||||||
|
|
||||||
|
```text
|
||||||
|
my-app
|
||||||
|
├─ db postgres-database db_def456
|
||||||
|
└─ api compute-service cps_abc123
|
||||||
|
https://xyz.ewr.prisma.build
|
||||||
|
```
|
||||||
|
|
||||||
|
With `--json`, the final envelope's `result.summary.nodes[].entities[]` lists what was deployed, each with `kind`, `id`, and `url` for services. `--report <path>` (or `PRISMA_COMPOSER_REPORT_FILE`) writes the outcome as JSON, including `failure.code` when the deploy fails. Request each service URL after the deploy:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
curl -i https://xyz.ewr.prisma.build
|
||||||
|
```
|
||||||
|
|
||||||
|
## CI Without GitHub
|
||||||
|
|
||||||
|
Any CI runs the same commands with the two credential variables as secrets:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm ci
|
||||||
|
npm run build
|
||||||
|
npx prisma deploy module.ts --stage "pr-$PR_NUMBER" --json --report deploy-report.json
|
||||||
|
```
|
||||||
|
|
||||||
|
`--build-id <id>` joins a build record your CI already created through `POST /v1/builds`.
|
||||||
|
|
||||||
|
## Teardown
|
||||||
|
|
||||||
|
The CLI has no `destroy` command, and `branch` has no delete.
|
||||||
|
|
||||||
|
- Connected GitHub repository: deleting the Git branch tears down the matching preview (services, databases, buckets). Production and the default branch are never torn down this way.
|
||||||
|
- Otherwise: call `destroy` from `@prisma/composer/control` with an explicit target. It needs `PRISMA_SERVICE_TOKEN` and `PRISMA_WORKSPACE_ID` in the environment and the app already built:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
// destroy-stage.ts
|
||||||
|
import { destroy } from "@prisma/composer/control";
|
||||||
|
import prismaConfig from "./prisma.config.ts";
|
||||||
|
|
||||||
|
const result = await destroy({
|
||||||
|
entry: "module.ts",
|
||||||
|
config: { value: prismaConfig.composer, file: "prisma.config.ts" },
|
||||||
|
target: { kind: "stage", stage: "pr-42" },
|
||||||
|
});
|
||||||
|
if (!result.ok) throw new Error(`${result.failure.code}: ${result.failure.message}`);
|
||||||
|
```
|
||||||
|
|
||||||
|
`config` is required in `@prisma/composer` 0.28.0: the `composer` section and the path of the file that declares it. Pass `name` when the app was deployed with `--name`. `target` is `{ kind: "stage", stage }` or `{ kind: "production" }` and has no default. Destroying a stage removes its resources, branch, and data; destroying production removes its resources and deletes the project once it is empty. Get the user's confirmation first. The deploy action's `mode: destroy` does not work against the current CLI.
|
||||||
|
|
||||||
|
## Bad
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx prisma deploy module.ts
|
||||||
|
```
|
||||||
|
|
||||||
|
Run without a build, this deploys whatever stale output is on disk, and without `--stage` it targets production.
|
||||||
|
|
||||||
|
## Good
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm run build
|
||||||
|
npx prisma dev module.ts # verify locally, then Ctrl-C
|
||||||
|
npx prisma auth whoami --json
|
||||||
|
npx prisma deploy module.ts --stage feat-search --json --report deploy-report.json
|
||||||
|
npx prisma project link my-app
|
||||||
|
npx prisma service list --branch feat-search --json
|
||||||
|
```
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- [`deploy` command](https://www.prisma.io/docs/cli/deploy)
|
||||||
|
- [Deploying](https://www.prisma.io/docs/composer/deploying)
|
||||||
|
- [Local development](https://www.prisma.io/docs/composer/local-development)
|
||||||
@@ -0,0 +1,101 @@
|
|||||||
|
# deploy-on-push
|
||||||
|
|
||||||
|
Deploy every pushed branch from the repository's own GitHub Actions with `prisma/cloud-deploy-action`.
|
||||||
|
|
||||||
|
## Priority
|
||||||
|
|
||||||
|
HIGH
|
||||||
|
|
||||||
|
## Why It Matters
|
||||||
|
|
||||||
|
The platform does not build on push. A connected repository without a workflow deploys nothing and reports no error, and a workflow without the connection skips with a green run. Both pieces are required, and a push to the default branch deploys production without any further prompt.
|
||||||
|
|
||||||
|
## How It Works
|
||||||
|
|
||||||
|
1. **The connection.** `prisma git connect` installs the Prisma GitHub App (if needed) and links the repository to the project. It lets workflow runs exchange their GitHub OIDC token for a 30-minute workspace token, and it tears down a preview when its Git branch is deleted.
|
||||||
|
2. **The workflow.** `prisma/cloud-deploy-action` runs install, your build command, and `prisma deploy <module>`. The default branch deploys production; any other branch deploys a stage named after it.
|
||||||
|
|
||||||
|
The Console can do both at once: importing the repository there opens a pull request that adds the workflow. The CLI only creates the connection.
|
||||||
|
|
||||||
|
## Setup From the CLI
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx prisma project link <app-name> # deploy does not link the directory
|
||||||
|
npx prisma git connect # uses the origin remote; needs an interactive terminal
|
||||||
|
```
|
||||||
|
|
||||||
|
`git connect` opens a browser for the GitHub App install and waits, so a person has to run it. With `--no-interactive` it fails with `CLI.INTERACTION_REQUIRED`; use the Console instead in that case. It fails with `PROJECT.SETUP_REQUIRED` when the directory is not linked.
|
||||||
|
|
||||||
|
Then commit the workflow:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# .github/workflows/prisma-deploy.yml
|
||||||
|
name: prisma-deploy
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
|
||||||
|
concurrency:
|
||||||
|
group: prisma-deploy-${{ github.ref }}
|
||||||
|
cancel-in-progress: false
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
id-token: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
deploy:
|
||||||
|
if: github.ref_type == 'branch'
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4
|
||||||
|
- uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: 22
|
||||||
|
- uses: oven-sh/setup-bun@v2
|
||||||
|
- uses: prisma/cloud-deploy-action@v1
|
||||||
|
with:
|
||||||
|
build-command: npm run build
|
||||||
|
```
|
||||||
|
|
||||||
|
- `id-token: write` is required for the OIDC exchange.
|
||||||
|
- Bun 1.3.10 or newer must be on the runner `PATH`; `oven-sh/setup-bun@v2` provides it.
|
||||||
|
- GitHub reads the workflow from the pushed commit, so a branch created before the file existed deploys nothing until it contains the file.
|
||||||
|
|
||||||
|
## Action Inputs and Outputs
|
||||||
|
|
||||||
|
Inputs (from `action.yml` in v1.9.0):
|
||||||
|
|
||||||
|
| Input | Default | Notes |
|
||||||
|
|-------|---------|-------|
|
||||||
|
| `build-command` | `npm run build` | Run verbatim; `none` skips the build |
|
||||||
|
| `install-command` | auto | `npm ci` or `bun install --frozen-lockfile` from the lockfile; pnpm and yarn need an explicit value |
|
||||||
|
| `module` | `module.ts` | The Composer entry |
|
||||||
|
| `stage` | derived | Empty: default branch is production, other branches become a stage of the same name |
|
||||||
|
| `working-directory` | `.` | For monorepos |
|
||||||
|
| `prisma-version` | `8.0.0-rc.9` | Used only when the repository has no `prisma` dev dependency; otherwise the installed version deploys |
|
||||||
|
| `mode` | `deploy` | `destroy` does not work against the current CLI |
|
||||||
|
|
||||||
|
Outputs: `outcome` (`succeeded`, `failed`, `skipped-no-credential`), `url` (root service), `urls` (JSON map of service address to URL), `build-id`, `report-path`. Repositories that are not connected can pass `PRISMA_SERVICE_TOKEN` from a secret in the step's `env`; an explicit token wins over OIDC.
|
||||||
|
|
||||||
|
## Checking a Push
|
||||||
|
|
||||||
|
- Watch the run in the repository's Actions tab. The job summary lists each service URL and, on failure, the cause.
|
||||||
|
- `outcome: skipped-no-credential` means the repository is not connected, `id-token: write` is missing, or the run came from a fork.
|
||||||
|
- `CLI.UNKNOWN_COMMAND` in the deploy step means an action release up to v1.5.0, which called the removed `prisma composer` commands. Use `@v1` (v1.9.0 or later).
|
||||||
|
- From a terminal: `npx prisma service list --branch <git-branch> --json`.
|
||||||
|
- Deleting the Git branch removes the preview's services, databases, and buckets. Production and the default branch are never torn down.
|
||||||
|
|
||||||
|
## Bad
|
||||||
|
|
||||||
|
Running `npx prisma git connect`, pushing, and reporting the app as deployed. The connection alone builds and deploys nothing.
|
||||||
|
|
||||||
|
## Good
|
||||||
|
|
||||||
|
Connect, commit `.github/workflows/prisma-deploy.yml`, push a non-default branch first, confirm the run's `url` responds, and only then merge to the default branch with the user's go-ahead.
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- [Deploy on push](https://www.prisma.io/docs/compute/deploy-on-push)
|
||||||
|
- [GitHub integration](https://www.prisma.io/docs/compute/github)
|
||||||
|
- [prisma/cloud-deploy-action](https://github.com/prisma/cloud-deploy-action)
|
||||||
@@ -0,0 +1,148 @@
|
|||||||
|
# ops-services-and-config
|
||||||
|
|
||||||
|
Inspect and operate what a deploy created: services, versions, logs, domains, environment variables, databases, and buckets.
|
||||||
|
|
||||||
|
## Priority
|
||||||
|
|
||||||
|
HIGH
|
||||||
|
|
||||||
|
## Why It Matters
|
||||||
|
|
||||||
|
Operations commands target explicitly: the service is a positional argument, the project comes from `--project` or the directory link, and the branch defaults to production. An agent that relies on the old `app` commands, on `PRISMA_SERVICE_ID`, or on the current Git branch reads or changes the wrong thing.
|
||||||
|
|
||||||
|
Every example below accepts `--project <id-or-name>` and `--json`. Without `--branch`, commands act on the production branch.
|
||||||
|
|
||||||
|
## Services
|
||||||
|
|
||||||
|
A service is one HTTP app on a branch. Every deploy creates an immutable version; one version serves traffic at a time.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx prisma service list --json
|
||||||
|
npx prisma service list --branch feat-search --json
|
||||||
|
npx prisma service show api --json
|
||||||
|
npx prisma service open api
|
||||||
|
```
|
||||||
|
|
||||||
|
`service show` returns the live version and the service URL. `service create` exists but is rarely needed; deploys create services.
|
||||||
|
|
||||||
|
## Logs
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx prisma service logs api --tail 200
|
||||||
|
npx prisma service logs api --follow
|
||||||
|
npx prisma service logs api --branch feat-search
|
||||||
|
npx prisma service logs api --version-id cpv_123 --from-start
|
||||||
|
```
|
||||||
|
|
||||||
|
Logs default to the live version. Use `--version-id` for a failed or stopped version. `SERVICE.LOGS_FAILED` carries the API status; `SERVICE.LOGS_INCOMPLETE` means the page ended early, so rerun. Build output is not here: read the GitHub Actions run, the terminal that ran `deploy`, the `--report` file, or the Console.
|
||||||
|
|
||||||
|
## Versions, Promote, Rollback
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx prisma service version list api --json
|
||||||
|
npx prisma service version show cpv_123 --json
|
||||||
|
npx prisma service version promote cpv_123
|
||||||
|
npx prisma service version rollback api --to cpv_122 --confirm cpv_122
|
||||||
|
npx prisma service version stop cpv_123
|
||||||
|
npx prisma service version start cpv_123
|
||||||
|
npx prisma service version delete cpv_123 --confirm cpv_123
|
||||||
|
```
|
||||||
|
|
||||||
|
- `promote` takes a version from a preview branch to production by rebuilding it with production env vars.
|
||||||
|
- `rollback` puts production back on an existing version without a rebuild. Without `--to` it picks the version before the live one (`SERVICE.NO_PREVIOUS_VERSION` or `SERVICE.LIVE_VERSION_UNKNOWN` when it cannot), and it asks for consent with the target version id. In a non-interactive run, list versions first and pass `--to <id> --confirm <id>`.
|
||||||
|
- A later production deploy creates a new version and makes it live, so fix the code before the next deploy after a rollback.
|
||||||
|
|
||||||
|
## Custom Domains
|
||||||
|
|
||||||
|
Domains attach to a service's production branch only, CNAME-based, up to three per service.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx prisma service domain add shop.example.com --service web
|
||||||
|
npx prisma service domain wait shop.example.com --service web --timeout 15m
|
||||||
|
npx prisma service domain show shop.example.com --service web --json
|
||||||
|
npx prisma service domain retry shop.example.com --service web
|
||||||
|
npx prisma service domain delete shop.example.com --service web --confirm shop.example.com
|
||||||
|
```
|
||||||
|
|
||||||
|
`add` verifies DNS first. If the CNAME is not visible yet, it fails with the record to create (pointing at `switchboard.<region>.prisma.build`); create it and run `add` again. `wait --timeout 0` does one status check. States: `pending_dns`, `provisioning_tls`, `active`, `failed`.
|
||||||
|
|
||||||
|
## Environment Variables
|
||||||
|
|
||||||
|
Three layers: production values, preview values shared by every preview branch, and per-branch overrides on top of preview. Production values cannot be branch-scoped.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx prisma project env list --json
|
||||||
|
npx prisma project env list --role preview --json
|
||||||
|
npx prisma project env list --branch feat-search --json
|
||||||
|
npx prisma project env add STRIPE_KEY --role production # value read from the shell environment
|
||||||
|
npx prisma project env add --file .env.preview --role preview
|
||||||
|
npx prisma project env add API_BASE_URL=https://staging.example.com --branch staging
|
||||||
|
npx prisma project env update STRIPE_KEY --role production
|
||||||
|
npx prisma project env delete STRIPE_KEY --role preview
|
||||||
|
```
|
||||||
|
|
||||||
|
- Every write names its scope: `--role production`, `--role preview`, or `--branch <name>`.
|
||||||
|
- `add` fails when the key exists in that scope; use `update`.
|
||||||
|
- Values are write-only. `list` shows names and metadata, never values, and nothing pulls them back into a `.env`.
|
||||||
|
- Values resolve at deploy time. A change applies on the next deploy (or `promote`).
|
||||||
|
- Keys match `[A-Z_][A-Z0-9_]*`; values are non-empty, up to 8 KB.
|
||||||
|
- Passing only `KEY` reads the value from the current environment and keeps it out of shell history.
|
||||||
|
- `COMPOSER_*` variables belong to the deploy and are rewritten on every deploy. Do not edit them.
|
||||||
|
|
||||||
|
## Databases and Buckets
|
||||||
|
|
||||||
|
A Composer app gets its databases and buckets from its module. These commands inspect them or create standalone ones.
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx prisma postgres list --json
|
||||||
|
npx prisma postgres list --branch feat-search --json
|
||||||
|
npx prisma postgres show db_123 --json
|
||||||
|
npx prisma postgres usage db_123 --json
|
||||||
|
npx prisma postgres connection create db_123 --name ci
|
||||||
|
npx prisma postgres connection rotate conn_123 --confirm conn_123
|
||||||
|
npx prisma postgres backup list db_123 --json
|
||||||
|
npx prisma bucket list --json
|
||||||
|
npx prisma bucket key create bkt_123 --role read
|
||||||
|
```
|
||||||
|
|
||||||
|
`postgres create`, `postgres connection create`, `postgres connection rotate`, and `bucket key create` print credentials exactly once. Store them in the intended secret store immediately and never echo them back. Deleting a database, restoring a backup, or deleting a bucket destroys data; do it only when the user asks, with the exact id as `--confirm`.
|
||||||
|
|
||||||
|
## Branches
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx prisma branch list --json
|
||||||
|
```
|
||||||
|
|
||||||
|
`branch` only lists. Branches are created by a stage deploy, a pushed Git branch, or `service create --branch`, and removed by deleting the Git branch of a connected repository or by the control API's `destroy`.
|
||||||
|
|
||||||
|
## Workspaces
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx prisma auth whoami --json
|
||||||
|
npx prisma auth workspace list --json
|
||||||
|
npx prisma auth workspace use <workspace-id>
|
||||||
|
npx prisma auth workspace logout <workspace-id>
|
||||||
|
```
|
||||||
|
|
||||||
|
`auth login` adds a session per workspace; `workspace use` switches. While `PRISMA_SERVICE_TOKEN` is set it overrides every stored session. `auth logout` ends all sessions.
|
||||||
|
|
||||||
|
## Bad
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx prisma service logs
|
||||||
|
```
|
||||||
|
|
||||||
|
Fails with `SERVICE.TARGET_REQUIRED`; there is no picker and no `PRISMA_SERVICE_ID` fallback.
|
||||||
|
|
||||||
|
## Good
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx prisma service logs api --project my-app --branch feat-search --tail 200 --json
|
||||||
|
```
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- [Deployments](https://www.prisma.io/docs/compute/deployments)
|
||||||
|
- [Environment variables](https://www.prisma.io/docs/compute/environment-variables)
|
||||||
|
- [Domains](https://www.prisma.io/docs/compute/domains)
|
||||||
|
- [`service` command](https://www.prisma.io/docs/cli/service)
|
||||||
@@ -0,0 +1,101 @@
|
|||||||
|
# runtime-requirements
|
||||||
|
|
||||||
|
What a service must do to run on Prisma Compute, and the platform limits it must design around.
|
||||||
|
|
||||||
|
## Priority
|
||||||
|
|
||||||
|
CRITICAL
|
||||||
|
|
||||||
|
## Why It Matters
|
||||||
|
|
||||||
|
A deploy can converge cleanly and still serve nothing: a loopback listener is unreachable, a slow handler gets a `504` from the ingress, and a sleeping instance stops background work. None of these show up as deploy errors.
|
||||||
|
|
||||||
|
## Runtime
|
||||||
|
|
||||||
|
- Services run on **Bun**, in a VM next to their Prisma Postgres database. Write server code for Bun, and bundle with `bun build --target=bun` or another bundler that inlines all dependencies. A build that leaves packages as imports needs `dependencies: "external"` on `node()` (Composer 0.29.0 and later).
|
||||||
|
- There is no global `Temporal`. A service that reads Prisma ORM `DateTime` columns as `Temporal` values compiles, deploys, then fails on the first read. Import a polyfill at the server entry or use string column types.
|
||||||
|
|
||||||
|
## Host and Port
|
||||||
|
|
||||||
|
- Listen on `service.port()` (default 3000). The runtime also exports it as `PORT`.
|
||||||
|
- Bind `0.0.0.0`. Compute routes external HTTP to the VM; a `localhost` or `127.0.0.1` listener looks started but is unreachable.
|
||||||
|
|
||||||
|
```ts
|
||||||
|
Bun.serve({ port: service.port(), hostname: "0.0.0.0", fetch: handler });
|
||||||
|
```
|
||||||
|
|
||||||
|
## 60 Seconds to First Byte
|
||||||
|
|
||||||
|
The ingress gives a request 60 seconds to start responding. If nothing comes back, the client gets `504 Gateway Time-out` (a short `openresty` HTML body) and Compute cancels the request. Your handler sees only its abort signal (`req.signal`); no error is logged.
|
||||||
|
|
||||||
|
- Respond within 60 seconds. For webhooks, return `200` or `202` before processing.
|
||||||
|
- Keep in-request timeouts (fetch timeouts, `AbortSignal.timeout`) under 60 seconds so your own error handling runs first.
|
||||||
|
- Continue longer work after the response with `waitUntil`, or persist a job and process it in steps from a separate trigger. Compute does not run scheduled jobs; the trigger is an external scheduler or the Composer `cron` module.
|
||||||
|
- The deadline covers only the first bytes. The docs say a response that has started is not cut off; the `prisma-composer-core-concepts` skill warns that the ingress buffers streamed responses. Send the first bytes early and test a streaming route on a stage before relying on it.
|
||||||
|
|
||||||
|
## Sleep and Keep-Awake
|
||||||
|
|
||||||
|
Idle instances scale to zero: the platform snapshots memory and resumes from it on the next request. Requests are unaffected, but `setTimeout`, `setInterval`, and floating promises can stall mid-flight. Do not build schedulers on `setInterval` inside a service.
|
||||||
|
|
||||||
|
`@prisma/compute` keeps an instance awake on a best-effort basis:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
import { KeepAwakeGuard, waitUntil } from "@prisma/compute";
|
||||||
|
|
||||||
|
waitUntil(processJob(job), { signal: AbortSignal.timeout(10 * 60_000) });
|
||||||
|
|
||||||
|
async function processBatch() {
|
||||||
|
using guard = new KeepAwakeGuard({ signal: AbortSignal.timeout(30_000) });
|
||||||
|
await doWork();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
- The `signal` caps how long the instance stays awake; it does not cancel the work.
|
||||||
|
- Release a manually created guard in `finally` with `guard.release()` where `using` is unavailable.
|
||||||
|
- Neither primitive makes work durable, retries it, or carries it through a restart or a new deployment.
|
||||||
|
|
||||||
|
## Connections
|
||||||
|
|
||||||
|
Scale to zero closes idle database connections. A long-lived client that treats a dropped connection as fatal crash-loops through `502`s. Keep pools small and reconnect-friendly, and log instead of exiting:
|
||||||
|
|
||||||
|
```ts
|
||||||
|
const sql = new SQL({ url: db.url, max: 1, idleTimeout: 10 });
|
||||||
|
process.on("uncaughtException", (err) => console.error("uncaughtException", err));
|
||||||
|
process.on("unhandledRejection", (err) => console.error("unhandledRejection", err));
|
||||||
|
```
|
||||||
|
|
||||||
|
A call into a sleeping service can get `ECONNRESET` during the cold start; retry it. The generated Composer RPC client already does.
|
||||||
|
|
||||||
|
## Limits
|
||||||
|
|
||||||
|
- No WebSocket servers.
|
||||||
|
- No persistent filesystem.
|
||||||
|
- No multi-region deployments. Each service runs in one region, and a Composer deploy uses the project's region, fixed when the first deploy creates the project: `us-east-1`, `us-west-1`, `eu-west-3`, `eu-central-1`, `ap-northeast-1`, or `ap-southeast-1`.
|
||||||
|
- A deployed `/rpc/<method>` of a Composer contract returns `401` to anything except the services wired to it. That is the service-key check, not a broken deploy.
|
||||||
|
|
||||||
|
## Bad
|
||||||
|
|
||||||
|
```ts
|
||||||
|
app.post("/webhook", async (c) => {
|
||||||
|
await processForTwoMinutes(await c.req.json());
|
||||||
|
return c.text("done");
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
The caller gets a `504` after 60 seconds, and the instance can sleep while the work continues.
|
||||||
|
|
||||||
|
## Good
|
||||||
|
|
||||||
|
```ts
|
||||||
|
app.post("/webhook", async (c) => {
|
||||||
|
const job = await c.req.json();
|
||||||
|
waitUntil(processForTwoMinutes(job), { signal: AbortSignal.timeout(5 * 60_000) });
|
||||||
|
return c.body(null, 202);
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- [Request timeout](https://www.prisma.io/docs/compute/request-timeout)
|
||||||
|
- [Keeping instances awake](https://www.prisma.io/docs/compute/keeping-instances-awake)
|
||||||
|
- [Known limitations](https://www.prisma.io/docs/compute/limitations)
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
---
|
||||||
|
name: prisma-database-setup
|
||||||
|
description: Deprecated compatibility name for prisma-orm-setup. Use only when a user or existing integration explicitly invokes prisma-database-setup; otherwise select prisma-orm-setup.
|
||||||
|
license: MIT
|
||||||
|
metadata:
|
||||||
|
author: prisma
|
||||||
|
version: "8.0.0"
|
||||||
|
---
|
||||||
|
|
||||||
|
# Deprecated: prisma-database-setup
|
||||||
|
|
||||||
|
Load `prisma-orm-setup` with the host's skill loader or read its installed `SKILL.md`. If unavailable, install it from [prisma/skills](https://github.com/prisma/skills/tree/main/prisma-orm-setup) before continuing. It covers Prisma 6, 7, and 8 setup and connection repair.
|
||||||
|
|
||||||
|
This compatibility entry contains no setup recipes. Keep it until consumers have migrated to the replacement.
|
||||||
@@ -0,0 +1,270 @@
|
|||||||
|
---
|
||||||
|
name: prisma-driver-adapter-implementation
|
||||||
|
description: Required reference for Prisma ORM 7 SQL driver adapter work. Use when implementing or modifying adapters, adding database drivers, or touching SqlDriverAdapter, Transaction, savepoint, result mapping, or DriverAdapterError behavior. Covers current transaction lifecycle, optional savepoint hooks, original database-error preservation, and verification.
|
||||||
|
license: MIT
|
||||||
|
metadata:
|
||||||
|
author: prisma
|
||||||
|
version: "7.9.1"
|
||||||
|
---
|
||||||
|
|
||||||
|
# Prisma SQL Driver Adapter Implementation
|
||||||
|
|
||||||
|
Use this guide with the exact `@prisma/driver-adapter-utils` version installed by the target Prisma release. Driver adapters are a protocol boundary: type-compatible code can still corrupt values, leak connections, or break transactions.
|
||||||
|
|
||||||
|
## When to Apply
|
||||||
|
|
||||||
|
- Implementing `SqlDriverAdapterFactory`, `SqlMigrationAwareDriverAdapterFactory`, `SqlDriverAdapter`, or `Transaction`
|
||||||
|
- Adding nested-transaction/savepoint support
|
||||||
|
- Mapping driver values, column metadata, bind arguments, or database errors
|
||||||
|
- Debugging `P2039`, transaction leaks, shadow-database failures, or adapter-specific query behavior
|
||||||
|
|
||||||
|
## Contract snapshot
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
interface SqlDriverAdapterFactory extends AdapterInfo {
|
||||||
|
connect(): Promise<SqlDriverAdapter>
|
||||||
|
}
|
||||||
|
|
||||||
|
interface SqlMigrationAwareDriverAdapterFactory extends SqlDriverAdapterFactory {
|
||||||
|
connectToShadowDb(): Promise<SqlDriverAdapter>
|
||||||
|
}
|
||||||
|
|
||||||
|
interface SqlDriverAdapter extends AdapterInfo {
|
||||||
|
queryRaw(query: SqlQuery): Promise<SqlResultSet>
|
||||||
|
executeRaw(query: SqlQuery): Promise<number>
|
||||||
|
executeScript(script: string): Promise<void>
|
||||||
|
startTransaction(isolationLevel?: IsolationLevel): Promise<Transaction>
|
||||||
|
getConnectionInfo?(): ConnectionInfo
|
||||||
|
dispose(): Promise<void>
|
||||||
|
}
|
||||||
|
|
||||||
|
interface Transaction extends AdapterInfo {
|
||||||
|
readonly options: { usePhantomQuery: boolean }
|
||||||
|
queryRaw(query: SqlQuery): Promise<SqlResultSet>
|
||||||
|
executeRaw(query: SqlQuery): Promise<number>
|
||||||
|
commit(): Promise<void>
|
||||||
|
rollback(): Promise<void>
|
||||||
|
createSavepoint?(name: string): Promise<void>
|
||||||
|
rollbackToSavepoint?(name: string): Promise<void>
|
||||||
|
releaseSavepoint?(name: string): Promise<void>
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`IsolationLevel` currently includes `READ UNCOMMITTED`, `READ COMMITTED`, `REPEATABLE READ`, `SNAPSHOT`, and `SERIALIZABLE`; validate what the concrete database supports.
|
||||||
|
|
||||||
|
## Priority rules
|
||||||
|
|
||||||
|
| Priority | Rule | Impact |
|
||||||
|
|----------|------|--------|
|
||||||
|
| CRITICAL | One dedicated connection per transaction | Prevents interleaving and leaks |
|
||||||
|
| CRITICAL | `commit`/`rollback` are lifecycle cleanup hooks | Prevents duplicate COMMIT/ROLLBACK |
|
||||||
|
| CRITICAL | Savepoints live on `Transaction`, not adapter-global depth | Makes nested scopes connection-local |
|
||||||
|
| CRITICAL | Preserve original database error code/message | Enables useful `P2039` fallback |
|
||||||
|
| HIGH | Map arguments and result metadata exactly | Prevents silent value corruption |
|
||||||
|
| HIGH | Shadow databases are isolated and always cleaned up | Makes Migrate safe |
|
||||||
|
| HIGH | Dispose only resources the adapter owns | Prevents shutting down caller-owned pools |
|
||||||
|
|
||||||
|
## Query implementation
|
||||||
|
|
||||||
|
`SqlQuery` contains `sql`, `args`, and parallel `argTypes`. Map each argument using both value and `ArgType`; do not discard type/arity information. Execute in the driver's array/tuple row mode so column order is stable.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
class ExampleQueryable {
|
||||||
|
readonly provider = 'postgres' as const
|
||||||
|
readonly adapterName = '@acme/adapter-example'
|
||||||
|
|
||||||
|
constructor(protected readonly connection: DriverConnection) {}
|
||||||
|
|
||||||
|
async queryRaw(query: SqlQuery): Promise<SqlResultSet> {
|
||||||
|
try {
|
||||||
|
const result = await this.connection.query({
|
||||||
|
text: query.sql,
|
||||||
|
values: query.args.map((value, index) =>
|
||||||
|
mapArg(value, query.argTypes[index]),
|
||||||
|
),
|
||||||
|
rowMode: 'array',
|
||||||
|
})
|
||||||
|
|
||||||
|
return {
|
||||||
|
columnNames: result.fields.map((field) => field.name),
|
||||||
|
columnTypes: result.fields.map(mapColumnType),
|
||||||
|
rows: result.rows,
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
throwAdapterError(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async executeRaw(query: SqlQuery): Promise<number> {
|
||||||
|
try {
|
||||||
|
const result = await this.connection.execute(
|
||||||
|
query.sql,
|
||||||
|
query.args.map((value, index) => mapArg(value, query.argTypes[index])),
|
||||||
|
)
|
||||||
|
return result.rowsAffected ?? 0
|
||||||
|
} catch (error) {
|
||||||
|
throwAdapterError(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Result mapping
|
||||||
|
|
||||||
|
Return `columnNames`, `columnTypes`, and `rows` with identical lengths/order. Map driver metadata to `ColumnTypeEnum` deliberately:
|
||||||
|
|
||||||
|
- signed integer widths to `Int32`/`Int64`; preserve 64-bit values without JS number truncation
|
||||||
|
- decimal/numeric to `Numeric` using the representation expected by Prisma
|
||||||
|
- binary to `Uint8Array`/`Bytes`
|
||||||
|
- date-only, time-only, and timestamp to `Date`, `Time`, and `DateTime`
|
||||||
|
- UUID, JSON, enum, arrays, and provider-specific unknown values to their explicit types
|
||||||
|
- unsupported native types to `DriverAdapterError({ kind: 'UnsupportedNativeDataType', type })`
|
||||||
|
|
||||||
|
Test `null`, empty arrays, array element types, big integers, decimals, byte arrays, JSON, dates, and user-defined/unknown native types.
|
||||||
|
|
||||||
|
### Script execution
|
||||||
|
|
||||||
|
`executeScript` must execute a migration script as the provider expects. Prefer the driver's native multi-statement/script facility or a real SQL parser. Naively splitting on `;` breaks functions, triggers, quoted strings, and dialect-specific blocks.
|
||||||
|
|
||||||
|
## Transaction protocol
|
||||||
|
|
||||||
|
`startTransaction` must acquire one dedicated connection, start the database transaction, apply the requested isolation level, and return a `Transaction` bound to that same connection. If setup fails, release it immediately.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
async startTransaction(level?: IsolationLevel): Promise<Transaction> {
|
||||||
|
const connection = await this.pool.acquire()
|
||||||
|
try {
|
||||||
|
const tx = new ExampleTransaction(connection, () => connection.release())
|
||||||
|
await tx.executeRaw({ sql: 'BEGIN', args: [], argTypes: [] })
|
||||||
|
if (level) {
|
||||||
|
await tx.executeRaw({
|
||||||
|
sql: `SET TRANSACTION ISOLATION LEVEL ${validateLevel(level)}`,
|
||||||
|
args: [],
|
||||||
|
argTypes: [],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return tx
|
||||||
|
} catch (error) {
|
||||||
|
connection.release(error)
|
||||||
|
throwAdapterError(error)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Commit and rollback
|
||||||
|
|
||||||
|
Prisma coordinates the SQL `COMMIT`/`ROLLBACK` through `executeRaw`. The transaction object's `commit()` and `rollback()` methods are lifecycle hooks: detach listeners and release the dedicated connection exactly once. They must not issue a second SQL commit/rollback.
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
class ExampleTransaction extends ExampleQueryable implements Transaction {
|
||||||
|
readonly options = { usePhantomQuery: false }
|
||||||
|
#closed = false
|
||||||
|
|
||||||
|
constructor(connection: DriverConnection, private readonly release: () => void) {
|
||||||
|
super(connection)
|
||||||
|
}
|
||||||
|
|
||||||
|
async commit() { this.finish() }
|
||||||
|
async rollback() { this.finish() }
|
||||||
|
|
||||||
|
private finish() {
|
||||||
|
if (this.#closed) return
|
||||||
|
this.#closed = true
|
||||||
|
this.release()
|
||||||
|
}
|
||||||
|
|
||||||
|
async createSavepoint(name: string) {
|
||||||
|
await this.control(`SAVEPOINT ${safeSavepoint(name)}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
async rollbackToSavepoint(name: string) {
|
||||||
|
await this.control(`ROLLBACK TO SAVEPOINT ${safeSavepoint(name)}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
async releaseSavepoint(name: string) {
|
||||||
|
await this.control(`RELEASE SAVEPOINT ${safeSavepoint(name)}`)
|
||||||
|
}
|
||||||
|
|
||||||
|
private async control(sql: string) {
|
||||||
|
await this.executeRaw({ sql, args: [], argTypes: [] })
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Implement the optional savepoint methods only where the provider supports them. Validate/quote savepoint identifiers. For providers whose savepoints are intentionally no-ops, document and test that limitation.
|
||||||
|
|
||||||
|
Never keep transaction depth on the shared adapter. Parallel transactions make adapter-global depth incorrect; nested state belongs to the returned transaction connection and Prisma's savepoint calls.
|
||||||
|
|
||||||
|
## Error mapping
|
||||||
|
|
||||||
|
Wrap recognized driver failures in `DriverAdapterError`. Map known conditions to `MappedError` kinds such as constraint violations, authentication/reachability, missing table/column/database, timeouts, closed transactions, invalid input, value range, and write conflicts.
|
||||||
|
|
||||||
|
For database errors, preserve `originalCode` and `originalMessage` even when falling back to the provider-specific raw variant:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import {
|
||||||
|
DriverAdapterError,
|
||||||
|
type Error as DriverAdapterErrorObject,
|
||||||
|
type MappedError,
|
||||||
|
} from '@prisma/driver-adapter-utils'
|
||||||
|
|
||||||
|
function convertDriverError(error: DatabaseError): DriverAdapterErrorObject {
|
||||||
|
return {
|
||||||
|
originalCode: String(error.code),
|
||||||
|
originalMessage: error.message,
|
||||||
|
...mapKnownOrRaw(error),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function mapKnownOrRaw(error: DatabaseError): MappedError {
|
||||||
|
if (error.code === '23505') {
|
||||||
|
return { kind: 'UniqueConstraintViolation', constraint: parsedConstraint(error) }
|
||||||
|
}
|
||||||
|
return {
|
||||||
|
kind: 'postgres',
|
||||||
|
code: String(error.code ?? 'N/A'),
|
||||||
|
severity: error.severity ?? 'N/A',
|
||||||
|
message: error.message,
|
||||||
|
detail: error.detail,
|
||||||
|
column: error.column,
|
||||||
|
hint: error.hint,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function throwAdapterError(error: unknown): never {
|
||||||
|
if (!isDatabaseError(error)) throw error
|
||||||
|
throw new DriverAdapterError(convertDriverError(error))
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Prisma uses preserved original details when an unmapped driver error becomes `P2039`. Do not replace every unknown exception with a fabricated `GenericJs` id; rethrow genuinely unexpected non-driver errors so programming bugs remain visible.
|
||||||
|
|
||||||
|
## Factory, ownership, and shadow database
|
||||||
|
|
||||||
|
- `connect()` returns a fresh usable adapter connection/pool wrapper.
|
||||||
|
- Track whether the factory created the pool. `dispose()` closes owned pools and only detaches listeners from caller-owned pools unless an explicit option transfers ownership.
|
||||||
|
- Implement `SqlMigrationAwareDriverAdapterFactory` only when `connectToShadowDb()` can create an isolated shadow database, connect to it, and drop it during disposal/failure cleanup.
|
||||||
|
- Never point the shadow adapter at the primary database. Quote generated identifiers and use cryptographically unique names.
|
||||||
|
- `getConnectionInfo()` should accurately report `schemaName`, `maxBindValues` when applicable, and `supportsRelationJoins`.
|
||||||
|
|
||||||
|
## Verification checklist
|
||||||
|
|
||||||
|
- [ ] Typecheck against the exact target `@prisma/driver-adapter-utils` version
|
||||||
|
- [ ] `queryRaw` preserves column order, types, nulls, and precision
|
||||||
|
- [ ] `executeRaw` reports affected rows correctly
|
||||||
|
- [ ] `executeScript` handles provider-specific multi-statement syntax
|
||||||
|
- [ ] Concurrent interactive transactions use distinct dedicated connections
|
||||||
|
- [ ] Success commits and releases once; failure rolls back and releases once
|
||||||
|
- [ ] Nested transaction tests exercise create/rollback/release savepoint hooks
|
||||||
|
- [ ] Unsupported isolation levels fail as `InvalidIsolationLevel`
|
||||||
|
- [ ] Known constraints map to structured errors
|
||||||
|
- [ ] Unmapped database errors retain original code/message and surface useful `P2039`
|
||||||
|
- [ ] Dispose ownership is tested for internal and external pools
|
||||||
|
- [ ] Shadow database creation, use, failure cleanup, and disposal are isolated
|
||||||
|
- [ ] Run Prisma Client integration/E2E tests, not only adapter unit tests
|
||||||
|
|
||||||
|
## Source references
|
||||||
|
|
||||||
|
- [Driver adapter interfaces](https://github.com/prisma/prisma/blob/v7/packages/driver-adapter-utils/src/types.ts)
|
||||||
|
- [PostgreSQL adapter transaction implementation](https://github.com/prisma/prisma/blob/v7/packages/adapter-pg/src/pg.ts)
|
||||||
|
- [PostgreSQL adapter error mapping](https://github.com/prisma/prisma/blob/v7/packages/adapter-pg/src/errors.ts)
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
---
|
||||||
|
name: prisma-mongodb-upgrade
|
||||||
|
description: Decision and migration guide for Prisma ORM MongoDB projects on v6, which have no upgrade path to v7. Use when a MongoDB project asks about upgrading Prisma, when "upgrade to prisma 7" comes up in a project with provider = "mongodb", or when evaluating a move to Prisma 8. Triggers on "upgrade prisma mongodb", "prisma 7 mongodb", "mongodb prisma migration", "prisma 8 mongodb".
|
||||||
|
license: MIT
|
||||||
|
metadata:
|
||||||
|
author: prisma
|
||||||
|
version: "0.2.0"
|
||||||
|
---
|
||||||
|
|
||||||
|
# Prisma MongoDB Upgrade Path
|
||||||
|
|
||||||
|
MongoDB projects are the one Prisma cohort with no road into Prisma 7: **v6 is the terminal
|
||||||
|
classic-ORM major for MongoDB, and v7 never ships a MongoDB connector**. The successor path
|
||||||
|
is Prisma 8, where MongoDB support is in [Early Access](https://www.prisma.io/docs/orm/supported-databases)
|
||||||
|
while PostgreSQL is a release candidate. The official
|
||||||
|
[Prisma ORM 6 to 8 (MongoDB) guide](https://www.prisma.io/docs/guides/upgrade-prisma-orm/mongodb)
|
||||||
|
is the source of truth for the migration steps. This skill frames the real decision — migrate to
|
||||||
|
Prisma 8 (the encouraged path), or stay on v6 where a hard blocker applies — and carries
|
||||||
|
the migration mechanics.
|
||||||
|
|
||||||
|
**Never do either of these:**
|
||||||
|
|
||||||
|
- Never advise a MongoDB project to "upgrade to Prisma 7". The connector does not exist
|
||||||
|
there. The `prisma-upgrade-v7` guide does not apply to MongoDB projects.
|
||||||
|
- Never solve the version question by rewriting the app onto a SQL database. Changing the
|
||||||
|
database engine is a separate, much larger decision that is not yours to make implicitly.
|
||||||
|
|
||||||
|
## The version landscape
|
||||||
|
|
||||||
|
| Version | MongoDB status |
|
||||||
|
|---------|----------------|
|
||||||
|
| Prisma ORM v6 | Fully supported (`mongodb` provider); latest 6.x is the current stable path; maintenance line |
|
||||||
|
| Prisma ORM v7 | **No MongoDB connector — not an option, ever** |
|
||||||
|
| Prisma 8 | MongoDB support in **Early Access** through `@prisma/orm-mongo`; still changes between release candidates — the successor path for MongoDB projects |
|
||||||
|
|
||||||
|
## The decision, up front
|
||||||
|
|
||||||
|
**Migrating to Prisma 8 is the encouraged path.** MongoDB support in Prisma 8 is Early
|
||||||
|
Access: functional and moving quickly — and the Prisma team wants MongoDB users to migrate
|
||||||
|
early and share feedback. The migration mechanics are
|
||||||
|
detailed in the references.
|
||||||
|
|
||||||
|
**Staying on the latest v6 remains a legitimate choice where a hard blocker applies** —
|
||||||
|
stated plainly: Prisma 8 has no MongoDB transaction method yet (multi-document writes use
|
||||||
|
the `mongodb` driver's sessions directly), and MongoDB behavior can still change between
|
||||||
|
Prisma 8 release candidates.
|
||||||
|
|
||||||
|
### Decision table
|
||||||
|
|
||||||
|
| Signal | Direction |
|
||||||
|
|--------|-----------|
|
||||||
|
| No blockers below apply | Migrate to Prisma 8; run the `verify-cutover-checklist` and share feedback with the Prisma team |
|
||||||
|
| Greenfield / prototype / internal tool | Migrate to Prisma 8 |
|
||||||
|
| Codebase uses multi-document transactions (`$transaction`) — check with grep, do not ask | Plan raw-driver session equivalents first (see `client-api-mapping`), or stay on v6 until Prisma 8 adds a MongoDB transaction method |
|
||||||
|
| Team cannot absorb breaking changes between release candidates | Stay on v6 until MongoDB support leaves Early Access |
|
||||||
|
| Risk-averse but interested | Point Prisma 8 at the v6 schema with `prisma6Schema(...)` (see `schema-contract-mapping`), rehearse on a copy (see `verify-cutover-checklist`), then migrate |
|
||||||
|
|
||||||
|
Note: this section will be updated when Prisma 8 adds a MongoDB transaction method.
|
||||||
|
|
||||||
|
### If staying on v6: hygiene (a deliberate stay, not neglect)
|
||||||
|
|
||||||
|
- Pin the Prisma packages to the latest 6.x line and keep taking 6.x patch releases.
|
||||||
|
- Track Prisma release notes and security advisories for the 6.x line.
|
||||||
|
- Keep the classic v6 MongoDB setup: `url = env("DATABASE_URL")` in the schema, `db push`
|
||||||
|
workflow, no SQL driver adapters (see [`prisma-orm-setup`](../prisma-orm-setup/references/v6-mongodb.md) for the v6 MongoDB shape).
|
||||||
|
- Re-evaluate when Prisma 8's MongoDB support leaves Early Access, or when the blockers are resolved.
|
||||||
|
|
||||||
|
## Reference files
|
||||||
|
|
||||||
|
| Reference | What it covers |
|
||||||
|
|-----------|----------------|
|
||||||
|
| `references/decision-stay-or-migrate.md` | The full decision framing, blocker checks, and stay-hygiene detail |
|
||||||
|
| `references/schema-contract-mapping.md` | v6 schema (`mongodb` provider, `@db.ObjectId`, composite types) → Prisma 8 contract concepts |
|
||||||
|
| `references/client-api-mapping.md` | v6 client calls → Prisma 8 equivalents, incl. raw escape hatches and transactions — names map, parity does not |
|
||||||
|
| `references/migrations-mapping.md` | v6 `db push`-only story → Prisma 8's plan/migrate/verify/sign flow |
|
||||||
|
| `references/verify-cutover-checklist.md` | No-data-moves verification: same DB, index parity, staged round-trip before cutover |
|
||||||
|
|
||||||
|
## Verified against
|
||||||
|
|
||||||
|
Prisma 8 claims in this skill were checked against the
|
||||||
|
[Prisma ORM 6 to 8 (MongoDB) guide](https://www.prisma.io/docs/guides/upgrade-prisma-orm/mongodb),
|
||||||
|
written for `@prisma/orm-mongo` 8.0.0-rc.13, and the `prisma-8` skill in
|
||||||
|
[prisma/orm](https://github.com/prisma/orm/tree/main/skills/prisma-8) at commit
|
||||||
|
`75c1460515fa2f11971533f6a1dec5dab35d4123`. MongoDB support still changes between release
|
||||||
|
candidates: **before acting on any Prisma 8 claim, check the installed version**
|
||||||
|
(`npm ls @prisma/orm-mongo`) and its synced `prisma-8` skill.
|
||||||
|
|
||||||
|
Prisma 8 on MongoDB requires Node.js 22.18+ (24.11+ on the 24 line; 24 recommended),
|
||||||
|
TypeScript 5.9+, MongoDB 8.0+, and `mongodb@7` as a peer dependency. The `mongodb@7` driver
|
||||||
|
no longer accepts AWS credentials in the connection string.
|
||||||
|
|
||||||
|
## Hand-off rule
|
||||||
|
|
||||||
|
This skill is the **discovery bridge**, not a replacement for Prisma 8's own
|
||||||
|
documentation. After a project switches to Prisma 8, run `prisma skills sync`, read the
|
||||||
|
synced `prisma-8/SKILL.md`, and follow it for day-to-day work — do not keep working from
|
||||||
|
this skill's summaries.
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
# client-api-mapping
|
||||||
|
|
||||||
|
How v6 Prisma Client calls map to Prisma 8's Mongo client — names map, parity does not.
|
||||||
|
|
||||||
|
## Priority
|
||||||
|
|
||||||
|
CRITICAL
|
||||||
|
|
||||||
|
## Why It Matters
|
||||||
|
|
||||||
|
The v6 and Prisma 8 client APIs look superficially similar, but none of the v6 MongoDB raw
|
||||||
|
methods exist under their old names, aggregation moved to a different lane entirely, and
|
||||||
|
transactions go through the driver rather than a Prisma method. Assuming parity produces
|
||||||
|
code that does not compile — or, in the transactions case, code that silently loses
|
||||||
|
atomicity.
|
||||||
|
|
||||||
|
## The mapping
|
||||||
|
|
||||||
|
| v6 call | Prisma 8 equivalent | Notes |
|
||||||
|
|---------|------------------------|-------|
|
||||||
|
| `prisma.user.findMany(...)` | `db.orm.users.where({ ... }).all()` | Chained API; collection-name keys (see `schema-contract-mapping.md`) |
|
||||||
|
| `prisma.user.findFirst(...)` | `db.orm.users.where({ ... }).first()` | `.where(...)` takes a plain equality object, not `{ equals: ... }` |
|
||||||
|
| `create` / `update` / `upsert` / `delete` | Same names on `db.orm.<collection>` | Every mutation except `create` needs a `.where(...)` first |
|
||||||
|
| `updateMany` / `deleteMany` | `updateAll` / `deleteAll` | |
|
||||||
|
| `prisma.user.aggregate(...)`, `groupBy(...)` | **No ORM equivalent.** Build a plan with `db.query.from(...).group(...).build()` and run it with `(await db.runtime()).query(plan)` | Group totals come from `acc` in `@prisma/orm-mongo/query-builder` |
|
||||||
|
| `<model>.findRaw(...)`, `<model>.aggregateRaw(...)` ([v6 docs](https://www.prisma.io/docs/orm/prisma-client/using-raw-sql/raw-queries#findraw)) | `db.raw.collection('<name>').aggregate([...]).build()`, or `db.query.rawCommand(...)` | Run the plan with `(await db.runtime()).query(plan)` |
|
||||||
|
| `$runCommandRaw(...)` ([v6 docs](https://www.prisma.io/docs/orm/prisma-client/using-raw-sql/raw-queries#runcommandraw)) | **No Prisma equivalent.** Create a `MongoClient`, pass it to the `mongo(...)` binding as `mongoClient`, and call `mongoClient.db(...).command(...)` | `db.raw` is collection-scoped; database-level commands go through the driver |
|
||||||
|
| `$transaction(...)` — works on v6 with a replica set ([v6 docs](https://www.prisma.io/docs/orm/overview/databases/mongodb#replica-set-configuration)) | **No Prisma method yet.** Use `mongodb` driver sessions (`client.startSession()` / `session.withTransaction(...)`) on a replica set | Pass `{ session }` to every operation; an operation without it runs outside the transaction |
|
||||||
|
| `$connect` / `$disconnect` | Connects lazily on first use; `db.close()` disconnects | |
|
||||||
|
|
||||||
|
**ObjectId filters in the pipeline builder:** `.match((f) => f.authorId.eq(authorId))` sends
|
||||||
|
the id as a plain string and matches nothing. Filter ObjectId fields through the ORM client
|
||||||
|
(`db.orm.posts.where({ authorId })`), or use `db.query.rawCommand(...)` with a real
|
||||||
|
`ObjectId`.
|
||||||
|
|
||||||
|
## Bad
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Assuming v6 names exist in Prisma 8:
|
||||||
|
await db.users.$runCommandRaw({ collStats: 'users' }); // no such method
|
||||||
|
await db.transaction(async (tx) => { ... }); // no such method on the MongoDB client
|
||||||
|
```
|
||||||
|
|
||||||
|
## Good
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { acc } from '@prisma/orm-mongo/query-builder';
|
||||||
|
|
||||||
|
// Aggregation through the typed pipeline builder:
|
||||||
|
const plan = db.query
|
||||||
|
.from('users')
|
||||||
|
.group((f) => ({ _id: f.role, n: acc.count() }))
|
||||||
|
.build();
|
||||||
|
const byRole = await (await db.runtime()).query(plan).toArray();
|
||||||
|
|
||||||
|
// Database-level commands through the MongoClient shared with the binding:
|
||||||
|
await mongoClient.db('my-app-db').command({ ping: 1 });
|
||||||
|
|
||||||
|
// Multi-document atomicity through a driver session:
|
||||||
|
const session = mongoClient.startSession();
|
||||||
|
try {
|
||||||
|
await session.withTransaction(async () => {
|
||||||
|
// ...writes, each with { session }...
|
||||||
|
});
|
||||||
|
} finally {
|
||||||
|
await session.endSession();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- [Prisma ORM 6 to 8 (MongoDB) guide, step 3](https://www.prisma.io/docs/guides/upgrade-prisma-orm/mongodb#3-port-client-calls)
|
||||||
|
- [Prisma 8 transactions on MongoDB](https://www.prisma.io/docs/orm/fundamentals/transactions#transactions-on-mongodb)
|
||||||
|
- [v6 MongoDB raw queries](https://www.prisma.io/docs/orm/prisma-client/using-raw-sql/raw-queries#raw-queries-with-mongodb)
|
||||||
|
- The `prisma-8` skill's `references/queries-mongo.md` — authoritative for the Prisma 8 side
|
||||||
+86
@@ -0,0 +1,86 @@
|
|||||||
|
# decision-stay-or-migrate
|
||||||
|
|
||||||
|
How to decide between migrating a MongoDB project to Prisma 8 and staying on Prisma v6.
|
||||||
|
|
||||||
|
## Priority
|
||||||
|
|
||||||
|
CRITICAL
|
||||||
|
|
||||||
|
## Why It Matters
|
||||||
|
|
||||||
|
MongoDB projects cannot follow the general "upgrade Prisma" advice: Prisma 7 has no MongoDB
|
||||||
|
connector, so the forward path is Prisma 8. Advising an impossible v7 upgrade, or
|
||||||
|
silently rewriting the app onto SQL, are both serious failure modes. The encouraged path is
|
||||||
|
migrating to Prisma 8 — its MongoDB support is Early Access and the Prisma team wants
|
||||||
|
early adopters' feedback — with a deliberate stay on v6 where a hard blocker applies.
|
||||||
|
|
||||||
|
## The facts the decision rests on
|
||||||
|
|
||||||
|
Prisma 8 side ([supported databases](https://www.prisma.io/docs/orm/supported-databases),
|
||||||
|
[6 to 8 MongoDB guide](https://www.prisma.io/docs/guides/upgrade-prisma-orm/mongodb)):
|
||||||
|
|
||||||
|
- **MongoDB support is Early Access** in `@prisma/orm-mongo`; PostgreSQL is a release
|
||||||
|
candidate.
|
||||||
|
- The implementation is not a stub: an ORM client, a typed aggregation-pipeline builder, a
|
||||||
|
raw lane, and first-class contract-driven migrations.
|
||||||
|
- **Prisma 8 has no MongoDB transaction method yet** — there is no `db.transaction(...)` on
|
||||||
|
the MongoDB client. Multi-document atomicity uses the `mongodb` driver's session API on a
|
||||||
|
replica set. This skill will be updated when a transaction method ships.
|
||||||
|
- Early Access means MongoDB behavior can change between release candidates. Floor:
|
||||||
|
Node.js 22.18+, TypeScript 5.9+, MongoDB 8.0+, and `mongodb@7`.
|
||||||
|
|
||||||
|
Prisma v6 side:
|
||||||
|
|
||||||
|
- v6 fully supports MongoDB, including transactions on replica sets — "MongoDB only allows
|
||||||
|
you to start a transaction on a replica set. Prisma ORM uses transactions internally"
|
||||||
|
([replica set configuration](https://www.prisma.io/docs/orm/overview/databases/mongodb#replica-set-configuration)).
|
||||||
|
- v6 MongoDB has no Prisma Migrate; the workflow is `db push`
|
||||||
|
([no support for Prisma Migrate](https://www.prisma.io/docs/orm/overview/databases/mongodb#no-support-for-prisma-migrate)).
|
||||||
|
|
||||||
|
## Blocker checks before migrating
|
||||||
|
|
||||||
|
Run these checks yourself — from the codebase, not by asking the user:
|
||||||
|
|
||||||
|
- **Search the codebase for `$transaction` usage** (grep for `$transaction`). If present,
|
||||||
|
plan the raw-driver session equivalents before migrating (see `client-api-mapping.md`) —
|
||||||
|
or stay on v6 until Prisma 8 adds a MongoDB transaction method.
|
||||||
|
- **Check the MongoDB server version** (must be 8.0+ for Prisma 8; v6 tolerated older).
|
||||||
|
- **Confirm the team can absorb changes between release candidates.** Someone has to
|
||||||
|
follow the release notes and update the code. For a production app, confirm the user accepts
|
||||||
|
Early Access status before migrating.
|
||||||
|
|
||||||
|
## Bad
|
||||||
|
|
||||||
|
```text
|
||||||
|
User: "We're on Prisma 6 with MongoDB. Should we upgrade to Prisma 7?"
|
||||||
|
Agent: "Yes — here's the v7 upgrade guide. Step 1: install a driver adapter..."
|
||||||
|
```
|
||||||
|
|
||||||
|
Prisma 7 has no MongoDB connector; this migration is impossible and the SQL driver-adapter
|
||||||
|
steps corrupt a working v6 setup.
|
||||||
|
|
||||||
|
## Good
|
||||||
|
|
||||||
|
```text
|
||||||
|
User: "We're on Prisma 6 with MongoDB. Should we upgrade to Prisma 7?"
|
||||||
|
Agent: "Prisma 7 does not support MongoDB — v6 is the last classic-ORM
|
||||||
|
major for MongoDB. The path forward is Prisma 8, the successor: its MongoDB support is
|
||||||
|
Early Access and migrating is encouraged. Let me check the codebase for blockers first —
|
||||||
|
searching for $transaction usage and checking the MongoDB server version..."
|
||||||
|
```
|
||||||
|
|
||||||
|
## Stay-on-v6 hygiene
|
||||||
|
|
||||||
|
Staying is a decision, not a default-by-neglect:
|
||||||
|
|
||||||
|
- Pin `prisma` and `@prisma/client` to the latest 6.x and keep taking 6.x patches.
|
||||||
|
- Watch Prisma release notes and security advisories for the 6.x maintenance line.
|
||||||
|
- Keep the classic setup (`url = env("DATABASE_URL")` in the schema; `db push`; no SQL
|
||||||
|
driver adapters).
|
||||||
|
- Re-evaluate when Prisma 8's MongoDB support leaves Early Access, or when the blockers are resolved.
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- [Prisma ORM 6 to 8 (MongoDB) guide](https://www.prisma.io/docs/guides/upgrade-prisma-orm/mongodb)
|
||||||
|
- [Prisma 8 supported databases](https://www.prisma.io/docs/orm/supported-databases)
|
||||||
|
- [Prisma v6 MongoDB documentation](https://www.prisma.io/docs/orm/overview/databases/mongodb)
|
||||||
@@ -0,0 +1,83 @@
|
|||||||
|
# migrations-mapping
|
||||||
|
|
||||||
|
How the v6 MongoDB "no migrations" story maps onto Prisma 8's first-class migration flow.
|
||||||
|
|
||||||
|
## Priority
|
||||||
|
|
||||||
|
HIGH
|
||||||
|
|
||||||
|
## Why It Matters
|
||||||
|
|
||||||
|
This is the largest workflow change in the migration — in v6, MongoDB explicitly has no
|
||||||
|
Prisma Migrate, while in Prisma 8 MongoDB participates in the full migration lifecycle.
|
||||||
|
Teams porting a `db push` habit into Prisma 8 without understanding the plan/verify/sign flow
|
||||||
|
will fight the tooling or bypass its safety rails.
|
||||||
|
|
||||||
|
## v6: `db push` only
|
||||||
|
|
||||||
|
MongoDB on v6 has no Prisma Migrate and no plans to add it — "MongoDB projects do not rely
|
||||||
|
on internal schemas" ([no support for Prisma Migrate](https://www.prisma.io/docs/orm/overview/databases/mongodb#no-support-for-prisma-migrate)).
|
||||||
|
The workflow is `prisma db push` to sync indexes and unique constraints, with no migration
|
||||||
|
history on disk.
|
||||||
|
|
||||||
|
## Prisma 8: bring the existing database under management
|
||||||
|
|
||||||
|
The database already has collections and data, so bootstrap it with `db update`. It diffs the
|
||||||
|
live database against the contract, applies the difference (strict validators, plus indexes
|
||||||
|
the contract declares that v6 never created), and signs the database:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx prisma contract emit
|
||||||
|
npx prisma db update --db "$DATABASE_URL" --dry-run
|
||||||
|
npx prisma db update --db "$DATABASE_URL" --advance-ref db
|
||||||
|
```
|
||||||
|
|
||||||
|
`--advance-ref db` records the result as the `db` ref that later migration plans diff from.
|
||||||
|
|
||||||
|
**Do not use `db init` here.** It only applies additive changes, and adding a validator to a
|
||||||
|
collection with existing documents counts as destructive, so it refuses.
|
||||||
|
|
||||||
|
## Prisma 8: every later schema change
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx prisma contract emit
|
||||||
|
npx prisma migration plan --name add_posts_indexes
|
||||||
|
npx prisma db migrate --db "$DATABASE_URL" --advance-ref db
|
||||||
|
npx prisma db verify --db "$DATABASE_URL"
|
||||||
|
```
|
||||||
|
|
||||||
|
- **Declare, do not hand-write:** indexes and validators live in the contract, and
|
||||||
|
`migration plan` derives the operations. Rendered MongoDB migrations import their factories
|
||||||
|
(`createCollection`, `validatedCollection`, `setValidation`, `createIndex`, `dropIndex`,
|
||||||
|
`collMod`, `dataTransform`) from `@prisma/orm-mongo/target/migration`.
|
||||||
|
- **Marker storage:** Prisma 8 records the database's contract state in a document in the
|
||||||
|
`_prisma_migrations` collection.
|
||||||
|
- **DDL is not transactional on MongoDB:** an interrupted `db migrate` is resumed by running
|
||||||
|
it again. After fixing anything by hand, run `prisma db sign` so the signature matches the
|
||||||
|
database.
|
||||||
|
- **Push-style alternative:** `db update` without a migration plan is the `db push` analogue
|
||||||
|
for local experiments. It keeps no history.
|
||||||
|
- **Validators:** Prisma 8 adds strict `$jsonSchema` validators to each collection by default.
|
||||||
|
Once they are live, writes to documents that do not match the contract fail with
|
||||||
|
`Document failed validation`.
|
||||||
|
|
||||||
|
## Bad
|
||||||
|
|
||||||
|
```text
|
||||||
|
Porting the v6 habit: run `db update` for every change in production, accumulating no
|
||||||
|
migration history, and hand-editing collections when verification fails.
|
||||||
|
```
|
||||||
|
|
||||||
|
## Good
|
||||||
|
|
||||||
|
```text
|
||||||
|
Bootstrap once with `db update --advance-ref db`. Then emit the contract, plan a migration,
|
||||||
|
apply it with `db migrate`, and check with `db verify`. Reserve plain `db update` for local
|
||||||
|
experiments, mirroring how `db push` was used on v6.
|
||||||
|
```
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- [Prisma ORM 6 to 8 (MongoDB) guide, step 4](https://www.prisma.io/docs/guides/upgrade-prisma-orm/mongodb#4-adopt-the-migration-lifecycle)
|
||||||
|
- [v6: no Prisma Migrate for MongoDB](https://www.prisma.io/docs/orm/overview/databases/mongodb#no-support-for-prisma-migrate)
|
||||||
|
- The `prisma-8` skill's `references/migrations.md` — authoritative for the Prisma 8 side
|
||||||
+65
@@ -0,0 +1,65 @@
|
|||||||
|
# schema-contract-mapping
|
||||||
|
|
||||||
|
How v6 MongoDB schema concepts map onto Prisma 8's contract model.
|
||||||
|
|
||||||
|
## Priority
|
||||||
|
|
||||||
|
HIGH
|
||||||
|
|
||||||
|
## Why It Matters
|
||||||
|
|
||||||
|
Prisma 8 describes the database with a *contract* (authored in PSL or TypeScript), and
|
||||||
|
several v6 MongoDB idioms have different equivalents. Translating mechanically without
|
||||||
|
knowing the mapping produces contracts that fail `contract emit` or verification, or that
|
||||||
|
silently change collection addressing.
|
||||||
|
|
||||||
|
## Start without porting
|
||||||
|
|
||||||
|
Prisma 8 can read the v6 `schema.prisma` directly: set
|
||||||
|
`contract: prisma6Schema('prisma/schema.prisma')` in `prisma.config.ts`, with `prisma6Schema`
|
||||||
|
from `@prisma/orm-mongo/config`. v6 keeps owning the database; after each schema change there,
|
||||||
|
run `prisma contract emit` and `prisma db sign`. A construct Prisma 8 cannot express fails
|
||||||
|
`contract emit` with a `PSL.PRISMA6_MONGO_*` diagnostic. Port the schema to a contract when
|
||||||
|
you need what v6 syntax cannot express, such as polymorphism.
|
||||||
|
|
||||||
|
## The mapping
|
||||||
|
|
||||||
|
| v6 concept | Prisma 8 equivalent | Notes |
|
||||||
|
|------------|------------------------|-------|
|
||||||
|
| (nothing) | `// use prisma-8` as the first line of `contract.prisma` | Without it, `contract emit` fails with `CONTRACT.SOURCE_LOAD_FAILED` |
|
||||||
|
| `datasource db { provider = "mongodb" }` + `url = env(...)` ([v6 docs](https://www.prisma.io/docs/orm/overview/databases/mongodb#example)) | No provider in the contract. `prisma.config.ts` wraps `defineConfig` from `@prisma/orm-mongo/config` in `definePrismaConfig`, with `db.connection` | `prisma orm init --target mongodb` scaffolds it; point the connection at the same database v6 uses |
|
||||||
|
| `id String @id @default(auto()) @map("_id") @db.ObjectId` ([using ObjectId](https://www.prisma.io/docs/orm/overview/databases/mongodb#using-objectid)) | `id ObjectId @id @map("_id")` | |
|
||||||
|
| `Int`, `Float`, `Boolean`, `DateTime` | `Int32`, `Double`, `Bool`, `Date` | The v6 names still work with a `PSL_DEPRECATED_SCALAR_NAME` warning; a later release removes them |
|
||||||
|
| `BigInt`, `Decimal`, `Bytes`, `Json` | `Int64`, `Decimal128`, `Binary`, `Json` | `Json` holds only JSON values; type a field that holds other BSON values, such as a `Date`, as `Bson` |
|
||||||
|
| `@default(now())`, `@updatedAt` | `temporal.createdAt()`, `temporal.updatedAt()` | |
|
||||||
|
| Composite types: `type Address { ... }` ([composite types](https://www.prisma.io/docs/orm/prisma-client/special-fields-and-types/composite-types)) | `type Address { ... }` | Unchanged |
|
||||||
|
| Enums read and written by key | Enums read and write their **storage value** (`role: 'author'`, not `'Author'`) | Declare the storage value in the enum, for example `Author = "author"` |
|
||||||
|
| Model names address the client (`prisma.user`) | **Collection names** address the ORM: `db.orm.users` — the `@@map(...)` value, or the model name exactly as written when there is no `@@map`. `db.orm.User` does not exist for a model mapped to `users` | The most common porting mistake |
|
||||||
|
| Indexes declared in schema, applied by `db push` | `@@index(...)` / `@@unique(...)` in the contract, applied by migrations | See `migrations-mapping.md` |
|
||||||
|
| No native polymorphism | `@@discriminator(field)` on the base model and `@@base(Base, "value")` on each variant | Declare a variant for **every** value the field has in existing data: the generated validator rejects writes to documents with an undeclared value. A variant must declare at least one field |
|
||||||
|
|
||||||
|
## Bad
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Ported from v6 and addressed by model name:
|
||||||
|
const user = await db.orm.User.where({ email }).first(); // no such key — the collection is mapped to "users"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Good
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Mongo ORM keys are collection names (@@map value, or the model name as written):
|
||||||
|
const user = await db.orm.users.where({ email }).first();
|
||||||
|
```
|
||||||
|
|
||||||
|
## Environment requirements
|
||||||
|
|
||||||
|
Prisma 8 on MongoDB requires MongoDB 8.0+ and `mongodb@7` as a peer dependency. v6 supports
|
||||||
|
older MongoDB servers, so check the server version before planning a migration.
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- [Prisma ORM 6 to 8 (MongoDB) guide, step 2](https://www.prisma.io/docs/guides/upgrade-prisma-orm/mongodb#2-port-the-schema-to-a-contract)
|
||||||
|
- [v6 MongoDB schema documentation](https://www.prisma.io/docs/orm/overview/databases/mongodb)
|
||||||
|
- [v6 composite types (MongoDB-only)](https://www.prisma.io/docs/orm/prisma-client/special-fields-and-types/composite-types)
|
||||||
|
- The `prisma-8` skill's `references/contract.md` — authoritative for the Prisma 8 side
|
||||||
+60
@@ -0,0 +1,60 @@
|
|||||||
|
# verify-cutover-checklist
|
||||||
|
|
||||||
|
Verification checklist for a v6 → Prisma 8 cutover: the data never moves — only the code does.
|
||||||
|
|
||||||
|
## Priority
|
||||||
|
|
||||||
|
CRITICAL
|
||||||
|
|
||||||
|
## Why It Matters
|
||||||
|
|
||||||
|
A v6 → Prisma 8 migration is a *client and workflow* migration against the **same MongoDB
|
||||||
|
database** — there is no data export/import step, and introducing one (or pointing the new
|
||||||
|
stack at a fresh database) turns a code migration into an outage. The checklist below keeps
|
||||||
|
the cutover observable and reversible.
|
||||||
|
|
||||||
|
## Ground rules
|
||||||
|
|
||||||
|
- **No data moves.** The Prisma 8 contract is authored to describe the existing collections;
|
||||||
|
both stacks read the same database during the staged phase.
|
||||||
|
- **v6 stays runnable until cutover is verified.** Do not delete the v6 client, schema, or
|
||||||
|
dependencies until the checklist passes.
|
||||||
|
|
||||||
|
## Checklist
|
||||||
|
|
||||||
|
1. **Same database, verified:** the Prisma 8 config points at the same connection string /
|
||||||
|
database name the v6 app uses. The `mongodb@7` driver rejects some URLs v6 accepted, such
|
||||||
|
as AWS credentials in the connection string — validate the URL with the driver first.
|
||||||
|
2. **Server floor:** MongoDB server is 8.0+ (Prisma 8's requirement; v6 tolerated older).
|
||||||
|
Confirm before authoring any contract.
|
||||||
|
3. **Rehearsal on a copy:** on a throwaway copy of the database, run `contract emit`,
|
||||||
|
`db update --dry-run`, `db update`, and `db verify`, and confirm `db verify` passes before
|
||||||
|
touching production. Verification failures here are contract-mapping bugs, not database
|
||||||
|
problems.
|
||||||
|
4. **Index parity:** enumerate indexes on every collection (`db.collection.getIndexes()`)
|
||||||
|
and confirm the Prisma 8 contract declares the same set — v6 `db push` may have created
|
||||||
|
indexes the new contract must re-declare, or verification and query performance will
|
||||||
|
diverge.
|
||||||
|
5. **Validator impact assessed:** Prisma 8 emits closed `$jsonSchema` validators by default;
|
||||||
|
confirm legacy documents (extra fields, drifted shapes) pass them on the staging copy
|
||||||
|
before applying to production.
|
||||||
|
6. **Storage-name addressing audited:** every ported call site uses collection storage
|
||||||
|
names (`db.orm.users`), not model names (see `schema-contract-mapping.md`).
|
||||||
|
7. **Transaction inventory mapped:** grep the v6 app for `$transaction`; each hit gets a
|
||||||
|
`mongodb` driver-session equivalent on a replica set (see `client-api-mapping.md`).
|
||||||
|
8. **Raw call inventory mapped:** every `$runCommandRaw` / `findRaw` / `aggregateRaw` call
|
||||||
|
has an explicit Prisma 8 replacement (`db.raw`, `db.query.rawCommand(...)`, the pipeline
|
||||||
|
builder, or the shared `MongoClient`).
|
||||||
|
9. **Staged read-only soak:** run the Prisma 8 stack read-only against staging/production data
|
||||||
|
alongside v6 and compare outputs before allowing writes.
|
||||||
|
10. **Cutover + rollback:** switch writes to Prisma 8 only after the soak; keep the v6 branch
|
||||||
|
deployable as the rollback path. Rolling back is a code rollback — the data was never
|
||||||
|
moved.
|
||||||
|
|
||||||
|
After cutover, follow the synced `prisma-8` skill for ongoing work (see the hand-off rule
|
||||||
|
in `SKILL.md`).
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- [v6 MongoDB documentation](https://www.prisma.io/docs/orm/overview/databases/mongodb)
|
||||||
|
- [Prisma ORM 6 to 8 (MongoDB) guide, step 5](https://www.prisma.io/docs/guides/upgrade-prisma-orm/mongodb#5-pre-flight-checklist-before-production-cutover)
|
||||||
@@ -0,0 +1,82 @@
|
|||||||
|
---
|
||||||
|
name: prisma-orm-setup
|
||||||
|
description: Set up Prisma ORM in an application, connect its database, or troubleshoot the connection of an existing Prisma 6, 7, or 8 app. Defaults new applications to Prisma ORM 8 and loads the package-owned prisma-8 skill; keeps existing Prisma 6/7 apps on their version with provider references for PostgreSQL, MySQL, SQLite, SQL Server, CockroachDB, MongoDB, and Prisma Postgres.
|
||||||
|
license: MIT
|
||||||
|
metadata:
|
||||||
|
author: prisma
|
||||||
|
version: "1.0.0"
|
||||||
|
---
|
||||||
|
|
||||||
|
# Prisma ORM setup
|
||||||
|
|
||||||
|
This skill owns ORM version selection for setup and connection work. Preserve the application's ORM version and intended database. A connection repair does not require a major upgrade.
|
||||||
|
|
||||||
|
New applications default to **Prisma ORM 8**. Detailed Prisma 8 configuration, queries, migrations, and runtime code belong to the versioned [prisma-8 skill](https://github.com/prisma/orm/tree/main/skills/prisma-8) shipped with the ORM package.
|
||||||
|
|
||||||
|
## 1. Detect the starting point
|
||||||
|
|
||||||
|
Read the package manifest, lockfile, Prisma configuration, schema, and application imports. Identify the ORM version, database provider, and runtime. The CLI version alone does not identify the application's version: a Prisma 8 CLI can coexist with a legacy client, so inspect `@prisma/client`, `@prisma/prisma7`, and the schema and configuration.
|
||||||
|
|
||||||
|
| Starting point | Path |
|
||||||
|
| ------------------------------------------------------- | -------------------------------------------------------- |
|
||||||
|
| Prisma 8 application | Step 4, without reinitializing |
|
||||||
|
| New application without a version choice | Step 3 |
|
||||||
|
| Prisma 6 or 7 application, or an explicit earlier major | [Step 5](#5-set-up-or-repair-an-earlier-version) |
|
||||||
|
|
||||||
|
For a new application, check the selected Prisma 8 release's [provider support](https://www.prisma.io/docs/orm/supported-databases) and runtime requirements before installing. If the provider is unsupported, explain the limitation and offer an explicitly selected earlier version. Keep the requested database; do not silently fall back or invent a supported target.
|
||||||
|
|
||||||
|
Use an existing database when supplied. Load `prisma-postgres-setup` only when Prisma Postgres is needed and no connection has been selected yet; return here once connected.
|
||||||
|
|
||||||
|
## 2. Handle requested major upgrades separately
|
||||||
|
|
||||||
|
When the user requests a major upgrade, load a workflow that supports the source version and provider. For PostgreSQL 7-to-8, use the [Prisma migration guide](https://www.prisma.io/docs/guides/upgrade-prisma-orm/postgresql); for MongoDB 6-to-8, use [prisma-mongodb-upgrade](../prisma-mongodb-upgrade/SKILL.md). Other providers need an explicitly supported migration path. `prisma-upgrade-v7` covers **6 to 7**; the package-owned `prisma-8` upgrade reference covers updates within 8.
|
||||||
|
|
||||||
|
## 3. Bootstrap a new Prisma 8 application
|
||||||
|
|
||||||
|
Check the selected release's [runtime requirements](https://www.prisma.io/docs/orm/release-status) and [initialization guide](https://www.prisma.io/docs/cli/orm-init). Resolve and pin a published Prisma CLI **8** release, including its prerelease suffix if needed; verify its version before initialization. Do not rely on a floating `latest` remaining version 8.
|
||||||
|
|
||||||
|
Use the project's package manager to run the installed CLI. For PostgreSQL and Prisma schema language authoring:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma orm init --yes --target postgres --authoring psl
|
||||||
|
```
|
||||||
|
|
||||||
|
Use the supported target for the selected provider. Preserve existing application files and connection configuration; do not let setup provision an unrelated database. Verify that the resolved ORM package is version 8 before proceeding.
|
||||||
|
|
||||||
|
## 4. Load the installed Prisma 8 guidance
|
||||||
|
|
||||||
|
Run the installed CLI through the project's package manager:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
prisma skills sync
|
||||||
|
```
|
||||||
|
|
||||||
|
Then **read** the synced `prisma-8/SKILL.md`, for example `.agents/skills/prisma-8/SKILL.md`, and follow its preconditions and selected references. Syncing alone does not load the instructions. If the package-owned guidance cannot be loaded, report the blocker. Continue with step 6.
|
||||||
|
|
||||||
|
## 5. Set up or repair an earlier version
|
||||||
|
|
||||||
|
For a new setup that explicitly selects an earlier version, pin packages to that major and use its runtime requirements. Keep the CLI, client, and SQL adapter releases compatible. Existing dependencies need not change for a connection repair.
|
||||||
|
|
||||||
|
- **Prisma 7 SQL:** use the provider reference below and [client setup](references/v7-client-setup.md).
|
||||||
|
- **Prisma 6 MongoDB:** use [MongoDB setup](references/v6-mongodb.md). SQL driver adapters do not apply.
|
||||||
|
- **Prisma 6 SQL:** preserve its generator, schema URL, and client initialization. Use the provider's connection details below and the [Prisma 6 documentation](https://www.prisma.io/docs/orm/v6); do not copy the Prisma 7 configuration or adapter examples into it.
|
||||||
|
|
||||||
|
| Database | Reference |
|
||||||
|
| -------------------------------- | --------------------------------------------------------- |
|
||||||
|
| PostgreSQL | [PostgreSQL](references/v7-postgresql.md) |
|
||||||
|
| MySQL / MariaDB / PlanetScale | [MySQL](references/v7-mysql.md) |
|
||||||
|
| SQLite / Turso | [SQLite](references/v7-sqlite.md) |
|
||||||
|
| Microsoft SQL Server / Azure SQL | [SQL Server](references/v7-sqlserver.md) |
|
||||||
|
| CockroachDB | [CockroachDB](references/v7-cockroachdb.md) |
|
||||||
|
| MongoDB / Atlas on Prisma 6 | [MongoDB](references/v6-mongodb.md) |
|
||||||
|
| Prisma Postgres with Prisma 7 | [Prisma Postgres](references/v7-prisma-postgres.md) |
|
||||||
|
|
||||||
|
The Prisma 7 SQL examples were verified with Prisma 7.10.0; the MongoDB examples with Prisma 6.19.3.
|
||||||
|
|
||||||
|
## 6. Connect and verify
|
||||||
|
|
||||||
|
The CLI and the application can load different environment files. Load the intended environment for each without printing secrets, and keep credentials in ignored environment files or the host's secret configuration. For SQL adapters, make the adapter's runtime options address the same database as the CLI connection URL.
|
||||||
|
|
||||||
|
For an existing app, preserve schema, migrations, and generator configuration unless the requested work requires changes. Diagnose the connection before running schema-changing commands.
|
||||||
|
|
||||||
|
Run the project's relevant checks and a read-only query through the application's client against the intended database. Report the ORM version, the loaded `prisma-8` skill version where applicable, and the query result. Package installation or a successful skill sync alone is not a completed setup.
|
||||||
@@ -0,0 +1,102 @@
|
|||||||
|
# MongoDB Setup
|
||||||
|
|
||||||
|
This reference configures **Prisma ORM 6 MongoDB** applications. Preserve an existing Prisma 6 app or use this path when 6 is explicitly selected. Do not apply Prisma 7 SQL adapters here.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- MongoDB 4.2+
|
||||||
|
- Replica Set configured (required for transactions)
|
||||||
|
- Latest Prisma 6.x release, or your team's pinned Prisma 6 version
|
||||||
|
- A Node.js and TypeScript version supported by the selected Prisma 6 release
|
||||||
|
|
||||||
|
## 1. Schema Configuration
|
||||||
|
|
||||||
|
Use the standard Prisma 6 MongoDB setup with `prisma-client-js`.
|
||||||
|
|
||||||
|
In `prisma/schema.prisma`:
|
||||||
|
|
||||||
|
```prisma
|
||||||
|
datasource db {
|
||||||
|
provider = "mongodb"
|
||||||
|
url = env("DATABASE_URL")
|
||||||
|
}
|
||||||
|
|
||||||
|
generator client {
|
||||||
|
provider = "prisma-client-js"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Driver Adapters
|
||||||
|
|
||||||
|
Do **not** apply the Prisma 7 SQL adapter setup here. MongoDB does not use a SQL `@prisma/adapter-*` package.
|
||||||
|
|
||||||
|
### ID Field Requirement
|
||||||
|
|
||||||
|
MongoDB models **must** have a mapped `_id` field using `@id` and `@map("_id")`, usually of type `String` with `auto()` and `db.ObjectId`.
|
||||||
|
|
||||||
|
```prisma
|
||||||
|
model User {
|
||||||
|
id String @id @default(auto()) @map("_id") @db.ObjectId
|
||||||
|
email String @unique
|
||||||
|
name String?
|
||||||
|
posts Post[]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Relations
|
||||||
|
|
||||||
|
Relations in MongoDB expect IDs to be `db.ObjectId` type.
|
||||||
|
|
||||||
|
```prisma
|
||||||
|
model Post {
|
||||||
|
id String @id @default(auto()) @map("_id") @db.ObjectId
|
||||||
|
author User @relation(fields: [authorId], references: [id])
|
||||||
|
authorId String @db.ObjectId
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 2. Environment Variable
|
||||||
|
|
||||||
|
In `.env`:
|
||||||
|
|
||||||
|
```env
|
||||||
|
DATABASE_URL="mongodb+srv://user:password@cluster.mongodb.net/mydb?retryWrites=true&w=majority"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Migrations vs Introspection
|
||||||
|
|
||||||
|
- **No Migrations**: MongoDB is schema-less. `prisma migrate` commands **do not work**.
|
||||||
|
- **db push**: Use `prisma db push` to sync indexes and constraints.
|
||||||
|
- **db pull**: Use `prisma db pull` to generate schema from existing data (sampling).
|
||||||
|
|
||||||
|
## Client setup
|
||||||
|
|
||||||
|
Keep existing pinned versions. For a new explicitly selected Prisma 6 setup:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev prisma@6
|
||||||
|
npm install @prisma/client@6 dotenv
|
||||||
|
```
|
||||||
|
|
||||||
|
Generate with the matching CLI, then initialize the client without a SQL adapter:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import 'dotenv/config'
|
||||||
|
import { PrismaClient } from '@prisma/client'
|
||||||
|
|
||||||
|
const prisma = new PrismaClient()
|
||||||
|
```
|
||||||
|
|
||||||
|
Use a read-only model query to verify connectivity. Review any index changes before applying `db push` to an existing database.
|
||||||
|
|
||||||
|
## Common Issues
|
||||||
|
|
||||||
|
### "Transactions not supported"
|
||||||
|
Ensure your MongoDB instance is a **Replica Set**. Standalone instances do not support transactions. Atlas clusters are replica sets by default.
|
||||||
|
|
||||||
|
### "Invalid ObjectID"
|
||||||
|
Ensure fields referencing IDs are decorated with `@db.ObjectId` if the target is an ObjectID.
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- [Prisma 6 MongoDB connector](https://www.prisma.io/docs/orm/v6/overview/databases/mongodb)
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
# Prisma Client Setup
|
||||||
|
|
||||||
|
Generate and instantiate **Prisma ORM 7** Client for SQL providers. For MongoDB, follow [Prisma 6 MongoDB setup](v6-mongodb.md). For an existing Prisma 6 SQL app, preserve its client setup rather than copying these examples.
|
||||||
|
|
||||||
|
## 1. Install dependencies
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install --save-dev prisma@7
|
||||||
|
npm install @prisma/client@7 dotenv
|
||||||
|
```
|
||||||
|
|
||||||
|
For an existing application, retain its pinned releases. For a new Prisma 7 application, use compatible CLI, client, and adapter versions and check the [Prisma 7 runtime requirements](https://www.prisma.io/docs/guides/upgrade-prisma-orm/v7#prerequisites).
|
||||||
|
|
||||||
|
## 2. Add generator block
|
||||||
|
|
||||||
|
In `prisma/schema.prisma`:
|
||||||
|
|
||||||
|
```prisma
|
||||||
|
generator client {
|
||||||
|
provider = "prisma-client"
|
||||||
|
output = "../generated"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`prisma-client` requires an explicit `output` path and does not generate into `node_modules` by default.
|
||||||
|
|
||||||
|
## 3. Generate Prisma Client
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx prisma generate
|
||||||
|
```
|
||||||
|
|
||||||
|
Re-run `prisma generate` after every schema change to keep the client in sync.
|
||||||
|
|
||||||
|
## 4. Instantiate Prisma Client
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
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 })
|
||||||
|
```
|
||||||
|
|
||||||
|
If you change the generator `output`, update the import path to match. For the SQL provider workflow, replace `PrismaPg` with the adapter for your database.
|
||||||
|
|
||||||
|
## 5. Use a single instance
|
||||||
|
|
||||||
|
Each `PrismaClient` instance creates a connection pool. Reuse a single instance per app process to avoid exhausting database connections.
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
# CockroachDB Setup
|
||||||
|
|
||||||
|
Configure **Prisma ORM 7** with CockroachDB. For an existing Prisma 6 app, keep its configuration and use the [Prisma 6 docs](https://www.prisma.io/docs/orm/v6); the configuration and adapter examples below are for 7.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- CockroachDB cluster
|
||||||
|
|
||||||
|
## 1. Schema Configuration
|
||||||
|
|
||||||
|
In `prisma/schema.prisma`:
|
||||||
|
|
||||||
|
```prisma
|
||||||
|
datasource db {
|
||||||
|
provider = "cockroachdb"
|
||||||
|
}
|
||||||
|
|
||||||
|
generator client {
|
||||||
|
provider = "prisma-client"
|
||||||
|
output = "../generated"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 2. Config Configuration
|
||||||
|
|
||||||
|
In `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'),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## 3. Environment Variable
|
||||||
|
|
||||||
|
In `.env`:
|
||||||
|
|
||||||
|
```env
|
||||||
|
DATABASE_URL="postgresql://user:password@host:26257/db?sslmode=verify-full"
|
||||||
|
```
|
||||||
|
|
||||||
|
Note: CockroachDB uses the PostgreSQL wire protocol, so the URL often looks like postgresql, but the provider **MUST** be `cockroachdb` in the schema to handle specific CRDB features correctly.
|
||||||
|
|
||||||
|
## Driver Adapter
|
||||||
|
|
||||||
|
Use a driver adapter for the standard SQL workflow. CockroachDB is PostgreSQL-compatible, so use the PostgreSQL adapter.
|
||||||
|
|
||||||
|
1. Install adapter and driver:
|
||||||
|
```bash
|
||||||
|
npm install @prisma/adapter-pg@7 pg
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Instantiate Prisma Client with the adapter:
|
||||||
|
```typescript
|
||||||
|
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 })
|
||||||
|
```
|
||||||
|
|
||||||
|
## ID Generation
|
||||||
|
|
||||||
|
CockroachDB uses `BigInt` or `UUID` for IDs efficiently.
|
||||||
|
|
||||||
|
```prisma
|
||||||
|
model User {
|
||||||
|
id BigInt @id @default(autoincrement()) // Uses unique_rowid()
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
Or using string UUIDs:
|
||||||
|
|
||||||
|
```prisma
|
||||||
|
model User {
|
||||||
|
id String @id @default(dbgenerated("gen_random_uuid()")) @db.Uuid
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Common Issues
|
||||||
|
|
||||||
|
### Schema Introspection
|
||||||
|
Always use `provider = "cockroachdb"` to ensure correct type mapping during `db pull`.
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- [Prisma 7 CockroachDB documentation](https://www.prisma.io/docs/orm/v7/core-concepts/supported-databases/cockroachdb)
|
||||||
@@ -0,0 +1,132 @@
|
|||||||
|
# MySQL Setup
|
||||||
|
|
||||||
|
Configure **Prisma ORM 7** with MySQL and MariaDB. For an existing Prisma 6 app, keep its configuration and use the [Prisma 6 docs](https://www.prisma.io/docs/orm/v6); the configuration and adapter examples below are for 7.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- MySQL or MariaDB database
|
||||||
|
- Connection string
|
||||||
|
|
||||||
|
## 1. Schema Configuration
|
||||||
|
|
||||||
|
In `prisma/schema.prisma`:
|
||||||
|
|
||||||
|
```prisma
|
||||||
|
datasource db {
|
||||||
|
provider = "mysql"
|
||||||
|
}
|
||||||
|
|
||||||
|
generator client {
|
||||||
|
provider = "prisma-client"
|
||||||
|
output = "../generated"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 2. Config Configuration
|
||||||
|
|
||||||
|
In `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'),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## 3. Environment Variable
|
||||||
|
|
||||||
|
In `.env`:
|
||||||
|
|
||||||
|
```env
|
||||||
|
DATABASE_URL="mysql://user:password@localhost:3306/mydb"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Connection String Format
|
||||||
|
|
||||||
|
```
|
||||||
|
mysql://USER:PASSWORD@HOST:PORT/DATABASE
|
||||||
|
```
|
||||||
|
|
||||||
|
- **USER**: Database user
|
||||||
|
- **PASSWORD**: Password
|
||||||
|
- **HOST**: Hostname
|
||||||
|
- **PORT**: Port (default 3306)
|
||||||
|
- **DATABASE**: Database name
|
||||||
|
|
||||||
|
## Driver Adapter
|
||||||
|
|
||||||
|
Use a driver adapter for the standard SQL workflow.
|
||||||
|
|
||||||
|
1. Install adapter and driver:
|
||||||
|
```bash
|
||||||
|
npm install @prisma/adapter-mariadb@7 mariadb
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Set `MYSQL_USER`, `MYSQL_PASSWORD`, and `MYSQL_DATABASE` in the application environment to match the CLI URL, and use the same host and port. Instantiate Prisma Client with the adapter:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import 'dotenv/config'
|
||||||
|
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 })
|
||||||
|
```
|
||||||
|
|
||||||
|
### Text protocol option
|
||||||
|
|
||||||
|
If you need the MariaDB driver's text protocol instead of the default binary `execute()` path, enable `useTextProtocol` explicitly:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { PrismaClient } from '../generated/client'
|
||||||
|
import { PrismaMariaDb } from '@prisma/adapter-mariadb'
|
||||||
|
|
||||||
|
const adapter = new PrismaMariaDb(process.env.DATABASE_URL!, {
|
||||||
|
useTextProtocol: true,
|
||||||
|
})
|
||||||
|
|
||||||
|
const prisma = new PrismaClient({ adapter })
|
||||||
|
```
|
||||||
|
|
||||||
|
Use this only when you specifically need text-protocol compatibility for your MariaDB setup.
|
||||||
|
|
||||||
|
## PlanetScale Setup
|
||||||
|
|
||||||
|
Check whether foreign key constraints are enabled on the PlanetScale database. When they are disabled, use `relationMode = "prisma"` and add indexes for relation fields. Do not override an existing database that has foreign keys enabled.
|
||||||
|
|
||||||
|
In `prisma/schema.prisma`:
|
||||||
|
|
||||||
|
```prisma
|
||||||
|
datasource db {
|
||||||
|
provider = "mysql"
|
||||||
|
relationMode = "prisma" // Emulate foreign keys in Prisma
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Common Issues
|
||||||
|
|
||||||
|
### "Too many connections"
|
||||||
|
|
||||||
|
Set `connectionLimit` on `PrismaMariaDb`, as in the example above. The Prisma 6 `connection_limit` URL parameter does not configure the Prisma 7 adapter pool.
|
||||||
|
|
||||||
|
### JSON Support
|
||||||
|
MySQL 5.7+ supports JSON. MariaDB 10.2+ supports JSON (as an alias for LONGTEXT with check constraints). Prisma handles this, but verify your version.
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- [Prisma 7 connection pool settings](https://www.prisma.io/docs/orm/v7/prisma-client/setup-and-configuration/databases-connections/connection-pool)
|
||||||
|
- [PlanetScale foreign key configuration](https://www.prisma.io/docs/orm/v7/overview/databases/planetscale)
|
||||||
|
- [Prisma 7 MySQL and MariaDB documentation](https://www.prisma.io/docs/orm/v7/core-concepts/supported-databases/mysql)
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
# PostgreSQL Setup
|
||||||
|
|
||||||
|
Configure **Prisma ORM 7** with PostgreSQL. For an existing Prisma 6 app, keep its configuration and use the [Prisma 6 docs](https://www.prisma.io/docs/orm/v6); the configuration and adapter examples below are for 7.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- PostgreSQL database (local or cloud)
|
||||||
|
- Connection string
|
||||||
|
|
||||||
|
## 1. Schema Configuration
|
||||||
|
|
||||||
|
In `prisma/schema.prisma`:
|
||||||
|
|
||||||
|
```prisma
|
||||||
|
datasource db {
|
||||||
|
provider = "postgresql"
|
||||||
|
}
|
||||||
|
|
||||||
|
generator client {
|
||||||
|
provider = "prisma-client"
|
||||||
|
output = "../generated"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 2. Config Configuration
|
||||||
|
|
||||||
|
In `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'),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## 3. Environment Variable
|
||||||
|
|
||||||
|
In `.env`:
|
||||||
|
|
||||||
|
```env
|
||||||
|
DATABASE_URL="postgresql://user:password@localhost:5432/mydb?schema=public"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Connection String Format
|
||||||
|
|
||||||
|
```
|
||||||
|
postgresql://USER:PASSWORD@HOST:PORT/DATABASE?schema=SCHEMA
|
||||||
|
```
|
||||||
|
|
||||||
|
- **USER**: Database user
|
||||||
|
- **PASSWORD**: Password (URL encoded if special chars)
|
||||||
|
- **HOST**: Hostname (localhost, IP, or domain)
|
||||||
|
- **PORT**: Port (default 5432)
|
||||||
|
- **DATABASE**: Database name
|
||||||
|
- **SCHEMA**: Schema name (default `public`)
|
||||||
|
|
||||||
|
## Driver Adapter
|
||||||
|
|
||||||
|
Use a driver adapter for the standard SQL workflow.
|
||||||
|
|
||||||
|
1. Install adapter and driver:
|
||||||
|
```bash
|
||||||
|
npm install @prisma/adapter-pg@7 pg
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Instantiate Prisma Client with the adapter:
|
||||||
|
```typescript
|
||||||
|
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 })
|
||||||
|
```
|
||||||
|
|
||||||
|
## Common Issues
|
||||||
|
|
||||||
|
### "Can't reach database server"
|
||||||
|
- Check host and port
|
||||||
|
- Check firewall settings
|
||||||
|
- Ensure database is running
|
||||||
|
|
||||||
|
### "Authentication failed"
|
||||||
|
- Check user/password
|
||||||
|
- Special characters in password must be URL-encoded
|
||||||
|
|
||||||
|
### "Schema does not exist"
|
||||||
|
- Ensure `?schema=public` (or your schema) is in the URL
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- [Prisma 7 PostgreSQL documentation](https://www.prisma.io/docs/orm/v7/core-concepts/supported-databases/postgresql)
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
# Prisma Postgres with Prisma ORM 7
|
||||||
|
|
||||||
|
Use this reference for an existing or explicitly selected **Prisma ORM 7** app. Obtain or reuse the database through [prisma-postgres-setup](../../prisma-postgres-setup/SKILL.md).
|
||||||
|
|
||||||
|
## Node.js connections
|
||||||
|
|
||||||
|
Use the PostgreSQL TCP connection supplied by Prisma Console or the integration and follow [PostgreSQL setup](v7-postgresql.md). Use a pooled or direct connection according to the intended operation. A `prisma+postgres://` Accelerate URL is not a TCP connection string for `PrismaPg`.
|
||||||
|
|
||||||
|
## Edge connections
|
||||||
|
|
||||||
|
For a runtime without PostgreSQL TCP support, Prisma Postgres provides an HTTP/WebSocket driver. With a Prisma 7 client:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npm install @prisma/adapter-ppg@7 @prisma/ppg
|
||||||
|
```
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { PrismaClient } from '../generated/client'
|
||||||
|
import { PrismaPostgresAdapter } from '@prisma/adapter-ppg'
|
||||||
|
|
||||||
|
const prisma = new PrismaClient({
|
||||||
|
adapter: new PrismaPostgresAdapter({
|
||||||
|
connectionString: process.env.DATABASE_URL!,
|
||||||
|
}),
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
The serverless driver takes a direct Prisma Postgres connection string as its credential and communicates over HTTP/WebSockets. It does not open a TCP connection. Load secrets through the host's supported mechanism and set the Prisma 7 generator's `runtime` to that deployment target.
|
||||||
|
|
||||||
|
These adapter examples do not configure Prisma 8. Its runtime guidance belongs to the installed `prisma-8` skill.
|
||||||
|
|
||||||
|
See the [Prisma Postgres serverless driver documentation](https://www.prisma.io/docs/postgres/database/serverless-driver) for connection selection and supported runtimes.
|
||||||
@@ -0,0 +1,114 @@
|
|||||||
|
# SQLite Setup
|
||||||
|
|
||||||
|
Configure **Prisma ORM 7** with SQLite. For an existing Prisma 6 app, keep its configuration and use the [Prisma 6 docs](https://www.prisma.io/docs/orm/v6); the configuration and adapter examples below are for 7.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- None (file-based)
|
||||||
|
|
||||||
|
## 1. Schema Configuration
|
||||||
|
|
||||||
|
In `prisma/schema.prisma`:
|
||||||
|
|
||||||
|
```prisma
|
||||||
|
datasource db {
|
||||||
|
provider = "sqlite"
|
||||||
|
}
|
||||||
|
|
||||||
|
generator client {
|
||||||
|
provider = "prisma-client"
|
||||||
|
output = "../generated"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 2. Config Configuration
|
||||||
|
|
||||||
|
In `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'),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## 3. Environment Variable
|
||||||
|
|
||||||
|
In `.env`:
|
||||||
|
|
||||||
|
```env
|
||||||
|
DATABASE_URL="file:./dev.db"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Connection String Format
|
||||||
|
|
||||||
|
```
|
||||||
|
file:PATH
|
||||||
|
```
|
||||||
|
|
||||||
|
- **PATH**: Relative path to the database file. Check `prisma.config.ts` if you need to confirm how your app resolves it.
|
||||||
|
|
||||||
|
## Driver Adapter
|
||||||
|
|
||||||
|
Use a driver adapter for the standard SQL workflow.
|
||||||
|
|
||||||
|
1. Install adapter and driver:
|
||||||
|
```bash
|
||||||
|
npm install @prisma/adapter-better-sqlite3@7 better-sqlite3
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Instantiate Prisma Client with the adapter:
|
||||||
|
```typescript
|
||||||
|
import 'dotenv/config'
|
||||||
|
import { PrismaClient } from '../generated/client'
|
||||||
|
import { PrismaBetterSqlite3 } from '@prisma/adapter-better-sqlite3'
|
||||||
|
|
||||||
|
const adapter = new PrismaBetterSqlite3({
|
||||||
|
url: process.env.DATABASE_URL!,
|
||||||
|
})
|
||||||
|
|
||||||
|
const prisma = new PrismaClient({ adapter })
|
||||||
|
```
|
||||||
|
|
||||||
|
## Using Driver Adapter (LibSQL / Turso)
|
||||||
|
|
||||||
|
For edge compatibility or Turso:
|
||||||
|
|
||||||
|
1. Install:
|
||||||
|
```bash
|
||||||
|
npm install @prisma/adapter-libsql@7 @libsql/client
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Instantiate:
|
||||||
|
```typescript
|
||||||
|
import 'dotenv/config'
|
||||||
|
import { PrismaClient } from '../generated/client'
|
||||||
|
import { PrismaLibSql } from '@prisma/adapter-libsql'
|
||||||
|
|
||||||
|
const adapter = new PrismaLibSql({
|
||||||
|
url: process.env.TURSO_DATABASE_URL,
|
||||||
|
authToken: process.env.TURSO_AUTH_TOKEN,
|
||||||
|
})
|
||||||
|
const prisma = new PrismaClient({ adapter })
|
||||||
|
```
|
||||||
|
|
||||||
|
## Limitations
|
||||||
|
|
||||||
|
- **Enums**: Prisma supports enum fields, but SQLite does not enforce enum values at the database level.
|
||||||
|
- **No Scalar Lists**: `String[]` is not supported directly.
|
||||||
|
- **Concurrency**: Write operations lock the file.
|
||||||
|
|
||||||
|
## Common Issues
|
||||||
|
|
||||||
|
### "Database file not found"
|
||||||
|
|
||||||
|
Check the resolved file path for both the CLI and the runtime adapter; relative paths can resolve differently. Use an explicit path to the intended file rather than silently creating a second database.
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- [Prisma 7 SQLite documentation](https://www.prisma.io/docs/orm/v7/core-concepts/supported-databases/sqlite)
|
||||||
@@ -0,0 +1,101 @@
|
|||||||
|
# SQL Server Setup
|
||||||
|
|
||||||
|
Configure **Prisma ORM 7** with SQL Server. For an existing Prisma 6 app, keep its configuration and use the [Prisma 6 docs](https://www.prisma.io/docs/orm/v6); the configuration and adapter examples below are for 7.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- SQL Server 2017, 2019, 2022, or Azure SQL
|
||||||
|
- TCP/IP enabled
|
||||||
|
|
||||||
|
## 1. Schema Configuration
|
||||||
|
|
||||||
|
In `prisma/schema.prisma`:
|
||||||
|
|
||||||
|
```prisma
|
||||||
|
datasource db {
|
||||||
|
provider = "sqlserver"
|
||||||
|
}
|
||||||
|
|
||||||
|
generator client {
|
||||||
|
provider = "prisma-client"
|
||||||
|
output = "../generated"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 2. Config Configuration
|
||||||
|
|
||||||
|
In `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'),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
## 3. Environment Variable
|
||||||
|
|
||||||
|
In `.env`:
|
||||||
|
|
||||||
|
```env
|
||||||
|
DATABASE_URL="sqlserver://localhost:1433;database=mydb;user=sa;password=Password123;encrypt=true;trustServerCertificate=true"
|
||||||
|
```
|
||||||
|
|
||||||
|
### Connection String Format
|
||||||
|
|
||||||
|
```
|
||||||
|
sqlserver://HOST:PORT;database=DB;user=USER;password=PASS;encrypt=true;trustServerCertificate=true
|
||||||
|
```
|
||||||
|
|
||||||
|
- **encrypt**: Required for Azure (true).
|
||||||
|
- **trustServerCertificate**: True for self-signed certs (local dev).
|
||||||
|
|
||||||
|
## Driver Adapter
|
||||||
|
|
||||||
|
Use a driver adapter for the standard SQL workflow.
|
||||||
|
|
||||||
|
1. Install adapter and driver:
|
||||||
|
```bash
|
||||||
|
npm install @prisma/adapter-mssql@7 mssql
|
||||||
|
```
|
||||||
|
|
||||||
|
2. Set `SQLSERVER_USER` and `SQLSERVER_PASSWORD` in the application environment to match the CLI URL, and use the same server, port, database, and TLS options. The following example is for local development with a self-signed certificate; use certificate verification for hosted databases. Instantiate Prisma Client with the adapter:
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import 'dotenv/config'
|
||||||
|
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 })
|
||||||
|
```
|
||||||
|
|
||||||
|
## Common Issues
|
||||||
|
|
||||||
|
### "Login failed for user"
|
||||||
|
- SQL Server auth vs Windows auth. Prisma typically uses SQL Server authentication (username/password).
|
||||||
|
- Ensure TCP/IP is enabled in SQL Server Configuration Manager.
|
||||||
|
|
||||||
|
### "Table not found" (dbo schema)
|
||||||
|
|
||||||
|
Check that the connection URL's `schema` parameter (normally `dbo`) matches the intended schema. Preserve an existing multi-schema configuration and model mappings.
|
||||||
|
|
||||||
|
## References
|
||||||
|
|
||||||
|
- [Prisma 7 SQL Server documentation](https://www.prisma.io/docs/orm/v7/core-concepts/supported-databases/sql-server)
|
||||||
@@ -0,0 +1,47 @@
|
|||||||
|
---
|
||||||
|
name: prisma-postgres-setup
|
||||||
|
description: Obtain or reuse a Prisma Postgres database and connect an application. Use when the user needs a database and has none configured ("I need a database", "add a Postgres database", "set up a database for this app"), runs or mentions `create-db` or `npx create-db`, or asks to set up or connect Prisma Postgres, including in v0 and the Vercel Marketplace. Hands Prisma ORM configuration to prisma-orm-setup; reuses an existing connection first and honors an explicit provider, driver, alternative ORM, or database-only choice.
|
||||||
|
license: MIT
|
||||||
|
metadata:
|
||||||
|
author: prisma
|
||||||
|
version: "2.2.0"
|
||||||
|
---
|
||||||
|
|
||||||
|
# Prisma Postgres setup
|
||||||
|
|
||||||
|
Connect the intended database, then verify it from the application. Keep provisioning separate from ORM configuration so an existing database is reused.
|
||||||
|
|
||||||
|
## 1. Inspect the project
|
||||||
|
|
||||||
|
Check the user's requested ORM or driver, installed packages, database connection, and environment-loading files. Check secret presence without printing values.
|
||||||
|
|
||||||
|
- Honor explicit choices such as Drizzle, `pg`, or database-only setup.
|
||||||
|
- For query or schema work in an already configured app, use its version-matched ORM guidance; do not restart setup.
|
||||||
|
|
||||||
|
## 2. Reuse or obtain a database
|
||||||
|
|
||||||
|
| Situation | Action |
|
||||||
|
| -------------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
|
||||||
|
| Existing connection or connected integration | Verify its project, database, and environment; reuse it. |
|
||||||
|
| v0, Vercel Marketplace, or a Vercel project | Read [Marketplace setup](references/vercel-marketplace.md) and use the native integration flow. |
|
||||||
|
| No database yet and no provider named | Offer `npx create-db@latest` for a working database now with no account (it is deleted after 24 hours unless claimed, and claiming needs a free Prisma account; read the create-db section in [provisioning](references/provisioning.md)), or a persistent database through [provisioning](references/provisioning.md). Ask which one when the request does not say. |
|
||||||
|
| Standalone persistent database | Read [provisioning](references/provisioning.md); use an authenticated CLI, MCP tool, Console, or Management API. |
|
||||||
|
| Temporary development database requested | Read the `create-db` section in [provisioning](references/provisioning.md), including expiry and claiming. |
|
||||||
|
|
||||||
|
Resolve the workspace, project, and region before creation. If several resources fit, ask which one to use. If provisioning is blocked by permissions or quota, report the blocker; do not delete another resource or switch workspaces to get around it.
|
||||||
|
|
||||||
|
## 3. Connect the application
|
||||||
|
|
||||||
|
Use the connection appropriate to the chosen driver and runtime. Store it in the project's secret environment configuration, never source code or chat. Preserve unrelated entries, update the intended variable once, and ensure local secret files are ignored by Git.
|
||||||
|
|
||||||
|
Application processes and CLI commands may load different environment files. For example, a framework may load `.env.development.local` while a shell command does not. A variable missing from the shell does not mean the database is missing: load the intended file for that command without displaying credentials, and do not provision another database.
|
||||||
|
|
||||||
|
## 4. Configure the ORM and verify
|
||||||
|
|
||||||
|
For Prisma ORM setup, read [prisma-orm-setup/SKILL.md](https://github.com/prisma/skills/blob/main/prisma-orm-setup/SKILL.md) directly, or load the installed `prisma-orm-setup` skill when the host resolves sibling skills by name. It owns ORM version selection and configuration. If that handoff is unavailable, report it.
|
||||||
|
|
||||||
|
For an explicitly selected alternative, keep that ORM or driver and use its documented setup. For database-only setup, stop after verifying connectivity.
|
||||||
|
|
||||||
|
Run a read-only query against the intended database through the application's chosen ORM or driver. Report what was connected, the selected ORM/version, and the query result without secrets. If any step is blocked or untested, say so instead of claiming setup is complete.
|
||||||
|
|
||||||
|
For Studio, SDK integrations, or database operations beyond initial setup, read [operations](references/operations.md).
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
# Console and programmatic operations
|
||||||
|
|
||||||
|
Read this only for work beyond connecting one application.
|
||||||
|
|
||||||
|
## Console and database operations
|
||||||
|
|
||||||
|
Use [Prisma Console](https://console.prisma.io) to inspect the selected project and open its database in Studio. Use links returned by the API or UI rather than constructing Console URLs from guessed ID formats.
|
||||||
|
|
||||||
|
For usage, backups, connections, or restoration, inspect current Platform CLI help or the [Management API schema](https://api.prisma.io/v1/doc). Resolve resource IDs before acting. Database deletion, restoration, and credential revocation are separate actions requiring the user's authorization; they are not routine setup steps.
|
||||||
|
|
||||||
|
## Management API SDK
|
||||||
|
|
||||||
|
Use `@prisma/management-api-sdk` for a typed API integration. Its installed types define current routes and request/response shapes independently of ORM versions.
|
||||||
|
|
||||||
|
- `createManagementApiClient({ token })` uses an existing token. Check HTTP errors before reading response data and follow pagination on collection routes.
|
||||||
|
- `createManagementApiSdk(...)` supports OAuth and token refresh. Implement persistent, protected token storage; do not copy a no-op storage example into an application.
|
||||||
|
- In the OAuth flow, persist and validate state and the verifier, handle the callback, and store refreshed tokens securely.
|
||||||
|
- Service-token and connection creation can return credentials once. Save them to the intended secret store without logging the response. Listing token metadata does not recover the original value.
|
||||||
|
|
||||||
|
For exact interfaces and a complete integration, use the [SDK documentation](https://www.prisma.io/docs/postgres/introduction/management-api-sdk) and installed package types. Keep ORM schema and migration work in the version-matched ORM skill.
|
||||||
@@ -0,0 +1,43 @@
|
|||||||
|
# Standalone provisioning
|
||||||
|
|
||||||
|
First reuse an existing connection or resource. For v0 or Vercel Marketplace, use the [native integration flow](vercel-marketplace.md) instead.
|
||||||
|
|
||||||
|
## Persistent databases
|
||||||
|
|
||||||
|
Choose an available authenticated surface: Prisma Console, the Prisma Platform CLI, a connected Prisma MCP server, or the Management API. Reuse existing authentication; do not ask the user to paste tokens into chat.
|
||||||
|
|
||||||
|
- **Console:** select the intended workspace and project at [Prisma Console](https://console.prisma.io), then obtain the database's connection details.
|
||||||
|
- **Platform CLI:** inspect the current command help before mutation. The Platform commands ship in the Prisma 8 CLI (`prisma` 8, also published as `@prisma/cli`); the `postgres` group of a Prisma 7 `prisma` binary only links an existing database. Start with `npx -y @prisma/cli@latest postgres --help`; discover list, create, and connection commands from that version.
|
||||||
|
- **MCP:** discover available tools and their input schemas. Confirm the workspace and resource context before invoking a provisioning tool. Missing tools or authentication are blockers, not permission to switch accounts.
|
||||||
|
- **Management API:** use the [current schema](https://api.prisma.io/v1/doc) at `https://api.prisma.io/v1`, or installed SDK types, for exact endpoints and payloads. Do not copy an older project/database response shape blindly.
|
||||||
|
|
||||||
|
List available regions and select one consistent with the user's location requirements and application. Resolve the intended workspace, project, and, where required, branch before creating a database. Follow pagination when listing resources. If creation is asynchronous, poll the returned resource until ready with a bounded wait; report a timeout without creating a replacement. Before retrying an ambiguous creation request, check whether it succeeded to avoid duplicates.
|
||||||
|
|
||||||
|
Store returned connection credentials immediately in the intended secret environment. Some credentials are shown only once. Select the direct or pooled endpoint appropriate to the chosen driver and runtime; inspect the returned connection details instead of assuming every endpoint is interchangeable.
|
||||||
|
|
||||||
|
## Authentication and errors
|
||||||
|
|
||||||
|
For server-to-server API access, use a workspace service token from the user's secret environment. If one is needed, direct the user to Workspace Settings → Service Tokens in Console and have them store it locally or in their secret manager. Use the bearer token without logging it. For an integration acting on behalf of users, use OAuth instead; see [operations](operations.md).
|
||||||
|
|
||||||
|
| Failure | Response |
|
||||||
|
| ------------------------------------ | ---------------------------------------------------------------------------------------- |
|
||||||
|
| Authentication or permission denied | Explain which authentication or access is missing. |
|
||||||
|
| Resource not found | Verify the resource ID and workspace; do not create a replacement automatically. |
|
||||||
|
| Invalid request | Check the current schema and selected region. |
|
||||||
|
| Rate limit or transient read failure | Retry with bounded backoff, honoring retry guidance. |
|
||||||
|
| Quota exhausted | Report the limit and available options. |
|
||||||
|
|
||||||
|
## Temporary databases with create-db
|
||||||
|
|
||||||
|
Use `create-db` when the user needs a working database now and has no connection or Prisma account. By default, the database is available for **24 hours** and is automatically deleted if unclaimed. Claim it through the returned claim URL **before its expiry** to keep it; claiming requires a Prisma account. Use the returned expiry as the deadline if a different lifetime was selected. See the [documented lifecycle](https://www.prisma.io/docs/postgres/npx-create-db#claiming-your-database).
|
||||||
|
|
||||||
|
Inspect the current commands when selecting a region or a non-default lifetime:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx create-db@latest create --help
|
||||||
|
npx create-db@latest regions --help
|
||||||
|
```
|
||||||
|
|
||||||
|
Choose a supported region and lifetime. Store the connection string and claim URL privately, then tell the user when the database expires and how to claim it using the returned lifecycle information. Do not promise persistence until claiming is complete. Avoid flags that print credentials into shared output.
|
||||||
|
|
||||||
|
For programmatic provisioning, the `create-db` package exposes `create()` and `regions()`. Check the installed types, handle success and error results, and store returned connection/claim information without logging it. See the [create-db documentation](https://www.prisma.io/docs/postgres/npx-create-db).
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
# v0, Vercel CLI and Vercel Marketplace
|
||||||
|
|
||||||
|
Use the Prisma Postgres native integration so the database belongs to the user's Vercel team, is billed through Vercel, and is connected to the Vercel project. Unless the user asks for a database outside Vercel, do not substitute Prisma Console, the Prisma CLI, `create-db` or a Prisma MCP server: they create a database that Vercel does not bill, connect or rotate.
|
||||||
|
|
||||||
|
The integration slug is `prisma` and the product is `prisma/prisma-postgres`.
|
||||||
|
|
||||||
|
## 1. Reuse an existing resource
|
||||||
|
|
||||||
|
1. In the linked project, run `vercel integration list`. If a Prisma Postgres resource is connected, reuse it and go to step 3.
|
||||||
|
2. Run `vercel integration list --all` to see the team's resources that are not connected to this project. Connect one with `vercel integration resource connect <resource-name>`.
|
||||||
|
3. If several resources fit, ask the user which one to use.
|
||||||
|
|
||||||
|
## 2. Install and provision with the Vercel CLI
|
||||||
|
|
||||||
|
The project must be linked (`vercel link`). Read the current options before provisioning; do not guess metadata or plan IDs:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
vercel integration add prisma --help
|
||||||
|
vercel integration add prisma/prisma-postgres --name <resource-name>
|
||||||
|
```
|
||||||
|
|
||||||
|
- In a non-interactive shell, pass the `region` metadata (`-m region=<value>`, values from `--help`) and `--plan`. The plan IDs are `free`, `starter`, `pro` and `business`. Use `free` unless the user chose a paid plan: a paid plan bills the user's Vercel account, so ask first.
|
||||||
|
- If Prisma is not yet installed on the team, the CLI asks the user to accept the integration's terms in the browser and waits. An agent cannot complete this step. Ask the user to accept, then let the command continue.
|
||||||
|
- By default the command connects the resource to the linked project's `production`, `preview` and `development` environments, then runs `vercel env pull`, which writes `.env.local`.
|
||||||
|
- One resource on all three environments means local development, previews and production share one database. Tell the user. If they want separate data, provision one resource per environment with `-e <environment>`, and connect only one Prisma resource to each environment.
|
||||||
|
|
||||||
|
In v0, use the host's native integration flow instead. It may appear as an integration request tool; discover what the host exposes instead of assuming a fixed tool name, then wait for the connection and its environment variables.
|
||||||
|
|
||||||
|
## 3. Environment variables
|
||||||
|
|
||||||
|
Connecting a resource sets these variables on each connected environment:
|
||||||
|
|
||||||
|
| Variable | Value | Use |
|
||||||
|
| --------------------- | ------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------ |
|
||||||
|
| `DATABASE_URL` | `postgres://<user>:<key>@db.prisma.io:5432/postgres?sslmode=require` | The application and Prisma CLI commands |
|
||||||
|
| `POSTGRES_URL` | The same value as `DATABASE_URL` | Libraries that read `POSTGRES_URL` |
|
||||||
|
| `PRISMA_DATABASE_URL` | The same value on resources created now. On older resources it can be a `prisma+postgres://accelerate.prisma-data.net/...` URL | Do not use in new code; use `DATABASE_URL` |
|
||||||
|
|
||||||
|
- With `--prefix`, each name gets the prefix as-is (`--prefix DB2_` gives `DB2_DATABASE_URL`). Read the prefixed name.
|
||||||
|
- Never print the values. `vercel env ls <environment>` lists names without values.
|
||||||
|
- `db.prisma.io` is the direct endpoint. It works for the application, migrations and Prisma Studio, so setup needs nothing else. Direct connections are capped low: 10 on Free and Starter, 5 of them reserved for the platform. Before production load from Vercel Functions, tell the user that application traffic should use the pooled endpoint (`pooled.db.prisma.io`), whose connection string Prisma Console shows for the database; `vercel integration open prisma` signs the user in. Do not overwrite the integration's variables: add the pooled string under a new name with `vercel env add`, keep `DATABASE_URL` for migrations, and switch the runtime client only if the user agrees.
|
||||||
|
|
||||||
|
## 4. First successful request
|
||||||
|
|
||||||
|
1. Make the variables available locally: `vercel env pull`, or run each command with `vercel env run -- <command>` to keep secrets off disk.
|
||||||
|
2. Return to `prisma-postgres-setup` step 4 to configure the chosen ORM or driver. Prisma ORM configuration belongs to `prisma-orm-setup`.
|
||||||
|
3. Run one read-only query (for example `SELECT 1`) through the application's ORM or driver against the connected database.
|
||||||
|
4. Deploy. Environment variable changes apply only to new deployments, so redeploy after connecting a resource, then call a route that queries the database.
|
||||||
|
|
||||||
|
## 5. Validate and report
|
||||||
|
|
||||||
|
- `vercel integration list` shows the resource, its status and the connected project.
|
||||||
|
- `vercel env ls production` lists `DATABASE_URL`.
|
||||||
|
- The local query and the deployed query both succeed.
|
||||||
|
|
||||||
|
Report the resource name, the environments it is connected to, the variable the application reads, and the query result, without secrets. If a step was blocked or not tested, say so.
|
||||||
|
|
||||||
|
## Plans, billing and backups
|
||||||
|
|
||||||
|
- Usage and invoices are on the user's Vercel bill. Changing the plan is the user's decision; do not do it on your own.
|
||||||
|
- The user can change plans in Prisma Console (`vercel integration open prisma`) or in the Vercel dashboard: **Integrations → Prisma → Manage → Settings → Change Plan**.
|
||||||
|
- Restorable daily backups come with paid plans. On Free, treat the connected database as having no backup.
|
||||||
|
|
||||||
|
## Common errors
|
||||||
|
|
||||||
|
| What you see | Cause | Fix |
|
||||||
|
| ---------------------------------------------------------------------------------------- | --------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||||
|
| The CLI asks the user to review and accept terms in the browser | Prisma is not installed on the team yet | Ask the user to accept. The agent cannot do it. |
|
||||||
|
| Connecting fails with an error that names an existing variable, project and environments | The project already has a variable such as `DATABASE_URL` | Ask the user. Remove the stale variable with `vercel env rm <name> <environment>`, or connect with `--prefix` and read the prefixed name. |
|
||||||
|
| A Prisma CLI command reports `DATABASE_URL` missing, but the app runs | The command does not load `.env.local` | Run it as `vercel env run -- <command>`, or load the intended file for that command. Do not provision another database. |
|
||||||
|
| `PRISMA_DATABASE_URL` starts with `prisma+postgres://accelerate.prisma-data.net` | An older resource still carries an Accelerate URL in that variable | Read `DATABASE_URL`, which holds a standard `postgres://` string. |
|
||||||
|
| Works locally; the deployment has no `DATABASE_URL` or old credentials | The deployment predates the connection or a secret rotation | Check `vercel env ls <environment>` and that the resource is connected to that environment, then redeploy. |
|
||||||
|
| "Too many connections" or connection-limit errors under load | Application traffic on the direct endpoint, or a client created per request | Create the database client once, outside the request handler. Move application traffic to the pooled endpoint (section 3). |
|
||||||
|
| Data is gone after a schema diff or reset | A shadow database or reset command ran against the connected database | Never point a shadow database URL or a reset command at the connected database; use a separate throwaway database. Restoring needs a paid plan's backup. |
|
||||||
|
|
||||||
|
## Where MCP fits
|
||||||
|
|
||||||
|
When native Marketplace MCP tools are available, inspect their descriptions, permissions, and resource scope before use. Use them for supported operations on the selected resource. Keep schema changes consistent with the application's migration workflow.
|
||||||
|
|
||||||
|
A general Prisma MCP provisioning tool creates a Prisma resource; that alone does not establish Marketplace registration, billing, project connection, or environment injection. Do not substitute it for a blocked native installation. Report the missing connection or permission.
|
||||||
|
|
||||||
|
The agent calls MCP tools while building the app. The generated app connects through its ORM or database driver; it does not need to call MCP for normal database queries.
|
||||||
|
|
||||||
|
Sources: [vercel integration](https://vercel.com/docs/cli/integration), [vercel env](https://vercel.com/docs/cli/env), [coding agents and Marketplace integrations](https://vercel.com/kb/guide/using-coding-agents-to-procure-vercel-marketplace-integrations), [Prisma Postgres on Vercel](https://www.prisma.io/docs/guides/postgres/vercel), [connection pooling](https://www.prisma.io/docs/postgres/database/connection-pooling), [v0 databases](https://v0.app/docs/databases), [v0 MCP](https://v0.app/docs/MCP), [Vercel native integrations](https://vercel.com/docs/integrations/create-integration/native-integration).
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
---
|
||||||
|
name: prisma-postgres
|
||||||
|
description: Deprecated compatibility name for prisma-postgres-setup. Use only when a user or existing integration explicitly invokes prisma-postgres; otherwise select prisma-postgres-setup.
|
||||||
|
license: MIT
|
||||||
|
metadata:
|
||||||
|
author: prisma
|
||||||
|
version: "8.0.0"
|
||||||
|
---
|
||||||
|
|
||||||
|
# Deprecated: prisma-postgres
|
||||||
|
|
||||||
|
Load `prisma-postgres-setup` with the host's skill loader or read its installed `SKILL.md`. If unavailable, install it from [prisma/skills](https://github.com/prisma/skills/tree/main/prisma-postgres-setup) before continuing.
|
||||||
|
|
||||||
|
This compatibility entry contains no setup recipes. Keep it until consumers have migrated to the replacement.
|
||||||
@@ -0,0 +1,259 @@
|
|||||||
|
---
|
||||||
|
name: prisma-upgrade-v7
|
||||||
|
description: Complete migration guide from Prisma ORM v6 to v7 covering all breaking changes. Use when upgrading Prisma versions, encountering v7 errors, or migrating existing projects. Triggers on "upgrade to prisma 7", "prisma 7 migration", "prisma-client generator", "driver adapter required".
|
||||||
|
license: MIT
|
||||||
|
metadata:
|
||||||
|
author: prisma
|
||||||
|
version: "7.6.0"
|
||||||
|
---
|
||||||
|
|
||||||
|
# Upgrade to Prisma ORM 7
|
||||||
|
|
||||||
|
Complete guide for migrating from Prisma ORM v6 to v7. This upgrade introduces significant breaking changes around the new `prisma-client` generator, driver adapters, `prisma.config.ts`, explicit environment loading, and generated client entrypoints.
|
||||||
|
|
||||||
|
## When to Apply
|
||||||
|
|
||||||
|
Reference this skill when:
|
||||||
|
- Upgrading from Prisma v6 to v7
|
||||||
|
- Updating to the `prisma-client` generator
|
||||||
|
- Setting up driver adapters
|
||||||
|
- Configuring `prisma.config.ts`
|
||||||
|
- Fixing import errors after upgrade
|
||||||
|
|
||||||
|
## Rule Categories by Priority
|
||||||
|
|
||||||
|
| Priority | Category | Impact | Prefix |
|
||||||
|
|----------|----------|--------|--------|
|
||||||
|
| 1 | Schema Migration | CRITICAL | `schema-changes` |
|
||||||
|
| 2 | Database Connectivity | CRITICAL | `driver-adapters` |
|
||||||
|
| 3 | Module System | CRITICAL | `esm-support` |
|
||||||
|
| 4 | Config and Env | HIGH | `prisma-config`, `env-variables` |
|
||||||
|
| 5 | Removed Features | HIGH | `removed-features` |
|
||||||
|
| 6 | Accelerate | HIGH | `accelerate-users` |
|
||||||
|
|
||||||
|
## Quick Reference
|
||||||
|
|
||||||
|
- `schema-changes` - generator migration, required output paths, generated entrypoints, and `Prisma.validator` replacement
|
||||||
|
- `driver-adapters` - required adapter installation for SQL providers, pool differences, and Prisma Postgres adapter choices
|
||||||
|
- `esm-support` - ESM-first setup plus CommonJS fallback with `moduleFormat = "cjs"`
|
||||||
|
- `prisma-config` - creating and using `prisma.config.ts`
|
||||||
|
- `env-variables` - explicit environment loading
|
||||||
|
- `removed-features` - removed middleware, metrics, and legacy CLI behavior
|
||||||
|
- `accelerate-users` - migration notes for Accelerate users
|
||||||
|
|
||||||
|
## Using MongoDB? This guide does not apply
|
||||||
|
|
||||||
|
Prisma 7 has no MongoDB connector. Do not apply any step in this guide to a project with
|
||||||
|
`provider = "mongodb"` — see the `prisma-mongodb-upgrade` skill for the actual decision
|
||||||
|
(stay on v6 deliberately vs migrate to Prisma 8).
|
||||||
|
|
||||||
|
## Important Notes
|
||||||
|
|
||||||
|
- **MongoDB projects should stay on Prisma 6.x or migrate to Prisma 8** - do not migrate MongoDB apps to Prisma 7's SQL client path (see `prisma-mongodb-upgrade`)
|
||||||
|
- **Node.js 20.19.0+** required
|
||||||
|
- **TypeScript 5.4.0+** required
|
||||||
|
- **Latest stable Prisma ORM version**: `7.6.0`
|
||||||
|
|
||||||
|
## Upgrade Steps Overview
|
||||||
|
|
||||||
|
1. Update packages to v7
|
||||||
|
2. Choose your module format (`esm` by default, `cjs` if needed)
|
||||||
|
3. Update TypeScript configuration
|
||||||
|
4. Update the schema generator block
|
||||||
|
5. Create `prisma.config.ts`
|
||||||
|
6. Install and configure a driver adapter for SQL providers
|
||||||
|
7. Update Prisma Client imports
|
||||||
|
8. Update client instantiation
|
||||||
|
9. Replace deprecated helper patterns like `Prisma.validator`
|
||||||
|
10. Run `prisma generate` and test
|
||||||
|
|
||||||
|
## Quick Upgrade Commands
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# Update packages
|
||||||
|
npm install @prisma/client@7
|
||||||
|
npm install -D prisma@7
|
||||||
|
|
||||||
|
# Install a driver adapter (PostgreSQL or Prisma Postgres via direct TCP)
|
||||||
|
npm install @prisma/adapter-pg pg
|
||||||
|
|
||||||
|
# Install dotenv for env loading
|
||||||
|
npm install dotenv
|
||||||
|
|
||||||
|
# Regenerate client
|
||||||
|
npx prisma generate
|
||||||
|
```
|
||||||
|
|
||||||
|
## Breaking Changes Summary
|
||||||
|
|
||||||
|
| Change | v6 | v7 |
|
||||||
|
|--------|----|----|
|
||||||
|
| Module format | Implicit / mixed | ESM-first, `moduleFormat = "cjs"` supported |
|
||||||
|
| Generator provider | `prisma-client-js` | `prisma-client` is the default, while `prisma-client-js` still exists for legacy setups |
|
||||||
|
| Output path | Auto (node_modules) | Required explicit |
|
||||||
|
| Driver adapters | Optional | Required for SQL providers |
|
||||||
|
| Config file | `.env` + schema | `prisma.config.ts` |
|
||||||
|
| Env loading | Automatic | Manual (dotenv) |
|
||||||
|
| Generated entrypoints | Single package export | `client`, `browser`, `models`, `enums` entrypoints |
|
||||||
|
| Type-safe query fragments | `Prisma.validator()` | TypeScript `satisfies` |
|
||||||
|
| Middleware | `$use()` | Client Extensions |
|
||||||
|
| Metrics | Preview feature | Removed |
|
||||||
|
|
||||||
|
## Rule Files
|
||||||
|
|
||||||
|
Detailed migration guides for each breaking change:
|
||||||
|
|
||||||
|
```
|
||||||
|
references/esm-support.md - ESM and CommonJS configuration
|
||||||
|
references/schema-changes.md - Generator, output, imports, and generated entrypoints
|
||||||
|
references/driver-adapters.md - Required driver adapter setup
|
||||||
|
references/prisma-config.md - New configuration file
|
||||||
|
references/env-variables.md - Environment variable loading
|
||||||
|
references/removed-features.md - Middleware, metrics, and CLI flags
|
||||||
|
references/accelerate-users.md - Special handling for Accelerate
|
||||||
|
```
|
||||||
|
|
||||||
|
## Step-by-Step Migration
|
||||||
|
|
||||||
|
### 1. Update package.json for ESM-first projects
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"type": "module"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
If you need to stay on CommonJS, keep your app as CJS and set `moduleFormat = "cjs"` in the generator block instead of forcing ESM.
|
||||||
|
|
||||||
|
### 2. Update tsconfig.json
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"module": "ESNext",
|
||||||
|
"moduleResolution": "bundler",
|
||||||
|
"target": "ES2023",
|
||||||
|
"strict": true,
|
||||||
|
"esModuleInterop": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Update schema.prisma
|
||||||
|
|
||||||
|
```prisma
|
||||||
|
// Before (v6)
|
||||||
|
generator client {
|
||||||
|
provider = "prisma-client-js"
|
||||||
|
}
|
||||||
|
|
||||||
|
// After (v7)
|
||||||
|
generator client {
|
||||||
|
provider = "prisma-client"
|
||||||
|
output = "../generated/prisma"
|
||||||
|
// Optional if you need CommonJS:
|
||||||
|
// moduleFormat = "cjs"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### 4. Create prisma.config.ts
|
||||||
|
|
||||||
|
```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'),
|
||||||
|
},
|
||||||
|
})
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. Install a driver adapter (SQL providers only)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# PostgreSQL
|
||||||
|
npm install @prisma/adapter-pg pg
|
||||||
|
|
||||||
|
# MySQL
|
||||||
|
npm install @prisma/adapter-mariadb mariadb
|
||||||
|
|
||||||
|
# SQLite
|
||||||
|
npm install @prisma/adapter-better-sqlite3 better-sqlite3
|
||||||
|
|
||||||
|
# Prisma Postgres in standard Node.js apps (recommended)
|
||||||
|
npm install @prisma/adapter-pg pg
|
||||||
|
|
||||||
|
# Prisma Postgres serverless driver (edge/serverless)
|
||||||
|
npm install @prisma/adapter-ppg @prisma/ppg
|
||||||
|
|
||||||
|
# Neon
|
||||||
|
npm install @prisma/adapter-neon
|
||||||
|
```
|
||||||
|
|
||||||
|
MongoDB does not have a SQL `@prisma/adapter-*` package in the published Prisma 7.6.0 packages. If you're upgrading a MongoDB project, stop and keep that project on the latest Prisma 6.x release instead of following the standard Prisma 7 migration path.
|
||||||
|
|
||||||
|
### 6. Update client instantiation
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
// Before (v6)
|
||||||
|
import { PrismaClient } from '@prisma/client'
|
||||||
|
const prisma = new PrismaClient()
|
||||||
|
|
||||||
|
// After (v7)
|
||||||
|
import { PrismaClient } from '../generated/prisma/client'
|
||||||
|
import { PrismaPg } from '@prisma/adapter-pg'
|
||||||
|
|
||||||
|
const adapter = new PrismaPg({
|
||||||
|
connectionString: process.env.DATABASE_URL
|
||||||
|
})
|
||||||
|
|
||||||
|
const prisma = new PrismaClient({ adapter })
|
||||||
|
```
|
||||||
|
|
||||||
|
### 7. Replace Prisma.validator with satisfies
|
||||||
|
|
||||||
|
```typescript
|
||||||
|
import { Prisma } from '../generated/prisma/client'
|
||||||
|
|
||||||
|
const userSelect = {
|
||||||
|
id: true,
|
||||||
|
email: true,
|
||||||
|
name: true,
|
||||||
|
} satisfies Prisma.UserSelect
|
||||||
|
```
|
||||||
|
|
||||||
|
### 8. Run migrations and generate
|
||||||
|
|
||||||
|
```bash
|
||||||
|
npx prisma generate
|
||||||
|
npx prisma migrate dev # if needed
|
||||||
|
```
|
||||||
|
|
||||||
|
## Troubleshooting
|
||||||
|
|
||||||
|
### "Cannot find module" errors
|
||||||
|
- Check that the generator `output` path matches your import path
|
||||||
|
- Ensure `prisma generate` ran successfully
|
||||||
|
|
||||||
|
### SSL certificate errors
|
||||||
|
- Add `ssl: { rejectUnauthorized: false }` to the adapter config if you need to preserve old behavior
|
||||||
|
- Or configure your certificates properly with `NODE_EXTRA_CA_CERTS` / OpenSSL CA settings
|
||||||
|
|
||||||
|
### Connection timeout issues
|
||||||
|
- Driver adapters use the underlying driver's defaults, which differ from v6
|
||||||
|
- Configure pool settings explicitly on the adapter if needed
|
||||||
|
|
||||||
|
## Resources
|
||||||
|
|
||||||
|
- [Official v7 Upgrade Guide](https://www.prisma.io/docs/orm/more/upgrades/to-v7)
|
||||||
|
- [Driver Adapters Documentation](https://www.prisma.io/docs/orm/core-concepts/supported-databases/database-drivers)
|
||||||
|
- [Prisma Config Reference](https://www.prisma.io/docs/orm/reference/prisma-config-reference)
|
||||||
|
|
||||||
|
## How to Use
|
||||||
|
|
||||||
|
Follow `references/schema-changes.md` and `references/driver-adapters.md` first, then apply the remaining reference files based on your project setup.
|
||||||
@@ -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
|
||||||
|
|
||||||
|
These examples apply to **Prisma ORM 7 SQL clients** during a 6-to-7 upgrade. They do not configure Prisma 8; use the installed package-owned `prisma-8` runtime guidance for that version.
|
||||||
|
|
||||||
|
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"]
|
||||||
|
}
|
||||||
|
```
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
../../.agents/skills/prisma-cli
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
../../.agents/skills/prisma-client-api
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
../../.agents/skills/prisma-compute
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
../../.agents/skills/prisma-database-setup
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
../../.agents/skills/prisma-driver-adapter-implementation
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
../../.agents/skills/prisma-mongodb-upgrade
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
../../.agents/skills/prisma-orm-setup
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
../../.agents/skills/prisma-postgres
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
../../.agents/skills/prisma-postgres-setup
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
../../.agents/skills/prisma-upgrade-v7
|
||||||
@@ -1,3 +1,38 @@
|
|||||||
NODE_ENV=development
|
NODE_ENV=development
|
||||||
HOST=127.0.0.1
|
HOST=127.0.0.1
|
||||||
PORT=3000
|
PORT=8800
|
||||||
|
LOG_LEVEL=info
|
||||||
|
API_BODY_LIMIT_BYTES=1048576
|
||||||
|
# 开发默认开启,生产默认关闭;可显式设置 true/false。
|
||||||
|
SWAGGER_ENABLED=true
|
||||||
|
# 只允许明确配置的 Web origin;小程序请求无需 CORS origin。
|
||||||
|
CORS_ORIGINS=
|
||||||
|
# 仅在部署明确确认 Nginx 来源时设置 IP/CIDR,默认不信任转发头。
|
||||||
|
TRUSTED_PROXY_CIDRS=
|
||||||
|
# 必填;至少 32 字节,开发/测试/生产分别生成,不使用共享默认值。
|
||||||
|
JWT_SECRET=
|
||||||
|
JWT_ISSUER=doodle-store
|
||||||
|
JWT_AUDIENCE=doodle-mini
|
||||||
|
JWT_EXPIRES_IN_SECONDS=86400
|
||||||
|
# 微信静默登录已接入,两项均必填;小程序 AppID 与对应 AppSecret。
|
||||||
|
# 仅服务端持有 AppSecret,不提交实际密钥,也不使用 JWT_SECRET 代替。
|
||||||
|
WECHAT_MINI_APP_ID=
|
||||||
|
WECHAT_MINI_APP_SECRET=
|
||||||
|
# Prisma 必填;用户名/密码/端口须与根 .env 一致,密码需 URL 编码。
|
||||||
|
# 仅连接 public schema;不要提交实际连接凭证。
|
||||||
|
DATABASE_URL=postgresql://doodle_dev:change-me-local-only@127.0.0.1:5434/doodle_dev?schema=public
|
||||||
|
# 新品按真实首次发布时间计算;旧数据发布时间未知时不标新品。
|
||||||
|
WORKSHEET_NEW_WINDOW_DAYS=30
|
||||||
|
# 可选公共资源 HTTPS 域名(不含路径);只解析 ready/public 资产,不授予上传权限。
|
||||||
|
QINIU_PUBLIC_DOMAIN=https://cdn.joeyone.cn
|
||||||
|
# 与 asset-sync 一致;前缀只拼接到备份相对路径,objectKey 本身已经包含前缀。
|
||||||
|
QINIU_KEY_PREFIX=doodle-assets/
|
||||||
|
# 对象所属空间,不是 URL 中的路径,也不需要在 server 配置 AK/SK。
|
||||||
|
QINIU_BUCKET=doodle-cn
|
||||||
|
|
||||||
|
# 仅服务端接收用户/管理员上传时使用,不能下发小程序。
|
||||||
|
QINIU_AK=
|
||||||
|
QINIU_SK=
|
||||||
|
QINIU_REGION=
|
||||||
|
# 首页每日刷新 UTC 小时(默认北京时间 06:00),可由管理员暂停。
|
||||||
|
SITE_REFRESH_HOUR_UTC=22
|
||||||
|
|||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
../../.agents/skills/prisma-cli
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
../../.agents/skills/prisma-client-api
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
../../.agents/skills/prisma-compute
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
../../.agents/skills/prisma-database-setup
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
../../.agents/skills/prisma-driver-adapter-implementation
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
../../.agents/skills/prisma-mongodb-upgrade
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
../../.agents/skills/prisma-orm-setup
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
../../.agents/skills/prisma-postgres
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
../../.agents/skills/prisma-postgres-setup
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
../../.agents/skills/prisma-upgrade-v7
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user