@ventlio/tanstack-query 0.5.12 → 0.5.13
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 +178 -150
- package/dist/config/bootstrapQueryRequest.d.ts +6 -0
- package/dist/config/useEnvironmentVariables.d.ts +4 -0
- package/dist/index.mjs +306 -89
- package/dist/index.mjs.map +1 -1
- package/dist/node_modules/@tanstack/react-store/dist/esm/index.js +1 -1
- package/dist/node_modules/{@tanstack/react-store/node_modules/use-sync-external-store → use-sync-external-store}/cjs/use-sync-external-store-shim/with-selector.development.js +1 -1
- package/dist/node_modules/use-sync-external-store/cjs/use-sync-external-store-shim/with-selector.development.js.map +1 -0
- package/dist/node_modules/{@tanstack/react-store/node_modules/use-sync-external-store → use-sync-external-store}/cjs/use-sync-external-store-shim/with-selector.production.js +1 -1
- package/dist/node_modules/use-sync-external-store/cjs/use-sync-external-store-shim/with-selector.production.js.map +1 -0
- package/dist/node_modules/{@tanstack/react-store/node_modules/use-sync-external-store → use-sync-external-store}/cjs/use-sync-external-store-shim.development.js +1 -1
- package/dist/node_modules/use-sync-external-store/cjs/use-sync-external-store-shim.development.js.map +1 -0
- package/dist/node_modules/{@tanstack/react-store/node_modules/use-sync-external-store → use-sync-external-store}/cjs/use-sync-external-store-shim.production.js +1 -1
- package/dist/node_modules/use-sync-external-store/cjs/use-sync-external-store-shim.production.js.map +1 -0
- package/dist/node_modules/{@tanstack/react-store/node_modules/use-sync-external-store → use-sync-external-store}/shim/index.js +1 -1
- package/dist/node_modules/use-sync-external-store/shim/index.js.map +1 -0
- package/dist/node_modules/{@tanstack/react-store/node_modules/use-sync-external-store → use-sync-external-store}/shim/with-selector.js +1 -1
- package/dist/node_modules/use-sync-external-store/shim/with-selector.js.map +1 -0
- package/dist/queries/useGetRequest.d.ts +12 -2
- package/dist/request/make-request.d.ts +12 -1
- package/dist/src/config/bootstrapQueryRequest.js +41 -1
- package/dist/src/config/bootstrapQueryRequest.js.map +1 -1
- package/dist/src/config/useEnvironmentVariables.js +34 -3
- package/dist/src/config/useEnvironmentVariables.js.map +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/queries/useDeleteRequest.js +19 -14
- package/dist/src/queries/useDeleteRequest.js.map +1 -1
- package/dist/src/queries/useGetInfiniteRequest.js +17 -12
- package/dist/src/queries/useGetInfiniteRequest.js.map +1 -1
- package/dist/src/queries/useGetRequest.js +86 -28
- package/dist/src/queries/useGetRequest.js.map +1 -1
- package/dist/src/queries/usePatchRequest.js +19 -14
- package/dist/src/queries/usePatchRequest.js.map +1 -1
- package/dist/src/queries/usePostRequest.js +18 -13
- package/dist/src/queries/usePostRequest.js.map +1 -1
- package/dist/src/request/make-request.js +75 -6
- package/dist/src/request/make-request.js.map +1 -1
- package/dist/types/index.d.ts +24 -5
- package/package.json +2 -2
- package/src/config/bootstrapQueryRequest.ts +47 -2
- package/src/config/useEnvironmentVariables.ts +41 -3
- package/src/queries/useDeleteRequest.ts +18 -20
- package/src/queries/useGetInfiniteRequest.ts +17 -17
- package/src/queries/useGetRequest.ts +109 -33
- package/src/queries/usePatchRequest.ts +19 -16
- package/src/queries/usePostRequest.ts +18 -15
- package/src/queries/usePutRequest.ts +16 -15
- package/src/request/make-request.ts +112 -15
- package/src/types/index.ts +38 -4
- package/dist/node_modules/@tanstack/react-store/node_modules/use-sync-external-store/cjs/use-sync-external-store-shim/with-selector.development.js.map +0 -1
- package/dist/node_modules/@tanstack/react-store/node_modules/use-sync-external-store/cjs/use-sync-external-store-shim/with-selector.production.js.map +0 -1
- package/dist/node_modules/@tanstack/react-store/node_modules/use-sync-external-store/cjs/use-sync-external-store-shim.development.js.map +0 -1
- package/dist/node_modules/@tanstack/react-store/node_modules/use-sync-external-store/cjs/use-sync-external-store-shim.production.js.map +0 -1
- package/dist/node_modules/@tanstack/react-store/node_modules/use-sync-external-store/shim/index.js.map +0 -1
- package/dist/node_modules/@tanstack/react-store/node_modules/use-sync-external-store/shim/with-selector.js.map +0 -1
package/README.md
CHANGED
|
@@ -19,13 +19,15 @@ But we were not discouraged. So, we set out to find a solution which led to the
|
|
|
19
19
|
- [✅] Post, Get, Patch Requests
|
|
20
20
|
- [✅] Query key tracker to track dynamic query and help fetch query cache from any page
|
|
21
21
|
- [✅] Persistent queries implementation (Not completed)
|
|
22
|
-
- [
|
|
23
|
-
- [
|
|
24
|
-
- [
|
|
25
|
-
- [
|
|
22
|
+
- [✅] Put request
|
|
23
|
+
- [✅] Generic return type (this is currently an issue if the API does not return object with the necessary properties required by the library)
|
|
24
|
+
- [✅] Generic Pagination for any response without infinite queries
|
|
25
|
+
- [✅] Infinite Get Query implementation (still using implementation meant for our use case)
|
|
26
|
+
- [✅] Enhanced middleware system with chainable middleware
|
|
27
|
+
- [✅] Cross-framework compatibility (Vite, Next.js, CRA, etc.)
|
|
26
28
|
- [❌] Server sent events
|
|
27
29
|
- [❌] Socket implementations
|
|
28
|
-
- [
|
|
30
|
+
- [✅] Tests
|
|
29
31
|
|
|
30
32
|
## Installation
|
|
31
33
|
|
|
@@ -85,6 +87,9 @@ REACT_APP_API_TIMEOUT=300000
|
|
|
85
87
|
NEXT_PUBLIC_API_URL='https://api.example.com'
|
|
86
88
|
NEXT_PUBLIC_API_TIMEOUT=300000
|
|
87
89
|
|
|
90
|
+
# For Vite (New!)
|
|
91
|
+
VITE_API_URL='https://api.example.com'
|
|
92
|
+
VITE_API_TIMEOUT=300000
|
|
88
93
|
```
|
|
89
94
|
|
|
90
95
|
```js
|
|
@@ -107,6 +112,68 @@ bootstrapQueryRequest(queryClient, {
|
|
|
107
112
|
modelConfig: {
|
|
108
113
|
idColumn: 'id', // used for useQueryModel to uniquely identify query data in a collection/array instance
|
|
109
114
|
},
|
|
115
|
+
// NEW: Configure custom pagination
|
|
116
|
+
pagination: {
|
|
117
|
+
pageParamName: 'page', // default page parameter name
|
|
118
|
+
// Custom function to extract pagination data from response
|
|
119
|
+
extractPagination: (response) => {
|
|
120
|
+
// Example for a different API format
|
|
121
|
+
return {
|
|
122
|
+
current_page: response.data.meta.currentPage,
|
|
123
|
+
next_page: response.data.meta.currentPage + 1,
|
|
124
|
+
previous_page: response.data.meta.currentPage - 1,
|
|
125
|
+
size: response.data.meta.perPage,
|
|
126
|
+
page_count: response.data.meta.lastPage,
|
|
127
|
+
total: response.data.meta.total,
|
|
128
|
+
};
|
|
129
|
+
},
|
|
130
|
+
// Custom function to build pagination URL
|
|
131
|
+
buildPaginationUrl: (url, page) => {
|
|
132
|
+
// Custom implementation
|
|
133
|
+
const [pathname, queryString] = url.split('?');
|
|
134
|
+
const queryParams = new URLSearchParams(queryString || '');
|
|
135
|
+
queryParams.set('page', String(page));
|
|
136
|
+
return pathname + '?' + queryParams.toString();
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
// NEW: Enhanced middleware system
|
|
140
|
+
middleware: [
|
|
141
|
+
// Array of middleware functions that will be executed in order
|
|
142
|
+
async (context, next) => {
|
|
143
|
+
// Log request
|
|
144
|
+
console.log('Request:', context.path);
|
|
145
|
+
|
|
146
|
+
// Continue to next middleware or make the request
|
|
147
|
+
const response = await next();
|
|
148
|
+
|
|
149
|
+
// Log response
|
|
150
|
+
console.log('Response:', response);
|
|
151
|
+
|
|
152
|
+
return response;
|
|
153
|
+
},
|
|
154
|
+
// Authentication middleware
|
|
155
|
+
async (context, next) => {
|
|
156
|
+
// Add authentication token if available
|
|
157
|
+
const token = localStorage.getItem('auth_token');
|
|
158
|
+
if (token) {
|
|
159
|
+
context.headers = {
|
|
160
|
+
...context.headers,
|
|
161
|
+
Authorization: `Bearer ${token}`,
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Continue to next middleware or make the request
|
|
166
|
+
const response = await next();
|
|
167
|
+
|
|
168
|
+
// Handle 401 errors
|
|
169
|
+
if (response.statusCode === 401) {
|
|
170
|
+
// Redirect to login or refresh token
|
|
171
|
+
window.location.href = '/login';
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
return response;
|
|
175
|
+
},
|
|
176
|
+
],
|
|
110
177
|
});
|
|
111
178
|
```
|
|
112
179
|
|
|
@@ -146,6 +213,111 @@ function LoginPage() {
|
|
|
146
213
|
}
|
|
147
214
|
```
|
|
148
215
|
|
|
216
|
+
## New Features
|
|
217
|
+
|
|
218
|
+
### 1. Enhanced Middleware System
|
|
219
|
+
|
|
220
|
+
The library now supports a chainable middleware system that allows you to intercept and modify requests and responses:
|
|
221
|
+
|
|
222
|
+
```jsx
|
|
223
|
+
// Define middleware functions
|
|
224
|
+
const loggingMiddleware = async (context, next) => {
|
|
225
|
+
console.log('Request:', context.path);
|
|
226
|
+
const response = await next();
|
|
227
|
+
console.log('Response:', response);
|
|
228
|
+
return response;
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
const authMiddleware = async (context, next) => {
|
|
232
|
+
// Add authentication token
|
|
233
|
+
const token = localStorage.getItem('auth_token');
|
|
234
|
+
if (token) {
|
|
235
|
+
context.headers = {
|
|
236
|
+
...context.headers,
|
|
237
|
+
Authorization: `Bearer ${token}`,
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
return await next();
|
|
242
|
+
};
|
|
243
|
+
|
|
244
|
+
// Use middleware in bootstrap
|
|
245
|
+
bootstrapQueryRequest(queryClient, {
|
|
246
|
+
middleware: [loggingMiddleware, authMiddleware],
|
|
247
|
+
});
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### 2. Configurable Pagination
|
|
251
|
+
|
|
252
|
+
The library now supports custom pagination configuration to work with any API format:
|
|
253
|
+
|
|
254
|
+
```jsx
|
|
255
|
+
// Global pagination configuration
|
|
256
|
+
bootstrapQueryRequest(queryClient, {
|
|
257
|
+
pagination: {
|
|
258
|
+
pageParamName: 'page', // default page parameter name
|
|
259
|
+
extractPagination: (response) => {
|
|
260
|
+
// Custom extraction for your API format
|
|
261
|
+
return {
|
|
262
|
+
current_page: response.data.meta.current,
|
|
263
|
+
next_page: response.data.meta.current + 1,
|
|
264
|
+
previous_page: response.data.meta.current - 1,
|
|
265
|
+
size: response.data.meta.per_page,
|
|
266
|
+
page_count: response.data.meta.last_page,
|
|
267
|
+
total: response.data.meta.total,
|
|
268
|
+
};
|
|
269
|
+
},
|
|
270
|
+
buildPaginationUrl: (url, page) => {
|
|
271
|
+
// Custom URL builder
|
|
272
|
+
const [pathname, queryString] = url.split('?');
|
|
273
|
+
const queryParams = new URLSearchParams(queryString || '');
|
|
274
|
+
queryParams.set('page', String(page));
|
|
275
|
+
return pathname + '?' + queryParams.toString();
|
|
276
|
+
},
|
|
277
|
+
},
|
|
278
|
+
});
|
|
279
|
+
|
|
280
|
+
// Per-request pagination configuration
|
|
281
|
+
const { data, nextPage, prevPage } = useGetRequest({
|
|
282
|
+
path: '/api/users',
|
|
283
|
+
load: true,
|
|
284
|
+
paginationConfig: {
|
|
285
|
+
// Override global pagination config for this specific request
|
|
286
|
+
pageParamName: 'p', // Use 'p' instead of 'page' for this API
|
|
287
|
+
extractPagination: (response) => {
|
|
288
|
+
// Custom extraction for this specific API
|
|
289
|
+
return {
|
|
290
|
+
current_page: response.data.page,
|
|
291
|
+
next_page: response.data.page + 1,
|
|
292
|
+
previous_page: response.data.page - 1,
|
|
293
|
+
size: response.data.limit,
|
|
294
|
+
page_count: Math.ceil(response.data.total / response.data.limit),
|
|
295
|
+
total: response.data.total,
|
|
296
|
+
};
|
|
297
|
+
},
|
|
298
|
+
},
|
|
299
|
+
});
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
### 3. Cross-Framework Compatibility
|
|
303
|
+
|
|
304
|
+
The library now automatically detects and works with various React frameworks:
|
|
305
|
+
|
|
306
|
+
- Create React App (CRA)
|
|
307
|
+
- Next.js
|
|
308
|
+
- Vite
|
|
309
|
+
- React Native
|
|
310
|
+
- Expo
|
|
311
|
+
|
|
312
|
+
Environment variables are automatically detected based on the framework's conventions:
|
|
313
|
+
|
|
314
|
+
```js
|
|
315
|
+
// For CRA: REACT_APP_API_URL
|
|
316
|
+
// For Next.js: NEXT_PUBLIC_API_URL
|
|
317
|
+
// For Vite: VITE_API_URL
|
|
318
|
+
// For React Native: Provided in the bootstrap config
|
|
319
|
+
```
|
|
320
|
+
|
|
149
321
|
# Hooks
|
|
150
322
|
|
|
151
323
|
## useGetRequest Hook
|
|
@@ -390,148 +562,4 @@ const { refetchQuery } = useRefetchQuery(['myQueryKey']);
|
|
|
390
562
|
const { data } = await refetchQuery<MyDataType>();
|
|
391
563
|
```
|
|
392
564
|
|
|
393
|
-
If you want to refetch a different query, you can pass a different `
|
|
394
|
-
|
|
395
|
-
```javascript
|
|
396
|
-
const { data } = (await refetchQuery) < MyDataType > ['myOtherQueryKey'];
|
|
397
|
-
```
|
|
398
|
-
|
|
399
|
-
If you want to perform additional operations after refetching the query, you can use the `data` returned by `refetchQuery` function:
|
|
400
|
-
|
|
401
|
-
```javascript
|
|
402
|
-
const { data } = await refetchQuery<MyDataType>();
|
|
403
|
-
// Perform additional operations with data
|
|
404
|
-
```
|
|
405
|
-
|
|
406
|
-
## Parameters
|
|
407
|
-
|
|
408
|
-
- `queryKey`: An array of any types that uniquely identifies the query.
|
|
409
|
-
|
|
410
|
-
## Return Value
|
|
411
|
-
|
|
412
|
-
- `refetchQuery`: A function that refetches the query and retrieves updated data.
|
|
413
|
-
|
|
414
|
-
## Example
|
|
415
|
-
|
|
416
|
-
```javascript
|
|
417
|
-
import { useQueryClient } from '@tanstack/react-query';
|
|
418
|
-
import { useRefetchQuery } from '@ventlio/tanstack-query';
|
|
419
|
-
|
|
420
|
-
const MyComponent = () => {
|
|
421
|
-
const queryClient = useQueryClient();
|
|
422
|
-
|
|
423
|
-
const { refetchQuery } = useRefetchQuery(['myQueryKey']);
|
|
424
|
-
|
|
425
|
-
const handleClick = async () => {
|
|
426
|
-
try {
|
|
427
|
-
// Refetch the query and retrieve updated data
|
|
428
|
-
const { data } = await refetchQuery<MyDataType>();
|
|
429
|
-
|
|
430
|
-
// Perform additional operations with data
|
|
431
|
-
console.log(data);
|
|
432
|
-
} catch (error) {
|
|
433
|
-
// Handle error
|
|
434
|
-
console.error(error);
|
|
435
|
-
}
|
|
436
|
-
};
|
|
437
|
-
|
|
438
|
-
return (
|
|
439
|
-
<button onClick={handleClick}>
|
|
440
|
-
Refetch Query
|
|
441
|
-
</button>
|
|
442
|
-
);
|
|
443
|
-
};
|
|
444
|
-
```
|
|
445
|
-
|
|
446
|
-
# useKeyTrackerModel
|
|
447
|
-
|
|
448
|
-
A custom hook that utilizes `useQueryClient` hook from `@tanstack/react-query` and `useState` hook from `react` to track a query key and retrieve query data.
|
|
449
|
-
|
|
450
|
-
## Usage
|
|
451
|
-
|
|
452
|
-
1. Import `useKeyTrackerModel` from @ventlio/tanstack-query:
|
|
453
|
-
|
|
454
|
-
```javascript
|
|
455
|
-
import { useKeyTrackerModel } from '@ventlio/tanstack-query';
|
|
456
|
-
```
|
|
457
|
-
|
|
458
|
-
2. Call `useKeyTrackerModel` with a `keyTracker` parameter which is a string that uniquely identifies the query key:
|
|
459
|
-
|
|
460
|
-
```javascript
|
|
461
|
-
const { refetchQuery, getQueryKey, queryKey, data } = useKeyTrackerModel < MyDataType > 'myKeyTracker';
|
|
462
|
-
```
|
|
463
|
-
|
|
464
|
-
3. Invoke `getQueryKey` function to retrieve the query key:
|
|
465
|
-
|
|
466
|
-
```javascript
|
|
467
|
-
const key = getQueryKey();
|
|
468
|
-
```
|
|
469
|
-
|
|
470
|
-
4. Invoke `refetchQuery` function to retrieve query data:
|
|
471
|
-
|
|
472
|
-
```javascript
|
|
473
|
-
const queryData = refetchQuery();
|
|
474
|
-
```
|
|
475
|
-
|
|
476
|
-
5. Use `queryKey` and `data` as needed in your component:
|
|
477
|
-
|
|
478
|
-
```javascript
|
|
479
|
-
return (
|
|
480
|
-
<div>
|
|
481
|
-
<p>Query Key: {queryKey}</p>
|
|
482
|
-
<p>Query Data: {data}</p>
|
|
483
|
-
</div>
|
|
484
|
-
);
|
|
485
|
-
```
|
|
486
|
-
|
|
487
|
-
## Parameters
|
|
488
|
-
|
|
489
|
-
- `keyTracker`: A string that uniquely identifies the query key.
|
|
490
|
-
|
|
491
|
-
## Return Value
|
|
492
|
-
|
|
493
|
-
- `refetchQuery`: A function that retrieves query data.
|
|
494
|
-
- `getQueryKey`: A function that retrieves the query key.
|
|
495
|
-
- `queryKey`: The query key.
|
|
496
|
-
- `data`: The query data.
|
|
497
|
-
|
|
498
|
-
## Example
|
|
499
|
-
|
|
500
|
-
```javascript
|
|
501
|
-
import { useQueryClient } from '@tanstack/react-query';
|
|
502
|
-
import { useState } from 'react';
|
|
503
|
-
import { useKeyTrackerModel } from '@ventlio/tanstack-query';
|
|
504
|
-
|
|
505
|
-
const MyComponent = () => {
|
|
506
|
-
const queryClient = useQueryClient();
|
|
507
|
-
|
|
508
|
-
const { refetchQuery, getQueryKey, queryKey, data } = useKeyTrackerModel < MyDataType > 'myKeyTracker';
|
|
509
|
-
|
|
510
|
-
const handleClick = async () => {
|
|
511
|
-
// Retrieve the query key
|
|
512
|
-
const key = getQueryKey();
|
|
513
|
-
|
|
514
|
-
// Retrieve query data
|
|
515
|
-
const queryData = refetchQuery();
|
|
516
|
-
|
|
517
|
-
// Perform additional operations with query key and data
|
|
518
|
-
console.log(key, queryData);
|
|
519
|
-
};
|
|
520
|
-
|
|
521
|
-
return (
|
|
522
|
-
<div>
|
|
523
|
-
<button onClick={handleClick}>Get Query Data</button>
|
|
524
|
-
<p>Query Key: {queryKey}</p>
|
|
525
|
-
<p>Query Data: {data}</p>
|
|
526
|
-
</div>
|
|
527
|
-
);
|
|
528
|
-
};
|
|
529
|
-
```
|
|
530
|
-
|
|
531
|
-
## Contributing
|
|
532
|
-
|
|
533
|
-
Contributions to this codebase are welcome. If you find any issues or have any suggestions, please feel free to create an issue or pull request.
|
|
534
|
-
|
|
535
|
-
## License
|
|
536
|
-
|
|
537
|
-
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
|
|
565
|
+
If you want to refetch a different query, you can pass a different `
|
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
import type { QueryClient } from '@tanstack/react-query';
|
|
2
2
|
import 'url-search-params-polyfill';
|
|
3
3
|
import type { BootstrapConfig } from '../types';
|
|
4
|
+
/**
|
|
5
|
+
* Bootstrap the query request system with configuration options
|
|
6
|
+
*
|
|
7
|
+
* @param queryClient - TanStack Query client instance
|
|
8
|
+
* @param options - Configuration options
|
|
9
|
+
*/
|
|
4
10
|
export declare const bootstrapQueryRequest: (queryClient: QueryClient, options?: BootstrapConfig) => Promise<void>;
|