使用 prisma-binding API 构建 GraphQL 服务:委托解析器(Delegate Resolver)完全指南
后端数据库GraphQL【免费下载链接】prisma1 Database Tools incl. ORM, Migrations and Admin UI (Postgres, MySQL MongoDB) [deprecated]项目地址https://gitcode.com/gh_mirrors/pr/prisma1点击查看免费下载本文是 Prisma Binding API 的深度实战指南围绕 docs/1.2/04-Reference/08-Prisma-Bindings/02-API.md 展开结合仓库中prisma-client-lib的实际源码讲解Prisma实例的构造参数、query/mutation委托解析器、exists存在性检查以及request原生请求方法的完整用法。读完本文你将能够在自己的 GraphQL Server 中直接用一行式委托调用替代手写 SQL / 直接操作数据库 API并理解每次调用在底层如何被翻译为对 Prisma 服务的 HTTP 请求。背景什么是 Prisma Bindingprisma-binding是专为 Prisma 服务设计的 GraphQL Binding 实现它提供了一层薄薄的便利层用于在 Prisma 服务之上构建 GraphQL 服务器。核心思路是在实现你的 resolver 时把查询或变更的“执行权”委托给底层 Prisma 数据库服务的 API而不是在 resolver 内部手写 SQL 或直接调用 MongoDB 之类的 NoSQL API。这样一来绝大多数 resolver 都可以简化为一行代码return ctx.db.query.posts({}, info)使用 Prisma Binding 构建 GraphQL 服务器的整体流程如下创建 Prisma 服务并定义数据模型data model下载自动生成的数据库 schema 定义database.graphql其中包含完整的 CRUD API定义你的应用层 schema通常命名为app.graphql用 Prisma 服务的 endpoint、数据库 schema 路径等信息实例化Prisma实现应用层 schema 的 resolver通过自动生成的委托解析器函数把请求委托给底层 Prisma 服务。快速上手从数据模型到第一个委托调用假设你的 Prisma 服务定义了如下数据模型type User { id: ID! unique name: String }基于该服务实例化Prisma之后就可以发送下列查询与变更// 基于具体的 Prisma 服务实例化 Prisma const prisma new Prisma({ typeDefs: schemas/database.graphql, endpoint: https://api.graph.cool/simple/v1/my-prisma-service, secret: my-super-secret-secret }) // 查询特定用户的 name 字段 prisma.query.user({ where: { id: abc } }, { name }) // 查询所有用户的 id 和 name prisma.query.users(null, { id name }) // 创建名为 Sarah 的用户并返回其 id prisma.mutation.createUser({ data: { name: Sarah } }, { id }) // 更新特定用户的 name并返回其 id prisma.mutation.updateUser({ where: { id: abc }, data: { name: Sarah } }, { id }) // 删除特定用户并返回其 id prisma.mutation.deleteUser({ where: { id: abc } }, { id })这些函数调用的本质都是在底层被翻译成一次针对你 Prisma 服务的真实 HTTP 请求借助graphql-request的能力。也就是说你不需要手动拼写完整的 GraphQL 查询字符串也不需要关心请求如何通过 HTTP 发出——委托解析器函数已经替你在底层完成了这一切。除了查询与变更API 还允许你直接询问某个节点是否存在于 Prisma 数据库中// 询问是否存在一个 id 为 abc 且其 author 名为 Sarah 的 post返回布尔值 prisma.exists.Post({ id: abc, author: { name: Sarah } })constructorPrismaOptions 参数详解Prisma的构造函数签名如下constructor(options: PrismaOptions): PrismaPrismaOptions类型包含以下字段KeyRequiredTypeDefaultNoteschemaPathYesstring-你的 Prisma 服务 schema 定义的文件路径通常是一个名为database.graphql的文件endpointYesstring-你的 Prisma 服务的 endpointsecretYesstring-你的 Prisma 服务的 secretfragmentReplacementsNoFragmentReplacementsnull一组 GraphQL fragment 定义指定 resolver 正确运行所需的字段debugNobooleanfalse是否将所有的查询/变更打印到控制台源码视角参数的实际处理从仓库源码可以印证上述参数的实际用途。在 cli/packages/prisma-client-lib/src/Client.ts 中Client构造函数接收{ typeDefs, endpoint, secret, debug, models }并完成以下初始化通过buildSchema(typeDefs)把 schema 定义解析为GraphQLSchema对象——这里需要说明的是文档表格中写作schemaPath而示例代码与当前仓库实现中该参数实际名为typeDefs它接收指向database.graphql的文件路径或 schema 字符串内容通过sign({}, secret)基于secret签发 JWT token后续所有请求都会携带Authorization: Bearer token请求头未提供 secret 时则不携带认证头创建BatchedGraphQLClient作为实际发送查询的 HTTP 客户端调用buildMethods()生成query、mutation等公开方法。对应地cli/packages/prisma-client-lib/src/types.ts 中定义了BaseClientOptionsendpoint、secret?、debug?、ClientOptions在基础上增加typeDefs与models以及FragmentReplacement{ field, fragment }类型。fragmentReplacements用于指定 resolver 运行时依赖的字段组合确保委托查询携带正确的 selection set。另外makePrismaClientClass.ts 展示了如何通过工厂函数把typeDefs、endpoint、secret、models固化为一个客户端类从而支持“静态绑定”的生成式用法。query 与 mutation自动生成的委托解析器query和mutation是Prisma实例上的两个公开属性更详细的 GraphQL Binding 概念参见 Prisma Bindings 总览。它们都暴露出大量自动生成的委托解析器函数这些函数按照 Prisma 数据库 schema 中Query和Mutation类型上的字段命名例如上面的user、users、createUser、updateUser、deleteUser。每个委托解析器本质上都是一个便利 API帮你把对 Prisma 服务的查询/变更请求打包发送出去你无需从头拼写完整的 query/mutation也无需操心 HTTP 传输细节——这一切都由委托解析器函数在底层处理。委托解析器的接口如下(args: any, info: GraphQLResolveInfo | string): PromiseT输入参数的使用方式args一个对象携带查询/变更所需的潜在参数例如where、datainfo一个代表查询/变更 selection set 的对象既可以直接写成字符串如{ id name }也可以传入GraphQLResolveInfo类型GraphQL 解析器中常见的第三个参数形式可直接把上层 resolver 的info透传进来实现 selection set 的自动透传。泛型类型T对应当前字段的返回类型。源码视角委托解析器如何生成从源码结构看buildMethods()会遍历 schema 的 type map在 Client.ts 中Object.assign(this, this._types.Query)与Object.assign(this, this._types.Mutation)把Query/Mutation根类型的所有字段函数挂到客户端实例上。每个字段函数被包装成“指令收集器”调用prisma.query.user(...)时并不会立即发起 HTTP 请求而是先把{ fieldName, args, field, typeName }记入_currentInstructions同时把返回对象的then/catch以及后续嵌套字段函数都绑定到同一个指令 id 上直到该 Promise 被 await 或调用.then时才通过processInstructions把收集到的指令链拼装成完整 GraphQL 文档经execute发送请求见 Client.ts。这一机制也解释了为什么可以链式访问嵌套字段例如prisma.query.user(...).posts(...)以及为什么query/mutation函数天然兼容info透传——它们最终都会被组装为一次请求。仓库中的 Client.test.ts 提供了针对extractPayload嵌套数组/嵌套对象解包的测试用例可用于验证这一请求-解包链路的行为。exists按 where 条件判断节点是否存在exists同样是Prisma实例上的公开属性。与query、mutation类似它也暴露一组自动生成的函数但每个类型只有一个函数。该函数以允许检索该类型单个节点的根字段命名例如类型User对应exists.User。它接收一个where对象作为输入并返回boolean值表示where表达的条件是否被满足。利用该函数你可以很方便地检查某种类型的节点是否存在于 Prisma 数据库中例如prisma.exists.Post({ id: abc, author: { name: Sarah } })源码视角exists 的实现方式在 Client.ts 的buildExists()中可以看到它的实现逻辑取 schema 的Query根类型借助getTypesAndWhere找出每个模型类型及其复数查询字段名然后为每个类型生成形如firstLetterLowercaseTypeName的函数例如Post→post最终暴露在exists上。该函数实际执行thispluralFieldName即调用对应的复数查询委托解析器最后用res.length 0判断是否命中至少一条记录并返回布尔值。类型定义Exists在 types.ts 中声明为(filter: Filter) Promiseboolean。request显式发送完整的 GraphQL 查询request方法允许你向 Prisma 服务发送任意 GraphQL 查询/变更。它的功能与自动生成的委托解析器完全一致但 API 更加“冗长”——你需要自己拼写完整的 query/mutation 文本。request底层同样依赖graphql-request。使用示例const query query ($userId: ID!){ user(id: $userId) { id name } } const variables { userId: abc } prisma.request(query, variables) .then(result console.log(result)) // 示例返回结果 // {data: { user: { id: abc, name: Sarah } } }当你需要发送委托解析器未覆盖的自定义查询例如聚合、连接connection查询或跨字段的复杂条件或者需要精确控制变量定义时request是比委托解析器更灵活的兜底方案。在 Client.ts 中buildGraphQL()生成的$graphql(query, variables)正是request的内核实现——直接调用this._client.request(query, variables)把查询与变量交给底层的BatchedGraphQLClient。源码视角一次委托调用背后的完整链路综合来看一次prisma.query.user(...)调用的完整链路可以概括为指令收集调用委托函数时参数与字段信息被写入_currentInstructions见 Client.ts文档组装.then/await触发processInstructionsgenerateSelections把指令链转化为 AST并自动生成变量定义同名参数会自动编号去重见 Client.ts调试输出若构造时传入debug: true则会在控制台打印组装好的查询文本与变量见 Client.ts请求发送execute把 AST 打印为查询字符串通过BatchedGraphQLClient发送携带Authorization: Bearer token见 Client.ts结果解包extractPayload沿指令链逐层剥开返回的data对象返回最内层的负载数据见 Client.ts。这一设计把“拼查询、发请求、解结果”三件事全部封装进了库内部让你在编写业务 resolver 时只需关心参数与 selection set——这正是 Prisma Binding 能显著简化 GraphQL Server 开发的原因所在。小结Prisma构造函数接收typeDefs或文档表格中的schemaPath、endpoint、secret以及可选的fragmentReplacements、debug其中secret会被用于签发 JWT 认证头debug用于打印实际发送的查询query与mutation暴露按 schema 字段命名的委托解析器签名统一为(args, info) PromiseTinfo既可以是字符串也可以是GraphQLResolveInfoexists提供按类型的存在性检查内部通过复数查询字段加上res.length 0判断实现request让你手动拼写完整查询适合委托解析器覆盖不到的场景底层与委托调用共用同一 HTTP 客户端。如果你想进一步了解委托解析器在完整 GraphQL Server 场景中的用法如ctx.db.query.posts({}, info)在 resolver 中的透传可以继续阅读 Prisma Bindings 总览如果关心生成式静态绑定的用法可以查看 makePrismaClientClass.ts 与 types.ts 中的类型定义。赞分享后端数据库GraphQL【免费下载链接】prisma1 Database Tools incl. ORM, Migrations and Admin UI (Postgres, MySQL MongoDB) [deprecated]项目地址https://gitcode.com/gh_mirrors/pr/prisma1点击查看免费下载相关推荐prisma-binding 实战指南使用 GraphQL Binding 委托构建 Prisma 服务prisma binding 实战指南使用 GraphQL Binding 委托构建 Prisma 服务 prisma binding 是专门为 Prisma后端数据库GraphQLprisma-binding 实战指南用 GraphQL Binding 委托 Prisma 服务构建 GraphQL Serverprisma binding 实战指南用 GraphQL Binding 委托 Prisma 服务构建 GraphQL Server prisma bindi后端数据库GraphQLPrisma Binding 使用指南用 GraphQL 委托机制为 Prisma 服务构建 GraphQL 服务器Prisma Binding 使用指南用 GraphQL 委托机制为 Prisma 服务构建 GraphQL 服务器 prisma binding 是专为 P后端数据库GraphQL创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
上一篇/下一篇内容由系统自动关联
返回资讯列表 →