@buoy-gg/react-query 1.7.8 → 2.1.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.
Files changed (38) hide show
  1. package/lib/commonjs/index.js +619 -24
  2. package/lib/commonjs/preset.js +1 -1
  3. package/lib/commonjs/react-query/components/ReactQueryDevToolsModal.js +12 -0
  4. package/lib/commonjs/react-query/components/modals/MutationBrowserModal.js +2 -1
  5. package/lib/commonjs/react-query/components/modals/QueryBrowserModal.js +8 -14
  6. package/lib/commonjs/react-query/hooks/useAllMutations.js +65 -15
  7. package/lib/commonjs/react-query/hooks/useWifiState.js +3 -3
  8. package/lib/commonjs/react-query/index.js +11 -0
  9. package/lib/commonjs/react-query/stores/index.js +48 -0
  10. package/lib/commonjs/react-query/stores/reactQueryEventStore.js +311 -0
  11. package/lib/commonjs/react-query/utils/modalStorageOperations.js +2 -2
  12. package/lib/module/index.js +113 -8
  13. package/lib/module/preset.js +2 -2
  14. package/lib/module/react-query/components/ReactQueryDevToolsModal.js +13 -1
  15. package/lib/module/react-query/components/modals/MutationBrowserModal.js +2 -1
  16. package/lib/module/react-query/components/modals/QueryBrowserModal.js +9 -15
  17. package/lib/module/react-query/hooks/useAllMutations.js +66 -16
  18. package/lib/module/react-query/hooks/useWifiState.js +4 -4
  19. package/lib/module/react-query/index.js +2 -1
  20. package/lib/module/react-query/stores/index.js +3 -0
  21. package/lib/module/react-query/stores/reactQueryEventStore.js +302 -0
  22. package/lib/module/react-query/utils/modalStorageOperations.js +3 -3
  23. package/lib/typescript/index.d.ts +61 -5
  24. package/lib/typescript/index.d.ts.map +1 -1
  25. package/lib/typescript/react-query/components/ReactQueryDevToolsModal.d.ts.map +1 -1
  26. package/lib/typescript/react-query/components/modals/MutationBrowserModal.d.ts.map +1 -1
  27. package/lib/typescript/react-query/components/modals/QueryBrowserModal.d.ts.map +1 -1
  28. package/lib/typescript/react-query/hooks/useAllMutations.d.ts +2 -2
  29. package/lib/typescript/react-query/hooks/useAllMutations.d.ts.map +1 -1
  30. package/lib/typescript/react-query/hooks/useWifiState.d.ts +1 -1
  31. package/lib/typescript/react-query/hooks/useWifiState.d.ts.map +1 -1
  32. package/lib/typescript/react-query/index.d.ts +1 -0
  33. package/lib/typescript/react-query/index.d.ts.map +1 -1
  34. package/lib/typescript/react-query/stores/index.d.ts +2 -0
  35. package/lib/typescript/react-query/stores/index.d.ts.map +1 -0
  36. package/lib/typescript/react-query/stores/reactQueryEventStore.d.ts +99 -0
  37. package/lib/typescript/react-query/stores/reactQueryEventStore.d.ts.map +1 -0
  38. package/package.json +17 -3
@@ -35,7 +35,7 @@ const EmptyComponent = () => null;
35
35
  // Save WiFi state to storage
36
36
  const saveWifiState = async enabled => {
37
37
  try {
38
- await (0, _sharedUi.safeSetItem)(_sharedUi.devToolsStorageKeys.settings.wifiEnabled(), enabled.toString());
38
+ await _sharedUi.persistentStorage.setItem(_sharedUi.devToolsStorageKeys.settings.wifiEnabled(), enabled.toString());
39
39
  } catch (error) {
40
40
  // Failed to save WiFi state
41
41
  }
@@ -5,7 +5,9 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.ReactQueryDevToolsModal = ReactQueryDevToolsModal;
7
7
  var _react = require("react");
8
+ var _reactQuery = require("@tanstack/react-query");
8
9
  var _ReactQueryModal = require("./modals/ReactQueryModal");
10
+ var _reactQueryEventStore = require("../stores/reactQueryEventStore");
9
11
  var _jsxRuntime = require("react/jsx-runtime");
10
12
  /** Configuration options for the high-level React Query dev tools modal wrapper. */
11
13
 
@@ -19,6 +21,16 @@ function ReactQueryDevToolsModal({
19
21
  onMinimize,
20
22
  enableSharedModalDimensions = true
21
23
  }) {
24
+ // Get QueryClient and connect to event store for unified Events DevTools
25
+ const queryClient = (0, _reactQuery.useQueryClient)();
26
+ (0, _react.useEffect)(() => {
27
+ // Connect the QueryClient to the event store so events flow to unified Events DevTools
28
+ // Only connect if not already connected (to preserve connection across modal open/close)
29
+ if (!_reactQueryEventStore.reactQueryEventStore.isConnected()) {
30
+ _reactQueryEventStore.reactQueryEventStore.setQueryClient(queryClient);
31
+ }
32
+ // Don't disconnect on unmount - keep the connection for unified Events DevTools
33
+ }, [queryClient]);
22
34
  const [selectedQueryKey, setSelectedQueryKey] = (0, _react.useState)(undefined);
23
35
  const [selectedMutationId, setSelectedMutationId] = (0, _react.useState)(undefined);
24
36
  const [activeFilter, setActiveFilter] = (0, _react.useState)(null);
@@ -40,7 +40,8 @@ function MutationBrowserModal({
40
40
  // Clear mutation cache handler
41
41
  const handleClearCache = (0, _react.useCallback)(() => {
42
42
  queryClient.getMutationCache().clear();
43
- }, [queryClient]);
43
+ onMutationSelect(undefined);
44
+ }, [queryClient, onMutationSelect]);
44
45
 
45
46
  // Track modal mode for conditional styling
46
47
  // Initialize with bottomSheet but it will be updated from persisted state if available
@@ -52,17 +52,11 @@ function QueryBrowserModal({
52
52
  const [ignoredPatterns, setIgnoredPatterns] = (0, _react.useState)(new Set());
53
53
  const [includedPatterns, setIncludedPatterns] = (0, _react.useState)(new Set());
54
54
 
55
- // AsyncStorage for persisting ignored patterns
56
- const {
57
- getItem: safeGetItem,
58
- setItem: safeSetItem
59
- } = (0, _sharedUi.useSafeAsyncStorage)();
60
-
61
55
  // Load ignored patterns from storage on mount
62
56
  (0, _react.useEffect)(() => {
63
57
  const loadFilters = async () => {
64
58
  try {
65
- const stored = await safeGetItem(_sharedUi.devToolsStorageKeys.reactQuery.ignoredPatterns());
59
+ const stored = await _sharedUi.persistentStorage.getItem(_sharedUi.devToolsStorageKeys.reactQuery.ignoredPatterns());
66
60
  if (stored) {
67
61
  const patterns = JSON.parse(stored);
68
62
  if (Array.isArray(patterns)) {
@@ -74,13 +68,13 @@ function QueryBrowserModal({
74
68
  }
75
69
  };
76
70
  loadFilters();
77
- }, [safeGetItem]);
71
+ }, []);
78
72
 
79
73
  // Load included patterns from storage on mount
80
74
  (0, _react.useEffect)(() => {
81
75
  const loadFilters = async () => {
82
76
  try {
83
- const stored = await safeGetItem(_sharedUi.devToolsStorageKeys.reactQuery.includedPatterns());
77
+ const stored = await _sharedUi.persistentStorage.getItem(_sharedUi.devToolsStorageKeys.reactQuery.includedPatterns());
84
78
  if (stored) {
85
79
  const patterns = JSON.parse(stored);
86
80
  if (Array.isArray(patterns)) {
@@ -92,33 +86,33 @@ function QueryBrowserModal({
92
86
  }
93
87
  };
94
88
  loadFilters();
95
- }, [safeGetItem]);
89
+ }, []);
96
90
 
97
91
  // Save ignored patterns to storage when they change
98
92
  (0, _react.useEffect)(() => {
99
93
  const saveFilters = async () => {
100
94
  try {
101
95
  const patterns = Array.from(ignoredPatterns);
102
- await safeSetItem(_sharedUi.devToolsStorageKeys.reactQuery.ignoredPatterns(), JSON.stringify(patterns));
96
+ await _sharedUi.persistentStorage.setItem(_sharedUi.devToolsStorageKeys.reactQuery.ignoredPatterns(), JSON.stringify(patterns));
103
97
  } catch (error) {
104
98
  console.error("Failed to save ignored patterns:", error);
105
99
  }
106
100
  };
107
101
  saveFilters();
108
- }, [ignoredPatterns, safeSetItem]);
102
+ }, [ignoredPatterns]);
109
103
 
110
104
  // Save included patterns to storage when they change
111
105
  (0, _react.useEffect)(() => {
112
106
  const saveFilters = async () => {
113
107
  try {
114
108
  const patterns = Array.from(includedPatterns);
115
- await safeSetItem(_sharedUi.devToolsStorageKeys.reactQuery.includedPatterns(), JSON.stringify(patterns));
109
+ await _sharedUi.persistentStorage.setItem(_sharedUi.devToolsStorageKeys.reactQuery.includedPatterns(), JSON.stringify(patterns));
116
110
  } catch (error) {
117
111
  console.error("Failed to save included patterns:", error);
118
112
  }
119
113
  };
120
114
  saveFilters();
121
- }, [includedPatterns, safeSetItem]);
115
+ }, [includedPatterns]);
122
116
 
123
117
  // Toggle pattern in ignored set
124
118
  const handlePatternToggle = (0, _react.useCallback)(pattern => {
@@ -7,27 +7,77 @@ exports.default = void 0;
7
7
  var _react = require("react");
8
8
  var _reactQuery = require("@tanstack/react-query");
9
9
  /**
10
- * Tracks all active React Query mutations with lightweight change detection. Debounces cache
11
- * updates so large mutation batches do not thrash the UI thread on mobile.
10
+ * Tracks all active React Query mutations with lightweight change detection.
11
+ * Mirrors the pattern used in useAllQueries for consistency.
12
12
  */
13
13
  function useAllMutations() {
14
14
  const queryClient = (0, _reactQuery.useQueryClient)();
15
- const [mutations, setMutations] = (0, _react.useState)([]);
16
- const mutationsSnapshotRef = (0, _react.useRef)(null);
15
+ const [mutations, setMutations] = (0, _react.useState)(() => {
16
+ // Initialize with current mutations to avoid flash
17
+ return queryClient.getMutationCache().getAll();
18
+ });
19
+
20
+ // Track mutation states using a Map for O(1) lookups
21
+ const mutationStatesRef = (0, _react.useRef)(new Map());
22
+ const updateTimerRef = (0, _react.useRef)(undefined);
23
+
24
+ // Check if mutations have changed
25
+ const hasMutationsChanged = (0, _react.useCallback)(newMutations => {
26
+ const statesMap = mutationStatesRef.current;
27
+
28
+ // Quick length check first
29
+ if (newMutations.length !== statesMap.size) {
30
+ return true;
31
+ }
32
+
33
+ // Check if any mutation state has changed
34
+ for (const mutation of newMutations) {
35
+ const prevState = statesMap.get(mutation.mutationId);
36
+ if (!prevState) return true;
37
+ if (prevState.status !== mutation.state.status || prevState.submittedAt !== mutation.state.submittedAt || prevState.isPaused !== mutation.state.isPaused) {
38
+ return true;
39
+ }
40
+ }
41
+ return false;
42
+ }, []);
43
+
44
+ // Update function
45
+ const updateMutations = (0, _react.useCallback)(() => {
46
+ const allMutations = queryClient.getMutationCache().getAll();
47
+ if (hasMutationsChanged(allMutations)) {
48
+ // Update states map
49
+ const newStatesMap = new Map();
50
+ allMutations.forEach(m => {
51
+ newStatesMap.set(m.mutationId, m.state);
52
+ });
53
+ mutationStatesRef.current = newStatesMap;
54
+ setMutations(allMutations);
55
+ }
56
+ }, [queryClient, hasMutationsChanged]);
17
57
  (0, _react.useEffect)(() => {
18
- const updateMutations = () => {
19
- const newMutations = queryClient.getMutationCache().getAll();
20
- const newStates = newMutations.map(m => m.state);
21
- const snapshot = JSON.stringify(newStates);
22
- if (mutationsSnapshotRef.current !== snapshot) {
23
- mutationsSnapshotRef.current = snapshot;
24
- setTimeout(() => setMutations(newMutations), 0);
58
+ // Initial update
59
+ updateMutations();
60
+
61
+ // Subscribe with event filtering (matching useAllQueries pattern)
62
+ const unsubscribe = queryClient.getMutationCache().subscribe(event => {
63
+ // Process events that affect mutation list
64
+ if (event.type === "added" || event.type === "removed" || event.type === "updated") {
65
+ // Debounce updates to batch rapid changes
66
+ if (updateTimerRef.current) {
67
+ clearTimeout(updateTimerRef.current);
68
+ }
69
+ updateTimerRef.current = setTimeout(() => {
70
+ updateMutations();
71
+ }, 10);
72
+ }
73
+ });
74
+ return () => {
75
+ unsubscribe();
76
+ if (updateTimerRef.current) {
77
+ clearTimeout(updateTimerRef.current);
25
78
  }
26
79
  };
27
- setTimeout(updateMutations, 0);
28
- const unsubscribe = queryClient.getMutationCache().subscribe(updateMutations);
29
- return () => unsubscribe();
30
- }, [queryClient]);
80
+ }, [queryClient, updateMutations]);
31
81
  return {
32
82
  mutations
33
83
  };
@@ -8,7 +8,7 @@ var _react = require("react");
8
8
  var _reactQuery = require("@tanstack/react-query");
9
9
  var _sharedUi = require("@buoy-gg/shared-ui");
10
10
  /**
11
- * Synchronizes a local Wi-Fi toggle with React Querys `onlineManager`, persisting the selection
11
+ * Synchronizes a local Wi-Fi toggle with React Query's `onlineManager`, persisting the selection
12
12
  * so developers can simulate offline mode across reloads.
13
13
  */
14
14
  function useWifiState() {
@@ -20,7 +20,7 @@ function useWifiState() {
20
20
  if (hasLoadedPersistedState.current) return;
21
21
  const loadPersistedState = async () => {
22
22
  try {
23
- const savedState = await (0, _sharedUi.safeGetItem)(_sharedUi.devToolsStorageKeys.settings.wifiEnabled());
23
+ const savedState = await _sharedUi.persistentStorage.getItem(_sharedUi.devToolsStorageKeys.settings.wifiEnabled());
24
24
  if (savedState !== null) {
25
25
  const isEnabled = savedState === "true";
26
26
  setIsOnline(isEnabled);
@@ -37,7 +37,7 @@ function useWifiState() {
37
37
  // Save WiFi state when it changes
38
38
  const saveWifiState = async enabled => {
39
39
  try {
40
- await (0, _sharedUi.safeSetItem)(_sharedUi.devToolsStorageKeys.settings.wifiEnabled(), enabled.toString());
40
+ await _sharedUi.persistentStorage.setItem(_sharedUi.devToolsStorageKeys.settings.wifiEnabled(), enabled.toString());
41
41
  } catch (error) {
42
42
  // Failed to save WiFi state
43
43
  }
@@ -13,4 +13,15 @@ Object.keys(_ReactQueryDevTools).forEach(function (key) {
13
13
  return _ReactQueryDevTools[key];
14
14
  }
15
15
  });
16
+ });
17
+ var _stores = require("./stores");
18
+ Object.keys(_stores).forEach(function (key) {
19
+ if (key === "default" || key === "__esModule") return;
20
+ if (key in exports && exports[key] === _stores[key]) return;
21
+ Object.defineProperty(exports, key, {
22
+ enumerable: true,
23
+ get: function () {
24
+ return _stores[key];
25
+ }
26
+ });
16
27
  });
@@ -0,0 +1,48 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ Object.defineProperty(exports, "clearReactQueryEvents", {
7
+ enumerable: true,
8
+ get: function () {
9
+ return _reactQueryEventStore.clearReactQueryEvents;
10
+ }
11
+ });
12
+ Object.defineProperty(exports, "disconnectQueryClient", {
13
+ enumerable: true,
14
+ get: function () {
15
+ return _reactQueryEventStore.disconnectQueryClient;
16
+ }
17
+ });
18
+ Object.defineProperty(exports, "getReactQueryEvents", {
19
+ enumerable: true,
20
+ get: function () {
21
+ return _reactQueryEventStore.getReactQueryEvents;
22
+ }
23
+ });
24
+ Object.defineProperty(exports, "isReactQueryConnected", {
25
+ enumerable: true,
26
+ get: function () {
27
+ return _reactQueryEventStore.isReactQueryConnected;
28
+ }
29
+ });
30
+ Object.defineProperty(exports, "reactQueryEventStore", {
31
+ enumerable: true,
32
+ get: function () {
33
+ return _reactQueryEventStore.reactQueryEventStore;
34
+ }
35
+ });
36
+ Object.defineProperty(exports, "setQueryClient", {
37
+ enumerable: true,
38
+ get: function () {
39
+ return _reactQueryEventStore.setQueryClient;
40
+ }
41
+ });
42
+ Object.defineProperty(exports, "subscribeToReactQueryEvents", {
43
+ enumerable: true,
44
+ get: function () {
45
+ return _reactQueryEventStore.subscribeToReactQueryEvents;
46
+ }
47
+ });
48
+ var _reactQueryEventStore = require("./reactQueryEventStore");
@@ -0,0 +1,311 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.subscribeToReactQueryEvents = exports.setQueryClient = exports.reactQueryEventStore = exports.isReactQueryConnected = exports.getReactQueryEvents = exports.disconnectQueryClient = exports.clearReactQueryEvents = void 0;
7
+ var _storageQueryUtils = require("../utils/storageQueryUtils");
8
+ /**
9
+ * React Query Event Store
10
+ *
11
+ * Bridges React Query's cache subscription system to a simple pub/sub pattern
12
+ * that can be consumed by the unified Events DevTools.
13
+ *
14
+ * Usage:
15
+ * 1. In your app, call setQueryClient(queryClient) to connect
16
+ * 2. The store will emit events for query/mutation state changes
17
+ * 3. The Events DevTools subscribes to these events
18
+ */
19
+
20
+ /**
21
+ * React Query event types for the unified timeline
22
+ */
23
+
24
+ /**
25
+ * Unified React Query event for the timeline
26
+ */
27
+
28
+ let eventIdCounter = 0;
29
+ function generateEventId() {
30
+ return `rq-${Date.now()}-${++eventIdCounter}`;
31
+ }
32
+ class ReactQueryEventStore {
33
+ events = [];
34
+ listeners = new Set();
35
+ queryClient = null;
36
+ queryUnsubscribe = null;
37
+ mutationUnsubscribe = null;
38
+ maxEvents = 200;
39
+
40
+ // Track fetch start times for duration calculation
41
+ fetchStartTimes = new Map();
42
+ mutationStartTimes = new Map();
43
+
44
+ // Track last known states to detect transitions
45
+ lastQueryStates = new Map();
46
+ lastMutationStates = new Map();
47
+
48
+ /**
49
+ * Connect a QueryClient to the store
50
+ * Call this in your app after creating the QueryClient
51
+ */
52
+ setQueryClient(queryClient) {
53
+ // Cleanup previous connection
54
+ this.disconnect();
55
+ this.queryClient = queryClient;
56
+
57
+ // Subscribe to query cache
58
+ this.queryUnsubscribe = queryClient.getQueryCache().subscribe(event => {
59
+ if (event.type === "updated" && event.query) {
60
+ this.handleQueryUpdate(event.query);
61
+ }
62
+ });
63
+
64
+ // Subscribe to mutation cache
65
+ this.mutationUnsubscribe = queryClient.getMutationCache().subscribe(event => {
66
+ if (event.type === "updated" && event.mutation) {
67
+ this.handleMutationUpdate(event.mutation);
68
+ }
69
+ });
70
+ }
71
+
72
+ /**
73
+ * Disconnect from the QueryClient
74
+ */
75
+ disconnect() {
76
+ if (this.queryUnsubscribe) {
77
+ this.queryUnsubscribe();
78
+ this.queryUnsubscribe = null;
79
+ }
80
+ if (this.mutationUnsubscribe) {
81
+ this.mutationUnsubscribe();
82
+ this.mutationUnsubscribe = null;
83
+ }
84
+ this.queryClient = null;
85
+ this.lastQueryStates.clear();
86
+ this.lastMutationStates.clear();
87
+ this.fetchStartTimes.clear();
88
+ this.mutationStartTimes.clear();
89
+ }
90
+
91
+ /**
92
+ * Handle query state updates and emit appropriate events
93
+ */
94
+ handleQueryUpdate(query) {
95
+ // Skip storage queries (internal to the devtools)
96
+ if ((0, _storageQueryUtils.isStorageQuery)(query.queryKey)) {
97
+ return;
98
+ }
99
+ const queryHash = query.queryHash;
100
+ const currentState = {
101
+ fetchStatus: query.state.fetchStatus,
102
+ status: query.state.status
103
+ };
104
+ const lastState = this.lastQueryStates.get(queryHash);
105
+
106
+ // Detect state transitions
107
+ if (!lastState) {
108
+ // New query - if it's fetching, emit fetch start
109
+ if (currentState.fetchStatus === "fetching") {
110
+ this.fetchStartTimes.set(queryHash, Date.now());
111
+ this.addEvent({
112
+ id: generateEventId(),
113
+ type: "query-fetch-start",
114
+ timestamp: Date.now(),
115
+ queryKey: query.queryKey,
116
+ queryHash,
117
+ query
118
+ });
119
+ }
120
+ } else {
121
+ // Existing query - check for transitions
122
+ const wasFetching = lastState.fetchStatus === "fetching";
123
+ const isFetching = currentState.fetchStatus === "fetching";
124
+
125
+ // Started fetching
126
+ if (!wasFetching && isFetching) {
127
+ this.fetchStartTimes.set(queryHash, Date.now());
128
+ this.addEvent({
129
+ id: generateEventId(),
130
+ type: "query-fetch-start",
131
+ timestamp: Date.now(),
132
+ queryKey: query.queryKey,
133
+ queryHash,
134
+ query
135
+ });
136
+ }
137
+
138
+ // Finished fetching
139
+ if (wasFetching && !isFetching) {
140
+ const startTime = this.fetchStartTimes.get(queryHash);
141
+ const duration = startTime ? Date.now() - startTime : undefined;
142
+ this.fetchStartTimes.delete(queryHash);
143
+ if (currentState.status === "error") {
144
+ this.addEvent({
145
+ id: generateEventId(),
146
+ type: "query-fetch-error",
147
+ timestamp: Date.now(),
148
+ queryKey: query.queryKey,
149
+ queryHash,
150
+ queryError: query.state.error,
151
+ duration,
152
+ query
153
+ });
154
+ } else {
155
+ this.addEvent({
156
+ id: generateEventId(),
157
+ type: "query-fetch-success",
158
+ timestamp: Date.now(),
159
+ queryKey: query.queryKey,
160
+ queryHash,
161
+ queryData: query.state.data,
162
+ duration,
163
+ query
164
+ });
165
+ }
166
+ }
167
+
168
+ // Query was invalidated
169
+ if (!lastState.status && query.state.isInvalidated) {
170
+ this.addEvent({
171
+ id: generateEventId(),
172
+ type: "query-invalidated",
173
+ timestamp: Date.now(),
174
+ queryKey: query.queryKey,
175
+ queryHash,
176
+ query
177
+ });
178
+ }
179
+ }
180
+
181
+ // Update last known state
182
+ this.lastQueryStates.set(queryHash, currentState);
183
+ }
184
+
185
+ /**
186
+ * Handle mutation state updates and emit appropriate events
187
+ */
188
+ handleMutationUpdate(mutation) {
189
+ const mutationId = mutation.mutationId;
190
+ const currentStatus = mutation.state.status;
191
+ const lastStatus = this.lastMutationStates.get(mutationId);
192
+ if (lastStatus !== currentStatus) {
193
+ // Status changed
194
+ if (currentStatus === "pending" && lastStatus !== "pending") {
195
+ // Mutation started
196
+ this.mutationStartTimes.set(mutationId, Date.now());
197
+ this.addEvent({
198
+ id: generateEventId(),
199
+ type: "mutation-start",
200
+ timestamp: Date.now(),
201
+ mutationId,
202
+ mutationKey: mutation.options.mutationKey,
203
+ mutationVariables: mutation.state.variables,
204
+ mutation
205
+ });
206
+ } else if (currentStatus === "success" && lastStatus === "pending") {
207
+ // Mutation succeeded
208
+ const startTime = this.mutationStartTimes.get(mutationId);
209
+ const duration = startTime ? Date.now() - startTime : undefined;
210
+ this.mutationStartTimes.delete(mutationId);
211
+ this.addEvent({
212
+ id: generateEventId(),
213
+ type: "mutation-success",
214
+ timestamp: Date.now(),
215
+ mutationId,
216
+ mutationKey: mutation.options.mutationKey,
217
+ mutationVariables: mutation.state.variables,
218
+ mutationData: mutation.state.data,
219
+ duration,
220
+ mutation
221
+ });
222
+ } else if (currentStatus === "error" && lastStatus === "pending") {
223
+ // Mutation failed
224
+ const startTime = this.mutationStartTimes.get(mutationId);
225
+ const duration = startTime ? Date.now() - startTime : undefined;
226
+ this.mutationStartTimes.delete(mutationId);
227
+ this.addEvent({
228
+ id: generateEventId(),
229
+ type: "mutation-error",
230
+ timestamp: Date.now(),
231
+ mutationId,
232
+ mutationKey: mutation.options.mutationKey,
233
+ mutationVariables: mutation.state.variables,
234
+ mutationError: mutation.state.error,
235
+ duration,
236
+ mutation
237
+ });
238
+ }
239
+ }
240
+
241
+ // Update last known status
242
+ this.lastMutationStates.set(mutationId, currentStatus);
243
+ }
244
+
245
+ /**
246
+ * Add an event to the store
247
+ */
248
+ addEvent(event) {
249
+ this.events = [event, ...this.events].slice(0, this.maxEvents);
250
+ this.notifyListeners();
251
+ }
252
+
253
+ /**
254
+ * Get all events
255
+ */
256
+ getEvents() {
257
+ return this.events;
258
+ }
259
+
260
+ /**
261
+ * Subscribe to event changes
262
+ */
263
+ subscribe(listener) {
264
+ this.listeners.add(listener);
265
+ // Immediately call with current events
266
+ listener(this.events);
267
+ return () => {
268
+ this.listeners.delete(listener);
269
+ };
270
+ }
271
+
272
+ /**
273
+ * Notify all listeners
274
+ */
275
+ notifyListeners() {
276
+ const events = this.events;
277
+ this.listeners.forEach(listener => listener(events));
278
+ }
279
+
280
+ /**
281
+ * Clear all events
282
+ */
283
+ clearEvents() {
284
+ this.events = [];
285
+ this.notifyListeners();
286
+ }
287
+
288
+ /**
289
+ * Check if connected to a QueryClient
290
+ */
291
+ isConnected() {
292
+ return this.queryClient !== null;
293
+ }
294
+ }
295
+
296
+ // Singleton instance
297
+ const reactQueryEventStore = exports.reactQueryEventStore = new ReactQueryEventStore();
298
+
299
+ // Convenience exports
300
+ const setQueryClient = queryClient => reactQueryEventStore.setQueryClient(queryClient);
301
+ exports.setQueryClient = setQueryClient;
302
+ const disconnectQueryClient = () => reactQueryEventStore.disconnect();
303
+ exports.disconnectQueryClient = disconnectQueryClient;
304
+ const getReactQueryEvents = () => reactQueryEventStore.getEvents();
305
+ exports.getReactQueryEvents = getReactQueryEvents;
306
+ const subscribeToReactQueryEvents = listener => reactQueryEventStore.subscribe(listener);
307
+ exports.subscribeToReactQueryEvents = subscribeToReactQueryEvents;
308
+ const clearReactQueryEvents = () => reactQueryEventStore.clearEvents();
309
+ exports.clearReactQueryEvents = clearReactQueryEvents;
310
+ const isReactQueryConnected = () => reactQueryEventStore.isConnected();
311
+ exports.isReactQueryConnected = isReactQueryConnected;
@@ -7,10 +7,10 @@ exports.savePanelHeight = exports.savePanelDimensions = exports.saveModalVisibil
7
7
  var _sharedUi = require("@buoy-gg/shared-ui");
8
8
  // Helper functions for persisting panel state using shared storage wrapper
9
9
  const setItem = async (key, value) => {
10
- await (0, _sharedUi.safeSetItem)(key, value);
10
+ await _sharedUi.persistentStorage.setItem(key, value);
11
11
  };
12
12
  const getItem = async key => {
13
- return (0, _sharedUi.safeGetItem)(key);
13
+ return _sharedUi.persistentStorage.getItem(key);
14
14
  };
15
15
  // Storage operations
16
16
  /**