@pluv/client 0.17.2 → 0.18.0

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/src/PluvRoom.ts CHANGED
@@ -1,8 +1,4 @@
1
- import type {
2
- AbstractCrdtDoc,
3
- AbstractCrdtType,
4
- InferCrdtStorageJson,
5
- } from "@pluv/crdt";
1
+ import type { AbstractCrdtDoc, AbstractCrdtType, InferCrdtStorageJson } from "@pluv/crdt";
6
2
  import type {
7
3
  BaseIOEventRecord,
8
4
  EventMessage,
@@ -17,7 +13,7 @@ import type {
17
13
  JsonObject,
18
14
  } from "@pluv/types";
19
15
  import { AbstractRoom } from "./AbstractRoom";
20
- import { AbstractStorageStore } from "./AbstractStorageStore";
16
+ import type { AbstractStorageStore } from "./AbstractStorageStore";
21
17
  import type { CrdtManagerOptions } from "./CrdtManager";
22
18
  import { CrdtManager } from "./CrdtManager";
23
19
  import { CrdtNotifier } from "./CrdtNotifier";
@@ -25,21 +21,12 @@ import type { EventNotifierSubscriptionCallback } from "./EventNotifier";
25
21
  import { EventNotifier } from "./EventNotifier";
26
22
  import type { OtherNotifierSubscriptionCallback } from "./OtherNotifier";
27
23
  import { OtherNotifier } from "./OtherNotifier";
28
- import type {
29
- StateNotifierSubjects,
30
- SubscriptionCallback,
31
- } from "./StateNotifier";
24
+ import type { StateNotifierSubjects, SubscriptionCallback } from "./StateNotifier";
32
25
  import { StateNotifier } from "./StateNotifier";
33
26
  import { StorageStore } from "./StorageStore";
34
27
  import type { UsersManagerConfig } from "./UsersManager";
35
28
  import { UsersManager } from "./UsersManager";
36
- import type {
37
- AuthorizationState,
38
- InternalSubscriptions,
39
- UserInfo,
40
- WebSocketConnection,
41
- WebSocketState,
42
- } from "./types";
29
+ import type { AuthorizationState, InternalSubscriptions, UserInfo, WebSocketConnection, WebSocketState } from "./types";
43
30
  import { ConnectionState } from "./types";
44
31
  import { debounce } from "./utils";
45
32
 
@@ -89,10 +76,7 @@ interface TimeoutIds {
89
76
  reconnect: number | null;
90
77
  }
91
78
 
92
- export type AuthEndpoint =
93
- | string
94
- | ((room: string) => string | FetchOptions)
95
- | true;
79
+ export type AuthEndpoint = string | ((room: string) => string | FetchOptions) | true;
96
80
  export type WsEndpoint = string | ((room: string) => string);
97
81
 
98
82
  type FetchOptions = { url: string; options?: RequestInit };
@@ -111,9 +95,7 @@ export type PluvRoomAddon<
111
95
  TIO extends IOLike = IOLike,
112
96
  TPresence extends JsonObject = {},
113
97
  TStorage extends Record<string, AbstractCrdtType<any, any>> = {},
114
- > = (
115
- input: PluvRoomAddonInput<TIO, TPresence, TStorage>,
116
- ) => Partial<PluvRoomAddonResult>;
98
+ > = (input: PluvRoomAddonInput<TIO, TPresence, TStorage>) => Partial<PluvRoomAddonResult>;
117
99
 
118
100
  export interface PluvRoomAddonInput<
119
101
  TIO extends IOLike = IOLike,
@@ -220,10 +202,7 @@ export class PluvRoom<
220
202
  this._listeners = {
221
203
  onAuthorizationFail: (error) => {
222
204
  this._clearTimeout(this._timeouts.reconnect);
223
- this._timeouts.reconnect = setTimeout(
224
- this._reconnect.bind(this),
225
- RECONNECT_TIMEOUT_MS,
226
- );
205
+ this._timeouts.reconnect = setTimeout(this._reconnect.bind(this), RECONNECT_TIMEOUT_MS);
227
206
 
228
207
  onAuthorizationFail?.(error);
229
208
  },
@@ -247,17 +226,25 @@ export class PluvRoom<
247
226
  return this._state.webSocket;
248
227
  }
249
228
 
250
- public broadcast<TEvent extends keyof InferIOInput<TIO>>(
251
- event: TEvent,
252
- data: Id<InferIOInput<TIO>[TEvent]>,
253
- ): void {
254
- if (!this._state.webSocket) return;
255
- if (this._state.connection.state !== ConnectionState.Open) return;
229
+ public broadcast = new Proxy(
230
+ <TEvent extends keyof InferIOInput<TIO>>(event: TEvent, data: Id<InferIOInput<TIO>[TEvent]>): void => {
231
+ if (!this._state.webSocket) return;
232
+ if (this._state.connection.state !== ConnectionState.Open) return;
256
233
 
257
- const type = event.toString();
234
+ const type = event.toString();
258
235
 
259
- this._sendMessage({ data, type });
260
- }
236
+ this._sendMessage({ data, type });
237
+ },
238
+ {
239
+ get(fn, prop) {
240
+ return (data: Id<InferIOInput<TIO>[any]>): void => {
241
+ return fn(prop, data);
242
+ };
243
+ },
244
+ },
245
+ ) as (<TEvent extends keyof InferIOInput<TIO>>(event: TEvent, data: Id<InferIOInput<TIO>[TEvent]>) => void) & {
246
+ [event in keyof InferIOInput<TIO>]: (data: Id<InferIOInput<TIO>[event]>) => void;
247
+ };
261
248
 
262
249
  public canRedo = (): boolean => {
263
250
  return !!this._crdtManager.doc.canRedo();
@@ -272,10 +259,9 @@ export class PluvRoom<
272
259
  throw new Error("Must provide an wsEndpoint.");
273
260
  }
274
261
 
275
- const canConnect = [
276
- ConnectionState.Closed,
277
- ConnectionState.Untouched,
278
- ].some((state) => this._state.connection.state === state);
262
+ const canConnect = [ConnectionState.Closed, ConnectionState.Untouched].some(
263
+ (state) => this._state.connection.state === state,
264
+ );
279
265
 
280
266
  if (!canConnect) return;
281
267
 
@@ -298,8 +284,7 @@ export class PluvRoom<
298
284
  try {
299
285
  authToken = await this._getAuthorization(this.id);
300
286
 
301
- authToken &&
302
- url.searchParams.set("token", encodeURIComponent(authToken));
287
+ authToken && url.searchParams.set("token", encodeURIComponent(authToken));
303
288
 
304
289
  webSocket = new WebSocket(url.toString());
305
290
  } catch (err) {
@@ -328,10 +313,9 @@ export class PluvRoom<
328
313
 
329
314
  if (!this._state.webSocket) return;
330
315
 
331
- const canDisconnect = [
332
- ConnectionState.Connecting,
333
- ConnectionState.Open,
334
- ].some((state) => this._state.connection.state === state);
316
+ const canDisconnect = [ConnectionState.Connecting, ConnectionState.Open].some(
317
+ (state) => this._state.connection.state === state,
318
+ );
335
319
 
336
320
  if (!canDisconnect) return;
337
321
 
@@ -346,18 +330,26 @@ export class PluvRoom<
346
330
  this._stateNotifier.subjects["my-presence"].next(null);
347
331
  }
348
332
 
349
- public event = <TEvent extends keyof InferIOOutput<TIO>>(
333
+ public event = new Proxy(
334
+ <TEvent extends keyof InferIOOutput<TIO>>(
335
+ event: TEvent,
336
+ callback: EventNotifierSubscriptionCallback<TIO, TEvent>,
337
+ ): (() => void) => this._eventNotifier.subscribe(event, callback),
338
+ {
339
+ get(fn, prop) {
340
+ return (callback: EventNotifierSubscriptionCallback<TIO, any>): (() => void) => fn(prop, callback);
341
+ },
342
+ },
343
+ ) as (<TEvent extends keyof InferIOOutput<TIO>>(
350
344
  event: TEvent,
351
345
  callback: EventNotifierSubscriptionCallback<TIO, TEvent>,
352
- ): (() => void) => {
353
- return this._eventNotifier.subscribe(event, callback);
346
+ ) => () => void) & {
347
+ [event in keyof InferIOOutput<TIO>]: (callback: EventNotifierSubscriptionCallback<TIO, event>) => () => void;
354
348
  };
355
349
 
356
350
  public getConnection(): WebSocketConnection {
357
351
  // Create a read-only clone of the connection state
358
- return Object.freeze(
359
- JSON.parse(JSON.stringify(this._state.connection)),
360
- );
352
+ return Object.freeze(JSON.parse(JSON.stringify(this._state.connection)));
361
353
  }
362
354
 
363
355
  public getDoc(): AbstractCrdtDoc<TStorage> {
@@ -372,9 +364,7 @@ export class PluvRoom<
372
364
  return this._usersManager.myself;
373
365
  };
374
366
 
375
- public getOther = (
376
- connectionId: string,
377
- ): Id<UserInfo<TIO, TPresence>> | null => {
367
+ public getOther = (connectionId: string): Id<UserInfo<TIO, TPresence>> | null => {
378
368
  return this._usersManager.getOther(connectionId);
379
369
  };
380
370
 
@@ -382,9 +372,7 @@ export class PluvRoom<
382
372
  return this._usersManager.getOthers();
383
373
  };
384
374
 
385
- public getStorage = <TKey extends keyof TStorage>(
386
- key: TKey,
387
- ): TStorage[TKey] | null => {
375
+ public getStorage = <TKey extends keyof TStorage>(key: TKey): TStorage[TKey] | null => {
388
376
  const sharedType = this._crdtManager.get(key);
389
377
 
390
378
  if (typeof sharedType === "undefined") return null;
@@ -392,10 +380,7 @@ export class PluvRoom<
392
380
  return sharedType;
393
381
  };
394
382
 
395
- public other = (
396
- connectionId: string,
397
- callback: OtherNotifierSubscriptionCallback<TIO>,
398
- ): (() => void) => {
383
+ public other = (connectionId: string, callback: OtherNotifierSubscriptionCallback<TIO>): (() => void) => {
399
384
  return this._otherNotifier.subscribe(connectionId, callback);
400
385
  };
401
386
 
@@ -418,19 +403,14 @@ export class PluvRoom<
418
403
  return this._crdtNotifier.subcribeRoot(fn);
419
404
  };
420
405
 
421
- public subscribe = <
422
- TSubject extends keyof StateNotifierSubjects<TIO, TPresence>,
423
- >(
406
+ public subscribe = <TSubject extends keyof StateNotifierSubjects<TIO, TPresence>>(
424
407
  name: TSubject,
425
408
  callback: SubscriptionCallback<TIO, TPresence, TSubject>,
426
409
  ): (() => void) => {
427
410
  return this._stateNotifier.subscribe(name, callback);
428
411
  };
429
412
 
430
- public transact = (
431
- fn: (storage: TStorage) => void,
432
- origin?: string,
433
- ): void => {
413
+ public transact = (fn: (storage: TStorage) => void, origin?: string): void => {
434
414
  const _origin = origin ?? this._state.connection.id;
435
415
 
436
416
  /**
@@ -462,10 +442,7 @@ export class PluvRoom<
462
442
  this._stateNotifier.subjects["my-presence"].next(myPresence);
463
443
  !!myself && this._stateNotifier.subjects["myself"].next(myself);
464
444
 
465
- this.broadcast(
466
- "$UPDATE_PRESENCE" as keyof InferIOInput<TIO>,
467
- { presence } as any,
468
- );
445
+ this.broadcast("$UPDATE_PRESENCE" as keyof InferIOInput<TIO>, { presence } as any);
469
446
  };
470
447
 
471
448
  private async _addToStorageStore(update: string): Promise<void> {
@@ -499,14 +476,8 @@ export class PluvRoom<
499
476
  onVisibilityChange: this._onVisibilityChange.bind(this),
500
477
  };
501
478
 
502
- window.addEventListener(
503
- "online",
504
- this._windowListeners.onNavigatorOnline,
505
- );
506
- document.addEventListener(
507
- "visibilitychange",
508
- this._windowListeners.onVisibilityChange,
509
- );
479
+ window.addEventListener("online", this._windowListeners.onNavigatorOnline);
480
+ document.addEventListener("visibilitychange", this._windowListeners.onVisibilityChange);
510
481
  }
511
482
 
512
483
  private _attachWsListeners(): void {
@@ -519,22 +490,10 @@ export class PluvRoom<
519
490
  onOpen: this._onOpen.bind(this),
520
491
  };
521
492
 
522
- this._state.webSocket.addEventListener(
523
- "close",
524
- this._wsListeners.onClose,
525
- );
526
- this._state.webSocket.addEventListener(
527
- "error",
528
- this._wsListeners.onError,
529
- );
530
- this._state.webSocket.addEventListener(
531
- "message",
532
- this._wsListeners.onMessage,
533
- );
534
- this._state.webSocket.addEventListener(
535
- "open",
536
- this._wsListeners.onOpen,
537
- );
493
+ this._state.webSocket.addEventListener("close", this._wsListeners.onClose);
494
+ this._state.webSocket.addEventListener("error", this._wsListeners.onError);
495
+ this._state.webSocket.addEventListener("message", this._wsListeners.onMessage);
496
+ this._state.webSocket.addEventListener("open", this._wsListeners.onOpen);
538
497
  }
539
498
 
540
499
  private _clearInterval(interval: number | null) {
@@ -574,14 +533,8 @@ export class PluvRoom<
574
533
  if (typeof window === "undefined") return;
575
534
  if (typeof document === "undefined") return;
576
535
 
577
- window.removeEventListener(
578
- "online",
579
- this._windowListeners.onNavigatorOnline,
580
- );
581
- document.removeEventListener(
582
- "visibilitychange",
583
- this._windowListeners.onVisibilityChange,
584
- );
536
+ window.removeEventListener("online", this._windowListeners.onNavigatorOnline);
537
+ document.removeEventListener("visibilitychange", this._windowListeners.onVisibilityChange);
585
538
 
586
539
  this._windowListeners = null;
587
540
  }
@@ -589,22 +542,10 @@ export class PluvRoom<
589
542
  private _detachWsListeners(): void {
590
543
  if (!this._state.webSocket || !this._wsListeners) return;
591
544
 
592
- this._state.webSocket.removeEventListener(
593
- "close",
594
- this._wsListeners.onClose,
595
- );
596
- this._state.webSocket.removeEventListener(
597
- "error",
598
- this._wsListeners.onError,
599
- );
600
- this._state.webSocket.removeEventListener(
601
- "message",
602
- this._wsListeners.onMessage,
603
- );
604
- this._state.webSocket.removeEventListener(
605
- "open",
606
- this._wsListeners.onOpen,
607
- );
545
+ this._state.webSocket.removeEventListener("close", this._wsListeners.onClose);
546
+ this._state.webSocket.removeEventListener("error", this._wsListeners.onError);
547
+ this._state.webSocket.removeEventListener("message", this._wsListeners.onMessage);
548
+ this._state.webSocket.removeEventListener("open", this._wsListeners.onOpen);
608
549
 
609
550
  this._wsListeners = null;
610
551
  }
@@ -676,9 +617,7 @@ export class PluvRoom<
676
617
 
677
618
  const result = this._endpoints.authEndpoint(room);
678
619
 
679
- return typeof result === "string"
680
- ? { url: result, options: {} }
681
- : result;
620
+ return typeof result === "string" ? { url: result, options: {} } : result;
682
621
  }
683
622
 
684
623
  private async _getAuthorization(room: string): Promise<string | null> {
@@ -697,9 +636,7 @@ export class PluvRoom<
697
636
  try {
698
637
  return await res.text().then((text) => text.trim());
699
638
  } catch (err) {
700
- throw new Error(
701
- err instanceof Error ? err.message : "Room is unauthorized",
702
- );
639
+ throw new Error(err instanceof Error ? err.message : "Room is unauthorized");
703
640
  }
704
641
  }
705
642
 
@@ -737,14 +674,9 @@ export class PluvRoom<
737
674
  // Should not reach here
738
675
  if (!this._state.webSocket) throw new Error("Could not find WebSocket");
739
676
 
740
- const data = message.data as BaseIOEventRecord<
741
- InferIOAuthorize<TIO>
742
- >["$PRESENCE_UPDATED"];
677
+ const data = message.data as BaseIOEventRecord<InferIOAuthorize<TIO>>["$PRESENCE_UPDATED"];
743
678
 
744
- this._usersManager.patchPresence(
745
- connectionId,
746
- data.presence as TPresence,
747
- );
679
+ this._usersManager.patchPresence(connectionId, data.presence as TPresence);
748
680
 
749
681
  const myPresence = this._usersManager.myPresence;
750
682
  const myself = this._usersManager.myself ?? null;
@@ -768,9 +700,7 @@ export class PluvRoom<
768
700
  // Should not reach here
769
701
  if (!this._state.webSocket) throw new Error("Could not find WebSocket");
770
702
 
771
- const data = message.data as BaseIOEventRecord<
772
- InferIOAuthorize<TIO>
773
- >["$OTHERS_RECEIVED"];
703
+ const data = message.data as BaseIOEventRecord<InferIOAuthorize<TIO>>["$OTHERS_RECEIVED"];
774
704
 
775
705
  Object.keys(data.others).forEach((connectionId) => {
776
706
  const { presence, user } = data.others[connectionId];
@@ -781,11 +711,7 @@ export class PluvRoom<
781
711
 
782
712
  const other = this._usersManager.getOther(connectionId);
783
713
 
784
- !!presence &&
785
- this._usersManager.patchPresence(
786
- connectionId,
787
- presence as TPresence,
788
- );
714
+ !!presence && this._usersManager.patchPresence(connectionId, presence as TPresence);
789
715
 
790
716
  this._otherNotifier.subject(connectionId).next(other);
791
717
  });
@@ -810,10 +736,7 @@ export class PluvRoom<
810
736
  return oldState;
811
737
  });
812
738
 
813
- this._usersManager.setMyself(
814
- connectionId,
815
- user as Id<InferIOAuthorizeUser<InferIOAuthorize<TIO>>>,
816
- );
739
+ this._usersManager.setMyself(connectionId, user as Id<InferIOAuthorizeUser<InferIOAuthorize<TIO>>>);
817
740
 
818
741
  const presence = this._usersManager.myPresence;
819
742
  const myself = this._usersManager.myself ?? null;
@@ -821,10 +744,7 @@ export class PluvRoom<
821
744
  this._stateNotifier.subjects["my-presence"].next(presence);
822
745
  this._stateNotifier.subjects["myself"].next(myself);
823
746
 
824
- const update =
825
- this._state.connection.count > 1
826
- ? this._crdtManager.doc.getEncodedState() ?? null
827
- : null;
747
+ const update = this._state.connection.count > 1 ? this._crdtManager.doc.getEncodedState() ?? null : null;
828
748
 
829
749
  this._sendMessage({
830
750
  type: "$INITIALIZE_SESSION",
@@ -832,18 +752,14 @@ export class PluvRoom<
832
752
  });
833
753
  }
834
754
 
835
- private async _handleStorageReceivedMessage(
836
- message: IOEventMessage<TIO>,
837
- ): Promise<void> {
755
+ private async _handleStorageReceivedMessage(message: IOEventMessage<TIO>): Promise<void> {
838
756
  const { connectionId } = message;
839
757
 
840
758
  if (!connectionId) return;
841
759
  // Should not reach here
842
760
  if (!this._state.webSocket) throw new Error("Could not find WebSocket");
843
761
 
844
- const data = message.data as BaseIOEventRecord<
845
- InferIOAuthorize<TIO>
846
- >["$STORAGE_RECEIVED"];
762
+ const data = message.data as BaseIOEventRecord<InferIOAuthorize<TIO>>["$STORAGE_RECEIVED"];
847
763
 
848
764
  this._crdtManager.initialize({
849
765
  onInitialized: async (update) => {
@@ -878,9 +794,7 @@ export class PluvRoom<
878
794
  // Should not reach here
879
795
  if (!this._state.webSocket) throw new Error("Could not find WebSocket");
880
796
 
881
- const data = message.data as BaseIOEventRecord<
882
- InferIOAuthorize<TIO>
883
- >[typeof ORIGIN_STORAGE_UPDATED];
797
+ const data = message.data as BaseIOEventRecord<InferIOAuthorize<TIO>>[typeof ORIGIN_STORAGE_UPDATED];
884
798
 
885
799
  if (!this._crdtManager) return;
886
800
 
@@ -917,9 +831,7 @@ export class PluvRoom<
917
831
  if (!this._state.webSocket) throw new Error("Could not find WebSocket");
918
832
  if (!this._usersManager.myself) return;
919
833
 
920
- const data = message.data as BaseIOEventRecord<
921
- InferIOAuthorize<TIO>
922
- >["$USER_JOINED"];
834
+ const data = message.data as BaseIOEventRecord<InferIOAuthorize<TIO>>["$USER_JOINED"];
923
835
 
924
836
  const myself = this._usersManager.myself;
925
837
 
@@ -927,11 +839,7 @@ export class PluvRoom<
927
839
  this._sendMessage({ type: "$GET_OTHERS", data: {} });
928
840
  }
929
841
 
930
- this._usersManager.setUser(
931
- connectionId,
932
- data.user,
933
- data.presence as TPresence,
934
- );
842
+ this._usersManager.setUser(connectionId, data.user, data.presence as TPresence);
935
843
 
936
844
  const other = this._usersManager.getOther(connectionId);
937
845
  const others = this._usersManager.getOthers();
@@ -942,10 +850,7 @@ export class PluvRoom<
942
850
 
943
851
  private _heartbeat(): void {
944
852
  this._clearTimeout(this._timeouts.pong);
945
- this._timeouts.pong = setTimeout(
946
- this._reconnect.bind(this),
947
- PONG_TIMEOUT_MS,
948
- );
853
+ this._timeouts.pong = setTimeout(this._reconnect.bind(this), PONG_TIMEOUT_MS);
949
854
 
950
855
  this._sendMessage({ type: "$PING", data: {} });
951
856
  }
@@ -968,10 +873,7 @@ export class PluvRoom<
968
873
  this._addToStorageStore(event.update);
969
874
  this._emitSharedTypes();
970
875
 
971
- if (
972
- origin === ORIGIN_INITIALIZED ||
973
- origin === ORIGIN_STORAGE_UPDATED
974
- ) {
876
+ if (origin === ORIGIN_INITIALIZED || origin === ORIGIN_STORAGE_UPDATED) {
975
877
  return;
976
878
  }
977
879
 
@@ -989,8 +891,7 @@ export class PluvRoom<
989
891
  }
990
892
 
991
893
  private _onAuthorizationFail(error: unknown): void {
992
- const authError =
993
- error instanceof Error ? error : new Error("Authorization failed");
894
+ const authError = error instanceof Error ? error : new Error("Authorization failed");
994
895
 
995
896
  this._listeners.onAuthorizationFail(authError);
996
897
 
@@ -1040,17 +941,13 @@ export class PluvRoom<
1040
941
  if (!message) return;
1041
942
 
1042
943
  const shouldLog =
1043
- typeof this._debug === "boolean"
1044
- ? this._debug
1045
- : this._debug.output.find((value) => value === message.type);
944
+ typeof this._debug === "boolean" ? this._debug : this._debug.output.find((value) => value === message.type);
1046
945
 
1047
946
  if (shouldLog) {
1048
947
  this._logDebug("WebSocket event received: ", message.type, message);
1049
948
  }
1050
949
 
1051
- this._eventNotifier
1052
- .subject(message.type as keyof InferIOOutput<TIO>)
1053
- .next(message as any);
950
+ this._eventNotifier.subject(message.type as keyof InferIOOutput<TIO>).next(message as any);
1054
951
 
1055
952
  const { connectionId } = message;
1056
953
 
@@ -1105,10 +1002,7 @@ export class PluvRoom<
1105
1002
  });
1106
1003
 
1107
1004
  this._clearInterval(this._intervals.heartbeat);
1108
- this._intervals.heartbeat = setInterval(
1109
- this._heartbeat.bind(this),
1110
- HEARTBEAT_INTERVAL_MS,
1111
- );
1005
+ this._intervals.heartbeat = setInterval(this._heartbeat.bind(this), HEARTBEAT_INTERVAL_MS);
1112
1006
  }
1113
1007
 
1114
1008
  private async _onNavigatorOnline(): Promise<void> {
@@ -1137,9 +1031,7 @@ export class PluvRoom<
1137
1031
  }
1138
1032
  }
1139
1033
 
1140
- private _parseMessage(message: {
1141
- data: string | ArrayBuffer;
1142
- }): IOEventMessage<TIO> | null {
1034
+ private _parseMessage(message: { data: string | ArrayBuffer }): IOEventMessage<TIO> | null {
1143
1035
  /**
1144
1036
  * !HACK
1145
1037
  * @description We'll only handle stringified JSONs for now
@@ -1181,17 +1073,13 @@ export class PluvRoom<
1181
1073
  await this.connect();
1182
1074
  }
1183
1075
 
1184
- private _sendMessage<
1185
- TMessage extends EventMessage<string, any> = EventMessage<string, any>,
1186
- >(data: TMessage): void {
1076
+ private _sendMessage<TMessage extends EventMessage<string, any> = EventMessage<string, any>>(data: TMessage): void {
1187
1077
  const webSocket = this._state.webSocket;
1188
1078
 
1189
1079
  if (webSocket?.readyState !== WebSocket.OPEN) return;
1190
1080
 
1191
1081
  const shouldLog =
1192
- typeof this._debug === "boolean"
1193
- ? this._debug
1194
- : this._debug.input.find((value) => value === data.type);
1082
+ typeof this._debug === "boolean" ? this._debug : this._debug.input.find((value) => value === data.type);
1195
1083
 
1196
1084
  if (shouldLog) {
1197
1085
  this._logDebug("WebSocket event sent: ", data.type, data);
@@ -1200,15 +1088,11 @@ export class PluvRoom<
1200
1088
  webSocket.send(JSON.stringify(data));
1201
1089
  }
1202
1090
 
1203
- private _updateState(
1204
- updater: (oldState: WebSocketState<TIO>) => WebSocketState<TIO>,
1205
- ): WebSocketState<TIO> {
1091
+ private _updateState(updater: (oldState: WebSocketState<TIO>) => WebSocketState<TIO>): WebSocketState<TIO> {
1206
1092
  let authorization: AuthorizationState<TIO>;
1207
1093
 
1208
1094
  try {
1209
- authorization = JSON.parse(
1210
- JSON.stringify(this._state.authorization),
1211
- );
1095
+ authorization = JSON.parse(JSON.stringify(this._state.authorization));
1212
1096
  } catch {
1213
1097
  throw new Error("User is not JSON serializable");
1214
1098
  }
@@ -3,10 +3,7 @@ import type { Subject } from "wonka";
3
3
  import { makeSubject, subscribe } from "wonka";
4
4
  import type { UserInfo, WebSocketState } from "./types";
5
5
 
6
- export interface StateNotifierSubjects<
7
- TIO extends IOLike,
8
- TPresence extends JsonObject,
9
- > {
6
+ export interface StateNotifierSubjects<TIO extends IOLike, TPresence extends JsonObject> {
10
7
  connection: Subject<Id<WebSocketState<TIO>>>;
11
8
  "my-presence": Subject<TPresence | null>;
12
9
  myself: Subject<Readonly<Id<UserInfo<TIO>>> | null>;
@@ -18,12 +15,7 @@ type InferSubjectValue<
18
15
  TIO extends IOLike,
19
16
  TPresence extends JsonObject,
20
17
  TSubject extends keyof StateNotifierSubjects<TIO, TPresence>,
21
- > =
22
- StateNotifierSubjects<TIO, TPresence>[TSubject] extends Subject<
23
- infer IValue
24
- >
25
- ? Id<IValue>
26
- : never;
18
+ > = StateNotifierSubjects<TIO, TPresence>[TSubject] extends Subject<infer IValue> ? Id<IValue> : never;
27
19
 
28
20
  export type SubscriptionCallback<
29
21
  TIO extends IOLike,
@@ -31,10 +23,7 @@ export type SubscriptionCallback<
31
23
  TSubject extends keyof StateNotifierSubjects<TIO, TPresence>,
32
24
  > = (value: InferSubjectValue<TIO, TPresence, TSubject>) => void;
33
25
 
34
- export class StateNotifier<
35
- TIO extends IOLike,
36
- TPresence extends JsonObject = {},
37
- > {
26
+ export class StateNotifier<TIO extends IOLike, TPresence extends JsonObject = {}> {
38
27
  public subjects: StateNotifierSubjects<TIO, TPresence> = {
39
28
  connection: makeSubject<Id<WebSocketState<TIO>>>(),
40
29
  "my-presence": makeSubject<TPresence>(),
@@ -43,9 +32,7 @@ export class StateNotifier<
43
32
  "storage-loaded": makeSubject<true>(),
44
33
  };
45
34
 
46
- public subscribe<
47
- TSubject extends keyof StateNotifierSubjects<TIO, TPresence>,
48
- >(
35
+ public subscribe<TSubject extends keyof StateNotifierSubjects<TIO, TPresence>>(
49
36
  name: TSubject,
50
37
  callback: SubscriptionCallback<TIO, TPresence, TSubject>,
51
38
  ): () => void {
@@ -1,11 +1,4 @@
1
- import type {
2
- Id,
3
- InferIOAuthorize,
4
- InferIOAuthorizeUser,
5
- InputZodLike,
6
- IOLike,
7
- JsonObject,
8
- } from "@pluv/types";
1
+ import type { Id, InferIOAuthorize, InferIOAuthorizeUser, InputZodLike, IOLike, JsonObject } from "@pluv/types";
9
2
  import type { UserInfo } from "./types";
10
3
 
11
4
  export type Presence = Record<string, unknown>;
@@ -15,10 +8,7 @@ export type UsersManagerConfig<TPresence extends JsonObject = {}> = {
15
8
  presence?: InputZodLike<TPresence>;
16
9
  };
17
10
 
18
- export class UsersManager<
19
- TIO extends IOLike,
20
- TPresence extends JsonObject = {},
21
- > {
11
+ export class UsersManager<TIO extends IOLike, TPresence extends JsonObject = {}> {
22
12
  private _initialPresence: TPresence;
23
13
  /**
24
14
  * @description This presence can be updated while the user is not
@@ -60,10 +50,7 @@ export class UsersManager<
60
50
  return Array.from(this._others.values());
61
51
  }
62
52
 
63
- public patchPresence(
64
- connectionId: string,
65
- patch: Partial<TPresence>,
66
- ): void {
53
+ public patchPresence(connectionId: string, patch: Partial<TPresence>): void {
67
54
  if (this._myself?.connectionId === connectionId) {
68
55
  const presence = {
69
56
  ...this._myPresence,
@@ -98,10 +85,7 @@ export class UsersManager<
98
85
  this._others.delete(connectionId);
99
86
  }
100
87
 
101
- public setMyself(
102
- connectionId: string,
103
- user: Id<InferIOAuthorizeUser<InferIOAuthorize<TIO>>>,
104
- ): void {
88
+ public setMyself(connectionId: string, user: Id<InferIOAuthorizeUser<InferIOAuthorize<TIO>>>): void {
105
89
  this._myself = {
106
90
  connectionId,
107
91
  presence: this._initialPresence,