reactjrx 1.40.1 → 1.44.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
@@ -472,7 +472,9 @@ const mergeResults = (stream$) => stream$.pipe(
472
472
  status: "loading"
473
473
  }
474
474
  ),
475
- rxjs.distinctUntilChanged(shallowEqual)
475
+ rxjs.distinctUntilChanged(
476
+ ({ data: prevData, ...prev }, { data: currData, ...curr }) => shallowEqual(prev, curr) && shallowEqual(prevData, currData)
477
+ )
476
478
  );
477
479
  function useAsyncQuery(query, mapOperatorOrOptions, options = {}) {
478
480
  const queryRef = useLiveRef(query);
@@ -597,27 +599,35 @@ function useAsyncQuery(query, mapOperatorOrOptions, options = {}) {
597
599
  const Context = react.createContext({
598
600
  client: null
599
601
  });
602
+ const ClientEffect = ({
603
+ client
604
+ }) => {
605
+ react.useEffect(() => {
606
+ const destroy = client.start();
607
+ return () => {
608
+ destroy();
609
+ };
610
+ }, [client]);
611
+ return null;
612
+ };
600
613
  const Provider = react.memo(
601
614
  ({
602
615
  children,
603
616
  client
604
617
  }) => {
605
618
  const value = react.useMemo(() => ({ client }), [client]);
606
- react.useEffect(
607
- () => () => {
608
- client.destroy();
609
- },
610
- [client]
611
- );
612
- return /* @__PURE__ */ jsxRuntime.jsx(Context.Provider, { value, children });
619
+ return /* @__PURE__ */ jsxRuntime.jsxs(Context.Provider, { value, children: [
620
+ /* @__PURE__ */ jsxRuntime.jsx(ClientEffect, { client: value.client }),
621
+ children
622
+ ] });
613
623
  }
614
624
  );
615
- const useReactJrxProvider = () => {
625
+ const useQueryClient = () => {
616
626
  const context = react.useContext(Context);
617
627
  if (context === null) {
618
628
  throw new Error("You forgot to register the provider");
619
629
  }
620
- return { ...context };
630
+ return context.client;
621
631
  };
622
632
  const arrayEqual = (a, b) => a.length === b.length && a.every((v, i) => v === b[i]);
623
633
  function isDefined(arg) {
@@ -630,10 +640,16 @@ const createActivityTrigger = (params$) => {
630
640
  return shouldRunTrigger !== false ? rxjs.merge(
631
641
  rxjs.fromEvent(document, "visibilitychange").pipe(
632
642
  rxjs.filter(() => !document.hidden),
633
- rxjs.map(() => ({ ignoreStale: shouldRunTrigger === "always" }))
643
+ rxjs.map(() => ({
644
+ type: "refetch",
645
+ ignoreStale: shouldRunTrigger === "always"
646
+ }))
634
647
  ),
635
648
  rxjs.fromEvent(window, "focus").pipe(
636
- rxjs.map(() => ({ ignoreStale: shouldRunTrigger === "always" }))
649
+ rxjs.map(() => ({
650
+ type: "refetch",
651
+ ignoreStale: shouldRunTrigger === "always"
652
+ }))
637
653
  )
638
654
  ) : rxjs.EMPTY;
639
655
  })
@@ -644,7 +660,10 @@ const createNetworkTrigger = (params$) => {
644
660
  rxjs.switchMap(({ options: { refetchOnReconnect = true } }) => {
645
661
  const shouldRunTrigger = typeof refetchOnReconnect === "function" ? refetchOnReconnect({}) : refetchOnReconnect;
646
662
  return shouldRunTrigger !== false ? rxjs.fromEvent(window, "online").pipe(
647
- rxjs.map(() => ({ ignoreStale: shouldRunTrigger === "always" }))
663
+ rxjs.map(() => ({
664
+ type: "refetch",
665
+ ignoreStale: shouldRunTrigger === "always"
666
+ }))
648
667
  ) : rxjs.EMPTY;
649
668
  })
650
669
  );
@@ -677,7 +696,7 @@ function useQuery({
677
696
  ...options
678
697
  }) {
679
698
  const internalRefresh$ = useSubject();
680
- const { client } = useReactJrxProvider();
699
+ const client = useQueryClient();
681
700
  const params$ = useQueryParams({ queryFn, queryKey, ...options });
682
701
  const result = useObserve(
683
702
  () => {
@@ -706,18 +725,18 @@ function useQuery({
706
725
  newKeyTrigger$,
707
726
  newObservableObjectQuery$
708
727
  );
709
- const refetch$ = rxjs.merge(
710
- internalRefresh$.current.pipe(rxjs.map(() => ({ ignoreStale: true }))),
728
+ const trigger$ = rxjs.merge(
729
+ internalRefresh$.current,
711
730
  rxjs.merge(activityRefetch$, networkRefetch$).pipe(rxjs.throttleTime(500))
712
731
  );
713
732
  return newQueryTrigger$.pipe(
714
733
  rxjs.withLatestFrom(key$),
715
734
  rxjs.switchMap(([, key]) => {
716
- const { result$ } = client.query$({
735
+ const { result$ } = client.query({
717
736
  key,
718
737
  fn$,
719
738
  options$,
720
- refetch$
739
+ trigger$
721
740
  });
722
741
  return result$.pipe(
723
742
  rxjs.scan(
@@ -754,7 +773,7 @@ function useQuery({
754
773
  [client]
755
774
  );
756
775
  const refetch = react.useCallback(() => {
757
- internalRefresh$.current.next();
776
+ internalRefresh$.current.next({ type: "refetch", ignoreStale: true });
758
777
  }, [client]);
759
778
  return { ...result, refetch };
760
779
  }
@@ -855,7 +874,7 @@ function createLogger(env) {
855
874
  };
856
875
  return _logger;
857
876
  }
858
- const Logger = createLogger("development");
877
+ const Logger = createLogger("production");
859
878
  const logger$3 = Logger.namespace("store");
860
879
  const createDebugger = (store$) => {
861
880
  return store$.pipe(
@@ -936,7 +955,12 @@ const createQueryStore = () => {
936
955
  }));
937
956
  };
938
957
  };
939
- const debugger$ = createDebugger(store$);
958
+ const start = () => {
959
+ const debugger$ = createDebugger(store$);
960
+ return () => {
961
+ debugger$.unsubscribe();
962
+ };
963
+ };
940
964
  return {
941
965
  set: setValue,
942
966
  get: getValue,
@@ -956,15 +980,10 @@ const createQueryStore = () => {
956
980
  queryTriggerSubject.next(event);
957
981
  },
958
982
  size: () => store.size,
959
- destroy: () => {
960
- debugger$.unsubscribe();
961
- queryEventSubject.complete();
962
- queryTriggerSubject.complete();
963
- }
983
+ start
964
984
  };
965
985
  };
966
986
  const createQueryTrigger = ({
967
- refetch$,
968
987
  options$,
969
988
  queryStore,
970
989
  key
@@ -982,12 +1001,6 @@ const createQueryTrigger = ({
982
1001
  rxjs.filter((event) => key === event.key),
983
1002
  rxjs.map(({ trigger: trigger2 }) => trigger2)
984
1003
  ),
985
- refetch$.pipe(
986
- rxjs.map((event) => ({
987
- ...event,
988
- type: "refetch"
989
- }))
990
- ),
991
1004
  enabledTrigger$.pipe(
992
1005
  rxjs.map(() => ({
993
1006
  type: "enabled",
@@ -1002,12 +1015,18 @@ const deduplicate = (key, queryStore) => (source) => {
1002
1015
  return rxjs.defer(() => {
1003
1016
  var _a;
1004
1017
  const sourceFromStore = (_a = queryStore.get(key)) == null ? void 0 : _a.deduplication_fn;
1018
+ if (sourceFromStore)
1019
+ return sourceFromStore;
1020
+ let sourceToDeduplicate;
1005
1021
  const deleteFromStore = () => {
1006
- queryStore.update(key, {
1007
- deduplication_fn: void 0
1008
- });
1022
+ var _a2;
1023
+ if (((_a2 = queryStore.get(key)) == null ? void 0 : _a2.deduplication_fn) === sourceToDeduplicate) {
1024
+ queryStore.update(key, {
1025
+ deduplication_fn: void 0
1026
+ });
1027
+ }
1009
1028
  };
1010
- const finalSource = sourceFromStore ?? source.pipe(
1029
+ sourceToDeduplicate = source.pipe(
1011
1030
  /**
1012
1031
  * Ideally we would want to remove the query from the store only on finalize,
1013
1032
  * which means whenever the query complete or error. Unfortunately finalize is
@@ -1027,12 +1046,10 @@ const deduplicate = (key, queryStore) => (source) => {
1027
1046
  bufferSize: 1
1028
1047
  })
1029
1048
  );
1030
- if (!sourceFromStore) {
1031
- queryStore.update(key, {
1032
- deduplication_fn: finalSource
1033
- });
1034
- }
1035
- return finalSource;
1049
+ queryStore.update(key, {
1050
+ deduplication_fn: sourceToDeduplicate
1051
+ });
1052
+ return sourceToDeduplicate;
1036
1053
  });
1037
1054
  };
1038
1055
  const notifyQueryResult = (options$) => (stream$) => stream$.pipe(
@@ -1156,8 +1173,9 @@ const createQueryFetch = ({
1156
1173
  const query = queryStore.get(serializedKey);
1157
1174
  const cacheResult = query == null ? void 0 : query.cache_fnResult;
1158
1175
  const hasCache = !!cacheResult;
1176
+ const ignoreStale = trigger2.type === "refetch" && trigger2.ignoreStale;
1159
1177
  if (hasCache) {
1160
- if (!(query == null ? void 0 : query.isStale) && !trigger2.ignoreStale) {
1178
+ if (!(query == null ? void 0 : query.isStale) && !ignoreStale) {
1161
1179
  return rxjs.of({
1162
1180
  fetchStatus: "idle",
1163
1181
  status: "success",
@@ -1185,6 +1203,12 @@ const compareKeys = (keyA, keyB, { exact = false } = {}) => {
1185
1203
  return keyA.reduce((acc, value, index) => {
1186
1204
  if (!acc)
1187
1205
  return false;
1206
+ if (value === void 0) {
1207
+ const hasNextItemInLineNotUndefined = keyA.slice(index, keyA.length - 1).some((item) => item !== void 0);
1208
+ if (!hasNextItemInLineNotUndefined) {
1209
+ return true;
1210
+ }
1211
+ }
1188
1212
  return serializeObject(value) === serializeObject(keyB[index]);
1189
1213
  }, true);
1190
1214
  };
@@ -1221,6 +1245,9 @@ const createInvalidationClient = ({
1221
1245
  keysToRefetch = Array.from(queryStore.keys());
1222
1246
  }
1223
1247
  keysToRefetch.forEach((key) => {
1248
+ queryStore.update(key, {
1249
+ deduplication_fn: void 0
1250
+ });
1224
1251
  queryStore.dispatchQueryTrigger({
1225
1252
  key,
1226
1253
  trigger: { ignoreStale: true, type: "refetch" }
@@ -1228,15 +1255,10 @@ const createInvalidationClient = ({
1228
1255
  });
1229
1256
  };
1230
1257
  return {
1231
- invalidateQueries,
1232
- destroy: () => {
1233
- }
1258
+ invalidateQueries
1234
1259
  };
1235
1260
  };
1236
- const logger$1 = Logger.namespace("refetch");
1237
- const createRefetchClient = ({
1238
- queryStore
1239
- }) => {
1261
+ const createRefetchClient = (_) => {
1240
1262
  const pipeQueryResult = ({
1241
1263
  options$
1242
1264
  }) => (stream) => {
@@ -1266,28 +1288,11 @@ const createRefetchClient = ({
1266
1288
  )
1267
1289
  );
1268
1290
  };
1269
- const pipeQueryTrigger = ({
1270
- key
1271
- }) => (stream) => {
1272
- return rxjs.merge(
1273
- stream.pipe(
1274
- rxjs.tap(({ ignoreStale }) => {
1275
- const query = queryStore.get(key);
1276
- if (query && ignoreStale && !query.isStale) {
1277
- logger$1.log(key, "marked stale by trigger!");
1278
- queryStore.update(key, {
1279
- isStale: true
1280
- });
1281
- }
1282
- })
1283
- )
1284
- );
1291
+ const refetchQueries = (_2) => {
1285
1292
  };
1286
1293
  return {
1287
1294
  pipeQueryResult,
1288
- pipeQueryTrigger,
1289
- destroy: () => {
1290
- }
1295
+ refetchQueries
1291
1296
  };
1292
1297
  };
1293
1298
  const difference = (a, b) => a.filter((element) => !b.includes(element));
@@ -1453,30 +1458,33 @@ const getInitialQueryEntity = ({ key }) => ({
1453
1458
  queryKey: key,
1454
1459
  runners: []
1455
1460
  });
1456
- const updateStoreWithQuery = ({
1461
+ const updateStoreWithNewQuery = ({
1457
1462
  queryStore,
1458
1463
  serializedKey,
1459
1464
  runner$,
1465
+ options$,
1460
1466
  key
1461
1467
  }) => (stream) => stream.pipe(
1462
- rxjs.map((value) => {
1468
+ rxjs.withLatestFrom(options$),
1469
+ rxjs.map(([trigger2, options]) => {
1463
1470
  if (key.length === 0)
1464
- return [value, () => {
1465
- }];
1471
+ return [trigger2, void 0];
1472
+ if (trigger2.type !== "initial")
1473
+ return [trigger2, void 0];
1466
1474
  if (!queryStore.get(serializedKey)) {
1467
1475
  queryStore.set(serializedKey, getInitialQueryEntity({ key }));
1468
1476
  } else {
1469
1477
  queryStore.update(serializedKey, {
1470
1478
  queryKey: key,
1471
- ...value.options.markStale && {
1479
+ ...options.markStale && {
1472
1480
  isStale: true
1473
1481
  }
1474
1482
  });
1475
1483
  }
1476
- return [value, queryStore.addRunner(serializedKey, runner$)];
1484
+ return [trigger2, queryStore.addRunner(serializedKey, runner$)];
1477
1485
  })
1478
1486
  );
1479
- const logger = Logger.namespace("cache");
1487
+ const logger$1 = Logger.namespace("cache");
1480
1488
  const createCacheClient = ({
1481
1489
  queryStore
1482
1490
  }) => {
@@ -1487,7 +1495,7 @@ const createCacheClient = ({
1487
1495
  const serializedKey = serializeKey(queryKey);
1488
1496
  if (queryKey.length === 0)
1489
1497
  return;
1490
- logger.log("set cache for query", serializeKey);
1498
+ logger$1.log("set cache for query", serializeKey);
1491
1499
  if (!queryStore.get(serializedKey)) {
1492
1500
  queryStore.set(serializedKey, getInitialQueryEntity({ key: queryKey }));
1493
1501
  }
@@ -1520,47 +1528,107 @@ const createCacheClient = ({
1520
1528
  setQueryData
1521
1529
  };
1522
1530
  };
1531
+ const logger = Logger.namespace("refetch");
1532
+ const markQueryAsStaleIfRefetch = ({
1533
+ key,
1534
+ serializedKey,
1535
+ queryStore
1536
+ }) => (stream) => {
1537
+ return stream.pipe(
1538
+ rxjs.tap((trigger2) => {
1539
+ if (trigger2.type !== "refetch")
1540
+ return;
1541
+ const query = queryStore.get(serializedKey);
1542
+ if (query && trigger2.ignoreStale && !query.isStale) {
1543
+ logger.log(key, "marked stale by trigger!");
1544
+ queryStore.update(serializedKey, {
1545
+ isStale: true
1546
+ });
1547
+ }
1548
+ })
1549
+ );
1550
+ };
1551
+ const dispatchExternalRefetchToAllQueries = ({
1552
+ queryStore,
1553
+ serializedKey
1554
+ }) => (stream) => stream.pipe(
1555
+ rxjs.tap((trigger2) => {
1556
+ if (trigger2.type === "refetch") {
1557
+ queryStore.update(serializedKey, {
1558
+ deduplication_fn: void 0
1559
+ });
1560
+ queryStore.dispatchQueryTrigger({
1561
+ key: serializedKey,
1562
+ trigger: trigger2
1563
+ });
1564
+ }
1565
+ }),
1566
+ rxjs.filter((trigger2) => trigger2.type !== "refetch")
1567
+ );
1523
1568
  const createClient = () => {
1524
1569
  const queryStore = createQueryStore();
1525
1570
  const invalidationClient = createInvalidationClient({ queryStore });
1526
1571
  const cacheClient = createCacheClient({ queryStore });
1527
- const refetchClient = createRefetchClient({ queryStore });
1528
- const query$ = ({
1572
+ const refetchClient = createRefetchClient();
1573
+ let hasCalledStart = false;
1574
+ const query = ({
1529
1575
  key,
1530
1576
  fn$: maybeFn$,
1531
1577
  fn: maybeFn,
1532
- refetch$ = new rxjs.Subject(),
1578
+ trigger$: externalTrigger$ = new rxjs.Subject(),
1533
1579
  options$ = new rxjs.BehaviorSubject({})
1534
1580
  }) => {
1581
+ if (!hasCalledStart) {
1582
+ throw new Error("You forgot to start client");
1583
+ }
1535
1584
  const serializedKey = serializeKey(key);
1536
- const internalRefetch$ = new rxjs.Subject();
1537
1585
  const fn$ = maybeFn$ ?? (maybeFn ? rxjs.of(maybeFn) : rxjs.NEVER);
1538
- Logger.log("query$()", serializedKey);
1586
+ Logger.log("query$)", serializedKey);
1539
1587
  const runner$ = options$.pipe(rxjs.map((options) => ({ options })));
1540
1588
  let deleteRunner = () => {
1541
1589
  };
1542
- const initialTrigger$ = rxjs.of({
1543
- type: "initial",
1544
- ignoreStale: false
1545
- });
1546
- const trigger$ = createQueryTrigger({
1547
- options$,
1548
- refetch$: rxjs.merge(refetch$, internalRefetch$),
1549
- key: serializedKey,
1550
- queryStore
1551
- }).pipe(refetchClient.pipeQueryTrigger({ options$, key: serializedKey }));
1552
- const result$ = rxjs.merge(initialTrigger$, trigger$).pipe(
1553
- rxjs.withLatestFrom(fn$, options$),
1554
- rxjs.map(([trigger2, fn, options]) => ({ trigger: trigger2, fn, options })),
1555
- updateStoreWithQuery({
1590
+ const trigger$ = rxjs.merge(
1591
+ externalTrigger$.pipe(
1592
+ dispatchExternalRefetchToAllQueries({
1593
+ queryStore,
1594
+ serializedKey
1595
+ })
1596
+ ),
1597
+ createQueryTrigger({
1598
+ options$,
1599
+ key: serializedKey,
1600
+ queryStore
1601
+ })
1602
+ ).pipe(rxjs.share());
1603
+ const result$ = rxjs.merge(
1604
+ rxjs.of({
1605
+ type: "initial"
1606
+ }),
1607
+ trigger$
1608
+ ).pipe(
1609
+ updateStoreWithNewQuery({
1556
1610
  key,
1557
1611
  queryStore,
1558
1612
  runner$,
1559
- serializedKey
1613
+ serializedKey,
1614
+ options$
1560
1615
  }),
1561
1616
  rxjs.map(([value, deleteRunnerFn]) => {
1562
- deleteRunner = deleteRunnerFn;
1563
- Logger.log("reactjrx", serializedKey, "query trigger", {
1617
+ if (deleteRunnerFn) {
1618
+ deleteRunner = deleteRunnerFn;
1619
+ }
1620
+ return value;
1621
+ }),
1622
+ markQueryAsStaleIfRefetch({
1623
+ key,
1624
+ options$,
1625
+ queryStore,
1626
+ serializedKey
1627
+ }),
1628
+ rxjs.withLatestFrom(fn$, options$),
1629
+ rxjs.map(([trigger2, fn, options]) => ({ trigger: trigger2, fn, options })),
1630
+ rxjs.map((value) => {
1631
+ Logger.log(serializedKey, "query trigger", {
1564
1632
  trigger: value.trigger,
1565
1633
  options: value.options
1566
1634
  });
@@ -1578,19 +1646,6 @@ const createClient = () => {
1578
1646
  trigger$
1579
1647
  })
1580
1648
  ),
1581
- // hooks
1582
- rxjs.switchMap(
1583
- (result) => rxjs.merge(
1584
- rxjs.of(result).pipe(
1585
- refetchClient.pipeQueryResult({
1586
- key: serializedKey,
1587
- queryStore,
1588
- options$,
1589
- refetch$: internalRefetch$
1590
- })
1591
- )
1592
- )
1593
- ),
1594
1649
  mergeResults,
1595
1650
  rxjs.withLatestFrom(options$),
1596
1651
  rxjs.takeWhile(([result, options]) => {
@@ -1606,7 +1661,7 @@ const createClient = () => {
1606
1661
  result$
1607
1662
  };
1608
1663
  };
1609
- const queryListenerSub = createQueryListener(
1664
+ const queryListener$ = createQueryListener(
1610
1665
  queryStore,
1611
1666
  (stream) => stream.pipe(
1612
1667
  rxjs.switchMap((key) => {
@@ -1624,17 +1679,25 @@ const createClient = () => {
1624
1679
  );
1625
1680
  })
1626
1681
  )
1627
- ).subscribe();
1682
+ );
1683
+ const start = () => {
1684
+ hasCalledStart = true;
1685
+ const queryListenerSub = queryListener$.subscribe();
1686
+ const started = [queryStore.start()];
1687
+ return () => {
1688
+ started.forEach((destroy) => {
1689
+ destroy();
1690
+ });
1691
+ queryListenerSub.unsubscribe();
1692
+ };
1693
+ };
1628
1694
  return {
1629
- query$,
1695
+ start,
1696
+ query,
1630
1697
  queryStore,
1631
1698
  ...invalidationClient,
1632
1699
  ...cacheClient,
1633
- ...refetchClient,
1634
- destroy: () => {
1635
- queryStore.destroy();
1636
- queryListenerSub.unsubscribe();
1637
- }
1700
+ ...refetchClient
1638
1701
  };
1639
1702
  };
1640
1703
  exports.PersistSignals = PersistSignals;
@@ -1654,7 +1717,7 @@ exports.useObserve = useObserve;
1654
1717
  exports.useObserveCallback = useObserveCallback;
1655
1718
  exports.usePersistSignalsContext = usePersistSignalsContext;
1656
1719
  exports.useQuery = useQuery;
1657
- exports.useReactJrxProvider = useReactJrxProvider;
1720
+ exports.useQueryClient = useQueryClient;
1658
1721
  exports.useScopeSignals = useScopeSignals;
1659
1722
  exports.useSetSignal = useSetSignal;
1660
1723
  exports.useSignal = useSignal;
package/dist/index.d.ts CHANGED
@@ -20,4 +20,4 @@ export * from "./lib/queries/react/useAsyncQuery";
20
20
  export * from "./lib/queries/react/useQuery";
21
21
  export * from "./lib/queries/react/useSubscribeEffect";
22
22
  export * from "./lib/queries/client/createClient";
23
- export { Provider as ReactjrxQueryProvider, useReactJrxProvider } from "./lib/queries/react/Provider";
23
+ export { Provider as ReactjrxQueryProvider, useQueryClient } from "./lib/queries/react/Provider";