floppy-disk 2.0.2 → 2.1.0-beta.1

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/esm/index.d.ts CHANGED
@@ -1,2 +1,3 @@
1
+ export { hashStoreKey } from './utils';
1
2
  export * from './vanilla';
2
3
  export * from './react';
package/esm/index.js CHANGED
@@ -1,2 +1,3 @@
1
+ export { hashStoreKey } from './utils';
1
2
  export * from './vanilla';
2
3
  export * from './react';
@@ -4,6 +4,10 @@ export type QueryState<TKey extends StoreKey = StoreKey, TResponse = any, TData
4
4
  * Query store key, an object that will be hashed into a string as a query store identifier.
5
5
  */
6
6
  key: TKey;
7
+ /**
8
+ * Query store key hash, a string used as a query store identifier.
9
+ */
10
+ keyHash: string;
7
11
  /**
8
12
  * Will only be called if the data is stale or empty.
9
13
  */
@@ -1,5 +1,5 @@
1
1
  import { useState } from 'preact/hooks';
2
- import { hashStoreKey, identityFn, noop } from '../utils';
2
+ import { identityFn, noop } from '../utils';
3
3
  import { createStores } from './create-stores';
4
4
  const getDecision = (value, param, { ifTrue, ifAlways }) => {
5
5
  if (value === true || (typeof value === 'function' && value(param) === true)) {
@@ -9,7 +9,6 @@ const getDecision = (value, param, { ifTrue, ifAlways }) => {
9
9
  ifAlways();
10
10
  }
11
11
  };
12
- const DEFAULT_STALE_TIME = 3000; // 3 seconds
13
12
  const INITIAL_QUERY_STATE = {
14
13
  isWaiting: false,
15
14
  isWaitingNextPage: false,
@@ -41,11 +40,13 @@ const useQueryDefaultDeps = (state) => [
41
40
  state.hasNextPage,
42
41
  ];
43
42
  export const createQuery = (queryFn, options = {}) => {
44
- const { onFirstSubscribe = noop, onSubscribe = noop, onLastUnsubscribe = noop, onBeforeChangeKey = noop, defaultDeps = useQueryDefaultDeps, select = identityFn, staleTime = DEFAULT_STALE_TIME, fetchOnMount = true, fetchOnWindowFocus = true, enabled = true, retry = 1, retryDelay = 3000, keepPreviousData, getNextPageParam = () => undefined, onSuccess = noop, onError = noop, onSettled = noop, hashKeyFn = hashStoreKey, ...createStoresOptions } = options;
43
+ const { onFirstSubscribe = noop, onSubscribe = noop, onLastUnsubscribe = noop, onBeforeChangeKey = noop, defaultDeps = useQueryDefaultDeps, select = identityFn, staleTime = 3000, // 3 seconds
44
+ fetchOnMount = true, fetchOnWindowFocus = true, enabled = true, retry = 1, retryDelay = 3000, // 3 seconds
45
+ keepPreviousData, getNextPageParam = () => undefined, onSuccess = noop, onError = noop, onSettled = noop, ...createStoresOptions } = options;
45
46
  const retryTimeoutId = new Map();
46
47
  const retryNextPageTimeoutId = new Map();
47
48
  const preventReplaceResponse = new Map(); // Prevent optimistic data to be replaced
48
- const useQuery = createStores(({ key: _key, get, set }) => {
49
+ const useQuery = createStores(({ get, set, key: _key, keyHash }) => {
49
50
  const key = _key;
50
51
  const getRetryProps = (error, retryCount) => {
51
52
  const maxRetryCount = (typeof retry === 'function' ? retry(error, key) : retry) || 0;
@@ -70,13 +71,13 @@ export const createQuery = (queryFn, options = {}) => {
70
71
  set({ isGoingToRetry: false, isWaiting: true });
71
72
  else
72
73
  set({ isGoingToRetry: false, isWaiting: true, isRefetching: true });
73
- clearTimeout(retryTimeoutId.get(hashKeyFn(key)));
74
+ clearTimeout(retryTimeoutId.get(keyHash));
74
75
  }
75
76
  const stateBeforeCallQuery = { ...get(), pageParam };
76
- preventReplaceResponse.set(hashKeyFn(key), false);
77
+ preventReplaceResponse.set(keyHash, false);
77
78
  queryFn(key, stateBeforeCallQuery)
78
79
  .then((response) => {
79
- if (preventReplaceResponse.get(hashKeyFn(key))) {
80
+ if (preventReplaceResponse.get(keyHash)) {
80
81
  set({ isWaiting: false });
81
82
  return;
82
83
  }
@@ -144,7 +145,7 @@ export const createQuery = (queryFn, options = {}) => {
144
145
  hasNextPage: pageParam !== undefined,
145
146
  });
146
147
  if (shouldRetry) {
147
- retryTimeoutId.set(hashKeyFn(key), window.setTimeout(() => {
148
+ retryTimeoutId.set(keyHash, window.setTimeout(() => {
148
149
  set({ retryCount: prevState.retryCount + 1 });
149
150
  callQuery();
150
151
  }, delay));
@@ -172,7 +173,7 @@ export const createQuery = (queryFn, options = {}) => {
172
173
  if (isWaitingNextPage || !hasNextPage)
173
174
  return;
174
175
  set({ isWaitingNextPage: true, isGoingToRetryNextPage: false });
175
- clearTimeout(retryNextPageTimeoutId.get(hashKeyFn(key)));
176
+ clearTimeout(retryNextPageTimeoutId.get(keyHash));
176
177
  queryFn(key, { ...state, pageParam })
177
178
  .then((response) => {
178
179
  const newPageParam = getNextPageParam(response, pageParams.length);
@@ -197,7 +198,7 @@ export const createQuery = (queryFn, options = {}) => {
197
198
  isGoingToRetryNextPage: shouldRetry,
198
199
  });
199
200
  if (shouldRetry) {
200
- retryNextPageTimeoutId.set(hashKeyFn(key), window.setTimeout(() => {
201
+ retryNextPageTimeoutId.set(keyHash, window.setTimeout(() => {
201
202
  set({ retryNextPageCount: prevState.retryNextPageCount + 1 });
202
203
  fetchNextPage();
203
204
  }, delay));
@@ -207,6 +208,7 @@ export const createQuery = (queryFn, options = {}) => {
207
208
  return {
208
209
  ...INITIAL_QUERY_STATE,
209
210
  key,
211
+ keyHash,
210
212
  fetch,
211
213
  forceFetch,
212
214
  fetchNextPage,
@@ -225,7 +227,6 @@ export const createQuery = (queryFn, options = {}) => {
225
227
  return {
226
228
  ...createStoresOptions,
227
229
  defaultDeps,
228
- hashKeyFn,
229
230
  onFirstSubscribe: (state) => {
230
231
  if (typeof window !== 'undefined' && fetchOnWindowFocus) {
231
232
  window.addEventListener('focus', fetchWindowFocusHandler);
@@ -244,8 +245,8 @@ export const createQuery = (queryFn, options = {}) => {
244
245
  window.removeEventListener('focus', fetchWindowFocusHandler);
245
246
  }
246
247
  useQuery.set(state.key, { retryCount: 0, retryNextPageCount: 0 }, true);
247
- clearTimeout(retryTimeoutId.get(hashKeyFn(state.key)));
248
- clearTimeout(retryNextPageTimeoutId.get(hashKeyFn(state.key)));
248
+ clearTimeout(retryTimeoutId.get(state.keyHash));
249
+ clearTimeout(retryNextPageTimeoutId.get(state.keyHash));
249
250
  onLastUnsubscribe(state);
250
251
  },
251
252
  onBeforeChangeKey: (nextKey, prevKey) => {
@@ -323,7 +324,7 @@ export const createQuery = (queryFn, options = {}) => {
323
324
  response: optimisticResponse,
324
325
  data: select(optimisticResponse, { key: key, data: null }),
325
326
  });
326
- preventReplaceResponse.set(hashKeyFn(key), true);
327
+ preventReplaceResponse.set(prevState.keyHash, true);
327
328
  const revert = () => {
328
329
  useQuery.set(key, {
329
330
  isOptimisticData: false,
@@ -3,9 +3,10 @@ import { WatchProps } from './create-store';
3
3
  type Maybe<T> = T | null | undefined;
4
4
  export type StoreKey = Record<string, any> | undefined;
5
5
  export type StoresInitializer<TKey extends StoreKey = StoreKey, T extends StoreData = StoreData> = (api: {
6
- key: TKey;
7
6
  get: () => T;
8
7
  set: (value: SetStoreData<T>, silent?: boolean) => void;
8
+ key: TKey;
9
+ keyHash: string;
9
10
  }) => T;
10
11
  export type UseStores<TKey extends StoreKey = StoreKey, T extends StoreData = StoreData> = {
11
12
  /**
@@ -6,11 +6,11 @@ export const createStores = (initializer, options = {}) => {
6
6
  const stores = new Map();
7
7
  const getStore = (_key) => {
8
8
  const key = _key || {};
9
- const normalizedKey = hashKeyFn(key);
10
- if (!stores.has(normalizedKey)) {
11
- stores.set(normalizedKey, initStore((api) => initializer({ key, ...api }), options));
9
+ const keyHash = hashKeyFn(key);
10
+ if (!stores.has(keyHash)) {
11
+ stores.set(keyHash, initStore((api) => initializer({ key, keyHash, ...api }), options));
12
12
  }
13
- return stores.get(normalizedKey);
13
+ return stores.get(keyHash);
14
14
  };
15
15
  /**
16
16
  * IMPORTANT NOTE: selectDeps function must not be changed after initialization.
@@ -18,9 +18,9 @@ export const createStores = (initializer, options = {}) => {
18
18
  const useStores = (...args) => {
19
19
  const [_key, selectDeps = defaultDeps] = (typeof args[0] === 'function' ? [{}, args[0]] : args);
20
20
  const key = _key || {};
21
- const normalizedKey = hashKeyFn(key);
21
+ const keyHash = hashKeyFn(key);
22
22
  // eslint-disable-next-line react-hooks/exhaustive-deps
23
- const { get, subscribe } = useMemo(() => getStore(key), [normalizedKey]);
23
+ const { get, subscribe } = useMemo(() => getStore(key), [keyHash]);
24
24
  const [state, setState] = useState(get);
25
25
  const isFirstRender = useRef(true);
26
26
  const prevKey = useRef(key);
@@ -34,7 +34,7 @@ export const createStores = (initializer, options = {}) => {
34
34
  const unsubs = subscribe(setState, selectDeps);
35
35
  return unsubs;
36
36
  // eslint-disable-next-line react-hooks/exhaustive-deps
37
- }, [normalizedKey]);
37
+ }, [keyHash]);
38
38
  return state;
39
39
  };
40
40
  useStores.get = (key) => {
@@ -4,6 +4,10 @@ export type QueryState<TKey extends StoreKey = StoreKey, TResponse = any, TData
4
4
  * Query store key, an object that will be hashed into a string as a query store identifier.
5
5
  */
6
6
  key: TKey;
7
+ /**
8
+ * Query store key hash, a string used as a query store identifier.
9
+ */
10
+ keyHash: string;
7
11
  /**
8
12
  * Will only be called if the data is stale or empty.
9
13
  */
@@ -1,5 +1,5 @@
1
1
  import { useState } from 'react';
2
- import { hashStoreKey, identityFn, noop } from '../utils';
2
+ import { identityFn, noop } from '../utils';
3
3
  import { createStores } from './create-stores';
4
4
  const getDecision = (value, param, { ifTrue, ifAlways }) => {
5
5
  if (value === true || (typeof value === 'function' && value(param) === true)) {
@@ -9,7 +9,6 @@ const getDecision = (value, param, { ifTrue, ifAlways }) => {
9
9
  ifAlways();
10
10
  }
11
11
  };
12
- const DEFAULT_STALE_TIME = 3000; // 3 seconds
13
12
  const INITIAL_QUERY_STATE = {
14
13
  isWaiting: false,
15
14
  isWaitingNextPage: false,
@@ -41,11 +40,13 @@ const useQueryDefaultDeps = (state) => [
41
40
  state.hasNextPage,
42
41
  ];
43
42
  export const createQuery = (queryFn, options = {}) => {
44
- const { onFirstSubscribe = noop, onSubscribe = noop, onLastUnsubscribe = noop, onBeforeChangeKey = noop, defaultDeps = useQueryDefaultDeps, select = identityFn, staleTime = DEFAULT_STALE_TIME, fetchOnMount = true, fetchOnWindowFocus = true, enabled = true, retry = 1, retryDelay = 3000, keepPreviousData, getNextPageParam = () => undefined, onSuccess = noop, onError = noop, onSettled = noop, hashKeyFn = hashStoreKey, ...createStoresOptions } = options;
43
+ const { onFirstSubscribe = noop, onSubscribe = noop, onLastUnsubscribe = noop, onBeforeChangeKey = noop, defaultDeps = useQueryDefaultDeps, select = identityFn, staleTime = 3000, // 3 seconds
44
+ fetchOnMount = true, fetchOnWindowFocus = true, enabled = true, retry = 1, retryDelay = 3000, // 3 seconds
45
+ keepPreviousData, getNextPageParam = () => undefined, onSuccess = noop, onError = noop, onSettled = noop, ...createStoresOptions } = options;
45
46
  const retryTimeoutId = new Map();
46
47
  const retryNextPageTimeoutId = new Map();
47
48
  const preventReplaceResponse = new Map(); // Prevent optimistic data to be replaced
48
- const useQuery = createStores(({ key: _key, get, set }) => {
49
+ const useQuery = createStores(({ get, set, key: _key, keyHash }) => {
49
50
  const key = _key;
50
51
  const getRetryProps = (error, retryCount) => {
51
52
  const maxRetryCount = (typeof retry === 'function' ? retry(error, key) : retry) || 0;
@@ -70,13 +71,13 @@ export const createQuery = (queryFn, options = {}) => {
70
71
  set({ isGoingToRetry: false, isWaiting: true });
71
72
  else
72
73
  set({ isGoingToRetry: false, isWaiting: true, isRefetching: true });
73
- clearTimeout(retryTimeoutId.get(hashKeyFn(key)));
74
+ clearTimeout(retryTimeoutId.get(keyHash));
74
75
  }
75
76
  const stateBeforeCallQuery = { ...get(), pageParam };
76
- preventReplaceResponse.set(hashKeyFn(key), false);
77
+ preventReplaceResponse.set(keyHash, false);
77
78
  queryFn(key, stateBeforeCallQuery)
78
79
  .then((response) => {
79
- if (preventReplaceResponse.get(hashKeyFn(key))) {
80
+ if (preventReplaceResponse.get(keyHash)) {
80
81
  set({ isWaiting: false });
81
82
  return;
82
83
  }
@@ -144,7 +145,7 @@ export const createQuery = (queryFn, options = {}) => {
144
145
  hasNextPage: pageParam !== undefined,
145
146
  });
146
147
  if (shouldRetry) {
147
- retryTimeoutId.set(hashKeyFn(key), window.setTimeout(() => {
148
+ retryTimeoutId.set(keyHash, window.setTimeout(() => {
148
149
  set({ retryCount: prevState.retryCount + 1 });
149
150
  callQuery();
150
151
  }, delay));
@@ -172,7 +173,7 @@ export const createQuery = (queryFn, options = {}) => {
172
173
  if (isWaitingNextPage || !hasNextPage)
173
174
  return;
174
175
  set({ isWaitingNextPage: true, isGoingToRetryNextPage: false });
175
- clearTimeout(retryNextPageTimeoutId.get(hashKeyFn(key)));
176
+ clearTimeout(retryNextPageTimeoutId.get(keyHash));
176
177
  queryFn(key, { ...state, pageParam })
177
178
  .then((response) => {
178
179
  const newPageParam = getNextPageParam(response, pageParams.length);
@@ -197,7 +198,7 @@ export const createQuery = (queryFn, options = {}) => {
197
198
  isGoingToRetryNextPage: shouldRetry,
198
199
  });
199
200
  if (shouldRetry) {
200
- retryNextPageTimeoutId.set(hashKeyFn(key), window.setTimeout(() => {
201
+ retryNextPageTimeoutId.set(keyHash, window.setTimeout(() => {
201
202
  set({ retryNextPageCount: prevState.retryNextPageCount + 1 });
202
203
  fetchNextPage();
203
204
  }, delay));
@@ -207,6 +208,7 @@ export const createQuery = (queryFn, options = {}) => {
207
208
  return {
208
209
  ...INITIAL_QUERY_STATE,
209
210
  key,
211
+ keyHash,
210
212
  fetch,
211
213
  forceFetch,
212
214
  fetchNextPage,
@@ -225,7 +227,6 @@ export const createQuery = (queryFn, options = {}) => {
225
227
  return {
226
228
  ...createStoresOptions,
227
229
  defaultDeps,
228
- hashKeyFn,
229
230
  onFirstSubscribe: (state) => {
230
231
  if (typeof window !== 'undefined' && fetchOnWindowFocus) {
231
232
  window.addEventListener('focus', fetchWindowFocusHandler);
@@ -244,8 +245,8 @@ export const createQuery = (queryFn, options = {}) => {
244
245
  window.removeEventListener('focus', fetchWindowFocusHandler);
245
246
  }
246
247
  useQuery.set(state.key, { retryCount: 0, retryNextPageCount: 0 }, true);
247
- clearTimeout(retryTimeoutId.get(hashKeyFn(state.key)));
248
- clearTimeout(retryNextPageTimeoutId.get(hashKeyFn(state.key)));
248
+ clearTimeout(retryTimeoutId.get(state.keyHash));
249
+ clearTimeout(retryNextPageTimeoutId.get(state.keyHash));
249
250
  onLastUnsubscribe(state);
250
251
  },
251
252
  onBeforeChangeKey: (nextKey, prevKey) => {
@@ -323,7 +324,7 @@ export const createQuery = (queryFn, options = {}) => {
323
324
  response: optimisticResponse,
324
325
  data: select(optimisticResponse, { key: key, data: null }),
325
326
  });
326
- preventReplaceResponse.set(hashKeyFn(key), true);
327
+ preventReplaceResponse.set(prevState.keyHash, true);
327
328
  const revert = () => {
328
329
  useQuery.set(key, {
329
330
  isOptimisticData: false,
@@ -3,9 +3,10 @@ import { WatchProps } from './create-store';
3
3
  type Maybe<T> = T | null | undefined;
4
4
  export type StoreKey = Record<string, any> | undefined;
5
5
  export type StoresInitializer<TKey extends StoreKey = StoreKey, T extends StoreData = StoreData> = (api: {
6
- key: TKey;
7
6
  get: () => T;
8
7
  set: (value: SetStoreData<T>, silent?: boolean) => void;
8
+ key: TKey;
9
+ keyHash: string;
9
10
  }) => T;
10
11
  export type UseStores<TKey extends StoreKey = StoreKey, T extends StoreData = StoreData> = {
11
12
  /**
@@ -6,11 +6,11 @@ export const createStores = (initializer, options = {}) => {
6
6
  const stores = new Map();
7
7
  const getStore = (_key) => {
8
8
  const key = _key || {};
9
- const normalizedKey = hashKeyFn(key);
10
- if (!stores.has(normalizedKey)) {
11
- stores.set(normalizedKey, initStore((api) => initializer({ key, ...api }), options));
9
+ const keyHash = hashKeyFn(key);
10
+ if (!stores.has(keyHash)) {
11
+ stores.set(keyHash, initStore((api) => initializer({ key, keyHash, ...api }), options));
12
12
  }
13
- return stores.get(normalizedKey);
13
+ return stores.get(keyHash);
14
14
  };
15
15
  /**
16
16
  * IMPORTANT NOTE: selectDeps function must not be changed after initialization.
@@ -18,9 +18,9 @@ export const createStores = (initializer, options = {}) => {
18
18
  const useStores = (...args) => {
19
19
  const [_key, selectDeps = defaultDeps] = (typeof args[0] === 'function' ? [{}, args[0]] : args);
20
20
  const key = _key || {};
21
- const normalizedKey = hashKeyFn(key);
21
+ const keyHash = hashKeyFn(key);
22
22
  // eslint-disable-next-line react-hooks/exhaustive-deps
23
- const { get, subscribe } = useMemo(() => getStore(key), [normalizedKey]);
23
+ const { get, subscribe } = useMemo(() => getStore(key), [keyHash]);
24
24
  const [state, setState] = useState(get);
25
25
  const isFirstRender = useRef(true);
26
26
  const prevKey = useRef(key);
@@ -34,7 +34,7 @@ export const createStores = (initializer, options = {}) => {
34
34
  const unsubs = subscribe(setState, selectDeps);
35
35
  return unsubs;
36
36
  // eslint-disable-next-line react-hooks/exhaustive-deps
37
- }, [normalizedKey]);
37
+ }, [keyHash]);
38
38
  return state;
39
39
  };
40
40
  useStores.get = (key) => {
package/lib/index.d.ts CHANGED
@@ -1,2 +1,3 @@
1
+ export { hashStoreKey } from './utils';
1
2
  export * from './vanilla';
2
3
  export * from './react';
package/lib/index.js CHANGED
@@ -1,5 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.hashStoreKey = void 0;
3
4
  const tslib_1 = require("tslib");
5
+ var utils_1 = require("./utils");
6
+ Object.defineProperty(exports, "hashStoreKey", { enumerable: true, get: function () { return utils_1.hashStoreKey; } });
4
7
  tslib_1.__exportStar(require("./vanilla"), exports);
5
8
  tslib_1.__exportStar(require("./react"), exports);
@@ -4,6 +4,10 @@ export type QueryState<TKey extends StoreKey = StoreKey, TResponse = any, TData
4
4
  * Query store key, an object that will be hashed into a string as a query store identifier.
5
5
  */
6
6
  key: TKey;
7
+ /**
8
+ * Query store key hash, a string used as a query store identifier.
9
+ */
10
+ keyHash: string;
7
11
  /**
8
12
  * Will only be called if the data is stale or empty.
9
13
  */
@@ -12,7 +12,6 @@ const getDecision = (value, param, { ifTrue, ifAlways }) => {
12
12
  ifAlways();
13
13
  }
14
14
  };
15
- const DEFAULT_STALE_TIME = 3000; // 3 seconds
16
15
  const INITIAL_QUERY_STATE = {
17
16
  isWaiting: false,
18
17
  isWaitingNextPage: false,
@@ -44,11 +43,13 @@ const useQueryDefaultDeps = (state) => [
44
43
  state.hasNextPage,
45
44
  ];
46
45
  const createQuery = (queryFn, options = {}) => {
47
- const { onFirstSubscribe = utils_1.noop, onSubscribe = utils_1.noop, onLastUnsubscribe = utils_1.noop, onBeforeChangeKey = utils_1.noop, defaultDeps = useQueryDefaultDeps, select = utils_1.identityFn, staleTime = DEFAULT_STALE_TIME, fetchOnMount = true, fetchOnWindowFocus = true, enabled = true, retry = 1, retryDelay = 3000, keepPreviousData, getNextPageParam = () => undefined, onSuccess = utils_1.noop, onError = utils_1.noop, onSettled = utils_1.noop, hashKeyFn = utils_1.hashStoreKey, ...createStoresOptions } = options;
46
+ const { onFirstSubscribe = utils_1.noop, onSubscribe = utils_1.noop, onLastUnsubscribe = utils_1.noop, onBeforeChangeKey = utils_1.noop, defaultDeps = useQueryDefaultDeps, select = utils_1.identityFn, staleTime = 3000, // 3 seconds
47
+ fetchOnMount = true, fetchOnWindowFocus = true, enabled = true, retry = 1, retryDelay = 3000, // 3 seconds
48
+ keepPreviousData, getNextPageParam = () => undefined, onSuccess = utils_1.noop, onError = utils_1.noop, onSettled = utils_1.noop, ...createStoresOptions } = options;
48
49
  const retryTimeoutId = new Map();
49
50
  const retryNextPageTimeoutId = new Map();
50
51
  const preventReplaceResponse = new Map(); // Prevent optimistic data to be replaced
51
- const useQuery = (0, create_stores_1.createStores)(({ key: _key, get, set }) => {
52
+ const useQuery = (0, create_stores_1.createStores)(({ get, set, key: _key, keyHash }) => {
52
53
  const key = _key;
53
54
  const getRetryProps = (error, retryCount) => {
54
55
  const maxRetryCount = (typeof retry === 'function' ? retry(error, key) : retry) || 0;
@@ -73,13 +74,13 @@ const createQuery = (queryFn, options = {}) => {
73
74
  set({ isGoingToRetry: false, isWaiting: true });
74
75
  else
75
76
  set({ isGoingToRetry: false, isWaiting: true, isRefetching: true });
76
- clearTimeout(retryTimeoutId.get(hashKeyFn(key)));
77
+ clearTimeout(retryTimeoutId.get(keyHash));
77
78
  }
78
79
  const stateBeforeCallQuery = { ...get(), pageParam };
79
- preventReplaceResponse.set(hashKeyFn(key), false);
80
+ preventReplaceResponse.set(keyHash, false);
80
81
  queryFn(key, stateBeforeCallQuery)
81
82
  .then((response) => {
82
- if (preventReplaceResponse.get(hashKeyFn(key))) {
83
+ if (preventReplaceResponse.get(keyHash)) {
83
84
  set({ isWaiting: false });
84
85
  return;
85
86
  }
@@ -147,7 +148,7 @@ const createQuery = (queryFn, options = {}) => {
147
148
  hasNextPage: pageParam !== undefined,
148
149
  });
149
150
  if (shouldRetry) {
150
- retryTimeoutId.set(hashKeyFn(key), window.setTimeout(() => {
151
+ retryTimeoutId.set(keyHash, window.setTimeout(() => {
151
152
  set({ retryCount: prevState.retryCount + 1 });
152
153
  callQuery();
153
154
  }, delay));
@@ -175,7 +176,7 @@ const createQuery = (queryFn, options = {}) => {
175
176
  if (isWaitingNextPage || !hasNextPage)
176
177
  return;
177
178
  set({ isWaitingNextPage: true, isGoingToRetryNextPage: false });
178
- clearTimeout(retryNextPageTimeoutId.get(hashKeyFn(key)));
179
+ clearTimeout(retryNextPageTimeoutId.get(keyHash));
179
180
  queryFn(key, { ...state, pageParam })
180
181
  .then((response) => {
181
182
  const newPageParam = getNextPageParam(response, pageParams.length);
@@ -200,7 +201,7 @@ const createQuery = (queryFn, options = {}) => {
200
201
  isGoingToRetryNextPage: shouldRetry,
201
202
  });
202
203
  if (shouldRetry) {
203
- retryNextPageTimeoutId.set(hashKeyFn(key), window.setTimeout(() => {
204
+ retryNextPageTimeoutId.set(keyHash, window.setTimeout(() => {
204
205
  set({ retryNextPageCount: prevState.retryNextPageCount + 1 });
205
206
  fetchNextPage();
206
207
  }, delay));
@@ -210,6 +211,7 @@ const createQuery = (queryFn, options = {}) => {
210
211
  return {
211
212
  ...INITIAL_QUERY_STATE,
212
213
  key,
214
+ keyHash,
213
215
  fetch,
214
216
  forceFetch,
215
217
  fetchNextPage,
@@ -228,7 +230,6 @@ const createQuery = (queryFn, options = {}) => {
228
230
  return {
229
231
  ...createStoresOptions,
230
232
  defaultDeps,
231
- hashKeyFn,
232
233
  onFirstSubscribe: (state) => {
233
234
  if (typeof window !== 'undefined' && fetchOnWindowFocus) {
234
235
  window.addEventListener('focus', fetchWindowFocusHandler);
@@ -247,8 +248,8 @@ const createQuery = (queryFn, options = {}) => {
247
248
  window.removeEventListener('focus', fetchWindowFocusHandler);
248
249
  }
249
250
  useQuery.set(state.key, { retryCount: 0, retryNextPageCount: 0 }, true);
250
- clearTimeout(retryTimeoutId.get(hashKeyFn(state.key)));
251
- clearTimeout(retryNextPageTimeoutId.get(hashKeyFn(state.key)));
251
+ clearTimeout(retryTimeoutId.get(state.keyHash));
252
+ clearTimeout(retryNextPageTimeoutId.get(state.keyHash));
252
253
  onLastUnsubscribe(state);
253
254
  },
254
255
  onBeforeChangeKey: (nextKey, prevKey) => {
@@ -326,7 +327,7 @@ const createQuery = (queryFn, options = {}) => {
326
327
  response: optimisticResponse,
327
328
  data: select(optimisticResponse, { key: key, data: null }),
328
329
  });
329
- preventReplaceResponse.set(hashKeyFn(key), true);
330
+ preventReplaceResponse.set(prevState.keyHash, true);
330
331
  const revert = () => {
331
332
  useQuery.set(key, {
332
333
  isOptimisticData: false,
@@ -3,9 +3,10 @@ import { WatchProps } from './create-store';
3
3
  type Maybe<T> = T | null | undefined;
4
4
  export type StoreKey = Record<string, any> | undefined;
5
5
  export type StoresInitializer<TKey extends StoreKey = StoreKey, T extends StoreData = StoreData> = (api: {
6
- key: TKey;
7
6
  get: () => T;
8
7
  set: (value: SetStoreData<T>, silent?: boolean) => void;
8
+ key: TKey;
9
+ keyHash: string;
9
10
  }) => T;
10
11
  export type UseStores<TKey extends StoreKey = StoreKey, T extends StoreData = StoreData> = {
11
12
  /**
@@ -9,11 +9,11 @@ const createStores = (initializer, options = {}) => {
9
9
  const stores = new Map();
10
10
  const getStore = (_key) => {
11
11
  const key = _key || {};
12
- const normalizedKey = hashKeyFn(key);
13
- if (!stores.has(normalizedKey)) {
14
- stores.set(normalizedKey, (0, vanilla_1.initStore)((api) => initializer({ key, ...api }), options));
12
+ const keyHash = hashKeyFn(key);
13
+ if (!stores.has(keyHash)) {
14
+ stores.set(keyHash, (0, vanilla_1.initStore)((api) => initializer({ key, keyHash, ...api }), options));
15
15
  }
16
- return stores.get(normalizedKey);
16
+ return stores.get(keyHash);
17
17
  };
18
18
  /**
19
19
  * IMPORTANT NOTE: selectDeps function must not be changed after initialization.
@@ -21,9 +21,9 @@ const createStores = (initializer, options = {}) => {
21
21
  const useStores = (...args) => {
22
22
  const [_key, selectDeps = defaultDeps] = (typeof args[0] === 'function' ? [{}, args[0]] : args);
23
23
  const key = _key || {};
24
- const normalizedKey = hashKeyFn(key);
24
+ const keyHash = hashKeyFn(key);
25
25
  // eslint-disable-next-line react-hooks/exhaustive-deps
26
- const { get, subscribe } = (0, hooks_1.useMemo)(() => getStore(key), [normalizedKey]);
26
+ const { get, subscribe } = (0, hooks_1.useMemo)(() => getStore(key), [keyHash]);
27
27
  const [state, setState] = (0, hooks_1.useState)(get);
28
28
  const isFirstRender = (0, hooks_1.useRef)(true);
29
29
  const prevKey = (0, hooks_1.useRef)(key);
@@ -37,7 +37,7 @@ const createStores = (initializer, options = {}) => {
37
37
  const unsubs = subscribe(setState, selectDeps);
38
38
  return unsubs;
39
39
  // eslint-disable-next-line react-hooks/exhaustive-deps
40
- }, [normalizedKey]);
40
+ }, [keyHash]);
41
41
  return state;
42
42
  };
43
43
  useStores.get = (key) => {
@@ -4,6 +4,10 @@ export type QueryState<TKey extends StoreKey = StoreKey, TResponse = any, TData
4
4
  * Query store key, an object that will be hashed into a string as a query store identifier.
5
5
  */
6
6
  key: TKey;
7
+ /**
8
+ * Query store key hash, a string used as a query store identifier.
9
+ */
10
+ keyHash: string;
7
11
  /**
8
12
  * Will only be called if the data is stale or empty.
9
13
  */
@@ -12,7 +12,6 @@ const getDecision = (value, param, { ifTrue, ifAlways }) => {
12
12
  ifAlways();
13
13
  }
14
14
  };
15
- const DEFAULT_STALE_TIME = 3000; // 3 seconds
16
15
  const INITIAL_QUERY_STATE = {
17
16
  isWaiting: false,
18
17
  isWaitingNextPage: false,
@@ -44,11 +43,13 @@ const useQueryDefaultDeps = (state) => [
44
43
  state.hasNextPage,
45
44
  ];
46
45
  const createQuery = (queryFn, options = {}) => {
47
- const { onFirstSubscribe = utils_1.noop, onSubscribe = utils_1.noop, onLastUnsubscribe = utils_1.noop, onBeforeChangeKey = utils_1.noop, defaultDeps = useQueryDefaultDeps, select = utils_1.identityFn, staleTime = DEFAULT_STALE_TIME, fetchOnMount = true, fetchOnWindowFocus = true, enabled = true, retry = 1, retryDelay = 3000, keepPreviousData, getNextPageParam = () => undefined, onSuccess = utils_1.noop, onError = utils_1.noop, onSettled = utils_1.noop, hashKeyFn = utils_1.hashStoreKey, ...createStoresOptions } = options;
46
+ const { onFirstSubscribe = utils_1.noop, onSubscribe = utils_1.noop, onLastUnsubscribe = utils_1.noop, onBeforeChangeKey = utils_1.noop, defaultDeps = useQueryDefaultDeps, select = utils_1.identityFn, staleTime = 3000, // 3 seconds
47
+ fetchOnMount = true, fetchOnWindowFocus = true, enabled = true, retry = 1, retryDelay = 3000, // 3 seconds
48
+ keepPreviousData, getNextPageParam = () => undefined, onSuccess = utils_1.noop, onError = utils_1.noop, onSettled = utils_1.noop, ...createStoresOptions } = options;
48
49
  const retryTimeoutId = new Map();
49
50
  const retryNextPageTimeoutId = new Map();
50
51
  const preventReplaceResponse = new Map(); // Prevent optimistic data to be replaced
51
- const useQuery = (0, create_stores_1.createStores)(({ key: _key, get, set }) => {
52
+ const useQuery = (0, create_stores_1.createStores)(({ get, set, key: _key, keyHash }) => {
52
53
  const key = _key;
53
54
  const getRetryProps = (error, retryCount) => {
54
55
  const maxRetryCount = (typeof retry === 'function' ? retry(error, key) : retry) || 0;
@@ -73,13 +74,13 @@ const createQuery = (queryFn, options = {}) => {
73
74
  set({ isGoingToRetry: false, isWaiting: true });
74
75
  else
75
76
  set({ isGoingToRetry: false, isWaiting: true, isRefetching: true });
76
- clearTimeout(retryTimeoutId.get(hashKeyFn(key)));
77
+ clearTimeout(retryTimeoutId.get(keyHash));
77
78
  }
78
79
  const stateBeforeCallQuery = { ...get(), pageParam };
79
- preventReplaceResponse.set(hashKeyFn(key), false);
80
+ preventReplaceResponse.set(keyHash, false);
80
81
  queryFn(key, stateBeforeCallQuery)
81
82
  .then((response) => {
82
- if (preventReplaceResponse.get(hashKeyFn(key))) {
83
+ if (preventReplaceResponse.get(keyHash)) {
83
84
  set({ isWaiting: false });
84
85
  return;
85
86
  }
@@ -147,7 +148,7 @@ const createQuery = (queryFn, options = {}) => {
147
148
  hasNextPage: pageParam !== undefined,
148
149
  });
149
150
  if (shouldRetry) {
150
- retryTimeoutId.set(hashKeyFn(key), window.setTimeout(() => {
151
+ retryTimeoutId.set(keyHash, window.setTimeout(() => {
151
152
  set({ retryCount: prevState.retryCount + 1 });
152
153
  callQuery();
153
154
  }, delay));
@@ -175,7 +176,7 @@ const createQuery = (queryFn, options = {}) => {
175
176
  if (isWaitingNextPage || !hasNextPage)
176
177
  return;
177
178
  set({ isWaitingNextPage: true, isGoingToRetryNextPage: false });
178
- clearTimeout(retryNextPageTimeoutId.get(hashKeyFn(key)));
179
+ clearTimeout(retryNextPageTimeoutId.get(keyHash));
179
180
  queryFn(key, { ...state, pageParam })
180
181
  .then((response) => {
181
182
  const newPageParam = getNextPageParam(response, pageParams.length);
@@ -200,7 +201,7 @@ const createQuery = (queryFn, options = {}) => {
200
201
  isGoingToRetryNextPage: shouldRetry,
201
202
  });
202
203
  if (shouldRetry) {
203
- retryNextPageTimeoutId.set(hashKeyFn(key), window.setTimeout(() => {
204
+ retryNextPageTimeoutId.set(keyHash, window.setTimeout(() => {
204
205
  set({ retryNextPageCount: prevState.retryNextPageCount + 1 });
205
206
  fetchNextPage();
206
207
  }, delay));
@@ -210,6 +211,7 @@ const createQuery = (queryFn, options = {}) => {
210
211
  return {
211
212
  ...INITIAL_QUERY_STATE,
212
213
  key,
214
+ keyHash,
213
215
  fetch,
214
216
  forceFetch,
215
217
  fetchNextPage,
@@ -228,7 +230,6 @@ const createQuery = (queryFn, options = {}) => {
228
230
  return {
229
231
  ...createStoresOptions,
230
232
  defaultDeps,
231
- hashKeyFn,
232
233
  onFirstSubscribe: (state) => {
233
234
  if (typeof window !== 'undefined' && fetchOnWindowFocus) {
234
235
  window.addEventListener('focus', fetchWindowFocusHandler);
@@ -247,8 +248,8 @@ const createQuery = (queryFn, options = {}) => {
247
248
  window.removeEventListener('focus', fetchWindowFocusHandler);
248
249
  }
249
250
  useQuery.set(state.key, { retryCount: 0, retryNextPageCount: 0 }, true);
250
- clearTimeout(retryTimeoutId.get(hashKeyFn(state.key)));
251
- clearTimeout(retryNextPageTimeoutId.get(hashKeyFn(state.key)));
251
+ clearTimeout(retryTimeoutId.get(state.keyHash));
252
+ clearTimeout(retryNextPageTimeoutId.get(state.keyHash));
252
253
  onLastUnsubscribe(state);
253
254
  },
254
255
  onBeforeChangeKey: (nextKey, prevKey) => {
@@ -326,7 +327,7 @@ const createQuery = (queryFn, options = {}) => {
326
327
  response: optimisticResponse,
327
328
  data: select(optimisticResponse, { key: key, data: null }),
328
329
  });
329
- preventReplaceResponse.set(hashKeyFn(key), true);
330
+ preventReplaceResponse.set(prevState.keyHash, true);
330
331
  const revert = () => {
331
332
  useQuery.set(key, {
332
333
  isOptimisticData: false,
@@ -3,9 +3,10 @@ import { WatchProps } from './create-store';
3
3
  type Maybe<T> = T | null | undefined;
4
4
  export type StoreKey = Record<string, any> | undefined;
5
5
  export type StoresInitializer<TKey extends StoreKey = StoreKey, T extends StoreData = StoreData> = (api: {
6
- key: TKey;
7
6
  get: () => T;
8
7
  set: (value: SetStoreData<T>, silent?: boolean) => void;
8
+ key: TKey;
9
+ keyHash: string;
9
10
  }) => T;
10
11
  export type UseStores<TKey extends StoreKey = StoreKey, T extends StoreData = StoreData> = {
11
12
  /**
@@ -9,11 +9,11 @@ const createStores = (initializer, options = {}) => {
9
9
  const stores = new Map();
10
10
  const getStore = (_key) => {
11
11
  const key = _key || {};
12
- const normalizedKey = hashKeyFn(key);
13
- if (!stores.has(normalizedKey)) {
14
- stores.set(normalizedKey, (0, vanilla_1.initStore)((api) => initializer({ key, ...api }), options));
12
+ const keyHash = hashKeyFn(key);
13
+ if (!stores.has(keyHash)) {
14
+ stores.set(keyHash, (0, vanilla_1.initStore)((api) => initializer({ key, keyHash, ...api }), options));
15
15
  }
16
- return stores.get(normalizedKey);
16
+ return stores.get(keyHash);
17
17
  };
18
18
  /**
19
19
  * IMPORTANT NOTE: selectDeps function must not be changed after initialization.
@@ -21,9 +21,9 @@ const createStores = (initializer, options = {}) => {
21
21
  const useStores = (...args) => {
22
22
  const [_key, selectDeps = defaultDeps] = (typeof args[0] === 'function' ? [{}, args[0]] : args);
23
23
  const key = _key || {};
24
- const normalizedKey = hashKeyFn(key);
24
+ const keyHash = hashKeyFn(key);
25
25
  // eslint-disable-next-line react-hooks/exhaustive-deps
26
- const { get, subscribe } = (0, react_1.useMemo)(() => getStore(key), [normalizedKey]);
26
+ const { get, subscribe } = (0, react_1.useMemo)(() => getStore(key), [keyHash]);
27
27
  const [state, setState] = (0, react_1.useState)(get);
28
28
  const isFirstRender = (0, react_1.useRef)(true);
29
29
  const prevKey = (0, react_1.useRef)(key);
@@ -37,7 +37,7 @@ const createStores = (initializer, options = {}) => {
37
37
  const unsubs = subscribe(setState, selectDeps);
38
38
  return unsubs;
39
39
  // eslint-disable-next-line react-hooks/exhaustive-deps
40
- }, [normalizedKey]);
40
+ }, [keyHash]);
41
41
  return state;
42
42
  };
43
43
  useStores.get = (key) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "floppy-disk",
3
- "version": "2.0.2",
3
+ "version": "2.1.0-beta.1",
4
4
  "description": "FloppyDisk - lightweight, simple, and powerful state management library",
5
5
  "keywords": [
6
6
  "state",