拓冰建站拓冰建站
首页 / 资讯中心 / 正文

使用 Prisma 构建 GraphQL 服务器:基于 prisma-binding 的完整实战指南

后端数据库GraphQL【免费下载链接】prisma1 Database Tools incl. ORM, Migrations and Admin UI (Postgres, MySQL MongoDB) [deprecated]项目地址https://gitcode.com/gh_mirrors/pr/prisma1点击查看免费下载本文以 Prisma 项目当前仓库gh_mirrors/pr/prisma1的官方教程为蓝本演示如何在已有的 Prisma 服务之上用graphql-yoga与prisma-binding搭建一个面向业务领域的 GraphQL 服务器。你将掌握应用 SchemaApplication Schema与 Prisma 数据库 Schema 的分层设计、通过.graphqlconfig.yml管理双 API、以及用一行行 resolver 把查询/变更委托给 Prisma GraphQL API 的完整流程。读完后你可以独立从零复刻出一个可运行、可在 Playground 中验证的博客类 GraphQL 后端。为什么不在客户端直接使用 Prisma APIPrisma 把数据库变成了一个 GraphQL API自动暴露对数据的强大 CRUD 操作。既然如此为什么不干脆让客户端直接调用 Prisma 的 API、省掉再写一层 GraphQL 服务器的工作原因在于让客户端直连 Prisma就等同于把你的整个数据库直接暴露给客户端。这在生产环境中并不可取主要有以下几点考量客户端应当消费**领域特定domain-specific**的 API而不是与通用 CRUD 操作打交道你需要为使用者提供认证/授权功能如密码注册、第三方认证提供商你的 API 需要与微服务或其他遗留系统集成你需要把Stripe、GitHub、Yelp 等第三方服务/公共 API整合进服务器逻辑你不希望把整个数据库 Schema 暴露给所有人GraphQL 的 introspection 特性会把 Schema 全部公开。因此标准的架构是客户端 → 你的 GraphQL 服务器领域 API→ Prisma 服务数据库 API。本教程正是教你搭好中间这一层。前置准备一个可运行的 Prisma 服务本教程假设你已经有一个正在运行的 Prisma 服务即至少拥有以下两个文件prisma.yml服务配置文件datamodel.graphql数据模型定义文件。同时请确保你能拿到该服务的endpoint它定义在prisma.yml的endpoint属性中。如果还没有 Prisma 服务请先完成下列任一入门教程再回来在 Demo 服务器上搭建 Prisma用全新的 MySQL 数据库搭建 Prisma用全新的 Postgres 数据库搭建 Prisma连接你的空 MySQL 数据库搭建 Prisma连接你的空 Postgres 数据库搭建 Prisma关于prisma.yml的完整字段说明datamodel、endpoint、secret、hooks、subscriptions、seed、变量引用等可参考 prisma.yml 配置参考。Step 1更新数据模型为了让后续步骤有一个合适的数据模型需要先调整已有 Prisma 服务的数据模型。这里假设你的数据模型存放在单个文件datamodel.graphql中如果不是请相应调整。打开datamodel.graphql把内容更新为type User { id: ID! unique name: String! posts: [Post!]! } type Post { id: ID! unique title: String! content: String! published: Boolean! default(value: false) author: User! }保存文件后打开终端并进入 Prisma 服务的根目录即prisma.yml所在的目录运行以下命令更新其 GraphQL APIprisma deploy部署完成后Prisma 服务的 GraphQL API 会为数据模型中定义的User与Post类型暴露对应的 CRUD 操作同时允许你通过connect等方式修改二者之间的关系relation——后面的 resolver 实现正是依赖了这一点。Step 2用graphql-yoga搭建 GraphQL 服务器接下来创建 GraphQL 服务器的目录结构并安装 NPM 依赖。注意当前存放 Prisma 服务文件prisma.yml与datamodel.graphql的目录稍后会被移入 GraphQL 服务器目录内部。在新目录中执行以下命令mkdir -p my-yoga-server/src touch my-yoga-server/src/index.js touch my-yoga-server/src/schema.graphql cd my-yoga-server yarn init -y这会创建预期的目录结构并生成package.json。其中index.js是服务器的入口文件schema.graphql定义应用 Schema即你的服务器对外暴露的 GraphQL API 的 Schema。接着把 Prisma 服务的根目录移动进my-yoga-server并重命名为prisma。完成后my-yoga-server的结构应类似my-yoga-server │ ├── package.json ├── prisma │ ├── datamodel.graphql │ └── prisma.yml └── src ├── schema.graphql └── index.js接下来安装两个核心依赖yarn add graphql-yoga prisma-binding两个依赖的分工如下graphql-yoga提供 GraphQL 服务器的功能基于 Express.jsprisma-binding让你可以轻松把 resolver 连接到 Prisma 的 GraphQL API——这正是本教程的技术核心。Step 3定义应用 Schema每个 GraphQL 服务器的 API 都由对应的 GraphQL Schema 定义。现在来定义服务器对外暴露的操作。从数据模型可以看出我们正在构建一个简单的博客应用客户端不应该能对Post、User类型为所欲为而是消费面向业务领域、按需裁剪的操作。打开schema.graphql添加如下 Schema 定义# import Post from ./generated/prisma.graphql # import User from ./generated/prisma.graphql type Query { posts(searchString: String): [Post!]! user(id: ID!): User } type Mutation { createDraft(authorId: ID!, title: String!, content: String!): Post publish(id: ID!): Post deletePost(id: ID!): Post signup(name: String!): User! }这个 Schema 定义了 6 个操作2 个查询 4 个变更操作签名说明postsposts(searchString: String): [Post!]!获取全部Post可传入searchString进行过滤useruser(id: ID!): User按id获取单个UsercreateDraftcreateDraft(authorId: ID!, title: String!, content: String!): Post为指定authorId的User创建草稿即published为false的Postpublishpublish(id: ID!): Post发布草稿把published置为truedeletePostdeletePost(id: ID!): Post删除一篇Postsignupsignup(name: String!): User!通过name创建新User这里有一点需要注意Post和User类型是从src/generated/prisma.graphql导入的——这个文件目前还不存在不用担心下一步就会把它下载下来。另外导入语法使用的是GraphQL 注释这些注释绝不能删除它们被graphql-import使用——该工具允许你在不同文件之间导入 SDL 类型这是标准 SDL 目前尚不支持的能力。仓库佐证graphql-import的能力在 Prisma 生态中承担跨文件导入 SDL 类型的职责正是它让schema.graphql能以# import Post from ./generated/prisma.graphql的方式复用 Prisma 数据库 Schema 中的类型。Step 4下载 Prisma 数据库 Schema下一步是把 Prisma GraphQL API 的 Schema即Prisma database schema下载到项目中以便从那里导入 SDL 类型。严格来说这一步并非绝对必要——你也可以在schema.graphql中重新定义一份一模一样的Post、User类型。但那样的话类型定义会存在于两个相互独立的位置今后每次更新类型都要改两遍。因此最佳实践是从 Prisma 的 GraphQL Schema 中导入类型保证单一事实来源。下载 Prisma database schema 需要用到 GraphQL CLI 和 GraphQL Config。首先全局安装 GraphQL CLIyarn global add graphql-cli接着在服务器根目录即my-yoga-server目录创建.graphqlconfigtouch .graphqlconfig.yml在其中写入以下内容定义本项目涉及的两个 GraphQL APIPrisma 的 GraphQL API 以及你graphql-yoga服务器的定制 APIprojects: app: schemaPath: src/schema.graphql extensions: endpoints: default: http://localhost:4000 prisma: schemaPath: src/generated/prisma.graphql extensions: prisma: prisma/prisma.yml这个文件中的信息会被 GraphQL CLI 以及 GraphQL Playground 使用——在 Playground 中你可以基于它并排操作两个 API。最后运行下面的命令把 Prisma database schema 下载到src/generated/prisma.graphqlgraphql get-schema --project prisma现在包含完整数据库 CRUD API 的 Prisma database schema 已经出现在.graphqlconfig.yml中projects.prisma.schemaPath指定的位置即src/generated/prisma.graphqlschema.graphql里的导入语句可以正常工作了。Pro tip如果你希望在每次向 Prisma 服务部署变更例如更新数据模型后自动更新Prisma database schema可以在prisma.yml中添加如下post-deploy hookhooks: post-deploy: - graphql get-schema -p prismahooks.post-deploy是prisma.yml的官方配置项详见 prisma.yml 配置参考其中演示的正是部署后下载 GraphQL schema 并触发代码生成的典型用法。Step 5实例化 Prisma binding实现 resolver 之前的最后一步是确保这些 resolver 能通过Prisma binding访问 Prisma 的 GraphQL API。做法是实例化一个 Prisma binding并把它挂到贯穿整个 resolver 链的context对象上。打开index.js添加如下代码——注意把__YOUR_PRISMA_ENDPOINT__占位符替换为你的 Prisma API 的 endpoint可在prisma.yml中找到const { GraphQLServer } require(graphql-yoga) const { Prisma } require(prisma-binding) const resolvers { Query: { posts: (_, args, context, info) { // ... }, user: (_, args, context, info) { // ... } }, Mutation: { createDraft: (_, args, context, info) { // ... }, publish: (_, args, context, info) { // ... }, deletePost: (_, args, context, info) { // ... }, signup: (_, args, context, info) { // ... } } } const server new GraphQLServer({ typeDefs: src/schema.graphql, resolvers, context: req ({ ...req, prisma: new Prisma({ typeDefs: src/generated/prisma.graphql, endpoint: __YOUR_PRISMA_ENDPOINT__, }), }), }) server.start(() console.log(GraphQL server is running on http://localhost:4000))稍后我们会为这些resolvers补上真正实现。同样记得替换__YOUR_PRISMA_ENDPOINT__占位符——这个 endpoint 定义在prisma.yml的endpoint属性中。关于Prisma构造器的可配置项可参考 Prisma Bindings API 参考除了教程中用到的typeDefsPrisma 服务 Schema 定义文件的路径与endpointPrisma 服务端点之外还支持secret服务密钥用于签发 JWT、fragmentReplacementsresolver 正常运行所必需的 GraphQL fragment 列表可选以及debug为true时把所有查询/变更打印到控制台默认false。Step 6用 Prisma bindings 实现 resolver把Prismabinding 实例挂到context之后所有 resolver 函数都能访问它并调用其 binding 函数。于是resolver 不再需要直接访问数据库而是把传入查询的执行委托delegating给 Prisma 的 GraphQL API。binding 函数提供了一套便捷的 JavaScript API 来向 GraphQL API 发送查询与变更。妙处在于你可以把info对象原样传递——它包含了客户端在查询中请求了哪些字段的信息这样 Prisma 就能非常高效地解析查询。在index.js中为 resolver 函数补上实现const resolvers { Query: { posts: (_, args, context, info) { return context.prisma.query.posts( { where: { OR: [ { title_contains: args.searchString }, { content_contains: args.searchString }, ], }, }, info, ) }, user: (_, args, context, info) { return context.prisma.query.user( { where: { id: args.id, }, }, info, ) }, }, Mutation: { createDraft: (_, args, context, info) { return context.prisma.mutation.createPost( { data: { title: args.title, content: args.content, author: { connect: { id: args.authorId, }, }, }, }, info, ) }, publish: (_, args, context, info) { return context.prisma.mutation.updatePost( { where: { id: args.id, }, data: { published: true, }, }, info, ) }, deletePost: (_, args, context, info) { return context.prisma.mutation.deletePost( { where: { id: args.id, }, }, info, ) }, signup: (_, args, context, info) { return context.prisma.mutation.createUser( { data: { name: args.name, }, }, info, ) }, }, }每个 resolver 的实现都只是一次 binding 函数的调用把操作委托给 Prisma API省去了任何手动数据库访问。可以看到几个关键模式查询委托context.prisma.query.posts({ where: {...} }, info)/context.prisma.query.user({ where: { id } }, info)通过where传递过滤条件创建 关系连接createPost的data.author.connect把新Post通过关系连接到指定User更新updatePost用where定位、用data指定新值发布草稿即把published置为true删除deletePost仅需where定位。从仓库源码看这类 binding 客户端在 cli/packages/prisma-client-lib 中实现Client.ts 的构造函数会用typeDefs构建 GraphQL Schema、基于secret签发 JWT并通过BatchedGraphQLClient带Authorization: Bearer token请求头向 endpoint 发起请求query/mutation/exists等属性则由 makePrismaClientClass.ts 工厂方法动态生成其内部把一次 binding 调用翻译成一次真实的 GraphQL HTTP 请求——这正是resolver 委托给 Prisma背后的底层机制。补充除query/mutation之外binding 还提供exists.Type(where)用于判断某类型节点是否满足条件返回布尔值以及更底层的request(query, variables)方法需要你手写完整 GraphQL 查询串详见 Prisma Bindings API 参考。Step 7启动服务器并在 Playground 中测试至此GraphQL 服务器的实现已经完成可以在 GraphQL Playground 中使用了。在终端中启动服务器node src/index.js然后在浏览器中访问http://localhost:4000打开 GraphQL Playground。Pro tip除了直接访问 URL你也可以在终端运行graphql playground命令——它会读取.graphqlconfig.yml中的信息让你并排使用两个 GraphQL API应用 API 与 Prisma API。接下来在 Playground 中依次发送下面的查询与变更来验证 API创建新用户mutation { signup(name: Alice) { id } }为某用户创建草稿把__USER_ID__替换为数据库中真实User的idmutation { createDraft( title: Join us at GraphQL Europe , content: Get a 10%-discount with this promo code on graphql-europe.org: gql-boilerplates, authorId: __USER_ID__ ) { id published } }发布草稿把__POST_ID__替换为数据库中真实Post的idmutation { publish( id: __POST_ID__, ) { id published } }按关键词过滤文章query { posts(searchString: GraphQL Europe) { id title content published author { id name } } }删除文章把__POST_ID__替换为数据库中真实Post的idmutation { deletePost( id: __POST_ID__, ) { id } }小结与延伸阅读回顾整个流程我们以一个已有 Prisma 服务为基础通过 7 个步骤搭出了一层领域特定的 GraphQL 服务器——更新数据模型 → 搭建graphql-yoga项目 → 定义应用 Schema → 用 GraphQL CLI 下载 Prisma database schema → 实例化 Prisma binding 挂到context→ 用一行行委托式 resolver 连接两层 API → 在 Playground 中验证增删改查。这套Prisma 只管数据库 CRUD、上层服务器专注业务领域的分层架构正是 Prisma 在 GraphQL 后端开发中的典型落地方式。想进一步深入可以在本仓库中继续阅读Prisma Bindings 概览binding 的设计动机、工作流程与示例Prisma Bindings API构造器参数、query/mutation/exists/request的完整用法Prisma Bindings 代码生成动态 binding 与静态代码生成binding 的取舍prisma.yml 配置参考endpoint、secret、hooks、subscriptions、seed等配置项的完整说明Prisma 客户端源码binding/client 底层如何用BatchedGraphQLClient发送请求、如何基于secret签发 JWT。赞分享后端数据库GraphQL【免费下载链接】prisma1 Database Tools incl. ORM, Migrations and Admin UI (Postgres, MySQL MongoDB) [deprecated]项目地址https://gitcode.com/gh_mirrors/pr/prisma1点击查看免费下载相关推荐open-code-review 内置 Bicep 审查规则详解面向 Azure IaC 的静态安全与质量审查清单open code review 内置 Bicep 审查规则详解面向 Azure IaC 的静态安全与质量审查清单 本文围绕 open code review后端数据库GraphQL基于 Prisma 服务构建 GraphQL 服务器使用 graphql-yoga 与 prisma-binding 的完整实战基于 Prisma 服务构建 GraphQL 服务器使用 graphql yoga 与 prisma binding 的完整实战 本文是一篇完整的实战指南以后端数据库GraphQLPrisma Bindings 实战指南用 prisma-binding 构建基于 Prisma 服务的 GraphQL 服务器Prisma Bindings 实战指南用 prisma binding 构建基于 Prisma 服务的 GraphQL 服务器 本篇指南围绕 prisma后端数据库GraphQL创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门