@openapi-qraft/react 2.3.2 â 2.4.0
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/CHANGELOG.md +6 -0
- package/README.md +167 -513
- package/package.json +6 -6
package/CHANGELOG.md
CHANGED
package/README.md
CHANGED
|
@@ -35,103 +35,208 @@ npm install @tanstack/react-query
|
|
|
35
35
|
|
|
36
36
|
## Getting Started
|
|
37
37
|
|
|
38
|
-
To get started with
|
|
39
|
-
|
|
40
|
-
callbacks to handle various React Query functionalities.
|
|
38
|
+
To get started with OpenAPI Qraft, you need to generate types and service definitions from your OpenAPI Document.
|
|
39
|
+
These are used to create type-safe hooks and interact with your API.
|
|
41
40
|
|
|
42
41
|
### 1. Generate OpenAPI Types & Services
|
|
43
42
|
|
|
44
|
-
|
|
45
|
-
and schemas from your OpenAPI Document.
|
|
46
|
-
|
|
47
|
-
To generate both TypeScript definitions and services using `openapi-qraft`, run the following command in the root directory of your project:
|
|
43
|
+
Run the following command in the root directory of your project using your package manager:
|
|
48
44
|
|
|
49
45
|
```bash
|
|
50
|
-
npx @openapi-qraft/cli --plugin tanstack-query-react --plugin openapi-typescript
|
|
46
|
+
npx @openapi-qraft/cli --plugin tanstack-query-react --plugin openapi-typescript \
|
|
47
|
+
--output-dir src/api https://raw.githubusercontent.com/swagger-api/swagger-petstore/master/src/main/resources/openapi.yaml
|
|
51
48
|
```
|
|
52
49
|
|
|
53
|
-
|
|
54
|
-
|
|
50
|
+
> ðĄ For stable project maintenance, it's recommended to install the CLI generator as a dev dependency.
|
|
51
|
+
> Read more about installation in the [documentation](https://openapi-qraft.github.io/openapi-qraft/docs/getting-started/installation).
|
|
55
52
|
|
|
56
|
-
### 2.
|
|
53
|
+
### 2. Use the generated services in your React application
|
|
57
54
|
|
|
58
|
-
|
|
55
|
+
Below are examples demonstrating how to use the generated services in your React application with
|
|
56
|
+
`useQuery`, `useMutation`, and `useInfiniteQuery` hooks from [TanStack Query](https://tanstack.com/query/latest).
|
|
59
57
|
|
|
60
|
-
|
|
61
|
-
// where `./api` is the '--output-dir' path to the services you generated
|
|
62
|
-
import { createAPIClient } from './api';
|
|
58
|
+
#### Example with `useQuery()`
|
|
63
59
|
|
|
64
|
-
|
|
65
|
-
|
|
60
|
+
```tsx title="src/App.tsx"
|
|
61
|
+
import { requestFn } from '@openapi-qraft/react';
|
|
62
|
+
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
63
|
+
import { createAPIClient } from './api'; // generated by OpenAPI Qraft
|
|
64
|
+
|
|
65
|
+
const queryClient = new QueryClient();
|
|
66
|
+
|
|
67
|
+
// Use `createAPIClient(...)` to initialize the API client as needed.
|
|
68
|
+
// It's a lightweight ðŠķ shortcut for working with TanStack Query ðī
|
|
69
|
+
const api = createAPIClient({
|
|
70
|
+
requestFn,
|
|
71
|
+
queryClient,
|
|
72
|
+
baseUrl: 'https://petstore3.swagger.io/api/v3',
|
|
73
|
+
});
|
|
66
74
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
75
|
+
function ExamplePetDetails({ petId }: { petId: number }) {
|
|
76
|
+
/**
|
|
77
|
+
* Executes the request to the API on mount:
|
|
78
|
+
* ###
|
|
79
|
+
* GET /pet/123456
|
|
80
|
+
**/
|
|
81
|
+
const {
|
|
82
|
+
data: pet,
|
|
83
|
+
isPending,
|
|
84
|
+
error,
|
|
85
|
+
} = api.pet.getPetById.useQuery({
|
|
86
|
+
path: { petId },
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
if (isPending) {
|
|
90
|
+
return <div>Loading...</div>;
|
|
91
|
+
}
|
|
70
92
|
|
|
71
|
-
|
|
93
|
+
if (error) {
|
|
94
|
+
return <div>Error: {error.message}</div>;
|
|
95
|
+
}
|
|
72
96
|
|
|
73
|
-
|
|
97
|
+
return <div>Pet Name: {pet?.name}</div>;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export default function App() {
|
|
101
|
+
return (
|
|
102
|
+
<QueryClientProvider client={queryClient}>
|
|
103
|
+
<ExamplePetDetails petId={123456} />
|
|
104
|
+
</QueryClientProvider>
|
|
105
|
+
);
|
|
106
|
+
}
|
|
107
|
+
```
|
|
74
108
|
|
|
75
|
-
|
|
109
|
+
#### Example with `useMutation()`
|
|
76
110
|
|
|
77
|
-
```tsx
|
|
78
|
-
import {
|
|
111
|
+
```tsx title="src/App.tsx"
|
|
112
|
+
import { requestFn } from '@openapi-qraft/react';
|
|
79
113
|
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
80
|
-
import {
|
|
81
|
-
|
|
82
|
-
|
|
114
|
+
import { createAPIClient } from './api'; // generated by OpenAPI Qraft
|
|
115
|
+
|
|
116
|
+
const queryClient = new QueryClient();
|
|
83
117
|
|
|
84
|
-
|
|
85
|
-
|
|
118
|
+
const api = createAPIClient({
|
|
119
|
+
requestFn,
|
|
120
|
+
queryClient,
|
|
121
|
+
baseUrl: 'https://petstore3.swagger.io/api/v3',
|
|
122
|
+
});
|
|
86
123
|
|
|
87
|
-
function
|
|
88
|
-
const
|
|
124
|
+
function EntityForm({ entityId }: { entityId: string }) {
|
|
125
|
+
const mutation = api.entities.postEntitiesIdDocuments.useMutation({
|
|
126
|
+
// âïļ useMutation() can be used with `undefined` parameters
|
|
127
|
+
path: {
|
|
128
|
+
entity_id: entityId,
|
|
129
|
+
},
|
|
130
|
+
header: {
|
|
131
|
+
'x-monite-version': '2023-09-01',
|
|
132
|
+
},
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
return (
|
|
136
|
+
<form
|
|
137
|
+
onSubmit={(event) => {
|
|
138
|
+
event.preventDefault();
|
|
139
|
+
const formData = new FormData(event.currentTarget);
|
|
140
|
+
/**
|
|
141
|
+
* Executes the request`:
|
|
142
|
+
* ###
|
|
143
|
+
* POST /entities/3e3e-3e3e-3e3e/documents
|
|
144
|
+
* x-monite-version: 2023-09-01
|
|
145
|
+
*
|
|
146
|
+
* {"company_tax_id_verification": ["verification-id"]}
|
|
147
|
+
**/
|
|
148
|
+
mutation.mutate({
|
|
149
|
+
company_tax_id_verification: [
|
|
150
|
+
String(formData.get('company_tax_id_verification')),
|
|
151
|
+
],
|
|
152
|
+
});
|
|
153
|
+
}}
|
|
154
|
+
>
|
|
155
|
+
<input name="company_tax_id_verification" />
|
|
156
|
+
<button>Submit</button>
|
|
157
|
+
</form>
|
|
158
|
+
);
|
|
159
|
+
}
|
|
89
160
|
|
|
161
|
+
export default function App() {
|
|
90
162
|
return (
|
|
91
163
|
<QueryClientProvider client={queryClient}>
|
|
92
|
-
<
|
|
93
|
-
value={{
|
|
94
|
-
baseUrl: 'https://api.sandbox.monite.com/v1', // base URL for all requests
|
|
95
|
-
requestFn, // `requestFn(...)` will be invoked for every request
|
|
96
|
-
}}
|
|
97
|
-
>
|
|
98
|
-
{children}
|
|
99
|
-
</QraftContext.Provider>
|
|
164
|
+
<EntityForm entityId="3e3e-3e3e-3e3e" />
|
|
100
165
|
</QueryClientProvider>
|
|
101
166
|
);
|
|
102
167
|
}
|
|
168
|
+
```
|
|
103
169
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
approval_policy_id: '1',
|
|
113
|
-
},
|
|
114
|
-
});
|
|
170
|
+
#### Example with `useInfiniteQuery()`
|
|
171
|
+
|
|
172
|
+
```tsx title="src/PostList.tsx"
|
|
173
|
+
import { requestFn } from '@openapi-qraft/react';
|
|
174
|
+
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
|
175
|
+
import { createAPIClient } from './api'; // generated by OpenAPI Qraft
|
|
176
|
+
|
|
177
|
+
const queryClient = new QueryClient();
|
|
115
178
|
|
|
116
|
-
|
|
179
|
+
const api = createAPIClient({
|
|
180
|
+
requestFn,
|
|
181
|
+
queryClient,
|
|
182
|
+
baseUrl: 'https://petstore3.swagger.io/api/v3',
|
|
183
|
+
});
|
|
117
184
|
|
|
118
|
-
|
|
185
|
+
/**
|
|
186
|
+
* Executes the initial request:
|
|
187
|
+
* ###
|
|
188
|
+
* GET /posts?limit=10&page=1
|
|
189
|
+
**/
|
|
190
|
+
function PostList() {
|
|
191
|
+
const infiniteQuery = api.posts.getPosts.useInfiniteQuery(
|
|
192
|
+
{ query: { limit: 10 } },
|
|
193
|
+
{
|
|
194
|
+
getNextPageParam: (lastPage, allPages, lastPageParams) => {
|
|
195
|
+
if (lastPage.length < 10) return; // if less than 10 items, there are no more pages
|
|
196
|
+
return {
|
|
197
|
+
query: {
|
|
198
|
+
page: Number(lastPageParams.query?.page) + 1,
|
|
199
|
+
},
|
|
200
|
+
};
|
|
201
|
+
},
|
|
202
|
+
initialPageParam: {
|
|
203
|
+
query: {
|
|
204
|
+
page: 1, // will be used in initial request
|
|
205
|
+
},
|
|
206
|
+
},
|
|
207
|
+
}
|
|
208
|
+
);
|
|
119
209
|
|
|
120
|
-
return
|
|
210
|
+
return (
|
|
211
|
+
<div>
|
|
212
|
+
{infiniteQuery.data?.pages.map((page, pageIndex) => (
|
|
213
|
+
<ul key={pageIndex}>
|
|
214
|
+
{page.map((post) => (
|
|
215
|
+
<li key={post.id}>{post.title}</li>
|
|
216
|
+
))}
|
|
217
|
+
</ul>
|
|
218
|
+
))}
|
|
219
|
+
<button
|
|
220
|
+
onClick={() => {
|
|
221
|
+
// âŽïļ Executes GET /posts?limit=10&page=2
|
|
222
|
+
infiniteQuery.fetchNextPage();
|
|
223
|
+
}}
|
|
224
|
+
>
|
|
225
|
+
Load More
|
|
226
|
+
</button>
|
|
227
|
+
</div>
|
|
228
|
+
);
|
|
121
229
|
}
|
|
122
230
|
|
|
123
|
-
function App() {
|
|
231
|
+
export default function App() {
|
|
124
232
|
return (
|
|
125
|
-
<
|
|
126
|
-
<
|
|
127
|
-
</
|
|
233
|
+
<QueryClientProvider client={queryClient}>
|
|
234
|
+
<PostList />
|
|
235
|
+
</QueryClientProvider>
|
|
128
236
|
);
|
|
129
237
|
}
|
|
130
238
|
```
|
|
131
239
|
|
|
132
|
-
> The Qraft is designed to be as modular as possible, enabling you to integrate your own request client and serializers.
|
|
133
|
-
> To ensure optimal tree-shaking, we do not include default serializers in the functions.
|
|
134
|
-
|
|
135
240
|
## Supported Hooks
|
|
136
241
|
|
|
137
242
|
- [x] [`useQuery(...)`](https://openapi-qraft.github.io/openapi-qraft/docs/hooks/useQuery)
|
|
@@ -173,461 +278,10 @@ function App() {
|
|
|
173
278
|
- [x] [`getInfiniteQueryState(...)`](https://openapi-qraft.github.io/openapi-qraft/docs/query-client/getInfiniteQueryState)
|
|
174
279
|
- [x] [`getMutationKey(...)`](https://openapi-qraft.github.io/openapi-qraft/docs/query-client/getMutationKey)
|
|
175
280
|
|
|
176
|
-
## Usage
|
|
177
|
-
|
|
178
|
-
With the client set up, you can now use the generated Hooks in your React Components to fetch data, execute mutations,
|
|
179
|
-
and more.
|
|
180
|
-
|
|
181
|
-
### [useQuery(...) ð](https://openapi-qraft.github.io/openapi-qraft/docs/hooks/useQuery)
|
|
182
|
-
|
|
183
|
-
```ts
|
|
184
|
-
/**
|
|
185
|
-
* Will execute the request:
|
|
186
|
-
* ###
|
|
187
|
-
* GET /entities?sort=updated_at
|
|
188
|
-
* x-monite-version: 2023-09-01
|
|
189
|
-
**/
|
|
190
|
-
const { data, error, isPending } = qraft.entities.getEntities.useQuery({
|
|
191
|
-
header: {
|
|
192
|
-
'x-monite-version': '2023-09-01',
|
|
193
|
-
},
|
|
194
|
-
query: {
|
|
195
|
-
sort: 'updated_at',
|
|
196
|
-
},
|
|
197
|
-
});
|
|
198
|
-
```
|
|
199
|
-
|
|
200
|
-
### [useMutation(...) ð](https://openapi-qraft.github.io/openapi-qraft/docs/hooks/useMutation)
|
|
201
|
-
|
|
202
|
-
#### With predefined parameters
|
|
203
|
-
|
|
204
|
-
In case you know the query parameters that are needed for mutation, you can preset them. In this case, you must pass
|
|
205
|
-
only `body` when calling `mutate()` function:
|
|
206
|
-
|
|
207
|
-
```ts
|
|
208
|
-
const mutation = qraft.entities.postEntitiesIdDocuments.useMutation({
|
|
209
|
-
path: {
|
|
210
|
-
entity_id: '3e3e-3e3e-3e3e',
|
|
211
|
-
},
|
|
212
|
-
header: {
|
|
213
|
-
'x-monite-version': '2023-09-01',
|
|
214
|
-
},
|
|
215
|
-
});
|
|
216
|
-
|
|
217
|
-
/**
|
|
218
|
-
* Will execute the request when call `mutation.mutate(...)`:
|
|
219
|
-
* ###
|
|
220
|
-
* POST /entities/3e3e-3e3e-3e3e/documents
|
|
221
|
-
* x-monite-version: 2023-09-01
|
|
222
|
-
*
|
|
223
|
-
* {"company_tax_id_verification": ["verification-id"]}
|
|
224
|
-
**/
|
|
225
|
-
mutation.mutate({
|
|
226
|
-
company_tax_id_verification: ['verification-id'],
|
|
227
|
-
});
|
|
228
|
-
```
|
|
229
|
-
|
|
230
|
-
#### Without predefined parameters
|
|
231
|
-
|
|
232
|
-
It happens that at the time of calling the Mutation Hook, you don't yet know what query parameters to be passed. In this
|
|
233
|
-
case,
|
|
234
|
-
you will need to pass the _parameters and the body_ of the request when you call `mutate()` function:
|
|
235
|
-
|
|
236
|
-
```ts
|
|
237
|
-
const mutation = qraft.entities.postEntitiesIdDocuments.useMutation();
|
|
238
|
-
|
|
239
|
-
/**
|
|
240
|
-
* Will execute the request when call `mutation.mutate(...)`:
|
|
241
|
-
* ###
|
|
242
|
-
* POST /entities/3e3e-3e3e-3e3e/documents
|
|
243
|
-
* x-monite-version: 2023-09-01
|
|
244
|
-
*
|
|
245
|
-
* {"company_tax_id_verification": ["verification-id"]}
|
|
246
|
-
**/
|
|
247
|
-
mutation.mutate({
|
|
248
|
-
path: {
|
|
249
|
-
entity_id: '3e3e-3e3e-3e3e',
|
|
250
|
-
},
|
|
251
|
-
header: {
|
|
252
|
-
'x-monite-version': '2023-09-01',
|
|
253
|
-
},
|
|
254
|
-
body: {
|
|
255
|
-
company_tax_id_verification: ['verification-id'],
|
|
256
|
-
},
|
|
257
|
-
});
|
|
258
|
-
```
|
|
259
|
-
|
|
260
|
-
### [useMutationState(...) ð](https://openapi-qraft.github.io/openapi-qraft/docs/hooks/useMutationState)
|
|
261
|
-
|
|
262
|
-
Mutation state is a helper hook that provides the current state of a mutation globally.
|
|
263
|
-
It could be used to track the status of a mutation in any component, which is useful for showing loading spinners or
|
|
264
|
-
disabling buttons.
|
|
265
|
-
|
|
266
|
-
```ts
|
|
267
|
-
const { mutate } = qraft.entities.postEntitiesIdDocuments.useMutation({
|
|
268
|
-
path: {
|
|
269
|
-
entity_id: '3e3e-3e3e-3e3e',
|
|
270
|
-
},
|
|
271
|
-
header: {
|
|
272
|
-
'x-monite-version': '2023-09-01',
|
|
273
|
-
},
|
|
274
|
-
});
|
|
275
|
-
|
|
276
|
-
const mutationState = qraft.entities.postEntitiesIdDocuments
|
|
277
|
-
// You can pass Partial parameters, or even `undefined` to specify filters
|
|
278
|
-
.useMutationState({ path: { entity_id: '3e3e-3e3e-3e3e' } })
|
|
279
|
-
?.at(0);
|
|
280
|
-
|
|
281
|
-
useEffect(() => {
|
|
282
|
-
if (!mutationState || mutationState.status === 'iddle') {
|
|
283
|
-
mutate({ company_tax_id_verification: ['verification-id'] });
|
|
284
|
-
}
|
|
285
|
-
}, [mutate, mutationState?.status]);
|
|
286
|
-
```
|
|
287
|
-
|
|
288
|
-
### [useInfiniteQuery(...) ð](https://openapi-qraft.github.io/openapi-qraft/docs/hooks/useInfiniteQuery)
|
|
289
|
-
|
|
290
|
-
#### _Offset-based_
|
|
291
|
-
|
|
292
|
-
```ts
|
|
293
|
-
/**
|
|
294
|
-
* Will execute the initial request:
|
|
295
|
-
* ###
|
|
296
|
-
* GET /posts?limit=10&page=1
|
|
297
|
-
**/
|
|
298
|
-
const infiniteQuery = qraft.posts.getPosts.useInfiniteQuery(
|
|
299
|
-
{ query: { limit: 10 } },
|
|
300
|
-
{
|
|
301
|
-
// * required by TanStack Query
|
|
302
|
-
getNextPageParam: (lastPage, allPages, lastPageParams) => {
|
|
303
|
-
if (lastPage.length < 10) return; // if less than 10 items, there are no more pages
|
|
304
|
-
return {
|
|
305
|
-
query: {
|
|
306
|
-
page: Number(lastPageParams.query?.page) + 1,
|
|
307
|
-
},
|
|
308
|
-
};
|
|
309
|
-
},
|
|
310
|
-
// * required by TanStack Query
|
|
311
|
-
initialPageParam: {
|
|
312
|
-
query: {
|
|
313
|
-
page: 1, // will be used in initial request
|
|
314
|
-
},
|
|
315
|
-
},
|
|
316
|
-
}
|
|
317
|
-
);
|
|
318
|
-
|
|
319
|
-
// âŽïļ will execute GET /posts?limit=10&page=2
|
|
320
|
-
infiniteQuery.fetchNextPage();
|
|
321
|
-
```
|
|
322
|
-
|
|
323
|
-
#### _Pagination token_ based
|
|
324
|
-
|
|
325
|
-
If your API uses pagination tokens, the Infinite Queries implementation becomes quite laconically:
|
|
326
|
-
|
|
327
|
-
```ts
|
|
328
|
-
/**
|
|
329
|
-
* Will execute the initial request:
|
|
330
|
-
* ###
|
|
331
|
-
* GET /data_exports
|
|
332
|
-
* x-monite-version: 2023-09-01
|
|
333
|
-
* x-monite-entity-id: 3e3e-3e3e-3e3e
|
|
334
|
-
**/
|
|
335
|
-
const infiniteQuery = qraft.dataExports.getDataExports.useInfiniteQuery(
|
|
336
|
-
{
|
|
337
|
-
header: {
|
|
338
|
-
'x-monite-version': '2023-09-01',
|
|
339
|
-
'x-monite-entity-id': '3e3e-3e3e-3e3e',
|
|
340
|
-
},
|
|
341
|
-
},
|
|
342
|
-
{
|
|
343
|
-
// * required by TanStack Query
|
|
344
|
-
initialPageParam: {
|
|
345
|
-
query: { pagination_token: undefined }, // will be used in initial request
|
|
346
|
-
},
|
|
347
|
-
// * required by TanStack Query
|
|
348
|
-
getNextPageParam: (lastPage, allPages, lastPageParam) => ({
|
|
349
|
-
query: { pagination_token: lastPage.next_pagination_token },
|
|
350
|
-
}),
|
|
351
|
-
// * optional
|
|
352
|
-
getPreviousPageParam: (firstPage, allPages, firstPageParam) => ({
|
|
353
|
-
query: { pagination_token: firstPage.prev_pagination_token },
|
|
354
|
-
}),
|
|
355
|
-
}
|
|
356
|
-
);
|
|
357
|
-
|
|
358
|
-
// âŽïļ will execute GET /data_exports?pagination_token=<NEXT_PAGINATION_TOKEN>
|
|
359
|
-
infiniteQuery.fetchNextPage();
|
|
360
|
-
|
|
361
|
-
// âŽïļ will execute GET /data_exports?pagination_token=<PREV_PAGINATION_TOKEN>
|
|
362
|
-
infiniteQuery.fetchPreviousPage();
|
|
363
|
-
```
|
|
364
|
-
|
|
365
|
-
### [useQueries(...) ð](https://openapi-qraft.github.io/openapi-qraft/docs/hooks/useQueries)
|
|
366
|
-
|
|
367
|
-
```ts
|
|
368
|
-
/**
|
|
369
|
-
* Will execute the request two queries:
|
|
370
|
-
* ###
|
|
371
|
-
* GET /entities/3e3e-3e3e-3e3e
|
|
372
|
-
* x-monite-version: 2023-09-01
|
|
373
|
-
* ###
|
|
374
|
-
* GET /entities/5c5c-5c5c-5c5c
|
|
375
|
-
* x-monite-version: 2023-09-01
|
|
376
|
-
**/
|
|
377
|
-
qraft.entities.getEntities.useQueries({
|
|
378
|
-
queries: [
|
|
379
|
-
{
|
|
380
|
-
parameters: {
|
|
381
|
-
header: {
|
|
382
|
-
'x-monite-version': '2023-09-01',
|
|
383
|
-
},
|
|
384
|
-
path: {
|
|
385
|
-
entity_id: '3e3e-3e3e-3e3e',
|
|
386
|
-
},
|
|
387
|
-
},
|
|
388
|
-
},
|
|
389
|
-
{
|
|
390
|
-
parameters: {
|
|
391
|
-
header: {
|
|
392
|
-
'x-monite-version': '2023-09-01',
|
|
393
|
-
},
|
|
394
|
-
path: {
|
|
395
|
-
entity_id: '5c5c-5c5c-5c5c',
|
|
396
|
-
},
|
|
397
|
-
},
|
|
398
|
-
},
|
|
399
|
-
],
|
|
400
|
-
combine: (results) => results.map((result) => result.data),
|
|
401
|
-
});
|
|
402
|
-
```
|
|
403
|
-
|
|
404
|
-
## [`QueryClient`](https://tanstack.com/query/latest/docs/reference/QueryClient) Methods
|
|
405
|
-
|
|
406
|
-
#### [setQueryData(...) ð](https://openapi-qraft.github.io/openapi-qraft/docs/query-client/setQueryData)
|
|
407
|
-
|
|
408
|
-
```ts
|
|
409
|
-
qraft.pet.getPetById.setQueryData(
|
|
410
|
-
{ path: { petId: 123 } }, // Query Key parameters
|
|
411
|
-
{ id: 123, name: 'Rex' }, // Data to set
|
|
412
|
-
queryClient
|
|
413
|
-
);
|
|
414
|
-
```
|
|
415
|
-
|
|
416
|
-
### [invalidateQueries(...) ð](https://openapi-qraft.github.io/openapi-qraft/docs/query-client/invalidateQueries)
|
|
417
|
-
|
|
418
|
-
[Queries Invalidation ð](https://tanstack.com/query/latest/docs/framework/react/guides/query-invalidation) is possible
|
|
419
|
-
using `<operation>.invalidateQueries(...)` method.
|
|
420
|
-
This method is a wrapper around the `queryClient.invalidateQueries(...)`.
|
|
421
|
-
|
|
422
|
-
##### Invalidation with _parameters_:
|
|
423
|
-
|
|
424
|
-
To invalidate queries, with the specified parameters, you can use the `invalidateQueries` method:
|
|
425
|
-
|
|
426
|
-
```ts
|
|
427
|
-
/**
|
|
428
|
-
* Will invalidate the queries with the specified parameters:
|
|
429
|
-
* ###
|
|
430
|
-
* GET /entities/3e3e-3e3e-3e3e
|
|
431
|
-
* x-monite-version: 2023-09-01
|
|
432
|
-
**/
|
|
433
|
-
qraft.entities.getEntities.invalidateQueries(
|
|
434
|
-
{
|
|
435
|
-
parameters: {
|
|
436
|
-
header: {
|
|
437
|
-
'x-monite-version': '2023-09-01',
|
|
438
|
-
},
|
|
439
|
-
path: {
|
|
440
|
-
entity_id: '3e3e-3e3e-3e3e',
|
|
441
|
-
},
|
|
442
|
-
},
|
|
443
|
-
},
|
|
444
|
-
queryClient
|
|
445
|
-
);
|
|
446
|
-
```
|
|
447
|
-
|
|
448
|
-
#### Invalidation without _parameters_:
|
|
449
|
-
|
|
450
|
-
To invalidate all queries for a specific endpoint, you can call `invalidateQueries` without any parameters:
|
|
451
|
-
|
|
452
|
-
```ts
|
|
453
|
-
/**
|
|
454
|
-
* Will invalidate the queries matching the specified endpoint:
|
|
455
|
-
* ###
|
|
456
|
-
* GET /entities/3e3e-3e3e-3e3e
|
|
457
|
-
* x-monite-version: 2023-09-01
|
|
458
|
-
* ###
|
|
459
|
-
* GET /entities/4c4c-4c4c-4c4c
|
|
460
|
-
* x-monite-version: 2023-09-01
|
|
461
|
-
**/
|
|
462
|
-
qraft.entities.getEntities.invalidateQueries(queryClient);
|
|
463
|
-
```
|
|
464
|
-
|
|
465
|
-
#### Invalidation with _queryKey_:
|
|
466
|
-
|
|
467
|
-
It could be useful to invalidate queries using `queryKey` directly:
|
|
468
|
-
|
|
469
|
-
```ts
|
|
470
|
-
/**
|
|
471
|
-
* Will invalidate the queries matching the specified endpoint:
|
|
472
|
-
* ###
|
|
473
|
-
* GET /entities/3e3e-3e3e-3e3e
|
|
474
|
-
* x-monite-version: 2023-09-01
|
|
475
|
-
**/
|
|
476
|
-
qraft.entities.getEntities.invalidateQueries(
|
|
477
|
-
{
|
|
478
|
-
// `queryKey` is fully typed to `qraft.entities.getEntities`
|
|
479
|
-
queryKey: qraft.entities.getEntities.getQueryKey({
|
|
480
|
-
header: {
|
|
481
|
-
'x-monite-version': '2023-09-01',
|
|
482
|
-
},
|
|
483
|
-
path: {
|
|
484
|
-
entity_id: '3e3e-3e3e-3e3e',
|
|
485
|
-
},
|
|
486
|
-
}),
|
|
487
|
-
},
|
|
488
|
-
queryClient
|
|
489
|
-
);
|
|
490
|
-
```
|
|
491
|
-
|
|
492
|
-
#### [Invalidation with predicate: ð](https://tanstack.com/query/latest/docs/framework/react/guides/filters#query-filters)
|
|
493
|
-
|
|
494
|
-
The `predicate(...)` function will be used as a final filter on all matching queries.
|
|
495
|
-
|
|
496
|
-
```ts
|
|
497
|
-
/**
|
|
498
|
-
* Will invalidate the queries matching the specified endpoint and predicate:
|
|
499
|
-
* ###
|
|
500
|
-
* GET /entities/3e3e-3e3e-3e3e
|
|
501
|
-
* x-monite-version: 2023-09-01
|
|
502
|
-
**/
|
|
503
|
-
qraft.entities.getEntities.invalidateQueries(
|
|
504
|
-
{
|
|
505
|
-
parameters, // * optional, or specific parameters, alternatively, you can use `queryKey`
|
|
506
|
-
predicate: (query) => {
|
|
507
|
-
// `infinite`âŽïļ property will preset for Infinite Queries
|
|
508
|
-
if ('infinite' in query.queryKey[0]) return false;
|
|
509
|
-
|
|
510
|
-
// `queryKey`âŽïļ is fully typed to `qraft.entities.getEntities` operation parameters
|
|
511
|
-
if (query.queryKey[1].path.entity_id === '4c4c-4c4c-4c4c') return false;
|
|
512
|
-
|
|
513
|
-
return true;
|
|
514
|
-
},
|
|
515
|
-
},
|
|
516
|
-
queryClient
|
|
517
|
-
);
|
|
518
|
-
```
|
|
519
|
-
|
|
520
|
-
### [fetchQuery(...) ð](https://openapi-qraft.github.io/openapi-qraft/docs/query-client/fetchQuery)
|
|
521
|
-
|
|
522
|
-
```ts
|
|
523
|
-
/**
|
|
524
|
-
* Will execute the request:
|
|
525
|
-
* ###
|
|
526
|
-
* GET /posts?limit=10
|
|
527
|
-
**/
|
|
528
|
-
import { requestFn } from '@openapi-qraft/react';
|
|
529
|
-
import { QueryClient } from '@tanstack/react-query';
|
|
530
|
-
|
|
531
|
-
const queryClient = new QueryClient();
|
|
532
|
-
|
|
533
|
-
const posts = qraft.posts.getPosts.fetchQuery(
|
|
534
|
-
{
|
|
535
|
-
parameters: { query: { limit: 10 } },
|
|
536
|
-
/**
|
|
537
|
-
* Request function should be provided, otherwise it will throw an error
|
|
538
|
-
* if default `queryFn` is not set previously using
|
|
539
|
-
* `QueryClient.setDefaultOptions(...)` method
|
|
540
|
-
*/
|
|
541
|
-
requestFn: requestFn,
|
|
542
|
-
baseUrl: 'https://api.sandbox.monite.com/v1', // must be provided if `requestFn` is set
|
|
543
|
-
},
|
|
544
|
-
queryClient
|
|
545
|
-
);
|
|
546
|
-
```
|
|
547
|
-
|
|
548
|
-
### [fetchInfiniteQuery(...) ð](https://openapi-qraft.github.io/openapi-qraft/docs/query-client/fetchInfiniteQuery)
|
|
549
|
-
|
|
550
|
-
```ts
|
|
551
|
-
/**
|
|
552
|
-
* Will execute the initial request:
|
|
553
|
-
* ###
|
|
554
|
-
* GET /posts?limit=10&page=1
|
|
555
|
-
* ###
|
|
556
|
-
* And then will execute the next page request:
|
|
557
|
-
* GET /posts?limit=10&page=2
|
|
558
|
-
**/
|
|
559
|
-
import { requestFn } from '@openapi-qraft/react';
|
|
560
|
-
import { QueryClient } from '@tanstack/react-query';
|
|
561
|
-
|
|
562
|
-
const queryClient = new QueryClient();
|
|
563
|
-
|
|
564
|
-
const posts = qraft.posts.getPosts.fetchInfiniteQuery(
|
|
565
|
-
{
|
|
566
|
-
parameters: { query: { limit: 10 } },
|
|
567
|
-
pages: 2, // How many pages to fetch
|
|
568
|
-
initialPageParam: {
|
|
569
|
-
query: { pagination_token: undefined }, // will be used in initial request
|
|
570
|
-
},
|
|
571
|
-
getNextPageParam: (lastPage, allPages, lastPageParam) => ({
|
|
572
|
-
query: { pagination_token: lastPage.next_pagination_token },
|
|
573
|
-
}),
|
|
574
|
-
/**
|
|
575
|
-
* Request function should be provided, otherwise it will throw an error
|
|
576
|
-
* if default `queryFn` is not set previously using
|
|
577
|
-
* `QueryClient.setDefaultOptions(...)` method
|
|
578
|
-
*/
|
|
579
|
-
requestFn: requestFn,
|
|
580
|
-
baseUrl: 'https://api.sandbox.monite.com/v1', // must be provided if `requestFn` is set
|
|
581
|
-
},
|
|
582
|
-
queryClient
|
|
583
|
-
);
|
|
584
|
-
|
|
585
|
-
console.log(
|
|
586
|
-
posts.pages, // all fetched pages
|
|
587
|
-
posts.pageParams // all page parameters
|
|
588
|
-
);
|
|
589
|
-
```
|
|
590
|
-
|
|
591
|
-
### Authorization and Custom Requests
|
|
592
|
-
|
|
593
|
-
To override any request, you can provide a custom `request` function to the `QraftContext`.
|
|
594
|
-
|
|
595
|
-
In the example below, we provide a custom `request` function to the `QraftContext` to handle the authorization token
|
|
596
|
-
using a custom `fetchToken` async function.
|
|
597
|
-
|
|
598
|
-
```tsx
|
|
599
|
-
import { QraftContext, requestFn } from '@openapi-qraft/react';
|
|
600
|
-
import { fetchToken } from './auth';
|
|
601
|
-
|
|
602
|
-
function QraftProvider({ children }: { children: React.ReactNode }) {
|
|
603
|
-
return (
|
|
604
|
-
<QraftContext.Provider
|
|
605
|
-
value={{
|
|
606
|
-
baseUrl: 'https://api.sandbox.monite.com/v1',
|
|
607
|
-
async requestFn(schema, requestInfo) {
|
|
608
|
-
const token = await fetchToken();
|
|
609
|
-
|
|
610
|
-
return requestFn(schema, {
|
|
611
|
-
...requestInfo,
|
|
612
|
-
/** Specify your predefined Headers **/
|
|
613
|
-
headers: {
|
|
614
|
-
Authorization: `Bearer ${token}`,
|
|
615
|
-
},
|
|
616
|
-
});
|
|
617
|
-
},
|
|
618
|
-
}}
|
|
619
|
-
>
|
|
620
|
-
{children}
|
|
621
|
-
</QraftContext.Provider>
|
|
622
|
-
);
|
|
623
|
-
}
|
|
624
|
-
```
|
|
625
|
-
|
|
626
281
|
## Contributing
|
|
627
282
|
|
|
628
283
|
Contributions are welcome! If you have suggestions or want to improve `@openapi-qraft/react`, please feel free to submit
|
|
629
|
-
a
|
|
630
|
-
pull request or open an issue.
|
|
284
|
+
a pull request or open an issue.
|
|
631
285
|
|
|
632
286
|
## License
|
|
633
287
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openapi-qraft/react",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.0",
|
|
4
4
|
"description": "OpenAPI client for React, providing type-safe requests and dynamic TanStack Query React Hooks via a modular, Proxy-based architecture.",
|
|
5
5
|
"scripts": {
|
|
6
6
|
"build": "NODE_ENV=production rollup --config rollup.config.mjs && tsc --project tsconfig.build.json --emitDeclarationOnly",
|
|
@@ -10,12 +10,12 @@
|
|
|
10
10
|
"typecheck": "tsc --noEmit",
|
|
11
11
|
"lint": "eslint",
|
|
12
12
|
"clean": "rimraf dist/",
|
|
13
|
-
"codegen": "openapi-qraft --
|
|
13
|
+
"codegen": "openapi-qraft --redocly && yarn _prettify-api",
|
|
14
14
|
"_prettify-api": "prettier --write src/tests/fixtures/api/**/*.ts"
|
|
15
15
|
},
|
|
16
16
|
"sideEffects": false,
|
|
17
17
|
"dependencies": {
|
|
18
|
-
"@openapi-qraft/tanstack-query-react-types": "2.
|
|
18
|
+
"@openapi-qraft/tanstack-query-react-types": "2.4.0"
|
|
19
19
|
},
|
|
20
20
|
"peerDependencies": {
|
|
21
21
|
"@tanstack/query-core": "^5.0.0",
|
|
@@ -23,11 +23,11 @@
|
|
|
23
23
|
"react": "^18 || ^19"
|
|
24
24
|
},
|
|
25
25
|
"devDependencies": {
|
|
26
|
-
"@openapi-qraft/cli": "2.
|
|
26
|
+
"@openapi-qraft/cli": "2.4.0",
|
|
27
27
|
"@openapi-qraft/eslint-config": "1.0.1",
|
|
28
|
-
"@openapi-qraft/openapi-typescript-plugin": "^1.2.
|
|
28
|
+
"@openapi-qraft/openapi-typescript-plugin": "^1.2.13",
|
|
29
29
|
"@openapi-qraft/rollup-config": "1.1.1",
|
|
30
|
-
"@openapi-qraft/tanstack-query-react-plugin": "2.
|
|
30
|
+
"@openapi-qraft/tanstack-query-react-plugin": "2.4.0",
|
|
31
31
|
"@openapi-qraft/test-fixtures": "1.0.1",
|
|
32
32
|
"@tanstack/query-core": "^5.66.3",
|
|
33
33
|
"@tanstack/react-query": "^5.66.3",
|