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 +1 -0
- package/esm/index.js +1 -0
- package/esm/preact/create-query.d.ts +4 -0
- package/esm/preact/create-query.js +15 -14
- package/esm/preact/create-stores.d.ts +2 -1
- package/esm/preact/create-stores.js +7 -7
- package/esm/react/create-query.d.ts +4 -0
- package/esm/react/create-query.js +15 -14
- package/esm/react/create-stores.d.ts +2 -1
- package/esm/react/create-stores.js +7 -7
- package/lib/index.d.ts +1 -0
- package/lib/index.js +3 -0
- package/lib/preact/create-query.d.ts +4 -0
- package/lib/preact/create-query.js +14 -13
- package/lib/preact/create-stores.d.ts +2 -1
- package/lib/preact/create-stores.js +7 -7
- package/lib/react/create-query.d.ts +4 -0
- package/lib/react/create-query.js +14 -13
- package/lib/react/create-stores.d.ts +2 -1
- package/lib/react/create-stores.js +7 -7
- package/package.json +1 -1
package/esm/index.d.ts
CHANGED
package/esm/index.js
CHANGED
|
@@ -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 {
|
|
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 =
|
|
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,
|
|
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(
|
|
74
|
+
clearTimeout(retryTimeoutId.get(keyHash));
|
|
74
75
|
}
|
|
75
76
|
const stateBeforeCallQuery = { ...get(), pageParam };
|
|
76
|
-
preventReplaceResponse.set(
|
|
77
|
+
preventReplaceResponse.set(keyHash, false);
|
|
77
78
|
queryFn(key, stateBeforeCallQuery)
|
|
78
79
|
.then((response) => {
|
|
79
|
-
if (preventReplaceResponse.get(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
248
|
-
clearTimeout(retryNextPageTimeoutId.get(
|
|
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(
|
|
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
|
|
10
|
-
if (!stores.has(
|
|
11
|
-
stores.set(
|
|
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(
|
|
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
|
|
21
|
+
const keyHash = hashKeyFn(key);
|
|
22
22
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
23
|
-
const { get, subscribe } = useMemo(() => getStore(key), [
|
|
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
|
-
}, [
|
|
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 {
|
|
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 =
|
|
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,
|
|
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(
|
|
74
|
+
clearTimeout(retryTimeoutId.get(keyHash));
|
|
74
75
|
}
|
|
75
76
|
const stateBeforeCallQuery = { ...get(), pageParam };
|
|
76
|
-
preventReplaceResponse.set(
|
|
77
|
+
preventReplaceResponse.set(keyHash, false);
|
|
77
78
|
queryFn(key, stateBeforeCallQuery)
|
|
78
79
|
.then((response) => {
|
|
79
|
-
if (preventReplaceResponse.get(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
248
|
-
clearTimeout(retryNextPageTimeoutId.get(
|
|
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(
|
|
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
|
|
10
|
-
if (!stores.has(
|
|
11
|
-
stores.set(
|
|
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(
|
|
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
|
|
21
|
+
const keyHash = hashKeyFn(key);
|
|
22
22
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
23
|
-
const { get, subscribe } = useMemo(() => getStore(key), [
|
|
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
|
-
}, [
|
|
37
|
+
}, [keyHash]);
|
|
38
38
|
return state;
|
|
39
39
|
};
|
|
40
40
|
useStores.get = (key) => {
|
package/lib/index.d.ts
CHANGED
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 =
|
|
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,
|
|
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(
|
|
77
|
+
clearTimeout(retryTimeoutId.get(keyHash));
|
|
77
78
|
}
|
|
78
79
|
const stateBeforeCallQuery = { ...get(), pageParam };
|
|
79
|
-
preventReplaceResponse.set(
|
|
80
|
+
preventReplaceResponse.set(keyHash, false);
|
|
80
81
|
queryFn(key, stateBeforeCallQuery)
|
|
81
82
|
.then((response) => {
|
|
82
|
-
if (preventReplaceResponse.get(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
251
|
-
clearTimeout(retryNextPageTimeoutId.get(
|
|
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(
|
|
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
|
|
13
|
-
if (!stores.has(
|
|
14
|
-
stores.set(
|
|
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(
|
|
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
|
|
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), [
|
|
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
|
-
}, [
|
|
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 =
|
|
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,
|
|
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(
|
|
77
|
+
clearTimeout(retryTimeoutId.get(keyHash));
|
|
77
78
|
}
|
|
78
79
|
const stateBeforeCallQuery = { ...get(), pageParam };
|
|
79
|
-
preventReplaceResponse.set(
|
|
80
|
+
preventReplaceResponse.set(keyHash, false);
|
|
80
81
|
queryFn(key, stateBeforeCallQuery)
|
|
81
82
|
.then((response) => {
|
|
82
|
-
if (preventReplaceResponse.get(
|
|
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(
|
|
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(
|
|
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(
|
|
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(
|
|
251
|
-
clearTimeout(retryNextPageTimeoutId.get(
|
|
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(
|
|
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
|
|
13
|
-
if (!stores.has(
|
|
14
|
-
stores.set(
|
|
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(
|
|
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
|
|
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), [
|
|
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
|
-
}, [
|
|
40
|
+
}, [keyHash]);
|
|
41
41
|
return state;
|
|
42
42
|
};
|
|
43
43
|
useStores.get = (key) => {
|