Prisma API 概览:探索 Prisma 服务自动生成的 GraphQL CRUD API Prisma API 概览探索 Prisma 服务自动生成的 GraphQL CRUD API【免费下载链接】prisma1 Database Tools incl. ORM, Migrations and Admin UI (Postgres, MySQL MongoDB) [deprecated]项目地址: https://gitcode.com/gh_mirrors/pr/prisma1导读本指南讲解 Prisma 1.x 中Prisma API的核心概念与使用方法。Prisma API 是基于已部署的 数据模型 自动生成的 GraphQL API为数据模型中的每个类型提供 CRUD 操作并支持数据库事件的实时订阅。阅读完本文你将掌握 Prisma API 的组成查询、变更、订阅、如何用 GraphQL Playground 与服务端点交互、API 的认证机制API secret / JWT token以及常见错误的排查思路。提示本文基于仓库中 docs/1.12/04-Reference/03-Prisma-API 的 Overview 章节展开并结合同目录的 Concepts、Queries、Mutations、Subscriptions 章节以及仓库源码中的实现细节进行深化。什么是 Prisma API一个 Prisma 服务会暴露一个GraphQL API该 API 是基于服务已部署的数据模型data model自动生成的通常被称为Prisma API。Prisma API 为数据模型中的每个类型自动生成 CRUD 操作主要分为三类能力Queries查询查询某个模型的单个或多个节点、跨关系查询数据、跨关系聚合数据Mutations变更创建、更新、upsert 和删除某个模型的节点跨关系创建、连接、断开、更新和 upsert 节点批量更新或删除节点Subscriptions订阅在节点被创建、更新或删除时获得实时通知从实现角度看Prisma API 的实际 GraphQL schema 被称为Prisma database schema它由 Prisma 服务端根据数据模型动态构建。在仓库的服务端源码中这一构建逻辑由 server/servers/api/src/main/scala/com/prisma/api/schema/SchemaBuilder.scala 及其实现类负责并通过 CachedSchemaBuilder 对生成的 schema 做缓存以提升重复请求的性能。Prisma API 中暴露的每一个操作都与数据模型中的某个**模型model或关系relation**相关联操作类别具体能力Queries查询某个模型的单个或多个节点、跨关系查询、跨关系聚合Mutations创建、更新、upsert、删除节点跨关系 create/connect/disconnect/update/upsert批量更新或删除Subscriptions节点被 created / updated / deleted 时获得通知探索 Prisma APIGraphQL Playground 是探索 Prisma API 的最佳工具你可以用它来执行 GraphQL 查询、变更和订阅直观地查看 schema 结构、字段类型和可用参数。打开服务对应 Playground 有两种方式命令行方式在服务的工作目录下运行prisma playground命令浏览器方式把服务的 HTTP endpoint 粘贴到浏览器地址栏中打开。prisma playground命令的底层实现在仓库源码 cli/packages/prisma-cli-core/src/commands/playground/index.ts 中可以看到该命令的完整实现逻辑命令通过definition.load读取服务的prisma.yml定义确定当前stage与所在cluster若prisma.yml中配置了endpoint则直接使用否则通过cluster.getApiEndpoint(service, stage, workspace)动态计算 API 端点默认在本地3000端口启动一个 express 服务器将/playground路由交给graphql-playground-middleware-express渲染并将/graphql路由通过express-request-proxy代理到真实的 Prisma API 端点启动后自动打开浏览器访问http://localhost:3000/playground。该命令支持若干 flag方便在不同场景下使用Flag简写说明--web-w强制打开 Web 版 Playground--env-file-e指定注入环境变量的.env文件路径--project-p指定 Prisma 定义文件prisma.yml的路径--server-only-s只启动服务器不自动打开浏览器--port-p指定 Web 版 Playground 的端口隐含--webPrisma API 核心概念速览在深入使用 Prisma API 之前先了解几个贯穿查询、变更、订阅三大模块的核心概念。详情见 Concepts 章节。节点选择Node selectionPrisma API 中的许多操作只影响数据库中的部分节点甚至只影响单个节点。此时需要通过where参数来指定目标节点。节点可以通过任意标注了unique指令的字段来选中。例如对如下数据模型type Post { id: ID! unique title: String! published: Boolean default(value: false) }按唯一字段检索单个节点query { post(where: { email: hellograph.cool }) { id } }按id更新单个节点的titlemutation { updatePost( where: { id: ohco0iewee6eizidohwigheif } data: { title: GraphQL is awesome } ) { id } }批量更新多个节点id_in接收一个 id 列表mutation { updatePost( where: { id_in: [ohco0iewee6eizidohwigheif, phah4ooqueengij0kan4sahlo, chae8keizohmiothuewuvahpa] } data: { published: true } ) { count } }批量操作Batch operations节点选择的一个典型应用是批量操作。批量更新或删除针对大量节点做了优化因此这类 mutation 只返回受影响节点的数量count而不返回节点的完整信息。例如updateManyPosts和deleteManyPosts都通过where选择节点并通过count字段返回受影响数量见上例。⚠️注意批量 mutation不会触发任何 subscription 事件连接查询Connections与直接返回节点列表的简单对象查询不同连接查询基于 Relay Connection 模型除了分页信息外还提供**聚合aggregation**等高级特性。例如posts查询可以按字段排序、分页选取Post节点而postsConnection查询还可以统计所有未发布的Post数量query { postsConnection { # aggregate 允许执行常用的聚合操作 aggregate { count } edges { # 每个 node 引用一个 Post 元素 node { title } } } }事务性变更Transactional mutationsPrisma API 中非批量的单次 mutation 总是以事务方式执行即使它包含跨多个关系的大量操作例如嵌套变更在多个类型上执行多次数据库写入。典型例子在一次 mutation 中创建一个User节点、两个新的Post节点并连接它们同时把该User连接到另外两个已存在的Post节点。如果其中任何一步失败例如违反了unique约束整个 mutation 会回滚。这些 mutation 是事务性的即具备原子性和隔离性在同一个嵌套 mutation 的两个独立动作之间不会有其他 mutation 改变数据单个动作的结果在整个 mutation 处理完成之前不可见。级联删除Cascading deletesPrisma 支持为数据模型中的关系配置不同的删除行为通过relation指令的onDelete参数指定。有两种主要行为CASCADE当一个节点被删除时与之关联的节点也会被删除SET_NULL当一个节点被删除时指向该节点的字段被置为null考虑下面的数据模型type User { id: ID! unique comments: [Comment!]! relation(name: CommentAuthor, onDelete: CASCADE) blog: Blog relation(name: BlogOwner, onDelete: CASCADE) } type Blog { id: ID! unique comments: [Comment!]! relation(name: Comments, onDelete: CASCADE) owner: User! relation(name: BlogOwner, onDelete: SET_NULL) } type Comment { id: ID! unique blog: Blog! relation(name: Comments, onDelete: SET_NULL) author: User relation(name: CommentAuthor, onDelete: SET_NULL) }分析三个类型的删除行为删除一个User节点时所有相关的Comment节点被删除相关的Blog节点被删除删除一个Blog节点时所有相关的Comment节点被删除相关的User节点的blog字段被置为null删除一个Comment节点时相关的Blog节点继续存在被删除的Comment从它的comments列表中移除相关的User节点继续存在被删除的Comment从它的comments列表中移除Prisma API 认证API secret 与 API tokenPrisma 服务的 GraphQL API 通常受API secret保护即prisma.yml中的secret属性。示例prisma.ymlendpoint: http://localhost:4466/myapi/dev datamodel: datamodel.graphql secret: mysecret123 # 你的 API secretAPI token用于对 Prisma API 的请求进行认证。API secret 用于签发 JWT该 JWT 需要放在 HTTP 请求的Authorization头中Authorization: Bearer __YOUR_API_TOKEN__通过 Prisma CLI 获取 API token获取 API token 最简单的方式是使用 Prisma CLI 的prisma token命令prisma token当在包含prisma.yml的目录中运行时CLI 会读取prisma.yml中的secret属性并生成对应的 JWT。从源码看该命令实现在 cli/packages/prisma-cli-core/src/commands/token/token.ts它会读取服务的名称与 stage调用definition.getToken(serviceName, stage)生成 token并支持--copy复制到剪贴板、--env-file、--project等参数。若prisma.yml中未设置 secret命令会提示There is no secret set in the prisma.yml。在 GraphQL Playground 中认证获取 API token 后即可用它来认证 API 请求例如通过 GraphQL Playground 使用 API。打开 Playground 后点击左下角的HTTP HEADERS区域将 API token 作为Authorization字段的值粘贴进去{ Authorization: Bearer __YOUR_API_TOKEN__ }使用真实 token 时大致长这样{ Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJkYXRhIjp7InNlcnZpY2UiOiJibG9nckBkZXYiLCJyb2xlcyI6WyJhZG1pbiJdfSwiaWF0IjoxNTE4NzE2NjA4LCJleHAiOjE1MTkzMjE0MDh9.zqBh_Oo4RmV4j3UQeVDYqJDxV-YHQiOR-XIlhjbWejw }JWT 的 ClaimsJWT 必须包含以下 claims过期时间exptoken 的过期时间服务信息service服务的名称和 stage示例 JWT Payload{ exp: 1300819380, service: my-serviceprod }未来可能会引入更细粒度的访问控制例如[write:Log, read:*]这样的角色概念。在 JavaScript 中生成服务 token考虑以下prisma.yml使用了环境变量service: my-service stage: ${env:PRISMA_STAGE} cluster: ${env:PRISMA_CLUSTER} datamodel: database/datamodel.graphql secret: ${env:PRISMA_SECRET}Node 服务端可以基于jsonwebtoken库为服务my-service的 stagePRISMA_STAGE生成签名 JWTvar jwt require(jsonwebtoken) jwt.sign( { data: { service: my-service process.env.PRISMA_STAGE, }, }, process.env.PRISMA_SECRET, { expiresIn: 1h, } )JWT 验证规则对 Prisma 服务的请求会验证 JWT 的以下属性必须使用为该服务配置的 secret 签名必须包含expclaim且过期时间在未来必须包含serviceclaim且服务名与 stage 与当前请求匹配从服务端源码 server/libs/auth/src/main/scala/com/prisma/auth/Auth.scala 可以看到验证的底层实现服务端使用Jwt.decodeRaw解码Authorization头剥离Bearer前缀并依次校验签名与过期时间若服务未配置任何 secretsecrets.isEmpty则直接放行认证。这也解释了为什么prisma.yml中的secret是 API 安全的第一道防线。错误处理当查询或变更出错时响应中会包含errors属性携带错误code、message等详细信息。Prisma API 有两类错误Application errors应用错误通常表示你的请求无效Internal server errors内部服务器错误通常表示 Prisma 服务内部发生了意外情况需要查看服务日志定位问题注意errors字段遵循官方 GraphQL 错误处理规范。应用错误排查API 返回错误通常意味着请求的查询或变更存在不正确之处——可能是笔误、遗漏了必填参数等。请对照错误信息检查输入。常见错误示例——认证失败 / token 无效{ errors: [ { code: 3015, requestId: api:api:cjc3kda1l000h0179mvzirggl, message: Your token is invalid. It might have expired or you might be using a token from a different project. } ] }检查你提供的 token 是否已过期、是否由prisma.yml中列出的 secret 签名。内部服务器错误排查可查阅服务日志获取更多错误信息。对于本地集群可以使用prisma logs命令。延伸阅读Prisma API 三大操作类型的完整指南均位于同目录下Concepts核心概念节点选择、批量操作、连接查询、事务性变更、级联删除Queries查询对象查询与连接查询、跨关系查询、orderBy/where/分页等查询参数Mutations变更对象变更、嵌套变更、标量列表变更、批量变更Subscriptions订阅类型订阅、订阅请求WebSocket 协议、组合订阅与高级过滤如果你希望深入服务端如何从数据模型生成这套 GraphQL schema可以阅读 server/servers/api/src/main/scala/com/prisma/api/schema 目录下的源码如果你对 CLI 如何打通 Playground 与 token 流程感兴趣可以查看 cli/packages/prisma-cli-core/src/commands/playground 与 cli/packages/prisma-cli-core/src/commands/token 的源码实现。【免费下载链接】prisma1 Database Tools incl. ORM, Migrations and Admin UI (Postgres, MySQL MongoDB) [deprecated]项目地址: https://gitcode.com/gh_mirrors/pr/prisma1创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考