diff --git a/.changeset/yellow-pianos-play.md b/.changeset/yellow-pianos-play.md
new file mode 100644
index 000000000000..8f542ad8454c
--- /dev/null
+++ b/.changeset/yellow-pianos-play.md
@@ -0,0 +1,5 @@
+---
+"@refinedev/graphql": patch
+---
+
+Enhanced the GraphQL error handling by throwing GraphQL errors
diff --git a/examples/data-provider-graphql/.gitignore b/examples/data-provider-graphql/.gitignore
new file mode 100644
index 000000000000..4d29575de804
--- /dev/null
+++ b/examples/data-provider-graphql/.gitignore
@@ -0,0 +1,23 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+# dependencies
+/node_modules
+/.pnp
+.pnp.js
+
+# testing
+/coverage
+
+# production
+/build
+
+# misc
+.DS_Store
+.env.local
+.env.development.local
+.env.test.local
+.env.production.local
+
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
diff --git a/examples/data-provider-graphql/README.md b/examples/data-provider-graphql/README.md
new file mode 100644
index 000000000000..fd57950234ca
--- /dev/null
+++ b/examples/data-provider-graphql/README.md
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+Build your React -based CRUD applications, without constraints. An open source, headless web application framework developed with flexibility in mind.
+
+
+
+
+[![Discord](https://img.shields.io/discord/837692625737613362.svg?label=&logo=discord&logoColor=ffffff&color=7389D8&labelColor=6A7EC2)](https://discord.gg/refine)
+[![Twitter Follow](https://img.shields.io/twitter/follow/refine_dev?style=social)](https://twitter.com/refine_dev)
+
+
+
+
+
+## Try this example on your local
+
+```bash
+npm create refine-app@latest -- --example data-provider-nestjs-query
+```
+
+## Try this example on CodeSandbox
+
+
+
+[![Open data-provider-nestjs-query example from refine](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/embed/github/refinedev/refine/tree/master/examples/data-provider-nestjs-query?view=preview&theme=dark&codemirror=1)
diff --git a/examples/data-provider-graphql/graphql.config.ts b/examples/data-provider-graphql/graphql.config.ts
new file mode 100644
index 000000000000..f58d3b7bde8e
--- /dev/null
+++ b/examples/data-provider-graphql/graphql.config.ts
@@ -0,0 +1,37 @@
+import type { IGraphQLConfig } from "graphql-config";
+
+const config: IGraphQLConfig = {
+ schema: "https://api.nestjs-query.refine.dev/graphql",
+ extensions: {
+ codegen: {
+ hooks: {
+ afterOneFileWrite: ["eslint --fix", "prettier --write"],
+ },
+ 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: {
+ skipTypename: true,
+ enumsAsTypes: true,
+ preResolveTypes: false,
+ useTypeImports: true,
+ },
+ presetConfig: {
+ typesPath: "./schema.types",
+ },
+ },
+ },
+ },
+ },
+};
+
+export default config;
diff --git a/examples/data-provider-graphql/index.html b/examples/data-provider-graphql/index.html
new file mode 100644
index 000000000000..c0fec4cb9c5a
--- /dev/null
+++ b/examples/data-provider-graphql/index.html
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+ refine Nestjs-Query example
+
+
+ You need to enable JavaScript to run this app.
+
+
+
+
diff --git a/examples/data-provider-graphql/package.json b/examples/data-provider-graphql/package.json
new file mode 100644
index 000000000000..fe2df9871387
--- /dev/null
+++ b/examples/data-provider-graphql/package.json
@@ -0,0 +1,51 @@
+{
+ "name": "data-provider-graphql",
+ "version": "1.0.0",
+ "private": true,
+ "type": "module",
+ "scripts": {
+ "build": "tsc && refine build",
+ "codegen": "graphql-codegen",
+ "dev": "refine dev",
+ "refine": "refine",
+ "start": "refine start"
+ },
+ "browserslist": {
+ "production": [
+ ">0.2%",
+ "not dead",
+ "not op_mini all"
+ ],
+ "development": [
+ "last 1 chrome version",
+ "last 1 firefox version",
+ "last 1 safari version"
+ ]
+ },
+ "dependencies": {
+ "@refinedev/antd": "^5.44.0",
+ "@refinedev/cli": "^2.16.39",
+ "@refinedev/core": "^4.56.0",
+ "@refinedev/graphql": "workspace:^",
+ "@refinedev/react-router-v6": "^4.6.0",
+ "@uiw/react-md-editor": "^3.19.5",
+ "antd": "^5.17.0",
+ "graphql-ws": "^5.9.1",
+ "react": "^18.0.0",
+ "react-dom": "^18.0.0",
+ "react-router-dom": "^6.8.1",
+ "urql": "^4.2.1"
+ },
+ "devDependencies": {
+ "@graphql-codegen/cli": "^5.0.0",
+ "@graphql-codegen/import-types-preset": "^3.0.0",
+ "@graphql-codegen/typescript": "^4.0.1",
+ "@graphql-codegen/typescript-operations": "^4.0.1",
+ "@types/node": "^18.16.2",
+ "@types/react": "^18.0.0",
+ "@types/react-dom": "^18.0.0",
+ "@vitejs/plugin-react": "^4.2.1",
+ "typescript": "^5.4.2",
+ "vite": "^5.1.6"
+ }
+}
diff --git a/examples/data-provider-graphql/public/favicon.ico b/examples/data-provider-graphql/public/favicon.ico
new file mode 100644
index 000000000000..a3df394d64c7
Binary files /dev/null and b/examples/data-provider-graphql/public/favicon.ico differ
diff --git a/examples/data-provider-graphql/public/manifest.json b/examples/data-provider-graphql/public/manifest.json
new file mode 100644
index 000000000000..04b4dc65e5eb
--- /dev/null
+++ b/examples/data-provider-graphql/public/manifest.json
@@ -0,0 +1,15 @@
+{
+ "short_name": "refine hasura example",
+ "name": "refine hasura example",
+ "icons": [
+ {
+ "src": "favicon.ico",
+ "sizes": "64x64 32x32 24x24 16x16",
+ "type": "image/x-icon"
+ }
+ ],
+ "start_url": ".",
+ "display": "standalone",
+ "theme_color": "#000000",
+ "background_color": "#ffffff"
+}
diff --git a/examples/data-provider-graphql/public/refine.svg b/examples/data-provider-graphql/public/refine.svg
new file mode 100644
index 000000000000..2eb16e9edeb5
--- /dev/null
+++ b/examples/data-provider-graphql/public/refine.svg
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/examples/data-provider-graphql/src/App.tsx b/examples/data-provider-graphql/src/App.tsx
new file mode 100644
index 000000000000..07f81fafe2a0
--- /dev/null
+++ b/examples/data-provider-graphql/src/App.tsx
@@ -0,0 +1,102 @@
+import { GitHubBanner, Refine } from "@refinedev/core";
+import {
+ useNotificationProvider,
+ ThemedLayoutV2,
+ ErrorComponent,
+ RefineThemes,
+} from "@refinedev/antd";
+import { Client, fetchExchange } from "urql";
+import createDataProvider, { createLiveProvider } from "@refinedev/graphql";
+import { createClient } from "graphql-ws";
+import routerProvider, {
+ NavigateToResource,
+ UnsavedChangesNotifier,
+ DocumentTitleHandler,
+} from "@refinedev/react-router-v6";
+import { BrowserRouter, Routes, Route, Outlet } from "react-router-dom";
+
+import "@refinedev/antd/dist/reset.css";
+
+import { PostList, PostCreate, PostEdit, PostShow } from "./pages/posts";
+import { CategoryList, CategoryCreate, CategoryEdit } from "./pages/categories";
+import { ConfigProvider, App as AntdApp } from "antd";
+
+const API_URL = "https://api.nestjs-query.refine.dev/graphql";
+const WS_URL = "wss://api.nestjs-query.refine.dev/graphql";
+
+export const client = new Client({
+ url: API_URL,
+ exchanges: [fetchExchange],
+});
+
+const App: React.FC = () => {
+ return (
+
+
+
+
+
+
+
+
+
+ }
+ >
+ }
+ />
+
+
+ } />
+ } />
+ } />
+ } />
+
+
+
+ } />
+ } />
+ } />
+
+
+ } />
+
+
+
+
+
+
+
+
+ );
+};
+
+export default App;
diff --git a/examples/data-provider-graphql/src/graphql/schema.types.ts b/examples/data-provider-graphql/src/graphql/schema.types.ts
new file mode 100644
index 000000000000..a0d2405b48ad
--- /dev/null
+++ b/examples/data-provider-graphql/src/graphql/schema.types.ts
@@ -0,0 +1,665 @@
+export type Maybe = T | null;
+export type InputMaybe = Maybe;
+export type Exact = {
+ [K in keyof T]: T[K];
+};
+export type MakeOptional = Omit & {
+ [SubKey in K]?: Maybe;
+};
+export type MakeMaybe = Omit & {
+ [SubKey in K]: Maybe;
+};
+export type MakeEmpty<
+ T extends { [key: string]: unknown },
+ K extends keyof T,
+> = { [_ in K]?: never };
+export type Incremental =
+ | T
+ | {
+ [P in keyof T]?: P extends " $fragmentName" | "__typename" ? T[P] : never;
+ };
+/** All built-in and custom scalars, mapped to their actual values */
+export type Scalars = {
+ ID: { input: string; output: string };
+ String: { input: string; output: string };
+ Boolean: { input: boolean; output: boolean };
+ Int: { input: number; output: number };
+ Float: { input: number; output: number };
+ DateTime: { input: any; output: any };
+};
+
+export type BlogPost = {
+ category: Category;
+ categoryId: Scalars["ID"]["output"];
+ content: Scalars["String"]["output"];
+ createdAt: Scalars["DateTime"]["output"];
+ id: Scalars["ID"]["output"];
+ status: PostStatus;
+ title: Scalars["String"]["output"];
+ updatedAt: Scalars["DateTime"]["output"];
+};
+
+export type BlogPostAggregateFilter = {
+ and?: InputMaybe>;
+ categoryId?: InputMaybe;
+ content?: InputMaybe;
+ createdAt?: InputMaybe;
+ id?: InputMaybe;
+ or?: InputMaybe>;
+ status?: InputMaybe;
+ title?: InputMaybe;
+ updatedAt?: InputMaybe;
+};
+
+export type BlogPostAggregateGroupBy = {
+ categoryId?: Maybe;
+ content?: Maybe;
+ createdAt?: Maybe;
+ id?: Maybe;
+ status?: Maybe;
+ title?: Maybe;
+ updatedAt?: Maybe;
+};
+
+export type BlogPostAggregateGroupByCreatedAtArgs = {
+ by?: GroupBy;
+};
+
+export type BlogPostAggregateGroupByUpdatedAtArgs = {
+ by?: GroupBy;
+};
+
+export type BlogPostAggregateResponse = {
+ avg?: Maybe;
+ count?: Maybe;
+ groupBy?: Maybe;
+ max?: Maybe;
+ min?: Maybe;
+ sum?: Maybe;
+};
+
+export type BlogPostAvgAggregate = {
+ categoryId?: Maybe;
+ id?: Maybe;
+};
+
+export type BlogPostConnection = {
+ /** Array of nodes. */
+ nodes: Array;
+ /** Paging information */
+ pageInfo: OffsetPageInfo;
+ /** Fetch total count of records */
+ totalCount: Scalars["Int"]["output"];
+};
+
+export type BlogPostCountAggregate = {
+ categoryId?: Maybe;
+ content?: Maybe;
+ createdAt?: Maybe;
+ id?: Maybe;
+ status?: Maybe;
+ title?: Maybe;
+ updatedAt?: Maybe;
+};
+
+export type BlogPostDeleteFilter = {
+ and?: InputMaybe>;
+ categoryId?: InputMaybe;
+ content?: InputMaybe;
+ createdAt?: InputMaybe;
+ id?: InputMaybe;
+ or?: InputMaybe>;
+ status?: InputMaybe;
+ title?: InputMaybe;
+ updatedAt?: InputMaybe;
+};
+
+export type BlogPostDeleteResponse = {
+ categoryId?: Maybe;
+ content?: Maybe;
+ createdAt?: Maybe;
+ id?: Maybe;
+ status?: Maybe;
+ title?: Maybe;
+ updatedAt?: Maybe;
+};
+
+export type BlogPostFilter = {
+ and?: InputMaybe>;
+ category?: InputMaybe;
+ categoryId?: InputMaybe;
+ content?: InputMaybe;
+ createdAt?: InputMaybe;
+ id?: InputMaybe;
+ or?: InputMaybe>;
+ status?: InputMaybe;
+ title?: InputMaybe;
+ updatedAt?: InputMaybe;
+};
+
+export type BlogPostFilterCategoryFilter = {
+ and?: InputMaybe>;
+ createdAt?: InputMaybe;
+ id?: InputMaybe;
+ or?: InputMaybe>;
+ title?: InputMaybe;
+ updatedAt?: InputMaybe;
+};
+
+export type BlogPostMaxAggregate = {
+ categoryId?: Maybe;
+ content?: Maybe;
+ createdAt?: Maybe;
+ id?: Maybe;
+ status?: Maybe;
+ title?: Maybe;
+ updatedAt?: Maybe;
+};
+
+export type BlogPostMinAggregate = {
+ categoryId?: Maybe;
+ content?: Maybe;
+ createdAt?: Maybe;
+ id?: Maybe;
+ status?: Maybe;
+ title?: Maybe;
+ updatedAt?: Maybe;
+};
+
+export type BlogPostSort = {
+ direction: SortDirection;
+ field: BlogPostSortFields;
+ nulls?: InputMaybe;
+};
+
+export type BlogPostSortFields =
+ | "categoryId"
+ | "content"
+ | "createdAt"
+ | "id"
+ | "status"
+ | "title"
+ | "updatedAt";
+
+export type BlogPostSubscriptionFilter = {
+ and?: InputMaybe>;
+ categoryId?: InputMaybe;
+ content?: InputMaybe;
+ createdAt?: InputMaybe;
+ id?: InputMaybe;
+ or?: InputMaybe>;
+ status?: InputMaybe;
+ title?: InputMaybe;
+ updatedAt?: InputMaybe;
+};
+
+export type BlogPostSumAggregate = {
+ categoryId?: Maybe;
+ id?: Maybe;
+};
+
+export type BlogPostUpdateFilter = {
+ and?: InputMaybe>;
+ categoryId?: InputMaybe;
+ content?: InputMaybe;
+ createdAt?: InputMaybe;
+ id?: InputMaybe;
+ or?: InputMaybe>;
+ status?: InputMaybe;
+ title?: InputMaybe;
+ updatedAt?: InputMaybe;
+};
+
+export type Category = {
+ blogPosts: CategoryBlogPostsConnection;
+ createdAt: Scalars["DateTime"]["output"];
+ id: Scalars["ID"]["output"];
+ title: Scalars["String"]["output"];
+ updatedAt: Scalars["DateTime"]["output"];
+};
+
+export type CategoryBlogPostsArgs = {
+ filter?: BlogPostFilter;
+ paging?: OffsetPaging;
+ sorting?: Array;
+};
+
+export type CategoryBlogPostsConnection = {
+ /** Array of nodes. */
+ nodes: Array;
+ /** Paging information */
+ pageInfo: OffsetPageInfo;
+ /** Fetch total count of records */
+ totalCount: Scalars["Int"]["output"];
+};
+
+export type CategoryConnection = {
+ /** Array of nodes. */
+ nodes: Array;
+ /** Paging information */
+ pageInfo: OffsetPageInfo;
+ /** Fetch total count of records */
+ totalCount: Scalars["Int"]["output"];
+};
+
+export type CategoryCreateInput = {
+ title: Scalars["String"]["input"];
+};
+
+export type CategoryDeleteFilter = {
+ and?: InputMaybe>;
+ createdAt?: InputMaybe;
+ id?: InputMaybe;
+ or?: InputMaybe>;
+ title?: InputMaybe;
+ updatedAt?: InputMaybe;
+};
+
+export type CategoryDeleteResponse = {
+ createdAt?: Maybe;
+ id?: Maybe;
+ title?: Maybe;
+ updatedAt?: Maybe;
+};
+
+export type CategoryFilter = {
+ and?: InputMaybe>;
+ blogPosts?: InputMaybe;
+ createdAt?: InputMaybe;
+ id?: InputMaybe;
+ or?: InputMaybe>;
+ title?: InputMaybe;
+ updatedAt?: InputMaybe;
+};
+
+export type CategoryFilterBlogPostFilter = {
+ and?: InputMaybe>;
+ categoryId?: InputMaybe;
+ content?: InputMaybe;
+ createdAt?: InputMaybe;
+ id?: InputMaybe;
+ or?: InputMaybe>;
+ status?: InputMaybe;
+ title?: InputMaybe;
+ updatedAt?: InputMaybe;
+};
+
+export type CategorySort = {
+ direction: SortDirection;
+ field: CategorySortFields;
+ nulls?: InputMaybe;
+};
+
+export type CategorySortFields = "createdAt" | "id" | "title" | "updatedAt";
+
+export type CategorySubscriptionFilter = {
+ and?: InputMaybe>;
+ createdAt?: InputMaybe;
+ id?: InputMaybe;
+ or?: InputMaybe>;
+ title?: InputMaybe;
+ updatedAt?: InputMaybe;
+};
+
+export type CategoryUpdateFilter = {
+ and?: InputMaybe>;
+ createdAt?: InputMaybe;
+ id?: InputMaybe;
+ or?: InputMaybe>;
+ title?: InputMaybe;
+ updatedAt?: InputMaybe;
+};
+
+export type CategoryUpdateInput = {
+ title: Scalars["String"]["input"];
+};
+
+export type CreateBlogPostSubscriptionFilterInput = {
+ /** Specify to filter the records returned. */
+ filter: BlogPostSubscriptionFilter;
+};
+
+export type CreateCategorySubscriptionFilterInput = {
+ /** Specify to filter the records returned. */
+ filter: CategorySubscriptionFilter;
+};
+
+export type CreateManyBlogPostsInput = {
+ /** Array of records to create */
+ blogPosts: Array;
+};
+
+export type CreateManyCategoriesInput = {
+ /** Array of records to create */
+ categories: Array;
+};
+
+export type CreateOneBlogPostInput = {
+ /** The record to create */
+ blogPost: PostCreateInput;
+};
+
+export type CreateOneCategoryInput = {
+ /** The record to create */
+ category: CategoryCreateInput;
+};
+
+export type DateFieldComparison = {
+ between?: InputMaybe;
+ eq?: InputMaybe;
+ gt?: InputMaybe;
+ gte?: InputMaybe;
+ in?: InputMaybe>;
+ is?: InputMaybe;
+ isNot?: InputMaybe;
+ lt?: InputMaybe;
+ lte?: InputMaybe;
+ neq?: InputMaybe;
+ notBetween?: InputMaybe;
+ notIn?: InputMaybe>;
+};
+
+export type DateFieldComparisonBetween = {
+ lower: Scalars["DateTime"]["input"];
+ upper: Scalars["DateTime"]["input"];
+};
+
+export type DeleteManyBlogPostsInput = {
+ /** Filter to find records to delete */
+ filter: BlogPostDeleteFilter;
+};
+
+export type DeleteManyCategoriesInput = {
+ /** Filter to find records to delete */
+ filter: CategoryDeleteFilter;
+};
+
+export type DeleteManyResponse = {
+ /** The number of records deleted. */
+ deletedCount: Scalars["Int"]["output"];
+};
+
+export type DeleteOneBlogPostInput = {
+ /** The id of the record to delete. */
+ id: Scalars["ID"]["input"];
+};
+
+export type DeleteOneBlogPostSubscriptionFilterInput = {
+ /** Specify to filter the records returned. */
+ filter: BlogPostSubscriptionFilter;
+};
+
+export type DeleteOneCategoryInput = {
+ /** The id of the record to delete. */
+ id: Scalars["ID"]["input"];
+};
+
+export type DeleteOneCategorySubscriptionFilterInput = {
+ /** Specify to filter the records returned. */
+ filter: CategorySubscriptionFilter;
+};
+
+/** Group by */
+export type GroupBy = "DAY" | "MONTH" | "WEEK" | "YEAR";
+
+export type IdFilterComparison = {
+ eq?: InputMaybe;
+ gt?: InputMaybe;
+ gte?: InputMaybe;
+ iLike?: InputMaybe;
+ in?: InputMaybe>;
+ is?: InputMaybe;
+ isNot?: InputMaybe;
+ like?: InputMaybe;
+ lt?: InputMaybe;
+ lte?: InputMaybe;
+ neq?: InputMaybe;
+ notILike?: InputMaybe;
+ notIn?: InputMaybe>;
+ notLike?: InputMaybe;
+};
+
+export type Mutation = {
+ createManyBlogPosts: Array;
+ createManyCategories: Array;
+ createOneBlogPost: BlogPost;
+ createOneCategory: Category;
+ deleteManyBlogPosts: DeleteManyResponse;
+ deleteManyCategories: DeleteManyResponse;
+ deleteOneBlogPost: BlogPostDeleteResponse;
+ deleteOneCategory: CategoryDeleteResponse;
+ updateManyBlogPosts: UpdateManyResponse;
+ updateManyCategories: UpdateManyResponse;
+ updateOneBlogPost: BlogPost;
+ updateOneCategory: Category;
+};
+
+export type MutationCreateManyBlogPostsArgs = {
+ input: CreateManyBlogPostsInput;
+};
+
+export type MutationCreateManyCategoriesArgs = {
+ input: CreateManyCategoriesInput;
+};
+
+export type MutationCreateOneBlogPostArgs = {
+ input: CreateOneBlogPostInput;
+};
+
+export type MutationCreateOneCategoryArgs = {
+ input: CreateOneCategoryInput;
+};
+
+export type MutationDeleteManyBlogPostsArgs = {
+ input: DeleteManyBlogPostsInput;
+};
+
+export type MutationDeleteManyCategoriesArgs = {
+ input: DeleteManyCategoriesInput;
+};
+
+export type MutationDeleteOneBlogPostArgs = {
+ input: DeleteOneBlogPostInput;
+};
+
+export type MutationDeleteOneCategoryArgs = {
+ input: DeleteOneCategoryInput;
+};
+
+export type MutationUpdateManyBlogPostsArgs = {
+ input: UpdateManyBlogPostsInput;
+};
+
+export type MutationUpdateManyCategoriesArgs = {
+ input: UpdateManyCategoriesInput;
+};
+
+export type MutationUpdateOneBlogPostArgs = {
+ input: UpdateOneBlogPostInput;
+};
+
+export type MutationUpdateOneCategoryArgs = {
+ input: UpdateOneCategoryInput;
+};
+
+export type OffsetPageInfo = {
+ /** true if paging forward and there are more records. */
+ hasNextPage?: Maybe;
+ /** true if paging backwards and there are more records. */
+ hasPreviousPage?: Maybe;
+};
+
+export type OffsetPaging = {
+ /** Limit the number of records returned */
+ limit?: InputMaybe;
+ /** Offset to start returning records from */
+ offset?: InputMaybe;
+};
+
+export type PostCreateInput = {
+ categoryId: Scalars["ID"]["input"];
+ content: Scalars["String"]["input"];
+ status: PostStatus;
+ title: Scalars["String"]["input"];
+};
+
+export type PostStatus = "DRAFT" | "PUBLISHED" | "REJECTED";
+
+export type PostStatusFilterComparison = {
+ eq?: InputMaybe;
+ gt?: InputMaybe;
+ gte?: InputMaybe;
+ iLike?: InputMaybe;
+ in?: InputMaybe>;
+ is?: InputMaybe;
+ isNot?: InputMaybe;
+ like?: InputMaybe;
+ lt?: InputMaybe;
+ lte?: InputMaybe;
+ neq?: InputMaybe;
+ notILike?: InputMaybe;
+ notIn?: InputMaybe>;
+ notLike?: InputMaybe;
+};
+
+export type PostUpdateInput = {
+ categoryId?: InputMaybe;
+ content?: InputMaybe;
+ status?: InputMaybe;
+ title?: InputMaybe;
+};
+
+export type Query = {
+ blogPost: BlogPost;
+ blogPostAggregate: Array;
+ blogPosts: BlogPostConnection;
+ categories: CategoryConnection;
+ category: Category;
+};
+
+export type QueryBlogPostArgs = {
+ id: Scalars["ID"]["input"];
+};
+
+export type QueryBlogPostAggregateArgs = {
+ filter?: InputMaybe;
+};
+
+export type QueryBlogPostsArgs = {
+ filter?: BlogPostFilter;
+ paging?: OffsetPaging;
+ sorting?: Array;
+};
+
+export type QueryCategoriesArgs = {
+ filter?: CategoryFilter;
+ paging?: OffsetPaging;
+ sorting?: Array;
+};
+
+export type QueryCategoryArgs = {
+ id: Scalars["ID"]["input"];
+};
+
+/** Sort Directions */
+export type SortDirection = "ASC" | "DESC";
+
+/** Sort Nulls Options */
+export type SortNulls = "NULLS_FIRST" | "NULLS_LAST";
+
+export type StringFieldComparison = {
+ eq?: InputMaybe;
+ gt?: InputMaybe;
+ gte?: InputMaybe;
+ iLike?: InputMaybe;
+ in?: InputMaybe>;
+ is?: InputMaybe;
+ isNot?: InputMaybe;
+ like?: InputMaybe;
+ lt?: InputMaybe;
+ lte?: InputMaybe;
+ neq?: InputMaybe;
+ notILike?: InputMaybe;
+ notIn?: InputMaybe>;
+ notLike?: InputMaybe;
+};
+
+export type Subscription = {
+ createdBlogPost: BlogPost;
+ createdCategory: Category;
+ deletedManyBlogPosts: DeleteManyResponse;
+ deletedManyCategories: DeleteManyResponse;
+ deletedOneBlogPost: BlogPostDeleteResponse;
+ deletedOneCategory: CategoryDeleteResponse;
+ updatedManyBlogPosts: UpdateManyResponse;
+ updatedManyCategories: UpdateManyResponse;
+ updatedOneBlogPost: BlogPost;
+ updatedOneCategory: Category;
+};
+
+export type SubscriptionCreatedBlogPostArgs = {
+ input?: InputMaybe;
+};
+
+export type SubscriptionCreatedCategoryArgs = {
+ input?: InputMaybe;
+};
+
+export type SubscriptionDeletedOneBlogPostArgs = {
+ input?: InputMaybe;
+};
+
+export type SubscriptionDeletedOneCategoryArgs = {
+ input?: InputMaybe;
+};
+
+export type SubscriptionUpdatedOneBlogPostArgs = {
+ input?: InputMaybe;
+};
+
+export type SubscriptionUpdatedOneCategoryArgs = {
+ input?: InputMaybe;
+};
+
+export type UpdateManyBlogPostsInput = {
+ /** Filter used to find fields to update */
+ filter: BlogPostUpdateFilter;
+ /** The update to apply to all records found using the filter */
+ update: PostUpdateInput;
+};
+
+export type UpdateManyCategoriesInput = {
+ /** Filter used to find fields to update */
+ filter: CategoryUpdateFilter;
+ /** The update to apply to all records found using the filter */
+ update: CategoryUpdateInput;
+};
+
+export type UpdateManyResponse = {
+ /** The number of records updated. */
+ updatedCount: Scalars["Int"]["output"];
+};
+
+export type UpdateOneBlogPostInput = {
+ /** The id of the record to update */
+ id: Scalars["ID"]["input"];
+ /** The update to apply. */
+ update: PostUpdateInput;
+};
+
+export type UpdateOneBlogPostSubscriptionFilterInput = {
+ /** Specify to filter the records returned. */
+ filter: BlogPostSubscriptionFilter;
+};
+
+export type UpdateOneCategoryInput = {
+ /** The id of the record to update */
+ id: Scalars["ID"]["input"];
+ /** The update to apply. */
+ update: CategoryUpdateInput;
+};
+
+export type UpdateOneCategorySubscriptionFilterInput = {
+ /** Specify to filter the records returned. */
+ filter: CategorySubscriptionFilter;
+};
diff --git a/examples/data-provider-graphql/src/graphql/types.ts b/examples/data-provider-graphql/src/graphql/types.ts
new file mode 100644
index 000000000000..2011d2312839
--- /dev/null
+++ b/examples/data-provider-graphql/src/graphql/types.ts
@@ -0,0 +1,85 @@
+import type * as Types from "./schema.types";
+
+export type CategoryCreateMutationVariables = Types.Exact<{
+ input: Types.CreateOneCategoryInput;
+}>;
+
+export type CategoryCreateMutation = {
+ createOneCategory: Pick;
+};
+
+export type CategoryEditMutationVariables = Types.Exact<{
+ input: Types.UpdateOneCategoryInput;
+}>;
+
+export type CategoryEditMutation = {
+ updateOneCategory: Pick;
+};
+
+export type CategoriesListQueryVariables = Types.Exact<{
+ paging: Types.OffsetPaging;
+ filter?: Types.InputMaybe;
+ sorting: Array | Types.CategorySort;
+}>;
+
+export type CategoriesListQuery = {
+ categories: Pick & {
+ nodes: Array>;
+ };
+};
+
+export type PostCreateMutationVariables = Types.Exact<{
+ input: Types.CreateOneBlogPostInput;
+}>;
+
+export type PostCreateMutation = {
+ createOneBlogPost: Pick<
+ Types.BlogPost,
+ "id" | "title" | "status" | "content"
+ > & { category: Pick };
+};
+
+export type PostEditMutationVariables = Types.Exact<{
+ input: Types.UpdateOneBlogPostInput;
+}>;
+
+export type PostEditMutation = {
+ updateOneBlogPost: Pick<
+ Types.BlogPost,
+ "id" | "title" | "status" | "categoryId" | "content"
+ > & { category: Pick };
+};
+
+export type BlogPostsListQueryVariables = Types.Exact<{
+ paging: Types.OffsetPaging;
+ filter?: Types.InputMaybe;
+ sorting: Array | Types.BlogPostSort;
+}>;
+
+export type BlogPostsListQuery = {
+ blogPosts: Pick & {
+ nodes: Array<
+ Pick & {
+ category: Pick;
+ }
+ >;
+ };
+};
+
+export type PostShowQueryVariables = Types.Exact<{
+ id: Types.Scalars["ID"]["input"];
+}>;
+
+export type PostShowQuery = {
+ blogPost: Pick & {
+ category: Pick;
+ };
+};
+
+export type CategoriesSelectQueryVariables = Types.Exact<{
+ [key: string]: never;
+}>;
+
+export type CategoriesSelectQuery = {
+ categories: { nodes: Array> };
+};
diff --git a/examples/data-provider-graphql/src/index.tsx b/examples/data-provider-graphql/src/index.tsx
new file mode 100644
index 000000000000..2902423c1ed1
--- /dev/null
+++ b/examples/data-provider-graphql/src/index.tsx
@@ -0,0 +1,13 @@
+import React from "react";
+import { createRoot } from "react-dom/client";
+
+import App from "./App";
+
+const container = document.getElementById("root");
+// eslint-disable-next-line
+const root = createRoot(container!);
+root.render(
+
+
+ ,
+);
diff --git a/examples/data-provider-graphql/src/interfaces/index.d.ts b/examples/data-provider-graphql/src/interfaces/index.d.ts
new file mode 100644
index 000000000000..0a15c12b5af9
--- /dev/null
+++ b/examples/data-provider-graphql/src/interfaces/index.d.ts
@@ -0,0 +1,13 @@
+export interface ICategory {
+ id: string;
+ title: string;
+}
+
+export interface IPost {
+ id: string;
+ title: string;
+ content: string;
+ status: string;
+ category: ICategory;
+ categoryId: string;
+}
diff --git a/examples/data-provider-graphql/src/pages/categories/create.tsx b/examples/data-provider-graphql/src/pages/categories/create.tsx
new file mode 100644
index 000000000000..0d12bda79d48
--- /dev/null
+++ b/examples/data-provider-graphql/src/pages/categories/create.tsx
@@ -0,0 +1,31 @@
+import { Create, useForm } from "@refinedev/antd";
+import type { GetFields } from "@refinedev/nestjs-query";
+
+import { Form, Input } from "antd";
+
+import type { CategoryCreateMutation } from "graphql/types";
+import { CATEGORY_CREATE_MUTATION } from "./queries";
+
+export const CategoryCreate = () => {
+ const { formProps, saveButtonProps } = useForm<
+ GetFields
+ >({ meta: { gqlMutation: CATEGORY_CREATE_MUTATION } });
+
+ return (
+
+
+
+
+
+
+ );
+};
diff --git a/examples/data-provider-graphql/src/pages/categories/edit.tsx b/examples/data-provider-graphql/src/pages/categories/edit.tsx
new file mode 100644
index 000000000000..6181350ce910
--- /dev/null
+++ b/examples/data-provider-graphql/src/pages/categories/edit.tsx
@@ -0,0 +1,47 @@
+import { Edit, ListButton, RefreshButton, useForm } from "@refinedev/antd";
+import type { GetFields } from "@refinedev/nestjs-query";
+
+import { Form, Input } from "antd";
+
+import { CATEGORY_EDIT_MUTATION } from "./queries";
+import type { CategoryEditMutation } from "graphql/types";
+
+export const CategoryEdit = () => {
+ const {
+ formProps,
+ saveButtonProps,
+ query: queryResult,
+ } = useForm>({
+ metaData: {
+ gqlMutation: CATEGORY_EDIT_MUTATION,
+ },
+ });
+
+ return (
+
+
+ queryResult?.refetch()} />
+ >
+ ),
+ }}
+ saveButtonProps={saveButtonProps}
+ >
+
+
+
+
+
+ );
+};
diff --git a/examples/data-provider-graphql/src/pages/categories/index.ts b/examples/data-provider-graphql/src/pages/categories/index.ts
new file mode 100644
index 000000000000..b9af745e6bcf
--- /dev/null
+++ b/examples/data-provider-graphql/src/pages/categories/index.ts
@@ -0,0 +1,3 @@
+export * from "./list";
+export * from "./create";
+export * from "./edit";
diff --git a/examples/data-provider-graphql/src/pages/categories/list.tsx b/examples/data-provider-graphql/src/pages/categories/list.tsx
new file mode 100644
index 000000000000..d1b168d963f0
--- /dev/null
+++ b/examples/data-provider-graphql/src/pages/categories/list.tsx
@@ -0,0 +1,63 @@
+import {
+ List,
+ useTable,
+ EditButton,
+ DateField,
+ getDefaultSortOrder,
+ DeleteButton,
+} from "@refinedev/antd";
+import type { GetFieldsFromList } from "@refinedev/nestjs-query";
+
+import { Space, Table } from "antd";
+
+import { CATEGORIES_LIST_QUERY } from "./queries";
+import type { CategoriesListQuery } from "graphql/types";
+
+type ICategory = GetFieldsFromList;
+
+export const CategoryList = () => {
+ const { tableProps, sorters } = useTable({
+ initialSorter: [
+ {
+ field: "id",
+ order: "asc",
+ },
+ ],
+ meta: {
+ gqlQuery: CATEGORIES_LIST_QUERY,
+ },
+ queryOptions: {
+ retry(failureCount, error) {
+ if (error?.message.includes("Network Error") && failureCount <= 3)
+ return true;
+ return false;
+ },
+ },
+ });
+
+ return (
+
+
+
+
+ }
+ defaultSortOrder={getDefaultSortOrder("createdAt", sorters)}
+ sorter
+ />
+
+ title="Actions"
+ dataIndex="actions"
+ render={(_, record) => (
+
+