floppy-disk 3.6.1 → 3.7.0-beta.2
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-mutation.d.mts +1 -11
- package/esm/react/create-query.d.mts +154 -19
- package/esm/react/create-stores.d.mts +32 -14
- package/esm/react/create-stream.d.mts +88 -0
- package/esm/react.d.mts +1 -0
- package/esm/react.mjs +313 -96
- package/package.json +4 -1
- package/react/create-mutation.d.ts +1 -11
- package/react/create-query.d.ts +154 -19
- package/react/create-stores.d.ts +32 -14
- package/react/create-stream.d.ts +88 -0
- package/react.d.ts +1 -0
- package/react.js +313 -95
package/esm/react.mjs
CHANGED
|
@@ -102,11 +102,7 @@ const createStores = (initialState, options) => {
|
|
|
102
102
|
store.key = key;
|
|
103
103
|
store.keyHash = keyHash;
|
|
104
104
|
stores.set(keyHash, store);
|
|
105
|
-
|
|
106
|
-
const useStore = (options2) => useStoreState(store, options2);
|
|
107
|
-
return Object.assign(useStore, {
|
|
108
|
-
...store,
|
|
109
|
-
delete: () => {
|
|
105
|
+
store.delete = () => {
|
|
110
106
|
if (store.getSubscriberCount() > 0) {
|
|
111
107
|
console.warn(
|
|
112
108
|
"Cannot delete store while it still has active subscribers. Unsubscribe all listeners before deleting the store."
|
|
@@ -115,13 +111,15 @@ const createStores = (initialState, options) => {
|
|
|
115
111
|
}
|
|
116
112
|
store.setState(initialState);
|
|
117
113
|
return stores.delete(keyHash);
|
|
118
|
-
}
|
|
119
|
-
}
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
const useStore = (options2) => useStoreState(store, options2);
|
|
117
|
+
return Object.assign(useStore, store);
|
|
120
118
|
};
|
|
121
119
|
return getStore;
|
|
122
120
|
};
|
|
123
121
|
|
|
124
|
-
const INITIAL_STATE$
|
|
122
|
+
const INITIAL_STATE$2 = {
|
|
125
123
|
isPending: false,
|
|
126
124
|
isRevalidating: false,
|
|
127
125
|
willRetryAt: void 0,
|
|
@@ -149,15 +147,15 @@ const createQuery = (queryFn, options = {}) => {
|
|
|
149
147
|
onSettled = noop,
|
|
150
148
|
shouldRetry: shouldRetryFn = (_, s) => s.retryCount === 0 ? [true, 1500] : [false]
|
|
151
149
|
} = options;
|
|
152
|
-
const initialState = { ...INITIAL_STATE$
|
|
150
|
+
const initialState = { ...INITIAL_STATE$2 };
|
|
153
151
|
const stores = /* @__PURE__ */ new Map();
|
|
154
152
|
const configureStoreEvents = (variableHash) => ({
|
|
155
153
|
...options,
|
|
156
154
|
onFirstSubscribe: (state, store) => {
|
|
157
155
|
var _a;
|
|
158
156
|
(_a = options.onFirstSubscribe) == null ? void 0 : _a.call(options, state, store);
|
|
159
|
-
const {
|
|
160
|
-
clearTimeout(
|
|
157
|
+
const { internal, revalidate: revalidate2 } = store;
|
|
158
|
+
clearTimeout(internal.garbageCollectionTimeoutId);
|
|
161
159
|
if (isClient) {
|
|
162
160
|
if (revalidateOnFocus) {
|
|
163
161
|
focusListeners.add(revalidate2);
|
|
@@ -167,9 +165,9 @@ const createQuery = (queryFn, options = {}) => {
|
|
|
167
165
|
}
|
|
168
166
|
}
|
|
169
167
|
if (revalidateOnReconnect) {
|
|
170
|
-
onlineListeners.add(revalidate2);
|
|
168
|
+
onlineListeners$1.add(revalidate2);
|
|
171
169
|
if (!onlineListenersAdded) {
|
|
172
|
-
window.addEventListener("online", onWindowOnline);
|
|
170
|
+
window.addEventListener("online", onWindowOnline$1);
|
|
173
171
|
onlineListenersAdded = true;
|
|
174
172
|
}
|
|
175
173
|
}
|
|
@@ -178,15 +176,15 @@ const createQuery = (queryFn, options = {}) => {
|
|
|
178
176
|
onLastUnsubscribe: (state, store) => {
|
|
179
177
|
var _a;
|
|
180
178
|
(_a = options.onLastUnsubscribe) == null ? void 0 : _a.call(options, state, store);
|
|
181
|
-
const {
|
|
182
|
-
clearTimeout(
|
|
183
|
-
if (
|
|
179
|
+
const { internal, revalidate: revalidate2 } = store;
|
|
180
|
+
clearTimeout(internal.retryTimeoutId);
|
|
181
|
+
if (internal.retryResolver) {
|
|
184
182
|
store.setState({ willRetryAt: void 0 });
|
|
185
|
-
|
|
186
|
-
|
|
183
|
+
internal.retryResolver(store.getState());
|
|
184
|
+
internal.retryResolver = void 0;
|
|
187
185
|
}
|
|
188
|
-
|
|
189
|
-
if (
|
|
186
|
+
internal.garbageCollectionTimeoutId = setTimeout(() => {
|
|
187
|
+
if (internal.promiseResolver || internal.retryResolver) {
|
|
190
188
|
store.setState(initialState);
|
|
191
189
|
} else {
|
|
192
190
|
stores.delete(variableHash);
|
|
@@ -201,23 +199,22 @@ const createQuery = (queryFn, options = {}) => {
|
|
|
201
199
|
}
|
|
202
200
|
}
|
|
203
201
|
if (revalidateOnReconnect) {
|
|
204
|
-
onlineListeners.delete(revalidate2);
|
|
205
|
-
if (onlineListeners.size === 0) {
|
|
206
|
-
window.removeEventListener("online", onWindowOnline);
|
|
202
|
+
onlineListeners$1.delete(revalidate2);
|
|
203
|
+
if (onlineListeners$1.size === 0) {
|
|
204
|
+
window.removeEventListener("online", onWindowOnline$1);
|
|
207
205
|
onlineListenersAdded = false;
|
|
208
206
|
}
|
|
209
207
|
}
|
|
210
208
|
}
|
|
211
209
|
}
|
|
212
210
|
});
|
|
213
|
-
const
|
|
214
|
-
|
|
215
|
-
metadata: {},
|
|
211
|
+
const getApis = (store, variable) => ({
|
|
212
|
+
internal: {},
|
|
216
213
|
setInitialData: (data, revalidate2 = false) => {
|
|
217
214
|
const state = store.getState();
|
|
218
215
|
if (state.state === "INITIAL" && state.data === void 0) {
|
|
219
|
-
const {
|
|
220
|
-
if (revalidate2)
|
|
216
|
+
const { internal } = store;
|
|
217
|
+
if (revalidate2) internal.isInvalidated = true;
|
|
221
218
|
store.setState({
|
|
222
219
|
state: "SUCCESS",
|
|
223
220
|
isSuccess: true,
|
|
@@ -235,28 +232,28 @@ const createQuery = (queryFn, options = {}) => {
|
|
|
235
232
|
return revalidate(store, variable, overwriteOngoingExecution);
|
|
236
233
|
},
|
|
237
234
|
invalidate: (options2) => {
|
|
238
|
-
const {
|
|
239
|
-
|
|
235
|
+
const { internal } = store;
|
|
236
|
+
internal.isInvalidated = true;
|
|
240
237
|
if (store.getSubscriberCount() > 0) {
|
|
241
|
-
|
|
238
|
+
store.execute(options2);
|
|
242
239
|
return true;
|
|
243
240
|
}
|
|
244
241
|
return false;
|
|
245
242
|
},
|
|
246
243
|
reset: () => {
|
|
247
244
|
var _a, _b;
|
|
248
|
-
const {
|
|
249
|
-
clearTimeout(
|
|
250
|
-
if (
|
|
245
|
+
const { internal } = store;
|
|
246
|
+
clearTimeout(internal.retryTimeoutId);
|
|
247
|
+
if (internal.retryResolver || internal.promiseResolver) {
|
|
251
248
|
console.debug(
|
|
252
249
|
"Ongoing query execution was ignored due to reset(). The result will not update the store state."
|
|
253
250
|
);
|
|
254
|
-
(_a =
|
|
255
|
-
(_b =
|
|
256
|
-
|
|
257
|
-
|
|
251
|
+
(_a = internal.promiseResolver) == null ? void 0 : _a.call(internal, initialState);
|
|
252
|
+
(_b = internal.retryResolver) == null ? void 0 : _b.call(internal, initialState);
|
|
253
|
+
internal.promiseResolver = void 0;
|
|
254
|
+
internal.retryResolver = void 0;
|
|
258
255
|
}
|
|
259
|
-
|
|
256
|
+
internal.promise = void 0;
|
|
260
257
|
store.setState(initialState);
|
|
261
258
|
},
|
|
262
259
|
delete: () => {
|
|
@@ -266,35 +263,36 @@ const createQuery = (queryFn, options = {}) => {
|
|
|
266
263
|
);
|
|
267
264
|
return false;
|
|
268
265
|
}
|
|
269
|
-
|
|
266
|
+
store.reset();
|
|
270
267
|
return stores.delete(store.variableHash);
|
|
271
268
|
},
|
|
272
269
|
optimisticUpdate: (optimisticData) => {
|
|
273
|
-
const {
|
|
274
|
-
|
|
270
|
+
const { internal, revalidate: revalidate2, rollbackOptimisticUpdate } = store;
|
|
271
|
+
internal.rollbackData = store.getState().data;
|
|
275
272
|
store.setState({ data: optimisticData });
|
|
276
273
|
return { revalidate: revalidate2, rollback: rollbackOptimisticUpdate };
|
|
277
274
|
},
|
|
278
275
|
rollbackOptimisticUpdate: () => {
|
|
279
|
-
const {
|
|
280
|
-
store.setState({ data:
|
|
281
|
-
return
|
|
276
|
+
const { internal } = store;
|
|
277
|
+
store.setState({ data: internal.rollbackData });
|
|
278
|
+
return internal.rollbackData;
|
|
282
279
|
}
|
|
283
280
|
});
|
|
284
281
|
const execute = async (store, variable, overwriteOngoingExecution = false) => {
|
|
285
|
-
const {
|
|
286
|
-
|
|
287
|
-
|
|
282
|
+
const { internal: _internal } = store;
|
|
283
|
+
const internal = _internal;
|
|
284
|
+
if (!overwriteOngoingExecution && internal.promise) return internal.promise;
|
|
285
|
+
clearTimeout(internal.retryTimeoutId);
|
|
288
286
|
const createPromise = () => {
|
|
289
287
|
const promise = new Promise((resolve) => {
|
|
290
|
-
|
|
288
|
+
internal.promiseResolver = resolve;
|
|
291
289
|
const stateBeforeExecute = store.getState();
|
|
292
290
|
store.setState({
|
|
293
291
|
isPending: true,
|
|
294
292
|
isRevalidating: stateBeforeExecute.state === "SUCCESS",
|
|
295
293
|
willRetryAt: void 0,
|
|
296
|
-
isRetrying: !!
|
|
297
|
-
retryCount:
|
|
294
|
+
isRetrying: !!internal.retryResolver,
|
|
295
|
+
retryCount: internal.retryResolver ? stateBeforeExecute.retryCount + 1 : 0
|
|
298
296
|
});
|
|
299
297
|
queryFn(variable, stateBeforeExecute, store.variableHash).then((data) => {
|
|
300
298
|
var _a;
|
|
@@ -303,8 +301,8 @@ const createQuery = (queryFn, options = {}) => {
|
|
|
303
301
|
"Query function returned undefined. Successful responses must not be undefined."
|
|
304
302
|
);
|
|
305
303
|
}
|
|
306
|
-
if (!
|
|
307
|
-
if (promise !==
|
|
304
|
+
if (!internal.promiseResolver) return;
|
|
305
|
+
if (promise !== internal.promise) return resolve(internal.promise);
|
|
308
306
|
const now = Date.now();
|
|
309
307
|
store.setState({
|
|
310
308
|
isPending: false,
|
|
@@ -320,17 +318,17 @@ const createQuery = (queryFn, options = {}) => {
|
|
|
320
318
|
error: void 0,
|
|
321
319
|
errorUpdatedAt: void 0
|
|
322
320
|
});
|
|
323
|
-
|
|
324
|
-
|
|
321
|
+
internal.isInvalidated = false;
|
|
322
|
+
internal.rollbackData = data;
|
|
325
323
|
resolve(store.getState());
|
|
326
|
-
(_a =
|
|
327
|
-
|
|
324
|
+
(_a = internal.retryResolver) == null ? void 0 : _a.call(internal, store.getState());
|
|
325
|
+
internal.retryResolver = void 0;
|
|
328
326
|
onSuccess(data, variable, stateBeforeExecute);
|
|
329
327
|
onSettled(variable, stateBeforeExecute);
|
|
330
328
|
}).catch((error) => {
|
|
331
329
|
var _a;
|
|
332
|
-
if (!
|
|
333
|
-
if (promise !==
|
|
330
|
+
if (!internal.promiseResolver && !internal.retryResolver) return;
|
|
331
|
+
if (promise !== internal.promise) return resolve(internal.promise);
|
|
334
332
|
const nextState = {
|
|
335
333
|
...store.getState(),
|
|
336
334
|
isPending: false,
|
|
@@ -340,8 +338,8 @@ const createQuery = (queryFn, options = {}) => {
|
|
|
340
338
|
const [shouldRetry, retryDelay] = shouldRetryFn(error, nextState);
|
|
341
339
|
const hasSubscriber = store.getSubscriberCount() > 0;
|
|
342
340
|
if (shouldRetry && hasSubscriber) {
|
|
343
|
-
|
|
344
|
-
|
|
341
|
+
internal.retryResolver = resolve;
|
|
342
|
+
internal.retryTimeoutId = setTimeout(createPromise, retryDelay);
|
|
345
343
|
store.setState({
|
|
346
344
|
isPending: false,
|
|
347
345
|
isRevalidating: false,
|
|
@@ -354,43 +352,38 @@ const createQuery = (queryFn, options = {}) => {
|
|
|
354
352
|
isRevalidating: false,
|
|
355
353
|
isRetrying: false,
|
|
356
354
|
retryCount: 0,
|
|
355
|
+
state: store.getState().state === "SUCCESS" ? "SUCCESS_BUT_REVALIDATION_ERROR" : "ERROR",
|
|
356
|
+
isError: true,
|
|
357
357
|
error,
|
|
358
|
-
errorUpdatedAt: Date.now()
|
|
359
|
-
...store.getState().data ? {
|
|
360
|
-
state: "SUCCESS_BUT_REVALIDATION_ERROR",
|
|
361
|
-
isError: false
|
|
362
|
-
} : {
|
|
363
|
-
state: "ERROR",
|
|
364
|
-
isError: true
|
|
365
|
-
}
|
|
358
|
+
errorUpdatedAt: Date.now()
|
|
366
359
|
});
|
|
367
360
|
const state = store.getState();
|
|
368
361
|
resolve(state);
|
|
369
|
-
(_a =
|
|
370
|
-
|
|
362
|
+
(_a = internal.retryResolver) == null ? void 0 : _a.call(internal, state);
|
|
363
|
+
internal.retryResolver = void 0;
|
|
371
364
|
if (onError) onError(error, variable, stateBeforeExecute);
|
|
372
365
|
else console.error(state);
|
|
373
366
|
onSettled(variable, stateBeforeExecute);
|
|
374
367
|
}
|
|
375
368
|
}).finally(() => {
|
|
376
|
-
if (
|
|
377
|
-
|
|
378
|
-
|
|
369
|
+
if (internal.promise === promise) {
|
|
370
|
+
internal.promise = void 0;
|
|
371
|
+
internal.promiseResolver = void 0;
|
|
379
372
|
}
|
|
380
373
|
});
|
|
381
374
|
});
|
|
382
|
-
|
|
375
|
+
internal.promise = promise;
|
|
383
376
|
return promise;
|
|
384
377
|
};
|
|
385
378
|
return createPromise();
|
|
386
379
|
};
|
|
387
380
|
const revalidate = async (store, variable, overwriteOngoingExecution) => {
|
|
388
|
-
const {
|
|
389
|
-
if (!overwriteOngoingExecution &&
|
|
381
|
+
const { internal } = store;
|
|
382
|
+
if (!overwriteOngoingExecution && internal.promise) return internal.promise;
|
|
390
383
|
const state = store.getState();
|
|
391
384
|
if (state.dataUpdatedAt) {
|
|
392
385
|
const isFresh = state.dataUpdatedAt + staleTime > Date.now();
|
|
393
|
-
if (isFresh && !
|
|
386
|
+
if (isFresh && !internal.isInvalidated) return state;
|
|
394
387
|
}
|
|
395
388
|
return execute(store, variable, overwriteOngoingExecution);
|
|
396
389
|
};
|
|
@@ -407,7 +400,16 @@ const createQuery = (queryFn, options = {}) => {
|
|
|
407
400
|
);
|
|
408
401
|
store.variableHash = variableHash;
|
|
409
402
|
stores.set(variableHash, store);
|
|
410
|
-
|
|
403
|
+
const apis = getApis(store, variable);
|
|
404
|
+
store.setInitialData = apis.setInitialData;
|
|
405
|
+
store.execute = apis.execute;
|
|
406
|
+
store.revalidate = apis.revalidate;
|
|
407
|
+
store.invalidate = apis.invalidate;
|
|
408
|
+
store.reset = apis.reset;
|
|
409
|
+
store.delete = apis.delete;
|
|
410
|
+
store.optimisticUpdate = apis.optimisticUpdate;
|
|
411
|
+
store.rollbackOptimisticUpdate = apis.rollbackOptimisticUpdate;
|
|
412
|
+
store.internal = apis.internal;
|
|
411
413
|
}
|
|
412
414
|
const useStore = (options2 = {}) => {
|
|
413
415
|
const {
|
|
@@ -475,15 +477,11 @@ const createQuery = (queryFn, options = {}) => {
|
|
|
475
477
|
return trackedState;
|
|
476
478
|
};
|
|
477
479
|
return Object.assign(useStore, {
|
|
478
|
-
|
|
479
|
-
getSubscriberCount: store.getSubscriberCount,
|
|
480
|
-
getState: store.getState,
|
|
480
|
+
...store,
|
|
481
481
|
setState: (value) => {
|
|
482
482
|
console.debug("Manual setState (not via provided actions) on query store");
|
|
483
483
|
store.setState(value);
|
|
484
|
-
}
|
|
485
|
-
...internals.get(store),
|
|
486
|
-
variableHash
|
|
484
|
+
}
|
|
487
485
|
});
|
|
488
486
|
};
|
|
489
487
|
return Object.assign(getStore, {
|
|
@@ -494,7 +492,7 @@ const createQuery = (queryFn, options = {}) => {
|
|
|
494
492
|
* - Useful for bulk refetching.
|
|
495
493
|
*/
|
|
496
494
|
executeAll: (options2) => {
|
|
497
|
-
stores.forEach((store) =>
|
|
495
|
+
stores.forEach((store) => store.execute(options2));
|
|
498
496
|
},
|
|
499
497
|
/**
|
|
500
498
|
* Revalidates all query instances.
|
|
@@ -503,7 +501,7 @@ const createQuery = (queryFn, options = {}) => {
|
|
|
503
501
|
* - Only re-fetches stale queries.
|
|
504
502
|
*/
|
|
505
503
|
revalidateAll: (options2) => {
|
|
506
|
-
stores.forEach((store) =>
|
|
504
|
+
stores.forEach((store) => store.revalidate(options2));
|
|
507
505
|
},
|
|
508
506
|
/**
|
|
509
507
|
* Invalidates all query instances.
|
|
@@ -513,13 +511,13 @@ const createQuery = (queryFn, options = {}) => {
|
|
|
513
511
|
* - Invalidated queries bypass `staleTime` until successfully executed again.
|
|
514
512
|
*/
|
|
515
513
|
invalidateAll: (options2) => {
|
|
516
|
-
stores.forEach((store) =>
|
|
514
|
+
stores.forEach((store) => store.invalidate(options2));
|
|
517
515
|
},
|
|
518
516
|
/**
|
|
519
517
|
* Resets all query instances.
|
|
520
518
|
*/
|
|
521
519
|
resetAll: () => {
|
|
522
|
-
stores.forEach((store) =>
|
|
520
|
+
stores.forEach((store) => store.reset());
|
|
523
521
|
}
|
|
524
522
|
});
|
|
525
523
|
};
|
|
@@ -527,10 +525,10 @@ let focusListenersAdded = false;
|
|
|
527
525
|
const focusListeners = /* @__PURE__ */ new Set();
|
|
528
526
|
const onWindowFocus = () => [...focusListeners].forEach((fn) => fn());
|
|
529
527
|
let onlineListenersAdded = false;
|
|
530
|
-
const onlineListeners = /* @__PURE__ */ new Set();
|
|
531
|
-
const onWindowOnline = () => [...onlineListeners].forEach((fn) => fn());
|
|
528
|
+
const onlineListeners$1 = /* @__PURE__ */ new Set();
|
|
529
|
+
const onWindowOnline$1 = () => [...onlineListeners$1].forEach((fn) => fn());
|
|
532
530
|
|
|
533
|
-
const INITIAL_STATE = {
|
|
531
|
+
const INITIAL_STATE$1 = {
|
|
534
532
|
state: "INITIAL",
|
|
535
533
|
isPending: false,
|
|
536
534
|
isSuccess: false,
|
|
@@ -543,7 +541,7 @@ const INITIAL_STATE = {
|
|
|
543
541
|
};
|
|
544
542
|
const createMutation = (mutationFn, options = {}) => {
|
|
545
543
|
const { onSuccess = noop, onError, onSettled = noop } = options;
|
|
546
|
-
const initialState = { ...INITIAL_STATE };
|
|
544
|
+
const initialState = { ...INITIAL_STATE$1 };
|
|
547
545
|
let ongoingPromise;
|
|
548
546
|
const resolveFns = /* @__PURE__ */ new Set([]);
|
|
549
547
|
const store = initStore(initialState, options);
|
|
@@ -661,7 +659,7 @@ const useMutation = (mutationFn, options = {}) => {
|
|
|
661
659
|
callbackRef.current.onSuccess = onSuccess;
|
|
662
660
|
callbackRef.current.onError = onError;
|
|
663
661
|
callbackRef.current.onSettled = onSettled;
|
|
664
|
-
const stateRef = useRef({ ...INITIAL_STATE });
|
|
662
|
+
const stateRef = useRef({ ...INITIAL_STATE$1 });
|
|
665
663
|
const [, reRender] = useState({});
|
|
666
664
|
const refs = useRef({
|
|
667
665
|
mutationFn,
|
|
@@ -744,7 +742,7 @@ const useMutation = (mutationFn, options = {}) => {
|
|
|
744
742
|
"Mutation state was reset while a request is still pending. The request will continue, but its result may override the reset state."
|
|
745
743
|
);
|
|
746
744
|
}
|
|
747
|
-
stateRef.current = { ...INITIAL_STATE };
|
|
745
|
+
stateRef.current = { ...INITIAL_STATE$1 };
|
|
748
746
|
reRender({});
|
|
749
747
|
}, []);
|
|
750
748
|
const r = [
|
|
@@ -758,4 +756,223 @@ const useMutation = (mutationFn, options = {}) => {
|
|
|
758
756
|
return r;
|
|
759
757
|
};
|
|
760
758
|
|
|
761
|
-
|
|
759
|
+
const INITIAL_STATE = {
|
|
760
|
+
connectionState: "INITIAL",
|
|
761
|
+
connectingAt: void 0,
|
|
762
|
+
connectedAt: void 0,
|
|
763
|
+
disconnectedAt: void 0,
|
|
764
|
+
state: "INITIAL",
|
|
765
|
+
isSuccess: false,
|
|
766
|
+
isError: false,
|
|
767
|
+
data: void 0,
|
|
768
|
+
dataUpdatedAt: void 0,
|
|
769
|
+
error: void 0,
|
|
770
|
+
errorUpdatedAt: void 0
|
|
771
|
+
};
|
|
772
|
+
const experimental_createStream = (connect, disconnect, options = {}) => {
|
|
773
|
+
const {
|
|
774
|
+
disconnectOn = () => 5e3,
|
|
775
|
+
// 5 seconds after any `DisconnectTrigger`
|
|
776
|
+
reconnectOn = () => false
|
|
777
|
+
// no need reconnect if still connected
|
|
778
|
+
} = options.connection || {};
|
|
779
|
+
const {
|
|
780
|
+
gcTime = 5 * 60 * 1e3
|
|
781
|
+
// 5 minutes
|
|
782
|
+
} = options.data || {};
|
|
783
|
+
const initialState = { ...INITIAL_STATE };
|
|
784
|
+
const stores = /* @__PURE__ */ new Map();
|
|
785
|
+
const connections = /* @__PURE__ */ new WeakMap();
|
|
786
|
+
const disconnectFns = /* @__PURE__ */ new WeakMap();
|
|
787
|
+
const disconnectTimeoutIds = /* @__PURE__ */ new WeakMap();
|
|
788
|
+
const clearDataTimeoutIds = /* @__PURE__ */ new WeakMap();
|
|
789
|
+
const configureStoreEvents = () => ({
|
|
790
|
+
...options,
|
|
791
|
+
onFirstSubscribe: (state, store) => {
|
|
792
|
+
var _a, _b;
|
|
793
|
+
clearTimeout((_a = disconnectTimeoutIds.get(store)) == null ? void 0 : _a["last-unsubscribe"]);
|
|
794
|
+
(_b = options.onFirstSubscribe) == null ? void 0 : _b.call(options, state, store);
|
|
795
|
+
triggerReconnect(store, "first-subscribe");
|
|
796
|
+
if (isClient) {
|
|
797
|
+
visibilityChangeListeners.add(triggers.visibilityChange);
|
|
798
|
+
onlineListeners.add(triggers.online);
|
|
799
|
+
offlineListeners.add(triggers.offline);
|
|
800
|
+
if (!listenersAdded) {
|
|
801
|
+
document.addEventListener("visibilitychange", onVisibilityChange);
|
|
802
|
+
window.addEventListener("online", onWindowOnline);
|
|
803
|
+
window.addEventListener("offline", onWindowOffline);
|
|
804
|
+
listenersAdded = true;
|
|
805
|
+
}
|
|
806
|
+
}
|
|
807
|
+
},
|
|
808
|
+
onLastUnsubscribe: (state, store) => {
|
|
809
|
+
var _a;
|
|
810
|
+
(_a = options.onLastUnsubscribe) == null ? void 0 : _a.call(options, state, store);
|
|
811
|
+
triggerDisconnect(store, "last-unsubscribe");
|
|
812
|
+
if (isClient) {
|
|
813
|
+
visibilityChangeListeners.delete(triggers.visibilityChange);
|
|
814
|
+
onlineListeners.delete(triggers.online);
|
|
815
|
+
offlineListeners.delete(triggers.offline);
|
|
816
|
+
if (visibilityChangeListeners.size === 0) {
|
|
817
|
+
document.removeEventListener("visibilitychange", onVisibilityChange);
|
|
818
|
+
window.removeEventListener("online", onWindowOnline);
|
|
819
|
+
window.removeEventListener("offline", onWindowOffline);
|
|
820
|
+
listenersAdded = false;
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
}
|
|
824
|
+
});
|
|
825
|
+
const getStore = (variable = {}) => {
|
|
826
|
+
const variableHash = getHash(variable);
|
|
827
|
+
let store;
|
|
828
|
+
if (stores.has(variableHash)) {
|
|
829
|
+
store = stores.get(variableHash);
|
|
830
|
+
} else {
|
|
831
|
+
store = initStore(
|
|
832
|
+
initialState,
|
|
833
|
+
configureStoreEvents()
|
|
834
|
+
// Intentionally using as any: don't want to add generic on `initStore`
|
|
835
|
+
);
|
|
836
|
+
store.variableHash = variableHash;
|
|
837
|
+
stores.set(variableHash, store);
|
|
838
|
+
store.connection = {};
|
|
839
|
+
store.connection.get = () => connections.get(store);
|
|
840
|
+
store.connection.reconnect = () => {
|
|
841
|
+
var _a;
|
|
842
|
+
const { connectionState } = store.getState();
|
|
843
|
+
if (connectionState === "CONNECTING") return;
|
|
844
|
+
(_a = disconnectFns.get(store)) == null ? void 0 : _a();
|
|
845
|
+
store.setState({
|
|
846
|
+
connectionState: "CONNECTING",
|
|
847
|
+
connectingAt: Date.now()
|
|
848
|
+
});
|
|
849
|
+
const connection = connect(variable, {
|
|
850
|
+
connected: () => {
|
|
851
|
+
store.setState({
|
|
852
|
+
connectionState: "CONNECTED",
|
|
853
|
+
connectedAt: Date.now(),
|
|
854
|
+
disconnectedAt: void 0
|
|
855
|
+
});
|
|
856
|
+
},
|
|
857
|
+
data: (reducer) => {
|
|
858
|
+
store.setState((prev) => {
|
|
859
|
+
var _a2;
|
|
860
|
+
return {
|
|
861
|
+
connectionState: "CONNECTED",
|
|
862
|
+
connectedAt: (_a2 = prev.connectedAt) != null ? _a2 : Date.now(),
|
|
863
|
+
state: "SUCCESS",
|
|
864
|
+
isSuccess: true,
|
|
865
|
+
isError: false,
|
|
866
|
+
data: reducer(prev.data),
|
|
867
|
+
dataUpdatedAt: Date.now(),
|
|
868
|
+
error: void 0,
|
|
869
|
+
errorUpdatedAt: void 0
|
|
870
|
+
};
|
|
871
|
+
});
|
|
872
|
+
},
|
|
873
|
+
error: (error) => {
|
|
874
|
+
store.setState((prev) => ({
|
|
875
|
+
state: prev.state === "SUCCESS" ? "SUCCESS_BUT_THEN_ERROR" : "ERROR",
|
|
876
|
+
isError: true,
|
|
877
|
+
error,
|
|
878
|
+
errorUpdatedAt: Date.now()
|
|
879
|
+
}));
|
|
880
|
+
}
|
|
881
|
+
});
|
|
882
|
+
connections.set(store, connection);
|
|
883
|
+
disconnectFns.set(store, () => disconnect(connection));
|
|
884
|
+
};
|
|
885
|
+
store.connection.disconnect = () => {
|
|
886
|
+
var _a;
|
|
887
|
+
if (store.getSubscriberCount()) {
|
|
888
|
+
console.warn("Stream disconnected while there is subscriber");
|
|
889
|
+
}
|
|
890
|
+
const disconnectTimeoutIds_ = disconnectTimeoutIds.get(store);
|
|
891
|
+
if (disconnectTimeoutIds_) {
|
|
892
|
+
clearTimeout(disconnectTimeoutIds_["last-unsubscribe"]);
|
|
893
|
+
clearTimeout(disconnectTimeoutIds_["document-hidden"]);
|
|
894
|
+
clearTimeout(disconnectTimeoutIds_.offline);
|
|
895
|
+
}
|
|
896
|
+
(_a = disconnectFns.get(store)) == null ? void 0 : _a();
|
|
897
|
+
if (store.getState().connectionState !== "INITIAL") {
|
|
898
|
+
store.setState({
|
|
899
|
+
connectionState: "DISCONNECTED",
|
|
900
|
+
disconnectedAt: Date.now()
|
|
901
|
+
});
|
|
902
|
+
}
|
|
903
|
+
connections.delete(store);
|
|
904
|
+
disconnectFns.delete(store);
|
|
905
|
+
clearDataTimeoutIds.set(
|
|
906
|
+
store,
|
|
907
|
+
setTimeout(() => {
|
|
908
|
+
store.data.reset();
|
|
909
|
+
}, gcTime)
|
|
910
|
+
);
|
|
911
|
+
};
|
|
912
|
+
store.data = {};
|
|
913
|
+
store.data.reset = () => {
|
|
914
|
+
store.setState({
|
|
915
|
+
state: "INITIAL",
|
|
916
|
+
isSuccess: false,
|
|
917
|
+
isError: false,
|
|
918
|
+
data: void 0,
|
|
919
|
+
dataUpdatedAt: void 0,
|
|
920
|
+
error: void 0,
|
|
921
|
+
errorUpdatedAt: void 0
|
|
922
|
+
});
|
|
923
|
+
};
|
|
924
|
+
}
|
|
925
|
+
const useStore = (options2) => useStoreState(store, {
|
|
926
|
+
initialState: { data: options2 == null ? void 0 : options2.initialData }
|
|
927
|
+
});
|
|
928
|
+
return Object.assign(useStore, store);
|
|
929
|
+
};
|
|
930
|
+
const triggerReconnect = (store, trigger) => {
|
|
931
|
+
clearTimeout(clearDataTimeoutIds.get(store));
|
|
932
|
+
const disconnectTimeoutIds_ = disconnectTimeoutIds.get(store);
|
|
933
|
+
if (disconnectTimeoutIds_) {
|
|
934
|
+
clearTimeout(disconnectTimeoutIds_["last-unsubscribe"]);
|
|
935
|
+
clearTimeout(disconnectTimeoutIds_["document-hidden"]);
|
|
936
|
+
clearTimeout(disconnectTimeoutIds_.offline);
|
|
937
|
+
}
|
|
938
|
+
const { connectionState } = store.getState();
|
|
939
|
+
console.info("triggerReconnect", connectionState);
|
|
940
|
+
if (connectionState === "INITIAL" || connectionState === "DISCONNECTED") {
|
|
941
|
+
return store.connection.reconnect();
|
|
942
|
+
}
|
|
943
|
+
const shouldReconnect = reconnectOn(trigger, store.getState());
|
|
944
|
+
console.log({ shouldReconnect });
|
|
945
|
+
if (shouldReconnect) store.connection.reconnect();
|
|
946
|
+
};
|
|
947
|
+
const triggerDisconnect = (store, trigger) => {
|
|
948
|
+
const disconnectDelay = disconnectOn(trigger, store.getState());
|
|
949
|
+
if (typeof disconnectDelay !== "number") return;
|
|
950
|
+
if (!disconnectTimeoutIds.has(store)) disconnectTimeoutIds.set(store, {});
|
|
951
|
+
const disconnectTimeoutIds_ = disconnectTimeoutIds.get(store);
|
|
952
|
+
disconnectTimeoutIds_[trigger] = setTimeout(() => {
|
|
953
|
+
store.connection.disconnect();
|
|
954
|
+
}, disconnectDelay);
|
|
955
|
+
};
|
|
956
|
+
const triggers = {
|
|
957
|
+
visibilityChange: () => {
|
|
958
|
+
console.info("visibilityChange", document.visibilityState);
|
|
959
|
+
if (document.visibilityState === "visible") {
|
|
960
|
+
stores.forEach((store) => triggerReconnect(store, "document-visible"));
|
|
961
|
+
} else {
|
|
962
|
+
stores.forEach((store) => triggerDisconnect(store, "document-hidden"));
|
|
963
|
+
}
|
|
964
|
+
},
|
|
965
|
+
online: () => stores.forEach((store) => triggerReconnect(store, "online")),
|
|
966
|
+
offline: () => stores.forEach((store) => triggerDisconnect(store, "offline"))
|
|
967
|
+
};
|
|
968
|
+
return getStore;
|
|
969
|
+
};
|
|
970
|
+
const visibilityChangeListeners = /* @__PURE__ */ new Set();
|
|
971
|
+
const onVisibilityChange = () => [...visibilityChangeListeners].forEach((fn) => fn());
|
|
972
|
+
const onlineListeners = /* @__PURE__ */ new Set();
|
|
973
|
+
const onWindowOnline = () => [...onlineListeners].forEach((fn) => fn());
|
|
974
|
+
const offlineListeners = /* @__PURE__ */ new Set();
|
|
975
|
+
const onWindowOffline = () => [...offlineListeners].forEach((fn) => fn());
|
|
976
|
+
let listenersAdded = false;
|
|
977
|
+
|
|
978
|
+
export { createMutation, createQuery, createStore, createStores, experimental_createStream, useIsomorphicLayoutEffect, useMutation, useStoreState };
|
package/package.json
CHANGED
|
@@ -2,7 +2,10 @@
|
|
|
2
2
|
"name": "floppy-disk",
|
|
3
3
|
"description": "Lightweight unified state management for sync and async data.",
|
|
4
4
|
"private": false,
|
|
5
|
-
"version": "3.
|
|
5
|
+
"version": "3.7.0-beta.2",
|
|
6
|
+
"publishConfig": {
|
|
7
|
+
"tag": "beta"
|
|
8
|
+
},
|
|
6
9
|
"keywords": [
|
|
7
10
|
"utilities",
|
|
8
11
|
"store",
|
|
@@ -44,17 +44,7 @@ export type MutationState<TData, TVariable, TError> = {
|
|
|
44
44
|
error: TError;
|
|
45
45
|
errorUpdatedAt: number;
|
|
46
46
|
});
|
|
47
|
-
export declare const INITIAL_STATE:
|
|
48
|
-
state: string;
|
|
49
|
-
isPending: boolean;
|
|
50
|
-
isSuccess: boolean;
|
|
51
|
-
isError: boolean;
|
|
52
|
-
variable: undefined;
|
|
53
|
-
data: undefined;
|
|
54
|
-
dataUpdatedAt: undefined;
|
|
55
|
-
error: undefined;
|
|
56
|
-
errorUpdatedAt: undefined;
|
|
57
|
-
};
|
|
47
|
+
export declare const INITIAL_STATE: MutationState<any, any, any>;
|
|
58
48
|
/**
|
|
59
49
|
* Configuration options for a mutation.
|
|
60
50
|
*
|