react-redux-cache 0.13.0 → 0.16.0-rc.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 +27 -28
- package/dist/createActions.d.ts +8 -0
- package/dist/createActions.js +7 -0
- package/dist/createCache.d.ts +44 -30
- package/dist/createCache.js +29 -22
- package/dist/createCacheReducer.d.ts +2 -11
- package/dist/createCacheReducer.js +13 -11
- package/dist/index.js +1 -3
- package/dist/mutate.d.ts +1 -2
- package/dist/query.d.ts +1 -2
- package/dist/types.d.ts +30 -11
- package/dist/useMutation.d.ts +1 -2
- package/dist/useMutation.js +2 -3
- package/dist/useQuery.js +7 -7
- package/package.json +5 -3
package/README.md
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
# react-redux-cache (RRC)
|
|
11
11
|
|
|
12
|
-
**Powerful** yet **lightweight** data fetching and caching library that supports **normalization** unlike `
|
|
12
|
+
**Powerful**, **performant** yet **lightweight** data fetching and caching library that supports **normalization** unlike `React Query` and `RTK-Query`, while having similar but not over-engineered, simple interface. Another advantage over `RTK-Query` is that it **doesn't use Immer** ([perf issue](https://github.com/reduxjs/redux-toolkit/issues/4793)). Built on top of `Redux`, covered with tests, fully typed and written on Typescript.
|
|
13
13
|
|
|
14
14
|
**Normalization** is the best way to keep the state of the app **consistent** between different views, reduces the number of fetches and allows to show cached data when navigating, which greatly improves **user experience**.
|
|
15
15
|
|
|
@@ -127,11 +127,21 @@ Examples of states, generated by cache reducer from `/example` project:
|
|
|
127
127
|
- [How race conditions are handled?](https://github.com/gentlee/react-redux-cache#how-race-conditions-are-handled)
|
|
128
128
|
|
|
129
129
|
### Installation
|
|
130
|
-
`react
|
|
130
|
+
`react` is a peer dependency.
|
|
131
|
+
|
|
132
|
+
`react-redux` and `fast-deep-equal` are optional peer dependencies:
|
|
133
|
+
- `react-redux` required when `storeHooks` is not provided when creating cache.
|
|
134
|
+
- `fast-deep-equal` required if `deepComparisonEnabled` cache option is enabled (default is true).
|
|
131
135
|
|
|
132
|
-
`fast-deep-equal` is an optional peer dependency if `deepComparisonEnabled` cache option is enabled (default is true).
|
|
133
136
|
```sh
|
|
134
|
-
|
|
137
|
+
# required
|
|
138
|
+
npm add react-redux-cache react
|
|
139
|
+
|
|
140
|
+
# without react-redux
|
|
141
|
+
npm add react-redux-cache react fast-deep-equal
|
|
142
|
+
|
|
143
|
+
# all required and optional peers
|
|
144
|
+
npm add react-redux-cache react react-redux fast-deep-equal
|
|
135
145
|
```
|
|
136
146
|
### Initialization
|
|
137
147
|
The only function that needs to be imported is either `withTypenames`, which is needed for normalization, or directly `createCache` if it is not needed. `createCache` creates fully typed reducer, hooks, actions, selectors and utils to be used in the app. You can create as many caches as needed, but keep in mind that normalization is not shared between them.
|
|
@@ -145,15 +155,14 @@ export type CacheTypenames = {
|
|
|
145
155
|
banks: Bank,
|
|
146
156
|
}
|
|
147
157
|
|
|
158
|
+
// `withTypenames` is only needed to provide proper Typenames for normalization - limitation of Typescript.
|
|
159
|
+
// `createCache` can be imported directly without `withTypenames`.
|
|
148
160
|
export const {
|
|
149
161
|
cache,
|
|
150
162
|
reducer,
|
|
151
163
|
hooks: {useClient, useMutation, useQuery},
|
|
152
|
-
// `withTypenames` is only needed to provide proper Typenames for normalization - limitation of Typescript.
|
|
153
|
-
// `createCache` can be imported directly without `withTypenames`.
|
|
154
164
|
} = withTypenames<CacheTypenames>().createCache({
|
|
155
|
-
// Used as prefix for actions and in default cacheStateSelector for selecting cache state from redux state.
|
|
156
|
-
name: 'cache',
|
|
165
|
+
name: 'cache', // Used as prefix for actions and in default cacheStateSelector for selecting cache state from redux state.
|
|
157
166
|
queries: {
|
|
158
167
|
getUsers: { query: getUsers },
|
|
159
168
|
getUser: {
|
|
@@ -176,15 +185,11 @@ For normalization two things are required:
|
|
|
176
185
|
- Return an object from queries and mutations that contains the following fields (besides `result`):
|
|
177
186
|
|
|
178
187
|
```typescript
|
|
179
|
-
type EntityChanges<T extends Typenames> = {
|
|
180
|
-
/** Entities that will be merged with existing. */
|
|
181
|
-
|
|
182
|
-
/**
|
|
183
|
-
|
|
184
|
-
/** Ids of entities that will be removed. */
|
|
185
|
-
remove?: EntityIds<T>
|
|
186
|
-
/** Alias for `merge` to support normalizr. */
|
|
187
|
-
entities?: EntityChanges<T>['merge']
|
|
188
|
+
type EntityChanges<T extends Typenames> = {
|
|
189
|
+
merge?: PartialEntitiesMap<T> /** Entities that will be merged with existing. */
|
|
190
|
+
replace?: Partial<EntitiesMap<T>> /** Entities that will replace existing. */
|
|
191
|
+
remove?: EntityIds<T> /** Ids of entities that will be removed. */
|
|
192
|
+
entities?: EntityChanges<T>['merge'] /** Alias for `merge` to support normalizr. */
|
|
188
193
|
}
|
|
189
194
|
```
|
|
190
195
|
|
|
@@ -200,21 +205,18 @@ const store = configureStore({
|
|
|
200
205
|
})
|
|
201
206
|
```
|
|
202
207
|
#### api.ts
|
|
203
|
-
Query result should be of type `QueryResponse`, mutation result should be of type `MutationResponse`.
|
|
204
208
|
For normalization `normalizr` package is used in this example, but any other tool can be used if query result is of proper type.
|
|
205
209
|
Perfect implementation is when the backend already returns normalized data.
|
|
206
210
|
```typescript
|
|
207
211
|
|
|
208
212
|
// Example of query with normalization (recommended)
|
|
209
213
|
|
|
214
|
+
// 1. Result can be get by any way - fetch, axios etc, even with database connection. There is no limitation here.
|
|
215
|
+
// 2. `satisfies` keyword is used here for proper typing of params and returned value.
|
|
210
216
|
export const getUser = (async (id) => {
|
|
211
|
-
// Result can be get by any way - fetch, axios etc, even with database connection.
|
|
212
|
-
// There is no limitation here.
|
|
213
217
|
const response = await ...
|
|
214
218
|
|
|
215
|
-
// In this example normalizr package is used, but it is not necessary.
|
|
216
219
|
return normalize(response, getUserSchema)
|
|
217
|
-
// satisfies keyword is used here for proper typing of params and returned value.
|
|
218
220
|
}) satisfies NormalizedQuery<CacheTypenames, number>
|
|
219
221
|
|
|
220
222
|
// Example of query without normalization (not recommended), with selecting access token from the store
|
|
@@ -278,10 +280,8 @@ export const updateBank = (async (bank) => {
|
|
|
278
280
|
const {httpError, response} = ...
|
|
279
281
|
return {
|
|
280
282
|
result: {
|
|
281
|
-
// Error is a part of the result, containing e.g. map of not valid fields and threir error messages
|
|
282
|
-
|
|
283
|
-
// Bank still can be returned from the backend with error e.g. when only some of fields were udpated
|
|
284
|
-
bank: response?.bank
|
|
283
|
+
httpError, // Error is a part of the result, containing e.g. map of not valid fields and threir error messages
|
|
284
|
+
bank: response?.bank // Bank still can be returned from the backend with error e.g. when only some of fields were udpated
|
|
285
285
|
}
|
|
286
286
|
}
|
|
287
287
|
}) satisfies Mutation<Partial<Bank>>
|
|
@@ -432,7 +432,6 @@ export const GetUsersScreen = () => {
|
|
|
432
432
|
const onLoadNextPage = () => {
|
|
433
433
|
const lastLoadedPage = usersResult?.page ?? 0
|
|
434
434
|
fetchUsers({
|
|
435
|
-
query: 'getUsers',
|
|
436
435
|
params: lastLoadedPage + 1,
|
|
437
436
|
})
|
|
438
437
|
}
|
|
@@ -504,7 +503,7 @@ export const defaultGetCacheKey = <P = unknown>(params: P): Key => {
|
|
|
504
503
|
|
|
505
504
|
It is recommended to override it when default implementation is not optimal or when keys in params object can be sorted in random order.
|
|
506
505
|
|
|
507
|
-
As example, can be
|
|
506
|
+
As example, can be overridden when implementing pagination.
|
|
508
507
|
|
|
509
508
|
#### How race conditions are handled?
|
|
510
509
|
|
package/dist/createActions.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { EntityChanges, Key, MutationState, QueryState, Typenames } from './types';
|
|
2
|
+
import { CacheState } from './types';
|
|
2
3
|
export type Actions<N extends string = string, T extends Typenames = Typenames, QP = unknown, QR = unknown, MP = unknown, MR = unknown> = ReturnType<typeof createActions<N, T, QP, QR, MP, MR>>;
|
|
3
4
|
export declare const createActions: <N extends string, T extends Typenames, QP, QR, MP, MR>(name: N) => {
|
|
4
5
|
updateQueryStateAndEntities: {
|
|
@@ -72,4 +73,11 @@ export declare const createActions: <N extends string, T extends Typenames, QP,
|
|
|
72
73
|
};
|
|
73
74
|
type: `@rrc/${N}/clearMutationState`;
|
|
74
75
|
};
|
|
76
|
+
clearCache: {
|
|
77
|
+
(stateToKeep?: Partial<CacheState<T, QP, QR, MP, MR>>): {
|
|
78
|
+
type: `@rrc/${N}/clearCache`;
|
|
79
|
+
stateToKeep: Partial<CacheState<T, QP, QR, MP, MR>> | undefined;
|
|
80
|
+
};
|
|
81
|
+
type: `@rrc/${N}/clearCache`;
|
|
82
|
+
};
|
|
75
83
|
};
|
package/dist/createActions.js
CHANGED
|
@@ -45,6 +45,12 @@ const createActions = (name) => {
|
|
|
45
45
|
mutationKeys,
|
|
46
46
|
});
|
|
47
47
|
clearMutationState.type = clearMutationStateType;
|
|
48
|
+
const clearCacheType = `${actionPrefix}clearCache`;
|
|
49
|
+
const clearCache = (stateToKeep) => ({
|
|
50
|
+
type: clearCacheType,
|
|
51
|
+
stateToKeep,
|
|
52
|
+
});
|
|
53
|
+
clearCache.type = clearCacheType;
|
|
48
54
|
return {
|
|
49
55
|
updateQueryStateAndEntities,
|
|
50
56
|
updateMutationStateAndEntities,
|
|
@@ -52,6 +58,7 @@ const createActions = (name) => {
|
|
|
52
58
|
invalidateQuery,
|
|
53
59
|
clearQueryState,
|
|
54
60
|
clearMutationState,
|
|
61
|
+
clearCache,
|
|
55
62
|
};
|
|
56
63
|
};
|
|
57
64
|
exports.createActions = createActions;
|
package/dist/createCache.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Cache, CacheOptions, Globals, Key, MutateOptions, MutationResult, OptionalPartial, QueryOptions, QueryResult, Typenames } from './types';
|
|
1
|
+
import type { Cache, CacheOptions, Globals, Key, MutateOptions, MutationResult, OptionalPartial, QueryOptions, QueryResult, Store, Typenames } from './types';
|
|
2
2
|
import { useMutation } from './useMutation';
|
|
3
3
|
import { useQuery } from './useQuery';
|
|
4
4
|
import { applyEntityChanges } from './utilsAndConstants';
|
|
@@ -11,17 +11,13 @@ import { applyEntityChanges } from './utilsAndConstants';
|
|
|
11
11
|
* })
|
|
12
12
|
*/
|
|
13
13
|
export declare const withTypenames: <T extends Typenames = Typenames>() => {
|
|
14
|
-
createCache: <N extends string, QP, QR, MP, MR>(partialCache: OptionalPartial<Omit<Cache<N, T, QP, QR, MP, MR>, "globals">, "options" | "queries" | "mutations" | "cacheStateSelector"> & {
|
|
14
|
+
createCache: <N extends string, QP, QR, MP, MR>(partialCache: OptionalPartial<Omit<Cache<N, T, QP, QR, MP, MR>, "globals">, "options" | "queries" | "mutations" | "cacheStateSelector" | "storeHooks"> & {
|
|
15
15
|
globals?: OptionalPartial<Cache<N, T, QP, QR, MP, MR>["globals"], "queries">;
|
|
16
16
|
}) => {
|
|
17
17
|
/** Keeps all options, passed while creating the cache. */
|
|
18
18
|
cache: Cache<N, T, QP, QR, MP, MR>;
|
|
19
19
|
/** Reducer of the cache, should be added to redux store. */
|
|
20
|
-
reducer: (state: {
|
|
21
|
-
entities: import("./types").EntitiesMap<T>;
|
|
22
|
-
queries: { [QK in keyof (QP | QR)]: import("./types").Dict<import("./types").QueryState<QP[QK], QR[QK]> | undefined>; };
|
|
23
|
-
mutations: { [MK in keyof (MP | MR)]: import("./types").MutationState<MP[MK], MR[MK]>; };
|
|
24
|
-
} | undefined, action: {
|
|
20
|
+
reducer: (state: import("./types").CacheState<T, QP, QR, MP, MR> | undefined, action: {
|
|
25
21
|
type: `@rrc/${N}/updateQueryStateAndEntities`;
|
|
26
22
|
queryKey: keyof QP & keyof QR;
|
|
27
23
|
queryCacheKey: Key;
|
|
@@ -51,11 +47,10 @@ export declare const withTypenames: <T extends Typenames = Typenames>() => {
|
|
|
51
47
|
} | {
|
|
52
48
|
type: `@rrc/${N}/clearMutationState`;
|
|
53
49
|
mutationKeys: (keyof MP & keyof MR)[];
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
};
|
|
50
|
+
} | {
|
|
51
|
+
type: `@rrc/${N}/clearCache`;
|
|
52
|
+
stateToKeep: Partial<import("./types").CacheState<T, QP, QR, MP, MR>> | undefined;
|
|
53
|
+
}) => import("./types").CacheState<T, QP, QR, MP, MR>;
|
|
59
54
|
actions: {
|
|
60
55
|
/** Updates query state, and optionally merges entity changes in a single action. */
|
|
61
56
|
updateQueryStateAndEntities: {
|
|
@@ -78,7 +73,7 @@ export declare const withTypenames: <T extends Typenames = Typenames>() => {
|
|
|
78
73
|
};
|
|
79
74
|
type: `@rrc/${N}/updateMutationStateAndEntities`;
|
|
80
75
|
};
|
|
81
|
-
/**
|
|
76
|
+
/** Merges EntityChanges to the state. */
|
|
82
77
|
mergeEntityChanges: {
|
|
83
78
|
(changes: import("./types").EntityChanges<T>): {
|
|
84
79
|
type: `@rrc/${N}/mergeEntityChanges`;
|
|
@@ -102,7 +97,7 @@ export declare const withTypenames: <T extends Typenames = Typenames>() => {
|
|
|
102
97
|
};
|
|
103
98
|
type: `@rrc/${N}/invalidateQuery`;
|
|
104
99
|
};
|
|
105
|
-
/**
|
|
100
|
+
/** Clears states for provided query keys and cache keys.
|
|
106
101
|
* If cache key for query key is not provided, the whole state for query key is cleared. */
|
|
107
102
|
clearQueryState: {
|
|
108
103
|
<K extends keyof QP & keyof QR>(queries: {
|
|
@@ -117,7 +112,7 @@ export declare const withTypenames: <T extends Typenames = Typenames>() => {
|
|
|
117
112
|
};
|
|
118
113
|
type: `@rrc/${N}/clearQueryState`;
|
|
119
114
|
};
|
|
120
|
-
/**
|
|
115
|
+
/** Clears states for provided mutation keys. */
|
|
121
116
|
clearMutationState: {
|
|
122
117
|
<K extends keyof MP & keyof MR>(mutationKeys: K[]): {
|
|
123
118
|
type: `@rrc/${N}/clearMutationState`;
|
|
@@ -125,8 +120,18 @@ export declare const withTypenames: <T extends Typenames = Typenames>() => {
|
|
|
125
120
|
};
|
|
126
121
|
type: `@rrc/${N}/clearMutationState`;
|
|
127
122
|
};
|
|
123
|
+
/** Replaces cache state with initial, optionally merging with provided state. Doesn't cancel running fetches and shoult be used with caution. */
|
|
124
|
+
clearCache: {
|
|
125
|
+
(stateToKeep?: Partial<import("./types").CacheState<T, QP, QR, MP, MR>> | undefined): {
|
|
126
|
+
type: `@rrc/${N}/clearCache`;
|
|
127
|
+
stateToKeep: Partial<import("./types").CacheState<T, QP, QR, MP, MR>> | undefined;
|
|
128
|
+
};
|
|
129
|
+
type: `@rrc/${N}/clearCache`;
|
|
130
|
+
};
|
|
128
131
|
};
|
|
129
132
|
selectors: {
|
|
133
|
+
/** This is a cacheStateSelector from createCache options, or default one if was not provided. */
|
|
134
|
+
selectCacheState: (state: any) => import("./types").CacheState<T, QP, QR, MP, MR>;
|
|
130
135
|
/** Selects query state. */
|
|
131
136
|
selectQueryState: <QK extends keyof QP | keyof QR>(state: unknown, query: QK, cacheKey: Key) => import("./types").QueryState<QK extends keyof QP & keyof QR ? QP[QK] : never, QK extends keyof QP & keyof QR ? QR[QK] : never>;
|
|
132
137
|
/** Selects query latest result. */
|
|
@@ -183,18 +188,18 @@ export declare const createCache: <N extends string, QP, QR, MP, MR>(partialCach
|
|
|
183
188
|
queries: Partial<{ [QK in keyof (QP & QR)]: QK extends keyof QP & keyof QR ? import("./types").QueryInfo<N, Typenames, QP[QK], QR[QK], QP, QR, MP, MR> : never; }>;
|
|
184
189
|
mutations: Partial<{ [MK in keyof (MP & MR)]: MK extends keyof MP & keyof MR ? import("./types").MutationInfo<N, Typenames, MP[MK], MR[MK], QP, QR, MP, MR> : never; }>;
|
|
185
190
|
options: Partial<CacheOptions>;
|
|
186
|
-
|
|
187
|
-
|
|
191
|
+
storeHooks: Partial<{
|
|
192
|
+
useStore: () => Store;
|
|
193
|
+
useSelector: <R>(selector: (state: unknown) => R, comparer?: (x: R, y: R) => boolean) => R;
|
|
194
|
+
}>;
|
|
195
|
+
cacheStateSelector: Partial<(state: any) => import("./types").CacheState<Typenames, QP, QR, MP, MR>>;
|
|
196
|
+
}> & Omit<Omit<Cache<N, Typenames, QP, QR, MP, MR>, "globals">, "queries" | "mutations" | "options" | "storeHooks" | "cacheStateSelector"> & {
|
|
188
197
|
globals?: OptionalPartial<Globals<N, Typenames, QP, QR, MP, MR>, "queries"> | undefined;
|
|
189
198
|
}) => {
|
|
190
199
|
/** Keeps all options, passed while creating the cache. */
|
|
191
200
|
cache: Cache<N, Typenames, QP, QR, MP, MR>;
|
|
192
201
|
/** Reducer of the cache, should be added to redux store. */
|
|
193
|
-
reducer: (state: {
|
|
194
|
-
entities: import("./types").EntitiesMap<Typenames>;
|
|
195
|
-
queries: { [QK_1 in keyof (QP | QR)]: import("./types").Dict<import("./types").QueryState<QP[QK_1], QR[QK_1]> | undefined>; };
|
|
196
|
-
mutations: { [MK_1 in keyof (MP | MR)]: import("./types").MutationState<MP[MK_1], MR[MK_1]>; };
|
|
197
|
-
} | undefined, action: {
|
|
202
|
+
reducer: (state: import("./types").CacheState<Typenames, QP, QR, MP, MR> | undefined, action: {
|
|
198
203
|
type: `@rrc/${N}/updateQueryStateAndEntities`;
|
|
199
204
|
queryKey: keyof QP & keyof QR;
|
|
200
205
|
queryCacheKey: Key;
|
|
@@ -224,11 +229,10 @@ export declare const createCache: <N extends string, QP, QR, MP, MR>(partialCach
|
|
|
224
229
|
} | {
|
|
225
230
|
type: `@rrc/${N}/clearMutationState`;
|
|
226
231
|
mutationKeys: (keyof MP & keyof MR)[];
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
};
|
|
232
|
+
} | {
|
|
233
|
+
type: `@rrc/${N}/clearCache`;
|
|
234
|
+
stateToKeep: Partial<import("./types").CacheState<Typenames, QP, QR, MP, MR>> | undefined;
|
|
235
|
+
}) => import("./types").CacheState<Typenames, QP, QR, MP, MR>;
|
|
232
236
|
actions: {
|
|
233
237
|
/** Updates query state, and optionally merges entity changes in a single action. */
|
|
234
238
|
updateQueryStateAndEntities: {
|
|
@@ -251,7 +255,7 @@ export declare const createCache: <N extends string, QP, QR, MP, MR>(partialCach
|
|
|
251
255
|
};
|
|
252
256
|
type: `@rrc/${N}/updateMutationStateAndEntities`;
|
|
253
257
|
};
|
|
254
|
-
/**
|
|
258
|
+
/** Merges EntityChanges to the state. */
|
|
255
259
|
mergeEntityChanges: {
|
|
256
260
|
(changes: import("./types").EntityChanges<Typenames>): {
|
|
257
261
|
type: `@rrc/${N}/mergeEntityChanges`;
|
|
@@ -275,7 +279,7 @@ export declare const createCache: <N extends string, QP, QR, MP, MR>(partialCach
|
|
|
275
279
|
};
|
|
276
280
|
type: `@rrc/${N}/invalidateQuery`;
|
|
277
281
|
};
|
|
278
|
-
/**
|
|
282
|
+
/** Clears states for provided query keys and cache keys.
|
|
279
283
|
* If cache key for query key is not provided, the whole state for query key is cleared. */
|
|
280
284
|
clearQueryState: {
|
|
281
285
|
<K extends keyof QP & keyof QR>(queries: {
|
|
@@ -290,7 +294,7 @@ export declare const createCache: <N extends string, QP, QR, MP, MR>(partialCach
|
|
|
290
294
|
};
|
|
291
295
|
type: `@rrc/${N}/clearQueryState`;
|
|
292
296
|
};
|
|
293
|
-
/**
|
|
297
|
+
/** Clears states for provided mutation keys. */
|
|
294
298
|
clearMutationState: {
|
|
295
299
|
<K extends keyof MP & keyof MR>(mutationKeys: K[]): {
|
|
296
300
|
type: `@rrc/${N}/clearMutationState`;
|
|
@@ -298,8 +302,18 @@ export declare const createCache: <N extends string, QP, QR, MP, MR>(partialCach
|
|
|
298
302
|
};
|
|
299
303
|
type: `@rrc/${N}/clearMutationState`;
|
|
300
304
|
};
|
|
305
|
+
/** Replaces cache state with initial, optionally merging with provided state. Doesn't cancel running fetches and shoult be used with caution. */
|
|
306
|
+
clearCache: {
|
|
307
|
+
(stateToKeep?: Partial<import("./types").CacheState<Typenames, QP, QR, MP, MR>> | undefined): {
|
|
308
|
+
type: `@rrc/${N}/clearCache`;
|
|
309
|
+
stateToKeep: Partial<import("./types").CacheState<Typenames, QP, QR, MP, MR>> | undefined;
|
|
310
|
+
};
|
|
311
|
+
type: `@rrc/${N}/clearCache`;
|
|
312
|
+
};
|
|
301
313
|
};
|
|
302
314
|
selectors: {
|
|
315
|
+
/** This is a cacheStateSelector from createCache options, or default one if was not provided. */
|
|
316
|
+
selectCacheState: (state: any) => import("./types").CacheState<Typenames, QP, QR, MP, MR>;
|
|
303
317
|
/** Selects query state. */
|
|
304
318
|
selectQueryState: <QK_1 extends keyof QP | keyof QR>(state: unknown, query: QK_1, cacheKey: Key) => import("./types").QueryState<QK_1 extends keyof QP & keyof QR ? QP[QK_1] : never, QK_1 extends keyof QP & keyof QR ? QR[QK_1] : never>;
|
|
305
319
|
/** Selects query latest result. */
|
package/dist/createCache.js
CHANGED
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.createCache = exports.withTypenames = void 0;
|
|
4
4
|
const react_1 = require("react");
|
|
5
|
-
const react_redux_1 = require("react-redux");
|
|
6
5
|
const createActions_1 = require("./createActions");
|
|
7
6
|
const createCacheReducer_1 = require("./createCacheReducer");
|
|
8
7
|
const createSelectors_1 = require("./createSelectors");
|
|
@@ -25,22 +24,26 @@ const withTypenames = () => {
|
|
|
25
24
|
*/
|
|
26
25
|
return {
|
|
27
26
|
createCache: (partialCache) => {
|
|
28
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
|
|
29
|
-
var
|
|
27
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
|
|
28
|
+
var _q, _r, _s, _t, _u, _v, _w, _x;
|
|
30
29
|
const abortControllers = new WeakMap();
|
|
31
30
|
// provide all optional fields
|
|
32
31
|
(_a = partialCache.options) !== null && _a !== void 0 ? _a : (partialCache.options = {});
|
|
33
|
-
(_b = (
|
|
34
|
-
(_c = (
|
|
35
|
-
(_d = (
|
|
36
|
-
(_e = partialCache.
|
|
37
|
-
(_f = partialCache.
|
|
38
|
-
(_g = partialCache.globals) !== null && _g !== void 0 ? _g : (
|
|
39
|
-
(_h = (
|
|
40
|
-
(_j =
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
32
|
+
(_b = (_q = partialCache.options).logsEnabled) !== null && _b !== void 0 ? _b : (_q.logsEnabled = false);
|
|
33
|
+
(_c = (_r = partialCache.options).additionalValidation) !== null && _c !== void 0 ? _c : (_r.additionalValidation = utilsAndConstants_1.IS_DEV);
|
|
34
|
+
(_d = (_s = partialCache.options).deepComparisonEnabled) !== null && _d !== void 0 ? _d : (_s.deepComparisonEnabled = true);
|
|
35
|
+
(_e = partialCache.globals) !== null && _e !== void 0 ? _e : (partialCache.globals = {});
|
|
36
|
+
(_f = (_t = partialCache.globals).queries) !== null && _f !== void 0 ? _f : (_t.queries = {});
|
|
37
|
+
(_g = (_u = partialCache.globals.queries).fetchPolicy) !== null && _g !== void 0 ? _g : (_u.fetchPolicy = utilsAndConstants_1.FetchPolicy.NoCacheOrExpired);
|
|
38
|
+
(_h = (_v = partialCache.globals.queries).skipFetch) !== null && _h !== void 0 ? _h : (_v.skipFetch = false);
|
|
39
|
+
(_j = partialCache.storeHooks) !== null && _j !== void 0 ? _j : (partialCache.storeHooks = {});
|
|
40
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
41
|
+
(_k = (_w = partialCache.storeHooks).useStore) !== null && _k !== void 0 ? _k : (_w.useStore = require('react-redux').useStore);
|
|
42
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
43
|
+
(_l = (_x = partialCache.storeHooks).useSelector) !== null && _l !== void 0 ? _l : (_x.useSelector = require('react-redux').useSelector);
|
|
44
|
+
(_m = partialCache.cacheStateSelector) !== null && _m !== void 0 ? _m : (partialCache.cacheStateSelector = (state) => state[cache.name]);
|
|
45
|
+
(_o = partialCache.mutations) !== null && _o !== void 0 ? _o : (partialCache.mutations = {});
|
|
46
|
+
(_p = partialCache.queries) !== null && _p !== void 0 ? _p : (partialCache.queries = {});
|
|
44
47
|
// @ts-expect-error private field for testing
|
|
45
48
|
partialCache.abortControllers = abortControllers;
|
|
46
49
|
const cache = partialCache;
|
|
@@ -49,11 +52,11 @@ const withTypenames = () => {
|
|
|
49
52
|
console.warn('react-redux-cache: optional dependency for fast-deep-equal was not provided, while deepComparisonEnabled option is true');
|
|
50
53
|
}
|
|
51
54
|
// selectors
|
|
52
|
-
const selectors = (0, createSelectors_1.createSelectors)(cache);
|
|
53
|
-
const { selectQueryState, selectQueryResult, selectQueryLoading, selectQueryError, selectQueryParams, selectQueryExpiresAt, selectMutationState, selectMutationResult, selectMutationLoading, selectMutationError, selectMutationParams, selectEntityById, selectEntities, selectEntitiesByTypename, } = selectors;
|
|
55
|
+
const selectors = Object.assign({ selectCacheState: cache.cacheStateSelector }, (0, createSelectors_1.createSelectors)(cache));
|
|
56
|
+
const { selectCacheState, selectQueryState, selectQueryResult, selectQueryLoading, selectQueryError, selectQueryParams, selectQueryExpiresAt, selectMutationState, selectMutationResult, selectMutationLoading, selectMutationError, selectMutationParams, selectEntityById, selectEntities, selectEntitiesByTypename, } = selectors;
|
|
54
57
|
// actions
|
|
55
58
|
const actions = (0, createActions_1.createActions)(cache.name);
|
|
56
|
-
const { updateQueryStateAndEntities, updateMutationStateAndEntities, mergeEntityChanges, invalidateQuery, clearQueryState, clearMutationState, } = actions;
|
|
59
|
+
const { updateQueryStateAndEntities, updateMutationStateAndEntities, mergeEntityChanges, invalidateQuery, clearQueryState, clearMutationState, clearCache, } = actions;
|
|
57
60
|
return {
|
|
58
61
|
/** Keeps all options, passed while creating the cache. */
|
|
59
62
|
cache,
|
|
@@ -64,17 +67,21 @@ const withTypenames = () => {
|
|
|
64
67
|
updateQueryStateAndEntities,
|
|
65
68
|
/** Updates mutation state, and optionally merges entity changes in a single action. */
|
|
66
69
|
updateMutationStateAndEntities,
|
|
67
|
-
/**
|
|
70
|
+
/** Merges EntityChanges to the state. */
|
|
68
71
|
mergeEntityChanges,
|
|
69
72
|
/** Invalidates query states. */
|
|
70
73
|
invalidateQuery,
|
|
71
|
-
/**
|
|
74
|
+
/** Clears states for provided query keys and cache keys.
|
|
72
75
|
* If cache key for query key is not provided, the whole state for query key is cleared. */
|
|
73
76
|
clearQueryState,
|
|
74
|
-
/**
|
|
77
|
+
/** Clears states for provided mutation keys. */
|
|
75
78
|
clearMutationState,
|
|
79
|
+
/** Replaces cache state with initial, optionally merging with provided state. Doesn't cancel running fetches and shoult be used with caution. */
|
|
80
|
+
clearCache,
|
|
76
81
|
},
|
|
77
82
|
selectors: {
|
|
83
|
+
/** This is a cacheStateSelector from createCache options, or default one if was not provided. */
|
|
84
|
+
selectCacheState,
|
|
78
85
|
/** Selects query state. */
|
|
79
86
|
selectQueryState,
|
|
80
87
|
/** Selects query latest result. */
|
|
@@ -107,7 +114,7 @@ const withTypenames = () => {
|
|
|
107
114
|
hooks: {
|
|
108
115
|
/** Returns client object with query and mutate functions. */
|
|
109
116
|
useClient: () => {
|
|
110
|
-
const store =
|
|
117
|
+
const store = cache.storeHooks.useStore();
|
|
111
118
|
return (0, react_1.useMemo)(() => {
|
|
112
119
|
const client = {
|
|
113
120
|
query: (options) => {
|
|
@@ -135,7 +142,7 @@ const withTypenames = () => {
|
|
|
135
142
|
useMutation: (options) => (0, useMutation_1.useMutation)(cache, actions, selectors, options, abortControllers),
|
|
136
143
|
/** useSelector + selectEntityById. */
|
|
137
144
|
useSelectEntityById: (id, typename) => {
|
|
138
|
-
return
|
|
145
|
+
return cache.storeHooks.useSelector((state) => selectEntityById(state, id, typename));
|
|
139
146
|
},
|
|
140
147
|
},
|
|
141
148
|
utils: {
|
|
@@ -1,12 +1,3 @@
|
|
|
1
1
|
import type { Actions } from './createActions';
|
|
2
|
-
import type { CacheOptions,
|
|
3
|
-
export
|
|
4
|
-
export declare const createCacheReducer: <N extends string, T extends Typenames, QP, QR, MP, MR>(actions: Actions<N, T, QP, QR, MP, MR>, queryKeys: (keyof (QP | QR))[], cacheOptions: CacheOptions) => (state: {
|
|
5
|
-
entities: EntitiesMap<T>;
|
|
6
|
-
queries: { [QK in keyof (QP | QR)]: Dict<QueryState<QP[QK], QR[QK]> | undefined>; };
|
|
7
|
-
mutations: { [MK in keyof (MP | MR)]: MutationState<MP[MK], MR[MK]>; };
|
|
8
|
-
} | undefined, action: ReturnType<(typeof actions)[keyof typeof actions]>) => {
|
|
9
|
-
entities: EntitiesMap<T>;
|
|
10
|
-
queries: { [QK in keyof (QP | QR)]: Dict<QueryState<QP[QK], QR[QK]> | undefined>; };
|
|
11
|
-
mutations: { [MK in keyof (MP | MR)]: MutationState<MP[MK], MR[MK]>; };
|
|
12
|
-
};
|
|
2
|
+
import type { CacheOptions, CacheState, Typenames } from './types';
|
|
3
|
+
export declare const createCacheReducer: <N extends string, T extends Typenames, QP, QR, MP, MR>(actions: Actions<N, T, QP, QR, MP, MR>, queryKeys: (keyof (QP | QR))[], cacheOptions: CacheOptions) => (state: CacheState<T, QP, QR, MP, MR> | undefined, action: ReturnType<(typeof actions)[keyof typeof actions]>) => CacheState<T, QP, QR, MP, MR>;
|
|
@@ -16,17 +16,14 @@ const utilsAndConstants_1 = require("./utilsAndConstants");
|
|
|
16
16
|
const optionalQueryKeys = ['error', 'expiresAt', 'result', 'params'];
|
|
17
17
|
const optionalMutationKeys = ['error', 'result', 'params'];
|
|
18
18
|
const createCacheReducer = (actions, queryKeys, cacheOptions) => {
|
|
19
|
-
const
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
queries: queryStateMap,
|
|
28
|
-
mutations: mutationStateMap,
|
|
29
|
-
};
|
|
19
|
+
const initialState = Object.freeze({
|
|
20
|
+
entities: Object.freeze({}),
|
|
21
|
+
queries: Object.freeze(queryKeys.reduce((result, x) => {
|
|
22
|
+
result[x] = Object.freeze({});
|
|
23
|
+
return result;
|
|
24
|
+
}, {})),
|
|
25
|
+
mutations: Object.freeze({}),
|
|
26
|
+
});
|
|
30
27
|
cacheOptions.logsEnabled &&
|
|
31
28
|
(0, utilsAndConstants_1.log)('createCacheReducer', {
|
|
32
29
|
queryKeys,
|
|
@@ -205,6 +202,11 @@ const createCacheReducer = (actions, queryKeys, cacheOptions) => {
|
|
|
205
202
|
? state
|
|
206
203
|
: Object.assign(Object.assign({}, state), { mutations: newMutations });
|
|
207
204
|
}
|
|
205
|
+
case actions.clearCache.type: {
|
|
206
|
+
const { stateToKeep } = action;
|
|
207
|
+
return stateToKeep
|
|
208
|
+
? Object.assign(Object.assign({}, initialState), stateToKeep) : initialState;
|
|
209
|
+
}
|
|
208
210
|
}
|
|
209
211
|
return state;
|
|
210
212
|
};
|
package/dist/index.js
CHANGED
|
@@ -27,12 +27,11 @@ Object.defineProperty(exports, "FetchPolicy", { enumerable: true, get: function
|
|
|
27
27
|
Object.defineProperty(exports, "isEmptyObject", { enumerable: true, get: function () { return utilsAndConstants_1.isEmptyObject; } });
|
|
28
28
|
// Backlog
|
|
29
29
|
// ! high (1.0.0-rc.0)
|
|
30
|
+
// optimistic response
|
|
30
31
|
// generate full api docs
|
|
31
32
|
// ! medium
|
|
32
|
-
// optimistic response
|
|
33
33
|
// onCancel & onAbort
|
|
34
34
|
// remove empty entities and queries from state
|
|
35
|
-
// reset [whole] cache to initial / to provided state
|
|
36
35
|
// globals for success, completions and loading states?
|
|
37
36
|
// make query key / cache key difference more clear in the docs
|
|
38
37
|
// check type of function arguments in dev
|
|
@@ -41,7 +40,6 @@ Object.defineProperty(exports, "isEmptyObject", { enumerable: true, get: functio
|
|
|
41
40
|
// ! low
|
|
42
41
|
// make error type generic
|
|
43
42
|
// allow multiple mutation with same keys?
|
|
44
|
-
// custom useStore & useSelector to support multiple stores?
|
|
45
43
|
// easy access to all currently loading queries and mutations?
|
|
46
44
|
// cancellation to queries
|
|
47
45
|
// if mutation & query already loading - make options: last, throttle, debounce, parallel?
|
package/dist/mutate.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { Store } from 'redux';
|
|
2
1
|
import type { Actions } from './createActions';
|
|
3
2
|
import { Selectors } from './createSelectors';
|
|
4
|
-
import type { Cache, Key, MutationResult, Typenames } from './types';
|
|
3
|
+
import type { Cache, Key, MutationResult, Store, Typenames } from './types';
|
|
5
4
|
export declare const mutate: <N extends string, T extends Typenames, QP, QR, MP, MR, MK extends keyof (MP & MR)>(logTag: string, store: Store, cache: Cache<N, T, QP, QR, MP, MR>, actions: Actions<N, T, QP, QR, MP, MR>, selectors: Selectors<N, T, QP, QR, MP, MR>, mutationKey: MK, params: MK extends keyof (MP | MR) ? MP[MK] : never, abortControllers: WeakMap<Store, Record<Key, AbortController>>, onCompleted?: ((response: import("./types").NormalizedQueryResponse<T, MR[keyof MP & keyof MR & string]> | undefined, error: unknown | undefined, params: MP[keyof MP & keyof MR & string] | undefined, store: Store, actions: Actions<N, T, QP, QR, MP, MR>, selectors: Selectors<N, T, QP, QR, MP, MR>) => void) | ((response: import("./types").NormalizedQueryResponse<T, MR[keyof MP & keyof MR & number]> | undefined, error: unknown | undefined, params: MP[keyof MP & keyof MR & number] | undefined, store: Store, actions: Actions<N, T, QP, QR, MP, MR>, selectors: Selectors<N, T, QP, QR, MP, MR>) => void) | ((response: import("./types").NormalizedQueryResponse<T, MR[keyof MP & keyof MR & symbol]> | undefined, error: unknown | undefined, params: MP[keyof MP & keyof MR & symbol] | undefined, store: Store, actions: Actions<N, T, QP, QR, MP, MR>, selectors: Selectors<N, T, QP, QR, MP, MR>) => void) | undefined, onSuccess?: ((response: import("./types").NormalizedQueryResponse<T, MR[keyof MP & keyof MR & string]>, params: MP[keyof MP & keyof MR & string] | undefined, store: Store, actions: Actions<N, T, QP, QR, MP, MR>, selectors: Selectors<N, T, QP, QR, MP, MR>) => void) | ((response: import("./types").NormalizedQueryResponse<T, MR[keyof MP & keyof MR & number]>, params: MP[keyof MP & keyof MR & number] | undefined, store: Store, actions: Actions<N, T, QP, QR, MP, MR>, selectors: Selectors<N, T, QP, QR, MP, MR>) => void) | ((response: import("./types").NormalizedQueryResponse<T, MR[keyof MP & keyof MR & symbol]>, params: MP[keyof MP & keyof MR & symbol] | undefined, store: Store, actions: Actions<N, T, QP, QR, MP, MR>, selectors: Selectors<N, T, QP, QR, MP, MR>) => void) | undefined, onError?: ((error: unknown, params: MP[keyof MP & keyof MR & string] | undefined, store: Store, actions: Actions<N, T, QP, QR, MP, MR>, selectors: Selectors<N, T, QP, QR, MP, MR>) => boolean | void | null | undefined) | ((error: unknown, params: MP[keyof MP & keyof MR & number] | undefined, store: Store, actions: Actions<N, T, QP, QR, MP, MR>, selectors: Selectors<N, T, QP, QR, MP, MR>) => boolean | void | null | undefined) | ((error: unknown, params: MP[keyof MP & keyof MR & symbol] | undefined, store: Store, actions: Actions<N, T, QP, QR, MP, MR>, selectors: Selectors<N, T, QP, QR, MP, MR>) => boolean | void | null | undefined) | undefined) => Promise<MutationResult<MK extends keyof (MP | MR) ? MR[MK] : never>>;
|
package/dist/query.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { Store } from 'redux';
|
|
2
1
|
import type { Actions } from './createActions';
|
|
3
2
|
import { Selectors } from './createSelectors';
|
|
4
|
-
import type { Cache, Key, QueryResult, Typenames } from './types';
|
|
3
|
+
import type { Cache, Key, QueryResult, Store, Typenames } from './types';
|
|
5
4
|
export declare const query: <N extends string, T extends Typenames, QP, QR, MP, MR, QK extends keyof (QP & QR)>(logTag: string, store: Store, cache: Cache<N, T, QP, QR, MP, MR>, actions: Actions<N, T, QP, QR, MP, MR>, selectors: Selectors<N, T, QP, QR, MP, MR>, queryKey: QK, cacheKey: Key, params: QK extends keyof (QP | QR) ? QP[QK] : never, secondsToLive: number | undefined, onlyIfExpired: boolean | undefined, mergeResults?: ((oldResult: QR[keyof QP & keyof QR & string] | undefined, response: import("./types").NormalizedQueryResponse<T, QR[keyof QP & keyof QR & string]>, params: QP[keyof QP & keyof QR & string] | undefined, store: Store, actions: Actions<N, T, QP, QR, MP, MR>, selectors: Selectors<N, T, QP, QR, MP, MR>) => QR[keyof QP & keyof QR & string]) | ((oldResult: QR[keyof QP & keyof QR & number] | undefined, response: import("./types").NormalizedQueryResponse<T, QR[keyof QP & keyof QR & number]>, params: QP[keyof QP & keyof QR & number] | undefined, store: Store, actions: Actions<N, T, QP, QR, MP, MR>, selectors: Selectors<N, T, QP, QR, MP, MR>) => QR[keyof QP & keyof QR & number]) | ((oldResult: QR[keyof QP & keyof QR & symbol] | undefined, response: import("./types").NormalizedQueryResponse<T, QR[keyof QP & keyof QR & symbol]>, params: QP[keyof QP & keyof QR & symbol] | undefined, store: Store, actions: Actions<N, T, QP, QR, MP, MR>, selectors: Selectors<N, T, QP, QR, MP, MR>) => QR[keyof QP & keyof QR & symbol]) | undefined, onCompleted?: ((response: import("./types").NormalizedQueryResponse<T, QR[keyof QP & keyof QR & string]> | undefined, error: unknown | undefined, params: QP[keyof QP & keyof QR & string] | undefined, store: Store, actions: Actions<N, T, QP, QR, MP, MR>, selectors: Selectors<N, T, QP, QR, MP, MR>) => void) | ((response: import("./types").NormalizedQueryResponse<T, QR[keyof QP & keyof QR & number]> | undefined, error: unknown | undefined, params: QP[keyof QP & keyof QR & number] | undefined, store: Store, actions: Actions<N, T, QP, QR, MP, MR>, selectors: Selectors<N, T, QP, QR, MP, MR>) => void) | ((response: import("./types").NormalizedQueryResponse<T, QR[keyof QP & keyof QR & symbol]> | undefined, error: unknown | undefined, params: QP[keyof QP & keyof QR & symbol] | undefined, store: Store, actions: Actions<N, T, QP, QR, MP, MR>, selectors: Selectors<N, T, QP, QR, MP, MR>) => void) | undefined, onSuccess?: ((response: import("./types").NormalizedQueryResponse<T, QR[keyof QP & keyof QR & string]>, params: QP[keyof QP & keyof QR & string] | undefined, store: Store, actions: Actions<N, T, QP, QR, MP, MR>, selectors: Selectors<N, T, QP, QR, MP, MR>) => void) | ((response: import("./types").NormalizedQueryResponse<T, QR[keyof QP & keyof QR & number]>, params: QP[keyof QP & keyof QR & number] | undefined, store: Store, actions: Actions<N, T, QP, QR, MP, MR>, selectors: Selectors<N, T, QP, QR, MP, MR>) => void) | ((response: import("./types").NormalizedQueryResponse<T, QR[keyof QP & keyof QR & symbol]>, params: QP[keyof QP & keyof QR & symbol] | undefined, store: Store, actions: Actions<N, T, QP, QR, MP, MR>, selectors: Selectors<N, T, QP, QR, MP, MR>) => void) | undefined, onError?: ((error: unknown, params: QP[keyof QP & keyof QR & string] | undefined, store: Store, actions: Actions<N, T, QP, QR, MP, MR>, selectors: Selectors<N, T, QP, QR, MP, MR>) => boolean | void | null | undefined) | ((error: unknown, params: QP[keyof QP & keyof QR & number] | undefined, store: Store, actions: Actions<N, T, QP, QR, MP, MR>, selectors: Selectors<N, T, QP, QR, MP, MR>) => boolean | void | null | undefined) | ((error: unknown, params: QP[keyof QP & keyof QR & symbol] | undefined, store: Store, actions: Actions<N, T, QP, QR, MP, MR>, selectors: Selectors<N, T, QP, QR, MP, MR>) => boolean | void | null | undefined) | undefined) => Promise<QueryResult<QK extends keyof (QP | QR) ? QR[QK] : never>>;
|
package/dist/types.d.ts
CHANGED
|
@@ -1,13 +1,11 @@
|
|
|
1
|
-
import type { Store } from 'redux';
|
|
2
1
|
import type { Actions } from './createActions';
|
|
3
|
-
import type { ReduxCacheState } from './createCacheReducer';
|
|
4
2
|
import type { Selectors } from './createSelectors';
|
|
5
3
|
export type Key = string | number | symbol;
|
|
6
4
|
export type Dict<T> = Record<Key, T>;
|
|
7
5
|
export type OptionalPartial<T, K extends keyof T> = Partial<{
|
|
8
6
|
[A in K]: Partial<T[A]>;
|
|
9
7
|
}> & Omit<T, K>;
|
|
10
|
-
/** Entity changes to be merged to
|
|
8
|
+
/** Entity changes to be merged to the state. */
|
|
11
9
|
export type EntityChanges<T extends Typenames> = {
|
|
12
10
|
/** Entities that will be merged with existing. */
|
|
13
11
|
merge?: PartialEntitiesMap<T>;
|
|
@@ -18,22 +16,34 @@ export type EntityChanges<T extends Typenames> = {
|
|
|
18
16
|
/** Alias for `merge` to support normalizr. */
|
|
19
17
|
entities?: EntityChanges<T>['merge'];
|
|
20
18
|
};
|
|
19
|
+
export type Store<S = unknown> = {
|
|
20
|
+
dispatch: (action: ReturnType<Actions[keyof Actions]>) => unknown;
|
|
21
|
+
getState: () => S;
|
|
22
|
+
};
|
|
21
23
|
/** Record of typename and its corresponding entity type */
|
|
22
24
|
export type Typenames = Record<string, object>;
|
|
23
25
|
export type Cache<N extends string, T extends Typenames, QP, QR, MP, MR> = {
|
|
24
|
-
/** Used as prefix for actions and in default cacheStateSelector for selecting cache state from
|
|
26
|
+
/** Used as prefix for actions and in default cacheStateSelector for selecting cache state from store root state. */
|
|
25
27
|
name: N;
|
|
28
|
+
/** Cache options. */
|
|
29
|
+
options: CacheOptions;
|
|
30
|
+
/** Default options for queries and mutations. */
|
|
31
|
+
globals: Globals<N, T, QP, QR, MP, MR>;
|
|
32
|
+
/** Hooks to access and subscribe to the store. Imported from react-redux if not overridden. */
|
|
33
|
+
storeHooks: {
|
|
34
|
+
useStore: () => Store;
|
|
35
|
+
useSelector: <R>(selector: (state: unknown) => R, comparer?: (x: R, y: R) => boolean) => R;
|
|
36
|
+
};
|
|
37
|
+
/** Should return cache state from store root state. Default implementation returns `state[name]`. */
|
|
38
|
+
cacheStateSelector: (state: any) => CacheState<T, QP, QR, MP, MR>;
|
|
39
|
+
/** Queries. */
|
|
26
40
|
queries: {
|
|
27
41
|
[QK in keyof (QP & QR)]: QK extends keyof (QP | QR) ? QueryInfo<N, T, QP[QK], QR[QK], QP, QR, MP, MR> : never;
|
|
28
42
|
};
|
|
43
|
+
/** Mutations. */
|
|
29
44
|
mutations: {
|
|
30
45
|
[MK in keyof (MP & MR)]: MK extends keyof (MP | MR) ? MutationInfo<N, T, MP[MK], MR[MK], QP, QR, MP, MR> : never;
|
|
31
46
|
};
|
|
32
|
-
/** Default options for queries and mutations. */
|
|
33
|
-
globals: Globals<N, T, QP, QR, MP, MR>;
|
|
34
|
-
options: CacheOptions;
|
|
35
|
-
/** Should return cache state from redux root state. Default implementation returns `state[name]`. */
|
|
36
|
-
cacheStateSelector: (state: any) => ReduxCacheState<T, QP, QR, MP, MR>;
|
|
37
47
|
};
|
|
38
48
|
export type Globals<N extends string, T extends Typenames, QP, QR, MP, MR> = {
|
|
39
49
|
/** Handles errors, not handled by onError from queries and mutations. @Default undefined. */
|
|
@@ -72,6 +82,15 @@ export type EntitiesMap<T extends Typenames> = {
|
|
|
72
82
|
export type EntityIds<T extends Typenames> = {
|
|
73
83
|
[K in keyof T]?: Key[];
|
|
74
84
|
};
|
|
85
|
+
export type CacheState<T extends Typenames, QP, QR, MP, MR> = {
|
|
86
|
+
entities: EntitiesMap<T>;
|
|
87
|
+
queries: {
|
|
88
|
+
[QK in keyof (QP | QR)]: Dict<QueryState<QP[QK], QR[QK]> | undefined>;
|
|
89
|
+
};
|
|
90
|
+
mutations: {
|
|
91
|
+
[MK in keyof (MP | MR)]: MutationState<MP[MK], MR[MK]>;
|
|
92
|
+
};
|
|
93
|
+
};
|
|
75
94
|
export type QueryInfo<N extends string, T extends Typenames = Typenames, P = unknown, R = unknown, QP = unknown, QR = unknown, MP = unknown, MR = unknown> = Partial<Pick<Globals<N, T, QP, QR, MP, MR>['queries'], 'skipFetch' | 'secondsToLive'>> & {
|
|
76
95
|
query: NormalizedQuery<T, P, R>;
|
|
77
96
|
/** Determines when useQuery fetch triggers should start fetching. Fetch is performed if function returns true.
|
|
@@ -96,7 +115,7 @@ export type QueryInfo<N extends string, T extends Typenames = Typenames, P = unk
|
|
|
96
115
|
export type Query<P = unknown, R = unknown> = (
|
|
97
116
|
/** Query parameters */
|
|
98
117
|
params: P,
|
|
99
|
-
/**
|
|
118
|
+
/** Store */
|
|
100
119
|
store: Store) => Promise<QueryResponse<R>>;
|
|
101
120
|
export type NormalizedQuery<T extends Typenames = Typenames, P = unknown, R = unknown> = (...args: Parameters<Query<P, R>>) => Promise<NormalizedQueryResponse<T, R>>;
|
|
102
121
|
export type QueryState<P, R> = MutationState<P, R> & {
|
|
@@ -127,7 +146,7 @@ export type MutationInfo<N extends string, T extends Typenames = Typenames, P =
|
|
|
127
146
|
export type Mutation<P = unknown, R = unknown> = (
|
|
128
147
|
/** Mutation parameters */
|
|
129
148
|
params: P,
|
|
130
|
-
/**
|
|
149
|
+
/** Store */
|
|
131
150
|
store: Store,
|
|
132
151
|
/** Signal is aborted for current mutation when the same mutation was called once again. */
|
|
133
152
|
abortSignal: AbortSignal) => Promise<MutationResponse<R>>;
|
package/dist/useMutation.d.ts
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { Store } from 'redux';
|
|
2
1
|
import { Actions } from './createActions';
|
|
3
2
|
import { Selectors } from './createSelectors';
|
|
4
|
-
import { Cache, Key, MutateOptions, MutationState, Typenames } from './types';
|
|
3
|
+
import { Cache, Key, MutateOptions, MutationState, Store, Typenames } from './types';
|
|
5
4
|
export declare const useMutation: <N extends string, T extends Typenames, QP, QR, MP, MR, MK extends keyof (MP & MR)>(cache: Cache<N, T, QP, QR, MP, MR>, actions: Actions<N, T, QP, QR, MP, MR>, selectors: Selectors<N, T, QP, QR, MP, MR>, options: Omit<MutateOptions<N, T, QP, QR, MP, MR, MK>, "params">, 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>>, MutationState<MK extends keyof MP & keyof MR ? MP[MK] : never, MK extends keyof MP & keyof MR ? MP[MK] : never>, () => boolean];
|
package/dist/useMutation.js
CHANGED
|
@@ -11,13 +11,12 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.useMutation = void 0;
|
|
13
13
|
const react_1 = require("react");
|
|
14
|
-
const react_redux_1 = require("react-redux");
|
|
15
14
|
const mutate_1 = require("./mutate");
|
|
16
15
|
const utilsAndConstants_1 = require("./utilsAndConstants");
|
|
17
16
|
const useMutation = (cache, actions, selectors, options, abortControllers) => {
|
|
18
17
|
var _a;
|
|
19
18
|
const { mutation: mutationKey, onCompleted, onSuccess, onError } = options;
|
|
20
|
-
const store =
|
|
19
|
+
const store = cache.storeHooks.useStore();
|
|
21
20
|
// Using single useMemo for performance reasons
|
|
22
21
|
const [mutationStateSelector, mutate, abort] = (0, react_1.useMemo)(() => {
|
|
23
22
|
return [
|
|
@@ -53,7 +52,7 @@ const useMutation = (cache, actions, selectors, options, abortControllers) => {
|
|
|
53
52
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
54
53
|
}, [mutationKey, store]);
|
|
55
54
|
// @ts-expect-error fix later
|
|
56
|
-
const mutationState = (_a =
|
|
55
|
+
const mutationState = (_a = cache.storeHooks.useSelector(mutationStateSelector)) !== null && _a !== void 0 ? _a : utilsAndConstants_1.EMPTY_OBJECT;
|
|
57
56
|
cache.options.logsEnabled &&
|
|
58
57
|
(0, utilsAndConstants_1.log)('useMutation', {
|
|
59
58
|
options,
|
package/dist/useQuery.js
CHANGED
|
@@ -11,7 +11,6 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
|
|
|
11
11
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
12
|
exports.useQuerySelectorStateComparer = exports.useQuery = void 0;
|
|
13
13
|
const react_1 = require("react");
|
|
14
|
-
const react_redux_1 = require("react-redux");
|
|
15
14
|
const query_1 = require("./query");
|
|
16
15
|
const utilsAndConstants_1 = require("./utilsAndConstants");
|
|
17
16
|
const useQuery = (cache, actions, selectors, options) => {
|
|
@@ -20,11 +19,11 @@ const useQuery = (cache, actions, selectors, options) => {
|
|
|
20
19
|
const logsEnabled = cache.options.logsEnabled;
|
|
21
20
|
const getCacheKey = (_b = cache.queries[queryKey].getCacheKey) !== null && _b !== void 0 ? _b : (utilsAndConstants_1.defaultGetCacheKey);
|
|
22
21
|
const cacheStateSelector = cache.cacheStateSelector;
|
|
23
|
-
const store =
|
|
22
|
+
const store = cache.storeHooks.useStore();
|
|
24
23
|
// @ts-expect-error fix types later
|
|
25
24
|
const cacheKey = getCacheKey(params);
|
|
26
25
|
/** Fetch query with the new parameters, or refetch with the same if parameters not provided. */
|
|
27
|
-
const
|
|
26
|
+
const performFetch = (0, react_1.useCallback)((options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
28
27
|
const paramsPassed = options && 'params' in options;
|
|
29
28
|
return yield (0, query_1.query)('useQuery.fetch', store, cache, actions, selectors, queryKey,
|
|
30
29
|
// @ts-expect-error fix later
|
|
@@ -36,7 +35,7 @@ const useQuery = (cache, actions, selectors, options) => {
|
|
|
36
35
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
37
36
|
[store, queryKey, cacheKey]);
|
|
38
37
|
/** Query state */
|
|
39
|
-
const queryState = (_c =
|
|
38
|
+
const queryState = (_c = cache.storeHooks.useSelector((state) => {
|
|
40
39
|
const queryState = cacheStateSelector(state).queries[queryKey][cacheKey];
|
|
41
40
|
return queryState; // TODO proper type
|
|
42
41
|
}, (exports.useQuerySelectorStateComparer))) !== null && _c !== void 0 ? _c : utilsAndConstants_1.EMPTY_OBJECT;
|
|
@@ -46,8 +45,9 @@ const useQuery = (cache, actions, selectors, options) => {
|
|
|
46
45
|
return;
|
|
47
46
|
}
|
|
48
47
|
const expired = queryState.expiresAt != null && queryState.expiresAt <= Date.now();
|
|
48
|
+
if (!fetchPolicy(expired,
|
|
49
49
|
// @ts-expect-error params
|
|
50
|
-
|
|
50
|
+
params, queryState, store, selectors)) {
|
|
51
51
|
logsEnabled &&
|
|
52
52
|
(0, utilsAndConstants_1.log)('useQuery.useEffect skip fetch due to fetch policy', {
|
|
53
53
|
queryState,
|
|
@@ -57,7 +57,7 @@ const useQuery = (cache, actions, selectors, options) => {
|
|
|
57
57
|
});
|
|
58
58
|
return;
|
|
59
59
|
}
|
|
60
|
-
|
|
60
|
+
performFetch();
|
|
61
61
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
62
62
|
}, [cacheKey, skipFetch]);
|
|
63
63
|
logsEnabled &&
|
|
@@ -66,7 +66,7 @@ const useQuery = (cache, actions, selectors, options) => {
|
|
|
66
66
|
options,
|
|
67
67
|
queryState,
|
|
68
68
|
});
|
|
69
|
-
return [queryState,
|
|
69
|
+
return [queryState, performFetch];
|
|
70
70
|
};
|
|
71
71
|
exports.useQuery = useQuery;
|
|
72
72
|
/** Omit `expiresAt` from comparison */
|
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.16.0-rc.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",
|
|
@@ -19,12 +19,14 @@
|
|
|
19
19
|
"peerDependencies": {
|
|
20
20
|
"fast-deep-equal": "*",
|
|
21
21
|
"react": "^16",
|
|
22
|
-
"react-redux": "^4"
|
|
23
|
-
"redux": "^4"
|
|
22
|
+
"react-redux": "^4"
|
|
24
23
|
},
|
|
25
24
|
"peerDependenciesMeta": {
|
|
26
25
|
"fast-deep-equal": {
|
|
27
26
|
"optional": true
|
|
27
|
+
},
|
|
28
|
+
"react-redux": {
|
|
29
|
+
"optional": true
|
|
28
30
|
}
|
|
29
31
|
},
|
|
30
32
|
"devDependencies": {
|