@pluv/client 0.38.13 → 0.39.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 +76 -0
- package/dist/index.d.mts +132 -115
- package/dist/index.d.ts +132 -115
- package/dist/index.js +101 -76
- package/dist/index.mjs +101 -76
- package/eslint.config.mjs +4 -0
- package/package.json +7 -7
- package/src/MockedRoom.ts +1 -0
- package/src/PluvClient.ts +25 -11
- package/src/PluvRoom.ts +135 -79
- package/src/UsersManager.ts +3 -9
- package/src/index.ts +10 -3
- package/src/types.ts +21 -0
- package/.eslintrc.js +0 -4
package/dist/index.mjs
CHANGED
|
@@ -316,9 +316,7 @@ var UsersManager = class {
|
|
|
316
316
|
patchPresence(connectionId, patch) {
|
|
317
317
|
var _a, _b;
|
|
318
318
|
if (((_a = this._myself) == null ? void 0 : _a.connectionId) === connectionId) {
|
|
319
|
-
|
|
320
|
-
this._myself.presence = presence2;
|
|
321
|
-
this._myPresence = presence2;
|
|
319
|
+
this.updateMyPresence(patch);
|
|
322
320
|
return;
|
|
323
321
|
}
|
|
324
322
|
const other = this._others.get(connectionId);
|
|
@@ -369,8 +367,8 @@ var UsersManager = class {
|
|
|
369
367
|
/**
|
|
370
368
|
* @description This method need not care about being connected.
|
|
371
369
|
*/
|
|
372
|
-
updateMyPresence(
|
|
373
|
-
this._myPresence = __spreadValues(__spreadValues({}, this._myPresence),
|
|
370
|
+
updateMyPresence(patch) {
|
|
371
|
+
this._myPresence = __spreadValues(__spreadValues({}, this._myPresence), patch);
|
|
374
372
|
if (!this._myself) return;
|
|
375
373
|
this._myself.presence = this._myPresence;
|
|
376
374
|
}
|
|
@@ -409,7 +407,9 @@ var debounce = (fn, options) => {
|
|
|
409
407
|
var ADD_TO_STORAGE_STATE_DEBOUNCE_MS = 1e3;
|
|
410
408
|
var HEARTBEAT_INTERVAL_MS = 1e4;
|
|
411
409
|
var PONG_TIMEOUT_MS = 2e3;
|
|
412
|
-
var RECONNECT_TIMEOUT_MS =
|
|
410
|
+
var RECONNECT_TIMEOUT_MS = 5e3;
|
|
411
|
+
var MIN_RECONNECT_TIMEOUT_MS = 1e3;
|
|
412
|
+
var MAX_RECONNECT_TIMEOUT_MS = 6e4;
|
|
413
413
|
var ORIGIN_INITIALIZED = "$initialized";
|
|
414
414
|
var ORIGIN_STORAGE_UPDATED = "$storageUpdated";
|
|
415
415
|
var DEFAULT_PLUV_CLIENT_ADDON = (input) => ({
|
|
@@ -427,6 +427,7 @@ var PluvRoom = class extends AbstractRoom {
|
|
|
427
427
|
onAuthorizationFail,
|
|
428
428
|
presence,
|
|
429
429
|
publicKey,
|
|
430
|
+
reconnectTimeoutMs = RECONNECT_TIMEOUT_MS,
|
|
430
431
|
router,
|
|
431
432
|
wsEndpoint
|
|
432
433
|
} = options;
|
|
@@ -436,7 +437,6 @@ var PluvRoom = class extends AbstractRoom {
|
|
|
436
437
|
this._intervals = {
|
|
437
438
|
heartbeat: null
|
|
438
439
|
};
|
|
439
|
-
this._metadata = {};
|
|
440
440
|
this._otherNotifier = new OtherNotifier();
|
|
441
441
|
this._publicKey = null;
|
|
442
442
|
this._stateNotifier = new StateNotifier();
|
|
@@ -447,12 +447,14 @@ var PluvRoom = class extends AbstractRoom {
|
|
|
447
447
|
pong: null,
|
|
448
448
|
reconnect: null
|
|
449
449
|
};
|
|
450
|
+
this._lastMetadata = null;
|
|
450
451
|
this._state = {
|
|
451
452
|
authorization: {
|
|
452
453
|
token: null,
|
|
453
454
|
user: null
|
|
454
455
|
},
|
|
455
456
|
connection: {
|
|
457
|
+
attempts: 0,
|
|
456
458
|
count: 0,
|
|
457
459
|
id: null,
|
|
458
460
|
state: "Untouched" /* Untouched */
|
|
@@ -591,18 +593,14 @@ var PluvRoom = class extends AbstractRoom {
|
|
|
591
593
|
};
|
|
592
594
|
const addon = this._getAddon(addons);
|
|
593
595
|
const { storage } = __spreadValues(__spreadValues({}, DEFAULT_PLUV_CLIENT_ADDON({ room: this })), addon({ room: this }));
|
|
596
|
+
this.metadata = metadata;
|
|
594
597
|
this._debug = debug;
|
|
595
598
|
this._endpoints = { authEndpoint, wsEndpoint };
|
|
599
|
+
this._reconnectTimeoutMs = reconnectTimeoutMs;
|
|
596
600
|
this._storageStore = storage;
|
|
597
|
-
if (typeof metadata !== "undefined") this._metadata = metadata;
|
|
598
601
|
if (!!publicKey) this._publicKey = publicKey;
|
|
599
602
|
this._listeners = {
|
|
600
603
|
onAuthorizationFail: (error) => {
|
|
601
|
-
this._clearTimeout(this._timeouts.reconnect);
|
|
602
|
-
this._timeouts.reconnect = setTimeout(
|
|
603
|
-
this._reconnect.bind(this),
|
|
604
|
-
RECONNECT_TIMEOUT_MS
|
|
605
|
-
);
|
|
606
604
|
onAuthorizationFail == null ? void 0 : onAuthorizationFail(error);
|
|
607
605
|
}
|
|
608
606
|
};
|
|
@@ -616,11 +614,13 @@ var PluvRoom = class extends AbstractRoom {
|
|
|
616
614
|
get webSocket() {
|
|
617
615
|
return this._state.webSocket;
|
|
618
616
|
}
|
|
619
|
-
connect() {
|
|
617
|
+
connect(...args) {
|
|
620
618
|
return __async(this, null, function* () {
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
619
|
+
var _a;
|
|
620
|
+
const params = (_a = args[0]) != null ? _a : {};
|
|
621
|
+
const metadata = params.metadata;
|
|
622
|
+
this._setMetadata(metadata);
|
|
623
|
+
if (!this._endpoints.wsEndpoint) throw new Error("Must provide a wsEndpoint.");
|
|
624
624
|
const canConnect = ["Closed" /* Closed */, "Untouched" /* Untouched */].some(
|
|
625
625
|
(state) => this._state.connection.state === state
|
|
626
626
|
);
|
|
@@ -632,21 +632,27 @@ var PluvRoom = class extends AbstractRoom {
|
|
|
632
632
|
});
|
|
633
633
|
yield this._storageStore.initialize();
|
|
634
634
|
yield this._applyStorageStore();
|
|
635
|
-
const url = new URL(this._getWsEndpoint(this.id));
|
|
635
|
+
const url = new URL(this._getWsEndpoint(this.id, params));
|
|
636
636
|
let authToken = null;
|
|
637
637
|
let webSocket;
|
|
638
638
|
try {
|
|
639
|
-
const publicKey = this._getPublicKey();
|
|
640
|
-
authToken = yield this._getAuthorization(this.id);
|
|
639
|
+
const publicKey = this._getPublicKey(params);
|
|
640
|
+
authToken = yield this._getAuthorization(this.id, params);
|
|
641
641
|
authToken && url.searchParams.set("token", encodeURIComponent(authToken));
|
|
642
642
|
publicKey && url.searchParams.set("public_key", encodeURIComponent(publicKey));
|
|
643
643
|
webSocket = new WebSocket(url.toString());
|
|
644
644
|
} catch (err) {
|
|
645
|
+
this._updateState((oldState) => {
|
|
646
|
+
oldState.connection.attempts += 1;
|
|
647
|
+
return oldState;
|
|
648
|
+
});
|
|
645
649
|
yield this._storageStore.destroy();
|
|
646
|
-
this.
|
|
650
|
+
this._pollReconnect();
|
|
651
|
+
yield Promise.resolve(this._onAuthorizationFail(err));
|
|
647
652
|
return;
|
|
648
653
|
}
|
|
649
654
|
this._updateState((oldState) => {
|
|
655
|
+
oldState.connection.attempts = 0;
|
|
650
656
|
oldState.authorization.token = authToken;
|
|
651
657
|
oldState.webSocket = webSocket;
|
|
652
658
|
return oldState;
|
|
@@ -657,16 +663,21 @@ var PluvRoom = class extends AbstractRoom {
|
|
|
657
663
|
}
|
|
658
664
|
disconnect() {
|
|
659
665
|
return __async(this, null, function* () {
|
|
660
|
-
if (!this._endpoints.wsEndpoint)
|
|
661
|
-
throw new Error("Must provide an wsEndpoint.");
|
|
662
|
-
}
|
|
666
|
+
if (!this._endpoints.wsEndpoint) throw new Error("Must provide a wsEndpoint.");
|
|
663
667
|
if (!this._state.webSocket) return;
|
|
664
668
|
const canDisconnect = ["Connecting" /* Connecting */, "Open" /* Open */].some(
|
|
665
669
|
(state) => this._state.connection.state === state
|
|
666
670
|
);
|
|
667
671
|
if (!canDisconnect) return;
|
|
668
|
-
this._clearInterval(this._intervals.heartbeat);
|
|
669
672
|
this._closeWs();
|
|
673
|
+
this._clearInterval(this._intervals.heartbeat);
|
|
674
|
+
this._clearTimeout(this._timeouts.reconnect);
|
|
675
|
+
this._updateState((oldState) => {
|
|
676
|
+
oldState.authorization.token = null;
|
|
677
|
+
oldState.connection.state = "Closed" /* Closed */;
|
|
678
|
+
oldState.webSocket = null;
|
|
679
|
+
return oldState;
|
|
680
|
+
});
|
|
670
681
|
yield this._storageStore.destroy();
|
|
671
682
|
this._crdtManager.destroy();
|
|
672
683
|
this._stateNotifier.subjects["my-presence"].next(null);
|
|
@@ -703,9 +714,11 @@ var PluvRoom = class extends AbstractRoom {
|
|
|
703
714
|
if (typeof window === "undefined") return;
|
|
704
715
|
if (typeof document === "undefined") return;
|
|
705
716
|
this._windowListeners = {
|
|
717
|
+
onNavigatorOffline: this._onNavigatorOffline.bind(this),
|
|
706
718
|
onNavigatorOnline: this._onNavigatorOnline.bind(this),
|
|
707
719
|
onVisibilityChange: this._onVisibilityChange.bind(this)
|
|
708
720
|
};
|
|
721
|
+
window.addEventListener("offline", this._windowListeners.onNavigatorOffline);
|
|
709
722
|
window.addEventListener("online", this._windowListeners.onNavigatorOnline);
|
|
710
723
|
document.addEventListener("visibilitychange", this._windowListeners.onVisibilityChange);
|
|
711
724
|
}
|
|
@@ -731,24 +744,17 @@ var PluvRoom = class extends AbstractRoom {
|
|
|
731
744
|
clearTimeout(timeout);
|
|
732
745
|
}
|
|
733
746
|
_closeWs() {
|
|
734
|
-
var _a, _b;
|
|
735
|
-
if (!this._state.webSocket) return;
|
|
747
|
+
var _a, _b, _c;
|
|
736
748
|
(_b = (_a = this._subscriptions).observeCrdt) == null ? void 0 : _b.call(_a);
|
|
749
|
+
this._clearInterval(this._intervals.heartbeat);
|
|
737
750
|
this._clearTimeout(this._timeouts.pong);
|
|
738
|
-
this._clearTimeout(this._timeouts.reconnect);
|
|
739
751
|
this._detachWindowListeners();
|
|
740
752
|
this._usersManager.removeMyself();
|
|
741
753
|
this._usersManager.removeUsers();
|
|
742
754
|
this._otherNotifier.clear();
|
|
743
755
|
this._stateNotifier.subjects.myself.next(null);
|
|
744
756
|
this._stateNotifier.subjects.others.next([]);
|
|
745
|
-
|
|
746
|
-
(readyState) => {
|
|
747
|
-
var _a2;
|
|
748
|
-
return readyState === ((_a2 = this._state.webSocket) == null ? void 0 : _a2.readyState);
|
|
749
|
-
}
|
|
750
|
-
);
|
|
751
|
-
if (canClose) this._state.webSocket.close();
|
|
757
|
+
(_c = this._state.webSocket) == null ? void 0 : _c.close();
|
|
752
758
|
this._detachWsListeners();
|
|
753
759
|
}
|
|
754
760
|
_detachWindowListeners() {
|
|
@@ -779,7 +785,8 @@ var PluvRoom = class extends AbstractRoom {
|
|
|
779
785
|
);
|
|
780
786
|
this._crdtNotifier.rootSubject.next(storageRoot);
|
|
781
787
|
}
|
|
782
|
-
_getAuthFetchOptions(room) {
|
|
788
|
+
_getAuthFetchOptions(room, params) {
|
|
789
|
+
const metadata = params.metadata;
|
|
783
790
|
if (typeof this._endpoints.authEndpoint === "undefined") return null;
|
|
784
791
|
if (this._endpoints.authEndpoint === true) {
|
|
785
792
|
return {
|
|
@@ -793,18 +800,16 @@ var PluvRoom = class extends AbstractRoom {
|
|
|
793
800
|
options: {}
|
|
794
801
|
};
|
|
795
802
|
}
|
|
796
|
-
const result = this._endpoints.authEndpoint({ metadata
|
|
803
|
+
const result = this._endpoints.authEndpoint({ metadata, room });
|
|
797
804
|
return typeof result === "string" ? { url: result, options: {} } : result;
|
|
798
805
|
}
|
|
799
|
-
_getAuthorization(room) {
|
|
806
|
+
_getAuthorization(room, params) {
|
|
800
807
|
return __async(this, null, function* () {
|
|
801
|
-
const fetchOptions = this._getAuthFetchOptions(room);
|
|
808
|
+
const fetchOptions = this._getAuthFetchOptions(room, params);
|
|
802
809
|
if (!fetchOptions) return null;
|
|
803
810
|
const { url, options } = fetchOptions;
|
|
804
811
|
const res = yield fetch(url, options);
|
|
805
|
-
if (!res.ok || res.status !== 200)
|
|
806
|
-
throw new Error("Room is unauthorized");
|
|
807
|
-
}
|
|
812
|
+
if (!res.ok || res.status !== 200) throw new Error("Room is unauthorized");
|
|
808
813
|
try {
|
|
809
814
|
return yield res.text().then((text) => text.trim());
|
|
810
815
|
} catch (err) {
|
|
@@ -812,19 +817,21 @@ var PluvRoom = class extends AbstractRoom {
|
|
|
812
817
|
}
|
|
813
818
|
});
|
|
814
819
|
}
|
|
815
|
-
_getPublicKey() {
|
|
820
|
+
_getPublicKey(params) {
|
|
821
|
+
const metadata = params.metadata;
|
|
816
822
|
if (!this._publicKey) return null;
|
|
817
823
|
if (typeof this._publicKey === "string") return this._publicKey;
|
|
818
|
-
return this._publicKey({ metadata
|
|
824
|
+
return this._publicKey({ metadata });
|
|
819
825
|
}
|
|
820
|
-
_getWsEndpoint(room) {
|
|
826
|
+
_getWsEndpoint(room, params) {
|
|
827
|
+
const metadata = params.metadata;
|
|
821
828
|
switch (typeof this._endpoints.wsEndpoint) {
|
|
822
829
|
case "undefined":
|
|
823
|
-
return !!this._getPublicKey() ? `wss://rooms.pluv.io/api/room/${room}` : `/api/pluv/room/${room}`;
|
|
830
|
+
return !!this._getPublicKey(params) ? `wss://rooms.pluv.io/api/room/${room}` : `/api/pluv/room/${room}`;
|
|
824
831
|
case "string":
|
|
825
832
|
return this._endpoints.wsEndpoint;
|
|
826
833
|
default:
|
|
827
|
-
return this._endpoints.wsEndpoint({ metadata
|
|
834
|
+
return this._endpoints.wsEndpoint({ metadata, room });
|
|
828
835
|
}
|
|
829
836
|
}
|
|
830
837
|
_handleExit(message) {
|
|
@@ -843,10 +850,9 @@ var PluvRoom = class extends AbstractRoom {
|
|
|
843
850
|
if (!connectionId) return;
|
|
844
851
|
if (!this._state.webSocket) throw new Error("Could not find WebSocket");
|
|
845
852
|
const data = message.data;
|
|
846
|
-
this._usersManager.patchPresence(connectionId, data.presence);
|
|
847
|
-
const myPresence = this._usersManager.myPresence;
|
|
848
853
|
const myself = (_a = this._usersManager.myself) != null ? _a : null;
|
|
849
854
|
if ((myself == null ? void 0 : myself.connectionId) === connectionId) return;
|
|
855
|
+
this._usersManager.patchPresence(connectionId, data.presence);
|
|
850
856
|
const other = this._usersManager.getOther(connectionId);
|
|
851
857
|
const others = this._usersManager.getOthers();
|
|
852
858
|
this._otherNotifier.subject(connectionId).next(other);
|
|
@@ -992,23 +998,30 @@ var PluvRoom = class extends AbstractRoom {
|
|
|
992
998
|
return oldState;
|
|
993
999
|
});
|
|
994
1000
|
}
|
|
995
|
-
/**
|
|
996
|
-
* TODO
|
|
997
|
-
* @description Determine if ws was closed with a code for closing without retries.
|
|
998
|
-
* Otherwise, attempt to retry again with incremental backoff
|
|
999
|
-
* @author leedavidcs
|
|
1000
|
-
* @date August 19, 2022
|
|
1001
|
-
*/
|
|
1002
1001
|
_onClose(event) {
|
|
1003
1002
|
return __async(this, null, function* () {
|
|
1004
1003
|
this._logDebug("WebSocket closed");
|
|
1005
1004
|
!!event.reason && this._logDebug(event.reason);
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1005
|
+
const shouldRetry = [
|
|
1006
|
+
// Going away: Client/server is shutting down or navigating
|
|
1007
|
+
1001,
|
|
1008
|
+
// Abnormal closure: Usually network error
|
|
1009
|
+
1006,
|
|
1010
|
+
// Internal error: may be a larger problem, but try reconnecting for now
|
|
1011
|
+
1011,
|
|
1012
|
+
// Service restart: Server restarted
|
|
1013
|
+
1012,
|
|
1014
|
+
// Try again later: server overloaded
|
|
1015
|
+
1013,
|
|
1016
|
+
// Bad gateway
|
|
1017
|
+
1014
|
|
1018
|
+
].some((okToRetryCode) => event.code === okToRetryCode);
|
|
1019
|
+
this._closeWs();
|
|
1020
|
+
if (!shouldRetry) this._clearTimeout(this._timeouts.reconnect);
|
|
1021
|
+
else this._pollReconnect();
|
|
1009
1022
|
this._updateState((oldState) => {
|
|
1010
1023
|
oldState.authorization.token = null;
|
|
1011
|
-
oldState.connection.state = "Closed" /* Closed */;
|
|
1024
|
+
oldState.connection.state = shouldRetry ? "Unavailable" /* Unavailable */ : "Closed" /* Closed */;
|
|
1012
1025
|
oldState.webSocket = null;
|
|
1013
1026
|
return oldState;
|
|
1014
1027
|
});
|
|
@@ -1017,7 +1030,6 @@ var PluvRoom = class extends AbstractRoom {
|
|
|
1017
1030
|
/**
|
|
1018
1031
|
* TODO
|
|
1019
1032
|
* @description Handle websocket errors in a meaningful way, should they occur
|
|
1020
|
-
* @author leedavidcs
|
|
1021
1033
|
* @date August 19, 2022
|
|
1022
1034
|
*/
|
|
1023
1035
|
_onError() {
|
|
@@ -1076,11 +1088,18 @@ var PluvRoom = class extends AbstractRoom {
|
|
|
1076
1088
|
this._clearInterval(this._intervals.heartbeat);
|
|
1077
1089
|
this._intervals.heartbeat = setInterval(this._heartbeat.bind(this), HEARTBEAT_INTERVAL_MS);
|
|
1078
1090
|
}
|
|
1091
|
+
_onNavigatorOffline() {
|
|
1092
|
+
return __async(this, null, function* () {
|
|
1093
|
+
if (this._state.connection.state === "Closed" /* Closed */) return;
|
|
1094
|
+
this._updateState((oldState) => {
|
|
1095
|
+
oldState.connection.state = "Unavailable" /* Unavailable */;
|
|
1096
|
+
return oldState;
|
|
1097
|
+
});
|
|
1098
|
+
});
|
|
1099
|
+
}
|
|
1079
1100
|
_onNavigatorOnline() {
|
|
1080
1101
|
return __async(this, null, function* () {
|
|
1081
|
-
if (this._state.connection.state !== "Unavailable" /* Unavailable */)
|
|
1082
|
-
return;
|
|
1083
|
-
}
|
|
1102
|
+
if (this._state.connection.state !== "Unavailable" /* Unavailable */) return;
|
|
1084
1103
|
yield this._reconnect();
|
|
1085
1104
|
});
|
|
1086
1105
|
}
|
|
@@ -1112,6 +1131,12 @@ var PluvRoom = class extends AbstractRoom {
|
|
|
1112
1131
|
return null;
|
|
1113
1132
|
}
|
|
1114
1133
|
}
|
|
1134
|
+
_pollReconnect() {
|
|
1135
|
+
this._clearTimeout(this._timeouts.reconnect);
|
|
1136
|
+
const timeoutMs = typeof this._reconnectTimeoutMs === "number" ? this._reconnectTimeoutMs : this._reconnectTimeoutMs({ attempts: this._state.connection.attempts });
|
|
1137
|
+
const clampedMs = Math.max(Math.min(MIN_RECONNECT_TIMEOUT_MS, timeoutMs), MAX_RECONNECT_TIMEOUT_MS);
|
|
1138
|
+
this._timeouts.reconnect = setTimeout(this._reconnect.bind(this), clampedMs);
|
|
1139
|
+
}
|
|
1115
1140
|
_reconnect() {
|
|
1116
1141
|
return __async(this, null, function* () {
|
|
1117
1142
|
if (!this._endpoints.wsEndpoint) {
|
|
@@ -1119,13 +1144,9 @@ var PluvRoom = class extends AbstractRoom {
|
|
|
1119
1144
|
}
|
|
1120
1145
|
if (!this._state.webSocket) return;
|
|
1121
1146
|
this._closeWs();
|
|
1122
|
-
this.
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
oldState.webSocket = null;
|
|
1126
|
-
return oldState;
|
|
1127
|
-
});
|
|
1128
|
-
yield this.connect();
|
|
1147
|
+
const metadata = this._lastMetadata;
|
|
1148
|
+
const params = typeof metadata === "undefined" ? [] : [{ metadata }];
|
|
1149
|
+
yield this.connect(...params);
|
|
1129
1150
|
});
|
|
1130
1151
|
}
|
|
1131
1152
|
_sendMessage(data) {
|
|
@@ -1146,6 +1167,9 @@ var PluvRoom = class extends AbstractRoom {
|
|
|
1146
1167
|
const message = typeof data === "string" ? data : JSON.stringify(data);
|
|
1147
1168
|
webSocket.send(message);
|
|
1148
1169
|
}
|
|
1170
|
+
_setMetadata(metadata) {
|
|
1171
|
+
return this.metadata ? this.metadata.parse(metadata) : metadata;
|
|
1172
|
+
}
|
|
1149
1173
|
_updateState(updater) {
|
|
1150
1174
|
let authorization;
|
|
1151
1175
|
try {
|
|
@@ -1175,17 +1199,17 @@ var PluvClient = class {
|
|
|
1175
1199
|
var _a;
|
|
1176
1200
|
const oldRoom = this.getRoom(room);
|
|
1177
1201
|
if (oldRoom) return oldRoom;
|
|
1178
|
-
const metadata = this._metadata ? this._metadata.parse(options.metadata) : options.metadata;
|
|
1179
1202
|
const newRoom = new PluvRoom(room, {
|
|
1180
1203
|
addons: options.addons,
|
|
1181
1204
|
authEndpoint: this._authEndpoint,
|
|
1182
1205
|
debug: options.debug,
|
|
1183
1206
|
initialPresence: options.initialPresence,
|
|
1184
1207
|
initialStorage: this._initialStorage,
|
|
1185
|
-
metadata,
|
|
1208
|
+
metadata: this.metadata,
|
|
1186
1209
|
onAuthorizationFail: options.onAuthorizationFail,
|
|
1187
1210
|
presence: this._presence,
|
|
1188
1211
|
publicKey: (_a = this._publicKey) != null ? _a : void 0,
|
|
1212
|
+
reconnectTimeoutMs: options.reconnectTimeoutMs,
|
|
1189
1213
|
router: options.router,
|
|
1190
1214
|
wsEndpoint: this._wsEndpoint
|
|
1191
1215
|
});
|
|
@@ -1193,11 +1217,11 @@ var PluvClient = class {
|
|
|
1193
1217
|
this._logDebug(`New room was created: ${room}`);
|
|
1194
1218
|
return newRoom;
|
|
1195
1219
|
};
|
|
1196
|
-
this.enter = (room) => __async(this, null, function* () {
|
|
1220
|
+
this.enter = (room, ...args) => __async(this, null, function* () {
|
|
1197
1221
|
const toEnter = typeof room === "string" ? this.getRoom(room) : room;
|
|
1198
1222
|
if (!toEnter) throw new Error(`Could not find room: ${room}.`);
|
|
1199
1223
|
this._rooms.set(toEnter.id, toEnter);
|
|
1200
|
-
yield toEnter.connect();
|
|
1224
|
+
yield toEnter.connect(...args);
|
|
1201
1225
|
this._logDebug(`Entered room: ${room}`);
|
|
1202
1226
|
return toEnter;
|
|
1203
1227
|
});
|
|
@@ -1216,10 +1240,10 @@ var PluvClient = class {
|
|
|
1216
1240
|
this._logDebug(`Left and deleted room: ${room}`);
|
|
1217
1241
|
});
|
|
1218
1242
|
const { authEndpoint, debug = false, initialStorage, metadata, presence, publicKey, wsEndpoint } = options;
|
|
1243
|
+
this.metadata = metadata;
|
|
1219
1244
|
this._authEndpoint = authEndpoint;
|
|
1220
1245
|
this._debug = debug;
|
|
1221
1246
|
this._initialStorage = initialStorage;
|
|
1222
|
-
this._metadata = metadata;
|
|
1223
1247
|
this._presence = presence;
|
|
1224
1248
|
this._wsEndpoint = wsEndpoint;
|
|
1225
1249
|
if (!!publicKey) this._publicKey = publicKey;
|
|
@@ -1268,6 +1292,7 @@ var MockedRoom = class extends AbstractRoom {
|
|
|
1268
1292
|
user: null
|
|
1269
1293
|
},
|
|
1270
1294
|
connection: {
|
|
1295
|
+
attempts: 0,
|
|
1271
1296
|
count: 1,
|
|
1272
1297
|
id: null,
|
|
1273
1298
|
state: "Untouched" /* Untouched */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pluv/client",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.39.0",
|
|
4
4
|
"description": "@pluv/io frontend client",
|
|
5
5
|
"author": "leedavidcs",
|
|
6
6
|
"license": "MIT",
|
|
@@ -18,20 +18,20 @@
|
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
20
|
"wonka": "^6.3.5",
|
|
21
|
-
"@pluv/crdt": "^0.
|
|
22
|
-
"@pluv/types": "^0.
|
|
21
|
+
"@pluv/crdt": "^0.39.0",
|
|
22
|
+
"@pluv/types": "^0.39.0"
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
|
-
"eslint": "^
|
|
25
|
+
"eslint": "^9.24.0",
|
|
26
26
|
"tsup": "^8.4.0",
|
|
27
27
|
"typescript": "^5.8.3",
|
|
28
|
-
"@pluv/tsconfig": "^0.
|
|
29
|
-
"eslint-config-pluv": "^0.
|
|
28
|
+
"@pluv/tsconfig": "^0.39.0",
|
|
29
|
+
"eslint-config-pluv": "^0.39.0"
|
|
30
30
|
},
|
|
31
31
|
"scripts": {
|
|
32
32
|
"build": "tsup src/index.ts --format esm,cjs --dts",
|
|
33
33
|
"dev": "tsup src/index.ts --format esm,cjs --watch --dts",
|
|
34
|
-
"lint": "eslint src/**/*.ts* --fix",
|
|
34
|
+
"lint": "eslint src/**/*.ts* --fix --max-warnings 0",
|
|
35
35
|
"clean": "rm -rf .turbo && rm -rf node_modules && rm -rf dist"
|
|
36
36
|
}
|
|
37
37
|
}
|
package/src/MockedRoom.ts
CHANGED
package/src/PluvClient.ts
CHANGED
|
@@ -2,11 +2,19 @@ import type { AbstractCrdtDocFactory, CrdtType } from "@pluv/crdt";
|
|
|
2
2
|
import type { InputZodLike, IOLike, JsonObject } from "@pluv/types";
|
|
3
3
|
import type { InferCallback } from "./infer";
|
|
4
4
|
import { PluvProcedure } from "./PluvProcedure";
|
|
5
|
-
import type {
|
|
5
|
+
import type {
|
|
6
|
+
AuthEndpoint,
|
|
7
|
+
PluvRoomAddon,
|
|
8
|
+
PluvRoomDebug,
|
|
9
|
+
ReconnectTimeoutMs,
|
|
10
|
+
RoomConfig,
|
|
11
|
+
RoomEndpoints,
|
|
12
|
+
WsEndpoint,
|
|
13
|
+
} from "./PluvRoom";
|
|
6
14
|
import { PluvRoom } from "./PluvRoom";
|
|
7
15
|
import type { PluvRouterEventConfig } from "./PluvRouter";
|
|
8
16
|
import { PluvRouter } from "./PluvRouter";
|
|
9
|
-
import type { PublicKey } from "./types";
|
|
17
|
+
import type { PublicKey, WithMetadata } from "./types";
|
|
10
18
|
|
|
11
19
|
export type PluvClientOptions<
|
|
12
20
|
TIO extends IOLike<any, any>,
|
|
@@ -34,8 +42,13 @@ export type CreateRoomOptions<
|
|
|
34
42
|
initialPresence?: TPresence;
|
|
35
43
|
initialStorage?: AbstractCrdtDocFactory<TStorage>;
|
|
36
44
|
onAuthorizationFail?: (error: Error) => void;
|
|
45
|
+
reconnectTimeoutMs?: ReconnectTimeoutMs;
|
|
37
46
|
router?: PluvRouter<TIO, TPresence, TStorage, TEvents>;
|
|
38
|
-
}
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
export type EnterRoomParams<TMetadata extends JsonObject = {}> = keyof TMetadata extends never
|
|
50
|
+
? []
|
|
51
|
+
: [WithMetadata<TMetadata>];
|
|
39
52
|
|
|
40
53
|
export class PluvClient<
|
|
41
54
|
TIO extends IOLike<any, any>,
|
|
@@ -43,10 +56,11 @@ export class PluvClient<
|
|
|
43
56
|
TStorage extends Record<string, CrdtType<any, any>> = {},
|
|
44
57
|
TMetadata extends JsonObject = {},
|
|
45
58
|
> {
|
|
59
|
+
public readonly metadata?: InputZodLike<TMetadata>;
|
|
60
|
+
|
|
46
61
|
private readonly _authEndpoint: AuthEndpoint<TMetadata> | undefined;
|
|
47
62
|
private readonly _debug: boolean;
|
|
48
63
|
private readonly _initialStorage?: AbstractCrdtDocFactory<TStorage>;
|
|
49
|
-
private readonly _metadata?: InputZodLike<TMetadata>;
|
|
50
64
|
private readonly _presence?: InputZodLike<TPresence>;
|
|
51
65
|
private readonly _publicKey: PublicKey<TMetadata> | null = null;
|
|
52
66
|
private readonly _rooms = new Map<string, PluvRoom<TIO, TMetadata, TPresence, TStorage, any>>();
|
|
@@ -65,10 +79,11 @@ export class PluvClient<
|
|
|
65
79
|
constructor(options: PluvClientOptions<TIO, TPresence, TStorage, TMetadata>) {
|
|
66
80
|
const { authEndpoint, debug = false, initialStorage, metadata, presence, publicKey, wsEndpoint } = options;
|
|
67
81
|
|
|
82
|
+
this.metadata = metadata;
|
|
83
|
+
|
|
68
84
|
this._authEndpoint = authEndpoint as AuthEndpoint<TMetadata>;
|
|
69
85
|
this._debug = debug;
|
|
70
86
|
this._initialStorage = initialStorage;
|
|
71
|
-
this._metadata = metadata;
|
|
72
87
|
this._presence = presence;
|
|
73
88
|
this._wsEndpoint = wsEndpoint;
|
|
74
89
|
|
|
@@ -83,18 +98,17 @@ export class PluvClient<
|
|
|
83
98
|
|
|
84
99
|
if (oldRoom) return oldRoom;
|
|
85
100
|
|
|
86
|
-
const metadata = this._metadata ? this._metadata.parse(options.metadata) : options.metadata;
|
|
87
|
-
|
|
88
101
|
const newRoom = new PluvRoom<TIO, TMetadata, TPresence, TStorage, TEvents>(room, {
|
|
89
102
|
addons: options.addons,
|
|
90
103
|
authEndpoint: this._authEndpoint,
|
|
91
104
|
debug: options.debug,
|
|
92
105
|
initialPresence: options.initialPresence,
|
|
93
106
|
initialStorage: this._initialStorage,
|
|
94
|
-
metadata,
|
|
107
|
+
metadata: this.metadata,
|
|
95
108
|
onAuthorizationFail: options.onAuthorizationFail,
|
|
96
109
|
presence: this._presence,
|
|
97
110
|
publicKey: this._publicKey ?? undefined,
|
|
111
|
+
reconnectTimeoutMs: options.reconnectTimeoutMs,
|
|
98
112
|
router: options.router,
|
|
99
113
|
wsEndpoint: this._wsEndpoint,
|
|
100
114
|
} as RoomConfig<TIO, TMetadata, TPresence, TStorage, TEvents>);
|
|
@@ -107,15 +121,15 @@ export class PluvClient<
|
|
|
107
121
|
};
|
|
108
122
|
|
|
109
123
|
public enter = async (
|
|
110
|
-
room: string | PluvRoom<TIO, any, any, any>,
|
|
124
|
+
room: string | PluvRoom<TIO, TMetadata, any, any, any>,
|
|
125
|
+
...args: EnterRoomParams<TMetadata>
|
|
111
126
|
): Promise<PluvRoom<TIO, TMetadata, TPresence, TStorage, any>> => {
|
|
112
127
|
const toEnter = typeof room === "string" ? this.getRoom(room) : room;
|
|
113
128
|
|
|
114
129
|
if (!toEnter) throw new Error(`Could not find room: ${room}.`);
|
|
115
130
|
|
|
116
131
|
this._rooms.set(toEnter.id, toEnter);
|
|
117
|
-
|
|
118
|
-
await toEnter.connect();
|
|
132
|
+
await toEnter.connect(...args);
|
|
119
133
|
|
|
120
134
|
this._logDebug(`Entered room: ${room}`);
|
|
121
135
|
|