playsocketjs 4.0.0 → 4.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
@@ -214,11 +214,12 @@ Validating an incoming storage update:
214
214
  const server = new PlaySocketServer();
215
215
 
216
216
  server.onEvent("storageUpdateRequested", ({ roomId, clientId, update, storage }) => {
217
+ const { key, type, value, secondValue } = server.getUpdateDetails(update);
218
+
217
219
  // Block updates on all keys except for "players" and "chats"
218
- if (!["players", "chats"].includes(update.key)) return false;
220
+ if (!["players", "chats"].includes(key)) return false;
219
221
 
220
- if (update.key === "chats") {
221
- const { type, value, secondValue } = server.getUpdateDetails(update);
222
+ if (key === "chats") {
222
223
  if (type !== "array-add") return false; // Only allow adding chats
223
224
  if (typeof value !== "string") return false; // Only allow strings
224
225
  }
@@ -315,7 +316,7 @@ The callback signature is `callback(verified, code?, message?)` where `code` ref
315
316
  | `move()` | `clientId: string, roomId: string` | `void` | Move a client that is already in a room to a different room. |
316
317
  | `onEvent()` | `event: string, callback: Function` | `() => void` | Register a server-side event callback. Returns unsubscribe function. |
317
318
  | `getRoomStorage()` | `roomId: string` | `object` | Get a snapshot of the current room storage. |
318
- | `getUpdateDetails()` | `update: object` | `object` | Get the details (`type`, `value` and `secondValue`) of a storage update for building validation logic. |
319
+ | `getUpdateDetails()` | `update: object` | `object` | Get the details (`key`, `type`, `value` and `secondValue`) of a storage update for building validation logic. |
319
320
  | `updateRoomStorage()` | `roomId: string, key: string, type: string, value: any, secondValue?: any` | `void` | Update a key in the shared storage of a room. |
320
321
  | `createRoom()` | `initialStorage?: object, size?: number, host?: string` | `object` | Create a room (returns object containing room ID and state).|
321
322
  | `destroyRoom()` | `roomId: string` | `void` | Destroy a room & kick all participants. |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "playsocketjs",
3
- "version": "4.0.0",
3
+ "version": "4.1.1",
4
4
  "description": "WebSocket wrapper for creating simple multiplayer systems with ease.",
5
5
  "type": "module",
6
6
  "module": "./src/client/client.js",
@@ -562,7 +562,7 @@ export default class PlaySocketServer {
562
562
  /**
563
563
  * Get the operation details from a storage update (e.g. in the "storageUpdateRequested" event)
564
564
  * @param {PropertyUpdate} update - Property update
565
- * @returns {{type: PropertyUpdateType | undefined, value: *, secondValue: *}} - Operation details
565
+ * @returns {{key: string | undefined, type: PropertyUpdateType | undefined, value: *, secondValue: *}} - Operation details
566
566
  */
567
567
  getUpdateDetails(update) {
568
568
  return getUpdateDetails(update);
@@ -436,12 +436,14 @@ export default class CRDTManager {
436
436
  * @returns {*} - Sanitized value
437
437
  */
438
438
  #sanitizeValue(value) {
439
+ if (value === undefined) return null; // Normalize undefined to null to avoid divergence in transport
440
+
439
441
  // Check total serialized size
440
442
  const jsonString = JSON.stringify(value);
441
443
  if (jsonString?.length > 50000) throw new Error("Value too large!"); // 50KB limit
442
444
 
443
445
  if (typeof value === "string") return (value.includes("<") || value.includes(">")) ? value.replace(/[<>]/g, "") : value;
444
- if (Array.isArray(value)) return value.map(item => this.#sanitizeValue(item));
446
+ if (Array.isArray(value)) return Array.from(value, item => this.#sanitizeValue(item));
445
447
  if (value && typeof value === "object") return Object.fromEntries(Object.entries(value).map(([k, v]) => [k, this.#sanitizeValue(v)]));
446
448
  return value;
447
449
  }
@@ -490,9 +492,9 @@ export default class CRDTManager {
490
492
  /**
491
493
  * Get the operation details from a property update
492
494
  * @param {PropertyUpdate} update - Property update
493
- * @returns {{type: PropertyUpdateType | undefined, value: *, secondValue: *}} - Operation details
495
+ * @returns {{key: string | undefined, type: PropertyUpdateType | undefined, value: *, secondValue: *}} - Operation details
494
496
  */
495
497
  export function getUpdateDetails(update) {
496
498
  const data = update?.operation?.data;
497
- return { type: data?.type, value: data?.value, secondValue: data?.secondValue };
499
+ return { key: update?.key, type: data?.type, value: data?.value, secondValue: data?.secondValue };
498
500
  }
@@ -102,9 +102,10 @@ export default class PlaySocketServer {
102
102
  /**
103
103
  * Get the operation details from a storage update (e.g. in the "storageUpdateRequested" event)
104
104
  * @param {PropertyUpdate} update - Property update
105
- * @returns {{type: PropertyUpdateType | undefined, value: *, secondValue: *}} - Operation details
105
+ * @returns {{key: string | undefined, type: PropertyUpdateType | undefined, value: *, secondValue: *}} - Operation details
106
106
  */
107
107
  getUpdateDetails(update: PropertyUpdate): {
108
+ key: string | undefined;
108
109
  type: PropertyUpdateType | undefined;
109
110
  value: any;
110
111
  secondValue: any;
@@ -137,9 +137,10 @@ export default class CRDTManager {
137
137
  /**
138
138
  * Get the operation details from a property update
139
139
  * @param {PropertyUpdate} update - Property update
140
- * @returns {{type: PropertyUpdateType | undefined, value: *, secondValue: *}} - Operation details
140
+ * @returns {{key: string | undefined, type: PropertyUpdateType | undefined, value: *, secondValue: *}} - Operation details
141
141
  */
142
142
  export declare function getUpdateDetails(update: PropertyUpdate): {
143
+ key: string | undefined;
143
144
  type: PropertyUpdateType | undefined;
144
145
  value: any;
145
146
  secondValue: any;