
Prisma 生态中的 graphql-request用最轻量的 GraphQL 客户端发送查询、认证与错误处理【免费下载链接】prisma1 Database Tools incl. ORM, Migrations and Admin UI (Postgres, MySQL MongoDB) [deprecated]项目地址: https://gitcode.com/gh_mirrors/pr/prisma1graphql-request 是 PrismaGraphcool生态中一个极简的 GraphQL 客户端专为 Node.js 与浏览器环境中的脚本和简单应用设计。本指南基于 docs/1.2/06-GraphQL-Ecosystem/06-GraphQL-Request/01-Overview.md 展开并结合 Prisma 仓库内部源码CLI 的 Client 与 Cluster 实现进行佐证帮助你从零掌握 graphql-request 的安装、两种调用方式、认证、变量、错误处理等完整用法并理解它为何成为 Prisma 工具链内部请求 GraphQL 服务的首选。graphql-request 是什么graphql-request 是一个最小化的 GraphQL 客户端它的设计目标非常明确让开发者以最少的代码量、最小的依赖体积向任意 GraphQL 端点发送 query 或 mutation。它既可以在 Node.js 环境下运行也支持浏览器非常适合编写一次性脚本如数据导入、迁移、批量任务构建简单应用的后端调用层在不需要缓存、不需要框架集成如 React/Vue的场景下替代 Apollo 或 Relay。在 Prisma 仓库中graphql-request 并非只是文档中的一个周边工具而是被真实用于 CLI 核心链路的依赖。例如 cli/packages/prisma-yml/package.json 中声明了graphql-request: ^1.5.0依赖下文会详细说明它在 Client.ts 与 Cluster.ts 中的落地用法。核心特性根据原文档graphql-request 主打以下特性最简单、最轻量的 GraphQL 客户端不内置缓存不绑定任何前端框架API 面积极小基于 Promise 的 API原生支持async/await风格编写异步代码TypeScript 支持自带类型声明开发时可以获得类型提示文档同时提到 Flow 支持coming soon。轻量不是口号而是设计取舍的结果。原文档 FAQ 中明确说明与 Apollo、Relay 相比graphql-request 没有内置缓存也没有针对前端框架的集成层目标就是把包体和 API 保持到最小。安装 graphql-request在 Node 项目中通过 npm 一键安装npm install graphql-request安装完成后即可在项目中引入使用。Prisma 仓库自身的 yarn.lockyarn.lock中也锁定并使用了该依赖说明它已被广泛用于实际工程。快速开始一行代码发送 GraphQL 查询graphql-request 最吸引人的地方在于它的极简调用方式。只需一条request函数调用即可完成一次 GraphQL 查询import { request } from graphql-request const query { Movie(title: Inception) { releaseDate actors { name } } } request(https://api.graph.cool/simple/v1/movies, query).then(data console.log(data))这里的request(endpoint, query, variables)是包导出的静态函数第一个参数是 GraphQL 端点 URL第二个参数是查询字符串第三个参数可省略是变量对象。在 Prisma 的实际使用中同样的模式被大量复用。例如 Cluster.ts 中封装了一个通用的request(query: string, variables?: any)方法见 Cluster.ts 第 267 行其内部正是基于GraphQLClient实例发起请求import { GraphQLClient } from graphql-request // ... return new GraphQLClient(cloudApiEndpoint, { headers: { Authorization: Bearer ${this.clusterSecret}, }, agent: getProxyAgent(cloudApiEndpoint), } as any)可以看到即使是在生产级 CLI 工具中graphql-request 也是开箱即用的创建客户端实例、传入 endpoint 与请求头即可发起查询。两种使用方式静态函数与客户端实例graphql-request 提供两种等价的使用方式开发者可以按场景自由选择import { request, GraphQLClient } from graphql-request // 方式一使用静态函数适合一次性请求 request(endpoint, query, variables).then(data console.log(data)) // 方式二创建 GraphQLClient 实例适合复用配置进行多次请求 const client new GraphQLClient(endpoint, { headers: {} }) client.request(query, variables).then(data console.log(data))两种方式的取舍很简单静态request无需管理实例状态适合脚本中的临时查询GraphQLClient实例可以在构造时统一配置 endpoint、headers、credentials 等选项后续所有请求自动复用适合在一个服务或模块内发起多次请求。Prisma CLI 正是采用实例化方案。在 Client.ts 中Client类持有clusterClient: GraphQLClient成员第 38 行并在initClusterClient方法中根据集群信息动态创建客户端实例this.clusterClient new GraphQLClient(cluster.getDeployEndpoint(), { headers: { ...(token { Authorization: Bearer ${token} }), }, agent, } as any)随后所有 deploy、迁移等操作都通过this.clusterClient.request(query, variables)完成避免了每次请求重复构造配置。实战示例详解通过 HTTP 请求头做认证绝大多数 GraphQL 服务使用 HTTP 头传递认证信息如 JWT。使用GraphQLClient构造选项中的headers即可import { GraphQLClient } from graphql-request const client new GraphQLClient(my-endpoint, { headers: { Authorization: Bearer my-jwt-token, }, }) const query { Movie(title: Inception) { releaseDate actors { name } } } client.request(query).then(data console.log(data))这也是 Prisma 内部的标准做法。在 Client.ts 中认证令牌通过cluster.getToken(serviceName, workspaceSlug, stageName)获取后被拼装为Authorization: Bearer token请求头第 80-85 行若首次请求因未授权失败还会触发login()手动登录流程后重建带 token 的客户端第 86-108 行这套失败自动重试认证的机制全部建立在 headers 配置之上。此外 Cluster.ts 的cloudClient第 106-113 行同样用Authorization: Bearer ${this.clusterSecret}头访问云端 API用于generateClusterToken、addServiceToCloudDBIfMissing等 mutation。向 fetch 传递更多选项GraphQLClient构造函数的第二个参数本质上是传给底层fetch的选项对象因此你可以直接透传credentials、mode等标准 fetch 选项import { GraphQLClient } from graphql-request const client new GraphQLClient(my-endpoint, { credentials: include, mode: cors, }) const query { Movie(title: Inception) { releaseDate actors { name } } } client.request(query).then(data console.log(data))credentials: include跨域请求时携带 Cookie 等凭据常用于浏览器端认证场景mode: cors显式启用跨域资源共享模式。这一透传机制在 Prisma CLI 中也被用来注入自定义的agent代理对象例如 Client.ts 中getProxyAgent(cluster.getDeployEndpoint())的结果被作为agent传入客户端构造选项从而让 CLI 在需要走代理的网络环境中也能正常访问 Prisma 服务。使用变量variables把查询参数与查询语句分离是 GraphQL 的推荐实践。graphql-request 的第三个参数就是变量对象import { request } from graphql-request const query query getMovie($title: String!) { Movie(title: $title) { releaseDate actors { name } } } const variables { title: Inception, } request(my-endpoint, query, variables).then(data console.log(data))注意变量在使用前必须在查询语句中通过$title语法声明其类型此处为非空字符串String!再以$title占位。变量对象中的键需要与声明一一对应。Prisma CLI 中的大量 mutation 都遵循这一模式。例如 Cluster.ts 中的generateClusterToken方法const query mutation ($input: GenerateClusterTokenRequest!) { generateClusterToken(input: $input) { clusterToken } } const { generateClusterToken: { clusterToken } } await this.cloudClient.request(query, { input: { workspaceSlug, clusterName: this.name, serviceName, stageName, }, })这里$input变量承载了完整的请求载荷返回值也通过解构提取展示了查询语句 变量分离在生产代码中的典型形态。错误处理当 GraphQL 服务端返回错误时graphql-request 会 reject Promise错误对象上带有response字段其中包含errors与dataimport { request } from graphql-request const wrongQuery { some random stuff } request(my-endpoint, wrongQuery) .then(data console.log(data)) .catch(err { console.log(err.response.errors) // GraphQL response errors console.log(err.response.data) // Response data if available })err.response.errorsGraphQL 服务端返回的错误数组err.response.data服务端可能返回的部分数据即使出错data 可能仍可用。这一错误结构在 Prisma CLI 中被直接依赖。在 Client.ts 的clientgetter 中捕获到异常后会检查e.response.errors[0].code是否为3015且消息包含decoded据此判断是否需要重新登录第 126-205 行随后抛出带提示信息的用户友好错误。也就是说CLI 的令牌过期自动提示重新登录能力正是基于 graphql-request 错误对象中的response.errors结构实现的。使用require代替import如果你的项目使用 CommonJS 而非 ES Module同样可以无缝使用const { request } require(graphql-request) const query { Movie(title: Inception) { releaseDate actors { name } } } request(my-endpoint, query).then(data console.log(data))Node 环境下的 Cookie 支持graphql-request 依赖全局fetch发起请求。在 Node 中若需要 Cookie 支持可以搭配fetch-cookie与node-fetch实现npm install fetch-cookie/node-fetchimport { GraphQLClient } from graphql-request // 使用这一行来启用 Cookie 支持 global[fetch] require(fetch-cookie/node-fetch)(require(node-fetch)) const client new GraphQLClient(my-endpoint) const query { Movie(title: Inception) { releaseDate actors { name } } } client.request(query).then(data console.log(data))原理是graphql-request 在浏览器中直接使用原生fetch而在 Node 环境中则读取全局fetch通过把fetch-cookie包装后的node-fetch挂到global[fetch]上即可让所有请求自动携带并维护 Cookie例如基于 session 的认证场景。更多示例原文档预告原文档还预告了以下进阶用法仓库内未展开可作为继续深入的方向Fragments在查询中使用 GraphQL fragment 复用字段片段结合graphql-tag用模板标签语法书写并解析查询TypeScript 返回类型为请求结果声明类型获得类型安全的返回值Prisma 内部已实际使用见下文。graphql-request 在 Prisma 源码中的实战印证为了让读者看到 graphql-request 在真实工程中的落地方式这里汇总本仓库中的几处关键使用点位置用途cli/packages/prisma-yml/package.json声明graphql-request: ^1.5.0依赖cli/packages/prisma-yml/src/Cluster.tscloudClient创建带 Bearer 认证头的客户端封装request(query, variables)统一入口执行generateClusterToken、addServiceToCloudDBIfMissing等管理 mutationcli/packages/prisma-cli-engine/src/Client/Client.tsinitClusterClient动态创建指向集群 deploy endpoint 的客户端introspect方法通过client.request(introspectionQuery)拉取服务端 introspection schema第 232-253 行cli/packages/prisma-db-introspection/src/databases/prisma/prismaDBClient.ts同样基于GraphQLClient向 Prisma 服务发起 introspection 与 schema 相关请求其中有一个值得关注的细节Prisma CLI 的 introspection内省功能直接复用了 graphql-request 的request方法见 Client.ts 第 252 行将 GraphQL 的 introspection 查询语句作为普通 query 发送从而在不引入额外客户端库的前提下获得服务端完整 schema。这恰好印证了文档简单、轻量、开箱即用的定位——复杂如 schema 拉取也不过是一次普通请求。FAQgraphql-request 与主流客户端的定位差异与 Apollo、Relay 的区别是什么graphql-request 是目前最精简、最容易上手的 GraphQL 客户端非常适合小脚本或简单应用。相比之下Apollo / Relay提供了内置缓存、前端框架集成React 等、订阅管理等重型能力graphql-request刻意不包含这些没有内置缓存没有框架集成目标是让包体与 API 面保持在最小。如果你的应用只是发个查询拿个数据graphql-request 足够如果应用需要复杂的状态管理、缓存失效策略或框架级集成才需要考虑 Apollo 或 Relay。与 Lokka 相比如何Lokka 同样是一个轻量方案但要发送一条简单的 GraphQL 查询仍需额外配置 transport如 [lokka-transport-http] 一类的设置代码。graphql-request 相比 Lokka 做的工作更少但使用起来简单得多——无需配置 transport直接调用即可。结语graphql-request 用最小的 API 面解决了向 GraphQL 端点发请求这一核心问题静态request函数应付临时查询GraphQLClient实例承载可复用的端点与请求头配置变量、错误处理、Cookie 等常见需求均有简洁的解决方案。从 Prisma 仓库内部看它不仅是文档中的推荐工具更是 CLI 集群管理、deploy、introspection 等核心链路的真实基础设施——理解了本文的用法你也就读懂了 Prisma 工具链与 GraphQL 服务交互的底层方式。【免费下载链接】prisma1 Database Tools incl. ORM, Migrations and Admin UI (Postgres, MySQL MongoDB) [deprecated]项目地址: https://gitcode.com/gh_mirrors/pr/prisma1创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考