@jay-framework/editor-client 0.6.7 → 0.6.9
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/package.json +5 -8
- package/dist/index.cjs +0 -275
package/package.json
CHANGED
|
@@ -1,15 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jay-framework/editor-client",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.9",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
8
8
|
"exports": {
|
|
9
|
-
".":
|
|
10
|
-
"import": "./dist/index.js",
|
|
11
|
-
"require": "./dist/index.cjs"
|
|
12
|
-
}
|
|
9
|
+
".": "./dist/index.js"
|
|
13
10
|
},
|
|
14
11
|
"files": [
|
|
15
12
|
"dist",
|
|
@@ -27,14 +24,14 @@
|
|
|
27
24
|
"test:watch": "vitest"
|
|
28
25
|
},
|
|
29
26
|
"dependencies": {
|
|
30
|
-
"@jay-framework/editor-protocol": "^0.6.
|
|
27
|
+
"@jay-framework/editor-protocol": "^0.6.9",
|
|
31
28
|
"get-port": "^7.0.0",
|
|
32
29
|
"socket.io-client": "^4.7.4",
|
|
33
30
|
"uuid": "^9.0.1"
|
|
34
31
|
},
|
|
35
32
|
"devDependencies": {
|
|
36
|
-
"@jay-framework/dev-environment": "^0.6.
|
|
37
|
-
"@jay-framework/jay-cli": "^0.6.
|
|
33
|
+
"@jay-framework/dev-environment": "^0.6.9",
|
|
34
|
+
"@jay-framework/jay-cli": "^0.6.9",
|
|
38
35
|
"@types/node": "^22.15.21",
|
|
39
36
|
"@types/uuid": "^9.0.7",
|
|
40
37
|
"rimraf": "^5.0.5",
|
package/dist/index.cjs
DELETED
|
@@ -1,275 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
4
|
-
var __publicField = (obj, key, value) => {
|
|
5
|
-
__defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
|
|
6
|
-
return value;
|
|
7
|
-
};
|
|
8
|
-
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
9
|
-
const socket_ioClient = require("socket.io-client");
|
|
10
|
-
const uuid = require("uuid");
|
|
11
|
-
const editorProtocol = require("@jay-framework/editor-protocol");
|
|
12
|
-
class ConnectionManager {
|
|
13
|
-
constructor(options = {}) {
|
|
14
|
-
__publicField(this, "socket", null);
|
|
15
|
-
__publicField(this, "connectionState", "disconnected");
|
|
16
|
-
__publicField(this, "portRange");
|
|
17
|
-
__publicField(this, "scanTimeout");
|
|
18
|
-
__publicField(this, "retryAttempts");
|
|
19
|
-
__publicField(this, "editorId");
|
|
20
|
-
__publicField(this, "autoReconnect");
|
|
21
|
-
__publicField(this, "reconnectDelay");
|
|
22
|
-
__publicField(this, "reconnectTimer", null);
|
|
23
|
-
__publicField(this, "isManualDisconnect", false);
|
|
24
|
-
__publicField(this, "isConnecting", false);
|
|
25
|
-
__publicField(this, "pendingRequests", /* @__PURE__ */ new Map());
|
|
26
|
-
__publicField(this, "stateChangeCallbacks", /* @__PURE__ */ new Set());
|
|
27
|
-
this.portRange = options.portRange || [3101, 3200];
|
|
28
|
-
this.scanTimeout = options.scanTimeout || 5e3;
|
|
29
|
-
this.retryAttempts = options.retryAttempts || 3;
|
|
30
|
-
this.editorId = options.editorId || uuid.v4();
|
|
31
|
-
this.autoReconnect = options.autoReconnect || true;
|
|
32
|
-
this.reconnectDelay = options.reconnectDelay || 1e3;
|
|
33
|
-
}
|
|
34
|
-
async connect() {
|
|
35
|
-
if (this.connectionState === "connected" || this.isConnecting) {
|
|
36
|
-
return;
|
|
37
|
-
}
|
|
38
|
-
this.isManualDisconnect = false;
|
|
39
|
-
this.isConnecting = true;
|
|
40
|
-
this.updateConnectionState("connecting");
|
|
41
|
-
try {
|
|
42
|
-
const serverPort = await this.discoverServer();
|
|
43
|
-
await this.establishConnection(serverPort);
|
|
44
|
-
this.updateConnectionState("connected");
|
|
45
|
-
} catch (error) {
|
|
46
|
-
this.updateConnectionState("error");
|
|
47
|
-
throw error;
|
|
48
|
-
} finally {
|
|
49
|
-
this.isConnecting = false;
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
async disconnect() {
|
|
53
|
-
this.isManualDisconnect = true;
|
|
54
|
-
this.isConnecting = false;
|
|
55
|
-
if (this.reconnectTimer) {
|
|
56
|
-
clearTimeout(this.reconnectTimer);
|
|
57
|
-
this.reconnectTimer = null;
|
|
58
|
-
}
|
|
59
|
-
if (this.socket) {
|
|
60
|
-
this.socket.disconnect();
|
|
61
|
-
this.socket = null;
|
|
62
|
-
}
|
|
63
|
-
this.updateConnectionState("disconnected");
|
|
64
|
-
}
|
|
65
|
-
getConnectionState() {
|
|
66
|
-
return this.connectionState;
|
|
67
|
-
}
|
|
68
|
-
onConnectionStateChange(callback) {
|
|
69
|
-
this.stateChangeCallbacks.add(callback);
|
|
70
|
-
return () => {
|
|
71
|
-
this.stateChangeCallbacks.delete(callback);
|
|
72
|
-
};
|
|
73
|
-
}
|
|
74
|
-
async sendMessage(message) {
|
|
75
|
-
if (this.connectionState !== "connected") {
|
|
76
|
-
throw new Error("Not connected to editor server");
|
|
77
|
-
}
|
|
78
|
-
if (!this.socket) {
|
|
79
|
-
throw new Error("Not connected to editor server - Socket not available");
|
|
80
|
-
}
|
|
81
|
-
return new Promise((resolve, reject) => {
|
|
82
|
-
const protocolMessage = editorProtocol.createProtocolMessage(message);
|
|
83
|
-
this.pendingRequests.set(protocolMessage.id, { resolve, reject });
|
|
84
|
-
setTimeout(() => {
|
|
85
|
-
if (this.pendingRequests.has(protocolMessage.id)) {
|
|
86
|
-
this.pendingRequests.delete(protocolMessage.id);
|
|
87
|
-
reject(new Error("Request timeout"));
|
|
88
|
-
}
|
|
89
|
-
}, this.scanTimeout);
|
|
90
|
-
this.socket.emit("protocol-message", protocolMessage);
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
updateConnectionState(newState) {
|
|
94
|
-
if (this.connectionState !== newState) {
|
|
95
|
-
this.connectionState;
|
|
96
|
-
this.connectionState = newState;
|
|
97
|
-
this.stateChangeCallbacks.forEach((callback) => {
|
|
98
|
-
try {
|
|
99
|
-
callback(newState);
|
|
100
|
-
} catch (error) {
|
|
101
|
-
console.error("Error in connection state callback:", error);
|
|
102
|
-
}
|
|
103
|
-
});
|
|
104
|
-
if (newState === "disconnected" && this.autoReconnect && !this.isManualDisconnect) {
|
|
105
|
-
this.scheduleReconnect();
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
scheduleReconnect() {
|
|
110
|
-
if (this.isManualDisconnect || this.reconnectTimer) {
|
|
111
|
-
return;
|
|
112
|
-
}
|
|
113
|
-
this.reconnectTimer = setTimeout(() => {
|
|
114
|
-
this.reconnectTimer = null;
|
|
115
|
-
this.attemptReconnect();
|
|
116
|
-
}, this.reconnectDelay);
|
|
117
|
-
}
|
|
118
|
-
async discoverServer() {
|
|
119
|
-
const [startPort, endPort] = this.portRange;
|
|
120
|
-
const ports = Array.from({ length: endPort - startPort + 1 }, (_, i) => startPort + i);
|
|
121
|
-
const errors = [];
|
|
122
|
-
for (let attempt = 0; attempt < this.retryAttempts; attempt++) {
|
|
123
|
-
for (const port of ports) {
|
|
124
|
-
try {
|
|
125
|
-
const response = await this.checkPort(port);
|
|
126
|
-
if (response) {
|
|
127
|
-
return port;
|
|
128
|
-
}
|
|
129
|
-
} catch (error) {
|
|
130
|
-
errors.push(`tried port ${port} with error ${error?.message}`);
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
if (attempt < this.retryAttempts - 1) {
|
|
134
|
-
await new Promise((resolve) => setTimeout(resolve, 1e3));
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
throw new Error(
|
|
138
|
-
`No editor server found in port range ${startPort}-${endPort}:
|
|
139
|
-
${errors.join("\n")}`
|
|
140
|
-
);
|
|
141
|
-
}
|
|
142
|
-
async checkPort(port) {
|
|
143
|
-
return new Promise((resolve, reject) => {
|
|
144
|
-
const timeout = setTimeout(() => {
|
|
145
|
-
reject(new Error(`Port ${port} timeout`));
|
|
146
|
-
}, this.scanTimeout);
|
|
147
|
-
const controller = new AbortController();
|
|
148
|
-
fetch(`http://localhost:${port}/editor-connect?id=${this.editorId}`, {
|
|
149
|
-
signal: controller.signal
|
|
150
|
-
}).then((response) => {
|
|
151
|
-
clearTimeout(timeout);
|
|
152
|
-
if (response.ok) {
|
|
153
|
-
return response.json();
|
|
154
|
-
}
|
|
155
|
-
throw new Error(`HTTP ${response.status}`);
|
|
156
|
-
}).then((data) => {
|
|
157
|
-
if (data.status === "init" || data.id === this.editorId && data.status === "match") {
|
|
158
|
-
resolve(data);
|
|
159
|
-
} else {
|
|
160
|
-
if (data.id)
|
|
161
|
-
reject(
|
|
162
|
-
new Error(
|
|
163
|
-
`failed to match on editorId ${this.editorId} !== port's ${data.id}`
|
|
164
|
-
)
|
|
165
|
-
);
|
|
166
|
-
else
|
|
167
|
-
reject(new Error(`failed to match on editorId ${this.editorId}`));
|
|
168
|
-
}
|
|
169
|
-
}).catch((error) => {
|
|
170
|
-
clearTimeout(timeout);
|
|
171
|
-
reject(error);
|
|
172
|
-
});
|
|
173
|
-
});
|
|
174
|
-
}
|
|
175
|
-
async establishConnection(port) {
|
|
176
|
-
return new Promise((resolve, reject) => {
|
|
177
|
-
this.socket = socket_ioClient.io(`http://localhost:${port}`, {
|
|
178
|
-
timeout: this.scanTimeout,
|
|
179
|
-
forceNew: true
|
|
180
|
-
});
|
|
181
|
-
this.socket.on("connect", () => {
|
|
182
|
-
console.log("Connected to editor server");
|
|
183
|
-
this.setupSocketHandlers();
|
|
184
|
-
resolve();
|
|
185
|
-
});
|
|
186
|
-
this.socket.on("connect_error", (error) => {
|
|
187
|
-
console.error("Connection error:", error);
|
|
188
|
-
reject(error);
|
|
189
|
-
});
|
|
190
|
-
this.socket.on("disconnect", () => {
|
|
191
|
-
console.log("Disconnected from editor server");
|
|
192
|
-
this.updateConnectionState("disconnected");
|
|
193
|
-
});
|
|
194
|
-
});
|
|
195
|
-
}
|
|
196
|
-
setupSocketHandlers() {
|
|
197
|
-
if (!this.socket)
|
|
198
|
-
return;
|
|
199
|
-
this.socket.on("protocol-response", (response) => {
|
|
200
|
-
const pendingRequest = this.pendingRequests.get(response.id);
|
|
201
|
-
if (pendingRequest) {
|
|
202
|
-
this.pendingRequests.delete(response.id);
|
|
203
|
-
if (response.payload.success) {
|
|
204
|
-
pendingRequest.resolve(response.payload);
|
|
205
|
-
} else {
|
|
206
|
-
pendingRequest.reject(new Error(response.payload.error || "Unknown error"));
|
|
207
|
-
}
|
|
208
|
-
}
|
|
209
|
-
});
|
|
210
|
-
}
|
|
211
|
-
async attemptReconnect() {
|
|
212
|
-
if (this.isManualDisconnect || this.isConnecting) {
|
|
213
|
-
return;
|
|
214
|
-
}
|
|
215
|
-
console.log("Attempting to reconnect...");
|
|
216
|
-
try {
|
|
217
|
-
await this.connect();
|
|
218
|
-
console.log("Reconnected successfully");
|
|
219
|
-
} catch (error) {
|
|
220
|
-
console.error("Reconnection failed:", error);
|
|
221
|
-
this.scheduleReconnect();
|
|
222
|
-
}
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
function createConnectionManager(options) {
|
|
226
|
-
return new ConnectionManager(options);
|
|
227
|
-
}
|
|
228
|
-
class EditorClient {
|
|
229
|
-
constructor(connectionManager) {
|
|
230
|
-
__publicField(this, "connectionManager");
|
|
231
|
-
this.connectionManager = connectionManager;
|
|
232
|
-
}
|
|
233
|
-
// Connection management - delegate to ConnectionManager
|
|
234
|
-
async connect() {
|
|
235
|
-
return this.connectionManager.connect();
|
|
236
|
-
}
|
|
237
|
-
async disconnect() {
|
|
238
|
-
return this.connectionManager.disconnect();
|
|
239
|
-
}
|
|
240
|
-
getConnectionState() {
|
|
241
|
-
return this.connectionManager.getConnectionState();
|
|
242
|
-
}
|
|
243
|
-
onConnectionStateChange(callback) {
|
|
244
|
-
return this.connectionManager.onConnectionStateChange(callback);
|
|
245
|
-
}
|
|
246
|
-
// EditorProtocol implementation - delegate to ConnectionManager
|
|
247
|
-
async publish(params) {
|
|
248
|
-
return this.connectionManager.sendMessage(params);
|
|
249
|
-
}
|
|
250
|
-
async saveImage(params) {
|
|
251
|
-
return this.connectionManager.sendMessage(params);
|
|
252
|
-
}
|
|
253
|
-
async hasImage(params) {
|
|
254
|
-
return this.connectionManager.sendMessage(params);
|
|
255
|
-
}
|
|
256
|
-
async send(params) {
|
|
257
|
-
return this.connectionManager.sendMessage(params);
|
|
258
|
-
}
|
|
259
|
-
// Get access to the underlying connection manager if needed
|
|
260
|
-
getConnectionManager() {
|
|
261
|
-
return this.connectionManager;
|
|
262
|
-
}
|
|
263
|
-
}
|
|
264
|
-
function createEditorClient(options) {
|
|
265
|
-
const connectionManager = new ConnectionManager(options);
|
|
266
|
-
return new EditorClient(connectionManager);
|
|
267
|
-
}
|
|
268
|
-
function createEditorClientWithConnectionManager(connectionManager) {
|
|
269
|
-
return new EditorClient(connectionManager);
|
|
270
|
-
}
|
|
271
|
-
exports.ConnectionManager = ConnectionManager;
|
|
272
|
-
exports.EditorClient = EditorClient;
|
|
273
|
-
exports.createConnectionManager = createConnectionManager;
|
|
274
|
-
exports.createEditorClient = createEditorClient;
|
|
275
|
-
exports.createEditorClientWithConnectionManager = createEditorClientWithConnectionManager;
|