@pluv/client 0.6.5 → 0.7.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.
@@ -1,5 +1,5 @@
1
1
 
2
- > @pluv/client@0.6.5 build /home/runner/work/pluv/pluv/packages/client
2
+ > @pluv/client@0.7.0 build /home/runner/work/pluv/pluv/packages/client
3
3
  > tsup src/index.ts --format esm,cjs --dts
4
4
 
5
5
  CLI Building entry: src/index.ts
@@ -8,10 +8,10 @@
8
8
  CLI Target: es6
9
9
  ESM Build start
10
10
  CJS Build start
11
- ESM dist/index.mjs 34.41 KB
12
- ESM ⚡️ Build success in 95ms
13
- CJS dist/index.js 35.55 KB
14
- CJS ⚡️ Build success in 96ms
11
+ ESM dist/index.mjs 34.72 KB
12
+ ESM ⚡️ Build success in 138ms
13
+ CJS dist/index.js 35.86 KB
14
+ CJS ⚡️ Build success in 138ms
15
15
  DTS Build start
16
- DTS ⚡️ Build success in 3764ms
17
- DTS dist/index.d.ts 11.68 KB
16
+ DTS ⚡️ Build success in 5111ms
17
+ DTS dist/index.d.ts 11.71 KB
package/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # @pluv/client
2
2
 
3
+ ## 0.7.0
4
+
5
+ ### Minor Changes
6
+
7
+ - ae679a8: updated offline presence to be set when reconnecting to a room
8
+
9
+ ### Patch Changes
10
+
11
+ - 0dd847e: updated storage to be synced when reconnected to the room
12
+ - bb2886b: fixed not reconnecting during heartbeat
13
+ - 3518a83: bumped dependencies
14
+ - Updated dependencies [0dd847e]
15
+ - Updated dependencies [bb2886b]
16
+ - Updated dependencies [ae679a8]
17
+ - Updated dependencies [3518a83]
18
+ - @pluv/crdt-yjs@0.3.7
19
+ - @pluv/types@0.2.0
20
+
3
21
  ## 0.6.5
4
22
 
5
23
  ### Patch Changes
package/dist/index.d.ts CHANGED
@@ -21,6 +21,7 @@ declare enum ConnectionState {
21
21
  Untouched = "Untouched"
22
22
  }
23
23
  interface WebSocketConnection {
24
+ count: number;
24
25
  id: string | null;
25
26
  state: ConnectionState;
26
27
  }
@@ -197,7 +198,7 @@ declare class PluvClient<TIO extends IOLike = IOLike> {
197
198
  private _logDebug;
198
199
  }
199
200
 
200
- declare const createClient: <TIO extends IOLike<_pluv_types.IOAuthorize<any, any>, {}, {}> = IOLike<_pluv_types.IOAuthorize<any, any>, {}, {}>>(options: PluvClientOptions<TIO>) => PluvClient<TIO>;
201
+ declare const createClient: <TIO extends IOLike<_pluv_types.IOAuthorize<any, any>, {}, {}, {}, {}> = IOLike<_pluv_types.IOAuthorize<any, any>, {}, {}, {}, {}>>(options: PluvClientOptions<TIO>) => PluvClient<TIO>;
201
202
 
202
203
  type MockedRoomEvents<TIO extends IOLike> = Partial<{
203
204
  [P in keyof InferIOInput<TIO>]: (data: Id<InferIOInput<TIO>[P]>) => Partial<InferIOOutput<TIO>>;
package/dist/index.js CHANGED
@@ -79,12 +79,12 @@ var import_crdt_yjs = require("@pluv/crdt-yjs");
79
79
  var CrdtManager = class {
80
80
  constructor(options = {}) {
81
81
  const { encodedState, initialStorage } = options;
82
- const doc1 = encodedState ? (0, import_crdt_yjs.doc)().applyUpdate(encodedState) : null;
83
- if (doc1 && !!Object.keys(doc1.toJSON()).length) {
84
- this.doc = doc1;
82
+ const _doc = encodedState ? (0, import_crdt_yjs.doc)().applyUpdate(encodedState) : null;
83
+ if (_doc && !!Object.keys(_doc.toJSON()).length) {
84
+ this.doc = _doc;
85
85
  return;
86
86
  }
87
- doc1 == null ? void 0 : doc1.destroy();
87
+ _doc == null ? void 0 : _doc.destroy();
88
88
  this.doc = (0, import_crdt_yjs.doc)(initialStorage == null ? void 0 : initialStorage());
89
89
  }
90
90
  destroy() {
@@ -257,7 +257,7 @@ var UsersManager = class {
257
257
  return;
258
258
  this._others.set(connectionId, __spreadProps(__spreadValues({}, other), { presence }));
259
259
  }
260
- setUser(connectionId, user) {
260
+ setUser(connectionId, user, presence) {
261
261
  var _a;
262
262
  if (((_a = this._myself) == null ? void 0 : _a.connectionId) === connectionId)
263
263
  return;
@@ -266,7 +266,7 @@ var UsersManager = class {
266
266
  return;
267
267
  this._others.set(connectionId, {
268
268
  connectionId,
269
- presence: this._initialPresence,
269
+ presence: presence != null ? presence : this._initialPresence,
270
270
  user
271
271
  });
272
272
  }
@@ -311,6 +311,7 @@ var PluvRoom = class extends AbstractRoom {
311
311
  user: null
312
312
  },
313
313
  connection: {
314
+ count: 0,
314
315
  id: null,
315
316
  state: "Untouched" /* Untouched */
316
317
  },
@@ -661,13 +662,14 @@ var PluvRoom = class extends AbstractRoom {
661
662
  this._stateNotifier.subjects["others"].next(others);
662
663
  }
663
664
  _handleRegisteredMessage(message) {
664
- var _a;
665
+ var _a, _b, _c;
665
666
  const { connectionId, user } = message;
666
667
  if (!connectionId)
667
668
  return;
668
669
  if (!this._state.webSocket)
669
670
  throw new Error("Could not find WebSocket");
670
671
  this._updateState((oldState) => {
672
+ oldState.connection.count += 1;
671
673
  oldState.connection.id = connectionId;
672
674
  oldState.authorization.user = user;
673
675
  return oldState;
@@ -676,11 +678,15 @@ var PluvRoom = class extends AbstractRoom {
676
678
  connectionId,
677
679
  user
678
680
  );
679
- const myPresence = this._usersManager.myPresence;
681
+ const presence = this._usersManager.myPresence;
680
682
  const myself = (_a = this._usersManager.myself) != null ? _a : null;
681
- this._stateNotifier.subjects["my-presence"].next(myPresence);
683
+ this._stateNotifier.subjects["my-presence"].next(presence);
682
684
  this._stateNotifier.subjects["myself"].next(myself);
683
- this._sendMessage({ type: "$GET_OTHERS", data: {} });
685
+ const update = this._state.connection.count > 1 ? (_c = (_b = this._crdtManager) == null ? void 0 : _b.doc.encodeStateAsUpdate()) != null ? _c : null : null;
686
+ this._sendMessage({
687
+ type: "$INITIALIZE_SESSION",
688
+ data: { presence, update }
689
+ });
684
690
  }
685
691
  _handleStorageReceivedMessage(message) {
686
692
  var _a;
@@ -737,20 +743,21 @@ var PluvRoom = class extends AbstractRoom {
737
743
  if (!this._usersManager.myself)
738
744
  return;
739
745
  const data = message.data;
740
- this._usersManager.setUser(connectionId, data.user);
746
+ const myself = this._usersManager.myself;
747
+ if (myself.connectionId === connectionId) {
748
+ this._sendMessage({ type: "$GET_OTHERS", data: {} });
749
+ }
750
+ this._usersManager.setUser(
751
+ connectionId,
752
+ data.user,
753
+ data.presence
754
+ );
741
755
  const other = this._usersManager.getOther(connectionId);
742
756
  const others = this._usersManager.getOthers();
743
757
  this._otherNotifier.subject(connectionId).next(other);
744
758
  this._stateNotifier.subjects["others"].next(others);
745
759
  }
746
760
  _heartbeat() {
747
- if (!this._state.webSocket)
748
- return;
749
- if (!this._state.connection.id)
750
- return;
751
- if (this._state.webSocket.readyState !== this._state.webSocket.OPEN) {
752
- return;
753
- }
754
761
  this._clearTimeout(this._timeouts.pong);
755
762
  this._timeouts.pong = setTimeout(
756
763
  this._reconnect.bind(this),
@@ -945,7 +952,7 @@ var PluvRoom = class extends AbstractRoom {
945
952
  this._closeWs();
946
953
  this._updateState((oldState) => {
947
954
  oldState.authorization.token = null;
948
- oldState.connection.state = "Unavailable" /* Unavailable */;
955
+ oldState.connection.state = "Closed" /* Closed */;
949
956
  oldState.webSocket = null;
950
957
  return oldState;
951
958
  });
@@ -1062,6 +1069,7 @@ var MockedRoom = class extends AbstractRoom {
1062
1069
  user: null
1063
1070
  },
1064
1071
  connection: {
1072
+ count: 1,
1065
1073
  id: null,
1066
1074
  state: "Untouched" /* Untouched */
1067
1075
  },
package/dist/index.mjs CHANGED
@@ -54,12 +54,12 @@ import { doc } from "@pluv/crdt-yjs";
54
54
  var CrdtManager = class {
55
55
  constructor(options = {}) {
56
56
  const { encodedState, initialStorage } = options;
57
- const doc1 = encodedState ? doc().applyUpdate(encodedState) : null;
58
- if (doc1 && !!Object.keys(doc1.toJSON()).length) {
59
- this.doc = doc1;
57
+ const _doc = encodedState ? doc().applyUpdate(encodedState) : null;
58
+ if (_doc && !!Object.keys(_doc.toJSON()).length) {
59
+ this.doc = _doc;
60
60
  return;
61
61
  }
62
- doc1 == null ? void 0 : doc1.destroy();
62
+ _doc == null ? void 0 : _doc.destroy();
63
63
  this.doc = doc(initialStorage == null ? void 0 : initialStorage());
64
64
  }
65
65
  destroy() {
@@ -232,7 +232,7 @@ var UsersManager = class {
232
232
  return;
233
233
  this._others.set(connectionId, __spreadProps(__spreadValues({}, other), { presence }));
234
234
  }
235
- setUser(connectionId, user) {
235
+ setUser(connectionId, user, presence) {
236
236
  var _a;
237
237
  if (((_a = this._myself) == null ? void 0 : _a.connectionId) === connectionId)
238
238
  return;
@@ -241,7 +241,7 @@ var UsersManager = class {
241
241
  return;
242
242
  this._others.set(connectionId, {
243
243
  connectionId,
244
- presence: this._initialPresence,
244
+ presence: presence != null ? presence : this._initialPresence,
245
245
  user
246
246
  });
247
247
  }
@@ -286,6 +286,7 @@ var PluvRoom = class extends AbstractRoom {
286
286
  user: null
287
287
  },
288
288
  connection: {
289
+ count: 0,
289
290
  id: null,
290
291
  state: "Untouched" /* Untouched */
291
292
  },
@@ -636,13 +637,14 @@ var PluvRoom = class extends AbstractRoom {
636
637
  this._stateNotifier.subjects["others"].next(others);
637
638
  }
638
639
  _handleRegisteredMessage(message) {
639
- var _a;
640
+ var _a, _b, _c;
640
641
  const { connectionId, user } = message;
641
642
  if (!connectionId)
642
643
  return;
643
644
  if (!this._state.webSocket)
644
645
  throw new Error("Could not find WebSocket");
645
646
  this._updateState((oldState) => {
647
+ oldState.connection.count += 1;
646
648
  oldState.connection.id = connectionId;
647
649
  oldState.authorization.user = user;
648
650
  return oldState;
@@ -651,11 +653,15 @@ var PluvRoom = class extends AbstractRoom {
651
653
  connectionId,
652
654
  user
653
655
  );
654
- const myPresence = this._usersManager.myPresence;
656
+ const presence = this._usersManager.myPresence;
655
657
  const myself = (_a = this._usersManager.myself) != null ? _a : null;
656
- this._stateNotifier.subjects["my-presence"].next(myPresence);
658
+ this._stateNotifier.subjects["my-presence"].next(presence);
657
659
  this._stateNotifier.subjects["myself"].next(myself);
658
- this._sendMessage({ type: "$GET_OTHERS", data: {} });
660
+ const update = this._state.connection.count > 1 ? (_c = (_b = this._crdtManager) == null ? void 0 : _b.doc.encodeStateAsUpdate()) != null ? _c : null : null;
661
+ this._sendMessage({
662
+ type: "$INITIALIZE_SESSION",
663
+ data: { presence, update }
664
+ });
659
665
  }
660
666
  _handleStorageReceivedMessage(message) {
661
667
  var _a;
@@ -712,20 +718,21 @@ var PluvRoom = class extends AbstractRoom {
712
718
  if (!this._usersManager.myself)
713
719
  return;
714
720
  const data = message.data;
715
- this._usersManager.setUser(connectionId, data.user);
721
+ const myself = this._usersManager.myself;
722
+ if (myself.connectionId === connectionId) {
723
+ this._sendMessage({ type: "$GET_OTHERS", data: {} });
724
+ }
725
+ this._usersManager.setUser(
726
+ connectionId,
727
+ data.user,
728
+ data.presence
729
+ );
716
730
  const other = this._usersManager.getOther(connectionId);
717
731
  const others = this._usersManager.getOthers();
718
732
  this._otherNotifier.subject(connectionId).next(other);
719
733
  this._stateNotifier.subjects["others"].next(others);
720
734
  }
721
735
  _heartbeat() {
722
- if (!this._state.webSocket)
723
- return;
724
- if (!this._state.connection.id)
725
- return;
726
- if (this._state.webSocket.readyState !== this._state.webSocket.OPEN) {
727
- return;
728
- }
729
736
  this._clearTimeout(this._timeouts.pong);
730
737
  this._timeouts.pong = setTimeout(
731
738
  this._reconnect.bind(this),
@@ -920,7 +927,7 @@ var PluvRoom = class extends AbstractRoom {
920
927
  this._closeWs();
921
928
  this._updateState((oldState) => {
922
929
  oldState.authorization.token = null;
923
- oldState.connection.state = "Unavailable" /* Unavailable */;
930
+ oldState.connection.state = "Closed" /* Closed */;
924
931
  oldState.webSocket = null;
925
932
  return oldState;
926
933
  });
@@ -1037,6 +1044,7 @@ var MockedRoom = class extends AbstractRoom {
1037
1044
  user: null
1038
1045
  },
1039
1046
  connection: {
1047
+ count: 1,
1040
1048
  id: null,
1041
1049
  state: "Untouched" /* Untouched */
1042
1050
  },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pluv/client",
3
- "version": "0.6.5",
3
+ "version": "0.7.0",
4
4
  "description": "@pluv/io frontend client",
5
5
  "author": "leedavidcs",
6
6
  "license": "MIT",
@@ -17,9 +17,9 @@
17
17
  "access": "public"
18
18
  },
19
19
  "dependencies": {
20
- "wonka": "^6.3.1",
21
- "@pluv/crdt-yjs": "^0.3.6",
22
- "@pluv/types": "^0.1.6"
20
+ "wonka": "^6.3.2",
21
+ "@pluv/crdt-yjs": "^0.3.7",
22
+ "@pluv/types": "^0.2.0"
23
23
  },
24
24
  "peerDependencies": {
25
25
  "yjs": "^13.0.0"
@@ -27,9 +27,9 @@
27
27
  "devDependencies": {
28
28
  "tsup": "^6.7.0",
29
29
  "typescript": "^5.0.4",
30
- "yjs": "^13.5.52",
30
+ "yjs": "^13.6.0",
31
31
  "@pluv/tsconfig": "^0.1.6",
32
- "eslint-config-pluv": "^0.1.10"
32
+ "eslint-config-pluv": "^0.1.11"
33
33
  },
34
34
  "scripts": {
35
35
  "build": "tsup src/index.ts --format esm,cjs --dts",
@@ -15,17 +15,17 @@ export class CrdtManager<TStorage extends Record<string, AbstractType<any>>> {
15
15
  constructor(options: CrdtManagerOptions<TStorage> = {}) {
16
16
  const { encodedState, initialStorage } = options;
17
17
 
18
- const doc1 = encodedState
18
+ const _doc = encodedState
19
19
  ? doc<TStorage>().applyUpdate(encodedState)
20
20
  : null;
21
21
 
22
- if (doc1 && !!Object.keys(doc1.toJSON()).length) {
23
- this.doc = doc1;
22
+ if (_doc && !!Object.keys(_doc.toJSON()).length) {
23
+ this.doc = _doc;
24
24
 
25
25
  return;
26
26
  }
27
27
 
28
- doc1?.destroy();
28
+ _doc?.destroy();
29
29
 
30
30
  this.doc = doc<TStorage>(initialStorage?.());
31
31
  }
package/src/MockedRoom.ts CHANGED
@@ -61,6 +61,7 @@ export class MockedRoom<
61
61
  user: null,
62
62
  },
63
63
  connection: {
64
+ count: 1,
64
65
  id: null,
65
66
  state: ConnectionState.Untouched,
66
67
  },
package/src/PluvRoom.ts CHANGED
@@ -134,6 +134,7 @@ export class PluvRoom<
134
134
  user: null,
135
135
  },
136
136
  connection: {
137
+ count: 0,
137
138
  id: null,
138
139
  state: ConnectionState.Untouched,
139
140
  },
@@ -611,6 +612,7 @@ export class PluvRoom<
611
612
  if (!this._state.webSocket) throw new Error("Could not find WebSocket");
612
613
 
613
614
  this._updateState((oldState) => {
615
+ oldState.connection.count += 1;
614
616
  oldState.connection.id = connectionId;
615
617
  oldState.authorization.user = user;
616
618
 
@@ -622,13 +624,21 @@ export class PluvRoom<
622
624
  user as Id<InferIOAuthorizeUser<InferIOAuthorize<TIO>>>
623
625
  );
624
626
 
625
- const myPresence = this._usersManager.myPresence;
627
+ const presence = this._usersManager.myPresence;
626
628
  const myself = this._usersManager.myself ?? null;
627
629
 
628
- this._stateNotifier.subjects["my-presence"].next(myPresence);
630
+ this._stateNotifier.subjects["my-presence"].next(presence);
629
631
  this._stateNotifier.subjects["myself"].next(myself);
630
632
 
631
- this._sendMessage({ type: "$GET_OTHERS", data: {} });
633
+ const update =
634
+ this._state.connection.count > 1
635
+ ? this._crdtManager?.doc.encodeStateAsUpdate() ?? null
636
+ : null;
637
+
638
+ this._sendMessage({
639
+ type: "$INITIALIZE_SESSION",
640
+ data: { presence, update },
641
+ });
632
642
  }
633
643
 
634
644
  private _handleStorageReceivedMessage(message: IOEventMessage<TIO>): void {
@@ -708,7 +718,17 @@ export class PluvRoom<
708
718
  InferIOAuthorize<TIO>
709
719
  >["$USER_JOINED"];
710
720
 
711
- this._usersManager.setUser(connectionId, data.user);
721
+ const myself = this._usersManager.myself;
722
+
723
+ if (myself.connectionId === connectionId) {
724
+ this._sendMessage({ type: "$GET_OTHERS", data: {} });
725
+ }
726
+
727
+ this._usersManager.setUser(
728
+ connectionId,
729
+ data.user,
730
+ data.presence as TPresence
731
+ );
712
732
 
713
733
  const other = this._usersManager.getOther(connectionId);
714
734
  const others = this._usersManager.getOthers();
@@ -718,12 +738,6 @@ export class PluvRoom<
718
738
  }
719
739
 
720
740
  private _heartbeat(): void {
721
- if (!this._state.webSocket) return;
722
- if (!this._state.connection.id) return;
723
- if (this._state.webSocket.readyState !== this._state.webSocket.OPEN) {
724
- return;
725
- }
726
-
727
741
  this._clearTimeout(this._timeouts.pong);
728
742
  this._timeouts.pong = setTimeout(
729
743
  this._reconnect.bind(this),
@@ -957,7 +971,7 @@ export class PluvRoom<
957
971
 
958
972
  this._updateState((oldState) => {
959
973
  oldState.authorization.token = null;
960
- oldState.connection.state = ConnectionState.Unavailable;
974
+ oldState.connection.state = ConnectionState.Closed;
961
975
  oldState.webSocket = null;
962
976
 
963
977
  return oldState;
@@ -128,7 +128,8 @@ export class UsersManager<
128
128
 
129
129
  public setUser(
130
130
  connectionId: string,
131
- user: Id<InferIOAuthorizeUser<InferIOAuthorize<TIO>>>
131
+ user: Id<InferIOAuthorizeUser<InferIOAuthorize<TIO>>>,
132
+ presence?: TPresence
132
133
  ): void {
133
134
  if (this._myself?.connectionId === connectionId) return;
134
135
 
@@ -138,7 +139,7 @@ export class UsersManager<
138
139
 
139
140
  this._others.set(connectionId, {
140
141
  connectionId,
141
- presence: this._initialPresence,
142
+ presence: presence ?? this._initialPresence,
142
143
  user,
143
144
  });
144
145
  }
package/src/types.ts CHANGED
@@ -24,6 +24,7 @@ export interface InternalSubscriptions {
24
24
  }
25
25
 
26
26
  export interface WebSocketConnection {
27
+ count: number;
27
28
  id: string | null;
28
29
  state: ConnectionState;
29
30
  }