@buoy-gg/react-query 3.0.1 → 3.0.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.
Files changed (47) hide show
  1. package/lib/commonjs/index.js +20 -0
  2. package/lib/commonjs/preset.js +23 -0
  3. package/lib/commonjs/react-query/components/modals/MutationBrowserFooter.js +4 -2
  4. package/lib/commonjs/react-query/components/modals/QueryBrowserFooter.js +5 -2
  5. package/lib/commonjs/react-query/components/modals/ReactQueryModalHeader.js +24 -1
  6. package/lib/commonjs/react-query/components/modals/SwipeIndicator.js +2 -2
  7. package/lib/commonjs/react-query/components/query-browser/MutationStatusCount.js +10 -5
  8. package/lib/commonjs/react-query/components/query-browser/QueryStatus.js +25 -5
  9. package/lib/commonjs/react-query/components/query-browser/QueryStatusCount.js +12 -1
  10. package/lib/commonjs/react-query/sync/dehydrate.js +56 -0
  11. package/lib/commonjs/react-query/sync/reactQuerySyncAdapter.js +132 -0
  12. package/lib/commonjs/react-query/sync/useReactQuerySyncAdapter.js +26 -0
  13. package/lib/module/index.js +5 -0
  14. package/lib/module/preset.js +23 -0
  15. package/lib/module/react-query/components/modals/MutationBrowserFooter.js +4 -2
  16. package/lib/module/react-query/components/modals/QueryBrowserFooter.js +5 -2
  17. package/lib/module/react-query/components/modals/ReactQueryModalHeader.js +24 -1
  18. package/lib/module/react-query/components/modals/SwipeIndicator.js +2 -1
  19. package/lib/module/react-query/components/query-browser/MutationStatusCount.js +10 -5
  20. package/lib/module/react-query/components/query-browser/QueryStatus.js +25 -5
  21. package/lib/module/react-query/components/query-browser/QueryStatusCount.js +12 -1
  22. package/lib/module/react-query/sync/dehydrate.js +52 -0
  23. package/lib/module/react-query/sync/reactQuerySyncAdapter.js +127 -0
  24. package/lib/module/react-query/sync/useReactQuerySyncAdapter.js +23 -0
  25. package/lib/typescript/index.d.ts +3 -0
  26. package/lib/typescript/index.d.ts.map +1 -1
  27. package/lib/typescript/preset.d.ts.map +1 -1
  28. package/lib/typescript/react-query/components/modals/MutationBrowserFooter.d.ts +3 -1
  29. package/lib/typescript/react-query/components/modals/MutationBrowserFooter.d.ts.map +1 -1
  30. package/lib/typescript/react-query/components/modals/QueryBrowserFooter.d.ts +4 -1
  31. package/lib/typescript/react-query/components/modals/QueryBrowserFooter.d.ts.map +1 -1
  32. package/lib/typescript/react-query/components/modals/ReactQueryModalHeader.d.ts +6 -1
  33. package/lib/typescript/react-query/components/modals/ReactQueryModalHeader.d.ts.map +1 -1
  34. package/lib/typescript/react-query/components/modals/SwipeIndicator.d.ts.map +1 -1
  35. package/lib/typescript/react-query/components/query-browser/MutationStatusCount.d.ts +2 -0
  36. package/lib/typescript/react-query/components/query-browser/MutationStatusCount.d.ts.map +1 -1
  37. package/lib/typescript/react-query/components/query-browser/QueryStatus.d.ts +5 -0
  38. package/lib/typescript/react-query/components/query-browser/QueryStatus.d.ts.map +1 -1
  39. package/lib/typescript/react-query/components/query-browser/QueryStatusCount.d.ts +2 -0
  40. package/lib/typescript/react-query/components/query-browser/QueryStatusCount.d.ts.map +1 -1
  41. package/lib/typescript/react-query/sync/dehydrate.d.ts +30 -0
  42. package/lib/typescript/react-query/sync/dehydrate.d.ts.map +1 -0
  43. package/lib/typescript/react-query/sync/reactQuerySyncAdapter.d.ts +34 -0
  44. package/lib/typescript/react-query/sync/reactQuerySyncAdapter.d.ts.map +1 -0
  45. package/lib/typescript/react-query/sync/useReactQuerySyncAdapter.d.ts +9 -0
  46. package/lib/typescript/react-query/sync/useReactQuerySyncAdapter.d.ts.map +1 -0
  47. package/package.json +3 -3
@@ -11,6 +11,8 @@ var _exportNames = {
11
11
  setQueryClient: true,
12
12
  disconnectQueryClient: true,
13
13
  reactQueryEventStore: true,
14
+ createReactQuerySyncAdapter: true,
15
+ useReactQuerySyncAdapter: true,
14
16
  ReactQueryModal: true,
15
17
  ReactQueryModalHeader: true,
16
18
  QueryBrowserModal: true,
@@ -316,6 +318,12 @@ Object.defineProperty(exports, "WifiToggle", {
316
318
  return _WifiToggle.WifiToggle;
317
319
  }
318
320
  });
321
+ Object.defineProperty(exports, "createReactQuerySyncAdapter", {
322
+ enumerable: true,
323
+ get: function () {
324
+ return _reactQuerySyncAdapter.createReactQuerySyncAdapter;
325
+ }
326
+ });
319
327
  Object.defineProperty(exports, "createReactQueryTool", {
320
328
  enumerable: true,
321
329
  get: function () {
@@ -484,6 +492,12 @@ Object.defineProperty(exports, "useReactQueryState", {
484
492
  return _useReactQueryState.useReactQueryState;
485
493
  }
486
494
  });
495
+ Object.defineProperty(exports, "useReactQuerySyncAdapter", {
496
+ enumerable: true,
497
+ get: function () {
498
+ return _useReactQuerySyncAdapter.useReactQuerySyncAdapter;
499
+ }
500
+ });
487
501
  Object.defineProperty(exports, "useStorageQueryCounts", {
488
502
  enumerable: true,
489
503
  get: function () {
@@ -504,6 +518,8 @@ Object.defineProperty(exports, "wifiTogglePreset", {
504
518
  });
505
519
  var _preset = require("./preset");
506
520
  var _reactQueryEventStore = require("./react-query/stores/reactQueryEventStore");
521
+ var _reactQuerySyncAdapter = require("./react-query/sync/reactQuerySyncAdapter");
522
+ var _useReactQuerySyncAdapter = require("./react-query/sync/useReactQuerySyncAdapter");
507
523
  var _ReactQueryModal = require("./react-query/components/modals/ReactQueryModal");
508
524
  var _ReactQueryModalHeader = require("./react-query/components/modals/ReactQueryModalHeader");
509
525
  var _QueryBrowserModal = require("./react-query/components/modals/QueryBrowserModal");
@@ -655,6 +671,10 @@ try {
655
671
  // QUERY CLIENT CONNECTION (Required for users to connect their QueryClient)
656
672
  // =============================================================================
657
673
 
674
+ // =============================================================================
675
+ // EXTERNAL SYNC (Adapter factory for @buoy-gg/external-sync's useExternalSync)
676
+ // =============================================================================
677
+
658
678
  // =============================================================================
659
679
  // COMPONENTS (For custom UI implementations)
660
680
  // =============================================================================
@@ -41,6 +41,29 @@ const saveWifiState = async enabled => {
41
41
  }
42
42
  };
43
43
 
44
+ /**
45
+ * Restore the persisted WiFi state into onlineManager on app load.
46
+ *
47
+ * The toggle is rendered as a `toggle-only` tool whose state lives in
48
+ * `onlineManager`, not in a mounted React component. The `useWifiState` hook
49
+ * only restores when its component (the modal) mounts, so without this the
50
+ * persisted offline state is lost on reload and defaults back to online.
51
+ * Running this at module load ensures the saved state is applied eagerly.
52
+ */
53
+ const restoreWifiState = async () => {
54
+ try {
55
+ const savedState = await _sharedUi.persistentStorage.getItem(_sharedUi.devToolsStorageKeys.settings.wifiEnabled());
56
+ if (savedState !== null) {
57
+ _reactQuery.onlineManager.setOnline(savedState === "true");
58
+ }
59
+ } catch (error) {
60
+ // Failed to restore WiFi state
61
+ }
62
+ };
63
+
64
+ // Eagerly restore persisted WiFi state on import so offline mode survives reloads.
65
+ restoreWifiState();
66
+
44
67
  /**
45
68
  * WiFi icon component - uses hooks to subscribe to onlineManager changes.
46
69
  *
@@ -21,7 +21,8 @@ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e
21
21
  function MutationBrowserFooter({
22
22
  activeFilter,
23
23
  onFilterChange,
24
- modalMode
24
+ modalMode,
25
+ size = "default"
25
26
  }) {
26
27
  const isFloatingMode = modalMode === "floating";
27
28
  const insets = (0, _sharedUi.useSafeAreaInsets)({
@@ -43,7 +44,8 @@ function MutationBrowserFooter({
43
44
  style: styles.filterContainer,
44
45
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_MutationStatusCount.default, {
45
46
  activeFilter: activeFilter,
46
- onFilterChange: onFilterChange
47
+ onFilterChange: onFilterChange,
48
+ size: size
47
49
  })
48
50
  })
49
51
  }, `footer-${isFloatingMode ? "floating" : "docked"}`);
@@ -20,7 +20,9 @@ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e
20
20
  function QueryBrowserFooter({
21
21
  activeFilter,
22
22
  onFilterChange,
23
- isFloatingMode = true // Default to floating mode if not specified
23
+ isFloatingMode = true,
24
+ // Default to floating mode if not specified
25
+ size = "default"
24
26
  }) {
25
27
  // Use safe area insets with a minimum bottom padding of 16 for docked mode
26
28
  // This ensures proper spacing even on resized simulators or devices without home indicator
@@ -37,7 +39,8 @@ function QueryBrowserFooter({
37
39
  style: styles.filterContainer,
38
40
  children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_QueryStatusCount.default, {
39
41
  activeFilter: activeFilter,
40
- onFilterChange: onFilterChange
42
+ onFilterChange: onFilterChange,
43
+ size: size
41
44
  })
42
45
  })
43
46
  });
@@ -7,6 +7,7 @@ exports.ReactQueryModalHeader = ReactQueryModalHeader;
7
7
  var _sharedUi = require("@buoy-gg/shared-ui");
8
8
  var _react = require("react");
9
9
  var _reactNative = require("react-native");
10
+ var _WifiToggle = require("../WifiToggle");
10
11
  var _jsxRuntime = require("react/jsx-runtime");
11
12
  /**
12
13
  * Shared header for all React Query modals. Handles tab switching when browsing and presents
@@ -22,7 +23,8 @@ function ReactQueryModalHeader({
22
23
  onSearchChange,
23
24
  onFilterPress,
24
25
  hasActiveFilters = false,
25
- onClearCache
26
+ onClearCache,
27
+ showWifiToggle = false
26
28
  }) {
27
29
  const [isSearchActive, setIsSearchActive] = (0, _react.useState)(false);
28
30
  const searchInputRef = (0, _react.useRef)(null);
@@ -112,6 +114,18 @@ function ReactQueryModalHeader({
112
114
  color: _sharedUi.buoyColors.textSecondary
113
115
  })
114
116
  }) : null]
117
+ }) : showWifiToggle ? /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
118
+ style: styles.tabRow,
119
+ children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
120
+ style: styles.tabSelectorWrap,
121
+ children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.TabSelector, {
122
+ tabs: tabs,
123
+ activeTab: activeTab,
124
+ onTabChange: tab => onTabChange(tab)
125
+ })
126
+ }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_WifiToggle.WifiToggle, {
127
+ size: 16
128
+ })]
115
129
  }) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.TabSelector, {
116
130
  tabs: tabs,
117
131
  activeTab: activeTab,
@@ -148,6 +162,15 @@ function ReactQueryModalHeader({
148
162
  });
149
163
  }
150
164
  const styles = _reactNative.StyleSheet.create({
165
+ tabRow: {
166
+ flex: 1,
167
+ flexDirection: "row",
168
+ alignItems: "center",
169
+ gap: 12
170
+ },
171
+ tabSelectorWrap: {
172
+ flex: 1
173
+ },
151
174
  headerSearchContainer: {
152
175
  flexDirection: "row",
153
176
  alignItems: "center",
@@ -5,8 +5,8 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.SwipeIndicator = SwipeIndicator;
7
7
  var _reactNative = require("react-native");
8
- var _react = require("react");
9
8
  var _sharedUi = require("@buoy-gg/shared-ui");
9
+ var _react = require("react");
10
10
  var _jsxRuntime = require("react/jsx-runtime");
11
11
  /**
12
12
  * Morphing swipe indicator – thin line ➜ pill ➜ circle with a pop-out cue at
@@ -188,7 +188,7 @@ function SwipeIndicator({
188
188
  }
189
189
  const styles = _reactNative.StyleSheet.create({
190
190
  container: {
191
- ..._reactNative.StyleSheet.absoluteFillObject,
191
+ ..._sharedUi.absoluteFill,
192
192
  zIndex: 1000,
193
193
  justifyContent: "center",
194
194
  alignItems: "center"
@@ -16,7 +16,8 @@ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e
16
16
  */
17
17
  const MutationStatusCount = ({
18
18
  activeFilter,
19
- onFilterChange
19
+ onFilterChange,
20
+ size = "default"
20
21
  }) => {
21
22
  const {
22
23
  pending,
@@ -62,7 +63,8 @@ const MutationStatusCount = ({
62
63
  isActive: activeFilter === "pending",
63
64
  onPress: event => handleFilterClick("pending", event),
64
65
  onTouchStart: handleTouchStart,
65
- showLabel: true
66
+ showLabel: true,
67
+ size: size
66
68
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_QueryStatus.default, {
67
69
  label: "Success",
68
70
  color: "green",
@@ -70,7 +72,8 @@ const MutationStatusCount = ({
70
72
  isActive: activeFilter === "success",
71
73
  onPress: event => handleFilterClick("success", event),
72
74
  onTouchStart: handleTouchStart,
73
- showLabel: true
75
+ showLabel: true,
76
+ size: size
74
77
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_QueryStatus.default, {
75
78
  label: "Error",
76
79
  color: "red",
@@ -78,7 +81,8 @@ const MutationStatusCount = ({
78
81
  isActive: activeFilter === "error",
79
82
  onPress: event => handleFilterClick("error", event),
80
83
  onTouchStart: handleTouchStart,
81
- showLabel: true
84
+ showLabel: true,
85
+ size: size
82
86
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_QueryStatus.default, {
83
87
  label: "Paused",
84
88
  color: "purple",
@@ -86,7 +90,8 @@ const MutationStatusCount = ({
86
90
  isActive: activeFilter === "paused",
87
91
  onPress: event => handleFilterClick("paused", event),
88
92
  onTouchStart: handleTouchStart,
89
- showLabel: true
93
+ showLabel: true,
94
+ size: size
90
95
  })]
91
96
  })
92
97
  });
@@ -17,8 +17,10 @@ const QueryStatus = ({
17
17
  showLabel = true,
18
18
  isActive = false,
19
19
  onPress,
20
- onTouchStart
20
+ onTouchStart,
21
+ size = "default"
21
22
  }) => {
23
+ const isLarge = size === "large";
22
24
  // Buoy theme color mapping for status indicators
23
25
  const getStatusColors = colorName => {
24
26
  const colorMap = {
@@ -64,7 +66,7 @@ const QueryStatus = ({
64
66
  const statusColors = getStatusColors(color);
65
67
  return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.TouchableOpacity, {
66
68
  "sentry-label": "ignore devtools query status",
67
- style: [styles.queryStatusTag, isActive && {
69
+ style: [styles.queryStatusTag, isLarge && styles.queryStatusTagLarge, isActive && {
68
70
  backgroundColor: statusColors.dot + "15",
69
71
  borderColor: statusColors.dot + "40"
70
72
  }],
@@ -73,16 +75,16 @@ const QueryStatus = ({
73
75
  onPressIn: onTouchStart,
74
76
  activeOpacity: 0.7,
75
77
  children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
76
- style: [styles.dot, {
78
+ style: [styles.dot, isLarge && styles.dotLarge, {
77
79
  backgroundColor: statusColors.dot
78
80
  }]
79
81
  }), showLabel && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
80
- style: [styles.label],
82
+ style: [styles.label, isLarge && styles.labelLarge],
81
83
  numberOfLines: 1,
82
84
  ellipsizeMode: "tail",
83
85
  children: label
84
86
  }), count > 0 && /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
85
- style: [styles.count, {
87
+ style: [styles.count, isLarge && styles.countLarge, {
86
88
  color: statusColors.dot
87
89
  }],
88
90
  numberOfLines: 1,
@@ -103,23 +105,41 @@ const styles = _reactNative.StyleSheet.create({
103
105
  borderWidth: 1,
104
106
  borderColor: _sharedUi.buoyColors.textMuted + "20"
105
107
  },
108
+ queryStatusTagLarge: {
109
+ borderRadius: 18,
110
+ paddingHorizontal: 16,
111
+ paddingVertical: 9,
112
+ height: 40,
113
+ gap: 9
114
+ },
106
115
  dot: {
107
116
  width: 6,
108
117
  height: 6,
109
118
  borderRadius: 3
110
119
  },
120
+ dotLarge: {
121
+ width: 9,
122
+ height: 9,
123
+ borderRadius: 4.5
124
+ },
111
125
  label: {
112
126
  fontSize: 11,
113
127
  fontWeight: "500",
114
128
  color: _sharedUi.buoyColors.textSecondary,
115
129
  fontFamily: "system"
116
130
  },
131
+ labelLarge: {
132
+ fontSize: 15
133
+ },
117
134
  count: {
118
135
  fontSize: 11,
119
136
  fontVariant: ["tabular-nums"],
120
137
  fontWeight: "600",
121
138
  marginLeft: "auto",
122
139
  fontFamily: "system"
140
+ },
141
+ countLarge: {
142
+ fontSize: 15
123
143
  }
124
144
  });
125
145
  var _default = exports.default = QueryStatus;
@@ -15,7 +15,8 @@ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e
15
15
  */
16
16
  const QueryStatusCount = ({
17
17
  activeFilter,
18
- onFilterChange
18
+ onFilterChange,
19
+ size = "default"
19
20
  }) => {
20
21
  const {
21
22
  fresh,
@@ -69,6 +70,8 @@ const QueryStatusCount = ({
69
70
  onPress: event => handleFilterClick("fresh", event),
70
71
  onTouchStart: handleTouchStart,
71
72
  showLabel: true // Always show labels now
73
+ ,
74
+ size: size
72
75
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_QueryStatus.default, {
73
76
  label: "Loading",
74
77
  color: "blue",
@@ -77,6 +80,8 @@ const QueryStatusCount = ({
77
80
  onPress: event => handleFilterClick("fetching", event),
78
81
  onTouchStart: handleTouchStart,
79
82
  showLabel: true // Always show labels now
83
+ ,
84
+ size: size
80
85
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_QueryStatus.default, {
81
86
  label: "Paused",
82
87
  color: "purple",
@@ -85,6 +90,8 @@ const QueryStatusCount = ({
85
90
  onPress: event => handleFilterClick("paused", event),
86
91
  onTouchStart: handleTouchStart,
87
92
  showLabel: true // Always show labels now
93
+ ,
94
+ size: size
88
95
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_QueryStatus.default, {
89
96
  label: "Stale",
90
97
  color: "yellow",
@@ -93,6 +100,8 @@ const QueryStatusCount = ({
93
100
  onPress: event => handleFilterClick("stale", event),
94
101
  onTouchStart: handleTouchStart,
95
102
  showLabel: true // Always show labels now
103
+ ,
104
+ size: size
96
105
  }), /*#__PURE__*/(0, _jsxRuntime.jsx)(_QueryStatus.default, {
97
106
  label: "Idle",
98
107
  color: "gray",
@@ -101,6 +110,8 @@ const QueryStatusCount = ({
101
110
  onPress: event => handleFilterClick("inactive", event),
102
111
  onTouchStart: handleTouchStart,
103
112
  showLabel: true // Always show labels now
113
+ ,
114
+ size: size
104
115
  })]
105
116
  })
106
117
  });
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.dehydrateQueryClient = dehydrateQueryClient;
7
+ /**
8
+ * Dehydration for external sync — ported from buoy-desktop's
9
+ * react-query-external-sync/hydration.ts so the desktop dashboard can
10
+ * hydrate an identical mirror of the device's QueryClient.
11
+ */
12
+
13
+ function dehydrateQueryClient(client) {
14
+ const mutations = client.getMutationCache().getAll().map(mutation => dehydrateMutation(mutation));
15
+ const queries = client.getQueryCache().getAll().map(query => dehydrateQuery(query));
16
+ return {
17
+ mutations,
18
+ queries
19
+ };
20
+ }
21
+ function dehydrateMutation(mutation) {
22
+ return {
23
+ mutationId: mutation.mutationId,
24
+ mutationKey: mutation.options.mutationKey,
25
+ state: mutation.state,
26
+ ...(mutation.options.scope && {
27
+ scope: mutation.options.scope
28
+ }),
29
+ ...(mutation.meta && {
30
+ meta: mutation.meta
31
+ })
32
+ };
33
+ }
34
+ function dehydrateQuery(query) {
35
+ const observerStates = query.observers.map(observer => ({
36
+ queryHash: query.queryHash,
37
+ options: observer.options,
38
+ // Remove queryFn from observer options so the dashboard can't accidentally
39
+ // run device fetch functions (they aren't serializable anyway)
40
+ queryFn: undefined
41
+ }));
42
+ return {
43
+ state: {
44
+ ...query.state,
45
+ ...(query.state.data !== undefined && {
46
+ data: query.state.data
47
+ })
48
+ },
49
+ queryKey: query.queryKey,
50
+ queryHash: query.queryHash,
51
+ ...(query.meta && {
52
+ meta: query.meta
53
+ }),
54
+ observers: observerStates
55
+ };
56
+ }
@@ -0,0 +1,132 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.createReactQuerySyncAdapter = createReactQuerySyncAdapter;
7
+ var _reactQuery = require("@tanstack/react-query");
8
+ var _dehydrate = require("./dehydrate");
9
+ /**
10
+ * Sync adapter for the React Query tool, consumed by @buoy-gg/external-sync's
11
+ * `useExternalSync` (structurally matches its ToolSyncAdapter interface so
12
+ * this package doesn't need a dependency on it).
13
+ *
14
+ * Action handlers are ported from buoy-desktop's react-query-external-sync
15
+ * (useSyncQueries.ts) so the dashboard keeps identical behavior, including
16
+ * the trigger/restore loading and error simulations used by the TanStack
17
+ * devtools UI.
18
+ */
19
+
20
+ function createReactQuerySyncAdapter(queryClient) {
21
+ const getQuery = params => {
22
+ const {
23
+ queryHash
24
+ } = params;
25
+ const query = queryClient.getQueryCache().get(queryHash);
26
+ if (!query) {
27
+ throw new Error(`Query with hash "${queryHash}" not found`);
28
+ }
29
+ return query;
30
+ };
31
+ return {
32
+ version: 1,
33
+ getSnapshot: () => ({
34
+ dehydratedState: (0, _dehydrate.dehydrateQueryClient)(queryClient),
35
+ isOnlineManagerOnline: _reactQuery.onlineManager.isOnline()
36
+ }),
37
+ subscribe: onChange => {
38
+ const unsubQueries = queryClient.getQueryCache().subscribe(onChange);
39
+ const unsubMutations = queryClient.getMutationCache().subscribe(onChange);
40
+ const unsubOnline = _reactQuery.onlineManager.subscribe(onChange);
41
+ return () => {
42
+ unsubQueries();
43
+ unsubMutations();
44
+ unsubOnline();
45
+ };
46
+ },
47
+ actions: {
48
+ refetch: params => {
49
+ const query = getQuery(params);
50
+ // Swallow fetch rejections — the resulting error state syncs anyway
51
+ return query.fetch().catch(() => undefined);
52
+ },
53
+ invalidate: params => queryClient.invalidateQueries(getQuery(params)),
54
+ reset: params => queryClient.resetQueries(getQuery(params)),
55
+ remove: params => {
56
+ queryClient.removeQueries(getQuery(params));
57
+ },
58
+ setQueryData: params => {
59
+ const {
60
+ queryKey,
61
+ data
62
+ } = params;
63
+ queryClient.setQueryData(queryKey, data, {
64
+ updatedAt: Date.now()
65
+ });
66
+ },
67
+ triggerError: params => {
68
+ const query = getQuery(params);
69
+ const __previousQueryOptions = query.options;
70
+ query.setState({
71
+ status: "error",
72
+ error: new Error("Unknown error from devtools"),
73
+ fetchMeta: {
74
+ ...query.state.fetchMeta,
75
+ // @ts-expect-error This does exist
76
+ __previousQueryOptions
77
+ }
78
+ });
79
+ },
80
+ restoreError: params => queryClient.resetQueries(getQuery(params)),
81
+ triggerLoading: params => {
82
+ const query = getQuery(params);
83
+ const __previousQueryOptions = query.options;
84
+ // Trigger a fetch in order to trigger suspense as well
85
+ query.fetch({
86
+ ...__previousQueryOptions,
87
+ queryFn: () => new Promise(() => {
88
+ // Never resolve — simulates perpetual loading
89
+ }),
90
+ gcTime: -1
91
+ }).catch(() => undefined);
92
+ query.setState({
93
+ data: undefined,
94
+ status: "pending",
95
+ fetchMeta: {
96
+ ...query.state.fetchMeta,
97
+ // @ts-expect-error This does exist
98
+ __previousQueryOptions
99
+ }
100
+ });
101
+ },
102
+ restoreLoading: params => {
103
+ const query = getQuery(params);
104
+ const previousState = query.state;
105
+ const previousOptions = query.state.fetchMeta ? query.state.fetchMeta.__previousQueryOptions : null;
106
+ query.cancel({
107
+ silent: true
108
+ });
109
+ query.setState({
110
+ ...previousState,
111
+ fetchStatus: "idle",
112
+ fetchMeta: null
113
+ });
114
+ if (previousOptions) {
115
+ query.fetch(previousOptions).catch(() => undefined);
116
+ }
117
+ },
118
+ clearQueryCache: () => {
119
+ queryClient.getQueryCache().clear();
120
+ },
121
+ clearMutationCache: () => {
122
+ queryClient.getMutationCache().clear();
123
+ },
124
+ setOnline: params => {
125
+ const {
126
+ online
127
+ } = params;
128
+ _reactQuery.onlineManager.setOnline(online);
129
+ }
130
+ }
131
+ };
132
+ }
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+
3
+ Object.defineProperty(exports, "__esModule", {
4
+ value: true
5
+ });
6
+ exports.useReactQuerySyncAdapter = useReactQuerySyncAdapter;
7
+ var _react = require("react");
8
+ var _reactQuery = require("@tanstack/react-query");
9
+ var _reactQuerySyncAdapter = require("./reactQuerySyncAdapter");
10
+ /**
11
+ * Context-based variant of createReactQuerySyncAdapter for zero-config
12
+ * wiring (FloatingDevTools' auto external sync): reads the QueryClient from
13
+ * the surrounding QueryClientProvider. Returns null when rendered outside a
14
+ * provider so callers can skip registering the query tool.
15
+ */
16
+ function useReactQuerySyncAdapter() {
17
+ let queryClient;
18
+ try {
19
+ // Just a context read — throws only when there is no provider above us,
20
+ // which never changes for a mounted tree, so hook order stays stable.
21
+ queryClient = (0, _reactQuery.useQueryClient)();
22
+ } catch {
23
+ queryClient = null;
24
+ }
25
+ return (0, _react.useMemo)(() => queryClient ? (0, _reactQuerySyncAdapter.createReactQuerySyncAdapter)(queryClient) : null, [queryClient]);
26
+ }
@@ -27,6 +27,11 @@ export { reactQueryToolPreset, createReactQueryTool, wifiTogglePreset, createWif
27
27
  // =============================================================================
28
28
  export { setQueryClient, disconnectQueryClient } from "./react-query/stores/reactQueryEventStore";
29
29
 
30
+ // =============================================================================
31
+ // EXTERNAL SYNC (Adapter factory for @buoy-gg/external-sync's useExternalSync)
32
+ // =============================================================================
33
+ export { createReactQuerySyncAdapter } from "./react-query/sync/reactQuerySyncAdapter";
34
+ export { useReactQuerySyncAdapter } from "./react-query/sync/useReactQuerySyncAdapter";
30
35
  // =============================================================================
31
36
  // COMPONENTS (For custom UI implementations)
32
37
  // =============================================================================
@@ -34,6 +34,29 @@ const saveWifiState = async enabled => {
34
34
  // Failed to save WiFi state
35
35
  }
36
36
  };
37
+
38
+ /**
39
+ * Restore the persisted WiFi state into onlineManager on app load.
40
+ *
41
+ * The toggle is rendered as a `toggle-only` tool whose state lives in
42
+ * `onlineManager`, not in a mounted React component. The `useWifiState` hook
43
+ * only restores when its component (the modal) mounts, so without this the
44
+ * persisted offline state is lost on reload and defaults back to online.
45
+ * Running this at module load ensures the saved state is applied eagerly.
46
+ */
47
+ const restoreWifiState = async () => {
48
+ try {
49
+ const savedState = await persistentStorage.getItem(devToolsStorageKeys.settings.wifiEnabled());
50
+ if (savedState !== null) {
51
+ onlineManager.setOnline(savedState === "true");
52
+ }
53
+ } catch (error) {
54
+ // Failed to restore WiFi state
55
+ }
56
+ };
57
+
58
+ // Eagerly restore persisted WiFi state on import so offline mode survives reloads.
59
+ restoreWifiState();
37
60
  import { useState, useEffect } from "react";
38
61
 
39
62
  /**
@@ -16,7 +16,8 @@ import { jsx as _jsx } from "react/jsx-runtime";
16
16
  export function MutationBrowserFooter({
17
17
  activeFilter,
18
18
  onFilterChange,
19
- modalMode
19
+ modalMode,
20
+ size = "default"
20
21
  }) {
21
22
  const isFloatingMode = modalMode === "floating";
22
23
  const insets = useSafeAreaInsets({
@@ -38,7 +39,8 @@ export function MutationBrowserFooter({
38
39
  style: styles.filterContainer,
39
40
  children: /*#__PURE__*/_jsx(MutationStatusCount, {
40
41
  activeFilter: activeFilter,
41
- onFilterChange: onFilterChange
42
+ onFilterChange: onFilterChange,
43
+ size: size
42
44
  })
43
45
  })
44
46
  }, `footer-${isFloatingMode ? "floating" : "docked"}`);
@@ -15,7 +15,9 @@ import { jsx as _jsx } from "react/jsx-runtime";
15
15
  export function QueryBrowserFooter({
16
16
  activeFilter,
17
17
  onFilterChange,
18
- isFloatingMode = true // Default to floating mode if not specified
18
+ isFloatingMode = true,
19
+ // Default to floating mode if not specified
20
+ size = "default"
19
21
  }) {
20
22
  // Use safe area insets with a minimum bottom padding of 16 for docked mode
21
23
  // This ensures proper spacing even on resized simulators or devices without home indicator
@@ -32,7 +34,8 @@ export function QueryBrowserFooter({
32
34
  style: styles.filterContainer,
33
35
  children: /*#__PURE__*/_jsx(QueryStatusCount, {
34
36
  activeFilter: activeFilter,
35
- onFilterChange: onFilterChange
37
+ onFilterChange: onFilterChange,
38
+ size: size
36
39
  })
37
40
  })
38
41
  });