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 CHANGED
@@ -63,10 +63,11 @@ socket.destroy();
63
63
  ### Constructor
64
64
 
65
65
  ```javascript
66
- new PlaySocket(id: string, options: PlaySocketOptions)
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(replicaId, debug) {
1714
- if (!replicaId) return console.error("No replicaId provided!");
1712
+ constructor(debug) {
1715
1713
  if (debug) this.#debug = true;
1716
- this.#replicaId = 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.#id, this.#debug);
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(async (resolve, reject) => {
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(replicaId, debug) {
1840
- if (!replicaId) return console.error("No replicaId provided!");
1838
+ constructor(debug) {
1841
1839
  if (debug) this.#debug = true;
1842
- this.#replicaId = 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 (!data.id) return;
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(crypto.randomUUID(), this.#debug)
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 processing message:', error);
2451
+ console.error('Error in message handler:', error);
2436
2452
  }
2437
2453
  }
2438
2454
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "playsocketjs",
3
- "version": "1.1.13",
3
+ "version": "1.2.1",
4
4
  "description": "WebSocket wrapper for creating simple multiplayer systems with ease.",
5
5
  "module": "dist/playsocket-client.js",
6
6
  "exports": {