@graphql-suite/query 0.8.3 → 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,191 +1,299 @@
1
- [![Monthly Downloads](https://img.shields.io/npm/dm/drizzle-graphql-suite.svg)](https://www.npmjs.com/package/drizzle-graphql-suite)
2
- [![NPM](https://img.shields.io/npm/v/drizzle-graphql-suite.svg 'NPM package version')](https://www.npmjs.com/package/drizzle-graphql-suite)
3
- [![CI](https://github.com/annexare/drizzle-graphql-suite/actions/workflows/ci.yml/badge.svg)](https://github.com/annexare/drizzle-graphql-suite/actions/workflows/ci.yml)
1
+ # @graphql-suite/query
4
2
 
5
- # drizzle-graphql-suite
3
+ > Part of [`graphql-suite`](https://github.com/annexare/graphql-suite).
4
+ > See also: [`schema`](https://github.com/annexare/graphql-suite/tree/main/packages/schema) | [`client`](https://github.com/annexare/graphql-suite/tree/main/packages/client)
6
5
 
7
- Auto-generated GraphQL CRUD, type-safe clients, and React Query hooks from Drizzle PostgreSQL schemas.
6
+ TanStack React Query hooks for `@graphql-suite/client` type-safe data fetching with caching, pagination, and mutations.
8
7
 
9
- ## Overview
10
-
11
- `drizzle-graphql-suite` is a three-layer toolkit that turns your Drizzle ORM schema into a fully working GraphQL API with end-to-end type safety:
12
-
13
- 1. **Schema builder** — generates a complete GraphQL schema with CRUD operations, relation-level filtering, per-operation hooks, and runtime permissions from Drizzle table definitions.
14
- 2. **Client** — provides a type-safe GraphQL client that infers query/mutation types directly from your Drizzle schema, with full TypeScript support for filters, relations, and results.
15
- 3. **React Query hooks** — wraps the client in TanStack React Query hooks for caching, pagination, and mutations with automatic cache invalidation.
16
-
17
- Inspired by [`drizzle-graphql`](https://github.com/drizzle-team/drizzle-graphql), rewritten with significant improvements including relation-level filtering, hooks, count queries, configurable schema generation, and code generation.
8
+ ## Installation
18
9
 
19
- ## Packages
10
+ ```bash
11
+ bun add @graphql-suite/query
12
+ ```
20
13
 
21
- | Subpath | Package | Description |
22
- |---------|---------|-------------|
23
- | `drizzle-graphql-suite/schema` | [`@drizzle-graphql-suite/schema`](packages/schema/README.md) | GraphQL schema builder with CRUD, filtering, hooks, permissions, and codegen |
24
- | `drizzle-graphql-suite/client` | [`@drizzle-graphql-suite/client`](packages/client/README.md) | Type-safe GraphQL client with full Drizzle type inference |
25
- | `drizzle-graphql-suite/query` | [`@drizzle-graphql-suite/query`](packages/query/README.md) | TanStack React Query hooks for the client |
14
+ ```bash
15
+ npm install @graphql-suite/query
16
+ ```
26
17
 
27
- ## Installation
18
+ Or install the full suite:
28
19
 
29
20
  ```bash
30
- bun add drizzle-graphql-suite
21
+ bun add graphql-suite
31
22
  ```
32
23
 
33
24
  ```bash
34
- npm install drizzle-graphql-suite
25
+ npm install graphql-suite
35
26
  ```
36
27
 
37
- ## Peer Dependencies
28
+ ## Setup
29
+
30
+ ### Provider
31
+
32
+ Wrap your app with `<GraphQLProvider>` inside a `<QueryClientProvider>`:
33
+
34
+ ```tsx
35
+ import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
36
+ import { GraphQLProvider } from '@graphql-suite/query'
37
+ import { client } from './graphql-client'
38
38
 
39
- Each subpath import has its own peer dependency requirements:
39
+ const queryClient = new QueryClient()
40
40
 
41
- | Subpath | Peer Dependencies |
42
- |---------|-------------------|
43
- | `./schema` | `drizzle-orm` >=0.44.0, `graphql` >=16.3.0 |
44
- | `./client` | `drizzle-orm` >=0.44.0 |
45
- | `./query` | `react` >=18.0.0, `@tanstack/react-query` >=5.0.0 |
41
+ function App() {
42
+ return (
43
+ <QueryClientProvider client={queryClient}>
44
+ <GraphQLProvider client={client}>
45
+ {/* your app */}
46
+ </GraphQLProvider>
47
+ </QueryClientProvider>
48
+ )
49
+ }
50
+ ```
46
51
 
47
- ## Quick Start
52
+ ### `useGraphQLClient()`
48
53
 
49
- ### 1. Server Build GraphQL Schema
54
+ Access the raw `GraphQLClient` instance from context:
50
55
 
51
56
  ```ts
52
- import { buildSchema } from 'drizzle-graphql-suite/schema'
53
- import { createYoga } from 'graphql-yoga'
54
- import { createServer } from 'node:http'
55
- import { db } from './db'
56
-
57
- const { schema, withPermissions } = buildSchema(db, {
58
- tables: { exclude: ['session', 'verification'] },
59
- hooks: {
60
- user: {
61
- query: {
62
- before: async ({ context }) => {
63
- if (!context.user) throw new Error('Unauthorized')
64
- },
65
- },
66
- },
67
- },
68
- })
57
+ import { useGraphQLClient } from '@graphql-suite/query'
69
58
 
70
- const yoga = createYoga({ schema })
71
- const server = createServer(yoga)
72
- server.listen(4000)
59
+ function MyComponent() {
60
+ const client = useGraphQLClient()
61
+ // client.entity('user'), client.execute(query, variables), etc.
62
+ }
73
63
  ```
74
64
 
75
- #### Per-Role Schemas (Optional)
65
+ ### `useEntity(entityName)`
66
+
67
+ Get a typed `EntityClient` for use with query and mutation hooks:
76
68
 
77
69
  ```ts
78
- import { permissive, restricted, readOnly } from 'drizzle-graphql-suite/schema'
70
+ import { useEntity } from '@graphql-suite/query'
79
71
 
80
- // Cached per id — call withPermissions on each request
81
- const schemas = {
82
- admin: schema,
83
- editor: withPermissions(permissive('editor', { audit: false, user: readOnly() })),
84
- viewer: withPermissions(restricted('viewer', { post: { query: true } })),
72
+ function UserList() {
73
+ const user = useEntity('user')
74
+ // Pass `user` to useEntityList, useEntityQuery, etc.
85
75
  }
86
76
  ```
87
77
 
88
- ### 2. Client — Type-Safe Queries
78
+ ## Query Hooks
89
79
 
90
- ```ts
91
- import { createDrizzleClient } from 'drizzle-graphql-suite/client'
92
- import * as schema from './db/schema'
80
+ ### `useEntityList(entity, params, options?)`
93
81
 
94
- const client = createDrizzleClient({
95
- schema,
96
- config: { suffixes: { list: 's' } },
97
- url: '/api/graphql',
98
- })
82
+ Fetch a list of records. Returns `UseQueryResult<T[]>`.
99
83
 
100
- const users = await client.entity('user').query({
101
- select: {
102
- id: true,
103
- name: true,
104
- posts: { id: true, title: true },
105
- },
106
- where: { name: { ilike: '%john%' } },
107
- limit: 10,
108
- })
84
+ **Params**: `select`, `where`, `limit`, `offset`, `orderBy`
85
+
86
+ ```tsx
87
+ import { useEntity, useEntityList } from '@graphql-suite/query'
88
+
89
+ function UserList() {
90
+ const user = useEntity('user')
91
+ const { data, isLoading, error } = useEntityList(user, {
92
+ select: { id: true, name: true, email: true },
93
+ where: { role: { eq: 'admin' } },
94
+ orderBy: { name: { direction: 'asc', priority: 1 } },
95
+ limit: 20,
96
+ })
97
+
98
+ if (isLoading) return <div>Loading...</div>
99
+ if (error) return <div>Error: {error.message}</div>
100
+
101
+ return (
102
+ <ul>
103
+ {data?.map((u) => <li key={u.id}>{u.name} ({u.email})</li>)}
104
+ </ul>
105
+ )
106
+ }
109
107
  ```
110
108
 
111
- ### 3. React — Query Hooks
109
+ ### `useEntityQuery(entity, params, options?)`
110
+
111
+ Fetch a single record. Returns `UseQueryResult<T | null>`.
112
+
113
+ **Params**: `select`, `where`, `offset`, `orderBy`
112
114
 
113
115
  ```tsx
114
- import { GraphQLProvider, useEntity, useEntityList } from 'drizzle-graphql-suite/query'
115
- import { QueryClient, QueryClientProvider } from '@tanstack/react-query'
116
+ function UserDetail({ userId }: { userId: string }) {
117
+ const user = useEntity('user')
118
+ const { data } = useEntityQuery(user, {
119
+ select: { id: true, name: true, email: true, role: true },
120
+ where: { id: { eq: userId } },
121
+ })
116
122
 
117
- const queryClient = new QueryClient()
123
+ if (!data) return null
124
+ return <div>{data.name} — {data.role}</div>
125
+ }
126
+ ```
127
+
128
+ ### `useEntityInfiniteQuery(entity, params, options?)`
129
+
130
+ Infinite scrolling with cursor-based pagination. Returns `UseInfiniteQueryResult` with pages containing `{ items: T[], count: number }`.
131
+
132
+ **Params**: `select`, `where`, `pageSize`, `orderBy`
133
+
134
+ ```tsx
135
+ function InfiniteUserList() {
136
+ const user = useEntity('user')
137
+ const { data, fetchNextPage, hasNextPage, isFetchingNextPage } =
138
+ useEntityInfiniteQuery(user, {
139
+ select: { id: true, name: true },
140
+ pageSize: 20,
141
+ orderBy: { name: { direction: 'asc', priority: 1 } },
142
+ })
143
+
144
+ const allUsers = data?.pages.flatMap((page) => page.items) ?? []
118
145
 
119
- function App() {
120
146
  return (
121
- <QueryClientProvider client={queryClient}>
122
- <GraphQLProvider client={graphqlClient}>
123
- <UserList />
124
- </GraphQLProvider>
125
- </QueryClientProvider>
147
+ <div>
148
+ <ul>
149
+ {allUsers.map((u) => <li key={u.id}>{u.name}</li>)}
150
+ </ul>
151
+ {hasNextPage && (
152
+ <button onClick={() => fetchNextPage()} disabled={isFetchingNextPage}>
153
+ {isFetchingNextPage ? 'Loading...' : 'Load more'}
154
+ </button>
155
+ )}
156
+ </div>
126
157
  )
127
158
  }
159
+ ```
128
160
 
129
- function UserList() {
161
+ ### Query Options
162
+
163
+ All query hooks accept an optional `options` parameter:
164
+
165
+ | Option | Type | Description |
166
+ |--------|------|-------------|
167
+ | `enabled` | `boolean` | Disable automatic fetching |
168
+ | `gcTime` | `number` | Garbage collection time (ms) |
169
+ | `staleTime` | `number` | Time until data is considered stale (ms) |
170
+ | `refetchOnWindowFocus` | `boolean` | Refetch when window regains focus |
171
+ | `queryKey` | `unknown[]` | Override the auto-generated query key |
172
+
173
+ ## Mutation Hooks
174
+
175
+ ### `useEntityInsert(entity, returning?, options?)`
176
+
177
+ Insert records. Call `.mutate({ values })` to execute.
178
+
179
+ ```tsx
180
+ function CreateUser() {
130
181
  const user = useEntity('user')
131
- const { data, isLoading } = useEntityList(user, {
132
- select: { id: true, name: true, email: true },
133
- limit: 20,
134
- })
182
+ const { mutate, isPending } = useEntityInsert(
183
+ user,
184
+ { id: true, name: true },
185
+ { onSuccess: (data) => console.log('Created:', data) },
186
+ )
135
187
 
136
- if (isLoading) return <div>Loading...</div>
137
- return <ul>{data?.map((u) => <li key={u.id}>{u.name}</li>)}</ul>
188
+ return (
189
+ <button
190
+ disabled={isPending}
191
+ onClick={() => mutate({
192
+ values: [{ name: 'Alice', email: 'alice@example.com' }],
193
+ })}
194
+ >
195
+ Create User
196
+ </button>
197
+ )
138
198
  }
139
199
  ```
140
200
 
141
- ## Framework Integration Examples
201
+ ### `useEntityUpdate(entity, returning?, options?)`
142
202
 
143
- `buildSchema()` returns a standard `GraphQLSchema` here's how to serve it from popular frameworks.
203
+ Update records. Call `.mutate({ set, where })` to execute.
144
204
 
145
- ### Next.js App Router
205
+ ```tsx
206
+ function UpdateRole({ userId }: { userId: string }) {
207
+ const user = useEntity('user')
208
+ const { mutate } = useEntityUpdate(user, { id: true, role: true })
146
209
 
147
- ```ts
148
- // app/api/graphql/route.ts
149
- import { createYoga } from 'graphql-yoga'
150
- import { buildSchema } from 'drizzle-graphql-suite/schema'
151
- import { db } from '@/db'
210
+ return (
211
+ <button onClick={() => mutate({
212
+ set: { role: 'admin' },
213
+ where: { id: { eq: userId } },
214
+ })}>
215
+ Make Admin
216
+ </button>
217
+ )
218
+ }
219
+ ```
152
220
 
153
- const { schema } = buildSchema(db)
221
+ ### `useEntityDelete(entity, returning?, options?)`
154
222
 
155
- const { handleRequest } = createYoga({
156
- schema,
157
- graphqlEndpoint: '/api/graphql',
158
- fetchAPI: { Response },
159
- })
223
+ Delete records. Call `.mutate({ where })` to execute.
224
+
225
+ ```tsx
226
+ function DeleteUser({ userId }: { userId: string }) {
227
+ const user = useEntity('user')
228
+ const { mutate } = useEntityDelete(user, { id: true })
160
229
 
161
- export { handleRequest as GET, handleRequest as POST }
230
+ return (
231
+ <button onClick={() => mutate({
232
+ where: { id: { eq: userId } },
233
+ })}>
234
+ Delete
235
+ </button>
236
+ )
237
+ }
162
238
  ```
163
239
 
164
- ### ElysiaJS
240
+ ### Mutation Options
241
+
242
+ All mutation hooks accept an optional `options` parameter:
243
+
244
+ | Option | Type | Description |
245
+ |--------|------|-------------|
246
+ | `invalidate` | `boolean` | Invalidate queries after mutation (default: `true`) |
247
+ | `invalidateKey` | `unknown[]` | Custom query key prefix to invalidate |
248
+ | `onSuccess` | `(data) => void` | Callback after successful mutation |
249
+ | `onError` | `(error) => void` | Callback after failed mutation |
250
+
251
+ ## Cache Invalidation
252
+
253
+ By default, all mutations invalidate queries with the `['gql']` key prefix. Since all query hooks use keys starting with `['gql', ...]`, this means every mutation refreshes all GraphQL queries.
254
+
255
+ ### Custom Invalidation Key
256
+
257
+ Narrow invalidation to specific queries:
165
258
 
166
259
  ```ts
167
- // server.ts
168
- import { Elysia } from 'elysia'
169
- import { yoga } from '@elysiajs/graphql-yoga'
170
- import { buildSchema } from 'drizzle-graphql-suite/schema'
171
- import { db } from './db'
260
+ const { mutate } = useEntityUpdate(user, { id: true }, {
261
+ invalidateKey: ['gql', 'list'], // only invalidate list queries
262
+ })
263
+ ```
172
264
 
173
- const { schema } = buildSchema(db)
265
+ ### Disable Invalidation
174
266
 
175
- new Elysia()
176
- .use(yoga({ schema }))
177
- .listen(3000)
267
+ ```ts
268
+ const { mutate } = useEntityInsert(user, undefined, {
269
+ invalidate: false,
270
+ })
178
271
  ```
179
272
 
180
- ## AI Agent Skill
273
+ ### Query Key Override
181
274
 
182
- This repo includes a [skills.sh](https://skills.sh) skill that provides AI coding agents (Claude Code, Cursor, etc.) with accurate, up-to-date guidance for all three packages.
275
+ Override the auto-generated key on query hooks for fine-grained cache control:
183
276
 
184
- ```bash
185
- bunx skills add annexare/drizzle-graphql-suite
186
- # or: npx skills add annexare/drizzle-graphql-suite
277
+ ```ts
278
+ const { data } = useEntityList(user, params, {
279
+ queryKey: ['users', 'admin-list'],
280
+ })
187
281
  ```
188
282
 
189
- ## License
283
+ ## Type Inference Flow
190
284
 
191
- MIT
285
+ Types flow end-to-end from your Drizzle schema to hook return types:
286
+
287
+ ```
288
+ Drizzle Schema (tables + relations)
289
+ ↓ InferEntityDefs
290
+ EntityDefs (fields, filters, inputs, orderBy per table)
291
+ ↓ createDrizzleClient
292
+ GraphQLClient<SchemaDescriptor, EntityDefs>
293
+ ↓ useEntity / client.entity()
294
+ EntityClient<EntityDefs, EntityDef>
295
+ ↓ useEntityList / useEntityQuery (select param)
296
+ InferResult<EntityDefs, EntityDef, Select>
297
+
298
+ Fully typed data: only selected fields, relations resolve to T[] or T | null
299
+ ```
package/index.d.ts CHANGED
@@ -1 +1,7 @@
1
- export * from '@drizzle-graphql-suite/query'
1
+ export { GraphQLProvider, useGraphQLClient } from './provider';
2
+ export type { GraphQLClientContext } from './types';
3
+ export { useEntity } from './useEntity';
4
+ export { useEntityInfiniteQuery } from './useEntityInfiniteQuery';
5
+ export { useEntityList } from './useEntityList';
6
+ export { useEntityDelete, useEntityInsert, useEntityUpdate } from './useEntityMutation';
7
+ export { useEntityQuery } from './useEntityQuery';
package/index.js CHANGED
@@ -1 +1,2 @@
1
- export * from '@drizzle-graphql-suite/query'
1
+ /** @graphql-suite/query v0.9.1 | MIT */
2
+ import{createContext as O,useContext as R}from"react";import{jsx as T}from"react/jsx-runtime";var H=O(null);function S({client:E,children:f}){return T(H.Provider,{value:E,children:f})}function B(){let E=R(H);if(!E)throw Error("useGraphQLClient must be used within a <GraphQLProvider>");return E}import{useMemo as V}from"react";function W(E){let f=B();return V(()=>f.entity(E),[f,E])}import{useInfiniteQuery as X}from"@tanstack/react-query";function Y(E,f,D){let U=D?.queryKey??["gql","infinite",f.select,f.where,f.orderBy,f.pageSize];return X({queryKey:U,initialPageParam:0,queryFn:async({pageParam:w=0})=>{let L={...f,limit:f.pageSize,offset:w*f.pageSize},z=await E.query(L),J=await E.count({where:f.where});return{items:z,count:J}},getNextPageParam:(w,L)=>{return L.length*f.pageSize<w.count?L.length:void 0},enabled:D?.enabled,gcTime:D?.gcTime,staleTime:D?.staleTime})}import{useQuery as Z}from"@tanstack/react-query";function _(E,f,D){let U=D?.queryKey??["gql","list",f.select,f.where,f.orderBy,f.limit,f.offset];return Z({queryKey:U,queryFn:async()=>{return await E.query(f)},enabled:D?.enabled,gcTime:D?.gcTime,staleTime:D?.staleTime,refetchOnWindowFocus:D?.refetchOnWindowFocus})}import{useMutation as F,useQueryClient as G}from"@tanstack/react-query";function $(E,f,D){let U=G(),w=D?.invalidate!==!1;return F({mutationFn:async(L)=>{return await E.insert({...L,returning:f})},onSuccess:(L)=>{if(w){let z=D?.invalidateKey??["gql"];U.invalidateQueries({queryKey:z})}D?.onSuccess?.(L)},onError:D?.onError})}function j(E,f,D){let U=G(),w=D?.invalidate!==!1;return F({mutationFn:async(L)=>{return await E.update({...L,returning:f})},onSuccess:(L)=>{if(w){let z=D?.invalidateKey??["gql"];U.invalidateQueries({queryKey:z})}D?.onSuccess?.(L)},onError:D?.onError})}function I(E,f,D){let U=G(),w=D?.invalidate!==!1;return F({mutationFn:async(L)=>{return await E.delete({...L,returning:f})},onSuccess:(L)=>{if(w){let z=D?.invalidateKey??["gql"];U.invalidateQueries({queryKey:z})}D?.onSuccess?.(L)},onError:D?.onError})}import{useQuery as K}from"@tanstack/react-query";function v(E,f,D){let U=D?.queryKey??["gql","single",f.select,f.where,f.orderBy,f.offset];return K({queryKey:U,queryFn:async()=>{return await E.querySingle(f)},enabled:D?.enabled,gcTime:D?.gcTime,staleTime:D?.staleTime,refetchOnWindowFocus:D?.refetchOnWindowFocus})}export{B as useGraphQLClient,j as useEntityUpdate,v as useEntityQuery,_ as useEntityList,$ as useEntityInsert,Y as useEntityInfiniteQuery,I as useEntityDelete,W as useEntity,S as GraphQLProvider};
package/package.json CHANGED
@@ -1,14 +1,24 @@
1
1
  {
2
2
  "name": "@graphql-suite/query",
3
- "version": "0.8.3",
3
+ "version": "0.9.1",
4
4
  "description": "React Query hooks for the Drizzle GraphQL client with caching and automatic invalidation",
5
5
  "license": "MIT",
6
6
  "author": "https://github.com/dmythro",
7
7
  "repository": {
8
8
  "type": "git",
9
- "url": "git+https://github.com/annexare/drizzle-graphql-suite.git",
9
+ "url": "git+https://github.com/annexare/graphql-suite.git",
10
10
  "directory": "packages/query"
11
11
  },
12
+ "homepage": "https://graphql-suite.annexare.com/query/overview/",
13
+ "keywords": [
14
+ "drizzle",
15
+ "graphql",
16
+ "react",
17
+ "react-query",
18
+ "tanstack",
19
+ "hooks",
20
+ "typescript"
21
+ ],
12
22
  "type": "module",
13
23
  "publishConfig": {
14
24
  "access": "public"
@@ -21,11 +31,8 @@
21
31
  "import": "./index.js"
22
32
  }
23
33
  },
24
- "dependencies": {
25
- "@drizzle-graphql-suite/query": "0.8.3"
26
- },
27
34
  "peerDependencies": {
28
- "@drizzle-graphql-suite/client": ">=0.7.0",
35
+ "@graphql-suite/client": ">=0.9.0",
29
36
  "@tanstack/react-query": ">=5.0.0",
30
37
  "react": ">=18.0.0"
31
38
  }
package/provider.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ import type { AnyEntityDefs, GraphQLClient, SchemaDescriptor } from '@graphql-suite/client';
2
+ import { type ReactNode } from 'react';
3
+ export declare function GraphQLProvider<TSchema extends SchemaDescriptor, TDefs extends AnyEntityDefs>({ client, children, }: {
4
+ client: GraphQLClient<TSchema, TDefs>;
5
+ children: ReactNode;
6
+ }): import("react/jsx-runtime").JSX.Element;
7
+ export declare function useGraphQLClient<TSchema extends SchemaDescriptor = SchemaDescriptor, TDefs extends AnyEntityDefs = AnyEntityDefs>(): GraphQLClient<TSchema, TDefs>;
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,40 @@
1
+ import './test-setup';
2
+ import { QueryClient } from '@tanstack/react-query';
3
+ import { type ReactNode } from 'react';
4
+ type RenderHookOptions = {
5
+ wrapper?: (props: {
6
+ children: ReactNode;
7
+ }) => ReactNode;
8
+ };
9
+ type RenderHookResult<T> = {
10
+ result: {
11
+ current: T;
12
+ };
13
+ rerender: () => void;
14
+ unmount: () => void;
15
+ };
16
+ export declare function renderHook<T>(callback: () => T, options?: RenderHookOptions): RenderHookResult<T>;
17
+ export declare function renderHookAsync<T>(callback: () => T, options?: RenderHookOptions): Promise<RenderHookResult<T>>;
18
+ type MockParams = any;
19
+ export declare function createMockEntityClient(): {
20
+ query: import("bun:test").Mock<(p: MockParams) => Promise<Record<string, unknown>[]>>;
21
+ querySingle: import("bun:test").Mock<(p: MockParams) => Promise<Record<string, unknown> | null>>;
22
+ count: import("bun:test").Mock<(p: MockParams) => Promise<number>>;
23
+ insert: import("bun:test").Mock<(p: MockParams) => Promise<Record<string, unknown>[]>>;
24
+ insertSingle: import("bun:test").Mock<(p: MockParams) => Promise<Record<string, unknown> | null>>;
25
+ update: import("bun:test").Mock<(p: MockParams) => Promise<Record<string, unknown>[]>>;
26
+ delete: import("bun:test").Mock<(p: MockParams) => Promise<Record<string, unknown>[]>>;
27
+ };
28
+ export declare function createMockGraphQLClient(entityClient?: any): {
29
+ entity: import("bun:test").Mock<(name: string) => any>;
30
+ url: string;
31
+ schema: {};
32
+ execute: import("bun:test").Mock<() => Promise<{
33
+ data: {};
34
+ }>>;
35
+ };
36
+ export declare function createTestQueryClient(): QueryClient;
37
+ export declare function createWrapper(mockClient: any, queryClient?: QueryClient): ({ children }: {
38
+ children: ReactNode;
39
+ }) => import("react/jsx-runtime").JSX.Element;
40
+ export {};
package/types.d.ts ADDED
@@ -0,0 +1,4 @@
1
+ import type { AnyEntityDefs, GraphQLClient, SchemaDescriptor } from '@graphql-suite/client';
2
+ export type GraphQLClientContext<TSchema extends SchemaDescriptor = SchemaDescriptor, TDefs extends AnyEntityDefs = AnyEntityDefs> = {
3
+ client: GraphQLClient<TSchema, TDefs>;
4
+ };
package/useEntity.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ import type { AnyEntityDefs, EntityClient, EntityDefsRef, SchemaDescriptor } from '@graphql-suite/client';
2
+ export declare function useEntity<TSchema extends SchemaDescriptor, TDefs extends AnyEntityDefs, TEntityName extends string & keyof TSchema & keyof TDefs>(entityName: TEntityName): EntityClient<EntityDefsRef<TDefs>, TEntityName>;
@@ -0,0 +1,26 @@
1
+ import type { AnyEntityDefs, EntityClient, EntityDef, EntityDefsRef, InferResult } from '@graphql-suite/client';
2
+ import { type UseInfiniteQueryResult } from '@tanstack/react-query';
3
+ type EntityInfiniteParams<TEntity extends EntityDef, TSelect extends Record<string, unknown>> = {
4
+ select: TSelect;
5
+ where?: TEntity extends {
6
+ filters: infer F;
7
+ } ? F : never;
8
+ pageSize: number;
9
+ orderBy?: TEntity extends {
10
+ orderBy: infer O;
11
+ } ? O : never;
12
+ };
13
+ type EntityInfiniteOptions = {
14
+ enabled?: boolean;
15
+ gcTime?: number;
16
+ staleTime?: number;
17
+ queryKey?: unknown[];
18
+ };
19
+ type PageData<T> = {
20
+ items: T[];
21
+ count: number;
22
+ };
23
+ export declare function useEntityInfiniteQuery<TDefs extends AnyEntityDefs, TEntityName extends string, TSelect extends Record<string, unknown>>(entity: EntityClient<EntityDefsRef<TDefs>, TEntityName>, params: EntityInfiniteParams<TDefs[TEntityName] & EntityDef, TSelect>, options?: EntityInfiniteOptions): UseInfiniteQueryResult<{
24
+ pages: PageData<InferResult<TDefs, TDefs[TEntityName] & EntityDef, TSelect>>[];
25
+ }>;
26
+ export {};
@@ -0,0 +1,22 @@
1
+ import type { AnyEntityDefs, EntityClient, EntityDef, EntityDefsRef, InferResult } from '@graphql-suite/client';
2
+ import { type UseQueryResult } from '@tanstack/react-query';
3
+ type EntityListParams<TEntity extends EntityDef, TSelect extends Record<string, unknown>> = {
4
+ select: TSelect;
5
+ where?: TEntity extends {
6
+ filters: infer F;
7
+ } ? F : never;
8
+ limit?: number;
9
+ offset?: number;
10
+ orderBy?: TEntity extends {
11
+ orderBy: infer O;
12
+ } ? O : never;
13
+ };
14
+ type EntityListOptions = {
15
+ enabled?: boolean;
16
+ gcTime?: number;
17
+ staleTime?: number;
18
+ refetchOnWindowFocus?: boolean;
19
+ queryKey?: unknown[];
20
+ };
21
+ export declare function useEntityList<TDefs extends AnyEntityDefs, TEntityName extends string, TSelect extends Record<string, unknown>>(entity: EntityClient<EntityDefsRef<TDefs>, TEntityName>, params: EntityListParams<TDefs[TEntityName] & EntityDef, TSelect>, options?: EntityListOptions): UseQueryResult<InferResult<TDefs, TDefs[TEntityName] & EntityDef, TSelect>[]>;
22
+ export {};
@@ -0,0 +1,41 @@
1
+ import type { AnyEntityDefs, EntityClient, EntityDef, EntityDefsRef, InferResult } from '@graphql-suite/client';
2
+ import { type UseMutationResult } from '@tanstack/react-query';
3
+ type InsertOptions<TResult> = {
4
+ invalidate?: boolean;
5
+ invalidateKey?: unknown[];
6
+ onSuccess?: (data: TResult) => void;
7
+ onError?: (error: Error) => void;
8
+ };
9
+ export declare function useEntityInsert<TDefs extends AnyEntityDefs, TEntityName extends string, TSelect extends Record<string, unknown>>(entity: EntityClient<EntityDefsRef<TDefs>, TEntityName>, returning?: TSelect, options?: InsertOptions<InferResult<TDefs, TDefs[TEntityName] & EntityDef, TSelect>[]>): UseMutationResult<InferResult<TDefs, TDefs[TEntityName] & EntityDef, TSelect>[], Error, {
10
+ values: TDefs[TEntityName] & EntityDef extends {
11
+ insertInput: infer I;
12
+ } ? I[] : never;
13
+ }>;
14
+ type UpdateParams<TEntity extends EntityDef> = {
15
+ set: TEntity extends {
16
+ updateInput: infer U;
17
+ } ? U : never;
18
+ where?: TEntity extends {
19
+ filters: infer F;
20
+ } ? F : never;
21
+ };
22
+ type UpdateOptions<TResult> = {
23
+ invalidate?: boolean;
24
+ invalidateKey?: unknown[];
25
+ onSuccess?: (data: TResult) => void;
26
+ onError?: (error: Error) => void;
27
+ };
28
+ export declare function useEntityUpdate<TDefs extends AnyEntityDefs, TEntityName extends string, TSelect extends Record<string, unknown>>(entity: EntityClient<EntityDefsRef<TDefs>, TEntityName>, returning?: TSelect, options?: UpdateOptions<InferResult<TDefs, TDefs[TEntityName] & EntityDef, TSelect>[]>): UseMutationResult<InferResult<TDefs, TDefs[TEntityName] & EntityDef, TSelect>[], Error, UpdateParams<TDefs[TEntityName] & EntityDef>>;
29
+ type DeleteParams<TEntity extends EntityDef> = {
30
+ where?: TEntity extends {
31
+ filters: infer F;
32
+ } ? F : never;
33
+ };
34
+ type DeleteOptions<TResult> = {
35
+ invalidate?: boolean;
36
+ invalidateKey?: unknown[];
37
+ onSuccess?: (data: TResult) => void;
38
+ onError?: (error: Error) => void;
39
+ };
40
+ export declare function useEntityDelete<TDefs extends AnyEntityDefs, TEntityName extends string, TSelect extends Record<string, unknown>>(entity: EntityClient<EntityDefsRef<TDefs>, TEntityName>, returning?: TSelect, options?: DeleteOptions<InferResult<TDefs, TDefs[TEntityName] & EntityDef, TSelect>[]>): UseMutationResult<InferResult<TDefs, TDefs[TEntityName] & EntityDef, TSelect>[], Error, DeleteParams<TDefs[TEntityName] & EntityDef>>;
41
+ export {};
@@ -0,0 +1,21 @@
1
+ import type { AnyEntityDefs, EntityClient, EntityDef, EntityDefsRef, InferResult } from '@graphql-suite/client';
2
+ import { type UseQueryResult } from '@tanstack/react-query';
3
+ type EntityQueryParams<TEntity extends EntityDef, TSelect extends Record<string, unknown>> = {
4
+ select: TSelect;
5
+ where?: TEntity extends {
6
+ filters: infer F;
7
+ } ? F : never;
8
+ offset?: number;
9
+ orderBy?: TEntity extends {
10
+ orderBy: infer O;
11
+ } ? O : never;
12
+ };
13
+ type EntityQueryOptions = {
14
+ enabled?: boolean;
15
+ gcTime?: number;
16
+ staleTime?: number;
17
+ refetchOnWindowFocus?: boolean;
18
+ queryKey?: unknown[];
19
+ };
20
+ export declare function useEntityQuery<TDefs extends AnyEntityDefs, TEntityName extends string, TSelect extends Record<string, unknown>>(entity: EntityClient<EntityDefsRef<TDefs>, TEntityName>, params: EntityQueryParams<TDefs[TEntityName] & EntityDef, TSelect>, options?: EntityQueryOptions): UseQueryResult<InferResult<TDefs, TDefs[TEntityName] & EntityDef, TSelect> | null>;
21
+ export {};