playsocketjs 2.1.0 → 2.1.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
@@ -77,7 +77,7 @@ socket.updateStorage('latestPlayer', 'set', 'Player4'); // Regular synced storag
77
77
  ### Constructor
78
78
 
79
79
  Creates a new PlaySocket instance with a specified ID and configuration options.
80
- The id can be set to `null` to let the server pick a unique one.
80
+ The ID can be set to `null` to let the server pick a unique one.
81
81
 
82
82
  ```javascript
83
83
  new PlaySocket(id?: string, options: PlaySocketOptions)
@@ -90,8 +90,8 @@ new PlaySocket(id?: string, options: PlaySocketOptions)
90
90
 
91
91
  ### Methods
92
92
 
93
- - `init()`: Initialize the WebSocket connection – Returns Promise (async) which resolves with the client's id
94
- - `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)
93
+ - `init()`: Initialize the WebSocket connection – Returns Promise (async) which resolves with the client's ID
94
+ - `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)
95
95
  - `joinRoom(hostId: string)`: Join an existing room – Returns Promise (async)
96
96
  - `destroy()`: Use this to leave a room and close the connection
97
97
  - `updateStorage(key: string, type: 'set' | 'array-add' | 'array-add-unique' | 'array-remove-matching' | 'array-update-matching', value: any, updateValue?: any)`: Update the shared storage. Safely update arrays in storage by adding, removing, or updating items. UpdateValue is only required for the 'array-update-matching' operation type
@@ -103,9 +103,9 @@ new PlaySocket(id?: string, options: PlaySocketOptions)
103
103
  - `error`: Error events (returns error `string`)
104
104
  - `instanceDestroyed`: Destruction event - triggered by manual .destroy() method invocation or by fatal errors and disconnects
105
105
  - `storageUpdated`: Storage state changes (returns storage `object`)
106
- - `hostMigrated`: Host changes (returns the new host's id `string`)
107
- - `clientConnected`: New client connected to the room (returns client-id `string`)
108
- - `clientDisconnected`: Client disconnected from the room (returns client-id `string`, room id (if available) `string`)
106
+ - `hostMigrated`: Host changes (returns the new host's ID `string`)
107
+ - `clientConnected`: New client connected to the room (returns client's ID `string`)
108
+ - `clientDisconnected`: Client disconnected from the room (returns client's ID `string`, room ID (if available) `string`)
109
109
 
110
110
  ### Properties (Read-only)
111
111
 
@@ -209,13 +209,13 @@ Creates a new PlaySocket Server instance with configuration options.
209
209
 
210
210
  #### Event types
211
211
 
212
- - `clientRegistered`: Client registered with the server (returns the client's id `string`, customData `object`)
213
- - `clientDisconnected`: Client disconnected from the server (returns the client's id `string`)
214
- - `clientJoinedRoom`: Client joined a room – note that clients can only leave by disconnecting (returns the client's id `string`, room id `string`)
215
- - `roomCreated`: Client created a room (returns room id `string`)
216
- - `roomDestroyed`: Room was destroyed, this happens when all participants leave (returns room id `string`)
217
- - `roomCreationRequested`: Room creation requested by client (returns `object` containing the client's id `string`, room id `string` and the initialStorage `object`) – if you return an `object` in the callback, it will take that as the initial storage instead
218
- - `storageUpdateRequested`: Room storage property update requested by client (returns `object` containing the client's id `string`, room id `string` and the update `object`) – if you return `false` in the callback, the update will be blocked
212
+ - `clientRegistered`: Client registered with the server (returns the client's ID `string`, customData `object`)
213
+ - `clientDisconnected`: Client disconnected from the server (returns the client's ID `string`)
214
+ - `clientJoinedRoom`: Client joined a room – note that clients can only leave by disconnecting (returns the client's ID `string`, room ID `string`)
215
+ - `roomCreated`: Client created a room (returns room ID `string`)
216
+ - `roomDestroyed`: Room was destroyed, this happens when all participants leave (returns room ID `string`)
217
+ - `roomCreationRequested`: Room creation requested by client (returns `object` containing the client's ID `string`, room ID `string` and the initialStorage `object`) – if you return an `object` in the callback, it will take that as the initial storage instead
218
+ - `storageUpdateRequested`: Room storage property update requested by client (returns `object` containing the client's ID `string`, room ID `string` and the update `object`) – if you return `false` in the callback, the update will be blocked
219
219
 
220
220
  ### Properties (Read-only)
221
221
 
@@ -1687,7 +1687,7 @@ function requireCrdtManager () {
1687
1687
  hasRequiredCrdtManager = 1;
1688
1688
  // Custom conflict-free replicated data type system with vector clocks
1689
1689
 
1690
- const CONSOLE_PREFIX = "CRDT Manager: ";
1690
+ const CONSOLE_PREFIX = "PlaySocket CRDT manager: ";
1691
1691
 
1692
1692
  class CRDTManager {
1693
1693
  // Storage
@@ -1835,50 +1835,53 @@ function requireCrdtManager () {
1835
1835
  const MIN_GC_DELAY = 1000; // Minimum 1s delay between garbage collection runs
1836
1836
  const MIN_AGE_FOR_GC = 5000; // Garbage collect ops that are older than 5s
1837
1837
 
1838
- if (Date.now() - this.#lastGCCheck < MIN_GC_DELAY) return;
1839
- this.#lastGCCheck = Date.now();
1840
-
1841
- for (const [key, operations] of this.#keyOperations.entries()) {
1842
- if (operations?.length < 5) continue; // Min op amount per key for garbage collection to run (otherwise not worth it)
1843
-
1844
- let retainCount = operations.length;
1845
- operations.forEach((op, index) => {
1846
- // Count how many ops, from last to latest, are older than the min-age in a row
1847
- if (op.uuid && this.#opUuidTimestamp.has(op.uuid) && (Date.now() - this.#opUuidTimestamp.get(op.uuid)) > MIN_AGE_FOR_GC) {
1848
- const removeCount = index + 1;
1849
- retainCount = operations.length - removeCount;
1850
- this.#opUuidTimestamp.delete(op.uuid); // Remove from timestamps if set to be deleted
1851
- }
1852
- });
1838
+ try {
1839
+ if (Date.now() - this.#lastGCCheck < MIN_GC_DELAY) return;
1840
+ this.#lastGCCheck = Date.now();
1841
+
1842
+ for (const [key, operations] of this.#keyOperations.entries()) {
1843
+ if (operations?.length < 5) continue; // Min op amount per key for garbage collection to run (otherwise not worth it)
1844
+
1845
+ let retainCount = operations.length;
1846
+ operations.forEach((op, index) => {
1847
+ // Count how many ops, from last to latest, are older than the min-age in a row
1848
+ if (op.uuid && this.#opUuidTimestamp.has(op.uuid) && (Date.now() - this.#opUuidTimestamp.get(op.uuid)) > MIN_AGE_FOR_GC) {
1849
+ const removeCount = index + 1;
1850
+ retainCount = operations.length - removeCount;
1851
+ this.#opUuidTimestamp.delete(op.uuid); // Remove from timestamps if set to be deleted
1852
+ }
1853
+ });
1853
1854
 
1854
- if (retainCount < operations.length) {
1855
- if (this.#debug) console.log(CONSOLE_PREFIX + `Running garbage collection for key ${key} with current operations:`, operations);
1856
- const retainOps = operations.slice(-retainCount); // Newest ops
1857
- const removeOps = operations.slice(0, -retainCount); // Oldest ops (start = idx 0, end = retainCount counted from right side)
1858
- const baselineVectorClock = removeOps[removeOps.length - 1]?.vectorClock || []; // Use the vector clock from the last operation that we remove/overwrite
1859
-
1860
- // Calculate the value at the point where retained operations start
1861
- let baselineValue = null;
1862
- for (const op of removeOps) {
1863
- if (!op.data) continue;
1864
- if (op.data.type.startsWith('array') && !Array.isArray(baselineValue)) baselineValue = []; // Initialize array if required
1865
- baselineValue = this.#handleOperation(
1866
- baselineValue,
1867
- op.data.type,
1868
- op.data.value,
1869
- op.data.updateValue
1870
- );
1855
+ if (retainCount < operations.length) {
1856
+ if (this.#debug) console.log(CONSOLE_PREFIX + `Running garbage collection for key ${key} with current operations:`, operations);
1857
+ const retainOps = operations.slice(-retainCount); // Newest ops
1858
+ const removeOps = operations.slice(0, -retainCount); // Oldest ops (start = idx 0, end = retainCount counted from right side)
1859
+ const baselineVectorClock = removeOps[removeOps.length - 1]?.vectorClock || []; // Use the vector clock from the last operation that we remove/overwrite
1860
+
1861
+ // Calculate the value at the point where retained operations start
1862
+ let baselineValue = null;
1863
+ for (const op of removeOps) {
1864
+ if (!op.data) continue;
1865
+ baselineValue = this.#handleOperation(
1866
+ baselineValue,
1867
+ op.data.type,
1868
+ op.data.value,
1869
+ op.data.updateValue
1870
+ );
1871
+ }
1872
+
1873
+ // Create a compact operation with baseline value and appropriate vector clock
1874
+ const compactOp = this.#createOperation({ type: "set", value: baselineValue }, baselineVectorClock);
1875
+
1876
+ // Debug log
1877
+ if (this.#debug) console.log(CONSOLE_PREFIX + "Operations after garbage collection for this key:", [compactOp, ...retainOps]);
1878
+
1879
+ // Combine compact op with retained operations
1880
+ this.#keyOperations.set(key, [compactOp, ...retainOps]);
1871
1881
  }
1872
-
1873
- // Create a compact operation with baseline value and appropriate vector clock
1874
- const compactOp = this.#createOperation({ type: "set", value: baselineValue }, baselineVectorClock);
1875
-
1876
- // Debug log
1877
- if (this.#debug) console.log(CONSOLE_PREFIX + "Operations after garbage collection for this key:", [compactOp, ...retainOps]);
1878
-
1879
- // Combine compact op with retained operations
1880
- this.#keyOperations.set(key, [compactOp, ...retainOps]);
1881
1882
  }
1883
+ } catch (error) {
1884
+ console.error(CONSOLE_PREFIX + "Error running garbage collection:", error);
1882
1885
  }
1883
1886
  }
1884
1887
 
@@ -1913,7 +1916,6 @@ function requireCrdtManager () {
1913
1916
 
1914
1917
  for (const op of ops) {
1915
1918
  if (!op.data) continue;
1916
- if (op.data.type.startsWith('array') && !Array.isArray(value)) value = []; // Initialize array if required
1917
1919
  value = this.#handleOperation(
1918
1920
  value,
1919
1921
  op.data.type,
@@ -1813,7 +1813,7 @@ function requireCrdtManager () {
1813
1813
  hasRequiredCrdtManager = 1;
1814
1814
  // Custom conflict-free replicated data type system with vector clocks
1815
1815
 
1816
- const CONSOLE_PREFIX = "CRDT Manager: ";
1816
+ const CONSOLE_PREFIX = "PlaySocket CRDT manager: ";
1817
1817
 
1818
1818
  class CRDTManager {
1819
1819
  // Storage
@@ -1961,50 +1961,53 @@ function requireCrdtManager () {
1961
1961
  const MIN_GC_DELAY = 1000; // Minimum 1s delay between garbage collection runs
1962
1962
  const MIN_AGE_FOR_GC = 5000; // Garbage collect ops that are older than 5s
1963
1963
 
1964
- if (Date.now() - this.#lastGCCheck < MIN_GC_DELAY) return;
1965
- this.#lastGCCheck = Date.now();
1966
-
1967
- for (const [key, operations] of this.#keyOperations.entries()) {
1968
- if (operations?.length < 5) continue; // Min op amount per key for garbage collection to run (otherwise not worth it)
1969
-
1970
- let retainCount = operations.length;
1971
- operations.forEach((op, index) => {
1972
- // Count how many ops, from last to latest, are older than the min-age in a row
1973
- if (op.uuid && this.#opUuidTimestamp.has(op.uuid) && (Date.now() - this.#opUuidTimestamp.get(op.uuid)) > MIN_AGE_FOR_GC) {
1974
- const removeCount = index + 1;
1975
- retainCount = operations.length - removeCount;
1976
- this.#opUuidTimestamp.delete(op.uuid); // Remove from timestamps if set to be deleted
1977
- }
1978
- });
1964
+ try {
1965
+ if (Date.now() - this.#lastGCCheck < MIN_GC_DELAY) return;
1966
+ this.#lastGCCheck = Date.now();
1967
+
1968
+ for (const [key, operations] of this.#keyOperations.entries()) {
1969
+ if (operations?.length < 5) continue; // Min op amount per key for garbage collection to run (otherwise not worth it)
1970
+
1971
+ let retainCount = operations.length;
1972
+ operations.forEach((op, index) => {
1973
+ // Count how many ops, from last to latest, are older than the min-age in a row
1974
+ if (op.uuid && this.#opUuidTimestamp.has(op.uuid) && (Date.now() - this.#opUuidTimestamp.get(op.uuid)) > MIN_AGE_FOR_GC) {
1975
+ const removeCount = index + 1;
1976
+ retainCount = operations.length - removeCount;
1977
+ this.#opUuidTimestamp.delete(op.uuid); // Remove from timestamps if set to be deleted
1978
+ }
1979
+ });
1979
1980
 
1980
- if (retainCount < operations.length) {
1981
- if (this.#debug) console.log(CONSOLE_PREFIX + `Running garbage collection for key ${key} with current operations:`, operations);
1982
- const retainOps = operations.slice(-retainCount); // Newest ops
1983
- const removeOps = operations.slice(0, -retainCount); // Oldest ops (start = idx 0, end = retainCount counted from right side)
1984
- const baselineVectorClock = removeOps[removeOps.length - 1]?.vectorClock || []; // Use the vector clock from the last operation that we remove/overwrite
1985
-
1986
- // Calculate the value at the point where retained operations start
1987
- let baselineValue = null;
1988
- for (const op of removeOps) {
1989
- if (!op.data) continue;
1990
- if (op.data.type.startsWith('array') && !Array.isArray(baselineValue)) baselineValue = []; // Initialize array if required
1991
- baselineValue = this.#handleOperation(
1992
- baselineValue,
1993
- op.data.type,
1994
- op.data.value,
1995
- op.data.updateValue
1996
- );
1997
- }
1981
+ if (retainCount < operations.length) {
1982
+ if (this.#debug) console.log(CONSOLE_PREFIX + `Running garbage collection for key ${key} with current operations:`, operations);
1983
+ const retainOps = operations.slice(-retainCount); // Newest ops
1984
+ const removeOps = operations.slice(0, -retainCount); // Oldest ops (start = idx 0, end = retainCount counted from right side)
1985
+ const baselineVectorClock = removeOps[removeOps.length - 1]?.vectorClock || []; // Use the vector clock from the last operation that we remove/overwrite
1986
+
1987
+ // Calculate the value at the point where retained operations start
1988
+ let baselineValue = null;
1989
+ for (const op of removeOps) {
1990
+ if (!op.data) continue;
1991
+ baselineValue = this.#handleOperation(
1992
+ baselineValue,
1993
+ op.data.type,
1994
+ op.data.value,
1995
+ op.data.updateValue
1996
+ );
1997
+ }
1998
1998
 
1999
- // Create a compact operation with baseline value and appropriate vector clock
2000
- const compactOp = this.#createOperation({ type: "set", value: baselineValue }, baselineVectorClock);
1999
+ // Create a compact operation with baseline value and appropriate vector clock
2000
+ const compactOp = this.#createOperation({ type: "set", value: baselineValue }, baselineVectorClock);
2001
2001
 
2002
- // Debug log
2003
- if (this.#debug) console.log(CONSOLE_PREFIX + "Operations after garbage collection for this key:", [compactOp, ...retainOps]);
2002
+ // Debug log
2003
+ if (this.#debug) console.log(CONSOLE_PREFIX + "Operations after garbage collection for this key:", [compactOp, ...retainOps]);
2004
2004
 
2005
- // Combine compact op with retained operations
2006
- this.#keyOperations.set(key, [compactOp, ...retainOps]);
2005
+ // Combine compact op with retained operations
2006
+ this.#keyOperations.set(key, [compactOp, ...retainOps]);
2007
+ }
2007
2008
  }
2009
+ } catch (error) {
2010
+ console.error(CONSOLE_PREFIX + "Error running garbage collection:", error);
2008
2011
  }
2009
2012
  }
2010
2013
 
@@ -2039,7 +2042,6 @@ function requireCrdtManager () {
2039
2042
 
2040
2043
  for (const op of ops) {
2041
2044
  if (!op.data) continue;
2042
- if (op.data.type.startsWith('array') && !Array.isArray(value)) value = []; // Initialize array if required
2043
2045
  value = this.#handleOperation(
2044
2046
  value,
2045
2047
  op.data.type,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "playsocketjs",
3
- "version": "2.1.0",
3
+ "version": "2.1.1",
4
4
  "description": "WebSocket wrapper for creating simple multiplayer systems with ease.",
5
5
  "module": "dist/playsocket-client.js",
6
6
  "exports": {