@pluv/client 0.25.4 → 0.27.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/dist/index.mjs CHANGED
@@ -52,6 +52,41 @@ var AbstractStorageStore = class {
52
52
  }
53
53
  };
54
54
 
55
+ // src/PluvProcedure.ts
56
+ var PluvProcedure = class _PluvProcedure {
57
+ constructor(config = {}) {
58
+ this._broadcast = null;
59
+ this._input = null;
60
+ const { broadcast, input } = config;
61
+ this._broadcast = broadcast != null ? broadcast : null;
62
+ this._input = input != null ? input : null;
63
+ }
64
+ get config() {
65
+ var _a, _b, _c;
66
+ return {
67
+ broadcast: (_b = (_a = this._broadcast) == null ? void 0 : _a.bind(this)) != null ? _b : null,
68
+ input: (_c = this._input) != null ? _c : null,
69
+ resolver: this._resolver()
70
+ };
71
+ }
72
+ broadcast(resolver) {
73
+ const { broadcast } = this.config;
74
+ if (!!broadcast) throw new Error("Broadcast was already defined for this procedure");
75
+ return new _PluvProcedure(__spreadProps(__spreadValues({}, this.config), {
76
+ broadcast: resolver
77
+ }));
78
+ }
79
+ input(input) {
80
+ return new _PluvProcedure({ input });
81
+ }
82
+ _resolver() {
83
+ return (data, context) => {
84
+ var _a;
85
+ return (_a = this._broadcast) == null ? void 0 : _a.call(this, data, context);
86
+ };
87
+ }
88
+ };
89
+
55
90
  // src/CrdtManager.ts
56
91
  import { noop } from "@pluv/crdt";
57
92
  var CrdtManager = class {
@@ -179,6 +214,21 @@ var OtherNotifier = class {
179
214
  }
180
215
  };
181
216
 
217
+ // src/PluvRouter.ts
218
+ var PluvRouter = class _PluvRouter {
219
+ constructor(events) {
220
+ this._defs = { events: {} };
221
+ this._defs = { events };
222
+ }
223
+ static merge(...routers) {
224
+ const events = Object.assign(/* @__PURE__ */ Object.create(null), ...routers.map((router) => router._defs.events));
225
+ if (Object.keys(events).some((key) => key.startsWith("$"))) {
226
+ throw new Error('Procedures may not start with "$"');
227
+ }
228
+ return new _PluvRouter(events);
229
+ }
230
+ };
231
+
182
232
  // src/StateNotifier.ts
183
233
  import { makeSubject as makeSubject4, subscribe as subscribe4 } from "wonka";
184
234
  var StateNotifier = class {
@@ -199,6 +249,31 @@ var StateNotifier = class {
199
249
  }
200
250
  };
201
251
 
252
+ // src/StorageStore.ts
253
+ var StorageStore = class extends AbstractStorageStore {
254
+ addUpdate() {
255
+ return Promise.resolve();
256
+ }
257
+ applyUpdates() {
258
+ return Promise.resolve();
259
+ }
260
+ destroy() {
261
+ return Promise.resolve();
262
+ }
263
+ flatten() {
264
+ return Promise.resolve();
265
+ }
266
+ getShouldFlatten() {
267
+ return Promise.resolve(false);
268
+ }
269
+ getUpdates() {
270
+ return Promise.resolve([]);
271
+ }
272
+ initialize() {
273
+ return Promise.resolve();
274
+ }
275
+ };
276
+
202
277
  // src/UsersManager.ts
203
278
  var UsersManager = class {
204
279
  constructor(config) {
@@ -292,7 +367,7 @@ var UsersManager = class {
292
367
  }
293
368
  };
294
369
 
295
- // src/types.ts
370
+ // src/enums.ts
296
371
  var ConnectionState = /* @__PURE__ */ ((ConnectionState2) => {
297
372
  ConnectionState2["Closed"] = "Closed";
298
373
  ConnectionState2["Connecting"] = "Connecting";
@@ -302,179 +377,6 @@ var ConnectionState = /* @__PURE__ */ ((ConnectionState2) => {
302
377
  return ConnectionState2;
303
378
  })(ConnectionState || {});
304
379
 
305
- // src/MockedRoom.ts
306
- var MockedRoom = class extends AbstractRoom {
307
- constructor(room, options) {
308
- const { events, initialPresence, initialStorage, presence } = options;
309
- super(room);
310
- this._crdtNotifier = new CrdtNotifier();
311
- this._eventNotifier = new EventNotifier();
312
- this._otherNotifier = new OtherNotifier();
313
- this._state = {
314
- authorization: {
315
- token: null,
316
- user: null
317
- },
318
- connection: {
319
- count: 1,
320
- id: null,
321
- state: "Untouched" /* Untouched */
322
- },
323
- webSocket: null
324
- };
325
- this._stateNotifier = new StateNotifier();
326
- this._subscriptions = {
327
- observeCrdt: null
328
- };
329
- this.canRedo = () => {
330
- return !!this._crdtManager.doc.canRedo();
331
- };
332
- this.canUndo = () => {
333
- return !!this._crdtManager.doc.canUndo();
334
- };
335
- this.event = (event, callback) => {
336
- return this._eventNotifier.subscribe(event, callback);
337
- };
338
- this.getConnection = () => {
339
- return Object.freeze(JSON.parse(JSON.stringify(this._state.connection)));
340
- };
341
- this.getMyPresence = () => {
342
- return this._usersManager.myPresence;
343
- };
344
- this.getMyself = () => {
345
- return this._usersManager.myself;
346
- };
347
- this.getOther = (connectionId) => {
348
- return this._usersManager.getOther(connectionId);
349
- };
350
- this.getOthers = () => {
351
- return this._usersManager.getOthers();
352
- };
353
- this.getStorage = (type) => {
354
- const sharedType = this._crdtManager.get(type);
355
- if (typeof sharedType === "undefined") return null;
356
- return sharedType;
357
- };
358
- this.other = (connectionId, callback) => {
359
- return this._otherNotifier.subscribe(connectionId, callback);
360
- };
361
- this.redo = () => {
362
- this._crdtManager.doc.redo();
363
- };
364
- this.storage = (key, fn) => {
365
- return this._crdtNotifier.subscribe(key, fn);
366
- };
367
- this.storageRoot = (fn) => {
368
- return this._crdtNotifier.subcribeRoot(fn);
369
- };
370
- this.subscribe = (name, callback) => {
371
- return this._stateNotifier.subscribe(name, callback);
372
- };
373
- this.transact = (fn, origin) => {
374
- const _origin = origin != null ? origin : this._state.connection.id;
375
- const crdtManager = this._crdtManager;
376
- if (typeof _origin !== "string") return;
377
- if (!crdtManager) return;
378
- crdtManager.doc.transact(() => {
379
- const storage = crdtManager.doc.get();
380
- fn(storage);
381
- }, _origin);
382
- };
383
- this.undo = () => {
384
- this._crdtManager.doc.undo();
385
- };
386
- this.updateMyPresence = (presence) => {
387
- var _a;
388
- const newPresence = typeof presence === "function" ? presence(this.getMyPresence()) : presence;
389
- this._usersManager.updateMyPresence(newPresence);
390
- const myPresence = this._usersManager.myPresence;
391
- const myself = (_a = this._usersManager.myself) != null ? _a : null;
392
- this._stateNotifier.subjects["my-presence"].next(myPresence);
393
- !!myself && this._stateNotifier.subjects["myself"].next(myself);
394
- };
395
- this._events = events;
396
- this._usersManager = new UsersManager({
397
- initialPresence,
398
- presence
399
- });
400
- this._crdtManager = new CrdtManager({
401
- initialStorage
402
- });
403
- this._observeCrdt();
404
- }
405
- get storageLoaded() {
406
- return true;
407
- }
408
- broadcast(event, data) {
409
- if (!this._events) return;
410
- const resolver = this._events[event];
411
- if (!resolver) return;
412
- const result = resolver(data);
413
- Object.keys(result).forEach((type) => {
414
- const _type = type.toString();
415
- const data2 = result[_type];
416
- if (!data2) return;
417
- this._eventNotifier.subject(_type).next(data2);
418
- });
419
- }
420
- getDoc() {
421
- return this._crdtManager.doc;
422
- }
423
- getStorageJson(type) {
424
- if (this._state.connection.id === null) return null;
425
- if (typeof type === "undefined") return this._crdtManager.doc.toJson();
426
- return this._crdtManager.doc.toJson(type);
427
- }
428
- _observeCrdt() {
429
- var _a, _b;
430
- (_b = (_a = this._subscriptions).observeCrdt) == null ? void 0 : _b.call(_a);
431
- if (!this._crdtManager) return;
432
- const unsubscribe = this._crdtManager.doc.subscribe((event) => {
433
- var _a2;
434
- const origin = (_a2 = event.origin) != null ? _a2 : null;
435
- if (!this._crdtManager) return;
436
- if (origin === "$STORAGE_UPDATED") return;
437
- const sharedTypes = this._crdtManager.doc.get();
438
- const storageRoot = Object.keys(sharedTypes).reduce(
439
- (acc, prop) => {
440
- if (!this._crdtManager) return acc;
441
- const serialized = this._crdtManager.doc.toJson(prop);
442
- this._crdtNotifier.subject(prop).next(serialized);
443
- return __spreadProps(__spreadValues({}, acc), { [prop]: serialized });
444
- },
445
- {}
446
- );
447
- this._crdtNotifier.rootSubject.next(storageRoot);
448
- });
449
- this._subscriptions.observeCrdt = unsubscribe;
450
- }
451
- };
452
-
453
- // src/StorageStore.ts
454
- var StorageStore = class extends AbstractStorageStore {
455
- addUpdate() {
456
- return Promise.resolve();
457
- }
458
- applyUpdates() {
459
- return Promise.resolve();
460
- }
461
- destroy() {
462
- return Promise.resolve();
463
- }
464
- flatten() {
465
- return Promise.resolve();
466
- }
467
- getShouldFlatten() {
468
- return Promise.resolve(false);
469
- }
470
- getUpdates() {
471
- return Promise.resolve([]);
472
- }
473
- initialize() {
474
- return Promise.resolve();
475
- }
476
- };
477
-
478
380
  // src/utils/debounce.ts
479
381
  var debounce = (fn, options) => {
480
382
  const { wait, immediate = false } = options != null ? options : {};
@@ -512,8 +414,10 @@ var PluvRoom = class extends AbstractRoom {
512
414
  debug = false,
513
415
  initialPresence,
514
416
  initialStorage,
417
+ metadata,
515
418
  onAuthorizationFail,
516
419
  presence,
420
+ router,
517
421
  wsEndpoint
518
422
  } = options;
519
423
  super(room);
@@ -522,6 +426,7 @@ var PluvRoom = class extends AbstractRoom {
522
426
  this._intervals = {
523
427
  heartbeat: null
524
428
  };
429
+ this._metadata = {};
525
430
  this._otherNotifier = new OtherNotifier();
526
431
  this._state = {
527
432
  authorization: {
@@ -546,17 +451,37 @@ var PluvRoom = class extends AbstractRoom {
546
451
  this._windowListeners = null;
547
452
  this._wsListeners = null;
548
453
  this.broadcast = new Proxy(
549
- (event, data) => {
454
+ (event, data) => __async(this, null, function* () {
550
455
  if (!this._state.webSocket) return;
551
456
  if (this._state.connection.state !== "Open" /* Open */) return;
552
457
  const type = event.toString();
553
- this._sendMessage({ data, type });
554
- },
458
+ const procedure = this._router._defs.events[type];
459
+ if (!(procedure == null ? void 0 : procedure.config.broadcast)) {
460
+ this._sendMessage({ data, type });
461
+ return;
462
+ }
463
+ const myself = this._usersManager.myself;
464
+ if (!myself) return;
465
+ const parsed = procedure.config.input ? procedure.config.input.parse(data) : data;
466
+ const context = {
467
+ doc: this._crdtManager.doc,
468
+ others: this._usersManager.getOthers(),
469
+ room: this.id,
470
+ user: myself
471
+ };
472
+ const output = yield procedure.config.broadcast(
473
+ parsed,
474
+ context
475
+ );
476
+ Object.entries(output).forEach(([_type, _data]) => {
477
+ this._sendMessage({ data: _data, type: _type });
478
+ });
479
+ }),
555
480
  {
556
481
  get(fn, prop) {
557
- return (data) => {
558
- return fn(prop, data);
559
- };
482
+ return (data) => __async(this, null, function* () {
483
+ return yield fn(prop, data);
484
+ });
560
485
  }
561
486
  }
562
487
  );
@@ -631,7 +556,10 @@ var PluvRoom = class extends AbstractRoom {
631
556
  const myself = (_a = this._usersManager.myself) != null ? _a : null;
632
557
  this._stateNotifier.subjects["my-presence"].next(myPresence);
633
558
  !!myself && this._stateNotifier.subjects["myself"].next(myself);
634
- this.broadcast("$UPDATE_PRESENCE", { presence: newPresence });
559
+ this.broadcast(
560
+ "$UPDATE_PRESENCE",
561
+ { presence: newPresence }
562
+ );
635
563
  };
636
564
  this._flattenStorageStore = debounce(
637
565
  () => __async(this, null, function* () {
@@ -652,9 +580,10 @@ var PluvRoom = class extends AbstractRoom {
652
580
  };
653
581
  const addon = this._getAddon(addons);
654
582
  const { storage } = __spreadValues(__spreadValues({}, DEFAULT_PLUV_CLIENT_ADDON({ room: this })), addon({ room: this }));
655
- this._storageStore = storage;
656
583
  this._debug = debug;
657
584
  this._endpoints = { authEndpoint, wsEndpoint };
585
+ this._storageStore = storage;
586
+ if (!!metadata) this._metadata = metadata;
658
587
  this._listeners = {
659
588
  onAuthorizationFail: (error) => {
660
589
  this._clearTimeout(this._timeouts.reconnect);
@@ -662,6 +591,7 @@ var PluvRoom = class extends AbstractRoom {
662
591
  onAuthorizationFail == null ? void 0 : onAuthorizationFail(error);
663
592
  }
664
593
  };
594
+ this._router = router != null ? router : new PluvRouter({});
665
595
  this._usersManager = new UsersManager({ initialPresence, presence });
666
596
  this._crdtManager = new CrdtManager({ initialStorage });
667
597
  }
@@ -846,7 +776,7 @@ var PluvRoom = class extends AbstractRoom {
846
776
  options: {}
847
777
  };
848
778
  }
849
- const result = this._endpoints.authEndpoint(room);
779
+ const result = this._endpoints.authEndpoint({ metadata: this._metadata, room });
850
780
  return typeof result === "string" ? { url: result, options: {} } : result;
851
781
  }
852
782
  _getAuthorization(room) {
@@ -872,7 +802,7 @@ var PluvRoom = class extends AbstractRoom {
872
802
  case "string":
873
803
  return this._endpoints.wsEndpoint;
874
804
  default:
875
- return this._endpoints.wsEndpoint(room);
805
+ return this._endpoints.wsEndpoint({ metadata: this._metadata, room });
876
806
  }
877
807
  }
878
808
  _handleExit(message) {
@@ -1230,8 +1160,11 @@ var PluvClient = class {
1230
1160
  authEndpoint: this._authEndpoint,
1231
1161
  debug: options.debug,
1232
1162
  initialPresence: options.initialPresence,
1233
- initialStorage: options.initialStorage,
1163
+ initialStorage: this._initialStorage,
1164
+ metadata: options.metadata,
1234
1165
  onAuthorizationFail: options.onAuthorizationFail,
1166
+ presence: this._presence,
1167
+ router: options.router,
1235
1168
  wsEndpoint: this._wsEndpoint
1236
1169
  });
1237
1170
  this._rooms.set(room, newRoom);
@@ -1240,9 +1173,7 @@ var PluvClient = class {
1240
1173
  };
1241
1174
  this.enter = (room) => __async(this, null, function* () {
1242
1175
  const toEnter = typeof room === "string" ? this.getRoom(room) : room;
1243
- if (!toEnter) {
1244
- throw new Error(`Could not find room: ${room}.`);
1245
- }
1176
+ if (!toEnter) throw new Error(`Could not find room: ${room}.`);
1246
1177
  this._rooms.set(toEnter.id, toEnter);
1247
1178
  yield toEnter.connect();
1248
1179
  this._logDebug(`Entered room: ${room}`);
@@ -1262,11 +1193,19 @@ var PluvClient = class {
1262
1193
  this._rooms.delete(toLeave.id);
1263
1194
  this._logDebug(`Left and deleted room: ${room}`);
1264
1195
  });
1265
- const { authEndpoint, debug = false, wsEndpoint } = options;
1196
+ const { authEndpoint, debug = false, initialStorage, presence, wsEndpoint } = options;
1266
1197
  this._authEndpoint = authEndpoint;
1267
1198
  this._debug = debug;
1199
+ this._initialStorage = initialStorage;
1200
+ this._presence = presence;
1268
1201
  this._wsEndpoint = wsEndpoint;
1269
1202
  }
1203
+ get procedure() {
1204
+ return new PluvProcedure();
1205
+ }
1206
+ router(events) {
1207
+ return new PluvRouter(events);
1208
+ }
1270
1209
  _logDebug(...data) {
1271
1210
  var _a;
1272
1211
  if (((_a = process == null ? void 0 : process.env) == null ? void 0 : _a.NODE_ENV) === "production") return;
@@ -1278,6 +1217,196 @@ var PluvClient = class {
1278
1217
  var createClient = (options) => {
1279
1218
  return new PluvClient(options);
1280
1219
  };
1220
+
1221
+ // src/MockedRoom.ts
1222
+ var MockedRoom = class extends AbstractRoom {
1223
+ constructor(room, options) {
1224
+ const { events, initialPresence, initialStorage, presence, router } = options;
1225
+ super(room);
1226
+ this._crdtNotifier = new CrdtNotifier();
1227
+ this._eventNotifier = new EventNotifier();
1228
+ this._otherNotifier = new OtherNotifier();
1229
+ this._state = {
1230
+ authorization: {
1231
+ token: null,
1232
+ user: null
1233
+ },
1234
+ connection: {
1235
+ count: 1,
1236
+ id: null,
1237
+ state: "Untouched" /* Untouched */
1238
+ },
1239
+ webSocket: null
1240
+ };
1241
+ this._stateNotifier = new StateNotifier();
1242
+ this._subscriptions = {
1243
+ observeCrdt: null
1244
+ };
1245
+ this.broadcast = new Proxy(
1246
+ (event, data) => __async(this, null, function* () {
1247
+ if (!this._state.webSocket) return;
1248
+ if (this._state.connection.state !== "Open" /* Open */) return;
1249
+ const type = event.toString();
1250
+ const procedure = this._router._defs.events[type];
1251
+ if (!(procedure == null ? void 0 : procedure.config.broadcast)) {
1252
+ this._simulateEvent(type, data);
1253
+ return;
1254
+ }
1255
+ const myself = this._usersManager.myself;
1256
+ if (!myself) return;
1257
+ const parsed = procedure.config.input ? procedure.config.input.parse(data) : data;
1258
+ const context = {
1259
+ doc: this._crdtManager.doc,
1260
+ others: this._usersManager.getOthers(),
1261
+ room: this.id,
1262
+ user: myself
1263
+ };
1264
+ const output = yield procedure.config.broadcast(
1265
+ parsed,
1266
+ context
1267
+ );
1268
+ Object.entries(output).forEach(([_type, _data]) => {
1269
+ this._simulateEvent(_type, _data);
1270
+ });
1271
+ }),
1272
+ {
1273
+ get(fn, prop) {
1274
+ return (data) => __async(this, null, function* () {
1275
+ return yield fn(prop, data);
1276
+ });
1277
+ }
1278
+ }
1279
+ );
1280
+ this.canRedo = () => {
1281
+ return !!this._crdtManager.doc.canRedo();
1282
+ };
1283
+ this.canUndo = () => {
1284
+ return !!this._crdtManager.doc.canUndo();
1285
+ };
1286
+ this.event = new Proxy(
1287
+ (event, callback) => this._eventNotifier.subscribe(event, callback),
1288
+ {
1289
+ get(fn, prop) {
1290
+ return (callback) => fn(prop, callback);
1291
+ }
1292
+ }
1293
+ );
1294
+ this.getConnection = () => {
1295
+ return Object.freeze(JSON.parse(JSON.stringify(this._state.connection)));
1296
+ };
1297
+ this.getMyPresence = () => {
1298
+ return this._usersManager.myPresence;
1299
+ };
1300
+ this.getMyself = () => {
1301
+ return this._usersManager.myself;
1302
+ };
1303
+ this.getOther = (connectionId) => {
1304
+ return this._usersManager.getOther(connectionId);
1305
+ };
1306
+ this.getOthers = () => {
1307
+ return this._usersManager.getOthers();
1308
+ };
1309
+ this.getStorage = (type) => {
1310
+ const sharedType = this._crdtManager.get(type);
1311
+ if (typeof sharedType === "undefined") return null;
1312
+ return sharedType;
1313
+ };
1314
+ this.other = (connectionId, callback) => {
1315
+ return this._otherNotifier.subscribe(connectionId, callback);
1316
+ };
1317
+ this.redo = () => {
1318
+ this._crdtManager.doc.redo();
1319
+ };
1320
+ this.storage = (key, fn) => {
1321
+ return this._crdtNotifier.subscribe(key, fn);
1322
+ };
1323
+ this.storageRoot = (fn) => {
1324
+ return this._crdtNotifier.subcribeRoot(fn);
1325
+ };
1326
+ this.subscribe = (name, callback) => {
1327
+ return this._stateNotifier.subscribe(name, callback);
1328
+ };
1329
+ this.transact = (fn, origin) => {
1330
+ const _origin = origin != null ? origin : this._state.connection.id;
1331
+ const crdtManager = this._crdtManager;
1332
+ if (typeof _origin !== "string") return;
1333
+ if (!crdtManager) return;
1334
+ crdtManager.doc.transact(() => {
1335
+ const storage = crdtManager.doc.get();
1336
+ fn(storage);
1337
+ }, _origin);
1338
+ };
1339
+ this.undo = () => {
1340
+ this._crdtManager.doc.undo();
1341
+ };
1342
+ this.updateMyPresence = (presence) => {
1343
+ var _a;
1344
+ const newPresence = typeof presence === "function" ? presence(this.getMyPresence()) : presence;
1345
+ this._usersManager.updateMyPresence(newPresence);
1346
+ const myPresence = this._usersManager.myPresence;
1347
+ const myself = (_a = this._usersManager.myself) != null ? _a : null;
1348
+ this._stateNotifier.subjects["my-presence"].next(myPresence);
1349
+ !!myself && this._stateNotifier.subjects["myself"].next(myself);
1350
+ };
1351
+ this._events = events;
1352
+ this._router = router != null ? router : new PluvRouter({});
1353
+ this._usersManager = new UsersManager({
1354
+ initialPresence,
1355
+ presence
1356
+ });
1357
+ this._crdtManager = new CrdtManager({
1358
+ initialStorage
1359
+ });
1360
+ this._observeCrdt();
1361
+ }
1362
+ get storageLoaded() {
1363
+ return true;
1364
+ }
1365
+ getDoc() {
1366
+ return this._crdtManager.doc;
1367
+ }
1368
+ getStorageJson(type) {
1369
+ if (this._state.connection.id === null) return null;
1370
+ if (typeof type === "undefined") return this._crdtManager.doc.toJson();
1371
+ return this._crdtManager.doc.toJson(type);
1372
+ }
1373
+ _observeCrdt() {
1374
+ var _a, _b;
1375
+ (_b = (_a = this._subscriptions).observeCrdt) == null ? void 0 : _b.call(_a);
1376
+ if (!this._crdtManager) return;
1377
+ const unsubscribe = this._crdtManager.doc.subscribe((event) => {
1378
+ var _a2;
1379
+ const origin = (_a2 = event.origin) != null ? _a2 : null;
1380
+ if (!this._crdtManager) return;
1381
+ if (origin === "$STORAGE_UPDATED") return;
1382
+ const sharedTypes = this._crdtManager.doc.get();
1383
+ const storageRoot = Object.keys(sharedTypes).reduce(
1384
+ (acc, prop) => {
1385
+ if (!this._crdtManager) return acc;
1386
+ const serialized = this._crdtManager.doc.toJson(prop);
1387
+ this._crdtNotifier.subject(prop).next(serialized);
1388
+ return __spreadProps(__spreadValues({}, acc), { [prop]: serialized });
1389
+ },
1390
+ {}
1391
+ );
1392
+ this._crdtNotifier.rootSubject.next(storageRoot);
1393
+ });
1394
+ this._subscriptions.observeCrdt = unsubscribe;
1395
+ }
1396
+ _simulateEvent(event, data) {
1397
+ if (!this._events) return;
1398
+ const type = event.toString();
1399
+ const resolver = this._events[type];
1400
+ if (!resolver) return;
1401
+ const result = resolver(data);
1402
+ Object.keys(result).forEach((type2) => {
1403
+ const _type = type2.toString();
1404
+ const data2 = result[_type];
1405
+ if (!data2) return;
1406
+ this._eventNotifier.subject(_type).next(data2);
1407
+ });
1408
+ }
1409
+ };
1281
1410
  export {
1282
1411
  AbstractRoom,
1283
1412
  AbstractStorageStore,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pluv/client",
3
- "version": "0.25.4",
3
+ "version": "0.27.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.4",
21
- "@pluv/crdt": "^0.25.4",
22
- "@pluv/types": "^0.25.4"
21
+ "@pluv/crdt": "^0.27.0",
22
+ "@pluv/types": "^0.27.0"
23
23
  },
24
24
  "devDependencies": {
25
25
  "eslint": "^8.57.0",
26
- "tsup": "^8.2.4",
27
- "typescript": "^5.5.4",
28
- "@pluv/tsconfig": "^0.25.4",
29
- "eslint-config-pluv": "^0.25.4"
26
+ "tsup": "^8.3.0",
27
+ "typescript": "^5.6.2",
28
+ "@pluv/tsconfig": "^0.27.0",
29
+ "eslint-config-pluv": "^0.27.0"
30
30
  },
31
31
  "scripts": {
32
32
  "build": "tsup src/index.ts --format esm,cjs --dts",
@@ -2,6 +2,7 @@ import type { AbstractCrdtDoc, CrdtType, InferCrdtJson } from "@pluv/crdt";
2
2
  import type { IOLike, Id, InferIOInput, InferIOOutput, JsonObject } from "@pluv/types";
3
3
  import type { EventNotifierSubscriptionCallback } from "./EventNotifier";
4
4
  import type { OtherNotifierSubscriptionCallback } from "./OtherNotifier";
5
+ import type { MergeEvents, PluvRouterEventConfig } from "./PluvRouter";
5
6
  import type { StateNotifierSubjects, SubscriptionCallback } from "./StateNotifier";
6
7
  import type { UpdateMyPresenceAction, UserInfo, WebSocketConnection } from "./types";
7
8
 
@@ -9,6 +10,7 @@ export abstract class AbstractRoom<
9
10
  TIO extends IOLike,
10
11
  TPresence extends JsonObject = {},
11
12
  TStorage extends Record<string, CrdtType<any, any>> = {},
13
+ TEvents extends PluvRouterEventConfig<TIO, TPresence, TStorage> = {},
12
14
  > {
13
15
  public readonly id: string;
14
16
 
@@ -18,9 +20,9 @@ export abstract class AbstractRoom<
18
20
 
19
21
  public abstract storageLoaded: boolean;
20
22
 
21
- public abstract broadcast<TEvent extends keyof InferIOInput<TIO>>(
23
+ public abstract broadcast<TEvent extends keyof InferIOInput<MergeEvents<TEvents, TIO>>>(
22
24
  event: TEvent,
23
- data: Id<InferIOInput<TIO>[TEvent]>,
25
+ data: Id<InferIOInput<MergeEvents<TEvents, TIO>>[TEvent]>,
24
26
  ): void;
25
27
 
26
28
  public abstract canRedo(): boolean;
@@ -29,9 +31,9 @@ export abstract class AbstractRoom<
29
31
 
30
32
  public abstract getDoc(): AbstractCrdtDoc<TStorage>;
31
33
 
32
- public abstract event<TEvent extends keyof InferIOOutput<TIO>>(
34
+ public abstract event<TEvent extends keyof InferIOOutput<MergeEvents<TEvents, TIO>>>(
33
35
  event: TEvent,
34
- callback: EventNotifierSubscriptionCallback<TIO, TEvent>,
36
+ callback: EventNotifierSubscriptionCallback<MergeEvents<TEvents, TIO>, TEvent>,
35
37
  ): () => void;
36
38
 
37
39
  public abstract getConnection(): WebSocketConnection;