@codeleap/query 6.2.3 → 6.8.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/dist/factors/createQueryManager.d.ts +36 -0
- package/dist/factors/createQueryManager.d.ts.map +1 -0
- package/dist/factors/createQueryOperations.d.ts +35 -0
- package/dist/factors/createQueryOperations.d.ts.map +1 -0
- package/dist/factors/index.d.ts +3 -0
- package/dist/factors/index.d.ts.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/lib/Mutations.d.ts +103 -0
- package/dist/lib/Mutations.d.ts.map +1 -0
- package/dist/lib/QueryClientEnhanced/index.d.ts +41 -0
- package/dist/lib/QueryClientEnhanced/index.d.ts.map +1 -0
- package/dist/lib/QueryClientEnhanced/types.d.ts +51 -0
- package/dist/lib/QueryClientEnhanced/types.d.ts.map +1 -0
- package/dist/lib/QueryKeys.d.ts +173 -0
- package/dist/lib/QueryKeys.d.ts.map +1 -0
- package/dist/lib/QueryManager.d.ts +202 -0
- package/dist/lib/QueryManager.d.ts.map +1 -0
- package/dist/lib/QueryOperations/index.d.ts +228 -0
- package/dist/lib/QueryOperations/index.d.ts.map +1 -0
- package/dist/lib/QueryOperations/types.d.ts +42 -0
- package/dist/lib/QueryOperations/types.d.ts.map +1 -0
- package/dist/lib/index.d.ts +6 -0
- package/dist/lib/index.d.ts.map +1 -0
- package/dist/types/core.d.ts +29 -0
- package/dist/types/core.d.ts.map +1 -0
- package/dist/types/create.d.ts +21 -0
- package/dist/types/create.d.ts.map +1 -0
- package/dist/types/delete.d.ts +18 -0
- package/dist/types/delete.d.ts.map +1 -0
- package/dist/types/index.d.ts +8 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/list.d.ts +19 -0
- package/dist/types/list.d.ts.map +1 -0
- package/dist/types/retrieve.d.ts +17 -0
- package/dist/types/retrieve.d.ts.map +1 -0
- package/dist/types/update.d.ts +13 -0
- package/dist/types/update.d.ts.map +1 -0
- package/dist/types/utility.d.ts +23 -0
- package/dist/types/utility.d.ts.map +1 -0
- package/dist/utils/index.d.ts +2 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/misc.d.ts +5 -0
- package/dist/utils/misc.d.ts.map +1 -0
- package/package.json +23 -8
- package/src/lib/Mutations.ts +30 -44
- package/src/lib/QueryClientEnhanced/index.ts +32 -4
- package/src/lib/QueryClientEnhanced/types.ts +25 -0
- package/src/lib/QueryKeys.ts +4 -2
- package/src/lib/QueryManager.ts +37 -33
- package/src/lib/QueryOperations/index.ts +11 -3
- package/src/lib/QueryOperations/types.ts +4 -3
- package/src/tests/setup.ts +14 -0
- package/src/types/core.ts +8 -1
- package/src/types/create.ts +10 -1
- package/src/types/delete.ts +8 -1
- package/src/types/list.ts +5 -0
- package/src/types/retrieve.ts +9 -0
- package/src/types/update.ts +3 -0
- package/src/types/utility.ts +5 -0
- package/src/utils/misc.ts +2 -0
- package/package.json.bak +0 -27
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { QueryManager } from '../lib';
|
|
2
|
+
import { QueryItem, QueryManagerOptions } from '../types';
|
|
3
|
+
/**
|
|
4
|
+
* Factory function to create a new QueryManager instance
|
|
5
|
+
* @template T - The query item type that extends QueryItem
|
|
6
|
+
* @template F - The filter type used for list queries
|
|
7
|
+
* @param options - Configuration options for the query manager
|
|
8
|
+
* @returns New QueryManager instance
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```typescript
|
|
12
|
+
* interface User extends QueryItem {
|
|
13
|
+
* name: string
|
|
14
|
+
* email: string
|
|
15
|
+
* status: 'active' | 'inactive'
|
|
16
|
+
* }
|
|
17
|
+
*
|
|
18
|
+
* interface UserFilters {
|
|
19
|
+
* status?: 'active' | 'inactive'
|
|
20
|
+
* search?: string
|
|
21
|
+
* }
|
|
22
|
+
*
|
|
23
|
+
* const userQueryManager = createQueryManager<User, UserFilters>({
|
|
24
|
+
* name: 'users',
|
|
25
|
+
* queryClient,
|
|
26
|
+
* listFn: (limit, offset, filters) => api.getUsers({ limit, offset, ...filters }),
|
|
27
|
+
* retrieveFn: (id) => api.getUser(id),
|
|
28
|
+
* createFn: (data) => api.createUser(data),
|
|
29
|
+
* updateFn: (data) => api.updateUser(data.id, data),
|
|
30
|
+
* deleteFn: (id) => api.deleteUser(id),
|
|
31
|
+
* listLimit: 20
|
|
32
|
+
* })
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export declare const createQueryManager: <T extends QueryItem, F = {}>(options: QueryManagerOptions<T, F>) => QueryManager<T, F>;
|
|
36
|
+
//# sourceMappingURL=createQueryManager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createQueryManager.d.ts","sourceRoot":"","sources":["../../src/factors/createQueryManager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,QAAQ,CAAA;AACrC,OAAO,EAAE,SAAS,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAA;AAEzD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,eAAO,MAAM,kBAAkB,GAAI,CAAC,SAAS,SAAS,EAAE,CAAC,GAAG,EAAE,EAAE,SAAS,mBAAmB,CAAC,CAAC,EAAE,CAAC,CAAC,uBAEjG,CAAA"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { QueryOperations } from '../lib';
|
|
2
|
+
import { QueryOperationsOptions } from '../lib/QueryOperations/types';
|
|
3
|
+
/**
|
|
4
|
+
* Factory function to create a new QueryOperations builder instance
|
|
5
|
+
* @param options - Configuration options including the QueryClient
|
|
6
|
+
* @returns New QueryOperations instance ready for operation registration
|
|
7
|
+
*
|
|
8
|
+
* @description
|
|
9
|
+
* This is the entry point for creating a new QueryOperations instance. Use this
|
|
10
|
+
* function to start building your collection of queries and mutations.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* import { QueryClient } from '@tanstack/react-query'
|
|
15
|
+
*
|
|
16
|
+
* const queryClient = new QueryClient()
|
|
17
|
+
*
|
|
18
|
+
* const userOperations = createQueryOperations({ queryClient })
|
|
19
|
+
* .query('getUser', async (id: string) => fetchUser(id))
|
|
20
|
+
* .query('getUsers', async (filters?: UserFilters) => fetchUsers(filters))
|
|
21
|
+
* .mutation('createUser', async (data: CreateUserData) => createUser(data))
|
|
22
|
+
* .mutation('updateUser', async (data: UpdateUserData) => updateUser(data))
|
|
23
|
+
* .mutation('deleteUser', async (id: string) => deleteUser(id))
|
|
24
|
+
*
|
|
25
|
+
* // In components
|
|
26
|
+
* function UserList() {
|
|
27
|
+
* const usersQuery = userOperations.useQuery('getUsers', { active: true })
|
|
28
|
+
* const createMutation = userOperations.useMutation('createUser')
|
|
29
|
+
*
|
|
30
|
+
* // Both hooks are fully type-safe
|
|
31
|
+
* }
|
|
32
|
+
* ```
|
|
33
|
+
*/
|
|
34
|
+
export declare function createQueryOperations(options: QueryOperationsOptions): QueryOperations<unknown, unknown>;
|
|
35
|
+
//# sourceMappingURL=createQueryOperations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createQueryOperations.d.ts","sourceRoot":"","sources":["../../src/factors/createQueryOperations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,QAAQ,CAAA;AACxC,OAAO,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAA;AAErE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,sBAAsB,qCAEpE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/factors/index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAA;AACpC,cAAc,yBAAyB,CAAA"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,OAAO,CAAA;AACrB,cAAc,SAAS,CAAA;AACvB,cAAc,WAAW,CAAA"}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { Query } from '@tanstack/query-core';
|
|
2
|
+
import { QueryKeys } from './QueryKeys';
|
|
3
|
+
import { QueryClient, QueryItem, RemovedItemMap, WithTempId } from '../types';
|
|
4
|
+
/**
|
|
5
|
+
* Class for managing mutations and cache updates for React Query list data
|
|
6
|
+
* @template T - The query item type that extends QueryItem
|
|
7
|
+
* @template F - The filter type used for list queries
|
|
8
|
+
*/
|
|
9
|
+
export declare class Mutations<T extends QueryItem, F> {
|
|
10
|
+
private queryKeys;
|
|
11
|
+
private queryClient;
|
|
12
|
+
private queryName;
|
|
13
|
+
/**
|
|
14
|
+
* Creates a new Mutations instance
|
|
15
|
+
* @param queryKeys - The QueryKeys instance for managing query keys
|
|
16
|
+
* @param queryClient - The React Query client instance
|
|
17
|
+
* @param queryName - The name of the query used for identification
|
|
18
|
+
*/
|
|
19
|
+
constructor(queryKeys: QueryKeys<T, F>, queryClient: QueryClient, queryName: string);
|
|
20
|
+
/**
|
|
21
|
+
* Adds a new item to the cached list data
|
|
22
|
+
* @param newItem - The new item to add to the list
|
|
23
|
+
* @param position - Where to add the item: 'start', 'end', or a RemovedItemMap for specific positions
|
|
24
|
+
* @param listFilters - Optional filters to target specific list queries
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```typescript
|
|
28
|
+
* // Add item to the beginning
|
|
29
|
+
* mutations.addItem(newUser, 'start')
|
|
30
|
+
*
|
|
31
|
+
* // Add item to the end with filters
|
|
32
|
+
* mutations.addItem(newUser, 'end', { status: 'active' })
|
|
33
|
+
*
|
|
34
|
+
* // Add item to specific positions (restore from removed item map)
|
|
35
|
+
* mutations.addItem(newUser, removedItemMap)
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
private _addItemAtKey;
|
|
39
|
+
addItem(newItem: T, position?: 'start' | 'end' | RemovedItemMap, listFilters?: F): void;
|
|
40
|
+
addItemToQuery(newItem: T, position: "start" | "end" | undefined, query: Query): void;
|
|
41
|
+
/**
|
|
42
|
+
* Removes an item from all or specific cached list query and returns the positions where it was found
|
|
43
|
+
* @param itemId - The ID of the item to remove
|
|
44
|
+
* @param listFilters - Optional filters to target a specific list query. If omitted, removes from all list queries
|
|
45
|
+
* @returns A RemovedItemMap containing the query keys and positions where the item was found, or null if not found in any query
|
|
46
|
+
*
|
|
47
|
+
* @example
|
|
48
|
+
* ```typescript
|
|
49
|
+
* // Remove from all list queries
|
|
50
|
+
* const removedPositions = mutations.removeItem('user-123')
|
|
51
|
+
*
|
|
52
|
+
* // Remove from a specific filtered list
|
|
53
|
+
* const removedPositions = mutations.removeItem('user-123', { status: 'active' })
|
|
54
|
+
*
|
|
55
|
+
* // Later, restore the item to its original positions
|
|
56
|
+
* if (removedPositions) {
|
|
57
|
+
* mutations.addItem(restoredUser, removedPositions)
|
|
58
|
+
* }
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
removeItem(itemId: QueryItem['id'], listFilters?: F): RemovedItemMap | null;
|
|
62
|
+
/**
|
|
63
|
+
* Updates existing items in all cached list queries and individual retrieve queries
|
|
64
|
+
* @param data - Single item or array of items to update. Items can have tempId for temporary identification
|
|
65
|
+
*
|
|
66
|
+
* @description
|
|
67
|
+
* This method:
|
|
68
|
+
* - Finds items by their ID or tempId in all list queries
|
|
69
|
+
* - Updates the items only if the data has actually changed (uses deep equality check)
|
|
70
|
+
* - Updates both list cache and individual retrieve cache
|
|
71
|
+
* - Removes tempId from the final cached data
|
|
72
|
+
*
|
|
73
|
+
* @example
|
|
74
|
+
* ```typescript
|
|
75
|
+
* // Update single item
|
|
76
|
+
* mutations.updateItems({ id: 'user-123', name: 'Updated Name', tempId: 'temp-1' })
|
|
77
|
+
*
|
|
78
|
+
* // Update multiple items
|
|
79
|
+
* mutations.updateItems([
|
|
80
|
+
* { id: 'user-123', name: 'Updated Name' },
|
|
81
|
+
* { id: 'user-456', status: 'active' }
|
|
82
|
+
* ])
|
|
83
|
+
* ```
|
|
84
|
+
*/
|
|
85
|
+
updateItems(data: WithTempId<T> | WithTempId<T>[]): void;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Factory function to create a new Mutations instance
|
|
89
|
+
* @template T - The query item type that extends QueryItem
|
|
90
|
+
* @template F - The filter type used for list queries
|
|
91
|
+
* @param queryKeys - The QueryKeys instance for managing query keys
|
|
92
|
+
* @param queryClient - The React Query client instance
|
|
93
|
+
* @param queryName - The name of the query used for identification
|
|
94
|
+
* @returns New Mutations instance
|
|
95
|
+
*
|
|
96
|
+
* @example
|
|
97
|
+
* ```typescript
|
|
98
|
+
* const userQueryKeys = createQueryKeys<User, UserFilters>('users', queryClient)
|
|
99
|
+
* const userMutations = createMutations(userQueryKeys, queryClient, 'users')
|
|
100
|
+
* ```
|
|
101
|
+
*/
|
|
102
|
+
export declare const createMutations: <T extends QueryItem, F>(queryKeys: QueryKeys<T, F>, queryClient: QueryClient, queryName: string) => Mutations<T, F>;
|
|
103
|
+
//# sourceMappingURL=Mutations.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Mutations.d.ts","sourceRoot":"","sources":["../../src/lib/Mutations.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,EAAY,MAAM,sBAAsB,CAAA;AACpE,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACvC,OAAO,EAAmD,WAAW,EAAE,SAAS,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAI9H;;;;GAIG;AACH,qBAAa,SAAS,CAAC,CAAC,SAAS,SAAS,EAAE,CAAC;IAQzC,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,WAAW;IACnB,OAAO,CAAC,SAAS;IATnB;;;;;OAKG;gBAEO,SAAS,EAAE,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,EAC1B,WAAW,EAAE,WAAW,EACxB,SAAS,EAAE,MAAM;IAG3B;;;;;;;;;;;;;;;;;OAiBG;IACH,OAAO,CAAC,aAAa;IAwBrB,OAAO,CAAC,OAAO,EAAE,CAAC,EAAE,QAAQ,GAAE,OAAO,GAAG,KAAK,GAAG,cAAwB,EAAE,WAAW,CAAC,EAAE,CAAC;IAiCzF,cAAc,CAAC,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,OAAO,GAAG,KAAK,YAAU,EAAE,KAAK,EAAE,KAAK,GAAG,IAAI;IAInF;;;;;;;;;;;;;;;;;;;OAmBG;IACH,UAAU,CAAC,MAAM,EAAE,SAAS,CAAC,IAAI,CAAC,EAAE,WAAW,CAAC,EAAE,CAAC,GAAG,cAAc,GAAG,IAAI;IAoD3E;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,WAAW,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,EAAE;CAsDlD;AAED;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,eAAe,GAAI,CAAC,SAAS,SAAS,EAAE,CAAC,EAAE,WAAW,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,aAAa,WAAW,EAAE,WAAW,MAAM,oBAE9H,CAAA"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { QueryClient, QueryKey, Query, QueryCacheNotifyEvent, QueryOptions } from '@tanstack/react-query';
|
|
2
|
+
import { DynamicEnhancedQuery, EnhancedQuery, PollQueryOptions, QueryKeyBuilder } from './types';
|
|
3
|
+
/**
|
|
4
|
+
* Thin wrapper around React Query's `QueryClient` that adds async primitives for polling, event listening, and proxy-based query handles.
|
|
5
|
+
* Pass an instance of this class wherever `QueryClient | QueryClientEnhanced` is accepted to unlock the enhanced API.
|
|
6
|
+
*/
|
|
7
|
+
export declare class QueryClientEnhanced {
|
|
8
|
+
client: QueryClient;
|
|
9
|
+
constructor(client: QueryClient);
|
|
10
|
+
/**
|
|
11
|
+
* Subscribes to cache events for a single query key.
|
|
12
|
+
* Returns the unsubscribe function, or `undefined` when the query is not yet in the cache.
|
|
13
|
+
*/
|
|
14
|
+
listenToQuery(key: QueryKey, callback: (e: QueryCacheNotifyEvent) => void): (() => void) | undefined;
|
|
15
|
+
/**
|
|
16
|
+
* Repeatedly refetches a query on a fixed `interval` until the `callback` returns `{ stop: true }`.
|
|
17
|
+
* Rejects immediately if the query key is not present in the cache when called.
|
|
18
|
+
*/
|
|
19
|
+
pollQuery<T, R>(key: QueryKey, options: PollQueryOptions<T, R>): Promise<R>;
|
|
20
|
+
/**
|
|
21
|
+
* Returns an `EnhancedQuery<T>` Proxy for `key`.
|
|
22
|
+
* `getData` and `setData` work even when the query is not yet in the cache; all other members log a warning and return `undefined` when the query is absent.
|
|
23
|
+
*/
|
|
24
|
+
queryProxy<T>(key: QueryKey): EnhancedQuery<T>;
|
|
25
|
+
/**
|
|
26
|
+
* Resolves with the refreshed `Query` object once it reaches a settled `idle` state with a `dataUpdatedAt` or `errorUpdatedAt` timestamp newer than the moment of the call.
|
|
27
|
+
* Rejects when the query is absent from the cache or when the fetch results in an error.
|
|
28
|
+
*/
|
|
29
|
+
waitForRefresh<T>(key: QueryKey): Promise<Query<T, Error, T, readonly unknown[]>>;
|
|
30
|
+
/**
|
|
31
|
+
* Registers a static query key and returns an `EnhancedQuery<Data>` proxy for it.
|
|
32
|
+
* When `options` are provided they are applied as query defaults and the query is pre-seeded in the cache — useful for initialising queries outside of a React component.
|
|
33
|
+
*/
|
|
34
|
+
queryKey<Data>(k: QueryKey, options?: QueryOptions<Data>): EnhancedQuery<Data>;
|
|
35
|
+
/**
|
|
36
|
+
* Returns a `DynamicEnhancedQuery` proxy whose every member is a function that accepts `BuilderArgs` to derive the final key before delegating.
|
|
37
|
+
* Use this when the query key depends on runtime parameters (e.g. `(id: string) => ['users', id]`).
|
|
38
|
+
*/
|
|
39
|
+
dynamicQueryKey<Data, BuilderArgs extends any[] = any[]>(k: QueryKeyBuilder<BuilderArgs>): DynamicEnhancedQuery<Data, BuilderArgs>;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/QueryClientEnhanced/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,KAAK,EAAW,qBAAqB,EAAc,YAAY,EAAE,MAAM,uBAAuB,CAAA;AAC9H,OAAO,EAAE,oBAAoB,EAAE,aAAa,EAAE,gBAAgB,EAAiB,eAAe,EAAE,MAAM,SAAS,CAAA;AAE/G;;;GAGG;AACH,qBAAa,mBAAmB;IACX,MAAM,EAAE,WAAW;gBAAnB,MAAM,EAAE,WAAW;IAEtC;;;OAGG;IACH,aAAa,CAAC,GAAG,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC,CAAC,EAAE,qBAAqB,KAAK,IAAI;IAqBzE;;;OAGG;IACG,SAAS,CAAC,CAAC,EAAE,CAAC,EAClB,GAAG,EAAE,QAAQ,EACb,OAAO,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC;IAwCjC;;;OAGG;IACH,UAAU,CAAC,CAAC,EAAE,GAAG,EAAE,QAAQ;IA6E3B;;;OAGG;IACH,cAAc,CAAC,CAAC,EAAE,GAAG,EAAE,QAAQ;IAqC/B;;;OAGG;IACH,QAAQ,CAAC,IAAI,EAAE,CAAC,EAAE,QAAQ,EAAE,OAAO,CAAC,EAAE,YAAY,CAAC,IAAI,CAAC;IAmBxD;;;OAGG;IACH,eAAe,CAAC,IAAI,EAAE,WAAW,SAAS,GAAG,EAAE,GAAG,GAAG,EAAE,EAAE,CAAC,EAAE,eAAe,CAAC,WAAW,CAAC;CAezF"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { QueryKey, Query, QueryCacheNotifyEvent, EnsureQueryDataOptions } from '@tanstack/react-query';
|
|
2
|
+
/** A function that accepts typed arguments and returns the `QueryKey` array for a given query. Used with `dynamicQueryKey` to create parameterised query proxies. */
|
|
3
|
+
export type QueryKeyBuilder<Args extends any[] = any[]> = (...args: Args) => QueryKey;
|
|
4
|
+
/** Value returned by a `PollingCallback` on each tick. Set `stop: true` to terminate the polling loop. */
|
|
5
|
+
export type PollingResult<T> = {
|
|
6
|
+
stop: boolean;
|
|
7
|
+
data: T;
|
|
8
|
+
};
|
|
9
|
+
/**
|
|
10
|
+
* Called after each poll tick.
|
|
11
|
+
* @param query — the refreshed query snapshot
|
|
12
|
+
* @param count — zero-based tick counter
|
|
13
|
+
* @param prev — result data from the previous tick, `undefined` on the first call
|
|
14
|
+
* Return `{ stop: true, data }` to end polling; `{ stop: false, data }` to continue.
|
|
15
|
+
*/
|
|
16
|
+
export type PollingCallback<T, R> = (query: Query<T>, count: number, prev?: R) => Promise<PollingResult<R>>;
|
|
17
|
+
export type PollQueryOptions<T, R> = {
|
|
18
|
+
/** Milliseconds to wait between each refetch. */
|
|
19
|
+
interval: number;
|
|
20
|
+
callback: PollingCallback<T, R>;
|
|
21
|
+
/** When `true`, fires the first refetch immediately instead of waiting one `interval`. Defaults to `false`. */
|
|
22
|
+
leading?: boolean;
|
|
23
|
+
/** Seed value passed as `prev` to the callback on the very first tick. */
|
|
24
|
+
initialData?: R;
|
|
25
|
+
};
|
|
26
|
+
/**
|
|
27
|
+
* A Proxy-based handle to a specific query inside `QueryClientEnhanced`.
|
|
28
|
+
* Extends the raw React Query `Query` object with ergonomic async helpers.
|
|
29
|
+
* Obtain via `queryKey()` or `queryProxy()` — do not instantiate directly.
|
|
30
|
+
*/
|
|
31
|
+
export interface EnhancedQuery<T> extends Query<T> {
|
|
32
|
+
/** Resolves once the query transitions to a settled `idle` state newer than when the call was made. Rejects if the query errors. */
|
|
33
|
+
waitForRefresh(): Promise<Query<T>>;
|
|
34
|
+
/** Subscribe to every cache notification for this query. Returns the unsubscribe function. */
|
|
35
|
+
listen(callback: (e: QueryCacheNotifyEvent) => void): () => void;
|
|
36
|
+
/** Triggers a refetch and resolves with the fresh data once settled. */
|
|
37
|
+
refresh(): Promise<T>;
|
|
38
|
+
poll<R>(options: PollQueryOptions<T, R>): Promise<R>;
|
|
39
|
+
/** Synchronous cache read — returns `undefined` when the query has never been fetched. */
|
|
40
|
+
getData(): T;
|
|
41
|
+
ensureData(options?: Partial<EnsureQueryDataOptions<T, Error, T, QueryKey, never>>): Promise<T>;
|
|
42
|
+
key: QueryKey;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Parameterised variant of `EnhancedQuery` produced by `dynamicQueryKey`.
|
|
46
|
+
* Every method accepts `BuilderArgs` to resolve the key before delegating to the underlying `EnhancedQuery`.
|
|
47
|
+
*/
|
|
48
|
+
export type DynamicEnhancedQuery<T, BuilderArgs extends any[]> = {
|
|
49
|
+
[P in keyof EnhancedQuery<T>]: (...args: BuilderArgs) => EnhancedQuery<T>[P];
|
|
50
|
+
};
|
|
51
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/lib/QueryClientEnhanced/types.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,QAAQ,EACR,KAAK,EACL,qBAAqB,EACrB,sBAAsB,EACvB,MAAM,uBAAuB,CAAA;AAE9B,qKAAqK;AACrK,MAAM,MAAM,eAAe,CAAC,IAAI,SAAS,GAAG,EAAE,GAAG,GAAG,EAAE,IAAI,CAAC,GAAG,IAAI,EAAE,IAAI,KAAK,QAAQ,CAAA;AAErF,0GAA0G;AAC1G,MAAM,MAAM,aAAa,CAAC,CAAC,IAAI;IAC7B,IAAI,EAAE,OAAO,CAAA;IACb,IAAI,EAAE,CAAC,CAAA;CACR,CAAA;AAED;;;;;;GAMG;AACH,MAAM,MAAM,eAAe,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,CAAC,KAAK,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAA;AAE3G,MAAM,MAAM,gBAAgB,CAAC,CAAC,EAAE,CAAC,IAAI;IACnC,iDAAiD;IACjD,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA;IAC/B,+GAA+G;IAC/G,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,0EAA0E;IAC1E,WAAW,CAAC,EAAE,CAAC,CAAA;CAChB,CAAA;AAED;;;;GAIG;AACH,MAAM,WAAW,aAAa,CAAC,CAAC,CAAE,SAAQ,KAAK,CAAC,CAAC,CAAC;IAChD,oIAAoI;IACpI,cAAc,IAAI,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;IACnC,8FAA8F;IAC9F,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC,EAAE,qBAAqB,KAAK,IAAI,GAAG,MAAM,IAAI,CAAA;IAChE,wEAAwE;IACxE,OAAO,IAAI,OAAO,CAAC,CAAC,CAAC,CAAA;IACrB,IAAI,CAAC,CAAC,EACJ,OAAO,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC,CAAC,GAC9B,OAAO,CAAC,CAAC,CAAC,CAAA;IACb,0FAA0F;IAC1F,OAAO,IAAI,CAAC,CAAA;IACZ,UAAU,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,sBAAsB,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAA;IAC/F,GAAG,EAAE,QAAQ,CAAA;CACd;AAED;;;GAGG;AACH,MAAM,MAAM,oBAAoB,CAAC,CAAC,EAAE,WAAW,SAAS,GAAG,EAAE,IAAI;KAC9D,CAAC,IAAI,MAAM,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,GAAG,IAAI,EAAE,WAAW,KAAK,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;CAC7E,CAAA"}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
import { CancelOptions, InvalidateOptions, InvalidateQueryFilters, Query, QueryFilters, QueryKey, RefetchOptions, RefetchQueryFilters } from '@tanstack/react-query';
|
|
2
|
+
import { ListPaginationResponse, ListSelector, QueryClient, QueryItem, RetrieveDataOptions } from '../types';
|
|
3
|
+
/**
|
|
4
|
+
* Class for managing React Query keys and operations for a specific query type
|
|
5
|
+
* @template T - The query item type that extends QueryItem
|
|
6
|
+
* @template F - The filter type used for list queries
|
|
7
|
+
*/
|
|
8
|
+
export declare class QueryKeys<T extends QueryItem, F> {
|
|
9
|
+
private queryName;
|
|
10
|
+
private queryClient;
|
|
11
|
+
/**
|
|
12
|
+
* Creates a new QueryKeys instance
|
|
13
|
+
* @param queryName - The name of the query used as base for all keys
|
|
14
|
+
* @param queryClient - The React Query client instance
|
|
15
|
+
*/
|
|
16
|
+
constructor(queryName: string, queryClient: QueryClient);
|
|
17
|
+
/**
|
|
18
|
+
* Gets the base query keys for different operations
|
|
19
|
+
* @returns Object containing base query keys for list, retrieve, create, update, and delete operations
|
|
20
|
+
*/
|
|
21
|
+
get keys(): {
|
|
22
|
+
list: QueryKey;
|
|
23
|
+
retrieve: (id: QueryItem["id"]) => QueryKey;
|
|
24
|
+
create: QueryKey;
|
|
25
|
+
update: QueryKey;
|
|
26
|
+
delete: QueryKey;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Generates a list query key with optional filters
|
|
30
|
+
* @param filters - Optional filters to include in the query key
|
|
31
|
+
* @returns Query key array with or without filters
|
|
32
|
+
*/
|
|
33
|
+
listKeyWithFilters(filters?: F): QueryKey;
|
|
34
|
+
/**
|
|
35
|
+
* React hook that returns a memoized list query key with filters
|
|
36
|
+
* @param filters - Optional filters to include in the query key
|
|
37
|
+
* @returns Memoized query key array
|
|
38
|
+
*/
|
|
39
|
+
useListKeyWithFilters(filters?: F): readonly unknown[];
|
|
40
|
+
/**
|
|
41
|
+
* React hook that returns a memoized retrieve query key
|
|
42
|
+
* @param id - The ID of the item to retrieve
|
|
43
|
+
* @returns Memoized query key array for retrieve operation
|
|
44
|
+
*/
|
|
45
|
+
useRetrieveKey(id: QueryItem['id']): readonly unknown[];
|
|
46
|
+
/**
|
|
47
|
+
* Predicate function to check if a query belongs to this query name (all operations)
|
|
48
|
+
* @private
|
|
49
|
+
* @param queryName - The query name to match against
|
|
50
|
+
* @param query - The query object to check
|
|
51
|
+
* @returns True if the query matches the query name
|
|
52
|
+
*/
|
|
53
|
+
private predicateQueryKeyAll;
|
|
54
|
+
/**
|
|
55
|
+
* Predicate function to check if a query is a list query for this query name
|
|
56
|
+
* @private
|
|
57
|
+
* @param queryName - The query name to match against
|
|
58
|
+
* @param query - The query object to check
|
|
59
|
+
* @param toIgnoreQueryKeys - Query keys to ignore in the matching
|
|
60
|
+
* @returns True if the query is a list query and not in the ignore list
|
|
61
|
+
*/
|
|
62
|
+
private predicateQueryKeyList;
|
|
63
|
+
/**
|
|
64
|
+
* Invalidates all queries for this query name
|
|
65
|
+
* @param filters - Optional filters to apply to the invalidation
|
|
66
|
+
* @param options - Optional invalidation options
|
|
67
|
+
* @returns Promise that resolves when invalidation is complete
|
|
68
|
+
*/
|
|
69
|
+
invalidateAll(filters?: InvalidateQueryFilters<QueryKey>, options?: InvalidateOptions): Promise<void>;
|
|
70
|
+
/**
|
|
71
|
+
* Invalidates list queries, optionally with specific filters
|
|
72
|
+
* @param listFilters - Optional filters to target specific list queries
|
|
73
|
+
* @param ignoreQueryKeys - Query keys to ignore during invalidation
|
|
74
|
+
* @param filters - Optional filters to apply to the invalidation
|
|
75
|
+
* @param options - Optional invalidation options
|
|
76
|
+
* @returns Promise that resolves when invalidation is complete
|
|
77
|
+
*/
|
|
78
|
+
invalidateList(listFilters?: F, ignoreQueryKeys?: QueryKey | QueryKey[], filters?: InvalidateQueryFilters<QueryKey>, options?: InvalidateOptions): Promise<void>;
|
|
79
|
+
/**
|
|
80
|
+
* Invalidates a specific retrieve query by ID
|
|
81
|
+
* @param id - The ID of the item to invalidate
|
|
82
|
+
* @param filters - Optional filters to apply to the invalidation
|
|
83
|
+
* @param options - Optional invalidation options
|
|
84
|
+
* @returns Promise that resolves when invalidation is complete
|
|
85
|
+
*/
|
|
86
|
+
invalidateRetrieve(id: QueryItem['id'], filters?: InvalidateQueryFilters<QueryKey>, options?: InvalidateOptions): Promise<void>;
|
|
87
|
+
/**
|
|
88
|
+
* Refetches all queries for this query name
|
|
89
|
+
* @param filters - Optional filters to apply to the refetch
|
|
90
|
+
* @param options - Optional refetch options
|
|
91
|
+
* @returns Promise that resolves when refetch is complete
|
|
92
|
+
*/
|
|
93
|
+
refetchAll(filters?: RefetchQueryFilters<QueryKey>, options?: RefetchOptions): Promise<void>;
|
|
94
|
+
/**
|
|
95
|
+
* Refetches list queries, optionally with specific filters
|
|
96
|
+
* @param listFilters - Optional filters to target specific list queries
|
|
97
|
+
* @param ignoreQueryKeys - Query keys to ignore during refetch
|
|
98
|
+
* @param filters - Optional filters to apply to the refetch
|
|
99
|
+
* @param options - Optional refetch options
|
|
100
|
+
* @returns Promise that resolves when refetch is complete
|
|
101
|
+
*/
|
|
102
|
+
refetchList(listFilters?: F, ignoreQueryKeys?: QueryKey | QueryKey[], filters?: RefetchQueryFilters<QueryKey>, options?: RefetchOptions): Promise<void>;
|
|
103
|
+
/**
|
|
104
|
+
* Refetches a specific retrieve query by ID
|
|
105
|
+
* @param id - The ID of the item to refetch
|
|
106
|
+
* @param filters - Optional filters to apply to the refetch
|
|
107
|
+
* @param options - Optional refetch options
|
|
108
|
+
* @returns Promise that resolves when refetch is complete
|
|
109
|
+
*/
|
|
110
|
+
refetchRetrieve(id: QueryItem['id'], filters?: RefetchQueryFilters<QueryKey>, options?: RefetchOptions): Promise<void>;
|
|
111
|
+
/**
|
|
112
|
+
* Removes a specific retrieve query data from the cache
|
|
113
|
+
* @param id - The ID of the item to remove from cache
|
|
114
|
+
* @param filters - Optional filters to apply to the removal
|
|
115
|
+
* @returns Promise that resolves when removal is complete
|
|
116
|
+
*/
|
|
117
|
+
removeRetrieveQueryData(id: QueryItem['id'], filters?: QueryFilters<QueryKey>): Promise<void>;
|
|
118
|
+
/**
|
|
119
|
+
* Cancels list queries that are currently in flight
|
|
120
|
+
* @param listFilters - Optional filters to target specific list queries
|
|
121
|
+
* @param ignoreQueryKeys - Query keys to ignore during cancellation
|
|
122
|
+
* @param filters - Optional filters to apply to the cancellation
|
|
123
|
+
* @param options - Optional cancellation options
|
|
124
|
+
* @returns Promise that resolves when cancellation is complete
|
|
125
|
+
*/
|
|
126
|
+
cancelListQueries(listFilters?: F, ignoreQueryKeys?: QueryKey | QueryKey[], filters?: QueryFilters<QueryKey>, options?: CancelOptions): Promise<void>;
|
|
127
|
+
/**
|
|
128
|
+
* Gets list data from the cache, including both items array and item map
|
|
129
|
+
* @param filters - Optional filters to target specific list data
|
|
130
|
+
* @returns Object containing items array and itemMap (keyed by ID)
|
|
131
|
+
*/
|
|
132
|
+
getListData(filters?: F): {
|
|
133
|
+
items: T[];
|
|
134
|
+
itemMap: Record<string | number, T>;
|
|
135
|
+
};
|
|
136
|
+
/**
|
|
137
|
+
* Retrieves item data from cache with intelligent fallback strategies
|
|
138
|
+
*
|
|
139
|
+
* @description Searches for an item using a multi-layered approach:
|
|
140
|
+
* 1. Direct cache lookup using retrieve query
|
|
141
|
+
* 2. Fallback to itemMap from list data (shallow search)
|
|
142
|
+
* 3. Deep search through all paginated list queries
|
|
143
|
+
*
|
|
144
|
+
* @param {QueryItem['id']} id - The unique identifier of the item to retrieve
|
|
145
|
+
* @param {RetrieveDataOptions} [options] - Configuration options for retrieval behavior
|
|
146
|
+
* @param {boolean} [options.onlyQueryData=false] - If true, only returns data from the specific retrieve query cache, ignoring list data fallbacks
|
|
147
|
+
* @param {boolean} [options.deepSearch=true] - If true, performs deep search through paginated queries when item not found in direct cache or itemMap
|
|
148
|
+
*
|
|
149
|
+
* @returns Item | undefined
|
|
150
|
+
*/
|
|
151
|
+
getRetrieveData(id: QueryItem['id'], options?: RetrieveDataOptions): T | undefined;
|
|
152
|
+
/**
|
|
153
|
+
* Gets all list queries from the query cache
|
|
154
|
+
* @returns Array of list queries for this query name
|
|
155
|
+
*/
|
|
156
|
+
getAllListQueries(): Query<ListPaginationResponse<T>, Error, Omit<ListSelector<T>, "allItems">, QueryKey>[];
|
|
157
|
+
/**
|
|
158
|
+
* Gets a specific list query from the query cache
|
|
159
|
+
* @param listFilters - Optional filters to identify a specific list query. If omitted, returns the unfiltered list query
|
|
160
|
+
* @returns The matching list query, or undefined if not found
|
|
161
|
+
*/
|
|
162
|
+
getListQuery(listFilters?: F): Query<ListPaginationResponse<T>, Error, Omit<ListSelector<T>, "allItems">, QueryKey>;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Factory function to create a new QueryKeys instance
|
|
166
|
+
* @template T - The query item type that extends QueryItem
|
|
167
|
+
* @template F - The filter type used for list queries
|
|
168
|
+
* @param name - The name of the query used as base for all keys
|
|
169
|
+
* @param queryClient - The React Query client instance
|
|
170
|
+
* @returns New QueryKeys instance
|
|
171
|
+
*/
|
|
172
|
+
export declare const createQueryKeys: <T extends QueryItem, F>(name: string, queryClient: QueryClient) => QueryKeys<T, F>;
|
|
173
|
+
//# sourceMappingURL=QueryKeys.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"QueryKeys.d.ts","sourceRoot":"","sources":["../../src/lib/QueryKeys.ts"],"names":[],"mappings":"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"}
|