react-redux-cache 0.5.0 → 0.6.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 +38 -17
- package/dist/createActions.d.ts +4 -4
- package/dist/createActions.js +4 -4
- package/dist/createCache.d.ts +12 -10
- package/dist/createCache.js +16 -17
- package/dist/index.js +6 -3
- package/dist/reducer.d.ts +2 -2
- package/dist/reducer.js +45 -21
- package/dist/types.d.ts +12 -5
- package/dist/useQuery.d.ts +3 -1
- package/dist/useQuery.js +10 -10
- package/dist/utilsAndConstants.d.ts +3 -1
- package/dist/utilsAndConstants.js +39 -8
- package/package.json +12 -6
package/README.md
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
<b>DOGE:</b> D7GMQdKhKC9ymbT9PtcetSFTQjyPRRfkwT <br>
|
|
8
8
|
</details>
|
|
9
9
|
|
|
10
|
-
# react-redux-cache
|
|
10
|
+
# react-redux-cache (RRC)
|
|
11
11
|
|
|
12
12
|
**Powerful** yet **lightweight** data fetching and caching library that supports **normalization** unlike `react-query` and `rtk-query`, while having similar but very simple interface. Built on top of `redux`, covered with tests, fully typed and written on Typescript.
|
|
13
13
|
|
|
@@ -122,15 +122,17 @@ Examples of states, generated by cache reducer from `/example` project:
|
|
|
122
122
|
- [api.ts](https://github.com/gentlee/react-redux-cache#apits)
|
|
123
123
|
- [Usage](https://github.com/gentlee/react-redux-cache#usage)
|
|
124
124
|
- [Advanced](https://github.com/gentlee/react-redux-cache#advanced)
|
|
125
|
-
- [
|
|
125
|
+
- [Extended cache policy](https://github.com/gentlee/react-redux-cache#extended-cache-policy)
|
|
126
126
|
- [Infinite scroll pagination](https://github.com/gentlee/react-redux-cache#infinite-scroll-pagination)
|
|
127
127
|
- [redux-persist](https://github.com/gentlee/react-redux-cache#redux-persist)
|
|
128
128
|
- [FAQ](https://github.com/gentlee/react-redux-cache#faq)
|
|
129
129
|
- [What is a query cache key?](https://github.com/gentlee/react-redux-cache#what-is-a-query-cache-key)
|
|
130
|
-
- [How
|
|
130
|
+
- [How race conditions are handled?](https://github.com/gentlee/react-redux-cache#how-race-conditions-are-handled)
|
|
131
131
|
|
|
132
132
|
### Installation
|
|
133
133
|
`react`, `redux` and `react-redux` are peer dependencies.
|
|
134
|
+
|
|
135
|
+
`fast-deep-equal` is an optional peer dependency if `deepComparisonEnabled` cache option is enabled (default is true).
|
|
134
136
|
```sh
|
|
135
137
|
npm add react-redux-cache react redux react-redux
|
|
136
138
|
```
|
|
@@ -146,7 +148,7 @@ export const {
|
|
|
146
148
|
} = createCache({
|
|
147
149
|
// Used as prefix for actions and in default cacheStateSelector for selecting cache state from redux state.
|
|
148
150
|
name: 'cache',
|
|
149
|
-
//
|
|
151
|
+
// Mapping of all typenames to their entity types, which is needed for proper normalization. Should be empty if normalization is not needed.
|
|
150
152
|
// Empty objects with type casting can be used as values.
|
|
151
153
|
typenames: {
|
|
152
154
|
users: {} as User, // here `users` entities will have type `User`
|
|
@@ -162,6 +164,24 @@ export const {
|
|
|
162
164
|
},
|
|
163
165
|
})
|
|
164
166
|
```
|
|
167
|
+
|
|
168
|
+
For normalization two things are required:
|
|
169
|
+
- Set proper typenames while creating the cache - mapping of all entities and their corresponding TS types.
|
|
170
|
+
- Return an object from queries and mutations, that contains the following fields (besides `result`):
|
|
171
|
+
|
|
172
|
+
```typescript
|
|
173
|
+
type EntityChanges<T extends Typenames> = {
|
|
174
|
+
/** Entities that will be merged with existing. */
|
|
175
|
+
merge?: PartialEntitiesMap<T>
|
|
176
|
+
/** Entities that will replace existing. */
|
|
177
|
+
replace?: Partial<EntitiesMap<T>>
|
|
178
|
+
/** Ids of entities that will be removed. */
|
|
179
|
+
remove?: EntityIds<T>
|
|
180
|
+
/** Alias for `merge` to support normalizr. */
|
|
181
|
+
entities?: EntityChanges<T>['merge']
|
|
182
|
+
}
|
|
183
|
+
```
|
|
184
|
+
|
|
165
185
|
#### store.ts
|
|
166
186
|
```typescript
|
|
167
187
|
// Create store as usual, passing the new cache reducer under the name of the cache.
|
|
@@ -248,31 +268,33 @@ export const UserScreen = () => {
|
|
|
248
268
|
|
|
249
269
|
### Advanced
|
|
250
270
|
|
|
251
|
-
####
|
|
271
|
+
#### Extended cache policy
|
|
252
272
|
|
|
253
273
|
`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:
|
|
254
274
|
|
|
255
275
|
```typescript
|
|
256
276
|
export const UserScreen = () => {
|
|
277
|
+
...
|
|
278
|
+
|
|
257
279
|
const user = useSelectEntityById(userId, 'users')
|
|
258
280
|
|
|
259
281
|
const [{loading, error}] = useQuery({
|
|
260
282
|
query: 'getUser',
|
|
261
283
|
params: userId,
|
|
262
|
-
skip: !!user //
|
|
284
|
+
skip: !!user // skip fetching if we already have user cached by some other query, e.g. getUsers
|
|
263
285
|
})
|
|
264
286
|
|
|
265
287
|
...
|
|
266
288
|
}
|
|
267
289
|
```
|
|
268
290
|
|
|
269
|
-
We can
|
|
291
|
+
We can additionally check that entity is full or "fresh" enough:
|
|
270
292
|
|
|
271
293
|
```typescript
|
|
272
|
-
|
|
294
|
+
skip: !!user && isFullUser(user)
|
|
273
295
|
```
|
|
274
296
|
|
|
275
|
-
|
|
297
|
+
Another approach is to set `skip: true` and manually run `fetch` when needed:
|
|
276
298
|
|
|
277
299
|
```typescript
|
|
278
300
|
export const UserScreen = () => {
|
|
@@ -289,6 +311,7 @@ export const UserScreen = () => {
|
|
|
289
311
|
fetchUser()
|
|
290
312
|
}
|
|
291
313
|
}, [screenIsVisible])
|
|
314
|
+
|
|
292
315
|
...
|
|
293
316
|
}
|
|
294
317
|
```
|
|
@@ -327,9 +350,7 @@ Here is an example of `getUsers` query configuration with pagination support. Yo
|
|
|
327
350
|
// Component
|
|
328
351
|
|
|
329
352
|
export const GetUsersScreen = () => {
|
|
330
|
-
const {
|
|
331
|
-
|
|
332
|
-
const [{result: usersResult, loading, error, params}, refetch] = useQuery({
|
|
353
|
+
const [{result: usersResult, loading, error, params}, fetchUsers] = useQuery({
|
|
333
354
|
query: 'getUsers',
|
|
334
355
|
params: 1 // page
|
|
335
356
|
})
|
|
@@ -339,7 +360,7 @@ export const GetUsersScreen = () => {
|
|
|
339
360
|
|
|
340
361
|
const onLoadNextPage = () => {
|
|
341
362
|
const lastLoadedPage = usersResult?.page ?? 0
|
|
342
|
-
|
|
363
|
+
fetchUsers({
|
|
343
364
|
query: 'getUsers',
|
|
344
365
|
params: lastLoadedPage + 1,
|
|
345
366
|
})
|
|
@@ -355,7 +376,7 @@ export const GetUsersScreen = () => {
|
|
|
355
376
|
<div>
|
|
356
377
|
{refreshing && <div className="spinner" />}
|
|
357
378
|
{usersResult?.items.map(renderUser)}
|
|
358
|
-
<button onClick={
|
|
379
|
+
<button onClick={() => fetchUsers()}>Refresh</button>
|
|
359
380
|
{loadingNextPage ? (
|
|
360
381
|
<div className="spinner" />
|
|
361
382
|
) : (
|
|
@@ -414,8 +435,8 @@ It is recommended to override it when default implementation is not optimal or w
|
|
|
414
435
|
|
|
415
436
|
As example, can be overriden when implementing pagination.
|
|
416
437
|
|
|
417
|
-
#### How
|
|
438
|
+
#### How race conditions are handled?
|
|
418
439
|
|
|
419
|
-
**Queries:**
|
|
440
|
+
**Queries:** Queries are throttled: query with the same cache key (generated from params by default) is cancelled if already running.
|
|
420
441
|
|
|
421
|
-
**Mutations:**
|
|
442
|
+
**Mutations:** Mutations are debounced: previous similar mutation is aborted if it was running when the new one started. Second argument in mutations is `AbortSignal`, which can be used e.g. for cancelling http requests.
|
package/dist/createActions.d.ts
CHANGED
|
@@ -3,22 +3,22 @@ export type ActionMap<N extends string, T extends Typenames, QP, QR, MP, MR> = R
|
|
|
3
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 QP & keyof QR>(queryKey: K, queryCacheKey: Key, state?: Partial<QueryMutationState<QP[K], QR[K]>> | undefined,
|
|
6
|
+
<K extends keyof QP & keyof QR>(queryKey: K, queryCacheKey: Key, state?: Partial<QueryMutationState<QP[K], QR[K]>> | undefined, entityChanges?: EntityChanges<T> | undefined): {
|
|
7
7
|
type: `@rrc/${N}/updateQueryStateAndEntities`;
|
|
8
8
|
queryKey: K;
|
|
9
9
|
queryCacheKey: Key;
|
|
10
10
|
state: Partial<QueryMutationState<QP[K], QR[K]>> | undefined;
|
|
11
|
-
|
|
11
|
+
entityChanges: 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 MP & keyof MR>(mutationKey: K_1, state?: Partial<QueryMutationState<MP[K_1], MR[K_1]>> | undefined,
|
|
17
|
+
<K_1 extends keyof MP & keyof MR>(mutationKey: K_1, state?: Partial<QueryMutationState<MP[K_1], MR[K_1]>> | undefined, entityChanges?: EntityChanges<T> | undefined): {
|
|
18
18
|
type: `@rrc/${N}/updateMutationStateAndEntities`;
|
|
19
19
|
mutationKey: K_1;
|
|
20
20
|
state: Partial<QueryMutationState<MP[K_1], MR[K_1]>> | undefined;
|
|
21
|
-
|
|
21
|
+
entityChanges: EntityChanges<T> | undefined;
|
|
22
22
|
};
|
|
23
23
|
type: `@rrc/${N}/updateMutationStateAndEntities`;
|
|
24
24
|
};
|
package/dist/createActions.js
CHANGED
|
@@ -5,20 +5,20 @@ const utilsAndConstants_1 = require("./utilsAndConstants");
|
|
|
5
5
|
const createActions = (name) => {
|
|
6
6
|
const actionPrefix = `@${utilsAndConstants_1.PACKAGE_SHORT_NAME}/${name}/`;
|
|
7
7
|
const updateQueryStateAndEntitiesType = `${actionPrefix}updateQueryStateAndEntities`;
|
|
8
|
-
const updateQueryStateAndEntities = (queryKey, queryCacheKey, state,
|
|
8
|
+
const updateQueryStateAndEntities = (queryKey, queryCacheKey, state, entityChanges) => ({
|
|
9
9
|
type: updateQueryStateAndEntitiesType,
|
|
10
10
|
queryKey,
|
|
11
11
|
queryCacheKey,
|
|
12
12
|
state,
|
|
13
|
-
|
|
13
|
+
entityChanges,
|
|
14
14
|
});
|
|
15
15
|
updateQueryStateAndEntities.type = updateQueryStateAndEntitiesType;
|
|
16
16
|
const updateMutationStateAndEntitiesType = `${actionPrefix}updateMutationStateAndEntities`;
|
|
17
|
-
const updateMutationStateAndEntities = (mutationKey, state,
|
|
17
|
+
const updateMutationStateAndEntities = (mutationKey, state, entityChanges) => ({
|
|
18
18
|
type: updateMutationStateAndEntitiesType,
|
|
19
19
|
mutationKey,
|
|
20
20
|
state,
|
|
21
|
-
|
|
21
|
+
entityChanges,
|
|
22
22
|
});
|
|
23
23
|
updateMutationStateAndEntities.type = updateMutationStateAndEntitiesType;
|
|
24
24
|
const mergeEntityChangesType = `${actionPrefix}mergeEntityChanges`;
|
package/dist/createCache.d.ts
CHANGED
|
@@ -18,12 +18,12 @@ export declare const createCache: <N extends string, T extends Typenames, QP, QR
|
|
|
18
18
|
queryKey: keyof QP & keyof QR;
|
|
19
19
|
queryCacheKey: Key;
|
|
20
20
|
state: Partial<QueryMutationState<QP[keyof QP & keyof QR], QR[keyof QP & keyof QR]>> | undefined;
|
|
21
|
-
|
|
21
|
+
entityChanges: import("./types").EntityChanges<T> | undefined;
|
|
22
22
|
} | {
|
|
23
23
|
type: `@rrc/${N}/updateMutationStateAndEntities`;
|
|
24
24
|
mutationKey: keyof MP & keyof MR;
|
|
25
25
|
state: Partial<QueryMutationState<MP[keyof MP & keyof MR], MR[keyof MP & keyof MR]>> | undefined;
|
|
26
|
-
|
|
26
|
+
entityChanges: import("./types").EntityChanges<T> | undefined;
|
|
27
27
|
} | {
|
|
28
28
|
type: `@rrc/${N}/mergeEntityChanges`;
|
|
29
29
|
changes: import("./types").EntityChanges<T>;
|
|
@@ -43,21 +43,21 @@ export declare const createCache: <N extends string, T extends Typenames, QP, QR
|
|
|
43
43
|
};
|
|
44
44
|
actions: {
|
|
45
45
|
updateQueryStateAndEntities: {
|
|
46
|
-
<K extends keyof QP & keyof QR>(queryKey: K, queryCacheKey: Key, state?: Partial<QueryMutationState<QP[K], QR[K]>> | undefined,
|
|
46
|
+
<K extends keyof QP & keyof QR>(queryKey: K, queryCacheKey: Key, state?: Partial<QueryMutationState<QP[K], QR[K]>> | undefined, entityChanges?: import("./types").EntityChanges<T> | undefined): {
|
|
47
47
|
type: `@rrc/${N}/updateQueryStateAndEntities`;
|
|
48
48
|
queryKey: K;
|
|
49
49
|
queryCacheKey: Key;
|
|
50
50
|
state: Partial<QueryMutationState<QP[K], QR[K]>> | undefined;
|
|
51
|
-
|
|
51
|
+
entityChanges: import("./types").EntityChanges<T> | undefined;
|
|
52
52
|
};
|
|
53
53
|
type: `@rrc/${N}/updateQueryStateAndEntities`;
|
|
54
54
|
};
|
|
55
55
|
updateMutationStateAndEntities: {
|
|
56
|
-
<K_1 extends keyof MP & keyof MR>(mutationKey: K_1, state?: Partial<QueryMutationState<MP[K_1], MR[K_1]>> | undefined,
|
|
56
|
+
<K_1 extends keyof MP & keyof MR>(mutationKey: K_1, state?: Partial<QueryMutationState<MP[K_1], MR[K_1]>> | undefined, entityChanges?: import("./types").EntityChanges<T> | undefined): {
|
|
57
57
|
type: `@rrc/${N}/updateMutationStateAndEntities`;
|
|
58
58
|
mutationKey: K_1;
|
|
59
59
|
state: Partial<QueryMutationState<MP[K_1], MR[K_1]>> | undefined;
|
|
60
|
-
|
|
60
|
+
entityChanges: import("./types").EntityChanges<T> | undefined;
|
|
61
61
|
};
|
|
62
62
|
type: `@rrc/${N}/updateMutationStateAndEntities`;
|
|
63
63
|
};
|
|
@@ -91,11 +91,11 @@ 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 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
|
|
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>;
|
|
95
95
|
/** Selects query latest result. */
|
|
96
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 QP | keyof QR>(state: unknown, query: QK_3, cacheKey: Key) => boolean
|
|
98
|
+
selectQueryLoading: <QK_3 extends keyof QP | keyof QR>(state: unknown, query: QK_3, cacheKey: Key) => boolean;
|
|
99
99
|
/** Selects query latest error. */
|
|
100
100
|
selectQueryError: <QK_4 extends keyof QP | keyof QR>(state: unknown, query: QK_4, cacheKey: Key) => Error | undefined;
|
|
101
101
|
/** Selects query latest params. */
|
|
@@ -109,7 +109,7 @@ export declare const createCache: <N extends string, T extends Typenames, QP, QR
|
|
|
109
109
|
/** Selects mutation latest error. */
|
|
110
110
|
selectMutationError: <MK_4 extends keyof MP | keyof MR>(state: unknown, mutation: MK_4) => Error | undefined;
|
|
111
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;
|
|
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) | undefined;
|
|
113
113
|
/** Selects entity by id and typename. */
|
|
114
114
|
selectEntityById: <TN extends keyof T>(state: unknown, id: Key | null | undefined, typename: TN) => T[TN] | undefined;
|
|
115
115
|
/** Selects all entities. */
|
|
@@ -127,7 +127,9 @@ export declare const createCache: <N extends string, T extends Typenames, QP, QR
|
|
|
127
127
|
}) => Promise<MutationResult<MK_6 extends keyof MP & keyof MR ? MR[MK_6] : never>>;
|
|
128
128
|
};
|
|
129
129
|
/** Fetches query when params change and subscribes to query state. */
|
|
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>, (
|
|
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>, (options?: {
|
|
131
|
+
params: QK_7 extends keyof QP & keyof QR ? QP[QK_7] : never;
|
|
132
|
+
} | undefined) => 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>>];
|
|
131
133
|
/** Subscribes to provided mutation state and provides mutate function. */
|
|
132
134
|
useMutation: <MK_7 extends keyof MP | keyof MR>(options: {
|
|
133
135
|
mutation: MK_7;
|
package/dist/createCache.js
CHANGED
|
@@ -14,17 +14,18 @@ const utilsAndConstants_1 = require("./utilsAndConstants");
|
|
|
14
14
|
* Creates reducer, actions and hooks for managing queries and mutations through redux cache.
|
|
15
15
|
*/
|
|
16
16
|
const createCache = (partialCache) => {
|
|
17
|
-
var _a, _b, _c, _d, _e, _f;
|
|
18
|
-
var
|
|
17
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
18
|
+
var _h, _j, _k;
|
|
19
19
|
const abortControllers = new WeakMap();
|
|
20
20
|
// provide all optional fields
|
|
21
21
|
(_a = partialCache.options) !== null && _a !== void 0 ? _a : (partialCache.options = {});
|
|
22
|
-
(_b = (
|
|
23
|
-
(_c = (
|
|
24
|
-
(_d = partialCache.
|
|
25
|
-
(_e = partialCache.
|
|
22
|
+
(_b = (_h = partialCache.options).logsEnabled) !== null && _b !== void 0 ? _b : (_h.logsEnabled = false);
|
|
23
|
+
(_c = (_j = partialCache.options).validateFunctionArguments) !== null && _c !== void 0 ? _c : (_j.validateFunctionArguments = utilsAndConstants_1.IS_DEV);
|
|
24
|
+
(_d = (_k = partialCache.options).deepComparisonEnabled) !== null && _d !== void 0 ? _d : (_k.deepComparisonEnabled = true);
|
|
25
|
+
(_e = partialCache.queries) !== null && _e !== void 0 ? _e : (partialCache.queries = {});
|
|
26
|
+
(_f = partialCache.mutations) !== null && _f !== void 0 ? _f : (partialCache.mutations = {});
|
|
26
27
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
27
|
-
(
|
|
28
|
+
(_g = partialCache.cacheStateSelector) !== null && _g !== void 0 ? _g : (partialCache.cacheStateSelector = (state) => state[cache.name]);
|
|
28
29
|
// @ts-expect-error private field for testing
|
|
29
30
|
partialCache.abortControllers = abortControllers;
|
|
30
31
|
const cache = partialCache;
|
|
@@ -33,12 +34,14 @@ const createCache = (partialCache) => {
|
|
|
33
34
|
return id == null ? undefined : cache.cacheStateSelector(state).entities[typename][id];
|
|
34
35
|
};
|
|
35
36
|
const selectQueryState = (state, query, cacheKey) => {
|
|
37
|
+
var _a;
|
|
36
38
|
// @ts-expect-error fix later
|
|
37
|
-
return cache.cacheStateSelector(state).queries[query][cacheKey];
|
|
39
|
+
return (_a = cache.cacheStateSelector(state).queries[query][cacheKey]) !== null && _a !== void 0 ? _a : utilsAndConstants_1.DEFAULT_QUERY_MUTATION_STATE;
|
|
38
40
|
};
|
|
39
41
|
const selectMutationState = (state, mutation) => {
|
|
42
|
+
var _a;
|
|
40
43
|
// @ts-expect-error fix later
|
|
41
|
-
return cache.cacheStateSelector(state).mutations[mutation];
|
|
44
|
+
return (_a = cache.cacheStateSelector(state).mutations[mutation]) !== null && _a !== void 0 ? _a : utilsAndConstants_1.DEFAULT_QUERY_MUTATION_STATE;
|
|
42
45
|
};
|
|
43
46
|
const actions = (0, createActions_1.createActions)(cache.name);
|
|
44
47
|
return {
|
|
@@ -52,23 +55,19 @@ const createCache = (partialCache) => {
|
|
|
52
55
|
selectQueryState,
|
|
53
56
|
/** Selects query latest result. */
|
|
54
57
|
selectQueryResult: (state, query, cacheKey) => {
|
|
55
|
-
|
|
56
|
-
return (_a = selectQueryState(state, query, cacheKey)) === null || _a === void 0 ? void 0 : _a.result;
|
|
58
|
+
return selectQueryState(state, query, cacheKey).result;
|
|
57
59
|
},
|
|
58
60
|
/** Selects query loading state. */
|
|
59
61
|
selectQueryLoading: (state, query, cacheKey) => {
|
|
60
|
-
|
|
61
|
-
return (_a = selectQueryState(state, query, cacheKey)) === null || _a === void 0 ? void 0 : _a.loading;
|
|
62
|
+
return selectQueryState(state, query, cacheKey).loading;
|
|
62
63
|
},
|
|
63
64
|
/** Selects query latest error. */
|
|
64
65
|
selectQueryError: (state, query, cacheKey) => {
|
|
65
|
-
|
|
66
|
-
return (_a = selectQueryState(state, query, cacheKey)) === null || _a === void 0 ? void 0 : _a.error;
|
|
66
|
+
return selectQueryState(state, query, cacheKey).error;
|
|
67
67
|
},
|
|
68
68
|
/** Selects query latest params. */
|
|
69
69
|
selectQueryParams: (state, query, cacheKey) => {
|
|
70
|
-
|
|
71
|
-
return (_a = selectQueryState(state, query, cacheKey)) === null || _a === void 0 ? void 0 : _a.params;
|
|
70
|
+
return selectQueryState(state, query, cacheKey).params;
|
|
72
71
|
},
|
|
73
72
|
/** Selects mutation state. */
|
|
74
73
|
selectMutationState,
|
package/dist/index.js
CHANGED
|
@@ -23,11 +23,14 @@ 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
|
-
// useQuery refresh with params use as client.query?
|
|
27
|
-
// update readme with how to use mergeResults for invalidating / updating caches?
|
|
28
26
|
// optimistic response
|
|
29
|
-
//
|
|
27
|
+
// type extractors?
|
|
28
|
+
// skip -> enabled?
|
|
29
|
+
// add full api docs
|
|
30
|
+
// update readme with how to use mergeResults for invalidating / updating caches?
|
|
31
|
+
// make query key / cache key difference more clear in the docs, and/or rename queryKey -> query?
|
|
30
32
|
// ! medium
|
|
33
|
+
// check type of function arguments in dev
|
|
31
34
|
// allow multiple mutation with same keys?
|
|
32
35
|
// type extractors from cache
|
|
33
36
|
// custom useStore
|
package/dist/reducer.d.ts
CHANGED
|
@@ -10,12 +10,12 @@ export declare const createCacheReducer: <N extends string, T extends Typenames,
|
|
|
10
10
|
queryKey: keyof QP & keyof QR;
|
|
11
11
|
queryCacheKey: import("./types").Key;
|
|
12
12
|
state: Partial<QueryMutationState<QP[keyof QP & keyof QR], QR[keyof QP & keyof QR]>> | undefined;
|
|
13
|
-
|
|
13
|
+
entityChanges: import("./types").EntityChanges<T> | undefined;
|
|
14
14
|
} | {
|
|
15
15
|
type: `@rrc/${N}/updateMutationStateAndEntities`;
|
|
16
16
|
mutationKey: keyof MP & keyof MR;
|
|
17
17
|
state: Partial<QueryMutationState<MP[keyof MP & keyof MR], MR[keyof MP & keyof MR]>> | undefined;
|
|
18
|
-
|
|
18
|
+
entityChanges: import("./types").EntityChanges<T> | undefined;
|
|
19
19
|
} | {
|
|
20
20
|
type: `@rrc/${N}/mergeEntityChanges`;
|
|
21
21
|
changes: import("./types").EntityChanges<T>;
|
package/dist/reducer.js
CHANGED
|
@@ -24,24 +24,47 @@ const createCacheReducer = (actions, typenames, queryKeys, cacheOptions) => {
|
|
|
24
24
|
queryKeys,
|
|
25
25
|
initialState,
|
|
26
26
|
});
|
|
27
|
+
const deepEqual = cacheOptions.deepComparisonEnabled ? utilsAndConstants_1.optionalUtils.deepEqual : undefined;
|
|
27
28
|
return (state = initialState, action) => {
|
|
28
29
|
var _a, _b;
|
|
29
30
|
switch (action.type) {
|
|
30
31
|
case actions.updateQueryStateAndEntities.type: {
|
|
31
|
-
const { queryKey, queryCacheKey, state: queryState,
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
const { queryKey, queryCacheKey, state: queryState, entityChanges, } = action;
|
|
33
|
+
const oldQueryState = (_a = state.queries[queryKey][queryCacheKey]) !== null && _a !== void 0 ? _a : utilsAndConstants_1.DEFAULT_QUERY_MUTATION_STATE;
|
|
34
|
+
let newQueryState = queryState && Object.assign(Object.assign({}, oldQueryState), queryState);
|
|
35
|
+
if (deepEqual === null || deepEqual === void 0 ? void 0 : deepEqual(oldQueryState, newQueryState)) {
|
|
36
|
+
newQueryState = undefined;
|
|
37
|
+
}
|
|
38
|
+
const newEntities = entityChanges && (0, utilsAndConstants_1.applyEntityChanges)(state.entities, entityChanges, cacheOptions);
|
|
39
|
+
let newState;
|
|
40
|
+
if (newEntities) {
|
|
41
|
+
newState !== null && newState !== void 0 ? newState : (newState = Object.assign({}, state));
|
|
42
|
+
newState.entities = newEntities;
|
|
43
|
+
}
|
|
44
|
+
if (newQueryState) {
|
|
45
|
+
newState !== null && newState !== void 0 ? newState : (newState = Object.assign({}, state));
|
|
46
|
+
newState.queries = Object.assign(Object.assign({}, state.queries), { [queryKey]: Object.assign(Object.assign({}, state.queries[queryKey]), { [queryCacheKey]: newQueryState }) });
|
|
35
47
|
}
|
|
36
|
-
return
|
|
48
|
+
return newState !== null && newState !== void 0 ? newState : state;
|
|
37
49
|
}
|
|
38
50
|
case actions.updateMutationStateAndEntities.type: {
|
|
39
|
-
const { mutationKey, state: mutationState,
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
51
|
+
const { mutationKey, state: mutationState, entityChanges, } = action;
|
|
52
|
+
const oldMutationState = (_b = state.mutations[mutationKey]) !== null && _b !== void 0 ? _b : utilsAndConstants_1.DEFAULT_QUERY_MUTATION_STATE;
|
|
53
|
+
let newMutationState = mutationState && Object.assign(Object.assign({}, oldMutationState), mutationState);
|
|
54
|
+
if (deepEqual === null || deepEqual === void 0 ? void 0 : deepEqual(oldMutationState, newMutationState)) {
|
|
55
|
+
newMutationState = undefined;
|
|
56
|
+
}
|
|
57
|
+
const newEntities = entityChanges && (0, utilsAndConstants_1.applyEntityChanges)(state.entities, entityChanges, cacheOptions);
|
|
58
|
+
let newState;
|
|
59
|
+
if (newEntities) {
|
|
60
|
+
newState !== null && newState !== void 0 ? newState : (newState = Object.assign({}, state));
|
|
61
|
+
newState.entities = newEntities;
|
|
43
62
|
}
|
|
44
|
-
|
|
63
|
+
if (newMutationState) {
|
|
64
|
+
newState !== null && newState !== void 0 ? newState : (newState = Object.assign({}, state));
|
|
65
|
+
newState.mutations = Object.assign(Object.assign({}, state.mutations), { [mutationKey]: newMutationState });
|
|
66
|
+
}
|
|
67
|
+
return newState !== null && newState !== void 0 ? newState : state;
|
|
45
68
|
}
|
|
46
69
|
case actions.mergeEntityChanges.type: {
|
|
47
70
|
const { changes } = action;
|
|
@@ -55,22 +78,24 @@ const createCacheReducer = (actions, typenames, queryKeys, cacheOptions) => {
|
|
|
55
78
|
}
|
|
56
79
|
let newQueries = undefined;
|
|
57
80
|
for (const query of queryKeysToClear) {
|
|
81
|
+
const queryState = (newQueries !== null && newQueries !== void 0 ? newQueries : state.queries)[query.key];
|
|
58
82
|
if (query.cacheKey != null) {
|
|
59
|
-
if (
|
|
83
|
+
if (queryState[query.cacheKey]) {
|
|
60
84
|
newQueries !== null && newQueries !== void 0 ? newQueries : (newQueries = Object.assign({}, state.queries));
|
|
61
|
-
|
|
85
|
+
if (state.queries[query.key] === newQueries[query.key]) {
|
|
86
|
+
newQueries[query.key] = Object.assign({}, newQueries[query.key]);
|
|
87
|
+
}
|
|
62
88
|
delete newQueries[query.key][query.cacheKey];
|
|
63
89
|
}
|
|
64
90
|
}
|
|
65
|
-
else if (
|
|
91
|
+
else if (queryState !== EMPTY_QUERY_STATE) {
|
|
66
92
|
newQueries !== null && newQueries !== void 0 ? newQueries : (newQueries = Object.assign({}, state.queries));
|
|
67
93
|
newQueries[query.key] = EMPTY_QUERY_STATE;
|
|
68
94
|
}
|
|
69
95
|
}
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
return Object.assign(Object.assign({}, state), { queries: newQueries });
|
|
96
|
+
return !newQueries
|
|
97
|
+
? state
|
|
98
|
+
: Object.assign(Object.assign({}, state), { queries: newQueries });
|
|
74
99
|
}
|
|
75
100
|
case actions.clearMutationState.type: {
|
|
76
101
|
const { mutationKeys } = action;
|
|
@@ -84,10 +109,9 @@ const createCacheReducer = (actions, typenames, queryKeys, cacheOptions) => {
|
|
|
84
109
|
delete newMutations[mutation];
|
|
85
110
|
}
|
|
86
111
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
return Object.assign(Object.assign({}, state), { mutations: newMutations });
|
|
112
|
+
return !newMutations
|
|
113
|
+
? state
|
|
114
|
+
: Object.assign(Object.assign({}, state), { mutations: newMutations });
|
|
91
115
|
}
|
|
92
116
|
}
|
|
93
117
|
return state;
|
package/dist/types.d.ts
CHANGED
|
@@ -22,7 +22,7 @@ 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
24
|
/**
|
|
25
|
-
* Mapping of all typenames to their entity types, which is needed for proper normalization.
|
|
25
|
+
* Mapping of all typenames to their entity types, which is needed for proper normalization. Should be empty if normalization is not needed.
|
|
26
26
|
* @key Typename.
|
|
27
27
|
* @value Object with proper type of the typename. Empty objects with type casting can be used.
|
|
28
28
|
* @example
|
|
@@ -44,14 +44,21 @@ export type Cache<N extends string, T extends Typenames, QP, QR, MP, MR> = {
|
|
|
44
44
|
export type CacheOptions = {
|
|
45
45
|
/**
|
|
46
46
|
* Enables validation of package function arguments. Recommened to enable in dev/testing mode.
|
|
47
|
-
*
|
|
47
|
+
* @default true in dev mode.
|
|
48
48
|
* */
|
|
49
49
|
validateFunctionArguments: boolean;
|
|
50
50
|
/**
|
|
51
|
-
*
|
|
52
|
-
*
|
|
51
|
+
* Enables console logs.
|
|
52
|
+
* @default false
|
|
53
53
|
*/
|
|
54
54
|
logsEnabled: boolean;
|
|
55
|
+
/**
|
|
56
|
+
* Enables deep comparison before merging entities to the state.
|
|
57
|
+
* Re-rendering is a heavier operation than comparison, so disabling it can lead to performance drop.
|
|
58
|
+
* Makes sense to disable only if merging equal results & entities to the state is a rare case.
|
|
59
|
+
* @default true
|
|
60
|
+
*/
|
|
61
|
+
deepComparisonEnabled: boolean;
|
|
55
62
|
};
|
|
56
63
|
export type PartialEntitiesMap<T extends Typenames> = {
|
|
57
64
|
[K in keyof T]?: Dict<Partial<T[K]>>;
|
|
@@ -122,5 +129,5 @@ export type QueryMutationState<P, R> = {
|
|
|
122
129
|
/** Error of the latest response. */
|
|
123
130
|
error?: Error;
|
|
124
131
|
/** Parameters of the latest request. */
|
|
125
|
-
params
|
|
132
|
+
params?: P;
|
|
126
133
|
};
|
package/dist/useQuery.d.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
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, 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>, (
|
|
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>, (options?: {
|
|
4
|
+
params: QK extends keyof QP & keyof QR ? QP[QK] : never;
|
|
5
|
+
} | undefined) => 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
|
@@ -23,10 +23,15 @@ const useQuery = (cache, actions, options) => {
|
|
|
23
23
|
const store = (0, react_redux_1.useStore)();
|
|
24
24
|
// @ts-expect-error fix types later
|
|
25
25
|
const cacheKey = getCacheKey(params);
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
26
|
+
/** Fetch query with the new parameters, or refetch with the same if parameters not provided. */
|
|
27
|
+
const fetch = (0, react_1.useCallback)((options) => __awaiter(void 0, void 0, void 0, function* () {
|
|
28
|
+
return yield (0, query_1.query)('useQuery.fetch', store, cache, actions, queryKey,
|
|
29
|
+
// @ts-expect-error fix later
|
|
30
|
+
options ? getCacheKey(options.params) : cacheKey, options ? options.params : params);
|
|
31
|
+
}),
|
|
32
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
33
|
+
[store, queryKey, cacheKey]);
|
|
34
|
+
/** Query state */
|
|
30
35
|
const queryState = (_c = (0, react_redux_1.useSelector)((state) => {
|
|
31
36
|
const queryState = cacheStateSelector(state).queries[queryKey][cacheKey];
|
|
32
37
|
return queryState; // TODO proper type
|
|
@@ -53,11 +58,6 @@ const useQuery = (cache, actions, options) => {
|
|
|
53
58
|
options,
|
|
54
59
|
queryState,
|
|
55
60
|
});
|
|
56
|
-
return [
|
|
57
|
-
/** Query state */
|
|
58
|
-
queryState,
|
|
59
|
-
/** Refetch query with the same parameters */
|
|
60
|
-
fetch,
|
|
61
|
-
];
|
|
61
|
+
return [queryState, fetch];
|
|
62
62
|
};
|
|
63
63
|
exports.useQuery = useQuery;
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import type { CacheOptions, EntitiesMap, EntityChanges, Key, Typenames } from './types';
|
|
2
2
|
export declare const PACKAGE_SHORT_NAME = "rrc";
|
|
3
|
+
export declare const optionalUtils: {
|
|
4
|
+
deepEqual?: (a: any, b: any) => boolean;
|
|
5
|
+
};
|
|
3
6
|
export declare const IS_DEV: boolean;
|
|
4
7
|
export declare const DEFAULT_QUERY_MUTATION_STATE: {
|
|
5
8
|
readonly loading: false;
|
|
6
|
-
readonly error: undefined;
|
|
7
9
|
};
|
|
8
10
|
export declare const defaultGetCacheKey: <P = unknown>(params: P) => Key;
|
|
9
11
|
export declare const log: (tag: string, data?: unknown) => void;
|
|
@@ -1,7 +1,16 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.applyEntityChanges = exports.log = exports.defaultGetCacheKey = exports.DEFAULT_QUERY_MUTATION_STATE = exports.IS_DEV = exports.PACKAGE_SHORT_NAME = void 0;
|
|
3
|
+
exports.applyEntityChanges = exports.log = exports.defaultGetCacheKey = exports.DEFAULT_QUERY_MUTATION_STATE = exports.IS_DEV = exports.optionalUtils = exports.PACKAGE_SHORT_NAME = void 0;
|
|
4
4
|
exports.PACKAGE_SHORT_NAME = 'rrc';
|
|
5
|
+
exports.optionalUtils = {
|
|
6
|
+
deepEqual: undefined,
|
|
7
|
+
};
|
|
8
|
+
try {
|
|
9
|
+
exports.optionalUtils.deepEqual = require('fast-deep-equal/es6');
|
|
10
|
+
}
|
|
11
|
+
catch (_a) {
|
|
12
|
+
console.debug(exports.PACKAGE_SHORT_NAME + ': fast-deep-equal optional dependency was not installed');
|
|
13
|
+
}
|
|
5
14
|
exports.IS_DEV = (() => {
|
|
6
15
|
try {
|
|
7
16
|
// @ts-expect-error __DEV__ is only for React Native
|
|
@@ -11,7 +20,7 @@ exports.IS_DEV = (() => {
|
|
|
11
20
|
return process.env.NODE_ENV === 'development';
|
|
12
21
|
}
|
|
13
22
|
})();
|
|
14
|
-
exports.DEFAULT_QUERY_MUTATION_STATE = { loading: false
|
|
23
|
+
exports.DEFAULT_QUERY_MUTATION_STATE = { loading: false };
|
|
15
24
|
const defaultGetCacheKey = (params) => {
|
|
16
25
|
switch (typeof params) {
|
|
17
26
|
case 'string':
|
|
@@ -40,6 +49,7 @@ const applyEntityChanges = (entities, changes, options) => {
|
|
|
40
49
|
if (!merge && !replace && !remove) {
|
|
41
50
|
return undefined;
|
|
42
51
|
}
|
|
52
|
+
const deepEqual = options.deepComparisonEnabled ? exports.optionalUtils.deepEqual : undefined;
|
|
43
53
|
let result;
|
|
44
54
|
for (const typename in entities) {
|
|
45
55
|
const entitiesToMerge = merge === null || merge === void 0 ? void 0 : merge[typename];
|
|
@@ -60,29 +70,50 @@ const applyEntityChanges = (entities, changes, options) => {
|
|
|
60
70
|
throw new Error('Merge, replace and remove changes have intersections for: ' + typename);
|
|
61
71
|
}
|
|
62
72
|
}
|
|
63
|
-
const
|
|
73
|
+
const oldEntities = entities[typename];
|
|
74
|
+
let newEntities;
|
|
64
75
|
// remove
|
|
65
|
-
entitiesToRemove === null || entitiesToRemove === void 0 ? void 0 : entitiesToRemove.forEach((id) =>
|
|
76
|
+
entitiesToRemove === null || entitiesToRemove === void 0 ? void 0 : entitiesToRemove.forEach((id) => {
|
|
77
|
+
if (oldEntities[id]) {
|
|
78
|
+
newEntities !== null && newEntities !== void 0 ? newEntities : (newEntities = Object.assign({}, oldEntities));
|
|
79
|
+
delete newEntities[id];
|
|
80
|
+
}
|
|
81
|
+
});
|
|
66
82
|
// replace
|
|
67
83
|
if (entitiesToReplace) {
|
|
68
84
|
for (const id in entitiesToReplace) {
|
|
69
|
-
|
|
85
|
+
const newEntity = entitiesToReplace[id];
|
|
86
|
+
if (!(deepEqual === null || deepEqual === void 0 ? void 0 : deepEqual(oldEntities[id], newEntity))) {
|
|
87
|
+
newEntities !== null && newEntities !== void 0 ? newEntities : (newEntities = Object.assign({}, oldEntities));
|
|
88
|
+
newEntities[id] = newEntity;
|
|
89
|
+
}
|
|
70
90
|
}
|
|
71
91
|
}
|
|
72
92
|
// merge
|
|
73
93
|
if (entitiesToMerge) {
|
|
74
94
|
for (const id in entitiesToMerge) {
|
|
75
|
-
|
|
95
|
+
const oldEntity = oldEntities[id];
|
|
96
|
+
const newEntity = Object.assign(Object.assign({}, oldEntity), entitiesToMerge[id]);
|
|
97
|
+
if (!(deepEqual === null || deepEqual === void 0 ? void 0 : deepEqual(oldEntity, newEntity))) {
|
|
98
|
+
newEntities !== null && newEntities !== void 0 ? newEntities : (newEntities = Object.assign({}, oldEntities));
|
|
99
|
+
newEntities[id] = newEntity;
|
|
100
|
+
}
|
|
76
101
|
}
|
|
77
102
|
}
|
|
103
|
+
if (!newEntities) {
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
78
106
|
result !== null && result !== void 0 ? result : (result = Object.assign({}, entities));
|
|
79
107
|
result[typename] = newEntities;
|
|
80
108
|
}
|
|
81
109
|
options.logsEnabled &&
|
|
82
110
|
(0, exports.log)('applyEntityChanges', {
|
|
83
111
|
entities,
|
|
84
|
-
|
|
85
|
-
|
|
112
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
113
|
+
changes: require('util').inspect(changes, { depth: 4 }),
|
|
114
|
+
options,
|
|
115
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
116
|
+
result: require('util').inspect(result, { depth: 4 }),
|
|
86
117
|
});
|
|
87
118
|
return result;
|
|
88
119
|
};
|
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.6.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",
|
|
@@ -14,6 +14,17 @@
|
|
|
14
14
|
"test": "node node_modules/jest/bin/jest.js",
|
|
15
15
|
"prepublishOnly": "yarn build && yarn test"
|
|
16
16
|
},
|
|
17
|
+
"peerDependencies": {
|
|
18
|
+
"fast-deep-equal": "*",
|
|
19
|
+
"react": "^16",
|
|
20
|
+
"react-redux": "^4",
|
|
21
|
+
"redux": "^4"
|
|
22
|
+
},
|
|
23
|
+
"peerDependenciesMeta": {
|
|
24
|
+
"fast-deep-equal": {
|
|
25
|
+
"optional": true
|
|
26
|
+
}
|
|
27
|
+
},
|
|
17
28
|
"devDependencies": {
|
|
18
29
|
"@testing-library/jest-dom": "6.1.4",
|
|
19
30
|
"@testing-library/react": "14.0.0",
|
|
@@ -40,11 +51,6 @@
|
|
|
40
51
|
"ts-jest": "29.1.0",
|
|
41
52
|
"typescript": "5.0"
|
|
42
53
|
},
|
|
43
|
-
"peerDependencies": {
|
|
44
|
-
"react": "^16",
|
|
45
|
-
"react-redux": "^4",
|
|
46
|
-
"redux": "^4"
|
|
47
|
-
},
|
|
48
54
|
"files": [
|
|
49
55
|
"dist/*"
|
|
50
56
|
],
|