reactjrx 1.101.0 → 1.101.1

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 CHANGED
@@ -61,7 +61,8 @@ function makeObservable(something) {
61
61
  function useObserve(source$, optionsOrDeps, maybeDeps) {
62
62
  const options = optionsOrDeps != null && !Array.isArray(optionsOrDeps) ? optionsOrDeps : {
63
63
  defaultValue: void 0,
64
- unsubscribeOnUnmount: true
64
+ unsubscribeOnUnmount: true,
65
+ compareFn: void 0
65
66
  };
66
67
  const deps = !maybeDeps && Array.isArray(optionsOrDeps) ? optionsOrDeps : typeof source$ === "function" ? maybeDeps ?? [] : [source$];
67
68
  const valueRef = React.useRef(
@@ -73,13 +74,15 @@ function useObserve(source$, optionsOrDeps, maybeDeps) {
73
74
  (next) => {
74
75
  const source = sourceRef.current;
75
76
  const sub = makeObservable(source).pipe(
77
+ optionsRef.current.defaultValue ? rxjs.startWith(optionsRef.current.defaultValue) : rxjs.identity,
76
78
  /**
77
- * @important
78
- * We only check primitives because underlying subscription might
79
- * be using objects and keeping same reference but pushing new
80
- * properties values
79
+ * @important there is already a Object.is comparison in place from react
80
+ * so we only add a custom compareFn if provided
81
81
  */
82
- rxjs.distinctUntilChanged((a, b) => a === b),
82
+ optionsRef.current.compareFn ? rxjs.distinctUntilChanged((a, b) => {
83
+ if (a === void 0 || b === void 0) return false;
84
+ return optionsRef.current.compareFn(a, b);
85
+ }) : rxjs.identity,
83
86
  rxjs.tap((value) => {
84
87
  valueRef.current = value;
85
88
  }),
@@ -476,6 +479,28 @@ function persistSignals({
476
479
  )
477
480
  );
478
481
  }
482
+ function shallowEqual(objA, objB) {
483
+ if (objA === null || objA === void 0 || objB === void 0) {
484
+ return objA === objB;
485
+ }
486
+ if (typeof objA !== "object" || typeof objB !== "object") {
487
+ return objA === objB;
488
+ }
489
+ if (objA.constructor !== (objB == null ? void 0 : objB.constructor)) {
490
+ return false;
491
+ }
492
+ const keysA = Object.keys(objA);
493
+ const keysB = Object.keys(objB);
494
+ if (keysA.length !== keysB.length) {
495
+ return false;
496
+ }
497
+ for (const key of keysA) {
498
+ if (!objB.hasOwnProperty(key) || objA[key] !== objB[key]) {
499
+ return false;
500
+ }
501
+ }
502
+ return true;
503
+ }
479
504
  function usePersistSignals({
480
505
  entries = [],
481
506
  onHydrated,
@@ -487,18 +512,21 @@ function usePersistSignals({
487
512
  return useObserve(
488
513
  () => {
489
514
  const persistence$ = adapterSubject.current.pipe(
490
- rxjs.concatMap((adapter2) => {
491
- if (!adapter2) return rxjs.NEVER;
492
- return entriesSubject.current.pipe(
493
- rxjs.concatMap(
494
- (entries2) => persistSignals({
495
- adapter: adapter2,
496
- entries: entries2,
497
- onHydrated: () => {
498
- var _a;
499
- (_a = onHydratedRef.current) == null ? void 0 : _a.call(onHydratedRef);
500
- }
501
- })
515
+ rxjs.switchMap((adapter2) => {
516
+ if (!adapter2) return rxjs.of({ type: "reset" });
517
+ return rxjs.merge(
518
+ rxjs.of({ type: "reset" }),
519
+ entriesSubject.current.pipe(
520
+ rxjs.concatMap(
521
+ (entries2) => persistSignals({
522
+ adapter: adapter2,
523
+ entries: entries2,
524
+ onHydrated: () => {
525
+ var _a;
526
+ (_a = onHydratedRef.current) == null ? void 0 : _a.call(onHydratedRef);
527
+ }
528
+ })
529
+ )
502
530
  )
503
531
  );
504
532
  })
@@ -506,6 +534,7 @@ function usePersistSignals({
506
534
  return persistence$.pipe(
507
535
  rxjs.scan(
508
536
  (acc, event) => {
537
+ if (event.type === "reset") return { isHydrated: false };
509
538
  if (event.type === "hydrated") return { isHydrated: true };
510
539
  return acc;
511
540
  },
@@ -513,8 +542,8 @@ function usePersistSignals({
513
542
  )
514
543
  );
515
544
  },
516
- { defaultValue: { isHydrated: false } },
517
- [adapterSubject]
545
+ { defaultValue: { isHydrated: false }, compareFn: shallowEqual },
546
+ [adapterSubject, entriesSubject]
518
547
  );
519
548
  }
520
549
  const useUnmountObservable = () => {
@@ -789,28 +818,6 @@ const matchKey = (keyA, keyB, { exact = false } = {}) => {
789
818
  }
790
819
  return partialMatchKey(keyA, keyB);
791
820
  };
792
- function shallowEqual(objA, objB) {
793
- if (objA === null || objA === void 0 || objB === void 0) {
794
- return objA === objB;
795
- }
796
- if (typeof objA !== "object" || typeof objB !== "object") {
797
- return objA === objB;
798
- }
799
- if (objA.constructor !== (objB == null ? void 0 : objB.constructor)) {
800
- return false;
801
- }
802
- const keysA = Object.keys(objA);
803
- const keysB = Object.keys(objB);
804
- if (keysA.length !== keysB.length) {
805
- return false;
806
- }
807
- for (const key of keysA) {
808
- if (!objB.hasOwnProperty(key) || objA[key] !== objB[key]) {
809
- return false;
810
- }
811
- }
812
- return true;
813
- }
814
821
  const distinctUntilStateChanged = (stream) => stream.pipe(
815
822
  rxjs.distinctUntilChanged(
816
823
  ({ data: prevData, ...prev }, { data: currData, ...curr }) => shallowEqual(prev, curr) && shallowEqual(prevData, currData)
@@ -1972,12 +1979,17 @@ const executeMutation = ({
1972
1979
  const isPaused = state.isPaused;
1973
1980
  const defaultFn = async () => await Promise.reject(new Error("No mutationFn found"));
1974
1981
  const mutationFn = options.mutationFn ?? defaultFn;
1975
- const contextFromOnMutate$ = makeObservable(
1976
- // eslint-disable-next-line @typescript-eslint/promise-function-async
1977
- () => {
1978
- var _a;
1979
- return ((_a = options.onMutate) == null ? void 0 : _a.call(options, variables)) ?? void 0;
1980
- }
1982
+ const onMutateFactory = () => {
1983
+ var _a;
1984
+ return ((_a = options.onMutate) == null ? void 0 : _a.call(options, variables)) ?? void 0;
1985
+ };
1986
+ const contextFromOnMutate$ = makeObservable(onMutateFactory);
1987
+ contextFromOnMutate$.pipe(
1988
+ rxjs.tap((context) => {
1989
+ if (context === void 0) {
1990
+ throw new Error("onMutate returned undefined");
1991
+ }
1992
+ })
1981
1993
  );
1982
1994
  const rawContext$ = rxjs.of(state.context);
1983
1995
  const context$ = rxjs.iif(() => isPaused, rawContext$, contextFromOnMutate$).pipe(
@@ -2005,10 +2017,7 @@ const executeMutation = ({
2005
2017
  };
2006
2018
  const queryRunner$ = context$.pipe(
2007
2019
  rxjs.switchMap((context) => {
2008
- const fn$ = typeof mutationFn === "function" ? (
2009
- // eslint-disable-next-line @typescript-eslint/promise-function-async
2010
- makeObservable(() => mutationFn(variables))
2011
- ) : mutationFn;
2020
+ const fn$ = typeof mutationFn === "function" ? makeObservable(() => mutationFn(variables)) : mutationFn;
2012
2021
  const sharedFn$ = fn$.pipe(rxjs.share());
2013
2022
  const completeWithoutValue$ = sharedFn$.pipe(
2014
2023
  rxjs.isEmpty(),
@@ -2185,6 +2194,7 @@ class Mutation {
2185
2194
  return (_b = (_a = mutationCache.config).onMutate) == null ? void 0 : _b.call(
2186
2195
  _a,
2187
2196
  variables2,
2197
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
2188
2198
  this
2189
2199
  );
2190
2200
  }
@@ -2208,6 +2218,7 @@ class Mutation {
2208
2218
  error,
2209
2219
  variables2,
2210
2220
  context,
2221
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
2211
2222
  this
2212
2223
  );
2213
2224
  }
@@ -2230,6 +2241,7 @@ class Mutation {
2230
2241
  error,
2231
2242
  variables2,
2232
2243
  context,
2244
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
2233
2245
  this
2234
2246
  );
2235
2247
  }
@@ -2251,6 +2263,7 @@ class Mutation {
2251
2263
  data,
2252
2264
  variables2,
2253
2265
  context,
2266
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
2254
2267
  this
2255
2268
  );
2256
2269
  }
package/dist/index.js CHANGED
@@ -11,7 +11,7 @@ var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "
11
11
  var _trigger$, _mutationRunner, _currentMutationSubject, _visibility$, _focusedSubject, _client, _currentQuery, _fetchSubject, _currentQueryInitialState, _lastResult, _lastQueryWithDefinedData, _observers, _observerCount, _cancelSubject, _executeSubject, _store, _defaultOptions, _initialState, _notifySubject, _store2, _mutationCache, _queryCache, _mutationDefaults, _queryDefaults, _defaultOptions2;
12
12
  import * as React from "react";
13
13
  import { useRef, useMemo, useCallback, useSyncExternalStore, useEffect, useState, createContext, memo, useContext } from "react";
14
- import { isObservable, from, of, defer, distinctUntilChanged, tap, catchError, EMPTY, Subject, BehaviorSubject, skip, first, map, switchMap, zip, share, merge, throttleTime, asyncScheduler, concatMap, NEVER, scan, throwError, timer, Observable, takeWhile, filter, last, mergeMap as mergeMap$1, takeUntil, identity, shareReplay, ignoreElements, fromEvent, noop as noop$1, startWith, pairwise, delay, interval, withLatestFrom, retry, iif, isEmpty, concat, toArray, take, combineLatest, endWith, lastValueFrom } from "rxjs";
14
+ import { isObservable, from, of, defer, startWith, identity, distinctUntilChanged, tap, catchError, EMPTY, Subject, BehaviorSubject, skip, first, map, switchMap, zip, share, merge, throttleTime, asyncScheduler, concatMap, scan, throwError, timer, Observable, takeWhile, filter, last, mergeMap as mergeMap$1, takeUntil, shareReplay, ignoreElements, fromEvent, noop as noop$1, pairwise, NEVER, delay, interval, withLatestFrom, retry, iif, isEmpty, concat, toArray, take, combineLatest, endWith, lastValueFrom } from "rxjs";
15
15
  import { catchError as catchError$1, mergeMap, retryWhen, concatMap as concatMap$1, first as first$1, tap as tap$1 } from "rxjs/operators";
16
16
  import { jsxs, jsx } from "react/jsx-runtime";
17
17
  const useLiveRef = (value) => {
@@ -43,7 +43,8 @@ function makeObservable(something) {
43
43
  function useObserve(source$, optionsOrDeps, maybeDeps) {
44
44
  const options = optionsOrDeps != null && !Array.isArray(optionsOrDeps) ? optionsOrDeps : {
45
45
  defaultValue: void 0,
46
- unsubscribeOnUnmount: true
46
+ unsubscribeOnUnmount: true,
47
+ compareFn: void 0
47
48
  };
48
49
  const deps = !maybeDeps && Array.isArray(optionsOrDeps) ? optionsOrDeps : typeof source$ === "function" ? maybeDeps ?? [] : [source$];
49
50
  const valueRef = useRef(
@@ -55,13 +56,15 @@ function useObserve(source$, optionsOrDeps, maybeDeps) {
55
56
  (next) => {
56
57
  const source = sourceRef.current;
57
58
  const sub = makeObservable(source).pipe(
59
+ optionsRef.current.defaultValue ? startWith(optionsRef.current.defaultValue) : identity,
58
60
  /**
59
- * @important
60
- * We only check primitives because underlying subscription might
61
- * be using objects and keeping same reference but pushing new
62
- * properties values
61
+ * @important there is already a Object.is comparison in place from react
62
+ * so we only add a custom compareFn if provided
63
63
  */
64
- distinctUntilChanged((a, b) => a === b),
64
+ optionsRef.current.compareFn ? distinctUntilChanged((a, b) => {
65
+ if (a === void 0 || b === void 0) return false;
66
+ return optionsRef.current.compareFn(a, b);
67
+ }) : identity,
65
68
  tap((value) => {
66
69
  valueRef.current = value;
67
70
  }),
@@ -458,6 +461,28 @@ function persistSignals({
458
461
  )
459
462
  );
460
463
  }
464
+ function shallowEqual(objA, objB) {
465
+ if (objA === null || objA === void 0 || objB === void 0) {
466
+ return objA === objB;
467
+ }
468
+ if (typeof objA !== "object" || typeof objB !== "object") {
469
+ return objA === objB;
470
+ }
471
+ if (objA.constructor !== (objB == null ? void 0 : objB.constructor)) {
472
+ return false;
473
+ }
474
+ const keysA = Object.keys(objA);
475
+ const keysB = Object.keys(objB);
476
+ if (keysA.length !== keysB.length) {
477
+ return false;
478
+ }
479
+ for (const key of keysA) {
480
+ if (!objB.hasOwnProperty(key) || objA[key] !== objB[key]) {
481
+ return false;
482
+ }
483
+ }
484
+ return true;
485
+ }
461
486
  function usePersistSignals({
462
487
  entries = [],
463
488
  onHydrated,
@@ -469,18 +494,21 @@ function usePersistSignals({
469
494
  return useObserve(
470
495
  () => {
471
496
  const persistence$ = adapterSubject.current.pipe(
472
- concatMap((adapter2) => {
473
- if (!adapter2) return NEVER;
474
- return entriesSubject.current.pipe(
475
- concatMap(
476
- (entries2) => persistSignals({
477
- adapter: adapter2,
478
- entries: entries2,
479
- onHydrated: () => {
480
- var _a;
481
- (_a = onHydratedRef.current) == null ? void 0 : _a.call(onHydratedRef);
482
- }
483
- })
497
+ switchMap((adapter2) => {
498
+ if (!adapter2) return of({ type: "reset" });
499
+ return merge(
500
+ of({ type: "reset" }),
501
+ entriesSubject.current.pipe(
502
+ concatMap(
503
+ (entries2) => persistSignals({
504
+ adapter: adapter2,
505
+ entries: entries2,
506
+ onHydrated: () => {
507
+ var _a;
508
+ (_a = onHydratedRef.current) == null ? void 0 : _a.call(onHydratedRef);
509
+ }
510
+ })
511
+ )
484
512
  )
485
513
  );
486
514
  })
@@ -488,6 +516,7 @@ function usePersistSignals({
488
516
  return persistence$.pipe(
489
517
  scan(
490
518
  (acc, event) => {
519
+ if (event.type === "reset") return { isHydrated: false };
491
520
  if (event.type === "hydrated") return { isHydrated: true };
492
521
  return acc;
493
522
  },
@@ -495,8 +524,8 @@ function usePersistSignals({
495
524
  )
496
525
  );
497
526
  },
498
- { defaultValue: { isHydrated: false } },
499
- [adapterSubject]
527
+ { defaultValue: { isHydrated: false }, compareFn: shallowEqual },
528
+ [adapterSubject, entriesSubject]
500
529
  );
501
530
  }
502
531
  const useUnmountObservable = () => {
@@ -771,28 +800,6 @@ const matchKey = (keyA, keyB, { exact = false } = {}) => {
771
800
  }
772
801
  return partialMatchKey(keyA, keyB);
773
802
  };
774
- function shallowEqual(objA, objB) {
775
- if (objA === null || objA === void 0 || objB === void 0) {
776
- return objA === objB;
777
- }
778
- if (typeof objA !== "object" || typeof objB !== "object") {
779
- return objA === objB;
780
- }
781
- if (objA.constructor !== (objB == null ? void 0 : objB.constructor)) {
782
- return false;
783
- }
784
- const keysA = Object.keys(objA);
785
- const keysB = Object.keys(objB);
786
- if (keysA.length !== keysB.length) {
787
- return false;
788
- }
789
- for (const key of keysA) {
790
- if (!objB.hasOwnProperty(key) || objA[key] !== objB[key]) {
791
- return false;
792
- }
793
- }
794
- return true;
795
- }
796
803
  const distinctUntilStateChanged = (stream) => stream.pipe(
797
804
  distinctUntilChanged(
798
805
  ({ data: prevData, ...prev }, { data: currData, ...curr }) => shallowEqual(prev, curr) && shallowEqual(prevData, currData)
@@ -1954,12 +1961,17 @@ const executeMutation = ({
1954
1961
  const isPaused = state.isPaused;
1955
1962
  const defaultFn = async () => await Promise.reject(new Error("No mutationFn found"));
1956
1963
  const mutationFn = options.mutationFn ?? defaultFn;
1957
- const contextFromOnMutate$ = makeObservable(
1958
- // eslint-disable-next-line @typescript-eslint/promise-function-async
1959
- () => {
1960
- var _a;
1961
- return ((_a = options.onMutate) == null ? void 0 : _a.call(options, variables)) ?? void 0;
1962
- }
1964
+ const onMutateFactory = () => {
1965
+ var _a;
1966
+ return ((_a = options.onMutate) == null ? void 0 : _a.call(options, variables)) ?? void 0;
1967
+ };
1968
+ const contextFromOnMutate$ = makeObservable(onMutateFactory);
1969
+ contextFromOnMutate$.pipe(
1970
+ tap((context) => {
1971
+ if (context === void 0) {
1972
+ throw new Error("onMutate returned undefined");
1973
+ }
1974
+ })
1963
1975
  );
1964
1976
  const rawContext$ = of(state.context);
1965
1977
  const context$ = iif(() => isPaused, rawContext$, contextFromOnMutate$).pipe(
@@ -1987,10 +1999,7 @@ const executeMutation = ({
1987
1999
  };
1988
2000
  const queryRunner$ = context$.pipe(
1989
2001
  switchMap((context) => {
1990
- const fn$ = typeof mutationFn === "function" ? (
1991
- // eslint-disable-next-line @typescript-eslint/promise-function-async
1992
- makeObservable(() => mutationFn(variables))
1993
- ) : mutationFn;
2002
+ const fn$ = typeof mutationFn === "function" ? makeObservable(() => mutationFn(variables)) : mutationFn;
1994
2003
  const sharedFn$ = fn$.pipe(share());
1995
2004
  const completeWithoutValue$ = sharedFn$.pipe(
1996
2005
  isEmpty(),
@@ -2167,6 +2176,7 @@ class Mutation {
2167
2176
  return (_b = (_a = mutationCache.config).onMutate) == null ? void 0 : _b.call(
2168
2177
  _a,
2169
2178
  variables2,
2179
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
2170
2180
  this
2171
2181
  );
2172
2182
  }
@@ -2190,6 +2200,7 @@ class Mutation {
2190
2200
  error,
2191
2201
  variables2,
2192
2202
  context,
2203
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
2193
2204
  this
2194
2205
  );
2195
2206
  }
@@ -2212,6 +2223,7 @@ class Mutation {
2212
2223
  error,
2213
2224
  variables2,
2214
2225
  context,
2226
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
2215
2227
  this
2216
2228
  );
2217
2229
  }
@@ -2233,6 +2245,7 @@ class Mutation {
2233
2245
  data,
2234
2246
  variables2,
2235
2247
  context,
2248
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
2236
2249
  this
2237
2250
  );
2238
2251
  }
@@ -3,6 +3,7 @@ import { Observable, BehaviorSubject } from 'rxjs';
3
3
  interface Option<R = undefined> {
4
4
  defaultValue: R;
5
5
  unsubscribeOnUnmount?: boolean;
6
+ compareFn?: (a: R, b: R) => boolean;
6
7
  }
7
8
  export declare function useObserve<T>(source: BehaviorSubject<T>): T;
8
9
  export declare function useObserve<T>(source: Observable<T>): T | undefined;
@@ -1,6 +1,20 @@
1
1
  import { Observable } from 'rxjs';
2
- export declare function makeObservable<Data>(fn: () => Observable<Data> | Data | Promise<Data>): Observable<Data>;
3
- export declare function makeObservable<Data>(fn: () => Data): Data extends Observable<infer ObservedData> ? Observable<ObservedData> : Data extends Promise<infer ThenData> ? Observable<ThenData> : Observable<Data>;
4
- export declare function makeObservable<Data>(fn: Data): Observable<Data>;
5
- export declare function makeObservable<Data>(fn: Promise<Data>): Observable<Data>;
2
+ type FnReturnToObservable<T> = T extends Observable<infer ObservedData> ? ObservedData : T extends Promise<infer ThenData> ? ThenData : T;
6
3
  export declare function makeObservable<Data>(fn: Observable<Data>): Observable<Data>;
4
+ export declare function makeObservable<Data>(fn: Promise<Data>): Observable<Data>;
5
+ export declare function makeObservable<Data>(fn: Promise<Data> | Observable<Data>): Observable<Data>;
6
+ export declare function makeObservable<Data>(fn: () => Promise<Data> | Observable<Data>): Observable<Data>;
7
+ /**
8
+ * Generic factory
9
+ */
10
+ export declare function makeObservable<TContext>(fn: () => Promise<TContext | undefined> | Observable<TContext | undefined> | TContext | undefined): Observable<undefined | TContext>;
11
+ /**
12
+ * Generic factory
13
+ */
14
+ export declare function makeObservable<Return>(fn: () => Return): Observable<FnReturnToObservable<Return>>;
15
+ /**
16
+ * Generic factory OR Observable
17
+ */
18
+ export declare function makeObservable<Data, Return>(fn: Observable<Data> | (() => Return)): Observable<Data | FnReturnToObservable<Return>>;
19
+ export declare function makeObservable<Data>(fn: Data): Observable<Data>;
20
+ export {};
@@ -3,6 +3,9 @@ import { Adapter } from '../persistance/adapters/Adapter';
3
3
  /**
4
4
  * Make sure to pass stable reference of entries and adapter if you don't
5
5
  * intentionally want to start over the process.
6
+ *
7
+ * `isHydrated` will be `true` after the first successful hydration. This value
8
+ * will be reset as soon as the adapter reference changes.
6
9
  */
7
10
  export declare function usePersistSignals({ entries, onHydrated, adapter }: {
8
11
  /**
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "reactjrx",
3
3
  "private": false,
4
- "version": "1.101.0",
4
+ "version": "1.101.1",
5
5
  "type": "module",
6
6
  "files": [
7
7
  "dist"
@@ -61,7 +61,7 @@
61
61
  "rollup-plugin-node-externals": "^7.0.1",
62
62
  "rxjs": "^7.8.0",
63
63
  "semantic-release": "^24.1.1",
64
- "typescript": "5.6.2",
64
+ "typescript": "^5.6.2",
65
65
  "vite": "^5.1.3",
66
66
  "vite-plugin-dts": "^4.2.1",
67
67
  "vitest": "^1.3.0"