@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/.turbo/turbo-build.log +9 -9
- package/CHANGELOG.md +179 -0
- package/dist/index.d.mts +163 -77
- package/dist/index.d.ts +163 -77
- package/dist/index.js +318 -189
- package/dist/index.mjs +318 -189
- package/package.json +7 -7
- package/src/AbstractRoom.ts +6 -4
- package/src/MockedRoom.ts +115 -27
- package/src/PluvClient.ts +80 -28
- package/src/PluvProcedure.ts +81 -0
- package/src/PluvRoom.ts +113 -45
- package/src/PluvRouter.ts +70 -0
- package/src/createClient.ts +11 -3
- package/src/enums.ts +7 -0
- package/src/index.ts +5 -3
- package/src/types.ts +43 -7
- package/src/utils/identity.ts +1 -0
- package/src/utils/index.ts +1 -0
package/dist/index.js
CHANGED
|
@@ -81,6 +81,41 @@ var AbstractStorageStore = class {
|
|
|
81
81
|
}
|
|
82
82
|
};
|
|
83
83
|
|
|
84
|
+
// src/PluvProcedure.ts
|
|
85
|
+
var PluvProcedure = class _PluvProcedure {
|
|
86
|
+
constructor(config = {}) {
|
|
87
|
+
this._broadcast = null;
|
|
88
|
+
this._input = null;
|
|
89
|
+
const { broadcast, input } = config;
|
|
90
|
+
this._broadcast = broadcast != null ? broadcast : null;
|
|
91
|
+
this._input = input != null ? input : null;
|
|
92
|
+
}
|
|
93
|
+
get config() {
|
|
94
|
+
var _a, _b, _c;
|
|
95
|
+
return {
|
|
96
|
+
broadcast: (_b = (_a = this._broadcast) == null ? void 0 : _a.bind(this)) != null ? _b : null,
|
|
97
|
+
input: (_c = this._input) != null ? _c : null,
|
|
98
|
+
resolver: this._resolver()
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
broadcast(resolver) {
|
|
102
|
+
const { broadcast } = this.config;
|
|
103
|
+
if (!!broadcast) throw new Error("Broadcast was already defined for this procedure");
|
|
104
|
+
return new _PluvProcedure(__spreadProps(__spreadValues({}, this.config), {
|
|
105
|
+
broadcast: resolver
|
|
106
|
+
}));
|
|
107
|
+
}
|
|
108
|
+
input(input) {
|
|
109
|
+
return new _PluvProcedure({ input });
|
|
110
|
+
}
|
|
111
|
+
_resolver() {
|
|
112
|
+
return (data, context) => {
|
|
113
|
+
var _a;
|
|
114
|
+
return (_a = this._broadcast) == null ? void 0 : _a.call(this, data, context);
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
};
|
|
118
|
+
|
|
84
119
|
// src/CrdtManager.ts
|
|
85
120
|
var import_crdt = require("@pluv/crdt");
|
|
86
121
|
var CrdtManager = class {
|
|
@@ -208,6 +243,21 @@ var OtherNotifier = class {
|
|
|
208
243
|
}
|
|
209
244
|
};
|
|
210
245
|
|
|
246
|
+
// src/PluvRouter.ts
|
|
247
|
+
var PluvRouter = class _PluvRouter {
|
|
248
|
+
constructor(events) {
|
|
249
|
+
this._defs = { events: {} };
|
|
250
|
+
this._defs = { events };
|
|
251
|
+
}
|
|
252
|
+
static merge(...routers) {
|
|
253
|
+
const events = Object.assign(/* @__PURE__ */ Object.create(null), ...routers.map((router) => router._defs.events));
|
|
254
|
+
if (Object.keys(events).some((key) => key.startsWith("$"))) {
|
|
255
|
+
throw new Error('Procedures may not start with "$"');
|
|
256
|
+
}
|
|
257
|
+
return new _PluvRouter(events);
|
|
258
|
+
}
|
|
259
|
+
};
|
|
260
|
+
|
|
211
261
|
// src/StateNotifier.ts
|
|
212
262
|
var import_wonka4 = require("wonka");
|
|
213
263
|
var StateNotifier = class {
|
|
@@ -228,6 +278,31 @@ var StateNotifier = class {
|
|
|
228
278
|
}
|
|
229
279
|
};
|
|
230
280
|
|
|
281
|
+
// src/StorageStore.ts
|
|
282
|
+
var StorageStore = class extends AbstractStorageStore {
|
|
283
|
+
addUpdate() {
|
|
284
|
+
return Promise.resolve();
|
|
285
|
+
}
|
|
286
|
+
applyUpdates() {
|
|
287
|
+
return Promise.resolve();
|
|
288
|
+
}
|
|
289
|
+
destroy() {
|
|
290
|
+
return Promise.resolve();
|
|
291
|
+
}
|
|
292
|
+
flatten() {
|
|
293
|
+
return Promise.resolve();
|
|
294
|
+
}
|
|
295
|
+
getShouldFlatten() {
|
|
296
|
+
return Promise.resolve(false);
|
|
297
|
+
}
|
|
298
|
+
getUpdates() {
|
|
299
|
+
return Promise.resolve([]);
|
|
300
|
+
}
|
|
301
|
+
initialize() {
|
|
302
|
+
return Promise.resolve();
|
|
303
|
+
}
|
|
304
|
+
};
|
|
305
|
+
|
|
231
306
|
// src/UsersManager.ts
|
|
232
307
|
var UsersManager = class {
|
|
233
308
|
constructor(config) {
|
|
@@ -321,7 +396,7 @@ var UsersManager = class {
|
|
|
321
396
|
}
|
|
322
397
|
};
|
|
323
398
|
|
|
324
|
-
// src/
|
|
399
|
+
// src/enums.ts
|
|
325
400
|
var ConnectionState = /* @__PURE__ */ ((ConnectionState2) => {
|
|
326
401
|
ConnectionState2["Closed"] = "Closed";
|
|
327
402
|
ConnectionState2["Connecting"] = "Connecting";
|
|
@@ -331,179 +406,6 @@ var ConnectionState = /* @__PURE__ */ ((ConnectionState2) => {
|
|
|
331
406
|
return ConnectionState2;
|
|
332
407
|
})(ConnectionState || {});
|
|
333
408
|
|
|
334
|
-
// src/MockedRoom.ts
|
|
335
|
-
var MockedRoom = class extends AbstractRoom {
|
|
336
|
-
constructor(room, options) {
|
|
337
|
-
const { events, initialPresence, initialStorage, presence } = options;
|
|
338
|
-
super(room);
|
|
339
|
-
this._crdtNotifier = new CrdtNotifier();
|
|
340
|
-
this._eventNotifier = new EventNotifier();
|
|
341
|
-
this._otherNotifier = new OtherNotifier();
|
|
342
|
-
this._state = {
|
|
343
|
-
authorization: {
|
|
344
|
-
token: null,
|
|
345
|
-
user: null
|
|
346
|
-
},
|
|
347
|
-
connection: {
|
|
348
|
-
count: 1,
|
|
349
|
-
id: null,
|
|
350
|
-
state: "Untouched" /* Untouched */
|
|
351
|
-
},
|
|
352
|
-
webSocket: null
|
|
353
|
-
};
|
|
354
|
-
this._stateNotifier = new StateNotifier();
|
|
355
|
-
this._subscriptions = {
|
|
356
|
-
observeCrdt: null
|
|
357
|
-
};
|
|
358
|
-
this.canRedo = () => {
|
|
359
|
-
return !!this._crdtManager.doc.canRedo();
|
|
360
|
-
};
|
|
361
|
-
this.canUndo = () => {
|
|
362
|
-
return !!this._crdtManager.doc.canUndo();
|
|
363
|
-
};
|
|
364
|
-
this.event = (event, callback) => {
|
|
365
|
-
return this._eventNotifier.subscribe(event, callback);
|
|
366
|
-
};
|
|
367
|
-
this.getConnection = () => {
|
|
368
|
-
return Object.freeze(JSON.parse(JSON.stringify(this._state.connection)));
|
|
369
|
-
};
|
|
370
|
-
this.getMyPresence = () => {
|
|
371
|
-
return this._usersManager.myPresence;
|
|
372
|
-
};
|
|
373
|
-
this.getMyself = () => {
|
|
374
|
-
return this._usersManager.myself;
|
|
375
|
-
};
|
|
376
|
-
this.getOther = (connectionId) => {
|
|
377
|
-
return this._usersManager.getOther(connectionId);
|
|
378
|
-
};
|
|
379
|
-
this.getOthers = () => {
|
|
380
|
-
return this._usersManager.getOthers();
|
|
381
|
-
};
|
|
382
|
-
this.getStorage = (type) => {
|
|
383
|
-
const sharedType = this._crdtManager.get(type);
|
|
384
|
-
if (typeof sharedType === "undefined") return null;
|
|
385
|
-
return sharedType;
|
|
386
|
-
};
|
|
387
|
-
this.other = (connectionId, callback) => {
|
|
388
|
-
return this._otherNotifier.subscribe(connectionId, callback);
|
|
389
|
-
};
|
|
390
|
-
this.redo = () => {
|
|
391
|
-
this._crdtManager.doc.redo();
|
|
392
|
-
};
|
|
393
|
-
this.storage = (key, fn) => {
|
|
394
|
-
return this._crdtNotifier.subscribe(key, fn);
|
|
395
|
-
};
|
|
396
|
-
this.storageRoot = (fn) => {
|
|
397
|
-
return this._crdtNotifier.subcribeRoot(fn);
|
|
398
|
-
};
|
|
399
|
-
this.subscribe = (name, callback) => {
|
|
400
|
-
return this._stateNotifier.subscribe(name, callback);
|
|
401
|
-
};
|
|
402
|
-
this.transact = (fn, origin) => {
|
|
403
|
-
const _origin = origin != null ? origin : this._state.connection.id;
|
|
404
|
-
const crdtManager = this._crdtManager;
|
|
405
|
-
if (typeof _origin !== "string") return;
|
|
406
|
-
if (!crdtManager) return;
|
|
407
|
-
crdtManager.doc.transact(() => {
|
|
408
|
-
const storage = crdtManager.doc.get();
|
|
409
|
-
fn(storage);
|
|
410
|
-
}, _origin);
|
|
411
|
-
};
|
|
412
|
-
this.undo = () => {
|
|
413
|
-
this._crdtManager.doc.undo();
|
|
414
|
-
};
|
|
415
|
-
this.updateMyPresence = (presence) => {
|
|
416
|
-
var _a;
|
|
417
|
-
const newPresence = typeof presence === "function" ? presence(this.getMyPresence()) : presence;
|
|
418
|
-
this._usersManager.updateMyPresence(newPresence);
|
|
419
|
-
const myPresence = this._usersManager.myPresence;
|
|
420
|
-
const myself = (_a = this._usersManager.myself) != null ? _a : null;
|
|
421
|
-
this._stateNotifier.subjects["my-presence"].next(myPresence);
|
|
422
|
-
!!myself && this._stateNotifier.subjects["myself"].next(myself);
|
|
423
|
-
};
|
|
424
|
-
this._events = events;
|
|
425
|
-
this._usersManager = new UsersManager({
|
|
426
|
-
initialPresence,
|
|
427
|
-
presence
|
|
428
|
-
});
|
|
429
|
-
this._crdtManager = new CrdtManager({
|
|
430
|
-
initialStorage
|
|
431
|
-
});
|
|
432
|
-
this._observeCrdt();
|
|
433
|
-
}
|
|
434
|
-
get storageLoaded() {
|
|
435
|
-
return true;
|
|
436
|
-
}
|
|
437
|
-
broadcast(event, data) {
|
|
438
|
-
if (!this._events) return;
|
|
439
|
-
const resolver = this._events[event];
|
|
440
|
-
if (!resolver) return;
|
|
441
|
-
const result = resolver(data);
|
|
442
|
-
Object.keys(result).forEach((type) => {
|
|
443
|
-
const _type = type.toString();
|
|
444
|
-
const data2 = result[_type];
|
|
445
|
-
if (!data2) return;
|
|
446
|
-
this._eventNotifier.subject(_type).next(data2);
|
|
447
|
-
});
|
|
448
|
-
}
|
|
449
|
-
getDoc() {
|
|
450
|
-
return this._crdtManager.doc;
|
|
451
|
-
}
|
|
452
|
-
getStorageJson(type) {
|
|
453
|
-
if (this._state.connection.id === null) return null;
|
|
454
|
-
if (typeof type === "undefined") return this._crdtManager.doc.toJson();
|
|
455
|
-
return this._crdtManager.doc.toJson(type);
|
|
456
|
-
}
|
|
457
|
-
_observeCrdt() {
|
|
458
|
-
var _a, _b;
|
|
459
|
-
(_b = (_a = this._subscriptions).observeCrdt) == null ? void 0 : _b.call(_a);
|
|
460
|
-
if (!this._crdtManager) return;
|
|
461
|
-
const unsubscribe = this._crdtManager.doc.subscribe((event) => {
|
|
462
|
-
var _a2;
|
|
463
|
-
const origin = (_a2 = event.origin) != null ? _a2 : null;
|
|
464
|
-
if (!this._crdtManager) return;
|
|
465
|
-
if (origin === "$STORAGE_UPDATED") return;
|
|
466
|
-
const sharedTypes = this._crdtManager.doc.get();
|
|
467
|
-
const storageRoot = Object.keys(sharedTypes).reduce(
|
|
468
|
-
(acc, prop) => {
|
|
469
|
-
if (!this._crdtManager) return acc;
|
|
470
|
-
const serialized = this._crdtManager.doc.toJson(prop);
|
|
471
|
-
this._crdtNotifier.subject(prop).next(serialized);
|
|
472
|
-
return __spreadProps(__spreadValues({}, acc), { [prop]: serialized });
|
|
473
|
-
},
|
|
474
|
-
{}
|
|
475
|
-
);
|
|
476
|
-
this._crdtNotifier.rootSubject.next(storageRoot);
|
|
477
|
-
});
|
|
478
|
-
this._subscriptions.observeCrdt = unsubscribe;
|
|
479
|
-
}
|
|
480
|
-
};
|
|
481
|
-
|
|
482
|
-
// src/StorageStore.ts
|
|
483
|
-
var StorageStore = class extends AbstractStorageStore {
|
|
484
|
-
addUpdate() {
|
|
485
|
-
return Promise.resolve();
|
|
486
|
-
}
|
|
487
|
-
applyUpdates() {
|
|
488
|
-
return Promise.resolve();
|
|
489
|
-
}
|
|
490
|
-
destroy() {
|
|
491
|
-
return Promise.resolve();
|
|
492
|
-
}
|
|
493
|
-
flatten() {
|
|
494
|
-
return Promise.resolve();
|
|
495
|
-
}
|
|
496
|
-
getShouldFlatten() {
|
|
497
|
-
return Promise.resolve(false);
|
|
498
|
-
}
|
|
499
|
-
getUpdates() {
|
|
500
|
-
return Promise.resolve([]);
|
|
501
|
-
}
|
|
502
|
-
initialize() {
|
|
503
|
-
return Promise.resolve();
|
|
504
|
-
}
|
|
505
|
-
};
|
|
506
|
-
|
|
507
409
|
// src/utils/debounce.ts
|
|
508
410
|
var debounce = (fn, options) => {
|
|
509
411
|
const { wait, immediate = false } = options != null ? options : {};
|
|
@@ -541,8 +443,10 @@ var PluvRoom = class extends AbstractRoom {
|
|
|
541
443
|
debug = false,
|
|
542
444
|
initialPresence,
|
|
543
445
|
initialStorage,
|
|
446
|
+
metadata,
|
|
544
447
|
onAuthorizationFail,
|
|
545
448
|
presence,
|
|
449
|
+
router,
|
|
546
450
|
wsEndpoint
|
|
547
451
|
} = options;
|
|
548
452
|
super(room);
|
|
@@ -551,6 +455,7 @@ var PluvRoom = class extends AbstractRoom {
|
|
|
551
455
|
this._intervals = {
|
|
552
456
|
heartbeat: null
|
|
553
457
|
};
|
|
458
|
+
this._metadata = {};
|
|
554
459
|
this._otherNotifier = new OtherNotifier();
|
|
555
460
|
this._state = {
|
|
556
461
|
authorization: {
|
|
@@ -575,17 +480,37 @@ var PluvRoom = class extends AbstractRoom {
|
|
|
575
480
|
this._windowListeners = null;
|
|
576
481
|
this._wsListeners = null;
|
|
577
482
|
this.broadcast = new Proxy(
|
|
578
|
-
(event, data) => {
|
|
483
|
+
(event, data) => __async(this, null, function* () {
|
|
579
484
|
if (!this._state.webSocket) return;
|
|
580
485
|
if (this._state.connection.state !== "Open" /* Open */) return;
|
|
581
486
|
const type = event.toString();
|
|
582
|
-
this.
|
|
583
|
-
|
|
487
|
+
const procedure = this._router._defs.events[type];
|
|
488
|
+
if (!(procedure == null ? void 0 : procedure.config.broadcast)) {
|
|
489
|
+
this._sendMessage({ data, type });
|
|
490
|
+
return;
|
|
491
|
+
}
|
|
492
|
+
const myself = this._usersManager.myself;
|
|
493
|
+
if (!myself) return;
|
|
494
|
+
const parsed = procedure.config.input ? procedure.config.input.parse(data) : data;
|
|
495
|
+
const context = {
|
|
496
|
+
doc: this._crdtManager.doc,
|
|
497
|
+
others: this._usersManager.getOthers(),
|
|
498
|
+
room: this.id,
|
|
499
|
+
user: myself
|
|
500
|
+
};
|
|
501
|
+
const output = yield procedure.config.broadcast(
|
|
502
|
+
parsed,
|
|
503
|
+
context
|
|
504
|
+
);
|
|
505
|
+
Object.entries(output).forEach(([_type, _data]) => {
|
|
506
|
+
this._sendMessage({ data: _data, type: _type });
|
|
507
|
+
});
|
|
508
|
+
}),
|
|
584
509
|
{
|
|
585
510
|
get(fn, prop) {
|
|
586
|
-
return (data) => {
|
|
587
|
-
return fn(prop, data);
|
|
588
|
-
};
|
|
511
|
+
return (data) => __async(this, null, function* () {
|
|
512
|
+
return yield fn(prop, data);
|
|
513
|
+
});
|
|
589
514
|
}
|
|
590
515
|
}
|
|
591
516
|
);
|
|
@@ -660,7 +585,10 @@ var PluvRoom = class extends AbstractRoom {
|
|
|
660
585
|
const myself = (_a = this._usersManager.myself) != null ? _a : null;
|
|
661
586
|
this._stateNotifier.subjects["my-presence"].next(myPresence);
|
|
662
587
|
!!myself && this._stateNotifier.subjects["myself"].next(myself);
|
|
663
|
-
this.broadcast(
|
|
588
|
+
this.broadcast(
|
|
589
|
+
"$UPDATE_PRESENCE",
|
|
590
|
+
{ presence: newPresence }
|
|
591
|
+
);
|
|
664
592
|
};
|
|
665
593
|
this._flattenStorageStore = debounce(
|
|
666
594
|
() => __async(this, null, function* () {
|
|
@@ -681,9 +609,10 @@ var PluvRoom = class extends AbstractRoom {
|
|
|
681
609
|
};
|
|
682
610
|
const addon = this._getAddon(addons);
|
|
683
611
|
const { storage } = __spreadValues(__spreadValues({}, DEFAULT_PLUV_CLIENT_ADDON({ room: this })), addon({ room: this }));
|
|
684
|
-
this._storageStore = storage;
|
|
685
612
|
this._debug = debug;
|
|
686
613
|
this._endpoints = { authEndpoint, wsEndpoint };
|
|
614
|
+
this._storageStore = storage;
|
|
615
|
+
if (!!metadata) this._metadata = metadata;
|
|
687
616
|
this._listeners = {
|
|
688
617
|
onAuthorizationFail: (error) => {
|
|
689
618
|
this._clearTimeout(this._timeouts.reconnect);
|
|
@@ -691,6 +620,7 @@ var PluvRoom = class extends AbstractRoom {
|
|
|
691
620
|
onAuthorizationFail == null ? void 0 : onAuthorizationFail(error);
|
|
692
621
|
}
|
|
693
622
|
};
|
|
623
|
+
this._router = router != null ? router : new PluvRouter({});
|
|
694
624
|
this._usersManager = new UsersManager({ initialPresence, presence });
|
|
695
625
|
this._crdtManager = new CrdtManager({ initialStorage });
|
|
696
626
|
}
|
|
@@ -875,7 +805,7 @@ var PluvRoom = class extends AbstractRoom {
|
|
|
875
805
|
options: {}
|
|
876
806
|
};
|
|
877
807
|
}
|
|
878
|
-
const result = this._endpoints.authEndpoint(room);
|
|
808
|
+
const result = this._endpoints.authEndpoint({ metadata: this._metadata, room });
|
|
879
809
|
return typeof result === "string" ? { url: result, options: {} } : result;
|
|
880
810
|
}
|
|
881
811
|
_getAuthorization(room) {
|
|
@@ -901,7 +831,7 @@ var PluvRoom = class extends AbstractRoom {
|
|
|
901
831
|
case "string":
|
|
902
832
|
return this._endpoints.wsEndpoint;
|
|
903
833
|
default:
|
|
904
|
-
return this._endpoints.wsEndpoint(room);
|
|
834
|
+
return this._endpoints.wsEndpoint({ metadata: this._metadata, room });
|
|
905
835
|
}
|
|
906
836
|
}
|
|
907
837
|
_handleExit(message) {
|
|
@@ -1259,8 +1189,11 @@ var PluvClient = class {
|
|
|
1259
1189
|
authEndpoint: this._authEndpoint,
|
|
1260
1190
|
debug: options.debug,
|
|
1261
1191
|
initialPresence: options.initialPresence,
|
|
1262
|
-
initialStorage:
|
|
1192
|
+
initialStorage: this._initialStorage,
|
|
1193
|
+
metadata: options.metadata,
|
|
1263
1194
|
onAuthorizationFail: options.onAuthorizationFail,
|
|
1195
|
+
presence: this._presence,
|
|
1196
|
+
router: options.router,
|
|
1264
1197
|
wsEndpoint: this._wsEndpoint
|
|
1265
1198
|
});
|
|
1266
1199
|
this._rooms.set(room, newRoom);
|
|
@@ -1269,9 +1202,7 @@ var PluvClient = class {
|
|
|
1269
1202
|
};
|
|
1270
1203
|
this.enter = (room) => __async(this, null, function* () {
|
|
1271
1204
|
const toEnter = typeof room === "string" ? this.getRoom(room) : room;
|
|
1272
|
-
if (!toEnter) {
|
|
1273
|
-
throw new Error(`Could not find room: ${room}.`);
|
|
1274
|
-
}
|
|
1205
|
+
if (!toEnter) throw new Error(`Could not find room: ${room}.`);
|
|
1275
1206
|
this._rooms.set(toEnter.id, toEnter);
|
|
1276
1207
|
yield toEnter.connect();
|
|
1277
1208
|
this._logDebug(`Entered room: ${room}`);
|
|
@@ -1291,11 +1222,19 @@ var PluvClient = class {
|
|
|
1291
1222
|
this._rooms.delete(toLeave.id);
|
|
1292
1223
|
this._logDebug(`Left and deleted room: ${room}`);
|
|
1293
1224
|
});
|
|
1294
|
-
const { authEndpoint, debug = false, wsEndpoint } = options;
|
|
1225
|
+
const { authEndpoint, debug = false, initialStorage, presence, wsEndpoint } = options;
|
|
1295
1226
|
this._authEndpoint = authEndpoint;
|
|
1296
1227
|
this._debug = debug;
|
|
1228
|
+
this._initialStorage = initialStorage;
|
|
1229
|
+
this._presence = presence;
|
|
1297
1230
|
this._wsEndpoint = wsEndpoint;
|
|
1298
1231
|
}
|
|
1232
|
+
get procedure() {
|
|
1233
|
+
return new PluvProcedure();
|
|
1234
|
+
}
|
|
1235
|
+
router(events) {
|
|
1236
|
+
return new PluvRouter(events);
|
|
1237
|
+
}
|
|
1299
1238
|
_logDebug(...data) {
|
|
1300
1239
|
var _a;
|
|
1301
1240
|
if (((_a = process == null ? void 0 : process.env) == null ? void 0 : _a.NODE_ENV) === "production") return;
|
|
@@ -1307,6 +1246,196 @@ var PluvClient = class {
|
|
|
1307
1246
|
var createClient = (options) => {
|
|
1308
1247
|
return new PluvClient(options);
|
|
1309
1248
|
};
|
|
1249
|
+
|
|
1250
|
+
// src/MockedRoom.ts
|
|
1251
|
+
var MockedRoom = class extends AbstractRoom {
|
|
1252
|
+
constructor(room, options) {
|
|
1253
|
+
const { events, initialPresence, initialStorage, presence, router } = options;
|
|
1254
|
+
super(room);
|
|
1255
|
+
this._crdtNotifier = new CrdtNotifier();
|
|
1256
|
+
this._eventNotifier = new EventNotifier();
|
|
1257
|
+
this._otherNotifier = new OtherNotifier();
|
|
1258
|
+
this._state = {
|
|
1259
|
+
authorization: {
|
|
1260
|
+
token: null,
|
|
1261
|
+
user: null
|
|
1262
|
+
},
|
|
1263
|
+
connection: {
|
|
1264
|
+
count: 1,
|
|
1265
|
+
id: null,
|
|
1266
|
+
state: "Untouched" /* Untouched */
|
|
1267
|
+
},
|
|
1268
|
+
webSocket: null
|
|
1269
|
+
};
|
|
1270
|
+
this._stateNotifier = new StateNotifier();
|
|
1271
|
+
this._subscriptions = {
|
|
1272
|
+
observeCrdt: null
|
|
1273
|
+
};
|
|
1274
|
+
this.broadcast = new Proxy(
|
|
1275
|
+
(event, data) => __async(this, null, function* () {
|
|
1276
|
+
if (!this._state.webSocket) return;
|
|
1277
|
+
if (this._state.connection.state !== "Open" /* Open */) return;
|
|
1278
|
+
const type = event.toString();
|
|
1279
|
+
const procedure = this._router._defs.events[type];
|
|
1280
|
+
if (!(procedure == null ? void 0 : procedure.config.broadcast)) {
|
|
1281
|
+
this._simulateEvent(type, data);
|
|
1282
|
+
return;
|
|
1283
|
+
}
|
|
1284
|
+
const myself = this._usersManager.myself;
|
|
1285
|
+
if (!myself) return;
|
|
1286
|
+
const parsed = procedure.config.input ? procedure.config.input.parse(data) : data;
|
|
1287
|
+
const context = {
|
|
1288
|
+
doc: this._crdtManager.doc,
|
|
1289
|
+
others: this._usersManager.getOthers(),
|
|
1290
|
+
room: this.id,
|
|
1291
|
+
user: myself
|
|
1292
|
+
};
|
|
1293
|
+
const output = yield procedure.config.broadcast(
|
|
1294
|
+
parsed,
|
|
1295
|
+
context
|
|
1296
|
+
);
|
|
1297
|
+
Object.entries(output).forEach(([_type, _data]) => {
|
|
1298
|
+
this._simulateEvent(_type, _data);
|
|
1299
|
+
});
|
|
1300
|
+
}),
|
|
1301
|
+
{
|
|
1302
|
+
get(fn, prop) {
|
|
1303
|
+
return (data) => __async(this, null, function* () {
|
|
1304
|
+
return yield fn(prop, data);
|
|
1305
|
+
});
|
|
1306
|
+
}
|
|
1307
|
+
}
|
|
1308
|
+
);
|
|
1309
|
+
this.canRedo = () => {
|
|
1310
|
+
return !!this._crdtManager.doc.canRedo();
|
|
1311
|
+
};
|
|
1312
|
+
this.canUndo = () => {
|
|
1313
|
+
return !!this._crdtManager.doc.canUndo();
|
|
1314
|
+
};
|
|
1315
|
+
this.event = new Proxy(
|
|
1316
|
+
(event, callback) => this._eventNotifier.subscribe(event, callback),
|
|
1317
|
+
{
|
|
1318
|
+
get(fn, prop) {
|
|
1319
|
+
return (callback) => fn(prop, callback);
|
|
1320
|
+
}
|
|
1321
|
+
}
|
|
1322
|
+
);
|
|
1323
|
+
this.getConnection = () => {
|
|
1324
|
+
return Object.freeze(JSON.parse(JSON.stringify(this._state.connection)));
|
|
1325
|
+
};
|
|
1326
|
+
this.getMyPresence = () => {
|
|
1327
|
+
return this._usersManager.myPresence;
|
|
1328
|
+
};
|
|
1329
|
+
this.getMyself = () => {
|
|
1330
|
+
return this._usersManager.myself;
|
|
1331
|
+
};
|
|
1332
|
+
this.getOther = (connectionId) => {
|
|
1333
|
+
return this._usersManager.getOther(connectionId);
|
|
1334
|
+
};
|
|
1335
|
+
this.getOthers = () => {
|
|
1336
|
+
return this._usersManager.getOthers();
|
|
1337
|
+
};
|
|
1338
|
+
this.getStorage = (type) => {
|
|
1339
|
+
const sharedType = this._crdtManager.get(type);
|
|
1340
|
+
if (typeof sharedType === "undefined") return null;
|
|
1341
|
+
return sharedType;
|
|
1342
|
+
};
|
|
1343
|
+
this.other = (connectionId, callback) => {
|
|
1344
|
+
return this._otherNotifier.subscribe(connectionId, callback);
|
|
1345
|
+
};
|
|
1346
|
+
this.redo = () => {
|
|
1347
|
+
this._crdtManager.doc.redo();
|
|
1348
|
+
};
|
|
1349
|
+
this.storage = (key, fn) => {
|
|
1350
|
+
return this._crdtNotifier.subscribe(key, fn);
|
|
1351
|
+
};
|
|
1352
|
+
this.storageRoot = (fn) => {
|
|
1353
|
+
return this._crdtNotifier.subcribeRoot(fn);
|
|
1354
|
+
};
|
|
1355
|
+
this.subscribe = (name, callback) => {
|
|
1356
|
+
return this._stateNotifier.subscribe(name, callback);
|
|
1357
|
+
};
|
|
1358
|
+
this.transact = (fn, origin) => {
|
|
1359
|
+
const _origin = origin != null ? origin : this._state.connection.id;
|
|
1360
|
+
const crdtManager = this._crdtManager;
|
|
1361
|
+
if (typeof _origin !== "string") return;
|
|
1362
|
+
if (!crdtManager) return;
|
|
1363
|
+
crdtManager.doc.transact(() => {
|
|
1364
|
+
const storage = crdtManager.doc.get();
|
|
1365
|
+
fn(storage);
|
|
1366
|
+
}, _origin);
|
|
1367
|
+
};
|
|
1368
|
+
this.undo = () => {
|
|
1369
|
+
this._crdtManager.doc.undo();
|
|
1370
|
+
};
|
|
1371
|
+
this.updateMyPresence = (presence) => {
|
|
1372
|
+
var _a;
|
|
1373
|
+
const newPresence = typeof presence === "function" ? presence(this.getMyPresence()) : presence;
|
|
1374
|
+
this._usersManager.updateMyPresence(newPresence);
|
|
1375
|
+
const myPresence = this._usersManager.myPresence;
|
|
1376
|
+
const myself = (_a = this._usersManager.myself) != null ? _a : null;
|
|
1377
|
+
this._stateNotifier.subjects["my-presence"].next(myPresence);
|
|
1378
|
+
!!myself && this._stateNotifier.subjects["myself"].next(myself);
|
|
1379
|
+
};
|
|
1380
|
+
this._events = events;
|
|
1381
|
+
this._router = router != null ? router : new PluvRouter({});
|
|
1382
|
+
this._usersManager = new UsersManager({
|
|
1383
|
+
initialPresence,
|
|
1384
|
+
presence
|
|
1385
|
+
});
|
|
1386
|
+
this._crdtManager = new CrdtManager({
|
|
1387
|
+
initialStorage
|
|
1388
|
+
});
|
|
1389
|
+
this._observeCrdt();
|
|
1390
|
+
}
|
|
1391
|
+
get storageLoaded() {
|
|
1392
|
+
return true;
|
|
1393
|
+
}
|
|
1394
|
+
getDoc() {
|
|
1395
|
+
return this._crdtManager.doc;
|
|
1396
|
+
}
|
|
1397
|
+
getStorageJson(type) {
|
|
1398
|
+
if (this._state.connection.id === null) return null;
|
|
1399
|
+
if (typeof type === "undefined") return this._crdtManager.doc.toJson();
|
|
1400
|
+
return this._crdtManager.doc.toJson(type);
|
|
1401
|
+
}
|
|
1402
|
+
_observeCrdt() {
|
|
1403
|
+
var _a, _b;
|
|
1404
|
+
(_b = (_a = this._subscriptions).observeCrdt) == null ? void 0 : _b.call(_a);
|
|
1405
|
+
if (!this._crdtManager) return;
|
|
1406
|
+
const unsubscribe = this._crdtManager.doc.subscribe((event) => {
|
|
1407
|
+
var _a2;
|
|
1408
|
+
const origin = (_a2 = event.origin) != null ? _a2 : null;
|
|
1409
|
+
if (!this._crdtManager) return;
|
|
1410
|
+
if (origin === "$STORAGE_UPDATED") return;
|
|
1411
|
+
const sharedTypes = this._crdtManager.doc.get();
|
|
1412
|
+
const storageRoot = Object.keys(sharedTypes).reduce(
|
|
1413
|
+
(acc, prop) => {
|
|
1414
|
+
if (!this._crdtManager) return acc;
|
|
1415
|
+
const serialized = this._crdtManager.doc.toJson(prop);
|
|
1416
|
+
this._crdtNotifier.subject(prop).next(serialized);
|
|
1417
|
+
return __spreadProps(__spreadValues({}, acc), { [prop]: serialized });
|
|
1418
|
+
},
|
|
1419
|
+
{}
|
|
1420
|
+
);
|
|
1421
|
+
this._crdtNotifier.rootSubject.next(storageRoot);
|
|
1422
|
+
});
|
|
1423
|
+
this._subscriptions.observeCrdt = unsubscribe;
|
|
1424
|
+
}
|
|
1425
|
+
_simulateEvent(event, data) {
|
|
1426
|
+
if (!this._events) return;
|
|
1427
|
+
const type = event.toString();
|
|
1428
|
+
const resolver = this._events[type];
|
|
1429
|
+
if (!resolver) return;
|
|
1430
|
+
const result = resolver(data);
|
|
1431
|
+
Object.keys(result).forEach((type2) => {
|
|
1432
|
+
const _type = type2.toString();
|
|
1433
|
+
const data2 = result[_type];
|
|
1434
|
+
if (!data2) return;
|
|
1435
|
+
this._eventNotifier.subject(_type).next(data2);
|
|
1436
|
+
});
|
|
1437
|
+
}
|
|
1438
|
+
};
|
|
1310
1439
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1311
1440
|
0 && (module.exports = {
|
|
1312
1441
|
AbstractRoom,
|