react-redux-cache 0.0.10 → 0.0.12

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 CHANGED
@@ -1,10 +1,10 @@
1
1
  # react-redux-cache
2
2
 
3
- **Powerful** yet **lightweight** data fetching and caching library that supports **normalization** unlike `react-query` and `rtk-query`, while having similar interface. Built on top of `redux`.
3
+ **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`, fully typed and written on Typescript. Can be considered as `ApolloClient` for protocols other than `GraphQL`.
4
4
 
5
- **Normalization** is the only 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**.
5
+ **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**.
6
6
 
7
- Hooks, reducer, actions and selectors are fully typed and written on Typescript, so redux store will be properly typed and you will remain a **full control** of its state with ability to write custom selectors, actions and reducers to manage cached state.
7
+ Remains **full control** of redux state with ability to write custom selectors, actions and reducers to manage cached state.
8
8
 
9
9
  Usage example can be found in `example/` folder and run by `npm run example` command from the root folder.
10
10
 
@@ -17,29 +17,36 @@ Usage example can be found in `example/` folder and run by `npm run example` com
17
17
  - [api.ts](https://github.com/gentlee/react-redux-cache#apits)
18
18
  - [Usage](https://github.com/gentlee/react-redux-cache#usage)
19
19
  - [Advanced](https://github.com/gentlee/react-redux-cache#advanced)
20
+ - [resultSelector](https://github.com/gentlee/react-redux-cache#resultselector)
21
+ - [Infinite scroll pagination](https://github.com/gentlee/react-redux-cache#infinite-scroll-pagination)
20
22
  - [redux-persist](https://github.com/gentlee/react-redux-cache#redux-persist)
23
+ - [FAQ](https://github.com/gentlee/react-redux-cache#faq)
24
+ - [What is cache key?](https://github.com/gentlee/react-redux-cache#what-is-cache-key)
21
25
 
22
26
  ### Installation
23
- `react` and `redux` are peer dependencies.
27
+ `react`, `redux` and `react-redux` are peer dependencies.
24
28
  ```sh
25
- npm add react-redux-cache react redux
29
+ npm add react-redux-cache react redux react-redux
26
30
  ```
27
31
  ### Initialization
28
- Create reducer, hooks, actions and selectors with `createCache`.
29
- All queries and mutations should be passed while initializing the cache, for proper typing and later access by key.
30
- In this example we omit usage of actions and selectors.
32
+ The only function that needs to be imported is `createCache`, which creates fully typed reducer, hooks, actions, selectors and utils to be used in the app.
33
+ All typenames, queries and mutations should be passed while initializing the cache for proper typing.
31
34
  #### cache.ts
32
35
  ```typescript
33
36
  export const {
34
37
  reducer,
35
- hooks: {useMutation, useQuery, useSelectEntityById},
38
+ hooks: {useClient, useMutation, useQuery, useSelectEntityById},
39
+ // Actions, selectors and utils may be not used at all
40
+ selectors: {entitiesSelector, entitiesByTypenameSelector},
41
+ actions: {setQueryStateAndEntities, setMutationStateAndEntities, mergeEntityChanges},
42
+ utils: {applyEntityChanges},
36
43
  } = createCache({
37
- // This selector should select cache state from redux store state, based on the path to its reducer.
44
+ // This selector should return the cache state based on the path to its reducer.
38
45
  cacheStateSelector: (state) => state.cache,
39
- // Typenames provide a mapping of all typenames to their entity types.
46
+ // Typenames provide a mapping of all typenames to their entity types, which is needed for normalization.
40
47
  // Empty objects with type casting can be used as values.
41
48
  typenames: {
42
- users: {} as User,
49
+ users: {} as User, // here `users` entities will have type `User`
43
50
  banks: {} as Bank,
44
51
  },
45
52
  queries: {
@@ -54,6 +61,8 @@ export const {
54
61
  ```
55
62
  #### store.ts
56
63
  ```typescript
64
+ // Create store as usual, passing the new cache reducer
65
+ // under the key, previously used in cacheStateSelector
57
66
  const store = configureStore({
58
67
  reducer: {
59
68
  cache: reducer,
@@ -65,11 +74,16 @@ Query result should be of type `QueryResponse`, mutation result should be of typ
65
74
  For normalization `normalizr` package is used in this example, but any other tool can be used if query result is of proper type.
66
75
  Perfect implementation is when the backend already returns normalized data.
67
76
  ```typescript
77
+
78
+ // Example of query with normalization (recommended)
79
+
68
80
  export const getUser = async (id: number) => {
69
81
  const result = await ...
70
82
 
71
83
  const normalizedResult: {
84
+ // result is id of the user
72
85
  result: number
86
+ // entities contain all normalized objects
73
87
  entities: {
74
88
  users: Record<number, User>
75
89
  banks: Record<string, Bank>
@@ -79,6 +93,15 @@ export const getUser = async (id: number) => {
79
93
  return normalizedResult
80
94
  }
81
95
 
96
+ // Example of query without normalization (not recommended)
97
+
98
+ export const getBank = (id: string) => {
99
+ const result: Bank = ...
100
+ return {result} // result is bank object, no entities passed
101
+ }
102
+
103
+ // Example of mutation with normalization
104
+
82
105
  export const removeUser = async (id: number) => {
83
106
  await ...
84
107
  return {
@@ -93,8 +116,8 @@ export const removeUser = async (id: number) => {
93
116
  export const UserScreen = () => {
94
117
  const {id} = useParams()
95
118
 
96
- // useQuery will infer all types from created cache,
97
- // telling you that params and result here are of type `number`.
119
+ // useQuery connects to redux state and if user with that id is already cached, fetch won't happen (with default cachePolicy 'cache-first')
120
+ // Infers all types from created cache, telling here that params and result are of type `number`.
98
121
  const [{result: userId, loading, error}] = useQuery({
99
122
  query: 'getUser',
100
123
  params: Number(id),
@@ -104,7 +127,7 @@ export const UserScreen = () => {
104
127
  mutation: 'updateUser',
105
128
  })
106
129
 
107
- // This selector is created by createCache and also returns proper types - User and Bank
130
+ // This selector is used for denormalization and returns entities with proper types - User and Bank
108
131
  const user = useSelectEntityById(userId, 'users')
109
132
  const bank = useSelectEntityById(user?.bankId, 'banks')
110
133
 
@@ -117,6 +140,113 @@ export const UserScreen = () => {
117
140
  ```
118
141
 
119
142
  ### Advanced
143
+
144
+ #### resultSelector
145
+
146
+ 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.
147
+
148
+ For example when single `User` entity is requested by `userId` for the first time, the entity can already be in the cache after `getUsers` query finished.
149
+
150
+ For that case `resultSelector` can be used:
151
+
152
+ ```typescript
153
+
154
+ // createCache
155
+
156
+ ... = createCache({
157
+ ...
158
+ queries: {
159
+ ...
160
+ getUser: {
161
+ query: getUser,
162
+ resultSelector: (state, id) => state.entities.users[id]?.id, // <-- Result is selected from cached entities
163
+ },
164
+ },
165
+ })
166
+
167
+ // component
168
+
169
+ export const UserScreen = () => {
170
+ ...
171
+
172
+ // When screen mounts for the first time, query is not fetched
173
+ // and cached value is returned if user entity was already in the cache
174
+ const [{result, loading, error}] = useQuery({
175
+ query: 'getUser',
176
+ params: userId,
177
+ })
178
+
179
+ ...
180
+ }
181
+
182
+ ```
183
+
184
+ #### Infinite scroll pagination
185
+
186
+ Here is an example of `getUsers` query configuration with pagination support. You can check full implementation in `/example` folder.
187
+
188
+ ```typescript
189
+ // createCache
190
+
191
+ ...
192
+ } = createCache({
193
+ ...
194
+ queries: {
195
+ getUsers: {
196
+ query: getUsers,
197
+ getCacheKey: () => 'all-pages', // single cache key is used for all pages
198
+ mergeResults: (oldResult, {result: newResult}) => {
199
+ if (!oldResult || newResult.page === 1) {
200
+ return newResult
201
+ }
202
+ if (newResult.page === oldResult.page + 1) {
203
+ return {
204
+ ...newResult,
205
+ items: [...oldResult.items, ...newResult.items],
206
+ }
207
+ }
208
+ return oldResult
209
+ },
210
+ },
211
+ },
212
+ ...
213
+ })
214
+
215
+ // Component
216
+
217
+ export const GetUsersScreen = () => {
218
+ const {query} = useClient()
219
+
220
+ const [{result: usersResult, loading, error}, refetch] = useQuery({
221
+ query: 'getUsers',
222
+ params: 1 // page
223
+ })
224
+
225
+ const onLoadNextPage = () => {
226
+ const lastLoadedPage = usersResult?.page ?? 0
227
+ query({
228
+ query: 'getUsers',
229
+ params: lastLoadedPage + 1,
230
+ })
231
+ }
232
+
233
+ const renderUser = (userId: number) => (
234
+ <UserRow key={userId} userId={userId}>
235
+ )
236
+
237
+ ...
238
+
239
+ return (
240
+ <div>
241
+ {usersResult?.items.map(renderUser)}
242
+ <button onClick={refetch}>Refresh</button>
243
+ <button onClick={onLoadNextPage}>Load next page</button>
244
+ </div>
245
+ )
246
+ }
247
+
248
+ ```
249
+
120
250
  #### redux-persist
121
251
 
122
252
  Here is a simple `redux-persist` configuration:
@@ -138,3 +268,28 @@ const persistedReducer = persistReducer(
138
268
  reducer
139
269
  )
140
270
  ```
271
+
272
+ ### FAQ
273
+
274
+ #### What is cache key?
275
+
276
+ **Cache key** is used for storing the query state and for performing a fetch when it changes. Queries with the same cache key share their state.
277
+
278
+ Default implementation for `getCacheKey` is:
279
+ ```typescript
280
+ export const defaultGetCacheKey = <P = unknown>(params: P): Key => {
281
+ switch (typeof params) {
282
+ case 'string':
283
+ case 'symbol':
284
+ return params
285
+ case 'object':
286
+ return JSON.stringify(params)
287
+ default:
288
+ return String(params)
289
+ }
290
+ }
291
+ ```
292
+
293
+ It is recommended to override it when default implementation is not optimal or when keys in params object can be sorted in random order.
294
+
295
+ As example, can be overriden when implementing pagination.
@@ -1,7 +1,8 @@
1
1
  import { mergeEntityChanges, setMutationStateAndEntities, setQueryStateAndEntities } from './reducer';
2
- import { Cache, EntitiesMap, Key, MutationCacheOptions, MutationResult, OptionalPartial, QueryOptions, QueryResult, Typenames } from './types';
2
+ import { Cache, EntitiesMap, Key, MutationResult, OptionalPartial, QueryOptions, QueryResult, Typenames } from './types';
3
3
  import { useMutation } from './useMutation';
4
4
  import { useQuery } from './useQuery';
5
+ import { applyEntityChanges } from './utilsAndConstants';
5
6
  /**
6
7
  * Creates reducer, actions and hooks for managing queries and mutations through redux cache.
7
8
  */
@@ -64,7 +65,6 @@ export declare const createCache: <T extends Typenames, QP, QR, MP, MR>(cache: O
64
65
  mutate: <MK_1 extends keyof MP | keyof MR>(options: {
65
66
  mutation: MK_1;
66
67
  params: MK_1 extends keyof MP & keyof MR ? MP[MK_1] : never;
67
- cacheOptions?: MutationCacheOptions | undefined;
68
68
  }) => Promise<MutationResult<MK_1 extends keyof MP & keyof MR ? MR[MK_1] : never>>;
69
69
  };
70
70
  /** Fetches query when params change and subscribes to query state. */
@@ -72,9 +72,11 @@ export declare const createCache: <T extends Typenames, QP, QR, MP, MR>(cache: O
72
72
  /** Subscribes to provided mutation state and provides mutate function. */
73
73
  useMutation: <MK_2 extends keyof MP | keyof MR>(options: {
74
74
  mutation: MK_2;
75
- cacheOptions?: MutationCacheOptions | undefined;
76
75
  }) => readonly [(params: MK_2 extends keyof MP & keyof MR ? MP[MK_2] : never) => Promise<void>, import("./types").QueryMutationState<MK_2 extends keyof MP & keyof MR ? MP[MK_2] : never>, () => boolean];
77
76
  /** Selects entity by id and subscribes to the changes. */
78
77
  useSelectEntityById: <K_3 extends keyof T>(id: Key | null | undefined, typename: K_3) => T[K_3] | undefined;
79
78
  };
79
+ utils: {
80
+ applyEntityChanges: (entities: EntitiesMap<T>, changes: import("./types").EntityChanges<T>) => EntitiesMap<T> | undefined;
81
+ };
80
82
  };
@@ -13,23 +13,17 @@ const utilsAndConstants_1 = require("./utilsAndConstants");
13
13
  * Creates reducer, actions and hooks for managing queries and mutations through redux cache.
14
14
  */
15
15
  const createCache = (cache) => {
16
- var _a, _b, _c, _d, _e, _f;
17
- var _g, _h, _j;
18
- // @ts-expect-error hot
19
- const hotReloadEnabled = Boolean(module === null || module === void 0 ? void 0 : module.hot);
16
+ var _a, _b, _c, _d, _e;
17
+ var _f, _g;
18
+ const abortControllers = new WeakMap();
20
19
  // provide all optional fields
21
- // and transform cacheOptions from QueryCachePolicy to QueryCacheOptions
22
20
  (_a = cache.options) !== null && _a !== void 0 ? _a : (cache.options = {});
23
- (_b = (_g = cache.options).logsEnabled) !== null && _b !== void 0 ? _b : (_g.logsEnabled = false);
24
- (_c = (_h = cache.options).validateFunctionArguments) !== null && _c !== void 0 ? _c : (_h.validateFunctionArguments = utilsAndConstants_1.isDev);
25
- (_d = (_j = cache.options).validateHookArguments) !== null && _d !== void 0 ? _d : (_j.validateHookArguments = utilsAndConstants_1.isDev && !hotReloadEnabled);
26
- (_e = cache.queries) !== null && _e !== void 0 ? _e : (cache.queries = {});
27
- (_f = cache.mutations) !== null && _f !== void 0 ? _f : (cache.mutations = {});
28
- for (const queryInfo of Object.values(cache.queries)) {
29
- if (typeof queryInfo.cacheOptions === 'string') {
30
- queryInfo.cacheOptions = useQuery_1.queryCacheOptionsByPolicy[queryInfo.cacheOptions];
31
- }
32
- }
21
+ (_b = (_f = cache.options).logsEnabled) !== null && _b !== void 0 ? _b : (_f.logsEnabled = false);
22
+ (_c = (_g = cache.options).validateFunctionArguments) !== null && _c !== void 0 ? _c : (_g.validateFunctionArguments = utilsAndConstants_1.isDev);
23
+ (_d = cache.queries) !== null && _d !== void 0 ? _d : (cache.queries = {});
24
+ (_e = cache.mutations) !== null && _e !== void 0 ? _e : (cache.mutations = {});
25
+ // @ts-expect-error for testing
26
+ cache.abortControllers = abortControllers;
33
27
  const nonPartialCache = cache;
34
28
  // make selectors
35
29
  const entitiesSelector = (state) => {
@@ -64,24 +58,15 @@ const createCache = (cache) => {
64
58
  return (0, react_1.useMemo)(() => {
65
59
  const client = {
66
60
  query: (options) => {
67
- var _a, _b;
68
- const { query: queryKey, params,
69
- // TODO can be memoized for all query keys while creating cache
70
- cacheOptions: cacheOptionsOrPolicy = Object.assign(Object.assign({}, ((_a = nonPartialCache.queries[queryKey].cacheOptions) !== null && _a !== void 0 ? _a : useQuery_1.defaultQueryCacheOptions)), { policy: 'cache-and-fetch' }), getCacheKey = nonPartialCache.queries[queryKey].getCacheKey, } = options;
71
- const cacheOptions = typeof cacheOptionsOrPolicy === 'string'
72
- ? useQuery_1.queryCacheOptionsByPolicy[cacheOptionsOrPolicy]
73
- : cacheOptionsOrPolicy;
74
- const getParamsKey = (_b = nonPartialCache.queries[queryKey].getParamsKey) !== null && _b !== void 0 ? _b : (utilsAndConstants_1.defaultGetParamsKey);
75
- const cacheKey = getCacheKey
76
- ? // @ts-expect-error fix later
77
- getCacheKey(params)
78
- : // @ts-expect-error fix later
79
- getParamsKey(params);
80
- return (0, query_1.query)('query', true, store, nonPartialCache, queryKey, cacheKey, cacheOptions, params);
61
+ var _a;
62
+ const { query: queryKey, params } = options;
63
+ const getCacheKey = (_a = nonPartialCache.queries[queryKey].getCacheKey) !== null && _a !== void 0 ? _a : (utilsAndConstants_1.defaultGetCacheKey);
64
+ // @ts-expect-error fix later
65
+ const cacheKey = getCacheKey(params);
66
+ return (0, query_1.query)('query', true, store, nonPartialCache, queryKey, cacheKey, params);
81
67
  },
82
68
  mutate: (options) => {
83
- var _a;
84
- return (0, mutate_1.mutate)('mutate', true, store, nonPartialCache, options.mutation, (_a = options.cacheOptions) !== null && _a !== void 0 ? _a : useMutation_1.defaultMutationCacheOptions, options.params);
69
+ return (0, mutate_1.mutate)('mutate', true, store, nonPartialCache, options.mutation, options.params, abortControllers);
85
70
  },
86
71
  };
87
72
  return client;
@@ -90,12 +75,17 @@ const createCache = (cache) => {
90
75
  /** Fetches query when params change and subscribes to query state. */
91
76
  useQuery: (options) => (0, useQuery_1.useQuery)(nonPartialCache, options),
92
77
  /** Subscribes to provided mutation state and provides mutate function. */
93
- useMutation: (options) => (0, useMutation_1.useMutation)(nonPartialCache, options),
78
+ useMutation: (options) => (0, useMutation_1.useMutation)(nonPartialCache, options, abortControllers),
94
79
  /** Selects entity by id and subscribes to the changes. */
95
80
  useSelectEntityById: (id, typename) => {
96
81
  return (0, react_redux_1.useSelector)((state) => id == null ? undefined : nonPartialCache.cacheStateSelector(state).entities[typename][id]);
97
82
  },
98
83
  },
84
+ utils: {
85
+ applyEntityChanges: (entities, changes) => {
86
+ return (0, utilsAndConstants_1.applyEntityChanges)(entities, changes, nonPartialCache.options);
87
+ },
88
+ },
99
89
  };
100
90
  };
101
91
  exports.createCache = createCache;
package/dist/index.d.ts CHANGED
@@ -1,6 +1,4 @@
1
1
  export { createCache } from './createCache';
2
2
  export type { ReduxCacheState } from './reducer';
3
3
  export * from './types';
4
- export { defaultMutationCacheOptions } from './useMutation';
5
- export { defaultQueryCacheOptions, queryCacheOptionsByPolicy } from './useQuery';
6
- export { defaultCacheOptions, defaultGetParamsKey, defaultQueryMutationState, processEntityChanges, } from './utilsAndConstants';
4
+ export { defaultGetCacheKey, defaultQueryMutationState } from './utilsAndConstants';
package/dist/index.js CHANGED
@@ -14,26 +14,18 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- exports.processEntityChanges = exports.defaultQueryMutationState = exports.defaultGetParamsKey = exports.defaultCacheOptions = exports.queryCacheOptionsByPolicy = exports.defaultQueryCacheOptions = exports.defaultMutationCacheOptions = exports.createCache = void 0;
17
+ exports.defaultQueryMutationState = exports.defaultGetCacheKey = exports.createCache = void 0;
18
18
  var createCache_1 = require("./createCache");
19
19
  Object.defineProperty(exports, "createCache", { enumerable: true, get: function () { return createCache_1.createCache; } });
20
20
  __exportStar(require("./types"), exports);
21
- var useMutation_1 = require("./useMutation");
22
- Object.defineProperty(exports, "defaultMutationCacheOptions", { enumerable: true, get: function () { return useMutation_1.defaultMutationCacheOptions; } });
23
- var useQuery_1 = require("./useQuery");
24
- Object.defineProperty(exports, "defaultQueryCacheOptions", { enumerable: true, get: function () { return useQuery_1.defaultQueryCacheOptions; } });
25
- Object.defineProperty(exports, "queryCacheOptionsByPolicy", { enumerable: true, get: function () { return useQuery_1.queryCacheOptionsByPolicy; } });
26
21
  var utilsAndConstants_1 = require("./utilsAndConstants");
27
- Object.defineProperty(exports, "defaultCacheOptions", { enumerable: true, get: function () { return utilsAndConstants_1.defaultCacheOptions; } });
28
- Object.defineProperty(exports, "defaultGetParamsKey", { enumerable: true, get: function () { return utilsAndConstants_1.defaultGetParamsKey; } });
22
+ Object.defineProperty(exports, "defaultGetCacheKey", { enumerable: true, get: function () { return utilsAndConstants_1.defaultGetCacheKey; } });
29
23
  Object.defineProperty(exports, "defaultQueryMutationState", { enumerable: true, get: function () { return utilsAndConstants_1.defaultQueryMutationState; } });
30
- Object.defineProperty(exports, "processEntityChanges", { enumerable: true, get: function () { return utilsAndConstants_1.processEntityChanges; } });
31
24
  // Backlog
32
25
  // ! high
33
- // mutate
34
26
  // cover with tests
35
- // suport persist (no loading etc)
36
27
  // ! medium
28
+ // allow multiple mutation with sam keys?
37
29
  // type extractors from cache
38
30
  // custom useStore
39
31
  // return back deserialize selector?
package/dist/mutate.d.ts CHANGED
@@ -1,5 +1,3 @@
1
1
  import { Store } from 'redux';
2
- import { Cache, Key, MutationCacheOptions, MutationResult, Typenames } from './types';
3
- export declare const abortControllers: WeakMap<Store<any, import("redux").AnyAction>, Record<Key, AbortController>>;
4
- export declare const getAbortController: (store: Store, mutationKey: Key) => AbortController | undefined;
5
- export declare const mutate: <T extends Typenames, QP, QR, MP, MR, MK extends keyof MP | keyof MR>(logTag: string, returnResult: boolean, store: Store, cache: Cache<T, QP, QR, MP, MR>, mutationKey: MK, cacheOptions: MutationCacheOptions, params: MK extends keyof MP & keyof MR ? MP[MK] : never) => Promise<void | MutationResult<MK extends keyof MP & keyof MR ? MR[MK] : never>>;
2
+ import { Cache, Key, MutationResult, Typenames } from './types';
3
+ export declare const mutate: <T extends Typenames, QP, QR, MP, MR, MK extends keyof MP | keyof MR>(logTag: string, returnResult: boolean, store: Store, cache: Cache<T, QP, QR, MP, MR>, mutationKey: MK, params: MK extends keyof MP & keyof MR ? MP[MK] : never, abortControllers: WeakMap<Store, Record<Key, AbortController>>) => Promise<void | MutationResult<MK extends keyof MP & keyof MR ? MR[MK] : never>>;
package/dist/mutate.js CHANGED
@@ -9,17 +9,14 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  });
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.mutate = exports.getAbortController = exports.abortControllers = void 0;
12
+ exports.mutate = void 0;
13
13
  const reducer_1 = require("./reducer");
14
14
  const utilsAndConstants_1 = require("./utilsAndConstants");
15
- exports.abortControllers = new WeakMap();
16
- const getAbortController = (store, mutationKey) => { var _a; return (_a = exports.abortControllers.get(store)) === null || _a === void 0 ? void 0 : _a[mutationKey]; };
17
- exports.getAbortController = getAbortController;
18
- const mutate = (logTag, returnResult, store, cache, mutationKey, cacheOptions, params) => __awaiter(void 0, void 0, void 0, function* () {
19
- let abortControllersOfStore = exports.abortControllers.get(store);
15
+ const mutate = (logTag, returnResult, store, cache, mutationKey, params, abortControllers) => __awaiter(void 0, void 0, void 0, function* () {
16
+ let abortControllersOfStore = abortControllers.get(store);
20
17
  if (abortControllersOfStore === undefined) {
21
18
  abortControllersOfStore = {};
22
- exports.abortControllers.set(store, abortControllersOfStore);
19
+ abortControllers.set(store, abortControllersOfStore);
23
20
  }
24
21
  {
25
22
  const abortController = abortControllersOfStore[mutationKey];
@@ -33,11 +30,10 @@ const mutate = (logTag, returnResult, store, cache, mutationKey, cacheOptions, p
33
30
  abortController.abort();
34
31
  }
35
32
  else {
36
- cacheOptions.cacheMutationState &&
37
- store.dispatch((0, reducer_1.setMutationStateAndEntities)(mutationKey, {
38
- loading: true,
39
- result: undefined,
40
- }));
33
+ store.dispatch((0, reducer_1.setMutationStateAndEntities)(mutationKey, {
34
+ loading: true,
35
+ result: undefined,
36
+ }));
41
37
  }
42
38
  }
43
39
  const abortController = new AbortController();
@@ -64,23 +60,19 @@ const mutate = (logTag, returnResult, store, cache, mutationKey, cacheOptions, p
64
60
  }
65
61
  delete abortControllersOfStore[mutationKey];
66
62
  if (error) {
67
- if (cacheOptions.cacheMutationState) {
68
- store.dispatch((0, reducer_1.setMutationStateAndEntities)(mutationKey, {
69
- error: error,
70
- loading: false,
71
- }));
72
- }
63
+ store.dispatch((0, reducer_1.setMutationStateAndEntities)(mutationKey, {
64
+ error: error,
65
+ loading: false,
66
+ }));
73
67
  return { error };
74
68
  }
75
69
  if (response) {
76
- store.dispatch((0, reducer_1.setMutationStateAndEntities)(mutationKey, cacheOptions.cacheMutationState
77
- ? {
78
- error: undefined,
79
- loading: false,
80
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
81
- result: response.result,
82
- }
83
- : undefined, cacheOptions.cacheEntities ? response : undefined));
70
+ store.dispatch((0, reducer_1.setMutationStateAndEntities)(mutationKey, {
71
+ error: undefined,
72
+ loading: false,
73
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
74
+ result: response.result,
75
+ }, response));
84
76
  // @ts-expect-error fix later
85
77
  return returnResult ? { result: response.result } : undefined;
86
78
  }
package/dist/query.d.ts CHANGED
@@ -1,3 +1,3 @@
1
1
  import { Store } from 'redux';
2
- import { Cache, Key, QueryCacheOptions, QueryResult, Typenames } from './types';
3
- export declare const query: <T extends Typenames, QP, QR, MP, MR, QK extends keyof QP | keyof QR>(logTag: string, returnResult: boolean, store: Store, cache: Cache<T, QP, QR, MP, MR>, queryKey: QK, cacheKey: Key, cacheOptions: QueryCacheOptions, params: QK extends keyof QP & keyof QR ? QP[QK] : never) => Promise<void | QueryResult<QK extends keyof QP & keyof QR ? QR[QK] : never>>;
2
+ import { Cache, Key, QueryResult, Typenames } from './types';
3
+ export declare const query: <T extends Typenames, QP, QR, MP, MR, QK extends keyof QP | keyof QR>(logTag: string, returnResult: boolean, store: Store, cache: Cache<T, QP, QR, MP, MR>, queryKey: QK, cacheKey: Key, params: QK extends keyof QP & keyof QR ? QP[QK] : never) => Promise<void | QueryResult<QK extends keyof QP & keyof QR ? QR[QK] : never>>;
package/dist/query.js CHANGED
@@ -12,7 +12,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.query = void 0;
13
13
  const reducer_1 = require("./reducer");
14
14
  const utilsAndConstants_1 = require("./utilsAndConstants");
15
- const query = (logTag, returnResult, store, cache, queryKey, cacheKey, cacheOptions, params) => __awaiter(void 0, void 0, void 0, function* () {
15
+ const query = (logTag, returnResult, store, cache, queryKey, cacheKey, params) => __awaiter(void 0, void 0, void 0, function* () {
16
16
  var _a;
17
17
  const logsEnabled = cache.options.logsEnabled;
18
18
  const cacheStateSelector = cache.cacheStateSelector;
@@ -28,10 +28,9 @@ const query = (logTag, returnResult, store, cache, queryKey, cacheKey, cacheOpti
28
28
  });
29
29
  return returnResult ? { cancelled: true } : undefined;
30
30
  }
31
- cacheOptions.cacheQueryState &&
32
- store.dispatch((0, reducer_1.setQueryStateAndEntities)(queryKey, cacheKey, {
33
- loading: true,
34
- }));
31
+ store.dispatch((0, reducer_1.setQueryStateAndEntities)(queryKey, cacheKey, {
32
+ loading: true,
33
+ }));
35
34
  logsEnabled && (0, utilsAndConstants_1.log)(`${logTag} started`, { queryStateOnStart, params, cacheKey });
36
35
  let response;
37
36
  const fetchFn = cache.queries[queryKey].query;
@@ -47,20 +46,18 @@ const query = (logTag, returnResult, store, cache, queryKey, cacheKey, cacheOpti
47
46
  }));
48
47
  return returnResult ? { error } : undefined;
49
48
  }
50
- const newState = cacheOptions.cacheQueryState
51
- ? {
52
- error: undefined,
53
- loading: false,
54
- result: cacheResultSelector
55
- ? undefined
56
- : mergeResults
57
- ? mergeResults(
58
- // @ts-expect-error fix later
59
- (_a = cacheStateSelector(store.getState()).queries[queryKey][cacheKey]) === null || _a === void 0 ? void 0 : _a.result, response, params)
60
- : response.result,
61
- }
62
- : undefined;
63
- store.dispatch((0, reducer_1.setQueryStateAndEntities)(queryKey, cacheKey, newState, cacheOptions.cacheEntities ? response : undefined));
49
+ const newState = {
50
+ error: undefined,
51
+ loading: false,
52
+ result: cacheResultSelector
53
+ ? undefined
54
+ : mergeResults
55
+ ? mergeResults(
56
+ // @ts-expect-error fix later
57
+ (_a = cacheStateSelector(store.getState()).queries[queryKey][cacheKey]) === null || _a === void 0 ? void 0 : _a.result, response, params)
58
+ : response.result,
59
+ };
60
+ store.dispatch((0, reducer_1.setQueryStateAndEntities)(queryKey, cacheKey, newState, response));
64
61
  // @ts-expect-error fix types
65
62
  return returnResult
66
63
  ? {
package/dist/reducer.js CHANGED
@@ -28,7 +28,7 @@ const createCacheReducer = (typenames, queries, mutations, cacheOptions) => {
28
28
  switch (action.type) {
29
29
  case '@RRC/SET_QUERY_STATE_AND_ENTITIES': {
30
30
  const { queryKey, queryCacheKey, state: queryState, entityChagnes } = action;
31
- const newEntities = entityChagnes && (0, utilsAndConstants_1.processEntityChanges)(state.entities, entityChagnes, cacheOptions);
31
+ const newEntities = entityChagnes && (0, utilsAndConstants_1.applyEntityChanges)(state.entities, entityChagnes, cacheOptions);
32
32
  if (!queryState && !newEntities) {
33
33
  return state;
34
34
  }
@@ -36,7 +36,7 @@ const createCacheReducer = (typenames, queries, mutations, cacheOptions) => {
36
36
  }
37
37
  case '@RRC/SET_MUTATION_STATE_AND_ENTITIES': {
38
38
  const { mutationKey, state: mutationState, entityChagnes } = action;
39
- const newEntities = entityChagnes && (0, utilsAndConstants_1.processEntityChanges)(state.entities, entityChagnes, cacheOptions);
39
+ const newEntities = entityChagnes && (0, utilsAndConstants_1.applyEntityChanges)(state.entities, entityChagnes, cacheOptions);
40
40
  if (!mutationState && !newEntities) {
41
41
  return state;
42
42
  }
@@ -44,7 +44,7 @@ const createCacheReducer = (typenames, queries, mutations, cacheOptions) => {
44
44
  }
45
45
  case '@RRC/MERGE_ENTITY_CHANGES': {
46
46
  const { changes } = action;
47
- const newEntities = (0, utilsAndConstants_1.processEntityChanges)(state.entities, changes, cacheOptions);
47
+ const newEntities = (0, utilsAndConstants_1.applyEntityChanges)(state.entities, changes, cacheOptions);
48
48
  return newEntities ? Object.assign(Object.assign({}, state), { entities: newEntities }) : state;
49
49
  }
50
50
  }
package/dist/types.d.ts CHANGED
@@ -35,12 +35,6 @@ export type CacheOptions = {
35
35
  * Default is true in dev mode.
36
36
  * */
37
37
  validateFunctionArguments: boolean;
38
- /**
39
- * Enables validation of package hook arguments. Recommened to enable in dev/testing mode and disable in production.
40
- * Should be disabled with hot reloading.
41
- * Default is true in dev mode without hot reloading.
42
- * */
43
- validateHookArguments: boolean;
44
38
  /**
45
39
  * Enable console logs.
46
40
  * Default is false.
@@ -60,12 +54,10 @@ export type Query<T extends Typenames, P, R> = (params: P) => Promise<QueryRespo
60
54
  export type QueryInfo<T extends Typenames, P, R, S> = {
61
55
  query: Query<T, P, R>;
62
56
  /**
63
- * Cache policy string or cache options object. After cache created, all strings are converted to objects.
64
- * Default is { policy: 'cache-first', cacheQueryState: true, cacheEntities: true }
65
- * @param cache-first for each params key fetch is not called if cache exists.
66
- * @param cache-and-fetch for each params key result is taken from cache and fetch is called.
57
+ * Cache policy.
58
+ * @default cache-first
67
59
  */
68
- cacheOptions?: QueryCacheOptions | QueryCachePolicy;
60
+ cachePolicy?: QueryCachePolicy;
69
61
  /**
70
62
  * Selector for query result from redux state.
71
63
  * Can prevent hook from doing unnecessary fetches.
@@ -75,15 +67,9 @@ export type QueryInfo<T extends Typenames, P, R, S> = {
75
67
  /** Merges results before saving to the store. */
76
68
  mergeResults?: (oldResult: R | undefined, response: QueryResponse<T, R>, params: P | undefined) => R;
77
69
  /**
78
- * Params key is used for determining if parameters were changed and fetch is needed.
79
- * Also used as cache key, of `getCacheKey` wasn't provided.
70
+ * Cache key is used for storing the query state and for performing a fetch when it changes. Queries with the same cache key share their state.
80
71
  * Default implementation uses `JSON.stringify` or `String()` depending on type.
81
- * */
82
- getParamsKey?: (params?: P) => Key;
83
- /**
84
- * Cache key is a key in redux state for caching query state.
85
- * Queries with equal cache keys have the same state.
86
- * Default implementation is equal to `getParamsKey`.
72
+ * It is recommended to override it when default implementation is not optimal or when keys in params object can be sorted in random order etc.
87
73
  * */
88
74
  getCacheKey?: (params?: P) => Key;
89
75
  };
@@ -91,23 +77,12 @@ export type UseQueryOptions<T extends Typenames, QP, QR, MP, MR, QK extends keyo
91
77
  query: QK;
92
78
  params: QK extends keyof (QP | QR) ? QP[QK] : never;
93
79
  skip?: boolean;
94
- } & Pick<QK extends keyof (QP | QR) ? QueryInfo<T, QP[QK], QR[QK], ReduxCacheState<T, QP, QR, MP, MR>> : never, 'cacheOptions' | 'mergeResults' | 'getCacheKey'>;
80
+ } & Pick<QK extends keyof (QP | QR) ? QueryInfo<T, QP[QK], QR[QK], ReduxCacheState<T, QP, QR, MP, MR>> : never, 'cachePolicy' | 'mergeResults' | 'getCacheKey'>;
95
81
  /**
96
82
  * @param cache-first for each params key fetch is not called if cache exists.
97
83
  * @param cache-and-fetch for each params key result is taken from cache and fetch is called.
98
84
  */
99
85
  export type QueryCachePolicy = 'cache-first' | 'cache-and-fetch';
100
- export type QueryCacheOptions = {
101
- /**
102
- * @param cache-first for each params key fetch is not called if cache exists.
103
- * @param cache-and-fetch for each params key result is taken from cache and fetch is called.
104
- */
105
- policy: QueryCachePolicy;
106
- /** If `false`, query state is not saved in the store. Default is `true`. */
107
- cacheQueryState: boolean;
108
- /** If `false`, entities from response are not saved to the store. Default is `true`. */
109
- cacheEntities: boolean;
110
- };
111
86
  export type QueryResponse<T extends Typenames, R> = EntityChanges<T> & {
112
87
  /** Normalized result of a query. */
113
88
  result: R;
@@ -123,11 +98,6 @@ export type Mutation<T extends Typenames, P, R> = (params: P,
123
98
  abortSignal: AbortSignal) => Promise<MutationResponse<T, R>>;
124
99
  export type MutationInfo<T extends Typenames, P, R> = {
125
100
  mutation: Mutation<T, P, R>;
126
- cacheOptions?: MutationCacheOptions;
127
- };
128
- export type MutationCacheOptions = Pick<QueryCacheOptions, 'cacheEntities'> & {
129
- /** If `false`, mutation state is not saved in the store. Default is `true`. */
130
- cacheMutationState: boolean;
131
101
  };
132
102
  export type MutationResponse<T extends Typenames, R> = EntityChanges<T> & {
133
103
  /** Normalized result of a mutation. */
@@ -1,6 +1,5 @@
1
- import { Cache, MutationCacheOptions, QueryMutationState, Typenames } from './types';
2
- export declare const defaultMutationCacheOptions: MutationCacheOptions;
1
+ import { Store } from 'redux';
2
+ import { Cache, Key, QueryMutationState, Typenames } from './types';
3
3
  export declare const useMutation: <T extends Typenames, MP, MR, MK extends keyof MP | keyof MR>(cache: Cache<T, unknown, unknown, MP, MR>, options: {
4
4
  mutation: MK;
5
- cacheOptions?: MutationCacheOptions | undefined;
6
- }) => readonly [(params: MK extends keyof MP & keyof MR ? MP[MK] : never) => Promise<void>, QueryMutationState<MK extends keyof MP & keyof MR ? MP[MK] : never>, () => boolean];
5
+ }, abortControllers: WeakMap<Store, Record<Key, AbortController>>) => readonly [(params: MK extends keyof MP & keyof MR ? MP[MK] : never) => Promise<void>, QueryMutationState<MK extends keyof MP & keyof MR ? MP[MK] : never>, () => boolean];
@@ -9,36 +9,15 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  });
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.useMutation = exports.defaultMutationCacheOptions = void 0;
12
+ exports.useMutation = void 0;
13
13
  const react_1 = require("react");
14
14
  const react_redux_1 = require("react-redux");
15
15
  const mutate_1 = require("./mutate");
16
16
  const reducer_1 = require("./reducer");
17
17
  const utilsAndConstants_1 = require("./utilsAndConstants");
18
- exports.defaultMutationCacheOptions = {
19
- cacheMutationState: true,
20
- cacheEntities: true,
21
- };
22
- const useMutation = (cache, options) => {
23
- var _a, _b;
24
- const { mutation: mutationKey, cacheOptions = (_a = cache.mutations[mutationKey].cacheOptions) !== null && _a !== void 0 ? _a : exports.defaultMutationCacheOptions, } = options;
25
- // Check values that should be set once.
26
- // Can be removed from deps.
27
- cache.options.validateHookArguments &&
28
- (() => {
29
- ;
30
- [
31
- ['cache', cache],
32
- ['cache.options', cache.options],
33
- ['cache.options.logsEnabled', cache.options.logsEnabled],
34
- ['cacheStateSelector', cache.cacheStateSelector],
35
- ['mutationKey', mutationKey],
36
- ['cacheOptions.cacheEntities', cacheOptions.cacheEntities],
37
- ['cacheOptions.cacheMutationState', cacheOptions.cacheMutationState],
38
- ]
39
- // eslint-disable-next-line react-hooks/rules-of-hooks
40
- .forEach((args) => (0, utilsAndConstants_1.useAssertValueNotChanged)(...args));
41
- })();
18
+ const useMutation = (cache, options, abortControllers) => {
19
+ var _a;
20
+ const { mutation: mutationKey } = options;
42
21
  const store = (0, react_redux_1.useStore)();
43
22
  // Using single useMemo for performance reasons
44
23
  const [mutationStateSelector, mutate, abort] = (0, react_1.useMemo)(() => {
@@ -54,27 +33,26 @@ const useMutation = (cache, options) => {
54
33
  },
55
34
  // mutate
56
35
  (params) => __awaiter(void 0, void 0, void 0, function* () {
57
- yield (0, mutate_1.mutate)('useMutation.mutate', false, store, cache, mutationKey, cacheOptions, params);
36
+ yield (0, mutate_1.mutate)('useMutation.mutate', false, store, cache, mutationKey, params, abortControllers);
58
37
  }),
59
38
  // abort
60
39
  () => {
61
- const abortController = (0, mutate_1.getAbortController)(store, mutationKey);
40
+ var _a;
41
+ const abortController = (_a = abortControllers.get(store)) === null || _a === void 0 ? void 0 : _a[mutationKey];
62
42
  if (abortController === undefined || abortController.signal.aborted) {
63
43
  return false;
64
44
  }
65
45
  abortController.abort();
66
- cacheOptions.cacheMutationState &&
67
- store.dispatch((0, reducer_1.setMutationStateAndEntities)(mutationKey, {
68
- loading: false,
69
- }));
46
+ store.dispatch((0, reducer_1.setMutationStateAndEntities)(mutationKey, {
47
+ loading: false,
48
+ }));
70
49
  return true;
71
50
  },
72
51
  ];
73
- },
74
- // eslint-disable-next-line react-hooks/exhaustive-deps
75
- [store, cacheOptions.cacheEntities, cacheOptions.cacheMutationState]);
52
+ // eslint-disable-next-line react-hooks/exhaustive-deps
53
+ }, [mutationKey, store]);
76
54
  // @ts-expect-error fix later
77
- const mutationState = (_b = (0, react_redux_1.useSelector)(mutationStateSelector)) !== null && _b !== void 0 ? _b : utilsAndConstants_1.defaultQueryMutationState;
55
+ const mutationState = (_a = (0, react_redux_1.useSelector)(mutationStateSelector)) !== null && _a !== void 0 ? _a : utilsAndConstants_1.defaultQueryMutationState;
78
56
  cache.options.logsEnabled &&
79
57
  (0, utilsAndConstants_1.log)('useMutation', {
80
58
  options,
@@ -1,8 +1,2 @@
1
- import { Cache, QueryCacheOptions, QueryCachePolicy, QueryMutationState, Typenames, UseQueryOptions } from './types';
2
- export declare const queryCacheOptionsByPolicy: Record<QueryCachePolicy, QueryCacheOptions>;
3
- export declare const defaultQueryCacheOptions: {
4
- readonly policy: "cache-first";
5
- readonly cacheQueryState: true;
6
- readonly cacheEntities: true;
7
- };
1
+ import { Cache, QueryMutationState, Typenames, UseQueryOptions } from './types';
8
2
  export declare const useQuery: <T extends Typenames, QP, QR, MP, MR, QK extends keyof QP | keyof QR>(cache: Cache<T, QP, QR, MP, MR>, options: UseQueryOptions<T, QP, QR, MP, MR, QK>) => readonly [QueryMutationState<QK extends keyof QP & keyof QR ? QR[QK] : never>, () => Promise<void>];
package/dist/useQuery.js CHANGED
@@ -9,84 +9,34 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  });
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.useQuery = exports.defaultQueryCacheOptions = exports.queryCacheOptionsByPolicy = void 0;
12
+ exports.useQuery = void 0;
13
13
  const react_1 = require("react");
14
14
  const react_redux_1 = require("react-redux");
15
15
  const query_1 = require("./query");
16
16
  const utilsAndConstants_1 = require("./utilsAndConstants");
17
- const cacheFirstOptions = {
18
- policy: 'cache-first',
19
- cacheQueryState: true,
20
- cacheEntities: true,
21
- };
22
- exports.queryCacheOptionsByPolicy = {
23
- 'cache-first': cacheFirstOptions,
24
- 'cache-and-fetch': Object.assign(Object.assign({}, cacheFirstOptions), { policy: 'cache-and-fetch' }),
25
- };
26
- exports.defaultQueryCacheOptions = cacheFirstOptions;
27
17
  const useQuery = (cache, options) => {
28
18
  var _a, _b, _c;
29
- const { query: queryKey, skip, params, cacheOptions: cacheOptionsOrPolicy = (_a = cache.queries[queryKey].cacheOptions) !== null && _a !== void 0 ? _a : exports.defaultQueryCacheOptions, getCacheKey = cache.queries[queryKey].getCacheKey, } = options;
19
+ const { query: queryKey, skip, params, cachePolicy = (_a = cache.queries[queryKey].cachePolicy) !== null && _a !== void 0 ? _a : 'cache-first', getCacheKey = (_b = cache.queries[queryKey].getCacheKey) !== null && _b !== void 0 ? _b : (utilsAndConstants_1.defaultGetCacheKey), } = options;
30
20
  const logsEnabled = cache.options.logsEnabled;
31
- const getParamsKey = (_b = cache.queries[queryKey].getParamsKey) !== null && _b !== void 0 ? _b : (utilsAndConstants_1.defaultGetParamsKey);
32
21
  const cacheResultSelector = cache.queries[queryKey].resultSelector;
33
22
  const cacheStateSelector = cache.cacheStateSelector;
34
- const cacheOptions = typeof cacheOptionsOrPolicy === 'string'
35
- ? exports.queryCacheOptionsByPolicy[cacheOptionsOrPolicy]
36
- : cacheOptionsOrPolicy;
37
23
  const store = (0, react_redux_1.useStore)();
38
- // Check values that should be set once.
39
- cache.options.validateHookArguments &&
40
- (() => {
41
- ;
42
- [
43
- ['store', store],
44
- ['cache', cache],
45
- ['cache.queries', cache.queries],
46
- ['cacheStateSelector', cache.cacheStateSelector],
47
- ['cacheOptions.cacheEntities', cacheOptions.cacheEntities],
48
- ['cacheOptions.cacheQueryState', cacheOptions.cacheQueryState],
49
- ['options.query', options.query],
50
- ['queryKey', queryKey],
51
- ['resultSelector', cache.queries[queryKey].resultSelector],
52
- ['mergeResults', cache.queries[queryKey].mergeResults],
53
- ['getParamsKey', cache.queries[queryKey].getParamsKey],
54
- ['getCacheKey', cache.queries[queryKey].getCacheKey],
55
- ]
56
- // eslint-disable-next-line react-hooks/rules-of-hooks
57
- .forEach((args) => (0, utilsAndConstants_1.useAssertValueNotChanged)(...args));
58
- })();
59
- const paramsKey = getParamsKey(
60
- // @ts-expect-error fix later
61
- params);
62
- const [cacheKey, resultSelector] = (0, react_1.useMemo)(() => {
63
- return [
64
- // cacheKey
65
- getCacheKey
66
- ? // @ts-expect-error fix types later
67
- getCacheKey(params)
68
- : paramsKey,
69
- // resultSelector
70
- cacheResultSelector &&
71
- ((state) => cacheResultSelector(cacheStateSelector(state),
72
- // @ts-expect-error fix types later
73
- params)),
74
- ];
24
+ // @ts-expect-error fix types later
25
+ const cacheKey = getCacheKey(params);
26
+ const resultSelector = (0, react_1.useMemo)(() => {
27
+ return (cacheResultSelector &&
28
+ ((state) => cacheResultSelector(cacheStateSelector(state),
29
+ // @ts-expect-error fix types later
30
+ params)));
75
31
  // eslint-disable-next-line react-hooks/exhaustive-deps
76
- }, [paramsKey]);
32
+ }, [cacheKey]);
77
33
  // eslint-disable-next-line react-hooks/rules-of-hooks
78
34
  const resultFromSelector = (resultSelector && (0, react_redux_1.useSelector)(resultSelector));
79
35
  const hasResultFromSelector = resultFromSelector !== undefined;
80
36
  const fetch = (0, react_1.useCallback)(() => __awaiter(void 0, void 0, void 0, function* () {
81
- yield (0, query_1.query)('useQuery.fetch', false, store, cache, queryKey, cacheKey, cacheOptions, params);
37
+ yield (0, query_1.query)('useQuery.fetch', false, store, cache, queryKey, cacheKey, params);
82
38
  // eslint-disable-next-line react-hooks/exhaustive-deps
83
- }), [
84
- cacheKey,
85
- paramsKey,
86
- cacheOptions.policy,
87
- cacheOptions.cacheEntities,
88
- cacheOptions.cacheQueryState,
89
- ]);
39
+ }), [store, queryKey, cacheKey]);
90
40
  const queryStateFromSelector = (_c = (0, react_redux_1.useSelector)((state) => {
91
41
  const queryState = cacheStateSelector(state).queries[queryKey][cacheKey];
92
42
  return queryState; // TODO proper type
@@ -96,23 +46,22 @@ const useQuery = (cache, options) => {
96
46
  : queryStateFromSelector;
97
47
  (0, react_1.useEffect)(() => {
98
48
  if (skip) {
99
- logsEnabled && (0, utilsAndConstants_1.log)('useQuery.useEffect skip fetch', { skip, paramsKey });
49
+ logsEnabled && (0, utilsAndConstants_1.log)('useQuery.useEffect skip fetch', { skip, cacheKey });
100
50
  return;
101
51
  }
102
- if (queryState.result != null && cacheOptions.policy === 'cache-first') {
52
+ if (queryState.result != null && cachePolicy === 'cache-first') {
103
53
  logsEnabled &&
104
54
  (0, utilsAndConstants_1.log)('useQuery.useEffect don`t fetch due to cache policy', {
105
55
  result: queryState.result,
106
- policy: cacheOptions.policy,
56
+ cachePolicy,
107
57
  });
108
58
  return;
109
59
  }
110
60
  fetch();
111
61
  // eslint-disable-next-line react-hooks/exhaustive-deps
112
- }, [paramsKey, cacheOptions.policy, skip]);
62
+ }, [cacheKey, cachePolicy, skip]);
113
63
  logsEnabled &&
114
64
  (0, utilsAndConstants_1.log)('useQuery', {
115
- paramsKey,
116
65
  cacheKey,
117
66
  options,
118
67
  resultFromSelector,
@@ -1,20 +1,14 @@
1
- import { CacheOptions, EntitiesMap, EntityChanges, Typenames } from './types';
1
+ import { CacheOptions, EntitiesMap, EntityChanges, Key, Typenames } from './types';
2
2
  export declare const PACKAGE_SHORT_NAME = "RRC";
3
3
  export declare const isDev: boolean;
4
- export declare const defaultCacheOptions: {
5
- logsEnabled: boolean;
6
- validateFunctionArguments: boolean;
7
- validateHookArguments: boolean;
8
- };
9
4
  export declare const defaultQueryMutationState: {
10
5
  readonly loading: false;
11
6
  readonly error: undefined;
12
7
  };
13
- export declare const defaultGetParamsKey: <P = unknown>(params: P) => string;
14
- export declare const useAssertValueNotChanged: (name: string, value: unknown) => void;
8
+ export declare const defaultGetCacheKey: <P = unknown>(params: P) => Key;
15
9
  export declare const log: (tag: string, data?: unknown) => void;
16
10
  /**
17
- * Process changes to entities map.
18
- * @return `undefined` if nothing to change, otherwise processed entities map.
11
+ * Apply changes to the entities map.
12
+ * @return `undefined` if nothing to change, otherwise new entities map with applied changes.
19
13
  */
20
- export declare const processEntityChanges: <T extends Typenames>(entities: EntitiesMap<T>, changes: EntityChanges<T>, options: CacheOptions) => EntitiesMap<T> | undefined;
14
+ export declare const applyEntityChanges: <T extends Typenames>(entities: EntitiesMap<T>, changes: EntityChanges<T>, options: CacheOptions) => EntitiesMap<T> | undefined;
@@ -1,7 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.processEntityChanges = exports.log = exports.useAssertValueNotChanged = exports.defaultGetParamsKey = exports.defaultQueryMutationState = exports.defaultCacheOptions = exports.isDev = exports.PACKAGE_SHORT_NAME = void 0;
4
- const react_1 = require("react");
3
+ exports.applyEntityChanges = exports.log = exports.defaultGetCacheKey = exports.defaultQueryMutationState = exports.isDev = exports.PACKAGE_SHORT_NAME = void 0;
5
4
  exports.PACKAGE_SHORT_NAME = 'RRC';
6
5
  exports.isDev = (() => {
7
6
  try {
@@ -12,15 +11,11 @@ exports.isDev = (() => {
12
11
  return process.env.NODE_ENV === 'development';
13
12
  }
14
13
  })();
15
- exports.defaultCacheOptions = {
16
- logsEnabled: false,
17
- validateFunctionArguments: true,
18
- validateHookArguments: true,
19
- };
20
14
  exports.defaultQueryMutationState = { loading: false, error: undefined };
21
- const defaultGetParamsKey = (params) => {
15
+ const defaultGetCacheKey = (params) => {
22
16
  switch (typeof params) {
23
17
  case 'string':
18
+ case 'symbol':
24
19
  return params;
25
20
  case 'object':
26
21
  return JSON.stringify(params);
@@ -28,27 +23,16 @@ const defaultGetParamsKey = (params) => {
28
23
  return String(params);
29
24
  }
30
25
  };
31
- exports.defaultGetParamsKey = defaultGetParamsKey;
32
- const useAssertValueNotChanged = (name, value) => {
33
- const firstMountRef = (0, react_1.useRef)(false);
34
- (0, react_1.useMemo)(() => {
35
- if (firstMountRef.current) {
36
- throw new Error(`${name} should not be modified`);
37
- }
38
- firstMountRef.current = true;
39
- // eslint-disable-next-line react-hooks/exhaustive-deps
40
- }, [value]);
41
- };
42
- exports.useAssertValueNotChanged = useAssertValueNotChanged;
26
+ exports.defaultGetCacheKey = defaultGetCacheKey;
43
27
  const log = (tag, data) => {
44
28
  console.debug(`@${exports.PACKAGE_SHORT_NAME} [${tag}]`, data);
45
29
  };
46
30
  exports.log = log;
47
31
  /**
48
- * Process changes to entities map.
49
- * @return `undefined` if nothing to change, otherwise processed entities map.
32
+ * Apply changes to the entities map.
33
+ * @return `undefined` if nothing to change, otherwise new entities map with applied changes.
50
34
  */
51
- const processEntityChanges = (entities, changes, options) => {
35
+ const applyEntityChanges = (entities, changes, options) => {
52
36
  var _a, _b, _c;
53
37
  if (options.validateFunctionArguments) {
54
38
  // check for merge and entities both set
@@ -99,11 +83,11 @@ const processEntityChanges = (entities, changes, options) => {
99
83
  result[typename] = newEntities;
100
84
  }
101
85
  options.logsEnabled &&
102
- (0, exports.log)('processEntityChanges', {
86
+ (0, exports.log)('applyEntityChanges', {
103
87
  entities,
104
88
  changes,
105
89
  result,
106
90
  });
107
91
  return result;
108
92
  };
109
- exports.processEntityChanges = processEntityChanges;
93
+ exports.applyEntityChanges = applyEntityChanges;
package/package.json CHANGED
@@ -2,14 +2,15 @@
2
2
  "name": "react-redux-cache",
3
3
  "author": "Alexander Danilov",
4
4
  "license": "MIT",
5
- "version": "0.0.10",
5
+ "version": "0.0.12",
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",
9
9
  "scripts": {
10
10
  "example": "(cd example && yarn && yarn start)",
11
11
  "clean": "rm -rf dist",
12
- "build": "yarn clean && tsc && yarn pack -f package.tgz",
12
+ "lint": "yarn eslint src",
13
+ "build": "yarn clean && yarn lint && tsc && yarn pack -f package.tgz",
13
14
  "test": "node node_modules/jest/bin/jest.js",
14
15
  "prepublishOnly": "yarn build && yarn test"
15
16
  },