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