floppy-disk 2.7.2 → 2.8.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/react/create-query.js +4 -0
- package/esm/react/create-stores.js +1 -1
- package/esm/vanilla.d.ts +1 -1
- package/esm/vanilla.js +2 -7
- package/lib/react/create-query.js +4 -0
- package/lib/react/create-stores.js +1 -1
- package/lib/vanilla.d.ts +1 -1
- package/lib/vanilla.js +1 -6
- package/package.json +3 -3
- package/esm/preact/create-bi-direction-query.d.ts +0 -167
- package/esm/preact/create-bi-direction-query.js +0 -74
- package/esm/preact/create-mutation.d.ts +0 -39
- package/esm/preact/create-mutation.js +0 -53
- package/esm/preact/create-query.d.ts +0 -294
- package/esm/preact/create-query.js +0 -416
- package/esm/preact/create-store.d.ts +0 -31
- package/esm/preact/create-store.js +0 -38
- package/esm/preact/create-stores.d.ts +0 -52
- package/esm/preact/create-stores.js +0 -100
- package/esm/preact/index.d.ts +0 -6
- package/esm/preact/index.js +0 -6
- package/lib/preact/create-bi-direction-query.d.ts +0 -167
- package/lib/preact/create-bi-direction-query.js +0 -78
- package/lib/preact/create-mutation.d.ts +0 -39
- package/lib/preact/create-mutation.js +0 -57
- package/lib/preact/create-query.d.ts +0 -294
- package/lib/preact/create-query.js +0 -420
- package/lib/preact/create-store.d.ts +0 -31
- package/lib/preact/create-store.js +0 -42
- package/lib/preact/create-stores.d.ts +0 -52
- package/lib/preact/create-stores.js +0 -104
- package/lib/preact/index.d.ts +0 -6
- package/lib/preact/index.js +0 -9
|
@@ -1,416 +0,0 @@
|
|
|
1
|
-
import { h as createElement } from 'preact';
|
|
2
|
-
import { useState } from 'preact/hooks';
|
|
3
|
-
import { getValueOrComputedValue, hasValue, identityFn, isClient, noop } from '../utils';
|
|
4
|
-
import { createStores } from './create-stores';
|
|
5
|
-
const INITIAL_QUERY_STATE = {
|
|
6
|
-
isWaiting: false,
|
|
7
|
-
isWaitingNextPage: false,
|
|
8
|
-
status: 'loading',
|
|
9
|
-
isLoading: true,
|
|
10
|
-
isSuccess: false,
|
|
11
|
-
isError: false,
|
|
12
|
-
isRefetching: false,
|
|
13
|
-
isRefetchError: false,
|
|
14
|
-
isPreviousData: false,
|
|
15
|
-
isOptimisticData: false,
|
|
16
|
-
data: undefined,
|
|
17
|
-
response: undefined,
|
|
18
|
-
responseUpdatedAt: undefined,
|
|
19
|
-
error: undefined,
|
|
20
|
-
errorUpdatedAt: undefined,
|
|
21
|
-
retryCount: 0,
|
|
22
|
-
isGoingToRetry: false,
|
|
23
|
-
pageParam: undefined,
|
|
24
|
-
pageParams: [undefined],
|
|
25
|
-
hasNextPage: false,
|
|
26
|
-
retryNextPageCount: 0,
|
|
27
|
-
isGoingToRetryNextPage: false,
|
|
28
|
-
};
|
|
29
|
-
const useQueryDefaultDeps = (state) => [
|
|
30
|
-
state.data,
|
|
31
|
-
state.error,
|
|
32
|
-
state.isWaitingNextPage,
|
|
33
|
-
state.hasNextPage,
|
|
34
|
-
];
|
|
35
|
-
/**
|
|
36
|
-
* @see https://floppy-disk.vercel.app/docs/api#createquery
|
|
37
|
-
*/
|
|
38
|
-
export const createQuery = (queryFn, options = {}) => {
|
|
39
|
-
const defaultFetchOnWindowFocus = options.fetchOnMount ?? true;
|
|
40
|
-
const defaultFetchOnReconnect = options.fetchOnMount ?? true;
|
|
41
|
-
const { onFirstSubscribe = noop, onSubscribe = noop, onLastUnsubscribe = noop, onBeforeChangeKey = noop, defaultDeps = useQueryDefaultDeps, select = identityFn, staleTime = 3000, // 3 seconds
|
|
42
|
-
fetchOnMount = true, fetchOnWindowFocus = defaultFetchOnWindowFocus, fetchOnReconnect = defaultFetchOnReconnect, enabled = true, retry = 1, retryDelay = 2000, // 2 seconds
|
|
43
|
-
keepPreviousData, getNextPageParam = () => undefined, onSuccess = noop, onError = noop, onSettled = noop, cacheTime = 5 * 60 * 1000, refetchInterval = false, ...createStoresOptions } = options;
|
|
44
|
-
const retryTimeoutId = new Map();
|
|
45
|
-
const retryNextPageTimeoutId = new Map();
|
|
46
|
-
const resetTimeoutId = new Map();
|
|
47
|
-
const refetchIntervalTimeoutId = new Map();
|
|
48
|
-
const preventReplaceResponse = new Map(); // Prevent optimistic data to be replaced
|
|
49
|
-
const useQuery = createStores(({ get, set, key: _key, keyHash }) => {
|
|
50
|
-
const key = _key;
|
|
51
|
-
const getRetryProps = (error, retryCount) => {
|
|
52
|
-
const prevState = get();
|
|
53
|
-
const maxRetryCount = getValueOrComputedValue(retry, error, prevState) || 0;
|
|
54
|
-
const delay = getValueOrComputedValue(retryDelay, error, prevState) || 0;
|
|
55
|
-
return { shouldRetry: retryCount < maxRetryCount, delay };
|
|
56
|
-
};
|
|
57
|
-
const forceFetch = () => new Promise((resolve) => {
|
|
58
|
-
const state = get();
|
|
59
|
-
const { isWaiting, isLoading, pageParams } = state;
|
|
60
|
-
const responseAllPages = [];
|
|
61
|
-
const newPageParams = [pageParams[0]];
|
|
62
|
-
let pageParam = pageParams[0];
|
|
63
|
-
clearTimeout(refetchIntervalTimeoutId.get(keyHash));
|
|
64
|
-
if (isWaiting || !getValueOrComputedValue(enabled, key))
|
|
65
|
-
return resolve(state);
|
|
66
|
-
if (isLoading)
|
|
67
|
-
set({ isWaiting: true });
|
|
68
|
-
else
|
|
69
|
-
set({ isWaiting: true, isRefetching: true });
|
|
70
|
-
const callQuery = () => {
|
|
71
|
-
if (get().isGoingToRetry) {
|
|
72
|
-
if (isLoading)
|
|
73
|
-
set({ isGoingToRetry: false, isWaiting: true });
|
|
74
|
-
else
|
|
75
|
-
set({ isGoingToRetry: false, isWaiting: true, isRefetching: true });
|
|
76
|
-
clearTimeout(retryTimeoutId.get(keyHash));
|
|
77
|
-
}
|
|
78
|
-
preventReplaceResponse.set(keyHash, false);
|
|
79
|
-
const stateBeforeCallQuery = { ...get(), pageParam };
|
|
80
|
-
queryFn(key, stateBeforeCallQuery)
|
|
81
|
-
.then((response) => {
|
|
82
|
-
if (preventReplaceResponse.get(keyHash)) {
|
|
83
|
-
set({ isWaiting: false, isRefetching: false });
|
|
84
|
-
return resolve(get());
|
|
85
|
-
}
|
|
86
|
-
responseAllPages.push(response);
|
|
87
|
-
const newPageParam = getNextPageParam(response, responseAllPages.length, stateBeforeCallQuery);
|
|
88
|
-
newPageParams.push(newPageParam);
|
|
89
|
-
if (hasValue(newPageParam) && newPageParams.length < pageParams.length) {
|
|
90
|
-
pageParam = newPageParam;
|
|
91
|
-
callQuery();
|
|
92
|
-
return;
|
|
93
|
-
}
|
|
94
|
-
const nextState = {
|
|
95
|
-
isWaiting: false,
|
|
96
|
-
status: 'success',
|
|
97
|
-
isLoading: false,
|
|
98
|
-
isSuccess: true,
|
|
99
|
-
isError: false,
|
|
100
|
-
isRefetching: false,
|
|
101
|
-
isRefetchError: false,
|
|
102
|
-
isPreviousData: false,
|
|
103
|
-
isOptimisticData: false,
|
|
104
|
-
data: responseAllPages.reduce((prev, responseCurrentPage) => {
|
|
105
|
-
return select(responseCurrentPage, { key, data: prev });
|
|
106
|
-
}, undefined),
|
|
107
|
-
response,
|
|
108
|
-
responseUpdatedAt: Date.now(),
|
|
109
|
-
error: undefined,
|
|
110
|
-
errorUpdatedAt: undefined,
|
|
111
|
-
retryCount: 0,
|
|
112
|
-
pageParam: newPageParam,
|
|
113
|
-
pageParams: newPageParams,
|
|
114
|
-
hasNextPage: hasValue(newPageParam),
|
|
115
|
-
};
|
|
116
|
-
const refetchIntervalValue = isClient && getValueOrComputedValue(refetchInterval, { ...get(), ...nextState });
|
|
117
|
-
if (refetchIntervalValue) {
|
|
118
|
-
refetchIntervalTimeoutId.set(keyHash, window.setTimeout(() => {
|
|
119
|
-
forceFetch();
|
|
120
|
-
}, refetchIntervalValue));
|
|
121
|
-
}
|
|
122
|
-
set(nextState);
|
|
123
|
-
onSuccess(response, stateBeforeCallQuery);
|
|
124
|
-
})
|
|
125
|
-
.catch((error) => {
|
|
126
|
-
const prevState = get();
|
|
127
|
-
const errorUpdatedAt = Date.now();
|
|
128
|
-
const { shouldRetry, delay } = getRetryProps(error, prevState.retryCount);
|
|
129
|
-
set(prevState.isSuccess && !prevState.isPreviousData
|
|
130
|
-
? {
|
|
131
|
-
isWaiting: false,
|
|
132
|
-
isRefetching: false,
|
|
133
|
-
isRefetchError: true,
|
|
134
|
-
data: responseAllPages.length
|
|
135
|
-
? responseAllPages.reduce((prev, response) => {
|
|
136
|
-
return select(response, { key, data: prev });
|
|
137
|
-
}, undefined)
|
|
138
|
-
: prevState.data,
|
|
139
|
-
error,
|
|
140
|
-
errorUpdatedAt,
|
|
141
|
-
isGoingToRetry: shouldRetry,
|
|
142
|
-
pageParam,
|
|
143
|
-
hasNextPage: hasValue(pageParam),
|
|
144
|
-
}
|
|
145
|
-
: {
|
|
146
|
-
isWaiting: false,
|
|
147
|
-
status: 'error',
|
|
148
|
-
isLoading: false,
|
|
149
|
-
isError: true,
|
|
150
|
-
data: undefined,
|
|
151
|
-
error,
|
|
152
|
-
errorUpdatedAt,
|
|
153
|
-
isGoingToRetry: shouldRetry,
|
|
154
|
-
pageParam,
|
|
155
|
-
hasNextPage: hasValue(pageParam),
|
|
156
|
-
});
|
|
157
|
-
if (shouldRetry && isClient) {
|
|
158
|
-
retryTimeoutId.set(keyHash, window.setTimeout(() => {
|
|
159
|
-
set({ retryCount: prevState.retryCount + 1 });
|
|
160
|
-
callQuery();
|
|
161
|
-
}, delay));
|
|
162
|
-
}
|
|
163
|
-
onError(error, stateBeforeCallQuery);
|
|
164
|
-
})
|
|
165
|
-
.finally(() => {
|
|
166
|
-
onSettled(stateBeforeCallQuery);
|
|
167
|
-
resolve(get());
|
|
168
|
-
});
|
|
169
|
-
};
|
|
170
|
-
callQuery();
|
|
171
|
-
});
|
|
172
|
-
const fetch = () => {
|
|
173
|
-
const { responseUpdatedAt } = get();
|
|
174
|
-
const isStale = Date.now() > (responseUpdatedAt || 0) + staleTime;
|
|
175
|
-
if (!isStale)
|
|
176
|
-
return;
|
|
177
|
-
forceFetch();
|
|
178
|
-
};
|
|
179
|
-
const fetchNextPage = () => new Promise((resolve) => {
|
|
180
|
-
const state = get();
|
|
181
|
-
if (typeof options.getNextPageParam !== 'function') {
|
|
182
|
-
console.warn('fetchNextPage with invalid getNextPageParam option');
|
|
183
|
-
return resolve(state);
|
|
184
|
-
}
|
|
185
|
-
const { isLoading, isWaitingNextPage, data, hasNextPage, pageParam, pageParams } = state;
|
|
186
|
-
if (isLoading)
|
|
187
|
-
return resolve(forceFetch());
|
|
188
|
-
if (isWaitingNextPage || !hasNextPage || !getValueOrComputedValue(enabled, key))
|
|
189
|
-
return resolve(state);
|
|
190
|
-
set({ isWaitingNextPage: true, isGoingToRetryNextPage: false });
|
|
191
|
-
clearTimeout(retryNextPageTimeoutId.get(keyHash));
|
|
192
|
-
const stateBeforeCallQuery = get();
|
|
193
|
-
queryFn(key, { ...state, pageParam })
|
|
194
|
-
.then((response) => {
|
|
195
|
-
if (preventReplaceResponse.get(keyHash)) {
|
|
196
|
-
set({ isWaitingNextPage: false });
|
|
197
|
-
return resolve(get());
|
|
198
|
-
}
|
|
199
|
-
const newPageParam = getNextPageParam(response, pageParams.length, stateBeforeCallQuery);
|
|
200
|
-
set({
|
|
201
|
-
isWaitingNextPage: false,
|
|
202
|
-
response,
|
|
203
|
-
responseUpdatedAt: Date.now(),
|
|
204
|
-
data: select(response, { key, data }),
|
|
205
|
-
pageParam: newPageParam,
|
|
206
|
-
pageParams: pageParams.concat(newPageParam),
|
|
207
|
-
hasNextPage: hasValue(newPageParam),
|
|
208
|
-
});
|
|
209
|
-
onSuccess(response, stateBeforeCallQuery);
|
|
210
|
-
})
|
|
211
|
-
.catch((error) => {
|
|
212
|
-
const prevState = get();
|
|
213
|
-
const { shouldRetry, delay } = getRetryProps(error, prevState.retryNextPageCount);
|
|
214
|
-
set({
|
|
215
|
-
isWaitingNextPage: false,
|
|
216
|
-
isError: true,
|
|
217
|
-
error,
|
|
218
|
-
errorUpdatedAt: Date.now(),
|
|
219
|
-
isGoingToRetryNextPage: shouldRetry,
|
|
220
|
-
});
|
|
221
|
-
if (shouldRetry) {
|
|
222
|
-
retryNextPageTimeoutId.set(keyHash, window.setTimeout(() => {
|
|
223
|
-
set({ retryNextPageCount: prevState.retryNextPageCount + 1 });
|
|
224
|
-
fetchNextPage();
|
|
225
|
-
}, delay));
|
|
226
|
-
}
|
|
227
|
-
onError(error, stateBeforeCallQuery);
|
|
228
|
-
})
|
|
229
|
-
.finally(() => {
|
|
230
|
-
onSettled(stateBeforeCallQuery);
|
|
231
|
-
resolve(get());
|
|
232
|
-
});
|
|
233
|
-
});
|
|
234
|
-
return {
|
|
235
|
-
...INITIAL_QUERY_STATE,
|
|
236
|
-
key,
|
|
237
|
-
keyHash,
|
|
238
|
-
fetch,
|
|
239
|
-
forceFetch,
|
|
240
|
-
fetchNextPage,
|
|
241
|
-
reset: () => {
|
|
242
|
-
preventReplaceResponse.set(keyHash, true);
|
|
243
|
-
set(INITIAL_QUERY_STATE);
|
|
244
|
-
},
|
|
245
|
-
optimisticUpdate: (response) => useQuery.optimisticUpdate({ key, response }),
|
|
246
|
-
};
|
|
247
|
-
}, (() => {
|
|
248
|
-
const windowFocusHandler = () => {
|
|
249
|
-
useQuery.getAllWithSubscriber().forEach((state) => {
|
|
250
|
-
const result = getValueOrComputedValue(fetchOnWindowFocus, state.key);
|
|
251
|
-
if (result === 'always')
|
|
252
|
-
state.forceFetch();
|
|
253
|
-
else if (result)
|
|
254
|
-
state.fetch();
|
|
255
|
-
});
|
|
256
|
-
};
|
|
257
|
-
const reconnectHandler = () => {
|
|
258
|
-
useQuery.getAllWithSubscriber().forEach((state) => {
|
|
259
|
-
const result = getValueOrComputedValue(fetchOnReconnect, state.key);
|
|
260
|
-
if (result === 'always')
|
|
261
|
-
state.forceFetch();
|
|
262
|
-
else if (result)
|
|
263
|
-
state.fetch();
|
|
264
|
-
});
|
|
265
|
-
};
|
|
266
|
-
return {
|
|
267
|
-
...createStoresOptions,
|
|
268
|
-
defaultDeps,
|
|
269
|
-
onFirstSubscribe: (state) => {
|
|
270
|
-
if (state.isSuccess) {
|
|
271
|
-
const refetchIntervalValue = isClient && getValueOrComputedValue(refetchInterval, state);
|
|
272
|
-
if (refetchIntervalValue) {
|
|
273
|
-
refetchIntervalTimeoutId.set(state.keyHash, window.setTimeout(() => {
|
|
274
|
-
state.forceFetch();
|
|
275
|
-
}, refetchIntervalValue));
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
if (isClient) {
|
|
279
|
-
if (fetchOnWindowFocus)
|
|
280
|
-
window.addEventListener('focus', windowFocusHandler);
|
|
281
|
-
if (fetchOnReconnect)
|
|
282
|
-
window.addEventListener('online', reconnectHandler);
|
|
283
|
-
}
|
|
284
|
-
clearTimeout(resetTimeoutId.get(state.keyHash));
|
|
285
|
-
onFirstSubscribe(state);
|
|
286
|
-
},
|
|
287
|
-
onSubscribe: (state) => {
|
|
288
|
-
const result = getValueOrComputedValue(fetchOnMount, state.key);
|
|
289
|
-
if (result === 'always')
|
|
290
|
-
state.forceFetch();
|
|
291
|
-
else if (result)
|
|
292
|
-
state.fetch();
|
|
293
|
-
onSubscribe(state);
|
|
294
|
-
},
|
|
295
|
-
onLastUnsubscribe: (state) => {
|
|
296
|
-
const totalSubs = useQuery.getAllWithSubscriber().length;
|
|
297
|
-
if (isClient && totalSubs === 0) {
|
|
298
|
-
if (fetchOnWindowFocus)
|
|
299
|
-
window.removeEventListener('focus', windowFocusHandler);
|
|
300
|
-
if (fetchOnReconnect)
|
|
301
|
-
window.removeEventListener('online', reconnectHandler);
|
|
302
|
-
}
|
|
303
|
-
useQuery.set(state.key, { retryCount: 0, retryNextPageCount: 0 }, true);
|
|
304
|
-
clearTimeout(retryTimeoutId.get(state.keyHash));
|
|
305
|
-
clearTimeout(retryNextPageTimeoutId.get(state.keyHash));
|
|
306
|
-
clearTimeout(refetchIntervalTimeoutId.get(state.keyHash));
|
|
307
|
-
if (isClient && cacheTime !== Infinity) {
|
|
308
|
-
resetTimeoutId.set(state.keyHash, window.setTimeout(() => {
|
|
309
|
-
useQuery.set(state.key, INITIAL_QUERY_STATE);
|
|
310
|
-
}, cacheTime));
|
|
311
|
-
}
|
|
312
|
-
onLastUnsubscribe(state);
|
|
313
|
-
},
|
|
314
|
-
onBeforeChangeKey: (nextKey, prevKey) => {
|
|
315
|
-
if (keepPreviousData) {
|
|
316
|
-
const nextData = useQuery.get(nextKey);
|
|
317
|
-
if (!nextData.data) {
|
|
318
|
-
const prevData = useQuery.get(prevKey);
|
|
319
|
-
if (prevData.data) {
|
|
320
|
-
useQuery.set(nextKey, {
|
|
321
|
-
status: 'success',
|
|
322
|
-
isLoading: false,
|
|
323
|
-
isSuccess: true,
|
|
324
|
-
isError: false,
|
|
325
|
-
data: prevData.data,
|
|
326
|
-
response: prevData.response,
|
|
327
|
-
isPreviousData: true,
|
|
328
|
-
}, true);
|
|
329
|
-
}
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
onBeforeChangeKey(nextKey, prevKey);
|
|
333
|
-
},
|
|
334
|
-
};
|
|
335
|
-
})());
|
|
336
|
-
useQuery.setInitialResponse = ({ key, response, skipRevalidation }) => {
|
|
337
|
-
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
338
|
-
useState(() => {
|
|
339
|
-
const state = useQuery.get(key);
|
|
340
|
-
if (response === undefined || state.isSuccess)
|
|
341
|
-
return;
|
|
342
|
-
const newPageParam = getNextPageParam(response, 1, state);
|
|
343
|
-
useQuery.set(key, {
|
|
344
|
-
status: 'success',
|
|
345
|
-
isLoading: false,
|
|
346
|
-
isSuccess: true,
|
|
347
|
-
isError: false,
|
|
348
|
-
response,
|
|
349
|
-
responseUpdatedAt: skipRevalidation ? Date.now() : undefined,
|
|
350
|
-
data: select(response, { key: key, data: undefined }),
|
|
351
|
-
pageParam: newPageParam,
|
|
352
|
-
pageParams: [undefined, newPageParam],
|
|
353
|
-
hasNextPage: hasValue(newPageParam),
|
|
354
|
-
});
|
|
355
|
-
});
|
|
356
|
-
};
|
|
357
|
-
useQuery.reset = () => {
|
|
358
|
-
useQuery.getStores().forEach((store, keyHash) => {
|
|
359
|
-
preventReplaceResponse.set(keyHash, true);
|
|
360
|
-
store.set(INITIAL_QUERY_STATE);
|
|
361
|
-
});
|
|
362
|
-
};
|
|
363
|
-
useQuery.resetSpecificKey = (key) => useQuery.get(key).reset();
|
|
364
|
-
useQuery.invalidate = () => {
|
|
365
|
-
useQuery.getStores().forEach((store) => {
|
|
366
|
-
const { get, set, getSubscribers } = store;
|
|
367
|
-
set({ responseUpdatedAt: undefined });
|
|
368
|
-
if (getSubscribers().size > 0)
|
|
369
|
-
get().forceFetch();
|
|
370
|
-
});
|
|
371
|
-
};
|
|
372
|
-
useQuery.invalidateSpecificKey = (key) => {
|
|
373
|
-
const { get, set, getSubscribers } = useQuery.getStore(key);
|
|
374
|
-
set({ responseUpdatedAt: undefined });
|
|
375
|
-
if (getSubscribers().size > 0)
|
|
376
|
-
get().forceFetch();
|
|
377
|
-
};
|
|
378
|
-
useQuery.optimisticUpdate = ({ key, response }) => {
|
|
379
|
-
const prevState = useQuery.get(key);
|
|
380
|
-
const optimisticResponse = getValueOrComputedValue(response, prevState);
|
|
381
|
-
useQuery.set(key, {
|
|
382
|
-
isOptimisticData: true,
|
|
383
|
-
response: optimisticResponse,
|
|
384
|
-
data: select(optimisticResponse, { key: key, data: undefined }),
|
|
385
|
-
});
|
|
386
|
-
preventReplaceResponse.set(prevState.keyHash, true);
|
|
387
|
-
const revert = () => {
|
|
388
|
-
useQuery.set(key, {
|
|
389
|
-
isOptimisticData: false,
|
|
390
|
-
response: prevState.response,
|
|
391
|
-
data: prevState.data,
|
|
392
|
-
});
|
|
393
|
-
};
|
|
394
|
-
const invalidate = () => useQuery.invalidateSpecificKey(key);
|
|
395
|
-
return { revert, invalidate };
|
|
396
|
-
};
|
|
397
|
-
useQuery.suspend = (key) => {
|
|
398
|
-
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
399
|
-
const state = useQuery(key);
|
|
400
|
-
if (state.isLoading)
|
|
401
|
-
throw state.forceFetch();
|
|
402
|
-
if (state.isError)
|
|
403
|
-
throw state.error;
|
|
404
|
-
return state;
|
|
405
|
-
};
|
|
406
|
-
const defaultElement = () => null;
|
|
407
|
-
useQuery.Render = (props) => {
|
|
408
|
-
const { queryKey, loading = defaultElement, success = defaultElement, error = defaultElement, } = props;
|
|
409
|
-
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
410
|
-
const state = useQuery(queryKey);
|
|
411
|
-
if (state.data)
|
|
412
|
-
return createElement(success, state.key);
|
|
413
|
-
return createElement(state.isLoading ? loading : error, state.key);
|
|
414
|
-
};
|
|
415
|
-
return useQuery;
|
|
416
|
-
};
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { InitStoreOptions, SelectDeps, SetStoreData, StoreData, StoreInitializer, Subscribers } from '../vanilla';
|
|
2
|
-
export type WatchProps<T> = {
|
|
3
|
-
selectDeps?: SelectDeps<T>;
|
|
4
|
-
render: (state: T) => any;
|
|
5
|
-
};
|
|
6
|
-
export type UseStore<T extends StoreData> = {
|
|
7
|
-
/**
|
|
8
|
-
* @param selectDeps A function that return the dependency array (just like in `useEffect`), to trigger reactivity.
|
|
9
|
-
* Defaults to `undefined` (reactive to all state change) if you didn't set `defaultDeps` on `createStore`.
|
|
10
|
-
*
|
|
11
|
-
* IMPORTANT NOTE: `selectDeps` must not be changed after initialization.
|
|
12
|
-
*/
|
|
13
|
-
(selectDeps?: SelectDeps<T>): T;
|
|
14
|
-
get: () => T;
|
|
15
|
-
set: (value: SetStoreData<T>, silent?: boolean) => void;
|
|
16
|
-
subscribe: (fn: (state: T) => void, selectDeps?: SelectDeps<T>) => () => void;
|
|
17
|
-
getSubscribers: () => Subscribers<T>;
|
|
18
|
-
/**
|
|
19
|
-
* Set default values inside a component.
|
|
20
|
-
*
|
|
21
|
-
* IMPORTANT NOTE: Put this on the root component or parent component, before any component subscribed!
|
|
22
|
-
*/
|
|
23
|
-
setDefaultValues: (values: SetStoreData<T>) => void;
|
|
24
|
-
Watch: (props: WatchProps<T>) => any;
|
|
25
|
-
};
|
|
26
|
-
/**
|
|
27
|
-
* @see https://floppy-disk.vercel.app/docs/api#createstore
|
|
28
|
-
*/
|
|
29
|
-
export declare const createStore: <T extends StoreData>(initializer: StoreInitializer<T>, options?: InitStoreOptions<T> & {
|
|
30
|
-
defaultDeps?: SelectDeps<T>;
|
|
31
|
-
}) => UseStore<T>;
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import { useEffect, useState } from 'preact/hooks';
|
|
2
|
-
import { initStore, } from '../vanilla';
|
|
3
|
-
/**
|
|
4
|
-
* @see https://floppy-disk.vercel.app/docs/api#createstore
|
|
5
|
-
*/
|
|
6
|
-
export const createStore = (initializer, options = {}) => {
|
|
7
|
-
const { get, set, subscribe, getSubscribers } = initStore(initializer, options);
|
|
8
|
-
const { defaultDeps } = options;
|
|
9
|
-
/**
|
|
10
|
-
* IMPORTANT NOTE: selectDeps function must not be changed after initialization.
|
|
11
|
-
*/
|
|
12
|
-
const useStore = (selectDeps = defaultDeps) => {
|
|
13
|
-
const [state, setState] = useState(get);
|
|
14
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
15
|
-
useEffect(() => subscribe(setState, selectDeps), []);
|
|
16
|
-
return state;
|
|
17
|
-
};
|
|
18
|
-
useStore.get = get;
|
|
19
|
-
useStore.set = set;
|
|
20
|
-
useStore.subscribe = subscribe;
|
|
21
|
-
useStore.getSubscribers = getSubscribers;
|
|
22
|
-
useStore.setDefaultValues = (value) => {
|
|
23
|
-
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
24
|
-
useState(() => {
|
|
25
|
-
const subscribers = getSubscribers();
|
|
26
|
-
if (subscribers.size > 0) {
|
|
27
|
-
console.warn('Put setDefaultValues on the root component or parent component, before any component subscribed!');
|
|
28
|
-
}
|
|
29
|
-
set(value);
|
|
30
|
-
});
|
|
31
|
-
};
|
|
32
|
-
const Watch = ({ selectDeps, render }) => {
|
|
33
|
-
const store = useStore(selectDeps);
|
|
34
|
-
return render(store);
|
|
35
|
-
};
|
|
36
|
-
useStore.Watch = Watch;
|
|
37
|
-
return useStore;
|
|
38
|
-
};
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
import { Maybe } from '../utils';
|
|
2
|
-
import { InitStoreOptions, InitStoreReturn, SelectDeps, SetStoreData, StoreData, Subscribers } from '../vanilla';
|
|
3
|
-
import { WatchProps } from './create-store';
|
|
4
|
-
export type StoreKey = Record<string, any> | undefined;
|
|
5
|
-
export type StoresInitializer<TKey extends StoreKey = StoreKey, T extends StoreData = StoreData> = (api: {
|
|
6
|
-
get: () => T;
|
|
7
|
-
set: (value: SetStoreData<T>, silent?: boolean) => void;
|
|
8
|
-
key: TKey;
|
|
9
|
-
keyHash: string;
|
|
10
|
-
}) => T;
|
|
11
|
-
export type UseStores<TKey extends StoreKey = StoreKey, T extends StoreData = StoreData> = {
|
|
12
|
-
/**
|
|
13
|
-
* @param key (Optional) Store key, an object that will be hashed into a string as a store identifier.
|
|
14
|
-
*
|
|
15
|
-
* @param selectDeps A function that return the dependency array (just like in `useEffect`), to trigger reactivity.
|
|
16
|
-
* Defaults to `undefined` (reactive to all state change) if you didn't set `defaultDeps` on `createStores`.
|
|
17
|
-
*
|
|
18
|
-
* IMPORTANT NOTE: `selectDeps` must not be changed after initialization.
|
|
19
|
-
*/
|
|
20
|
-
(...args: [Maybe<TKey>, SelectDeps<T>?] | [SelectDeps<T>?]): T;
|
|
21
|
-
get: (key?: Maybe<TKey>) => T;
|
|
22
|
-
getAll: () => T[];
|
|
23
|
-
getAllWithSubscriber: () => T[];
|
|
24
|
-
set: (key: Maybe<TKey>, value: SetStoreData<T>, silent?: boolean) => void;
|
|
25
|
-
setAll: (value: SetStoreData<T>, silent?: boolean) => void;
|
|
26
|
-
subscribe: (key: Maybe<TKey>, fn: (state: T) => void, selectDeps?: SelectDeps<T>) => () => void;
|
|
27
|
-
getSubscribers: (key: Maybe<TKey>) => Subscribers<T>;
|
|
28
|
-
getStore: (key?: Maybe<TKey>) => InitStoreReturn<T>;
|
|
29
|
-
getStores: () => Map<string, InitStoreReturn<T>>;
|
|
30
|
-
/**
|
|
31
|
-
* Set default values inside a component.
|
|
32
|
-
*
|
|
33
|
-
* IMPORTANT NOTE: Put this on the root component or parent component, before any component subscribed!
|
|
34
|
-
*/
|
|
35
|
-
setDefaultValues: (key: Maybe<TKey>, values: SetStoreData<T>) => void;
|
|
36
|
-
Watch: (props: WatchProps<T> & {
|
|
37
|
-
storeKey?: Maybe<TKey>;
|
|
38
|
-
}) => any;
|
|
39
|
-
};
|
|
40
|
-
export type CreateStoresOptions<TKey extends StoreKey = StoreKey, T extends StoreData = StoreData> = InitStoreOptions<T> & {
|
|
41
|
-
onBeforeChangeKey?: (nextKey: TKey, prevKey: TKey) => void;
|
|
42
|
-
/**
|
|
43
|
-
* Will be triggered when a single store with a specific key was initialized.
|
|
44
|
-
*/
|
|
45
|
-
onStoreInitialized?: (key: TKey, keyHash: string) => void;
|
|
46
|
-
defaultDeps?: SelectDeps<T>;
|
|
47
|
-
hashKeyFn?: (obj: TKey) => string;
|
|
48
|
-
};
|
|
49
|
-
/**
|
|
50
|
-
* @see https://floppy-disk.vercel.app/docs/api#createstores
|
|
51
|
-
*/
|
|
52
|
-
export declare const createStores: <TKey extends StoreKey = StoreKey, T extends StoreData = StoreData>(initializer: StoresInitializer<TKey, T>, options?: CreateStoresOptions<TKey, T>) => UseStores<TKey, T>;
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
import { useEffect, useMemo, useRef, useState } from 'preact/hooks';
|
|
2
|
-
import { hashStoreKey, noop } from '../utils';
|
|
3
|
-
import { initStore, } from '../vanilla';
|
|
4
|
-
/**
|
|
5
|
-
* @see https://floppy-disk.vercel.app/docs/api#createstores
|
|
6
|
-
*/
|
|
7
|
-
export const createStores = (initializer, options = {}) => {
|
|
8
|
-
const { onBeforeChangeKey = noop, onStoreInitialized = noop, defaultDeps, hashKeyFn = hashStoreKey, } = options;
|
|
9
|
-
const stores = new Map();
|
|
10
|
-
const getStore = (_key) => {
|
|
11
|
-
const key = _key || {};
|
|
12
|
-
const keyHash = hashKeyFn(key);
|
|
13
|
-
if (!stores.has(keyHash)) {
|
|
14
|
-
stores.set(keyHash, initStore((api) => initializer({ key, keyHash, ...api }), options));
|
|
15
|
-
onStoreInitialized(key, keyHash);
|
|
16
|
-
}
|
|
17
|
-
return stores.get(keyHash);
|
|
18
|
-
};
|
|
19
|
-
/**
|
|
20
|
-
* IMPORTANT NOTE: selectDeps function must not be changed after initialization.
|
|
21
|
-
*/
|
|
22
|
-
const useStores = (...args) => {
|
|
23
|
-
const [_key, selectDeps = defaultDeps] = (typeof args[0] === 'function' ? [{}, args[0]] : args);
|
|
24
|
-
const key = _key || {};
|
|
25
|
-
const keyHash = hashKeyFn(key);
|
|
26
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
27
|
-
const { get, subscribe } = useMemo(() => getStore(key), [keyHash]);
|
|
28
|
-
const [state, setState] = useState(get);
|
|
29
|
-
const isFirstRender = useRef(true);
|
|
30
|
-
const prevKey = useRef(key);
|
|
31
|
-
useEffect(() => {
|
|
32
|
-
if (!isFirstRender.current) {
|
|
33
|
-
onBeforeChangeKey(key, prevKey.current);
|
|
34
|
-
setState(get);
|
|
35
|
-
}
|
|
36
|
-
isFirstRender.current = false;
|
|
37
|
-
prevKey.current = key;
|
|
38
|
-
const unsubs = subscribe(setState, selectDeps);
|
|
39
|
-
return unsubs;
|
|
40
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
41
|
-
}, [keyHash]);
|
|
42
|
-
return state;
|
|
43
|
-
};
|
|
44
|
-
useStores.get = (key) => {
|
|
45
|
-
const store = getStore(key);
|
|
46
|
-
return store.get();
|
|
47
|
-
};
|
|
48
|
-
useStores.getAll = () => {
|
|
49
|
-
const allStores = [];
|
|
50
|
-
stores.forEach((store) => {
|
|
51
|
-
allStores.push(store.get());
|
|
52
|
-
});
|
|
53
|
-
return allStores;
|
|
54
|
-
};
|
|
55
|
-
useStores.getAllWithSubscriber = () => {
|
|
56
|
-
const allStores = [];
|
|
57
|
-
stores.forEach((store) => {
|
|
58
|
-
const subscribers = store.getSubscribers();
|
|
59
|
-
if (subscribers.size > 0)
|
|
60
|
-
allStores.push(store.get());
|
|
61
|
-
});
|
|
62
|
-
return allStores;
|
|
63
|
-
};
|
|
64
|
-
useStores.set = (key, value, silent) => {
|
|
65
|
-
const store = getStore(key);
|
|
66
|
-
store.set(value, silent);
|
|
67
|
-
};
|
|
68
|
-
useStores.setAll = (value, silent) => {
|
|
69
|
-
stores.forEach((store) => {
|
|
70
|
-
store.set(value, silent);
|
|
71
|
-
});
|
|
72
|
-
};
|
|
73
|
-
useStores.subscribe = (key, fn, selectDeps) => {
|
|
74
|
-
const store = getStore(key);
|
|
75
|
-
return store.subscribe(fn, selectDeps);
|
|
76
|
-
};
|
|
77
|
-
useStores.getSubscribers = (key) => {
|
|
78
|
-
const store = getStore(key);
|
|
79
|
-
return store.getSubscribers();
|
|
80
|
-
};
|
|
81
|
-
useStores.getStore = (key) => getStore(key);
|
|
82
|
-
useStores.getStores = () => stores;
|
|
83
|
-
useStores.setDefaultValues = (key, value) => {
|
|
84
|
-
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
85
|
-
useState(() => {
|
|
86
|
-
const store = getStore(key);
|
|
87
|
-
const subscribers = store.getSubscribers();
|
|
88
|
-
if (subscribers.size > 0) {
|
|
89
|
-
console.warn('Put setDefaultValues on the root component or parent component, before any component subscribed!');
|
|
90
|
-
}
|
|
91
|
-
store.set(value);
|
|
92
|
-
});
|
|
93
|
-
};
|
|
94
|
-
const Watch = ({ storeKey, selectDeps, render }) => {
|
|
95
|
-
const store = useStores(storeKey, selectDeps);
|
|
96
|
-
return render(store);
|
|
97
|
-
};
|
|
98
|
-
useStores.Watch = Watch;
|
|
99
|
-
return useStores;
|
|
100
|
-
};
|
package/esm/preact/index.d.ts
DELETED