资讯动态

在 Node 脚本中通过 Prisma Bindings 访问 Prisma 服务:从零搭建可运行的查询与变更客户端

发布时间:2026/9/23 9:05:01 来源:尧图企业网站定制
在 Node 脚本中通过 Prisma Bindings 访问 Prisma 服务从零搭建可运行的查询与变更客户端【免费下载链接】prisma1 Database Tools incl. ORM, Migrations and Admin UI (Postgres, MySQL MongoDB) [deprecated]项目地址: https://gitcode.com/gh_mirrors/pr/prisma1本篇技术指南讲解如何在一个普通 Node.js 脚本中借助 Prisma Bindings 生成的高层 JavaScript API 访问已经部署好的 Prisma 服务你将掌握更新数据模型、下载 Prisma 数据库 schema、实例化Prismabinding、发送 queries/mutations、使用exists检查节点存在性以及通过request发送原始 GraphQL 操作等完整实战技能并理解其底层实现机制。前置准备一个正在运行的 Prisma 服务本教程假设你已经拥有一个正在运行的 Prisma 服务并已记录下它的endpoint即 GraphQL API 的访问地址。Prisma 服务的 endpoint 通常存放在服务根目录下的prisma.yml配置文件中。如果你还没有自己的 Prisma 服务可以按以下教程先完成部署以下为仓库中 1.12 版本对应的完整操作指南在 Demo 服务器上设置 Prisma使用新的 MySQL 数据库设置 Prisma使用新的 Postgres 数据库设置 Prisma连接空 MySQL 数据库设置 Prisma连接空 Postgres 数据库设置 Prisma提示本教程中所有要求执行的操作都带有步骤编号。如果只想快速上手、不关心原理细节可以直接按步骤编号逐个执行命令。Step 1更新数据模型为了让后续步骤拥有合适的数据结构需要先确保现有 Prisma 服务的数据模型包含User和Post两个类型及其一对多关系。1.1 修改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! }这里有几个关键的数据模型要素id: ID! unique每个类型的主键字段unique指令确保其值全局唯一posts: [Post!]!与author: User!定义了User与Post之间的一对多关系Prisma 会在生成的 API 中自动暴露相应的关联查询与嵌套变更published: Boolean! default(value: false)带默认值的标量字段创建节点时若不显式传入则自动取false。1.2 重新部署服务保存文件后打开终端进入 Prisma 服务的根目录即存放prisma.yml的目录执行prisma deploy部署成功后Prisma 服务的 GraphQL API 就会针对数据模型中的User和Post类型暴露完整的 CRUD 操作增删改查、批量操作、聚合计数等并允许对它们之间的关系进行读写与连接connect/disconnect/create等嵌套操作。Step 2搭建项目目录接下来为 Node 脚本创建独立的项目目录结构。2.1 初始化项目打开终端进入一个新目录依次粘贴执行以下命令mkdir -p my-node-script/src touch my-node-script/src/index.js cd my-node-script yarn init -y2.2 将 Prisma 服务移入项目把 Prisma 服务的根目录移入my-node-script并重命名为prismacd .. mkdir my-node-script/prisma mv datamodel.graphql prisma.yml my-node-script/prisma cd my-node-script此时目录结构应如下所示. └── my-node-script ├── package.json ├── prisma │ ├── datamodel.graphql │ └── prisma.yml └── src └── index.js2.3 安装依赖安装prisma-bindingPrisma binding 库本体以及graphqlGraphQL 运行时binding 内部依赖它解析 schemayarn add prisma-binding graphqlStep 3下载 Prisma 数据库 schema下一步是把 Prisma GraphQL API 的 schema即Prisma database schema下载到项目中供 Prisma binding 实例引用。这一步借助 GraphQL CLI 与 GraphQL Config 完成。3.1 安装 GraphQL CLIyarn global add graphql-cli3.2 创建.graphqlconfig.yml在服务器项目根目录即my-node-script目录创建配置文件touch .graphqlconfig.yml写入如下内容将 Prisma 的 GraphQL API 定义为一个projectprojects: prisma: schemaPath: src/generated/prisma.graphql extensions: prisma: prisma/prisma.yml参数说明projects.prisma项目名称后续graphql get-schema -p prisma中的-p参数即指向它schemaPathschema 下载后的保存位置即src/generated/prisma.graphqlextensions.prisma指向prisma/prisma.ymlGraphQL CLI 据此读取 endpoint、secret 等连接信息。该文件的信息同时被 GraphQL CLI 与 GraphQL Playground 使用是打通「schema 下载」「Playground 调试」「binding 实例化」三个环节的枢纽。3.3 下载 schema执行graphql get-schemaPrisma database schema 随即被下载到schemaPath指定的位置src/generated/prisma.graphql。这份 schema 完整定义了针对你数据库的 CRUD API包括Queryusers、posts、节点查询等、MutationcreateUser、createPost、updatePost、deleteManyPosts等以及对应的输入类型与过滤器类型。3.4进阶部署后自动刷新 schema如果希望每次prisma deploy后 schema 都自动重新下载可以在prisma.yml中增加如下post-deploy hookhooks字段的完整定义见 prisma.yml YAML 结构参考hooks: post-deploy: - graphql get-schema -p prisma从本仓库源码来看deploy 命令确实会在部署流程末尾执行post-deploy钩子在 deploy.ts 中命令通过this.definition.getHooks(post-deploy)读取钩子列表并逐个执行且可用--skip-hooks标志关闭对应 flags 定义见 deploy.ts。这意味着上述 hook 会在每次部署后自动运行graphql get-schema -p prisma保证src/generated/prisma.graphql始终与最新数据模型一致。Step 4发送 queries 和 mutations现在开始用 Prisma binding 与 Prisma 服务通信。4.1 实例化 Prisma bindingPrisma binding 实例相当于 Prisma 服务的「JavaScript SDK」。实例化时需要两个关键信息typeDefs上一步下载的 Prisma database schema 路径字符串形式传入endpointPrisma API 地址即prisma/prisma.yml中存储的 endpoint。将如下代码写入src/index.jsconst { Prisma } require(prisma-binding) const prisma new Prisma({ typeDefs: src/generated/prisma.graphql, endpoint: __YOUR_PRISMA_ENDPOINT__ })⚠️重要请务必将__YOUR_PRISMA_ENDPOINT__替换为你的真实 Prisma endpoint该值存储在prisma/prisma.yml中。4.2 发送查询与变更的完整示例下面的脚本演示了完整的增删改查链路创建用户、查询用户、创建关联帖子、更新帖子、嵌套查询用户连同其帖子标题、批量删除prisma.mutation .createUser({ data: { name: Alice } }, { id name }) .then(console.log) // { id: cjhcidn31c88i0b62zp4tdemt, name: Alice } .then(() prisma.query.users(null, { id name })) .then(response { console.log(response) // [ { id: cjhcidn31c88i0b62zp4tdemt, name: Alice } ] return prisma.mutation.createPost({ data: { title: Prisma rocks!, content: Prisma rocks!, author: { connect: { id: response[0].id } } } }) }) .then(response { console.log(response) /* { id: cjhcidoo5c8af0b62kv4dtv3c, title: Prisma rocks!, content: Prisma rocks!, published: false } */ return prisma.mutation.updatePost({ where: { id: response.id }, data: { published: true } }) }) .then(console.log) /* { id: cjhcidoo5c8af0b62kv4dtv3c, title: Prisma rocks!, content: Prisma rocks!, published: true } */ .then(() prisma.query.users(null, { id posts { title } })) .then(console.log) // [ { id: cjhcidn31c88i0b62zp4tdemt, posts: [ [Object] ] } ] .then(() prisma.mutation.deleteManyPosts()) .then(console.log) // { count: 1 } .then(() prisma.mutation.deleteManyUsers()) .then(console.log) // { count: 1 }运行脚本node src/index.js4.3 底层机制binding 如何把「链式调用」变成 GraphQL 请求虽然本仓库未包含prisma-binding包自身的源码但仓库中的prisma-client-libPrisma Client 的运行时基础库实现了与之同构的「指令式链式调用」机制可用于印证 binding 的底层工作原理。以 Client.ts 为例schema 解析与构建构造时通过buildSchema(typeDefs)将传入的 schema 文本解析为可执行的GraphQLSchema绑定实例的所有可用方法都来自这张 schemaClient.ts方法自动生成buildMethods()把 schema 中Query、Mutation、Subscription根类型的字段动态挂载到客户端实例上因此prisma.mutation.createUser(...)这样的调用并不是手写的而是根据 schema 自动生成的Client.ts参数自动包装对create*开头的 mutation传入的参数会被自动包装为{ data: ... }对delete*开头以及单参数查询的字段会被自动包装为{ where: ... }这就是示例中createUser({ data: ... })与users(null, ...)这种写法的由来Client.ts指令收集与延迟执行链式调用先把每个字段fieldName、args、类型名记录为「指令」直到遇到.then()/await时才一次性拼接成完整的 GraphQL document 并通过BatchedGraphQLClient发送Client.ts响应解包服务端返回结果后extractPayload会逐层剥离操作名包装如data.createUser最终只把用户真正关心的对象/数组交给回调这也是示例中console.log直接打印出{ id, name }而不是{ createUser: {...} }的原因Client.ts。关于secret如果 Prisma 服务开启了服务端密钥prisma.yml中的secretbinding 构造时还可以传入secret选项底层会自动签发 JWT 并在Authorization: Bearer token请求头中携带见 Client.ts。Step 5检查特定节点是否存在除了query与mutationPrisma binding 还提供一个非常实用的属性exists用于判断数据库中是否存在满足特定过滤条件的节点。exists会为数据模型中的每个类型暴露一个同名的函数——在本教程的数据模型下即prisma.exists.User(filter)与prisma.exists.Post(filter)。这些函数接收过滤参数始终返回true或false。5.1 使用exists的完整示例将src/index.js的内容替换为const { Prisma } require(prisma-binding) const prisma new Prisma({ typeDefs: src/generated/prisma.graphql, endpoint: __YOUR_PRISMA_ENDPOINT__ }) prisma.mutation .createUser({ data: { name: Alice } }) .then(response { return prisma.mutation.createPost({ data: { title: Prisma rocks!, content: Prisma rocks!, author: { connect: { id: response.id } } } }) }) .then(() prisma.exists.User({ name: Alice })) .then(response console.log(response)) // true .then(() prisma.exists.Post({ title: Prisma rocks })) .then(response console.log(response)) // true .then(() prisma.mutation.deleteManyPosts()) .then(() prisma.mutation.deleteManyUsers()) .then(() prisma.exists.Post({ title: Prisma rocks })) .then(response console.log(response)) // false .then(() prisma.exists.User({ name: Alice })) .then(console.log) // false⚠️重要同样记得替换__YOUR_PRISMA_ENDPOINT__。运行node src/index.js输出应依次为true、true数据存在时删除后再次检查则输出false、false。5.2 底层实现exists是「查询 判空」从 Client.ts 的buildExists()实现可以看到exists并不是一次新的 GraphQL 操作类型而是复用现有查询能力它从 schema 的Query根类型中读取每个模型对应的复数查询字段如users、posts及其过滤输入类型getTypesAndWhere为每个类型生成lowercaseName(args)函数该函数内部执行thispluralFieldName即一次带where过滤的列表查询然后判断返回数组length 0[firstLetterLowercaseTypeName]: args { return thispluralFieldName.then(res { return res.length 0 }) }因此prisma.exists.User({ name: Alice })本质上等价于「查询所有 name 为 Alice 的用户并判断结果是否非空」。这也是为什么exists是异步的返回 Promise需要配合.then()或await使用。Step 6发送原始 queries 和 mutationsPrisma binding 还允许通过request属性以字符串形式向 Prisma 服务发送完整的查询/变更。这种方式更为「啰嗦」——你必须完整拼写出整个操作且响应会多一层开销顶层会包含操作名作为键例如{ createUser: {...} }。Prisma binding 的request底层使用graphql-request因此拥有与graphql-request完全一致的 APIrequest(query, variables)。6.1 使用request的完整示例将src/index.js的内容替换为const { Prisma } require(prisma-binding) const prisma new Prisma({ typeDefs: src/generated/prisma.graphql, endpoint: __YOUR_PRISMA_ENDPOINT__ }) const query { users { id name } } const mutation mutation CreateUser($name: String!) { createUser(data: { name: $name }) { id name } } const variables { name: Bob } prisma.mutation .createUser({ data: { name: Alice } }, { id name }) .then(console.log) // { id: cjhcijh30cgww0b622rwkkvbo, name: Alice } .then(() prisma.request(mutation, variables)) .then(console.log) // { createUser: { id: cjhcijjndch0d0b62qux6o52a, name: Bob } } .then(() prisma.query.users(null, { id name })) .then(console.log) /* [ { id: cjhciiacxcf850b62mcuaa3uz, name: Alice }, { id: cjhcijjndch0d0b62qux6o52a, name: Bob } ] */ .then(() prisma.request(query)) .then(console.log) /* { users: [ { id: cjhciiacxcf850b62mcuaa3uz, name: Alice }, { id: cjhcijjndch0d0b62qux6o52a, name: Bob } ] } */运行node src/index.js6.2 何时选择request而不是链式 API从上面的输出对比可以清楚看到两种方式的差异特性链式 APIprisma.query/prisma.mutationprisma.request(query, variables)调用形式对象方法链字段选择用字符串片段手写完整 GraphQL 文档字符串变量传递通过方法的第二个参数选择集或直接传参通过第二个参数variables传入响应结构已剥离操作名直接返回数据本体返回结果带操作名顶层键如{ users: [...] }适用场景日常 CRUD代码简洁、类型友好复用现成 GraphQL 字符串、动态拼接操作、或对齐graphql-request生态延伸用 codegen 生成类型安全的 Binding如果项目使用 TypeScript/JavaScript 并希望获得类型提示prisma-binding还提供内置的generator CLI可根据已下载的 schema 直接生成 binding 代码详见 Code generation (Codegen)。其核心用法prisma-binding -i [input] -l [language] -b [outputBinding] Options: --input, -i Path to prisma.graphql file [string] [required] --language, -l typescript | javascript [string] [required] --outputBinding, -b Output binding, e.g. binding.ts [string] [required]它也支持通过.graphqlconfig.yml的extensions.codegen配置驱动例如projects: myapp: schemaPath: src/generated/prisma.graphql extensions: prisma: prisma/prisma.yml codegen: - generator: prisma-binding language: typescript output: binding: src/generated/prisma.ts配合prisma.yml中的 post-deploy hookgraphql get-schema与graphql codegen按序执行即可实现「改数据模型 → 部署 → schema 与 binding 同步再生成」的自动化工作流与本教程手动三步部署、下载 schema、实例化 binding形成从简到繁的完整演进路径。总结通过本教程你已经掌握了在 Node 脚本中访问 Prisma 服务的完整链路更新数据模型并用prisma deploy同步 GraphQL API搭建项目目录并把 Prisma 服务并入脚本项目用 GraphQL CLI 下载 Prisma database schema到src/generated/prisma.graphql并可用 post-deploy hook 实现自动刷新实例化PrismabindingtypeDefsendpoint通过prisma.query/prisma.mutation发送类型安全、返回简洁的查询与变更用exists判断节点是否存在底层即「带 where 的列表查询 判空」用request发送原始 GraphQL 字符串兼容graphql-request的 API 与响应结构。配合 codegen 生成类型安全的 binding 代码Prisma binding 足以作为日常服务端脚本、数据迁移脚本与 GraphQL 服务开发中的通用数据访问层。本仓库中 prisma-client-lib 的运行时实现为理解 binding 的「链式调用→GraphQL 文档→响应解包」机制提供了同构的参考实现值得进一步阅读。【免费下载链接】prisma1 Database Tools incl. ORM, Migrations and Admin UI (Postgres, MySQL MongoDB) [deprecated]项目地址: https://gitcode.com/gh_mirrors/pr/prisma1创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价