@pluv/io 0.4.2 → 0.6.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
@@ -279,9 +279,7 @@ var IORoom = class {
279
279
  this._platform = platform;
280
280
  this.id = id;
281
281
  this._listeners = {
282
- onDestroy: (encodedState) => {
283
- onDestroy == null ? void 0 : onDestroy(encodedState);
284
- }
282
+ onDestroy: (event) => onDestroy == null ? void 0 : onDestroy(event)
285
283
  };
286
284
  if (authorize2)
287
285
  this._authorize = authorize2;
@@ -300,10 +298,11 @@ var IORoom = class {
300
298
  }
301
299
  register(webSocket, options) {
302
300
  return __async(this, null, function* () {
303
- var _a;
301
+ var _b;
302
+ const _a = options, { token } = _a, _platformEventContext = __objRest(_a, ["token"]);
303
+ const platformEventContext = _platformEventContext;
304
304
  if (!this._uninitialize)
305
305
  yield this._initialize();
306
- const token = options == null ? void 0 : options.token;
307
306
  const sessionId = this._platform.randomUUID();
308
307
  const pluvWs = this._platform.convertWebSocket(webSocket, {
309
308
  room: this.id
@@ -315,7 +314,7 @@ var IORoom = class {
315
314
  );
316
315
  const uninitializeWs = yield pluvWs.initialize();
317
316
  const user = yield this._getAuthorizedUser(token);
318
- const isUnauthorized = !!((_a = this._authorize) == null ? void 0 : _a.required) && !user;
317
+ const isUnauthorized = !!((_b = this._authorize) == null ? void 0 : _b.required) && !user;
319
318
  const isTokenInUse = !!user && Array.from(this._sessions.values()).some(
320
319
  (session2) => {
321
320
  var _a2;
@@ -351,7 +350,9 @@ var IORoom = class {
351
350
  user != null ? user : {}
352
351
  );
353
352
  const onClose = this._onClose(session, uninitializeWs).bind(this);
354
- const onMessage = this._onMessage(session).bind(this);
353
+ const onMessage = this._onMessage(session, platformEventContext).bind(
354
+ this
355
+ );
355
356
  pluvWs.addEventListener("close", onClose);
356
357
  pluvWs.addEventListener("error", onClose);
357
358
  pluvWs.addEventListener("message", onMessage);
@@ -477,7 +478,10 @@ var IORoom = class {
477
478
  const encodedState = this._doc.encodeStateAsUpdate();
478
479
  this._doc.destroy();
479
480
  this._doc = doc();
480
- this._listeners.onDestroy(encodedState);
481
+ this._listeners.onDestroy(__spreadProps(__spreadValues({}, this._context), {
482
+ encodedState,
483
+ room: this.id
484
+ }));
481
485
  this._uninitialize = null;
482
486
  });
483
487
  });
@@ -521,10 +525,10 @@ var IORoom = class {
521
525
  });
522
526
  };
523
527
  }
524
- _onMessage(session) {
528
+ _onMessage(session, platformEventContext) {
525
529
  return (event) => {
526
530
  var _a, _b, _c;
527
- const context = {
531
+ const baseContext = {
528
532
  context: this._context,
529
533
  doc: this._doc,
530
534
  room: this.id,
@@ -552,10 +556,13 @@ var IORoom = class {
552
556
  });
553
557
  return;
554
558
  }
559
+ const extendedContext = __spreadProps(__spreadValues({}, baseContext), {
560
+ context: __spreadValues(__spreadValues({}, this._context), platformEventContext)
561
+ });
555
562
  Promise.all([
556
- (_a = resolver.broadcast) == null ? void 0 : _a.call(resolver, inputs, context),
557
- (_b = resolver.self) == null ? void 0 : _b.call(resolver, inputs, context),
558
- (_c = resolver.sync) == null ? void 0 : _c.call(resolver, inputs, context)
563
+ (_a = resolver.broadcast) == null ? void 0 : _a.call(resolver, inputs, extendedContext),
564
+ (_b = resolver.self) == null ? void 0 : _b.call(resolver, inputs, extendedContext),
565
+ (_c = resolver.sync) == null ? void 0 : _c.call(resolver, inputs, baseContext)
559
566
  ]).then(([broadcast, self, sync]) => {
560
567
  if (broadcast) {
561
568
  Object.entries(broadcast).forEach(([type, data]) => {
@@ -686,7 +693,7 @@ var IORoom = class {
686
693
  var PluvIO = class {
687
694
  constructor(options) {
688
695
  this._context = {};
689
- this._initialStorage = null;
696
+ this._getInitialStorage = null;
690
697
  this._rooms = /* @__PURE__ */ new Map();
691
698
  this._authorize = null;
692
699
  this._events = {
@@ -722,20 +729,25 @@ var PluvIO = class {
722
729
  }
723
730
  };
724
731
  },
725
- self: (_0, _1) => __async(this, [_0, _1], function* ({ update }, { doc: doc2, room }) {
732
+ self: (_0, _1) => __async(this, [_0, _1], function* ({ update }, { context, doc: doc2, room }) {
726
733
  var _a, _b;
727
734
  const oldState = yield this._platform.persistance.getStorageState(room);
728
735
  const updates = [
729
- oldState ? null : yield (_a = this._initialStorage) == null ? void 0 : _a.call(this, room),
736
+ oldState ? null : yield (_a = this._getInitialStorage) == null ? void 0 : _a.call(this, __spreadProps(__spreadValues({}, context), {
737
+ room
738
+ })),
730
739
  update
731
740
  ];
732
741
  if (updates.some((_update) => !!_update)) {
733
- const state2 = updates.reduce((_doc, _up) => _doc.applyUpdate(_up), doc2).encodeStateAsUpdate();
742
+ const encodedState = updates.reduce((_doc, _up) => _doc.applyUpdate(_up), doc2).encodeStateAsUpdate();
734
743
  yield this._platform.persistance.setStorageState(
735
744
  room,
736
- state2
745
+ encodedState
737
746
  );
738
- this._listeners.onStorageUpdated(room, state2);
747
+ this._listeners.onStorageUpdated(__spreadProps(__spreadValues({}, context), {
748
+ encodedState,
749
+ room
750
+ }));
739
751
  }
740
752
  const state = (_b = yield this._platform.persistance.getStorageState(
741
753
  room
@@ -768,16 +780,19 @@ var PluvIO = class {
768
780
  }
769
781
  },
770
782
  $UPDATE_STORAGE: {
771
- resolver: ({ origin, update }, { doc: doc2, room }) => {
783
+ resolver: ({ origin, update }, { context, doc: doc2, room }) => {
772
784
  if (origin === "$STORAGE_RECEIVED" && Object.keys(doc2.toJSON()).length) {
773
785
  return;
774
786
  }
775
787
  const updated = doc2.applyUpdate(update);
776
- const state = updated.encodeStateAsUpdate();
777
- this._platform.persistance.setStorageState(room, state).then(() => {
778
- this._listeners.onStorageUpdated(room, state);
788
+ const encodedState = updated.encodeStateAsUpdate();
789
+ this._platform.persistance.setStorageState(room, encodedState).then(() => {
790
+ this._listeners.onStorageUpdated(__spreadProps(__spreadValues({}, context), {
791
+ encodedState,
792
+ room
793
+ }));
779
794
  });
780
- return { $STORAGE_UPDATED: { state } };
795
+ return { $STORAGE_UPDATED: { state: encodedState } };
781
796
  }
782
797
  }
783
798
  };
@@ -786,7 +801,7 @@ var PluvIO = class {
786
801
  context,
787
802
  debug = false,
788
803
  events,
789
- initialStorage,
804
+ getInitialStorage,
790
805
  onRoomDeleted,
791
806
  onStorageUpdated,
792
807
  platform
@@ -799,15 +814,11 @@ var PluvIO = class {
799
814
  this._context = context;
800
815
  if (events)
801
816
  this._events = events;
802
- if (initialStorage)
803
- this._initialStorage = initialStorage;
817
+ if (getInitialStorage)
818
+ this._getInitialStorage = getInitialStorage;
804
819
  this._listeners = {
805
- onRoomDeleted: (room, encodedState) => {
806
- return onRoomDeleted == null ? void 0 : onRoomDeleted(room, encodedState);
807
- },
808
- onStorageUpdated: (room, encodedState) => {
809
- return onStorageUpdated == null ? void 0 : onStorageUpdated(room, encodedState);
810
- }
820
+ onRoomDeleted: (event) => onRoomDeleted == null ? void 0 : onRoomDeleted(event),
821
+ onStorageUpdated: (event) => onStorageUpdated == null ? void 0 : onStorageUpdated(event)
811
822
  };
812
823
  }
813
824
  createToken(params) {
@@ -838,9 +849,9 @@ var PluvIO = class {
838
849
  })
839
850
  );
840
851
  }
841
- getRoom(room, options = {}) {
842
- var _a;
843
- const { debug } = options;
852
+ getRoom(room, options) {
853
+ var _b;
854
+ const _a = options, { debug } = _a, platformRoomContext = __objRest(_a, ["debug"]);
844
855
  this._purgeEmptyRooms();
845
856
  if (!/^[a-z0-9]+[a-z0-9\-_]+[a-z0-9]+$/i.test(room)) {
846
857
  throw new Error("Unsupported room name");
@@ -849,20 +860,25 @@ var PluvIO = class {
849
860
  const oldRoom = this._rooms.get(room);
850
861
  if (oldRoom)
851
862
  return oldRoom;
863
+ const roomContext = __spreadValues(__spreadValues({}, this._context), platformRoomContext);
852
864
  const newRoom = new IORoom(room, {
853
- authorize: (_a = this._authorize) != null ? _a : void 0,
854
- context: this._context,
865
+ authorize: (_b = this._authorize) != null ? _b : void 0,
866
+ context: roomContext,
855
867
  debug: debug != null ? debug : this._debug,
856
868
  events: this._events,
857
- onDestroy: (encodedState) => {
869
+ onDestroy: ({ encodedState, room: room2 }) => {
858
870
  this._logDebug(
859
- `${colors2.blue("Deleting empty room:")} ${room}`
871
+ `${colors2.blue("Deleting empty room:")} ${room2}`
860
872
  );
861
- this._rooms.delete(room);
862
- this._listeners.onRoomDeleted(room, encodedState);
873
+ const roomContext2 = __spreadValues({
874
+ room: room2,
875
+ encodedState
876
+ }, platformRoomContext);
877
+ this._rooms.delete(room2);
878
+ this._listeners.onRoomDeleted(roomContext2);
863
879
  if (this._debug) {
864
880
  const rooms = Array.from(this._rooms.keys());
865
- this._logDebug(`${colors2.blue("Deleted room:")} ${room}`);
881
+ this._logDebug(`${colors2.blue("Deleted room:")} ${room2}`);
866
882
  this._logDebug(
867
883
  `${colors2.blue("Rooms available:")} ${rooms.join(", ")}`
868
884
  );
@@ -917,7 +933,7 @@ var createIO = (params) => {
917
933
  authorize: authorize2,
918
934
  context,
919
935
  debug,
920
- initialStorage,
936
+ getInitialStorage,
921
937
  onRoomDeleted,
922
938
  onStorageUpdated,
923
939
  platform
@@ -926,7 +942,7 @@ var createIO = (params) => {
926
942
  authorize: authorize2,
927
943
  context,
928
944
  debug,
929
- initialStorage,
945
+ getInitialStorage,
930
946
  onRoomDeleted,
931
947
  onStorageUpdated,
932
948
  platform
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pluv/io",
3
- "version": "0.4.2",
3
+ "version": "0.6.0",
4
4
  "description": "@pluv/io server-side websocket manager",
5
5
  "author": "leedavidcs",
6
6
  "license": "MIT",
@@ -4,9 +4,19 @@ import type { AbstractWebSocket } from "./AbstractWebSocket";
4
4
  import { Persistance } from "./Persistance";
5
5
  import { PubSub } from "./PubSub";
6
6
 
7
- export type InferWebSocketType<TPlatform extends AbstractPlatform<any>> =
7
+ export type InferPlatformWebSocketType<TPlatform extends AbstractPlatform> =
8
8
  TPlatform extends AbstractPlatform<infer IWebSocket> ? IWebSocket : never;
9
9
 
10
+ export type InferPlatformRoomContextType<TPlatform extends AbstractPlatform> =
11
+ TPlatform extends AbstractPlatform<any, infer IIOContext>
12
+ ? IIOContext
13
+ : never;
14
+
15
+ export type InferPlatformEventContextType<TPlatform extends AbstractPlatform> =
16
+ TPlatform extends AbstractPlatform<any, any, infer IRoomContext>
17
+ ? IRoomContext
18
+ : never;
19
+
10
20
  export type AbstractPlatformConfig =
11
21
  | { persistance?: undefined; pubSub?: undefined }
12
22
  | {
@@ -18,7 +28,14 @@ export interface ConvertWebSocketConfig {
18
28
  room: string;
19
29
  }
20
30
 
21
- export abstract class AbstractPlatform<TWebSocket = any> {
31
+ export abstract class AbstractPlatform<
32
+ TWebSocket = any,
33
+ TIOContext extends Record<string, any> = {},
34
+ TRoomContext extends Record<string, any> = {}
35
+ > {
36
+ readonly _ioContext: TIOContext | undefined;
37
+ readonly _roomContext: TRoomContext | undefined;
38
+
22
39
  public persistance: AbstractPersistance;
23
40
  public pubSub: AbstractPubSub;
24
41
 
package/src/IORoom.ts CHANGED
@@ -14,11 +14,15 @@ import type {
14
14
  IOLike,
15
15
  JsonObject,
16
16
  Maybe,
17
- MaybePromise,
18
- Spread,
19
17
  } from "@pluv/types";
20
18
  import colors from "kleur";
21
- import type { AbstractPlatform, InferWebSocketType } from "./AbstractPlatform";
19
+ import type {
20
+ AbstractPlatform,
21
+ InferPlatformEventContextType,
22
+ InferPlatformRoomContextType,
23
+ InferPlatformWebSocketType,
24
+ } from "./AbstractPlatform";
25
+ import { AbstractMessageEvent } from "./AbstractWebSocket";
22
26
  import { authorize } from "./authorize";
23
27
  import type {
24
28
  EventResolver,
@@ -28,7 +32,6 @@ import type {
28
32
  SendMessageOptions,
29
33
  WebSocketSession,
30
34
  } from "./types";
31
- import { AbstractMessageEvent } from "./AbstractWebSocket";
32
35
 
33
36
  const PING_TIMEOUT_MS = 30_000;
34
37
 
@@ -41,8 +44,13 @@ interface BroadcastParams<TIO extends IORoom<any, any, any, any, any>> {
41
44
  senderId?: string;
42
45
  }
43
46
 
44
- interface IORoomListeners {
45
- onDestroy: (encodedState: string) => void;
47
+ export type IORoomListenerEvent<TPlatform extends AbstractPlatform> = {
48
+ room: string;
49
+ encodedState: string;
50
+ } & InferPlatformRoomContextType<TPlatform>;
51
+
52
+ interface IORoomListeners<TPlatform extends AbstractPlatform> {
53
+ onDestroy: (event: IORoomListenerEvent<TPlatform>) => void;
46
54
  }
47
55
 
48
56
  export type IORoomConfig<
@@ -53,11 +61,12 @@ export type IORoomConfig<
53
61
  TOutputBroadcast extends EventRecord<string, any> = {},
54
62
  TOutputSelf extends EventRecord<string, any> = {},
55
63
  TOutputSync extends EventRecord<string, any> = {}
56
- > = Partial<IORoomListeners> & {
64
+ > = Partial<IORoomListeners<TPlatform>> & {
57
65
  authorize?: TAuthorize;
58
- context: TContext;
66
+ context: TContext & InferPlatformRoomContextType<TPlatform>;
59
67
  debug: boolean;
60
68
  events: InferEventConfig<
69
+ TPlatform,
61
70
  TContext,
62
71
  TInput,
63
72
  TOutputBroadcast,
@@ -72,14 +81,15 @@ interface SendMessageSender {
72
81
  user: JsonObject | null;
73
82
  }
74
83
 
75
- export interface WebsocketRegisterOptions {
84
+ export type WebsocketRegisterOptions<TPlatform extends AbstractPlatform> = {
76
85
  token?: string | null;
77
- }
86
+ } & InferPlatformRoomContextType<TPlatform> &
87
+ InferPlatformEventContextType<TPlatform>;
78
88
 
79
89
  export class IORoom<
80
90
  TPlatform extends AbstractPlatform<any> = AbstractPlatform<any>,
81
91
  TAuthorize extends IOAuthorize<any, any> = BaseIOAuthorize,
82
- TContext extends JsonObject = {},
92
+ TContext extends Record<string, any> = {},
83
93
  TInput extends EventRecord<string, any> = {},
84
94
  TOutputBroadcast extends EventRecord<string, any> = {},
85
95
  TOutputSelf extends EventRecord<string, any> = {},
@@ -87,17 +97,19 @@ export class IORoom<
87
97
  > implements
88
98
  IOLike<TAuthorize, TInput, TOutputBroadcast, TOutputSelf, TOutputSync>
89
99
  {
90
- private readonly _context: TContext;
100
+ private readonly _context: TContext &
101
+ InferPlatformRoomContextType<TPlatform>;
91
102
  private readonly _debug: boolean;
92
103
  private readonly _platform: TPlatform;
93
104
 
94
105
  private _doc: YjsDoc<any> = doc();
95
- private _listeners: IORoomListeners;
106
+ private _listeners: IORoomListeners<TPlatform>;
96
107
  private _sessions = new Map<string, WebSocketSession>();
97
108
  private _uninitialize: (() => Promise<void>) | null = null;
98
109
 
99
110
  readonly _authorize: TAuthorize | null = null;
100
111
  readonly _events: InferEventConfig<
112
+ TPlatform,
101
113
  TContext,
102
114
  TInput,
103
115
  TOutputBroadcast,
@@ -130,9 +142,7 @@ export class IORoom<
130
142
  this.id = id;
131
143
 
132
144
  this._listeners = {
133
- onDestroy: (encodedState) => {
134
- onDestroy?.(encodedState);
135
- },
145
+ onDestroy: (event) => onDestroy?.(event),
136
146
  };
137
147
 
138
148
  if (authorize) this._authorize = authorize;
@@ -166,12 +176,16 @@ export class IORoom<
166
176
  }
167
177
 
168
178
  public async register(
169
- webSocket: InferWebSocketType<TPlatform>,
170
- options?: WebsocketRegisterOptions
179
+ webSocket: InferPlatformWebSocketType<TPlatform>,
180
+ options: WebsocketRegisterOptions<TPlatform>
171
181
  ): Promise<void> {
182
+ const { token, ..._platformEventContext } = options;
183
+ const platformEventContext =
184
+ _platformEventContext as InferPlatformRoomContextType<TPlatform> &
185
+ InferPlatformEventContextType<TPlatform>;
186
+
172
187
  if (!this._uninitialize) await this._initialize();
173
188
 
174
- const token = options?.token;
175
189
  const sessionId = this._platform.randomUUID();
176
190
  const pluvWs = this._platform.convertWebSocket(webSocket, {
177
191
  room: this.id,
@@ -230,7 +244,9 @@ export class IORoom<
230
244
  );
231
245
 
232
246
  const onClose = this._onClose(session, uninitializeWs).bind(this);
233
- const onMessage = this._onMessage(session).bind(this);
247
+ const onMessage = this._onMessage(session, platformEventContext).bind(
248
+ this
249
+ );
234
250
 
235
251
  pluvWs.addEventListener("close", onClose);
236
252
  pluvWs.addEventListener("error", onClose);
@@ -340,6 +356,7 @@ export class IORoom<
340
356
  message: EventMessage<string, any>
341
357
  ):
342
358
  | InferEventConfig<
359
+ TPlatform,
343
360
  TContext,
344
361
  TInput,
345
362
  TOutputBroadcast,
@@ -373,6 +390,7 @@ export class IORoom<
373
390
  private _getEventResolverObject(
374
391
  message: EventMessage<string, any>
375
392
  ): EventResolverObject<
393
+ TPlatform,
376
394
  TContext,
377
395
  TInput[string],
378
396
  TOutputBroadcast,
@@ -384,8 +402,15 @@ export class IORoom<
384
402
  if (!eventConfig) return {};
385
403
 
386
404
  const resolver:
387
- | EventResolver<TContext, TInput[string], TOutputBroadcast>
405
+ | EventResolver<
406
+ TContext &
407
+ InferPlatformRoomContextType<TPlatform> &
408
+ InferPlatformEventContextType<TPlatform>,
409
+ TInput[string],
410
+ TOutputBroadcast
411
+ >
388
412
  | EventResolverObject<
413
+ TPlatform,
389
414
  TContext,
390
415
  TInput[string],
391
416
  TOutputBroadcast,
@@ -427,7 +452,11 @@ export class IORoom<
427
452
  this._doc.destroy();
428
453
  this._doc = doc();
429
454
 
430
- this._listeners.onDestroy(encodedState);
455
+ this._listeners.onDestroy({
456
+ ...this._context,
457
+ encodedState,
458
+ room: this.id,
459
+ });
431
460
 
432
461
  this._uninitialize = null;
433
462
  };
@@ -485,10 +514,11 @@ export class IORoom<
485
514
  }
486
515
 
487
516
  private _onMessage(
488
- session: WebSocketSession
517
+ session: WebSocketSession,
518
+ platformEventContext: InferPlatformEventContextType<TPlatform>
489
519
  ): (event: AbstractMessageEvent) => void {
490
520
  return (event: AbstractMessageEvent): void => {
491
- const context: EventResolverContext<TContext> = {
521
+ const baseContext: EventResolverContext<TContext> = {
492
522
  context: this._context,
493
523
  doc: this._doc,
494
524
  room: this.id,
@@ -524,10 +554,19 @@ export class IORoom<
524
554
  return;
525
555
  }
526
556
 
557
+ const extendedContext: EventResolverContext<
558
+ TContext &
559
+ InferPlatformRoomContextType<TPlatform> &
560
+ InferPlatformEventContextType<TPlatform>
561
+ > = {
562
+ ...baseContext,
563
+ context: { ...this._context, ...platformEventContext },
564
+ };
565
+
527
566
  Promise.all([
528
- resolver.broadcast?.(inputs, context),
529
- resolver.self?.(inputs, context),
530
- resolver.sync?.(inputs, context),
567
+ resolver.broadcast?.(inputs, extendedContext),
568
+ resolver.self?.(inputs, extendedContext),
569
+ resolver.sync?.(inputs, baseContext),
531
570
  ]).then(([broadcast, self, sync]) => {
532
571
  if (broadcast) {
533
572
  Object.entries(broadcast).forEach(([type, data]: any) => {