ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

prisma-binding 实战指南:用 GraphQL Binding 委托机制构建 Prisma GraphQL 服务器

prisma-binding 实战指南:用 GraphQL Binding 委托机制构建 Prisma GraphQL 服务器 后端数据库GraphQL【免费下载链接】prisma1 Database Tools incl. ORM, Migrations and Admin UI (Postgres, MySQL MongoDB) [deprecated]项目地址https://gitcode.com/gh_mirrors/pr/prisma1点击查看免费下载prisma-binding是面向 Prisma 服务的专用 GraphQL binding它在上层为开发者提供了一个便捷层将查询query与变更mutation的**执行委托delegation**给底层 Prisma 数据库服务的 API从而大幅简化 GraphQL resolver 的实现。本文将以docs/1.2/06-GraphQL-Ecosystem/02-GraphQL-Binding/02-Prisma-Binding.md为核心骨架结合本仓库cli/packages/prisma-client-lib的源码实现完整讲解 Prisma Binding 的安装、实例化、查询委托、exists 判断与 request 用法并剖析其底层工作方式。读完本文你将能够基于自己的 Prisma 数据模型快速搭建 GraphQL 服务器并理解动态绑定与静态绑定两种实践形态。背景GraphQL Binding 与 Prisma BindingGraphQL binding 是一种模块化构建块它允许把已有的 GraphQL API或其中的一部分嵌入到你自己的 GraphQL 服务器中——可以理解为把 GraphQL API 变成可复用的乐高积木。本仓库对应的概念文档 01-GraphQL-Binding.md 中给出了一般化定义graphql-binding包负责创建你自己的 binding而一个 binding 对象会暴露binding.query、binding.mutation与binding.subscription三类属性分别对应 schema 中Query、Mutation、Subscription根类型的各个字段。prisma-binding正是这一通用思想在 Prisma 数据库服务上的落地Prisma 服务本身对外暴露一个完整的 GraphQL CRUD API由数据模型自动生成prisma-binding则把这个 API 包装成语义化的 JavaScript 调用接口。其核心价值是你不必手工拼写完整的 GraphQL query/mutation 字符串也不必自己处理 HTTP 传输细节所有这些都由自动生成的 delegate resolver 函数在底层完成。从仓库源码结构看这套思想在后续演进中沉淀为 cli/packages/prisma-client-lib/src/Client.ts 中的Client基类实现prisma-binding文档所描述的query/mutation/exists/requestAPI 与该实现一脉相承。工作原理五步构建委托链prisma-binding的工作方式可以概括为以下五个步骤创建 Prisma 服务通过定义数据模型datamodel来创建你的 Prisma 服务下载生成的数据库 schema 定义得到database.graphql文件其中包含完整的 CRUD API定义应用 schema通常命名为app.graphql它是你的 GraphQL 服务器对外暴露的 schema实例化Prisma传入 Prisma 服务的相关信息如 endpoint 和数据库 schema 定义文件的路径实现 resolver通过自动生成的 delegate resolver 函数将应用 schema 的 resolver 委托给底层 Prisma 服务。注意如果使用 GraphQL boilerplate 项目例如通过graphql create创建Prisma binding 通常已经配置好并预置了若干示例 resolver。你既可以使用动态绑定例如node-basicboilerplate 中的方式也可以使用静态绑定例如typescript-basicboilerplate 中的方式后文会专门对比这两种形态。安装在项目中安装prisma-binding非常简单yarn add prisma-binding # 或 npm install --save prisma-binding从本仓库的工程结构看prisma-binding的核心逻辑已被吸收进 cli/packages/prisma-client-lib 这个包其中 makePrismaClientClass.ts 以typeDefs、endpoint、secret、models为参数生成一个继承自Client的类而 Client.ts 则承载了构造、方法构建、查询执行等全部核心行为。快速示例从数据模型到委托调用假设你的 Prisma 服务数据模型如下type User { id: ID! unique name: String }基于该服务实例化Prisma后你就可以发送如下查询/变更注意原文档示例中where后缺少冒号此处给出修正后的可运行写法// 基于具体服务实例化 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 })可以看到每个方法调用都以参数对象 选择集selection set通常写成字符串作为输入。在底层这些调用会被翻译成一次针对你 Prisma 服务的真实 HTTP 请求基于graphql-request实现。PrismaAPI 还允许你询问某个节点在 Prisma 数据库中是否存在// 询问是否存在 id 为 abc、且 author 名为 Sarah 的 post返回布尔值 prisma.exists.Post({ id: abc, author: { name: Sarah } })源码视角这些调用到底发生了什么本仓库 Client.ts 的实现可以印证上述行为。其构造函数接收{ typeDefs, endpoint, secret, debug, models }选项对应文档中的PrismaOptions内部会用buildSchema(typeDefs)将 schema 定义解析为GraphQLSchema若提供了secret则用jsonwebtoken的sign({}, secret)生成 token并在 HTTP 请求头Authorization: Bearer token中携带见 Client.ts调用buildMethods()构建query/mutation委托方法并通过buildGraphQL()构建$graphql、通过buildExists()构建$exists。委托调用的核心机制位于getTypes()它遍历 schema 的类型表为每个GraphQLObjectType的字段生成一个代理函数。当你调用prisma.query.user(...)时实际是把一条指令包含fieldName、args、field、typeName压入_currentInstructions随后由processInstructions通过generateSelections把指令链重新组装成 GraphQL AST再经execute发出请求。注意getTypes()为字段包装的值带有then/catch方法并标记为Symbol.toStringTag: Promise这正是文档中每个 delegate resolver 返回PromiseT的体现Client.ts。exists的底层实现也值得留意buildExists()通过getTypesAndWhere(queryType)找出所有可查询的模型类型为每个类型生成一个函数它调用对应的 plural 查询字段如users({ where: args })再通过res.length 0得到布尔结果Client.ts。API 详解Prisma 构造函数constructor(options: PrismaOptions): PrismaPrismaOptions类型包含以下字段原文档的PrismaOptions表格结合仓库 types.ts 的类型定义说明如下KeyRequiredTypeDefaultNoteschemaPathYesstring-Prisma 服务 schema 定义的文件路径通常是名为database.graphql的文件endpointYesstring-Prisma 服务的 endpointsecretYesstring-Prisma 服务的 secretfragmentReplacementsNoFragmentReplacementsnull一组 GraphQL fragment 定义指定 resolver 正常工作所需的字段debugNobooleanfalse将所有 query/mutation 打印到控制台补充两点从仓库源码确认的细节secret的可选性在 types.ts 中BaseClientOptions将secret声明为可选secret?: string未提供 secret 时不生成 token也不附加Authorization头。生产环境若 Prisma 服务启用了鉴权则必须提供。debug的实际行为在 Client.ts 中processInstructions在this._debug为真时会打印完整的 query 文档含变量这对排查委托查询非常有帮助。typeDefs与schemaPath的命名差异文档表格中字段名为schemaPath而文档示例与仓库代码makePrismaClientClass.ts中实际使用的是typeDefs或生成代码中的prisma-schema二者指向同一概念Prisma 服务的数据库 schema 定义。query 与 mutationquery和mutation是Prisma实例上的公开属性类型均为Query暴露一组以 Prisma 数据库 schema 中Query/Mutation类型字段命名的自动生成 delegate resolver 函数。每个 delegate resolver 本质上是一个便捷 API帮你向 Prisma 服务发送 query/mutation让你不必从零拼写完整查询字符串、也不必操心 HTTP 传输。delegate resolver 的接口如下(args: any, info: GraphQLResolveInfo | string): PromiseT参数语义args携带 query/mutation 潜在参数的对象info表示该 query/mutation 选择集的对象既可以是字符串形式的 selection set也可以是GraphQLResolveInfoGraphQL 解析链中传递的 info 对象内含入站查询的 AST泛型T对应所查询字段的返回类型。在 resolver 中使用时典型写法是把父级传入的info原样透传给委托函数从而只请求客户端真正需要的字段const resolvers { Query: { user(parent, args, context, info) { return prisma.query.user(args, info) }, }, }这一透传模式意味着你的应用 schema 可以窄于数据库 schema客户端请求什么字段就只从 Prisma 服务取回什么字段。existsexists同样是Prisma实例上的公开属性。与query/mutation类似它暴露若干自动生成的函数但每个类型只有一个函数。该函数以允许检索该类型单个节点的根字段命名例如类型User对应exists.User接收一个where对象作为输入返回boolean表示where条件是否满足。这让检查某类型节点在 Prisma 数据库中是否存在变得非常容易例如先判存在再决定创建或更新的upsert 式业务逻辑async function ensureUser(name) { const exists await prisma.exists.User({ name }) return exists ? prisma.query.users({ where: { name } }, { id name }) : prisma.mutation.createUser({ data: { name } }, { id name }) }如前所述其实现基于 plural 查询字段的长度判断res.length 0见 Client.ts。requestrequest方法让你以手写 GraphQL 字符串的方式向 Prisma 服务发送 query/mutation。它的功能与自动生成的 delegate resolver 相同但 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 } } }注意这里变量名$userId是显式声明的而 delegate resolver 的变量生成是自动的——这是两者体验差异的直观体现。在仓库实现中Client通过buildGraphQL()生成$graphql方法直接调用BatchedGraphQLClient.request(query, variables)Client.ts这与文档中request的语义一致。动态绑定与静态绑定原文档提到 boilerplate 中可能存在两种 binding 形态结合仓库的代码生成器可以进一步理解二者的区别动态绑定运行时传入typeDefs与endpoint实例化 Prismaquery/mutation的方法完全由运行时解析 schema 动态生成。其优点是灵活、schema 变化无需重新生成代码缺点是没有编译期类型检查与 IDE 补全。静态绑定在构建期由代码生成器产出带有完整类型声明的客户端代码。本仓库 cli/packages/prisma-client-lib/src/codegen/generators 下提供了javascript-client.ts、typescript-client.ts、flow-client.ts、go-client.ts等多个生成器。以 javascript-client.ts 为例它会生成如下形态的产物use strict; var prisma_lib_1 require(prisma-client-lib); var typeDefs require(./prisma-schema).typeDefs var models [{ name: User, embedded: false }] exports.Prisma prisma_lib_1.makePrismaClientClass({ typeDefs: typeDefs, endpoint: ..., secret: ..., models: models, }); exports.prisma new exports.Prisma();其中models数组记录了每个模型的embedded标志供Client判断内嵌embedded类型从而决定嵌套选择集如何生成Client.ts。对应测试可参考 codegen/generators/tests/javascript-client.test.ts 与 Client.test.ts。适用前提与注意事项本文所有 API 均以Prisma 服务已就绪为前提你需要先通过 CLI 创建并部署 Prisma 服务拿到可用的endpoint与若启用鉴权secret以及服务生成的database.graphql或prisma-schema文件。prisma-binding依赖的 Prisma 服务 schema 应包含完整的 CRUD 根字段user/users/createUser/updateUser/deleteUser等delegate resolver 与exists均基于这些字段生成。若服务端点启用了鉴权secret缺失会导致请求被拒绝同时注意 WebSocket 订阅场景下Authorization通过connectionParams携带Client.ts两者的鉴权凭证是同一份 token。下一步演进prisma-binding文档预告的方向是在构建期为自动生成的 delegate resolver 做代码生成Code generation at build-time。这一点在仓库中已经落地为 prisma-client-lib 的完整代码生成管线——从makePrismaClientClass到各语言生成器与对应快照测试形成了动态委托运行时 静态类型代码生成的组合能力。若要进一步深入可以阅读 Client.ts 中关于 Relay Connection、subscription payload 映射mapSubscriptionPayload、指令批处理与内存释放_releaseMemory等实现细节这些共同构成了 Prisma GraphQL 委托层的完整图景。赞分享后端数据库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 服务构建 GraphQL Serverprisma binding 实战指南用 GraphQL Binding 委托 Prisma 服务构建 GraphQL Server prisma bindi后端数据库GraphQLPrisma Binding 使用指南用 GraphQL 委托机制为 Prisma 服务构建 GraphQL 服务器Prisma Binding 使用指南用 GraphQL 委托机制为 Prisma 服务构建 GraphQL 服务器 prisma binding 是专为 P后端数据库GraphQLPrisma Binding 实战指南用 GraphQL 委托解析器搭建基于 Prisma 服务的 GraphQL 服务端Prisma Binding 实战指南用 GraphQL 委托解析器搭建基于 Prisma 服务的 GraphQL 服务端 prisma binding 是后端数据库GraphQL创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表