reactjrx 1.35.0 → 1.40.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 +995 -268
- package/dist/index.d.ts +4 -4
- package/dist/index.js +997 -270
- package/dist/lib/logger.d.ts +48 -0
- package/dist/lib/queries/client/cache/cacheClient.d.ts +12 -0
- package/dist/lib/queries/client/cache/invalidateCache.d.ts +5 -0
- package/dist/lib/queries/client/cache/logger.d.ts +24 -0
- package/dist/lib/queries/client/cache/registerResultInCache.d.ts +8 -0
- package/dist/lib/queries/client/createClient.d.ts +69 -17
- package/dist/lib/queries/client/deduplication/deduplicate.d.ts +3 -0
- package/dist/lib/queries/client/fetch/mapWithComplete.d.ts +4 -0
- package/dist/lib/queries/client/fetch/notifyQueryResult.d.ts +3 -0
- package/dist/lib/queries/client/fetch/queryFetch.d.ts +12 -0
- package/dist/lib/queries/client/invalidation/invalidationClient.d.ts +12 -0
- package/dist/lib/queries/client/invalidation/logger.d.ts +24 -0
- package/dist/lib/queries/client/invalidation/markAsStale.d.ts +8 -0
- package/dist/lib/queries/client/keys/compareKeys.d.ts +4 -0
- package/dist/lib/queries/client/keys/serializeKey.d.ts +3 -0
- package/dist/lib/queries/client/keys/types.d.ts +10 -0
- package/dist/lib/queries/client/operators.d.ts +2 -3
- package/dist/lib/queries/client/refetch/client.d.ts +18 -0
- package/dist/lib/queries/client/store/createQueryStore.d.ts +55 -0
- package/dist/lib/queries/client/store/debugger.d.ts +3 -0
- package/dist/lib/queries/client/store/garbageCache.d.ts +5 -0
- package/dist/lib/queries/client/store/initializeQueryInStore.d.ts +8 -0
- package/dist/lib/queries/client/store/mapStoreQueryToRunnerOptions.d.ts +4 -0
- package/dist/lib/queries/client/store/queryListener.d.ts +3 -0
- package/dist/lib/queries/client/store/updateStoreWithQuery.d.ts +14 -0
- package/dist/lib/queries/client/triggers.d.ts +17 -0
- package/dist/lib/queries/client/types.d.ts +42 -1
- package/dist/lib/queries/{Provider.d.ts → react/Provider.d.ts} +2 -15
- package/dist/lib/queries/react/helpers.d.ts +27 -0
- package/dist/lib/queries/react/triggers/activityTrigger.d.ts +9 -0
- package/dist/lib/queries/react/triggers/networkTrigger.d.ts +7 -0
- package/dist/lib/queries/react/types.d.ts +13 -0
- package/dist/lib/queries/react/useQuery.d.ts +6 -0
- package/dist/lib/utils/difference.d.ts +1 -0
- package/package.json +1 -1
- package/dist/lib/queries/cache/useCreateCacheStore.d.ts +0 -9
- package/dist/lib/queries/deduplication/deduplicate.d.ts +0 -3
- package/dist/lib/queries/deduplication/useQueryStore.d.ts +0 -3
- package/dist/lib/queries/invalidation/autoRefetch.d.ts +0 -4
- package/dist/lib/queries/keys/serializeKey.d.ts +0 -1
- package/dist/lib/queries/operators.d.ts +0 -2
- package/dist/lib/queries/querx.d.ts +0 -3
- package/dist/lib/queries/types.d.ts +0 -10
- package/dist/lib/queries/useQuery.d.ts +0 -12
- /package/dist/lib/queries/{useAsyncQuery.d.ts → react/useAsyncQuery.d.ts} +0 -0
- /package/dist/lib/queries/{useSubscribeEffect.d.ts → react/useSubscribeEffect.d.ts} +0 -0
package/dist/index.cjs
CHANGED
|
@@ -411,15 +411,6 @@ function retryBackoff(config) {
|
|
|
411
411
|
);
|
|
412
412
|
});
|
|
413
413
|
}
|
|
414
|
-
const retryFromOptions = (options) => retryBackoff({
|
|
415
|
-
initialInterval: 100,
|
|
416
|
-
...typeof options.retry === "function" ? {
|
|
417
|
-
shouldRetry: options.retry
|
|
418
|
-
} : {
|
|
419
|
-
maxRetries: options.retry === false ? 0 : options.retry ?? 3
|
|
420
|
-
}
|
|
421
|
-
});
|
|
422
|
-
const querx = (options) => (source) => source.pipe(retryFromOptions(options));
|
|
423
414
|
const useBehaviorSubject = (state) => {
|
|
424
415
|
const subject = useConstant(() => new rxjs.BehaviorSubject(state));
|
|
425
416
|
const completed = react.useRef(false);
|
|
@@ -459,6 +450,31 @@ function shallowEqual(objA, objB) {
|
|
|
459
450
|
}
|
|
460
451
|
return true;
|
|
461
452
|
}
|
|
453
|
+
const retryOnError = (options) => retryBackoff({
|
|
454
|
+
initialInterval: 100,
|
|
455
|
+
...typeof options.retry === "function" ? {
|
|
456
|
+
shouldRetry: options.retry
|
|
457
|
+
} : {
|
|
458
|
+
maxRetries: options.retry === false ? 0 : options.retry ?? 3
|
|
459
|
+
}
|
|
460
|
+
});
|
|
461
|
+
const mergeResults = (stream$) => stream$.pipe(
|
|
462
|
+
rxjs.scan(
|
|
463
|
+
(acc, current) => {
|
|
464
|
+
return {
|
|
465
|
+
...acc,
|
|
466
|
+
...current
|
|
467
|
+
};
|
|
468
|
+
},
|
|
469
|
+
{
|
|
470
|
+
data: void 0,
|
|
471
|
+
error: void 0,
|
|
472
|
+
fetchStatus: "idle",
|
|
473
|
+
status: "loading"
|
|
474
|
+
}
|
|
475
|
+
),
|
|
476
|
+
rxjs.distinctUntilChanged(shallowEqual)
|
|
477
|
+
);
|
|
462
478
|
function useAsyncQuery(query, mapOperatorOrOptions, options = {}) {
|
|
463
479
|
const queryRef = useLiveRef(query);
|
|
464
480
|
const triggerSubject = useSubject();
|
|
@@ -505,7 +521,7 @@ function useAsyncQuery(query, mapOperatorOrOptions, options = {}) {
|
|
|
505
521
|
}),
|
|
506
522
|
rxjs.combineLatest([
|
|
507
523
|
rxjs.defer(() => rxjs.from(queryRef.current(args))).pipe(
|
|
508
|
-
|
|
524
|
+
retryOnError(optionsRef.current),
|
|
509
525
|
rxjs.first(),
|
|
510
526
|
rxjs.map((data) => ({ data, isError: false })),
|
|
511
527
|
rxjs.catchError((error) => {
|
|
@@ -519,7 +535,6 @@ function useAsyncQuery(query, mapOperatorOrOptions, options = {}) {
|
|
|
519
535
|
isLastMutationCalled
|
|
520
536
|
]).pipe(
|
|
521
537
|
rxjs.map(([{ data, isError }, isLastMutationCalled2]) => {
|
|
522
|
-
console.log("success", { data, isLastMutationCalled: isLastMutationCalled2 });
|
|
523
538
|
if (!isError) {
|
|
524
539
|
if (optionsRef.current.onSuccess != null)
|
|
525
540
|
optionsRef.current.onSuccess(data, args);
|
|
@@ -580,217 +595,15 @@ function useAsyncQuery(query, mapOperatorOrOptions, options = {}) {
|
|
|
580
595
|
}, []);
|
|
581
596
|
return { ...result, isLoading: result.status === "loading", mutate, reset };
|
|
582
597
|
}
|
|
583
|
-
const useCreateCacheStore = () => {
|
|
584
|
-
const cacheStore = useBehaviorSubject({});
|
|
585
|
-
useSubscribe(
|
|
586
|
-
() => cacheStore.current.pipe(
|
|
587
|
-
rxjs.skip(1),
|
|
588
|
-
rxjs.tap(() => {
|
|
589
|
-
const store = cacheStore.current.getValue();
|
|
590
|
-
console.log(
|
|
591
|
-
"[cache] update",
|
|
592
|
-
Object.keys(store).reduce((acc, key) => {
|
|
593
|
-
const entry = store[key];
|
|
594
|
-
if (entry != null) {
|
|
595
|
-
acc[key] = entry;
|
|
596
|
-
}
|
|
597
|
-
acc[key]._debug = {
|
|
598
|
-
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
599
|
-
// @ts-expect-error
|
|
600
|
-
eol: new Date(store[key].date + store[key].ttl)
|
|
601
|
-
};
|
|
602
|
-
return acc;
|
|
603
|
-
}, {})
|
|
604
|
-
);
|
|
605
|
-
})
|
|
606
|
-
),
|
|
607
|
-
[cacheStore]
|
|
608
|
-
);
|
|
609
|
-
useSubscribe(
|
|
610
|
-
() => rxjs.interval(1e3).pipe(
|
|
611
|
-
rxjs.withLatestFrom(cacheStore.current),
|
|
612
|
-
rxjs.tap(() => {
|
|
613
|
-
const now = (/* @__PURE__ */ new Date()).getTime();
|
|
614
|
-
const store = cacheStore.current.getValue();
|
|
615
|
-
const keys = Object.keys(store);
|
|
616
|
-
const validKeys = keys.filter((key) => {
|
|
617
|
-
const value = store[key];
|
|
618
|
-
if (value != null && value.date + value.ttl > now) {
|
|
619
|
-
return true;
|
|
620
|
-
}
|
|
621
|
-
return false;
|
|
622
|
-
});
|
|
623
|
-
if (validKeys.length === keys.length) {
|
|
624
|
-
return;
|
|
625
|
-
}
|
|
626
|
-
const newStore = validKeys.reduce((acc, key) => {
|
|
627
|
-
const entry = store[key];
|
|
628
|
-
if (entry != null) {
|
|
629
|
-
acc[key] = entry;
|
|
630
|
-
}
|
|
631
|
-
return acc;
|
|
632
|
-
}, {});
|
|
633
|
-
cacheStore.current.next(newStore);
|
|
634
|
-
})
|
|
635
|
-
),
|
|
636
|
-
[cacheStore]
|
|
637
|
-
);
|
|
638
|
-
return cacheStore;
|
|
639
|
-
};
|
|
640
|
-
const useQueryStore = () => {
|
|
641
|
-
const [store] = react.useState(/* @__PURE__ */ new Map());
|
|
642
|
-
return store;
|
|
643
|
-
};
|
|
644
|
-
const DEFAULT_STALE = 9999;
|
|
645
|
-
const autoRefetch = (options$ = rxjs.of({})) => (source) => {
|
|
646
|
-
return source.pipe(
|
|
647
|
-
rxjs.repeat({
|
|
648
|
-
delay: () => options$.pipe(
|
|
649
|
-
rxjs.switchMap(
|
|
650
|
-
(options) => options.staleTime === Infinity ? rxjs.EMPTY : rxjs.timer(options.staleTime ?? DEFAULT_STALE)
|
|
651
|
-
)
|
|
652
|
-
)
|
|
653
|
-
})
|
|
654
|
-
);
|
|
655
|
-
};
|
|
656
|
-
const deduplicate = (key, queryStore) => (source) => {
|
|
657
|
-
if (!key)
|
|
658
|
-
return source;
|
|
659
|
-
const sourceFromStore = queryStore == null ? void 0 : queryStore.get(key);
|
|
660
|
-
const finalSource = sourceFromStore ?? source.pipe(
|
|
661
|
-
rxjs.finalize(() => {
|
|
662
|
-
queryStore == null ? void 0 : queryStore.delete(key);
|
|
663
|
-
}),
|
|
664
|
-
rxjs.shareReplay({
|
|
665
|
-
refCount: true,
|
|
666
|
-
bufferSize: 1
|
|
667
|
-
})
|
|
668
|
-
);
|
|
669
|
-
if (sourceFromStore == null) {
|
|
670
|
-
queryStore == null ? void 0 : queryStore.set(key, finalSource);
|
|
671
|
-
}
|
|
672
|
-
return finalSource;
|
|
673
|
-
};
|
|
674
|
-
const serializeKey = (key) => {
|
|
675
|
-
if (key.length === 0)
|
|
676
|
-
return "";
|
|
677
|
-
return JSON.stringify(key);
|
|
678
|
-
};
|
|
679
|
-
const notifyQueryResult = (options$) => (stream$) => stream$.pipe(
|
|
680
|
-
rxjs.withLatestFrom(options$),
|
|
681
|
-
rxjs.map(([result, options]) => {
|
|
682
|
-
var _a, _b;
|
|
683
|
-
if (result.error) {
|
|
684
|
-
(_a = options.onError) == null ? void 0 : _a.call(options, result.error);
|
|
685
|
-
} else {
|
|
686
|
-
(_b = options.onSuccess) == null ? void 0 : _b.call(options, result);
|
|
687
|
-
}
|
|
688
|
-
return result;
|
|
689
|
-
})
|
|
690
|
-
);
|
|
691
|
-
const mergeResults = (stream$) => stream$.pipe(
|
|
692
|
-
rxjs.startWith({ isLoading: false, data: void 0, error: void 0 }),
|
|
693
|
-
rxjs.pairwise(),
|
|
694
|
-
rxjs.map(([previous, current]) => ({
|
|
695
|
-
isLoading: false,
|
|
696
|
-
data: void 0,
|
|
697
|
-
error: void 0,
|
|
698
|
-
...previous,
|
|
699
|
-
...current
|
|
700
|
-
})),
|
|
701
|
-
rxjs.distinctUntilChanged(shallowEqual)
|
|
702
|
-
);
|
|
703
|
-
const createClient = () => {
|
|
704
|
-
const queryStore = /* @__PURE__ */ new Map();
|
|
705
|
-
const refetch$ = new rxjs.Subject();
|
|
706
|
-
const query$ = ({
|
|
707
|
-
key,
|
|
708
|
-
fn$,
|
|
709
|
-
options$
|
|
710
|
-
}) => {
|
|
711
|
-
const refetch$2 = new rxjs.Subject();
|
|
712
|
-
const enabled$ = options$.pipe(rxjs.map(({ enabled = true }) => enabled));
|
|
713
|
-
const disabled$ = enabled$.pipe(
|
|
714
|
-
rxjs.distinctUntilChanged(),
|
|
715
|
-
rxjs.filter((enabled) => !enabled)
|
|
716
|
-
);
|
|
717
|
-
const triggers = [
|
|
718
|
-
refetch$2.pipe(rxjs.startWith(null)),
|
|
719
|
-
enabled$.pipe(
|
|
720
|
-
rxjs.distinctUntilChanged(),
|
|
721
|
-
rxjs.filter((enabled) => enabled)
|
|
722
|
-
)
|
|
723
|
-
];
|
|
724
|
-
const serializedKey = serializeKey(key);
|
|
725
|
-
const query$2 = rxjs.combineLatest(triggers).pipe(
|
|
726
|
-
rxjs.tap((params) => {
|
|
727
|
-
console.log("query$ trigger", { key, params });
|
|
728
|
-
}),
|
|
729
|
-
rxjs.withLatestFrom(fn$),
|
|
730
|
-
rxjs.switchMap(([, query]) => {
|
|
731
|
-
const deferredQuery = rxjs.defer(() => {
|
|
732
|
-
const queryOrResponse = typeof query === "function" ? query() : query;
|
|
733
|
-
return rxjs.from(queryOrResponse);
|
|
734
|
-
});
|
|
735
|
-
return rxjs.merge(
|
|
736
|
-
disabled$.pipe(
|
|
737
|
-
rxjs.take(1),
|
|
738
|
-
rxjs.map(() => ({
|
|
739
|
-
isLoading: false
|
|
740
|
-
}))
|
|
741
|
-
),
|
|
742
|
-
rxjs.merge(
|
|
743
|
-
rxjs.of({ isLoading: true, error: void 0 }),
|
|
744
|
-
deferredQuery.pipe(
|
|
745
|
-
deduplicate(serializedKey, queryStore),
|
|
746
|
-
rxjs.map((result) => ({
|
|
747
|
-
isLoading: false,
|
|
748
|
-
data: { result },
|
|
749
|
-
error: void 0
|
|
750
|
-
})),
|
|
751
|
-
rxjs.catchError(
|
|
752
|
-
(error) => rxjs.of({
|
|
753
|
-
isLoading: false,
|
|
754
|
-
data: void 0,
|
|
755
|
-
error
|
|
756
|
-
})
|
|
757
|
-
),
|
|
758
|
-
notifyQueryResult(options$)
|
|
759
|
-
)
|
|
760
|
-
).pipe(autoRefetch(options$), rxjs.takeUntil(disabled$))
|
|
761
|
-
);
|
|
762
|
-
}),
|
|
763
|
-
mergeResults,
|
|
764
|
-
rxjs.tap((data) => {
|
|
765
|
-
console.log("query$ return", data);
|
|
766
|
-
})
|
|
767
|
-
);
|
|
768
|
-
return {
|
|
769
|
-
query$: query$2,
|
|
770
|
-
refetch$: refetch$2,
|
|
771
|
-
enabled$
|
|
772
|
-
};
|
|
773
|
-
};
|
|
774
|
-
return {
|
|
775
|
-
query$,
|
|
776
|
-
refetch$,
|
|
777
|
-
queryStore,
|
|
778
|
-
destroy: () => {
|
|
779
|
-
}
|
|
780
|
-
};
|
|
781
|
-
};
|
|
782
598
|
const Context = react.createContext({
|
|
783
|
-
|
|
784
|
-
client: createClient()
|
|
599
|
+
client: null
|
|
785
600
|
});
|
|
786
601
|
const Provider = react.memo(
|
|
787
602
|
({
|
|
788
603
|
children,
|
|
789
604
|
client
|
|
790
605
|
}) => {
|
|
791
|
-
const
|
|
792
|
-
const queryStore = useQueryStore();
|
|
793
|
-
const value = react.useMemo(() => ({ cacheStore, queryStore, client }), [client]);
|
|
606
|
+
const value = react.useMemo(() => ({ client }), [client]);
|
|
794
607
|
react.useEffect(
|
|
795
608
|
() => () => {
|
|
796
609
|
client.destroy();
|
|
@@ -800,91 +613,137 @@ const Provider = react.memo(
|
|
|
800
613
|
return /* @__PURE__ */ jsxRuntime.jsx(Context.Provider, { value, children });
|
|
801
614
|
}
|
|
802
615
|
);
|
|
803
|
-
const
|
|
616
|
+
const useReactJrxProvider = () => {
|
|
804
617
|
const context = react.useContext(Context);
|
|
618
|
+
if (context === null) {
|
|
619
|
+
throw new Error("You forgot to register the provider");
|
|
620
|
+
}
|
|
805
621
|
return { ...context };
|
|
806
622
|
};
|
|
807
623
|
const arrayEqual = (a, b) => a.length === b.length && a.every((v, i) => v === b[i]);
|
|
808
624
|
function isDefined(arg) {
|
|
809
625
|
return arg !== null && arg !== void 0;
|
|
810
626
|
}
|
|
811
|
-
const
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
627
|
+
const createActivityTrigger = (params$) => {
|
|
628
|
+
return params$.pipe(
|
|
629
|
+
rxjs.switchMap(({ options: { refetchOnWindowFocus = true } }) => {
|
|
630
|
+
const shouldRunTrigger = typeof refetchOnWindowFocus === "function" ? refetchOnWindowFocus({}) : refetchOnWindowFocus;
|
|
631
|
+
return shouldRunTrigger !== false ? rxjs.merge(
|
|
632
|
+
rxjs.fromEvent(document, "visibilitychange").pipe(
|
|
633
|
+
rxjs.filter(() => !document.hidden),
|
|
634
|
+
rxjs.map(() => ({ ignoreStale: shouldRunTrigger === "always" }))
|
|
635
|
+
),
|
|
636
|
+
rxjs.fromEvent(window, "focus").pipe(
|
|
637
|
+
rxjs.map(() => ({ ignoreStale: shouldRunTrigger === "always" }))
|
|
638
|
+
)
|
|
639
|
+
) : rxjs.EMPTY;
|
|
640
|
+
})
|
|
641
|
+
);
|
|
642
|
+
};
|
|
643
|
+
const createNetworkTrigger = (params$) => {
|
|
644
|
+
return params$.pipe(
|
|
645
|
+
rxjs.switchMap(({ options: { refetchOnReconnect = true } }) => {
|
|
646
|
+
const shouldRunTrigger = typeof refetchOnReconnect === "function" ? refetchOnReconnect({}) : refetchOnReconnect;
|
|
647
|
+
return shouldRunTrigger !== false ? rxjs.fromEvent(window, "online").pipe(
|
|
648
|
+
rxjs.map(() => ({ ignoreStale: shouldRunTrigger === "always" }))
|
|
649
|
+
) : rxjs.EMPTY;
|
|
650
|
+
})
|
|
651
|
+
);
|
|
652
|
+
};
|
|
653
|
+
const useQueryParams = ({
|
|
654
|
+
queryKey,
|
|
655
|
+
queryFn,
|
|
656
|
+
...options
|
|
657
|
+
}) => {
|
|
658
|
+
const params$ = useBehaviorSubject({ queryKey, options, queryFn });
|
|
819
659
|
react.useEffect(() => {
|
|
820
660
|
params$.current.next({
|
|
821
|
-
|
|
661
|
+
queryKey,
|
|
822
662
|
options,
|
|
823
|
-
|
|
663
|
+
queryFn
|
|
824
664
|
});
|
|
825
|
-
}, [
|
|
665
|
+
}, [queryKey, options, queryFn]);
|
|
666
|
+
return params$;
|
|
667
|
+
};
|
|
668
|
+
const defaultValue = {
|
|
669
|
+
data: void 0,
|
|
670
|
+
isLoading: true,
|
|
671
|
+
error: void 0,
|
|
672
|
+
status: "loading",
|
|
673
|
+
fetchStatus: "idle"
|
|
674
|
+
};
|
|
675
|
+
function useQuery({
|
|
676
|
+
queryKey,
|
|
677
|
+
queryFn,
|
|
678
|
+
...options
|
|
679
|
+
}) {
|
|
680
|
+
const internalRefresh$ = useSubject();
|
|
681
|
+
const { client } = useReactJrxProvider();
|
|
682
|
+
const params$ = useQueryParams({ queryFn, queryKey, ...options });
|
|
826
683
|
const result = useObserve(
|
|
827
684
|
() => {
|
|
828
|
-
const
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
rxjs.map(({ key: key2 }) => key2 ?? []),
|
|
834
|
-
rxjs.distinctUntilChanged(arrayEqual)
|
|
685
|
+
const key$ = params$.current.pipe(rxjs.map(({ queryKey: queryKey2 }) => queryKey2 ?? []));
|
|
686
|
+
const initialTrigger$ = rxjs.of(null);
|
|
687
|
+
const newKeyTrigger$ = key$.pipe(
|
|
688
|
+
rxjs.distinctUntilChanged(arrayEqual),
|
|
689
|
+
rxjs.skip(1)
|
|
835
690
|
);
|
|
691
|
+
const isQueryObject = (query) => !!query && typeof query !== "function";
|
|
836
692
|
const newObservableObjectQuery$ = params$.current.pipe(
|
|
837
|
-
rxjs.map(({
|
|
693
|
+
rxjs.map(({ queryFn: queryFn2 }) => queryFn2),
|
|
694
|
+
rxjs.filter(isQueryObject),
|
|
838
695
|
rxjs.distinctUntilChanged(shallowEqual),
|
|
839
|
-
rxjs.skip(1)
|
|
840
|
-
rxjs.filter((query2) => !!query2 && typeof query2 !== "function"),
|
|
841
|
-
rxjs.startWith(params$.current.getValue().query),
|
|
842
|
-
rxjs.filter(isDefined)
|
|
696
|
+
isQueryObject(params$.current.getValue().queryFn) ? rxjs.skip(1) : rxjs.identity
|
|
843
697
|
);
|
|
844
698
|
const fn$ = params$.current.pipe(
|
|
845
|
-
rxjs.map(({
|
|
699
|
+
rxjs.map(({ queryFn: queryFn2 }) => queryFn2),
|
|
846
700
|
rxjs.filter(isDefined)
|
|
847
701
|
);
|
|
848
702
|
const options$ = params$.current.pipe(rxjs.map(({ options: options2 }) => options2));
|
|
849
|
-
const
|
|
850
|
-
|
|
703
|
+
const activityRefetch$ = createActivityTrigger(params$.current);
|
|
704
|
+
const networkRefetch$ = createNetworkTrigger(params$.current);
|
|
705
|
+
const newQueryTrigger$ = rxjs.merge(
|
|
706
|
+
initialTrigger$,
|
|
707
|
+
newKeyTrigger$,
|
|
851
708
|
newObservableObjectQuery$
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
rxjs.
|
|
855
|
-
|
|
856
|
-
|
|
709
|
+
);
|
|
710
|
+
const refetch$ = rxjs.merge(
|
|
711
|
+
internalRefresh$.current.pipe(rxjs.map(() => ({ ignoreStale: true }))),
|
|
712
|
+
rxjs.merge(activityRefetch$, networkRefetch$).pipe(rxjs.throttleTime(500))
|
|
713
|
+
);
|
|
714
|
+
return newQueryTrigger$.pipe(
|
|
715
|
+
rxjs.withLatestFrom(key$),
|
|
716
|
+
rxjs.switchMap(([, key]) => {
|
|
717
|
+
const { result$ } = client.query$({
|
|
718
|
+
key,
|
|
857
719
|
fn$,
|
|
858
|
-
options
|
|
720
|
+
options$,
|
|
721
|
+
refetch$
|
|
859
722
|
});
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
{ data: currentData, ...restCurrent }
|
|
873
|
-
]) => ({
|
|
874
|
-
...restPrevious,
|
|
875
|
-
...restCurrent,
|
|
876
|
-
data: currentData && "result" in currentData ? currentData.result : previousData == null ? void 0 : previousData.result
|
|
877
|
-
})
|
|
723
|
+
return result$.pipe(
|
|
724
|
+
rxjs.scan(
|
|
725
|
+
(previousValue, { data: currentData, ...currentValue }) => ({
|
|
726
|
+
data: void 0,
|
|
727
|
+
...previousValue,
|
|
728
|
+
...currentValue,
|
|
729
|
+
isLoading: currentValue.status === "loading",
|
|
730
|
+
...currentData && {
|
|
731
|
+
data: currentData.result
|
|
732
|
+
}
|
|
733
|
+
}),
|
|
734
|
+
{}
|
|
878
735
|
)
|
|
879
736
|
);
|
|
880
|
-
})
|
|
737
|
+
})
|
|
881
738
|
/**
|
|
882
739
|
* @important
|
|
883
740
|
* We skip the first result as it is comparable to default passed value.
|
|
884
741
|
* This is assuming all query are async and does not return a result right away.
|
|
885
742
|
* This is a design choice.
|
|
886
743
|
*/
|
|
887
|
-
params$.current.getValue().options.enabled !== false
|
|
744
|
+
// params$.current.getValue().options.enabled !== false
|
|
745
|
+
// ? skip(1)
|
|
746
|
+
// : identity
|
|
888
747
|
);
|
|
889
748
|
},
|
|
890
749
|
{
|
|
@@ -920,6 +779,873 @@ function useSubscribeEffect(source, unsafeOptions, deps = []) {
|
|
|
920
779
|
);
|
|
921
780
|
useSubscribe(enhancerMakeObservable, deps);
|
|
922
781
|
}
|
|
782
|
+
const serializeObject = (object) => {
|
|
783
|
+
if (Array.isArray(object)) {
|
|
784
|
+
return object.reduce((acc, value, index) => {
|
|
785
|
+
if (index === object.length - 1)
|
|
786
|
+
return `${acc}${serializeObject(value)}]`;
|
|
787
|
+
return `${acc}${serializeObject(value)},`;
|
|
788
|
+
}, "[");
|
|
789
|
+
}
|
|
790
|
+
if (object === void 0)
|
|
791
|
+
return "";
|
|
792
|
+
return JSON.stringify(object, Object.keys(object).sort());
|
|
793
|
+
};
|
|
794
|
+
const serializeKey = (key) => {
|
|
795
|
+
if (key.length === 0)
|
|
796
|
+
return "[]";
|
|
797
|
+
return serializeObject(key);
|
|
798
|
+
};
|
|
799
|
+
const resetStyle = { backgroundColor: "transparent", color: "inherit" };
|
|
800
|
+
function createLogger(env) {
|
|
801
|
+
const _logger = {
|
|
802
|
+
namespaces: [
|
|
803
|
+
{ name: "@reactjrx", style: { backgroundColor: "#d02f4e", color: "white" } }
|
|
804
|
+
],
|
|
805
|
+
namespace(name, style) {
|
|
806
|
+
const logger2 = createLogger(env);
|
|
807
|
+
logger2.namespaces.push({
|
|
808
|
+
name,
|
|
809
|
+
style: style ?? resetStyle
|
|
810
|
+
});
|
|
811
|
+
return logger2;
|
|
812
|
+
},
|
|
813
|
+
printNamespaces() {
|
|
814
|
+
return {
|
|
815
|
+
namespaces: _logger.namespaces.map(({ name }) => `%c ${name} %c`).join(" "),
|
|
816
|
+
styles: _logger.namespaces.reduce((acc, { style }) => {
|
|
817
|
+
acc.push(
|
|
818
|
+
`background-color: ${style.backgroundColor}; color: ${style.color};`
|
|
819
|
+
);
|
|
820
|
+
acc.push("background-color: transparent; color: inherit;");
|
|
821
|
+
return acc;
|
|
822
|
+
}, [])
|
|
823
|
+
};
|
|
824
|
+
},
|
|
825
|
+
print(method, ...message) {
|
|
826
|
+
if (env === "development") {
|
|
827
|
+
const { namespaces, styles } = _logger.printNamespaces();
|
|
828
|
+
console[method](namespaces, ...styles, ...message);
|
|
829
|
+
}
|
|
830
|
+
return _logger;
|
|
831
|
+
},
|
|
832
|
+
printWithoutNamespace(method, ...message) {
|
|
833
|
+
if (env === "development") {
|
|
834
|
+
console[method](...message);
|
|
835
|
+
}
|
|
836
|
+
return _logger;
|
|
837
|
+
},
|
|
838
|
+
log(...message) {
|
|
839
|
+
return _logger.print("log", ...message);
|
|
840
|
+
},
|
|
841
|
+
warn(...message) {
|
|
842
|
+
return _logger.print("warn", ...message);
|
|
843
|
+
},
|
|
844
|
+
error(...message) {
|
|
845
|
+
return _logger.print("error", ...message);
|
|
846
|
+
},
|
|
847
|
+
group(...message) {
|
|
848
|
+
return _logger.print("group", ...message);
|
|
849
|
+
},
|
|
850
|
+
groupEnd() {
|
|
851
|
+
if (env === "development") {
|
|
852
|
+
console.groupEnd();
|
|
853
|
+
}
|
|
854
|
+
return _logger;
|
|
855
|
+
}
|
|
856
|
+
};
|
|
857
|
+
return _logger;
|
|
858
|
+
}
|
|
859
|
+
const Logger = createLogger("development");
|
|
860
|
+
const logger$3 = Logger.namespace("store");
|
|
861
|
+
const createDebugger = (store$) => {
|
|
862
|
+
return store$.pipe(
|
|
863
|
+
rxjs.map(
|
|
864
|
+
(value) => [...value.keys()].reduce((acc, key) => {
|
|
865
|
+
var _a;
|
|
866
|
+
acc[key] = (_a = value.get(key)) == null ? void 0 : _a.getValue();
|
|
867
|
+
return acc;
|
|
868
|
+
}, {})
|
|
869
|
+
),
|
|
870
|
+
rxjs.distinctUntilChanged(shallowEqual)
|
|
871
|
+
).subscribe((value) => {
|
|
872
|
+
logger$3.log("store", "update", value);
|
|
873
|
+
});
|
|
874
|
+
};
|
|
875
|
+
const createQueryStore = () => {
|
|
876
|
+
const store = /* @__PURE__ */ new Map();
|
|
877
|
+
const store$ = new rxjs.BehaviorSubject(store);
|
|
878
|
+
const queryEventSubject = new rxjs.Subject();
|
|
879
|
+
const queryTriggerSubject = new rxjs.Subject();
|
|
880
|
+
const notify = () => {
|
|
881
|
+
store$.next(store);
|
|
882
|
+
};
|
|
883
|
+
const setValue = (key, value) => {
|
|
884
|
+
store.set(key, new rxjs.BehaviorSubject(value));
|
|
885
|
+
notify();
|
|
886
|
+
};
|
|
887
|
+
const getValue = (serializedKey) => {
|
|
888
|
+
var _a;
|
|
889
|
+
return (_a = store.get(serializedKey)) == null ? void 0 : _a.getValue();
|
|
890
|
+
};
|
|
891
|
+
const getValue$ = (key) => {
|
|
892
|
+
return store$.pipe(
|
|
893
|
+
rxjs.map(() => store.get(key)),
|
|
894
|
+
rxjs.filter(isDefined),
|
|
895
|
+
rxjs.map((entry) => entry.getValue()),
|
|
896
|
+
rxjs.distinctUntilChanged(shallowEqual)
|
|
897
|
+
);
|
|
898
|
+
};
|
|
899
|
+
const updateValue = (key, value) => {
|
|
900
|
+
const existingObject = store.get(key);
|
|
901
|
+
if (!existingObject)
|
|
902
|
+
return;
|
|
903
|
+
if (typeof value === "function") {
|
|
904
|
+
existingObject.next({
|
|
905
|
+
...existingObject.getValue(),
|
|
906
|
+
...value(existingObject.getValue())
|
|
907
|
+
});
|
|
908
|
+
} else {
|
|
909
|
+
existingObject.next({ ...existingObject.getValue(), ...value });
|
|
910
|
+
}
|
|
911
|
+
store$.next(store);
|
|
912
|
+
};
|
|
913
|
+
const updateMany = (value, predicate = () => true) => {
|
|
914
|
+
store.forEach((oldValue$) => {
|
|
915
|
+
const oldValue = oldValue$.getValue();
|
|
916
|
+
if (predicate(oldValue)) {
|
|
917
|
+
oldValue$.next({ ...oldValue, ...value });
|
|
918
|
+
}
|
|
919
|
+
});
|
|
920
|
+
store$.next(store);
|
|
921
|
+
};
|
|
922
|
+
const deleteValue = (key) => {
|
|
923
|
+
store.delete(key);
|
|
924
|
+
store$.next(store);
|
|
925
|
+
};
|
|
926
|
+
const addRunner = (key, stream) => {
|
|
927
|
+
updateValue(key, (old) => ({
|
|
928
|
+
...old,
|
|
929
|
+
runners: [...old.runners, stream]
|
|
930
|
+
}));
|
|
931
|
+
return () => {
|
|
932
|
+
var _a;
|
|
933
|
+
const newListeners = ((_a = store.get(key)) == null ? void 0 : _a.getValue().runners.filter((reference) => reference !== stream)) ?? [];
|
|
934
|
+
updateValue(key, (old) => ({
|
|
935
|
+
...old,
|
|
936
|
+
runners: newListeners
|
|
937
|
+
}));
|
|
938
|
+
};
|
|
939
|
+
};
|
|
940
|
+
const debugger$ = createDebugger(store$);
|
|
941
|
+
return {
|
|
942
|
+
set: setValue,
|
|
943
|
+
get: getValue,
|
|
944
|
+
get$: getValue$,
|
|
945
|
+
delete: deleteValue,
|
|
946
|
+
update: updateValue,
|
|
947
|
+
keys: () => store.keys(),
|
|
948
|
+
updateMany,
|
|
949
|
+
addRunner,
|
|
950
|
+
store$,
|
|
951
|
+
queryEvent$: queryEventSubject.asObservable(),
|
|
952
|
+
dispatchQueryEvent: (event) => {
|
|
953
|
+
queryEventSubject.next(event);
|
|
954
|
+
},
|
|
955
|
+
queryTrigger$: queryTriggerSubject.asObservable(),
|
|
956
|
+
dispatchQueryTrigger: (event) => {
|
|
957
|
+
queryTriggerSubject.next(event);
|
|
958
|
+
},
|
|
959
|
+
size: () => store.size,
|
|
960
|
+
destroy: () => {
|
|
961
|
+
debugger$.unsubscribe();
|
|
962
|
+
queryEventSubject.complete();
|
|
963
|
+
queryTriggerSubject.complete();
|
|
964
|
+
}
|
|
965
|
+
};
|
|
966
|
+
};
|
|
967
|
+
const createQueryTrigger = ({
|
|
968
|
+
refetch$,
|
|
969
|
+
options$,
|
|
970
|
+
queryStore,
|
|
971
|
+
key
|
|
972
|
+
}) => {
|
|
973
|
+
const enabledOption$ = options$.pipe(
|
|
974
|
+
rxjs.map(({ enabled = true }) => enabled),
|
|
975
|
+
rxjs.distinctUntilChanged()
|
|
976
|
+
);
|
|
977
|
+
const enabledTrigger$ = enabledOption$.pipe(
|
|
978
|
+
rxjs.skip(1),
|
|
979
|
+
rxjs.filter((enabled) => enabled)
|
|
980
|
+
);
|
|
981
|
+
return rxjs.merge(
|
|
982
|
+
queryStore.queryTrigger$.pipe(
|
|
983
|
+
rxjs.filter((event) => key === event.key),
|
|
984
|
+
rxjs.map(({ trigger: trigger2 }) => trigger2)
|
|
985
|
+
),
|
|
986
|
+
refetch$.pipe(
|
|
987
|
+
rxjs.map((event) => ({
|
|
988
|
+
...event,
|
|
989
|
+
type: "refetch"
|
|
990
|
+
}))
|
|
991
|
+
),
|
|
992
|
+
enabledTrigger$.pipe(
|
|
993
|
+
rxjs.map(() => ({
|
|
994
|
+
type: "enabled",
|
|
995
|
+
ignoreStale: false
|
|
996
|
+
}))
|
|
997
|
+
)
|
|
998
|
+
);
|
|
999
|
+
};
|
|
1000
|
+
const deduplicate = (key, queryStore) => (source) => {
|
|
1001
|
+
if (key === serializeKey([]))
|
|
1002
|
+
return source;
|
|
1003
|
+
return rxjs.defer(() => {
|
|
1004
|
+
var _a;
|
|
1005
|
+
const sourceFromStore = (_a = queryStore.get(key)) == null ? void 0 : _a.deduplication_fn;
|
|
1006
|
+
const deleteFromStore = () => {
|
|
1007
|
+
queryStore.update(key, {
|
|
1008
|
+
deduplication_fn: void 0
|
|
1009
|
+
});
|
|
1010
|
+
};
|
|
1011
|
+
const finalSource = sourceFromStore ?? source.pipe(
|
|
1012
|
+
/**
|
|
1013
|
+
* Ideally we would want to remove the query from the store only on finalize,
|
|
1014
|
+
* which means whenever the query complete or error. Unfortunately finalize is
|
|
1015
|
+
* triggered after a new stream arrive which create a concurrency issue.
|
|
1016
|
+
* tap is triggered correctly synchronously and before a new query arrive.
|
|
1017
|
+
*/
|
|
1018
|
+
rxjs.tap({
|
|
1019
|
+
error: deleteFromStore,
|
|
1020
|
+
complete: deleteFromStore
|
|
1021
|
+
}),
|
|
1022
|
+
/**
|
|
1023
|
+
* Because tap is not called on unsubscription we still need to handle the case.
|
|
1024
|
+
*/
|
|
1025
|
+
rxjs.finalize(deleteFromStore),
|
|
1026
|
+
rxjs.shareReplay({
|
|
1027
|
+
refCount: true,
|
|
1028
|
+
bufferSize: 1
|
|
1029
|
+
})
|
|
1030
|
+
);
|
|
1031
|
+
if (!sourceFromStore) {
|
|
1032
|
+
queryStore.update(key, {
|
|
1033
|
+
deduplication_fn: finalSource
|
|
1034
|
+
});
|
|
1035
|
+
}
|
|
1036
|
+
return finalSource;
|
|
1037
|
+
});
|
|
1038
|
+
};
|
|
1039
|
+
const notifyQueryResult = (options$) => (stream$) => stream$.pipe(
|
|
1040
|
+
rxjs.withLatestFrom(options$),
|
|
1041
|
+
rxjs.map(([result, options]) => {
|
|
1042
|
+
var _a, _b;
|
|
1043
|
+
if (result.error) {
|
|
1044
|
+
(_a = options.onError) == null ? void 0 : _a.call(options, result.error);
|
|
1045
|
+
} else {
|
|
1046
|
+
(_b = options.onSuccess) == null ? void 0 : _b.call(options, result);
|
|
1047
|
+
}
|
|
1048
|
+
return result;
|
|
1049
|
+
})
|
|
1050
|
+
);
|
|
1051
|
+
const registerResultInCache = ({
|
|
1052
|
+
queryStore,
|
|
1053
|
+
serializedKey,
|
|
1054
|
+
options
|
|
1055
|
+
}) => (stream) => stream.pipe(
|
|
1056
|
+
rxjs.tap((result) => {
|
|
1057
|
+
queryStore.update(serializedKey, {
|
|
1058
|
+
...options.cacheTime !== 0 && {
|
|
1059
|
+
cache_fnResult: { result }
|
|
1060
|
+
}
|
|
1061
|
+
});
|
|
1062
|
+
})
|
|
1063
|
+
);
|
|
1064
|
+
const mapWithComplete = (mapFn) => (stream) => {
|
|
1065
|
+
return stream.pipe(rxjs.map(mapFn({ isComplete: false })));
|
|
1066
|
+
};
|
|
1067
|
+
const createQueryFetch = ({
|
|
1068
|
+
options$,
|
|
1069
|
+
options,
|
|
1070
|
+
fn,
|
|
1071
|
+
queryStore,
|
|
1072
|
+
serializedKey,
|
|
1073
|
+
trigger: trigger2,
|
|
1074
|
+
trigger$
|
|
1075
|
+
}) => {
|
|
1076
|
+
const enabledOption$ = options$.pipe(
|
|
1077
|
+
rxjs.map(({ enabled = true }) => enabled),
|
|
1078
|
+
rxjs.distinctUntilChanged()
|
|
1079
|
+
);
|
|
1080
|
+
const disabled$ = enabledOption$.pipe(
|
|
1081
|
+
rxjs.distinctUntilChanged(),
|
|
1082
|
+
rxjs.filter((enabled) => !enabled)
|
|
1083
|
+
);
|
|
1084
|
+
const deferredQuery = rxjs.defer(() => {
|
|
1085
|
+
const queryOrResponse = typeof fn === "function" ? fn() : fn;
|
|
1086
|
+
return rxjs.from(queryOrResponse);
|
|
1087
|
+
});
|
|
1088
|
+
const fnExecution$ = deferredQuery.pipe(
|
|
1089
|
+
retryOnError(options),
|
|
1090
|
+
deduplicate(serializedKey, queryStore),
|
|
1091
|
+
rxjs.tap(() => {
|
|
1092
|
+
queryStore.dispatchQueryEvent({
|
|
1093
|
+
key: serializedKey,
|
|
1094
|
+
type: "fetchSuccess"
|
|
1095
|
+
});
|
|
1096
|
+
queryStore.update(serializedKey, {
|
|
1097
|
+
lastFetchedAt: (/* @__PURE__ */ new Date()).getTime()
|
|
1098
|
+
});
|
|
1099
|
+
}),
|
|
1100
|
+
registerResultInCache({ serializedKey, options, queryStore }),
|
|
1101
|
+
mapWithComplete(({ isComplete }) => (result) => ({
|
|
1102
|
+
status: "success",
|
|
1103
|
+
...isComplete && {
|
|
1104
|
+
fetchStatus: "idle"
|
|
1105
|
+
},
|
|
1106
|
+
data: { result },
|
|
1107
|
+
error: void 0
|
|
1108
|
+
})),
|
|
1109
|
+
rxjs.endWith({
|
|
1110
|
+
fetchStatus: "idle"
|
|
1111
|
+
}),
|
|
1112
|
+
rxjs.catchError((error) => {
|
|
1113
|
+
queryStore.dispatchQueryEvent({
|
|
1114
|
+
key: serializedKey,
|
|
1115
|
+
type: "fetchError"
|
|
1116
|
+
});
|
|
1117
|
+
return rxjs.of({
|
|
1118
|
+
fetchStatus: "idle",
|
|
1119
|
+
status: "error",
|
|
1120
|
+
data: void 0,
|
|
1121
|
+
error
|
|
1122
|
+
});
|
|
1123
|
+
}),
|
|
1124
|
+
notifyQueryResult(options$)
|
|
1125
|
+
);
|
|
1126
|
+
const newCache$ = queryStore.queryEvent$.pipe(
|
|
1127
|
+
rxjs.filter(
|
|
1128
|
+
(event) => event.key === serializedKey && event.type === "queryDataSet"
|
|
1129
|
+
),
|
|
1130
|
+
rxjs.map(() => {
|
|
1131
|
+
var _a, _b;
|
|
1132
|
+
return (_b = (_a = queryStore.get(serializedKey)) == null ? void 0 : _a.cache_fnResult) == null ? void 0 : _b.result;
|
|
1133
|
+
}),
|
|
1134
|
+
rxjs.filter(isDefined),
|
|
1135
|
+
rxjs.map((result) => ({
|
|
1136
|
+
status: "success",
|
|
1137
|
+
data: { result }
|
|
1138
|
+
})),
|
|
1139
|
+
/**
|
|
1140
|
+
* @important
|
|
1141
|
+
* To avoid cache update being returned being the first result is returned.
|
|
1142
|
+
* For example if user set query data inside onSuccess callback, we simulate
|
|
1143
|
+
* a small delay to ensure it happens after.
|
|
1144
|
+
*/
|
|
1145
|
+
rxjs.delay(1)
|
|
1146
|
+
);
|
|
1147
|
+
const execution$ = rxjs.merge(
|
|
1148
|
+
disabled$.pipe(
|
|
1149
|
+
rxjs.take(1),
|
|
1150
|
+
rxjs.map(() => ({
|
|
1151
|
+
fetchStatus: "idle"
|
|
1152
|
+
}))
|
|
1153
|
+
),
|
|
1154
|
+
rxjs.merge(
|
|
1155
|
+
rxjs.of({ fetchStatus: "fetching", error: void 0 }),
|
|
1156
|
+
fnExecution$
|
|
1157
|
+
).pipe(rxjs.takeUntil(disabled$)),
|
|
1158
|
+
newCache$
|
|
1159
|
+
).pipe(rxjs.takeUntil(trigger$));
|
|
1160
|
+
const query = queryStore.get(serializedKey);
|
|
1161
|
+
const cacheResult = query == null ? void 0 : query.cache_fnResult;
|
|
1162
|
+
const hasCache = !!cacheResult;
|
|
1163
|
+
if (hasCache) {
|
|
1164
|
+
if (!(query == null ? void 0 : query.isStale) && !trigger2.ignoreStale) {
|
|
1165
|
+
return rxjs.of({
|
|
1166
|
+
fetchStatus: "idle",
|
|
1167
|
+
status: "success",
|
|
1168
|
+
data: { result: cacheResult.result },
|
|
1169
|
+
error: void 0
|
|
1170
|
+
});
|
|
1171
|
+
} else {
|
|
1172
|
+
return rxjs.merge(
|
|
1173
|
+
rxjs.of({
|
|
1174
|
+
fetchStatus: "fetching",
|
|
1175
|
+
status: "success",
|
|
1176
|
+
data: { result: cacheResult.result },
|
|
1177
|
+
error: void 0
|
|
1178
|
+
}),
|
|
1179
|
+
execution$
|
|
1180
|
+
);
|
|
1181
|
+
}
|
|
1182
|
+
}
|
|
1183
|
+
return execution$;
|
|
1184
|
+
};
|
|
1185
|
+
const compareKeys = (keyA, keyB, { exact = false } = {}) => {
|
|
1186
|
+
if (exact) {
|
|
1187
|
+
return serializeKey(keyA) === serializeKey(keyB);
|
|
1188
|
+
}
|
|
1189
|
+
return keyA.reduce((acc, value, index) => {
|
|
1190
|
+
if (!acc)
|
|
1191
|
+
return false;
|
|
1192
|
+
return serializeObject(value) === serializeObject(keyB[index]);
|
|
1193
|
+
}, true);
|
|
1194
|
+
};
|
|
1195
|
+
const logger$2 = Logger.namespace("invalidation");
|
|
1196
|
+
const createInvalidationClient = ({
|
|
1197
|
+
queryStore
|
|
1198
|
+
}) => {
|
|
1199
|
+
const invalidateQueries = ({
|
|
1200
|
+
queryKey,
|
|
1201
|
+
exact = false,
|
|
1202
|
+
predicate
|
|
1203
|
+
} = {}) => {
|
|
1204
|
+
let keysToRefetch = [];
|
|
1205
|
+
if (queryKey) {
|
|
1206
|
+
logger$2.log(`invalidation requested for`, queryKey);
|
|
1207
|
+
queryStore.updateMany({ isStale: true }, (entry) => {
|
|
1208
|
+
const isValid = compareKeys(queryKey, entry.queryKey, { exact });
|
|
1209
|
+
if (isValid) {
|
|
1210
|
+
keysToRefetch.push(serializeKey(entry.queryKey));
|
|
1211
|
+
}
|
|
1212
|
+
return isValid;
|
|
1213
|
+
});
|
|
1214
|
+
} else if (predicate) {
|
|
1215
|
+
queryStore.updateMany({ isStale: true }, (entry) => {
|
|
1216
|
+
const isValid = predicate(entry);
|
|
1217
|
+
if (isValid) {
|
|
1218
|
+
keysToRefetch.push(serializeKey(entry.queryKey));
|
|
1219
|
+
}
|
|
1220
|
+
return isValid;
|
|
1221
|
+
});
|
|
1222
|
+
} else {
|
|
1223
|
+
logger$2.log(`Invalidation requested for all queries`);
|
|
1224
|
+
queryStore.updateMany({ isStale: true });
|
|
1225
|
+
keysToRefetch = Array.from(queryStore.keys());
|
|
1226
|
+
}
|
|
1227
|
+
keysToRefetch.forEach((key) => {
|
|
1228
|
+
queryStore.dispatchQueryTrigger({
|
|
1229
|
+
key,
|
|
1230
|
+
trigger: { ignoreStale: true, type: "refetch" }
|
|
1231
|
+
});
|
|
1232
|
+
});
|
|
1233
|
+
};
|
|
1234
|
+
return {
|
|
1235
|
+
invalidateQueries,
|
|
1236
|
+
destroy: () => {
|
|
1237
|
+
}
|
|
1238
|
+
};
|
|
1239
|
+
};
|
|
1240
|
+
const logger$1 = Logger.namespace("refetch");
|
|
1241
|
+
const createRefetchClient = ({
|
|
1242
|
+
queryStore
|
|
1243
|
+
}) => {
|
|
1244
|
+
const pipeQueryResult = ({
|
|
1245
|
+
options$
|
|
1246
|
+
}) => (stream) => {
|
|
1247
|
+
const sharedStream = stream.pipe(rxjs.share());
|
|
1248
|
+
return rxjs.merge(
|
|
1249
|
+
sharedStream,
|
|
1250
|
+
sharedStream.pipe(
|
|
1251
|
+
rxjs.filter(
|
|
1252
|
+
(result) => !!result.data && result.fetchStatus !== "fetching"
|
|
1253
|
+
),
|
|
1254
|
+
rxjs.distinctUntilChanged((prev, curr) => prev.data === curr.data),
|
|
1255
|
+
rxjs.withLatestFrom(options$),
|
|
1256
|
+
rxjs.map(([, { refetchInterval }]) => refetchInterval),
|
|
1257
|
+
rxjs.filter(isDefined),
|
|
1258
|
+
rxjs.switchMap((refetchInterval) => {
|
|
1259
|
+
if (typeof refetchInterval === "number") {
|
|
1260
|
+
return rxjs.timer(refetchInterval).pipe(
|
|
1261
|
+
rxjs.map(() => ({
|
|
1262
|
+
type: "refetch",
|
|
1263
|
+
ignoreStale: true
|
|
1264
|
+
})),
|
|
1265
|
+
rxjs.switchMap(() => rxjs.EMPTY)
|
|
1266
|
+
);
|
|
1267
|
+
}
|
|
1268
|
+
return rxjs.EMPTY;
|
|
1269
|
+
})
|
|
1270
|
+
)
|
|
1271
|
+
);
|
|
1272
|
+
};
|
|
1273
|
+
const pipeQueryTrigger = ({
|
|
1274
|
+
key
|
|
1275
|
+
}) => (stream) => {
|
|
1276
|
+
return rxjs.merge(
|
|
1277
|
+
stream.pipe(
|
|
1278
|
+
rxjs.tap(({ ignoreStale }) => {
|
|
1279
|
+
const query = queryStore.get(key);
|
|
1280
|
+
if (query && ignoreStale && !query.isStale) {
|
|
1281
|
+
logger$1.log(key, "marked stale by trigger!");
|
|
1282
|
+
queryStore.update(key, {
|
|
1283
|
+
isStale: true
|
|
1284
|
+
});
|
|
1285
|
+
}
|
|
1286
|
+
})
|
|
1287
|
+
)
|
|
1288
|
+
);
|
|
1289
|
+
};
|
|
1290
|
+
return {
|
|
1291
|
+
pipeQueryResult,
|
|
1292
|
+
pipeQueryTrigger,
|
|
1293
|
+
destroy: () => {
|
|
1294
|
+
}
|
|
1295
|
+
};
|
|
1296
|
+
};
|
|
1297
|
+
const difference = (a, b) => a.filter((element) => !b.includes(element));
|
|
1298
|
+
const createQueryListener = (store, onQuery) => store.store$.pipe(
|
|
1299
|
+
rxjs.map((store2) => [...store2.keys()]),
|
|
1300
|
+
rxjs.startWith([]),
|
|
1301
|
+
rxjs.pairwise(),
|
|
1302
|
+
rxjs.mergeMap(([previousKeys, currentKeys]) => {
|
|
1303
|
+
const newKeys = difference(currentKeys, previousKeys);
|
|
1304
|
+
return rxjs.merge(
|
|
1305
|
+
...newKeys.map((key) => {
|
|
1306
|
+
const deleted$ = store.store$.pipe(
|
|
1307
|
+
rxjs.map(() => store.get(key)),
|
|
1308
|
+
rxjs.filter((item) => item === void 0)
|
|
1309
|
+
);
|
|
1310
|
+
return rxjs.merge(rxjs.NEVER, rxjs.of(key)).pipe(
|
|
1311
|
+
rxjs.tap(() => {
|
|
1312
|
+
console.log("QUERY", key, "in");
|
|
1313
|
+
}),
|
|
1314
|
+
onQuery,
|
|
1315
|
+
rxjs.finalize(() => {
|
|
1316
|
+
console.log("QUERY", key, "complete");
|
|
1317
|
+
}),
|
|
1318
|
+
rxjs.takeUntil(deleted$)
|
|
1319
|
+
);
|
|
1320
|
+
})
|
|
1321
|
+
);
|
|
1322
|
+
})
|
|
1323
|
+
);
|
|
1324
|
+
const mapStoreQueryToRunnerOptions = (stream) => stream.pipe(
|
|
1325
|
+
rxjs.switchMap((entry) => rxjs.combineLatest(entry.runners)),
|
|
1326
|
+
rxjs.map((runnerValues) => runnerValues.map(({ options }) => options))
|
|
1327
|
+
);
|
|
1328
|
+
const mapOptionsToOption$1 = (stream) => stream.pipe(
|
|
1329
|
+
rxjs.map(
|
|
1330
|
+
(options) => options.reduce(
|
|
1331
|
+
(acc, value) => {
|
|
1332
|
+
return {
|
|
1333
|
+
...acc,
|
|
1334
|
+
lowestStaleTime: value.staleTime === void 0 ? acc.lowestStaleTime : Math.min(
|
|
1335
|
+
value.staleTime ?? Infinity,
|
|
1336
|
+
acc.lowestStaleTime ?? Infinity
|
|
1337
|
+
)
|
|
1338
|
+
};
|
|
1339
|
+
},
|
|
1340
|
+
{ lowestStaleTime: void 0 }
|
|
1341
|
+
)
|
|
1342
|
+
),
|
|
1343
|
+
rxjs.distinctUntilChanged(shallowEqual)
|
|
1344
|
+
);
|
|
1345
|
+
const onlyFetchEventDone = (key) => (stream) => stream.pipe(
|
|
1346
|
+
rxjs.filter(
|
|
1347
|
+
(event) => event.key === key && (event.type === "fetchError" || event.type === "fetchSuccess")
|
|
1348
|
+
)
|
|
1349
|
+
);
|
|
1350
|
+
const markAsStale = ({
|
|
1351
|
+
queryStore
|
|
1352
|
+
}) => (stream) => stream.pipe(
|
|
1353
|
+
rxjs.switchMap((key) => {
|
|
1354
|
+
const query$ = queryStore.get$(key);
|
|
1355
|
+
return queryStore.queryEvent$.pipe(
|
|
1356
|
+
onlyFetchEventDone(key),
|
|
1357
|
+
rxjs.switchMap(
|
|
1358
|
+
() => query$.pipe(
|
|
1359
|
+
mapStoreQueryToRunnerOptions,
|
|
1360
|
+
mapOptionsToOption$1,
|
|
1361
|
+
rxjs.tap(({ lowestStaleTime = 0 }) => {
|
|
1362
|
+
var _a;
|
|
1363
|
+
if (lowestStaleTime === 0) {
|
|
1364
|
+
logger$2.log(key, "marked as stale!", {
|
|
1365
|
+
staleTime: lowestStaleTime
|
|
1366
|
+
});
|
|
1367
|
+
queryStore.update(key, { isStale: true });
|
|
1368
|
+
} else if ((_a = queryStore.get(key)) == null ? void 0 : _a.isStale) {
|
|
1369
|
+
logger$2.log(key, "marked non stale", {
|
|
1370
|
+
staleTime: lowestStaleTime
|
|
1371
|
+
});
|
|
1372
|
+
queryStore.update(key, { isStale: false });
|
|
1373
|
+
}
|
|
1374
|
+
}),
|
|
1375
|
+
rxjs.filter(
|
|
1376
|
+
({ lowestStaleTime }) => lowestStaleTime !== Infinity && lowestStaleTime !== 0
|
|
1377
|
+
),
|
|
1378
|
+
rxjs.switchMap(({ lowestStaleTime = 0 }) => rxjs.timer(lowestStaleTime)),
|
|
1379
|
+
rxjs.tap(() => {
|
|
1380
|
+
var _a;
|
|
1381
|
+
if (!((_a = queryStore.get(key)) == null ? void 0 : _a.isStale)) {
|
|
1382
|
+
logger$2.log(key, "marked as stale!");
|
|
1383
|
+
queryStore.update(key, { isStale: true });
|
|
1384
|
+
}
|
|
1385
|
+
})
|
|
1386
|
+
)
|
|
1387
|
+
),
|
|
1388
|
+
rxjs.map(() => key)
|
|
1389
|
+
);
|
|
1390
|
+
})
|
|
1391
|
+
);
|
|
1392
|
+
const mapOptionsToOption = (stream) => stream.pipe(
|
|
1393
|
+
rxjs.map(
|
|
1394
|
+
(options) => options.reduce(
|
|
1395
|
+
(acc, value) => {
|
|
1396
|
+
return {
|
|
1397
|
+
...acc,
|
|
1398
|
+
lowestCacheTime: value.cacheTime === void 0 ? acc.lowestCacheTime : Math.min(
|
|
1399
|
+
value.cacheTime ?? Infinity,
|
|
1400
|
+
acc.lowestCacheTime ?? Infinity
|
|
1401
|
+
)
|
|
1402
|
+
};
|
|
1403
|
+
},
|
|
1404
|
+
{ lowestCacheTime: void 0 }
|
|
1405
|
+
)
|
|
1406
|
+
),
|
|
1407
|
+
rxjs.distinctUntilChanged(shallowEqual)
|
|
1408
|
+
);
|
|
1409
|
+
const onCacheUpdate = (stream) => stream.pipe(
|
|
1410
|
+
rxjs.map((item) => item.cache_fnResult),
|
|
1411
|
+
rxjs.distinctUntilChanged(shallowEqual)
|
|
1412
|
+
);
|
|
1413
|
+
const invalidateCache = ({
|
|
1414
|
+
queryStore
|
|
1415
|
+
}) => (stream) => stream.pipe(
|
|
1416
|
+
rxjs.switchMap((key) => {
|
|
1417
|
+
const query$ = queryStore.get$(key);
|
|
1418
|
+
const invalidateCache$ = query$.pipe(
|
|
1419
|
+
onCacheUpdate,
|
|
1420
|
+
rxjs.switchMap(
|
|
1421
|
+
() => query$.pipe(
|
|
1422
|
+
mapStoreQueryToRunnerOptions,
|
|
1423
|
+
mapOptionsToOption,
|
|
1424
|
+
rxjs.switchMap(
|
|
1425
|
+
({
|
|
1426
|
+
lowestCacheTime = 5 * 60 * 1e3
|
|
1427
|
+
/* 5mn */
|
|
1428
|
+
}) => rxjs.timer(lowestCacheTime).pipe(
|
|
1429
|
+
rxjs.tap(() => {
|
|
1430
|
+
queryStore.update(key, { cache_fnResult: void 0 });
|
|
1431
|
+
})
|
|
1432
|
+
)
|
|
1433
|
+
)
|
|
1434
|
+
)
|
|
1435
|
+
)
|
|
1436
|
+
);
|
|
1437
|
+
return invalidateCache$.pipe(rxjs.map(() => key));
|
|
1438
|
+
})
|
|
1439
|
+
);
|
|
1440
|
+
const garbageCache = ({
|
|
1441
|
+
queryStore
|
|
1442
|
+
}) => (stream) => stream.pipe(
|
|
1443
|
+
rxjs.switchMap((key) => {
|
|
1444
|
+
const query$ = queryStore.get$(key);
|
|
1445
|
+
return query$.pipe(
|
|
1446
|
+
rxjs.filter((entry) => !entry.cache_fnResult),
|
|
1447
|
+
rxjs.map((entry) => entry.runners.length > 0),
|
|
1448
|
+
rxjs.pairwise(),
|
|
1449
|
+
rxjs.filter(([hadRunners, hasRunners]) => hadRunners && !hasRunners),
|
|
1450
|
+
rxjs.tap(() => {
|
|
1451
|
+
queryStore.delete(key);
|
|
1452
|
+
}),
|
|
1453
|
+
rxjs.map(() => key)
|
|
1454
|
+
);
|
|
1455
|
+
})
|
|
1456
|
+
);
|
|
1457
|
+
const getInitialQueryEntity = ({ key }) => ({
|
|
1458
|
+
isStale: true,
|
|
1459
|
+
queryKey: key,
|
|
1460
|
+
runners: []
|
|
1461
|
+
});
|
|
1462
|
+
const updateStoreWithQuery = ({
|
|
1463
|
+
queryStore,
|
|
1464
|
+
serializedKey,
|
|
1465
|
+
runner$,
|
|
1466
|
+
key
|
|
1467
|
+
}) => (stream) => stream.pipe(
|
|
1468
|
+
rxjs.map((value) => {
|
|
1469
|
+
if (key.length === 0)
|
|
1470
|
+
return [value, () => {
|
|
1471
|
+
}];
|
|
1472
|
+
if (!queryStore.get(serializedKey)) {
|
|
1473
|
+
queryStore.set(serializedKey, getInitialQueryEntity({ key }));
|
|
1474
|
+
} else {
|
|
1475
|
+
queryStore.update(serializedKey, {
|
|
1476
|
+
queryKey: key,
|
|
1477
|
+
...value.options.markStale && {
|
|
1478
|
+
isStale: true
|
|
1479
|
+
}
|
|
1480
|
+
});
|
|
1481
|
+
}
|
|
1482
|
+
return [value, queryStore.addRunner(serializedKey, runner$)];
|
|
1483
|
+
})
|
|
1484
|
+
);
|
|
1485
|
+
const logger = Logger.namespace("cache");
|
|
1486
|
+
const createCacheClient = ({
|
|
1487
|
+
queryStore
|
|
1488
|
+
}) => {
|
|
1489
|
+
const setQueryData = ({
|
|
1490
|
+
queryKey,
|
|
1491
|
+
updater
|
|
1492
|
+
}) => {
|
|
1493
|
+
const serializedKey = serializeKey(queryKey);
|
|
1494
|
+
if (queryKey.length === 0)
|
|
1495
|
+
return;
|
|
1496
|
+
logger.log("set cache for query", serializeKey);
|
|
1497
|
+
if (!queryStore.get(serializedKey)) {
|
|
1498
|
+
queryStore.set(serializedKey, getInitialQueryEntity({ key: queryKey }));
|
|
1499
|
+
}
|
|
1500
|
+
queryStore.update(serializedKey, (entity) => {
|
|
1501
|
+
var _a;
|
|
1502
|
+
if (typeof updater === "function") {
|
|
1503
|
+
const callableUpdater = updater;
|
|
1504
|
+
return {
|
|
1505
|
+
...entity,
|
|
1506
|
+
cache_fnResult: {
|
|
1507
|
+
result: callableUpdater(
|
|
1508
|
+
(_a = entity.cache_fnResult) == null ? void 0 : _a.result
|
|
1509
|
+
)
|
|
1510
|
+
}
|
|
1511
|
+
};
|
|
1512
|
+
}
|
|
1513
|
+
return {
|
|
1514
|
+
...entity,
|
|
1515
|
+
cache_fnResult: {
|
|
1516
|
+
result: updater
|
|
1517
|
+
}
|
|
1518
|
+
};
|
|
1519
|
+
});
|
|
1520
|
+
queryStore.dispatchQueryEvent({
|
|
1521
|
+
key: serializedKey,
|
|
1522
|
+
type: "queryDataSet"
|
|
1523
|
+
});
|
|
1524
|
+
};
|
|
1525
|
+
return {
|
|
1526
|
+
setQueryData
|
|
1527
|
+
};
|
|
1528
|
+
};
|
|
1529
|
+
const createClient = () => {
|
|
1530
|
+
const queryStore = createQueryStore();
|
|
1531
|
+
const invalidationClient = createInvalidationClient({ queryStore });
|
|
1532
|
+
const cacheClient = createCacheClient({ queryStore });
|
|
1533
|
+
const refetchClient = createRefetchClient({ queryStore });
|
|
1534
|
+
const query$ = ({
|
|
1535
|
+
key,
|
|
1536
|
+
fn$: maybeFn$,
|
|
1537
|
+
fn: maybeFn,
|
|
1538
|
+
refetch$ = new rxjs.Subject(),
|
|
1539
|
+
options$ = new rxjs.BehaviorSubject({})
|
|
1540
|
+
}) => {
|
|
1541
|
+
const serializedKey = serializeKey(key);
|
|
1542
|
+
const internalRefetch$ = new rxjs.Subject();
|
|
1543
|
+
const fn$ = maybeFn$ ?? (maybeFn ? rxjs.of(maybeFn) : rxjs.NEVER);
|
|
1544
|
+
console.log("query$()", serializedKey);
|
|
1545
|
+
const runner$ = options$.pipe(rxjs.map((options) => ({ options })));
|
|
1546
|
+
let deleteRunner = () => {
|
|
1547
|
+
};
|
|
1548
|
+
const initialTrigger$ = rxjs.of({
|
|
1549
|
+
type: "initial",
|
|
1550
|
+
ignoreStale: false
|
|
1551
|
+
});
|
|
1552
|
+
const trigger$ = createQueryTrigger({
|
|
1553
|
+
options$,
|
|
1554
|
+
refetch$: rxjs.merge(refetch$, internalRefetch$),
|
|
1555
|
+
key: serializedKey,
|
|
1556
|
+
queryStore
|
|
1557
|
+
}).pipe(refetchClient.pipeQueryTrigger({ options$, key: serializedKey }));
|
|
1558
|
+
const result$ = rxjs.merge(initialTrigger$, trigger$).pipe(
|
|
1559
|
+
rxjs.withLatestFrom(fn$, options$),
|
|
1560
|
+
rxjs.map(([trigger2, fn, options]) => ({ trigger: trigger2, fn, options })),
|
|
1561
|
+
updateStoreWithQuery({
|
|
1562
|
+
key,
|
|
1563
|
+
queryStore,
|
|
1564
|
+
runner$,
|
|
1565
|
+
serializedKey
|
|
1566
|
+
}),
|
|
1567
|
+
rxjs.map(([value, deleteRunnerFn]) => {
|
|
1568
|
+
deleteRunner = deleteRunnerFn;
|
|
1569
|
+
console.log("reactjrx", serializedKey, "query trigger", {
|
|
1570
|
+
trigger: value.trigger,
|
|
1571
|
+
options: value.options
|
|
1572
|
+
});
|
|
1573
|
+
return value;
|
|
1574
|
+
}),
|
|
1575
|
+
rxjs.filter(({ options }) => options.enabled !== false),
|
|
1576
|
+
rxjs.mergeMap(
|
|
1577
|
+
({ fn, options, trigger: trigger2 }) => createQueryFetch({
|
|
1578
|
+
options$,
|
|
1579
|
+
options,
|
|
1580
|
+
fn,
|
|
1581
|
+
queryStore,
|
|
1582
|
+
serializedKey,
|
|
1583
|
+
trigger: trigger2,
|
|
1584
|
+
trigger$
|
|
1585
|
+
})
|
|
1586
|
+
),
|
|
1587
|
+
// hooks
|
|
1588
|
+
rxjs.switchMap(
|
|
1589
|
+
(result) => rxjs.merge(
|
|
1590
|
+
rxjs.of(result).pipe(
|
|
1591
|
+
refetchClient.pipeQueryResult({
|
|
1592
|
+
key: serializedKey,
|
|
1593
|
+
queryStore,
|
|
1594
|
+
options$,
|
|
1595
|
+
refetch$: internalRefetch$
|
|
1596
|
+
})
|
|
1597
|
+
)
|
|
1598
|
+
)
|
|
1599
|
+
),
|
|
1600
|
+
mergeResults,
|
|
1601
|
+
rxjs.withLatestFrom(options$),
|
|
1602
|
+
rxjs.takeWhile(([result, options]) => {
|
|
1603
|
+
const shouldStop = result.data !== void 0 && options.terminateOnFirstResult;
|
|
1604
|
+
return !shouldStop;
|
|
1605
|
+
}, true),
|
|
1606
|
+
rxjs.map(([result]) => result),
|
|
1607
|
+
rxjs.tap((result) => {
|
|
1608
|
+
console.log("result", result);
|
|
1609
|
+
}),
|
|
1610
|
+
rxjs.finalize(() => {
|
|
1611
|
+
deleteRunner();
|
|
1612
|
+
})
|
|
1613
|
+
);
|
|
1614
|
+
return {
|
|
1615
|
+
result$
|
|
1616
|
+
};
|
|
1617
|
+
};
|
|
1618
|
+
const queryListenerSub = createQueryListener(
|
|
1619
|
+
queryStore,
|
|
1620
|
+
(stream) => stream.pipe(
|
|
1621
|
+
rxjs.switchMap((key) => {
|
|
1622
|
+
const key$ = rxjs.of(key);
|
|
1623
|
+
return rxjs.merge(
|
|
1624
|
+
invalidateCache({
|
|
1625
|
+
queryStore
|
|
1626
|
+
})(key$),
|
|
1627
|
+
markAsStale({
|
|
1628
|
+
queryStore
|
|
1629
|
+
})(key$),
|
|
1630
|
+
garbageCache({
|
|
1631
|
+
queryStore
|
|
1632
|
+
})(key$)
|
|
1633
|
+
);
|
|
1634
|
+
})
|
|
1635
|
+
)
|
|
1636
|
+
).subscribe();
|
|
1637
|
+
return {
|
|
1638
|
+
query$,
|
|
1639
|
+
queryStore,
|
|
1640
|
+
...invalidationClient,
|
|
1641
|
+
...cacheClient,
|
|
1642
|
+
...refetchClient,
|
|
1643
|
+
destroy: () => {
|
|
1644
|
+
queryStore.destroy();
|
|
1645
|
+
queryListenerSub.unsubscribe();
|
|
1646
|
+
}
|
|
1647
|
+
};
|
|
1648
|
+
};
|
|
923
1649
|
exports.PersistSignals = PersistSignals;
|
|
924
1650
|
exports.ReactjrxQueryProvider = Provider;
|
|
925
1651
|
exports.SIGNAL_RESET = SIGNAL_RESET;
|
|
@@ -937,6 +1663,7 @@ exports.useObserve = useObserve;
|
|
|
937
1663
|
exports.useObserveCallback = useObserveCallback;
|
|
938
1664
|
exports.usePersistSignalsContext = usePersistSignalsContext;
|
|
939
1665
|
exports.useQuery = useQuery;
|
|
1666
|
+
exports.useReactJrxProvider = useReactJrxProvider;
|
|
940
1667
|
exports.useScopeSignals = useScopeSignals;
|
|
941
1668
|
exports.useSetSignal = useSetSignal;
|
|
942
1669
|
exports.useSignal = useSignal;
|