@buoy-gg/sync-broker 4.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/LICENSE +58 -0
- package/README.md +55 -0
- package/dist/index.d.mts +167 -0
- package/dist/index.d.ts +167 -0
- package/dist/index.js +482 -0
- package/dist/index.mjs +441 -0
- package/package.json +52 -0
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,441 @@
|
|
|
1
|
+
// src/socketHandle.ts
|
|
2
|
+
var users = [];
|
|
3
|
+
var allDevices = [];
|
|
4
|
+
var dashboardClients = [];
|
|
5
|
+
var deviceIdMap = /* @__PURE__ */ new Map();
|
|
6
|
+
var activeConnectionsMap = /* @__PURE__ */ new Map();
|
|
7
|
+
var deviceCapabilities = /* @__PURE__ */ new Map();
|
|
8
|
+
var dashboardWatches = /* @__PURE__ */ new Map();
|
|
9
|
+
var watchCounts = /* @__PURE__ */ new Map();
|
|
10
|
+
var toWatchKey = (targetDeviceId, toolId) => JSON.stringify([targetDeviceId, toolId]);
|
|
11
|
+
var fromWatchKey = (key) => JSON.parse(key);
|
|
12
|
+
function socketHandle({ io }) {
|
|
13
|
+
const LOG_PREFIX = "[SERVER]";
|
|
14
|
+
function handleClose(id, reason) {
|
|
15
|
+
const user = users.find((user2) => user2.id === id);
|
|
16
|
+
const deviceId = deviceIdMap.get(id);
|
|
17
|
+
if (!deviceId || !users.some((u) => u.id !== id && u.deviceId === deviceId)) {
|
|
18
|
+
users = users.filter((user2) => user2.id !== id);
|
|
19
|
+
console.log(
|
|
20
|
+
`${LOG_PREFIX} Client disconnected - ID: ${id}, Name: ${user?.deviceName || "Unknown"} - Removing user record`
|
|
21
|
+
);
|
|
22
|
+
if (deviceId) {
|
|
23
|
+
const deviceIndex = allDevices.findIndex(
|
|
24
|
+
(u) => u.deviceId === deviceId
|
|
25
|
+
);
|
|
26
|
+
if (deviceIndex !== -1) {
|
|
27
|
+
allDevices[deviceIndex].isConnected = false;
|
|
28
|
+
allDevices[deviceIndex].lastDisconnectReason = reason;
|
|
29
|
+
activeConnectionsMap.delete(deviceId);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
} else {
|
|
33
|
+
console.log(
|
|
34
|
+
`${LOG_PREFIX} Client disconnected - ID: ${id}, Name: ${user?.deviceName || "Unknown"} - Keeping user record for same device with ID: ${deviceId}`
|
|
35
|
+
);
|
|
36
|
+
}
|
|
37
|
+
deviceIdMap.delete(id);
|
|
38
|
+
const wasDashboard = dashboardClients.includes(id);
|
|
39
|
+
dashboardClients = dashboardClients.filter((clientId) => clientId !== id);
|
|
40
|
+
releaseDashboardWatches(id);
|
|
41
|
+
console.log(
|
|
42
|
+
`${LOG_PREFIX} Client disconnected - ID: ${id}, Name: ${user?.deviceName || "Unknown"}, Was Dashboard: ${wasDashboard}, Reason: ${reason ?? "unknown"}`
|
|
43
|
+
);
|
|
44
|
+
io.emit(
|
|
45
|
+
"all-devices-update",
|
|
46
|
+
allDevices.filter((device) => device.deviceName !== "Dashboard")
|
|
47
|
+
);
|
|
48
|
+
console.log(
|
|
49
|
+
`${LOG_PREFIX} Updated users list: ${users.map((u) => u.deviceName).join(", ")}`
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
function addNewUser({
|
|
53
|
+
id,
|
|
54
|
+
deviceName,
|
|
55
|
+
deviceId,
|
|
56
|
+
platform,
|
|
57
|
+
extraDeviceInfo,
|
|
58
|
+
envVariables,
|
|
59
|
+
connectionNonce
|
|
60
|
+
}) {
|
|
61
|
+
const isDashboard = deviceName === "Dashboard";
|
|
62
|
+
if (deviceId) {
|
|
63
|
+
deviceIdMap.set(id, deviceId);
|
|
64
|
+
activeConnectionsMap.set(deviceId, id);
|
|
65
|
+
const existingUserIndex = users.findIndex(
|
|
66
|
+
(user) => user.deviceId === deviceId
|
|
67
|
+
);
|
|
68
|
+
const existingDeviceIndex = allDevices.findIndex(
|
|
69
|
+
(device) => device.deviceId === deviceId
|
|
70
|
+
);
|
|
71
|
+
if (existingUserIndex !== -1) {
|
|
72
|
+
console.log(
|
|
73
|
+
`${LOG_PREFIX} Reconnecting existing device - ID: ${id}, Name: ${deviceName}, DeviceId: ${deviceId}, Platform: ${platform || "Unknown"}, ExtraDeviceInfo: ${extraDeviceInfo}`
|
|
74
|
+
);
|
|
75
|
+
users[existingUserIndex].id = id;
|
|
76
|
+
if (platform) {
|
|
77
|
+
users[existingUserIndex].platform = platform;
|
|
78
|
+
}
|
|
79
|
+
if (extraDeviceInfo) {
|
|
80
|
+
users[existingUserIndex].extraDeviceInfo = extraDeviceInfo;
|
|
81
|
+
}
|
|
82
|
+
if (envVariables) {
|
|
83
|
+
users[existingUserIndex].envVariables = envVariables;
|
|
84
|
+
}
|
|
85
|
+
users[existingUserIndex].isConnected = true;
|
|
86
|
+
users[existingUserIndex].connectionNonce = connectionNonce;
|
|
87
|
+
if (existingDeviceIndex !== -1) {
|
|
88
|
+
allDevices[existingDeviceIndex].id = id;
|
|
89
|
+
allDevices[existingDeviceIndex].isConnected = true;
|
|
90
|
+
allDevices[existingDeviceIndex].connectionNonce = connectionNonce;
|
|
91
|
+
if (platform) {
|
|
92
|
+
allDevices[existingDeviceIndex].platform = platform;
|
|
93
|
+
}
|
|
94
|
+
if (extraDeviceInfo) {
|
|
95
|
+
allDevices[existingDeviceIndex].extraDeviceInfo = extraDeviceInfo;
|
|
96
|
+
}
|
|
97
|
+
if (envVariables) {
|
|
98
|
+
allDevices[existingDeviceIndex].envVariables = envVariables;
|
|
99
|
+
}
|
|
100
|
+
} else if (deviceName !== "Dashboard") {
|
|
101
|
+
allDevices.push({
|
|
102
|
+
id,
|
|
103
|
+
deviceName,
|
|
104
|
+
deviceId,
|
|
105
|
+
platform,
|
|
106
|
+
isConnected: true,
|
|
107
|
+
extraDeviceInfo,
|
|
108
|
+
envVariables
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
io.emit(
|
|
112
|
+
"all-devices-update",
|
|
113
|
+
allDevices.filter((device) => device.deviceName !== "Dashboard")
|
|
114
|
+
);
|
|
115
|
+
console.log(
|
|
116
|
+
`${LOG_PREFIX} Updated users list: ${users.map((u) => u.deviceName).join(", ")}`
|
|
117
|
+
);
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
const extractNumber = (name) => {
|
|
122
|
+
const match = name.match(/(\d+)$/);
|
|
123
|
+
return match ? parseInt(match[1], 10) : 1;
|
|
124
|
+
};
|
|
125
|
+
let highestNumber = 0;
|
|
126
|
+
users.forEach((user) => {
|
|
127
|
+
if (user.deviceName.startsWith(deviceName)) {
|
|
128
|
+
const number = extractNumber(user.deviceName);
|
|
129
|
+
if (number >= highestNumber) {
|
|
130
|
+
highestNumber = number;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
});
|
|
134
|
+
if (highestNumber > 0 && !isDashboard) {
|
|
135
|
+
deviceName = `${deviceName} #${highestNumber + 1}`;
|
|
136
|
+
}
|
|
137
|
+
if (id) {
|
|
138
|
+
const newUser = {
|
|
139
|
+
id,
|
|
140
|
+
deviceName,
|
|
141
|
+
deviceId,
|
|
142
|
+
platform,
|
|
143
|
+
isConnected: true,
|
|
144
|
+
extraDeviceInfo,
|
|
145
|
+
envVariables,
|
|
146
|
+
connectionNonce
|
|
147
|
+
};
|
|
148
|
+
users.push(newUser);
|
|
149
|
+
if (deviceName !== "Dashboard" && deviceId) {
|
|
150
|
+
const existingDeviceIndex = allDevices.findIndex(
|
|
151
|
+
(device) => device.deviceId === deviceId
|
|
152
|
+
);
|
|
153
|
+
if (existingDeviceIndex !== -1) {
|
|
154
|
+
allDevices[existingDeviceIndex] = { ...newUser };
|
|
155
|
+
} else {
|
|
156
|
+
allDevices.push({ ...newUser });
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
console.log(
|
|
160
|
+
`${LOG_PREFIX} New user connected - ID: ${id}, Name: ${deviceName}${deviceId ? `, DeviceId: ${deviceId}` : ""}${platform ? `, Platform: ${platform}` : ""}`
|
|
161
|
+
);
|
|
162
|
+
if (isDashboard && id) {
|
|
163
|
+
dashboardClients.push(id);
|
|
164
|
+
console.log(`${LOG_PREFIX} Registered dashboard client with ID: ${id}`);
|
|
165
|
+
}
|
|
166
|
+
io.emit(
|
|
167
|
+
"all-devices-update",
|
|
168
|
+
allDevices.filter((device) => device.deviceName !== "Dashboard")
|
|
169
|
+
);
|
|
170
|
+
console.log(
|
|
171
|
+
`${LOG_PREFIX} Updated device list: ${users.map((u) => u.deviceName).join(", ")}`
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
function getDeviceFromDeviceId(deviceId) {
|
|
176
|
+
return allDevices.find((device) => device.deviceId === deviceId);
|
|
177
|
+
}
|
|
178
|
+
function handleUserMessage(message, deviceName) {
|
|
179
|
+
console.log(`${LOG_PREFIX} Message from ${deviceName}: ${message}`);
|
|
180
|
+
io.emit("message", `Device ${deviceName} sent message: ${message}`);
|
|
181
|
+
}
|
|
182
|
+
function forwardToDashboards(event, message) {
|
|
183
|
+
dashboardClients = dashboardClients.filter(
|
|
184
|
+
(id) => io.sockets.sockets.has(id)
|
|
185
|
+
);
|
|
186
|
+
if (dashboardClients.length === 0) {
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
for (const dashboardId of dashboardClients) {
|
|
190
|
+
io.sockets.sockets.get(dashboardId)?.emit(event, message);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
function withTargetUsers(targetDeviceId, action, actionName) {
|
|
194
|
+
const deviceName = getDeviceFromDeviceId(targetDeviceId)?.deviceName;
|
|
195
|
+
if (targetDeviceId === "No devices available") {
|
|
196
|
+
console.log(
|
|
197
|
+
`${LOG_PREFIX} Skipping ${actionName} - No devices available`
|
|
198
|
+
);
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
if (targetDeviceId === "All") {
|
|
202
|
+
console.log(`${LOG_PREFIX} Broadcasting ${actionName} to all devices`);
|
|
203
|
+
const deviceUsers = users.filter(
|
|
204
|
+
(user) => user.deviceName !== "Dashboard"
|
|
205
|
+
);
|
|
206
|
+
console.log(
|
|
207
|
+
`${LOG_PREFIX} Sending to ${deviceUsers.length} devices: ${deviceUsers.map((u) => u.deviceName).join(", ")}`
|
|
208
|
+
);
|
|
209
|
+
deviceUsers.forEach(action);
|
|
210
|
+
} else {
|
|
211
|
+
const targetUser = users.find((user) => user.deviceId === targetDeviceId);
|
|
212
|
+
if (targetUser) {
|
|
213
|
+
console.log(
|
|
214
|
+
`${LOG_PREFIX} Sending to target device ${targetUser.deviceName} (${targetUser.deviceId}) targetDeviceId: ${targetDeviceId}`
|
|
215
|
+
);
|
|
216
|
+
action(targetUser);
|
|
217
|
+
} else {
|
|
218
|
+
console.log(
|
|
219
|
+
`${LOG_PREFIX} Target device not found - DeviceId: ${targetDeviceId}, DeviceName: ${deviceName}`
|
|
220
|
+
);
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
function handleDevtoolWatch(dashboardId, message) {
|
|
225
|
+
const key = toWatchKey(message.targetDeviceId, message.toolId);
|
|
226
|
+
let watches = dashboardWatches.get(dashboardId);
|
|
227
|
+
if (!watches) {
|
|
228
|
+
watches = /* @__PURE__ */ new Set();
|
|
229
|
+
dashboardWatches.set(dashboardId, watches);
|
|
230
|
+
}
|
|
231
|
+
if (message.watching) {
|
|
232
|
+
if (!watches.has(key)) {
|
|
233
|
+
watches.add(key);
|
|
234
|
+
watchCounts.set(key, (watchCounts.get(key) ?? 0) + 1);
|
|
235
|
+
}
|
|
236
|
+
console.log(
|
|
237
|
+
`${LOG_PREFIX} Dashboard ${dashboardId} watching "${message.toolId}" on ${message.targetDeviceId}`
|
|
238
|
+
);
|
|
239
|
+
withTargetUsers(
|
|
240
|
+
message.targetDeviceId,
|
|
241
|
+
(user) => io.to(user.id).emit("devtool-watch", message),
|
|
242
|
+
`devtool watch ${message.toolId}`
|
|
243
|
+
);
|
|
244
|
+
} else if (watches.has(key)) {
|
|
245
|
+
watches.delete(key);
|
|
246
|
+
decrementWatch(key);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
function decrementWatch(key) {
|
|
250
|
+
const next = (watchCounts.get(key) ?? 1) - 1;
|
|
251
|
+
if (next > 0) {
|
|
252
|
+
watchCounts.set(key, next);
|
|
253
|
+
return;
|
|
254
|
+
}
|
|
255
|
+
watchCounts.delete(key);
|
|
256
|
+
const [targetDeviceId, toolId] = fromWatchKey(key);
|
|
257
|
+
console.log(
|
|
258
|
+
`${LOG_PREFIX} Last dashboard stopped watching "${toolId}" on ${targetDeviceId}`
|
|
259
|
+
);
|
|
260
|
+
withTargetUsers(
|
|
261
|
+
targetDeviceId,
|
|
262
|
+
(user) => io.to(user.id).emit("devtool-watch", { toolId, targetDeviceId, watching: false }),
|
|
263
|
+
`devtool unwatch ${toolId}`
|
|
264
|
+
);
|
|
265
|
+
}
|
|
266
|
+
function releaseDashboardWatches(dashboardId) {
|
|
267
|
+
const watches = dashboardWatches.get(dashboardId);
|
|
268
|
+
if (!watches) return;
|
|
269
|
+
dashboardWatches.delete(dashboardId);
|
|
270
|
+
for (const key of watches) {
|
|
271
|
+
decrementWatch(key);
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
io.on("connection", (socket) => {
|
|
275
|
+
const {
|
|
276
|
+
deviceName,
|
|
277
|
+
deviceId,
|
|
278
|
+
platform,
|
|
279
|
+
extraDeviceInfo,
|
|
280
|
+
envVariables,
|
|
281
|
+
connectionNonce
|
|
282
|
+
} = socket.handshake.query;
|
|
283
|
+
console.log(
|
|
284
|
+
`${LOG_PREFIX} New connection - ID: ${socket.id}, Name: ${deviceName || "Unknown Device"}${deviceId ? `, DeviceId: ${deviceId}` : ""}${platform ? `, Platform: ${platform}` : ""}${extraDeviceInfo ? `, ExtraDeviceInfo: ${extraDeviceInfo}` : ""}${envVariables ? `, EnvVariables: ${envVariables}` : ""}`
|
|
285
|
+
);
|
|
286
|
+
addNewUser({
|
|
287
|
+
id: socket.id,
|
|
288
|
+
deviceName: deviceName || "Unknown Device Name",
|
|
289
|
+
deviceId,
|
|
290
|
+
platform,
|
|
291
|
+
extraDeviceInfo,
|
|
292
|
+
envVariables,
|
|
293
|
+
connectionNonce
|
|
294
|
+
});
|
|
295
|
+
if (deviceName === "Dashboard") {
|
|
296
|
+
for (const capabilities of deviceCapabilities.values()) {
|
|
297
|
+
socket.emit("devtool-capabilities", capabilities);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
socket.on(
|
|
301
|
+
"device-license",
|
|
302
|
+
(payload) => {
|
|
303
|
+
const nextIsPro = payload?.isPro === "1" || payload?.isPro === true;
|
|
304
|
+
const nextKey = payload?.licenseKey || void 0;
|
|
305
|
+
const user = users.find((u) => u.id === socket.id);
|
|
306
|
+
if (user) {
|
|
307
|
+
user.isPro = nextIsPro;
|
|
308
|
+
user.licenseKey = nextIsPro ? nextKey : void 0;
|
|
309
|
+
}
|
|
310
|
+
const did = user?.deviceId || deviceIdMap.get(socket.id);
|
|
311
|
+
if (did) {
|
|
312
|
+
const device = allDevices.find((d) => d.deviceId === did);
|
|
313
|
+
if (device) {
|
|
314
|
+
device.isPro = nextIsPro;
|
|
315
|
+
device.licenseKey = nextIsPro ? nextKey : void 0;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
console.log(
|
|
319
|
+
`${LOG_PREFIX} device-license from ${user?.deviceName || socket.id}: isPro=${nextIsPro}${nextKey ? ", key set" : ""}`
|
|
320
|
+
);
|
|
321
|
+
io.emit(
|
|
322
|
+
"all-devices-update",
|
|
323
|
+
allDevices.filter((device) => device.deviceName !== "Dashboard")
|
|
324
|
+
);
|
|
325
|
+
}
|
|
326
|
+
);
|
|
327
|
+
socket.on(
|
|
328
|
+
"disconnect",
|
|
329
|
+
(reason) => handleClose(socket.id, reason)
|
|
330
|
+
);
|
|
331
|
+
socket.on("message", (msg) => {
|
|
332
|
+
handleUserMessage(msg, deviceName || "Unknown");
|
|
333
|
+
});
|
|
334
|
+
socket.on("devtool-capabilities", (message) => {
|
|
335
|
+
console.log(
|
|
336
|
+
`${LOG_PREFIX} Capabilities from ${message.persistentDeviceId}: ${message.tools.map((tool) => `${tool.toolId}@v${tool.version}`).join(", ")}`
|
|
337
|
+
);
|
|
338
|
+
deviceCapabilities.set(message.persistentDeviceId, message);
|
|
339
|
+
forwardToDashboards("devtool-capabilities", message);
|
|
340
|
+
for (const key of watchCounts.keys()) {
|
|
341
|
+
const [targetDeviceId, toolId] = fromWatchKey(key);
|
|
342
|
+
if (targetDeviceId === "All" || targetDeviceId === message.persistentDeviceId) {
|
|
343
|
+
socket.emit("devtool-watch", {
|
|
344
|
+
toolId,
|
|
345
|
+
targetDeviceId,
|
|
346
|
+
watching: true
|
|
347
|
+
});
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
});
|
|
351
|
+
socket.on("devtool-sync", (message) => {
|
|
352
|
+
forwardToDashboards("devtool-sync", message);
|
|
353
|
+
});
|
|
354
|
+
socket.on(
|
|
355
|
+
"devtool-action-result",
|
|
356
|
+
(message) => {
|
|
357
|
+
console.log(
|
|
358
|
+
`${LOG_PREFIX} Action result from ${message.persistentDeviceId}: ${message.toolId}.${message.action} -> ${message.ok ? "ok" : `error: ${message.error}`}`
|
|
359
|
+
);
|
|
360
|
+
forwardToDashboards("devtool-action-result", message);
|
|
361
|
+
}
|
|
362
|
+
);
|
|
363
|
+
socket.on("devtool-watch", (message) => {
|
|
364
|
+
handleDevtoolWatch(socket.id, message);
|
|
365
|
+
});
|
|
366
|
+
socket.on("request-devtool-state", (message) => {
|
|
367
|
+
withTargetUsers(
|
|
368
|
+
message.targetDeviceId,
|
|
369
|
+
(user) => io.to(user.id).emit("request-devtool-state", message),
|
|
370
|
+
`devtool state request ${message.toolId}`
|
|
371
|
+
);
|
|
372
|
+
});
|
|
373
|
+
socket.on("devtool-action", (message) => {
|
|
374
|
+
console.log(
|
|
375
|
+
`${LOG_PREFIX} Devtool action from dashboard: ${message.toolId}.${message.action} -> ${message.targetDeviceId}`
|
|
376
|
+
);
|
|
377
|
+
withTargetUsers(
|
|
378
|
+
message.targetDeviceId,
|
|
379
|
+
(user) => io.to(user.id).emit("devtool-action", message),
|
|
380
|
+
`devtool action ${message.toolId}.${message.action}`
|
|
381
|
+
);
|
|
382
|
+
});
|
|
383
|
+
});
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
// src/createBroker.ts
|
|
387
|
+
import http from "http";
|
|
388
|
+
import { Server as SocketIOServer } from "socket.io";
|
|
389
|
+
var DEFAULT_BROKER_PORT = 42831;
|
|
390
|
+
var SOCKET_CONFIG = {
|
|
391
|
+
cors: {
|
|
392
|
+
origin: "*",
|
|
393
|
+
methods: ["GET", "POST"]
|
|
394
|
+
},
|
|
395
|
+
// Dev-tool snapshots are whole app-state dumps (a dehydrated React Query
|
|
396
|
+
// cache, a Redux/Zustand store, an aggregated event log, etc.) and a device
|
|
397
|
+
// pushes one per watched tool on connect. socket.io v3+ caps inbound messages
|
|
398
|
+
// at 1 MB by default and TERMINATES the connection ("transport error") when a
|
|
399
|
+
// single message exceeds it — which, with a dashboard watching all ~11 tools
|
|
400
|
+
// at once, makes a device's connection flap. These are local, trusted dev
|
|
401
|
+
// connections, so lift the cap well clear of any realistic state dump.
|
|
402
|
+
maxHttpBufferSize: 1e8,
|
|
403
|
+
// 100 MB
|
|
404
|
+
transports: ["websocket", "polling"],
|
|
405
|
+
pingTimeout: 3e4,
|
|
406
|
+
pingInterval: 25e3
|
|
407
|
+
};
|
|
408
|
+
function createBroker(options = {}) {
|
|
409
|
+
const port = options.port ?? DEFAULT_BROKER_PORT;
|
|
410
|
+
const httpServer = http.createServer((_req, res) => {
|
|
411
|
+
res.writeHead(200, { "content-type": "text/plain" });
|
|
412
|
+
res.end(`Buoy sync broker running on port ${port}`);
|
|
413
|
+
});
|
|
414
|
+
const io = new SocketIOServer(httpServer, {
|
|
415
|
+
...SOCKET_CONFIG,
|
|
416
|
+
...options.socketOptions
|
|
417
|
+
});
|
|
418
|
+
socketHandle({ io });
|
|
419
|
+
httpServer.on("error", (error) => {
|
|
420
|
+
options.onError?.(error);
|
|
421
|
+
});
|
|
422
|
+
httpServer.listen(port, () => {
|
|
423
|
+
options.onListening?.(port);
|
|
424
|
+
});
|
|
425
|
+
const close = () => new Promise((resolve) => {
|
|
426
|
+
io.close(() => {
|
|
427
|
+
httpServer.close(() => resolve());
|
|
428
|
+
});
|
|
429
|
+
});
|
|
430
|
+
return { io, httpServer, port, close };
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
// src/protocol.ts
|
|
434
|
+
var SYNC_PROTOCOL_VERSION = 1;
|
|
435
|
+
export {
|
|
436
|
+
DEFAULT_BROKER_PORT,
|
|
437
|
+
SOCKET_CONFIG,
|
|
438
|
+
SYNC_PROTOCOL_VERSION,
|
|
439
|
+
createBroker,
|
|
440
|
+
socketHandle
|
|
441
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@buoy-gg/sync-broker",
|
|
3
|
+
"version": "4.0.1",
|
|
4
|
+
"description": "Headless Socket.IO broker for the Buoy devtool sync protocol (v1) — routes messages between devices and dashboard/MCP clients",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.mjs",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": {
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"default": "./dist/index.mjs"
|
|
13
|
+
},
|
|
14
|
+
"require": {
|
|
15
|
+
"types": "./dist/index.d.ts",
|
|
16
|
+
"default": "./dist/index.js"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"./package.json": "./package.json"
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"dist"
|
|
23
|
+
],
|
|
24
|
+
"sideEffects": false,
|
|
25
|
+
"dependencies": {
|
|
26
|
+
"socket.io": "^4.8.1"
|
|
27
|
+
},
|
|
28
|
+
"devDependencies": {
|
|
29
|
+
"@types/node": "^22.0.0",
|
|
30
|
+
"rimraf": "^5.0.0",
|
|
31
|
+
"tsup": "^8.5.1",
|
|
32
|
+
"typescript": "~5.8.3"
|
|
33
|
+
},
|
|
34
|
+
"engines": {
|
|
35
|
+
"node": ">=18"
|
|
36
|
+
},
|
|
37
|
+
"repository": {
|
|
38
|
+
"type": "git",
|
|
39
|
+
"url": "https://github.com/LovesWorking/react-native-buoy.git",
|
|
40
|
+
"directory": "packages/sync-broker"
|
|
41
|
+
},
|
|
42
|
+
"publishConfig": {
|
|
43
|
+
"access": "public",
|
|
44
|
+
"tag": "latest"
|
|
45
|
+
},
|
|
46
|
+
"scripts": {
|
|
47
|
+
"build": "tsup",
|
|
48
|
+
"typecheck": "tsc --noEmit",
|
|
49
|
+
"clean": "rimraf dist",
|
|
50
|
+
"test": "pnpm run typecheck"
|
|
51
|
+
}
|
|
52
|
+
}
|