@buoy-gg/core 7.0.41 → 7.0.42
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 +14 -95
- package/bin/buoy.js +19 -340
- package/lib/commonjs/Buoy.js +1 -107
- package/lib/commonjs/browserRegister.js +1 -48
- package/lib/commonjs/browserRegister.server.js +1 -10
- package/lib/commonjs/earlyHookScript.js +1 -0
- package/lib/commonjs/earlyNetwork.js +1 -0
- package/lib/commonjs/floatingMenu/AppHost.js +1 -460
- package/lib/commonjs/floatingMenu/AppHost.web.js +1 -376
- package/lib/commonjs/floatingMenu/AppHostLogic.js +1 -50
- package/lib/commonjs/floatingMenu/AppIcon.js +1 -91
- package/lib/commonjs/floatingMenu/AppIcon.web.js +1 -53
- package/lib/commonjs/floatingMenu/BrowserToolRuntime.js +1 -150
- package/lib/commonjs/floatingMenu/DefaultConfigContext.js +1 -45
- package/lib/commonjs/floatingMenu/DevToolsSettingsModal.js +1 -18
- package/lib/commonjs/floatingMenu/DevToolsSettingsModal.shared.js +1 -1114
- package/lib/commonjs/floatingMenu/DevToolsSettingsModal.web.js +1 -48
- package/lib/commonjs/floatingMenu/DevToolsVisibilityContext.js +1 -49
- package/lib/commonjs/floatingMenu/FloatingDevTools.js +1 -559
- package/lib/commonjs/floatingMenu/FloatingDevTools.web.js +1 -415
- package/lib/commonjs/floatingMenu/FloatingMenu.js +1 -371
- package/lib/commonjs/floatingMenu/MinimizedToolsContext.js +1 -274
- package/lib/commonjs/floatingMenu/MinimizedToolsStack.js +1 -288
- package/lib/commonjs/floatingMenu/MinimizedToolsStack.web.js +1 -377
- package/lib/commonjs/floatingMenu/ToggleStateManager.js +1 -36
- package/lib/commonjs/floatingMenu/ToolHost.js +1 -281
- package/lib/commonjs/floatingMenu/ToolOpenerBridge.js +1 -41
- package/lib/commonjs/floatingMenu/autoDiscoverPresets.js +1 -471
- package/lib/commonjs/floatingMenu/autoExternalSync.js +1 -443
- package/lib/commonjs/floatingMenu/defaultConfig.js +1 -167
- package/lib/commonjs/floatingMenu/deviceIdentity.js +1 -173
- package/lib/commonjs/floatingMenu/dial/DialDevTools.js +1 -904
- package/lib/commonjs/floatingMenu/dial/DialDevTools.web.js +1 -895
- package/lib/commonjs/floatingMenu/dial/DialHyperspace.js +1 -177
- package/lib/commonjs/floatingMenu/dial/DialIcon.js +1 -304
- package/lib/commonjs/floatingMenu/dial/DialPagination.js +1 -165
- package/lib/commonjs/floatingMenu/dial/DialSnow.js +1 -92
- package/lib/commonjs/floatingMenu/dial/OnboardingTooltip.js +1 -246
- package/lib/commonjs/floatingMenu/dial/OnboardingTooltip.web.js +2 -147
- package/lib/commonjs/floatingMenu/dial/dialUsageStore.js +1 -93
- package/lib/commonjs/floatingMenu/dial/onboardingConstants.js +1 -42
- package/lib/commonjs/floatingMenu/dial/onboardingConstants.web.js +1 -42
- package/lib/commonjs/floatingMenu/externalSyncGate.js +1 -49
- package/lib/commonjs/floatingMenu/floatingTools.js +1 -42
- package/lib/commonjs/floatingMenu/floatingTools.web.js +1 -30
- package/lib/commonjs/floatingMenu/optionalRequire.js +1 -37
- package/lib/commonjs/floatingMenu/settingsBus.js +1 -12
- package/lib/commonjs/floatingMenu/sync/appSyncAdapter.js +1 -115
- package/lib/commonjs/floatingMenu/types.js +1 -5
- package/lib/commonjs/floatingMenu/useDesktopSyncStatus.js +1 -28
- package/lib/commonjs/floatingMenu/useDesktopSyncStatus.web.js +1 -14
- package/lib/commonjs/index.js +1 -291
- package/lib/commonjs/index.web.js +1 -241
- package/lib/commonjs/reactDevtoolsTypes.js +1 -1
- package/lib/commonjs/releaseOptIn.js +1 -0
- package/lib/commonjs/telemetry/installPing.js +1 -131
- package/lib/commonjs/toolkit.js +1 -584
- package/lib/commonjs/toolkitComponents.js +1 -241
- package/lib/commonjs/utils/autoDiscoverPresets.web.js +1 -46
- package/lib/commonjs/utils/createWebTool.js +1 -20
- package/lib/commonjs/utils/createWebTools.js +1 -30
- package/lib/commonjs/version.js +1 -18
- package/lib/module/Buoy.js +1 -102
- package/lib/module/browserRegister.js +1 -44
- package/lib/module/browserRegister.server.js +1 -6
- package/lib/module/earlyHookScript.js +1 -0
- package/lib/module/earlyNetwork.js +1 -0
- package/lib/module/floatingMenu/AppHost.js +1 -452
- package/lib/module/floatingMenu/AppHost.web.js +1 -368
- package/lib/module/floatingMenu/AppHostLogic.js +1 -45
- package/lib/module/floatingMenu/AppIcon.js +1 -84
- package/lib/module/floatingMenu/AppIcon.web.js +1 -47
- package/lib/module/floatingMenu/BrowserToolRuntime.js +1 -146
- package/lib/module/floatingMenu/DefaultConfigContext.js +1 -39
- package/lib/module/floatingMenu/DevToolsSettingsModal.js +1 -3
- package/lib/module/floatingMenu/DevToolsSettingsModal.shared.js +1 -1110
- package/lib/module/floatingMenu/DevToolsSettingsModal.web.js +1 -44
- package/lib/module/floatingMenu/DevToolsVisibilityContext.js +1 -44
- package/lib/module/floatingMenu/FloatingDevTools.js +1 -556
- package/lib/module/floatingMenu/FloatingDevTools.web.js +1 -412
- package/lib/module/floatingMenu/FloatingMenu.js +1 -366
- package/lib/module/floatingMenu/MinimizedToolsContext.js +1 -266
- package/lib/module/floatingMenu/MinimizedToolsStack.js +1 -285
- package/lib/module/floatingMenu/MinimizedToolsStack.web.js +1 -374
- package/lib/module/floatingMenu/ToggleStateManager.js +1 -32
- package/lib/module/floatingMenu/ToolHost.js +1 -273
- package/lib/module/floatingMenu/ToolOpenerBridge.js +1 -37
- package/lib/module/floatingMenu/autoDiscoverPresets.js +1 -467
- package/lib/module/floatingMenu/autoExternalSync.js +1 -436
- package/lib/module/floatingMenu/defaultConfig.js +1 -158
- package/lib/module/floatingMenu/deviceIdentity.js +1 -163
- package/lib/module/floatingMenu/dial/DialDevTools.js +1 -900
- package/lib/module/floatingMenu/dial/DialDevTools.web.js +1 -891
- package/lib/module/floatingMenu/dial/DialHyperspace.js +1 -173
- package/lib/module/floatingMenu/dial/DialIcon.js +1 -301
- package/lib/module/floatingMenu/dial/DialPagination.js +1 -160
- package/lib/module/floatingMenu/dial/DialSnow.js +1 -90
- package/lib/module/floatingMenu/dial/OnboardingTooltip.js +1 -240
- package/lib/module/floatingMenu/dial/OnboardingTooltip.web.js +2 -142
- package/lib/module/floatingMenu/dial/dialUsageStore.js +1 -85
- package/lib/module/floatingMenu/dial/onboardingConstants.js +1 -3
- package/lib/module/floatingMenu/dial/onboardingConstants.web.js +1 -3
- package/lib/module/floatingMenu/externalSyncGate.js +1 -44
- package/lib/module/floatingMenu/floatingTools.js +1 -27
- package/lib/module/floatingMenu/floatingTools.web.js +1 -3
- package/lib/module/floatingMenu/optionalRequire.js +1 -33
- package/lib/module/floatingMenu/settingsBus.js +1 -3
- package/lib/module/floatingMenu/sync/appSyncAdapter.js +1 -112
- package/lib/module/floatingMenu/types.js +1 -3
- package/lib/module/floatingMenu/useDesktopSyncStatus.js +1 -25
- package/lib/module/floatingMenu/useDesktopSyncStatus.web.js +1 -10
- package/lib/module/index.js +1 -41
- package/lib/module/index.web.js +1 -36
- package/lib/module/reactDevtoolsTypes.js +1 -1
- package/lib/module/releaseOptIn.js +1 -0
- package/lib/module/telemetry/installPing.js +1 -127
- package/lib/module/toolkit.js +1 -62
- package/lib/module/toolkitComponents.js +1 -230
- package/lib/module/utils/autoDiscoverPresets.web.js +1 -38
- package/lib/module/utils/createWebTool.js +1 -17
- package/lib/module/utils/createWebTools.js +1 -25
- package/lib/module/version.js +1 -14
- package/lib/typescript/commonjs/browserRegister.d.ts +9 -1
- package/lib/typescript/commonjs/browserRegister.server.d.ts +1 -0
- package/lib/typescript/commonjs/earlyHookScript.d.ts +12 -0
- package/lib/typescript/commonjs/earlyNetwork.d.ts +52 -0
- package/lib/typescript/commonjs/floatingMenu/defaultConfig.d.ts +1 -1
- package/lib/typescript/commonjs/index.web.d.ts +1 -0
- package/lib/typescript/commonjs/releaseOptIn.d.ts +4 -0
- package/lib/typescript/commonjs/version.d.ts +1 -1
- package/lib/typescript/module/browserRegister.d.ts +9 -1
- package/lib/typescript/module/browserRegister.server.d.ts +1 -0
- package/lib/typescript/module/earlyHookScript.d.ts +12 -0
- package/lib/typescript/module/earlyNetwork.d.ts +52 -0
- package/lib/typescript/module/floatingMenu/defaultConfig.d.ts +1 -1
- package/lib/typescript/module/index.web.d.ts +1 -0
- package/lib/typescript/module/releaseOptIn.d.ts +4 -0
- package/lib/typescript/module/version.d.ts +1 -1
- package/lib/web/chunks/chunk-5SGL6QL4.mjs +1 -0
- package/lib/web/chunks/chunk-FROELTJH.mjs +1 -0
- package/lib/web/chunks/chunk-QZDVCMCT.mjs +1 -2
- package/lib/web/chunks/chunk-R7RGRTY5.mjs +1 -2
- package/lib/web/index.mjs +2 -3
- package/lib/web/register-server.mjs +1 -2
- package/lib/web/register.mjs +1 -2
- package/lib/web/toolkit.mjs +1 -2
- package/package.json +5 -5
- package/lib/typescript/commonjs/Buoy.d.ts.map +0 -1
- package/lib/typescript/commonjs/browserRegister.d.ts.map +0 -1
- package/lib/typescript/commonjs/browserRegister.server.d.ts.map +0 -1
- package/lib/typescript/commonjs/floatingMenu/AppHost.d.ts.map +0 -1
- package/lib/typescript/commonjs/floatingMenu/AppHost.web.d.ts.map +0 -1
- package/lib/typescript/commonjs/floatingMenu/AppHostLogic.d.ts.map +0 -1
- package/lib/typescript/commonjs/floatingMenu/AppIcon.d.ts.map +0 -1
- package/lib/typescript/commonjs/floatingMenu/AppIcon.web.d.ts.map +0 -1
- package/lib/typescript/commonjs/floatingMenu/BrowserToolRuntime.d.ts.map +0 -1
- package/lib/typescript/commonjs/floatingMenu/DefaultConfigContext.d.ts.map +0 -1
- package/lib/typescript/commonjs/floatingMenu/DevToolsSettingsModal.d.ts.map +0 -1
- package/lib/typescript/commonjs/floatingMenu/DevToolsSettingsModal.shared.d.ts.map +0 -1
- package/lib/typescript/commonjs/floatingMenu/DevToolsSettingsModal.web.d.ts.map +0 -1
- package/lib/typescript/commonjs/floatingMenu/DevToolsVisibilityContext.d.ts.map +0 -1
- package/lib/typescript/commonjs/floatingMenu/FloatingDevTools.d.ts.map +0 -1
- package/lib/typescript/commonjs/floatingMenu/FloatingDevTools.web.d.ts.map +0 -1
- package/lib/typescript/commonjs/floatingMenu/FloatingMenu.d.ts.map +0 -1
- package/lib/typescript/commonjs/floatingMenu/MinimizedToolsContext.d.ts.map +0 -1
- package/lib/typescript/commonjs/floatingMenu/MinimizedToolsStack.d.ts.map +0 -1
- package/lib/typescript/commonjs/floatingMenu/MinimizedToolsStack.web.d.ts.map +0 -1
- package/lib/typescript/commonjs/floatingMenu/ToggleStateManager.d.ts.map +0 -1
- package/lib/typescript/commonjs/floatingMenu/ToolHost.d.ts.map +0 -1
- package/lib/typescript/commonjs/floatingMenu/ToolOpenerBridge.d.ts.map +0 -1
- package/lib/typescript/commonjs/floatingMenu/autoDiscoverPresets.d.ts.map +0 -1
- package/lib/typescript/commonjs/floatingMenu/autoExternalSync.d.ts.map +0 -1
- package/lib/typescript/commonjs/floatingMenu/defaultConfig.d.ts.map +0 -1
- package/lib/typescript/commonjs/floatingMenu/deviceIdentity.d.ts.map +0 -1
- package/lib/typescript/commonjs/floatingMenu/dial/DialDevTools.d.ts.map +0 -1
- package/lib/typescript/commonjs/floatingMenu/dial/DialDevTools.web.d.ts.map +0 -1
- package/lib/typescript/commonjs/floatingMenu/dial/DialHyperspace.d.ts.map +0 -1
- package/lib/typescript/commonjs/floatingMenu/dial/DialIcon.d.ts.map +0 -1
- package/lib/typescript/commonjs/floatingMenu/dial/DialPagination.d.ts.map +0 -1
- package/lib/typescript/commonjs/floatingMenu/dial/DialSnow.d.ts.map +0 -1
- package/lib/typescript/commonjs/floatingMenu/dial/OnboardingTooltip.d.ts.map +0 -1
- package/lib/typescript/commonjs/floatingMenu/dial/OnboardingTooltip.web.d.ts.map +0 -1
- package/lib/typescript/commonjs/floatingMenu/dial/dialUsageStore.d.ts.map +0 -1
- package/lib/typescript/commonjs/floatingMenu/dial/onboardingConstants.d.ts.map +0 -1
- package/lib/typescript/commonjs/floatingMenu/dial/onboardingConstants.web.d.ts.map +0 -1
- package/lib/typescript/commonjs/floatingMenu/externalSyncGate.d.ts.map +0 -1
- package/lib/typescript/commonjs/floatingMenu/floatingTools.d.ts.map +0 -1
- package/lib/typescript/commonjs/floatingMenu/floatingTools.web.d.ts.map +0 -1
- package/lib/typescript/commonjs/floatingMenu/optionalRequire.d.ts.map +0 -1
- package/lib/typescript/commonjs/floatingMenu/settingsBus.d.ts.map +0 -1
- package/lib/typescript/commonjs/floatingMenu/sync/appSyncAdapter.d.ts.map +0 -1
- package/lib/typescript/commonjs/floatingMenu/types.d.ts.map +0 -1
- package/lib/typescript/commonjs/floatingMenu/useDesktopSyncStatus.d.ts.map +0 -1
- package/lib/typescript/commonjs/floatingMenu/useDesktopSyncStatus.web.d.ts.map +0 -1
- package/lib/typescript/commonjs/index.d.ts.map +0 -1
- package/lib/typescript/commonjs/index.web.d.ts.map +0 -1
- package/lib/typescript/commonjs/reactDevtoolsTypes.d.ts.map +0 -1
- package/lib/typescript/commonjs/telemetry/installPing.d.ts.map +0 -1
- package/lib/typescript/commonjs/toolkit.d.ts.map +0 -1
- package/lib/typescript/commonjs/toolkitComponents.d.ts.map +0 -1
- package/lib/typescript/commonjs/utils/autoDiscoverPresets.web.d.ts.map +0 -1
- package/lib/typescript/commonjs/utils/createWebTool.d.ts.map +0 -1
- package/lib/typescript/commonjs/utils/createWebTools.d.ts.map +0 -1
- package/lib/typescript/commonjs/version.d.ts.map +0 -1
- package/lib/typescript/module/Buoy.d.ts.map +0 -1
- package/lib/typescript/module/browserRegister.d.ts.map +0 -1
- package/lib/typescript/module/browserRegister.server.d.ts.map +0 -1
- package/lib/typescript/module/floatingMenu/AppHost.d.ts.map +0 -1
- package/lib/typescript/module/floatingMenu/AppHost.web.d.ts.map +0 -1
- package/lib/typescript/module/floatingMenu/AppHostLogic.d.ts.map +0 -1
- package/lib/typescript/module/floatingMenu/AppIcon.d.ts.map +0 -1
- package/lib/typescript/module/floatingMenu/AppIcon.web.d.ts.map +0 -1
- package/lib/typescript/module/floatingMenu/BrowserToolRuntime.d.ts.map +0 -1
- package/lib/typescript/module/floatingMenu/DefaultConfigContext.d.ts.map +0 -1
- package/lib/typescript/module/floatingMenu/DevToolsSettingsModal.d.ts.map +0 -1
- package/lib/typescript/module/floatingMenu/DevToolsSettingsModal.shared.d.ts.map +0 -1
- package/lib/typescript/module/floatingMenu/DevToolsSettingsModal.web.d.ts.map +0 -1
- package/lib/typescript/module/floatingMenu/DevToolsVisibilityContext.d.ts.map +0 -1
- package/lib/typescript/module/floatingMenu/FloatingDevTools.d.ts.map +0 -1
- package/lib/typescript/module/floatingMenu/FloatingDevTools.web.d.ts.map +0 -1
- package/lib/typescript/module/floatingMenu/FloatingMenu.d.ts.map +0 -1
- package/lib/typescript/module/floatingMenu/MinimizedToolsContext.d.ts.map +0 -1
- package/lib/typescript/module/floatingMenu/MinimizedToolsStack.d.ts.map +0 -1
- package/lib/typescript/module/floatingMenu/MinimizedToolsStack.web.d.ts.map +0 -1
- package/lib/typescript/module/floatingMenu/ToggleStateManager.d.ts.map +0 -1
- package/lib/typescript/module/floatingMenu/ToolHost.d.ts.map +0 -1
- package/lib/typescript/module/floatingMenu/ToolOpenerBridge.d.ts.map +0 -1
- package/lib/typescript/module/floatingMenu/autoDiscoverPresets.d.ts.map +0 -1
- package/lib/typescript/module/floatingMenu/autoExternalSync.d.ts.map +0 -1
- package/lib/typescript/module/floatingMenu/defaultConfig.d.ts.map +0 -1
- package/lib/typescript/module/floatingMenu/deviceIdentity.d.ts.map +0 -1
- package/lib/typescript/module/floatingMenu/dial/DialDevTools.d.ts.map +0 -1
- package/lib/typescript/module/floatingMenu/dial/DialDevTools.web.d.ts.map +0 -1
- package/lib/typescript/module/floatingMenu/dial/DialHyperspace.d.ts.map +0 -1
- package/lib/typescript/module/floatingMenu/dial/DialIcon.d.ts.map +0 -1
- package/lib/typescript/module/floatingMenu/dial/DialPagination.d.ts.map +0 -1
- package/lib/typescript/module/floatingMenu/dial/DialSnow.d.ts.map +0 -1
- package/lib/typescript/module/floatingMenu/dial/OnboardingTooltip.d.ts.map +0 -1
- package/lib/typescript/module/floatingMenu/dial/OnboardingTooltip.web.d.ts.map +0 -1
- package/lib/typescript/module/floatingMenu/dial/dialUsageStore.d.ts.map +0 -1
- package/lib/typescript/module/floatingMenu/dial/onboardingConstants.d.ts.map +0 -1
- package/lib/typescript/module/floatingMenu/dial/onboardingConstants.web.d.ts.map +0 -1
- package/lib/typescript/module/floatingMenu/externalSyncGate.d.ts.map +0 -1
- package/lib/typescript/module/floatingMenu/floatingTools.d.ts.map +0 -1
- package/lib/typescript/module/floatingMenu/floatingTools.web.d.ts.map +0 -1
- package/lib/typescript/module/floatingMenu/optionalRequire.d.ts.map +0 -1
- package/lib/typescript/module/floatingMenu/settingsBus.d.ts.map +0 -1
- package/lib/typescript/module/floatingMenu/sync/appSyncAdapter.d.ts.map +0 -1
- package/lib/typescript/module/floatingMenu/types.d.ts.map +0 -1
- package/lib/typescript/module/floatingMenu/useDesktopSyncStatus.d.ts.map +0 -1
- package/lib/typescript/module/floatingMenu/useDesktopSyncStatus.web.d.ts.map +0 -1
- package/lib/typescript/module/index.d.ts.map +0 -1
- package/lib/typescript/module/index.web.d.ts.map +0 -1
- package/lib/typescript/module/reactDevtoolsTypes.d.ts.map +0 -1
- package/lib/typescript/module/telemetry/installPing.d.ts.map +0 -1
- package/lib/typescript/module/toolkit.d.ts.map +0 -1
- package/lib/typescript/module/toolkitComponents.d.ts.map +0 -1
- package/lib/typescript/module/utils/autoDiscoverPresets.web.d.ts.map +0 -1
- package/lib/typescript/module/utils/createWebTool.d.ts.map +0 -1
- package/lib/typescript/module/utils/createWebTools.d.ts.map +0 -1
- package/lib/typescript/module/version.d.ts.map +0 -1
- package/lib/web/chunks/chunk-5NZOQR6Q.mjs +0 -2
- package/lib/web/chunks/chunk-CGDSLLZF.mjs +0 -2
- package/lib/web/chunks/chunk-DCJDUSNR.mjs +0 -2
- package/lib/web/chunks/chunk-IDSHFS6G.mjs +0 -2
- package/lib/web/chunks/chunk-JOAMJGCS.mjs +0 -2
- package/lib/web/chunks/chunk-KYKZ2N52.mjs +0 -2
- package/lib/web/chunks/chunk-NGM7JGGS.mjs +0 -2
- package/lib/web/chunks/chunk-Z3XWDDIO.mjs +0 -2
- package/lib/web/chunks/chunk-ZTGQ6TTY.mjs +0 -2
package/README.md
CHANGED
|
@@ -1,109 +1,28 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
1
3
|
# @buoy-gg/core
|
|
2
4
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
+
The floating developer-tools menu for your React Native app. Add the tool packages you need to inspect requests, app state, storage and performance.
|
|
6
|
+
|
|
7
|
+
<a href="https://buoy.gg/buoy/latest/docs/quick-start"><b>Quick start</b></a> · <a href="https://buoy.gg">buoy.gg</a> · <a href="https://github.com/Buoy-gg/buoy">All tools</a>
|
|
5
8
|
|
|
6
|
-
|
|
9
|
+
[](https://www.npmjs.com/package/@buoy-gg/core) [](https://www.npmjs.com/package/@buoy-gg/core)
|
|
7
10
|
|
|
8
|
-
|
|
11
|
+
<a href="https://buoy.gg"><img src="https://raw.githubusercontent.com/Buoy-gg/buoy/main/.github/readme/film.png" alt="Play the 53-second Buoy film on buoy.gg" width="640" /></a>
|
|
9
12
|
|
|
10
|
-
|
|
13
|
+
</div>
|
|
14
|
+
|
|
15
|
+
## Install
|
|
11
16
|
|
|
12
17
|
```bash
|
|
13
18
|
npm install @buoy-gg/core @buoy-gg/network
|
|
14
19
|
npx --package=@buoy-gg/core buoy login
|
|
15
20
|
```
|
|
16
21
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
```tsx
|
|
20
|
-
import { Stack } from "expo-router";
|
|
21
|
-
import { Buoy, FloatingDevTools } from "@buoy-gg/core";
|
|
22
|
-
|
|
23
|
-
Buoy.init({ licenseKey: process.env.EXPO_PUBLIC_BUOY_KEY });
|
|
24
|
-
|
|
25
|
-
export default function RootLayout() {
|
|
26
|
-
return (
|
|
27
|
-
<>
|
|
28
|
-
<Stack />
|
|
29
|
-
<FloatingDevTools />
|
|
30
|
-
</>
|
|
31
|
-
);
|
|
32
|
-
}
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
The login command writes the Expo key to `.env.local`. Keep the navigator and menu inside your existing providers. Without Expo Router, keep your app’s root content in place of `Stack`. For React Native CLI, load the key through your app’s environment configuration and pass it to `Buoy.init`; `.env.local` is not loaded automatically.
|
|
36
|
-
|
|
37
|
-
Restart the development server after installation. Open Buoy, complete any account prompt, and select Network. Trigger a new HTTP request in your app and check its URL and status. If no request appears, check whether the app used cached data or an unsupported transport.
|
|
38
|
-
|
|
39
|
-
See the [Quick Start](https://buoy.gg/buoy/latest/docs/quick-start) for the full setup and [Installation](https://buoy.gg/buoy/latest/docs/installation) for requirements. Other tools may need store registration, provider context, or native dependencies.
|
|
40
|
-
|
|
41
|
-
The dial shows the most recently opened tool first. Tools you haven’t opened keep their registration order.
|
|
42
|
-
|
|
43
|
-
## Tools
|
|
44
|
-
|
|
45
|
-
| Tool | Package | What it does |
|
|
46
|
-
| --- | --- | --- |
|
|
47
|
-
| [Network](https://buoy.gg/buoy/latest/docs/tools/network) | `@buoy-gg/network` | Inspect HTTP requests captured through your React Native app’s global `fetch` and `XMLHttpRequest` hooks. Open a request to see its URL, status, headers, timing, and captured body. |
|
|
48
|
-
| [Storage](https://buoy.gg/buoy/latest/docs/tools/storage) | `@buoy-gg/storage` | Browse and edit supported AsyncStorage, registered MMKV instances, and registered SecureStore keys inside your app. |
|
|
49
|
-
| [Time Machine](https://buoy.gg/buoy/latest/docs/tools/time-machine) | `@buoy-gg/time-machine` | Save and restore supported client state; external side effects are not reversed. |
|
|
50
|
-
| [Ask Buoy](https://buoy.gg/buoy/latest/docs/tools/ask-buoy) | `@buoy-gg/ask-buoy` | Use an in-app assistant with your model endpoint and configured tools. |
|
|
51
|
-
| [Env](https://buoy.gg/buoy/latest/docs/tools/env) | `@buoy-gg/env` | Inspect runtime environment values and validate required variables. |
|
|
52
|
-
| [Query](https://buoy.gg/buoy/latest/docs/tools/react-query) | `@buoy-gg/react-query` | Inspect the TanStack Query cache used by your app. Refetch or invalidate a query and simulate states while checking the screen that consumes it. |
|
|
53
|
-
| [Routes](https://buoy.gg/buoy/latest/docs/tools/routes) | `@buoy-gg/route-events` | Inspect recorded navigation events and supported routes. |
|
|
54
|
-
| [Debug Borders](https://buoy.gg/buoy/latest/docs/tools/debug-borders) | `@buoy-gg/debug-borders` | Show layout borders and component labels over your React Native app. Tap a label to inspect the component’s available properties. |
|
|
55
|
-
| [Highlight Updates](https://buoy.gg/buoy/latest/docs/tools/highlight-updates) | `@buoy-gg/highlight-updates` | Highlight observed React component updates in development builds and inspect the available render details. |
|
|
56
|
-
| [Bench](https://buoy.gg/buoy/latest/docs/tools/perf-monitor) | `@buoy-gg/perf-monitor` | Measure available frame-rate, CPU, and memory metrics on a device. Record comparable runs to investigate performance changes. |
|
|
57
|
-
| [JS Top](https://buoy.gg/buoy/latest/docs/tools/js-top) | `@buoy-gg/js-top` | Task Manager for the JS thread — which timers, Promise chains & callbacks eat your JS FPS |
|
|
58
|
-
| [Images](https://buoy.gg/buoy/latest/docs/tools/images) | `@buoy-gg/images` | Inspect image loads observed by Buoy’s supported image hooks, including timing, dimensions, and estimated decoded memory. |
|
|
59
|
-
| [Assets](https://buoy.gg/buoy/latest/docs/tools/assets) | `@buoy-gg/assets` | Inspect assets visible to the runtime registry and, in development, the Metro dependency graph. Compare sizes and find possible duplicates. |
|
|
60
|
-
| [Events](https://buoy.gg/buoy/latest/docs/tools/events) | `@buoy-gg/events` | Review events from configured Buoy tools in one timeline. Filter by source, inspect an event, and export a selection for debugging. |
|
|
61
|
-
| [Console](https://buoy.gg/buoy/latest/docs/tools/console) | `@buoy-gg/console` | Read captured JavaScript console logs in your React Native app. Filter messages by level, search their contents, and inspect logged objects. |
|
|
62
|
-
| [Sentry](https://buoy.gg/buoy/latest/docs/tools/sentry) | `@buoy-gg/sentry` | Inspect captured Sentry envelopes and diagnostic estimates. |
|
|
63
|
-
| [Redux](https://buoy.gg/buoy/latest/docs/tools/redux) | `@buoy-gg/redux` | Inspect your connected Redux store, review captured actions and state changes, and dispatch actions from your device. |
|
|
64
|
-
| [Zustand](https://buoy.gg/buoy/latest/docs/tools/zustand) | `@buoy-gg/zustand` | Inspect the Zustand stores you register with Buoy. Review changes, edit state, and restore retained snapshots. |
|
|
65
|
-
| [Jotai](https://buoy.gg/buoy/latest/docs/tools/jotai) | `@buoy-gg/jotai` | Inspect registered Jotai atoms and their captured changes, with live values and per-atom history. |
|
|
66
|
-
| [Impersonate](https://buoy.gg/buoy/latest/docs/tools/impersonate) | `@buoy-gg/impersonate` | Connect your app’s user-switching flow to Buoy so testers can switch test accounts, roles, or flags without rebuilding. |
|
|
67
|
-
| [Overlay](https://buoy.gg/buoy/latest/docs/tools/image-overlay) | `@buoy-gg/image-overlay` | Place a reference image over your app to compare spacing, alignment, and sizing on the device. |
|
|
68
|
-
|
|
69
|
-
TV tools and the iOS Simulator camera have separate [platform requirements](https://buoy.gg/buoy/latest/docs/overview).
|
|
70
|
-
|
|
71
|
-
## Desktop and AI
|
|
72
|
-
|
|
73
|
-
Inspect configured tools in the floating menu on your device. You can also connect them to:
|
|
74
|
-
|
|
75
|
-
- [Buoy Desktop](https://github.com/Buoy-gg/Buoy-Desktop), for desktop panels and remote actions. React Native apps need `@buoy-gg/external-sync`; follow the [connection guide](https://buoy.gg/buoy/latest/docs/desktop) and sign in to Desktop separately.
|
|
76
|
-
- [MCP](https://buoy.gg/buoy/latest/docs/mcp), for an AI editor to inspect and act on the app. Configure both process and device accounts; data and action tools require Pro.
|
|
77
|
-
- [Ask Buoy](https://buoy.gg/buoy/latest/docs/tools/ask-buoy), for an in-app assistant. It requires Pro, a model endpoint you configure, and the tool integrations its tasks depend on.
|
|
78
|
-
|
|
79
|
-
Supported features vary by platform, build, and installed tools. [Flutter](https://buoy.gg/buoy/latest/docs/flutter/quick-start) has a separate debug-build setup.
|
|
80
|
-
|
|
81
|
-
## Account and plan requirements
|
|
82
|
-
|
|
83
|
-
Use a Free or Pro Buoy account. History limits and paid features vary by tool; see [pricing](https://buoy.gg/pricing). Production access requires Pro where supported. Development-only hooks and actions remain unavailable in release builds.
|
|
84
|
-
|
|
85
|
-
## Production and connections
|
|
86
|
-
|
|
87
|
-
Start with a development build. Before enabling Buoy in a shipped app, restrict access using your app’s authorization checks and review the [component reference](https://buoy.gg/buoy/latest/docs/floating-devtools). Production access requires Pro, and development-only capabilities remain unavailable.
|
|
88
|
-
|
|
89
|
-
Hiding the menu is not a substitute for backend authorization. Headless mode hides the on-device UI; it still requires account admission and sync configuration. Release sync is disabled by default and must be explicitly enabled.
|
|
90
|
-
|
|
91
|
-
Device sessions can travel over your LAN to the configured broker. Buoy also makes account and license requests; development telemetry is described in [Telemetry](https://buoy.gg/buoy/latest/docs/telemetry). Ask Buoy sends model requests to the endpoint you configure.
|
|
92
|
-
|
|
93
|
-
## License
|
|
94
|
-
|
|
95
|
-
Proprietary software. © Buoy LLC. All rights reserved. See the [Terms of Service](https://buoy.gg/terms).
|
|
96
|
-
|
|
97
|
-
### Custom floating controls
|
|
98
|
-
|
|
99
|
-
The DevTools bubble uses the shared `FloatingTool` shell. Custom tools can use the same shell with `openFloatingTool`; `FloatingDevTools` already mounts the host. See the [integration guide](https://buoy.gg/buoy/latest/docs/custom-tools/floating-tools).
|
|
100
|
-
|
|
101
|
-
## Web support (unreleased)
|
|
102
|
-
|
|
103
|
-
Import `FloatingDevTools` from `@buoy-gg/core/web` and pass the tool namespaces through `modules`. Settings, account status, and modal persistence share their implementation with native. The browser build is available in this checkout and has not been published yet. See the [web setup guide](https://buoy.gg/buoy/latest/docs/web-preview) for registration, dependencies, and browser boundaries.
|
|
22
|
+
Call `Buoy.init` with your key and render `<FloatingDevTools />` inside your existing providers. The login command writes the Expo key to `.env.local`; React Native CLI apps load the key through their own environment config.
|
|
104
23
|
|
|
105
|
-
|
|
24
|
+
The [Quick start](https://buoy.gg/buoy/latest/docs/quick-start) walks through the full setup, and [every tool](https://buoy.gg/buoy/latest/docs/overview) has its own guide.
|
|
106
25
|
|
|
107
|
-
|
|
26
|
+
---
|
|
108
27
|
|
|
109
|
-
|
|
28
|
+
<sub>Part of <a href="https://buoy.gg">Buoy</a>, developer tools that live inside your app. Proprietary software. © Buoy LLC. <a href="https://buoy.gg/terms">Terms</a></sub>
|
package/bin/buoy.js
CHANGED
|
@@ -1,352 +1,31 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
'use strict';
|
|
16
|
-
|
|
17
|
-
const http = require('node:http');
|
|
18
|
-
const fs = require('node:fs');
|
|
19
|
-
const path = require('node:path');
|
|
20
|
-
const crypto = require('node:crypto');
|
|
21
|
-
const { spawn } = require('node:child_process');
|
|
22
|
-
|
|
23
|
-
const SITE = process.env.BUOY_SITE_URL || 'https://buoy.gg';
|
|
24
|
-
const LOGIN_TIMEOUT_MS = 5 * 60 * 1000;
|
|
25
|
-
|
|
26
|
-
const ESC = '\x1b[';
|
|
27
|
-
const color = (code) => (s) => `${ESC}${code}m${s}${ESC}0m`;
|
|
28
|
-
const cyan = color(36);
|
|
29
|
-
const green = color(32);
|
|
30
|
-
const red = color(31);
|
|
31
|
-
const dim = color(2);
|
|
32
|
-
const bold = color(1);
|
|
33
|
-
|
|
34
|
-
function log(msg) {
|
|
35
|
-
process.stdout.write(`${msg}\n`);
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
function fail(msg) {
|
|
39
|
-
process.stderr.write(`${red('x')} ${msg}\n`);
|
|
40
|
-
process.exit(1);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Open a URL in the user's default browser.
|
|
45
|
-
*
|
|
46
|
-
* Failure is not fatal: headless boxes, SSH sessions and locked-down machines
|
|
47
|
-
* all land here, and the URL is printed regardless so it can be opened by hand.
|
|
48
|
-
*/
|
|
49
|
-
function openBrowser(url) {
|
|
50
|
-
const cmd =
|
|
51
|
-
process.platform === 'darwin'
|
|
52
|
-
? 'open'
|
|
53
|
-
: process.platform === 'win32'
|
|
54
|
-
? 'cmd'
|
|
55
|
-
: 'xdg-open';
|
|
56
|
-
const args = process.platform === 'win32' ? ['/c', 'start', '', url] : [url];
|
|
57
|
-
try {
|
|
58
|
-
spawn(cmd, args, { stdio: 'ignore', detached: true }).unref();
|
|
59
|
-
} catch {
|
|
60
|
-
/* the URL is printed either way */
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/** Select the public variable prefix supported by the app's bundler. */
|
|
65
|
-
function detectEnvVarName(root) {
|
|
66
|
-
let webVarName = null;
|
|
67
|
-
try {
|
|
68
|
-
const pkgPath = path.join(root, 'package.json');
|
|
69
|
-
if (fs.existsSync(pkgPath)) {
|
|
70
|
-
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf8'));
|
|
71
|
-
const deps = Object.assign({}, pkg.dependencies, pkg.devDependencies);
|
|
72
|
-
if (deps.expo) return 'EXPO_PUBLIC_BUOY_KEY';
|
|
73
|
-
if (deps.vite) webVarName = 'VITE_BUOY_KEY';
|
|
74
|
-
}
|
|
75
|
-
if (
|
|
76
|
-
fs.existsSync(path.join(root, 'app.config.js')) ||
|
|
77
|
-
fs.existsSync(path.join(root, 'app.config.ts'))
|
|
78
|
-
) {
|
|
79
|
-
return 'EXPO_PUBLIC_BUOY_KEY';
|
|
80
|
-
}
|
|
81
|
-
const appJson = path.join(root, 'app.json');
|
|
82
|
-
if (fs.existsSync(appJson)) {
|
|
83
|
-
const parsed = JSON.parse(fs.readFileSync(appJson, 'utf8'));
|
|
84
|
-
if (parsed && parsed.expo) return 'EXPO_PUBLIC_BUOY_KEY';
|
|
85
|
-
}
|
|
86
|
-
} catch {
|
|
87
|
-
/* Use the detected bundler or the generic name. */
|
|
88
|
-
}
|
|
89
|
-
return webVarName || 'BUOY_KEY';
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
/**
|
|
93
|
-
* Expo and Vite include `.env.local` in production builds. Free keys belong
|
|
94
|
-
* in `.env.development.local` to keep them in development builds and avoid
|
|
95
|
-
* account verification from every production client. Paid keys can also be
|
|
96
|
-
* used in TestFlight or QA builds, so they keep `.env.local`.
|
|
97
|
-
*/
|
|
98
|
-
function envFileFor(varName, tier) {
|
|
99
|
-
if (varName !== 'EXPO_PUBLIC_BUOY_KEY' && varName !== 'VITE_BUOY_KEY') return '.env.local';
|
|
100
|
-
return tier === 'pro' || tier === 'business' ? '.env.local' : '.env.development.local';
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/** Drop `NAME=...` from an env file if present. True when a line was removed. */
|
|
104
|
-
function removeEnvVar(root, name, fileName) {
|
|
105
|
-
const file = path.join(root, fileName);
|
|
106
|
-
let contents;
|
|
107
|
-
try {
|
|
108
|
-
contents = fs.readFileSync(file, 'utf8');
|
|
109
|
-
} catch {
|
|
110
|
-
return false;
|
|
111
|
-
}
|
|
112
|
-
const pattern = new RegExp('^' + name + '=.*\\n?', 'm');
|
|
113
|
-
if (!pattern.test(contents)) return false;
|
|
114
|
-
fs.writeFileSync(file, contents.replace(pattern, ''), { mode: 0o600 });
|
|
115
|
-
return true;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
/** Upsert `NAME=value` in an env file, preserving everything else in the file. */
|
|
119
|
-
function writeEnvVar(root, name, value, fileName = '.env.local') {
|
|
120
|
-
const file = path.join(root, fileName);
|
|
121
|
-
let contents = '';
|
|
122
|
-
try {
|
|
123
|
-
contents = fs.readFileSync(file, 'utf8');
|
|
124
|
-
} catch {
|
|
125
|
-
/* new file */
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
const line = `${name}=${value}`;
|
|
129
|
-
const pattern = new RegExp('^' + name + '=.*$', 'm');
|
|
130
|
-
|
|
131
|
-
if (pattern.test(contents)) {
|
|
132
|
-
contents = contents.replace(pattern, line);
|
|
133
|
-
} else {
|
|
134
|
-
if (contents && !contents.endsWith('\n')) contents += '\n';
|
|
135
|
-
contents += `${line}\n`;
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
fs.writeFileSync(file, contents, { mode: 0o600 });
|
|
139
|
-
return file;
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
/**
|
|
143
|
-
* Make sure the env file is ignored.
|
|
144
|
-
*
|
|
145
|
-
* The whole point of a per-developer key is that it identifies one person; a
|
|
146
|
-
* key committed to a shared repo turns the count back into "repos", which is
|
|
147
|
-
* exactly what this flow exists to avoid.
|
|
148
|
-
*/
|
|
149
|
-
function ensureGitignored(root, fileName = '.env.local') {
|
|
150
|
-
const file = path.join(root, '.gitignore');
|
|
151
|
-
let contents = '';
|
|
152
|
-
try {
|
|
153
|
-
contents = fs.readFileSync(file, 'utf8');
|
|
154
|
-
} catch {
|
|
155
|
-
return false;
|
|
156
|
-
}
|
|
157
|
-
const exact = new RegExp('^' + fileName.replace(/\./g, '\\.') + '$', 'm');
|
|
158
|
-
// `.env*`, `*.local` and `.env*.local` all cover both files we might write.
|
|
159
|
-
if (exact.test(contents) || /^\.env\*|^\*\.local$|^\.env\*\.local$/m.test(contents)) return false;
|
|
160
|
-
|
|
161
|
-
if (contents && !contents.endsWith('\n')) contents += '\n';
|
|
162
|
-
contents += `\n# Buoy license key (per developer - do not commit)\n${fileName}\n`;
|
|
163
|
-
fs.writeFileSync(file, contents);
|
|
164
|
-
return true;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
/**
|
|
168
|
-
* Loopback auth.
|
|
169
|
-
*
|
|
170
|
-
* The browser does the signing in (it already holds the Clerk session), then
|
|
171
|
-
* hands the key back to a short-lived server on 127.0.0.1. Chosen over a
|
|
172
|
-
* device-code flow because it needs no server-side pending-code state, and over
|
|
173
|
-
* redirecting with the key in the URL because that would write a credential
|
|
174
|
-
* into browser history.
|
|
175
|
-
*/
|
|
176
|
-
function awaitKeyFromBrowser() {
|
|
177
|
-
return new Promise((resolve, reject) => {
|
|
178
|
-
const state = crypto.randomBytes(16).toString('hex');
|
|
179
|
-
|
|
180
|
-
const server = http.createServer((req, res) => {
|
|
181
|
-
// The page runs on buoy.gg and posts here cross-origin.
|
|
182
|
-
if (req.headers.origin === SITE) {
|
|
183
|
-
res.setHeader('Access-Control-Allow-Origin', SITE);
|
|
184
|
-
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
|
|
185
|
-
res.setHeader('Access-Control-Allow-Methods', 'POST, OPTIONS');
|
|
186
|
-
// Private Network Access: Chrome is moving to require a public site to
|
|
187
|
-
// be granted permission before it may reach loopback, via this header
|
|
188
|
-
// on the preflight. Sending it costs nothing today and is the
|
|
189
|
-
// difference between this flow surviving that rollout and silently
|
|
190
|
-
// failing for every Chrome user on the same day.
|
|
191
|
-
res.setHeader('Access-Control-Allow-Private-Network', 'true');
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
if (req.method === 'OPTIONS') {
|
|
195
|
-
res.writeHead(204).end();
|
|
196
|
-
return;
|
|
197
|
-
}
|
|
198
|
-
if (req.method !== 'POST') {
|
|
199
|
-
res.writeHead(405).end();
|
|
200
|
-
return;
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
let body = '';
|
|
204
|
-
req.on('data', (chunk) => {
|
|
205
|
-
body += chunk;
|
|
206
|
-
// A local server that accepts unbounded input is a local server that
|
|
207
|
-
// can be made to eat all your memory.
|
|
208
|
-
if (body.length > 4096) req.destroy();
|
|
209
|
-
});
|
|
210
|
-
req.on('end', () => {
|
|
211
|
-
let parsed = {};
|
|
212
|
-
try {
|
|
213
|
-
parsed = JSON.parse(body);
|
|
214
|
-
} catch {
|
|
215
|
-
/* handled by the check below */
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
// Any page in any tab can POST to localhost. The nonce is what proves
|
|
219
|
-
// this response belongs to the login WE just started.
|
|
220
|
-
if (parsed.state !== state || typeof parsed.key !== 'string' || !parsed.key) {
|
|
221
|
-
res.writeHead(400).end();
|
|
222
|
-
return;
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
res.writeHead(200, { 'Content-Type': 'application/json' });
|
|
226
|
-
res.end('{"ok":true}');
|
|
227
|
-
server.close();
|
|
228
|
-
resolve({
|
|
229
|
-
key: parsed.key.trim(),
|
|
230
|
-
tier: parsed.tier || 'free',
|
|
231
|
-
email: parsed.email || '',
|
|
232
|
-
});
|
|
233
|
-
});
|
|
234
|
-
});
|
|
235
|
-
|
|
236
|
-
server.on('error', reject);
|
|
237
|
-
|
|
238
|
-
// Port 0 = let the OS pick. Bound to loopback only, so nothing on the
|
|
239
|
-
// network can reach it.
|
|
240
|
-
server.listen(0, '127.0.0.1', () => {
|
|
241
|
-
const { port } = server.address();
|
|
242
|
-
const url = `${SITE}/cli/login?port=${port}&state=${state}`;
|
|
243
|
-
|
|
244
|
-
log('');
|
|
245
|
-
log(` Opening ${cyan(url)}`);
|
|
246
|
-
log(dim(' If your browser did not open, paste that URL into a browser on this computer.'));
|
|
247
|
-
log('');
|
|
248
|
-
log(dim(' Waiting for you to finish signing in...'));
|
|
249
|
-
|
|
250
|
-
openBrowser(url);
|
|
251
|
-
});
|
|
252
|
-
|
|
253
|
-
setTimeout(() => {
|
|
254
|
-
server.close();
|
|
255
|
-
reject(new Error('Timed out waiting for the browser (5 minutes).'));
|
|
256
|
-
}, LOGIN_TIMEOUT_MS).unref();
|
|
257
|
-
});
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
async function login() {
|
|
261
|
-
const root = process.cwd();
|
|
262
|
-
|
|
263
|
-
let result;
|
|
264
|
-
try {
|
|
265
|
-
result = await awaitKeyFromBrowser();
|
|
266
|
-
} catch (err) {
|
|
267
|
-
fail(`${err.message}\n Nothing was written.`);
|
|
268
|
-
return;
|
|
269
|
-
}
|
|
270
|
-
|
|
271
|
-
const varName = detectEnvVarName(root);
|
|
272
|
-
const fileName = envFileFor(varName, result.tier);
|
|
273
|
-
const file = writeEnvVar(root, varName, result.key, fileName);
|
|
274
|
-
// An earlier login may have left the key in .env.local; a free key there
|
|
275
|
-
// would still ride along into release builds.
|
|
276
|
-
const moved = fileName !== '.env.local' && removeEnvVar(root, varName, '.env.local');
|
|
277
|
-
const addedIgnore = ensureGitignored(root, fileName);
|
|
278
|
-
const relative = path.relative(root, file) || fileName;
|
|
279
|
-
|
|
280
|
-
log('');
|
|
281
|
-
log(
|
|
282
|
-
`${green('OK')} Signed in${result.email ? ' as ' + bold(result.email) : ''} - ${bold(result.tier)} tier`
|
|
283
|
-
);
|
|
284
|
-
log(` Wrote ${cyan(varName)} to ${cyan(relative)}`);
|
|
285
|
-
if (moved) log(dim(` Removed the old ${varName} line from .env.local`));
|
|
286
|
-
if (fileName === '.env.development.local') {
|
|
287
|
-
log(dim(' This file is loaded in development, keeping the key out of production builds.'));
|
|
288
|
-
}
|
|
289
|
-
if (addedIgnore) log(dim(` Added ${fileName} to .gitignore`));
|
|
290
|
-
log('');
|
|
291
|
-
log(' Use it in your app:');
|
|
292
|
-
log('');
|
|
293
|
-
if (varName === 'VITE_BUOY_KEY') {
|
|
294
|
-
log(cyan(' <FloatingDevTools modules={modules} licenseKey={import.meta.env.VITE_BUOY_KEY} />'));
|
|
295
|
-
log('');
|
|
296
|
-
log(dim(' Keep your existing tool modules and providers, then reload the web app.'));
|
|
297
|
-
} else {
|
|
298
|
-
log(cyan(` Buoy.init({ licenseKey: ${varName} });`));
|
|
299
|
-
log('');
|
|
300
|
-
log(dim(' Swift: pass the key through BuoyConfig.licenseKey in your development build.'));
|
|
301
|
-
log(dim(' Bare React Native does not load .env.local automatically; wire your existing env loader.'));
|
|
302
|
-
}
|
|
303
|
-
log('');
|
|
304
|
-
}
|
|
305
|
-
|
|
306
|
-
function help() {
|
|
307
|
-
log(`
|
|
308
|
-
${bold('buoy')} - React Buoy CLI
|
|
309
|
-
|
|
310
|
-
${bold('Usage')}
|
|
2
|
+
"use strict";const http=require("node:http");const fs=require("node:fs");const path=require("node:path");const crypto=require("node:crypto");const{spawn}=require("node:child_process");const SITE=process.env.BUOY_SITE_URL||"https://buoy.gg";const LOGIN_TIMEOUT_MS=5*60*1e3;const ESC="\x1B[";const color=e=>o=>`${ESC}${e}m${o}${ESC}0m`;const cyan=color(36);const green=color(32);const red=color(31);const dim=color(2);const bold=color(1);function log(e){process.stdout.write(`${e}
|
|
3
|
+
`)}function fail(e){process.stderr.write(`${red("x")} ${e}
|
|
4
|
+
`);process.exit(1)}function openBrowser(e){const o=process.platform==="darwin"?"open":process.platform==="win32"?"cmd":"xdg-open";const s=process.platform==="win32"?["/c","start","",e]:[e];try{spawn(o,s,{stdio:"ignore",detached:true}).unref()}catch{}}function detectEnvVarName(e){let o=null;try{const s=path.join(e,"package.json");if(fs.existsSync(s)){const i=JSON.parse(fs.readFileSync(s,"utf8"));const n=Object.assign({},i.dependencies,i.devDependencies);if(n.expo)return"EXPO_PUBLIC_BUOY_KEY";if(n.next)o="NEXT_PUBLIC_BUOY_KEY";else if(n.vite)o="VITE_BUOY_KEY"}if(fs.existsSync(path.join(e,"app.config.js"))||fs.existsSync(path.join(e,"app.config.ts"))){return"EXPO_PUBLIC_BUOY_KEY"}const t=path.join(e,"app.json");if(fs.existsSync(t)){const i=JSON.parse(fs.readFileSync(t,"utf8"));if(i&&i.expo)return"EXPO_PUBLIC_BUOY_KEY"}}catch{}return o||"BUOY_KEY"}function envFileFor(e,o){if(!["EXPO_PUBLIC_BUOY_KEY","VITE_BUOY_KEY","NEXT_PUBLIC_BUOY_KEY"].includes(e))return".env.local";return o==="pro"||o==="business"?".env.local":".env.development.local"}function removeEnvVar(e,o,s){const t=path.join(e,s);let i;try{i=fs.readFileSync(t,"utf8")}catch{return false}const n=new RegExp("^"+o+"=.*\\n?","m");if(!n.test(i))return false;fs.writeFileSync(t,i.replace(n,""),{mode:384});return true}function writeEnvVar(e,o,s,t=".env.local"){const i=path.join(e,t);let n="";try{n=fs.readFileSync(i,"utf8")}catch{}const c=`${o}=${s}`;const r=new RegExp("^"+o+"=.*$","m");if(r.test(n)){n=n.replace(r,c)}else{if(n&&!n.endsWith("\n"))n+="\n";n+=`${c}
|
|
5
|
+
`}fs.writeFileSync(i,n,{mode:384});return i}function ensureGitignored(e,o=".env.local"){const s=path.join(e,".gitignore");let t="";try{t=fs.readFileSync(s,"utf8")}catch{return false}const i=new RegExp("^"+o.replace(/\./g,"\\.")+"$","m");if(i.test(t)||/^\.env\*|^\*\.local$|^\.env\*\.local$/m.test(t))return false;if(t&&!t.endsWith("\n"))t+="\n";t+=`
|
|
6
|
+
# Buoy license key (per developer - do not commit)
|
|
7
|
+
${o}
|
|
8
|
+
`;fs.writeFileSync(s,t);return true}function awaitKeyFromBrowser(){return new Promise((e,o)=>{const s=crypto.randomBytes(16).toString("hex");const t=http.createServer((i,n)=>{if(i.headers.origin===SITE){n.setHeader("Access-Control-Allow-Origin",SITE);n.setHeader("Access-Control-Allow-Headers","Content-Type");n.setHeader("Access-Control-Allow-Methods","POST, OPTIONS");n.setHeader("Access-Control-Allow-Private-Network","true")}if(i.method==="OPTIONS"){n.writeHead(204).end();return}if(i.method!=="POST"){n.writeHead(405).end();return}let c="";i.on("data",r=>{c+=r;if(c.length>4096)i.destroy()});i.on("end",()=>{let r={};try{r=JSON.parse(c)}catch{}if(r.state!==s||typeof r.key!=="string"||!r.key){n.writeHead(400).end();return}n.writeHead(200,{"Content-Type":"application/json"});n.end('{"ok":true}');t.close();e({key:r.key.trim(),tier:r.tier||"free",email:r.email||""})})});t.on("error",o);t.listen(0,"127.0.0.1",()=>{const{port:i}=t.address();const n=`${SITE}/cli/login?port=${i}&state=${s}`;log("");log(` Opening ${cyan(n)}`);log(dim(" If your browser did not open, paste that URL into a browser on this computer."));log("");log(dim(" Waiting for you to finish signing in..."));openBrowser(n)});setTimeout(()=>{t.close();o(new Error("Timed out waiting for the browser (5 minutes)."))},LOGIN_TIMEOUT_MS).unref()})}async function login(){const e=process.cwd();let o;try{o=await awaitKeyFromBrowser()}catch(a){fail(`${a.message}
|
|
9
|
+
Nothing was written.`);return}const s=detectEnvVarName(e);const t=envFileFor(s,o.tier);const i=writeEnvVar(e,s,o.key,t);const n=t!==".env.local"&&removeEnvVar(e,s,".env.local");const c=ensureGitignored(e,t);const r=path.relative(e,i)||t;log("");log(`${green("OK")} Signed in${o.email?" as "+bold(o.email):""} - ${bold(o.tier)} tier`);log(` Wrote ${cyan(s)} to ${cyan(r)}`);if(n)log(dim(` Removed the old ${s} line from .env.local`));if(t===".env.development.local"){log(dim(" This file is loaded in development, keeping the key out of production builds."))}if(c)log(dim(` Added ${t} to .gitignore`));log("");log(" Use it in your app:");log("");if(s==="VITE_BUOY_KEY"){log(cyan(" <FloatingDevTools modules={modules} licenseKey={import.meta.env.VITE_BUOY_KEY} />"));log("");log(dim(" Keep your existing tool modules and providers, then reload the web app."))}else if(s==="NEXT_PUBLIC_BUOY_KEY"){log(cyan(" <FloatingDevTools modules={modules} licenseKey={process.env.NEXT_PUBLIC_BUOY_KEY} />"));log("");log(dim(" Restart next dev so it picks up the new variable."))}else{log(cyan(` Buoy.init({ licenseKey: ${s} });`));log("");log(dim(" Swift: pass the key through BuoyConfig.licenseKey in your development build."));log(dim(" Bare React Native does not load .env.local automatically; wire your existing env loader."))}log("")}function help(){log(`
|
|
10
|
+
${bold("buoy")} - React Buoy CLI
|
|
11
|
+
|
|
12
|
+
${bold("Usage")}
|
|
311
13
|
npx --package=@buoy-gg/core buoy <command>
|
|
312
14
|
|
|
313
|
-
${dim(
|
|
15
|
+
${dim("(if npx picks the wrong one)")}
|
|
314
16
|
|
|
315
|
-
${bold(
|
|
17
|
+
${bold("Commands")}
|
|
316
18
|
login Sign in and write your license key to an env file
|
|
317
19
|
help Show this message
|
|
318
20
|
|
|
319
|
-
${bold(
|
|
21
|
+
${bold("Notes")}
|
|
320
22
|
Run login from your app directory. Complete browser sign-in to receive
|
|
321
|
-
your account key. Expo uses EXPO_PUBLIC_BUOY_KEY
|
|
322
|
-
For
|
|
323
|
-
to .env.local. Other projects receive BUOY_KEY in .env.local and must
|
|
23
|
+
your account key. Expo uses EXPO_PUBLIC_BUOY_KEY, Vite uses VITE_BUOY_KEY
|
|
24
|
+
and Next.js uses NEXT_PUBLIC_BUOY_KEY. For these, a free key goes to
|
|
25
|
+
.env.development.local and a paid key goes to .env.local. Other projects receive BUOY_KEY in .env.local and must
|
|
324
26
|
configure their own environment loader and variable mapping.
|
|
325
27
|
This command does not install tools or verify a Desktop connection.
|
|
326
28
|
|
|
327
29
|
Docs: ${SITE}/buoy/latest/docs/installation
|
|
328
|
-
`);
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
// Only dispatch when run as a program. Without this guard, importing the file
|
|
332
|
-
// in a test would parse the test runner's own argv and exit the process.
|
|
333
|
-
if (require.main === module) {
|
|
334
|
-
const command = process.argv[2];
|
|
335
|
-
|
|
336
|
-
if (command === 'login') {
|
|
337
|
-
login();
|
|
338
|
-
} else if (!command || command === 'help' || command === '--help' || command === '-h') {
|
|
339
|
-
help();
|
|
340
|
-
} else {
|
|
341
|
-
fail(`Unknown command: ${command}\n Run \`npx buoy help\` to see what is available.`);
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
module.exports = {
|
|
346
|
-
detectEnvVarName,
|
|
347
|
-
envFileFor,
|
|
348
|
-
writeEnvVar,
|
|
349
|
-
removeEnvVar,
|
|
350
|
-
ensureGitignored,
|
|
351
|
-
awaitKeyFromBrowser,
|
|
352
|
-
};
|
|
30
|
+
`)}if(require.main===module){const e=process.argv[2];if(e==="login"){login()}else if(!e||e==="help"||e==="--help"||e==="-h"){help()}else{fail(`Unknown command: ${e}
|
|
31
|
+
Run \`npx buoy help\` to see what is available.`)}}module.exports={detectEnvVarName,envFileFor,writeEnvVar,removeEnvVar,ensureGitignored,awaitKeyFromBrowser};
|
package/lib/commonjs/Buoy.js
CHANGED
|
@@ -1,107 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, "__esModule", {
|
|
4
|
-
value: true
|
|
5
|
-
});
|
|
6
|
-
exports.default = exports.Buoy = void 0;
|
|
7
|
-
exports.isTelemetryEnabled = isTelemetryEnabled;
|
|
8
|
-
var _license = require("@buoy-gg/license");
|
|
9
|
-
/**
|
|
10
|
-
* Buoy SDK - Main entry point for React Buoy configuration
|
|
11
|
-
*
|
|
12
|
-
* Initialize once at app startup, before rendering any components:
|
|
13
|
-
*
|
|
14
|
-
* @example
|
|
15
|
-
* ```tsx
|
|
16
|
-
* import { Buoy } from '@buoy-gg/core';
|
|
17
|
-
*
|
|
18
|
-
* Buoy.init({
|
|
19
|
-
* licenseKey: 'YOUR_LICENSE_KEY',
|
|
20
|
-
* });
|
|
21
|
-
* ```
|
|
22
|
-
*/
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Telemetry stays on unless an app explicitly opts out. Read at ping time
|
|
26
|
-
* rather than captured, so `Buoy.init()` still wins if it runs after mount.
|
|
27
|
-
*/
|
|
28
|
-
let telemetryEnabled = true;
|
|
29
|
-
|
|
30
|
-
/** Whether the anonymous install ping is allowed to fire. */
|
|
31
|
-
function isTelemetryEnabled() {
|
|
32
|
-
return telemetryEnabled;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* Buoy SDK namespace
|
|
37
|
-
*
|
|
38
|
-
* Use `Buoy.init()` to configure your license key at app startup.
|
|
39
|
-
*/
|
|
40
|
-
const Buoy = exports.Buoy = {
|
|
41
|
-
/**
|
|
42
|
-
* Initialize Buoy with your license key
|
|
43
|
-
*
|
|
44
|
-
* Call this once at app startup, before rendering FloatingDevTools.
|
|
45
|
-
* Typically placed in App.tsx or index.js.
|
|
46
|
-
*
|
|
47
|
-
* @example
|
|
48
|
-
* ```tsx
|
|
49
|
-
* import { Buoy } from '@buoy-gg/core';
|
|
50
|
-
*
|
|
51
|
-
* // With hardcoded key
|
|
52
|
-
* Buoy.init({
|
|
53
|
-
* licenseKey: '36063C-27282E-8E73F5-55488F-2213DF-V3',
|
|
54
|
-
* });
|
|
55
|
-
*
|
|
56
|
-
* // With environment variable
|
|
57
|
-
* Buoy.init({
|
|
58
|
-
* licenseKey: process.env.BUOY_LICENSE_KEY!,
|
|
59
|
-
* });
|
|
60
|
-
* ```
|
|
61
|
-
*/
|
|
62
|
-
init(config) {
|
|
63
|
-
if (config.telemetry === false) telemetryEnabled = false;
|
|
64
|
-
void _license.LicenseManager.configure(config.licenseKey).catch(error => {
|
|
65
|
-
console.warn("[Buoy] License initialization failed:", error);
|
|
66
|
-
});
|
|
67
|
-
},
|
|
68
|
-
/**
|
|
69
|
-
* Initialize Buoy asynchronously
|
|
70
|
-
*
|
|
71
|
-
* Use this if you need to wait for initialization to complete.
|
|
72
|
-
*
|
|
73
|
-
* @example
|
|
74
|
-
* ```tsx
|
|
75
|
-
* await Buoy.initAsync({
|
|
76
|
-
* licenseKey: 'YOUR_LICENSE_KEY',
|
|
77
|
-
* });
|
|
78
|
-
* console.log('Buoy is ready!');
|
|
79
|
-
* ```
|
|
80
|
-
*/
|
|
81
|
-
async initAsync(config) {
|
|
82
|
-
if (config.telemetry === false) telemetryEnabled = false;
|
|
83
|
-
return _license.LicenseManager.configure(config.licenseKey);
|
|
84
|
-
},
|
|
85
|
-
/**
|
|
86
|
-
* Check if Buoy Pro is active
|
|
87
|
-
*/
|
|
88
|
-
isPro() {
|
|
89
|
-
return _license.LicenseManager.isPro();
|
|
90
|
-
},
|
|
91
|
-
/**
|
|
92
|
-
* Get the current license state
|
|
93
|
-
*/
|
|
94
|
-
getState() {
|
|
95
|
-
return _license.LicenseManager.getState();
|
|
96
|
-
},
|
|
97
|
-
/**
|
|
98
|
-
* Force device re-registration (debugging helper)
|
|
99
|
-
* Clears cached fingerprint so next init will register device again
|
|
100
|
-
*/
|
|
101
|
-
async forceReregister() {
|
|
102
|
-
await _license.LicenseManager.forceReregister();
|
|
103
|
-
}
|
|
104
|
-
};
|
|
105
|
-
|
|
106
|
-
// Also export as default for flexibility
|
|
107
|
-
var _default = exports.default = Buoy;
|
|
1
|
+
"use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.default=exports.Buoy=void 0;exports.isTelemetryEnabled=isTelemetryEnabled;var _license=require("@buoy-gg/license");let telemetryEnabled=true;function isTelemetryEnabled(){return telemetryEnabled}const Buoy=exports.Buoy={init(e){if(e.telemetry===false)telemetryEnabled=false;void _license.LicenseManager.configure(e.licenseKey).catch(r=>{console.warn("[Buoy] License initialization failed:",r)})},async initAsync(e){if(e.telemetry===false)telemetryEnabled=false;return _license.LicenseManager.configure(e.licenseKey)},isPro(){return _license.LicenseManager.isPro()},getState(){return _license.LicenseManager.getState()},async forceReregister(){await _license.LicenseManager.forceReregister()}};var _default=exports.default=Buoy;
|