playsocketjs 1.1.13 → 1.2.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/README.md +3 -2
- package/dist/playsocket-client.js +10 -9
- package/dist/playsocket-server.js +26 -10
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -63,10 +63,11 @@ socket.destroy();
|
|
|
63
63
|
### Constructor
|
|
64
64
|
|
|
65
65
|
```javascript
|
|
66
|
-
new PlaySocket(id
|
|
66
|
+
new PlaySocket(id?: string, options: PlaySocketOptions)
|
|
67
67
|
```
|
|
68
68
|
|
|
69
69
|
Creates a new PlaySocket instance with a specified ID and configuration options.
|
|
70
|
+
Note: With PlaySocket, the id can be set to `null` to let the server pick a unique one.
|
|
70
71
|
|
|
71
72
|
#### Configuration options
|
|
72
73
|
- `endpoint`: WebSocket server endpoint (e.g., 'wss://example.com/socket')
|
|
@@ -77,7 +78,7 @@ Creates a new PlaySocket instance with a specified ID and configuration options.
|
|
|
77
78
|
|
|
78
79
|
#### Core
|
|
79
80
|
|
|
80
|
-
- `init()`: Initialize the WebSocket connection – Returns Promise (async)
|
|
81
|
+
- `init()`: Initialize the WebSocket connection – Returns Promise (async) which resolves with the client's id
|
|
81
82
|
- `createRoom(initialStorage?: object, maxSize?: number)`: Create a new room and become host – Returns Promise (async) which resolves with the room id (matches the creator's id)
|
|
82
83
|
- `joinRoom(hostId: string)`: Join an existing room – Returns Promise (async)
|
|
83
84
|
- `destroy()`: Use this to leave a room and close the connection
|
|
@@ -1708,12 +1708,10 @@ function requireCrdtManager () {
|
|
|
1708
1708
|
|
|
1709
1709
|
/**
|
|
1710
1710
|
* Create a new instance
|
|
1711
|
-
* @param {string} replicaId - Choose a uuid (falls back to random uuid)
|
|
1712
1711
|
*/
|
|
1713
|
-
constructor(
|
|
1714
|
-
if (!replicaId) return console.error("No replicaId provided!");
|
|
1712
|
+
constructor(debug) {
|
|
1715
1713
|
if (debug) this.#debug = true;
|
|
1716
|
-
this.#replicaId =
|
|
1714
|
+
this.#replicaId = crypto.randomUUID();
|
|
1717
1715
|
this.#vectorClock.set(this.#replicaId, 0);
|
|
1718
1716
|
}
|
|
1719
1717
|
|
|
@@ -2096,7 +2094,7 @@ class PlaySocket {
|
|
|
2096
2094
|
if (options.endpoint) this.#endpoint = options.endpoint;
|
|
2097
2095
|
if (options.customData) this.#customData = { ...options.customData };
|
|
2098
2096
|
if (options.debug) this.#debug = true; // Enabling extra logging
|
|
2099
|
-
this.#crdtManager = new crdtManagerExports.CRDTManager(this.#
|
|
2097
|
+
this.#crdtManager = new crdtManagerExports.CRDTManager(this.#debug);
|
|
2100
2098
|
}
|
|
2101
2099
|
|
|
2102
2100
|
/**
|
|
@@ -2143,15 +2141,14 @@ class PlaySocket {
|
|
|
2143
2141
|
async init() {
|
|
2144
2142
|
if (this.#initialized) return Promise.reject(new Error("Already initialized"));
|
|
2145
2143
|
if (!this.#endpoint) return Promise.reject(new Error("No websocket endpoint provided"));
|
|
2146
|
-
if (!this.#id) return Promise.reject(new Error("No id provided"));
|
|
2147
2144
|
this.#triggerEvent("status", "Initializing...");
|
|
2148
2145
|
|
|
2149
2146
|
// Connect to WS server
|
|
2150
2147
|
await this.#connect();
|
|
2151
2148
|
|
|
2152
2149
|
// Register with server
|
|
2153
|
-
await Promise.race([
|
|
2154
|
-
new Promise(
|
|
2150
|
+
const id = await Promise.race([
|
|
2151
|
+
new Promise((resolve, reject) => {
|
|
2155
2152
|
this.#pendingRegistration = { resolve, reject }; // Resolve or reject depending on answer to registration msg
|
|
2156
2153
|
|
|
2157
2154
|
// Register with server
|
|
@@ -2165,6 +2162,10 @@ class PlaySocket {
|
|
|
2165
2162
|
]).finally(() => {
|
|
2166
2163
|
this.#pendingRegistration = null;
|
|
2167
2164
|
});
|
|
2165
|
+
|
|
2166
|
+
// If the server sent out an id, store and return that
|
|
2167
|
+
if (id) this.#id = id;
|
|
2168
|
+
return this.#id;
|
|
2168
2169
|
}
|
|
2169
2170
|
|
|
2170
2171
|
/**
|
|
@@ -2273,7 +2274,7 @@ class PlaySocket {
|
|
|
2273
2274
|
if (this.#pendingRegistration) {
|
|
2274
2275
|
this.#sessionToken = message.sessionToken;
|
|
2275
2276
|
this.#initialized = true;
|
|
2276
|
-
this.#pendingRegistration.resolve();
|
|
2277
|
+
this.#pendingRegistration.resolve(message.id);
|
|
2277
2278
|
this.#triggerEvent("status", "Connected to server.");
|
|
2278
2279
|
}
|
|
2279
2280
|
break;
|
|
@@ -1834,12 +1834,10 @@ function requireCrdtManager () {
|
|
|
1834
1834
|
|
|
1835
1835
|
/**
|
|
1836
1836
|
* Create a new instance
|
|
1837
|
-
* @param {string} replicaId - Choose a uuid (falls back to random uuid)
|
|
1838
1837
|
*/
|
|
1839
|
-
constructor(
|
|
1840
|
-
if (!replicaId) return console.error("No replicaId provided!");
|
|
1838
|
+
constructor(debug) {
|
|
1841
1839
|
if (debug) this.#debug = true;
|
|
1842
|
-
this.#replicaId =
|
|
1840
|
+
this.#replicaId = crypto.randomUUID();
|
|
1843
1841
|
this.#vectorClock.set(this.#replicaId, 0);
|
|
1844
1842
|
}
|
|
1845
1843
|
|
|
@@ -2273,17 +2271,35 @@ function requireServer () {
|
|
|
2273
2271
|
|
|
2274
2272
|
switch (data.type) {
|
|
2275
2273
|
case 'register':
|
|
2276
|
-
// Register client ID
|
|
2277
|
-
if (
|
|
2278
|
-
if (this.#clients.get(data.id)) {
|
|
2274
|
+
// Register client ID if provided & check for a duplicate
|
|
2275
|
+
if (data.id && this.#clients.get(data.id)) {
|
|
2279
2276
|
ws.send(encode({ type: 'id_taken' }), { binary: true });
|
|
2280
2277
|
return;
|
|
2281
2278
|
}
|
|
2279
|
+
|
|
2280
|
+
// Generate client ID if none provided
|
|
2281
|
+
if (!data.id) {
|
|
2282
|
+
const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789';
|
|
2283
|
+
const maxAttempts = 50;
|
|
2284
|
+
for (let i = 0; i < maxAttempts; i++) {
|
|
2285
|
+
const id = Array.from({ length: 6 }, () => chars[Math.floor(Math.random() * chars.length)]).join('');
|
|
2286
|
+
if (!this.#clients.get(id)) {
|
|
2287
|
+
data.id = id;
|
|
2288
|
+
break;
|
|
2289
|
+
}
|
|
2290
|
+
}
|
|
2291
|
+
if (!data.id) {
|
|
2292
|
+
ws.send(encode({ type: 'id_taken' }), { binary: true });
|
|
2293
|
+
throw new Error('Failed to generate unique ID!');
|
|
2294
|
+
}
|
|
2295
|
+
}
|
|
2296
|
+
|
|
2297
|
+
|
|
2282
2298
|
ws.clientId = data.id; // Adds the provided id to the ws object as clientId
|
|
2283
2299
|
this.#clients.set(data.id, ws);
|
|
2284
2300
|
const sessionToken = this.#generateSessionToken();
|
|
2285
2301
|
this.#clientTokens.set(data.id, sessionToken); // Token is used when reconnecting to prevent impersonation attacks
|
|
2286
|
-
ws.send(encode({ type: 'registered', sessionToken }), { binary: true });
|
|
2302
|
+
ws.send(encode({ type: 'registered', id: data.id, sessionToken }), { binary: true });
|
|
2287
2303
|
this.#triggerEvent("clientRegistered", data.id, data.customData);
|
|
2288
2304
|
break;
|
|
2289
2305
|
|
|
@@ -2342,7 +2358,7 @@ function requireServer () {
|
|
|
2342
2358
|
participants: [ws.clientId],
|
|
2343
2359
|
host: ws.clientId,
|
|
2344
2360
|
maxSize: data.size || null,
|
|
2345
|
-
crdtManager: new CRDTManager(
|
|
2361
|
+
crdtManager: new CRDTManager(this.#debug)
|
|
2346
2362
|
};
|
|
2347
2363
|
|
|
2348
2364
|
// Load state if provided
|
|
@@ -2432,7 +2448,7 @@ function requireServer () {
|
|
|
2432
2448
|
break;
|
|
2433
2449
|
}
|
|
2434
2450
|
} catch (error) {
|
|
2435
|
-
console.error('Error
|
|
2451
|
+
console.error('Error in message handler:', error);
|
|
2436
2452
|
}
|
|
2437
2453
|
}
|
|
2438
2454
|
|