react-redux-cache 0.4.2 → 0.5.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/README.md +125 -83
- package/dist/createActions.d.ts +8 -8
- package/dist/createCache.d.ts +34 -30
- package/dist/createCache.js +9 -0
- package/dist/index.js +2 -4
- package/dist/mutate.d.ts +1 -1
- package/dist/mutate.js +2 -1
- package/dist/query.d.ts +1 -1
- package/dist/query.js +8 -14
- package/dist/reducer.d.ts +12 -12
- package/dist/types.d.ts +13 -15
- package/dist/useMutation.d.ts +2 -2
- package/dist/useQuery.d.ts +1 -1
- package/dist/useQuery.js +1 -16
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -15,74 +15,103 @@
|
|
|
15
15
|
|
|
16
16
|
Can be considered as `ApolloClient` for protocols other than `GraphQL`, but with **full control** over its storage - redux store, with ability to write custom selectors, actions and reducers to manage cached state.
|
|
17
17
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
18
|
+
Examples of states, generated by cache reducer from `/example` project:
|
|
19
|
+
<details>
|
|
20
|
+
<summary>
|
|
21
|
+
Normalized
|
|
22
|
+
</summary>
|
|
23
|
+
|
|
24
|
+
```js
|
|
25
|
+
{
|
|
26
|
+
entities: {
|
|
27
|
+
// each typename has its own map of entities, stored by id
|
|
28
|
+
users: {
|
|
29
|
+
"0": {id: 0, bankId: "0", name: "User 0 *"},
|
|
30
|
+
"1": {id: 1, bankId: "1", name: "User 1 *"},
|
|
31
|
+
"2": {id: 2, bankId: "2", name: "User 2"},
|
|
32
|
+
"3": {id: 3, bankId: "3", name: "User 3"}
|
|
33
|
+
},
|
|
34
|
+
banks: {
|
|
35
|
+
"0": {id: "0", name: "Bank 0"},
|
|
36
|
+
"1": {id: "1", name: "Bank 1"},
|
|
37
|
+
"2": {id: "2", name: "Bank 2"},
|
|
38
|
+
"3": {id: "3", name: "Bank 3"}
|
|
39
|
+
}
|
|
28
40
|
},
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
+
queries: {
|
|
42
|
+
// each query has its own map of query states, stored by cache key, which is generated from query params
|
|
43
|
+
getUser: {
|
|
44
|
+
"2": {loading: false, error: undefined, result: 2, params: 2},
|
|
45
|
+
"3": {loading: true, params: 3}
|
|
46
|
+
},
|
|
47
|
+
getUsers: {
|
|
48
|
+
// example of paginated state under custom cache key
|
|
49
|
+
"all-pages": {
|
|
50
|
+
loading: false,
|
|
51
|
+
result: {items: [0,1,2], page: 1},
|
|
52
|
+
params: {page: 1}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
41
55
|
},
|
|
42
|
-
|
|
43
|
-
//
|
|
44
|
-
|
|
56
|
+
mutations: {
|
|
57
|
+
// each mutation has its own state as well
|
|
58
|
+
updateUser: {
|
|
59
|
+
loading: false,
|
|
60
|
+
result: 1,
|
|
61
|
+
params: {id: 1, name: "User 1 *"}
|
|
62
|
+
}
|
|
45
63
|
}
|
|
46
|
-
},
|
|
47
|
-
mutations: {
|
|
48
|
-
// each mutation has its own state as well
|
|
49
|
-
updateUser: {loading: false, result: 1}
|
|
50
64
|
}
|
|
51
|
-
|
|
52
|
-
|
|
65
|
+
```
|
|
66
|
+
</details>
|
|
53
67
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
68
|
+
<details>
|
|
69
|
+
<summary>
|
|
70
|
+
Not normalized
|
|
71
|
+
</summary>
|
|
72
|
+
|
|
73
|
+
```js
|
|
74
|
+
{
|
|
75
|
+
// entities map is used for normalization and is empty here
|
|
76
|
+
entities: {},
|
|
77
|
+
queries: {
|
|
78
|
+
// each query has its own map of query states, stored by cache key, which is generated from query params
|
|
79
|
+
getUser: {
|
|
80
|
+
"2": {
|
|
81
|
+
loading: false,
|
|
82
|
+
error: undefined,
|
|
83
|
+
result: {id: 2, bank: {id: "2", name: "Bank 2"}, name: "User 2"},
|
|
84
|
+
params: 2
|
|
85
|
+
},
|
|
86
|
+
"3": {loading: true, params: 3}
|
|
87
|
+
},
|
|
88
|
+
getUsers: {
|
|
89
|
+
// example of paginated state under custom cache key
|
|
90
|
+
"all-pages": {
|
|
91
|
+
loading: false,
|
|
92
|
+
result: {
|
|
93
|
+
items: [
|
|
94
|
+
{id: 0, bank: {id: "0", name: "Bank 0"}, name: "User 0 *"},
|
|
95
|
+
{id: 1, bank: {id: "1", name: "Bank 1"}, name: "User 1 *"},
|
|
96
|
+
{id: 2, bank: {id: "2", name: "Bank 2"}, name: "User 2"}
|
|
97
|
+
],
|
|
98
|
+
page: 1
|
|
99
|
+
},
|
|
100
|
+
params: {page: 1}
|
|
76
101
|
}
|
|
77
102
|
}
|
|
103
|
+
},
|
|
104
|
+
mutations: {
|
|
105
|
+
// each mutation has its own state as well
|
|
106
|
+
updateUser: {
|
|
107
|
+
loading: false,
|
|
108
|
+
result: {id: 1, bank: {id: "1", name: "Bank 1"}, name: "User 1 *"},
|
|
109
|
+
params: {id: 1, name: "User 1 *"}
|
|
110
|
+
}
|
|
78
111
|
}
|
|
79
|
-
},
|
|
80
|
-
mutations: {
|
|
81
|
-
// each mutation has its own state as well
|
|
82
|
-
updateUser: {loading: false, result: {id: 1, bank: {id: "1", name: "Bank 1"}, name: "User 1 *"}}
|
|
83
112
|
}
|
|
84
|
-
|
|
85
|
-
|
|
113
|
+
```
|
|
114
|
+
</details>
|
|
86
115
|
|
|
87
116
|
### Table of contents
|
|
88
117
|
|
|
@@ -219,44 +248,49 @@ export const UserScreen = () => {
|
|
|
219
248
|
|
|
220
249
|
### Advanced
|
|
221
250
|
|
|
222
|
-
####
|
|
223
|
-
|
|
224
|
-
By default result of a query is stored under its **cache key**, but sometimes it makes sense to take result from other queries or normalized entities.
|
|
251
|
+
#### Advanced cache policy & skip / fetch usage
|
|
225
252
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
For that case `resultSelector` can be used:
|
|
253
|
+
`cache-first` cache policy skips fetching if result is already cached, but sometimes it can't determine that we already have result in some other's query result or in normalized entities cache. In that case we can use `skip` parameter of a query:
|
|
229
254
|
|
|
230
255
|
```typescript
|
|
256
|
+
export const UserScreen = () => {
|
|
257
|
+
const user = useSelectEntityById(userId, 'users')
|
|
231
258
|
|
|
232
|
-
|
|
259
|
+
const [{loading, error}] = useQuery({
|
|
260
|
+
query: 'getUser',
|
|
261
|
+
params: userId,
|
|
262
|
+
skip: !!user // we skip fetching if we already have user cached by some other query, e.g. getUsers
|
|
263
|
+
})
|
|
233
264
|
|
|
234
|
-
... = createCache({
|
|
235
265
|
...
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
266
|
+
}
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
We can additional check that entity is full enough:
|
|
270
|
+
|
|
271
|
+
```typescript
|
|
272
|
+
skip: !!user && isFullUser(user)
|
|
273
|
+
```
|
|
244
274
|
|
|
245
|
-
|
|
275
|
+
Other approach is to set `skip: true` and manually run `fetch` when needed:
|
|
246
276
|
|
|
277
|
+
```typescript
|
|
247
278
|
export const UserScreen = () => {
|
|
248
|
-
|
|
279
|
+
const screenIsVisible = useScreenIsVisible()
|
|
249
280
|
|
|
250
|
-
|
|
251
|
-
// and cached value is returned if user entity was already in the cache
|
|
252
|
-
const [{result, loading, error}] = useQuery({
|
|
281
|
+
const [{result, loading, error}, fetchUser] = useQuery({
|
|
253
282
|
query: 'getUser',
|
|
254
283
|
params: userId,
|
|
284
|
+
skip: true
|
|
255
285
|
})
|
|
256
286
|
|
|
287
|
+
useEffect(() => {
|
|
288
|
+
if (screenIsVisible) {
|
|
289
|
+
fetchUser()
|
|
290
|
+
}
|
|
291
|
+
}, [screenIsVisible])
|
|
257
292
|
...
|
|
258
293
|
}
|
|
259
|
-
|
|
260
294
|
```
|
|
261
295
|
|
|
262
296
|
#### Infinite scroll pagination
|
|
@@ -295,11 +329,14 @@ Here is an example of `getUsers` query configuration with pagination support. Yo
|
|
|
295
329
|
export const GetUsersScreen = () => {
|
|
296
330
|
const {query} = useClient()
|
|
297
331
|
|
|
298
|
-
const [{result: usersResult, loading, error}, refetch] = useQuery({
|
|
332
|
+
const [{result: usersResult, loading, error, params}, refetch] = useQuery({
|
|
299
333
|
query: 'getUsers',
|
|
300
334
|
params: 1 // page
|
|
301
335
|
})
|
|
302
336
|
|
|
337
|
+
const refreshing = loading && params === 1
|
|
338
|
+
const loadingNextPage = loading && !refreshing
|
|
339
|
+
|
|
303
340
|
const onLoadNextPage = () => {
|
|
304
341
|
const lastLoadedPage = usersResult?.page ?? 0
|
|
305
342
|
query({
|
|
@@ -316,9 +353,14 @@ export const GetUsersScreen = () => {
|
|
|
316
353
|
|
|
317
354
|
return (
|
|
318
355
|
<div>
|
|
356
|
+
{refreshing && <div className="spinner" />}
|
|
319
357
|
{usersResult?.items.map(renderUser)}
|
|
320
358
|
<button onClick={refetch}>Refresh</button>
|
|
321
|
-
|
|
359
|
+
{loadingNextPage ? (
|
|
360
|
+
<div className="spinner" />
|
|
361
|
+
) : (
|
|
362
|
+
<button onClick={loadNextPage}>Load next page</button>
|
|
363
|
+
)}
|
|
322
364
|
</div>
|
|
323
365
|
)
|
|
324
366
|
}
|
package/dist/createActions.d.ts
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
import type { EntityChanges, Key, QueryMutationState, Typenames } from './types';
|
|
2
|
-
export type ActionMap<N extends string, T extends Typenames, QR, MR> = ReturnType<typeof createActions<N, T, QR, MR>>;
|
|
3
|
-
export declare const createActions: <N extends string, T extends Typenames, QR, MR>(name: N) => {
|
|
2
|
+
export type ActionMap<N extends string, T extends Typenames, QP, QR, MP, MR> = ReturnType<typeof createActions<N, T, QP, QR, MP, MR>>;
|
|
3
|
+
export declare const createActions: <N extends string, T extends Typenames, QP, QR, MP, MR>(name: N) => {
|
|
4
4
|
/** Updates query state, and optionally merges entity changes in a single action. */
|
|
5
5
|
updateQueryStateAndEntities: {
|
|
6
|
-
<K extends keyof QR>(queryKey: K, queryCacheKey: Key, state?: Partial<QueryMutationState<QR[K]>> | undefined, entityChagnes?: EntityChanges<T> | undefined): {
|
|
6
|
+
<K extends keyof QP & keyof QR>(queryKey: K, queryCacheKey: Key, state?: Partial<QueryMutationState<QP[K], QR[K]>> | undefined, entityChagnes?: EntityChanges<T> | undefined): {
|
|
7
7
|
type: `@rrc/${N}/updateQueryStateAndEntities`;
|
|
8
8
|
queryKey: K;
|
|
9
9
|
queryCacheKey: Key;
|
|
10
|
-
state: Partial<QueryMutationState<QR[K]>> | undefined;
|
|
10
|
+
state: Partial<QueryMutationState<QP[K], QR[K]>> | undefined;
|
|
11
11
|
entityChagnes: EntityChanges<T> | undefined;
|
|
12
12
|
};
|
|
13
13
|
type: `@rrc/${N}/updateQueryStateAndEntities`;
|
|
14
14
|
};
|
|
15
15
|
/** Updates mutation state, and optionally merges entity changes in a single action. */
|
|
16
16
|
updateMutationStateAndEntities: {
|
|
17
|
-
<K_1 extends keyof MR>(mutationKey: K_1, state?: Partial<QueryMutationState<MR[K_1]>> | undefined, entityChagnes?: EntityChanges<T> | undefined): {
|
|
17
|
+
<K_1 extends keyof MP & keyof MR>(mutationKey: K_1, state?: Partial<QueryMutationState<MP[K_1], MR[K_1]>> | undefined, entityChagnes?: EntityChanges<T> | undefined): {
|
|
18
18
|
type: `@rrc/${N}/updateMutationStateAndEntities`;
|
|
19
19
|
mutationKey: K_1;
|
|
20
|
-
state: Partial<QueryMutationState<MR[K_1]>> | undefined;
|
|
20
|
+
state: Partial<QueryMutationState<MP[K_1], MR[K_1]>> | undefined;
|
|
21
21
|
entityChagnes: EntityChanges<T> | undefined;
|
|
22
22
|
};
|
|
23
23
|
type: `@rrc/${N}/updateMutationStateAndEntities`;
|
|
@@ -33,7 +33,7 @@ export declare const createActions: <N extends string, T extends Typenames, QR,
|
|
|
33
33
|
/** Clear states for provided query keys and cache keys.
|
|
34
34
|
* If cache key for query key is not provided, the whole state for query key is cleared. */
|
|
35
35
|
clearQueryState: {
|
|
36
|
-
<K_2 extends keyof QR>(queryKeys: {
|
|
36
|
+
<K_2 extends keyof QP & keyof QR>(queryKeys: {
|
|
37
37
|
key: K_2;
|
|
38
38
|
cacheKey?: Key | undefined;
|
|
39
39
|
}[]): {
|
|
@@ -47,7 +47,7 @@ export declare const createActions: <N extends string, T extends Typenames, QR,
|
|
|
47
47
|
};
|
|
48
48
|
/** Clear states for provided mutation keys. */
|
|
49
49
|
clearMutationState: {
|
|
50
|
-
<K_3 extends keyof MR>(mutationKeys: K_3[]): {
|
|
50
|
+
<K_3 extends keyof MP & keyof MR>(mutationKeys: K_3[]): {
|
|
51
51
|
type: `@rrc/${N}/clearMutationState`;
|
|
52
52
|
mutationKeys: K_3[];
|
|
53
53
|
};
|
package/dist/createCache.d.ts
CHANGED
|
@@ -11,18 +11,18 @@ export declare const createCache: <N extends string, T extends Typenames, QP, QR
|
|
|
11
11
|
/** Reducer of the cache, should be added to redux store. */
|
|
12
12
|
reducer: (state: {
|
|
13
13
|
entities: import("./types").EntitiesMap<T>;
|
|
14
|
-
queries: { [QK in keyof
|
|
15
|
-
mutations: { [MK in keyof
|
|
14
|
+
queries: QP | QR extends infer T_1 ? { [QK in keyof T_1]: import("./types").Dict<QueryMutationState<QP[QK], QR[QK]>>; } : never;
|
|
15
|
+
mutations: MP | MR extends infer T_2 ? { [MK in keyof T_2]: QueryMutationState<MP[MK], MR[MK]>; } : never;
|
|
16
16
|
} | undefined, action: {
|
|
17
17
|
type: `@rrc/${N}/updateQueryStateAndEntities`;
|
|
18
|
-
queryKey: keyof QR;
|
|
18
|
+
queryKey: keyof QP & keyof QR;
|
|
19
19
|
queryCacheKey: Key;
|
|
20
|
-
state: Partial<QueryMutationState<QR[keyof QR]>> | undefined;
|
|
20
|
+
state: Partial<QueryMutationState<QP[keyof QP & keyof QR], QR[keyof QP & keyof QR]>> | undefined;
|
|
21
21
|
entityChagnes: import("./types").EntityChanges<T> | undefined;
|
|
22
22
|
} | {
|
|
23
23
|
type: `@rrc/${N}/updateMutationStateAndEntities`;
|
|
24
|
-
mutationKey: keyof MR;
|
|
25
|
-
state: Partial<QueryMutationState<MR[keyof MR]>> | undefined;
|
|
24
|
+
mutationKey: keyof MP & keyof MR;
|
|
25
|
+
state: Partial<QueryMutationState<MP[keyof MP & keyof MR], MR[keyof MP & keyof MR]>> | undefined;
|
|
26
26
|
entityChagnes: import("./types").EntityChanges<T> | undefined;
|
|
27
27
|
} | {
|
|
28
28
|
type: `@rrc/${N}/mergeEntityChanges`;
|
|
@@ -30,33 +30,33 @@ export declare const createCache: <N extends string, T extends Typenames, QP, QR
|
|
|
30
30
|
} | {
|
|
31
31
|
type: `@rrc/${N}/clearQueryState`;
|
|
32
32
|
queryKeys: {
|
|
33
|
-
key: keyof QR;
|
|
33
|
+
key: keyof QP & keyof QR;
|
|
34
34
|
cacheKey?: Key | undefined;
|
|
35
35
|
}[];
|
|
36
36
|
} | {
|
|
37
37
|
type: `@rrc/${N}/clearMutationState`;
|
|
38
|
-
mutationKeys: (keyof MR)[];
|
|
38
|
+
mutationKeys: (keyof MP & keyof MR)[];
|
|
39
39
|
}) => {
|
|
40
40
|
entities: import("./types").EntitiesMap<T>;
|
|
41
|
-
queries: { [QK in keyof
|
|
42
|
-
mutations: { [MK in keyof
|
|
41
|
+
queries: QP | QR extends infer T_3 ? { [QK in keyof T_3]: import("./types").Dict<QueryMutationState<QP[QK], QR[QK]>>; } : never;
|
|
42
|
+
mutations: MP | MR extends infer T_4 ? { [MK in keyof T_4]: QueryMutationState<MP[MK], MR[MK]>; } : never;
|
|
43
43
|
};
|
|
44
44
|
actions: {
|
|
45
45
|
updateQueryStateAndEntities: {
|
|
46
|
-
<K extends keyof QR>(queryKey: K, queryCacheKey: Key, state?: Partial<QueryMutationState<QR[K]>> | undefined, entityChagnes?: import("./types").EntityChanges<T> | undefined): {
|
|
46
|
+
<K extends keyof QP & keyof QR>(queryKey: K, queryCacheKey: Key, state?: Partial<QueryMutationState<QP[K], QR[K]>> | undefined, entityChagnes?: import("./types").EntityChanges<T> | undefined): {
|
|
47
47
|
type: `@rrc/${N}/updateQueryStateAndEntities`;
|
|
48
48
|
queryKey: K;
|
|
49
49
|
queryCacheKey: Key;
|
|
50
|
-
state: Partial<QueryMutationState<QR[K]>> | undefined;
|
|
50
|
+
state: Partial<QueryMutationState<QP[K], QR[K]>> | undefined;
|
|
51
51
|
entityChagnes: import("./types").EntityChanges<T> | undefined;
|
|
52
52
|
};
|
|
53
53
|
type: `@rrc/${N}/updateQueryStateAndEntities`;
|
|
54
54
|
};
|
|
55
55
|
updateMutationStateAndEntities: {
|
|
56
|
-
<K_1 extends keyof MR>(mutationKey: K_1, state?: Partial<QueryMutationState<MR[K_1]>> | undefined, entityChagnes?: import("./types").EntityChanges<T> | undefined): {
|
|
56
|
+
<K_1 extends keyof MP & keyof MR>(mutationKey: K_1, state?: Partial<QueryMutationState<MP[K_1], MR[K_1]>> | undefined, entityChagnes?: import("./types").EntityChanges<T> | undefined): {
|
|
57
57
|
type: `@rrc/${N}/updateMutationStateAndEntities`;
|
|
58
58
|
mutationKey: K_1;
|
|
59
|
-
state: Partial<QueryMutationState<MR[K_1]>> | undefined;
|
|
59
|
+
state: Partial<QueryMutationState<MP[K_1], MR[K_1]>> | undefined;
|
|
60
60
|
entityChagnes: import("./types").EntityChanges<T> | undefined;
|
|
61
61
|
};
|
|
62
62
|
type: `@rrc/${N}/updateMutationStateAndEntities`;
|
|
@@ -69,7 +69,7 @@ export declare const createCache: <N extends string, T extends Typenames, QP, QR
|
|
|
69
69
|
type: `@rrc/${N}/mergeEntityChanges`;
|
|
70
70
|
};
|
|
71
71
|
clearQueryState: {
|
|
72
|
-
<K_2 extends keyof QR>(queryKeys: {
|
|
72
|
+
<K_2 extends keyof QP & keyof QR>(queryKeys: {
|
|
73
73
|
key: K_2;
|
|
74
74
|
cacheKey?: Key | undefined;
|
|
75
75
|
}[]): {
|
|
@@ -82,7 +82,7 @@ export declare const createCache: <N extends string, T extends Typenames, QP, QR
|
|
|
82
82
|
type: `@rrc/${N}/clearQueryState`;
|
|
83
83
|
};
|
|
84
84
|
clearMutationState: {
|
|
85
|
-
<K_3 extends keyof MR>(mutationKeys: K_3[]): {
|
|
85
|
+
<K_3 extends keyof MP & keyof MR>(mutationKeys: K_3[]): {
|
|
86
86
|
type: `@rrc/${N}/clearMutationState`;
|
|
87
87
|
mutationKeys: K_3[];
|
|
88
88
|
};
|
|
@@ -91,21 +91,25 @@ export declare const createCache: <N extends string, T extends Typenames, QP, QR
|
|
|
91
91
|
};
|
|
92
92
|
selectors: {
|
|
93
93
|
/** Selects query state. */
|
|
94
|
-
selectQueryState: <QK_1 extends keyof
|
|
94
|
+
selectQueryState: <QK_1 extends keyof QP | keyof QR>(state: unknown, query: QK_1, cacheKey: Key) => QueryMutationState<QK_1 extends keyof QP & keyof QR ? QP[QK_1] : never, QK_1 extends keyof QP & keyof QR ? QR[QK_1] : never> | undefined;
|
|
95
95
|
/** Selects query latest result. */
|
|
96
|
-
selectQueryResult: <QK_2 extends keyof
|
|
96
|
+
selectQueryResult: <QK_2 extends keyof QP | keyof QR>(state: unknown, query: QK_2, cacheKey: Key) => (QK_2 extends keyof QP & keyof QR ? QR[QK_2] : never) | undefined;
|
|
97
97
|
/** Selects query loading state. */
|
|
98
|
-
selectQueryLoading: <QK_3 extends keyof
|
|
98
|
+
selectQueryLoading: <QK_3 extends keyof QP | keyof QR>(state: unknown, query: QK_3, cacheKey: Key) => boolean | undefined;
|
|
99
99
|
/** Selects query latest error. */
|
|
100
|
-
selectQueryError: <QK_4 extends keyof
|
|
100
|
+
selectQueryError: <QK_4 extends keyof QP | keyof QR>(state: unknown, query: QK_4, cacheKey: Key) => Error | undefined;
|
|
101
|
+
/** Selects query latest params. */
|
|
102
|
+
selectQueryParams: <QK_5 extends keyof QP | keyof QR>(state: unknown, query: QK_5, cacheKey: Key) => (QK_5 extends keyof QP & keyof QR ? QP[QK_5] : never) | undefined;
|
|
101
103
|
/** Selects mutation state. */
|
|
102
|
-
selectMutationState: <MK_1 extends keyof MP | keyof MR>(state: unknown, mutation: MK_1) => QueryMutationState<MK_1 extends keyof MP & keyof MR ? MR[MK_1] : never>;
|
|
104
|
+
selectMutationState: <MK_1 extends keyof MP | keyof MR>(state: unknown, mutation: MK_1) => QueryMutationState<MK_1 extends keyof MP & keyof MR ? MP[MK_1] : never, MK_1 extends keyof MP & keyof MR ? MR[MK_1] : never>;
|
|
103
105
|
/** Selects mutation latest result. */
|
|
104
106
|
selectMutationResult: <MK_2 extends keyof MP | keyof MR>(state: unknown, mutation: MK_2) => (MK_2 extends keyof MP & keyof MR ? MR[MK_2] : never) | undefined;
|
|
105
107
|
/** Selects mutation loading state. */
|
|
106
108
|
selectMutationLoading: <MK_3 extends keyof MP | keyof MR>(state: unknown, mutation: MK_3) => boolean;
|
|
107
109
|
/** Selects mutation latest error. */
|
|
108
110
|
selectMutationError: <MK_4 extends keyof MP | keyof MR>(state: unknown, mutation: MK_4) => Error | undefined;
|
|
111
|
+
/** Selects mutation latest params. */
|
|
112
|
+
selectMutationParams: <MK_5 extends keyof MP | keyof MR>(state: unknown, mutation: MK_5) => MK_5 extends keyof MP & keyof MR ? MP[MK_5] : never;
|
|
109
113
|
/** Selects entity by id and typename. */
|
|
110
114
|
selectEntityById: <TN extends keyof T>(state: unknown, id: Key | null | undefined, typename: TN) => T[TN] | undefined;
|
|
111
115
|
/** Selects all entities. */
|
|
@@ -116,18 +120,18 @@ export declare const createCache: <N extends string, T extends Typenames, QP, QR
|
|
|
116
120
|
hooks: {
|
|
117
121
|
/** Returns client object with query and mutate functions. */
|
|
118
122
|
useClient: () => {
|
|
119
|
-
query: <
|
|
120
|
-
mutate: <
|
|
121
|
-
mutation:
|
|
122
|
-
params:
|
|
123
|
-
}) => Promise<MutationResult<
|
|
123
|
+
query: <QK_6 extends keyof QP | keyof QR>(options: Omit<QueryOptions<T, QP, QR, QK_6>, "cachePolicy">) => Promise<QueryResult<QK_6 extends keyof QP & keyof QR ? QR[QK_6] : never>>;
|
|
124
|
+
mutate: <MK_6 extends keyof MP | keyof MR>(options: {
|
|
125
|
+
mutation: MK_6;
|
|
126
|
+
params: MK_6 extends keyof MP & keyof MR ? MP[MK_6] : never;
|
|
127
|
+
}) => Promise<MutationResult<MK_6 extends keyof MP & keyof MR ? MR[MK_6] : never>>;
|
|
124
128
|
};
|
|
125
129
|
/** Fetches query when params change and subscribes to query state. */
|
|
126
|
-
useQuery: <
|
|
130
|
+
useQuery: <QK_7 extends keyof QP | keyof QR>(options: import("./types").UseQueryOptions<T, QP, QR, QK_7>) => readonly [QueryMutationState<QK_7 extends keyof QP & keyof QR ? QP[QK_7] : never, QK_7 extends keyof QP & keyof QR ? QR[QK_7] : never>, () => Promise<QueryResult<QK_7 extends infer T_5 ? T_5 extends QK_7 ? T_5 extends keyof QP & keyof QR ? QR[T_5] : never : never : never>>];
|
|
127
131
|
/** Subscribes to provided mutation state and provides mutate function. */
|
|
128
|
-
useMutation: <
|
|
129
|
-
mutation:
|
|
130
|
-
}) => readonly [(params:
|
|
132
|
+
useMutation: <MK_7 extends keyof MP | keyof MR>(options: {
|
|
133
|
+
mutation: MK_7;
|
|
134
|
+
}) => readonly [(params: MK_7 extends keyof MP & keyof MR ? MP[MK_7] : never) => Promise<MutationResult<MK_7 extends infer T_6 ? T_6 extends MK_7 ? T_6 extends keyof MP & keyof MR ? MR[T_6] : never : never : never>>, QueryMutationState<MK_7 extends keyof MP & keyof MR ? MP[MK_7] : never, MK_7 extends keyof MP & keyof MR ? MP[MK_7] : never>, () => boolean];
|
|
131
135
|
/** useSelector + selectEntityById. */
|
|
132
136
|
useSelectEntityById: <TN_2 extends keyof T>(id: Key | null | undefined, typename: TN_2) => T[TN_2] | undefined;
|
|
133
137
|
};
|
package/dist/createCache.js
CHANGED
|
@@ -65,6 +65,11 @@ const createCache = (partialCache) => {
|
|
|
65
65
|
var _a;
|
|
66
66
|
return (_a = selectQueryState(state, query, cacheKey)) === null || _a === void 0 ? void 0 : _a.error;
|
|
67
67
|
},
|
|
68
|
+
/** Selects query latest params. */
|
|
69
|
+
selectQueryParams: (state, query, cacheKey) => {
|
|
70
|
+
var _a;
|
|
71
|
+
return (_a = selectQueryState(state, query, cacheKey)) === null || _a === void 0 ? void 0 : _a.params;
|
|
72
|
+
},
|
|
68
73
|
/** Selects mutation state. */
|
|
69
74
|
selectMutationState,
|
|
70
75
|
/** Selects mutation latest result. */
|
|
@@ -79,6 +84,10 @@ const createCache = (partialCache) => {
|
|
|
79
84
|
selectMutationError: (state, mutation) => {
|
|
80
85
|
return selectMutationState(state, mutation).error;
|
|
81
86
|
},
|
|
87
|
+
/** Selects mutation latest params. */
|
|
88
|
+
selectMutationParams: (state, mutation) => {
|
|
89
|
+
return selectMutationState(state, mutation).params;
|
|
90
|
+
},
|
|
82
91
|
/** Selects entity by id and typename. */
|
|
83
92
|
selectEntityById,
|
|
84
93
|
/** Selects all entities. */
|
package/dist/index.js
CHANGED
|
@@ -23,8 +23,8 @@ Object.defineProperty(exports, "defaultGetCacheKey", { enumerable: true, get: fu
|
|
|
23
23
|
Object.defineProperty(exports, "defaultQueryMutationState", { enumerable: true, get: function () { return utilsAndConstants_1.DEFAULT_QUERY_MUTATION_STATE; } });
|
|
24
24
|
// Backlog
|
|
25
25
|
// ! high
|
|
26
|
-
//
|
|
27
|
-
//
|
|
26
|
+
// useQuery refresh with params use as client.query?
|
|
27
|
+
// update readme with how to use mergeResults for invalidating / updating caches?
|
|
28
28
|
// optimistic response
|
|
29
29
|
// make query key / cache key difference more clear in the docs, and/or rename queryKey -> query
|
|
30
30
|
// ! medium
|
|
@@ -32,14 +32,12 @@ Object.defineProperty(exports, "defaultQueryMutationState", { enumerable: true,
|
|
|
32
32
|
// type extractors from cache
|
|
33
33
|
// custom useStore
|
|
34
34
|
// return back deserialize selector?
|
|
35
|
-
// resultSelector - return also boolean that result is full enough or make cache policy as a function
|
|
36
35
|
// selector for entities by typename
|
|
37
36
|
// callback option on error / success?
|
|
38
37
|
// refetch queries on mutation success
|
|
39
38
|
// remove query/mutation state when it finished without errors
|
|
40
39
|
// deep equal entities while merging state
|
|
41
40
|
// make error type generic
|
|
42
|
-
// don't cache result if resultSelector set? throw error if mergeResult set with resultSelector?
|
|
43
41
|
// ! low
|
|
44
42
|
// access to currently loading queries and mutations?
|
|
45
43
|
// add params to the state?
|
package/dist/mutate.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { Store } from 'redux';
|
|
2
2
|
import type { ActionMap } from './createActions';
|
|
3
3
|
import type { Cache, Key, MutationResult, Typenames } from './types';
|
|
4
|
-
export declare const mutate: <N extends string, T extends Typenames, QP, QR, MP, MR, MK extends keyof MP | keyof MR>(logTag: string, store: Store, cache: Cache<N, T, QP, QR, MP, MR>, { updateMutationStateAndEntities }: Pick<ActionMap<N, T,
|
|
4
|
+
export declare const mutate: <N extends string, T extends Typenames, QP, QR, MP, MR, MK extends keyof MP | keyof MR>(logTag: string, store: Store, cache: Cache<N, T, QP, QR, MP, MR>, { updateMutationStateAndEntities, }: Pick<ActionMap<N, T, unknown, unknown, MP, MR>, "updateMutationStateAndEntities">, mutationKey: MK, params: MK extends keyof MP & keyof MR ? MP[MK] : never, abortControllers: WeakMap<Store, Record<Key, AbortController>>) => Promise<MutationResult<MK extends keyof MP & keyof MR ? MR[MK] : never>>;
|
package/dist/mutate.js
CHANGED
|
@@ -11,7 +11,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.mutate = void 0;
|
|
13
13
|
const utilsAndConstants_1 = require("./utilsAndConstants");
|
|
14
|
-
const mutate = (logTag, store, cache, { updateMutationStateAndEntities }, mutationKey, params, abortControllers) => __awaiter(void 0, void 0, void 0, function* () {
|
|
14
|
+
const mutate = (logTag, store, cache, { updateMutationStateAndEntities, }, mutationKey, params, abortControllers) => __awaiter(void 0, void 0, void 0, function* () {
|
|
15
15
|
let abortControllersOfStore = abortControllers.get(store);
|
|
16
16
|
if (abortControllersOfStore === undefined) {
|
|
17
17
|
abortControllersOfStore = {};
|
|
@@ -31,6 +31,7 @@ const mutate = (logTag, store, cache, { updateMutationStateAndEntities }, mutati
|
|
|
31
31
|
else {
|
|
32
32
|
store.dispatch(updateMutationStateAndEntities(mutationKey, {
|
|
33
33
|
loading: true,
|
|
34
|
+
params,
|
|
34
35
|
result: undefined,
|
|
35
36
|
}));
|
|
36
37
|
}
|
package/dist/query.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { Store } from 'redux';
|
|
2
2
|
import type { ActionMap } from './createActions';
|
|
3
3
|
import type { Cache, Key, QueryResult, Typenames } from './types';
|
|
4
|
-
export declare const query: <N extends string, T extends Typenames, QP, QR, MP, MR, QK extends keyof QP | keyof QR>(logTag: string, store: Store, cache: Cache<N, T, QP, QR, MP, MR>, { updateQueryStateAndEntities }: Pick<ActionMap<N, T, QR,
|
|
4
|
+
export declare const query: <N extends string, T extends Typenames, QP, QR, MP, MR, QK extends keyof QP | keyof QR>(logTag: string, store: Store, cache: Cache<N, T, QP, QR, MP, MR>, { updateQueryStateAndEntities, }: Pick<ActionMap<N, T, QP, QR, unknown, unknown>, "updateQueryStateAndEntities">, queryKey: QK, cacheKey: Key, params: QK extends keyof QP & keyof QR ? QP[QK] : never) => Promise<QueryResult<QK extends keyof QP & keyof QR ? QR[QK] : never>>;
|
package/dist/query.js
CHANGED
|
@@ -11,11 +11,10 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.query = void 0;
|
|
13
13
|
const utilsAndConstants_1 = require("./utilsAndConstants");
|
|
14
|
-
const query = (logTag, store, cache, { updateQueryStateAndEntities }, queryKey, cacheKey, params) => __awaiter(void 0, void 0, void 0, function* () {
|
|
14
|
+
const query = (logTag, store, cache, { updateQueryStateAndEntities, }, queryKey, cacheKey, params) => __awaiter(void 0, void 0, void 0, function* () {
|
|
15
15
|
var _a;
|
|
16
16
|
const logsEnabled = cache.options.logsEnabled;
|
|
17
17
|
const cacheStateSelector = cache.cacheStateSelector;
|
|
18
|
-
const cacheResultSelector = cache.queries[queryKey].resultSelector;
|
|
19
18
|
const mergeResults = cache.queries[queryKey].mergeResults;
|
|
20
19
|
const queryStateOnStart = cacheStateSelector(store.getState()).queries[queryKey][cacheKey];
|
|
21
20
|
if (queryStateOnStart === null || queryStateOnStart === void 0 ? void 0 : queryStateOnStart.loading) {
|
|
@@ -29,6 +28,7 @@ const query = (logTag, store, cache, { updateQueryStateAndEntities }, queryKey,
|
|
|
29
28
|
}
|
|
30
29
|
store.dispatch(updateQueryStateAndEntities(queryKey, cacheKey, {
|
|
31
30
|
loading: true,
|
|
31
|
+
params,
|
|
32
32
|
}));
|
|
33
33
|
logsEnabled && (0, utilsAndConstants_1.log)(`${logTag} started`, { queryStateOnStart, params, cacheKey });
|
|
34
34
|
let response;
|
|
@@ -48,22 +48,16 @@ const query = (logTag, store, cache, { updateQueryStateAndEntities }, queryKey,
|
|
|
48
48
|
const newState = {
|
|
49
49
|
error: undefined,
|
|
50
50
|
loading: false,
|
|
51
|
-
result:
|
|
52
|
-
?
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
(_a = cacheStateSelector(store.getState()).queries[queryKey][cacheKey]) === null || _a === void 0 ? void 0 : _a.result, response, params, store)
|
|
57
|
-
: response.result,
|
|
51
|
+
result: mergeResults
|
|
52
|
+
? mergeResults(
|
|
53
|
+
// @ts-expect-error fix later
|
|
54
|
+
(_a = cacheStateSelector(store.getState()).queries[queryKey][cacheKey]) === null || _a === void 0 ? void 0 : _a.result, response, params, store)
|
|
55
|
+
: response.result,
|
|
58
56
|
};
|
|
59
57
|
store.dispatch(updateQueryStateAndEntities(queryKey, cacheKey, newState, response));
|
|
60
58
|
return {
|
|
61
59
|
// @ts-expect-error fix types
|
|
62
|
-
result:
|
|
63
|
-
? cacheResultSelector(cacheStateSelector(store.getState()),
|
|
64
|
-
// @ts-expect-error fix types
|
|
65
|
-
params)
|
|
66
|
-
: newState === null || newState === void 0 ? void 0 : newState.result,
|
|
60
|
+
result: newState === null || newState === void 0 ? void 0 : newState.result,
|
|
67
61
|
};
|
|
68
62
|
});
|
|
69
63
|
exports.query = query;
|
package/dist/reducer.d.ts
CHANGED
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import type { ActionMap } from './createActions';
|
|
2
2
|
import type { CacheOptions, Dict, EntitiesMap, QueryMutationState, Typenames } from './types';
|
|
3
|
-
export type ReduxCacheState<T extends Typenames, QR, MR> = ReturnType<ReturnType<typeof createCacheReducer<string, T, QR, MR>>>;
|
|
4
|
-
export declare const createCacheReducer: <N extends string, T extends Typenames, QR, MR>(actions: ActionMap<N, T, QR, MR>, typenames: T, queryKeys: (keyof QR)[], cacheOptions: CacheOptions) => (state: {
|
|
3
|
+
export type ReduxCacheState<T extends Typenames, QP, QR, MP, MR> = ReturnType<ReturnType<typeof createCacheReducer<string, T, QP, QR, MP, MR>>>;
|
|
4
|
+
export declare const createCacheReducer: <N extends string, T extends Typenames, QP, QR, MP, MR>(actions: ActionMap<N, T, QP, QR, MP, MR>, typenames: T, queryKeys: (keyof QP & keyof QR)[], cacheOptions: CacheOptions) => (state: {
|
|
5
5
|
entities: EntitiesMap<T>;
|
|
6
|
-
queries: { [QK in keyof
|
|
7
|
-
mutations: { [MK in keyof
|
|
6
|
+
queries: QP | QR extends infer T_1 ? { [QK in keyof T_1]: Dict<QueryMutationState<QP[QK], QR[QK]>>; } : never;
|
|
7
|
+
mutations: MP | MR extends infer T_2 ? { [MK in keyof T_2]: QueryMutationState<MP[MK], MR[MK]>; } : never;
|
|
8
8
|
} | undefined, action: {
|
|
9
9
|
type: `@rrc/${N}/updateQueryStateAndEntities`;
|
|
10
|
-
queryKey: keyof QR;
|
|
10
|
+
queryKey: keyof QP & keyof QR;
|
|
11
11
|
queryCacheKey: import("./types").Key;
|
|
12
|
-
state: Partial<QueryMutationState<QR[keyof QR]>> | undefined;
|
|
12
|
+
state: Partial<QueryMutationState<QP[keyof QP & keyof QR], QR[keyof QP & keyof QR]>> | undefined;
|
|
13
13
|
entityChagnes: import("./types").EntityChanges<T> | undefined;
|
|
14
14
|
} | {
|
|
15
15
|
type: `@rrc/${N}/updateMutationStateAndEntities`;
|
|
16
|
-
mutationKey: keyof MR;
|
|
17
|
-
state: Partial<QueryMutationState<MR[keyof MR]>> | undefined;
|
|
16
|
+
mutationKey: keyof MP & keyof MR;
|
|
17
|
+
state: Partial<QueryMutationState<MP[keyof MP & keyof MR], MR[keyof MP & keyof MR]>> | undefined;
|
|
18
18
|
entityChagnes: import("./types").EntityChanges<T> | undefined;
|
|
19
19
|
} | {
|
|
20
20
|
type: `@rrc/${N}/mergeEntityChanges`;
|
|
@@ -22,14 +22,14 @@ export declare const createCacheReducer: <N extends string, T extends Typenames,
|
|
|
22
22
|
} | {
|
|
23
23
|
type: `@rrc/${N}/clearQueryState`;
|
|
24
24
|
queryKeys: {
|
|
25
|
-
key: keyof QR;
|
|
25
|
+
key: keyof QP & keyof QR;
|
|
26
26
|
cacheKey?: import("./types").Key | undefined;
|
|
27
27
|
}[];
|
|
28
28
|
} | {
|
|
29
29
|
type: `@rrc/${N}/clearMutationState`;
|
|
30
|
-
mutationKeys: (keyof MR)[];
|
|
30
|
+
mutationKeys: (keyof MP & keyof MR)[];
|
|
31
31
|
}) => {
|
|
32
32
|
entities: EntitiesMap<T>;
|
|
33
|
-
queries: { [QK in keyof
|
|
34
|
-
mutations: { [MK in keyof
|
|
33
|
+
queries: QP | QR extends infer T_1 ? { [QK in keyof T_1]: Dict<QueryMutationState<QP[QK], QR[QK]>>; } : never;
|
|
34
|
+
mutations: MP | MR extends infer T_2 ? { [MK in keyof T_2]: QueryMutationState<MP[MK], MR[MK]>; } : never;
|
|
35
35
|
};
|
package/dist/types.d.ts
CHANGED
|
@@ -21,8 +21,10 @@ export type Typenames = Record<string, object>;
|
|
|
21
21
|
export type Cache<N extends string, T extends Typenames, QP, QR, MP, MR> = {
|
|
22
22
|
/** Used as prefix for actions and in default cacheStateSelector for selecting cache state from redux state. */
|
|
23
23
|
name: N;
|
|
24
|
-
/**
|
|
25
|
-
*
|
|
24
|
+
/**
|
|
25
|
+
* Mapping of all typenames to their entity types, which is needed for proper normalization. Can be empty If normalization not needed.
|
|
26
|
+
* @key Typename.
|
|
27
|
+
* @value Object with proper type of the typename. Empty objects with type casting can be used.
|
|
26
28
|
* @example
|
|
27
29
|
* typenames: {
|
|
28
30
|
users: {} as User, // here `users` entities will have type `User`
|
|
@@ -30,14 +32,14 @@ export type Cache<N extends string, T extends Typenames, QP, QR, MP, MR> = {
|
|
|
30
32
|
} */
|
|
31
33
|
typenames: T;
|
|
32
34
|
queries: {
|
|
33
|
-
[QK in keyof (QP & QR)]: QK extends keyof (QP | QR) ? QueryInfo<T, QP[QK], QR[QK]
|
|
35
|
+
[QK in keyof (QP & QR)]: QK extends keyof (QP | QR) ? QueryInfo<T, QP[QK], QR[QK]> : never;
|
|
34
36
|
};
|
|
35
37
|
mutations: {
|
|
36
38
|
[MK in keyof (MP & MR)]: MK extends keyof (MP | MR) ? MutationInfo<T, MP[MK], MR[MK]> : never;
|
|
37
39
|
};
|
|
38
40
|
options: CacheOptions;
|
|
39
41
|
/** Should return cache state from redux root state. Default implementation returns `state[name]`. */
|
|
40
|
-
cacheStateSelector: (state: any) => ReduxCacheState<T, QR, MR>;
|
|
42
|
+
cacheStateSelector: (state: any) => ReduxCacheState<T, QP, QR, MP, MR>;
|
|
41
43
|
};
|
|
42
44
|
export type CacheOptions = {
|
|
43
45
|
/**
|
|
@@ -61,19 +63,13 @@ export type EntityIds<T extends Typenames> = {
|
|
|
61
63
|
[K in keyof T]?: Key[];
|
|
62
64
|
};
|
|
63
65
|
export type Query<T extends Typenames, P, R> = (params: P) => Promise<QueryResponse<T, R>>;
|
|
64
|
-
export type QueryInfo<T extends Typenames, P, R
|
|
66
|
+
export type QueryInfo<T extends Typenames, P, R> = {
|
|
65
67
|
query: Query<T, P, R>;
|
|
66
68
|
/**
|
|
67
69
|
* Cache policy.
|
|
68
70
|
* @default cache-first
|
|
69
71
|
*/
|
|
70
72
|
cachePolicy?: QueryCachePolicy;
|
|
71
|
-
/**
|
|
72
|
-
* Selector for query result from redux state.
|
|
73
|
-
* Can prevent hook from doing unnecessary fetches.
|
|
74
|
-
* Needed when query result may already be in the cache, e.g. for single entity query by id.
|
|
75
|
-
* */
|
|
76
|
-
resultSelector?: (state: S, params: P) => R | undefined;
|
|
77
73
|
/** Merges results before saving to the store. Default implementation is using the latest result. */
|
|
78
74
|
mergeResults?: (oldResult: R | undefined, response: QueryResponse<T, R>, params: P | undefined, store: Store) => R;
|
|
79
75
|
/**
|
|
@@ -83,11 +79,11 @@ export type QueryInfo<T extends Typenames, P, R, S> = {
|
|
|
83
79
|
* */
|
|
84
80
|
getCacheKey?: (params?: P) => Key;
|
|
85
81
|
};
|
|
86
|
-
export type UseQueryOptions<T extends Typenames, QP, QR,
|
|
82
|
+
export type UseQueryOptions<T extends Typenames, QP, QR, QK extends keyof (QP & QR)> = {
|
|
87
83
|
query: QK;
|
|
88
84
|
params: QK extends keyof (QP | QR) ? QP[QK] : never;
|
|
89
85
|
skip?: boolean;
|
|
90
|
-
} & Pick<
|
|
86
|
+
} & Pick<QueryInfo<T, unknown, unknown>, 'cachePolicy'>;
|
|
91
87
|
/**
|
|
92
88
|
* @param cache-first for each params key fetch is not called if cache exists.
|
|
93
89
|
* @param cache-and-fetch for each params key result is taken from cache and fetch is called.
|
|
@@ -102,7 +98,7 @@ export type QueryResult<R> = {
|
|
|
102
98
|
cancelled?: true;
|
|
103
99
|
result?: R;
|
|
104
100
|
};
|
|
105
|
-
export type QueryOptions<T extends Typenames, QP, QR,
|
|
101
|
+
export type QueryOptions<T extends Typenames, QP, QR, QK extends keyof (QP & QR)> = Omit<UseQueryOptions<T, QP, QR, QK>, 'skip'>;
|
|
106
102
|
export type Mutation<T extends Typenames, P, R> = (params: P,
|
|
107
103
|
/** Signal is aborted for current mutation when the same mutation was called once again. */
|
|
108
104
|
abortSignal: AbortSignal) => Promise<MutationResponse<T, R>>;
|
|
@@ -118,11 +114,13 @@ export type MutationResult<R> = {
|
|
|
118
114
|
aborted?: true;
|
|
119
115
|
result?: R;
|
|
120
116
|
};
|
|
121
|
-
export type QueryMutationState<R> = {
|
|
117
|
+
export type QueryMutationState<P, R> = {
|
|
122
118
|
/** `true` when query or mutation is currently in progress. */
|
|
123
119
|
loading: boolean;
|
|
124
120
|
/** Result of the latest successfull response. */
|
|
125
121
|
result?: R;
|
|
126
122
|
/** Error of the latest response. */
|
|
127
123
|
error?: Error;
|
|
124
|
+
/** Parameters of the latest request. */
|
|
125
|
+
params: P;
|
|
128
126
|
};
|
package/dist/useMutation.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Store } from 'redux';
|
|
2
2
|
import { ActionMap } from './createActions';
|
|
3
3
|
import { Cache, Key, QueryMutationState, Typenames } from './types';
|
|
4
|
-
export declare const useMutation: <N extends string, T extends Typenames, MP, MR, MK extends keyof MP | keyof MR>(cache: Cache<N, T, unknown, unknown, MP, MR>, actions: Pick<ActionMap<N, T, unknown, MR>, "updateMutationStateAndEntities">, options: {
|
|
4
|
+
export declare const useMutation: <N extends string, T extends Typenames, MP, MR, MK extends keyof MP | keyof MR>(cache: Cache<N, T, unknown, unknown, MP, MR>, actions: Pick<ActionMap<N, T, unknown, unknown, MP, MR>, "updateMutationStateAndEntities">, options: {
|
|
5
5
|
mutation: MK;
|
|
6
|
-
}, abortControllers: WeakMap<Store, Record<Key, AbortController>>) => readonly [(params: MK extends keyof MP & keyof MR ? MP[MK] : never) => Promise<import("./types").MutationResult<MK extends infer T_1 ? T_1 extends MK ? T_1 extends keyof MP & keyof MR ? MR[T_1] : never : never : never>>, QueryMutationState<MK extends keyof MP & keyof MR ? MP[MK] : never>, () => boolean];
|
|
6
|
+
}, abortControllers: WeakMap<Store, Record<Key, AbortController>>) => readonly [(params: MK extends keyof MP & keyof MR ? MP[MK] : never) => Promise<import("./types").MutationResult<MK extends infer T_1 ? T_1 extends MK ? T_1 extends keyof MP & keyof MR ? MR[T_1] : never : never : never>>, QueryMutationState<MK extends keyof MP & keyof MR ? MP[MK] : never, MK extends keyof MP & keyof MR ? MP[MK] : never>, () => boolean];
|
package/dist/useQuery.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import { ActionMap } from './createActions';
|
|
2
2
|
import { Cache, QueryMutationState, Typenames, UseQueryOptions } from './types';
|
|
3
|
-
export declare const useQuery: <N extends string, T extends Typenames, QP, QR, MP, MR, QK extends keyof QP | keyof QR>(cache: Cache<N, T, QP, QR, MP, MR>, actions: Pick<ActionMap<N, T, QR, MR>, "updateQueryStateAndEntities">, options: UseQueryOptions<T, QP, QR,
|
|
3
|
+
export declare const useQuery: <N extends string, T extends Typenames, QP, QR, MP, MR, QK extends keyof QP | keyof QR>(cache: Cache<N, T, QP, QR, MP, MR>, actions: Pick<ActionMap<N, T, QP, QR, MP, MR>, "updateQueryStateAndEntities">, options: UseQueryOptions<T, QP, QR, QK>) => readonly [QueryMutationState<QK extends keyof QP & keyof QR ? QP[QK] : never, QK extends keyof QP & keyof QR ? QR[QK] : never>, () => Promise<import("./types").QueryResult<QK extends infer T_1 ? T_1 extends QK ? T_1 extends keyof QP & keyof QR ? QR[T_1] : never : never : never>>];
|
package/dist/useQuery.js
CHANGED
|
@@ -19,32 +19,18 @@ const useQuery = (cache, actions, options) => {
|
|
|
19
19
|
const { query: queryKey, skip, params, cachePolicy = (_a = cache.queries[queryKey].cachePolicy) !== null && _a !== void 0 ? _a : 'cache-first', } = options;
|
|
20
20
|
const logsEnabled = cache.options.logsEnabled;
|
|
21
21
|
const getCacheKey = (_b = cache.queries[queryKey].getCacheKey) !== null && _b !== void 0 ? _b : (utilsAndConstants_1.defaultGetCacheKey);
|
|
22
|
-
const cacheResultSelector = cache.queries[queryKey].resultSelector;
|
|
23
22
|
const cacheStateSelector = cache.cacheStateSelector;
|
|
24
23
|
const store = (0, react_redux_1.useStore)();
|
|
25
24
|
// @ts-expect-error fix types later
|
|
26
25
|
const cacheKey = getCacheKey(params);
|
|
27
|
-
const resultSelector = (0, react_1.useMemo)(() => {
|
|
28
|
-
return (cacheResultSelector &&
|
|
29
|
-
((state) => cacheResultSelector(cacheStateSelector(state),
|
|
30
|
-
// @ts-expect-error fix types later
|
|
31
|
-
params)));
|
|
32
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
33
|
-
}, [cacheKey]);
|
|
34
|
-
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
35
|
-
const resultFromSelector = (resultSelector && (0, react_redux_1.useSelector)(resultSelector));
|
|
36
|
-
const hasResultFromSelector = resultFromSelector !== undefined;
|
|
37
26
|
const fetch = (0, react_1.useCallback)(() => __awaiter(void 0, void 0, void 0, function* () {
|
|
38
27
|
return yield (0, query_1.query)('useQuery.fetch', store, cache, actions, queryKey, cacheKey, params);
|
|
39
28
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
40
29
|
}), [store, queryKey, cacheKey]);
|
|
41
|
-
const
|
|
30
|
+
const queryState = (_c = (0, react_redux_1.useSelector)((state) => {
|
|
42
31
|
const queryState = cacheStateSelector(state).queries[queryKey][cacheKey];
|
|
43
32
|
return queryState; // TODO proper type
|
|
44
33
|
})) !== null && _c !== void 0 ? _c : utilsAndConstants_1.DEFAULT_QUERY_MUTATION_STATE;
|
|
45
|
-
const queryState = hasResultFromSelector
|
|
46
|
-
? (Object.assign(Object.assign({}, queryStateFromSelector), { result: resultFromSelector }))
|
|
47
|
-
: queryStateFromSelector;
|
|
48
34
|
(0, react_1.useEffect)(() => {
|
|
49
35
|
if (skip) {
|
|
50
36
|
logsEnabled && (0, utilsAndConstants_1.log)('useQuery.useEffect skip fetch', { skip, cacheKey });
|
|
@@ -65,7 +51,6 @@ const useQuery = (cache, actions, options) => {
|
|
|
65
51
|
(0, utilsAndConstants_1.log)('useQuery', {
|
|
66
52
|
cacheKey,
|
|
67
53
|
options,
|
|
68
|
-
resultFromSelector,
|
|
69
54
|
queryState,
|
|
70
55
|
});
|
|
71
56
|
return [
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "react-redux-cache",
|
|
3
3
|
"author": "Alexander Danilov",
|
|
4
4
|
"license": "MIT",
|
|
5
|
-
"version": "0.
|
|
5
|
+
"version": "0.5.0",
|
|
6
6
|
"description": "Powerful data fetching and caching library that supports normalization, built on top of redux",
|
|
7
7
|
"main": "dist/index.js",
|
|
8
8
|
"types": "dist/index.d.ts",
|