@rozenite/tanstack-query-plugin 1.0.0-alpha.0 → 1.0.0-alpha.10

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 (44) hide show
  1. package/README.md +2 -2
  2. package/dist/assets/CXEL7IU7-BTFA0aeQ.js +1172 -0
  3. package/dist/assets/tanstack-query-DWTo8DT_.js +48 -0
  4. package/dist/react-native.cjs +1 -1
  5. package/dist/react-native.d.ts +1 -5
  6. package/dist/react-native.js +3 -86
  7. package/dist/rozenite.config.d.ts +7 -0
  8. package/dist/rozenite.json +1 -1
  9. package/dist/src/react-native/useHandleDevToolsMessages.d.ts +3 -0
  10. package/dist/src/react-native/useHandleInitialData.d.ts +3 -0
  11. package/dist/src/react-native/useSyncTanStackCache.d.ts +3 -0
  12. package/dist/src/react-native/useTanStackQueryDevTools.d.ts +2 -0
  13. package/dist/src/shared/dehydrate.d.ts +6 -0
  14. package/dist/src/shared/hydrate.d.ts +10 -0
  15. package/dist/src/shared/messaging.d.ts +34 -0
  16. package/dist/src/shared/types.d.ts +25 -0
  17. package/dist/src/shared/useSyncOnlineStatus.d.ts +2 -0
  18. package/dist/src/ui/tanstack-query.d.ts +1 -0
  19. package/dist/src/ui/useHandleSyncMessages.d.ts +2 -0
  20. package/dist/src/ui/useSyncDevToolsEvents.d.ts +2 -0
  21. package/dist/src/ui/useSyncInitialData.d.ts +2 -0
  22. package/dist/tanstack-query.html +1 -1
  23. package/dist/useTanstackQueryDevTools.cjs +1 -0
  24. package/dist/useTanstackQueryDevTools.js +312 -0
  25. package/package.json +14 -9
  26. package/project.json +12 -0
  27. package/react-native.ts +2 -2
  28. package/src/react-native/useHandleDevToolsMessages.ts +119 -0
  29. package/src/react-native/useHandleInitialData.ts +24 -0
  30. package/src/react-native/useSyncTanStackCache.ts +246 -0
  31. package/src/react-native/useTanstackQueryDevTools.ts +21 -0
  32. package/src/shared/dehydrate.ts +42 -0
  33. package/src/shared/hydrate.ts +250 -0
  34. package/src/shared/messaging.ts +54 -0
  35. package/src/shared/types.ts +48 -0
  36. package/src/shared/useSyncOnlineStatus.ts +29 -0
  37. package/src/ui/tanstack-query.tsx +21 -184
  38. package/src/ui/useHandleSyncMessages.ts +66 -0
  39. package/src/ui/useSyncDevToolsEvents.ts +55 -0
  40. package/src/ui/useSyncInitialData.ts +14 -0
  41. package/tsconfig.json +13 -6
  42. package/tsconfig.tsbuildinfo +1 -0
  43. package/dist/assets/tanstack-query-CXp_Psxe.js +0 -48
  44. package/src/react-native/useTanStackQueryDevTools.ts +0 -214
@@ -0,0 +1,119 @@
1
+ import { useEffect } from 'react';
2
+ import { QueryClient } from '@tanstack/react-query';
3
+ import { TanStackQueryPluginClient } from '../shared/messaging';
4
+
5
+ export const useHandleDevToolsMessages = (
6
+ queryClient: QueryClient,
7
+ client: TanStackQueryPluginClient | null
8
+ ) => {
9
+ useEffect(() => {
10
+ if (!client) {
11
+ return;
12
+ }
13
+
14
+ const subscription = client.onMessage(
15
+ 'devtools-action',
16
+ ({ type, queryHash }) => {
17
+ const activeQuery = queryClient.getQueryCache().get(queryHash);
18
+
19
+ if (!activeQuery) {
20
+ console.warn(`No active query found for hash: ${queryHash}`);
21
+ return;
22
+ }
23
+
24
+ switch (type) {
25
+ case 'TRIGGER_ERROR': {
26
+ const __previousQueryOptions = activeQuery.options;
27
+ const error = new Error('Unknown error from devtools');
28
+
29
+ activeQuery.setState({
30
+ status: 'error',
31
+ error,
32
+ fetchMeta: {
33
+ ...activeQuery.state.fetchMeta,
34
+ // @ts-expect-error This does exist
35
+ __previousQueryOptions,
36
+ },
37
+ });
38
+ break;
39
+ }
40
+ case 'RESTORE_ERROR': {
41
+ queryClient.resetQueries(activeQuery);
42
+ break;
43
+ }
44
+ case 'TRIGGER_LOADING': {
45
+ if (!activeQuery) return;
46
+ const __previousQueryOptions = activeQuery.options;
47
+ // Trigger a fetch in order to trigger suspense as well.
48
+ activeQuery.fetch({
49
+ ...__previousQueryOptions,
50
+ queryFn: () => {
51
+ return new Promise(() => {
52
+ // Never resolve - simulates perpetual loading
53
+ });
54
+ },
55
+ gcTime: -1,
56
+ });
57
+ activeQuery.setState({
58
+ data: undefined,
59
+ status: 'pending',
60
+ fetchMeta: {
61
+ ...activeQuery.state.fetchMeta,
62
+ // @ts-expect-error This does exist
63
+ __previousQueryOptions,
64
+ },
65
+ });
66
+ break;
67
+ }
68
+ case 'RESTORE_LOADING': {
69
+ const previousState = activeQuery.state;
70
+ const previousOptions = activeQuery.state.fetchMeta
71
+ ? (
72
+ activeQuery.state.fetchMeta as unknown as {
73
+ __previousQueryOptions: unknown;
74
+ }
75
+ ).__previousQueryOptions
76
+ : null;
77
+
78
+ activeQuery.cancel({ silent: true });
79
+ activeQuery.setState({
80
+ ...previousState,
81
+ fetchStatus: 'idle',
82
+ fetchMeta: null,
83
+ });
84
+
85
+ if (previousOptions) {
86
+ activeQuery.fetch(previousOptions);
87
+ }
88
+ break;
89
+ }
90
+ case 'RESET': {
91
+ queryClient.resetQueries(activeQuery);
92
+ break;
93
+ }
94
+ case 'REMOVE': {
95
+ queryClient.removeQueries(activeQuery);
96
+ break;
97
+ }
98
+ case 'REFETCH': {
99
+ activeQuery.fetch().catch(() => {
100
+ // Ignore errors
101
+ });
102
+ break;
103
+ }
104
+ case 'INVALIDATE': {
105
+ queryClient.invalidateQueries(activeQuery);
106
+ break;
107
+ }
108
+ default: {
109
+ console.warn(`Unknown devtools action: ${type}`);
110
+ }
111
+ }
112
+ }
113
+ );
114
+
115
+ return () => {
116
+ subscription.remove();
117
+ };
118
+ }, [client]);
119
+ };
@@ -0,0 +1,24 @@
1
+ import { useEffect } from 'react';
2
+ import { TanStackQueryPluginClient } from '../shared/messaging';
3
+ import { QueryClient } from '@tanstack/react-query';
4
+ import { dehydrateQueryClient } from '../shared/dehydrate';
5
+
6
+ export const useHandleInitialData = (
7
+ queryClient: QueryClient,
8
+ client: TanStackQueryPluginClient | null
9
+ ) => {
10
+ useEffect(() => {
11
+ if (!client) {
12
+ return;
13
+ }
14
+
15
+ const subscription = client.onMessage('request-initial-data', () => {
16
+ const dehydratedState = dehydrateQueryClient(queryClient);
17
+ client.send('sync-data', { data: dehydratedState });
18
+ });
19
+
20
+ return () => {
21
+ subscription.remove();
22
+ };
23
+ }, [client, queryClient]);
24
+ };
@@ -0,0 +1,246 @@
1
+ import {
2
+ QueryClient,
3
+ QueryCacheNotifyEvent,
4
+ MutationCacheNotifyEvent,
5
+ } from '@tanstack/react-query';
6
+ import { useEffect, useMemo, useRef } from 'react';
7
+ import equal from 'fast-deep-equal';
8
+ import { TanStackQueryPluginClient } from '../shared/messaging';
9
+ import {
10
+ dehydrateQuery,
11
+ dehydrateMutation,
12
+ dehydrateObservers,
13
+ } from '../shared/dehydrate';
14
+ import { SerializableObserver, PartialQueryState } from '../shared/types';
15
+
16
+ export const useSyncTanStackCache = (
17
+ queryClient: QueryClient,
18
+ client: TanStackQueryPluginClient | null
19
+ ) => {
20
+ const previousObserversRef = useRef<Map<string, SerializableObserver[]>>(
21
+ new Map()
22
+ );
23
+
24
+ const handler = useMemo(() => {
25
+ return (event: QueryCacheNotifyEvent | MutationCacheNotifyEvent): void => {
26
+ if (!client) {
27
+ return;
28
+ }
29
+
30
+ if (event.type === 'observerResultsUpdated') {
31
+ // We don't need to sync this type of events.
32
+ return;
33
+ }
34
+
35
+ if ('query' in event) {
36
+ const { query, type } = event;
37
+
38
+ if (type === 'added' || type === 'removed') {
39
+ if (type === 'removed') {
40
+ // We don't need to store observers for removed queries.
41
+ previousObserversRef.current.delete(query.queryHash);
42
+ }
43
+
44
+ const dehydratedQuery = dehydrateQuery(query);
45
+ client.send('sync-query-event', { type, data: dehydratedQuery });
46
+ return;
47
+ }
48
+
49
+ if (type === 'updated' && 'action' in event) {
50
+ const action = event.action;
51
+
52
+ switch (action.type) {
53
+ case 'fetch': {
54
+ // Only need loading state and fetch metadata
55
+ const fetchData: PartialQueryState = {
56
+ queryHash: query.queryHash,
57
+ state: {
58
+ status: query.state.status,
59
+ fetchStatus: query.state.fetchStatus,
60
+ fetchMeta: query.state.fetchMeta,
61
+ dataUpdatedAt: query.state.dataUpdatedAt,
62
+ errorUpdatedAt: query.state.errorUpdatedAt,
63
+ },
64
+ };
65
+ client.send('sync-query-event', {
66
+ type: 'updated',
67
+ action: 'fetch',
68
+ data: fetchData,
69
+ });
70
+ break;
71
+ }
72
+
73
+ case 'success': {
74
+ // Only need new data and success state
75
+ const successData: PartialQueryState = {
76
+ queryHash: query.queryHash,
77
+ state: {
78
+ status: query.state.status,
79
+ data: query.state.data,
80
+ dataUpdatedAt: query.state.dataUpdatedAt,
81
+ error: query.state.error,
82
+ errorUpdatedAt: query.state.errorUpdatedAt,
83
+ fetchStatus: query.state.fetchStatus,
84
+ },
85
+ };
86
+ client.send('sync-query-event', {
87
+ type: 'updated',
88
+ action: 'success',
89
+ data: successData,
90
+ });
91
+ break;
92
+ }
93
+
94
+ case 'error': {
95
+ // Only need error information
96
+ const errorData: PartialQueryState = {
97
+ queryHash: query.queryHash,
98
+ state: {
99
+ status: query.state.status,
100
+ error: query.state.error,
101
+ errorUpdatedAt: query.state.errorUpdatedAt,
102
+ fetchStatus: query.state.fetchStatus,
103
+ },
104
+ };
105
+ client.send('sync-query-event', {
106
+ type: 'updated',
107
+ action: 'error',
108
+ data: errorData,
109
+ });
110
+ break;
111
+ }
112
+
113
+ case 'setState': {
114
+ // Only need the specific state changes
115
+ const setStateData: PartialQueryState = {
116
+ queryHash: query.queryHash,
117
+ state: action.state, // Only the changed state parts
118
+ };
119
+ client.send('sync-query-event', {
120
+ type: 'updated',
121
+ action: 'setState',
122
+ data: setStateData,
123
+ });
124
+ break;
125
+ }
126
+
127
+ case 'invalidate': {
128
+ // Only need invalidation flag
129
+ const invalidateData: PartialQueryState = {
130
+ queryHash: query.queryHash,
131
+ state: {
132
+ isInvalidated: query.state.isInvalidated,
133
+ },
134
+ };
135
+ client.send('sync-query-event', {
136
+ type: 'updated',
137
+ action: 'invalidate',
138
+ data: invalidateData,
139
+ });
140
+ break;
141
+ }
142
+
143
+ case 'pause': {
144
+ // Need to sync the paused fetch status
145
+ const pauseData: PartialQueryState = {
146
+ queryHash: query.queryHash,
147
+ state: {
148
+ fetchStatus: query.state.fetchStatus,
149
+ },
150
+ };
151
+ client.send('sync-query-event', {
152
+ type: 'updated',
153
+ action: 'pause',
154
+ data: pauseData,
155
+ });
156
+ break;
157
+ }
158
+
159
+ case 'continue': {
160
+ // Need to sync the resumed fetch status
161
+ const continueData: PartialQueryState = {
162
+ queryHash: query.queryHash,
163
+ state: {
164
+ fetchStatus: query.state.fetchStatus,
165
+ },
166
+ };
167
+ client.send('sync-query-event', {
168
+ type: 'updated',
169
+ action: 'continue',
170
+ data: continueData,
171
+ });
172
+ break;
173
+ }
174
+
175
+ default: {
176
+ // Fallback to full data for unknown actions
177
+ const dehydratedQuery = dehydrateQuery(query);
178
+ client.send('sync-query-event', { type, data: dehydratedQuery });
179
+ }
180
+ }
181
+ return;
182
+ }
183
+
184
+ if (
185
+ type === 'observerAdded' ||
186
+ type === 'observerRemoved' ||
187
+ type === 'observerOptionsUpdated'
188
+ ) {
189
+ const dehydratedObservers = dehydrateObservers(query);
190
+ const previousObservers = previousObserversRef.current.get(
191
+ query.queryHash
192
+ );
193
+
194
+ // For observerOptionsUpdated, only send if the observers actually changed
195
+ if (type === 'observerOptionsUpdated' && previousObservers) {
196
+ if (equal(previousObservers, dehydratedObservers)) {
197
+ // No meaningful change, skip sending
198
+ return;
199
+ }
200
+ }
201
+
202
+ previousObserversRef.current.set(
203
+ query.queryHash,
204
+ dehydratedObservers
205
+ );
206
+
207
+ client.send('sync-query-event', {
208
+ type,
209
+ data: {
210
+ queryHash: query.queryHash,
211
+ observers: dehydratedObservers,
212
+ },
213
+ });
214
+ return;
215
+ }
216
+ }
217
+
218
+ const { mutation, type } = event;
219
+ if (mutation) {
220
+ const dehydratedMutation = dehydrateMutation(mutation);
221
+ client.send('sync-mutation-event', {
222
+ type,
223
+ data: dehydratedMutation,
224
+ });
225
+ }
226
+ };
227
+ }, [client]);
228
+
229
+ useEffect(() => {
230
+ if (!client) {
231
+ return;
232
+ }
233
+
234
+ const mutationCacheSubscription = queryClient
235
+ .getMutationCache()
236
+ .subscribe(handler);
237
+ const queryCacheSubscription = queryClient
238
+ .getQueryCache()
239
+ .subscribe(handler);
240
+
241
+ return () => {
242
+ mutationCacheSubscription();
243
+ queryCacheSubscription();
244
+ };
245
+ }, [client, queryClient, handler]);
246
+ };
@@ -0,0 +1,21 @@
1
+ import { QueryClient } from '@tanstack/react-query';
2
+ import { useRozeniteDevToolsClient } from '@rozenite/plugin-bridge';
3
+ import { TanStackQueryPluginEventMap } from '../shared/messaging';
4
+ import { useSyncOnlineStatus } from '../shared/useSyncOnlineStatus';
5
+ import { useHandleDevToolsMessages } from './useHandleDevToolsMessages';
6
+ import { useSyncTanStackCache } from './useSyncTanStackCache';
7
+ import { useHandleInitialData } from './useHandleInitialData';
8
+
9
+ export const useTanStackQueryDevTools = (queryClient: QueryClient) => {
10
+ const client = useRozeniteDevToolsClient<TanStackQueryPluginEventMap>({
11
+ pluginId: '@rozenite/tanstack-query-plugin',
12
+ });
13
+
14
+ useSyncOnlineStatus(client);
15
+
16
+ useHandleDevToolsMessages(queryClient, client);
17
+
18
+ useSyncTanStackCache(queryClient, client);
19
+
20
+ useHandleInitialData(queryClient, client);
21
+ };
@@ -0,0 +1,42 @@
1
+ import type { Query, Mutation, QueryClient } from '@tanstack/react-query';
2
+ import type {
3
+ SerializableQuery,
4
+ SerializableMutation,
5
+ SerializableObserver,
6
+ SerializableQueryClient,
7
+ } from './types';
8
+
9
+ export const dehydrateObservers = (query: Query): SerializableObserver[] => {
10
+ return query.observers.map((observer) => ({
11
+ queryHash: query.queryHash,
12
+ options: observer.options,
13
+ }));
14
+ };
15
+
16
+ export const dehydrateQuery = (query: Query): SerializableQuery => {
17
+ const dehydratedObservers: SerializableObserver[] = dehydrateObservers(query);
18
+
19
+ return {
20
+ state: query.state,
21
+ queryKey: query.queryKey,
22
+ queryHash: query.queryHash,
23
+ observers: dehydratedObservers,
24
+ };
25
+ };
26
+
27
+ export const dehydrateMutation = (mutation: Mutation): SerializableMutation => {
28
+ return {
29
+ mutationId: mutation.mutationId,
30
+ state: mutation.state,
31
+ options: mutation.options,
32
+ };
33
+ };
34
+
35
+ export const dehydrateQueryClient = (
36
+ queryClient: QueryClient
37
+ ): SerializableQueryClient => {
38
+ return {
39
+ queries: queryClient.getQueryCache().getAll().map(dehydrateQuery),
40
+ mutations: queryClient.getMutationCache().getAll().map(dehydrateMutation),
41
+ };
42
+ };
@@ -0,0 +1,250 @@
1
+ import {
2
+ InfiniteQueryObserverOptions,
3
+ MutationOptions,
4
+ MutationState,
5
+ QueryClient,
6
+ QueryObserver,
7
+ QueryObserverOptions,
8
+ QueryState,
9
+ } from '@tanstack/react-query';
10
+ import type {
11
+ SerializableQuery,
12
+ SerializableMutation,
13
+ SerializableQueryClient,
14
+ SerializableObserver,
15
+ PartialQueryState,
16
+ } from './types';
17
+
18
+ const mockQueryFn = () => {
19
+ return Promise.resolve(null);
20
+ };
21
+
22
+ const hydrateObservers = (
23
+ client: QueryClient,
24
+ queryHash: string,
25
+ dehydratedObservers: SerializableObserver[]
26
+ ) => {
27
+ const query = client.getQueryCache().get(queryHash);
28
+
29
+ if (!query) {
30
+ return;
31
+ }
32
+
33
+ query.observers.forEach((observer) => {
34
+ query.removeObserver(observer);
35
+ });
36
+
37
+ dehydratedObservers.forEach((observerState) => {
38
+ const hydratedOptions: InfiniteQueryObserverOptions | QueryObserverOptions =
39
+ observerState.options;
40
+
41
+ if ('initialPageParam' in hydratedOptions) {
42
+ delete hydratedOptions.initialPageParam;
43
+ }
44
+
45
+ if ('behavior' in hydratedOptions) {
46
+ delete hydratedOptions.behavior;
47
+ }
48
+
49
+ hydratedOptions.queryFn = mockQueryFn;
50
+
51
+ const observer = new QueryObserver(
52
+ client,
53
+ hydratedOptions as QueryObserverOptions
54
+ );
55
+ query.addObserver(observer);
56
+ });
57
+ };
58
+
59
+ const hydrateMutation = (
60
+ client: QueryClient,
61
+ dehydratedMutation: SerializableMutation
62
+ ) => {
63
+ const mutationCache = client.getMutationCache();
64
+ const { options, state } = dehydratedMutation;
65
+
66
+ const existingMutation = mutationCache.find({
67
+ mutationKey: options.mutationKey,
68
+ });
69
+ const hydratedState: MutationState<unknown, Error, void, unknown> =
70
+ state as MutationState<unknown, Error, void, unknown>;
71
+ const hydratedOptions: MutationOptions = options;
72
+
73
+ if (existingMutation) {
74
+ mutationCache.remove(existingMutation);
75
+ }
76
+
77
+ mutationCache.build(client, hydratedOptions, hydratedState);
78
+ };
79
+
80
+ const hydrateQuery = (
81
+ client: QueryClient,
82
+ dehydratedQuery: SerializableQuery
83
+ ) => {
84
+ const queryCache = client.getQueryCache();
85
+ const { queryKey, state, queryHash, observers } = dehydratedQuery;
86
+
87
+ let query = queryCache.get(queryHash);
88
+ const data = state.data;
89
+ const hydratedState: QueryState = state;
90
+
91
+ // Do not hydrate if an existing query exists with newer data
92
+ if (query) {
93
+ if (
94
+ query.state.dataUpdatedAt < state.dataUpdatedAt ||
95
+ query.state.fetchStatus !== state.fetchStatus
96
+ ) {
97
+ query.setState({
98
+ ...hydratedState,
99
+ data,
100
+ });
101
+ query.setOptions({
102
+ ...query.options,
103
+ queryFn: mockQueryFn,
104
+ retry: 0,
105
+ });
106
+ }
107
+ } else {
108
+ // Restore query
109
+ query = queryCache.build(
110
+ client,
111
+ {
112
+ ...client.getDefaultOptions().hydrate?.queries,
113
+ queryKey,
114
+ queryHash,
115
+ queryFn: mockQueryFn,
116
+ },
117
+ {
118
+ ...hydratedState,
119
+ data,
120
+ }
121
+ );
122
+ }
123
+
124
+ hydrateObservers(client, queryHash, observers);
125
+ };
126
+
127
+ export const hydrateQueryClient = (
128
+ client: QueryClient,
129
+ dehydratedState: SerializableQueryClient
130
+ ): void => {
131
+ // Hydrate mutations
132
+ dehydratedState.mutations.forEach((mutation) =>
133
+ hydrateMutation(client, mutation)
134
+ );
135
+
136
+ // Hydrate queries
137
+ dehydratedState.queries.forEach((query) => hydrateQuery(client, query));
138
+ };
139
+
140
+ export const applyQueryEvent = (
141
+ queryClient: QueryClient,
142
+ type:
143
+ | 'added'
144
+ | 'updated'
145
+ | 'removed'
146
+ | 'observerAdded'
147
+ | 'observerRemoved'
148
+ | 'observerResultsUpdated'
149
+ | 'observerOptionsUpdated',
150
+ data: SerializableQuery | PartialQueryState,
151
+ action?: string
152
+ ): void => {
153
+ const queryCache = queryClient.getQueryCache();
154
+
155
+ switch (type) {
156
+ case 'added': {
157
+ hydrateQuery(queryClient, data as SerializableQuery);
158
+ break;
159
+ }
160
+ case 'updated': {
161
+ if (action && 'state' in data && !('queryKey' in data)) {
162
+ // Handle action-based partial state update
163
+ applyPartialQueryState(queryClient, data as PartialQueryState);
164
+ } else {
165
+ // Handle full query update (backward compatibility)
166
+ hydrateQuery(queryClient, data as SerializableQuery);
167
+ }
168
+ break;
169
+ }
170
+ case 'observerAdded':
171
+ case 'observerRemoved':
172
+ case 'observerOptionsUpdated': {
173
+ hydrateObservers(queryClient, data.queryHash, (data as any).observers);
174
+ break;
175
+ }
176
+ case 'removed': {
177
+ const query = queryCache.get(data.queryHash);
178
+ if (query) {
179
+ queryCache.remove(query);
180
+ }
181
+ break;
182
+ }
183
+ }
184
+ };
185
+
186
+ // New function to handle action-based partial state updates
187
+ export const applyPartialQueryState = (
188
+ queryClient: QueryClient,
189
+ data: PartialQueryState
190
+ ): void => {
191
+ const queryCache = queryClient.getQueryCache();
192
+ const query = queryCache.get(data.queryHash);
193
+
194
+ if (!query) {
195
+ // Query doesn't exist, we need to create it with minimal data
196
+ // This is a fallback for when we receive a partial update for a non-existent query
197
+ return;
198
+ }
199
+
200
+ // Apply the partial state changes
201
+ if (data.state) {
202
+ query.setState(data.state);
203
+ }
204
+ };
205
+
206
+ export const applyMutationEvent = (
207
+ queryClient: QueryClient,
208
+ type:
209
+ | 'added'
210
+ | 'updated'
211
+ | 'removed'
212
+ | 'observerAdded'
213
+ | 'observerRemoved'
214
+ | 'observerResultsUpdated'
215
+ | 'observerOptionsUpdated',
216
+ data: SerializableMutation
217
+ ): void => {
218
+ const mutationCache = queryClient.getMutationCache();
219
+
220
+ switch (type) {
221
+ case 'added':
222
+ case 'updated':
223
+ case 'observerAdded':
224
+ case 'observerRemoved':
225
+ case 'observerResultsUpdated':
226
+ case 'observerOptionsUpdated': {
227
+ hydrateMutation(queryClient, data);
228
+ break;
229
+ }
230
+ case 'removed': {
231
+ const mutation = mutationCache.find({
232
+ mutationKey: data.options.mutationKey,
233
+ });
234
+ if (mutation) {
235
+ mutationCache.remove(mutation);
236
+ }
237
+ break;
238
+ }
239
+ }
240
+ };
241
+
242
+ export const applyQueryObserverEvent = (
243
+ queryClient: QueryClient,
244
+ data: {
245
+ queryHash: string;
246
+ observers: SerializableObserver[];
247
+ }
248
+ ): void => {
249
+ hydrateObservers(queryClient, data.queryHash, data.observers);
250
+ };