Skip to content

Commit 5ae905f

Browse files
committed
unify builders
1 parent 2c006ff commit 5ae905f

16 files changed

+267
-443
lines changed

README.md

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,16 @@
66

77
The simplest way to start building with Tanstack Query.
88

9-
This library builds on top of Tanstack Query to provide out-of-the-box functionality to help you get started faster, and keep the application code structured.
9+
This library builds on top of Tanstack Query to provide out-of-the-box functionality to help you get started faster, and keep the application code well-structured.
1010

11-
It uses the builder pattern, the best pattern that works with complex Typescript types.
11+
It uses the builder pattern, the best pattern for working with complex Typescript types.
1212

1313
[Visit the docs →](https://gkurt.com/react-query-builder/)
1414

1515
## Features
1616

1717
- REST client using fetch API
18-
- Automaticly created query keys and easy invalidation
18+
- Automatically created query keys and easy invalidation
1919
- Customizable with middlewares
2020
- Tag based invalidation
2121
- Declarative optimistic updates
@@ -24,17 +24,11 @@ It uses the builder pattern, the best pattern that works with complex Typescript
2424
## Advantages
2525

2626
- 💪 Strong-typed
27-
- 🧩 Consistently structured
2827
- 🚀 Features out-of-the-box
2928
- ⚙️ Customizable and extendable
3029
- 🪶 Zero dependencies
3130
- 🚢 SSR and Router compatible
3231

33-
## TODO
34-
35-
- Infinite queries
36-
- Single interface for mutations and queries
37-
3832
## Examples
3933

4034
Following code loads a list of Posts from an API, and presents a Delete button to delete each one.
@@ -49,9 +43,15 @@ const baseMutation = new HttpMutationBuilder().withBaseUrl(baseUrl);
4943

5044
type PostData = { id: number; title: string; body: string; userId: number };
5145

52-
const postsQuery = baseQuery.withTags("refreshable", "posts").withPath("/posts").withData<PostData[]>();
46+
const postsQuery = baseQuery
47+
.withTags("refreshable", "posts")
48+
.withPath("/posts")
49+
.withData<PostData[]>();
5350

54-
const deletePostMutation = baseMutation.withUpdates("posts").withMethod("delete").withPath("/posts/:id");
51+
const deletePostMutation = baseMutation
52+
.withUpdates("posts")
53+
.withMethod("delete")
54+
.withPath("/posts/:id");
5555

5656
export function MyApp() {
5757
const posts = postsQuery.useQuery({});
@@ -70,7 +70,10 @@ export function MyApp() {
7070
<h2>{post.title}</h2>
7171
<p>{post.body}</p>
7272

73-
<button onClick={() => onDelete(post.id)} disabled={deletePost.isPending}>
73+
<button
74+
onClick={() => onDelete(post.id)}
75+
disabled={deletePost.isPending}
76+
>
7477
Delete
7578
</button>
7679
</div>

examples/vite/src/App.tsx

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import './App.css';
55
import { HttpQueryBuilder } from 'react-query-builder';
66
import { queryClient } from './client';
77

8-
const baseQuery = new HttpQueryBuilder({
8+
const builder = new HttpQueryBuilder({
99
queryClient,
1010
syncChannel: new BroadcastChannel('react-query-builder'),
1111
})
@@ -17,23 +17,21 @@ const baseQuery = new HttpQueryBuilder({
1717
refreshable: unknown;
1818
}>();
1919

20-
const baseMutation = baseQuery.asMutationBuilder();
20+
const resetMutation = builder.withPath('/reset').withMethod('post').withUpdates('*');
2121

22-
const resetMutation = baseMutation.withPath('/reset').withUpdates('*');
23-
24-
const postsQuery = baseQuery
22+
const postsQuery = builder
2523
.withTags('refreshable', 'posts')
2624
.withPath('/posts')
2725
.withData<PostData[]>()
2826
.withSearch<{ page?: number }>()
2927
.withConfig({
3028
options: {
31-
initialPageParam: { search: { page: 0 } },
29+
getInitialPageParam: { search: { page: 0 } },
3230
getNextPageParam: (prev, __, lastVars) => (!prev?.length ? null : { search: { page: (lastVars?.search?.page || 0) + 1 } }),
3331
},
3432
});
3533

36-
const postQuery = baseQuery
34+
const postQuery = builder
3735
.withTags('refreshable')
3836
.withPath('/posts/:id')
3937
.withData<PostData>()
@@ -44,13 +42,13 @@ const postQuery = baseQuery
4442
return { ...res, titleUppercase: res.title.toUpperCase() };
4543
});
4644

47-
const commentsQuery = baseQuery
45+
const commentsQuery = builder
4846
.withTags('refreshable')
4947
.withPath('/comments')
5048
.withSearch<{ postId: number | null }>()
5149
.withData<CommentData[]>();
5250

53-
const editPostMutation = baseMutation
51+
const editPostMutation = builder
5452
.withPath('/posts/:id')
5553
.withMethod('put')
5654
.withBody<Partial<PostData>>()
@@ -78,7 +76,7 @@ const editPostMutation = baseMutation
7876
return res;
7977
});
8078

81-
const deletePostMutation = baseMutation.withMethod('delete').withPath('/posts/:id').withUpdates({
79+
const deletePostMutation = builder.withMethod('delete').withPath('/posts/:id').withUpdates({
8280
type: 'posts',
8381
optimistic: true,
8482
updater: 'delete-params-by-id',
@@ -92,7 +90,7 @@ function App() {
9290

9391
const deleteErrors = deletePostMutation.useMutationState(undefined, { status: 'error' }, (x) => x.state.variables?.params.id);
9492

95-
const refresh = () => baseQuery.client.operateTags({ tags: 'refreshable', operation: 'reset' });
93+
const refresh = () => builder.client.operateTags({ tags: 'refreshable', operation: 'reset' });
9694

9795
if (postId) return <PostPage postId={postId} onBack={() => setPostId(null)} />;
9896

@@ -124,8 +122,8 @@ function App() {
124122
</a>
125123

126124
<button
127-
onClick={() => deletePostMutation.mutate({ params: { id: post.id } })}
128-
disabled={deletePostMutation.isMutating() > 0}
125+
onClick={() => deletePostMutation.client.mutate({ params: { id: post.id } })}
126+
disabled={deletePostMutation.client.isMutating() > 0}
129127
>
130128
Delete
131129
</button>

src/builder/HttpMutationBuilder.ts

Lines changed: 0 additions & 115 deletions
This file was deleted.

src/builder/HttpQueryBuilder.ts

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
import { RequestError } from '../http/errors';
22
import { ExtractPathParams, HttpMethod } from '../http/types';
33
import { WithOptional } from '../type-utils';
4-
import { HttpMutationBuilder } from './HttpMutationBuilder';
5-
import { MutationBuilder } from './MutationBuilder';
64
import { QueryBuilder } from './QueryBuilder';
7-
import { QueryBuilderConfig } from './QueryBuilderFrozen';
5+
import { BuilderConfig } from './types';
86
import { HttpBaseHeaders, HttpBaseParams, HttpBaseSearch, HttpBuilderVars } from './types';
97
import { createHttpMergeVarsFn, createHttpQueryFn, createHttpQueryHashFn } from './utils';
108

@@ -20,7 +18,7 @@ export class HttpQueryBuilder<
2018
TKey extends [HttpBuilderVars] = [HttpBuilderVars<TParam, TSearch, TBody, THeader, TMeta>],
2119
> extends QueryBuilder<HttpBuilderVars<TParam, TSearch, TBody, THeader, TMeta>, TData, TError, TKey, TTags> {
2220
constructor(
23-
config?: WithOptional<QueryBuilderConfig<HttpBuilderVars<TParam, TSearch, TBody, THeader, TMeta>, TData, TError, TKey>, 'queryFn'>,
21+
config?: WithOptional<BuilderConfig<HttpBuilderVars<TParam, TSearch, TBody, THeader, TMeta>, TData, TError, TKey>, 'queryFn'>,
2422
) {
2523
const mergeVars = config?.mergeVars || createHttpMergeVarsFn();
2624
const queryFn = config?.queryFn || createHttpQueryFn(mergeVars);
@@ -103,11 +101,4 @@ export class HttpQueryBuilder<
103101
withTagTypes(): this {
104102
return this as any;
105103
}
106-
107-
protected MutationBuilderConstructor = HttpMutationBuilder as typeof MutationBuilder;
108-
109-
asMutationBuilder(): HttpMutationBuilder<TParam, TSearch, TBody, THeader, TMeta, TData, TError, TTags, TKey> {
110-
const { options, ...restConfig } = this.config;
111-
return new this.MutationBuilderConstructor(restConfig) as any;
112-
}
113104
}

src/builder/MutationBuilder.ts

Lines changed: 0 additions & 56 deletions
This file was deleted.

0 commit comments

Comments
 (0)