reactjrx 1.47.0 → 1.48.0
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/dist/index.cjs +102 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +103 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -232,6 +232,107 @@ const createLocalforageAdapter = (forage) => ({
|
|
|
232
232
|
await forage.setItem(key, JSON.stringify(value));
|
|
233
233
|
}
|
|
234
234
|
});
|
|
235
|
+
const createLocalStorageAdapter = (forage) => ({
|
|
236
|
+
getItem: async (key) => {
|
|
237
|
+
const serializedValue = forage.getItem(key);
|
|
238
|
+
if (!serializedValue)
|
|
239
|
+
return void 0;
|
|
240
|
+
return JSON.parse(serializedValue);
|
|
241
|
+
},
|
|
242
|
+
setItem: async (key, value) => {
|
|
243
|
+
forage.setItem(key, JSON.stringify(value));
|
|
244
|
+
}
|
|
245
|
+
});
|
|
246
|
+
const IDENTIFIER_PERSISTANCE_KEY = "__reactjrx";
|
|
247
|
+
const getNormalizedPersistanceValue = (unknownValue) => {
|
|
248
|
+
if (typeof unknownValue === "object" && unknownValue !== null && IDENTIFIER_PERSISTANCE_KEY in unknownValue && unknownValue[IDENTIFIER_PERSISTANCE_KEY] === IDENTIFIER_PERSISTANCE_KEY) {
|
|
249
|
+
return unknownValue;
|
|
250
|
+
}
|
|
251
|
+
return void 0;
|
|
252
|
+
};
|
|
253
|
+
const persistValue = async ({
|
|
254
|
+
adapter,
|
|
255
|
+
signal: signal2,
|
|
256
|
+
version
|
|
257
|
+
}) => {
|
|
258
|
+
const state = signal2.getValue();
|
|
259
|
+
const value = {
|
|
260
|
+
value: state,
|
|
261
|
+
[IDENTIFIER_PERSISTANCE_KEY]: IDENTIFIER_PERSISTANCE_KEY,
|
|
262
|
+
migrationVersion: version
|
|
263
|
+
};
|
|
264
|
+
await adapter.setItem(signal2.config.key, value);
|
|
265
|
+
};
|
|
266
|
+
const hydrateValueToSignal = ({
|
|
267
|
+
adapter,
|
|
268
|
+
version,
|
|
269
|
+
signal: signal2
|
|
270
|
+
}) => {
|
|
271
|
+
return rxjs.from(adapter.getItem(signal2.config.key)).pipe(
|
|
272
|
+
rxjs.switchMap((value) => {
|
|
273
|
+
const normalizedValue = getNormalizedPersistanceValue(value);
|
|
274
|
+
if (!normalizedValue)
|
|
275
|
+
return rxjs.of(value);
|
|
276
|
+
if (normalizedValue.migrationVersion !== void 0 && version > normalizedValue.migrationVersion) {
|
|
277
|
+
return rxjs.of(value);
|
|
278
|
+
}
|
|
279
|
+
signal2.setValue(value.value);
|
|
280
|
+
return rxjs.of(value);
|
|
281
|
+
})
|
|
282
|
+
);
|
|
283
|
+
};
|
|
284
|
+
const usePersistSignals = ({
|
|
285
|
+
entries = [],
|
|
286
|
+
onReady,
|
|
287
|
+
adapter = createLocalStorageAdapter(localStorage)
|
|
288
|
+
}) => {
|
|
289
|
+
const entriesRef = useLiveRef(entries);
|
|
290
|
+
const onReadyRef = useLiveRef(onReady);
|
|
291
|
+
const adapterRef = useLiveRef(adapter);
|
|
292
|
+
const isHydrated = useObserve(
|
|
293
|
+
() => {
|
|
294
|
+
const entries2 = entriesRef.current;
|
|
295
|
+
const stream = entries2.length === 0 ? rxjs.of(true) : rxjs.zip(
|
|
296
|
+
...entries2.map(
|
|
297
|
+
({ signal: signal2, version }) => hydrateValueToSignal({
|
|
298
|
+
adapter: adapterRef.current,
|
|
299
|
+
signal: signal2,
|
|
300
|
+
version
|
|
301
|
+
})
|
|
302
|
+
)
|
|
303
|
+
).pipe(rxjs.map(() => true));
|
|
304
|
+
return stream.pipe(
|
|
305
|
+
rxjs.tap(() => {
|
|
306
|
+
if (onReadyRef.current != null)
|
|
307
|
+
onReadyRef.current();
|
|
308
|
+
}),
|
|
309
|
+
rxjs.catchError((error) => {
|
|
310
|
+
console.error("Unable to hydrate", error);
|
|
311
|
+
return rxjs.EMPTY;
|
|
312
|
+
})
|
|
313
|
+
);
|
|
314
|
+
},
|
|
315
|
+
{ defaultValue: false },
|
|
316
|
+
[]
|
|
317
|
+
);
|
|
318
|
+
useSubscribe(() => {
|
|
319
|
+
return !isHydrated ? rxjs.EMPTY : rxjs.merge(
|
|
320
|
+
...entriesRef.current.map(
|
|
321
|
+
({ signal: signal2, version }) => signal2.subject.pipe(
|
|
322
|
+
rxjs.throttleTime(500, rxjs.asyncScheduler, {
|
|
323
|
+
trailing: true
|
|
324
|
+
}),
|
|
325
|
+
rxjs.switchMap(
|
|
326
|
+
() => rxjs.from(
|
|
327
|
+
persistValue({ adapter: adapterRef.current, signal: signal2, version })
|
|
328
|
+
)
|
|
329
|
+
)
|
|
330
|
+
)
|
|
331
|
+
)
|
|
332
|
+
);
|
|
333
|
+
}, [isHydrated, adapterRef]);
|
|
334
|
+
return { isHydrated };
|
|
335
|
+
};
|
|
235
336
|
const useUnmountObservable = () => {
|
|
236
337
|
const subject = useSubject({
|
|
237
338
|
onBeforeComplete: () => {
|
|
@@ -1575,6 +1676,7 @@ exports.useBehaviorSubject = useBehaviorSubject;
|
|
|
1575
1676
|
exports.useLiveRef = useLiveRef;
|
|
1576
1677
|
exports.useObserve = useObserve;
|
|
1577
1678
|
exports.useObserveCallback = useObserveCallback;
|
|
1679
|
+
exports.usePersistSignals = usePersistSignals;
|
|
1578
1680
|
exports.useQuery = useQuery;
|
|
1579
1681
|
exports.useQueryClient = useQueryClient;
|
|
1580
1682
|
exports.useSignalValue = useSignalValue;
|
package/dist/index.d.ts
CHANGED
|
@@ -9,6 +9,7 @@ export * from "./lib/state/useSignalValue";
|
|
|
9
9
|
export * from "./lib/state/constants";
|
|
10
10
|
export * from "./lib/state/persistance/adapters/createSharedStoreAdapter";
|
|
11
11
|
export * from "./lib/state/persistance/adapters/createLocalforageAdapter";
|
|
12
|
+
export * from "./lib/state/persistance/usePersistSignals";
|
|
12
13
|
export * from "./lib/utils/useUnmountObservable";
|
|
13
14
|
export * from "./lib/utils/retryBackoff";
|
|
14
15
|
export * from "./lib/utils/useLiveRef";
|
package/dist/index.js
CHANGED
|
@@ -5,7 +5,7 @@ var __publicField = (obj, key, value) => {
|
|
|
5
5
|
return value;
|
|
6
6
|
};
|
|
7
7
|
import { useRef, useMemo, useCallback, useSyncExternalStore, useEffect, createContext, memo, useContext } from "react";
|
|
8
|
-
import { distinctUntilChanged, tap, finalize, catchError, EMPTY, Subject, identity, BehaviorSubject, defer, iif, timer, throwError, scan,
|
|
8
|
+
import { distinctUntilChanged, tap, finalize, catchError, EMPTY, Subject, identity, BehaviorSubject, of, zip, map, merge, throttleTime, asyncScheduler, switchMap, from, defer, iif, timer, throwError, scan, take, startWith, combineLatest, first, takeUntil, filter, concatMap as concatMap$1, mergeMap, fromEvent, skip, withLatestFrom, retry, shareReplay, endWith, delay, share, pairwise, NEVER, takeWhile } from "rxjs";
|
|
9
9
|
import { retryWhen, concatMap, tap as tap$1 } from "rxjs/operators";
|
|
10
10
|
import { jsxs, jsx } from "react/jsx-runtime";
|
|
11
11
|
const useLiveRef = (value) => {
|
|
@@ -230,6 +230,107 @@ const createLocalforageAdapter = (forage) => ({
|
|
|
230
230
|
await forage.setItem(key, JSON.stringify(value));
|
|
231
231
|
}
|
|
232
232
|
});
|
|
233
|
+
const createLocalStorageAdapter = (forage) => ({
|
|
234
|
+
getItem: async (key) => {
|
|
235
|
+
const serializedValue = forage.getItem(key);
|
|
236
|
+
if (!serializedValue)
|
|
237
|
+
return void 0;
|
|
238
|
+
return JSON.parse(serializedValue);
|
|
239
|
+
},
|
|
240
|
+
setItem: async (key, value) => {
|
|
241
|
+
forage.setItem(key, JSON.stringify(value));
|
|
242
|
+
}
|
|
243
|
+
});
|
|
244
|
+
const IDENTIFIER_PERSISTANCE_KEY = "__reactjrx";
|
|
245
|
+
const getNormalizedPersistanceValue = (unknownValue) => {
|
|
246
|
+
if (typeof unknownValue === "object" && unknownValue !== null && IDENTIFIER_PERSISTANCE_KEY in unknownValue && unknownValue[IDENTIFIER_PERSISTANCE_KEY] === IDENTIFIER_PERSISTANCE_KEY) {
|
|
247
|
+
return unknownValue;
|
|
248
|
+
}
|
|
249
|
+
return void 0;
|
|
250
|
+
};
|
|
251
|
+
const persistValue = async ({
|
|
252
|
+
adapter,
|
|
253
|
+
signal: signal2,
|
|
254
|
+
version
|
|
255
|
+
}) => {
|
|
256
|
+
const state = signal2.getValue();
|
|
257
|
+
const value = {
|
|
258
|
+
value: state,
|
|
259
|
+
[IDENTIFIER_PERSISTANCE_KEY]: IDENTIFIER_PERSISTANCE_KEY,
|
|
260
|
+
migrationVersion: version
|
|
261
|
+
};
|
|
262
|
+
await adapter.setItem(signal2.config.key, value);
|
|
263
|
+
};
|
|
264
|
+
const hydrateValueToSignal = ({
|
|
265
|
+
adapter,
|
|
266
|
+
version,
|
|
267
|
+
signal: signal2
|
|
268
|
+
}) => {
|
|
269
|
+
return from(adapter.getItem(signal2.config.key)).pipe(
|
|
270
|
+
switchMap((value) => {
|
|
271
|
+
const normalizedValue = getNormalizedPersistanceValue(value);
|
|
272
|
+
if (!normalizedValue)
|
|
273
|
+
return of(value);
|
|
274
|
+
if (normalizedValue.migrationVersion !== void 0 && version > normalizedValue.migrationVersion) {
|
|
275
|
+
return of(value);
|
|
276
|
+
}
|
|
277
|
+
signal2.setValue(value.value);
|
|
278
|
+
return of(value);
|
|
279
|
+
})
|
|
280
|
+
);
|
|
281
|
+
};
|
|
282
|
+
const usePersistSignals = ({
|
|
283
|
+
entries = [],
|
|
284
|
+
onReady,
|
|
285
|
+
adapter = createLocalStorageAdapter(localStorage)
|
|
286
|
+
}) => {
|
|
287
|
+
const entriesRef = useLiveRef(entries);
|
|
288
|
+
const onReadyRef = useLiveRef(onReady);
|
|
289
|
+
const adapterRef = useLiveRef(adapter);
|
|
290
|
+
const isHydrated = useObserve(
|
|
291
|
+
() => {
|
|
292
|
+
const entries2 = entriesRef.current;
|
|
293
|
+
const stream = entries2.length === 0 ? of(true) : zip(
|
|
294
|
+
...entries2.map(
|
|
295
|
+
({ signal: signal2, version }) => hydrateValueToSignal({
|
|
296
|
+
adapter: adapterRef.current,
|
|
297
|
+
signal: signal2,
|
|
298
|
+
version
|
|
299
|
+
})
|
|
300
|
+
)
|
|
301
|
+
).pipe(map(() => true));
|
|
302
|
+
return stream.pipe(
|
|
303
|
+
tap(() => {
|
|
304
|
+
if (onReadyRef.current != null)
|
|
305
|
+
onReadyRef.current();
|
|
306
|
+
}),
|
|
307
|
+
catchError((error) => {
|
|
308
|
+
console.error("Unable to hydrate", error);
|
|
309
|
+
return EMPTY;
|
|
310
|
+
})
|
|
311
|
+
);
|
|
312
|
+
},
|
|
313
|
+
{ defaultValue: false },
|
|
314
|
+
[]
|
|
315
|
+
);
|
|
316
|
+
useSubscribe(() => {
|
|
317
|
+
return !isHydrated ? EMPTY : merge(
|
|
318
|
+
...entriesRef.current.map(
|
|
319
|
+
({ signal: signal2, version }) => signal2.subject.pipe(
|
|
320
|
+
throttleTime(500, asyncScheduler, {
|
|
321
|
+
trailing: true
|
|
322
|
+
}),
|
|
323
|
+
switchMap(
|
|
324
|
+
() => from(
|
|
325
|
+
persistValue({ adapter: adapterRef.current, signal: signal2, version })
|
|
326
|
+
)
|
|
327
|
+
)
|
|
328
|
+
)
|
|
329
|
+
)
|
|
330
|
+
);
|
|
331
|
+
}, [isHydrated, adapterRef]);
|
|
332
|
+
return { isHydrated };
|
|
333
|
+
};
|
|
233
334
|
const useUnmountObservable = () => {
|
|
234
335
|
const subject = useSubject({
|
|
235
336
|
onBeforeComplete: () => {
|
|
@@ -1574,6 +1675,7 @@ export {
|
|
|
1574
1675
|
useLiveRef,
|
|
1575
1676
|
useObserve,
|
|
1576
1677
|
useObserveCallback,
|
|
1678
|
+
usePersistSignals,
|
|
1577
1679
|
useQuery,
|
|
1578
1680
|
useQueryClient,
|
|
1579
1681
|
useSignalValue,
|