@buoy-gg/core 6.0.0 → 7.0.0
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/README.md +91 -28
- package/lib/commonjs/floatingMenu/DevToolsSettingsModal.js +64 -0
- package/lib/commonjs/floatingMenu/FloatingDevTools.js +34 -10
- package/lib/commonjs/floatingMenu/FloatingDevTools.web.js +7 -1
- package/lib/commonjs/floatingMenu/autoDiscoverPresets.js +30 -15
- package/lib/commonjs/floatingMenu/autoExternalSync.js +43 -34
- package/lib/commonjs/floatingMenu/optionalRequire.js +33 -0
- package/lib/commonjs/floatingMenu/useDesktopSyncStatus.js +28 -0
- package/lib/module/floatingMenu/DevToolsSettingsModal.js +65 -1
- package/lib/module/floatingMenu/FloatingDevTools.js +35 -11
- package/lib/module/floatingMenu/FloatingDevTools.web.js +7 -1
- package/lib/module/floatingMenu/autoDiscoverPresets.js +31 -15
- package/lib/module/floatingMenu/autoExternalSync.js +44 -34
- package/lib/module/floatingMenu/optionalRequire.js +29 -0
- package/lib/module/floatingMenu/useDesktopSyncStatus.js +25 -0
- package/lib/typescript/commonjs/floatingMenu/DevToolsSettingsModal.d.ts.map +1 -1
- package/lib/typescript/commonjs/floatingMenu/FloatingDevTools.d.ts +18 -4
- package/lib/typescript/commonjs/floatingMenu/FloatingDevTools.d.ts.map +1 -1
- package/lib/typescript/commonjs/floatingMenu/FloatingDevTools.web.d.ts +6 -1
- package/lib/typescript/commonjs/floatingMenu/FloatingDevTools.web.d.ts.map +1 -1
- package/lib/typescript/commonjs/floatingMenu/autoDiscoverPresets.d.ts.map +1 -1
- package/lib/typescript/commonjs/floatingMenu/autoExternalSync.d.ts +6 -1
- package/lib/typescript/commonjs/floatingMenu/autoExternalSync.d.ts.map +1 -1
- package/lib/typescript/commonjs/floatingMenu/optionalRequire.d.ts +12 -0
- package/lib/typescript/commonjs/floatingMenu/optionalRequire.d.ts.map +1 -0
- package/lib/typescript/commonjs/floatingMenu/useDesktopSyncStatus.d.ts +14 -0
- package/lib/typescript/commonjs/floatingMenu/useDesktopSyncStatus.d.ts.map +1 -0
- package/lib/typescript/module/floatingMenu/DevToolsSettingsModal.d.ts.map +1 -1
- package/lib/typescript/module/floatingMenu/FloatingDevTools.d.ts +18 -4
- package/lib/typescript/module/floatingMenu/FloatingDevTools.d.ts.map +1 -1
- package/lib/typescript/module/floatingMenu/FloatingDevTools.web.d.ts +6 -1
- package/lib/typescript/module/floatingMenu/FloatingDevTools.web.d.ts.map +1 -1
- package/lib/typescript/module/floatingMenu/autoDiscoverPresets.d.ts.map +1 -1
- package/lib/typescript/module/floatingMenu/autoExternalSync.d.ts +6 -1
- package/lib/typescript/module/floatingMenu/autoExternalSync.d.ts.map +1 -1
- package/lib/typescript/module/floatingMenu/optionalRequire.d.ts +12 -0
- package/lib/typescript/module/floatingMenu/optionalRequire.d.ts.map +1 -0
- package/lib/typescript/module/floatingMenu/useDesktopSyncStatus.d.ts +14 -0
- package/lib/typescript/module/floatingMenu/useDesktopSyncStatus.d.ts.map +1 -0
- package/package.json +19 -8
package/README.md
CHANGED
|
@@ -1,43 +1,106 @@
|
|
|
1
|
-
# @buoy/core
|
|
1
|
+
# @buoy-gg/core
|
|
2
2
|
|
|
3
|
-
[](https://www.npmjs.com/package/@buoy-gg/core)
|
|
4
|
+
[](https://www.npmjs.com/package/@buoy-gg/core)
|
|
4
5
|
|
|
6
|
+
**Devtools that live in your app. And answer to your agent.**
|
|
5
7
|
|
|
6
|
-
|
|
8
|
+
Buoy is a floating dev menu that ships inside your React Native app. Every request, state change, render, and frame — live on the phone, on your desktop, and in Claude or Cursor. Drop in one component, install the tools you want, and they appear in the menu on their own.
|
|
9
|
+
|
|
10
|
+

|
|
7
11
|
|
|
8
12
|
## Install
|
|
13
|
+
|
|
9
14
|
```bash
|
|
10
|
-
|
|
15
|
+
npm install @buoy-gg/core
|
|
11
16
|
```
|
|
12
17
|
|
|
13
|
-
## Quick
|
|
18
|
+
## Quick start
|
|
19
|
+
|
|
14
20
|
```tsx
|
|
15
|
-
import {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
const APPS: InstalledApp[] = [
|
|
20
|
-
{
|
|
21
|
-
id: 'env',
|
|
22
|
-
name: 'Environment',
|
|
23
|
-
icon: '🛰️',
|
|
24
|
-
component: EnvVarsModal,
|
|
25
|
-
singleton: true,
|
|
26
|
-
},
|
|
27
|
-
];
|
|
28
|
-
|
|
29
|
-
export function DevToolsHost() {
|
|
21
|
+
import { FloatingDevTools } from "@buoy-gg/core";
|
|
22
|
+
|
|
23
|
+
export default function App() {
|
|
30
24
|
return (
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
25
|
+
<>
|
|
26
|
+
{/* Your app */}
|
|
27
|
+
<FloatingDevTools />
|
|
28
|
+
</>
|
|
34
29
|
);
|
|
35
30
|
}
|
|
36
31
|
```
|
|
37
32
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
33
|
+
That's the whole setup — a floating dev menu appears inside your app. Install any tool package and it auto-appears in the menu; most need zero config, a few take one line (like passing `zustandStores` or calling `watchAtoms()`). Add a `licenseKey` prop to unlock [Pro](https://buoy.gg/pricing): production builds, the MCP server, and unlimited capture.
|
|
34
|
+
|
|
35
|
+
## The 15 tools
|
|
36
|
+
|
|
37
|
+
| Tool | Package | What it does |
|
|
38
|
+
| --- | --- | --- |
|
|
39
|
+
| [Network](https://buoy.gg/buoy/latest/docs/tools/network) | `@buoy-gg/network` | Every request, response, timing & error — GraphQL operations extracted and named |
|
|
40
|
+
| [Storage](https://buoy.gg/buoy/latest/docs/tools/storage) | `@buoy-gg/storage` | Browse & edit AsyncStorage, MMKV & SecureStore with change history |
|
|
41
|
+
| [Env](https://buoy.gg/buoy/latest/docs/tools/env) | `@buoy-gg/env` | Auto-discovers `EXPO_PUBLIC_` vars, validates types, scores config health |
|
|
42
|
+
| [Query](https://buoy.gg/buoy/latest/docs/tools/react-query) | `@buoy-gg/react-query` | TanStack Query cache — refetch, invalidate, simulate loading & error states |
|
|
43
|
+
| [Routes](https://buoy.gg/buoy/latest/docs/tools/routes) | `@buoy-gg/route-events` | Navigation events, the live stack, and the full sitemap — jump to any screen |
|
|
44
|
+
| [Debug Borders](https://buoy.gg/buoy/latest/docs/tools/debug-borders) | `@buoy-gg/debug-borders` | Depth-colored layout borders — tap any label for testID, a11y props & styles |
|
|
45
|
+
| [Highlight Updates](https://buoy.gg/buoy/latest/docs/tools/highlight-updates) | `@buoy-gg/highlight-updates` | Every render, with the cause: mount, state, props, or parent |
|
|
46
|
+
| [Bench](https://buoy.gg/buoy/latest/docs/tools/perf-monitor) | `@buoy-gg/perf-monitor` | UI/JS FPS, CPU, memory & jank on a real device — batch benchmarks, ranked reports |
|
|
47
|
+
| [Events](https://buoy.gg/buoy/latest/docs/tools/events) | `@buoy-gg/events` | One timeline across every tool, with LLM-friendly export presets |
|
|
48
|
+
| [Console](https://buoy.gg/buoy/latest/docs/tools/console) | `@buoy-gg/console` | Chrome-DevTools console on device — read logs with no cable and no Metro |
|
|
49
|
+
| [Redux](https://buoy.gg/buoy/latest/docs/tools/redux) | `@buoy-gg/redux` | Inspect, dispatch & time travel — flags actions that blow the frame budget |
|
|
50
|
+
| [Zustand](https://buoy.gg/buoy/latest/docs/tools/zustand) | `@buoy-gg/zustand` | State, diffs, jump-to-state, one-tap reset — no middleware needed |
|
|
51
|
+
| [Jotai](https://buoy.gg/buoy/latest/docs/tools/jotai) | `@buoy-gg/jotai` | One `watchAtoms()` call — every event shows `prev → next` |
|
|
52
|
+
| [Impersonate](https://buoy.gg/buoy/latest/docs/tools/impersonate) | `@buoy-gg/impersonate` | Switch users, roles & flags without rebuilding |
|
|
53
|
+
| [Overlay](https://buoy.gg/buoy/latest/docs/tools/image-overlay) | `@buoy-gg/image-overlay` | Pin Figma mockups pixel-perfect over the app |
|
|
54
|
+
|
|
55
|
+
Grab everything in one line:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
npm i @buoy-gg/{core,network,storage,env,react-query,route-events,debug-borders,highlight-updates,perf-monitor,events,console,redux,zustand,jotai,impersonate,image-overlay}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Three surfaces, one live session
|
|
62
|
+
|
|
63
|
+
Every tool runs inside your app's process. The phone, the desktop, and your agent all see the same session, live.
|
|
64
|
+
|
|
65
|
+
- **On the phone** — tap the floating menu. Works on any device, no cable, no desktop app, no Metro.
|
|
66
|
+
- **On your desktop** — [Buoy Desktop](https://github.com/Buoy-gg/Buoy-Desktop) (free) mirrors the tools to full-screen panels on macOS, Windows & Linux, with a live FPS / CPU / memory HUD and remote control of the device. Devices connect automatically — physical phones included, no URLs to configure.
|
|
67
|
+
- **Through your agent** — the [Buoy MCP server](https://buoy.gg/buoy/latest/docs/mcp) gives Claude Code, Cursor, or any MCP editor structured tool calls into the running app: read live state, tap real buttons, run benchmarks on a physical device.
|
|
68
|
+
|
|
69
|
+
## Free vs Pro
|
|
70
|
+
|
|
71
|
+
Every tool is **free** — no key, no signup, no time limit.
|
|
72
|
+
|
|
73
|
+
**Pro** unlocks production builds, the MCP server, and unlimited capture. Activate with one prop:
|
|
74
|
+
|
|
75
|
+
```tsx
|
|
76
|
+
<FloatingDevTools licenseKey="YOUR_LICENSE_KEY" />
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
**Weekend Pass:** every Saturday and Sunday, every Pro feature unlocks free for everyone — built into the product, not a promo. Details at [buoy.gg/pricing](https://buoy.gg/pricing).
|
|
80
|
+
|
|
81
|
+
## Safe in production
|
|
82
|
+
|
|
83
|
+
Everything runs in your app's process. The broker that mirrors the session to desktop and MCP binds to localhost only — nothing ever leaves your machine. You decide who sees the tools:
|
|
84
|
+
|
|
85
|
+
```tsx
|
|
86
|
+
{isInternalUser && <FloatingDevTools />}
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
That one line is the whole production story: internal builds and flagged users get the full toolkit; everyone else gets nothing.
|
|
90
|
+
|
|
91
|
+
Need the session with **no on-device UI at all** — field builds or devices handed to non-developers? Headless mode keeps every tool syncing to Buoy Desktop and MCP while rendering nothing on the device:
|
|
92
|
+
|
|
93
|
+
```tsx
|
|
94
|
+
<FloatingDevTools headless />
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Links
|
|
98
|
+
|
|
99
|
+
- [Full documentation](https://buoy.gg/buoy/latest/docs/overview)
|
|
100
|
+
- [GitHub](https://github.com/Buoy-gg/buoy)
|
|
101
|
+
- [Buoy Desktop](https://github.com/Buoy-gg/Buoy-Desktop)
|
|
102
|
+
- [Pricing](https://buoy.gg/pricing)
|
|
103
|
+
|
|
104
|
+
## License
|
|
42
105
|
|
|
43
|
-
|
|
106
|
+
Proprietary software. © Buoy LLC. All rights reserved. See the [Terms of Service](https://buoy.gg/terms).
|
|
@@ -7,6 +7,7 @@ exports.useDevToolsSettings = exports.DevToolsSettingsModal = void 0;
|
|
|
7
7
|
var _react = require("react");
|
|
8
8
|
var _reactNative = require("react-native");
|
|
9
9
|
var _settingsBus = require("./settingsBus.js");
|
|
10
|
+
var _useDesktopSyncStatus = require("./useDesktopSyncStatus.js");
|
|
10
11
|
var _sharedUi = require("@buoy-gg/shared-ui");
|
|
11
12
|
var _floatingToolsCore = require("@buoy-gg/floating-tools-core");
|
|
12
13
|
var _DefaultConfigContext = require("./DefaultConfigContext.js");
|
|
@@ -158,6 +159,9 @@ const DevToolsSettingsModal = ({
|
|
|
158
159
|
const [activeTabLoaded, setActiveTabLoaded] = (0, _react.useState)(false);
|
|
159
160
|
const [expandedSettings, setExpandedSettings] = (0, _react.useState)(new Set());
|
|
160
161
|
const [showLicenseModal, setShowLicenseModal] = (0, _react.useState)(false);
|
|
162
|
+
// null when external-sync isn't installed (or predates the status store);
|
|
163
|
+
// "idle" until AutoExternalSync initializes — the row hides in both cases.
|
|
164
|
+
const desktopSyncStatus = (0, _useDesktopSyncStatus.useDesktopSyncStatus)();
|
|
161
165
|
|
|
162
166
|
// Load persisted active tab on mount
|
|
163
167
|
(0, _react.useEffect)(() => {
|
|
@@ -808,6 +812,66 @@ const DevToolsSettingsModal = ({
|
|
|
808
812
|
children: clearSuccess ? "CLEARED" : isClearing ? "CLEARING..." : "CLEAR ALL SETTINGS"
|
|
809
813
|
})]
|
|
810
814
|
})]
|
|
815
|
+
}), desktopSyncStatus && desktopSyncStatus.state !== "idle" && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
816
|
+
style: [styles.storageStatusCard, {
|
|
817
|
+
borderColor: desktopSyncStatus.state === "connected" ? _sharedUi.buoyColors.success + "60" : _sharedUi.buoyColors.warning + "60"
|
|
818
|
+
}],
|
|
819
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
820
|
+
style: styles.storageStatusHeader,
|
|
821
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
822
|
+
style: [styles.storageStatusIcon, {
|
|
823
|
+
backgroundColor: desktopSyncStatus.state === "connected" ? _sharedUi.buoyColors.success + "15" : _sharedUi.buoyColors.warning + "15"
|
|
824
|
+
}],
|
|
825
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.Globe, {
|
|
826
|
+
size: 18,
|
|
827
|
+
color: desktopSyncStatus.state === "connected" ? _sharedUi.buoyColors.success : _sharedUi.buoyColors.warning
|
|
828
|
+
})
|
|
829
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
830
|
+
style: styles.storageStatusInfo,
|
|
831
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
832
|
+
style: styles.storageStatusLabel,
|
|
833
|
+
children: "DESKTOP SYNC"
|
|
834
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
835
|
+
style: styles.storageStatusBadgeContainer,
|
|
836
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.View, {
|
|
837
|
+
style: [styles.storageStatusBadge, {
|
|
838
|
+
backgroundColor: desktopSyncStatus.state === "connected" ? _sharedUi.buoyColors.success + "20" : _sharedUi.buoyColors.warning + "20",
|
|
839
|
+
borderColor: desktopSyncStatus.state === "connected" ? _sharedUi.buoyColors.success + "60" : _sharedUi.buoyColors.warning + "60"
|
|
840
|
+
}],
|
|
841
|
+
children: /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
842
|
+
style: [styles.storageStatusBadgeText, {
|
|
843
|
+
color: desktopSyncStatus.state === "connected" ? _sharedUi.buoyColors.success : _sharedUi.buoyColors.warning
|
|
844
|
+
}],
|
|
845
|
+
children: desktopSyncStatus.state === "connected" ? "CONNECTED" : desktopSyncStatus.state === "connecting" ? "CONNECTING..." : "RETRYING"
|
|
846
|
+
})
|
|
847
|
+
}), desktopSyncStatus.state === "connected" ? /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.CheckCircle2, {
|
|
848
|
+
size: 14,
|
|
849
|
+
color: _sharedUi.buoyColors.success
|
|
850
|
+
}) : /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.AlertTriangle, {
|
|
851
|
+
size: 14,
|
|
852
|
+
color: _sharedUi.buoyColors.warning
|
|
853
|
+
})]
|
|
854
|
+
})]
|
|
855
|
+
})]
|
|
856
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, {
|
|
857
|
+
style: styles.storageStatusDescription,
|
|
858
|
+
children: [desktopSyncStatus.state === "connected" ? "Streaming tool data to Buoy Desktop at " : "Trying to reach Buoy Desktop at ", /*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
859
|
+
style: styles.adviceHintCode,
|
|
860
|
+
children: desktopSyncStatus.targetURL ?? "(unknown URL)"
|
|
861
|
+
}), desktopSyncStatus.state !== "connected" && " — is the desktop app running? Override with the externalSync socketURL option if it runs elsewhere."]
|
|
862
|
+
}), desktopSyncStatus.state === "retrying" && desktopSyncStatus.lastError && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
863
|
+
style: styles.adviceHint,
|
|
864
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.AlertTriangle, {
|
|
865
|
+
size: 14,
|
|
866
|
+
color: _sharedUi.buoyColors.warning
|
|
867
|
+
}), /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.Text, {
|
|
868
|
+
style: styles.adviceHintText,
|
|
869
|
+
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_reactNative.Text, {
|
|
870
|
+
style: styles.adviceHintBold,
|
|
871
|
+
children: "Last error:"
|
|
872
|
+
}), " ", desktopSyncStatus.lastError]
|
|
873
|
+
})]
|
|
874
|
+
})]
|
|
811
875
|
}), renderGlobalSettingCard("enableSharedModalDimensions", "SHARED MODAL SIZE", "MODAL", "Sync dimensions across all tools", "When enabled, all tool modals will share the same size and position. Resizing one modal will affect all others. When disabled, each tool remembers its own size and position independently.", "Keep OFF for the best experience. This allows you to customize each tool's modal size separately. Enable only if you prefer uniform modal sizes across all dev tools."), _reactNative.Platform.OS !== "web" && renderGlobalSettingCard("expandableWindowControls", "EXPAND CONTROLS", "MODAL", "iPad-style expandable window buttons", "When enabled, the window control buttons (minimize, toggle mode, close) start as small dots and expand into larger, easy-to-tap buttons when pressed — similar to iPad window controls. When disabled, buttons are directly tappable at their small size.", "Keep ON for touch devices where the small buttons are hard to press. Turn OFF if you prefer direct single-tap access (e.g. when using a mouse or simulator)."), isDevelopmentMode && /*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.View, {
|
|
812
876
|
style: styles.exportConfigCard,
|
|
813
877
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsxs)(_reactNative.TouchableOpacity, {
|
|
@@ -10,6 +10,7 @@ var _AppHost = require("./AppHost.js");
|
|
|
10
10
|
var _FloatingMenu = require("./FloatingMenu.js");
|
|
11
11
|
var _autoDiscoverPresets = require("./autoDiscoverPresets.js");
|
|
12
12
|
var _DevToolsVisibilityContext = require("./DevToolsVisibilityContext.js");
|
|
13
|
+
var _optionalRequire = require("./optionalRequire.js");
|
|
13
14
|
var _sharedUi = require("@buoy-gg/shared-ui");
|
|
14
15
|
var _MinimizedToolsContext = require("./MinimizedToolsContext.js");
|
|
15
16
|
var _defaultConfig = require("./defaultConfig.js");
|
|
@@ -115,6 +116,7 @@ const FloatingDevTools = ({
|
|
|
115
116
|
zustandStores,
|
|
116
117
|
environment,
|
|
117
118
|
externalSync = true,
|
|
119
|
+
headless = false,
|
|
118
120
|
...props
|
|
119
121
|
}) => {
|
|
120
122
|
const resolvedEnvironment = environment ?? (0, _sharedUi.normalizeEnvironment)(process.env.NODE_ENV ?? "dev");
|
|
@@ -167,8 +169,8 @@ const FloatingDevTools = ({
|
|
|
167
169
|
watchStores
|
|
168
170
|
} = require("@buoy-gg/zustand");
|
|
169
171
|
return watchStores(zustandStores);
|
|
170
|
-
} catch {
|
|
171
|
-
|
|
172
|
+
} catch (e) {
|
|
173
|
+
(0, _optionalRequire.reportOptionalRequireError)("@buoy-gg/zustand", e);
|
|
172
174
|
}
|
|
173
175
|
}, []); // eslint-disable-line react-hooks/exhaustive-deps
|
|
174
176
|
|
|
@@ -196,7 +198,7 @@ const FloatingDevTools = ({
|
|
|
196
198
|
requiredEnvVars: createEnvVarConfig(requiredEnvVars)
|
|
197
199
|
}));
|
|
198
200
|
} catch (error) {
|
|
199
|
-
|
|
201
|
+
(0, _optionalRequire.reportOptionalRequireError)("@buoy-gg/env", error);
|
|
200
202
|
}
|
|
201
203
|
}
|
|
202
204
|
|
|
@@ -210,7 +212,7 @@ const FloatingDevTools = ({
|
|
|
210
212
|
requiredStorageKeys
|
|
211
213
|
}));
|
|
212
214
|
} catch (error) {
|
|
213
|
-
|
|
215
|
+
(0, _optionalRequire.reportOptionalRequireError)("@buoy-gg/storage", error);
|
|
214
216
|
}
|
|
215
217
|
}
|
|
216
218
|
return overrides;
|
|
@@ -234,7 +236,8 @@ const FloatingDevTools = ({
|
|
|
234
236
|
DebugBordersStandaloneOverlay
|
|
235
237
|
} = require("@buoy-gg/debug-borders");
|
|
236
238
|
return DebugBordersStandaloneOverlay;
|
|
237
|
-
} catch {
|
|
239
|
+
} catch (e) {
|
|
240
|
+
(0, _optionalRequire.reportOptionalRequireError)("@buoy-gg/debug-borders", e);
|
|
238
241
|
return null;
|
|
239
242
|
}
|
|
240
243
|
}, []);
|
|
@@ -247,7 +250,8 @@ const FloatingDevTools = ({
|
|
|
247
250
|
HighlightUpdatesOverlay: Overlay
|
|
248
251
|
} = require("@buoy-gg/highlight-updates");
|
|
249
252
|
return Overlay;
|
|
250
|
-
} catch {
|
|
253
|
+
} catch (e) {
|
|
254
|
+
(0, _optionalRequire.reportOptionalRequireError)("@buoy-gg/highlight-updates", e);
|
|
251
255
|
return null;
|
|
252
256
|
}
|
|
253
257
|
}, []);
|
|
@@ -260,7 +264,8 @@ const FloatingDevTools = ({
|
|
|
260
264
|
ImageOverlayStandalone
|
|
261
265
|
} = require("@buoy-gg/image-overlay");
|
|
262
266
|
return ImageOverlayStandalone;
|
|
263
|
-
} catch {
|
|
267
|
+
} catch (e) {
|
|
268
|
+
(0, _optionalRequire.reportOptionalRequireError)("@buoy-gg/image-overlay", e);
|
|
264
269
|
return null;
|
|
265
270
|
}
|
|
266
271
|
}, []);
|
|
@@ -273,7 +278,8 @@ const FloatingDevTools = ({
|
|
|
273
278
|
PerfMonitorOverlay: Overlay
|
|
274
279
|
} = require("@buoy-gg/perf-monitor");
|
|
275
280
|
return Overlay;
|
|
276
|
-
} catch {
|
|
281
|
+
} catch (e) {
|
|
282
|
+
(0, _optionalRequire.reportOptionalRequireError)("@buoy-gg/perf-monitor", e);
|
|
277
283
|
return null;
|
|
278
284
|
}
|
|
279
285
|
}, []);
|
|
@@ -287,7 +293,8 @@ const FloatingDevTools = ({
|
|
|
287
293
|
RouteTracker: Tracker
|
|
288
294
|
} = require("@buoy-gg/route-events");
|
|
289
295
|
return Tracker;
|
|
290
|
-
} catch {
|
|
296
|
+
} catch (e) {
|
|
297
|
+
(0, _optionalRequire.reportOptionalRequireError)("@buoy-gg/route-events", e);
|
|
291
298
|
return null;
|
|
292
299
|
}
|
|
293
300
|
}, []);
|
|
@@ -300,7 +307,8 @@ const FloatingDevTools = ({
|
|
|
300
307
|
ImpersonateOverlay: Overlay
|
|
301
308
|
} = require("@buoy-gg/impersonate");
|
|
302
309
|
return Overlay;
|
|
303
|
-
} catch {
|
|
310
|
+
} catch (e) {
|
|
311
|
+
(0, _optionalRequire.reportOptionalRequireError)("@buoy-gg/impersonate", e);
|
|
304
312
|
return null;
|
|
305
313
|
}
|
|
306
314
|
}, []);
|
|
@@ -326,6 +334,22 @@ const FloatingDevTools = ({
|
|
|
326
334
|
return null;
|
|
327
335
|
}
|
|
328
336
|
|
|
337
|
+
// Headless (sync-only): tool adapters + route tracking + desktop sync, no
|
|
338
|
+
// on-device UI. requireLicense is intentionally skipped — there's nothing
|
|
339
|
+
// to gate. All hooks above already ran, so hook order is preserved, and
|
|
340
|
+
// AutoExternalSync is additionally dev-gated (the broker must never be
|
|
341
|
+
// contacted in production).
|
|
342
|
+
if (headless) {
|
|
343
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
|
|
344
|
+
children: [RouteTracker && /*#__PURE__*/(0, _jsxRuntime.jsx)(RouteTracker, {}), isDevelopment && externalSync !== false && (0, _autoExternalSync.isExternalSyncAvailable)() && /*#__PURE__*/(0, _jsxRuntime.jsx)(_autoExternalSync.AutoExternalSync, {
|
|
345
|
+
options: typeof externalSync === "object" ? externalSync : undefined,
|
|
346
|
+
requiredEnvVars: requiredEnvVars,
|
|
347
|
+
isPro: isLicensed,
|
|
348
|
+
licenseKey: licenseKey
|
|
349
|
+
})]
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
|
|
329
353
|
// Gate: If requireLicense is enabled and no license, show only the license modal
|
|
330
354
|
if (requireLicense && isInitialized && !licenseKey) {
|
|
331
355
|
return /*#__PURE__*/(0, _jsxRuntime.jsx)(_sharedUi.LicenseEntryModal, {
|
|
@@ -57,7 +57,8 @@ function FloatingDevTools({
|
|
|
57
57
|
availableEnvironments: _availableEnvironments,
|
|
58
58
|
onEnvironmentSwitch: _onEnvironmentSwitch,
|
|
59
59
|
apps,
|
|
60
|
-
disableHints: _disableHints
|
|
60
|
+
disableHints: _disableHints,
|
|
61
|
+
headless = false
|
|
61
62
|
}) {
|
|
62
63
|
// Internal state for dial and settings
|
|
63
64
|
const [isDialOpen, setIsDialOpen] = (0, _react.useState)(false);
|
|
@@ -135,6 +136,11 @@ function FloatingDevTools({
|
|
|
135
136
|
setIsSettingsOpen(true);
|
|
136
137
|
}, []);
|
|
137
138
|
const handleCloseSettings = (0, _react.useCallback)(() => setIsSettingsOpen(false), []);
|
|
139
|
+
|
|
140
|
+
// Headless: desktop sync is native-only, so there is nothing to mount on
|
|
141
|
+
// web — accept the prop for API parity and render nothing. (After all
|
|
142
|
+
// hooks so hook order is preserved.)
|
|
143
|
+
if (headless) return null;
|
|
138
144
|
return /*#__PURE__*/(0, _jsxRuntime.jsxs)(_jsxRuntime.Fragment, {
|
|
139
145
|
children: [/*#__PURE__*/(0, _jsxRuntime.jsx)(_floatingToolsWeb.FloatingTools, {
|
|
140
146
|
enablePositionPersistence: true,
|
|
@@ -5,6 +5,7 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
5
5
|
});
|
|
6
6
|
exports.autoDiscoverPresets = autoDiscoverPresets;
|
|
7
7
|
exports.autoDiscoverPresetsWithCustom = autoDiscoverPresetsWithCustom;
|
|
8
|
+
var _optionalRequire = require("./optionalRequire.js");
|
|
8
9
|
/**
|
|
9
10
|
* Automatically discovers and loads dev tool presets from installed packages.
|
|
10
11
|
*
|
|
@@ -68,7 +69,8 @@ function autoDiscoverPresets() {
|
|
|
68
69
|
envToolPreset
|
|
69
70
|
} = require("@buoy-gg/env");
|
|
70
71
|
return envToolPreset;
|
|
71
|
-
} catch {
|
|
72
|
+
} catch (e) {
|
|
73
|
+
(0, _optionalRequire.reportOptionalRequireError)("@buoy-gg/env", e);
|
|
72
74
|
return null;
|
|
73
75
|
}
|
|
74
76
|
}
|
|
@@ -83,7 +85,8 @@ function autoDiscoverPresets() {
|
|
|
83
85
|
networkToolPreset
|
|
84
86
|
} = require("@buoy-gg/network");
|
|
85
87
|
return networkToolPreset;
|
|
86
|
-
} catch {
|
|
88
|
+
} catch (e) {
|
|
89
|
+
(0, _optionalRequire.reportOptionalRequireError)("@buoy-gg/network", e);
|
|
87
90
|
return null;
|
|
88
91
|
}
|
|
89
92
|
}
|
|
@@ -98,7 +101,8 @@ function autoDiscoverPresets() {
|
|
|
98
101
|
storageToolPreset
|
|
99
102
|
} = require("@buoy-gg/storage");
|
|
100
103
|
return storageToolPreset;
|
|
101
|
-
} catch {
|
|
104
|
+
} catch (e) {
|
|
105
|
+
(0, _optionalRequire.reportOptionalRequireError)("@buoy-gg/storage", e);
|
|
102
106
|
return null;
|
|
103
107
|
}
|
|
104
108
|
}
|
|
@@ -114,7 +118,8 @@ function autoDiscoverPresets() {
|
|
|
114
118
|
wifiTogglePreset
|
|
115
119
|
} = require("@buoy-gg/react-query");
|
|
116
120
|
return [reactQueryToolPreset, wifiTogglePreset];
|
|
117
|
-
} catch {
|
|
121
|
+
} catch (e) {
|
|
122
|
+
(0, _optionalRequire.reportOptionalRequireError)("@buoy-gg/react-query", e);
|
|
118
123
|
return null;
|
|
119
124
|
}
|
|
120
125
|
}
|
|
@@ -129,7 +134,8 @@ function autoDiscoverPresets() {
|
|
|
129
134
|
routeEventsToolPreset
|
|
130
135
|
} = require("@buoy-gg/route-events");
|
|
131
136
|
return routeEventsToolPreset;
|
|
132
|
-
} catch {
|
|
137
|
+
} catch (e) {
|
|
138
|
+
(0, _optionalRequire.reportOptionalRequireError)("@buoy-gg/route-events", e);
|
|
133
139
|
return null;
|
|
134
140
|
}
|
|
135
141
|
}
|
|
@@ -144,7 +150,8 @@ function autoDiscoverPresets() {
|
|
|
144
150
|
debugBordersToolPreset
|
|
145
151
|
} = require("@buoy-gg/debug-borders");
|
|
146
152
|
return debugBordersToolPreset;
|
|
147
|
-
} catch {
|
|
153
|
+
} catch (e) {
|
|
154
|
+
(0, _optionalRequire.reportOptionalRequireError)("@buoy-gg/debug-borders", e);
|
|
148
155
|
return null;
|
|
149
156
|
}
|
|
150
157
|
}
|
|
@@ -160,7 +167,8 @@ function autoDiscoverPresets() {
|
|
|
160
167
|
highlightUpdatesModalPreset
|
|
161
168
|
} = require("@buoy-gg/highlight-updates");
|
|
162
169
|
return [highlightUpdatesModalPreset, highlightUpdatesPreset];
|
|
163
|
-
} catch {
|
|
170
|
+
} catch (e) {
|
|
171
|
+
(0, _optionalRequire.reportOptionalRequireError)("@buoy-gg/highlight-updates", e);
|
|
164
172
|
return null;
|
|
165
173
|
}
|
|
166
174
|
}
|
|
@@ -175,7 +183,8 @@ function autoDiscoverPresets() {
|
|
|
175
183
|
reduxToolPreset
|
|
176
184
|
} = require("@buoy-gg/redux");
|
|
177
185
|
return reduxToolPreset;
|
|
178
|
-
} catch {
|
|
186
|
+
} catch (e) {
|
|
187
|
+
(0, _optionalRequire.reportOptionalRequireError)("@buoy-gg/redux", e);
|
|
179
188
|
return null;
|
|
180
189
|
}
|
|
181
190
|
}
|
|
@@ -190,7 +199,8 @@ function autoDiscoverPresets() {
|
|
|
190
199
|
zustandToolPreset
|
|
191
200
|
} = require("@buoy-gg/zustand");
|
|
192
201
|
return zustandToolPreset;
|
|
193
|
-
} catch {
|
|
202
|
+
} catch (e) {
|
|
203
|
+
(0, _optionalRequire.reportOptionalRequireError)("@buoy-gg/zustand", e);
|
|
194
204
|
return null;
|
|
195
205
|
}
|
|
196
206
|
}
|
|
@@ -205,7 +215,8 @@ function autoDiscoverPresets() {
|
|
|
205
215
|
eventsToolPreset
|
|
206
216
|
} = require("@buoy-gg/events");
|
|
207
217
|
return eventsToolPreset;
|
|
208
|
-
} catch {
|
|
218
|
+
} catch (e) {
|
|
219
|
+
(0, _optionalRequire.reportOptionalRequireError)("@buoy-gg/events", e);
|
|
209
220
|
return null;
|
|
210
221
|
}
|
|
211
222
|
}
|
|
@@ -220,7 +231,8 @@ function autoDiscoverPresets() {
|
|
|
220
231
|
jotaiToolPreset
|
|
221
232
|
} = require("@buoy-gg/jotai");
|
|
222
233
|
return jotaiToolPreset;
|
|
223
|
-
} catch {
|
|
234
|
+
} catch (e) {
|
|
235
|
+
(0, _optionalRequire.reportOptionalRequireError)("@buoy-gg/jotai", e);
|
|
224
236
|
return null;
|
|
225
237
|
}
|
|
226
238
|
}
|
|
@@ -235,7 +247,8 @@ function autoDiscoverPresets() {
|
|
|
235
247
|
imageOverlayToolPreset
|
|
236
248
|
} = require("@buoy-gg/image-overlay");
|
|
237
249
|
return imageOverlayToolPreset;
|
|
238
|
-
} catch {
|
|
250
|
+
} catch (e) {
|
|
251
|
+
(0, _optionalRequire.reportOptionalRequireError)("@buoy-gg/image-overlay", e);
|
|
239
252
|
return null;
|
|
240
253
|
}
|
|
241
254
|
}
|
|
@@ -251,7 +264,8 @@ function autoDiscoverPresets() {
|
|
|
251
264
|
perfMonitorModalPreset
|
|
252
265
|
} = require("@buoy-gg/perf-monitor");
|
|
253
266
|
return [perfMonitorPreset, perfMonitorModalPreset];
|
|
254
|
-
} catch {
|
|
267
|
+
} catch (e) {
|
|
268
|
+
(0, _optionalRequire.reportOptionalRequireError)("@buoy-gg/perf-monitor", e);
|
|
255
269
|
return null;
|
|
256
270
|
}
|
|
257
271
|
}
|
|
@@ -272,8 +286,9 @@ function autoDiscoverPresets() {
|
|
|
272
286
|
}
|
|
273
287
|
}
|
|
274
288
|
} catch (error) {
|
|
275
|
-
//
|
|
276
|
-
//
|
|
289
|
+
// Loaders swallow their own require failures; anything reaching here
|
|
290
|
+
// is a preset-shape problem in an installed package — surface it.
|
|
291
|
+
(0, _optionalRequire.reportOptionalRequireError)(name, error);
|
|
277
292
|
}
|
|
278
293
|
}
|
|
279
294
|
return discoveredPresets;
|
|
@@ -7,12 +7,14 @@ exports.AutoExternalSync = AutoExternalSync;
|
|
|
7
7
|
exports.isExternalSyncAvailable = isExternalSyncAvailable;
|
|
8
8
|
var _react = require("react");
|
|
9
9
|
var _reactNative = require("react-native");
|
|
10
|
+
var _optionalRequire = require("./optionalRequire.js");
|
|
10
11
|
/**
|
|
11
12
|
* Zero-config device→desktop sync for FloatingDevTools.
|
|
12
13
|
*
|
|
13
14
|
* When @buoy-gg/external-sync is installed, FloatingDevTools renders
|
|
14
15
|
* <AutoExternalSync /> in dev builds: it connects to the Buoy Desktop broker
|
|
15
|
-
* (
|
|
16
|
+
* (port 42831 on the Metro host, so physical devices reach the dev machine
|
|
17
|
+
* automatically — a background retry when the desktop app isn't running) and
|
|
16
18
|
* registers a sync adapter for every installed tool package, discovered with
|
|
17
19
|
* the same guarded-require pattern as autoDiscoverPresets. No <DevToolsSync>
|
|
18
20
|
* wiring needed in the app.
|
|
@@ -47,85 +49,90 @@ let debugBordersModule = null;
|
|
|
47
49
|
let impersonateModule = null;
|
|
48
50
|
let perfMonitorModule = null;
|
|
49
51
|
let expoConstantsModule = null;
|
|
52
|
+
|
|
53
|
+
// Catch bodies report through reportOptionalRequireError: silent for a
|
|
54
|
+
// genuinely absent package, one dev warning when an installed package fails
|
|
55
|
+
// to load (broken transitive resolve, top-level crash).
|
|
50
56
|
try {
|
|
51
57
|
externalSyncModule = require("@buoy-gg/external-sync");
|
|
52
|
-
} catch {
|
|
53
|
-
|
|
58
|
+
} catch (e) {
|
|
59
|
+
(0, _optionalRequire.reportOptionalRequireError)("@buoy-gg/external-sync", e);
|
|
54
60
|
}
|
|
55
61
|
try {
|
|
56
62
|
storageModule = require("@buoy-gg/storage");
|
|
57
|
-
} catch {
|
|
58
|
-
|
|
63
|
+
} catch (e) {
|
|
64
|
+
(0, _optionalRequire.reportOptionalRequireError)("@buoy-gg/storage", e);
|
|
59
65
|
}
|
|
60
66
|
try {
|
|
61
67
|
networkModule = require("@buoy-gg/network");
|
|
62
|
-
} catch {
|
|
63
|
-
|
|
68
|
+
} catch (e) {
|
|
69
|
+
(0, _optionalRequire.reportOptionalRequireError)("@buoy-gg/network", e);
|
|
64
70
|
}
|
|
65
71
|
try {
|
|
66
72
|
reactQueryModule = require("@buoy-gg/react-query");
|
|
67
|
-
} catch {
|
|
68
|
-
|
|
73
|
+
} catch (e) {
|
|
74
|
+
(0, _optionalRequire.reportOptionalRequireError)("@buoy-gg/react-query", e);
|
|
69
75
|
}
|
|
70
76
|
try {
|
|
71
77
|
routeEventsModule = require("@buoy-gg/route-events");
|
|
72
|
-
} catch {
|
|
73
|
-
|
|
78
|
+
} catch (e) {
|
|
79
|
+
(0, _optionalRequire.reportOptionalRequireError)("@buoy-gg/route-events", e);
|
|
74
80
|
}
|
|
75
81
|
try {
|
|
76
82
|
reduxModule = require("@buoy-gg/redux");
|
|
77
|
-
} catch {
|
|
78
|
-
|
|
83
|
+
} catch (e) {
|
|
84
|
+
(0, _optionalRequire.reportOptionalRequireError)("@buoy-gg/redux", e);
|
|
79
85
|
}
|
|
80
86
|
try {
|
|
81
87
|
zustandModule = require("@buoy-gg/zustand");
|
|
82
|
-
} catch {
|
|
83
|
-
|
|
88
|
+
} catch (e) {
|
|
89
|
+
(0, _optionalRequire.reportOptionalRequireError)("@buoy-gg/zustand", e);
|
|
84
90
|
}
|
|
85
91
|
try {
|
|
86
92
|
jotaiModule = require("@buoy-gg/jotai");
|
|
87
|
-
} catch {
|
|
88
|
-
|
|
93
|
+
} catch (e) {
|
|
94
|
+
(0, _optionalRequire.reportOptionalRequireError)("@buoy-gg/jotai", e);
|
|
89
95
|
}
|
|
90
96
|
try {
|
|
91
97
|
eventsModule = require("@buoy-gg/events");
|
|
92
|
-
} catch {
|
|
93
|
-
|
|
98
|
+
} catch (e) {
|
|
99
|
+
(0, _optionalRequire.reportOptionalRequireError)("@buoy-gg/events", e);
|
|
94
100
|
}
|
|
95
101
|
try {
|
|
96
102
|
consoleModule = require("@buoy-gg/console");
|
|
97
|
-
} catch {
|
|
98
|
-
|
|
103
|
+
} catch (e) {
|
|
104
|
+
(0, _optionalRequire.reportOptionalRequireError)("@buoy-gg/console", e);
|
|
99
105
|
}
|
|
100
106
|
try {
|
|
101
107
|
envModule = require("@buoy-gg/env");
|
|
102
|
-
} catch {
|
|
103
|
-
|
|
108
|
+
} catch (e) {
|
|
109
|
+
(0, _optionalRequire.reportOptionalRequireError)("@buoy-gg/env", e);
|
|
104
110
|
}
|
|
105
111
|
try {
|
|
106
112
|
highlightUpdatesModule = require("@buoy-gg/highlight-updates");
|
|
107
|
-
} catch {
|
|
108
|
-
|
|
113
|
+
} catch (e) {
|
|
114
|
+
(0, _optionalRequire.reportOptionalRequireError)("@buoy-gg/highlight-updates", e);
|
|
109
115
|
}
|
|
110
116
|
try {
|
|
111
117
|
debugBordersModule = require("@buoy-gg/debug-borders");
|
|
112
|
-
} catch {
|
|
113
|
-
|
|
118
|
+
} catch (e) {
|
|
119
|
+
(0, _optionalRequire.reportOptionalRequireError)("@buoy-gg/debug-borders", e);
|
|
114
120
|
}
|
|
115
121
|
try {
|
|
116
122
|
impersonateModule = require("@buoy-gg/impersonate");
|
|
117
|
-
} catch {
|
|
118
|
-
|
|
123
|
+
} catch (e) {
|
|
124
|
+
(0, _optionalRequire.reportOptionalRequireError)("@buoy-gg/impersonate", e);
|
|
119
125
|
}
|
|
120
126
|
try {
|
|
121
127
|
perfMonitorModule = require("@buoy-gg/perf-monitor");
|
|
122
|
-
} catch {
|
|
123
|
-
|
|
128
|
+
} catch (e) {
|
|
129
|
+
(0, _optionalRequire.reportOptionalRequireError)("@buoy-gg/perf-monitor", e);
|
|
124
130
|
}
|
|
125
131
|
try {
|
|
126
132
|
expoConstantsModule = require("expo-constants");
|
|
127
|
-
} catch {
|
|
128
|
-
// not installed (RN CLI apps)
|
|
133
|
+
} catch (e) {
|
|
134
|
+
// not installed (RN CLI apps) — still report real load failures
|
|
135
|
+
(0, _optionalRequire.reportOptionalRequireError)("expo-constants", e);
|
|
129
136
|
}
|
|
130
137
|
|
|
131
138
|
/** Whether zero-config sync can run (the external-sync package is installed). */
|
|
@@ -165,7 +172,9 @@ function AutoExternalSync({
|
|
|
165
172
|
socket
|
|
166
173
|
} = useExternalSyncSocket({
|
|
167
174
|
deviceName: options?.deviceName ?? identity.deviceName,
|
|
168
|
-
|
|
175
|
+
// Older external-sync versions predate getDefaultSocketURL and require
|
|
176
|
+
// an explicit URL — keep the literal fallback for them.
|
|
177
|
+
socketURL: options?.socketURL ?? externalSyncModule.getDefaultSocketURL?.() ?? "http://localhost:42831",
|
|
169
178
|
persistentDeviceId: deviceId,
|
|
170
179
|
platform: _reactNative.Platform.OS,
|
|
171
180
|
enableLogs: options?.enableLogs
|