使用 Refine 集成 Nestjs-Query GraphQL Data Provider:从零构建可扩展的 CRUD 应用 📅 发布时间:2026/9/12 10:06:21 👁 浏览次数: 使用 Refine 集成 Nestjs-Query GraphQL Data Provider从零构建可扩展的 CRUD 应用【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refine本指南以># 方式一使用 create-refine-app 直接拉取示例 npm create refine-applatest -- --example>import dataProvider, { GraphQLClient, liveProvider } from refinedev/nestjs-query; import { createClient } from graphql-ws; const API_URL https://api.nestjs-query.refine.dev/graphql; const WS_URL wss://api.nestjs-query.refine.dev/graphql; const client new GraphQLClient(API_URL); const gqlDataProvider dataProvider(client); // 在 Refine 中 // dataProvider{gqlDataProvider} // liveProvider{liveProvider(createClient({ url: WS_URL }))}要点拆解GraphQLClient负责 HTTP 层示例指向托管在api.nestjs-query.refine.dev的公共演示 API你将GraphQLClient实例传入dataProvider(client)即完成数据层装配liveProvider负责实时层它接收一个graphql-ws的ClientcreateClient({ url: WS_URL })用于建立 WebSocket 连接并订阅变更事件options.liveMode: auto开启自动实时模式配合实时订阅的数据操作会自动刷新syncWithLocation与warnWhenUnsavedChanges分别控制路由同步与未保存更改提醒。资源resources与路由的映射同样在入口完成示例注册了blog_posts与categories两个资源并为每个资源绑定 list/create/edit/show 路由例如blog_posts的详情路由为/blog_posts/show/:id由 show.tsx 渲染。组织 GraphQL 文档与生成类型Nestjs-Query 的 Data Provider 并不依赖运行时的 schema introspection而是要求你把业务查询写成 GraphQL 文档通常用graphql-tag的gql模板标签并通过meta传入。示例把所有文档集中在各资源的queries.ts中例如 posts/queries.tsimport gql from graphql-tag; export const POSTS_LIST_QUERY gql query BlogPostsList( $paging: OffsetPaging! $filter: BlogPostFilter $sorting: [BlogPostSort!]! ) { blogPosts(paging: $paging, filter: $filter, sorting: $sorting) { nodes { id title category { title } content createdAt } totalCount } } ; export const POST_CREATE_MUTATION gql mutation PostCreate($input: CreateOneBlogPostInput!) { createOneBlogPost(input: $input) { id title status category { id } content } } ;值得注意的约定列表查询必须声明paging、filter、sorting三个参数并返回nodes与totalCount——这是 Data Provider 实现分页、筛选与排序的契约其中$paging: OffsetPaging!采用偏移分页变更统一使用$input参数创建用CreateOneXxxInput!更新用UpdateOneXxxInput!与 Nestjs-Query 服务端约定一一对应查询字段决定列表/表单能访问的字段Data Provider 据此推断出带类型的安全数据形状。用 GraphQL Codegen 保持类型同步手写类型既不安全也不可持续示例通过 graphql.config.ts 接入 GraphQL Codegen直接以远端 schema 为源生成类型const config: IGraphQLConfig { schema: https://api.nestjs-query.refine.dev/graphql, extensions: { codegen: { generates: { src/graphql/schema.types.ts: { plugins: [typescript], config: { skipTypename: true, enumsAsTypes: true }, }, src/graphql/types.ts: { preset: import-types, documents: [src/**/*.{ts,tsx}], plugins: [typescript-operations], config: { preResolveTypes: false, useTypeImports: true }, }, }, }, }, };运行npm run codegen后src/graphql/schema.types.ts整个 GraphQL schema 的 TypeScript 定义枚举以enumsAsTypes生成src/graphql/types.ts针对src/**/*.{ts,tsx}中所有 GraphQL 文档生成的 operation 类型如BlogPostsListQuery、PostCreateMutation并由import-typespreset 引用 schema 类型避免重复。页面代码中大量出现的import type { BlogPostsListQuery } from graphql/types与GetFieldsFromListBlogPostsListQuery类型工具正是 Codegen 与 Data Provider 类型推导协同工作的结果前端数据结构一旦与后端 schema 脱节编译期就会报错。列表页实战useTable 与 meta.gqlQuery列表页是 Data Provider 能力的集中体现参见 posts/list.tsxconst { tableProps, filters, sorters } useTableIPost({ meta: { gqlQuery: POSTS_LIST_QUERY, }, sorters: { initial: [{ field: id, order: desc }], }, });关键机制meta.gqlQuery指定列表查询文档useTable触发getList时Data Provider 会把 Refine 当前的分页current/pageSize、排序sorters与筛选filters状态翻译成 Nestjs-Query 的paging、sorting、filter变量服务端排序表格列通过sorter{{ multiple: 1 }}与getDefaultSortOrder(id, sorters)把 UI 排序状态回传给useTable再由 Data Provider 序列化为 GraphQLsorting参数服务端筛选categoryId列使用FilterDropdown包裹一个多选Select配合getDefaultFilter(categoryId, filters, in)声明IN语义的筛选条件下拉选项来自useSelectconst { selectProps } useSelectGetFieldsFromListCategoriesSelectQuery({ resource: categories, meta: { gqlQuery: CATEGORIES_SELECT_QUERY }, pagination: { mode: server }, });useSelect同样通过meta.gqlQuery消费 CATEGORIES_SELECT_QUERY并以服务端分页模式加载选项——这意味着即使分类数量很大也只在需要时请求对应分页数据不会一次性拉全量。创建、编辑与详情页gqlMutation 与 gqlShow创建页posts/create.tsx 使用useForm并把创建变更挂在meta.gqlMutation上const { formProps, saveButtonProps } useFormGetFieldsPostCreateMutation({ meta: { gqlMutation: POST_CREATE_MUTATION }, });表单字段title、status、categoryId、content与 antdForm.Item的name一一对应提交时useForm调用 Data Provider 的create方法将表单值打包为$input执行createOneBlogPost变更。status使用Select枚举DRAFT/PUBLISHED/REJECTEDcontent则用uiw/react-md-editor提供 Markdown 编辑体验。编辑页posts/edit.tsx 的形态与创建页对称useForm同时接收meta.gqlMutationPOST_EDIT_MUTATION进入页面时先自动执行getOne回填表单提交时执行updateOneBlogPost。头部额外挂了ListButton返回列表与RefreshButton调用queryResult?.refetch()刷新详情。详情页posts/show.tsx 使用useShow并传入meta.gqlQueryPOST_SHOW_QUERYconst { query: queryResult } useShowGetFieldsPostShowQuery({ meta: { gqlQuery: POST_SHOW_QUERY }, });详情页通过useShow触发getOne渲染id、title、status、关联分类category.title并用MarkdownField渲染 Markdown 格式的content——即便内容带复杂排版也能安全展示。分类资源验证同一模式的可复用性分类模块categories/queries.ts以完全相同的方式工作CATEGORIES_LIST_QUERY同样声明paging/filter/sorting并返回nodestotalCount创建与编辑分别对应createOneCategory/updateOneCategory。这说明 Nestjs-Query Data Provider 是契约驱动的只要后端遵循分页 过滤 排序 单对象变更的规范前端接入成本就是写一段 GraphQL 文档 挂一个 meta这么简单。底层原理Data Provider 如何基于 meta 分发操作要理解这套机制的可靠性可以深入 dataProvider 源码 观察它的执行逻辑列表查询getList方法会读取meta?.gqlQuery用gql.query解析出查询文本与变量定义paging、filter、sorting再把 Refine 的分页/排序/筛选状态映射为变量后调用client.request发起请求见 index.ts单条查询与批量查询getOne/getMany同样以meta?.gqlQuery为文档来源按约定注入id或filter变量写操作create、update、deleteOne等统一走meta?.gqlMutation ?? meta?.gqlQuery的取值逻辑见 index.ts创建/更新把$input作为变量传入删除则构造对应的 filtercustom 方法custom同时支持meta.gqlQuery与meta.gqlMutation由gql.query/gql.mutation解析后决定以 query 还是 mutation 执行见 index.ts。因此可以推断meta就是 Data Provider 与具体 GraphQL 文档之间的唯一契约面。gqlQuery用于读操作列表/详情/下拉gqlMutation用于写操作创建/编辑二者缺一不可gqlSubscription则被 liveProvider 用来订阅指定资源的变更事件——当后端通过 WebSocket 推送数据更新时Refine 会依据liveMode配置自动触发对应查询的重取从而让表格与详情页保持实时一致无需手动刷新。小结通过data-provider-nestjs-query示例可以看到Refine 集成 Nestjs-Query GraphQL 后端的完整路径是入口装配GraphQLClient dataProvider liveProvider→ 编写 GraphQL 文档并挂到 meta → Codegen 生成类型 → 用 useTable/useForm/useShow 消费。你无需为分页、排序、筛选、变更参数拼接编写任何样板代码所有协议层细节都被 Data Provider 封装换来的是可读性、类型安全与可维护性俱佳的前端数据层。若你的后端同样基于 Nestjs-Query 构建可直接复用本示例的 App.tsx 与 queries.ts 模式作为项目起点。【免费下载链接】refineA React Framework for building internal tools, admin panels, dashboards B2B apps with unmatched flexibility.项目地址: https://gitcode.com/GitHub_Trending/re/refine创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考