@pluv/client 2.3.1 → 3.1.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/PluvClient.ts CHANGED
@@ -1,10 +1,5 @@
1
- import type {
2
- AbstractCrdtDocFactory,
3
- CrdtType,
4
- InferStorage,
5
- NoopCrdtDocFactory,
6
- } from "@pluv/crdt";
7
- import type { InputZodLike, IOLike, JsonObject } from "@pluv/types";
1
+ import type { AbstractCrdtDocFactory, InferStorage, NoopCrdtDocFactory } from "@pluv/crdt";
2
+ import type { InferIOCrdtKind, InputZodLike, IOLike, JsonObject } from "@pluv/types";
8
3
  import { MAX_PRESENCE_SIZE_BYTES } from "./constants";
9
4
  import type { InferCallback } from "./infer";
10
5
  import { PluvProcedure } from "./PluvProcedure";
@@ -23,13 +18,12 @@ import { PluvRouter } from "./PluvRouter";
23
18
  import type { PluvClientLimits, PublicKey, WithMetadata } from "./types";
24
19
 
25
20
  export type PluvClientOptions<
26
- TIO extends IOLike<any, any>,
21
+ TIO extends IOLike<any, any, any>,
27
22
  TPresence extends Record<string, any>,
28
- TCrdt extends AbstractCrdtDocFactory<any, any>,
23
+ TCrdt extends InferIOCrdtKind<TIO>,
29
24
  TMetadata extends JsonObject,
30
25
  > = RoomEndpoints<TIO, TMetadata> & {
31
26
  debug?: boolean;
32
- initialStorage?: TCrdt;
33
27
  /**
34
28
  * @description Configurable limits defined for client-side validation. You should only set
35
29
  * this if you control the server and have changed the limits there.
@@ -39,10 +33,12 @@ export type PluvClientOptions<
39
33
  presence?: InputZodLike<TPresence>;
40
34
  publicKey?: PublicKey<TMetadata>;
41
35
  types: InferCallback<TIO>;
42
- };
36
+ } & (InferIOCrdtKind<TIO> extends NoopCrdtDocFactory
37
+ ? { initialStorage?: "[ERROR]: Must provide crdt to createIO to use storage" }
38
+ : { initialStorage?: TCrdt });
43
39
 
44
40
  export type CreateRoomOptions<
45
- TIO extends IOLike<any, any>,
41
+ TIO extends IOLike<any, any, any>,
46
42
  TPresence extends Record<string, any>,
47
43
  TCrdt extends AbstractCrdtDocFactory<any, any>,
48
44
  TMetadata extends JsonObject,
@@ -62,9 +58,9 @@ export type EnterRoomParams<TMetadata extends JsonObject = {}> = keyof TMetadata
62
58
  : [WithMetadata<TMetadata>];
63
59
 
64
60
  export class PluvClient<
65
- TIO extends IOLike<any, any>,
61
+ TIO extends IOLike<any, any, any>,
66
62
  TPresence extends Record<string, any> = {},
67
- TCrdt extends AbstractCrdtDocFactory<any, any> = NoopCrdtDocFactory,
63
+ TCrdt extends InferIOCrdtKind<TIO> = InferIOCrdtKind<TIO>,
68
64
  TMetadata extends JsonObject = {},
69
65
  > {
70
66
  public readonly metadata?: InputZodLike<TMetadata>;
@@ -104,7 +100,7 @@ export class PluvClient<
104
100
 
105
101
  this._authEndpoint = authEndpoint as AuthEndpoint<TMetadata>;
106
102
  this._debug = debug;
107
- this._initialStorage = initialStorage;
103
+ this._initialStorage = initialStorage as TCrdt;
108
104
  this._limits = {
109
105
  presenceMaxSize: MAX_PRESENCE_SIZE_BYTES,
110
106
  ...limits,
package/src/PluvRoom.ts CHANGED
@@ -134,7 +134,7 @@ export type WsEndpoint<TMetadata extends JsonObject> =
134
134
 
135
135
  type FetchOptions = { url: string; options?: RequestInit };
136
136
 
137
- export type RoomEndpoints<TIO extends IOLike<any, any>, TMetadata extends JsonObject> = {
137
+ export type RoomEndpoints<TIO extends IOLike<any, any, any>, TMetadata extends JsonObject> = {
138
138
  wsEndpoint?: WsEndpoint<TMetadata>;
139
139
  } & (InferIOAuthorizeUser<InferIOAuthorize<TIO>> extends BaseUser
140
140
  ? { authEndpoint: AuthEndpoint<TMetadata> }
@@ -204,7 +204,7 @@ export type RoomConfig<
204
204
  >;
205
205
 
206
206
  export class PluvRoom<
207
- TIO extends IOLike<any, any>,
207
+ TIO extends IOLike<any, any, any>,
208
208
  TMetadata extends JsonObject = {},
209
209
  TPresence extends Record<string, any> = {},
210
210
  TCrdt extends AbstractCrdtDocFactory<any, any> = NoopCrdtDocFactory,
@@ -311,13 +311,6 @@ export class PluvRoom<
311
311
  this._crdtManager = new CrdtManager<TCrdt>({ initialStorage });
312
312
  }
313
313
 
314
- /**
315
- * @deprecated To be removed in v3. Use `getStorageLoaded` instead.
316
- */
317
- public get storageLoaded(): boolean {
318
- return this.getStorageLoaded();
319
- }
320
-
321
314
  public get webSocket(): WebSocket | null {
322
315
  return this._state.webSocket;
323
316
  }
@@ -493,23 +486,6 @@ export class PluvRoom<
493
486
  this._stateNotifier.subjects["my-presence"].next(null);
494
487
  }
495
488
 
496
- /**
497
- * @deprecated To be removed in v3. Use PluvRoom.subscribe.event instead
498
- */
499
- public event = new Proxy(
500
- <TEvent extends keyof InferIOOutput<MergeEvents<TEvents, TIO>>>(
501
- event: TEvent,
502
- callback: EventNotifierSubscriptionCallback<MergeEvents<TEvents, TIO>, any>,
503
- ): (() => void) => this._eventNotifier.subscribe(event, callback),
504
- {
505
- get(fn, prop) {
506
- return (
507
- callback: EventNotifierSubscriptionCallback<MergeEvents<TEvents, TIO>, any>,
508
- ): (() => void) => fn(prop as any, callback);
509
- },
510
- },
511
- ) as EventProxy<TIO, TEvents>;
512
-
513
489
  public getConnection = (): WebSocketConnection => {
514
490
  // Create a read-only clone of the connection state
515
491
  return Object.freeze(JSON.parse(JSON.stringify(this._state.connection)));
@@ -567,61 +543,10 @@ export class PluvRoom<
567
543
  );
568
544
  };
569
545
 
570
- /**
571
- * @deprecated To be removed in v3. Use PluvRoom.subscribe.other instead
572
- */
573
- public other = (
574
- connectionId: string,
575
- callback: OtherSubscriptionCallback<TIO, TPresence>,
576
- ): (() => void) => {
577
- const clientId = this._usersManager.getClientId(connectionId);
578
-
579
- if (!clientId) return () => undefined;
580
-
581
- return this._usersNotifier.subscribeOther(clientId, callback);
582
- };
583
-
584
546
  public redo = (): void => {
585
547
  this._crdtManager.doc.redo();
586
548
  };
587
549
 
588
- /**
589
- * @deprecated To be removed in v3. Use PluvRoom.subscribe.storage instead
590
- */
591
- public storage = new Proxy(
592
- <TKey extends keyof InferStorage<TCrdt>>(
593
- key: TKey,
594
- callback: StorageSubscriptionCallback<InferStorage<TCrdt>, TKey>,
595
- ): (() => void) => this._crdtNotifier.subscribe(key, callback),
596
- {
597
- get: (fn, prop) => {
598
- type _Storage = InferStorage<TCrdt>;
599
-
600
- if (!!prop) {
601
- return (callback: StorageRootSubscriptionCallback<_Storage>) => {
602
- return this._crdtNotifier.subcribeRoot(callback);
603
- };
604
- }
605
-
606
- return (callback: StorageSubscriptionCallback<_Storage, keyof _Storage>) => {
607
- return fn(prop as keyof InferStorage<TCrdt>, callback);
608
- };
609
- },
610
- },
611
- ) as StorageProxy<InferStorage<TCrdt>>;
612
-
613
- /**
614
- * @deprecated To be removed in v3. Use PluvRoom.subscribe.storage instead
615
- * @description Subscribes to the root storage object (serialized)
616
- */
617
- public storageRoot = (
618
- callback: (value: {
619
- [P in keyof InferStorage<TCrdt>]: InferCrdtJson<InferStorage<TCrdt>[P]>;
620
- }) => void,
621
- ): (() => void) => {
622
- return this._crdtNotifier.subcribeRoot(callback);
623
- };
624
-
625
550
  public subscribe = new Proxy(
626
551
  <TSubject extends keyof StateNotifierSubjects<TIO, TPresence>>(
627
552
  name: TSubject,
@@ -659,9 +584,9 @@ export class PluvRoom<
659
584
  };
660
585
  }
661
586
 
662
- if (prop === "event") return this.event;
663
- if (prop === "other") return this.other;
664
- if (prop === "storage") return this.storage;
587
+ if (prop === "event") return this._event;
588
+ if (prop === "other") return this._other;
589
+ if (prop === "storage") return this._storage;
665
590
  },
666
591
  },
667
592
  ) as SubscribeProxy<TIO, TPresence, InferStorage<TCrdt>, TEvents>;
@@ -816,6 +741,20 @@ export class PluvRoom<
816
741
  this._crdtNotifier.rootSubject.next(storageRoot);
817
742
  }
818
743
 
744
+ private _event = new Proxy(
745
+ <TEvent extends keyof InferIOOutput<MergeEvents<TEvents, TIO>>>(
746
+ event: TEvent,
747
+ callback: EventNotifierSubscriptionCallback<MergeEvents<TEvents, TIO>, any>,
748
+ ): (() => void) => this._eventNotifier.subscribe(event, callback),
749
+ {
750
+ get(fn, prop) {
751
+ return (
752
+ callback: EventNotifierSubscriptionCallback<MergeEvents<TEvents, TIO>, any>,
753
+ ): (() => void) => fn(prop as any, callback);
754
+ },
755
+ },
756
+ ) as EventProxy<TIO, TEvents>;
757
+
819
758
  private _flattenStorageStore = debounce(
820
759
  async (): Promise<void> => {
821
760
  const shouldFlatten = await this._storageStore.getShouldFlatten();
@@ -1497,6 +1436,17 @@ export class PluvRoom<
1497
1436
  return await this._onVisibilityChange();
1498
1437
  }
1499
1438
 
1439
+ private _other = (
1440
+ connectionId: string,
1441
+ callback: OtherSubscriptionCallback<TIO, TPresence>,
1442
+ ): (() => void) => {
1443
+ const clientId = this._usersManager.getClientId(connectionId);
1444
+
1445
+ if (!clientId) return () => undefined;
1446
+
1447
+ return this._usersNotifier.subscribeOther(clientId, callback);
1448
+ };
1449
+
1500
1450
  private _parseMessage(message: { data: string | ArrayBuffer }): IOEventMessage<TIO> | null {
1501
1451
  /**
1502
1452
  * !HACK
@@ -1597,6 +1547,28 @@ export class PluvRoom<
1597
1547
  return parsed;
1598
1548
  }
1599
1549
 
1550
+ private _storage = new Proxy(
1551
+ <TKey extends keyof InferStorage<TCrdt>>(
1552
+ key: TKey,
1553
+ callback: StorageSubscriptionCallback<InferStorage<TCrdt>, TKey>,
1554
+ ): (() => void) => this._crdtNotifier.subscribe(key, callback),
1555
+ {
1556
+ get: (fn, prop) => {
1557
+ type _Storage = InferStorage<TCrdt>;
1558
+
1559
+ if (!!prop) {
1560
+ return (callback: StorageRootSubscriptionCallback<_Storage>) => {
1561
+ return this._crdtNotifier.subcribeRoot(callback);
1562
+ };
1563
+ }
1564
+
1565
+ return (callback: StorageSubscriptionCallback<_Storage, keyof _Storage>) => {
1566
+ return fn(prop as keyof InferStorage<TCrdt>, callback);
1567
+ };
1568
+ },
1569
+ },
1570
+ ) as StorageProxy<InferStorage<TCrdt>>;
1571
+
1600
1572
  private _updateState(
1601
1573
  updater: (oldState: WebSocketState<TIO>) => WebSocketState<TIO>,
1602
1574
  ): WebSocketState<TIO> {
@@ -1,12 +1,11 @@
1
- import type { AbstractCrdtDocFactory, NoopCrdtDocFactory } from "@pluv/crdt";
2
- import type { IOLike, JsonObject } from "@pluv/types";
1
+ import type { InferIOCrdtKind, IOLike, JsonObject } from "@pluv/types";
3
2
  import type { PluvClientOptions } from "./PluvClient";
4
3
  import { PluvClient } from "./PluvClient";
5
4
 
6
5
  export const createClient = <
7
- TIO extends IOLike<any, any>,
6
+ TIO extends IOLike<any, any, any>,
8
7
  TPresence extends Record<string, any> = {},
9
- TCrdt extends AbstractCrdtDocFactory<any, any> = NoopCrdtDocFactory,
8
+ TCrdt extends InferIOCrdtKind<TIO> = InferIOCrdtKind<TIO>,
10
9
  TMetadata extends JsonObject = {},
11
10
  >(
12
11
  options: PluvClientOptions<TIO, TPresence, TCrdt, TMetadata>,
package/src/infer.ts CHANGED
@@ -1,10 +1,10 @@
1
1
  import type { IOLike } from "@pluv/types";
2
2
  import type { identity } from "./utils";
3
3
 
4
- export type InferCallback<TIO extends IOLike<any, any>> = (i: typeof identity) => {
4
+ export type InferCallback<TIO extends IOLike<any, any, any>> = (i: typeof identity) => {
5
5
  io: (io: TIO) => TIO;
6
6
  };
7
7
 
8
- export const infer = <TIO extends IOLike<any, any>>(
8
+ export const infer = <TIO extends IOLike<any, any, any>>(
9
9
  callback: InferCallback<TIO>,
10
10
  ): InferCallback<TIO> => callback;