@pluv/client 0.6.3 → 0.6.5
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/.turbo/turbo-build.log +7 -7
- package/CHANGELOG.md +17 -0
- package/README.md +2 -1
- package/dist/index.d.ts +5 -2
- package/dist/index.js +59 -23
- package/dist/index.mjs +59 -23
- package/package.json +3 -3
- package/src/AbstractRoom.ts +2 -0
- package/src/MockedRoom.ts +12 -6
- package/src/PluvClient.ts +3 -3
- package/src/PluvRoom.ts +31 -4
- package/src/UsersManager.ts +38 -10
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
> @pluv/client@0.6.
|
|
2
|
+
> @pluv/client@0.6.5 build /home/runner/work/pluv/pluv/packages/client
|
|
3
3
|
> tsup src/index.ts --format esm,cjs --dts
|
|
4
4
|
|
|
5
5
|
[34mCLI[39m Building entry: src/index.ts
|
|
@@ -8,10 +8,10 @@
|
|
|
8
8
|
[34mCLI[39m Target: es6
|
|
9
9
|
[34mESM[39m Build start
|
|
10
10
|
[34mCJS[39m Build start
|
|
11
|
-
[32mESM[39m [1mdist/index.mjs [22m[
|
|
12
|
-
[32mESM[39m ⚡️ Build success in
|
|
13
|
-
[32mCJS[39m [1mdist/index.js [22m[
|
|
14
|
-
[32mCJS[39m ⚡️ Build success in
|
|
11
|
+
[32mESM[39m [1mdist/index.mjs [22m[32m34.41 KB[39m
|
|
12
|
+
[32mESM[39m ⚡️ Build success in 95ms
|
|
13
|
+
[32mCJS[39m [1mdist/index.js [22m[32m35.55 KB[39m
|
|
14
|
+
[32mCJS[39m ⚡️ Build success in 96ms
|
|
15
15
|
[34mDTS[39m Build start
|
|
16
|
-
[32mDTS[39m ⚡️ Build success in
|
|
17
|
-
[32mDTS[39m [1mdist/index.d.ts [22m[32m11.
|
|
16
|
+
[32mDTS[39m ⚡️ Build success in 3764ms
|
|
17
|
+
[32mDTS[39m [1mdist/index.d.ts [22m[32m11.68 KB[39m
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,22 @@
|
|
|
1
1
|
# @pluv/client
|
|
2
2
|
|
|
3
|
+
## 0.6.5
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 7ad4967: fixed user's presence not updating locally while offline
|
|
8
|
+
- 4535687: fix local yjs doc not updating while disconnected
|
|
9
|
+
- @pluv/crdt-yjs@0.3.6
|
|
10
|
+
- @pluv/types@0.1.6
|
|
11
|
+
|
|
12
|
+
## 0.6.4
|
|
13
|
+
|
|
14
|
+
### Patch Changes
|
|
15
|
+
|
|
16
|
+
- 78fd644: updated readmes with links to the documentation website
|
|
17
|
+
- Updated dependencies [78fd644]
|
|
18
|
+
- @pluv/crdt-yjs@0.3.6
|
|
19
|
+
|
|
3
20
|
## 0.6.3
|
|
4
21
|
|
|
5
22
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -23,7 +23,6 @@
|
|
|
23
23
|
<a href="https://commitizen.github.io/cz-cli/">
|
|
24
24
|
<img src="https://img.shields.io/badge/commitizen-friendly-brightgreen.svg" alt="Commitizen friendly" />
|
|
25
25
|
</a>
|
|
26
|
-
<img src="https://img.shields.io/badge/docs-coming%20soon!-blue" alt="Docs coming soon!" />
|
|
27
26
|
</p>
|
|
28
27
|
|
|
29
28
|
<p align="center">
|
|
@@ -34,6 +33,8 @@
|
|
|
34
33
|
|
|
35
34
|
> Framework agnostic frontend client for [@pluv/io](https://www.npmjs.com/package/@pluv/io)
|
|
36
35
|
|
|
36
|
+
**👉 See full documentation on [pluv.io](https://pluv.io/docs/introduction). 👈**
|
|
37
|
+
|
|
37
38
|
## Installation
|
|
38
39
|
|
|
39
40
|
```bash
|
package/dist/index.d.ts
CHANGED
|
@@ -60,6 +60,7 @@ declare abstract class AbstractRoom<TIO extends IOLike, TPresence extends JsonOb
|
|
|
60
60
|
abstract other(connectionId: string, callback: OtherNotifierSubscriptionCallback<TIO>): () => void;
|
|
61
61
|
abstract storage<TKey extends keyof TStorage>(key: TKey, fn: (value: InferYjsSharedTypeJson<TStorage[TKey]>) => void): () => void;
|
|
62
62
|
abstract subscribe<TSubject extends keyof StateNotifierSubjects<TIO, TPresence>>(name: TSubject, callback: SubscriptionCallback<TIO, TPresence, TSubject>): () => void;
|
|
63
|
+
abstract updateMyPresence(presence: Partial<TPresence>): void;
|
|
63
64
|
}
|
|
64
65
|
|
|
65
66
|
interface CrdtManagerOptions<TStorage extends Record<string, AbstractType<any>> = {}> {
|
|
@@ -133,6 +134,7 @@ declare class PluvRoom<TIO extends IOLike, TPresence extends JsonObject = {}, TS
|
|
|
133
134
|
other: (connectionId: string, callback: OtherNotifierSubscriptionCallback<TIO>) => (() => void);
|
|
134
135
|
storage: <TKey extends keyof TStorage>(key: TKey, fn: (value: InferYjsSharedTypeJson<TStorage[TKey]>) => void) => (() => void);
|
|
135
136
|
subscribe: <TSubject extends keyof StateNotifierSubjects<TIO, TPresence>>(name: TSubject, callback: SubscriptionCallback<TIO, TPresence, TSubject>) => (() => void);
|
|
137
|
+
updateMyPresence: (presence: Partial<TPresence>) => void;
|
|
136
138
|
private _attachWindowListeners;
|
|
137
139
|
private _attachWsListeners;
|
|
138
140
|
private _clearInterval;
|
|
@@ -188,10 +190,10 @@ declare class PluvClient<TIO extends IOLike = IOLike> {
|
|
|
188
190
|
private _rooms;
|
|
189
191
|
constructor(options: PluvClientOptions<TIO>);
|
|
190
192
|
createRoom: <TPresence extends JsonObject = {}, TStorage extends Record<string, AbstractType<any>> = {}>(room: string, options?: PluvRoomOptions<TIO, TPresence, TStorage>) => PluvRoom<TIO, TPresence, TStorage>;
|
|
191
|
-
enter: (room: string | PluvRoom<TIO,
|
|
193
|
+
enter: (room: string | PluvRoom<TIO, any, any>) => Promise<PluvRoom<TIO, JsonObject, any>>;
|
|
192
194
|
getRoom: <TPresence extends JsonObject = {}, TStorage extends Record<string, AbstractType<any>> = {}>(room: string) => PluvRoom<TIO, TPresence, TStorage> | null;
|
|
193
195
|
getRooms: () => readonly PluvRoom<TIO, JsonObject, any>[];
|
|
194
|
-
leave: (room: string | PluvRoom<TIO,
|
|
196
|
+
leave: (room: string | PluvRoom<TIO, any, any>) => void;
|
|
195
197
|
private _logDebug;
|
|
196
198
|
}
|
|
197
199
|
|
|
@@ -225,6 +227,7 @@ declare class MockedRoom<TIO extends IOLike, TPresence extends JsonObject = {},
|
|
|
225
227
|
other: (connectionId: string, callback: OtherNotifierSubscriptionCallback<TIO>) => (() => void);
|
|
226
228
|
storage: <TKey extends keyof TStorage>(key: TKey, fn: (value: InferYjsSharedTypeJson<TStorage[TKey]>) => void) => (() => void);
|
|
227
229
|
subscribe: <TSubject extends keyof StateNotifierSubjects<TIO, TPresence>>(name: TSubject, callback: SubscriptionCallback<TIO, TPresence, TSubject>) => (() => void);
|
|
230
|
+
updateMyPresence: (presence: Partial<TPresence>) => void;
|
|
228
231
|
private _observeCrdt;
|
|
229
232
|
}
|
|
230
233
|
|
package/dist/index.js
CHANGED
|
@@ -189,13 +189,20 @@ var ConnectionState = /* @__PURE__ */ ((ConnectionState2) => {
|
|
|
189
189
|
// src/UsersManager.ts
|
|
190
190
|
var UsersManager = class {
|
|
191
191
|
constructor(config) {
|
|
192
|
+
/**
|
|
193
|
+
* @description This is only set when the user is connected.
|
|
194
|
+
*/
|
|
192
195
|
this._myself = null;
|
|
193
196
|
this._others = /* @__PURE__ */ new Map();
|
|
194
197
|
this._presence = null;
|
|
195
198
|
const { initialPresence, presence = null } = config;
|
|
196
199
|
this._initialPresence = initialPresence;
|
|
200
|
+
this._myPresence = initialPresence;
|
|
197
201
|
this._presence = presence;
|
|
198
202
|
}
|
|
203
|
+
get myPresence() {
|
|
204
|
+
return this._myPresence;
|
|
205
|
+
}
|
|
199
206
|
get myself() {
|
|
200
207
|
return this._myself;
|
|
201
208
|
}
|
|
@@ -212,21 +219,15 @@ var UsersManager = class {
|
|
|
212
219
|
patchPresence(connectionId, patch) {
|
|
213
220
|
var _a, _b;
|
|
214
221
|
if (((_a = this._myself) == null ? void 0 : _a.connectionId) === connectionId) {
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
patch
|
|
219
|
-
);
|
|
222
|
+
const presence2 = __spreadValues(__spreadValues({}, this._myPresence), patch);
|
|
223
|
+
this._myself.presence = presence2;
|
|
224
|
+
this._myPresence = presence2;
|
|
220
225
|
return;
|
|
221
226
|
}
|
|
222
227
|
const other = this._others.get(connectionId);
|
|
223
228
|
if (!other)
|
|
224
229
|
return;
|
|
225
|
-
const presence =
|
|
226
|
-
/* @__PURE__ */ Object.create(null),
|
|
227
|
-
other.presence,
|
|
228
|
-
patch
|
|
229
|
-
);
|
|
230
|
+
const presence = __spreadValues(__spreadValues({}, other.presence), patch);
|
|
230
231
|
(_b = this._presence) == null ? void 0 : _b.parse(presence);
|
|
231
232
|
this._others.set(connectionId, __spreadProps(__spreadValues({}, other), { presence }));
|
|
232
233
|
}
|
|
@@ -242,11 +243,13 @@ var UsersManager = class {
|
|
|
242
243
|
presence: this._initialPresence,
|
|
243
244
|
user
|
|
244
245
|
};
|
|
246
|
+
this._myPresence = this._initialPresence;
|
|
245
247
|
}
|
|
246
248
|
setPresence(connectionId, presence) {
|
|
247
249
|
var _a;
|
|
248
250
|
if (((_a = this._myself) == null ? void 0 : _a.connectionId) === connectionId) {
|
|
249
251
|
this._myself.presence = presence;
|
|
252
|
+
this._myPresence = presence;
|
|
250
253
|
return;
|
|
251
254
|
}
|
|
252
255
|
const other = this._others.get(connectionId);
|
|
@@ -267,6 +270,15 @@ var UsersManager = class {
|
|
|
267
270
|
user
|
|
268
271
|
});
|
|
269
272
|
}
|
|
273
|
+
/**
|
|
274
|
+
* @description This method need not care about being connected.
|
|
275
|
+
*/
|
|
276
|
+
updateMyPresence(presence) {
|
|
277
|
+
this._myPresence = __spreadValues(__spreadValues({}, this._myPresence), presence);
|
|
278
|
+
if (!this._myself)
|
|
279
|
+
return;
|
|
280
|
+
this._myself.presence = this._myPresence;
|
|
281
|
+
}
|
|
270
282
|
};
|
|
271
283
|
|
|
272
284
|
// src/PluvRoom.ts
|
|
@@ -343,6 +355,18 @@ var PluvRoom = class extends AbstractRoom {
|
|
|
343
355
|
this.subscribe = (name, callback) => {
|
|
344
356
|
return this._stateNotifier.subscribe(name, callback);
|
|
345
357
|
};
|
|
358
|
+
this.updateMyPresence = (presence) => {
|
|
359
|
+
var _a;
|
|
360
|
+
this._usersManager.updateMyPresence(presence);
|
|
361
|
+
const myPresence = this._usersManager.myPresence;
|
|
362
|
+
const myself = (_a = this._usersManager.myself) != null ? _a : null;
|
|
363
|
+
this._stateNotifier.subjects["my-presence"].next(myPresence);
|
|
364
|
+
!!myself && this._stateNotifier.subjects["myself"].next(myself);
|
|
365
|
+
this.broadcast(
|
|
366
|
+
"$UPDATE_PRESENCE",
|
|
367
|
+
{ presence }
|
|
368
|
+
);
|
|
369
|
+
};
|
|
346
370
|
this._debug = debug;
|
|
347
371
|
this._endpoints = {
|
|
348
372
|
authEndpoint,
|
|
@@ -430,8 +454,10 @@ var PluvRoom = class extends AbstractRoom {
|
|
|
430
454
|
].some((state) => this._state.connection.state === state);
|
|
431
455
|
if (!canDisconnect)
|
|
432
456
|
return;
|
|
457
|
+
this._clearInterval(this._intervals.heartbeat);
|
|
433
458
|
this._closeWs();
|
|
434
459
|
(_a = this._crdtManager) == null ? void 0 : _a.destroy();
|
|
460
|
+
this._stateNotifier.subjects["my-presence"].next(null);
|
|
435
461
|
this._updateState((oldState) => {
|
|
436
462
|
oldState.authorization.token = null;
|
|
437
463
|
oldState.connection.state = "Closed" /* Closed */;
|
|
@@ -503,7 +529,6 @@ var PluvRoom = class extends AbstractRoom {
|
|
|
503
529
|
if (!this._state.webSocket)
|
|
504
530
|
return;
|
|
505
531
|
(_b = (_a = this._subscriptions).observeCrdt) == null ? void 0 : _b.call(_a);
|
|
506
|
-
this._clearInterval(this._intervals.heartbeat);
|
|
507
532
|
this._clearTimeout(this._timeouts.pong);
|
|
508
533
|
this._clearTimeout(this._timeouts.reconnect);
|
|
509
534
|
this._detachWindowListeners();
|
|
@@ -517,7 +542,6 @@ var PluvRoom = class extends AbstractRoom {
|
|
|
517
542
|
if (canClose)
|
|
518
543
|
this._state.webSocket.close();
|
|
519
544
|
this._detachWsListeners();
|
|
520
|
-
this._stateNotifier.subjects["my-presence"].next(null);
|
|
521
545
|
this._stateNotifier.subjects["myself"].next(null);
|
|
522
546
|
}
|
|
523
547
|
_detachWindowListeners() {
|
|
@@ -592,7 +616,7 @@ var PluvRoom = class extends AbstractRoom {
|
|
|
592
616
|
this._otherNotifier.subjects.delete(connectionId);
|
|
593
617
|
}
|
|
594
618
|
_handlePresenceUpdatedMessage(message) {
|
|
595
|
-
var _a
|
|
619
|
+
var _a;
|
|
596
620
|
const { connectionId } = message;
|
|
597
621
|
if (!connectionId)
|
|
598
622
|
return;
|
|
@@ -603,8 +627,8 @@ var PluvRoom = class extends AbstractRoom {
|
|
|
603
627
|
connectionId,
|
|
604
628
|
data.presence
|
|
605
629
|
);
|
|
606
|
-
const myPresence =
|
|
607
|
-
const myself = (
|
|
630
|
+
const myPresence = this._usersManager.myPresence;
|
|
631
|
+
const myself = (_a = this._usersManager.myself) != null ? _a : null;
|
|
608
632
|
if ((myself == null ? void 0 : myself.connectionId) === connectionId) {
|
|
609
633
|
this._stateNotifier.subjects["my-presence"].next(myPresence);
|
|
610
634
|
this._stateNotifier.subjects["myself"].next(myself);
|
|
@@ -637,7 +661,7 @@ var PluvRoom = class extends AbstractRoom {
|
|
|
637
661
|
this._stateNotifier.subjects["others"].next(others);
|
|
638
662
|
}
|
|
639
663
|
_handleRegisteredMessage(message) {
|
|
640
|
-
var _a
|
|
664
|
+
var _a;
|
|
641
665
|
const { connectionId, user } = message;
|
|
642
666
|
if (!connectionId)
|
|
643
667
|
return;
|
|
@@ -652,8 +676,8 @@ var PluvRoom = class extends AbstractRoom {
|
|
|
652
676
|
connectionId,
|
|
653
677
|
user
|
|
654
678
|
);
|
|
655
|
-
const myPresence =
|
|
656
|
-
const myself = (
|
|
679
|
+
const myPresence = this._usersManager.myPresence;
|
|
680
|
+
const myself = (_a = this._usersManager.myself) != null ? _a : null;
|
|
657
681
|
this._stateNotifier.subjects["my-presence"].next(myPresence);
|
|
658
682
|
this._stateNotifier.subjects["myself"].next(myself);
|
|
659
683
|
this._sendMessage({ type: "$GET_OTHERS", data: {} });
|
|
@@ -758,6 +782,13 @@ var PluvRoom = class extends AbstractRoom {
|
|
|
758
782
|
return;
|
|
759
783
|
if (origin === "$STORAGE_UPDATED")
|
|
760
784
|
return;
|
|
785
|
+
const sharedTypes = this._crdtManager.doc.getSharedTypes();
|
|
786
|
+
Object.entries(sharedTypes).forEach(([prop, sharedType]) => {
|
|
787
|
+
if (!this._crdtManager)
|
|
788
|
+
return;
|
|
789
|
+
const serialized = sharedType.toJSON();
|
|
790
|
+
this._crdtNotifier.subject(prop).next(serialized);
|
|
791
|
+
});
|
|
761
792
|
this._sendMessage({
|
|
762
793
|
type: "$UPDATE_STORAGE",
|
|
763
794
|
data: { origin, update }
|
|
@@ -1069,6 +1100,14 @@ var MockedRoom = class extends AbstractRoom {
|
|
|
1069
1100
|
this.subscribe = (name, callback) => {
|
|
1070
1101
|
return this._stateNotifier.subscribe(name, callback);
|
|
1071
1102
|
};
|
|
1103
|
+
this.updateMyPresence = (presence) => {
|
|
1104
|
+
var _a;
|
|
1105
|
+
this._usersManager.updateMyPresence(presence);
|
|
1106
|
+
const myPresence = this._usersManager.myPresence;
|
|
1107
|
+
const myself = (_a = this._usersManager.myself) != null ? _a : null;
|
|
1108
|
+
this._stateNotifier.subjects["my-presence"].next(myPresence);
|
|
1109
|
+
!!myself && this._stateNotifier.subjects["myself"].next(myself);
|
|
1110
|
+
};
|
|
1072
1111
|
this._events = events;
|
|
1073
1112
|
this._usersManager = new UsersManager({
|
|
1074
1113
|
initialPresence,
|
|
@@ -1112,14 +1151,11 @@ var MockedRoom = class extends AbstractRoom {
|
|
|
1112
1151
|
if (origin === "$STORAGE_UPDATED")
|
|
1113
1152
|
return;
|
|
1114
1153
|
const sharedTypes = this._crdtManager.doc.getSharedTypes();
|
|
1115
|
-
Object.
|
|
1154
|
+
Object.entries(sharedTypes).forEach(([prop, sharedType]) => {
|
|
1116
1155
|
if (!this._crdtManager)
|
|
1117
1156
|
return;
|
|
1118
|
-
const sharedType = sharedTypes[key];
|
|
1119
|
-
if (!sharedType)
|
|
1120
|
-
return;
|
|
1121
1157
|
const serialized = sharedType.toJSON();
|
|
1122
|
-
this._crdtNotifier.subject(
|
|
1158
|
+
this._crdtNotifier.subject(prop).next(serialized);
|
|
1123
1159
|
});
|
|
1124
1160
|
}
|
|
1125
1161
|
);
|
package/dist/index.mjs
CHANGED
|
@@ -164,13 +164,20 @@ var ConnectionState = /* @__PURE__ */ ((ConnectionState2) => {
|
|
|
164
164
|
// src/UsersManager.ts
|
|
165
165
|
var UsersManager = class {
|
|
166
166
|
constructor(config) {
|
|
167
|
+
/**
|
|
168
|
+
* @description This is only set when the user is connected.
|
|
169
|
+
*/
|
|
167
170
|
this._myself = null;
|
|
168
171
|
this._others = /* @__PURE__ */ new Map();
|
|
169
172
|
this._presence = null;
|
|
170
173
|
const { initialPresence, presence = null } = config;
|
|
171
174
|
this._initialPresence = initialPresence;
|
|
175
|
+
this._myPresence = initialPresence;
|
|
172
176
|
this._presence = presence;
|
|
173
177
|
}
|
|
178
|
+
get myPresence() {
|
|
179
|
+
return this._myPresence;
|
|
180
|
+
}
|
|
174
181
|
get myself() {
|
|
175
182
|
return this._myself;
|
|
176
183
|
}
|
|
@@ -187,21 +194,15 @@ var UsersManager = class {
|
|
|
187
194
|
patchPresence(connectionId, patch) {
|
|
188
195
|
var _a, _b;
|
|
189
196
|
if (((_a = this._myself) == null ? void 0 : _a.connectionId) === connectionId) {
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
patch
|
|
194
|
-
);
|
|
197
|
+
const presence2 = __spreadValues(__spreadValues({}, this._myPresence), patch);
|
|
198
|
+
this._myself.presence = presence2;
|
|
199
|
+
this._myPresence = presence2;
|
|
195
200
|
return;
|
|
196
201
|
}
|
|
197
202
|
const other = this._others.get(connectionId);
|
|
198
203
|
if (!other)
|
|
199
204
|
return;
|
|
200
|
-
const presence =
|
|
201
|
-
/* @__PURE__ */ Object.create(null),
|
|
202
|
-
other.presence,
|
|
203
|
-
patch
|
|
204
|
-
);
|
|
205
|
+
const presence = __spreadValues(__spreadValues({}, other.presence), patch);
|
|
205
206
|
(_b = this._presence) == null ? void 0 : _b.parse(presence);
|
|
206
207
|
this._others.set(connectionId, __spreadProps(__spreadValues({}, other), { presence }));
|
|
207
208
|
}
|
|
@@ -217,11 +218,13 @@ var UsersManager = class {
|
|
|
217
218
|
presence: this._initialPresence,
|
|
218
219
|
user
|
|
219
220
|
};
|
|
221
|
+
this._myPresence = this._initialPresence;
|
|
220
222
|
}
|
|
221
223
|
setPresence(connectionId, presence) {
|
|
222
224
|
var _a;
|
|
223
225
|
if (((_a = this._myself) == null ? void 0 : _a.connectionId) === connectionId) {
|
|
224
226
|
this._myself.presence = presence;
|
|
227
|
+
this._myPresence = presence;
|
|
225
228
|
return;
|
|
226
229
|
}
|
|
227
230
|
const other = this._others.get(connectionId);
|
|
@@ -242,6 +245,15 @@ var UsersManager = class {
|
|
|
242
245
|
user
|
|
243
246
|
});
|
|
244
247
|
}
|
|
248
|
+
/**
|
|
249
|
+
* @description This method need not care about being connected.
|
|
250
|
+
*/
|
|
251
|
+
updateMyPresence(presence) {
|
|
252
|
+
this._myPresence = __spreadValues(__spreadValues({}, this._myPresence), presence);
|
|
253
|
+
if (!this._myself)
|
|
254
|
+
return;
|
|
255
|
+
this._myself.presence = this._myPresence;
|
|
256
|
+
}
|
|
245
257
|
};
|
|
246
258
|
|
|
247
259
|
// src/PluvRoom.ts
|
|
@@ -318,6 +330,18 @@ var PluvRoom = class extends AbstractRoom {
|
|
|
318
330
|
this.subscribe = (name, callback) => {
|
|
319
331
|
return this._stateNotifier.subscribe(name, callback);
|
|
320
332
|
};
|
|
333
|
+
this.updateMyPresence = (presence) => {
|
|
334
|
+
var _a;
|
|
335
|
+
this._usersManager.updateMyPresence(presence);
|
|
336
|
+
const myPresence = this._usersManager.myPresence;
|
|
337
|
+
const myself = (_a = this._usersManager.myself) != null ? _a : null;
|
|
338
|
+
this._stateNotifier.subjects["my-presence"].next(myPresence);
|
|
339
|
+
!!myself && this._stateNotifier.subjects["myself"].next(myself);
|
|
340
|
+
this.broadcast(
|
|
341
|
+
"$UPDATE_PRESENCE",
|
|
342
|
+
{ presence }
|
|
343
|
+
);
|
|
344
|
+
};
|
|
321
345
|
this._debug = debug;
|
|
322
346
|
this._endpoints = {
|
|
323
347
|
authEndpoint,
|
|
@@ -405,8 +429,10 @@ var PluvRoom = class extends AbstractRoom {
|
|
|
405
429
|
].some((state) => this._state.connection.state === state);
|
|
406
430
|
if (!canDisconnect)
|
|
407
431
|
return;
|
|
432
|
+
this._clearInterval(this._intervals.heartbeat);
|
|
408
433
|
this._closeWs();
|
|
409
434
|
(_a = this._crdtManager) == null ? void 0 : _a.destroy();
|
|
435
|
+
this._stateNotifier.subjects["my-presence"].next(null);
|
|
410
436
|
this._updateState((oldState) => {
|
|
411
437
|
oldState.authorization.token = null;
|
|
412
438
|
oldState.connection.state = "Closed" /* Closed */;
|
|
@@ -478,7 +504,6 @@ var PluvRoom = class extends AbstractRoom {
|
|
|
478
504
|
if (!this._state.webSocket)
|
|
479
505
|
return;
|
|
480
506
|
(_b = (_a = this._subscriptions).observeCrdt) == null ? void 0 : _b.call(_a);
|
|
481
|
-
this._clearInterval(this._intervals.heartbeat);
|
|
482
507
|
this._clearTimeout(this._timeouts.pong);
|
|
483
508
|
this._clearTimeout(this._timeouts.reconnect);
|
|
484
509
|
this._detachWindowListeners();
|
|
@@ -492,7 +517,6 @@ var PluvRoom = class extends AbstractRoom {
|
|
|
492
517
|
if (canClose)
|
|
493
518
|
this._state.webSocket.close();
|
|
494
519
|
this._detachWsListeners();
|
|
495
|
-
this._stateNotifier.subjects["my-presence"].next(null);
|
|
496
520
|
this._stateNotifier.subjects["myself"].next(null);
|
|
497
521
|
}
|
|
498
522
|
_detachWindowListeners() {
|
|
@@ -567,7 +591,7 @@ var PluvRoom = class extends AbstractRoom {
|
|
|
567
591
|
this._otherNotifier.subjects.delete(connectionId);
|
|
568
592
|
}
|
|
569
593
|
_handlePresenceUpdatedMessage(message) {
|
|
570
|
-
var _a
|
|
594
|
+
var _a;
|
|
571
595
|
const { connectionId } = message;
|
|
572
596
|
if (!connectionId)
|
|
573
597
|
return;
|
|
@@ -578,8 +602,8 @@ var PluvRoom = class extends AbstractRoom {
|
|
|
578
602
|
connectionId,
|
|
579
603
|
data.presence
|
|
580
604
|
);
|
|
581
|
-
const myPresence =
|
|
582
|
-
const myself = (
|
|
605
|
+
const myPresence = this._usersManager.myPresence;
|
|
606
|
+
const myself = (_a = this._usersManager.myself) != null ? _a : null;
|
|
583
607
|
if ((myself == null ? void 0 : myself.connectionId) === connectionId) {
|
|
584
608
|
this._stateNotifier.subjects["my-presence"].next(myPresence);
|
|
585
609
|
this._stateNotifier.subjects["myself"].next(myself);
|
|
@@ -612,7 +636,7 @@ var PluvRoom = class extends AbstractRoom {
|
|
|
612
636
|
this._stateNotifier.subjects["others"].next(others);
|
|
613
637
|
}
|
|
614
638
|
_handleRegisteredMessage(message) {
|
|
615
|
-
var _a
|
|
639
|
+
var _a;
|
|
616
640
|
const { connectionId, user } = message;
|
|
617
641
|
if (!connectionId)
|
|
618
642
|
return;
|
|
@@ -627,8 +651,8 @@ var PluvRoom = class extends AbstractRoom {
|
|
|
627
651
|
connectionId,
|
|
628
652
|
user
|
|
629
653
|
);
|
|
630
|
-
const myPresence =
|
|
631
|
-
const myself = (
|
|
654
|
+
const myPresence = this._usersManager.myPresence;
|
|
655
|
+
const myself = (_a = this._usersManager.myself) != null ? _a : null;
|
|
632
656
|
this._stateNotifier.subjects["my-presence"].next(myPresence);
|
|
633
657
|
this._stateNotifier.subjects["myself"].next(myself);
|
|
634
658
|
this._sendMessage({ type: "$GET_OTHERS", data: {} });
|
|
@@ -733,6 +757,13 @@ var PluvRoom = class extends AbstractRoom {
|
|
|
733
757
|
return;
|
|
734
758
|
if (origin === "$STORAGE_UPDATED")
|
|
735
759
|
return;
|
|
760
|
+
const sharedTypes = this._crdtManager.doc.getSharedTypes();
|
|
761
|
+
Object.entries(sharedTypes).forEach(([prop, sharedType]) => {
|
|
762
|
+
if (!this._crdtManager)
|
|
763
|
+
return;
|
|
764
|
+
const serialized = sharedType.toJSON();
|
|
765
|
+
this._crdtNotifier.subject(prop).next(serialized);
|
|
766
|
+
});
|
|
736
767
|
this._sendMessage({
|
|
737
768
|
type: "$UPDATE_STORAGE",
|
|
738
769
|
data: { origin, update }
|
|
@@ -1044,6 +1075,14 @@ var MockedRoom = class extends AbstractRoom {
|
|
|
1044
1075
|
this.subscribe = (name, callback) => {
|
|
1045
1076
|
return this._stateNotifier.subscribe(name, callback);
|
|
1046
1077
|
};
|
|
1078
|
+
this.updateMyPresence = (presence) => {
|
|
1079
|
+
var _a;
|
|
1080
|
+
this._usersManager.updateMyPresence(presence);
|
|
1081
|
+
const myPresence = this._usersManager.myPresence;
|
|
1082
|
+
const myself = (_a = this._usersManager.myself) != null ? _a : null;
|
|
1083
|
+
this._stateNotifier.subjects["my-presence"].next(myPresence);
|
|
1084
|
+
!!myself && this._stateNotifier.subjects["myself"].next(myself);
|
|
1085
|
+
};
|
|
1047
1086
|
this._events = events;
|
|
1048
1087
|
this._usersManager = new UsersManager({
|
|
1049
1088
|
initialPresence,
|
|
@@ -1087,14 +1126,11 @@ var MockedRoom = class extends AbstractRoom {
|
|
|
1087
1126
|
if (origin === "$STORAGE_UPDATED")
|
|
1088
1127
|
return;
|
|
1089
1128
|
const sharedTypes = this._crdtManager.doc.getSharedTypes();
|
|
1090
|
-
Object.
|
|
1129
|
+
Object.entries(sharedTypes).forEach(([prop, sharedType]) => {
|
|
1091
1130
|
if (!this._crdtManager)
|
|
1092
1131
|
return;
|
|
1093
|
-
const sharedType = sharedTypes[key];
|
|
1094
|
-
if (!sharedType)
|
|
1095
|
-
return;
|
|
1096
1132
|
const serialized = sharedType.toJSON();
|
|
1097
|
-
this._crdtNotifier.subject(
|
|
1133
|
+
this._crdtNotifier.subject(prop).next(serialized);
|
|
1098
1134
|
});
|
|
1099
1135
|
}
|
|
1100
1136
|
);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pluv/client",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.5",
|
|
4
4
|
"description": "@pluv/io frontend client",
|
|
5
5
|
"author": "leedavidcs",
|
|
6
6
|
"license": "MIT",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
20
|
"wonka": "^6.3.1",
|
|
21
|
-
"@pluv/crdt-yjs": "^0.3.
|
|
21
|
+
"@pluv/crdt-yjs": "^0.3.6",
|
|
22
22
|
"@pluv/types": "^0.1.6"
|
|
23
23
|
},
|
|
24
24
|
"peerDependencies": {
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"tsup": "^6.7.0",
|
|
29
29
|
"typescript": "^5.0.4",
|
|
30
30
|
"yjs": "^13.5.52",
|
|
31
|
-
"@pluv/tsconfig": "^0.1.
|
|
31
|
+
"@pluv/tsconfig": "^0.1.6",
|
|
32
32
|
"eslint-config-pluv": "^0.1.10"
|
|
33
33
|
},
|
|
34
34
|
"scripts": {
|
package/src/AbstractRoom.ts
CHANGED
package/src/MockedRoom.ts
CHANGED
|
@@ -177,6 +177,16 @@ export class MockedRoom<
|
|
|
177
177
|
return this._stateNotifier.subscribe(name, callback);
|
|
178
178
|
};
|
|
179
179
|
|
|
180
|
+
public updateMyPresence = (presence: Partial<TPresence>): void => {
|
|
181
|
+
this._usersManager.updateMyPresence(presence);
|
|
182
|
+
|
|
183
|
+
const myPresence = this._usersManager.myPresence;
|
|
184
|
+
const myself = this._usersManager.myself ?? null;
|
|
185
|
+
|
|
186
|
+
this._stateNotifier.subjects["my-presence"].next(myPresence);
|
|
187
|
+
!!myself && this._stateNotifier.subjects["myself"].next(myself);
|
|
188
|
+
};
|
|
189
|
+
|
|
180
190
|
private _observeCrdt(): void {
|
|
181
191
|
this._subscriptions.observeCrdt?.();
|
|
182
192
|
|
|
@@ -191,16 +201,12 @@ export class MockedRoom<
|
|
|
191
201
|
|
|
192
202
|
const sharedTypes = this._crdtManager.doc.getSharedTypes();
|
|
193
203
|
|
|
194
|
-
Object.
|
|
204
|
+
Object.entries(sharedTypes).forEach(([prop, sharedType]) => {
|
|
195
205
|
if (!this._crdtManager) return;
|
|
196
206
|
|
|
197
|
-
const sharedType = sharedTypes[key];
|
|
198
|
-
|
|
199
|
-
if (!sharedType) return;
|
|
200
|
-
|
|
201
207
|
const serialized = sharedType.toJSON();
|
|
202
208
|
|
|
203
|
-
this._crdtNotifier.subject(
|
|
209
|
+
this._crdtNotifier.subject(prop).next(serialized);
|
|
204
210
|
});
|
|
205
211
|
}
|
|
206
212
|
);
|
package/src/PluvClient.ts
CHANGED
|
@@ -17,7 +17,7 @@ export class PluvClient<TIO extends IOLike = IOLike> {
|
|
|
17
17
|
private _debug: boolean;
|
|
18
18
|
private _wsEndpoint: WsEndpoint;
|
|
19
19
|
|
|
20
|
-
private _rooms = new Map<string, PluvRoom<TIO,
|
|
20
|
+
private _rooms = new Map<string, PluvRoom<TIO, any, any>>();
|
|
21
21
|
|
|
22
22
|
constructor(options: PluvClientOptions<TIO>) {
|
|
23
23
|
const { authEndpoint, debug = false, wsEndpoint } = options;
|
|
@@ -55,7 +55,7 @@ export class PluvClient<TIO extends IOLike = IOLike> {
|
|
|
55
55
|
};
|
|
56
56
|
|
|
57
57
|
public enter = async (
|
|
58
|
-
room: string | PluvRoom<TIO,
|
|
58
|
+
room: string | PluvRoom<TIO, any, any>
|
|
59
59
|
): Promise<PluvRoom<TIO, JsonObject, any>> => {
|
|
60
60
|
const toEnter = typeof room === "string" ? this.getRoom(room) : room;
|
|
61
61
|
|
|
@@ -89,7 +89,7 @@ export class PluvClient<TIO extends IOLike = IOLike> {
|
|
|
89
89
|
return Array.from(this._rooms.values());
|
|
90
90
|
};
|
|
91
91
|
|
|
92
|
-
public leave = (room: string | PluvRoom<TIO,
|
|
92
|
+
public leave = (room: string | PluvRoom<TIO, any, any>): void => {
|
|
93
93
|
const toLeave = typeof room === "string" ? this.getRoom(room) : room;
|
|
94
94
|
|
|
95
95
|
if (!toLeave) return;
|
package/src/PluvRoom.ts
CHANGED
|
@@ -279,9 +279,13 @@ export class PluvRoom<
|
|
|
279
279
|
|
|
280
280
|
if (!canDisconnect) return;
|
|
281
281
|
|
|
282
|
+
this._clearInterval(this._intervals.heartbeat);
|
|
283
|
+
|
|
282
284
|
this._closeWs();
|
|
283
285
|
this._crdtManager?.destroy();
|
|
284
286
|
|
|
287
|
+
this._stateNotifier.subjects["my-presence"].next(null);
|
|
288
|
+
|
|
285
289
|
this._updateState((oldState) => {
|
|
286
290
|
oldState.authorization.token = null;
|
|
287
291
|
oldState.connection.state = ConnectionState.Closed;
|
|
@@ -352,6 +356,21 @@ export class PluvRoom<
|
|
|
352
356
|
return this._stateNotifier.subscribe(name, callback);
|
|
353
357
|
};
|
|
354
358
|
|
|
359
|
+
public updateMyPresence = (presence: Partial<TPresence>): void => {
|
|
360
|
+
this._usersManager.updateMyPresence(presence);
|
|
361
|
+
|
|
362
|
+
const myPresence = this._usersManager.myPresence;
|
|
363
|
+
const myself = this._usersManager.myself ?? null;
|
|
364
|
+
|
|
365
|
+
this._stateNotifier.subjects["my-presence"].next(myPresence);
|
|
366
|
+
!!myself && this._stateNotifier.subjects["myself"].next(myself);
|
|
367
|
+
|
|
368
|
+
this.broadcast(
|
|
369
|
+
"$UPDATE_PRESENCE" as keyof InferIOInput<TIO>,
|
|
370
|
+
{ presence } as any
|
|
371
|
+
);
|
|
372
|
+
};
|
|
373
|
+
|
|
355
374
|
private _attachWindowListeners(): void {
|
|
356
375
|
if (typeof window === "undefined") return;
|
|
357
376
|
if (typeof document === "undefined") return;
|
|
@@ -416,7 +435,6 @@ export class PluvRoom<
|
|
|
416
435
|
|
|
417
436
|
this._subscriptions.observeCrdt?.();
|
|
418
437
|
|
|
419
|
-
this._clearInterval(this._intervals.heartbeat);
|
|
420
438
|
this._clearTimeout(this._timeouts.pong);
|
|
421
439
|
this._clearTimeout(this._timeouts.reconnect);
|
|
422
440
|
|
|
@@ -431,7 +449,6 @@ export class PluvRoom<
|
|
|
431
449
|
|
|
432
450
|
this._detachWsListeners();
|
|
433
451
|
|
|
434
|
-
this._stateNotifier.subjects["my-presence"].next(null);
|
|
435
452
|
this._stateNotifier.subjects["myself"].next(null);
|
|
436
453
|
}
|
|
437
454
|
|
|
@@ -537,7 +554,7 @@ export class PluvRoom<
|
|
|
537
554
|
data.presence as TPresence
|
|
538
555
|
);
|
|
539
556
|
|
|
540
|
-
const myPresence = this._usersManager.
|
|
557
|
+
const myPresence = this._usersManager.myPresence;
|
|
541
558
|
const myself = this._usersManager.myself ?? null;
|
|
542
559
|
|
|
543
560
|
if (myself?.connectionId === connectionId) {
|
|
@@ -605,7 +622,7 @@ export class PluvRoom<
|
|
|
605
622
|
user as Id<InferIOAuthorizeUser<InferIOAuthorize<TIO>>>
|
|
606
623
|
);
|
|
607
624
|
|
|
608
|
-
const myPresence = this._usersManager.
|
|
625
|
+
const myPresence = this._usersManager.myPresence;
|
|
609
626
|
const myself = this._usersManager.myself ?? null;
|
|
610
627
|
|
|
611
628
|
this._stateNotifier.subjects["my-presence"].next(myPresence);
|
|
@@ -739,6 +756,16 @@ export class PluvRoom<
|
|
|
739
756
|
|
|
740
757
|
if (origin === "$STORAGE_UPDATED") return;
|
|
741
758
|
|
|
759
|
+
const sharedTypes = this._crdtManager.doc.getSharedTypes();
|
|
760
|
+
|
|
761
|
+
Object.entries(sharedTypes).forEach(([prop, sharedType]) => {
|
|
762
|
+
if (!this._crdtManager) return;
|
|
763
|
+
|
|
764
|
+
const serialized = sharedType.toJSON();
|
|
765
|
+
|
|
766
|
+
this._crdtNotifier.subject(prop).next(serialized);
|
|
767
|
+
});
|
|
768
|
+
|
|
742
769
|
this._sendMessage({
|
|
743
770
|
type: "$UPDATE_STORAGE",
|
|
744
771
|
data: { origin, update },
|
package/src/UsersManager.ts
CHANGED
|
@@ -20,6 +20,14 @@ export class UsersManager<
|
|
|
20
20
|
TPresence extends JsonObject = {}
|
|
21
21
|
> {
|
|
22
22
|
private _initialPresence: TPresence;
|
|
23
|
+
/**
|
|
24
|
+
* @description This presence can be updated while the user is not
|
|
25
|
+
* connected.
|
|
26
|
+
*/
|
|
27
|
+
private _myPresence: TPresence;
|
|
28
|
+
/**
|
|
29
|
+
* @description This is only set when the user is connected.
|
|
30
|
+
*/
|
|
23
31
|
private _myself: UserInfo<TIO, TPresence> | null = null;
|
|
24
32
|
private _others = new Map<string, UserInfo<TIO, TPresence>>();
|
|
25
33
|
private _presence: InputZodLike<TPresence> | null = null;
|
|
@@ -28,9 +36,14 @@ export class UsersManager<
|
|
|
28
36
|
const { initialPresence, presence = null } = config;
|
|
29
37
|
|
|
30
38
|
this._initialPresence = initialPresence as TPresence;
|
|
39
|
+
this._myPresence = initialPresence as TPresence;
|
|
31
40
|
this._presence = presence;
|
|
32
41
|
}
|
|
33
42
|
|
|
43
|
+
public get myPresence(): TPresence {
|
|
44
|
+
return this._myPresence;
|
|
45
|
+
}
|
|
46
|
+
|
|
34
47
|
public get myself(): UserInfo<TIO, TPresence> | null {
|
|
35
48
|
return this._myself;
|
|
36
49
|
}
|
|
@@ -52,11 +65,13 @@ export class UsersManager<
|
|
|
52
65
|
patch: Partial<TPresence>
|
|
53
66
|
): void {
|
|
54
67
|
if (this._myself?.connectionId === connectionId) {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
68
|
+
const presence = {
|
|
69
|
+
...this._myPresence,
|
|
70
|
+
...patch,
|
|
71
|
+
} as TPresence;
|
|
72
|
+
|
|
73
|
+
this._myself.presence = presence;
|
|
74
|
+
this._myPresence = presence;
|
|
60
75
|
|
|
61
76
|
return;
|
|
62
77
|
}
|
|
@@ -65,11 +80,10 @@ export class UsersManager<
|
|
|
65
80
|
|
|
66
81
|
if (!other) return;
|
|
67
82
|
|
|
68
|
-
const presence =
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
) as TPresence;
|
|
83
|
+
const presence = {
|
|
84
|
+
...other.presence,
|
|
85
|
+
...patch,
|
|
86
|
+
} as TPresence;
|
|
73
87
|
|
|
74
88
|
this._presence?.parse(presence);
|
|
75
89
|
|
|
@@ -93,11 +107,14 @@ export class UsersManager<
|
|
|
93
107
|
presence: this._initialPresence,
|
|
94
108
|
user,
|
|
95
109
|
};
|
|
110
|
+
|
|
111
|
+
this._myPresence = this._initialPresence;
|
|
96
112
|
}
|
|
97
113
|
|
|
98
114
|
public setPresence(connectionId: string, presence: TPresence): void {
|
|
99
115
|
if (this._myself?.connectionId === connectionId) {
|
|
100
116
|
this._myself.presence = presence;
|
|
117
|
+
this._myPresence = presence;
|
|
101
118
|
|
|
102
119
|
return;
|
|
103
120
|
}
|
|
@@ -125,4 +142,15 @@ export class UsersManager<
|
|
|
125
142
|
user,
|
|
126
143
|
});
|
|
127
144
|
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* @description This method need not care about being connected.
|
|
148
|
+
*/
|
|
149
|
+
public updateMyPresence(presence: Partial<TPresence>): void {
|
|
150
|
+
this._myPresence = { ...this._myPresence, ...presence };
|
|
151
|
+
|
|
152
|
+
if (!this._myself) return;
|
|
153
|
+
|
|
154
|
+
this._myself.presence = this._myPresence;
|
|
155
|
+
}
|
|
128
156
|
}
|