@buoy-gg/external-sync 6.0.1 → 7.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/commonjs/index.js +38 -0
- package/lib/commonjs/syncStatusStore.js +40 -0
- package/lib/commonjs/useExternalSyncSocket.js +32 -4
- package/lib/commonjs/utils/getDefaultSocketURL.js +62 -0
- package/lib/commonjs/utils/platformUtils.js +28 -2
- package/lib/module/index.js +9 -0
- package/lib/module/syncStatusStore.js +34 -0
- package/lib/module/useExternalSyncSocket.js +32 -4
- package/lib/module/utils/getDefaultSocketURL.js +56 -0
- package/lib/module/utils/platformUtils.js +28 -2
- package/lib/typescript/index.d.ts +3 -0
- package/lib/typescript/index.d.ts.map +1 -1
- package/lib/typescript/syncStatusStore.d.ts +20 -0
- package/lib/typescript/syncStatusStore.d.ts.map +1 -0
- package/lib/typescript/types.d.ts +8 -1
- package/lib/typescript/types.d.ts.map +1 -1
- package/lib/typescript/useExternalSyncSocket.d.ts.map +1 -1
- package/lib/typescript/utils/getDefaultSocketURL.d.ts +25 -0
- package/lib/typescript/utils/getDefaultSocketURL.d.ts.map +1 -0
- package/lib/typescript/utils/platformUtils.d.ts +2 -1
- package/lib/typescript/utils/platformUtils.d.ts.map +1 -1
- package/package.json +7 -8
package/lib/commonjs/index.js
CHANGED
|
@@ -3,12 +3,48 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", {
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
|
+
Object.defineProperty(exports, "DEFAULT_BROKER_PORT", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: function () {
|
|
9
|
+
return _getDefaultSocketURL.DEFAULT_BROKER_PORT;
|
|
10
|
+
}
|
|
11
|
+
});
|
|
6
12
|
Object.defineProperty(exports, "SYNC_PROTOCOL_VERSION", {
|
|
7
13
|
enumerable: true,
|
|
8
14
|
get: function () {
|
|
9
15
|
return _types.SYNC_PROTOCOL_VERSION;
|
|
10
16
|
}
|
|
11
17
|
});
|
|
18
|
+
Object.defineProperty(exports, "getDefaultSocketURL", {
|
|
19
|
+
enumerable: true,
|
|
20
|
+
get: function () {
|
|
21
|
+
return _getDefaultSocketURL.getDefaultSocketURL;
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
Object.defineProperty(exports, "getMetroHost", {
|
|
25
|
+
enumerable: true,
|
|
26
|
+
get: function () {
|
|
27
|
+
return _getDefaultSocketURL.getMetroHost;
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
Object.defineProperty(exports, "getSyncStatus", {
|
|
31
|
+
enumerable: true,
|
|
32
|
+
get: function () {
|
|
33
|
+
return _syncStatusStore.getSyncStatus;
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
Object.defineProperty(exports, "setSyncStatus", {
|
|
37
|
+
enumerable: true,
|
|
38
|
+
get: function () {
|
|
39
|
+
return _syncStatusStore.setSyncStatus;
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
Object.defineProperty(exports, "subscribeSyncStatus", {
|
|
43
|
+
enumerable: true,
|
|
44
|
+
get: function () {
|
|
45
|
+
return _syncStatusStore.subscribeSyncStatus;
|
|
46
|
+
}
|
|
47
|
+
});
|
|
12
48
|
Object.defineProperty(exports, "useExternalSync", {
|
|
13
49
|
enumerable: true,
|
|
14
50
|
get: function () {
|
|
@@ -23,4 +59,6 @@ Object.defineProperty(exports, "useExternalSyncSocket", {
|
|
|
23
59
|
});
|
|
24
60
|
var _useExternalSync = require("./useExternalSync");
|
|
25
61
|
var _useExternalSyncSocket = require("./useExternalSyncSocket");
|
|
62
|
+
var _getDefaultSocketURL = require("./utils/getDefaultSocketURL");
|
|
63
|
+
var _syncStatusStore = require("./syncStatusStore");
|
|
26
64
|
var _types = require("./types");
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.getSyncStatus = getSyncStatus;
|
|
7
|
+
exports.setSyncStatus = setSyncStatus;
|
|
8
|
+
exports.subscribeSyncStatus = subscribeSyncStatus;
|
|
9
|
+
/**
|
|
10
|
+
* Module-level desktop-sync status, written by useExternalSyncSocket and
|
|
11
|
+
* read by the floating menu's settings modal (via useSyncExternalStore).
|
|
12
|
+
* Lives here rather than in core because only the socket hook knows the
|
|
13
|
+
* platform-rewritten URL and every connection transition — including for
|
|
14
|
+
* apps that call the hook directly instead of using zero-config sync.
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
let status = {
|
|
18
|
+
targetURL: null,
|
|
19
|
+
state: "idle",
|
|
20
|
+
lastError: null,
|
|
21
|
+
since: 0
|
|
22
|
+
};
|
|
23
|
+
const listeners = new Set();
|
|
24
|
+
function setSyncStatus(patch) {
|
|
25
|
+
status = {
|
|
26
|
+
...status,
|
|
27
|
+
...patch,
|
|
28
|
+
since: Date.now()
|
|
29
|
+
};
|
|
30
|
+
listeners.forEach(listener => listener());
|
|
31
|
+
}
|
|
32
|
+
function getSyncStatus() {
|
|
33
|
+
return status;
|
|
34
|
+
}
|
|
35
|
+
function subscribeSyncStatus(listener) {
|
|
36
|
+
listeners.add(listener);
|
|
37
|
+
return () => {
|
|
38
|
+
listeners.delete(listener);
|
|
39
|
+
};
|
|
40
|
+
}
|
|
@@ -7,7 +7,9 @@ exports.useExternalSyncSocket = useExternalSyncSocket;
|
|
|
7
7
|
var _react = require("react");
|
|
8
8
|
var _socket = require("socket.io-client");
|
|
9
9
|
var _platformUtils = require("./utils/platformUtils");
|
|
10
|
+
var _getDefaultSocketURL = require("./utils/getDefaultSocketURL");
|
|
10
11
|
var _logger = require("./utils/logger");
|
|
12
|
+
var _syncStatusStore = require("./syncStatusStore");
|
|
11
13
|
// True only in development. Guarded so it doesn't throw in environments
|
|
12
14
|
// (web/electron bundles) where __DEV__ may be undefined.
|
|
13
15
|
const isDev = typeof __DEV__ !== "undefined" ? __DEV__ : false;
|
|
@@ -50,6 +52,8 @@ function useExternalSyncSocket({
|
|
|
50
52
|
const [socket, setSocket] = (0, _react.useState)(null);
|
|
51
53
|
const [isConnected, setIsConnected] = (0, _react.useState)(false);
|
|
52
54
|
const initialized = (0, _react.useRef)(false);
|
|
55
|
+
// Derived once per render; stable string, so effect deps stay quiet.
|
|
56
|
+
const resolvedSocketURL = socketURL ?? (0, _getDefaultSocketURL.getDefaultSocketURL)();
|
|
53
57
|
// Tracks whether we've already logged a connection error for the current
|
|
54
58
|
// outage, so the reconnection backoff doesn't spam an error on every retry.
|
|
55
59
|
const hasLoggedConnectError = (0, _react.useRef)(false);
|
|
@@ -58,19 +62,33 @@ function useExternalSyncSocket({
|
|
|
58
62
|
(0, _logger.log)(`${logPrefix} Socket connected successfully`, enableLogs);
|
|
59
63
|
hasLoggedConnectError.current = false;
|
|
60
64
|
setIsConnected(true);
|
|
65
|
+
(0, _syncStatusStore.setSyncStatus)({
|
|
66
|
+
state: "connected",
|
|
67
|
+
lastError: null
|
|
68
|
+
});
|
|
61
69
|
};
|
|
62
70
|
const onDisconnect = reason => {
|
|
63
71
|
(0, _logger.log)(`${logPrefix} Socket disconnected. Reason: ${reason}`, enableLogs);
|
|
64
72
|
setIsConnected(false);
|
|
73
|
+
(0, _syncStatusStore.setSyncStatus)({
|
|
74
|
+
state: "retrying"
|
|
75
|
+
});
|
|
65
76
|
};
|
|
66
77
|
const onConnectError = error => {
|
|
78
|
+
(0, _syncStatusStore.setSyncStatus)({
|
|
79
|
+
state: "retrying",
|
|
80
|
+
lastError: error.message
|
|
81
|
+
});
|
|
67
82
|
// Never surface this in production builds.
|
|
68
83
|
if (!isDev) return;
|
|
69
84
|
// Reconnection retries indefinitely; only log the first failure of an
|
|
70
85
|
// outage to avoid flooding the console until the server comes back up.
|
|
71
86
|
if (hasLoggedConnectError.current) return;
|
|
72
87
|
hasLoggedConnectError.current = true;
|
|
73
|
-
|
|
88
|
+
// A localhost target on an Android device means a USB (adb reverse)
|
|
89
|
+
// setup — name the exact command instead of the generic hint.
|
|
90
|
+
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. `;
|
|
91
|
+
(0, _logger.log)(`[buoy] desktop sync: can't reach ${currentSocketURL} (is Buoy Desktop running?). ` + `Retrying in the background. ${hint}(${error.message})`, enableLogs, "warn");
|
|
74
92
|
};
|
|
75
93
|
const onConnectTimeout = () => {
|
|
76
94
|
(0, _logger.log)(`${logPrefix} Socket connection timeout`, enableLogs, "error");
|
|
@@ -81,8 +99,13 @@ function useExternalSyncSocket({
|
|
|
81
99
|
if (!persistentDeviceId) return;
|
|
82
100
|
if (initialized.current) return;
|
|
83
101
|
initialized.current = true;
|
|
84
|
-
const platformUrl = (0, _platformUtils.getPlatformSpecificURL)(
|
|
102
|
+
const platformUrl = (0, _platformUtils.getPlatformSpecificURL)(resolvedSocketURL, platform);
|
|
85
103
|
currentSocketURL = platformUrl;
|
|
104
|
+
(0, _syncStatusStore.setSyncStatus)({
|
|
105
|
+
targetURL: platformUrl,
|
|
106
|
+
state: "connecting",
|
|
107
|
+
lastError: null
|
|
108
|
+
});
|
|
86
109
|
(0, _logger.log)(`${logPrefix} Platform: ${platform}, using URL: ${platformUrl}`, enableLogs);
|
|
87
110
|
try {
|
|
88
111
|
if (!globalSocketInstance) {
|
|
@@ -145,12 +168,17 @@ function useExternalSyncSocket({
|
|
|
145
168
|
|
|
146
169
|
// Update socket URL when socketURL changes
|
|
147
170
|
(0, _react.useEffect)(() => {
|
|
148
|
-
const platformUrl = (0, _platformUtils.getPlatformSpecificURL)(
|
|
171
|
+
const platformUrl = (0, _platformUtils.getPlatformSpecificURL)(resolvedSocketURL, platform);
|
|
149
172
|
if (socketRef.current && currentSocketURL !== platformUrl && persistentDeviceId) {
|
|
150
173
|
(0, _logger.log)(`${logPrefix} Socket URL changed from ${currentSocketURL} to ${platformUrl}`, enableLogs);
|
|
151
174
|
try {
|
|
152
175
|
socketRef.current.disconnect();
|
|
153
176
|
currentSocketURL = platformUrl;
|
|
177
|
+
(0, _syncStatusStore.setSyncStatus)({
|
|
178
|
+
targetURL: platformUrl,
|
|
179
|
+
state: "connecting",
|
|
180
|
+
lastError: null
|
|
181
|
+
});
|
|
154
182
|
(0, _logger.log)(`${logPrefix} Creating new socket connection to ${platformUrl}`, enableLogs);
|
|
155
183
|
globalSocketInstance = (0, _socket.io)(platformUrl, {
|
|
156
184
|
autoConnect: true,
|
|
@@ -174,7 +202,7 @@ function useExternalSyncSocket({
|
|
|
174
202
|
(0, _logger.log)(`${logPrefix} Failed to update socket connection: ${error}`, enableLogs, "error");
|
|
175
203
|
}
|
|
176
204
|
}
|
|
177
|
-
}, [
|
|
205
|
+
}, [resolvedSocketURL, deviceName, logPrefix, persistentDeviceId, platform, enableLogs]);
|
|
178
206
|
function connect() {
|
|
179
207
|
if (socketRef.current && !socketRef.current.connected) {
|
|
180
208
|
(0, _logger.log)(`${logPrefix} Manually connecting to socket server`, enableLogs);
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.DEFAULT_BROKER_PORT = void 0;
|
|
7
|
+
exports.getDefaultSocketURL = getDefaultSocketURL;
|
|
8
|
+
exports.getMetroHost = getMetroHost;
|
|
9
|
+
/**
|
|
10
|
+
* Default broker-URL derivation. Kept in its own module (and never imported
|
|
11
|
+
* from types.ts) because the deep react-native require below must not reach
|
|
12
|
+
* non-Metro bundles — the desktop app imports this package's types only.
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
/** Port Buoy Desktop's broker listens on. */
|
|
16
|
+
const DEFAULT_BROKER_PORT = exports.DEFAULT_BROKER_PORT = 42831;
|
|
17
|
+
const HOST_RE = /^https?:\/\/([^:/]+)/;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Host of the Metro dev server that served this bundle — the machine most
|
|
21
|
+
* likely running Buoy Desktop. On a physical device this is the computer's
|
|
22
|
+
* LAN IP, where "localhost" would be the phone itself.
|
|
23
|
+
*
|
|
24
|
+
* scriptURL is the only source that works everywhere we've tested:
|
|
25
|
+
* NativeModules.SourceCode.scriptURL is undefined on bridgeless, and
|
|
26
|
+
* expo-constants hostUri/experienceUrl/linkingUri are all undefined in
|
|
27
|
+
* Expo dev-client builds. Returns null on web or if RN internals move.
|
|
28
|
+
*/
|
|
29
|
+
function getMetroHost() {
|
|
30
|
+
try {
|
|
31
|
+
// Requires stay lexically inside try{} so Metro treats them as optional;
|
|
32
|
+
// react-native-web has neither path and falls through to null.
|
|
33
|
+
const NativeSourceCode =
|
|
34
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
35
|
+
require("react-native/Libraries/NativeModules/specs/NativeSourceCode").default;
|
|
36
|
+
const scriptURL = NativeSourceCode?.getConstants?.().scriptURL;
|
|
37
|
+
const match = scriptURL?.match(HOST_RE);
|
|
38
|
+
if (match) return match[1];
|
|
39
|
+
} catch {
|
|
40
|
+
// web / RN internals moved — try the old-architecture module
|
|
41
|
+
}
|
|
42
|
+
try {
|
|
43
|
+
const {
|
|
44
|
+
NativeModules
|
|
45
|
+
} = require("react-native");
|
|
46
|
+
const scriptURL = NativeModules?.SourceCode?.getConstants?.().scriptURL ?? NativeModules?.SourceCode?.scriptURL;
|
|
47
|
+
const match = scriptURL?.match(HOST_RE);
|
|
48
|
+
if (match) return match[1];
|
|
49
|
+
} catch {
|
|
50
|
+
// not React Native
|
|
51
|
+
}
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Default Buoy Desktop broker URL: the Metro host (falling back to
|
|
57
|
+
* localhost) on port 42831. Android-emulator 10.0.2.2 rewriting is applied
|
|
58
|
+
* later by getPlatformSpecificURL, so localhost still works there.
|
|
59
|
+
*/
|
|
60
|
+
function getDefaultSocketURL() {
|
|
61
|
+
return `http://${getMetroHost() ?? "localhost"}:${DEFAULT_BROKER_PORT}`;
|
|
62
|
+
}
|
|
@@ -4,14 +4,40 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.getPlatformSpecificURL = void 0;
|
|
7
|
+
/**
|
|
8
|
+
* True only on an actual Android EMULATOR, detected via the build fingerprint
|
|
9
|
+
* (same heuristic react-native-device-info uses), with no native dependency.
|
|
10
|
+
* Physical devices must NOT get the 10.0.2.2 rewrite: over USB (`adb reverse`)
|
|
11
|
+
* the Metro-derived host is "localhost", and rewriting it to the
|
|
12
|
+
* emulator-only 10.0.2.2 alias breaks the connection — keeping localhost lets
|
|
13
|
+
* `adb reverse tcp:42831 tcp:42831` forward it to the dev machine.
|
|
14
|
+
*
|
|
15
|
+
* The react-native require stays lexically inside try{} (Metro optional-dep
|
|
16
|
+
* rule) and this module is never imported from types.ts, so non-Metro
|
|
17
|
+
* bundles (the desktop app) are unaffected.
|
|
18
|
+
*/
|
|
19
|
+
const isAndroidEmulator = () => {
|
|
20
|
+
try {
|
|
21
|
+
const {
|
|
22
|
+
Platform
|
|
23
|
+
} = require("react-native");
|
|
24
|
+
if (Platform.OS !== "android") return false;
|
|
25
|
+
const fingerprint = Platform.constants?.Fingerprint ?? "";
|
|
26
|
+
return /generic|emulator|goldfish|ranchu|sdk_gphone|vbox/i.test(fingerprint);
|
|
27
|
+
} catch {
|
|
28
|
+
return false;
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
|
|
7
32
|
/**
|
|
8
33
|
* Get platform-specific URL for socket connection.
|
|
9
|
-
* On Android emulator, replaces localhost with 10.0.2.2
|
|
34
|
+
* On the Android emulator (only), replaces localhost with 10.0.2.2 —
|
|
35
|
+
* the emulator's alias for the host machine's loopback.
|
|
10
36
|
*/
|
|
11
37
|
const getPlatformSpecificURL = (baseUrl, platform) => {
|
|
12
38
|
try {
|
|
13
39
|
const url = new URL(baseUrl);
|
|
14
|
-
if (platform === "android" && (url.hostname === "localhost" || url.hostname === "127.0.0.1")) {
|
|
40
|
+
if (platform === "android" && (url.hostname === "localhost" || url.hostname === "127.0.0.1") && isAndroidEmulator()) {
|
|
15
41
|
url.hostname = "10.0.2.2";
|
|
16
42
|
return url.toString();
|
|
17
43
|
}
|
package/lib/module/index.js
CHANGED
|
@@ -6,6 +6,15 @@
|
|
|
6
6
|
export { useExternalSync } from "./useExternalSync";
|
|
7
7
|
export { useExternalSyncSocket } from "./useExternalSyncSocket";
|
|
8
8
|
|
|
9
|
+
// ============================================================
|
|
10
|
+
// BROKER URL DERIVATION
|
|
11
|
+
// ============================================================
|
|
12
|
+
export { getDefaultSocketURL, getMetroHost, DEFAULT_BROKER_PORT } from "./utils/getDefaultSocketURL";
|
|
13
|
+
|
|
14
|
+
// ============================================================
|
|
15
|
+
// SYNC STATUS (read by the floating menu's settings modal)
|
|
16
|
+
// ============================================================
|
|
17
|
+
export { getSyncStatus, setSyncStatus, subscribeSyncStatus } from "./syncStatusStore";
|
|
9
18
|
// ============================================================
|
|
10
19
|
// PROTOCOL
|
|
11
20
|
// ============================================================
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Module-level desktop-sync status, written by useExternalSyncSocket and
|
|
5
|
+
* read by the floating menu's settings modal (via useSyncExternalStore).
|
|
6
|
+
* Lives here rather than in core because only the socket hook knows the
|
|
7
|
+
* platform-rewritten URL and every connection transition — including for
|
|
8
|
+
* apps that call the hook directly instead of using zero-config sync.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
let status = {
|
|
12
|
+
targetURL: null,
|
|
13
|
+
state: "idle",
|
|
14
|
+
lastError: null,
|
|
15
|
+
since: 0
|
|
16
|
+
};
|
|
17
|
+
const listeners = new Set();
|
|
18
|
+
export function setSyncStatus(patch) {
|
|
19
|
+
status = {
|
|
20
|
+
...status,
|
|
21
|
+
...patch,
|
|
22
|
+
since: Date.now()
|
|
23
|
+
};
|
|
24
|
+
listeners.forEach(listener => listener());
|
|
25
|
+
}
|
|
26
|
+
export function getSyncStatus() {
|
|
27
|
+
return status;
|
|
28
|
+
}
|
|
29
|
+
export function subscribeSyncStatus(listener) {
|
|
30
|
+
listeners.add(listener);
|
|
31
|
+
return () => {
|
|
32
|
+
listeners.delete(listener);
|
|
33
|
+
};
|
|
34
|
+
}
|
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
import { useEffect, useRef, useState } from "react";
|
|
4
4
|
import { io as socketIO } from "socket.io-client";
|
|
5
5
|
import { getPlatformSpecificURL } from "./utils/platformUtils";
|
|
6
|
+
import { getDefaultSocketURL } from "./utils/getDefaultSocketURL";
|
|
6
7
|
import { log } from "./utils/logger";
|
|
8
|
+
import { setSyncStatus } from "./syncStatusStore";
|
|
7
9
|
// True only in development. Guarded so it doesn't throw in environments
|
|
8
10
|
// (web/electron bundles) where __DEV__ may be undefined.
|
|
9
11
|
const isDev = typeof __DEV__ !== "undefined" ? __DEV__ : false;
|
|
@@ -46,6 +48,8 @@ export function useExternalSyncSocket({
|
|
|
46
48
|
const [socket, setSocket] = useState(null);
|
|
47
49
|
const [isConnected, setIsConnected] = useState(false);
|
|
48
50
|
const initialized = useRef(false);
|
|
51
|
+
// Derived once per render; stable string, so effect deps stay quiet.
|
|
52
|
+
const resolvedSocketURL = socketURL ?? getDefaultSocketURL();
|
|
49
53
|
// Tracks whether we've already logged a connection error for the current
|
|
50
54
|
// outage, so the reconnection backoff doesn't spam an error on every retry.
|
|
51
55
|
const hasLoggedConnectError = useRef(false);
|
|
@@ -54,19 +58,33 @@ export function useExternalSyncSocket({
|
|
|
54
58
|
log(`${logPrefix} Socket connected successfully`, enableLogs);
|
|
55
59
|
hasLoggedConnectError.current = false;
|
|
56
60
|
setIsConnected(true);
|
|
61
|
+
setSyncStatus({
|
|
62
|
+
state: "connected",
|
|
63
|
+
lastError: null
|
|
64
|
+
});
|
|
57
65
|
};
|
|
58
66
|
const onDisconnect = reason => {
|
|
59
67
|
log(`${logPrefix} Socket disconnected. Reason: ${reason}`, enableLogs);
|
|
60
68
|
setIsConnected(false);
|
|
69
|
+
setSyncStatus({
|
|
70
|
+
state: "retrying"
|
|
71
|
+
});
|
|
61
72
|
};
|
|
62
73
|
const onConnectError = error => {
|
|
74
|
+
setSyncStatus({
|
|
75
|
+
state: "retrying",
|
|
76
|
+
lastError: error.message
|
|
77
|
+
});
|
|
63
78
|
// Never surface this in production builds.
|
|
64
79
|
if (!isDev) return;
|
|
65
80
|
// Reconnection retries indefinitely; only log the first failure of an
|
|
66
81
|
// outage to avoid flooding the console until the server comes back up.
|
|
67
82
|
if (hasLoggedConnectError.current) return;
|
|
68
83
|
hasLoggedConnectError.current = true;
|
|
69
|
-
|
|
84
|
+
// A localhost target on an Android device means a USB (adb reverse)
|
|
85
|
+
// setup — name the exact command instead of the generic hint.
|
|
86
|
+
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. `;
|
|
87
|
+
log(`[buoy] desktop sync: can't reach ${currentSocketURL} (is Buoy Desktop running?). ` + `Retrying in the background. ${hint}(${error.message})`, enableLogs, "warn");
|
|
70
88
|
};
|
|
71
89
|
const onConnectTimeout = () => {
|
|
72
90
|
log(`${logPrefix} Socket connection timeout`, enableLogs, "error");
|
|
@@ -77,8 +95,13 @@ export function useExternalSyncSocket({
|
|
|
77
95
|
if (!persistentDeviceId) return;
|
|
78
96
|
if (initialized.current) return;
|
|
79
97
|
initialized.current = true;
|
|
80
|
-
const platformUrl = getPlatformSpecificURL(
|
|
98
|
+
const platformUrl = getPlatformSpecificURL(resolvedSocketURL, platform);
|
|
81
99
|
currentSocketURL = platformUrl;
|
|
100
|
+
setSyncStatus({
|
|
101
|
+
targetURL: platformUrl,
|
|
102
|
+
state: "connecting",
|
|
103
|
+
lastError: null
|
|
104
|
+
});
|
|
82
105
|
log(`${logPrefix} Platform: ${platform}, using URL: ${platformUrl}`, enableLogs);
|
|
83
106
|
try {
|
|
84
107
|
if (!globalSocketInstance) {
|
|
@@ -141,12 +164,17 @@ export function useExternalSyncSocket({
|
|
|
141
164
|
|
|
142
165
|
// Update socket URL when socketURL changes
|
|
143
166
|
useEffect(() => {
|
|
144
|
-
const platformUrl = getPlatformSpecificURL(
|
|
167
|
+
const platformUrl = getPlatformSpecificURL(resolvedSocketURL, platform);
|
|
145
168
|
if (socketRef.current && currentSocketURL !== platformUrl && persistentDeviceId) {
|
|
146
169
|
log(`${logPrefix} Socket URL changed from ${currentSocketURL} to ${platformUrl}`, enableLogs);
|
|
147
170
|
try {
|
|
148
171
|
socketRef.current.disconnect();
|
|
149
172
|
currentSocketURL = platformUrl;
|
|
173
|
+
setSyncStatus({
|
|
174
|
+
targetURL: platformUrl,
|
|
175
|
+
state: "connecting",
|
|
176
|
+
lastError: null
|
|
177
|
+
});
|
|
150
178
|
log(`${logPrefix} Creating new socket connection to ${platformUrl}`, enableLogs);
|
|
151
179
|
globalSocketInstance = socketIO(platformUrl, {
|
|
152
180
|
autoConnect: true,
|
|
@@ -170,7 +198,7 @@ export function useExternalSyncSocket({
|
|
|
170
198
|
log(`${logPrefix} Failed to update socket connection: ${error}`, enableLogs, "error");
|
|
171
199
|
}
|
|
172
200
|
}
|
|
173
|
-
}, [
|
|
201
|
+
}, [resolvedSocketURL, deviceName, logPrefix, persistentDeviceId, platform, enableLogs]);
|
|
174
202
|
function connect() {
|
|
175
203
|
if (socketRef.current && !socketRef.current.connected) {
|
|
176
204
|
log(`${logPrefix} Manually connecting to socket server`, enableLogs);
|
|
@@ -0,0 +1,56 @@
|
|
|
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 of the Metro dev server that served this bundle — the machine most
|
|
15
|
+
* likely running Buoy Desktop. On a physical device this is the computer's
|
|
16
|
+
* LAN IP, where "localhost" would be the phone itself.
|
|
17
|
+
*
|
|
18
|
+
* scriptURL is the only source that works everywhere we've tested:
|
|
19
|
+
* NativeModules.SourceCode.scriptURL is undefined on bridgeless, and
|
|
20
|
+
* expo-constants hostUri/experienceUrl/linkingUri are all undefined in
|
|
21
|
+
* Expo dev-client builds. Returns null on web or if RN internals move.
|
|
22
|
+
*/
|
|
23
|
+
export function getMetroHost() {
|
|
24
|
+
try {
|
|
25
|
+
// Requires stay lexically inside try{} so Metro treats them as optional;
|
|
26
|
+
// react-native-web has neither path and falls through to null.
|
|
27
|
+
const NativeSourceCode =
|
|
28
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
29
|
+
require("react-native/Libraries/NativeModules/specs/NativeSourceCode").default;
|
|
30
|
+
const scriptURL = NativeSourceCode?.getConstants?.().scriptURL;
|
|
31
|
+
const match = scriptURL?.match(HOST_RE);
|
|
32
|
+
if (match) return match[1];
|
|
33
|
+
} catch {
|
|
34
|
+
// web / RN internals moved — try the old-architecture module
|
|
35
|
+
}
|
|
36
|
+
try {
|
|
37
|
+
const {
|
|
38
|
+
NativeModules
|
|
39
|
+
} = require("react-native");
|
|
40
|
+
const scriptURL = NativeModules?.SourceCode?.getConstants?.().scriptURL ?? NativeModules?.SourceCode?.scriptURL;
|
|
41
|
+
const match = scriptURL?.match(HOST_RE);
|
|
42
|
+
if (match) return match[1];
|
|
43
|
+
} catch {
|
|
44
|
+
// not React Native
|
|
45
|
+
}
|
|
46
|
+
return null;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Default Buoy Desktop broker URL: the Metro host (falling back to
|
|
51
|
+
* localhost) on port 42831. Android-emulator 10.0.2.2 rewriting is applied
|
|
52
|
+
* later by getPlatformSpecificURL, so localhost still works there.
|
|
53
|
+
*/
|
|
54
|
+
export function getDefaultSocketURL() {
|
|
55
|
+
return `http://${getMetroHost() ?? "localhost"}:${DEFAULT_BROKER_PORT}`;
|
|
56
|
+
}
|
|
@@ -1,13 +1,39 @@
|
|
|
1
1
|
"use strict";
|
|
2
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
|
+
|
|
3
28
|
/**
|
|
4
29
|
* Get platform-specific URL for socket connection.
|
|
5
|
-
* On Android emulator, replaces localhost with 10.0.2.2
|
|
30
|
+
* On the Android emulator (only), replaces localhost with 10.0.2.2 —
|
|
31
|
+
* the emulator's alias for the host machine's loopback.
|
|
6
32
|
*/
|
|
7
33
|
export const getPlatformSpecificURL = (baseUrl, platform) => {
|
|
8
34
|
try {
|
|
9
35
|
const url = new URL(baseUrl);
|
|
10
|
-
if (platform === "android" && (url.hostname === "localhost" || url.hostname === "127.0.0.1")) {
|
|
36
|
+
if (platform === "android" && (url.hostname === "localhost" || url.hostname === "127.0.0.1") && isAndroidEmulator()) {
|
|
11
37
|
url.hostname = "10.0.2.2";
|
|
12
38
|
return url.toString();
|
|
13
39
|
}
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
export { useExternalSync } from "./useExternalSync";
|
|
2
2
|
export { useExternalSyncSocket } from "./useExternalSyncSocket";
|
|
3
|
+
export { getDefaultSocketURL, getMetroHost, DEFAULT_BROKER_PORT, } from "./utils/getDefaultSocketURL";
|
|
4
|
+
export { getSyncStatus, setSyncStatus, subscribeSyncStatus, } from "./syncStatusStore";
|
|
5
|
+
export type { SyncStatus } from "./syncStatusStore";
|
|
3
6
|
export { SYNC_PROTOCOL_VERSION } from "./types";
|
|
4
7
|
export type { ToolSyncAdapter, ToolAction, ToolCapability, SyncKind, UseExternalSyncProps, UseExternalSyncSocketProps, DeviceCapabilitiesMessage, DevToolSyncMessage, DevToolActionMessage, DevToolActionResultMessage, DevToolWatchMessage, DevToolRequestMessage, PlatformOS, } from "./types";
|
|
5
8
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
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,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
|
+
{"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,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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
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
|
+
export interface SyncStatus {
|
|
9
|
+
/** Final (platform-rewritten) broker URL being dialed; null before init. */
|
|
10
|
+
targetURL: string | null;
|
|
11
|
+
state: "idle" | "connecting" | "connected" | "retrying";
|
|
12
|
+
/** Message of the most recent connect error; cleared on connect. */
|
|
13
|
+
lastError: string | null;
|
|
14
|
+
/** Epoch ms of the last state change. */
|
|
15
|
+
since: number;
|
|
16
|
+
}
|
|
17
|
+
export declare function setSyncStatus(patch: Partial<SyncStatus>): void;
|
|
18
|
+
export declare function getSyncStatus(): SyncStatus;
|
|
19
|
+
export declare function subscribeSyncStatus(listener: () => void): () => void;
|
|
20
|
+
//# sourceMappingURL=syncStatusStore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|
|
@@ -103,7 +103,14 @@ export interface UseExternalSyncProps {
|
|
|
103
103
|
export type PlatformOS = "ios" | "android" | "web" | "windows" | "macos" | "native" | "tv" | "tvos" | "visionos" | "maccatalyst";
|
|
104
104
|
export interface UseExternalSyncSocketProps {
|
|
105
105
|
deviceName: string;
|
|
106
|
-
|
|
106
|
+
/**
|
|
107
|
+
* Broker URL to dial. @default derived from Metro's scriptURL host
|
|
108
|
+
* (the machine that served the bundle — Buoy Desktop's machine) on port
|
|
109
|
+
* 42831, so physical devices work zero-config (Android over USB: run
|
|
110
|
+
* `adb reverse tcp:42831 tcp:42831`). Pass explicitly for tunnels or a
|
|
111
|
+
* broker on another machine.
|
|
112
|
+
*/
|
|
113
|
+
socketURL?: string;
|
|
107
114
|
persistentDeviceId: string | null;
|
|
108
115
|
extraDeviceInfo?: Record<string, string>;
|
|
109
116
|
envVariables?: Record<string, string>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AA0B/C,yEAAyE;AACzE,eAAO,MAAM,qBAAqB,IAAI,CAAC;AAEvC,+EAA+E;AAC/E,MAAM,MAAM,QAAQ,GAAG,UAAU,CAAC;AAMlC,mFAAmF;AACnF,MAAM,MAAM,UAAU,GAAG,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;AAEzE;;;;;;GAMG;AACH,MAAM,WAAW,eAAe;IAC9B,sEAAsE;IACtE,OAAO,EAAE,MAAM,CAAC;IAChB,oFAAoF;IACpF,WAAW,EAAE,MAAM,OAAO,CAAC;IAC3B;;;;OAIG;IACH,SAAS,EAAE,CAAC,QAAQ,EAAE,MAAM,IAAI,KAAK,MAAM,IAAI,CAAC;IAChD,sDAAsD;IACtD,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;CACtC;AAMD,4EAA4E;AAC5E,MAAM,WAAW,yBAAyB;IACxC,kBAAkB,EAAE,MAAM,CAAC;IAC3B,eAAe,EAAE,MAAM,CAAC;IACxB,KAAK,EAAE,cAAc,EAAE,CAAC;CACzB;AAED,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED,+CAA+C;AAC/C,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,kBAAkB,EAAE,MAAM,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,sDAAsD;IACtD,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,QAAQ,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,8CAA8C;AAC9C,MAAM,WAAW,0BAA0B;IACzC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,kBAAkB,EAAE,MAAM,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,EAAE,EAAE,OAAO,CAAC;IACZ,uEAAuE;IACvE,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,2BAA2B;IAC3B,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAMD,uEAAuE;AACvE,MAAM,WAAW,mBAAmB;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,gFAAgF;AAChF,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,iDAAiD;AACjD,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAMD,MAAM,WAAW,oBAAoB;IACnC,yEAAyE;IACzE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IACvC,8DAA8D;IAC9D,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,oCAAoC;IACpC,QAAQ,EAAE,MAAM,CAAC;IACjB,yCAAyC;IACzC,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,qBAAqB;IACrB,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAMD;;GAEG;AACH,MAAM,MAAM,UAAU,GAClB,KAAK,GACL,SAAS,GACT,KAAK,GACL,SAAS,GACT,OAAO,GACP,QAAQ,GACR,IAAI,GACJ,MAAM,GACN,UAAU,GACV,aAAa,CAAC;AAMlB,MAAM,WAAW,0BAA0B;IACzC,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useExternalSyncSocket.d.ts","sourceRoot":"","sources":["../../src/useExternalSyncSocket.ts"],"names":[],"mappings":"AACA,OAAO,EAAkB,MAAM,EAAE,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"useExternalSyncSocket.d.ts","sourceRoot":"","sources":["../../src/useExternalSyncSocket.ts"],"names":[],"mappings":"AACA,OAAO,EAAkB,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAM1D,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,SAAS,CAAC;AA0B1D;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,EACpC,UAAU,EACV,SAAS,EACT,kBAAkB,EAClB,eAAe,EACf,YAAY,EACZ,QAAQ,EACR,UAAkB,GACnB,EAAE,0BAA0B;;;;;EA4O5B"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default broker-URL derivation. Kept in its own module (and never imported
|
|
3
|
+
* from types.ts) because the deep react-native require below must not reach
|
|
4
|
+
* non-Metro bundles — the desktop app imports this package's types only.
|
|
5
|
+
*/
|
|
6
|
+
/** Port Buoy Desktop's broker listens on. */
|
|
7
|
+
export declare const DEFAULT_BROKER_PORT = 42831;
|
|
8
|
+
/**
|
|
9
|
+
* Host of the Metro dev server that served this bundle — the machine most
|
|
10
|
+
* likely running Buoy Desktop. On a physical device this is the computer's
|
|
11
|
+
* LAN IP, where "localhost" would be the phone itself.
|
|
12
|
+
*
|
|
13
|
+
* scriptURL is the only source that works everywhere we've tested:
|
|
14
|
+
* NativeModules.SourceCode.scriptURL is undefined on bridgeless, and
|
|
15
|
+
* expo-constants hostUri/experienceUrl/linkingUri are all undefined in
|
|
16
|
+
* Expo dev-client builds. Returns null on web or if RN internals move.
|
|
17
|
+
*/
|
|
18
|
+
export declare function getMetroHost(): string | null;
|
|
19
|
+
/**
|
|
20
|
+
* Default Buoy Desktop broker URL: the Metro host (falling back to
|
|
21
|
+
* localhost) on port 42831. Android-emulator 10.0.2.2 rewriting is applied
|
|
22
|
+
* later by getPlatformSpecificURL, so localhost still works there.
|
|
23
|
+
*/
|
|
24
|
+
export declare function getDefaultSocketURL(): string;
|
|
25
|
+
//# sourceMappingURL=getDefaultSocketURL.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getDefaultSocketURL.d.ts","sourceRoot":"","sources":["../../../src/utils/getDefaultSocketURL.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,6CAA6C;AAC7C,eAAO,MAAM,mBAAmB,QAAQ,CAAC;AAIzC;;;;;;;;;GASG;AACH,wBAAgB,YAAY,IAAI,MAAM,GAAG,IAAI,CAyB5C;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAE5C"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { PlatformOS } from "../types";
|
|
2
2
|
/**
|
|
3
3
|
* Get platform-specific URL for socket connection.
|
|
4
|
-
* On Android emulator, replaces localhost with 10.0.2.2
|
|
4
|
+
* On the Android emulator (only), replaces localhost with 10.0.2.2 —
|
|
5
|
+
* the emulator's alias for the host machine's loopback.
|
|
5
6
|
*/
|
|
6
7
|
export declare const getPlatformSpecificURL: (baseUrl: string, platform: PlatformOS) => string;
|
|
7
8
|
//# sourceMappingURL=platformUtils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"platformUtils.d.ts","sourceRoot":"","sources":["../../../src/utils/platformUtils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"platformUtils.d.ts","sourceRoot":"","sources":["../../../src/utils/platformUtils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AA4B3C;;;;GAIG;AACH,eAAO,MAAM,sBAAsB,GACjC,SAAS,MAAM,EACf,UAAU,UAAU,KACnB,MAkBF,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@buoy-gg/external-sync",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "7.0.1",
|
|
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",
|
|
@@ -25,16 +25,16 @@
|
|
|
25
25
|
"lib"
|
|
26
26
|
],
|
|
27
27
|
"sideEffects": false,
|
|
28
|
-
"dependencies": {
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"socket.io-client": "^4.8.1"
|
|
30
|
+
},
|
|
29
31
|
"peerDependencies": {
|
|
30
32
|
"react": "*",
|
|
31
|
-
"react-native": "*"
|
|
32
|
-
"socket.io-client": ">=4.0.0"
|
|
33
|
+
"react-native": "*"
|
|
33
34
|
},
|
|
34
35
|
"devDependencies": {
|
|
35
36
|
"@types/react": "^19.1.0",
|
|
36
37
|
"@types/react-native": "^0.73.0",
|
|
37
|
-
"socket.io-client": "^4.8.1",
|
|
38
38
|
"typescript": "~5.8.3"
|
|
39
39
|
},
|
|
40
40
|
"react-native-builder-bob": {
|
|
@@ -58,13 +58,12 @@
|
|
|
58
58
|
},
|
|
59
59
|
"repository": {
|
|
60
60
|
"type": "git",
|
|
61
|
-
"url": "https://github.com/
|
|
62
|
-
"directory": "packages/external-sync"
|
|
61
|
+
"url": "https://github.com/Buoy-gg/buoy.git"
|
|
63
62
|
},
|
|
64
63
|
"bugs": {
|
|
65
64
|
"url": "https://github.com/LovesWorking/react-native-buoy/issues"
|
|
66
65
|
},
|
|
67
|
-
"homepage": "https://
|
|
66
|
+
"homepage": "https://buoy.gg",
|
|
68
67
|
"publishConfig": {
|
|
69
68
|
"access": "public",
|
|
70
69
|
"tag": "latest"
|