reactjrx 1.33.0 → 1.35.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 +231 -159
- package/dist/index.d.ts +3 -1
- package/dist/index.js +232 -160
- package/dist/lib/binding/useObserve.d.ts +2 -2
- package/dist/lib/queries/Provider.d.ts +8 -6
- package/dist/lib/queries/client/createClient.d.ts +21 -0
- package/dist/lib/queries/client/operators.d.ts +5 -0
- package/dist/lib/queries/client/types.d.ts +7 -0
- package/dist/lib/queries/invalidation/autoRefetch.d.ts +2 -2
- package/dist/lib/queries/{useMutation.d.ts → useAsyncQuery.d.ts} +19 -19
- package/dist/lib/state/useSignal.d.ts +1 -1
- package/dist/lib/state/useSignalValue.d.ts +1 -1
- package/package.json +1 -1
- package/dist/lib/queries/keys/withKeyComparison.d.ts +0 -16
package/dist/index.cjs
CHANGED
|
@@ -147,8 +147,8 @@ function trigger(mapper = rxjs.identity) {
|
|
|
147
147
|
}
|
|
148
148
|
const SIGNAL_RESET = Symbol("SIGNAL_RESET");
|
|
149
149
|
function signal(options) {
|
|
150
|
-
const { default:
|
|
151
|
-
const subject = new rxjs.BehaviorSubject(
|
|
150
|
+
const { default: defaultValue2 } = options ?? {};
|
|
151
|
+
const subject = new rxjs.BehaviorSubject(defaultValue2);
|
|
152
152
|
const setValue = (arg) => {
|
|
153
153
|
if (arg === subject.getValue())
|
|
154
154
|
return;
|
|
@@ -160,7 +160,7 @@ function signal(options) {
|
|
|
160
160
|
return;
|
|
161
161
|
}
|
|
162
162
|
if (arg === SIGNAL_RESET) {
|
|
163
|
-
subject.next(
|
|
163
|
+
subject.next(defaultValue2 ?? void 0);
|
|
164
164
|
return;
|
|
165
165
|
}
|
|
166
166
|
subject.next(arg);
|
|
@@ -459,13 +459,13 @@ function shallowEqual(objA, objB) {
|
|
|
459
459
|
}
|
|
460
460
|
return true;
|
|
461
461
|
}
|
|
462
|
-
function
|
|
462
|
+
function useAsyncQuery(query, mapOperatorOrOptions, options = {}) {
|
|
463
463
|
const queryRef = useLiveRef(query);
|
|
464
464
|
const triggerSubject = useSubject();
|
|
465
465
|
const resetSubject = useSubject({
|
|
466
466
|
/**
|
|
467
467
|
* @important
|
|
468
|
-
* Because
|
|
468
|
+
* Because async query can still run after unmount, the user might
|
|
469
469
|
* want to use reset for whatever reason. We will only manually complete
|
|
470
470
|
* this subject whenever the main query hook finalize.
|
|
471
471
|
*/
|
|
@@ -519,6 +519,7 @@ function useMutation(query, mapOperatorOrOptions, options = {}) {
|
|
|
519
519
|
isLastMutationCalled
|
|
520
520
|
]).pipe(
|
|
521
521
|
rxjs.map(([{ data, isError }, isLastMutationCalled2]) => {
|
|
522
|
+
console.log("success", { data, isLastMutationCalled: isLastMutationCalled2 });
|
|
522
523
|
if (!isError) {
|
|
523
524
|
if (optionsRef.current.onSuccess != null)
|
|
524
525
|
optionsRef.current.onSuccess(data, args);
|
|
@@ -546,12 +547,12 @@ function useMutation(query, mapOperatorOrOptions, options = {}) {
|
|
|
546
547
|
})
|
|
547
548
|
)
|
|
548
549
|
).pipe(
|
|
550
|
+
rxjs.filter((state) => !!state && !!Object.keys(state).length),
|
|
549
551
|
/**
|
|
550
552
|
* @important
|
|
551
553
|
* state update optimization
|
|
552
554
|
*/
|
|
553
|
-
rxjs.distinctUntilChanged(shallowEqual)
|
|
554
|
-
rxjs.filter((state) => !!state && !!Object.keys(state).length)
|
|
555
|
+
rxjs.distinctUntilChanged(shallowEqual)
|
|
555
556
|
).subscribe((state) => {
|
|
556
557
|
data$.current.next({
|
|
557
558
|
...data$.current.getValue(),
|
|
@@ -579,7 +580,6 @@ function useMutation(query, mapOperatorOrOptions, options = {}) {
|
|
|
579
580
|
}, []);
|
|
580
581
|
return { ...result, isLoading: result.status === "loading", mutate, reset };
|
|
581
582
|
}
|
|
582
|
-
const arrayEqual = (a, b) => a.length === b.length && a.every((v, i) => v === b[i]);
|
|
583
583
|
const useCreateCacheStore = () => {
|
|
584
584
|
const cacheStore = useBehaviorSubject({});
|
|
585
585
|
useSubscribe(
|
|
@@ -641,21 +641,17 @@ const useQueryStore = () => {
|
|
|
641
641
|
const [store] = react.useState(/* @__PURE__ */ new Map());
|
|
642
642
|
return store;
|
|
643
643
|
};
|
|
644
|
-
const
|
|
645
|
-
const
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
const serializeKey = (key) => {
|
|
656
|
-
if (key.length === 0)
|
|
657
|
-
return "";
|
|
658
|
-
return JSON.stringify(key);
|
|
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
|
+
);
|
|
659
655
|
};
|
|
660
656
|
const deduplicate = (key, queryStore) => (source) => {
|
|
661
657
|
if (!key)
|
|
@@ -675,54 +671,151 @@ const deduplicate = (key, queryStore) => (source) => {
|
|
|
675
671
|
}
|
|
676
672
|
return finalSource;
|
|
677
673
|
};
|
|
678
|
-
const
|
|
679
|
-
if (
|
|
680
|
-
return
|
|
681
|
-
return
|
|
682
|
-
rxjs.repeat({
|
|
683
|
-
delay: options.staleTime ?? 999999
|
|
684
|
-
})
|
|
685
|
-
);
|
|
674
|
+
const serializeKey = (key) => {
|
|
675
|
+
if (key.length === 0)
|
|
676
|
+
return "";
|
|
677
|
+
return JSON.stringify(key);
|
|
686
678
|
};
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
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 }),
|
|
692
693
|
rxjs.pairwise(),
|
|
693
|
-
rxjs.map(([previous, current]) => {
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
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: () => {
|
|
709
779
|
}
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
780
|
+
};
|
|
781
|
+
};
|
|
782
|
+
const Context = react.createContext({
|
|
783
|
+
cacheStore: {},
|
|
784
|
+
client: createClient()
|
|
785
|
+
});
|
|
786
|
+
const Provider = react.memo(
|
|
787
|
+
({
|
|
788
|
+
children,
|
|
789
|
+
client
|
|
790
|
+
}) => {
|
|
791
|
+
const cacheStore = useCreateCacheStore();
|
|
792
|
+
const queryStore = useQueryStore();
|
|
793
|
+
const value = react.useMemo(() => ({ cacheStore, queryStore, client }), [client]);
|
|
794
|
+
react.useEffect(
|
|
795
|
+
() => () => {
|
|
796
|
+
client.destroy();
|
|
797
|
+
},
|
|
798
|
+
[client]
|
|
799
|
+
);
|
|
800
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Context.Provider, { value, children });
|
|
801
|
+
}
|
|
713
802
|
);
|
|
803
|
+
const useProvider = () => {
|
|
804
|
+
const context = react.useContext(Context);
|
|
805
|
+
return { ...context };
|
|
806
|
+
};
|
|
807
|
+
const arrayEqual = (a, b) => a.length === b.length && a.every((v, i) => v === b[i]);
|
|
808
|
+
function isDefined(arg) {
|
|
809
|
+
return arg !== null && arg !== void 0;
|
|
810
|
+
}
|
|
811
|
+
const defaultValue = { data: void 0, isLoading: true, error: void 0 };
|
|
714
812
|
function useQuery(keyOrQuery, queryOrOptionOrNothing, optionsOrNothing) {
|
|
715
813
|
const query = Array.isArray(keyOrQuery) ? queryOrOptionOrNothing : keyOrQuery;
|
|
716
814
|
const options = optionsOrNothing ?? (queryOrOptionOrNothing !== query ? queryOrOptionOrNothing : void 0) ?? {};
|
|
815
|
+
const internalRefresh$ = useSubject();
|
|
816
|
+
const { client } = useProvider();
|
|
717
817
|
const key = Array.isArray(keyOrQuery) ? keyOrQuery : void 0;
|
|
718
818
|
const params$ = useBehaviorSubject({ key, options, query });
|
|
719
|
-
const refetch$ = useSubject();
|
|
720
|
-
const data$ = useBehaviorSubject({
|
|
721
|
-
data: void 0,
|
|
722
|
-
error: void 0,
|
|
723
|
-
isLoading: true
|
|
724
|
-
});
|
|
725
|
-
const { queryStore } = useProvider();
|
|
726
819
|
react.useEffect(() => {
|
|
727
820
|
params$.current.next({
|
|
728
821
|
key,
|
|
@@ -730,104 +823,81 @@ function useQuery(keyOrQuery, queryOrOptionOrNothing, optionsOrNothing) {
|
|
|
730
823
|
query
|
|
731
824
|
});
|
|
732
825
|
}, [key, options, query]);
|
|
733
|
-
useSubscribe(() => {
|
|
734
|
-
const options$ = params$.current.pipe(
|
|
735
|
-
rxjs.map(({ options: options2 }) => options2),
|
|
736
|
-
rxjs.distinctUntilChanged(shallowEqual)
|
|
737
|
-
);
|
|
738
|
-
const newKeyReceived$ = params$.current.pipe(
|
|
739
|
-
rxjs.map(({ key: key2 }) => key2 ?? []),
|
|
740
|
-
rxjs.distinctUntilChanged(arrayEqual)
|
|
741
|
-
);
|
|
742
|
-
const newQuery$ = params$.current.pipe(
|
|
743
|
-
rxjs.map(({ query: query2 }) => query2 ?? (() => rxjs.of(void 0)))
|
|
744
|
-
);
|
|
745
|
-
const queryAsObservableObjectChanged$ = newQuery$.pipe(
|
|
746
|
-
rxjs.filter((query2) => typeof query2 !== "function"),
|
|
747
|
-
rxjs.distinctUntilChanged(shallowEqual)
|
|
748
|
-
);
|
|
749
|
-
const enabledOptionChanged$ = options$.pipe(
|
|
750
|
-
rxjs.map(({ enabled = true }) => enabled),
|
|
751
|
-
rxjs.distinctUntilChanged(),
|
|
752
|
-
rxjs.share()
|
|
753
|
-
);
|
|
754
|
-
const queryTrigger$ = rxjs.combineLatest([
|
|
755
|
-
newKeyReceived$,
|
|
756
|
-
enabledOptionChanged$,
|
|
757
|
-
queryAsObservableObjectChanged$.pipe(rxjs.startWith(void 0)),
|
|
758
|
-
refetch$.current.pipe(rxjs.startWith(void 0))
|
|
759
|
-
]);
|
|
760
|
-
const disabled$ = enabledOptionChanged$.pipe(
|
|
761
|
-
rxjs.filter((enabled) => !enabled),
|
|
762
|
-
rxjs.tap(() => {
|
|
763
|
-
data$.current.next({
|
|
764
|
-
...data$.current.getValue(),
|
|
765
|
-
isLoading: false
|
|
766
|
-
});
|
|
767
|
-
})
|
|
768
|
-
);
|
|
769
|
-
return queryTrigger$.pipe(
|
|
770
|
-
rxjs.withLatestFrom(options$, newQuery$),
|
|
771
|
-
rxjs.map(([[key2, enabled], options2, query2]) => ({
|
|
772
|
-
key: key2,
|
|
773
|
-
enabled,
|
|
774
|
-
options: options2,
|
|
775
|
-
query: query2
|
|
776
|
-
})),
|
|
777
|
-
withKeyComparison,
|
|
778
|
-
rxjs.filter(({ enabled }) => enabled),
|
|
779
|
-
rxjs.switchMap(({ key: key2, options: options2, isUsingDifferentKey, query: query2 }) => {
|
|
780
|
-
const serializedKey = serializeKey(key2);
|
|
781
|
-
return rxjs.of(null).pipe(
|
|
782
|
-
rxjs.tap(() => {
|
|
783
|
-
data$.current.next({
|
|
784
|
-
...data$.current.getValue(),
|
|
785
|
-
data: isUsingDifferentKey ? void 0 : data$.current.getValue().data,
|
|
786
|
-
error: void 0,
|
|
787
|
-
isLoading: true
|
|
788
|
-
});
|
|
789
|
-
}),
|
|
790
|
-
rxjs.switchMap(() => {
|
|
791
|
-
const query$ = rxjs.defer(() => {
|
|
792
|
-
const queryOrResponse = typeof query2 === "function" ? query2() : query2;
|
|
793
|
-
return rxjs.from(queryOrResponse);
|
|
794
|
-
});
|
|
795
|
-
return query$.pipe(
|
|
796
|
-
querx(options2),
|
|
797
|
-
deduplicate(serializedKey, queryStore),
|
|
798
|
-
// key.length > 0 ? withCache(key) : identity,
|
|
799
|
-
rxjs.map((response) => [response]),
|
|
800
|
-
rxjs.catchError((error) => {
|
|
801
|
-
return rxjs.of([void 0, error]);
|
|
802
|
-
}),
|
|
803
|
-
rxjs.tap(([response, error]) => {
|
|
804
|
-
if (response) {
|
|
805
|
-
if (options2.onSuccess != null)
|
|
806
|
-
options2.onSuccess(response);
|
|
807
|
-
}
|
|
808
|
-
data$.current.next({
|
|
809
|
-
...data$.current.getValue(),
|
|
810
|
-
isLoading: false,
|
|
811
|
-
error,
|
|
812
|
-
data: response
|
|
813
|
-
});
|
|
814
|
-
})
|
|
815
|
-
);
|
|
816
|
-
}),
|
|
817
|
-
autoRefetch(options2),
|
|
818
|
-
rxjs.takeUntil(disabled$)
|
|
819
|
-
);
|
|
820
|
-
})
|
|
821
|
-
);
|
|
822
|
-
}, []);
|
|
823
826
|
const result = useObserve(
|
|
824
|
-
() =>
|
|
825
|
-
|
|
826
|
-
|
|
827
|
+
() => {
|
|
828
|
+
const computedDefaultValue = {
|
|
829
|
+
...defaultValue,
|
|
830
|
+
isLoading: params$.current.getValue().options.enabled !== false
|
|
831
|
+
};
|
|
832
|
+
const newKeyReceived$ = params$.current.pipe(
|
|
833
|
+
rxjs.map(({ key: key2 }) => key2 ?? []),
|
|
834
|
+
rxjs.distinctUntilChanged(arrayEqual)
|
|
835
|
+
);
|
|
836
|
+
const newObservableObjectQuery$ = params$.current.pipe(
|
|
837
|
+
rxjs.map(({ query: query2 }) => query2),
|
|
838
|
+
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)
|
|
843
|
+
);
|
|
844
|
+
const fn$ = params$.current.pipe(
|
|
845
|
+
rxjs.map(({ query: query2 }) => query2),
|
|
846
|
+
rxjs.filter(isDefined)
|
|
847
|
+
);
|
|
848
|
+
const options$ = params$.current.pipe(rxjs.map(({ options: options2 }) => options2));
|
|
849
|
+
const triggers$ = rxjs.combineLatest([
|
|
850
|
+
newKeyReceived$,
|
|
851
|
+
newObservableObjectQuery$
|
|
852
|
+
]);
|
|
853
|
+
return triggers$.pipe(
|
|
854
|
+
rxjs.switchMap(([key2]) => {
|
|
855
|
+
const { query$, refetch$ } = client.query$({
|
|
856
|
+
key: key2,
|
|
857
|
+
fn$,
|
|
858
|
+
options$
|
|
859
|
+
});
|
|
860
|
+
const subscriptions = [internalRefresh$.current.subscribe(refetch$)];
|
|
861
|
+
return query$.pipe(
|
|
862
|
+
rxjs.finalize(() => {
|
|
863
|
+
subscriptions.forEach((sub) => {
|
|
864
|
+
sub.unsubscribe();
|
|
865
|
+
});
|
|
866
|
+
}),
|
|
867
|
+
rxjs.startWith(computedDefaultValue),
|
|
868
|
+
rxjs.pairwise(),
|
|
869
|
+
rxjs.map(
|
|
870
|
+
([
|
|
871
|
+
{ data: previousData, ...restPrevious },
|
|
872
|
+
{ data: currentData, ...restCurrent }
|
|
873
|
+
]) => ({
|
|
874
|
+
...restPrevious,
|
|
875
|
+
...restCurrent,
|
|
876
|
+
data: currentData && "result" in currentData ? currentData.result : previousData == null ? void 0 : previousData.result
|
|
877
|
+
})
|
|
878
|
+
)
|
|
879
|
+
);
|
|
880
|
+
}),
|
|
881
|
+
/**
|
|
882
|
+
* @important
|
|
883
|
+
* We skip the first result as it is comparable to default passed value.
|
|
884
|
+
* This is assuming all query are async and does not return a result right away.
|
|
885
|
+
* This is a design choice.
|
|
886
|
+
*/
|
|
887
|
+
params$.current.getValue().options.enabled !== false ? rxjs.skip(1) : rxjs.identity
|
|
888
|
+
);
|
|
889
|
+
},
|
|
890
|
+
{
|
|
891
|
+
defaultValue: {
|
|
892
|
+
...defaultValue,
|
|
893
|
+
isLoading: params$.current.getValue().options.enabled !== false
|
|
894
|
+
}
|
|
895
|
+
},
|
|
896
|
+
[client]
|
|
827
897
|
);
|
|
828
|
-
const refetch = react.useCallback((
|
|
829
|
-
|
|
830
|
-
}, []);
|
|
898
|
+
const refetch = react.useCallback(() => {
|
|
899
|
+
internalRefresh$.current.next();
|
|
900
|
+
}, [client]);
|
|
831
901
|
return { ...result, refetch };
|
|
832
902
|
}
|
|
833
903
|
function useSubscribeEffect(source, unsafeOptions, deps = []) {
|
|
@@ -853,6 +923,7 @@ function useSubscribeEffect(source, unsafeOptions, deps = []) {
|
|
|
853
923
|
exports.PersistSignals = PersistSignals;
|
|
854
924
|
exports.ReactjrxQueryProvider = Provider;
|
|
855
925
|
exports.SIGNAL_RESET = SIGNAL_RESET;
|
|
926
|
+
exports.createClient = createClient;
|
|
856
927
|
exports.createLocalforageAdapter = createLocalforageAdapter;
|
|
857
928
|
exports.createSharedStoreAdapter = createSharedStoreAdapter;
|
|
858
929
|
exports.exponentialBackoffDelay = exponentialBackoffDelay;
|
|
@@ -860,8 +931,8 @@ exports.getDelay = getDelay;
|
|
|
860
931
|
exports.retryBackoff = retryBackoff;
|
|
861
932
|
exports.signal = signal;
|
|
862
933
|
exports.trigger = trigger;
|
|
934
|
+
exports.useAsyncQuery = useAsyncQuery;
|
|
863
935
|
exports.useLiveRef = useLiveRef;
|
|
864
|
-
exports.useMutation = useMutation;
|
|
865
936
|
exports.useObserve = useObserve;
|
|
866
937
|
exports.useObserveCallback = useObserveCallback;
|
|
867
938
|
exports.usePersistSignalsContext = usePersistSignalsContext;
|
|
@@ -870,6 +941,7 @@ exports.useScopeSignals = useScopeSignals;
|
|
|
870
941
|
exports.useSetSignal = useSetSignal;
|
|
871
942
|
exports.useSignal = useSignal;
|
|
872
943
|
exports.useSignalValue = useSignalValue;
|
|
944
|
+
exports.useSubject = useSubject;
|
|
873
945
|
exports.useSubscribe = useSubscribe;
|
|
874
946
|
exports.useSubscribeEffect = useSubscribeEffect;
|
|
875
947
|
exports.useUnmountObservable = useUnmountObservable;
|
package/dist/index.d.ts
CHANGED
|
@@ -2,6 +2,7 @@ export * from "./lib/binding/useObserve";
|
|
|
2
2
|
export * from "./lib/binding/useSubscribe";
|
|
3
3
|
export * from "./lib/binding/useObserveCallback";
|
|
4
4
|
export * from "./lib/binding/trigger";
|
|
5
|
+
export * from "./lib/binding/useSubject";
|
|
5
6
|
export * from "./lib/state/signal";
|
|
6
7
|
export * from "./lib/state/useSignal";
|
|
7
8
|
export * from "./lib/state/useSetSignal";
|
|
@@ -15,7 +16,8 @@ export * from "./lib/state/persistance/createLocalforageAdapter";
|
|
|
15
16
|
export * from "./lib/utils/useUnmountObservable";
|
|
16
17
|
export * from "./lib/utils/retryBackoff";
|
|
17
18
|
export * from "./lib/utils/useLiveRef";
|
|
18
|
-
export * from "./lib/queries/
|
|
19
|
+
export * from "./lib/queries/useAsyncQuery";
|
|
19
20
|
export * from "./lib/queries/useQuery";
|
|
20
21
|
export * from "./lib/queries/useSubscribeEffect";
|
|
22
|
+
export * from "./lib/queries/client/createClient";
|
|
21
23
|
export { Provider as ReactjrxQueryProvider } from "./lib/queries/Provider";
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
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,
|
|
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, repeat, shareReplay, pairwise, retry } 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:
|
|
149
|
-
const subject = new BehaviorSubject(
|
|
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(
|
|
161
|
+
subject.next(defaultValue2 ?? void 0);
|
|
162
162
|
return;
|
|
163
163
|
}
|
|
164
164
|
subject.next(arg);
|
|
@@ -457,13 +457,13 @@ function shallowEqual(objA, objB) {
|
|
|
457
457
|
}
|
|
458
458
|
return true;
|
|
459
459
|
}
|
|
460
|
-
function
|
|
460
|
+
function useAsyncQuery(query, mapOperatorOrOptions, options = {}) {
|
|
461
461
|
const queryRef = useLiveRef(query);
|
|
462
462
|
const triggerSubject = useSubject();
|
|
463
463
|
const resetSubject = useSubject({
|
|
464
464
|
/**
|
|
465
465
|
* @important
|
|
466
|
-
* Because
|
|
466
|
+
* Because async query can still run after unmount, the user might
|
|
467
467
|
* want to use reset for whatever reason. We will only manually complete
|
|
468
468
|
* this subject whenever the main query hook finalize.
|
|
469
469
|
*/
|
|
@@ -517,6 +517,7 @@ function useMutation(query, mapOperatorOrOptions, options = {}) {
|
|
|
517
517
|
isLastMutationCalled
|
|
518
518
|
]).pipe(
|
|
519
519
|
map(([{ data, isError }, isLastMutationCalled2]) => {
|
|
520
|
+
console.log("success", { data, isLastMutationCalled: isLastMutationCalled2 });
|
|
520
521
|
if (!isError) {
|
|
521
522
|
if (optionsRef.current.onSuccess != null)
|
|
522
523
|
optionsRef.current.onSuccess(data, args);
|
|
@@ -544,12 +545,12 @@ function useMutation(query, mapOperatorOrOptions, options = {}) {
|
|
|
544
545
|
})
|
|
545
546
|
)
|
|
546
547
|
).pipe(
|
|
548
|
+
filter((state) => !!state && !!Object.keys(state).length),
|
|
547
549
|
/**
|
|
548
550
|
* @important
|
|
549
551
|
* state update optimization
|
|
550
552
|
*/
|
|
551
|
-
distinctUntilChanged(shallowEqual)
|
|
552
|
-
filter((state) => !!state && !!Object.keys(state).length)
|
|
553
|
+
distinctUntilChanged(shallowEqual)
|
|
553
554
|
).subscribe((state) => {
|
|
554
555
|
data$.current.next({
|
|
555
556
|
...data$.current.getValue(),
|
|
@@ -577,7 +578,6 @@ function useMutation(query, mapOperatorOrOptions, options = {}) {
|
|
|
577
578
|
}, []);
|
|
578
579
|
return { ...result, isLoading: result.status === "loading", mutate, reset };
|
|
579
580
|
}
|
|
580
|
-
const arrayEqual = (a, b) => a.length === b.length && a.every((v, i) => v === b[i]);
|
|
581
581
|
const useCreateCacheStore = () => {
|
|
582
582
|
const cacheStore = useBehaviorSubject({});
|
|
583
583
|
useSubscribe(
|
|
@@ -639,21 +639,17 @@ const useQueryStore = () => {
|
|
|
639
639
|
const [store] = useState(/* @__PURE__ */ new Map());
|
|
640
640
|
return store;
|
|
641
641
|
};
|
|
642
|
-
const
|
|
643
|
-
const
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
const serializeKey = (key) => {
|
|
654
|
-
if (key.length === 0)
|
|
655
|
-
return "";
|
|
656
|
-
return JSON.stringify(key);
|
|
642
|
+
const DEFAULT_STALE = 9999;
|
|
643
|
+
const autoRefetch = (options$ = of({})) => (source) => {
|
|
644
|
+
return source.pipe(
|
|
645
|
+
repeat({
|
|
646
|
+
delay: () => options$.pipe(
|
|
647
|
+
switchMap(
|
|
648
|
+
(options) => options.staleTime === Infinity ? EMPTY : timer(options.staleTime ?? DEFAULT_STALE)
|
|
649
|
+
)
|
|
650
|
+
)
|
|
651
|
+
})
|
|
652
|
+
);
|
|
657
653
|
};
|
|
658
654
|
const deduplicate = (key, queryStore) => (source) => {
|
|
659
655
|
if (!key)
|
|
@@ -673,54 +669,151 @@ const deduplicate = (key, queryStore) => (source) => {
|
|
|
673
669
|
}
|
|
674
670
|
return finalSource;
|
|
675
671
|
};
|
|
676
|
-
const
|
|
677
|
-
if (
|
|
678
|
-
return
|
|
679
|
-
return
|
|
680
|
-
repeat({
|
|
681
|
-
delay: options.staleTime ?? 999999
|
|
682
|
-
})
|
|
683
|
-
);
|
|
672
|
+
const serializeKey = (key) => {
|
|
673
|
+
if (key.length === 0)
|
|
674
|
+
return "";
|
|
675
|
+
return JSON.stringify(key);
|
|
684
676
|
};
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
677
|
+
const notifyQueryResult = (options$) => (stream$) => stream$.pipe(
|
|
678
|
+
withLatestFrom(options$),
|
|
679
|
+
map(([result, options]) => {
|
|
680
|
+
var _a, _b;
|
|
681
|
+
if (result.error) {
|
|
682
|
+
(_a = options.onError) == null ? void 0 : _a.call(options, result.error);
|
|
683
|
+
} else {
|
|
684
|
+
(_b = options.onSuccess) == null ? void 0 : _b.call(options, result);
|
|
685
|
+
}
|
|
686
|
+
return result;
|
|
687
|
+
})
|
|
688
|
+
);
|
|
689
|
+
const mergeResults = (stream$) => stream$.pipe(
|
|
690
|
+
startWith({ isLoading: false, data: void 0, error: void 0 }),
|
|
690
691
|
pairwise(),
|
|
691
|
-
map(([previous, current]) => {
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
692
|
+
map(([previous, current]) => ({
|
|
693
|
+
isLoading: false,
|
|
694
|
+
data: void 0,
|
|
695
|
+
error: void 0,
|
|
696
|
+
...previous,
|
|
697
|
+
...current
|
|
698
|
+
})),
|
|
699
|
+
distinctUntilChanged(shallowEqual)
|
|
700
|
+
);
|
|
701
|
+
const createClient = () => {
|
|
702
|
+
const queryStore = /* @__PURE__ */ new Map();
|
|
703
|
+
const refetch$ = new Subject();
|
|
704
|
+
const query$ = ({
|
|
705
|
+
key,
|
|
706
|
+
fn$,
|
|
707
|
+
options$
|
|
708
|
+
}) => {
|
|
709
|
+
const refetch$2 = new Subject();
|
|
710
|
+
const enabled$ = options$.pipe(map(({ enabled = true }) => enabled));
|
|
711
|
+
const disabled$ = enabled$.pipe(
|
|
712
|
+
distinctUntilChanged(),
|
|
713
|
+
filter((enabled) => !enabled)
|
|
714
|
+
);
|
|
715
|
+
const triggers = [
|
|
716
|
+
refetch$2.pipe(startWith(null)),
|
|
717
|
+
enabled$.pipe(
|
|
718
|
+
distinctUntilChanged(),
|
|
719
|
+
filter((enabled) => enabled)
|
|
720
|
+
)
|
|
721
|
+
];
|
|
722
|
+
const serializedKey = serializeKey(key);
|
|
723
|
+
const query$2 = combineLatest(triggers).pipe(
|
|
724
|
+
tap((params) => {
|
|
725
|
+
console.log("query$ trigger", { key, params });
|
|
726
|
+
}),
|
|
727
|
+
withLatestFrom(fn$),
|
|
728
|
+
switchMap(([, query]) => {
|
|
729
|
+
const deferredQuery = defer(() => {
|
|
730
|
+
const queryOrResponse = typeof query === "function" ? query() : query;
|
|
731
|
+
return from(queryOrResponse);
|
|
732
|
+
});
|
|
733
|
+
return merge(
|
|
734
|
+
disabled$.pipe(
|
|
735
|
+
take(1),
|
|
736
|
+
map(() => ({
|
|
737
|
+
isLoading: false
|
|
738
|
+
}))
|
|
739
|
+
),
|
|
740
|
+
merge(
|
|
741
|
+
of({ isLoading: true, error: void 0 }),
|
|
742
|
+
deferredQuery.pipe(
|
|
743
|
+
deduplicate(serializedKey, queryStore),
|
|
744
|
+
map((result) => ({
|
|
745
|
+
isLoading: false,
|
|
746
|
+
data: { result },
|
|
747
|
+
error: void 0
|
|
748
|
+
})),
|
|
749
|
+
catchError(
|
|
750
|
+
(error) => of({
|
|
751
|
+
isLoading: false,
|
|
752
|
+
data: void 0,
|
|
753
|
+
error
|
|
754
|
+
})
|
|
755
|
+
),
|
|
756
|
+
notifyQueryResult(options$)
|
|
757
|
+
)
|
|
758
|
+
).pipe(autoRefetch(options$), takeUntil(disabled$))
|
|
759
|
+
);
|
|
760
|
+
}),
|
|
761
|
+
mergeResults,
|
|
762
|
+
tap((data) => {
|
|
763
|
+
console.log("query$ return", data);
|
|
764
|
+
})
|
|
765
|
+
);
|
|
766
|
+
return {
|
|
767
|
+
query$: query$2,
|
|
768
|
+
refetch$: refetch$2,
|
|
769
|
+
enabled$
|
|
770
|
+
};
|
|
771
|
+
};
|
|
772
|
+
return {
|
|
773
|
+
query$,
|
|
774
|
+
refetch$,
|
|
775
|
+
queryStore,
|
|
776
|
+
destroy: () => {
|
|
707
777
|
}
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
778
|
+
};
|
|
779
|
+
};
|
|
780
|
+
const Context = createContext({
|
|
781
|
+
cacheStore: {},
|
|
782
|
+
client: createClient()
|
|
783
|
+
});
|
|
784
|
+
const Provider = memo(
|
|
785
|
+
({
|
|
786
|
+
children,
|
|
787
|
+
client
|
|
788
|
+
}) => {
|
|
789
|
+
const cacheStore = useCreateCacheStore();
|
|
790
|
+
const queryStore = useQueryStore();
|
|
791
|
+
const value = useMemo(() => ({ cacheStore, queryStore, client }), [client]);
|
|
792
|
+
useEffect(
|
|
793
|
+
() => () => {
|
|
794
|
+
client.destroy();
|
|
795
|
+
},
|
|
796
|
+
[client]
|
|
797
|
+
);
|
|
798
|
+
return /* @__PURE__ */ jsx(Context.Provider, { value, children });
|
|
799
|
+
}
|
|
711
800
|
);
|
|
801
|
+
const useProvider = () => {
|
|
802
|
+
const context = useContext(Context);
|
|
803
|
+
return { ...context };
|
|
804
|
+
};
|
|
805
|
+
const arrayEqual = (a, b) => a.length === b.length && a.every((v, i) => v === b[i]);
|
|
806
|
+
function isDefined(arg) {
|
|
807
|
+
return arg !== null && arg !== void 0;
|
|
808
|
+
}
|
|
809
|
+
const defaultValue = { data: void 0, isLoading: true, error: void 0 };
|
|
712
810
|
function useQuery(keyOrQuery, queryOrOptionOrNothing, optionsOrNothing) {
|
|
713
811
|
const query = Array.isArray(keyOrQuery) ? queryOrOptionOrNothing : keyOrQuery;
|
|
714
812
|
const options = optionsOrNothing ?? (queryOrOptionOrNothing !== query ? queryOrOptionOrNothing : void 0) ?? {};
|
|
813
|
+
const internalRefresh$ = useSubject();
|
|
814
|
+
const { client } = useProvider();
|
|
715
815
|
const key = Array.isArray(keyOrQuery) ? keyOrQuery : void 0;
|
|
716
816
|
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();
|
|
724
817
|
useEffect(() => {
|
|
725
818
|
params$.current.next({
|
|
726
819
|
key,
|
|
@@ -728,104 +821,81 @@ function useQuery(keyOrQuery, queryOrOptionOrNothing, optionsOrNothing) {
|
|
|
728
821
|
query
|
|
729
822
|
});
|
|
730
823
|
}, [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
|
-
}, []);
|
|
821
824
|
const result = useObserve(
|
|
822
|
-
() =>
|
|
823
|
-
|
|
824
|
-
|
|
825
|
+
() => {
|
|
826
|
+
const computedDefaultValue = {
|
|
827
|
+
...defaultValue,
|
|
828
|
+
isLoading: params$.current.getValue().options.enabled !== false
|
|
829
|
+
};
|
|
830
|
+
const newKeyReceived$ = params$.current.pipe(
|
|
831
|
+
map(({ key: key2 }) => key2 ?? []),
|
|
832
|
+
distinctUntilChanged(arrayEqual)
|
|
833
|
+
);
|
|
834
|
+
const newObservableObjectQuery$ = params$.current.pipe(
|
|
835
|
+
map(({ query: query2 }) => query2),
|
|
836
|
+
distinctUntilChanged(shallowEqual),
|
|
837
|
+
skip(1),
|
|
838
|
+
filter((query2) => !!query2 && typeof query2 !== "function"),
|
|
839
|
+
startWith(params$.current.getValue().query),
|
|
840
|
+
filter(isDefined)
|
|
841
|
+
);
|
|
842
|
+
const fn$ = params$.current.pipe(
|
|
843
|
+
map(({ query: query2 }) => query2),
|
|
844
|
+
filter(isDefined)
|
|
845
|
+
);
|
|
846
|
+
const options$ = params$.current.pipe(map(({ options: options2 }) => options2));
|
|
847
|
+
const triggers$ = combineLatest([
|
|
848
|
+
newKeyReceived$,
|
|
849
|
+
newObservableObjectQuery$
|
|
850
|
+
]);
|
|
851
|
+
return triggers$.pipe(
|
|
852
|
+
switchMap(([key2]) => {
|
|
853
|
+
const { query$, refetch$ } = client.query$({
|
|
854
|
+
key: key2,
|
|
855
|
+
fn$,
|
|
856
|
+
options$
|
|
857
|
+
});
|
|
858
|
+
const subscriptions = [internalRefresh$.current.subscribe(refetch$)];
|
|
859
|
+
return query$.pipe(
|
|
860
|
+
finalize(() => {
|
|
861
|
+
subscriptions.forEach((sub) => {
|
|
862
|
+
sub.unsubscribe();
|
|
863
|
+
});
|
|
864
|
+
}),
|
|
865
|
+
startWith(computedDefaultValue),
|
|
866
|
+
pairwise(),
|
|
867
|
+
map(
|
|
868
|
+
([
|
|
869
|
+
{ data: previousData, ...restPrevious },
|
|
870
|
+
{ data: currentData, ...restCurrent }
|
|
871
|
+
]) => ({
|
|
872
|
+
...restPrevious,
|
|
873
|
+
...restCurrent,
|
|
874
|
+
data: currentData && "result" in currentData ? currentData.result : previousData == null ? void 0 : previousData.result
|
|
875
|
+
})
|
|
876
|
+
)
|
|
877
|
+
);
|
|
878
|
+
}),
|
|
879
|
+
/**
|
|
880
|
+
* @important
|
|
881
|
+
* We skip the first result as it is comparable to default passed value.
|
|
882
|
+
* This is assuming all query are async and does not return a result right away.
|
|
883
|
+
* This is a design choice.
|
|
884
|
+
*/
|
|
885
|
+
params$.current.getValue().options.enabled !== false ? skip(1) : identity
|
|
886
|
+
);
|
|
887
|
+
},
|
|
888
|
+
{
|
|
889
|
+
defaultValue: {
|
|
890
|
+
...defaultValue,
|
|
891
|
+
isLoading: params$.current.getValue().options.enabled !== false
|
|
892
|
+
}
|
|
893
|
+
},
|
|
894
|
+
[client]
|
|
825
895
|
);
|
|
826
|
-
const refetch = useCallback((
|
|
827
|
-
|
|
828
|
-
}, []);
|
|
896
|
+
const refetch = useCallback(() => {
|
|
897
|
+
internalRefresh$.current.next();
|
|
898
|
+
}, [client]);
|
|
829
899
|
return { ...result, refetch };
|
|
830
900
|
}
|
|
831
901
|
function useSubscribeEffect(source, unsafeOptions, deps = []) {
|
|
@@ -852,6 +922,7 @@ export {
|
|
|
852
922
|
PersistSignals,
|
|
853
923
|
Provider as ReactjrxQueryProvider,
|
|
854
924
|
SIGNAL_RESET,
|
|
925
|
+
createClient,
|
|
855
926
|
createLocalforageAdapter,
|
|
856
927
|
createSharedStoreAdapter,
|
|
857
928
|
exponentialBackoffDelay,
|
|
@@ -859,8 +930,8 @@ export {
|
|
|
859
930
|
retryBackoff,
|
|
860
931
|
signal,
|
|
861
932
|
trigger,
|
|
933
|
+
useAsyncQuery,
|
|
862
934
|
useLiveRef,
|
|
863
|
-
useMutation,
|
|
864
935
|
useObserve,
|
|
865
936
|
useObserveCallback,
|
|
866
937
|
usePersistSignalsContext,
|
|
@@ -869,6 +940,7 @@ export {
|
|
|
869
940
|
useSetSignal,
|
|
870
941
|
useSignal,
|
|
871
942
|
useSignalValue,
|
|
943
|
+
useSubject,
|
|
872
944
|
useSubscribe,
|
|
873
945
|
useSubscribeEffect,
|
|
874
946
|
useUnmountObservable,
|
|
@@ -10,6 +10,6 @@ interface Option<R = undefined> {
|
|
|
10
10
|
export declare function useObserve<T>(source: BehaviorSubject<T>): T;
|
|
11
11
|
export declare function useObserve<T>(source: Observable<T>): T | undefined;
|
|
12
12
|
export declare function useObserve<T>(source: () => Observable<T>, deps: DependencyList): T | undefined;
|
|
13
|
-
export declare function useObserve<T
|
|
14
|
-
export declare function useObserve<T
|
|
13
|
+
export declare function useObserve<T>(source: Observable<T>, options: Option<T>): T;
|
|
14
|
+
export declare function useObserve<T>(source: () => Observable<T>, options: Option<T>, deps: DependencyList): T;
|
|
15
15
|
export {};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type ReactNode } from "react";
|
|
2
2
|
import { type BehaviorSubject } from "rxjs";
|
|
3
|
+
import { createClient } from "./client/createClient";
|
|
3
4
|
type CacheStore = Record<string, {
|
|
4
5
|
value: any;
|
|
5
6
|
date: number;
|
|
@@ -9,15 +10,16 @@ export declare const Context: import("react").Context<{
|
|
|
9
10
|
cacheStore: {
|
|
10
11
|
current: BehaviorSubject<CacheStore>;
|
|
11
12
|
};
|
|
12
|
-
|
|
13
|
-
}
|
|
14
|
-
export declare const Provider: import("react").MemoExoticComponent<({ children }: {
|
|
13
|
+
client: ReturnType<typeof createClient>;
|
|
14
|
+
}>;
|
|
15
|
+
export declare const Provider: import("react").MemoExoticComponent<({ children, client }: {
|
|
15
16
|
children: ReactNode;
|
|
17
|
+
client: ReturnType<typeof createClient>;
|
|
16
18
|
}) => import("react/jsx-runtime").JSX.Element>;
|
|
17
19
|
export declare const useProvider: () => {
|
|
18
|
-
cacheStore
|
|
20
|
+
cacheStore: {
|
|
19
21
|
current: BehaviorSubject<CacheStore>;
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
+
};
|
|
23
|
+
client: ReturnType<typeof createClient>;
|
|
22
24
|
};
|
|
23
25
|
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { type Observable, Subject } from "rxjs";
|
|
2
|
+
import { type QuerxOptions } from "../types";
|
|
3
|
+
import { type QueryResult } from "./types";
|
|
4
|
+
type Query<T> = (() => Promise<T>) | (() => Observable<T>) | Observable<T>;
|
|
5
|
+
export declare const createClient: () => {
|
|
6
|
+
query$: <T>({ key, fn$, options$ }: {
|
|
7
|
+
key: any[];
|
|
8
|
+
fn$: Observable<Query<T>>;
|
|
9
|
+
options$: Observable<QuerxOptions<T>>;
|
|
10
|
+
}) => {
|
|
11
|
+
query$: Observable<QueryResult<T>>;
|
|
12
|
+
refetch$: Subject<void>;
|
|
13
|
+
enabled$: Observable<boolean>;
|
|
14
|
+
};
|
|
15
|
+
refetch$: Subject<{
|
|
16
|
+
key: any[];
|
|
17
|
+
}>;
|
|
18
|
+
queryStore: Map<any, any>;
|
|
19
|
+
destroy: () => void;
|
|
20
|
+
};
|
|
21
|
+
export {};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { type Observable } from "rxjs";
|
|
2
|
+
import { type QuerxOptions } from "../types";
|
|
3
|
+
import { type QueryResult } from "./types";
|
|
4
|
+
export declare const notifyQueryResult: <T>(options$: Observable<QuerxOptions<T>>) => (stream$: Observable<Partial<QueryResult<T>>>) => Observable<Partial<QueryResult<T>>>;
|
|
5
|
+
export declare const mergeResults: <T>(stream$: Observable<Partial<QueryResult<T>>>) => Observable<QueryResult<T>>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { type Observable } from "rxjs";
|
|
2
|
-
export declare const autoRefetch: <T>(options
|
|
2
|
+
export declare const autoRefetch: <T>(options$?: Observable<{
|
|
3
3
|
staleTime?: number;
|
|
4
|
-
}) => (source: Observable<T>) => Observable<T>;
|
|
4
|
+
}>) => (source: Observable<T>) => Observable<T>;
|
|
@@ -4,22 +4,22 @@ interface QueryState<R> {
|
|
|
4
4
|
status: "idle" | "loading" | "error" | "success";
|
|
5
5
|
error: unknown;
|
|
6
6
|
}
|
|
7
|
-
export interface
|
|
7
|
+
export interface AsyncQueryOptions<Result, Params> {
|
|
8
8
|
retry?: false | number | ((attempt: number, error: unknown) => boolean);
|
|
9
9
|
/**
|
|
10
|
-
* Called for every
|
|
10
|
+
* Called for every async query on error.
|
|
11
11
|
* `merge` mapping will run callback as they happen.
|
|
12
12
|
* Use `concat` if you need to run callbacks in order of calling.
|
|
13
13
|
*/
|
|
14
14
|
onError?: (error: unknown, params: Params) => void;
|
|
15
15
|
/**
|
|
16
|
-
* Called for every
|
|
16
|
+
* Called for every async query on success.
|
|
17
17
|
* `merge` mapping will run callback as they happen.
|
|
18
18
|
* Use `concat` if you need to run callbacks in order of calling.
|
|
19
19
|
*/
|
|
20
20
|
onSuccess?: (data: Result, params: Params) => void;
|
|
21
21
|
/**
|
|
22
|
-
* When true, any running
|
|
22
|
+
* When true, any running async query will be cancelled (when possible) on unmount.
|
|
23
23
|
* You need to handle it yourself for promises if needed.
|
|
24
24
|
* Callbacks will not be called as a result.
|
|
25
25
|
*
|
|
@@ -39,19 +39,19 @@ interface Result<A, R> {
|
|
|
39
39
|
status: "idle" | "loading" | "error" | "success";
|
|
40
40
|
isLoading: boolean;
|
|
41
41
|
/**
|
|
42
|
-
* If the latest
|
|
42
|
+
* If the latest async query is in a success state, data contains its result.
|
|
43
43
|
*
|
|
44
44
|
* @important
|
|
45
|
-
* The value does not automatically reset when a new
|
|
46
|
-
* when a new
|
|
45
|
+
* The value does not automatically reset when a new async query run. It will be updated
|
|
46
|
+
* when a new async query success or error.
|
|
47
47
|
*/
|
|
48
48
|
data: R | undefined;
|
|
49
49
|
/**
|
|
50
|
-
* If the latest
|
|
50
|
+
* If the latest async query is in a error state, error contains its error.
|
|
51
51
|
*
|
|
52
52
|
* @important
|
|
53
|
-
* The value does not automatically reset when a new
|
|
54
|
-
* when a new
|
|
53
|
+
* The value does not automatically reset when a new async query run. It will be updated
|
|
54
|
+
* when a new async query success or error.
|
|
55
55
|
*/
|
|
56
56
|
error: unknown | undefined;
|
|
57
57
|
mutate: (args: A) => void;
|
|
@@ -63,20 +63,20 @@ interface Result<A, R> {
|
|
|
63
63
|
* it when specific need arise.
|
|
64
64
|
*
|
|
65
65
|
* `merge`:
|
|
66
|
-
* Run each
|
|
67
|
-
* The result is always from the latest
|
|
66
|
+
* Run each async query as they are triggered without any cancellation or queue system.
|
|
67
|
+
* The result is always from the latest async query triggered, not necessarily
|
|
68
68
|
* the latest one running.
|
|
69
69
|
*
|
|
70
70
|
* `concat`:
|
|
71
|
-
* Unlike merge, it will trigger each
|
|
72
|
-
* a queue system. The result is not necessarily the last triggered
|
|
73
|
-
* but the current running
|
|
71
|
+
* Unlike merge, it will trigger each async query sequentially following
|
|
72
|
+
* a queue system. The result is not necessarily the last triggered async query
|
|
73
|
+
* but the current running async query.
|
|
74
74
|
*
|
|
75
75
|
* `switch`:
|
|
76
|
-
* Only run the latest
|
|
77
|
-
* Result correspond to the current running
|
|
76
|
+
* Only run the latest async query triggered and cancel any previously running one.
|
|
77
|
+
* Result correspond to the current running async query.
|
|
78
78
|
*/
|
|
79
79
|
type MapOperator = "switch" | "concat" | "merge";
|
|
80
|
-
export declare function
|
|
81
|
-
export declare function
|
|
80
|
+
export declare function useAsyncQuery<A = void, R = undefined>(query: (args: A) => Promise<R> | Observable<R>, mapOperatorOrOptions?: MapOperator, options?: AsyncQueryOptions<R, A>): Result<A, R>;
|
|
81
|
+
export declare function useAsyncQuery<A = void, R = undefined>(query: (args: A) => Promise<R> | Observable<R>, mapOperatorOrOptions?: AsyncQueryOptions<R, A>): Result<A, R>;
|
|
82
82
|
export {};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { type Signal } from "./signal";
|
|
2
|
-
export declare const useSignal: <S
|
|
2
|
+
export declare const useSignal: <S>(signal: Signal<S, S>) => readonly [S, (stateOrUpdater: typeof import("./constants").SIGNAL_RESET | S | ((prev: S) => S)) => void];
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
import { type Signal } from "./signal";
|
|
2
|
-
export declare const useSignalValue: <S
|
|
2
|
+
export declare const useSignalValue: <S>(signal: Signal<S, S>, key?: string) => S;
|
package/package.json
CHANGED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import type { Observable } from "rxjs";
|
|
2
|
-
export declare const withKeyComparison: <T extends {
|
|
3
|
-
key: any[];
|
|
4
|
-
}>(stream: Observable<T>) => Observable<(T & {
|
|
5
|
-
previousKey: undefined;
|
|
6
|
-
isUsingDifferentKey: boolean;
|
|
7
|
-
} extends infer T_1 ? T_1 extends T & {
|
|
8
|
-
previousKey: undefined;
|
|
9
|
-
isUsingDifferentKey: boolean;
|
|
10
|
-
} ? T_1 extends null | undefined ? never : T_1 : never : never) | (T & {
|
|
11
|
-
previousKey: any[];
|
|
12
|
-
isUsingDifferentKey: boolean;
|
|
13
|
-
} extends infer T_2 ? T_2 extends T & {
|
|
14
|
-
previousKey: any[];
|
|
15
|
-
isUsingDifferentKey: boolean;
|
|
16
|
-
} ? T_2 extends null | undefined ? never : T_2 : never : never)>;
|