@buoy-gg/react-query 1.7.8 → 2.1.2
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/lib/commonjs/index.js +619 -24
- package/lib/commonjs/preset.js +1 -1
- package/lib/commonjs/react-query/components/DataEditorMode.js +9 -16
- package/lib/commonjs/react-query/components/MutationEditorMode.js +1 -3
- package/lib/commonjs/react-query/components/ReactQueryDevToolsModal.js +12 -0
- package/lib/commonjs/react-query/components/modals/MutationBrowserModal.js +2 -1
- package/lib/commonjs/react-query/components/modals/QueryBrowserModal.js +8 -14
- package/lib/commonjs/react-query/components/query-browser/ActionButton.js +40 -69
- package/lib/commonjs/react-query/components/query-browser/QueryActions.js +70 -84
- package/lib/commonjs/react-query/hooks/useActionButtons.js +7 -15
- package/lib/commonjs/react-query/hooks/useAllMutations.js +65 -15
- package/lib/commonjs/react-query/hooks/useMutationActionButtons.js +1 -2
- package/lib/commonjs/react-query/hooks/useWifiState.js +3 -3
- package/lib/commonjs/react-query/index.js +11 -0
- package/lib/commonjs/react-query/stores/index.js +48 -0
- package/lib/commonjs/react-query/stores/reactQueryEventStore.js +311 -0
- package/lib/commonjs/react-query/utils/modalStorageOperations.js +2 -2
- package/lib/module/index.js +113 -8
- package/lib/module/preset.js +2 -2
- package/lib/module/react-query/components/DataEditorMode.js +9 -16
- package/lib/module/react-query/components/MutationEditorMode.js +1 -3
- package/lib/module/react-query/components/ReactQueryDevToolsModal.js +13 -1
- package/lib/module/react-query/components/modals/MutationBrowserModal.js +2 -1
- package/lib/module/react-query/components/modals/QueryBrowserModal.js +9 -15
- package/lib/module/react-query/components/query-browser/ActionButton.js +40 -70
- package/lib/module/react-query/components/query-browser/QueryActions.js +70 -84
- package/lib/module/react-query/hooks/useActionButtons.js +7 -15
- package/lib/module/react-query/hooks/useAllMutations.js +66 -16
- package/lib/module/react-query/hooks/useMutationActionButtons.js +1 -2
- package/lib/module/react-query/hooks/useWifiState.js +4 -4
- package/lib/module/react-query/index.js +2 -1
- package/lib/module/react-query/stores/index.js +3 -0
- package/lib/module/react-query/stores/reactQueryEventStore.js +302 -0
- package/lib/module/react-query/utils/modalStorageOperations.js +3 -3
- package/lib/typescript/index.d.ts +61 -5
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/react-query/components/DataEditorMode.d.ts.map +1 -1
- package/lib/typescript/react-query/components/MutationEditorMode.d.ts.map +1 -1
- package/lib/typescript/react-query/components/ReactQueryDevToolsModal.d.ts.map +1 -1
- package/lib/typescript/react-query/components/modals/MutationBrowserModal.d.ts.map +1 -1
- package/lib/typescript/react-query/components/modals/QueryBrowserModal.d.ts.map +1 -1
- package/lib/typescript/react-query/components/query-browser/ActionButton.d.ts +4 -42
- package/lib/typescript/react-query/components/query-browser/ActionButton.d.ts.map +1 -1
- package/lib/typescript/react-query/components/query-browser/QueryActions.d.ts.map +1 -1
- package/lib/typescript/react-query/hooks/useActionButtons.d.ts +5 -8
- package/lib/typescript/react-query/hooks/useActionButtons.d.ts.map +1 -1
- package/lib/typescript/react-query/hooks/useAllMutations.d.ts +2 -2
- package/lib/typescript/react-query/hooks/useAllMutations.d.ts.map +1 -1
- package/lib/typescript/react-query/hooks/useMutationActionButtons.d.ts +1 -8
- package/lib/typescript/react-query/hooks/useMutationActionButtons.d.ts.map +1 -1
- package/lib/typescript/react-query/hooks/useWifiState.d.ts +1 -1
- package/lib/typescript/react-query/hooks/useWifiState.d.ts.map +1 -1
- package/lib/typescript/react-query/index.d.ts +1 -0
- package/lib/typescript/react-query/index.d.ts.map +1 -1
- package/lib/typescript/react-query/stores/index.d.ts +2 -0
- package/lib/typescript/react-query/stores/index.d.ts.map +1 -0
- package/lib/typescript/react-query/stores/reactQueryEventStore.d.ts +99 -0
- package/lib/typescript/react-query/stores/reactQueryEventStore.d.ts.map +1 -0
- package/package.json +17 -3
|
@@ -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.
|
|
11
|
-
*
|
|
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
|
-
|
|
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
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
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
|
-
|
|
28
|
-
const unsubscribe = queryClient.getMutationCache().subscribe(updateMutations);
|
|
29
|
-
return () => unsubscribe();
|
|
30
|
-
}, [queryClient]);
|
|
80
|
+
}, [queryClient, updateMutations]);
|
|
31
81
|
return {
|
|
32
82
|
mutations
|
|
33
83
|
};
|
|
@@ -14,8 +14,7 @@ function useMutationActionButtons(selectedMutation) {
|
|
|
14
14
|
const queryClient = (0, _reactQuery.useQueryClient)();
|
|
15
15
|
return (0, _react.useMemo)(() => [{
|
|
16
16
|
label: "Remove",
|
|
17
|
-
|
|
18
|
-
textColorClass: "btnRemove",
|
|
17
|
+
variant: "remove",
|
|
19
18
|
disabled: false,
|
|
20
19
|
onPress: () => queryClient.getMutationCache().remove(selectedMutation)
|
|
21
20
|
}], [selectedMutation, queryClient]);
|
|
@@ -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 Query
|
|
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
|
|
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
|
|
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
|
|
10
|
+
await _sharedUi.persistentStorage.setItem(key, value);
|
|
11
11
|
};
|
|
12
12
|
const getItem = async key => {
|
|
13
|
-
return
|
|
13
|
+
return _sharedUi.persistentStorage.getItem(key);
|
|
14
14
|
};
|
|
15
15
|
// Storage operations
|
|
16
16
|
/**
|
package/lib/module/index.js
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
+
/**
|
|
4
|
+
* @buoy-gg/react-query
|
|
5
|
+
*
|
|
6
|
+
* React Query DevTools for React Native.
|
|
7
|
+
*
|
|
8
|
+
* PUBLIC API - Only these exports are supported for external use.
|
|
9
|
+
* Internal stores and event subscription mechanisms are not exported
|
|
10
|
+
* to prevent bypassing the tool's intended usage patterns.
|
|
11
|
+
*/
|
|
12
|
+
|
|
3
13
|
// Check if @tanstack/react-query is installed
|
|
4
14
|
try {
|
|
5
15
|
require("@tanstack/react-query");
|
|
@@ -7,13 +17,108 @@ try {
|
|
|
7
17
|
throw new Error("\n\n[@buoy-gg/react-query] ERROR: Missing required peer dependency\n\n" + "This package requires @tanstack/react-query to be installed.\n\n" + "Install it with:\n" + " npm install @tanstack/react-query\n" + " or\n" + " pnpm add @tanstack/react-query\n" + " or\n" + " yarn add @tanstack/react-query\n\n" + "For more information, visit: https://tanstack.com/query/latest\n");
|
|
8
18
|
}
|
|
9
19
|
|
|
10
|
-
//
|
|
20
|
+
// =============================================================================
|
|
21
|
+
// PRESET (Primary entry point for users)
|
|
22
|
+
// =============================================================================
|
|
11
23
|
export { reactQueryToolPreset, createReactQueryTool, wifiTogglePreset, createWifiToggleTool } from "./preset";
|
|
12
24
|
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
|
|
16
|
-
export
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
25
|
+
// =============================================================================
|
|
26
|
+
// QUERY CLIENT CONNECTION (Required for users to connect their QueryClient)
|
|
27
|
+
// =============================================================================
|
|
28
|
+
export { setQueryClient, disconnectQueryClient } from "./react-query/stores/reactQueryEventStore";
|
|
29
|
+
|
|
30
|
+
// =============================================================================
|
|
31
|
+
// COMPONENTS (For custom UI implementations)
|
|
32
|
+
// =============================================================================
|
|
33
|
+
|
|
34
|
+
// Main modals
|
|
35
|
+
export { ReactQueryModal } from "./react-query/components/modals/ReactQueryModal";
|
|
36
|
+
export { ReactQueryModalHeader } from "./react-query/components/modals/ReactQueryModalHeader";
|
|
37
|
+
export { QueryBrowserModal } from "./react-query/components/modals/QueryBrowserModal";
|
|
38
|
+
export { MutationBrowserModal } from "./react-query/components/modals/MutationBrowserModal";
|
|
39
|
+
export { MutationEditorModal } from "./react-query/components/modals/MutationEditorModal";
|
|
40
|
+
export { DataEditorModal } from "./react-query/components/modals/DataEditorModal";
|
|
41
|
+
export { QueryBrowserFooter } from "./react-query/components/modals/QueryBrowserFooter";
|
|
42
|
+
export { MutationBrowserFooter } from "./react-query/components/modals/MutationBrowserFooter";
|
|
43
|
+
export { SwipeIndicator } from "./react-query/components/modals/SwipeIndicator";
|
|
44
|
+
|
|
45
|
+
// Query browser components
|
|
46
|
+
export { Explorer, QueryBrowser, QueryDetails, QueryInformation, QueryActions, QueryRow, QueryStatus, QueryStatusCount, QueryDetailsChip, MutationsList, MutationDetails, MutationInformation, MutationButton, MutationStatusCount, MutationDetailsChips, ActionButton, ClearCacheButton, NetworkToggleButton, StorageStatusCount } from "./react-query/components/query-browser";
|
|
47
|
+
|
|
48
|
+
// Mode components
|
|
49
|
+
export { QueryBrowserMode } from "./react-query/components/QueryBrowserMode";
|
|
50
|
+
export { MutationBrowserMode } from "./react-query/components/MutationBrowserMode";
|
|
51
|
+
export { MutationEditorMode } from "./react-query/components/MutationEditorMode";
|
|
52
|
+
export { DataEditorMode } from "./react-query/components/DataEditorMode";
|
|
53
|
+
export { QuerySelector } from "./react-query/components/QuerySelector";
|
|
54
|
+
export { QueryDebugInfo } from "./react-query/components/QueryDebugInfo";
|
|
55
|
+
export { WifiToggle } from "./react-query/components/WifiToggle";
|
|
56
|
+
export { ReactQuerySection } from "./react-query/components/ReactQuerySection";
|
|
57
|
+
export { ReactQueryDevToolsModal } from "./react-query/components/ReactQueryDevToolsModal";
|
|
58
|
+
|
|
59
|
+
// Shared data viewer components
|
|
60
|
+
export { VirtualizedDataExplorer, DataViewer, TypeLegend } from "@buoy-gg/shared-ui/dataViewer";
|
|
61
|
+
|
|
62
|
+
// =============================================================================
|
|
63
|
+
// HOOKS (For consuming React Query data)
|
|
64
|
+
// =============================================================================
|
|
65
|
+
export { default as useAllQueries } from "./react-query/hooks/useAllQueries";
|
|
66
|
+
export { default as useAllMutations } from "./react-query/hooks/useAllMutations";
|
|
67
|
+
export { useGetQueryByQueryKey, useGetQueryByQueryKeyWithVersion } from "./react-query/hooks/useSelectedQuery";
|
|
68
|
+
export { useGetMutationById } from "./react-query/hooks/useSelectedMutation";
|
|
69
|
+
export { default as useQueryStatusCounts } from "./react-query/hooks/useQueryStatusCounts";
|
|
70
|
+
export { useStorageQueryCounts } from "./react-query/hooks/useStorageQueryCounts";
|
|
71
|
+
export { useReactQueryState } from "./react-query/hooks/useReactQueryState";
|
|
72
|
+
export { useActionButtons } from "./react-query/hooks/useActionButtons";
|
|
73
|
+
export { useMutationActionButtons } from "./react-query/hooks/useMutationActionButtons";
|
|
74
|
+
export { useModalManager } from "./react-query/hooks/useModalManager";
|
|
75
|
+
export { useModalPersistence } from "./react-query/hooks/useModalPersistence";
|
|
76
|
+
export { useWifiState } from "./react-query/hooks/useWifiState";
|
|
77
|
+
|
|
78
|
+
// =============================================================================
|
|
79
|
+
// UTILITIES (Public helpers only)
|
|
80
|
+
// =============================================================================
|
|
81
|
+
|
|
82
|
+
// Action utilities
|
|
83
|
+
export { default as invalidate } from "./react-query/utils/actions/invalidate";
|
|
84
|
+
export { default as refetch } from "./react-query/utils/actions/refetch";
|
|
85
|
+
export { default as reset } from "./react-query/utils/actions/reset";
|
|
86
|
+
export { default as remove } from "./react-query/utils/actions/remove";
|
|
87
|
+
export { default as deleteItem } from "./react-query/utils/actions/deleteItem";
|
|
88
|
+
export { default as triggerError } from "./react-query/utils/actions/triggerError";
|
|
89
|
+
export { default as triggerLoading } from "./react-query/utils/actions/triggerLoading";
|
|
90
|
+
|
|
91
|
+
// Query status utilities
|
|
92
|
+
export * from "./react-query/utils/getQueryStatusLabel";
|
|
93
|
+
export * from "./react-query/utils/getQueryStatusColor";
|
|
94
|
+
|
|
95
|
+
// Storage utilities
|
|
96
|
+
export * from "./react-query/utils/getStorageQueryCounts";
|
|
97
|
+
export * from "./react-query/utils/storageQueryUtils";
|
|
98
|
+
export * from "./react-query/utils/modalStorageOperations";
|
|
99
|
+
|
|
100
|
+
// Data manipulation utilities
|
|
101
|
+
export * from "./react-query/utils/updateNestedDataByPath";
|
|
102
|
+
export * from "./react-query/utils/deleteNestedDataByPath";
|
|
103
|
+
export { safeStringify, displayValue, parseDisplayValue } from "@buoy-gg/shared-ui";
|
|
104
|
+
|
|
105
|
+
// =============================================================================
|
|
106
|
+
// TYPES
|
|
107
|
+
// =============================================================================
|
|
108
|
+
|
|
109
|
+
export { isPlainObject } from "./react-query/types/types";
|
|
110
|
+
|
|
111
|
+
// =============================================================================
|
|
112
|
+
// INTERNAL EXPORTS (For @buoy-gg/* packages only - not part of public API)
|
|
113
|
+
// =============================================================================
|
|
114
|
+
/** @internal */
|
|
115
|
+
export { reactQueryEventStore } from "./react-query/stores/reactQueryEventStore";
|
|
116
|
+
|
|
117
|
+
// =============================================================================
|
|
118
|
+
// NOT EXPORTED (Internal controls)
|
|
119
|
+
// =============================================================================
|
|
120
|
+
// The following are intentionally NOT exported to prevent bypassing:
|
|
121
|
+
// - getReactQueryEvents (internal store access)
|
|
122
|
+
// - subscribeToReactQueryEvents (internal subscription)
|
|
123
|
+
// - clearReactQueryEvents (internal store control)
|
|
124
|
+
// - isReactQueryConnected (internal state query)
|
package/lib/module/preset.js
CHANGED
|
@@ -21,7 +21,7 @@ import { QueryIcon } from "@buoy-gg/floating-tools-core";
|
|
|
21
21
|
import { Wifi } from "@buoy-gg/shared-ui";
|
|
22
22
|
import { ReactQueryDevToolsModal } from "./react-query/components/ReactQueryDevToolsModal";
|
|
23
23
|
import { onlineManager } from "@tanstack/react-query";
|
|
24
|
-
import { devToolsStorageKeys,
|
|
24
|
+
import { devToolsStorageKeys, persistentStorage } from "@buoy-gg/shared-ui";
|
|
25
25
|
|
|
26
26
|
// Empty component for toggle-only mode
|
|
27
27
|
const EmptyComponent = () => null;
|
|
@@ -29,7 +29,7 @@ const EmptyComponent = () => null;
|
|
|
29
29
|
// Save WiFi state to storage
|
|
30
30
|
const saveWifiState = async enabled => {
|
|
31
31
|
try {
|
|
32
|
-
await
|
|
32
|
+
await persistentStorage.setItem(devToolsStorageKeys.settings.wifiEnabled(), enabled.toString());
|
|
33
33
|
} catch (error) {
|
|
34
34
|
// Failed to save WiFi state
|
|
35
35
|
}
|