@buoy-gg/external-sync 7.0.41 → 7.0.43
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/commonjs/attachDeviceSync.js +1 -294
- package/lib/commonjs/brokerAccess.js +1 -29
- package/lib/commonjs/crashFlush.js +1 -73
- package/lib/commonjs/emitBudget.js +1 -57
- package/lib/commonjs/index.js +1 -83
- package/lib/commonjs/realNow.js +1 -0
- package/lib/commonjs/syncStatusStore.js +1 -40
- package/lib/commonjs/types.js +1 -97
- package/lib/commonjs/useExternalSync.js +1 -73
- package/lib/commonjs/useExternalSyncSocket.js +1 -241
- package/lib/commonjs/utils/getDefaultSocketURL.js +1 -84
- package/lib/commonjs/utils/getDefaultSocketURL.web.js +1 -27
- package/lib/commonjs/utils/logger.js +1 -24
- package/lib/commonjs/utils/platformUtils.js +1 -50
- package/lib/commonjs/utils/platformUtils.web.js +1 -9
- package/lib/module/attachDeviceSync.js +1 -290
- package/lib/module/brokerAccess.js +1 -25
- package/lib/module/crashFlush.js +1 -67
- package/lib/module/emitBudget.js +1 -52
- package/lib/module/index.js +1 -29
- package/lib/module/realNow.js +1 -0
- package/lib/module/syncStatusStore.js +1 -34
- package/lib/module/types.js +1 -93
- package/lib/module/useExternalSync.js +1 -69
- package/lib/module/useExternalSyncSocket.js +1 -235
- package/lib/module/utils/getDefaultSocketURL.js +1 -76
- package/lib/module/utils/getDefaultSocketURL.web.js +1 -19
- package/lib/module/utils/logger.js +1 -20
- package/lib/module/utils/platformUtils.js +1 -45
- package/lib/module/utils/platformUtils.web.js +1 -5
- package/lib/typescript/realNow.d.ts +27 -0
- package/lib/typescript/syncStatusStore.d.ts +0 -7
- package/lib/web/index.mjs +1 -2
- package/package.json +3 -6
- package/lib/typescript/attachDeviceSync.d.ts.map +0 -1
- package/lib/typescript/brokerAccess.d.ts.map +0 -1
- package/lib/typescript/crashFlush.d.ts.map +0 -1
- package/lib/typescript/emitBudget.d.ts.map +0 -1
- package/lib/typescript/index.d.ts.map +0 -1
- package/lib/typescript/syncStatusStore.d.ts.map +0 -1
- package/lib/typescript/types.d.ts.map +0 -1
- package/lib/typescript/useExternalSync.d.ts.map +0 -1
- package/lib/typescript/useExternalSyncSocket.d.ts.map +0 -1
- package/lib/typescript/utils/getDefaultSocketURL.d.ts.map +0 -1
- package/lib/typescript/utils/getDefaultSocketURL.web.d.ts.map +0 -1
- package/lib/typescript/utils/logger.d.ts.map +0 -1
- package/lib/typescript/utils/platformUtils.d.ts.map +0 -1
- package/lib/typescript/utils/platformUtils.web.d.ts.map +0 -1
|
@@ -1,69 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
import { useAccountAccess } from "@buoy-gg/license";
|
|
4
|
-
import { useEffect, useRef } from "react";
|
|
5
|
-
import { attachDeviceSync } from "./attachDeviceSync";
|
|
6
|
-
/**
|
|
7
|
-
* Device-side sync bridge: syncs any number of dev tools to the desktop
|
|
8
|
-
* dashboard and executes actions invoked remotely.
|
|
9
|
-
*
|
|
10
|
-
* Backpressure: a tool's adapter is only subscribed while a dashboard is
|
|
11
|
-
* watching it (`devtool-watch`), so unwatched tools cost nothing. The server
|
|
12
|
-
* re-sends current watch state whenever it receives `devtool-capabilities`,
|
|
13
|
-
* which the device announces on every (re)connect.
|
|
14
|
-
*
|
|
15
|
-
* Usage:
|
|
16
|
-
* ```ts
|
|
17
|
-
* useExternalSync({
|
|
18
|
-
* tools: {
|
|
19
|
-
* storage: {
|
|
20
|
-
* version: 1,
|
|
21
|
-
* getSnapshot: () => storageEventStore.getEvents(),
|
|
22
|
-
* subscribe: (cb) => storageEventStore.subscribeToEvents(cb),
|
|
23
|
-
* actions: {
|
|
24
|
-
* clearEvents: () => storageEventStore.clearEvents(),
|
|
25
|
-
* },
|
|
26
|
-
* },
|
|
27
|
-
* },
|
|
28
|
-
* socket,
|
|
29
|
-
* deviceId: 'my-device-id',
|
|
30
|
-
* });
|
|
31
|
-
* ```
|
|
32
|
-
*/
|
|
33
|
-
export function useExternalSync({
|
|
34
|
-
tools,
|
|
35
|
-
socket,
|
|
36
|
-
deviceId,
|
|
37
|
-
enabled = true,
|
|
38
|
-
throttleMs = 200,
|
|
39
|
-
enableLogs = false
|
|
40
|
-
}) {
|
|
41
|
-
const account = useAccountAccess();
|
|
42
|
-
const admitted = account.status === "admitted";
|
|
43
|
-
const toolsRef = useRef(tools);
|
|
44
|
-
toolsRef.current = tools;
|
|
45
|
-
|
|
46
|
-
// Watch state persists across effect re-runs (e.g. when tools are
|
|
47
|
-
// added/removed) so an already-watched tool stays subscribed.
|
|
48
|
-
const watchedRef = useRef(new Map());
|
|
49
|
-
|
|
50
|
-
// Re-run the effect only when tools are added/removed, not on every
|
|
51
|
-
// object-reference change.
|
|
52
|
-
const toolIdsKey = Object.keys(tools).sort().join(",");
|
|
53
|
-
useEffect(() => {
|
|
54
|
-
if (!socket || !deviceId || !enabled || !admitted) {
|
|
55
|
-
watchedRef.current.clear();
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
|
-
return attachDeviceSync({
|
|
59
|
-
socket,
|
|
60
|
-
deviceId,
|
|
61
|
-
getTools: () => toolsRef.current,
|
|
62
|
-
watched: watchedRef.current,
|
|
63
|
-
throttleMs,
|
|
64
|
-
enableLogs
|
|
65
|
-
});
|
|
66
|
-
// toolIdsKey stands in for `tools` (see comment above its definition).
|
|
67
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
68
|
-
}, [socket, deviceId, enabled, admitted, throttleMs, enableLogs, toolIdsKey]);
|
|
69
|
-
}
|
|
1
|
+
"use strict";import{useAccountAccess as p}from"@buoy-gg/license";import{useEffect as y,useRef as a}from"react";import{attachDeviceSync as w}from"./attachDeviceSync";export function useExternalSync({tools:t,socket:r,deviceId:c,enabled:e=true,throttleMs:n=200,enableLogs:u=false}){const i=p();const o=i.status==="admitted";const s=a(t);s.current=t;const f=a(new Map);const m=Object.keys(t).sort().join(",");y(()=>{if(!r||!c||!e||!o){f.current.clear();return}return w({socket:r,deviceId:c,getTools:()=>s.current,watched:f.current,throttleMs:n,enableLogs:u})},[r,c,e,o,n,u,m])}
|
|
@@ -1,235 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
import { watchBrokerAccess } from "./brokerAccess";
|
|
4
|
-
import { useEffect, useRef, useState } from "react";
|
|
5
|
-
import { io as socketIO } from "socket.io-client";
|
|
6
|
-
import { getPlatformSpecificURL } from "./utils/platformUtils";
|
|
7
|
-
import { getDefaultSocketURL } from "./utils/getDefaultSocketURL";
|
|
8
|
-
import { log } from "./utils/logger";
|
|
9
|
-
import { setSyncStatus } from "./syncStatusStore";
|
|
10
|
-
// True only in development. Guarded so it doesn't throw in environments
|
|
11
|
-
// (web/electron bundles) where __DEV__ may be undefined.
|
|
12
|
-
const isDev = typeof __DEV__ !== "undefined" ? __DEV__ : false;
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Singleton socket instance that persists across component renders.
|
|
16
|
-
* Multiple components share the same socket connection.
|
|
17
|
-
*/
|
|
18
|
-
let globalSocketInstance = null;
|
|
19
|
-
let currentSocketURL = "";
|
|
20
|
-
let currentDeviceId = "";
|
|
21
|
-
let currentPlatform = "";
|
|
22
|
-
|
|
23
|
-
/**
|
|
24
|
-
* Identifies a single socket INSTANCE. Sent in the handshake query and reused
|
|
25
|
-
* for the life of the instance, so it survives socket.io reconnects but
|
|
26
|
-
* changes whenever we create a brand-new socket (remount / Fast Refresh /
|
|
27
|
-
* URL change). The dashboard uses this to tell a flapping connection that's
|
|
28
|
-
* merely reconnecting (stable nonce) from an app that keeps recreating its
|
|
29
|
-
* socket (changing nonce).
|
|
30
|
-
*/
|
|
31
|
-
const makeConnectionNonce = () => `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
|
|
32
|
-
|
|
33
|
-
/**
|
|
34
|
-
* Identifies this JS RUNTIME, not this socket. Held on globalThis so every
|
|
35
|
-
* socket the runtime opens (Fast Refresh, remounts, a double-mounted dev
|
|
36
|
-
* tools layer) carries the same value, while a second app that pinned the
|
|
37
|
-
* same deviceId carries a different one. That difference is the only way
|
|
38
|
-
* the broker can tell "one device, many sockets" from "many devices, one
|
|
39
|
-
* id" — it flags the latter as a collision in the device list.
|
|
40
|
-
*/
|
|
41
|
-
export function getInstanceId() {
|
|
42
|
-
const g = globalThis;
|
|
43
|
-
if (!g.__buoyInstanceId) g.__buoyInstanceId = makeConnectionNonce();
|
|
44
|
-
return g.__buoyInstanceId;
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* The socket.io handshake query — the ONE place the device says who it is.
|
|
48
|
-
* `connectionNonce` is fresh per socket instance; `instanceId` is fixed per
|
|
49
|
-
* runtime (see above). Pure, so the shape is unit-tested.
|
|
50
|
-
*/
|
|
51
|
-
export function buildHandshakeQuery(identity) {
|
|
52
|
-
const withoutAccountKey = values => values && Object.fromEntries(Object.entries(values).filter(([key]) => !["BUOY_LICENSE_KEY", "BUOY_KEY", "EXPO_PUBLIC_BUOY_KEY", "VITE_BUOY_KEY", "REACT_APP_BUOY_KEY", "licenseKey"].includes(key)));
|
|
53
|
-
return {
|
|
54
|
-
deviceName: identity.deviceName,
|
|
55
|
-
deviceId: identity.persistentDeviceId,
|
|
56
|
-
platform: identity.platform,
|
|
57
|
-
extraDeviceInfo: JSON.stringify(withoutAccountKey(identity.extraDeviceInfo)),
|
|
58
|
-
envVariables: JSON.stringify(withoutAccountKey(identity.envVariables)),
|
|
59
|
-
connectionNonce: makeConnectionNonce(),
|
|
60
|
-
instanceId: getInstanceId()
|
|
61
|
-
};
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
/**
|
|
65
|
-
* Hook that manages a Socket.IO connection for device-to-dashboard communication.
|
|
66
|
-
*
|
|
67
|
-
* Features:
|
|
68
|
-
* - Singleton pattern for socket connection
|
|
69
|
-
* - Platform-specific URL handling (Android emulator -> 10.0.2.2)
|
|
70
|
-
* - Connection state tracking
|
|
71
|
-
*/
|
|
72
|
-
export function useExternalSyncSocket({
|
|
73
|
-
deviceName,
|
|
74
|
-
socketURL,
|
|
75
|
-
persistentDeviceId,
|
|
76
|
-
extraDeviceInfo,
|
|
77
|
-
envVariables,
|
|
78
|
-
platform,
|
|
79
|
-
enableLogs = false
|
|
80
|
-
}) {
|
|
81
|
-
const socketRef = useRef(null);
|
|
82
|
-
const [socket, setSocket] = useState(null);
|
|
83
|
-
const [isConnected, setIsConnected] = useState(false);
|
|
84
|
-
// Derived once per render; stable string, so effect deps stay quiet.
|
|
85
|
-
const resolvedSocketURL = socketURL ?? getDefaultSocketURL();
|
|
86
|
-
// Tracks whether we've already logged a connection error for the current
|
|
87
|
-
// outage, so the reconnection backoff doesn't spam an error on every retry.
|
|
88
|
-
const hasLoggedConnectError = useRef(false);
|
|
89
|
-
const logPrefix = `[${deviceName}]`;
|
|
90
|
-
const onConnect = () => {
|
|
91
|
-
log(`${logPrefix} Socket connected successfully`, enableLogs);
|
|
92
|
-
hasLoggedConnectError.current = false;
|
|
93
|
-
setIsConnected(true);
|
|
94
|
-
setSyncStatus({
|
|
95
|
-
state: "connected",
|
|
96
|
-
lastError: null
|
|
97
|
-
});
|
|
98
|
-
};
|
|
99
|
-
const onDisconnect = reason => {
|
|
100
|
-
log(`${logPrefix} Socket disconnected. Reason: ${reason}`, enableLogs);
|
|
101
|
-
setIsConnected(false);
|
|
102
|
-
setSyncStatus({
|
|
103
|
-
state: "retrying"
|
|
104
|
-
});
|
|
105
|
-
};
|
|
106
|
-
const onConnectError = error => {
|
|
107
|
-
setSyncStatus({
|
|
108
|
-
state: "retrying",
|
|
109
|
-
lastError: error.message
|
|
110
|
-
});
|
|
111
|
-
// Never surface this in production builds.
|
|
112
|
-
if (!isDev) return;
|
|
113
|
-
// Reconnection retries indefinitely; only log the first failure of an
|
|
114
|
-
// outage to avoid flooding the console until the server comes back up.
|
|
115
|
-
if (hasLoggedConnectError.current) return;
|
|
116
|
-
hasLoggedConnectError.current = true;
|
|
117
|
-
// A localhost target on an Android device means a USB (adb reverse)
|
|
118
|
-
// setup — name the exact command instead of the generic hint.
|
|
119
|
-
const hint = platform === "android" && /localhost|127\.0\.0\.1/.test(currentSocketURL) ? `If this device is connected over USB, run: adb reverse tcp:42831 tcp:42831. ` : `If it's running on another machine or port, pass socketURL via the externalSync prop. `;
|
|
120
|
-
log(`[buoy] desktop sync: can't reach ${currentSocketURL} (is Buoy Desktop running?). ` + `Retrying in the background. ${hint}(${error.message})`, enableLogs, "warn");
|
|
121
|
-
};
|
|
122
|
-
const onConnectTimeout = () => {
|
|
123
|
-
log(`${logPrefix} Socket connection timeout`, enableLogs, "error");
|
|
124
|
-
};
|
|
125
|
-
|
|
126
|
-
// Reuse the transport, but reattach listeners after every effect setup
|
|
127
|
-
// (including React Strict Mode replay and Fast Refresh).
|
|
128
|
-
useEffect(() => {
|
|
129
|
-
if (!persistentDeviceId) return;
|
|
130
|
-
const platformUrl = getPlatformSpecificURL(resolvedSocketURL, platform);
|
|
131
|
-
setSyncStatus({
|
|
132
|
-
targetURL: platformUrl,
|
|
133
|
-
state: "connecting",
|
|
134
|
-
lastError: null
|
|
135
|
-
});
|
|
136
|
-
log(`${logPrefix} Platform: ${platform}, using URL: ${platformUrl}`, enableLogs);
|
|
137
|
-
try {
|
|
138
|
-
if (globalSocketInstance && (currentSocketURL !== platformUrl || currentDeviceId !== persistentDeviceId || currentPlatform !== platform)) {
|
|
139
|
-
globalSocketInstance.disconnect();
|
|
140
|
-
globalSocketInstance = null;
|
|
141
|
-
}
|
|
142
|
-
if (!globalSocketInstance) {
|
|
143
|
-
log(`${logPrefix} Creating new socket instance to ${platformUrl}`, enableLogs);
|
|
144
|
-
globalSocketInstance = socketIO(platformUrl, {
|
|
145
|
-
autoConnect: true,
|
|
146
|
-
query: buildHandshakeQuery({
|
|
147
|
-
deviceName,
|
|
148
|
-
persistentDeviceId,
|
|
149
|
-
platform,
|
|
150
|
-
extraDeviceInfo,
|
|
151
|
-
envVariables
|
|
152
|
-
}),
|
|
153
|
-
reconnection: true,
|
|
154
|
-
reconnectionAttempts: Infinity,
|
|
155
|
-
reconnectionDelay: 1000,
|
|
156
|
-
reconnectionDelayMax: 5000,
|
|
157
|
-
transports: ["websocket"]
|
|
158
|
-
});
|
|
159
|
-
currentSocketURL = platformUrl;
|
|
160
|
-
currentDeviceId = persistentDeviceId;
|
|
161
|
-
currentPlatform = platform;
|
|
162
|
-
} else {
|
|
163
|
-
log(`${logPrefix} Reusing existing socket instance to ${platformUrl}`, enableLogs);
|
|
164
|
-
}
|
|
165
|
-
socketRef.current = globalSocketInstance;
|
|
166
|
-
const activeSocket = socketRef.current;
|
|
167
|
-
setSocket(activeSocket);
|
|
168
|
-
activeSocket.on("connect_error", onConnectError);
|
|
169
|
-
activeSocket.on("connect_timeout", onConnectTimeout);
|
|
170
|
-
setIsConnected(activeSocket.connected);
|
|
171
|
-
if (activeSocket.connected) {
|
|
172
|
-
log(`${logPrefix} Socket already connected on init`, enableLogs);
|
|
173
|
-
}
|
|
174
|
-
activeSocket.on("connect", onConnect);
|
|
175
|
-
activeSocket.on("disconnect", onDisconnect);
|
|
176
|
-
return () => {
|
|
177
|
-
log(`${logPrefix} Cleaning up socket event listeners`, enableLogs);
|
|
178
|
-
activeSocket.off("connect", onConnect);
|
|
179
|
-
activeSocket.off("disconnect", onDisconnect);
|
|
180
|
-
activeSocket.off("connect_error", onConnectError);
|
|
181
|
-
activeSocket.off("connect_timeout", onConnectTimeout);
|
|
182
|
-
};
|
|
183
|
-
} catch (error) {
|
|
184
|
-
log(`${logPrefix} Failed to initialize socket: ${error}`, enableLogs, "error");
|
|
185
|
-
}
|
|
186
|
-
}, [persistentDeviceId, resolvedSocketURL, platform]);
|
|
187
|
-
|
|
188
|
-
// Update socket query parameters when deviceName changes
|
|
189
|
-
useEffect(() => {
|
|
190
|
-
if (socketRef.current && socketRef.current.io.opts.query && persistentDeviceId) {
|
|
191
|
-
log(`${logPrefix} Updating device name in socket connection`, enableLogs);
|
|
192
|
-
socketRef.current.io.opts.query = {
|
|
193
|
-
...socketRef.current.io.opts.query,
|
|
194
|
-
deviceName,
|
|
195
|
-
deviceId: persistentDeviceId,
|
|
196
|
-
platform
|
|
197
|
-
};
|
|
198
|
-
}
|
|
199
|
-
}, [deviceName, logPrefix, persistentDeviceId, platform, enableLogs]);
|
|
200
|
-
function connect() {
|
|
201
|
-
if (socketRef.current && !socketRef.current.connected) {
|
|
202
|
-
log(`${logPrefix} Manually connecting to socket server`, enableLogs);
|
|
203
|
-
socketRef.current.connect();
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
function disconnect() {
|
|
207
|
-
if (socketRef.current && socketRef.current.connected) {
|
|
208
|
-
log(`${logPrefix} Manually disconnecting from socket server`, enableLogs);
|
|
209
|
-
socketRef.current.disconnect();
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
// A connected transport is not permission to sync. Legacy desktop brokers
|
|
214
|
-
// never send this announcement, so updated SDKs withhold tools from them.
|
|
215
|
-
const [admittedSocket, setAdmittedSocket] = useState(null);
|
|
216
|
-
useEffect(() => {
|
|
217
|
-
if (!socket) return;
|
|
218
|
-
return watchBrokerAccess(socket, ready => {
|
|
219
|
-
setAdmittedSocket(ready ? socket : null);
|
|
220
|
-
setSyncStatus(ready ? {
|
|
221
|
-
state: "connected",
|
|
222
|
-
lastError: null
|
|
223
|
-
} : {
|
|
224
|
-
state: "retrying",
|
|
225
|
-
lastError: "Update Buoy Desktop and sign in to enable desktop sync."
|
|
226
|
-
});
|
|
227
|
-
});
|
|
228
|
-
}, [socket]);
|
|
229
|
-
return {
|
|
230
|
-
socket: admittedSocket === socket ? socket : null,
|
|
231
|
-
connect,
|
|
232
|
-
disconnect,
|
|
233
|
-
isConnected: isConnected && admittedSocket === socket && socket !== null
|
|
234
|
-
};
|
|
235
|
-
}
|
|
1
|
+
"use strict";import{watchBrokerAccess as w}from"./brokerAccess";import{useEffect as $,useRef as O,useState as g}from"react";import{io as M}from"socket.io-client";import{getPlatformSpecificURL as N}from"./utils/platformUtils";import{getDefaultSocketURL as V}from"./utils/getDefaultSocketURL";import{log as r}from"./utils/logger";import{setSyncStatus as f}from"./syncStatusStore";import{pinSocketTimers as q,realClearTimeout as j,realSetTimeout as J}from"./realNow";const b=typeof __DEV__!=="undefined"?__DEV__:false;let l=null;let m="";let v="";let x="";let _=0;let d=null;const z=2e3;const B=()=>`${Date.now().toString(36)}-${Math.random().toString(36).slice(2,10)}`;export function getInstanceId(){const o=globalThis;if(!o.__buoyInstanceId)o.__buoyInstanceId=B();return o.__buoyInstanceId}export function buildHandshakeQuery(o){const k=i=>i&&Object.fromEntries(Object.entries(i).filter(([S])=>!["BUOY_LICENSE_KEY","BUOY_KEY","EXPO_PUBLIC_BUOY_KEY","VITE_BUOY_KEY","REACT_APP_BUOY_KEY","licenseKey"].includes(S)));return{deviceName:o.deviceName,deviceId:o.persistentDeviceId,platform:o.platform,extraDeviceInfo:JSON.stringify(k(o.extraDeviceInfo)),envVariables:JSON.stringify(k(o.envVariables)),connectionNonce:B(),instanceId:getInstanceId()}}export function useExternalSyncSocket({deviceName:o,socketURL:k,persistentDeviceId:i,extraDeviceInfo:S,envVariables:Y,platform:u,enableLogs:n=false}){const s=O(null);const[a,A]=g(null);const[P,y]=g(false);const p=k??V();const E=O(false);const c=`[${o}]`;const U=()=>{r(`${c} Socket connected successfully`,n);E.current=false;y(true);f({state:"connected",lastError:null})};const I=e=>{r(`${c} Socket disconnected. Reason: ${e}`,n);y(false);f({state:"retrying"})};const C=e=>{f({state:"retrying",lastError:e.message});if(!b)return;if(E.current)return;E.current=true;const t=u==="android"&&/localhost|127\.0\.0\.1/.test(m)?`If this device is connected over USB, run: adb reverse tcp:42831 tcp:42831. `:`If it's running on another machine or port, pass socketURL via the externalSync prop. `;r(`[buoy] desktop sync: can't reach ${m} (is Buoy Desktop running?). Retrying in the background. ${t}(${e.message})`,n,"warn")};const h=()=>{r(`${c} Socket connection timeout`,n,"error")};$(()=>{if(!i)return;const e=N(p,u);f({targetURL:e,state:"connecting",lastError:null});r(`${c} Platform: ${u}, using URL: ${e}`,n);try{if(l&&(m!==e||v!==i||x!==u)){l.disconnect();l=null}if(!l){r(`${c} Creating new socket instance to ${e}`,n);l=M(e,{autoConnect:true,query:buildHandshakeQuery({deviceName:o,persistentDeviceId:i,platform:u,extraDeviceInfo:S,envVariables:Y}),reconnection:true,reconnectionAttempts:Infinity,reconnectionDelay:1e3,reconnectionDelayMax:5e3,transports:["websocket"]});q(l);m=e;v=i;x=u}else{r(`${c} Reusing existing socket instance to ${e}`,n)}s.current=l;const t=s.current;_++;if(d){j(d);d=null}A(t);t.on("connect_error",C);t.on("connect_timeout",h);y(t.connected);if(t.connected){r(`${c} Socket already connected on init`,n)}t.on("connect",U);t.on("disconnect",I);return()=>{r(`${c} Cleaning up socket event listeners`,n);t.off("connect",U);t.off("disconnect",I);t.off("connect_error",C);t.off("connect_timeout",h);_--;if(_===0){d=J(()=>{d=null;if(_>0||l!==t)return;r(`${c} No longer used; disconnecting`,n);t.disconnect();l=null;f({state:"idle",lastError:null})},z)}}}catch(t){r(`${c} Failed to initialize socket: ${t}`,n,"error")}},[i,p,u]);$(()=>{if(s.current&&s.current.io.opts.query&&i){r(`${c} Updating device name in socket connection`,n);s.current.io.opts.query={...s.current.io.opts.query,deviceName:o,deviceId:i,platform:u}}},[o,c,i,u,n]);function T(){if(s.current&&!s.current.connected){r(`${c} Manually connecting to socket server`,n);s.current.connect()}}function D(){if(s.current&&s.current.connected){r(`${c} Manually disconnecting from socket server`,n);s.current.disconnect()}}const[R,K]=g(null);$(()=>{if(!a)return;return w(a,e=>{K(e?a:null);f(e?{state:"connected",lastError:null}:{state:"retrying",lastError:"Update Buoy Desktop and sign in to enable desktop sync."})})},[a]);return{socket:R===a?a:null,connect:T,disconnect:D,isConnected:P&&R===a&&a!==null}}
|
|
@@ -1,76 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Default broker-URL derivation. Kept in its own module (and never imported
|
|
5
|
-
* from types.ts) because the deep react-native require below must not reach
|
|
6
|
-
* non-Metro bundles — the desktop app imports this package's types only.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
|
-
/** Port Buoy Desktop's broker listens on. */
|
|
10
|
-
export const DEFAULT_BROKER_PORT = 42831;
|
|
11
|
-
const HOST_RE = /^https?:\/\/([^:/]+)/;
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* Host out of a bundle's scriptURL, or null when there isn't one.
|
|
15
|
-
*
|
|
16
|
-
* Release bundles are loaded from disk (`file:///.../main.jsbundle`), so this
|
|
17
|
-
* returns null and callers fall back to localhost — correct for simulators,
|
|
18
|
-
* emulators, and Android over USB (`adb reverse tcp:42831 tcp:42831`). A
|
|
19
|
-
* physical iOS device in a release build has no derivable host at all and
|
|
20
|
-
* must be given an explicit socketURL.
|
|
21
|
-
*/
|
|
22
|
-
export function hostFromScriptURL(scriptURL) {
|
|
23
|
-
return scriptURL?.match(HOST_RE)?.[1] ?? null;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
/** Broker URL for a host, falling back to localhost when none is known. */
|
|
27
|
-
export function socketURLForHost(host) {
|
|
28
|
-
return `http://${host ?? "localhost"}:${DEFAULT_BROKER_PORT}`;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Host of the Metro dev server that served this bundle — the machine most
|
|
33
|
-
* likely running Buoy Desktop. On a physical device this is the computer's
|
|
34
|
-
* LAN IP, where "localhost" would be the phone itself.
|
|
35
|
-
*
|
|
36
|
-
* scriptURL is the only source that works everywhere we've tested:
|
|
37
|
-
* NativeModules.SourceCode.scriptURL is undefined on bridgeless, and
|
|
38
|
-
* expo-constants hostUri/experienceUrl/linkingUri are all undefined in
|
|
39
|
-
* Expo dev-client builds. Returns null on web or if RN internals move.
|
|
40
|
-
*/
|
|
41
|
-
export function getMetroHost() {
|
|
42
|
-
try {
|
|
43
|
-
// The public route to the SourceCode TurboModule that
|
|
44
|
-
// react-native/Libraries/NativeModules/specs/NativeSourceCode wraps. Deep
|
|
45
|
-
// imports warn on RN 0.80+; react-native-web has no registry and falls
|
|
46
|
-
// through to null.
|
|
47
|
-
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
48
|
-
const {
|
|
49
|
-
TurboModuleRegistry
|
|
50
|
-
} = require("react-native");
|
|
51
|
-
const NativeSourceCode = TurboModuleRegistry?.get?.("SourceCode");
|
|
52
|
-
const host = hostFromScriptURL(NativeSourceCode?.getConstants?.().scriptURL);
|
|
53
|
-
if (host) return host;
|
|
54
|
-
} catch {
|
|
55
|
-
// web / RN internals moved — try the old-architecture module
|
|
56
|
-
}
|
|
57
|
-
try {
|
|
58
|
-
const {
|
|
59
|
-
NativeModules
|
|
60
|
-
} = require("react-native");
|
|
61
|
-
const host = hostFromScriptURL(NativeModules?.SourceCode?.getConstants?.().scriptURL ?? NativeModules?.SourceCode?.scriptURL);
|
|
62
|
-
if (host) return host;
|
|
63
|
-
} catch {
|
|
64
|
-
// not React Native
|
|
65
|
-
}
|
|
66
|
-
return null;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
/**
|
|
70
|
-
* Default Buoy Desktop broker URL: the Metro host (falling back to
|
|
71
|
-
* localhost) on port 42831. Android-emulator 10.0.2.2 rewriting is applied
|
|
72
|
-
* later by getPlatformSpecificURL, so localhost still works there.
|
|
73
|
-
*/
|
|
74
|
-
export function getDefaultSocketURL() {
|
|
75
|
-
return socketURLForHost(getMetroHost());
|
|
76
|
-
}
|
|
1
|
+
"use strict";export const DEFAULT_BROKER_PORT=42831;const r=/^https?:\/\/([^:/]+)/;export function hostFromScriptURL(t){return t?.match(r)?.[1]??null}export function socketURLForHost(t){return`http://${t??"localhost"}:${DEFAULT_BROKER_PORT}`}export function getMetroHost(){try{const{TurboModuleRegistry:t}=require("react-native");const e=t?.get?.("SourceCode");const o=hostFromScriptURL(e?.getConstants?.().scriptURL);if(o)return o}catch{}try{const{NativeModules:t}=require("react-native");const e=hostFromScriptURL(t?.SourceCode?.getConstants?.().scriptURL??t?.SourceCode?.scriptURL);if(e)return e}catch{}return null}export function getDefaultSocketURL(){return socketURLForHost(getMetroHost())}
|
|
@@ -1,19 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
export const DEFAULT_BROKER_PORT = 42831;
|
|
4
|
-
export function hostFromScriptURL(url) {
|
|
5
|
-
try {
|
|
6
|
-
return url && /^https?:/.test(url) ? new URL(url).hostname : null;
|
|
7
|
-
} catch {
|
|
8
|
-
return null;
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
export function socketURLForHost(host) {
|
|
12
|
-
return `http://${host ?? "localhost"}:${DEFAULT_BROKER_PORT}`;
|
|
13
|
-
}
|
|
14
|
-
export function getMetroHost() {
|
|
15
|
-
return null;
|
|
16
|
-
}
|
|
17
|
-
export function getDefaultSocketURL() {
|
|
18
|
-
return socketURLForHost(typeof location === "undefined" ? null : location.hostname);
|
|
19
|
-
}
|
|
1
|
+
"use strict";export const DEFAULT_BROKER_PORT=42831;export function hostFromScriptURL(t){try{return t&&/^https?:/.test(t)?new URL(t).hostname:null}catch{return null}}export function socketURLForHost(t){return`http://${t??"localhost"}:${DEFAULT_BROKER_PORT}`}export function getMetroHost(){return null}export function getDefaultSocketURL(){return socketURLForHost(typeof location==="undefined"?null:location.hostname)}
|
|
@@ -1,20 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Helper function for controlled logging.
|
|
5
|
-
* Only shows logs when enableLogs is true.
|
|
6
|
-
* Always shows warnings and errors regardless of enableLogs setting.
|
|
7
|
-
*/
|
|
8
|
-
export function log(message, enableLogs, type = "log") {
|
|
9
|
-
if (!enableLogs && type === "log") return;
|
|
10
|
-
switch (type) {
|
|
11
|
-
case "warn":
|
|
12
|
-
console.warn(message);
|
|
13
|
-
break;
|
|
14
|
-
case "error":
|
|
15
|
-
console.error(message);
|
|
16
|
-
break;
|
|
17
|
-
default:
|
|
18
|
-
console.log(message);
|
|
19
|
-
}
|
|
20
|
-
}
|
|
1
|
+
"use strict";export function log(o,c,r="log"){if(!c&&r==="log")return;switch(r){case"warn":console.warn(o);break;case"error":console.error(o);break;default:console.log(o)}}
|
|
@@ -1,45 +1 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* True only on an actual Android EMULATOR, detected via the build fingerprint
|
|
5
|
-
* (same heuristic react-native-device-info uses), with no native dependency.
|
|
6
|
-
* Physical devices must NOT get the 10.0.2.2 rewrite: over USB (`adb reverse`)
|
|
7
|
-
* the Metro-derived host is "localhost", and rewriting it to the
|
|
8
|
-
* emulator-only 10.0.2.2 alias breaks the connection — keeping localhost lets
|
|
9
|
-
* `adb reverse tcp:42831 tcp:42831` forward it to the dev machine.
|
|
10
|
-
*
|
|
11
|
-
* The react-native require stays lexically inside try{} (Metro optional-dep
|
|
12
|
-
* rule) and this module is never imported from types.ts, so non-Metro
|
|
13
|
-
* bundles (the desktop app) are unaffected.
|
|
14
|
-
*/
|
|
15
|
-
const isAndroidEmulator = () => {
|
|
16
|
-
try {
|
|
17
|
-
const {
|
|
18
|
-
Platform
|
|
19
|
-
} = require("react-native");
|
|
20
|
-
if (Platform.OS !== "android") return false;
|
|
21
|
-
const fingerprint = Platform.constants?.Fingerprint ?? "";
|
|
22
|
-
return /generic|emulator|goldfish|ranchu|sdk_gphone|vbox/i.test(fingerprint);
|
|
23
|
-
} catch {
|
|
24
|
-
return false;
|
|
25
|
-
}
|
|
26
|
-
};
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Get platform-specific URL for socket connection.
|
|
30
|
-
* On the Android emulator (only), replaces localhost with 10.0.2.2 —
|
|
31
|
-
* the emulator's alias for the host machine's loopback.
|
|
32
|
-
*/
|
|
33
|
-
export const getPlatformSpecificURL = (baseUrl, platform) => {
|
|
34
|
-
try {
|
|
35
|
-
const url = new URL(baseUrl);
|
|
36
|
-
if (platform === "android" && (url.hostname === "localhost" || url.hostname === "127.0.0.1") && isAndroidEmulator()) {
|
|
37
|
-
url.hostname = "10.0.2.2";
|
|
38
|
-
return url.toString();
|
|
39
|
-
}
|
|
40
|
-
return baseUrl;
|
|
41
|
-
} catch (e) {
|
|
42
|
-
console.warn("Error getting platform-specific URL:", e);
|
|
43
|
-
return baseUrl;
|
|
44
|
-
}
|
|
45
|
-
};
|
|
1
|
+
"use strict";const e=()=>{try{const{Platform:t}=require("react-native");if(t.OS!=="android")return false;const n=t.constants?.Fingerprint??"";return/generic|emulator|goldfish|ranchu|sdk_gphone|vbox/i.test(n)}catch{return false}};export const getPlatformSpecificURL=(t,n)=>{try{const r=new URL(t);if(n==="android"&&(r.hostname==="localhost"||r.hostname==="127.0.0.1")&&e()){r.hostname="10.0.2.2";return r.toString()}return t}catch(r){console.warn("Error getting platform-specific URL:",r);return t}};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The device's real clock.
|
|
3
|
+
*
|
|
4
|
+
* @buoy-gg/clock can override the APP's clock (Date.now, new Date). Buoy's
|
|
5
|
+
* own bookkeeping must keep real time regardless: license expiry, sync
|
|
6
|
+
* throttles and request deadlines would otherwise lock tools or stall when
|
|
7
|
+
* someone travels a month ahead. The clock package publishes the real clock
|
|
8
|
+
* on `globalThis.__buoyRealNow`; without it, Date.now is already real.
|
|
9
|
+
*/
|
|
10
|
+
export declare function realNow(): number;
|
|
11
|
+
/**
|
|
12
|
+
* setTimeout that a clock jump never fires early. @buoy-gg/clock tracks the
|
|
13
|
+
* app's timers so a jump ahead can run the ones that come due; Buoy's own
|
|
14
|
+
* deadlines and heartbeats must not be among them.
|
|
15
|
+
*/
|
|
16
|
+
export declare function realSetTimeout(callback: () => void, ms: number): ReturnType<typeof setTimeout>;
|
|
17
|
+
export declare function realClearTimeout(handle: unknown): void;
|
|
18
|
+
/** Run `fn` on the real clock (a no-op scope when @buoy-gg/clock is absent). */
|
|
19
|
+
export declare function withRealClock<T>(fn: () => T): T;
|
|
20
|
+
/**
|
|
21
|
+
* Keep a socket.io socket on real time: its Manager and engine get real
|
|
22
|
+
* timers (engine.io's heartbeat is a ping-timeout setTimeout a jump would
|
|
23
|
+
* fire) and the engine's clock-reading methods run in a real-clock scope. The
|
|
24
|
+
* engine is rebuilt on every reconnect, so `open` re-pins it.
|
|
25
|
+
*/
|
|
26
|
+
export declare function pinSocketTimers(socket: unknown): void;
|
|
27
|
+
//# sourceMappingURL=realNow.d.ts.map
|
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Module-level desktop-sync status, written by useExternalSyncSocket and
|
|
3
|
-
* read by the floating menu's settings modal (via useSyncExternalStore).
|
|
4
|
-
* Lives here rather than in core because only the socket hook knows the
|
|
5
|
-
* platform-rewritten URL and every connection transition — including for
|
|
6
|
-
* apps that call the hook directly instead of using zero-config sync.
|
|
7
|
-
*/
|
|
8
1
|
export interface SyncStatus {
|
|
9
2
|
/** Final (platform-rewritten) broker URL being dialed; null before init. */
|
|
10
3
|
targetURL: string | null;
|
package/lib/web/index.mjs
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
var S=process.env.NODE_ENV!=="production";typeof window<"u"&&typeof globalThis.global>"u"&&(globalThis.global=globalThis);import{useAccountAccess as me}from"@buoy-gg/license/web";import{useEffect as ve,useRef as ae}from"react";import{LicenseManager as I}from"@buoy-gg/license/web";function l(t,c,n="log"){if(!(!c&&n==="log"))switch(n){case"warn":console.warn(t);break;case"error":console.error(t);break;default:console.log(t)}}var q="__buoyFlushToolSync";function K(){let t=globalThis;return t[q]||(t[q]=new Set),t[q]}function V(t){K().add(t)}function W(t){K().delete(t)}function he(t){try{for(let c of K())try{c(t)}catch{}}catch{}}function j(t,c){let n=0,i=[t],h=new Set;for(;i.length>0;){if(n>c)return{over:!0,approxBytes:n};let o=i.pop();if(o==null)n+=4;else if(typeof o=="string")n+=o.length+2;else if(typeof o=="number")n+=8;else if(typeof o=="boolean")n+=5;else if(typeof o=="object"){if(h.has(o))continue;if(h.add(o),Array.isArray(o)){n+=2+o.length;for(let s=0;s<o.length;s++)i.push(o[s])}else{n+=2;for(let s in o)n+=s.length+4,i.push(o[s])}}else n+=4}return{over:n>c,approxBytes:n}}var re=1;var P="[ExternalSync]";function ie({socket:t,deviceId:c,getTools:n,watched:i,throttleMs:h=200,enableLogs:o=!1}){let s=!1,a=!1,p=0,g=()=>!s&&a&&t.connected&&I.hasAccountAccess(),m=new Map,k={},v={},w=e=>e==="All"||e===c,u=(e,r)=>{if(g())try{t.emit(e,r)}catch(y){l(`${P} Failed to emit "${e}": ${y}. Payload must be JSON-serializable.`,o,"error")}},M=new Set,x=e=>{if(!g())return;let r=n()[e];if(!r)return;k[e]=Date.now();let y;try{y=r.getSnapshot()}catch{return}let{over:T,approxBytes:$}=j(y,2097152);if(T){M.has(e)||(M.add(e),console.warn(`${P} "${e}" snapshot \u2248${($/1e6).toFixed(1)}MB exceeds the ${2097152/1e6}MB sync budget \u2014 dropped (dashboard will be stale for this tool). The adapter should ship a wire-form snapshot (summaries + on-demand detail).`));return}let Y={toolId:e,persistentDeviceId:c,timestamp:k[e],version:r.version,kind:"snapshot",payload:y};u("devtool-sync",Y)},A=e=>{if(v[e])return;let r=Date.now()-(k[e]??0);if(r>=h){x(e);return}v[e]=setTimeout(()=>{delete v[e],x(e)},h-r)},O=e=>{t.connected&&m.has(e)&&(v[e]&&(clearTimeout(v[e]),delete v[e]),x(e))};V(O);let D=new Map,C=(e,r)=>{if(!g())return;let y=n()[e];if(y){if(m.has(e)){if(D.get(e)===r)return;let T=m.get(e);m.set(e,y.subscribe(r==="stream"?()=>A(e):()=>{})),D.set(e,r),T?.(),l(`${P} "${e}" watch mode \u2192 ${r}`,o);return}m.set(e,y.subscribe(r==="stream"?()=>A(e):()=>{})),D.set(e,r),l(`${P} Watching "${e}" (${r})`,o)}},E=e=>{m.get(e)?.(),m.delete(e),D.delete(e),v[e]&&(clearTimeout(v[e]),delete v[e]),l(`${P} Stopped watching "${e}"`,o)},N=()=>{let e={persistentDeviceId:c,protocolVersion:1,tools:Object.entries(n()).map(([r,y])=>({toolId:r,version:y.version,actions:Object.keys(y.actions??{})}))};u("devtool-capabilities",e)},f=e=>{if(!(!g()||!w(e.targetDeviceId)))if(e.watching){let r=e.consolidated===!0&&e.stream===!1?"capture":"stream";i.set(e.toolId,r),C(e.toolId,r),r==="stream"&&x(e.toolId)}else i.delete(e.toolId),E(e.toolId)},d=e=>{!g()||!w(e.targetDeviceId)||x(e.toolId)},Q=async e=>{if(!g()||!w(e.targetDeviceId))return;let r=p,{requestId:y,toolId:T,action:$,params:Y}=e,b={requestId:y,toolId:T,action:$,persistentDeviceId:c,timestamp:Date.now(),ok:!1},ne=n()[T],oe=ne?.actions?.[$];if(!oe){b.error=ne?`Unknown action "${$}" on tool "${T}"`:`Unknown tool "${T}"`,u("devtool-action-result",b);return}try{b.result=await oe(Y),b.ok=!0}catch(U){b.error=U instanceof Error?U.message:String(U)}if(!(r!==p||!g())){if(b.ok){let{over:U,approxBytes:Se}=j(b.result,8388608);U&&(b.ok=!1,b.result=void 0,b.error=`Result \u2248${(Se/1e6).toFixed(1)}MB exceeds the ${8388608/1e6}MB sync budget. Narrow the request (e.g. includeValues:false, a limit, or a more specific action).`)}b.timestamp=Date.now(),u("devtool-action-result",b)}},B=()=>{p+=1;for(let r of[...m.keys()])E(r);i.clear();for(let r of Object.values(v))clearTimeout(r);let e=t;e.sendBuffer&&(e.sendBuffer=e.sendBuffer.filter(r=>!["devtool-sync","devtool-capabilities","devtool-action-result","device-license"].includes(String(r.data?.[0]))))},Z=()=>{let e=I.getState();t.emit("device-license",{tier:e.tier,isPro:e.isPro?"1":"0"}),N()},ee=e=>{a=e?.protocol===1&&e.ready===!0,g()?Z():B()},ye=I.subscribe(()=>{I.hasAccountAccess()?g()&&Z():(t.connected&&t.emit("device-license",{tier:"locked",isPro:"0"}),B())}),L=()=>{a=!1,t.emit("buoy:access:request")},te=()=>{a=!1,B()};t.on("buoy:access",ee);for(let[e,r]of i)n()[e]&&C(e,r);return t.on("connect",L),t.on("disconnect",te),t.on("devtool-watch",f),t.on("request-devtool-state",d),t.on("devtool-action",Q),t.connected&&L(),()=>{s=!0,ye(),t.off("buoy:access",ee),B(),W(O),t.off("connect",L),t.off("disconnect",te),t.off("devtool-watch",f),t.off("request-devtool-state",d),t.off("devtool-action",Q);for(let e of[...m.keys()])E(e)}}function be({tools:t,socket:c,deviceId:n,enabled:i=!0,throttleMs:h=200,enableLogs:o=!1}){let a=me().status==="admitted",p=ae(t);p.current=t;let g=ae(new Map),m=Object.keys(t).sort().join(",");ve(()=>{if(!c||!n||!i||!a){g.current.clear();return}return ie({socket:c,deviceId:n,getTools:()=>p.current,watched:g.current,throttleMs:h,enableLogs:o})},[c,n,i,a,h,o,m])}function le(t,c){let n=()=>c(!1),i=()=>{n(),t.emit("buoy:access:request")},h=o=>{let s=o;c(s?.protocol===1&&s?.ready===!0)};return t.on("connect",i),t.on("disconnect",n),t.on("buoy:access",h),n(),t.connected&&i(),()=>{t.off("connect",i),t.off("disconnect",n),t.off("buoy:access",h)}}import{useEffect as G,useRef as fe,useState as J}from"react";import{io as De}from"socket.io-client";function ue(t,c){return t}var xe=42831;function Te(t){return`http://${t??"localhost"}:42831`}function ke(){return null}function H(){return Te(typeof location>"u"?null:location.hostname)}var z={targetURL:null,state:"idle",lastError:null,since:0},X=new Set;function R(t){z={...z,...t,since:Date.now()},X.forEach(c=>c())}function we(){return z}function Re(t){return X.add(t),()=>{X.delete(t)}}var Ee=typeof S<"u"?S:!1,_=null,F="",de="",pe="",ge=()=>`${Date.now().toString(36)}-${Math.random().toString(36).slice(2,10)}`;function _e(){let t=globalThis;return t.__buoyInstanceId||(t.__buoyInstanceId=ge()),t.__buoyInstanceId}function Me(t){let c=n=>n&&Object.fromEntries(Object.entries(n).filter(([i])=>!["BUOY_LICENSE_KEY","BUOY_KEY","EXPO_PUBLIC_BUOY_KEY","VITE_BUOY_KEY","REACT_APP_BUOY_KEY","licenseKey"].includes(i)));return{deviceName:t.deviceName,deviceId:t.persistentDeviceId,platform:t.platform,extraDeviceInfo:JSON.stringify(c(t.extraDeviceInfo)),envVariables:JSON.stringify(c(t.envVariables)),connectionNonce:ge(),instanceId:_e()}}function Ae({deviceName:t,socketURL:c,persistentDeviceId:n,extraDeviceInfo:i,envVariables:h,platform:o,enableLogs:s=!1}){let a=fe(null),[p,g]=J(null),[m,k]=J(!1),v=c??H(),w=fe(!1),u=`[${t}]`,M=()=>{l(`${u} Socket connected successfully`,s),w.current=!1,k(!0),R({state:"connected",lastError:null})},x=f=>{l(`${u} Socket disconnected. Reason: ${f}`,s),k(!1),R({state:"retrying"})},A=f=>{if(R({state:"retrying",lastError:f.message}),!Ee||w.current)return;w.current=!0;let d=o==="android"&&/localhost|127\.0\.0\.1/.test(F)?"If this device is connected over USB, run: adb reverse tcp:42831 tcp:42831. ":"If it's running on another machine or port, pass socketURL via the externalSync prop. ";l(`[buoy] desktop sync: can't reach ${F} (is Buoy Desktop running?). Retrying in the background. ${d}(${f.message})`,s,"warn")},O=()=>{l(`${u} Socket connection timeout`,s,"error")};G(()=>{if(!n)return;let f=ue(v,o);R({targetURL:f,state:"connecting",lastError:null}),l(`${u} Platform: ${o}, using URL: ${f}`,s);try{_&&(F!==f||de!==n||pe!==o)&&(_.disconnect(),_=null),_?l(`${u} Reusing existing socket instance to ${f}`,s):(l(`${u} Creating new socket instance to ${f}`,s),_=De(f,{autoConnect:!0,query:Me({deviceName:t,persistentDeviceId:n,platform:o,extraDeviceInfo:i,envVariables:h}),reconnection:!0,reconnectionAttempts:1/0,reconnectionDelay:1e3,reconnectionDelayMax:5e3,transports:["websocket"]}),F=f,de=n,pe=o),a.current=_;let d=a.current;return g(d),d.on("connect_error",A),d.on("connect_timeout",O),k(d.connected),d.connected&&l(`${u} Socket already connected on init`,s),d.on("connect",M),d.on("disconnect",x),()=>{l(`${u} Cleaning up socket event listeners`,s),d.off("connect",M),d.off("disconnect",x),d.off("connect_error",A),d.off("connect_timeout",O)}}catch(d){l(`${u} Failed to initialize socket: ${d}`,s,"error")}},[n,v,o]),G(()=>{a.current&&a.current.io.opts.query&&n&&(l(`${u} Updating device name in socket connection`,s),a.current.io.opts.query={...a.current.io.opts.query,deviceName:t,deviceId:n,platform:o})},[t,u,n,o,s]);function D(){a.current&&!a.current.connected&&(l(`${u} Manually connecting to socket server`,s),a.current.connect())}function C(){a.current&&a.current.connected&&(l(`${u} Manually disconnecting from socket server`,s),a.current.disconnect())}let[E,N]=J(null);return G(()=>{if(p)return le(p,f=>{N(f?p:null),R(f?{state:"connected",lastError:null}:{state:"retrying",lastError:"Update Buoy Desktop and sign in to enable desktop sync."})})},[p]),{socket:E===p?p:null,connect:D,disconnect:C,isConnected:m&&E===p&&p!==null}}export{xe as DEFAULT_BROKER_PORT,re as SYNC_PROTOCOL_VERSION,he as flushToolSyncNow,H as getDefaultSocketURL,ke as getMetroHost,we as getSyncStatus,V as registerToolFlusher,R as setSyncStatus,Re as subscribeSyncStatus,W as unregisterToolFlusher,be as useExternalSync,Ae as useExternalSyncSocket};
|
|
1
|
+
"use client";var ne=process.env.NODE_ENV!=="production";typeof window<"u"&&typeof globalThis.global>"u"&&(globalThis.global=globalThis);import{useAccountAccess as he}from"@buoy-gg/license/web";import{useEffect as ve,useRef as oe}from"react";import{LicenseManager as P}from"@buoy-gg/license/web";function p(e,o,n="log"){if(!(!o&&n==="log"))switch(n){case"warn":console.warn(e);break;case"error":console.error(e);break;default:console.log(e)}}var j="__buoyFlushToolSync";function K(){let e=globalThis;return e[j]||(e[j]=new Set),e[j]}function re(e){K().add(e)}function ce(e){K().delete(e)}function be(e){try{for(let o of K())try{o(e)}catch{}}catch{}}function se(e,o){let n=0,i=[e],l=new Set;for(;i.length>0;){if(n>o)return{over:true,approxBytes:n};let r=i.pop();if(r==null)n+=4;else if(typeof r=="string")n+=r.length+2;else if(typeof r=="number")n+=8;else if(typeof r=="boolean")n+=5;else if(typeof r=="object"){if(l.has(r))continue;if(l.add(r),Array.isArray(r)){n+=2+r.length;for(let c=0;c<r.length;c++)i.push(r[c])}else{n+=2;for(let c in r)n+=c.length+4,i.push(r[c])}}else n+=4}return{over:n>o,approxBytes:n}}var $e=1;function U(){let e=globalThis.__buoyRealNow;return typeof e=="function"?e():Date.now()}function ie(){return globalThis.__buoyRealTimers??globalThis}function ae(e,o){return ie().setTimeout(e,o)}function le(e){ie().clearTimeout(e)}function _e(e){let o=globalThis.__buoyWithRealClock;return typeof o=="function"?o(e):e()}var Ie=["_resetPingTimeout","_hasPingExpired"];function ke(e){let o=e?.io;if(!o||o.__buoyRealTimers)return;let n=l=>{if(l){l.setTimeoutFn=ae,l.clearTimeoutFn=le;for(let r of Ie){let c=l[r];if(typeof c!="function"||c.__buoyReal)continue;let a=function(...y){return _e(()=>c.apply(this,y))};a.__buoyReal=true,l[r]=a}}};n(o),n(o.engine);let i=o.open;typeof i=="function"&&(o.open=function(...l){let r=i.apply(this,l);return n(this?.engine),r}),o.__buoyRealTimers=true}var N="[ExternalSync]";function Se({socket:e,deviceId:o,getTools:n,watched:i,throttleMs:l=200,enableLogs:r=false}){let c=false,a=false,y=0,m=()=>!c&&a&&e.connected&&P.hasAccountAccess(),b=new Map,k={},h={},S=t=>t==="All"||t===o,f=(t,s)=>{if(m())try{e.emit(t,s)}catch(g){p(`${N} Failed to emit "${t}": ${g}. Payload must be JSON-serializable.`,r,"error")}},R=new Set,_=t=>{if(!m())return;let s=n()[t];if(!s)return;k[t]=U();let g;try{g=s.getSnapshot()}catch{return}let{over:I,approxBytes:B}=se(g,2097152);if(I){R.has(t)||(R.add(t),console.warn(`${N} "${t}" snapshot \u2248${(B/1e6).toFixed(1)}MB exceeds the ${2097152/1e6}MB sync budget \u2014 dropped (dashboard will be stale for this tool). The adapter should ship a wire-form snapshot (summaries + on-demand detail).`));return}let V={toolId:t,persistentDeviceId:o,timestamp:k[t],version:s.version,kind:"snapshot",payload:g};f("devtool-sync",V)},D=t=>{if(h[t])return;let s=U()-(k[t]??0);if(s>=l){_(t);return}h[t]=setTimeout(()=>{delete h[t],_(t)},l-s)},O=t=>{e.connected&&b.has(t)&&(h[t]&&(clearTimeout(h[t]),delete h[t]),_(t))};re(O);let w=new Map,L=(t,s)=>{if(!m())return;let g=n()[t];if(g){if(b.has(t)){if(w.get(t)===s)return;let I=b.get(t);b.set(t,g.subscribe(s==="stream"?()=>D(t):()=>{})),w.set(t,s),I?.(),p(`${N} "${t}" watch mode \u2192 ${s}`,r);return}b.set(t,g.subscribe(s==="stream"?()=>D(t):()=>{})),w.set(t,s),p(`${N} Watching "${t}" (${s})`,r)}},E=t=>{b.get(t)?.(),b.delete(t),w.delete(t),h[t]&&(clearTimeout(h[t]),delete h[t]),p(`${N} Stopped watching "${t}"`,r)},F=()=>{let t={persistentDeviceId:o,protocolVersion:1,tools:Object.entries(n()).map(([s,g])=>({toolId:s,version:g.version,actions:Object.keys(g.actions??{})}))};f("devtool-capabilities",t)},d=t=>{if(!(!m()||!S(t.targetDeviceId)))if(t.watching){let s=t.consolidated===true&&t.stream===false?"capture":"stream";i.set(t.toolId,s),L(t.toolId,s),s==="stream"&&_(t.toolId)}else i.delete(t.toolId),E(t.toolId)},u=t=>{!m()||!S(t.targetDeviceId)||_(t.toolId)},X=async t=>{if(!m()||!S(t.targetDeviceId))return;let s=y,{requestId:g,toolId:I,action:B,params:V}=t,v={requestId:g,toolId:I,action:B,persistentDeviceId:o,timestamp:U(),ok:false},ee=n()[I],te=ee?.actions?.[B];if(!te){v.error=ee?`Unknown action "${B}" on tool "${I}"`:`Unknown tool "${I}"`,f("devtool-action-result",v);return}try{v.result=await te(V),v.ok=true}catch(x){v.error=x instanceof Error?x.message:String(x)}if(!(s!==y||!m())){if(v.ok){let{over:x,approxBytes:me}=se(v.result,8388608);x&&(v.ok=false,v.result=void 0,v.error=`Result \u2248${(me/1e6).toFixed(1)}MB exceeds the ${8388608/1e6}MB sync budget. Narrow the request (e.g. includeValues:false, a limit, or a more specific action).`)}v.timestamp=U(),f("devtool-action-result",v)}},A=()=>{y+=1;for(let s of[...b.keys()])E(s);i.clear();for(let s of Object.values(h))clearTimeout(s);let t=e;t.sendBuffer&&(t.sendBuffer=t.sendBuffer.filter(s=>!["devtool-sync","devtool-capabilities","devtool-action-result","device-license"].includes(String(s.data?.[0]))))},G=()=>{let t=P.getState();e.emit("device-license",{tier:t.tier,isPro:t.isPro?"1":"0"}),F()},Q=t=>{a=t?.protocol===1&&t.ready===true,m()?G():A()},ge=P.subscribe(()=>{P.hasAccountAccess()?m()&&G():(e.connected&&e.emit("device-license",{tier:"locked",isPro:"0"}),A())}),Y=()=>{a=false,e.emit("buoy:access:request")},Z=()=>{a=false,A()};e.on("buoy:access",Q);for(let[t,s]of i)n()[t]&&L(t,s);return e.on("connect",Y),e.on("disconnect",Z),e.on("devtool-watch",d),e.on("request-devtool-state",u),e.on("devtool-action",X),e.connected&&Y(),()=>{c=true,ge(),e.off("buoy:access",Q),A(),ce(O),e.off("connect",Y),e.off("disconnect",Z),e.off("devtool-watch",d),e.off("request-devtool-state",u),e.off("devtool-action",X);for(let t of[...b.keys()])E(t)}}function Te({tools:e,socket:o,deviceId:n,enabled:i=true,throttleMs:l=200,enableLogs:r=false}){let c=he().status==="admitted",a=oe(e);a.current=e;let y=oe(new Map),m=Object.keys(e).sort().join(",");ve(()=>{if(!o||!n||!i||!c){y.current.clear();return}return Se({socket:o,deviceId:n,getTools:()=>a.current,watched:y.current,throttleMs:l,enableLogs:r})},[o,n,i,c,l,r,m])}function we(e,o){let n=()=>o(false),i=()=>{n(),e.emit("buoy:access:request")},l=r=>{let c=r;o(c?.protocol===1&&c?.ready===true)};return e.on("connect",i),e.on("disconnect",n),e.on("buoy:access",l),n(),e.connected&&i(),()=>{e.off("connect",i),e.off("disconnect",n),e.off("buoy:access",l)}}import{useEffect as J,useRef as ue,useState as W}from"react";import{io as Ee}from"socket.io-client";function Re(e,o){return e}var De=42831;function Oe(e){return`http://${e??"localhost"}:42831`}function Be(){return null}function fe(){return Oe(typeof location>"u"?null:location.hostname)}var z={targetURL:null,state:"idle",lastError:null,since:0},H=new Set;function T(e){z={...z,...e,since:U()},H.forEach(o=>o())}function xe(){return z}function Ue(e){return H.add(e),()=>{H.delete(e)}}var Ne=typeof ne<"u"?ne:false,$=null,q="",de="",pe="",C=0,M=null,Me=2e3,ye=()=>`${Date.now().toString(36)}-${Math.random().toString(36).slice(2,10)}`;function Le(){let e=globalThis;return e.__buoyInstanceId||(e.__buoyInstanceId=ye()),e.__buoyInstanceId}function Ae(e){let o=n=>n&&Object.fromEntries(Object.entries(n).filter(([i])=>!["BUOY_LICENSE_KEY","BUOY_KEY","EXPO_PUBLIC_BUOY_KEY","VITE_BUOY_KEY","REACT_APP_BUOY_KEY","licenseKey"].includes(i)));return{deviceName:e.deviceName,deviceId:e.persistentDeviceId,platform:e.platform,extraDeviceInfo:JSON.stringify(o(e.extraDeviceInfo)),envVariables:JSON.stringify(o(e.envVariables)),connectionNonce:ye(),instanceId:Le()}}function Pe({deviceName:e,socketURL:o,persistentDeviceId:n,extraDeviceInfo:i,envVariables:l,platform:r,enableLogs:c=false}){let a=ue(null),[y,m]=W(null),[b,k]=W(false),h=o??fe(),S=ue(false),f=`[${e}]`,R=()=>{p(`${f} Socket connected successfully`,c),S.current=false,k(true),T({state:"connected",lastError:null})},_=d=>{p(`${f} Socket disconnected. Reason: ${d}`,c),k(false),T({state:"retrying"})},D=d=>{if(T({state:"retrying",lastError:d.message}),!Ne||S.current)return;S.current=true;let u=r==="android"&&/localhost|127\.0\.0\.1/.test(q)?"If this device is connected over USB, run: adb reverse tcp:42831 tcp:42831. ":"If it's running on another machine or port, pass socketURL via the externalSync prop. ";p(`[buoy] desktop sync: can't reach ${q} (is Buoy Desktop running?). Retrying in the background. ${u}(${d.message})`,c,"warn")},O=()=>{p(`${f} Socket connection timeout`,c,"error")};J(()=>{if(!n)return;let d=Re(h,r);T({targetURL:d,state:"connecting",lastError:null}),p(`${f} Platform: ${r}, using URL: ${d}`,c);try{$&&(q!==d||de!==n||pe!==r)&&($.disconnect(),$=null),$?p(`${f} Reusing existing socket instance to ${d}`,c):(p(`${f} Creating new socket instance to ${d}`,c),$=Ee(d,{autoConnect:true,query:Ae({deviceName:e,persistentDeviceId:n,platform:r,extraDeviceInfo:i,envVariables:l}),reconnection:true,reconnectionAttempts:1/0,reconnectionDelay:1e3,reconnectionDelayMax:5e3,transports:["websocket"]}),ke($),q=d,de=n,pe=r),a.current=$;let u=a.current;return C++,M&&(le(M),M=null),m(u),u.on("connect_error",D),u.on("connect_timeout",O),k(u.connected),u.connected&&p(`${f} Socket already connected on init`,c),u.on("connect",R),u.on("disconnect",_),()=>{p(`${f} Cleaning up socket event listeners`,c),u.off("connect",R),u.off("disconnect",_),u.off("connect_error",D),u.off("connect_timeout",O),C--,C===0&&(M=ae(()=>{M=null,!(C>0||$!==u)&&(p(`${f} No longer used; disconnecting`,c),u.disconnect(),$=null,T({state:"idle",lastError:null}))},Me))}}catch(u){p(`${f} Failed to initialize socket: ${u}`,c,"error")}},[n,h,r]),J(()=>{a.current&&a.current.io.opts.query&&n&&(p(`${f} Updating device name in socket connection`,c),a.current.io.opts.query={...a.current.io.opts.query,deviceName:e,deviceId:n,platform:r})},[e,f,n,r,c]);function w(){a.current&&!a.current.connected&&(p(`${f} Manually connecting to socket server`,c),a.current.connect())}function L(){a.current&&a.current.connected&&(p(`${f} Manually disconnecting from socket server`,c),a.current.disconnect())}let[E,F]=W(null);return J(()=>{if(y)return we(y,d=>{F(d?y:null),T(d?{state:"connected",lastError:null}:{state:"retrying",lastError:"Update Buoy Desktop and sign in to enable desktop sync."})})},[y]),{socket:E===y?y:null,connect:w,disconnect:L,isConnected:b&&E===y&&y!==null}}export{De as DEFAULT_BROKER_PORT,$e as SYNC_PROTOCOL_VERSION,be as flushToolSyncNow,fe as getDefaultSocketURL,Be as getMetroHost,xe as getSyncStatus,re as registerToolFlusher,T as setSyncStatus,Ue as subscribeSyncStatus,ce as unregisterToolFlusher,Te as useExternalSync,Pe as useExternalSyncSocket};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@buoy-gg/external-sync",
|
|
3
|
-
"version": "7.0.
|
|
3
|
+
"version": "7.0.43",
|
|
4
4
|
"description": "Generic device-to-desktop sync for Buoy dev tools",
|
|
5
5
|
"main": "lib/commonjs/index.js",
|
|
6
6
|
"module": "lib/module/index.js",
|
|
@@ -35,13 +35,10 @@
|
|
|
35
35
|
"sideEffects": false,
|
|
36
36
|
"dependencies": {
|
|
37
37
|
"socket.io-client": "^4.8.1",
|
|
38
|
-
"@buoy-gg/license": "^7.0.
|
|
38
|
+
"@buoy-gg/license": "^7.0.43"
|
|
39
39
|
},
|
|
40
40
|
"peerDependencies": {
|
|
41
|
-
"react": "*"
|
|
42
|
-
"react-native": "*",
|
|
43
|
-
"react-native-web": "^0.21.0",
|
|
44
|
-
"react-dom": ">=18"
|
|
41
|
+
"react": "*"
|
|
45
42
|
},
|
|
46
43
|
"devDependencies": {
|
|
47
44
|
"@types/react": "^19.1.0",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"attachDeviceSync.d.ts","sourceRoot":"","sources":["../../src/attachDeviceSync.ts"],"names":[],"mappings":"AAQA,OAAO,EAQL,KAAK,eAAe,EACrB,MAAM,SAAS,CAAC;AAIjB,2DAA2D;AAC3D,MAAM,MAAM,UAAU,GAAG;IACvB,SAAS,EAAE,OAAO,CAAC;IACnB,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC;IACrD,EAAE,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,KAAK,OAAO,CAAC;IACnE,GAAG,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,KAAK,OAAO,CAAC;CACrE,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,SAAS,GAAG,SAAS,GAAG,QAAQ,CAAC;AAE7C,MAAM,MAAM,uBAAuB,GAAG;IACpC,MAAM,EAAE,UAAU,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IAChD;;;;OAIG;IACH,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IAChC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,EAC/B,MAAM,EACN,QAAQ,EACR,QAAQ,EACR,OAAO,EACP,UAAgB,EAChB,UAAkB,GACnB,EAAE,uBAAuB,GAAG,MAAM,IAAI,CAsStC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"brokerAccess.d.ts","sourceRoot":"","sources":["../../src/brokerAccess.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,OAAO,CAAC;IACnB,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,GAAG,OAAO,CAAC;IAC/D,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,IAAI,GAAG,OAAO,CAAC;IAChE,IAAI,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;CAC9B;AACD,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,GAC/B,MAAM,IAAI,CAoBZ"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"crashFlush.d.ts","sourceRoot":"","sources":["../../src/crashFlush.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAIH,oEAAoE;AACpE,MAAM,MAAM,WAAW,GAAG,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;AAiBnD,gEAAgE;AAChE,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI,CAE5D;AAED,8DAA8D;AAC9D,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,WAAW,GAAG,IAAI,CAE9D;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAYrD"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"emitBudget.d.ts","sourceRoot":"","sources":["../../src/emitBudget.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,mDAAmD;AACnD,eAAO,MAAM,uBAAuB,QAAkB,CAAC;AACvD,gFAAgF;AAChF,eAAO,MAAM,uBAAuB,QAAkB,CAAC;AAEvD,wBAAgB,cAAc,CAC5B,KAAK,EAAE,OAAO,EACd,KAAK,EAAE,MAAM,GACZ;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CA2BxC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAKhE,OAAO,EACL,mBAAmB,EACnB,YAAY,EACZ,mBAAmB,GACpB,MAAM,6BAA6B,CAAC;AAKrC,OAAO,EACL,gBAAgB,EAChB,mBAAmB,EACnB,qBAAqB,GACtB,MAAM,cAAc,CAAC;AACtB,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAKhD,OAAO,EACL,aAAa,EACb,aAAa,EACb,mBAAmB,GACpB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAKpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,SAAS,CAAC;AAKhD,YAAY,EACV,eAAe,EACf,UAAU,EACV,cAAc,EACd,QAAQ,EACR,oBAAoB,EACpB,0BAA0B,EAC1B,yBAAyB,EACzB,kBAAkB,EAClB,oBAAoB,EACpB,0BAA0B,EAC1B,mBAAmB,EACnB,qBAAqB,EACrB,UAAU,GACX,MAAM,SAAS,CAAC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"syncStatusStore.d.ts","sourceRoot":"","sources":["../../src/syncStatusStore.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,MAAM,WAAW,UAAU;IACzB,4EAA4E;IAC5E,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,KAAK,EAAE,MAAM,GAAG,YAAY,GAAG,WAAW,GAAG,UAAU,CAAC;IACxD,oEAAoE;IACpE,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,yCAAyC;IACzC,KAAK,EAAE,MAAM,CAAC;CACf;AAWD,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,CAAC,UAAU,CAAC,GAAG,IAAI,CAG9D;AAED,wBAAgB,aAAa,IAAI,UAAU,CAE1C;AAED,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAKpE"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useExternalSync.d.ts","sourceRoot":"","sources":["../../src/useExternalSync.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAC;AAEpD;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,eAAe,CAAC,EAC9B,KAAK,EACL,MAAM,EACN,QAAQ,EACR,OAAc,EACd,UAAgB,EAChB,UAAkB,GACnB,EAAE,oBAAoB,QA4BtB"}
|