@pluv/client 0.25.4 → 0.26.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
@@ -199,6 +199,31 @@ var StateNotifier = class {
199
199
  }
200
200
  };
201
201
 
202
+ // src/StorageStore.ts
203
+ var StorageStore = class extends AbstractStorageStore {
204
+ addUpdate() {
205
+ return Promise.resolve();
206
+ }
207
+ applyUpdates() {
208
+ return Promise.resolve();
209
+ }
210
+ destroy() {
211
+ return Promise.resolve();
212
+ }
213
+ flatten() {
214
+ return Promise.resolve();
215
+ }
216
+ getShouldFlatten() {
217
+ return Promise.resolve(false);
218
+ }
219
+ getUpdates() {
220
+ return Promise.resolve([]);
221
+ }
222
+ initialize() {
223
+ return Promise.resolve();
224
+ }
225
+ };
226
+
202
227
  // src/UsersManager.ts
203
228
  var UsersManager = class {
204
229
  constructor(config) {
@@ -302,179 +327,6 @@ var ConnectionState = /* @__PURE__ */ ((ConnectionState2) => {
302
327
  return ConnectionState2;
303
328
  })(ConnectionState || {});
304
329
 
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
330
  // src/utils/debounce.ts
479
331
  var debounce = (fn, options) => {
480
332
  const { wait, immediate = false } = options != null ? options : {};
@@ -512,6 +364,7 @@ var PluvRoom = class extends AbstractRoom {
512
364
  debug = false,
513
365
  initialPresence,
514
366
  initialStorage,
367
+ metadata,
515
368
  onAuthorizationFail,
516
369
  presence,
517
370
  wsEndpoint
@@ -522,6 +375,7 @@ var PluvRoom = class extends AbstractRoom {
522
375
  this._intervals = {
523
376
  heartbeat: null
524
377
  };
378
+ this._metadata = {};
525
379
  this._otherNotifier = new OtherNotifier();
526
380
  this._state = {
527
381
  authorization: {
@@ -652,9 +506,10 @@ var PluvRoom = class extends AbstractRoom {
652
506
  };
653
507
  const addon = this._getAddon(addons);
654
508
  const { storage } = __spreadValues(__spreadValues({}, DEFAULT_PLUV_CLIENT_ADDON({ room: this })), addon({ room: this }));
655
- this._storageStore = storage;
656
509
  this._debug = debug;
657
510
  this._endpoints = { authEndpoint, wsEndpoint };
511
+ this._storageStore = storage;
512
+ if (!!metadata) this._metadata = metadata;
658
513
  this._listeners = {
659
514
  onAuthorizationFail: (error) => {
660
515
  this._clearTimeout(this._timeouts.reconnect);
@@ -846,7 +701,7 @@ var PluvRoom = class extends AbstractRoom {
846
701
  options: {}
847
702
  };
848
703
  }
849
- const result = this._endpoints.authEndpoint(room);
704
+ const result = this._endpoints.authEndpoint({ metadata: this._metadata, room });
850
705
  return typeof result === "string" ? { url: result, options: {} } : result;
851
706
  }
852
707
  _getAuthorization(room) {
@@ -872,7 +727,7 @@ var PluvRoom = class extends AbstractRoom {
872
727
  case "string":
873
728
  return this._endpoints.wsEndpoint;
874
729
  default:
875
- return this._endpoints.wsEndpoint(room);
730
+ return this._endpoints.wsEndpoint({ metadata: this._metadata, room });
876
731
  }
877
732
  }
878
733
  _handleExit(message) {
@@ -1231,6 +1086,7 @@ var PluvClient = class {
1231
1086
  debug: options.debug,
1232
1087
  initialPresence: options.initialPresence,
1233
1088
  initialStorage: options.initialStorage,
1089
+ metadata: options.metadata,
1234
1090
  onAuthorizationFail: options.onAuthorizationFail,
1235
1091
  wsEndpoint: this._wsEndpoint
1236
1092
  });
@@ -1240,9 +1096,7 @@ var PluvClient = class {
1240
1096
  };
1241
1097
  this.enter = (room) => __async(this, null, function* () {
1242
1098
  const toEnter = typeof room === "string" ? this.getRoom(room) : room;
1243
- if (!toEnter) {
1244
- throw new Error(`Could not find room: ${room}.`);
1245
- }
1099
+ if (!toEnter) throw new Error(`Could not find room: ${room}.`);
1246
1100
  this._rooms.set(toEnter.id, toEnter);
1247
1101
  yield toEnter.connect();
1248
1102
  this._logDebug(`Entered room: ${room}`);
@@ -1278,6 +1132,154 @@ var PluvClient = class {
1278
1132
  var createClient = (options) => {
1279
1133
  return new PluvClient(options);
1280
1134
  };
1135
+
1136
+ // src/MockedRoom.ts
1137
+ var MockedRoom = class extends AbstractRoom {
1138
+ constructor(room, options) {
1139
+ const { events, initialPresence, initialStorage, presence } = options;
1140
+ super(room);
1141
+ this._crdtNotifier = new CrdtNotifier();
1142
+ this._eventNotifier = new EventNotifier();
1143
+ this._otherNotifier = new OtherNotifier();
1144
+ this._state = {
1145
+ authorization: {
1146
+ token: null,
1147
+ user: null
1148
+ },
1149
+ connection: {
1150
+ count: 1,
1151
+ id: null,
1152
+ state: "Untouched" /* Untouched */
1153
+ },
1154
+ webSocket: null
1155
+ };
1156
+ this._stateNotifier = new StateNotifier();
1157
+ this._subscriptions = {
1158
+ observeCrdt: null
1159
+ };
1160
+ this.canRedo = () => {
1161
+ return !!this._crdtManager.doc.canRedo();
1162
+ };
1163
+ this.canUndo = () => {
1164
+ return !!this._crdtManager.doc.canUndo();
1165
+ };
1166
+ this.event = (event, callback) => {
1167
+ return this._eventNotifier.subscribe(event, callback);
1168
+ };
1169
+ this.getConnection = () => {
1170
+ return Object.freeze(JSON.parse(JSON.stringify(this._state.connection)));
1171
+ };
1172
+ this.getMyPresence = () => {
1173
+ return this._usersManager.myPresence;
1174
+ };
1175
+ this.getMyself = () => {
1176
+ return this._usersManager.myself;
1177
+ };
1178
+ this.getOther = (connectionId) => {
1179
+ return this._usersManager.getOther(connectionId);
1180
+ };
1181
+ this.getOthers = () => {
1182
+ return this._usersManager.getOthers();
1183
+ };
1184
+ this.getStorage = (type) => {
1185
+ const sharedType = this._crdtManager.get(type);
1186
+ if (typeof sharedType === "undefined") return null;
1187
+ return sharedType;
1188
+ };
1189
+ this.other = (connectionId, callback) => {
1190
+ return this._otherNotifier.subscribe(connectionId, callback);
1191
+ };
1192
+ this.redo = () => {
1193
+ this._crdtManager.doc.redo();
1194
+ };
1195
+ this.storage = (key, fn) => {
1196
+ return this._crdtNotifier.subscribe(key, fn);
1197
+ };
1198
+ this.storageRoot = (fn) => {
1199
+ return this._crdtNotifier.subcribeRoot(fn);
1200
+ };
1201
+ this.subscribe = (name, callback) => {
1202
+ return this._stateNotifier.subscribe(name, callback);
1203
+ };
1204
+ this.transact = (fn, origin) => {
1205
+ const _origin = origin != null ? origin : this._state.connection.id;
1206
+ const crdtManager = this._crdtManager;
1207
+ if (typeof _origin !== "string") return;
1208
+ if (!crdtManager) return;
1209
+ crdtManager.doc.transact(() => {
1210
+ const storage = crdtManager.doc.get();
1211
+ fn(storage);
1212
+ }, _origin);
1213
+ };
1214
+ this.undo = () => {
1215
+ this._crdtManager.doc.undo();
1216
+ };
1217
+ this.updateMyPresence = (presence) => {
1218
+ var _a;
1219
+ const newPresence = typeof presence === "function" ? presence(this.getMyPresence()) : presence;
1220
+ this._usersManager.updateMyPresence(newPresence);
1221
+ const myPresence = this._usersManager.myPresence;
1222
+ const myself = (_a = this._usersManager.myself) != null ? _a : null;
1223
+ this._stateNotifier.subjects["my-presence"].next(myPresence);
1224
+ !!myself && this._stateNotifier.subjects["myself"].next(myself);
1225
+ };
1226
+ this._events = events;
1227
+ this._usersManager = new UsersManager({
1228
+ initialPresence,
1229
+ presence
1230
+ });
1231
+ this._crdtManager = new CrdtManager({
1232
+ initialStorage
1233
+ });
1234
+ this._observeCrdt();
1235
+ }
1236
+ get storageLoaded() {
1237
+ return true;
1238
+ }
1239
+ broadcast(event, data) {
1240
+ if (!this._events) return;
1241
+ const resolver = this._events[event];
1242
+ if (!resolver) return;
1243
+ const result = resolver(data);
1244
+ Object.keys(result).forEach((type) => {
1245
+ const _type = type.toString();
1246
+ const data2 = result[_type];
1247
+ if (!data2) return;
1248
+ this._eventNotifier.subject(_type).next(data2);
1249
+ });
1250
+ }
1251
+ getDoc() {
1252
+ return this._crdtManager.doc;
1253
+ }
1254
+ getStorageJson(type) {
1255
+ if (this._state.connection.id === null) return null;
1256
+ if (typeof type === "undefined") return this._crdtManager.doc.toJson();
1257
+ return this._crdtManager.doc.toJson(type);
1258
+ }
1259
+ _observeCrdt() {
1260
+ var _a, _b;
1261
+ (_b = (_a = this._subscriptions).observeCrdt) == null ? void 0 : _b.call(_a);
1262
+ if (!this._crdtManager) return;
1263
+ const unsubscribe = this._crdtManager.doc.subscribe((event) => {
1264
+ var _a2;
1265
+ const origin = (_a2 = event.origin) != null ? _a2 : null;
1266
+ if (!this._crdtManager) return;
1267
+ if (origin === "$STORAGE_UPDATED") return;
1268
+ const sharedTypes = this._crdtManager.doc.get();
1269
+ const storageRoot = Object.keys(sharedTypes).reduce(
1270
+ (acc, prop) => {
1271
+ if (!this._crdtManager) return acc;
1272
+ const serialized = this._crdtManager.doc.toJson(prop);
1273
+ this._crdtNotifier.subject(prop).next(serialized);
1274
+ return __spreadProps(__spreadValues({}, acc), { [prop]: serialized });
1275
+ },
1276
+ {}
1277
+ );
1278
+ this._crdtNotifier.rootSubject.next(storageRoot);
1279
+ });
1280
+ this._subscriptions.observeCrdt = unsubscribe;
1281
+ }
1282
+ };
1281
1283
  export {
1282
1284
  AbstractRoom,
1283
1285
  AbstractStorageStore,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pluv/client",
3
- "version": "0.25.4",
3
+ "version": "0.26.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.26.0",
22
+ "@pluv/types": "^0.26.0"
23
23
  },
24
24
  "devDependencies": {
25
25
  "eslint": "^8.57.0",
26
26
  "tsup": "^8.2.4",
27
27
  "typescript": "^5.5.4",
28
- "@pluv/tsconfig": "^0.25.4",
29
- "eslint-config-pluv": "^0.25.4"
28
+ "@pluv/tsconfig": "^0.26.0",
29
+ "eslint-config-pluv": "^0.26.0"
30
30
  },
31
31
  "scripts": {
32
32
  "build": "tsup src/index.ts --format esm,cjs --dts",
package/src/PluvClient.ts CHANGED
@@ -3,42 +3,43 @@ import type { IOLike, JsonObject } from "@pluv/types";
3
3
  import type { AuthEndpoint, PluvRoomOptions, RoomConfig, RoomEndpoints, WsEndpoint } from "./PluvRoom";
4
4
  import { PluvRoom } from "./PluvRoom";
5
5
 
6
- export type PluvClientOptions<TIO extends IOLike> = RoomEndpoints<TIO> & {
6
+ export type PluvClientOptions<TIO extends IOLike, TMetadata extends JsonObject> = RoomEndpoints<TIO, TMetadata> & {
7
7
  debug?: boolean;
8
8
  };
9
9
 
10
- export class PluvClient<TIO extends IOLike = IOLike> {
11
- private _authEndpoint: AuthEndpoint | undefined;
10
+ export class PluvClient<TIO extends IOLike = IOLike, TMetadata extends JsonObject = {}> {
11
+ private _authEndpoint: AuthEndpoint<TMetadata> | undefined;
12
12
  private _debug: boolean;
13
- private _wsEndpoint: WsEndpoint | undefined;
13
+ private _wsEndpoint: WsEndpoint<TMetadata> | undefined;
14
14
 
15
- private _rooms = new Map<string, PluvRoom<TIO, any, any>>();
15
+ private _rooms = new Map<string, PluvRoom<TIO, TMetadata, any, any>>();
16
16
 
17
- constructor(options: PluvClientOptions<TIO>) {
17
+ constructor(options: PluvClientOptions<TIO, TMetadata>) {
18
18
  const { authEndpoint, debug = false, wsEndpoint } = options;
19
19
 
20
- this._authEndpoint = authEndpoint as AuthEndpoint;
20
+ this._authEndpoint = authEndpoint as AuthEndpoint<TMetadata>;
21
21
  this._debug = debug;
22
22
  this._wsEndpoint = wsEndpoint;
23
23
  }
24
24
 
25
25
  public createRoom = <TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}>(
26
26
  room: string,
27
- options: PluvRoomOptions<TIO, TPresence, TStorage>,
28
- ): PluvRoom<TIO, TPresence, TStorage> => {
27
+ options: PluvRoomOptions<TIO, TMetadata, TPresence, TStorage>,
28
+ ): PluvRoom<TIO, TMetadata, TPresence, TStorage> => {
29
29
  const oldRoom = this.getRoom<TPresence, TStorage>(room);
30
30
 
31
31
  if (oldRoom) return oldRoom;
32
32
 
33
- const newRoom = new PluvRoom<TIO, TPresence, TStorage>(room, {
33
+ const newRoom = new PluvRoom<TIO, TMetadata, TPresence, TStorage>(room, {
34
34
  addons: options.addons,
35
35
  authEndpoint: this._authEndpoint,
36
36
  debug: options.debug,
37
37
  initialPresence: options.initialPresence,
38
38
  initialStorage: options.initialStorage,
39
+ metadata: options.metadata,
39
40
  onAuthorizationFail: options.onAuthorizationFail,
40
41
  wsEndpoint: this._wsEndpoint,
41
- } as RoomConfig<TIO, TPresence, TStorage>);
42
+ } as RoomConfig<TIO, TMetadata, TPresence, TStorage>);
42
43
 
43
44
  this._rooms.set(room, newRoom);
44
45
 
@@ -47,12 +48,12 @@ export class PluvClient<TIO extends IOLike = IOLike> {
47
48
  return newRoom;
48
49
  };
49
50
 
50
- public enter = async (room: string | PluvRoom<TIO, any, any>): Promise<PluvRoom<TIO, JsonObject, any>> => {
51
+ public enter = async (
52
+ room: string | PluvRoom<TIO, any, any, any>,
53
+ ): Promise<PluvRoom<TIO, TMetadata, JsonObject, any>> => {
51
54
  const toEnter = typeof room === "string" ? this.getRoom(room) : room;
52
55
 
53
- if (!toEnter) {
54
- throw new Error(`Could not find room: ${room}.`);
55
- }
56
+ if (!toEnter) throw new Error(`Could not find room: ${room}.`);
56
57
 
57
58
  this._rooms.set(toEnter.id, toEnter);
58
59
 
@@ -65,17 +66,17 @@ export class PluvClient<TIO extends IOLike = IOLike> {
65
66
 
66
67
  public getRoom = <TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}>(
67
68
  room: string,
68
- ): PluvRoom<TIO, TPresence, TStorage> | null => {
69
- const found = this._rooms.get(room) as PluvRoom<TIO, TPresence, TStorage> | undefined;
69
+ ): PluvRoom<TIO, TMetadata, TPresence, TStorage> | null => {
70
+ const found = this._rooms.get(room) as PluvRoom<TIO, TMetadata, TPresence, TStorage> | undefined;
70
71
 
71
72
  return found ?? null;
72
73
  };
73
74
 
74
- public getRooms = (): readonly PluvRoom<TIO, JsonObject, any>[] => {
75
+ public getRooms = (): readonly PluvRoom<TIO, TMetadata, JsonObject, any>[] => {
75
76
  return Array.from(this._rooms.values());
76
77
  };
77
78
 
78
- public leave = async (room: string | PluvRoom<TIO, any, any>): Promise<void> => {
79
+ public leave = async (room: string | PluvRoom<TIO, any, any, any>): Promise<void> => {
79
80
  const toLeave = typeof room === "string" ? this.getRoom(room) : room;
80
81
 
81
82
  if (!toLeave) return;