@pluv/client 2.0.2 → 2.2.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/.turbo/turbo-build.log +8 -8
- package/CHANGELOG.md +141 -0
- package/dist/index.d.mts +74 -79
- package/dist/index.d.ts +74 -79
- package/dist/index.js +267 -68
- package/dist/index.mjs +269 -70
- package/package.json +5 -5
- package/src/CrdtManager.ts +9 -13
- package/src/CrdtNotifier.ts +2 -1
- package/src/ListenerManager.ts +21 -0
- package/src/MockedRoom.ts +118 -48
- package/src/PluvClient.ts +8 -8
- package/src/PluvProcedure.ts +27 -25
- package/src/PluvRoom.ts +235 -82
- package/src/PluvRouter.ts +31 -22
- package/src/StateNotifier.ts +13 -19
- package/src/UsersManager.ts +18 -4
- package/src/UsersNotifier.ts +66 -0
- package/src/constants.ts +1 -0
- package/src/createClient.ts +2 -2
- package/src/index.ts +2 -1
- package/src/types.ts +10 -31
- package/src/OtherNotifier.ts +0 -50
package/dist/index.js
CHANGED
|
@@ -78,6 +78,7 @@ var AbstractStorageStore = class {
|
|
|
78
78
|
|
|
79
79
|
// src/constants.ts
|
|
80
80
|
var MAX_PRESENCE_SIZE_BYTES = 512;
|
|
81
|
+
var PLUV_PRESENCE_META_KEY = "__pluv";
|
|
81
82
|
|
|
82
83
|
// src/PluvProcedure.ts
|
|
83
84
|
var PluvProcedure = class _PluvProcedure {
|
|
@@ -124,7 +125,7 @@ var CrdtManager = class {
|
|
|
124
125
|
this.initialized = false;
|
|
125
126
|
const { initialStorage = import_crdt.noop.doc({}) } = options;
|
|
126
127
|
this._docFactory = initialStorage;
|
|
127
|
-
this.doc =
|
|
128
|
+
this.doc = this._docFactory.getEmpty();
|
|
128
129
|
}
|
|
129
130
|
/**
|
|
130
131
|
* !HACK
|
|
@@ -164,11 +165,7 @@ var CrdtManager = class {
|
|
|
164
165
|
if (!updates.length) return this;
|
|
165
166
|
const initialized = this._docFactory.getInitialized();
|
|
166
167
|
const reference = initialized.get();
|
|
167
|
-
this.doc = this._applyDocUpdates(
|
|
168
|
-
this._docFactory.getEmpty(),
|
|
169
|
-
updates,
|
|
170
|
-
origin
|
|
171
|
-
).rebuildStorage(reference);
|
|
168
|
+
this.doc = this._applyDocUpdates(this.doc, updates, origin).rebuildStorage(reference);
|
|
172
169
|
this.initialized = true;
|
|
173
170
|
initialized.destroy();
|
|
174
171
|
return this;
|
|
@@ -228,31 +225,21 @@ var EventNotifier = class {
|
|
|
228
225
|
}
|
|
229
226
|
};
|
|
230
227
|
|
|
231
|
-
// src/
|
|
228
|
+
// src/ListenerManager.ts
|
|
232
229
|
var import_wonka3 = require("wonka");
|
|
233
|
-
var
|
|
230
|
+
var ListenerManager = class {
|
|
234
231
|
constructor() {
|
|
235
|
-
this.
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
}
|
|
241
|
-
this._subjects.clear();
|
|
242
|
-
}
|
|
243
|
-
delete(clientId) {
|
|
244
|
-
this.subject(clientId).next(null);
|
|
245
|
-
this._subjects.delete(clientId);
|
|
246
|
-
}
|
|
247
|
-
subject(clientId) {
|
|
248
|
-
const subject = this._subjects.get(clientId);
|
|
249
|
-
if (subject) return subject;
|
|
250
|
-
const newSubject = (0, import_wonka3.makeSubject)();
|
|
251
|
-
this._subjects.set(clientId, newSubject);
|
|
252
|
-
return newSubject;
|
|
232
|
+
this.subjects = {
|
|
233
|
+
close: (0, import_wonka3.makeSubject)(),
|
|
234
|
+
error: (0, import_wonka3.makeSubject)(),
|
|
235
|
+
message: (0, import_wonka3.makeSubject)(),
|
|
236
|
+
open: (0, import_wonka3.makeSubject)()
|
|
237
|
+
};
|
|
253
238
|
}
|
|
254
|
-
subscribe(
|
|
255
|
-
|
|
239
|
+
subscribe(kind, callback) {
|
|
240
|
+
var _a;
|
|
241
|
+
const source = (_a = this.subjects[kind]) == null ? void 0 : _a.source;
|
|
242
|
+
if (!source) return () => void 0;
|
|
256
243
|
return (0, import_wonka3.subscribe)(callback)(source).unsubscribe;
|
|
257
244
|
}
|
|
258
245
|
};
|
|
@@ -473,6 +460,9 @@ var UsersManager = class {
|
|
|
473
460
|
);
|
|
474
461
|
const presence = __spreadValues(__spreadValues(__spreadValues({}, this.initialPresence), cleanedPresence), cleanedPatch);
|
|
475
462
|
const validated = this._presence ? this._presence.parse(presence) : presence;
|
|
463
|
+
if (!!presence[PLUV_PRESENCE_META_KEY]) {
|
|
464
|
+
validated[PLUV_PRESENCE_META_KEY] = presence[PLUV_PRESENCE_META_KEY];
|
|
465
|
+
}
|
|
476
466
|
this._others.set(clientId, __spreadProps(__spreadValues({}, other), { presence: validated }));
|
|
477
467
|
return validated;
|
|
478
468
|
}
|
|
@@ -550,6 +540,43 @@ var UsersManager = class {
|
|
|
550
540
|
}
|
|
551
541
|
};
|
|
552
542
|
|
|
543
|
+
// src/UsersNotifier.ts
|
|
544
|
+
var import_wonka5 = require("wonka");
|
|
545
|
+
var UsersNotifier = class {
|
|
546
|
+
constructor() {
|
|
547
|
+
this.others = (0, import_wonka5.makeSubject)();
|
|
548
|
+
this._otherSubjects = /* @__PURE__ */ new Map();
|
|
549
|
+
}
|
|
550
|
+
clear() {
|
|
551
|
+
this._otherSubjects.forEach((subject) => {
|
|
552
|
+
subject.next(null);
|
|
553
|
+
});
|
|
554
|
+
this._otherSubjects.clear();
|
|
555
|
+
}
|
|
556
|
+
delete(clientId) {
|
|
557
|
+
this.other(clientId).next(null);
|
|
558
|
+
this._otherSubjects.delete(clientId);
|
|
559
|
+
}
|
|
560
|
+
other(clientId) {
|
|
561
|
+
const subject = this._otherSubjects.get(clientId);
|
|
562
|
+
if (subject) return subject;
|
|
563
|
+
const newSubject = (0, import_wonka5.makeSubject)();
|
|
564
|
+
this._otherSubjects.set(clientId, newSubject);
|
|
565
|
+
return newSubject;
|
|
566
|
+
}
|
|
567
|
+
subscribeOther(clientId, callback) {
|
|
568
|
+
const source = this.other(clientId).source;
|
|
569
|
+
const subscription = (0, import_wonka5.subscribe)(callback)(source);
|
|
570
|
+
return subscription.unsubscribe;
|
|
571
|
+
}
|
|
572
|
+
subscribeOthers(callback) {
|
|
573
|
+
const subscription = (0, import_wonka5.subscribe)(
|
|
574
|
+
({ others, event }) => callback(others, event)
|
|
575
|
+
)(this.others.source);
|
|
576
|
+
return subscription.unsubscribe;
|
|
577
|
+
}
|
|
578
|
+
};
|
|
579
|
+
|
|
553
580
|
// src/PluvRoom.ts
|
|
554
581
|
var ADD_TO_STORAGE_STATE_DEBOUNCE_MS = 1e3;
|
|
555
582
|
var HEARTBEAT_INTERVAL_MS = 1e4;
|
|
@@ -569,7 +596,7 @@ var PluvRoom = class {
|
|
|
569
596
|
this._intervals = {
|
|
570
597
|
heartbeat: null
|
|
571
598
|
};
|
|
572
|
-
this.
|
|
599
|
+
this._listenerManager = new ListenerManager();
|
|
573
600
|
this._publicKey = null;
|
|
574
601
|
this._stateNotifier = new StateNotifier();
|
|
575
602
|
this._subscriptions = {
|
|
@@ -579,6 +606,7 @@ var PluvRoom = class {
|
|
|
579
606
|
pong: null,
|
|
580
607
|
reconnect: null
|
|
581
608
|
};
|
|
609
|
+
this._usersNotifier = new UsersNotifier();
|
|
582
610
|
this._lastMetadata = null;
|
|
583
611
|
this._state = {
|
|
584
612
|
authorization: {
|
|
@@ -587,10 +615,12 @@ var PluvRoom = class {
|
|
|
587
615
|
},
|
|
588
616
|
connection: {
|
|
589
617
|
attempts: 0,
|
|
590
|
-
count: 0,
|
|
591
618
|
id: null,
|
|
592
619
|
state: import_types.ConnectionState.Untouched
|
|
593
620
|
},
|
|
621
|
+
storage: {
|
|
622
|
+
state: import_types.StorageState.Unavailable
|
|
623
|
+
},
|
|
594
624
|
webSocket: null
|
|
595
625
|
};
|
|
596
626
|
this._windowListeners = null;
|
|
@@ -633,6 +663,9 @@ var PluvRoom = class {
|
|
|
633
663
|
this.canUndo = () => {
|
|
634
664
|
return !!this._crdtManager.doc.canUndo();
|
|
635
665
|
};
|
|
666
|
+
/**
|
|
667
|
+
* @deprecated To be removed in v3. Use PluvRoom.subscribe.event instead
|
|
668
|
+
*/
|
|
636
669
|
this.event = new Proxy(
|
|
637
670
|
(event, callback) => this._eventNotifier.subscribe(event, callback),
|
|
638
671
|
{
|
|
@@ -664,23 +697,80 @@ var PluvRoom = class {
|
|
|
664
697
|
if (typeof sharedType === "undefined") return null;
|
|
665
698
|
return sharedType;
|
|
666
699
|
};
|
|
700
|
+
this.getStorageLoaded = () => {
|
|
701
|
+
return this._state.storage.state === import_types.StorageState.Offline || this._state.storage.state === import_types.StorageState.Synced;
|
|
702
|
+
};
|
|
703
|
+
/**
|
|
704
|
+
* @deprecated To be removed in v3. Use PluvRoom.subscribe.other instead
|
|
705
|
+
*/
|
|
667
706
|
this.other = (connectionId, callback) => {
|
|
668
707
|
const clientId = this._usersManager.getClientId(connectionId);
|
|
669
708
|
if (!clientId) return () => void 0;
|
|
670
|
-
return this.
|
|
709
|
+
return this._usersNotifier.subscribeOther(clientId, callback);
|
|
671
710
|
};
|
|
672
711
|
this.redo = () => {
|
|
673
712
|
this._crdtManager.doc.redo();
|
|
674
713
|
};
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
this.
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
714
|
+
/**
|
|
715
|
+
* @deprecated To be removed in v3. Use PluvRoom.subscribe.storage instead
|
|
716
|
+
*/
|
|
717
|
+
this.storage = new Proxy(
|
|
718
|
+
(key, callback) => this._crdtNotifier.subscribe(key, callback),
|
|
719
|
+
{
|
|
720
|
+
get: (fn, prop) => {
|
|
721
|
+
if (!!prop) {
|
|
722
|
+
return (callback) => {
|
|
723
|
+
return this._crdtNotifier.subcribeRoot(callback);
|
|
724
|
+
};
|
|
725
|
+
}
|
|
726
|
+
return (callback) => {
|
|
727
|
+
return fn(prop, callback);
|
|
728
|
+
};
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
);
|
|
732
|
+
/**
|
|
733
|
+
* @deprecated To be removed in v3. Use PluvRoom.subscribe.storage instead
|
|
734
|
+
* @description Subscribes to the root storage object (serialized)
|
|
735
|
+
*/
|
|
736
|
+
this.storageRoot = (callback) => {
|
|
737
|
+
return this._crdtNotifier.subcribeRoot(callback);
|
|
683
738
|
};
|
|
739
|
+
this.subscribe = new Proxy(
|
|
740
|
+
(name, callback) => this._stateNotifier.subscribe(name, callback),
|
|
741
|
+
{
|
|
742
|
+
get: (fn, prop) => {
|
|
743
|
+
if (prop === "connection") {
|
|
744
|
+
return (callback) => {
|
|
745
|
+
return fn("connection", callback);
|
|
746
|
+
};
|
|
747
|
+
}
|
|
748
|
+
if (prop === "myPresence") {
|
|
749
|
+
return (callback) => {
|
|
750
|
+
return fn("my-presence", callback);
|
|
751
|
+
};
|
|
752
|
+
}
|
|
753
|
+
if (prop === "myself") {
|
|
754
|
+
return (callback) => {
|
|
755
|
+
return fn("myself", callback);
|
|
756
|
+
};
|
|
757
|
+
}
|
|
758
|
+
if (prop === "others") {
|
|
759
|
+
return (callback) => {
|
|
760
|
+
return this._usersNotifier.subscribeOthers(callback);
|
|
761
|
+
};
|
|
762
|
+
}
|
|
763
|
+
if (prop === "storageLoaded") {
|
|
764
|
+
return (callback) => {
|
|
765
|
+
return fn("storage-loaded", callback);
|
|
766
|
+
};
|
|
767
|
+
}
|
|
768
|
+
if (prop === "event") return this.event;
|
|
769
|
+
if (prop === "other") return this.other;
|
|
770
|
+
if (prop === "storage") return this.storage;
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
);
|
|
684
774
|
this.transact = (fn, origin) => {
|
|
685
775
|
const _origin = origin != null ? origin : this._state.connection.id;
|
|
686
776
|
if (typeof _origin !== "string") return;
|
|
@@ -760,12 +850,18 @@ var PluvRoom = class {
|
|
|
760
850
|
});
|
|
761
851
|
this._crdtManager = new CrdtManager({ initialStorage });
|
|
762
852
|
}
|
|
853
|
+
/**
|
|
854
|
+
* @deprecated To be removed in v3. Use `getStorageLoaded` instead.
|
|
855
|
+
*/
|
|
763
856
|
get storageLoaded() {
|
|
764
|
-
return this.
|
|
857
|
+
return this.getStorageLoaded();
|
|
765
858
|
}
|
|
766
859
|
get webSocket() {
|
|
767
860
|
return this._state.webSocket;
|
|
768
861
|
}
|
|
862
|
+
addEventListener(kind, handler) {
|
|
863
|
+
return this._listenerManager.subscribe(kind, handler);
|
|
864
|
+
}
|
|
769
865
|
connect(...args) {
|
|
770
866
|
return __async(this, null, function* () {
|
|
771
867
|
var _a;
|
|
@@ -807,6 +903,7 @@ var PluvRoom = class {
|
|
|
807
903
|
this._updateState((oldState) => {
|
|
808
904
|
oldState.connection.attempts = 0;
|
|
809
905
|
oldState.authorization.token = authToken;
|
|
906
|
+
oldState.storage.state = import_types.StorageState.Loading;
|
|
810
907
|
oldState.webSocket = webSocket;
|
|
811
908
|
return oldState;
|
|
812
909
|
});
|
|
@@ -827,6 +924,7 @@ var PluvRoom = class {
|
|
|
827
924
|
this._updateState((oldState) => {
|
|
828
925
|
oldState.authorization.token = null;
|
|
829
926
|
oldState.connection.state = import_types.ConnectionState.Closed;
|
|
927
|
+
oldState.storage.state = oldState.storage.state === import_types.StorageState.Synced ? import_types.StorageState.Offline : import_types.StorageState.Unavailable;
|
|
830
928
|
oldState.webSocket = null;
|
|
831
929
|
return oldState;
|
|
832
930
|
});
|
|
@@ -891,9 +989,10 @@ var PluvRoom = class {
|
|
|
891
989
|
this._detachWindowListeners();
|
|
892
990
|
this._usersManager.removeMyself();
|
|
893
991
|
this._usersManager.clearConnections();
|
|
894
|
-
this.
|
|
992
|
+
this._usersNotifier.clear();
|
|
895
993
|
this._stateNotifier.subjects.myself.next(null);
|
|
896
994
|
this._stateNotifier.subjects.others.next([]);
|
|
995
|
+
this._usersNotifier.others.next({ others: [], event: { kind: "clear" } });
|
|
897
996
|
(_c = this._state.webSocket) == null ? void 0 : _c.close();
|
|
898
997
|
this._detachWsListeners();
|
|
899
998
|
}
|
|
@@ -984,7 +1083,16 @@ var PluvRoom = class {
|
|
|
984
1083
|
const deleted = this._usersManager.deleteConnection(connectionId);
|
|
985
1084
|
const others = this._usersManager.getOthers();
|
|
986
1085
|
this._stateNotifier.subjects.others.next(others);
|
|
987
|
-
if (!
|
|
1086
|
+
if (!deleted) {
|
|
1087
|
+
console.warn("Could not identify exited connection");
|
|
1088
|
+
return;
|
|
1089
|
+
}
|
|
1090
|
+
const { data: user, remaining } = deleted;
|
|
1091
|
+
this._usersNotifier.others.next({
|
|
1092
|
+
others,
|
|
1093
|
+
event: { kind: "leave", user }
|
|
1094
|
+
});
|
|
1095
|
+
if (!remaining && !!clientId) this._usersNotifier.delete(clientId);
|
|
988
1096
|
}
|
|
989
1097
|
_handlePresenceUpdatedMessage(message) {
|
|
990
1098
|
var _a;
|
|
@@ -1003,19 +1111,31 @@ var PluvRoom = class {
|
|
|
1003
1111
|
return;
|
|
1004
1112
|
}
|
|
1005
1113
|
if (!!clientId) {
|
|
1006
|
-
const
|
|
1007
|
-
this.
|
|
1008
|
-
|
|
1009
|
-
|
|
1010
|
-
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
|
|
1114
|
+
const other2 = this._usersManager.getOther(connectionId);
|
|
1115
|
+
const others2 = this._usersManager.getOthers();
|
|
1116
|
+
this._usersNotifier.other(clientId).next(other2);
|
|
1117
|
+
this._stateNotifier.subjects.others.next(others2);
|
|
1118
|
+
if (!!other2) {
|
|
1119
|
+
this._usersNotifier.others.next({
|
|
1120
|
+
others: others2,
|
|
1121
|
+
event: { kind: "update", user: other2 }
|
|
1122
|
+
});
|
|
1123
|
+
}
|
|
1124
|
+
return;
|
|
1016
1125
|
}
|
|
1126
|
+
const added = this._usersManager.addConnection({
|
|
1127
|
+
connectionId,
|
|
1128
|
+
presence: data.presence,
|
|
1129
|
+
user: message.user
|
|
1130
|
+
});
|
|
1131
|
+
const other = this._usersManager.getOther(connectionId);
|
|
1017
1132
|
const others = this._usersManager.getOthers();
|
|
1133
|
+
this._usersNotifier.other(added.clientId).next(other);
|
|
1018
1134
|
this._stateNotifier.subjects.others.next(others);
|
|
1135
|
+
this._usersNotifier.others.next({
|
|
1136
|
+
others,
|
|
1137
|
+
event: { kind: "update", user: added.data }
|
|
1138
|
+
});
|
|
1019
1139
|
}
|
|
1020
1140
|
_handleReceiveOthers(message) {
|
|
1021
1141
|
if (!message.connectionId) return;
|
|
@@ -1032,10 +1152,14 @@ var PluvRoom = class {
|
|
|
1032
1152
|
if (result.isMyself) return;
|
|
1033
1153
|
const clientId = result.clientId;
|
|
1034
1154
|
const other = this._usersManager.getOther(connectionId);
|
|
1035
|
-
this.
|
|
1155
|
+
this._usersNotifier.other(clientId).next(other);
|
|
1036
1156
|
});
|
|
1037
1157
|
const others = this._usersManager.getOthers();
|
|
1038
1158
|
this._stateNotifier.subjects.others.next(others);
|
|
1159
|
+
this._usersNotifier.others.next({
|
|
1160
|
+
others,
|
|
1161
|
+
event: { kind: "sync", users: others }
|
|
1162
|
+
});
|
|
1039
1163
|
}
|
|
1040
1164
|
_handleRegisteredMessage(message) {
|
|
1041
1165
|
return __async(this, null, function* () {
|
|
@@ -1047,7 +1171,6 @@ var PluvRoom = class {
|
|
|
1047
1171
|
const data = message.data;
|
|
1048
1172
|
const state = data.state;
|
|
1049
1173
|
this._updateState((oldState) => {
|
|
1050
|
-
oldState.connection.count += 1;
|
|
1051
1174
|
oldState.connection.id = connectionId;
|
|
1052
1175
|
oldState.authorization.user = user != null ? user : null;
|
|
1053
1176
|
return oldState;
|
|
@@ -1099,6 +1222,10 @@ var PluvRoom = class {
|
|
|
1099
1222
|
const encodedState = this._crdtManager.doc.getEncodedState();
|
|
1100
1223
|
this._emitSharedTypes();
|
|
1101
1224
|
this._observeCrdt();
|
|
1225
|
+
this._updateState((oldState) => {
|
|
1226
|
+
oldState.storage.state = import_types.StorageState.Synced;
|
|
1227
|
+
return oldState;
|
|
1228
|
+
});
|
|
1102
1229
|
this._stateNotifier.subjects["storage-loaded"].next(true);
|
|
1103
1230
|
this._sendMessage({
|
|
1104
1231
|
type: "$updateStorage",
|
|
@@ -1137,6 +1264,11 @@ var PluvRoom = class {
|
|
|
1137
1264
|
const quitters = this._usersManager.getOthers().filter((other) => !active.has(other.connectionId));
|
|
1138
1265
|
quitters.forEach((quitter) => {
|
|
1139
1266
|
this._usersManager.deleteConnection(quitter.connectionId);
|
|
1267
|
+
const remaining2 = this._usersManager.getOthers();
|
|
1268
|
+
this._usersNotifier.others.next({
|
|
1269
|
+
others: remaining2,
|
|
1270
|
+
event: { kind: "leave", user: quitter }
|
|
1271
|
+
});
|
|
1140
1272
|
});
|
|
1141
1273
|
const remaining = this._usersManager.getOthers();
|
|
1142
1274
|
this._stateNotifier.subjects.others.next(remaining);
|
|
@@ -1159,8 +1291,12 @@ var PluvRoom = class {
|
|
|
1159
1291
|
});
|
|
1160
1292
|
const other = this._usersManager.getOther(connectionId);
|
|
1161
1293
|
const others = this._usersManager.getOthers();
|
|
1162
|
-
this.
|
|
1294
|
+
this._usersNotifier.other(added.clientId).next(other);
|
|
1163
1295
|
this._stateNotifier.subjects.others.next(others);
|
|
1296
|
+
this._usersNotifier.others.next({
|
|
1297
|
+
others,
|
|
1298
|
+
event: { kind: "enter", user: added.data }
|
|
1299
|
+
});
|
|
1164
1300
|
}
|
|
1165
1301
|
_heartbeat() {
|
|
1166
1302
|
this._clearTimeout(this._timeouts.pong);
|
|
@@ -1202,11 +1338,13 @@ var PluvRoom = class {
|
|
|
1202
1338
|
this._listeners.onAuthorizationFail(authError);
|
|
1203
1339
|
this._updateState((oldState) => {
|
|
1204
1340
|
oldState.connection.state = import_types.ConnectionState.Unavailable;
|
|
1341
|
+
oldState.storage.state = import_types.StorageState.Unavailable;
|
|
1205
1342
|
return oldState;
|
|
1206
1343
|
});
|
|
1207
1344
|
}
|
|
1208
1345
|
_onClose(event) {
|
|
1209
1346
|
return __async(this, null, function* () {
|
|
1347
|
+
this._listenerManager.subjects.close.next(event);
|
|
1210
1348
|
this._logDebug("WebSocket closed");
|
|
1211
1349
|
if (!!event.reason) this._logDebug(event.reason);
|
|
1212
1350
|
const shouldRetry = [
|
|
@@ -1234,6 +1372,7 @@ var PluvRoom = class {
|
|
|
1234
1372
|
*/
|
|
1235
1373
|
import_types.ConnectionState.Closed
|
|
1236
1374
|
);
|
|
1375
|
+
oldState.storage.state = oldState.storage.state === import_types.StorageState.Synced ? import_types.StorageState.Offline : import_types.StorageState.Unavailable;
|
|
1237
1376
|
oldState.webSocket = null;
|
|
1238
1377
|
return oldState;
|
|
1239
1378
|
});
|
|
@@ -1250,9 +1389,11 @@ var PluvRoom = class {
|
|
|
1250
1389
|
* @description Handle websocket errors in a meaningful way, should they occur
|
|
1251
1390
|
* @date August 19, 2022
|
|
1252
1391
|
*/
|
|
1253
|
-
_onError() {
|
|
1392
|
+
_onError(event) {
|
|
1393
|
+
this._listenerManager.subjects.error.next(event);
|
|
1254
1394
|
}
|
|
1255
1395
|
_onMessage(event) {
|
|
1396
|
+
this._listenerManager.subjects.message.next(event);
|
|
1256
1397
|
const message = this._parseMessage(event);
|
|
1257
1398
|
if (!message) return;
|
|
1258
1399
|
const shouldLog = typeof this._debug === "boolean" ? this._debug : this._debug.output.find((value) => value === message.type);
|
|
@@ -1300,7 +1441,8 @@ var PluvRoom = class {
|
|
|
1300
1441
|
default:
|
|
1301
1442
|
}
|
|
1302
1443
|
}
|
|
1303
|
-
_onOpen() {
|
|
1444
|
+
_onOpen(event) {
|
|
1445
|
+
this._listenerManager.subjects.open.next(event);
|
|
1304
1446
|
if (this._state.connection.state !== import_types.ConnectionState.Connecting) return;
|
|
1305
1447
|
this._logDebug("WebSocket connected");
|
|
1306
1448
|
this._updateState((oldState) => {
|
|
@@ -1318,6 +1460,7 @@ var PluvRoom = class {
|
|
|
1318
1460
|
if (this._state.connection.state === import_types.ConnectionState.Closed) return;
|
|
1319
1461
|
this._updateState((oldState) => {
|
|
1320
1462
|
oldState.connection.state = import_types.ConnectionState.Unavailable;
|
|
1463
|
+
oldState.storage.state = oldState.storage.state === import_types.StorageState.Synced ? import_types.StorageState.Offline : import_types.StorageState.Unavailable;
|
|
1321
1464
|
return oldState;
|
|
1322
1465
|
});
|
|
1323
1466
|
});
|
|
@@ -1417,6 +1560,7 @@ var PluvRoom = class {
|
|
|
1417
1560
|
const oldState = __spreadProps(__spreadValues({}, this._state), {
|
|
1418
1561
|
authorization,
|
|
1419
1562
|
connection: JSON.parse(JSON.stringify(this._state.connection)),
|
|
1563
|
+
storage: JSON.parse(JSON.stringify(this._state.storage)),
|
|
1420
1564
|
webSocket: this._state.webSocket
|
|
1421
1565
|
});
|
|
1422
1566
|
const newState = updater(oldState);
|
|
@@ -1533,9 +1677,13 @@ var infer = (callback) => callback;
|
|
|
1533
1677
|
var import_types2 = require("@pluv/types");
|
|
1534
1678
|
var MockedRoom = class {
|
|
1535
1679
|
constructor(room, options) {
|
|
1680
|
+
/**
|
|
1681
|
+
* @deprecated To be removed in v3. Use `getStorageLoaded` instead.
|
|
1682
|
+
*/
|
|
1683
|
+
this.storageLoaded = true;
|
|
1536
1684
|
this._crdtNotifier = new CrdtNotifier();
|
|
1537
1685
|
this._eventNotifier = new EventNotifier();
|
|
1538
|
-
this.
|
|
1686
|
+
this._usersNotifier = new UsersNotifier();
|
|
1539
1687
|
this._state = {
|
|
1540
1688
|
authorization: {
|
|
1541
1689
|
token: null,
|
|
@@ -1543,10 +1691,12 @@ var MockedRoom = class {
|
|
|
1543
1691
|
},
|
|
1544
1692
|
connection: {
|
|
1545
1693
|
attempts: 0,
|
|
1546
|
-
count: 1,
|
|
1547
1694
|
id: null,
|
|
1548
1695
|
state: import_types2.ConnectionState.Untouched
|
|
1549
1696
|
},
|
|
1697
|
+
storage: {
|
|
1698
|
+
state: import_types2.StorageState.Unavailable
|
|
1699
|
+
},
|
|
1550
1700
|
webSocket: null
|
|
1551
1701
|
};
|
|
1552
1702
|
this._stateNotifier = new StateNotifier();
|
|
@@ -1622,20 +1772,66 @@ var MockedRoom = class {
|
|
|
1622
1772
|
this.other = (connectionId, callback) => {
|
|
1623
1773
|
const clientId = this._usersManager.getClientId(connectionId);
|
|
1624
1774
|
if (!clientId) return () => void 0;
|
|
1625
|
-
return this.
|
|
1775
|
+
return this._usersNotifier.subscribeOther(clientId, callback);
|
|
1626
1776
|
};
|
|
1627
1777
|
this.redo = () => {
|
|
1628
1778
|
this._crdtManager.doc.redo();
|
|
1629
1779
|
};
|
|
1630
|
-
this.storage = (
|
|
1631
|
-
|
|
1632
|
-
|
|
1780
|
+
this.storage = new Proxy(
|
|
1781
|
+
(key, callback) => this._crdtNotifier.subscribe(key, callback),
|
|
1782
|
+
{
|
|
1783
|
+
get: (fn, prop) => {
|
|
1784
|
+
if (!!prop) {
|
|
1785
|
+
return (callback) => {
|
|
1786
|
+
return this._crdtNotifier.subcribeRoot(callback);
|
|
1787
|
+
};
|
|
1788
|
+
}
|
|
1789
|
+
return (callback) => {
|
|
1790
|
+
return fn(prop, callback);
|
|
1791
|
+
};
|
|
1792
|
+
}
|
|
1793
|
+
}
|
|
1794
|
+
);
|
|
1633
1795
|
this.storageRoot = (fn) => {
|
|
1634
1796
|
return this._crdtNotifier.subcribeRoot(fn);
|
|
1635
1797
|
};
|
|
1636
|
-
this.subscribe = (
|
|
1637
|
-
|
|
1638
|
-
|
|
1798
|
+
this.subscribe = new Proxy(
|
|
1799
|
+
(name, callback) => {
|
|
1800
|
+
return this._stateNotifier.subscribe(name, callback);
|
|
1801
|
+
},
|
|
1802
|
+
{
|
|
1803
|
+
get: (fn, prop) => {
|
|
1804
|
+
if (prop === "connection") {
|
|
1805
|
+
return (callback) => {
|
|
1806
|
+
return fn("connection", callback);
|
|
1807
|
+
};
|
|
1808
|
+
}
|
|
1809
|
+
if (prop === "myPresence") {
|
|
1810
|
+
return (callback) => {
|
|
1811
|
+
return fn("my-presence", callback);
|
|
1812
|
+
};
|
|
1813
|
+
}
|
|
1814
|
+
if (prop === "myself") {
|
|
1815
|
+
return (callback) => {
|
|
1816
|
+
return fn("myself", callback);
|
|
1817
|
+
};
|
|
1818
|
+
}
|
|
1819
|
+
if (prop === "others") {
|
|
1820
|
+
return (callback) => {
|
|
1821
|
+
return this._usersNotifier.subscribeOthers(callback);
|
|
1822
|
+
};
|
|
1823
|
+
}
|
|
1824
|
+
if (prop === "storageLoaded") {
|
|
1825
|
+
return (callback) => {
|
|
1826
|
+
return fn("storage-loaded", callback);
|
|
1827
|
+
};
|
|
1828
|
+
}
|
|
1829
|
+
if (prop === "event") return this.event;
|
|
1830
|
+
if (prop === "other") return this.other;
|
|
1831
|
+
if (prop === "storage") return this.storage;
|
|
1832
|
+
}
|
|
1833
|
+
}
|
|
1834
|
+
);
|
|
1639
1835
|
this.transact = (fn, origin) => {
|
|
1640
1836
|
const _origin = origin != null ? origin : this._state.connection.id;
|
|
1641
1837
|
const crdtManager = this._crdtManager;
|
|
@@ -1675,8 +1871,8 @@ var MockedRoom = class {
|
|
|
1675
1871
|
});
|
|
1676
1872
|
this._observeCrdt();
|
|
1677
1873
|
}
|
|
1678
|
-
|
|
1679
|
-
return
|
|
1874
|
+
addEventListener(kind, handler) {
|
|
1875
|
+
return () => void 0;
|
|
1680
1876
|
}
|
|
1681
1877
|
getDoc() {
|
|
1682
1878
|
return this._crdtManager.doc;
|
|
@@ -1686,6 +1882,9 @@ var MockedRoom = class {
|
|
|
1686
1882
|
if (typeof type === "undefined") return this._crdtManager.doc.toJson();
|
|
1687
1883
|
return this._crdtManager.doc.toJson(type);
|
|
1688
1884
|
}
|
|
1885
|
+
getStorageLoaded() {
|
|
1886
|
+
return true;
|
|
1887
|
+
}
|
|
1689
1888
|
_observeCrdt() {
|
|
1690
1889
|
var _a, _b;
|
|
1691
1890
|
(_b = (_a = this._subscriptions).observeCrdt) == null ? void 0 : _b.call(_a);
|