@spoosh/react 0.15.2 → 0.15.4

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.js CHANGED
@@ -688,6 +688,7 @@ function createUseSubscription(options) {
688
688
  });
689
689
  const controllerRef = (0, import_react5.useRef)(null);
690
690
  const subscriptionVersionRef = (0, import_react5.useRef)(0);
691
+ const prevQueryKeyRef = (0, import_react5.useRef)(queryKey);
691
692
  const queryKeyChanged = controllerRef.current && controllerRef.current.queryKey !== queryKey;
692
693
  if (!controllerRef.current || queryKeyChanged) {
693
694
  const controller2 = (0, import_core5.createSubscriptionController)({
@@ -716,14 +717,18 @@ function createUseSubscription(options) {
716
717
  const state = (0, import_react5.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
717
718
  const [isPending, setIsPending] = (0, import_react5.useState)(enabled);
718
719
  (0, import_react5.useEffect)(() => {
720
+ const queryKeyChanged2 = prevQueryKeyRef.current !== queryKey;
721
+ prevQueryKeyRef.current = queryKey;
719
722
  if (!enabled) {
720
723
  return;
721
724
  }
725
+ if (queryKeyChanged2) {
726
+ subscriptionVersionRef.current++;
727
+ }
722
728
  setIsPending(true);
723
729
  controller.mount();
724
730
  controller.subscribe();
725
731
  return () => {
726
- subscriptionVersionRef.current++;
727
732
  controller.unsubscribe();
728
733
  };
729
734
  }, [queryKey, enabled, controller]);
@@ -733,7 +738,6 @@ function createUseSubscription(options) {
733
738
  }
734
739
  }, [state.isConnected, state.data, state.error]);
735
740
  const disconnect = (0, import_react5.useCallback)(() => {
736
- subscriptionVersionRef.current++;
737
741
  controller.unsubscribe();
738
742
  }, [controller]);
739
743
  const trigger = (0, import_react5.useCallback)(async () => {
@@ -744,6 +748,7 @@ function createUseSubscription(options) {
744
748
  await controller.subscribe();
745
749
  }, [controller]);
746
750
  const loading = isPending;
751
+ const stateWithQueue = state;
747
752
  return {
748
753
  meta: {},
749
754
  data: state.data,
@@ -752,6 +757,8 @@ function createUseSubscription(options) {
752
757
  isConnected: state.isConnected,
753
758
  _queryKey: queryKey,
754
759
  _subscriptionVersion: subscriptionVersionRef.current,
760
+ _messageQueue: stateWithQueue._messageQueue,
761
+ _queueIndex: stateWithQueue._queueIndex ?? 0,
755
762
  trigger,
756
763
  disconnect
757
764
  };
@@ -844,72 +851,82 @@ function createUseSSE(options) {
844
851
  });
845
852
  const prevVersionRef = (0, import_react6.useRef)(subscription._subscriptionVersion);
846
853
  const lastMessageIndexRef = (0, import_react6.useRef)({});
854
+ const lastProcessedQueueIndexRef = (0, import_react6.useRef)(0);
847
855
  (0, import_react6.useEffect)(() => {
848
856
  if (subscription._subscriptionVersion !== prevVersionRef.current) {
849
857
  setAccumulatedData({});
850
858
  lastMessageIndexRef.current = {};
859
+ lastProcessedQueueIndexRef.current = 0;
851
860
  }
852
861
  prevVersionRef.current = subscription._subscriptionVersion;
853
862
  }, [subscription._subscriptionVersion]);
863
+ const subscriptionState = subscription;
864
+ const messageQueue = subscriptionState._messageQueue ?? [];
865
+ const queueIndex = subscriptionState._queueIndex ?? 0;
854
866
  (0, import_react6.useEffect)(() => {
855
- const data = subscription.data;
856
- if (!data) {
857
- return;
858
- }
859
- if (eventSet && !eventSet.has(data.event)) {
867
+ if (queueIndex <= lastProcessedQueueIndexRef.current) {
860
868
  return;
861
869
  }
862
- const parser = transport.utils.resolveParser(
863
- parseRef.current,
864
- data.event
865
- );
866
- let parsed;
867
- try {
868
- parsed = parser(data.data);
869
- } catch {
870
- parsed = data.data;
871
- }
872
- if (parsed === void 0) {
873
- return;
874
- }
875
- const accumulator = transport.utils.resolveAccumulator(
876
- accumulateRef.current,
877
- data.event
878
- );
879
- const parsedObj = parsed;
880
- const messageIndex = typeof parsedObj?.index === "number" ? parsedObj.index : void 0;
881
- if (messageIndex !== void 0) {
882
- const lastIndex = lastMessageIndexRef.current[data.event];
883
- if (lastIndex !== void 0 && messageIndex < lastIndex) {
884
- setAccumulatedData({});
885
- lastMessageIndexRef.current = {};
870
+ const startIndex = lastProcessedQueueIndexRef.current;
871
+ const messagesToProcess = messageQueue.slice(startIndex);
872
+ lastProcessedQueueIndexRef.current = queueIndex;
873
+ for (const data of messagesToProcess) {
874
+ if (!data) continue;
875
+ if (eventSet && !eventSet.has(data.event)) {
876
+ continue;
886
877
  }
887
- lastMessageIndexRef.current[data.event] = messageIndex;
888
- }
889
- setAccumulatedData((prev) => {
890
- const previousEventData = prev[data.event];
891
- let newEventData;
878
+ const parser = transport.utils.resolveParser(
879
+ parseRef.current,
880
+ data.event
881
+ );
882
+ let parsed;
892
883
  try {
893
- newEventData = accumulator(previousEventData, parsed);
884
+ parsed = parser(data.data);
894
885
  } catch {
895
- newEventData = parsed;
886
+ parsed = data.data;
896
887
  }
897
- const newAccumulated = {
898
- ...prev,
899
- [data.event]: newEventData
900
- };
901
- eventEmitter?.emit(
902
- "spoosh:subscription:accumulate",
903
- {
904
- queryKey: subscription._queryKey,
905
- eventType: data.event,
906
- accumulatedData: newAccumulated,
907
- timestamp: Date.now()
908
- }
888
+ if (parsed === void 0) {
889
+ continue;
890
+ }
891
+ const accumulator = transport.utils.resolveAccumulator(
892
+ accumulateRef.current,
893
+ data.event
909
894
  );
910
- return newAccumulated;
911
- });
912
- }, [subscription.data, subscription._queryKey, eventSet]);
895
+ const parsedObj = parsed;
896
+ const messageIndex = typeof parsedObj?.index === "number" ? parsedObj.index : void 0;
897
+ if (messageIndex !== void 0) {
898
+ const lastIndex = lastMessageIndexRef.current[data.event];
899
+ if (lastIndex !== void 0 && messageIndex < lastIndex) {
900
+ setAccumulatedData({});
901
+ lastMessageIndexRef.current = {};
902
+ }
903
+ lastMessageIndexRef.current[data.event] = messageIndex;
904
+ }
905
+ setAccumulatedData((prev) => {
906
+ const previousEventData = prev[data.event];
907
+ let newEventData;
908
+ try {
909
+ newEventData = accumulator(previousEventData, parsed);
910
+ } catch {
911
+ newEventData = parsed;
912
+ }
913
+ const newAccumulated = {
914
+ ...prev,
915
+ [data.event]: newEventData
916
+ };
917
+ eventEmitter?.emit(
918
+ "spoosh:subscription:accumulate",
919
+ {
920
+ queryKey: subscription._queryKey,
921
+ eventType: data.event,
922
+ accumulatedData: newAccumulated,
923
+ timestamp: Date.now()
924
+ }
925
+ );
926
+ return newAccumulated;
927
+ });
928
+ }
929
+ }, [queueIndex, subscription._queryKey, eventSet]);
913
930
  const reset = (0, import_react6.useCallback)(() => {
914
931
  setAccumulatedData({});
915
932
  }, []);
package/dist/index.mjs CHANGED
@@ -712,6 +712,7 @@ function createUseSubscription(options) {
712
712
  });
713
713
  const controllerRef = useRef5(null);
714
714
  const subscriptionVersionRef = useRef5(0);
715
+ const prevQueryKeyRef = useRef5(queryKey);
715
716
  const queryKeyChanged = controllerRef.current && controllerRef.current.queryKey !== queryKey;
716
717
  if (!controllerRef.current || queryKeyChanged) {
717
718
  const controller2 = createSubscriptionController({
@@ -740,14 +741,18 @@ function createUseSubscription(options) {
740
741
  const state = useSyncExternalStore5(subscribe, getSnapshot, getSnapshot);
741
742
  const [isPending, setIsPending] = useState4(enabled);
742
743
  useEffect4(() => {
744
+ const queryKeyChanged2 = prevQueryKeyRef.current !== queryKey;
745
+ prevQueryKeyRef.current = queryKey;
743
746
  if (!enabled) {
744
747
  return;
745
748
  }
749
+ if (queryKeyChanged2) {
750
+ subscriptionVersionRef.current++;
751
+ }
746
752
  setIsPending(true);
747
753
  controller.mount();
748
754
  controller.subscribe();
749
755
  return () => {
750
- subscriptionVersionRef.current++;
751
756
  controller.unsubscribe();
752
757
  };
753
758
  }, [queryKey, enabled, controller]);
@@ -757,7 +762,6 @@ function createUseSubscription(options) {
757
762
  }
758
763
  }, [state.isConnected, state.data, state.error]);
759
764
  const disconnect = useCallback4(() => {
760
- subscriptionVersionRef.current++;
761
765
  controller.unsubscribe();
762
766
  }, [controller]);
763
767
  const trigger = useCallback4(async () => {
@@ -768,6 +772,7 @@ function createUseSubscription(options) {
768
772
  await controller.subscribe();
769
773
  }, [controller]);
770
774
  const loading = isPending;
775
+ const stateWithQueue = state;
771
776
  return {
772
777
  meta: {},
773
778
  data: state.data,
@@ -776,6 +781,8 @@ function createUseSubscription(options) {
776
781
  isConnected: state.isConnected,
777
782
  _queryKey: queryKey,
778
783
  _subscriptionVersion: subscriptionVersionRef.current,
784
+ _messageQueue: stateWithQueue._messageQueue,
785
+ _queueIndex: stateWithQueue._queueIndex ?? 0,
779
786
  trigger,
780
787
  disconnect
781
788
  };
@@ -868,72 +875,82 @@ function createUseSSE(options) {
868
875
  });
869
876
  const prevVersionRef = useRef6(subscription._subscriptionVersion);
870
877
  const lastMessageIndexRef = useRef6({});
878
+ const lastProcessedQueueIndexRef = useRef6(0);
871
879
  useEffect5(() => {
872
880
  if (subscription._subscriptionVersion !== prevVersionRef.current) {
873
881
  setAccumulatedData({});
874
882
  lastMessageIndexRef.current = {};
883
+ lastProcessedQueueIndexRef.current = 0;
875
884
  }
876
885
  prevVersionRef.current = subscription._subscriptionVersion;
877
886
  }, [subscription._subscriptionVersion]);
887
+ const subscriptionState = subscription;
888
+ const messageQueue = subscriptionState._messageQueue ?? [];
889
+ const queueIndex = subscriptionState._queueIndex ?? 0;
878
890
  useEffect5(() => {
879
- const data = subscription.data;
880
- if (!data) {
881
- return;
882
- }
883
- if (eventSet && !eventSet.has(data.event)) {
891
+ if (queueIndex <= lastProcessedQueueIndexRef.current) {
884
892
  return;
885
893
  }
886
- const parser = transport.utils.resolveParser(
887
- parseRef.current,
888
- data.event
889
- );
890
- let parsed;
891
- try {
892
- parsed = parser(data.data);
893
- } catch {
894
- parsed = data.data;
895
- }
896
- if (parsed === void 0) {
897
- return;
898
- }
899
- const accumulator = transport.utils.resolveAccumulator(
900
- accumulateRef.current,
901
- data.event
902
- );
903
- const parsedObj = parsed;
904
- const messageIndex = typeof parsedObj?.index === "number" ? parsedObj.index : void 0;
905
- if (messageIndex !== void 0) {
906
- const lastIndex = lastMessageIndexRef.current[data.event];
907
- if (lastIndex !== void 0 && messageIndex < lastIndex) {
908
- setAccumulatedData({});
909
- lastMessageIndexRef.current = {};
894
+ const startIndex = lastProcessedQueueIndexRef.current;
895
+ const messagesToProcess = messageQueue.slice(startIndex);
896
+ lastProcessedQueueIndexRef.current = queueIndex;
897
+ for (const data of messagesToProcess) {
898
+ if (!data) continue;
899
+ if (eventSet && !eventSet.has(data.event)) {
900
+ continue;
910
901
  }
911
- lastMessageIndexRef.current[data.event] = messageIndex;
912
- }
913
- setAccumulatedData((prev) => {
914
- const previousEventData = prev[data.event];
915
- let newEventData;
902
+ const parser = transport.utils.resolveParser(
903
+ parseRef.current,
904
+ data.event
905
+ );
906
+ let parsed;
916
907
  try {
917
- newEventData = accumulator(previousEventData, parsed);
908
+ parsed = parser(data.data);
918
909
  } catch {
919
- newEventData = parsed;
910
+ parsed = data.data;
920
911
  }
921
- const newAccumulated = {
922
- ...prev,
923
- [data.event]: newEventData
924
- };
925
- eventEmitter?.emit(
926
- "spoosh:subscription:accumulate",
927
- {
928
- queryKey: subscription._queryKey,
929
- eventType: data.event,
930
- accumulatedData: newAccumulated,
931
- timestamp: Date.now()
932
- }
912
+ if (parsed === void 0) {
913
+ continue;
914
+ }
915
+ const accumulator = transport.utils.resolveAccumulator(
916
+ accumulateRef.current,
917
+ data.event
933
918
  );
934
- return newAccumulated;
935
- });
936
- }, [subscription.data, subscription._queryKey, eventSet]);
919
+ const parsedObj = parsed;
920
+ const messageIndex = typeof parsedObj?.index === "number" ? parsedObj.index : void 0;
921
+ if (messageIndex !== void 0) {
922
+ const lastIndex = lastMessageIndexRef.current[data.event];
923
+ if (lastIndex !== void 0 && messageIndex < lastIndex) {
924
+ setAccumulatedData({});
925
+ lastMessageIndexRef.current = {};
926
+ }
927
+ lastMessageIndexRef.current[data.event] = messageIndex;
928
+ }
929
+ setAccumulatedData((prev) => {
930
+ const previousEventData = prev[data.event];
931
+ let newEventData;
932
+ try {
933
+ newEventData = accumulator(previousEventData, parsed);
934
+ } catch {
935
+ newEventData = parsed;
936
+ }
937
+ const newAccumulated = {
938
+ ...prev,
939
+ [data.event]: newEventData
940
+ };
941
+ eventEmitter?.emit(
942
+ "spoosh:subscription:accumulate",
943
+ {
944
+ queryKey: subscription._queryKey,
945
+ eventType: data.event,
946
+ accumulatedData: newAccumulated,
947
+ timestamp: Date.now()
948
+ }
949
+ );
950
+ return newAccumulated;
951
+ });
952
+ }
953
+ }, [queueIndex, subscription._queryKey, eventSet]);
937
954
  const reset = useCallback5(() => {
938
955
  setAccumulatedData({});
939
956
  }, []);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spoosh/react",
3
- "version": "0.15.2",
3
+ "version": "0.15.4",
4
4
  "license": "MIT",
5
5
  "description": "React hooks for Spoosh API toolkit",
6
6
  "keywords": [
@@ -34,7 +34,7 @@
34
34
  }
35
35
  },
36
36
  "peerDependencies": {
37
- "@spoosh/core": ">=0.18.2",
37
+ "@spoosh/core": ">=0.18.3",
38
38
  "@spoosh/transport-sse": ">=0.1.0",
39
39
  "react": "^18 || ^19"
40
40
  },
@@ -46,7 +46,7 @@
46
46
  "devDependencies": {
47
47
  "@testing-library/react": "^16.0.0",
48
48
  "jsdom": "^26.0.0",
49
- "@spoosh/core": "0.18.2",
49
+ "@spoosh/core": "0.18.3",
50
50
  "@spoosh/transport-sse": "0.1.2",
51
51
  "@spoosh/test-utils": "0.3.0"
52
52
  },