tanstack-cacher 1.2.0 → 1.3.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/LICENSE +1 -1
- package/{dist/index.d.ts → index.d.ts} +23 -17
- package/{dist/index.js → index.js} +97 -75
- package/package.json +19 -15
- package/dist/index.d.mts +0 -87
- package/dist/index.mjs +0 -415
package/LICENSE
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as _tanstack_react_query from '@tanstack/react-query';
|
|
2
|
-
import { QueryClient, QueryKey,
|
|
2
|
+
import { QueryClient, QueryKey, UseMutationOptions } from '@tanstack/react-query';
|
|
3
3
|
export * from '@tanstack/react-query';
|
|
4
4
|
|
|
5
5
|
interface PaginationConfig {
|
|
@@ -9,10 +9,11 @@ interface PaginationConfig {
|
|
|
9
9
|
pageSizePath?: string;
|
|
10
10
|
}
|
|
11
11
|
interface CacheConfig<TData, TItem> {
|
|
12
|
-
queryClient
|
|
12
|
+
queryClient?: QueryClient;
|
|
13
13
|
queryKey: QueryKey;
|
|
14
|
-
itemsPath
|
|
14
|
+
itemsPath?: string;
|
|
15
15
|
pagination?: PaginationConfig;
|
|
16
|
+
isPaginated?: boolean;
|
|
16
17
|
keyExtractor?: (item: TItem) => string | number;
|
|
17
18
|
initialData?: TData;
|
|
18
19
|
}
|
|
@@ -41,20 +42,27 @@ declare class QueryCacheManager<TData, TItem> {
|
|
|
41
42
|
createHandlers(): CacheHandlers<TItem>;
|
|
42
43
|
}
|
|
43
44
|
|
|
44
|
-
type
|
|
45
|
+
type CacheManagerConstructor = new <TData, TItem>(config: CacheConfig<TData, TItem>) => QueryCacheManager<TData, TItem>;
|
|
46
|
+
declare class CacheManagerFactory {
|
|
47
|
+
private managerClass;
|
|
48
|
+
setManagerClass(managerClass: CacheManagerConstructor): void;
|
|
49
|
+
resetManagerClass(): void;
|
|
50
|
+
create<TData, TItem>(config: CacheConfig<TData, TItem>): QueryCacheManager<TData, TItem>;
|
|
51
|
+
getManagerClass(): CacheManagerConstructor;
|
|
52
|
+
}
|
|
53
|
+
declare const cacheManagerFactory: CacheManagerFactory;
|
|
45
54
|
|
|
46
|
-
type
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
};
|
|
52
|
-
type CustomMutationOptions<TData, TError, TVariables, TContext> = UseMutationOptions<TData, TError, TVariables, TContext> & {
|
|
55
|
+
type MutationTypes = 'add' | 'invalidate' | 'remove' | 'update';
|
|
56
|
+
interface CacheActions<TData, TItem = unknown> extends Omit<CacheConfig<TData, TItem>, 'queryClient'> {
|
|
57
|
+
type: MutationTypes;
|
|
58
|
+
}
|
|
59
|
+
type CustomMutationOptions<TData, TError, TVariables> = UseMutationOptions<TData, TError, TVariables> & {
|
|
53
60
|
notify?: boolean;
|
|
54
61
|
notifyError?: boolean;
|
|
55
62
|
errorMessage?: string;
|
|
56
63
|
notifySuccess?: boolean;
|
|
57
64
|
successMessage?: string;
|
|
65
|
+
cacheActions?: CacheActions<TData>[] | CacheActions<TData>;
|
|
58
66
|
notificationConfig?: NotificationOptions;
|
|
59
67
|
getErrorMessage?: (error: TError) => string;
|
|
60
68
|
};
|
|
@@ -63,11 +71,7 @@ interface NotificationOptions {
|
|
|
63
71
|
[key: string]: any;
|
|
64
72
|
}
|
|
65
73
|
|
|
66
|
-
declare
|
|
67
|
-
cache?: QueryCacheManager<TData, TItem>;
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
declare const useCustomMutation: <TData, TError, TVariables = void, TContext = unknown>(options: CustomMutationOptions<TData, TError, TVariables, TContext>) => _tanstack_react_query.UseMutationResult<TData, TError, TVariables, TContext>;
|
|
74
|
+
declare const useCustomMutation: <TData, TError, TVariables = void>(options: CustomMutationOptions<TData, TError, TVariables>) => _tanstack_react_query.UseMutationResult<TData, TError, TVariables, unknown>;
|
|
71
75
|
|
|
72
76
|
declare const useQueryCacheManagers: <T extends Record<string, QueryCacheManager<any, any>>>(configs: { [K in keyof T]: {
|
|
73
77
|
queryKey: readonly unknown[];
|
|
@@ -81,7 +85,9 @@ interface NotificationContextType {
|
|
|
81
85
|
|
|
82
86
|
declare const useNotificationContext: () => NotificationContextType;
|
|
83
87
|
|
|
88
|
+
type CacheOptions<TData = any, TItem = any> = Omit<CacheConfig<TData, TItem>, 'queryClient' | 'queryKey'>;
|
|
89
|
+
|
|
84
90
|
declare const resetCacheManager: (queryKey: QueryKey) => void;
|
|
85
91
|
declare const resetAllCacheManagers: () => void;
|
|
86
92
|
|
|
87
|
-
export { type CacheConfig, type CacheHandlers, type
|
|
93
|
+
export { type CacheConfig, type CacheHandlers, type CacheManagerConstructor, type CacheOptions, type CustomMutationOptions, type InsertPosition, type PaginationConfig, QueryCacheManager, cacheManagerFactory, resetAllCacheManagers, resetCacheManager, useCustomMutation, useNotificationContext, useQueryCacheManagers };
|
|
@@ -11,7 +11,7 @@ function getAtPath(obj, path, defaultValue) {
|
|
|
11
11
|
const keys = path.split(".");
|
|
12
12
|
let result = obj;
|
|
13
13
|
for (const key of keys) {
|
|
14
|
-
if (result === null
|
|
14
|
+
if (result === null) {
|
|
15
15
|
return defaultValue;
|
|
16
16
|
}
|
|
17
17
|
result = result[key];
|
|
@@ -40,13 +40,46 @@ function incrementAtPath(obj, path, increment) {
|
|
|
40
40
|
const newValue = currentValue + increment;
|
|
41
41
|
return setAtPath(obj, path, newValue);
|
|
42
42
|
}
|
|
43
|
+
var runCacheManagers = (type, manager, data) => {
|
|
44
|
+
switch (type) {
|
|
45
|
+
case "invalidate":
|
|
46
|
+
manager.invalidate();
|
|
47
|
+
break;
|
|
48
|
+
case "remove":
|
|
49
|
+
manager.delete(data);
|
|
50
|
+
break;
|
|
51
|
+
case "add":
|
|
52
|
+
manager.add(data);
|
|
53
|
+
break;
|
|
54
|
+
case "update":
|
|
55
|
+
manager.update(data);
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
// src/managers/QueryCacheManager/QueryCache.consts.ts
|
|
61
|
+
var DEFAULT_PAGINATION_PATHS = {
|
|
62
|
+
totalElementsPath: "data.page.totalElements",
|
|
63
|
+
totalPagesPath: "data.page.totalPages",
|
|
64
|
+
currentPagePath: "data.page.number",
|
|
65
|
+
pageSizePath: "data.page.size"
|
|
66
|
+
};
|
|
43
67
|
|
|
44
68
|
// src/managers/QueryCacheManager/QueryCache.manager.ts
|
|
69
|
+
var defaultQueryClient = new reactQuery.QueryClient();
|
|
45
70
|
var QueryCacheManager = class {
|
|
46
71
|
constructor(config) {
|
|
72
|
+
const isPaginated = Boolean(config.pagination);
|
|
47
73
|
this.config = {
|
|
48
74
|
...config,
|
|
49
|
-
|
|
75
|
+
itemsPath: config.itemsPath ?? "data.content",
|
|
76
|
+
queryClient: config.queryClient ?? defaultQueryClient,
|
|
77
|
+
isPaginated,
|
|
78
|
+
keyExtractor: config.keyExtractor || ((item) => item.id),
|
|
79
|
+
pagination: isPaginated ? {
|
|
80
|
+
...DEFAULT_PAGINATION_PATHS,
|
|
81
|
+
...config.pagination
|
|
82
|
+
} : void 0
|
|
50
83
|
};
|
|
51
84
|
}
|
|
52
85
|
/**
|
|
@@ -284,75 +317,25 @@ var QueryCacheManager = class {
|
|
|
284
317
|
}
|
|
285
318
|
};
|
|
286
319
|
|
|
287
|
-
// src/
|
|
288
|
-
var
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
paginated: {
|
|
292
|
-
itemsPath: "data.content",
|
|
293
|
-
pagination: {
|
|
294
|
-
totalElementsPath: "data.page.totalElements",
|
|
295
|
-
totalPagesPath: "data.page.totalPages",
|
|
296
|
-
currentPagePath: "data.page.number",
|
|
297
|
-
pageSizePath: "data.page.size"
|
|
298
|
-
}
|
|
299
|
-
},
|
|
300
|
-
nonPaginated: {
|
|
301
|
-
itemsPath: "data"
|
|
320
|
+
// src/managers/QueryCacheManager/CacheManagerFactory.ts
|
|
321
|
+
var CacheManagerFactory = class {
|
|
322
|
+
constructor() {
|
|
323
|
+
this.managerClass = QueryCacheManager;
|
|
302
324
|
}
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
cacheConfigRegistry.set(key, config);
|
|
306
|
-
});
|
|
307
|
-
var getOrCreateCacheManager = (queryKey, queryClient, options) => {
|
|
308
|
-
const key = JSON.stringify(queryKey);
|
|
309
|
-
if (cacheRegistry.has(key)) {
|
|
310
|
-
return cacheRegistry.get(key);
|
|
325
|
+
setManagerClass(managerClass) {
|
|
326
|
+
this.managerClass = managerClass;
|
|
311
327
|
}
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
if (!config) {
|
|
315
|
-
throw new Error(
|
|
316
|
-
`[CacheManager] Unknown cacheType "${cacheType}". Available: ${[
|
|
317
|
-
...cacheConfigRegistry.keys()
|
|
318
|
-
].join(", ")}`
|
|
319
|
-
);
|
|
328
|
+
resetManagerClass() {
|
|
329
|
+
this.managerClass = QueryCacheManager;
|
|
320
330
|
}
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
queryKey,
|
|
324
|
-
...config
|
|
325
|
-
});
|
|
326
|
-
cacheRegistry.set(key, manager);
|
|
327
|
-
return manager;
|
|
328
|
-
};
|
|
329
|
-
var resetCacheManager = (queryKey) => {
|
|
330
|
-
cacheRegistry.delete(JSON.stringify(queryKey));
|
|
331
|
-
};
|
|
332
|
-
var resetAllCacheManagers = () => {
|
|
333
|
-
cacheRegistry.clear();
|
|
334
|
-
};
|
|
335
|
-
|
|
336
|
-
// src/hooks/useCustomQuery.ts
|
|
337
|
-
function useCustomQuery(options) {
|
|
338
|
-
const queryClient = reactQuery.useQueryClient();
|
|
339
|
-
const { queryKey, cacheType, cacheConfig, ...rest } = options;
|
|
340
|
-
const queryResult = reactQuery.useQuery({
|
|
341
|
-
queryKey,
|
|
342
|
-
...rest
|
|
343
|
-
});
|
|
344
|
-
let cache;
|
|
345
|
-
if (cacheType) {
|
|
346
|
-
cache = getOrCreateCacheManager(queryKey, queryClient, {
|
|
347
|
-
cacheType,
|
|
348
|
-
cacheConfig
|
|
349
|
-
});
|
|
331
|
+
create(config) {
|
|
332
|
+
return new this.managerClass(config);
|
|
350
333
|
}
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
334
|
+
getManagerClass() {
|
|
335
|
+
return this.managerClass;
|
|
336
|
+
}
|
|
337
|
+
};
|
|
338
|
+
var cacheManagerFactory = new CacheManagerFactory();
|
|
356
339
|
var NotificationContext = react.createContext(
|
|
357
340
|
void 0
|
|
358
341
|
);
|
|
@@ -371,6 +354,7 @@ var useCustomMutation = (options) => {
|
|
|
371
354
|
const {
|
|
372
355
|
onError,
|
|
373
356
|
onSuccess,
|
|
357
|
+
cacheActions,
|
|
374
358
|
notify = false,
|
|
375
359
|
notifyError = false,
|
|
376
360
|
notifySuccess = false,
|
|
@@ -380,21 +364,32 @@ var useCustomMutation = (options) => {
|
|
|
380
364
|
getErrorMessage,
|
|
381
365
|
...rest
|
|
382
366
|
} = options;
|
|
383
|
-
const
|
|
367
|
+
const notificationContext = useNotificationContext();
|
|
384
368
|
return reactQuery.useMutation({
|
|
385
369
|
...rest,
|
|
386
|
-
onSuccess: (data, variables,
|
|
370
|
+
onSuccess: (data, variables, mResult, context) => {
|
|
387
371
|
if (notify || notifySuccess) {
|
|
388
|
-
showSuccess(successMessage, notificationConfig);
|
|
372
|
+
notificationContext?.showSuccess?.(successMessage, notificationConfig);
|
|
373
|
+
}
|
|
374
|
+
onSuccess?.(data, variables, mResult, context);
|
|
375
|
+
if (Array.isArray(cacheActions)) {
|
|
376
|
+
cacheActions.forEach((item) => {
|
|
377
|
+
const { type, ...rest2 } = item;
|
|
378
|
+
const manager = cacheManagerFactory.create(rest2);
|
|
379
|
+
runCacheManagers(type, manager, data);
|
|
380
|
+
});
|
|
381
|
+
} else if (cacheActions) {
|
|
382
|
+
const { type, ...rest2 } = cacheActions;
|
|
383
|
+
const manager = cacheManagerFactory.create(rest2);
|
|
384
|
+
runCacheManagers(type, manager, data);
|
|
389
385
|
}
|
|
390
|
-
onSuccess?.(data, variables, context, mutation);
|
|
391
386
|
},
|
|
392
|
-
onError: (apiError, variables,
|
|
387
|
+
onError: (apiError, variables, mResult, context) => {
|
|
393
388
|
const message = getErrorMessage ? getErrorMessage(apiError) : apiError?.error?.message ?? errorMessage;
|
|
394
389
|
if (notify || notifyError) {
|
|
395
|
-
showError(message, notificationConfig);
|
|
390
|
+
notificationContext?.showError(message, notificationConfig);
|
|
396
391
|
}
|
|
397
|
-
onError?.(apiError, variables,
|
|
392
|
+
onError?.(apiError, variables, mResult, context);
|
|
398
393
|
}
|
|
399
394
|
});
|
|
400
395
|
};
|
|
@@ -413,11 +408,38 @@ var useQueryCacheManagers = (configs) => {
|
|
|
413
408
|
return managers;
|
|
414
409
|
};
|
|
415
410
|
|
|
411
|
+
// src/utils/cacheRegistry.ts
|
|
412
|
+
var cacheConfigRegistry = /* @__PURE__ */ new Map();
|
|
413
|
+
var cacheRegistry = /* @__PURE__ */ new Map();
|
|
414
|
+
var defaultConfigs = {
|
|
415
|
+
paginated: {
|
|
416
|
+
itemsPath: "data.content",
|
|
417
|
+
pagination: {
|
|
418
|
+
totalElementsPath: "data.page.totalElements",
|
|
419
|
+
totalPagesPath: "data.page.totalPages",
|
|
420
|
+
currentPagePath: "data.page.number",
|
|
421
|
+
pageSizePath: "data.page.size"
|
|
422
|
+
}
|
|
423
|
+
},
|
|
424
|
+
nonPaginated: {
|
|
425
|
+
itemsPath: "data"
|
|
426
|
+
}
|
|
427
|
+
};
|
|
428
|
+
Object.entries(defaultConfigs).forEach(([key, config]) => {
|
|
429
|
+
cacheConfigRegistry.set(key, config);
|
|
430
|
+
});
|
|
431
|
+
var resetCacheManager = (queryKey) => {
|
|
432
|
+
cacheRegistry.delete(JSON.stringify(queryKey));
|
|
433
|
+
};
|
|
434
|
+
var resetAllCacheManagers = () => {
|
|
435
|
+
cacheRegistry.clear();
|
|
436
|
+
};
|
|
437
|
+
|
|
416
438
|
exports.QueryCacheManager = QueryCacheManager;
|
|
439
|
+
exports.cacheManagerFactory = cacheManagerFactory;
|
|
417
440
|
exports.resetAllCacheManagers = resetAllCacheManagers;
|
|
418
441
|
exports.resetCacheManager = resetCacheManager;
|
|
419
442
|
exports.useCustomMutation = useCustomMutation;
|
|
420
|
-
exports.useCustomQuery = useCustomQuery;
|
|
421
443
|
exports.useNotificationContext = useNotificationContext;
|
|
422
444
|
exports.useQueryCacheManagers = useQueryCacheManagers;
|
|
423
445
|
Object.keys(reactQuery).forEach(function (k) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tanstack-cacher",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.1",
|
|
4
4
|
"description": "A lightweight cache management utility for TanStack Query that simplifies adding, updating, deleting, and synchronizing cached data",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
"web": "http://github.com/hacagahasanli"
|
|
20
20
|
}
|
|
21
21
|
],
|
|
22
|
-
"homepage": "https://github.com/hacagahasanli/tanstack-cacher",
|
|
22
|
+
"homepage": "https://github.com/hacagahasanli/tanstack-cacher#readme",
|
|
23
23
|
"keywords": [
|
|
24
24
|
"react",
|
|
25
25
|
"react-query",
|
|
@@ -28,26 +28,30 @@
|
|
|
28
28
|
"cache-manager",
|
|
29
29
|
"optimistic-updates"
|
|
30
30
|
],
|
|
31
|
-
"main": "./
|
|
32
|
-
"module": "./
|
|
33
|
-
"types": "./
|
|
31
|
+
"main": "./index.js",
|
|
32
|
+
"module": "./index.js",
|
|
33
|
+
"types": "./index.d.ts",
|
|
34
|
+
"files": [
|
|
35
|
+
"index.js",
|
|
36
|
+
"index.d.ts",
|
|
37
|
+
"styles",
|
|
38
|
+
"LICENSE",
|
|
39
|
+
"README.md"
|
|
40
|
+
],
|
|
34
41
|
"exports": {
|
|
35
42
|
".": {
|
|
36
|
-
"types": "./
|
|
37
|
-
"import": "./
|
|
38
|
-
|
|
39
|
-
|
|
43
|
+
"types": "./index.d.ts",
|
|
44
|
+
"import": "./index.js"
|
|
45
|
+
},
|
|
46
|
+
"./package.json": "./package.json"
|
|
40
47
|
},
|
|
41
|
-
"files": [
|
|
42
|
-
"dist",
|
|
43
|
-
"README.md",
|
|
44
|
-
"LICENSE"
|
|
45
|
-
],
|
|
46
48
|
"engines": {
|
|
47
49
|
"node": ">=16"
|
|
48
50
|
},
|
|
49
51
|
"scripts": {
|
|
50
|
-
"build": "tsup",
|
|
52
|
+
"build": "tsup && npm run copy-dist",
|
|
53
|
+
"copy-dist": "cp dist/index.js index.js && cp dist/index.d.ts index.d.ts",
|
|
54
|
+
"locale-build": "tsup",
|
|
51
55
|
"dev": "tsup --watch",
|
|
52
56
|
"lint": "eslint src --ext .ts,.tsx",
|
|
53
57
|
"lint:fix": "eslint src --ext .ts,.tsx --fix",
|
package/dist/index.d.mts
DELETED
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
import * as _tanstack_react_query from '@tanstack/react-query';
|
|
2
|
-
import { QueryClient, QueryKey, UseQueryOptions, UseMutationOptions, UseQueryResult } from '@tanstack/react-query';
|
|
3
|
-
export * from '@tanstack/react-query';
|
|
4
|
-
|
|
5
|
-
interface PaginationConfig {
|
|
6
|
-
totalElementsPath?: string;
|
|
7
|
-
totalPagesPath?: string;
|
|
8
|
-
currentPagePath?: string;
|
|
9
|
-
pageSizePath?: string;
|
|
10
|
-
}
|
|
11
|
-
interface CacheConfig<TData, TItem> {
|
|
12
|
-
queryClient: QueryClient;
|
|
13
|
-
queryKey: QueryKey;
|
|
14
|
-
itemsPath: string;
|
|
15
|
-
pagination?: PaginationConfig;
|
|
16
|
-
keyExtractor?: (item: TItem) => string | number;
|
|
17
|
-
initialData?: TData;
|
|
18
|
-
}
|
|
19
|
-
interface CacheHandlers<TItem> {
|
|
20
|
-
onAdd: (newItem: TItem, position?: 'start' | 'end') => void;
|
|
21
|
-
onUpdate: (updatedItem: Partial<TItem>, matcher?: (item: TItem) => boolean) => void;
|
|
22
|
-
onDelete: (itemOrId: TItem | string | number, matcher?: (item: TItem) => boolean) => void;
|
|
23
|
-
}
|
|
24
|
-
type InsertPosition = 'start' | 'end';
|
|
25
|
-
|
|
26
|
-
declare class QueryCacheManager<TData, TItem> {
|
|
27
|
-
private config;
|
|
28
|
-
constructor(config: CacheConfig<TData, TItem>);
|
|
29
|
-
private getItems;
|
|
30
|
-
private setItems;
|
|
31
|
-
private updatePaginationOnAdd;
|
|
32
|
-
private updatePaginationOnRemove;
|
|
33
|
-
add(newItem: TItem, position?: InsertPosition): void;
|
|
34
|
-
update(updatedItem: Partial<TItem>, matcher?: (item: TItem) => boolean): void;
|
|
35
|
-
delete(itemOrId: TItem | string | number, matcher?: (item: TItem) => boolean): void;
|
|
36
|
-
replace(newData: TData): void;
|
|
37
|
-
clear(): void;
|
|
38
|
-
getItemsFromCache(): TItem[];
|
|
39
|
-
getDataFromCache(): TData | undefined;
|
|
40
|
-
invalidate(): void;
|
|
41
|
-
createHandlers(): CacheHandlers<TItem>;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
type CacheOptions<TData = any, TItem = any> = Omit<CacheConfig<TData, TItem>, 'queryClient' | 'queryKey'>;
|
|
45
|
-
|
|
46
|
-
type CustomQueryOptions<TData, TError = unknown> = UseQueryOptions<TData, TError> & {
|
|
47
|
-
queryKey: QueryKey;
|
|
48
|
-
cacheType?: string;
|
|
49
|
-
queryFn: () => Promise<TData>;
|
|
50
|
-
cacheConfig?: CacheOptions;
|
|
51
|
-
};
|
|
52
|
-
type CustomMutationOptions<TData, TError, TVariables, TContext> = UseMutationOptions<TData, TError, TVariables, TContext> & {
|
|
53
|
-
notify?: boolean;
|
|
54
|
-
notifyError?: boolean;
|
|
55
|
-
errorMessage?: string;
|
|
56
|
-
notifySuccess?: boolean;
|
|
57
|
-
successMessage?: string;
|
|
58
|
-
notificationConfig?: NotificationOptions;
|
|
59
|
-
getErrorMessage?: (error: TError) => string;
|
|
60
|
-
};
|
|
61
|
-
interface NotificationOptions {
|
|
62
|
-
duration?: number;
|
|
63
|
-
[key: string]: any;
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
declare function useCustomQuery<TData, TError = unknown, TItem = any>(options: CustomQueryOptions<TData, TError>): UseQueryResult<TData, TError> & {
|
|
67
|
-
cache?: QueryCacheManager<TData, TItem>;
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
declare const useCustomMutation: <TData, TError, TVariables = void, TContext = unknown>(options: CustomMutationOptions<TData, TError, TVariables, TContext>) => _tanstack_react_query.UseMutationResult<TData, TError, TVariables, TContext>;
|
|
71
|
-
|
|
72
|
-
declare const useQueryCacheManagers: <T extends Record<string, QueryCacheManager<any, any>>>(configs: { [K in keyof T]: {
|
|
73
|
-
queryKey: readonly unknown[];
|
|
74
|
-
options?: Partial<Omit<CacheConfig<any, any>, "queryClient">>;
|
|
75
|
-
}; }) => T;
|
|
76
|
-
|
|
77
|
-
interface NotificationContextType {
|
|
78
|
-
showError: (message: string, options?: NotificationOptions) => void;
|
|
79
|
-
showSuccess: (message: string, options?: NotificationOptions) => void;
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
declare const useNotificationContext: () => NotificationContextType;
|
|
83
|
-
|
|
84
|
-
declare const resetCacheManager: (queryKey: QueryKey) => void;
|
|
85
|
-
declare const resetAllCacheManagers: () => void;
|
|
86
|
-
|
|
87
|
-
export { type CacheConfig, type CacheHandlers, type CacheOptions, type CustomMutationOptions, type CustomQueryOptions, type InsertPosition, type PaginationConfig, QueryCacheManager, resetAllCacheManagers, resetCacheManager, useCustomMutation, useCustomQuery, useNotificationContext, useQueryCacheManagers };
|
package/dist/index.mjs
DELETED
|
@@ -1,415 +0,0 @@
|
|
|
1
|
-
import { useQueryClient, useQuery, useMutation } from '@tanstack/react-query';
|
|
2
|
-
export * from '@tanstack/react-query';
|
|
3
|
-
import { createContext, useContext } from 'react';
|
|
4
|
-
|
|
5
|
-
// src/index.ts
|
|
6
|
-
|
|
7
|
-
// src/managers/QueryCacheManager/QueryCache.utils.ts
|
|
8
|
-
function getAtPath(obj, path, defaultValue) {
|
|
9
|
-
if (!obj || !path) return defaultValue;
|
|
10
|
-
const keys = path.split(".");
|
|
11
|
-
let result = obj;
|
|
12
|
-
for (const key of keys) {
|
|
13
|
-
if (result === null || result === void 0) {
|
|
14
|
-
return defaultValue;
|
|
15
|
-
}
|
|
16
|
-
result = result[key];
|
|
17
|
-
}
|
|
18
|
-
return result !== void 0 ? result : defaultValue;
|
|
19
|
-
}
|
|
20
|
-
function setAtPath(obj, path, value) {
|
|
21
|
-
if (!path) return obj;
|
|
22
|
-
const keys = path.split(".");
|
|
23
|
-
const root = obj ? { ...obj } : {};
|
|
24
|
-
let current = root;
|
|
25
|
-
for (let i = 0; i < keys.length - 1; i++) {
|
|
26
|
-
const key = keys[i];
|
|
27
|
-
if (!current[key] || typeof current[key] !== "object") {
|
|
28
|
-
current[key] = {};
|
|
29
|
-
} else {
|
|
30
|
-
current[key] = { ...current[key] };
|
|
31
|
-
}
|
|
32
|
-
current = current[key];
|
|
33
|
-
}
|
|
34
|
-
current[keys[keys.length - 1]] = value;
|
|
35
|
-
return root;
|
|
36
|
-
}
|
|
37
|
-
function incrementAtPath(obj, path, increment) {
|
|
38
|
-
const currentValue = getAtPath(obj, path, 0);
|
|
39
|
-
const newValue = currentValue + increment;
|
|
40
|
-
return setAtPath(obj, path, newValue);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// src/managers/QueryCacheManager/QueryCache.manager.ts
|
|
44
|
-
var QueryCacheManager = class {
|
|
45
|
-
constructor(config) {
|
|
46
|
-
this.config = {
|
|
47
|
-
...config,
|
|
48
|
-
keyExtractor: config.keyExtractor || ((item) => item.id)
|
|
49
|
-
};
|
|
50
|
-
}
|
|
51
|
-
/**
|
|
52
|
-
* Get items array from data
|
|
53
|
-
* Returns empty array if path doesn't exist or data is null
|
|
54
|
-
*/
|
|
55
|
-
getItems(data) {
|
|
56
|
-
if (!data) return [];
|
|
57
|
-
if (!this.config.itemsPath) {
|
|
58
|
-
return Array.isArray(data) ? data : [];
|
|
59
|
-
}
|
|
60
|
-
const items = getAtPath(data, this.config.itemsPath, []);
|
|
61
|
-
return Array.isArray(items) ? items : [];
|
|
62
|
-
}
|
|
63
|
-
/**
|
|
64
|
-
* Set items array in data
|
|
65
|
-
* Creates nested structure if it doesn't exist
|
|
66
|
-
*/
|
|
67
|
-
setItems(data, items) {
|
|
68
|
-
if (!data) {
|
|
69
|
-
if (this.config.initialData) {
|
|
70
|
-
data = this.config.initialData;
|
|
71
|
-
} else {
|
|
72
|
-
if (!this.config.itemsPath) {
|
|
73
|
-
return items;
|
|
74
|
-
}
|
|
75
|
-
data = {};
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
if (!this.config.itemsPath) {
|
|
79
|
-
return items;
|
|
80
|
-
}
|
|
81
|
-
return setAtPath(data, this.config.itemsPath, items);
|
|
82
|
-
}
|
|
83
|
-
/**
|
|
84
|
-
* Update pagination metadata after adding items
|
|
85
|
-
*/
|
|
86
|
-
updatePaginationOnAdd(data, addedCount) {
|
|
87
|
-
if (!this.config.pagination) return data;
|
|
88
|
-
let result = data;
|
|
89
|
-
if (this.config.pagination.totalElementsPath) {
|
|
90
|
-
result = incrementAtPath(
|
|
91
|
-
result,
|
|
92
|
-
this.config.pagination.totalElementsPath,
|
|
93
|
-
addedCount
|
|
94
|
-
);
|
|
95
|
-
}
|
|
96
|
-
if (this.config.pagination.totalPagesPath && this.config.pagination.pageSizePath && this.config.pagination.totalElementsPath) {
|
|
97
|
-
const pageSize = getAtPath(result, this.config.pagination.pageSizePath, 0);
|
|
98
|
-
const totalElements = getAtPath(
|
|
99
|
-
result,
|
|
100
|
-
this.config.pagination.totalElementsPath,
|
|
101
|
-
0
|
|
102
|
-
);
|
|
103
|
-
if (pageSize > 0) {
|
|
104
|
-
const totalPages = Math.ceil(totalElements / pageSize);
|
|
105
|
-
result = setAtPath(
|
|
106
|
-
result,
|
|
107
|
-
this.config.pagination.totalPagesPath,
|
|
108
|
-
totalPages
|
|
109
|
-
);
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
return result;
|
|
113
|
-
}
|
|
114
|
-
/**
|
|
115
|
-
* Update pagination metadata after removing items
|
|
116
|
-
*/
|
|
117
|
-
updatePaginationOnRemove(data, removedCount) {
|
|
118
|
-
if (!this.config.pagination) return data;
|
|
119
|
-
let result = data;
|
|
120
|
-
if (this.config.pagination.totalElementsPath) {
|
|
121
|
-
result = incrementAtPath(
|
|
122
|
-
result,
|
|
123
|
-
this.config.pagination.totalElementsPath,
|
|
124
|
-
-removedCount
|
|
125
|
-
);
|
|
126
|
-
}
|
|
127
|
-
if (this.config.pagination.totalPagesPath && this.config.pagination.pageSizePath && this.config.pagination.totalElementsPath) {
|
|
128
|
-
const pageSize = getAtPath(result, this.config.pagination.pageSizePath, 0);
|
|
129
|
-
const totalElements = getAtPath(
|
|
130
|
-
result,
|
|
131
|
-
this.config.pagination.totalElementsPath,
|
|
132
|
-
0
|
|
133
|
-
);
|
|
134
|
-
if (pageSize > 0) {
|
|
135
|
-
const totalPages = Math.ceil(Math.max(0, totalElements) / pageSize);
|
|
136
|
-
result = setAtPath(
|
|
137
|
-
result,
|
|
138
|
-
this.config.pagination.totalPagesPath,
|
|
139
|
-
totalPages
|
|
140
|
-
);
|
|
141
|
-
}
|
|
142
|
-
}
|
|
143
|
-
return result;
|
|
144
|
-
}
|
|
145
|
-
/**
|
|
146
|
-
* Add item to cache
|
|
147
|
-
*
|
|
148
|
-
* @param newItem - The item to add
|
|
149
|
-
* @param position - Where to add: 'start' or 'end'
|
|
150
|
-
*/
|
|
151
|
-
add(newItem, position = "start") {
|
|
152
|
-
try {
|
|
153
|
-
this.config.queryClient.setQueryData(this.config.queryKey, (oldData) => {
|
|
154
|
-
const items = this.getItems(oldData);
|
|
155
|
-
const updatedItems = position === "start" ? [newItem, ...items] : [...items, newItem];
|
|
156
|
-
let result = this.setItems(oldData, updatedItems);
|
|
157
|
-
result = this.updatePaginationOnAdd(result, 1);
|
|
158
|
-
return result;
|
|
159
|
-
});
|
|
160
|
-
} catch (error) {
|
|
161
|
-
console.error("[QueryCacheManager] Add failed:", error);
|
|
162
|
-
this.invalidate();
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
/**
|
|
166
|
-
* Update existing item
|
|
167
|
-
*
|
|
168
|
-
* @param updatedItem - Partial item data to update
|
|
169
|
-
* @param matcher - Optional custom matcher function. Defaults to matching by key
|
|
170
|
-
*/
|
|
171
|
-
update(updatedItem, matcher) {
|
|
172
|
-
try {
|
|
173
|
-
this.config.queryClient.setQueryData(this.config.queryKey, (oldData) => {
|
|
174
|
-
const items = this.getItems(oldData);
|
|
175
|
-
const matchFn = matcher || ((item) => this.config.keyExtractor(item) === this.config.keyExtractor(updatedItem));
|
|
176
|
-
const updatedItems = items.map(
|
|
177
|
-
(item) => matchFn(item) ? { ...item, ...updatedItem } : item
|
|
178
|
-
);
|
|
179
|
-
return this.setItems(oldData, updatedItems);
|
|
180
|
-
});
|
|
181
|
-
} catch (error) {
|
|
182
|
-
console.error("[QueryCacheManager] Update failed:", error);
|
|
183
|
-
this.invalidate();
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
/**
|
|
187
|
-
* Remove item from cache
|
|
188
|
-
*
|
|
189
|
-
* @param itemOrId - Item object or ID to remove
|
|
190
|
-
* @param matcher - Optional custom matcher function. Defaults to matching by key
|
|
191
|
-
*/
|
|
192
|
-
delete(itemOrId, matcher) {
|
|
193
|
-
try {
|
|
194
|
-
this.config.queryClient.setQueryData(this.config.queryKey, (oldData) => {
|
|
195
|
-
const items = this.getItems(oldData);
|
|
196
|
-
const matchFn = matcher || ((item) => {
|
|
197
|
-
if (typeof itemOrId === "object") {
|
|
198
|
-
return this.config.keyExtractor(item) === this.config.keyExtractor(itemOrId);
|
|
199
|
-
}
|
|
200
|
-
return this.config.keyExtractor(item) === itemOrId;
|
|
201
|
-
});
|
|
202
|
-
const originalLength = items.length;
|
|
203
|
-
const updatedItems = items.filter((item) => !matchFn(item));
|
|
204
|
-
const removedCount = originalLength - updatedItems.length;
|
|
205
|
-
let result = this.setItems(oldData, updatedItems);
|
|
206
|
-
if (removedCount > 0) {
|
|
207
|
-
result = this.updatePaginationOnRemove(result, removedCount);
|
|
208
|
-
}
|
|
209
|
-
return result;
|
|
210
|
-
});
|
|
211
|
-
} catch (error) {
|
|
212
|
-
console.error("[QueryCacheManager] Delete failed:", error);
|
|
213
|
-
this.invalidate();
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
/**
|
|
217
|
-
* Replace full data
|
|
218
|
-
*
|
|
219
|
-
* @param newData - Complete new data to replace cache
|
|
220
|
-
*/
|
|
221
|
-
replace(newData) {
|
|
222
|
-
try {
|
|
223
|
-
this.config.queryClient.setQueryData(this.config.queryKey, newData);
|
|
224
|
-
} catch (error) {
|
|
225
|
-
console.error("[QueryCacheManager] Replace failed:", error);
|
|
226
|
-
this.invalidate();
|
|
227
|
-
}
|
|
228
|
-
}
|
|
229
|
-
/**
|
|
230
|
-
* Clear all items (keeps structure, empties array)
|
|
231
|
-
*/
|
|
232
|
-
clear() {
|
|
233
|
-
try {
|
|
234
|
-
this.config.queryClient.setQueryData(this.config.queryKey, (oldData) => {
|
|
235
|
-
let result = this.setItems(oldData, []);
|
|
236
|
-
if (this.config.pagination?.totalElementsPath) {
|
|
237
|
-
result = setAtPath(result, this.config.pagination.totalElementsPath, 0);
|
|
238
|
-
}
|
|
239
|
-
if (this.config.pagination?.totalPagesPath) {
|
|
240
|
-
result = setAtPath(result, this.config.pagination.totalPagesPath, 0);
|
|
241
|
-
}
|
|
242
|
-
return result;
|
|
243
|
-
});
|
|
244
|
-
} catch (error) {
|
|
245
|
-
console.error("[QueryCacheManager] Clear failed:", error);
|
|
246
|
-
this.invalidate();
|
|
247
|
-
}
|
|
248
|
-
}
|
|
249
|
-
/**
|
|
250
|
-
* Get current items from cache
|
|
251
|
-
*
|
|
252
|
-
* @returns Current items array or empty array if no data
|
|
253
|
-
*/
|
|
254
|
-
getItemsFromCache() {
|
|
255
|
-
const data = this.config.queryClient.getQueryData(this.config.queryKey);
|
|
256
|
-
return this.getItems(data);
|
|
257
|
-
}
|
|
258
|
-
/**
|
|
259
|
-
* Get full data from cache
|
|
260
|
-
*
|
|
261
|
-
* @returns Current full data or undefined if no data
|
|
262
|
-
*/
|
|
263
|
-
getDataFromCache() {
|
|
264
|
-
return this.config.queryClient.getQueryData(this.config.queryKey);
|
|
265
|
-
}
|
|
266
|
-
/**
|
|
267
|
-
* Invalidate query to trigger refetch
|
|
268
|
-
*/
|
|
269
|
-
invalidate() {
|
|
270
|
-
this.config.queryClient.invalidateQueries({ queryKey: this.config.queryKey });
|
|
271
|
-
}
|
|
272
|
-
/**
|
|
273
|
-
* Get handlers for use with mutations
|
|
274
|
-
*
|
|
275
|
-
* @returns Object with onAdd, onUpdate, onDelete handlers
|
|
276
|
-
*/
|
|
277
|
-
createHandlers() {
|
|
278
|
-
return {
|
|
279
|
-
onAdd: (newItem, position) => this.add(newItem, position),
|
|
280
|
-
onUpdate: (updatedItem, matcher) => this.update(updatedItem, matcher),
|
|
281
|
-
onDelete: (itemOrId, matcher) => this.delete(itemOrId, matcher)
|
|
282
|
-
};
|
|
283
|
-
}
|
|
284
|
-
};
|
|
285
|
-
|
|
286
|
-
// src/utils/cacheRegistry.ts
|
|
287
|
-
var cacheConfigRegistry = /* @__PURE__ */ new Map();
|
|
288
|
-
var cacheRegistry = /* @__PURE__ */ new Map();
|
|
289
|
-
var defaultConfigs = {
|
|
290
|
-
paginated: {
|
|
291
|
-
itemsPath: "data.content",
|
|
292
|
-
pagination: {
|
|
293
|
-
totalElementsPath: "data.page.totalElements",
|
|
294
|
-
totalPagesPath: "data.page.totalPages",
|
|
295
|
-
currentPagePath: "data.page.number",
|
|
296
|
-
pageSizePath: "data.page.size"
|
|
297
|
-
}
|
|
298
|
-
},
|
|
299
|
-
nonPaginated: {
|
|
300
|
-
itemsPath: "data"
|
|
301
|
-
}
|
|
302
|
-
};
|
|
303
|
-
Object.entries(defaultConfigs).forEach(([key, config]) => {
|
|
304
|
-
cacheConfigRegistry.set(key, config);
|
|
305
|
-
});
|
|
306
|
-
var getOrCreateCacheManager = (queryKey, queryClient, options) => {
|
|
307
|
-
const key = JSON.stringify(queryKey);
|
|
308
|
-
if (cacheRegistry.has(key)) {
|
|
309
|
-
return cacheRegistry.get(key);
|
|
310
|
-
}
|
|
311
|
-
const cacheType = options?.cacheType;
|
|
312
|
-
const config = options?.cacheConfig || cacheType && cacheConfigRegistry.get(cacheType);
|
|
313
|
-
if (!config) {
|
|
314
|
-
throw new Error(
|
|
315
|
-
`[CacheManager] Unknown cacheType "${cacheType}". Available: ${[
|
|
316
|
-
...cacheConfigRegistry.keys()
|
|
317
|
-
].join(", ")}`
|
|
318
|
-
);
|
|
319
|
-
}
|
|
320
|
-
const manager = new QueryCacheManager({
|
|
321
|
-
queryClient,
|
|
322
|
-
queryKey,
|
|
323
|
-
...config
|
|
324
|
-
});
|
|
325
|
-
cacheRegistry.set(key, manager);
|
|
326
|
-
return manager;
|
|
327
|
-
};
|
|
328
|
-
var resetCacheManager = (queryKey) => {
|
|
329
|
-
cacheRegistry.delete(JSON.stringify(queryKey));
|
|
330
|
-
};
|
|
331
|
-
var resetAllCacheManagers = () => {
|
|
332
|
-
cacheRegistry.clear();
|
|
333
|
-
};
|
|
334
|
-
|
|
335
|
-
// src/hooks/useCustomQuery.ts
|
|
336
|
-
function useCustomQuery(options) {
|
|
337
|
-
const queryClient = useQueryClient();
|
|
338
|
-
const { queryKey, cacheType, cacheConfig, ...rest } = options;
|
|
339
|
-
const queryResult = useQuery({
|
|
340
|
-
queryKey,
|
|
341
|
-
...rest
|
|
342
|
-
});
|
|
343
|
-
let cache;
|
|
344
|
-
if (cacheType) {
|
|
345
|
-
cache = getOrCreateCacheManager(queryKey, queryClient, {
|
|
346
|
-
cacheType,
|
|
347
|
-
cacheConfig
|
|
348
|
-
});
|
|
349
|
-
}
|
|
350
|
-
return {
|
|
351
|
-
...queryResult,
|
|
352
|
-
cache
|
|
353
|
-
};
|
|
354
|
-
}
|
|
355
|
-
var NotificationContext = createContext(
|
|
356
|
-
void 0
|
|
357
|
-
);
|
|
358
|
-
|
|
359
|
-
// src/hooks/useNotificationContext.ts
|
|
360
|
-
var useNotificationContext = () => {
|
|
361
|
-
const context = useContext(NotificationContext);
|
|
362
|
-
if (!context) {
|
|
363
|
-
throw new Error("useNotificationContext must be used within an NotificationProvider");
|
|
364
|
-
}
|
|
365
|
-
return context;
|
|
366
|
-
};
|
|
367
|
-
|
|
368
|
-
// src/hooks/useCustomMutation.ts
|
|
369
|
-
var useCustomMutation = (options) => {
|
|
370
|
-
const {
|
|
371
|
-
onError,
|
|
372
|
-
onSuccess,
|
|
373
|
-
notify = false,
|
|
374
|
-
notifyError = false,
|
|
375
|
-
notifySuccess = false,
|
|
376
|
-
errorMessage = "Operation failed!",
|
|
377
|
-
successMessage = "Operation successfull!",
|
|
378
|
-
notificationConfig = { duration: 2 },
|
|
379
|
-
getErrorMessage,
|
|
380
|
-
...rest
|
|
381
|
-
} = options;
|
|
382
|
-
const { showSuccess, showError } = useNotificationContext();
|
|
383
|
-
return useMutation({
|
|
384
|
-
...rest,
|
|
385
|
-
onSuccess: (data, variables, context, mutation) => {
|
|
386
|
-
if (notify || notifySuccess) {
|
|
387
|
-
showSuccess(successMessage, notificationConfig);
|
|
388
|
-
}
|
|
389
|
-
onSuccess?.(data, variables, context, mutation);
|
|
390
|
-
},
|
|
391
|
-
onError: (apiError, variables, context, mutation) => {
|
|
392
|
-
const message = getErrorMessage ? getErrorMessage(apiError) : apiError?.error?.message ?? errorMessage;
|
|
393
|
-
if (notify || notifyError) {
|
|
394
|
-
showError(message, notificationConfig);
|
|
395
|
-
}
|
|
396
|
-
onError?.(apiError, variables, context, mutation);
|
|
397
|
-
}
|
|
398
|
-
});
|
|
399
|
-
};
|
|
400
|
-
var useQueryCacheManagers = (configs) => {
|
|
401
|
-
const queryClient = useQueryClient();
|
|
402
|
-
const managers = {};
|
|
403
|
-
Object.entries(configs).forEach(([key, config]) => {
|
|
404
|
-
const options = config.options ?? {};
|
|
405
|
-
managers[key] = new QueryCacheManager({
|
|
406
|
-
queryKey: config.queryKey,
|
|
407
|
-
queryClient,
|
|
408
|
-
...options,
|
|
409
|
-
itemsPath: options.itemsPath ?? ""
|
|
410
|
-
});
|
|
411
|
-
});
|
|
412
|
-
return managers;
|
|
413
|
-
};
|
|
414
|
-
|
|
415
|
-
export { QueryCacheManager, resetAllCacheManagers, resetCacheManager, useCustomMutation, useCustomQuery, useNotificationContext, useQueryCacheManagers };
|