@pluv/client 1.0.1 → 2.0.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 +19 -0
- package/dist/index.d.mts +111 -172
- package/dist/index.d.ts +111 -172
- package/dist/index.js +117 -127
- package/dist/index.mjs +98 -106
- package/package.json +5 -5
- package/src/CrdtManager.ts +28 -18
- package/src/EventNotifier.ts +7 -6
- package/src/MockedRoom.ts +61 -41
- package/src/OtherNotifier.ts +7 -6
- package/src/PluvClient.ts +36 -28
- package/src/PluvProcedure.ts +2 -1
- package/src/PluvRoom.ts +123 -110
- package/src/PluvRouter.ts +1 -23
- package/src/StateNotifier.ts +1 -2
- package/src/UsersManager.ts +2 -2
- package/src/createClient.ts +5 -5
- package/src/index.ts +14 -12
- package/src/types.ts +5 -19
- package/src/AbstractRoom.ts +0 -84
- package/src/enums.ts +0 -9
package/dist/index.mjs
CHANGED
|
@@ -38,13 +38,6 @@ var __async = (__this, __arguments, generator) => {
|
|
|
38
38
|
});
|
|
39
39
|
};
|
|
40
40
|
|
|
41
|
-
// src/AbstractRoom.ts
|
|
42
|
-
var AbstractRoom = class {
|
|
43
|
-
constructor(room) {
|
|
44
|
-
this.id = room;
|
|
45
|
-
}
|
|
46
|
-
};
|
|
47
|
-
|
|
48
41
|
// src/AbstractStorageStore.ts
|
|
49
42
|
var AbstractStorageStore = class {
|
|
50
43
|
constructor(room) {
|
|
@@ -90,6 +83,9 @@ var PluvProcedure = class _PluvProcedure {
|
|
|
90
83
|
}
|
|
91
84
|
};
|
|
92
85
|
|
|
86
|
+
// src/PluvRoom.ts
|
|
87
|
+
import { ConnectionState } from "@pluv/types";
|
|
88
|
+
|
|
93
89
|
// src/CrdtManager.ts
|
|
94
90
|
import { noop } from "@pluv/crdt";
|
|
95
91
|
var CrdtManager = class {
|
|
@@ -105,14 +101,17 @@ var CrdtManager = class {
|
|
|
105
101
|
* update. This unfortunately means updates can be dropped entirely
|
|
106
102
|
* @date June 13, 2023
|
|
107
103
|
*/
|
|
108
|
-
applyUpdate(
|
|
104
|
+
applyUpdate(params) {
|
|
105
|
+
const { origin, update } = params;
|
|
109
106
|
if (!this.initialized) return this;
|
|
110
107
|
const updates = typeof update === "string" ? [update] : update;
|
|
111
108
|
this._applyDocUpdates(this.doc, updates, origin);
|
|
112
109
|
return this;
|
|
113
110
|
}
|
|
114
111
|
destroy() {
|
|
112
|
+
this.initialized = false;
|
|
115
113
|
this.doc.destroy();
|
|
114
|
+
this.doc = this._docFactory.getEmpty();
|
|
116
115
|
}
|
|
117
116
|
get(key) {
|
|
118
117
|
return this.doc.get(key);
|
|
@@ -121,7 +120,7 @@ var CrdtManager = class {
|
|
|
121
120
|
return this._docFactory.getInitialized().getEncodedState();
|
|
122
121
|
}
|
|
123
122
|
initialize(params) {
|
|
124
|
-
const {
|
|
123
|
+
const { origin, update } = params;
|
|
125
124
|
if (this.initialized) {
|
|
126
125
|
console.warn("Attempted to initialize storage multiple times");
|
|
127
126
|
return this;
|
|
@@ -141,9 +140,11 @@ var CrdtManager = class {
|
|
|
141
140
|
).rebuildStorage(reference);
|
|
142
141
|
this.initialized = true;
|
|
143
142
|
initialized.destroy();
|
|
144
|
-
onInitialized == null ? void 0 : onInitialized(this.doc.getEncodedState());
|
|
145
143
|
return this;
|
|
146
144
|
}
|
|
145
|
+
resolveEncodedState(updates) {
|
|
146
|
+
return this._docFactory.resolveEncodedState(updates);
|
|
147
|
+
}
|
|
147
148
|
_applyDocUpdates(doc, updates, origin) {
|
|
148
149
|
doc.transact(() => {
|
|
149
150
|
doc.batchApplyEncodedState({ origin, updates });
|
|
@@ -518,15 +519,6 @@ var UsersManager = class {
|
|
|
518
519
|
}
|
|
519
520
|
};
|
|
520
521
|
|
|
521
|
-
// src/enums.ts
|
|
522
|
-
var ConnectionState = {
|
|
523
|
-
Closed: "Closed",
|
|
524
|
-
Connecting: "Connecting",
|
|
525
|
-
Open: "Open",
|
|
526
|
-
Unavailable: "Unavailable",
|
|
527
|
-
Untouched: "Untouched"
|
|
528
|
-
};
|
|
529
|
-
|
|
530
522
|
// src/PluvRoom.ts
|
|
531
523
|
var ADD_TO_STORAGE_STATE_DEBOUNCE_MS = 1e3;
|
|
532
524
|
var HEARTBEAT_INTERVAL_MS = 1e4;
|
|
@@ -539,24 +531,8 @@ var ORIGIN_STORAGE_UPDATED = "$storageUpdated";
|
|
|
539
531
|
var DEFAULT_PLUV_CLIENT_ADDON = (input) => ({
|
|
540
532
|
storage: new StorageStore(input.room.id)
|
|
541
533
|
});
|
|
542
|
-
var PluvRoom = class
|
|
534
|
+
var PluvRoom = class {
|
|
543
535
|
constructor(room, options) {
|
|
544
|
-
const {
|
|
545
|
-
addons = [],
|
|
546
|
-
authEndpoint,
|
|
547
|
-
debug = false,
|
|
548
|
-
initialPresence,
|
|
549
|
-
initialStorage,
|
|
550
|
-
limits,
|
|
551
|
-
metadata,
|
|
552
|
-
onAuthorizationFail,
|
|
553
|
-
presence,
|
|
554
|
-
publicKey,
|
|
555
|
-
reconnectTimeoutMs = RECONNECT_TIMEOUT_MS,
|
|
556
|
-
router,
|
|
557
|
-
wsEndpoint
|
|
558
|
-
} = options;
|
|
559
|
-
super(room);
|
|
560
536
|
this._crdtNotifier = new CrdtNotifier();
|
|
561
537
|
this._eventNotifier = new EventNotifier();
|
|
562
538
|
this._intervals = {
|
|
@@ -703,7 +679,7 @@ var PluvRoom = class extends AbstractRoom {
|
|
|
703
679
|
const shouldFlatten = yield this._storageStore.getShouldFlatten();
|
|
704
680
|
if (!shouldFlatten) return;
|
|
705
681
|
const updates = yield this._storageStore.getUpdates();
|
|
706
|
-
this._crdtManager.applyUpdate(updates, this);
|
|
682
|
+
this._crdtManager.applyUpdate({ update: updates, origin: this });
|
|
707
683
|
const encodedState = this._crdtManager.doc.getEncodedState();
|
|
708
684
|
yield this._storageStore.flatten(encodedState);
|
|
709
685
|
}),
|
|
@@ -715,14 +691,30 @@ var PluvRoom = class extends AbstractRoom {
|
|
|
715
691
|
DEFAULT_PLUV_CLIENT_ADDON
|
|
716
692
|
);
|
|
717
693
|
};
|
|
694
|
+
const {
|
|
695
|
+
addons = [],
|
|
696
|
+
authEndpoint,
|
|
697
|
+
debug = false,
|
|
698
|
+
initialPresence,
|
|
699
|
+
initialStorage,
|
|
700
|
+
limits,
|
|
701
|
+
metadata,
|
|
702
|
+
onAuthorizationFail,
|
|
703
|
+
presence,
|
|
704
|
+
publicKey,
|
|
705
|
+
reconnectTimeoutMs = RECONNECT_TIMEOUT_MS,
|
|
706
|
+
router,
|
|
707
|
+
wsEndpoint
|
|
708
|
+
} = options;
|
|
709
|
+
this.id = room;
|
|
710
|
+
this.metadata = metadata;
|
|
718
711
|
const addon = this._getAddon(addons);
|
|
719
712
|
const { storage } = __spreadValues(__spreadValues({}, DEFAULT_PLUV_CLIENT_ADDON({ room: this })), addon({ room: this }));
|
|
720
|
-
this.
|
|
713
|
+
this._storageStore = storage;
|
|
721
714
|
this._debug = debug;
|
|
722
715
|
this._endpoints = { authEndpoint, wsEndpoint };
|
|
723
716
|
this._limits = limits;
|
|
724
717
|
this._reconnectTimeoutMs = reconnectTimeoutMs;
|
|
725
|
-
this._storageStore = storage;
|
|
726
718
|
if (!!publicKey) this._publicKey = publicKey;
|
|
727
719
|
this._listeners = {
|
|
728
720
|
onAuthorizationFail: (error) => {
|
|
@@ -760,6 +752,7 @@ var PluvRoom = class extends AbstractRoom {
|
|
|
760
752
|
oldState.connection.state = ConnectionState.Connecting;
|
|
761
753
|
return oldState;
|
|
762
754
|
});
|
|
755
|
+
yield this._storageStore.initialize();
|
|
763
756
|
const wsEndpoint = this._getWsEndpoint(this.id, params);
|
|
764
757
|
const url = new URL(wsEndpoint);
|
|
765
758
|
let authToken = null;
|
|
@@ -824,20 +817,6 @@ var PluvRoom = class extends AbstractRoom {
|
|
|
824
817
|
this._flattenStorageStore();
|
|
825
818
|
});
|
|
826
819
|
}
|
|
827
|
-
_applyStorageStore() {
|
|
828
|
-
return __async(this, null, function* () {
|
|
829
|
-
const updates = yield this._storageStore.getUpdates();
|
|
830
|
-
this._crdtManager.initialize({
|
|
831
|
-
onInitialized: () => {
|
|
832
|
-
this._stateNotifier.subjects["storage-loaded"].next(true);
|
|
833
|
-
this._observeCrdt();
|
|
834
|
-
},
|
|
835
|
-
origin: ORIGIN_INITIALIZED,
|
|
836
|
-
update: updates
|
|
837
|
-
});
|
|
838
|
-
this._emitSharedTypes();
|
|
839
|
-
});
|
|
840
|
-
}
|
|
841
820
|
_attachWindowListeners() {
|
|
842
821
|
if (typeof window === "undefined") return;
|
|
843
822
|
if (typeof document === "undefined") return;
|
|
@@ -1028,33 +1007,35 @@ var PluvRoom = class extends AbstractRoom {
|
|
|
1028
1007
|
this._stateNotifier.subjects.others.next(others);
|
|
1029
1008
|
}
|
|
1030
1009
|
_handleRegisteredMessage(message) {
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1038
|
-
|
|
1039
|
-
oldState
|
|
1040
|
-
|
|
1041
|
-
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1010
|
+
return __async(this, null, function* () {
|
|
1011
|
+
var _a, _b, _c;
|
|
1012
|
+
const { connectionId } = message;
|
|
1013
|
+
const user = message.user;
|
|
1014
|
+
if (!connectionId) return;
|
|
1015
|
+
if (!this._state.webSocket) throw new Error("Could not find WebSocket");
|
|
1016
|
+
const data = message.data;
|
|
1017
|
+
const state = data.state;
|
|
1018
|
+
this._updateState((oldState) => {
|
|
1019
|
+
oldState.connection.count += 1;
|
|
1020
|
+
oldState.connection.id = connectionId;
|
|
1021
|
+
oldState.authorization.user = user != null ? user : null;
|
|
1022
|
+
return oldState;
|
|
1023
|
+
});
|
|
1024
|
+
const userInfo = {
|
|
1025
|
+
connectionId,
|
|
1026
|
+
presence: (_a = data.presence) != null ? _a : void 0,
|
|
1027
|
+
user
|
|
1028
|
+
};
|
|
1029
|
+
this._usersManager.setMyself(userInfo);
|
|
1030
|
+
const presence = this._usersManager.myPresence;
|
|
1031
|
+
const myself = (_b = this._usersManager.myself) != null ? _b : null;
|
|
1032
|
+
this._stateNotifier.subjects["my-presence"].next(presence);
|
|
1033
|
+
this._stateNotifier.subjects.myself.next(myself);
|
|
1034
|
+
const update = !state ? (_c = this._crdtManager.resolveEncodedState(yield this._storageStore.getUpdates())) != null ? _c : this._crdtManager.getInitialState() : this._crdtManager.getInitialState();
|
|
1035
|
+
this._sendMessage({
|
|
1036
|
+
type: "$initializeSession",
|
|
1037
|
+
data: { presence, update }
|
|
1038
|
+
});
|
|
1058
1039
|
});
|
|
1059
1040
|
}
|
|
1060
1041
|
_handleStorageReceivedMessage(message) {
|
|
@@ -1063,24 +1044,34 @@ var PluvRoom = class extends AbstractRoom {
|
|
|
1063
1044
|
if (!connectionId) return;
|
|
1064
1045
|
if (!this._state.webSocket) throw new Error("Could not find WebSocket");
|
|
1065
1046
|
const data = message.data;
|
|
1047
|
+
const changeKind = data.changeKind;
|
|
1066
1048
|
const state = data.state;
|
|
1067
|
-
this.
|
|
1068
|
-
|
|
1069
|
-
|
|
1070
|
-
|
|
1071
|
-
|
|
1072
|
-
|
|
1073
|
-
|
|
1074
|
-
origin:
|
|
1075
|
-
|
|
1076
|
-
|
|
1049
|
+
const updates = yield this._storageStore.getUpdates();
|
|
1050
|
+
const origin = ORIGIN_INITIALIZED;
|
|
1051
|
+
const updateStorage = (update) => {
|
|
1052
|
+
return this._crdtManager.initialized ? this._crdtManager.applyUpdate({ update, origin }) : this._crdtManager.initialize({ update, origin });
|
|
1053
|
+
};
|
|
1054
|
+
if (changeKind === "empty") {
|
|
1055
|
+
this._crdtManager.destroy();
|
|
1056
|
+
this._crdtManager.initialize({ origin, update: updates });
|
|
1057
|
+
} else if (changeKind === "initialized") {
|
|
1058
|
+
if (!!updates.length) updateStorage(updates);
|
|
1059
|
+
else {
|
|
1060
|
+
const encodedState2 = updateStorage(state).doc.getEncodedState();
|
|
1061
|
+
this._addToStorageStore(encodedState2);
|
|
1062
|
+
}
|
|
1063
|
+
} else {
|
|
1064
|
+
const encodedState2 = updateStorage(state).doc.getEncodedState();
|
|
1065
|
+
if (!!updates.length) this._crdtManager.applyUpdate({ update: updates, origin });
|
|
1066
|
+
yield this._addToStorageStore(encodedState2);
|
|
1067
|
+
}
|
|
1077
1068
|
const encodedState = this._crdtManager.doc.getEncodedState();
|
|
1078
|
-
yield this._storageStore.addUpdate(encodedState);
|
|
1079
1069
|
this._emitSharedTypes();
|
|
1080
|
-
|
|
1070
|
+
this._observeCrdt();
|
|
1071
|
+
this._stateNotifier.subjects["storage-loaded"].next(true);
|
|
1081
1072
|
this._sendMessage({
|
|
1082
1073
|
type: "$updateStorage",
|
|
1083
|
-
data: { origin
|
|
1074
|
+
data: { origin, update: encodedState }
|
|
1084
1075
|
});
|
|
1085
1076
|
});
|
|
1086
1077
|
}
|
|
@@ -1150,7 +1141,8 @@ var PluvRoom = class extends AbstractRoom {
|
|
|
1150
1141
|
}
|
|
1151
1142
|
_logDebug(...data) {
|
|
1152
1143
|
var _a;
|
|
1153
|
-
if (
|
|
1144
|
+
if (typeof process === "undefined") return;
|
|
1145
|
+
if (((_a = process.env) == null ? void 0 : _a.NODE_ENV) === "production") return;
|
|
1154
1146
|
if (this._debug) console.log(...data);
|
|
1155
1147
|
}
|
|
1156
1148
|
_observeCrdt() {
|
|
@@ -1159,11 +1151,11 @@ var PluvRoom = class extends AbstractRoom {
|
|
|
1159
1151
|
const unsubscribe = this._crdtManager.doc.subscribe((event) => {
|
|
1160
1152
|
var _a2;
|
|
1161
1153
|
const origin = (_a2 = event.origin) != null ? _a2 : null;
|
|
1162
|
-
this._addToStorageStore(event.update);
|
|
1163
1154
|
this._emitSharedTypes();
|
|
1164
1155
|
if (origin === ORIGIN_INITIALIZED || origin === ORIGIN_STORAGE_UPDATED) {
|
|
1165
1156
|
return;
|
|
1166
1157
|
}
|
|
1158
|
+
this._addToStorageStore(event.update);
|
|
1167
1159
|
if (!this._state.webSocket) return;
|
|
1168
1160
|
if (!this._state.connection.id) return;
|
|
1169
1161
|
if (this._state.webSocket.readyState !== WebSocket.OPEN) return;
|
|
@@ -1410,7 +1402,7 @@ var PluvClient = class {
|
|
|
1410
1402
|
this._publicKey = null;
|
|
1411
1403
|
this._rooms = /* @__PURE__ */ new Map();
|
|
1412
1404
|
this.createRoom = (room, options = {}) => {
|
|
1413
|
-
var _a;
|
|
1405
|
+
var _a, _b;
|
|
1414
1406
|
const oldRoom = this.getRoom(room);
|
|
1415
1407
|
if (oldRoom) return oldRoom;
|
|
1416
1408
|
const newRoom = new PluvRoom(room, {
|
|
@@ -1418,12 +1410,12 @@ var PluvClient = class {
|
|
|
1418
1410
|
authEndpoint: this._authEndpoint,
|
|
1419
1411
|
debug: options.debug,
|
|
1420
1412
|
initialPresence: options.initialPresence,
|
|
1421
|
-
initialStorage: this._initialStorage,
|
|
1413
|
+
initialStorage: (_a = options.initialStorage) != null ? _a : this._initialStorage,
|
|
1422
1414
|
limits: this._limits,
|
|
1423
1415
|
metadata: this.metadata,
|
|
1424
1416
|
onAuthorizationFail: options.onAuthorizationFail,
|
|
1425
1417
|
presence: this._presence,
|
|
1426
|
-
publicKey: (
|
|
1418
|
+
publicKey: (_b = this._publicKey) != null ? _b : void 0,
|
|
1427
1419
|
reconnectTimeoutMs: options.reconnectTimeoutMs,
|
|
1428
1420
|
router: options.router,
|
|
1429
1421
|
wsEndpoint: this._wsEndpoint
|
|
@@ -1492,7 +1484,8 @@ var PluvClient = class {
|
|
|
1492
1484
|
}
|
|
1493
1485
|
_logDebug(...data) {
|
|
1494
1486
|
var _a;
|
|
1495
|
-
if (
|
|
1487
|
+
if (typeof process === "undefined") return;
|
|
1488
|
+
if (((_a = process.env) == null ? void 0 : _a.NODE_ENV) === "production") return;
|
|
1496
1489
|
if (this._debug) console.log(...data);
|
|
1497
1490
|
}
|
|
1498
1491
|
};
|
|
@@ -1506,10 +1499,9 @@ var createClient = (options) => {
|
|
|
1506
1499
|
var infer = (callback) => callback;
|
|
1507
1500
|
|
|
1508
1501
|
// src/MockedRoom.ts
|
|
1509
|
-
|
|
1502
|
+
import { ConnectionState as ConnectionState2 } from "@pluv/types";
|
|
1503
|
+
var MockedRoom = class {
|
|
1510
1504
|
constructor(room, options) {
|
|
1511
|
-
const { events, initialPresence, initialStorage, limits, presence, router } = options;
|
|
1512
|
-
super(room);
|
|
1513
1505
|
this._crdtNotifier = new CrdtNotifier();
|
|
1514
1506
|
this._eventNotifier = new EventNotifier();
|
|
1515
1507
|
this._otherNotifier = new OtherNotifier();
|
|
@@ -1522,7 +1514,7 @@ var MockedRoom = class extends AbstractRoom {
|
|
|
1522
1514
|
attempts: 0,
|
|
1523
1515
|
count: 1,
|
|
1524
1516
|
id: null,
|
|
1525
|
-
state:
|
|
1517
|
+
state: ConnectionState2.Untouched
|
|
1526
1518
|
},
|
|
1527
1519
|
webSocket: null
|
|
1528
1520
|
};
|
|
@@ -1533,7 +1525,7 @@ var MockedRoom = class extends AbstractRoom {
|
|
|
1533
1525
|
this.broadcast = new Proxy(
|
|
1534
1526
|
(event, data) => __async(this, null, function* () {
|
|
1535
1527
|
if (!this._state.webSocket) return;
|
|
1536
|
-
if (this._state.connection.state !==
|
|
1528
|
+
if (this._state.connection.state !== ConnectionState2.Open) return;
|
|
1537
1529
|
const type = event.toString();
|
|
1538
1530
|
const procedure = this._router._defs.events[type];
|
|
1539
1531
|
if (!(procedure == null ? void 0 : procedure.config.broadcast)) {
|
|
@@ -1635,6 +1627,8 @@ var MockedRoom = class extends AbstractRoom {
|
|
|
1635
1627
|
this._stateNotifier.subjects["my-presence"].next(myPresence);
|
|
1636
1628
|
if (!!myself) this._stateNotifier.subjects["myself"].next(myself);
|
|
1637
1629
|
};
|
|
1630
|
+
const { events, initialPresence, initialStorage, limits, presence, router } = options;
|
|
1631
|
+
this.id = room;
|
|
1638
1632
|
this._events = events;
|
|
1639
1633
|
this._limits = __spreadValues({
|
|
1640
1634
|
presenceMaxSize: MAX_PRESENCE_SIZE_BYTES
|
|
@@ -1710,9 +1704,7 @@ var register = (params) => {
|
|
|
1710
1704
|
};
|
|
1711
1705
|
};
|
|
1712
1706
|
export {
|
|
1713
|
-
AbstractRoom,
|
|
1714
1707
|
AbstractStorageStore,
|
|
1715
|
-
ConnectionState,
|
|
1716
1708
|
MockedRoom,
|
|
1717
1709
|
PluvClient,
|
|
1718
1710
|
PluvRoom,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pluv/client",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
4
4
|
"description": "@pluv/io frontend client",
|
|
5
5
|
"author": "leedavidcs",
|
|
6
6
|
"license": "MIT",
|
|
@@ -18,15 +18,15 @@
|
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
20
|
"wonka": "^6.3.5",
|
|
21
|
-
"@pluv/crdt": "^
|
|
22
|
-
"@pluv/types": "^
|
|
21
|
+
"@pluv/crdt": "^2.0.0",
|
|
22
|
+
"@pluv/types": "^2.0.0"
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
25
|
"eslint": "^9.25.1",
|
|
26
26
|
"tsup": "^8.4.0",
|
|
27
27
|
"typescript": "^5.8.3",
|
|
28
|
-
"@pluv/tsconfig": "^
|
|
29
|
-
"eslint-config-pluv": "^
|
|
28
|
+
"@pluv/tsconfig": "^2.0.0",
|
|
29
|
+
"eslint-config-pluv": "^2.0.0"
|
|
30
30
|
},
|
|
31
31
|
"scripts": {
|
|
32
32
|
"build": "tsup src/index.ts --format esm,cjs --dts",
|
package/src/CrdtManager.ts
CHANGED
|
@@ -1,24 +1,28 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { AbstractCrdtDocFactory, CrdtDocLike, CrdtType, InferStorage } from "@pluv/crdt";
|
|
2
2
|
import { noop } from "@pluv/crdt";
|
|
3
3
|
|
|
4
|
-
export type CrdtManagerOptions<
|
|
5
|
-
initialStorage?:
|
|
4
|
+
export type CrdtManagerOptions<TCrdt extends AbstractCrdtDocFactory<any>> = {
|
|
5
|
+
initialStorage?: TCrdt;
|
|
6
6
|
};
|
|
7
7
|
|
|
8
|
-
|
|
9
|
-
onInitialized?: (state: string) => void;
|
|
8
|
+
interface CrdtManagerInitializeParams {
|
|
10
9
|
origin?: any;
|
|
11
10
|
update: string | readonly string[];
|
|
12
|
-
}
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
interface ApplyUpdateParams {
|
|
14
|
+
origin?: any;
|
|
15
|
+
update: string | readonly string[];
|
|
16
|
+
}
|
|
13
17
|
|
|
14
|
-
export class CrdtManager<
|
|
15
|
-
public doc:
|
|
18
|
+
export class CrdtManager<TCrdt extends AbstractCrdtDocFactory<any>> {
|
|
19
|
+
public doc: CrdtDocLike<InferStorage<TCrdt>>;
|
|
16
20
|
public initialized: boolean = false;
|
|
17
21
|
|
|
18
|
-
private readonly _docFactory:
|
|
22
|
+
private readonly _docFactory: TCrdt;
|
|
19
23
|
|
|
20
|
-
constructor(options: CrdtManagerOptions<
|
|
21
|
-
const { initialStorage = noop.doc({}) as
|
|
24
|
+
constructor(options: CrdtManagerOptions<TCrdt>) {
|
|
25
|
+
const { initialStorage = noop.doc({}) as any } = options;
|
|
22
26
|
|
|
23
27
|
this._docFactory = initialStorage;
|
|
24
28
|
this.doc = initialStorage.getEmpty();
|
|
@@ -30,7 +34,9 @@ export class CrdtManager<TStorage extends Record<string, CrdtType<any, any>>> {
|
|
|
30
34
|
* update. This unfortunately means updates can be dropped entirely
|
|
31
35
|
* @date June 13, 2023
|
|
32
36
|
*/
|
|
33
|
-
public applyUpdate(
|
|
37
|
+
public applyUpdate(params: ApplyUpdateParams): this {
|
|
38
|
+
const { origin, update } = params;
|
|
39
|
+
|
|
34
40
|
if (!this.initialized) return this;
|
|
35
41
|
|
|
36
42
|
const updates: readonly string[] = typeof update === "string" ? [update] : update;
|
|
@@ -41,10 +47,12 @@ export class CrdtManager<TStorage extends Record<string, CrdtType<any, any>>> {
|
|
|
41
47
|
}
|
|
42
48
|
|
|
43
49
|
public destroy(): void {
|
|
50
|
+
this.initialized = false;
|
|
44
51
|
this.doc.destroy();
|
|
52
|
+
this.doc = this._docFactory.getEmpty();
|
|
45
53
|
}
|
|
46
54
|
|
|
47
|
-
public get<TKey extends keyof
|
|
55
|
+
public get<TKey extends keyof InferStorage<TCrdt>>(key: TKey): InferStorage<TCrdt>[TKey] {
|
|
48
56
|
return this.doc.get(key);
|
|
49
57
|
}
|
|
50
58
|
|
|
@@ -53,7 +61,7 @@ export class CrdtManager<TStorage extends Record<string, CrdtType<any, any>>> {
|
|
|
53
61
|
}
|
|
54
62
|
|
|
55
63
|
public initialize(params: CrdtManagerInitializeParams): this {
|
|
56
|
-
const {
|
|
64
|
+
const { origin, update } = params;
|
|
57
65
|
|
|
58
66
|
/**
|
|
59
67
|
* !HACK
|
|
@@ -94,16 +102,18 @@ export class CrdtManager<TStorage extends Record<string, CrdtType<any, any>>> {
|
|
|
94
102
|
this.initialized = true;
|
|
95
103
|
initialized.destroy();
|
|
96
104
|
|
|
97
|
-
onInitialized?.(this.doc.getEncodedState());
|
|
98
|
-
|
|
99
105
|
return this;
|
|
100
106
|
}
|
|
101
107
|
|
|
108
|
+
public resolveEncodedState(updates: string | string[] | readonly string[]): string | null {
|
|
109
|
+
return this._docFactory.resolveEncodedState(updates);
|
|
110
|
+
}
|
|
111
|
+
|
|
102
112
|
private _applyDocUpdates(
|
|
103
|
-
doc:
|
|
113
|
+
doc: CrdtDocLike<InferStorage<TCrdt>>,
|
|
104
114
|
updates: readonly string[],
|
|
105
115
|
origin?: string,
|
|
106
|
-
):
|
|
116
|
+
): CrdtDocLike<InferStorage<TCrdt>> {
|
|
107
117
|
doc.transact(() => {
|
|
108
118
|
doc.batchApplyEncodedState({ origin, updates });
|
|
109
119
|
}, origin);
|
package/src/EventNotifier.ts
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
EventNotifierSubscriptionCallback,
|
|
3
|
+
Id,
|
|
4
|
+
InferIOOutput,
|
|
5
|
+
IOEventMessage,
|
|
6
|
+
IOLike,
|
|
7
|
+
} from "@pluv/types";
|
|
2
8
|
import type { Subject } from "wonka";
|
|
3
9
|
import { makeSubject, subscribe } from "wonka";
|
|
4
10
|
|
|
5
|
-
export type EventNotifierSubscriptionCallback<
|
|
6
|
-
TIO extends IOLike<any, any>,
|
|
7
|
-
TEvent extends keyof InferIOOutput<TIO>,
|
|
8
|
-
> = (value: Id<IOEventMessage<TIO, TEvent>>) => void;
|
|
9
|
-
|
|
10
11
|
export class EventNotifier<TIO extends IOLike> {
|
|
11
12
|
public subjects = new Map<
|
|
12
13
|
keyof InferIOOutput<TIO>,
|