@buoy-gg/external-sync 3.0.0 → 3.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -8,6 +8,10 @@ var _react = require("react");
|
|
|
8
8
|
var _socket = require("socket.io-client");
|
|
9
9
|
var _platformUtils = require("./utils/platformUtils");
|
|
10
10
|
var _logger = require("./utils/logger");
|
|
11
|
+
// True only in development. Guarded so it doesn't throw in environments
|
|
12
|
+
// (web/electron bundles) where __DEV__ may be undefined.
|
|
13
|
+
const isDev = typeof __DEV__ !== "undefined" ? __DEV__ : false;
|
|
14
|
+
|
|
11
15
|
/**
|
|
12
16
|
* Singleton socket instance that persists across component renders.
|
|
13
17
|
* Multiple components share the same socket connection.
|
|
@@ -15,6 +19,16 @@ var _logger = require("./utils/logger");
|
|
|
15
19
|
let globalSocketInstance = null;
|
|
16
20
|
let currentSocketURL = "";
|
|
17
21
|
|
|
22
|
+
/**
|
|
23
|
+
* Identifies a single socket INSTANCE. Sent in the handshake query and reused
|
|
24
|
+
* for the life of the instance, so it survives socket.io reconnects but
|
|
25
|
+
* changes whenever we create a brand-new socket (remount / Fast Refresh /
|
|
26
|
+
* URL change). The dashboard uses this to tell a flapping connection that's
|
|
27
|
+
* merely reconnecting (stable nonce) from an app that keeps recreating its
|
|
28
|
+
* socket (changing nonce).
|
|
29
|
+
*/
|
|
30
|
+
const makeConnectionNonce = () => `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
|
|
31
|
+
|
|
18
32
|
/**
|
|
19
33
|
* Hook that manages a Socket.IO connection for device-to-dashboard communication.
|
|
20
34
|
*
|
|
@@ -36,9 +50,13 @@ function useExternalSyncSocket({
|
|
|
36
50
|
const [socket, setSocket] = (0, _react.useState)(null);
|
|
37
51
|
const [isConnected, setIsConnected] = (0, _react.useState)(false);
|
|
38
52
|
const initialized = (0, _react.useRef)(false);
|
|
53
|
+
// Tracks whether we've already logged a connection error for the current
|
|
54
|
+
// outage, so the reconnection backoff doesn't spam an error on every retry.
|
|
55
|
+
const hasLoggedConnectError = (0, _react.useRef)(false);
|
|
39
56
|
const logPrefix = `[${deviceName}]`;
|
|
40
57
|
const onConnect = () => {
|
|
41
58
|
(0, _logger.log)(`${logPrefix} Socket connected successfully`, enableLogs);
|
|
59
|
+
hasLoggedConnectError.current = false;
|
|
42
60
|
setIsConnected(true);
|
|
43
61
|
};
|
|
44
62
|
const onDisconnect = reason => {
|
|
@@ -46,7 +64,13 @@ function useExternalSyncSocket({
|
|
|
46
64
|
setIsConnected(false);
|
|
47
65
|
};
|
|
48
66
|
const onConnectError = error => {
|
|
49
|
-
|
|
67
|
+
// Never surface this in production builds.
|
|
68
|
+
if (!isDev) return;
|
|
69
|
+
// Reconnection retries indefinitely; only log the first failure of an
|
|
70
|
+
// outage to avoid flooding the console until the server comes back up.
|
|
71
|
+
if (hasLoggedConnectError.current) return;
|
|
72
|
+
hasLoggedConnectError.current = true;
|
|
73
|
+
(0, _logger.log)(`${logPrefix} Socket connection error: ${error.message}. Retrying in the background until the dashboard is available.`, enableLogs, "warn");
|
|
50
74
|
};
|
|
51
75
|
const onConnectTimeout = () => {
|
|
52
76
|
(0, _logger.log)(`${logPrefix} Socket connection timeout`, enableLogs, "error");
|
|
@@ -70,9 +94,13 @@ function useExternalSyncSocket({
|
|
|
70
94
|
deviceId: persistentDeviceId,
|
|
71
95
|
platform,
|
|
72
96
|
extraDeviceInfo: JSON.stringify(extraDeviceInfo),
|
|
73
|
-
envVariables: JSON.stringify(envVariables)
|
|
97
|
+
envVariables: JSON.stringify(envVariables),
|
|
98
|
+
connectionNonce: makeConnectionNonce()
|
|
74
99
|
},
|
|
75
|
-
reconnection:
|
|
100
|
+
reconnection: true,
|
|
101
|
+
reconnectionAttempts: Infinity,
|
|
102
|
+
reconnectionDelay: 1000,
|
|
103
|
+
reconnectionDelayMax: 5000,
|
|
76
104
|
transports: ["websocket"]
|
|
77
105
|
});
|
|
78
106
|
} else {
|
|
@@ -131,9 +159,13 @@ function useExternalSyncSocket({
|
|
|
131
159
|
deviceId: persistentDeviceId,
|
|
132
160
|
platform,
|
|
133
161
|
extraDeviceInfo: JSON.stringify(extraDeviceInfo),
|
|
134
|
-
envVariables: JSON.stringify(envVariables)
|
|
162
|
+
envVariables: JSON.stringify(envVariables),
|
|
163
|
+
connectionNonce: makeConnectionNonce()
|
|
135
164
|
},
|
|
136
|
-
reconnection:
|
|
165
|
+
reconnection: true,
|
|
166
|
+
reconnectionAttempts: Infinity,
|
|
167
|
+
reconnectionDelay: 1000,
|
|
168
|
+
reconnectionDelayMax: 5000,
|
|
137
169
|
transports: ["websocket"]
|
|
138
170
|
});
|
|
139
171
|
socketRef.current = globalSocketInstance;
|
|
@@ -4,6 +4,10 @@ import { useEffect, useRef, useState } from "react";
|
|
|
4
4
|
import { io as socketIO } from "socket.io-client";
|
|
5
5
|
import { getPlatformSpecificURL } from "./utils/platformUtils";
|
|
6
6
|
import { log } from "./utils/logger";
|
|
7
|
+
// True only in development. Guarded so it doesn't throw in environments
|
|
8
|
+
// (web/electron bundles) where __DEV__ may be undefined.
|
|
9
|
+
const isDev = typeof __DEV__ !== "undefined" ? __DEV__ : false;
|
|
10
|
+
|
|
7
11
|
/**
|
|
8
12
|
* Singleton socket instance that persists across component renders.
|
|
9
13
|
* Multiple components share the same socket connection.
|
|
@@ -11,6 +15,16 @@ import { log } from "./utils/logger";
|
|
|
11
15
|
let globalSocketInstance = null;
|
|
12
16
|
let currentSocketURL = "";
|
|
13
17
|
|
|
18
|
+
/**
|
|
19
|
+
* Identifies a single socket INSTANCE. Sent in the handshake query and reused
|
|
20
|
+
* for the life of the instance, so it survives socket.io reconnects but
|
|
21
|
+
* changes whenever we create a brand-new socket (remount / Fast Refresh /
|
|
22
|
+
* URL change). The dashboard uses this to tell a flapping connection that's
|
|
23
|
+
* merely reconnecting (stable nonce) from an app that keeps recreating its
|
|
24
|
+
* socket (changing nonce).
|
|
25
|
+
*/
|
|
26
|
+
const makeConnectionNonce = () => `${Date.now().toString(36)}-${Math.random().toString(36).slice(2, 10)}`;
|
|
27
|
+
|
|
14
28
|
/**
|
|
15
29
|
* Hook that manages a Socket.IO connection for device-to-dashboard communication.
|
|
16
30
|
*
|
|
@@ -32,9 +46,13 @@ export function useExternalSyncSocket({
|
|
|
32
46
|
const [socket, setSocket] = useState(null);
|
|
33
47
|
const [isConnected, setIsConnected] = useState(false);
|
|
34
48
|
const initialized = useRef(false);
|
|
49
|
+
// Tracks whether we've already logged a connection error for the current
|
|
50
|
+
// outage, so the reconnection backoff doesn't spam an error on every retry.
|
|
51
|
+
const hasLoggedConnectError = useRef(false);
|
|
35
52
|
const logPrefix = `[${deviceName}]`;
|
|
36
53
|
const onConnect = () => {
|
|
37
54
|
log(`${logPrefix} Socket connected successfully`, enableLogs);
|
|
55
|
+
hasLoggedConnectError.current = false;
|
|
38
56
|
setIsConnected(true);
|
|
39
57
|
};
|
|
40
58
|
const onDisconnect = reason => {
|
|
@@ -42,7 +60,13 @@ export function useExternalSyncSocket({
|
|
|
42
60
|
setIsConnected(false);
|
|
43
61
|
};
|
|
44
62
|
const onConnectError = error => {
|
|
45
|
-
|
|
63
|
+
// Never surface this in production builds.
|
|
64
|
+
if (!isDev) return;
|
|
65
|
+
// Reconnection retries indefinitely; only log the first failure of an
|
|
66
|
+
// outage to avoid flooding the console until the server comes back up.
|
|
67
|
+
if (hasLoggedConnectError.current) return;
|
|
68
|
+
hasLoggedConnectError.current = true;
|
|
69
|
+
log(`${logPrefix} Socket connection error: ${error.message}. Retrying in the background until the dashboard is available.`, enableLogs, "warn");
|
|
46
70
|
};
|
|
47
71
|
const onConnectTimeout = () => {
|
|
48
72
|
log(`${logPrefix} Socket connection timeout`, enableLogs, "error");
|
|
@@ -66,9 +90,13 @@ export function useExternalSyncSocket({
|
|
|
66
90
|
deviceId: persistentDeviceId,
|
|
67
91
|
platform,
|
|
68
92
|
extraDeviceInfo: JSON.stringify(extraDeviceInfo),
|
|
69
|
-
envVariables: JSON.stringify(envVariables)
|
|
93
|
+
envVariables: JSON.stringify(envVariables),
|
|
94
|
+
connectionNonce: makeConnectionNonce()
|
|
70
95
|
},
|
|
71
|
-
reconnection:
|
|
96
|
+
reconnection: true,
|
|
97
|
+
reconnectionAttempts: Infinity,
|
|
98
|
+
reconnectionDelay: 1000,
|
|
99
|
+
reconnectionDelayMax: 5000,
|
|
72
100
|
transports: ["websocket"]
|
|
73
101
|
});
|
|
74
102
|
} else {
|
|
@@ -127,9 +155,13 @@ export function useExternalSyncSocket({
|
|
|
127
155
|
deviceId: persistentDeviceId,
|
|
128
156
|
platform,
|
|
129
157
|
extraDeviceInfo: JSON.stringify(extraDeviceInfo),
|
|
130
|
-
envVariables: JSON.stringify(envVariables)
|
|
158
|
+
envVariables: JSON.stringify(envVariables),
|
|
159
|
+
connectionNonce: makeConnectionNonce()
|
|
131
160
|
},
|
|
132
|
-
reconnection:
|
|
161
|
+
reconnection: true,
|
|
162
|
+
reconnectionAttempts: Infinity,
|
|
163
|
+
reconnectionDelay: 1000,
|
|
164
|
+
reconnectionDelayMax: 5000,
|
|
133
165
|
transports: ["websocket"]
|
|
134
166
|
});
|
|
135
167
|
socketRef.current = globalSocketInstance;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useExternalSyncSocket.d.ts","sourceRoot":"","sources":["../../src/useExternalSyncSocket.ts"],"names":[],"mappings":"AACA,OAAO,EAAkB,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAI1D,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"useExternalSyncSocket.d.ts","sourceRoot":"","sources":["../../src/useExternalSyncSocket.ts"],"names":[],"mappings":"AACA,OAAO,EAAkB,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAI1D,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;;;;;EAsN5B"}
|