@pluv/io 0.17.3 → 0.18.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/src/IORoom.ts CHANGED
@@ -4,7 +4,6 @@ import type {
4
4
  BaseIOAuthorize,
5
5
  BaseIOEventRecord,
6
6
  EventMessage,
7
- EventRecord,
8
7
  IOAuthorize,
9
8
  IOLike,
10
9
  Id,
@@ -24,62 +23,44 @@ import type {
24
23
  InferPlatformWebSocketType,
25
24
  } from "./AbstractPlatform";
26
25
  import { AbstractMessageEvent } from "./AbstractWebSocket";
26
+ import type { PluvRouter, PluvRouterEventConfig } from "./PluvRouter";
27
27
  import { authorize } from "./authorize";
28
- import type {
29
- EventResolver,
30
- EventResolverContext,
31
- EventResolverObject,
32
- InferEventConfig,
33
- SendMessageOptions,
34
- WebSocketSession,
35
- } from "./types";
28
+ import type { EventResolverContext, IORoomListenerEvent, SendMessageOptions, WebSocketSession } from "./types";
36
29
 
37
30
  const PING_TIMEOUT_MS = 30_000;
38
31
 
39
- type BroadcastMessage<TIO extends IORoom<any, any, any, any, any>> =
32
+ type BroadcastMessage<TIO extends IORoom<any, any, any, any>> =
40
33
  | InferEventMessage<InferIOInput<TIO>>
41
34
  | InferEventMessage<BaseIOEventRecord<InferIOAuthorize<TIO>>>;
42
35
 
43
- interface BroadcastParams<TIO extends IORoom<any, any, any, any, any>> {
36
+ interface BroadcastParams<TIO extends IORoom<any, any, any, any>> {
44
37
  message: BroadcastMessage<TIO>;
45
38
  senderId?: string;
46
39
  }
47
40
 
48
- export type IORoomListenerEvent<TPlatform extends AbstractPlatform> = {
49
- room: string;
50
- encodedState: string;
51
- } & InferPlatformRoomContextType<TPlatform>;
52
-
53
41
  interface IORoomListeners<TPlatform extends AbstractPlatform> {
54
42
  onDestroy: (event: IORoomListenerEvent<TPlatform>) => void;
55
43
  }
56
44
 
45
+ export type BroadcastProxy<TIO extends IORoom<any, any, any, any>> = (<TEvent extends keyof InferIOInput<TIO>>(
46
+ event: TEvent,
47
+ data: Id<InferIOInput<TIO>[TEvent]>,
48
+ ) => Promise<void>) & {
49
+ [event in keyof InferIOInput<TIO>]: (data: Id<InferIOInput<TIO>>[event]) => Promise<void>;
50
+ };
51
+
57
52
  export type IORoomConfig<
58
53
  TPlatform extends AbstractPlatform<any> = AbstractPlatform<any>,
59
- TAuthorize extends IOAuthorize<
60
- any,
61
- any,
62
- InferPlatformRoomContextType<TPlatform>
63
- > = BaseIOAuthorize,
54
+ TAuthorize extends IOAuthorize<any, any, InferPlatformRoomContextType<TPlatform>> = BaseIOAuthorize,
64
55
  TContext extends JsonObject = {},
65
- TInput extends EventRecord<string, any> = {},
66
- TOutputBroadcast extends EventRecord<string, any> = {},
67
- TOutputSelf extends EventRecord<string, any> = {},
68
- TOutputSync extends EventRecord<string, any> = {},
56
+ TEvents extends PluvRouterEventConfig<TPlatform, TAuthorize, TContext> = {},
69
57
  > = Partial<IORoomListeners<TPlatform>> & {
70
58
  authorize?: TAuthorize;
71
59
  context: TContext & InferPlatformRoomContextType<TPlatform>;
72
60
  crdt?: { doc: (value: any) => AbstractCrdtDocFactory<any> };
73
61
  debug: boolean;
74
- events: InferEventConfig<
75
- TPlatform,
76
- TContext,
77
- TInput,
78
- TOutputBroadcast,
79
- TOutputSelf,
80
- TOutputSync
81
- >;
82
62
  platform: TPlatform;
63
+ router: PluvRouter<TPlatform, TAuthorize, TContext, TEvents>;
83
64
  };
84
65
 
85
66
  interface SendMessageSender {
@@ -94,69 +75,55 @@ export type WebsocketRegisterOptions<TPlatform extends AbstractPlatform> = {
94
75
 
95
76
  export class IORoom<
96
77
  TPlatform extends AbstractPlatform<any> = AbstractPlatform<any>,
97
- TAuthorize extends IOAuthorize<
98
- any,
99
- any,
100
- InferPlatformRoomContextType<TPlatform>
101
- > = BaseIOAuthorize,
78
+ TAuthorize extends IOAuthorize<any, any, InferPlatformRoomContextType<TPlatform>> = BaseIOAuthorize,
102
79
  TContext extends Record<string, any> = {},
103
- TInput extends EventRecord<string, any> = {},
104
- TOutputBroadcast extends EventRecord<string, any> = {},
105
- TOutputSelf extends EventRecord<string, any> = {},
106
- TOutputSync extends EventRecord<string, any> = {},
107
- > implements
108
- IOLike<TAuthorize, TInput, TOutputBroadcast, TOutputSelf, TOutputSync>
80
+ TEvents extends PluvRouterEventConfig<TPlatform, TAuthorize, TContext> = {},
81
+ > implements IOLike<TAuthorize, TEvents>
109
82
  {
110
- private readonly _context: TContext &
111
- InferPlatformRoomContextType<TPlatform>;
83
+ private readonly _context: TContext & InferPlatformRoomContextType<TPlatform>;
112
84
  private readonly _debug: boolean;
113
85
  private readonly _docFactory: AbstractCrdtDocFactory<any>;
114
86
  private readonly _platform: TPlatform;
115
87
 
116
88
  private _doc: AbstractCrdtDoc<any>;
117
89
  private _listeners: IORoomListeners<TPlatform>;
118
- private _sessions = new Map<string, WebSocketSession>();
90
+ private _sessions = new Map<string, WebSocketSession<TAuthorize>>();
119
91
  private _uninitialize: (() => Promise<void>) | null = null;
120
92
 
121
93
  readonly _authorize: TAuthorize | null = null;
122
- readonly _events: InferEventConfig<
123
- TPlatform,
124
- TContext,
125
- TInput,
126
- TOutputBroadcast,
127
- TOutputSelf,
128
- TOutputSync
129
- >;
94
+ readonly _router: PluvRouter<TPlatform, TAuthorize, TContext, TEvents>;
130
95
 
131
96
  readonly id: string;
132
97
 
133
- constructor(
134
- id: string,
135
- config: IORoomConfig<
136
- TPlatform,
137
- TAuthorize,
138
- TContext,
139
- TInput,
140
- TOutputBroadcast,
141
- TOutputSelf,
142
- TOutputSync
143
- >,
144
- ) {
145
- const {
146
- authorize,
147
- context,
148
- crdt = noop,
149
- debug,
150
- events,
151
- onDestroy,
152
- platform,
153
- } = config;
98
+ public get _events() {
99
+ return this._router._events;
100
+ }
101
+
102
+ public get broadcast(): BroadcastProxy<this> {
103
+ const _broadcast = <TEvent extends keyof InferIOInput<this>>(
104
+ event: TEvent,
105
+ data: Id<InferIOInput<this>[TEvent]>,
106
+ ): Promise<void> => {
107
+ const message = { type: event, data } as BroadcastMessage<this>;
108
+
109
+ return Promise.resolve(this._broadcast({ message }));
110
+ };
111
+
112
+ return new Proxy(_broadcast, {
113
+ get(fn, prop) {
114
+ return (data: any) => fn(prop as any, data);
115
+ },
116
+ }) as BroadcastProxy<this>;
117
+ }
118
+
119
+ constructor(id: string, config: IORoomConfig<TPlatform, TAuthorize, TContext, TEvents>) {
120
+ const { authorize, context, crdt = noop, debug, onDestroy, platform, router } = config;
154
121
 
155
122
  this._context = context;
156
123
  this._debug = debug;
157
124
  this._docFactory = crdt.doc(() => ({}));
158
125
  this._doc = this._docFactory.getEmpty();
159
- this._events = events;
126
+ this._router = router;
160
127
  this._platform = platform;
161
128
 
162
129
  this.id = id;
@@ -168,15 +135,6 @@ export class IORoom<
168
135
  if (authorize) this._authorize = authorize;
169
136
  }
170
137
 
171
- public broadcast<TEvent extends keyof InferIOInput<this>>(
172
- event: TEvent,
173
- data: Id<InferIOInput<this>[TEvent]>,
174
- ): Promise<void> {
175
- const message = { type: event, data } as BroadcastMessage<this>;
176
-
177
- return Promise.resolve(this._broadcast({ message }));
178
- }
179
-
180
138
  public getSize(): number {
181
139
  const currentTime = new Date().getTime();
182
140
 
@@ -189,9 +147,7 @@ export class IORoom<
189
147
  return Array.from(this._sessions.values()).reduce((count, session) => {
190
148
  if (session.quit) return count;
191
149
 
192
- return currentTime - session.timers.ping > PING_TIMEOUT_MS
193
- ? count
194
- : count + 1;
150
+ return currentTime - session.timers.ping > PING_TIMEOUT_MS ? count : count + 1;
195
151
  }, 0);
196
152
  }
197
153
 
@@ -200,9 +156,8 @@ export class IORoom<
200
156
  options: WebsocketRegisterOptions<TPlatform>,
201
157
  ): Promise<void> {
202
158
  const { token, ..._platformEventContext } = options;
203
- const platformEventContext =
204
- _platformEventContext as InferPlatformRoomContextType<TPlatform> &
205
- InferPlatformEventContextType<TPlatform>;
159
+ const platformEventContext = _platformEventContext as InferPlatformRoomContextType<TPlatform> &
160
+ InferPlatformEventContextType<TPlatform>;
206
161
 
207
162
  if (!this._uninitialize) await this._initialize();
208
163
 
@@ -215,11 +170,7 @@ export class IORoom<
215
170
  userId: user?.id ?? null,
216
171
  });
217
172
 
218
- this._logDebug(
219
- `${colors.blue(
220
- `Registering connection for room ${this.id}:`,
221
- )} ${sessionId}`,
222
- );
173
+ this._logDebug(`${colors.blue(`Registering connection for room ${this.id}:`)} ${sessionId}`);
223
174
 
224
175
  const uninitializeWs = await pluvWs.initialize();
225
176
  const ioAuthorize = this._getIOAuthorize(options);
@@ -227,17 +178,10 @@ export class IORoom<
227
178
  const isUnauthorized = !!ioAuthorize?.required && !user;
228
179
  // There is an attempt for multiple of the same identities. Probably malicious.
229
180
  const isTokenInUse =
230
- !!user &&
231
- Array.from(this._sessions.values()).some(
232
- (session) => session.user?.id === user.id,
233
- );
181
+ !!user && Array.from(this._sessions.values()).some((session) => session.user?.id === user.id);
234
182
 
235
183
  if (isUnauthorized || isTokenInUse) {
236
- this._logDebug(
237
- `${colors.blue(
238
- "Authorization failed for connection:",
239
- )} ${sessionId}`,
240
- );
184
+ this._logDebug(`${colors.blue("Authorization failed for connection:")} ${sessionId}`);
241
185
 
242
186
  pluvWs.handleError({ error: new Error("Not authorized") });
243
187
  pluvWs.close(3000, "WebSocket unauthorized.");
@@ -246,7 +190,7 @@ export class IORoom<
246
190
  }
247
191
 
248
192
  const currentTime = new Date().getTime();
249
- const session: WebSocketSession = {
193
+ const session: WebSocketSession<TAuthorize> = {
250
194
  id: sessionId,
251
195
  presence: null,
252
196
  quit: false,
@@ -260,16 +204,10 @@ export class IORoom<
260
204
 
261
205
  this._sessions.set(session.id, session);
262
206
 
263
- await this._platform.persistance.addUser(
264
- this.id,
265
- sessionId,
266
- user ?? {},
267
- );
207
+ await this._platform.persistance.addUser(this.id, sessionId, user ?? {});
268
208
 
269
209
  const onClose = this._onClose(session, uninitializeWs).bind(this);
270
- const onMessage = this._onMessage(session, platformEventContext).bind(
271
- this,
272
- );
210
+ const onMessage = this._onMessage(session, platformEventContext).bind(this);
273
211
 
274
212
  pluvWs.addEventListener("close", onClose);
275
213
  pluvWs.addEventListener("error", onClose);
@@ -277,11 +215,7 @@ export class IORoom<
277
215
 
278
216
  this._emitRegistered(session);
279
217
 
280
- this._logDebug(
281
- `${colors.blue(
282
- `Registered connection for room ${this.id}:`,
283
- )} ${sessionId}`,
284
- );
218
+ this._logDebug(`${colors.blue(`Registered connection for room ${this.id}:`)} ${sessionId}`);
285
219
 
286
220
  const size = this.getSize();
287
221
 
@@ -295,9 +229,7 @@ export class IORoom<
295
229
  const sender = senderId ? this._sessions.get(senderId) : null;
296
230
 
297
231
  const quitters = Array.from(this._sessions.values()).filter(
298
- (session) =>
299
- session.quit ||
300
- currentTime - session.timers.ping > PING_TIMEOUT_MS,
232
+ (session) => session.quit || currentTime - session.timers.ping > PING_TIMEOUT_MS,
301
233
  );
302
234
 
303
235
  quitters.forEach((session) => {
@@ -314,7 +246,7 @@ export class IORoom<
314
246
  });
315
247
  }
316
248
 
317
- private _emitQuitters(quitters: readonly WebSocketSession[]): void {
249
+ private _emitQuitters(quitters: readonly WebSocketSession<TAuthorize>[]): void {
318
250
  quitters.forEach((quitter) => {
319
251
  this._broadcast({
320
252
  message: {
@@ -326,7 +258,7 @@ export class IORoom<
326
258
  });
327
259
  }
328
260
 
329
- private _emitRegistered(session: WebSocketSession): void {
261
+ private _emitRegistered(session: WebSocketSession<TAuthorize>): void {
330
262
  this._sendSelfMessage(
331
263
  {
332
264
  type: "$REGISTERED",
@@ -351,11 +283,11 @@ export class IORoom<
351
283
  private async _getAuthorizedUser(
352
284
  token: Maybe<string>,
353
285
  context: InferPlatformRoomContextType<TPlatform>,
354
- ): Promise<InferIOAuthorizeUser<InferIOAuthorize<this>> | null> {
286
+ ): Promise<InferIOAuthorizeUser<InferIOAuthorize<this>>> {
355
287
  const ioAuthorize = this._getIOAuthorize(context);
356
288
 
357
- if (!ioAuthorize) return null;
358
- if (!token) return null;
289
+ if (!ioAuthorize) return null as InferIOAuthorizeUser<InferIOAuthorize<this>>;
290
+ if (!token) return null as InferIOAuthorizeUser<InferIOAuthorize<this>>;
359
291
 
360
292
  const payload = await authorize({
361
293
  platform: this._platform,
@@ -366,99 +298,38 @@ export class IORoom<
366
298
  this._logDebug(colors.blue("Could not decode token:"));
367
299
  this._logDebug(token);
368
300
 
369
- return null;
301
+ return null as InferIOAuthorizeUser<InferIOAuthorize<this>>;
370
302
  }
371
303
 
372
304
  if (payload.room !== this.id) {
373
- this._logDebug(
374
- colors.blue(`Token is not authorized for room ${this.id}:`),
375
- );
305
+ this._logDebug(colors.blue(`Token is not authorized for room ${this.id}:`));
376
306
  this._logDebug(colors.blue("Received:"), payload.room);
377
307
  this._logDebug(token);
378
308
 
379
- return null;
309
+ return null as InferIOAuthorizeUser<InferIOAuthorize<this>>;
380
310
  }
381
311
 
382
312
  try {
383
313
  return ioAuthorize.user.parse(payload.user) ?? null;
384
314
  } catch {
385
- this._logDebug(
386
- `${colors.blue("Token fails validation:")} ${token}`,
387
- );
315
+ this._logDebug(`${colors.blue("Token fails validation:")} ${token}`);
388
316
 
389
- return null;
317
+ return null as InferIOAuthorizeUser<InferIOAuthorize<this>>;
390
318
  }
391
319
  }
392
320
 
393
- private _getEventConfig(
321
+ private _getProcedure(
394
322
  message: EventMessage<string, any>,
395
- ):
396
- | InferEventConfig<
397
- TPlatform,
398
- TContext,
399
- TInput,
400
- TOutputBroadcast,
401
- TOutputSelf,
402
- TOutputSync
403
- >[keyof TInput]
404
- | null {
405
- return this._events[message.type as keyof TInput] ?? null;
323
+ ): (typeof this._router)["_events"][keyof (typeof this._router)["_events"]] | null {
324
+ return this._router._events[message.type as keyof (typeof this._router)["_events"]] ?? null;
406
325
  }
407
326
 
408
- private _getEventInputs(
409
- message: EventMessage<string, any>,
410
- ): TInput[string] {
411
- const eventConfig = this._getEventConfig(message);
412
-
413
- if (!eventConfig) return message.data;
327
+ private _getProcedureInputs(message: EventMessage<string, any>): InferIOInput<this>[keyof TEvents] {
328
+ const procedure = this._getProcedure(message);
414
329
 
415
- /**
416
- * !HACK
417
- * @description If the config doesn't specify validation, we
418
- * assume no input is to be expected, but pass through all values
419
- * regardless. Leave this up to the implementer of the event.
420
- * @author leedavidcs
421
- * @date September 25, 2022
422
- */
423
- return eventConfig.input
424
- ? (eventConfig.input.parse(message.data) as TInput[string])
425
- : message.data;
426
- }
330
+ if (!procedure) return message.data;
427
331
 
428
- private _getEventResolverObject(
429
- message: EventMessage<string, any>,
430
- ): EventResolverObject<
431
- TPlatform,
432
- TContext,
433
- TInput[string],
434
- TOutputBroadcast,
435
- TOutputSelf,
436
- TOutputSync
437
- > {
438
- const eventConfig = this._getEventConfig(message);
439
-
440
- if (!eventConfig) return {};
441
-
442
- const resolver:
443
- | EventResolver<
444
- TContext &
445
- InferPlatformRoomContextType<TPlatform> &
446
- InferPlatformEventContextType<TPlatform>,
447
- TInput[string],
448
- TOutputBroadcast
449
- >
450
- | EventResolverObject<
451
- TPlatform,
452
- TContext,
453
- TInput[string],
454
- TOutputBroadcast,
455
- TOutputSelf,
456
- TOutputSync
457
- > = eventConfig.resolver;
458
-
459
- return typeof resolver === "function"
460
- ? { broadcast: resolver }
461
- : { ...resolver };
332
+ return procedure.config.input ? procedure.config.input.parse(message.data) : message.data;
462
333
  }
463
334
 
464
335
  private async _initialize(): Promise<void> {
@@ -470,17 +341,14 @@ export class IORoom<
470
341
  this._uninitialize = null;
471
342
  }
472
343
 
473
- const pubSubId = await this._platform.pubSub.subscribe(
474
- this.id,
475
- ({ options = {}, ...message }) => {
476
- const session = {
477
- id: message.connectionId,
478
- user: message.user,
479
- };
344
+ const pubSubId = await this._platform.pubSub.subscribe(this.id, ({ options = {}, ...message }) => {
345
+ const session = {
346
+ id: message.connectionId,
347
+ user: message.user,
348
+ };
480
349
 
481
- this._sendMessage(message, session, options);
482
- },
483
- );
350
+ this._sendMessage(message, session, options);
351
+ });
484
352
 
485
353
  this._uninitialize = async () => {
486
354
  this._platform.pubSub.unsubscribe(pubSubId);
@@ -504,59 +372,44 @@ export class IORoom<
504
372
  this._debug && console.log(...data);
505
373
  }
506
374
 
507
- private _onClose(
508
- session: WebSocketSession,
509
- callback?: () => void,
510
- ): () => void {
375
+ private _onClose(session: WebSocketSession<TAuthorize>, callback?: () => void): () => void {
511
376
  return (): void => {
512
377
  if (!this._uninitialize) return;
513
378
 
514
379
  session.quit = true;
515
380
 
516
- this._logDebug(
517
- `${colors.blue(
518
- `(Unregistering connection for room ${this.id}:`,
519
- )} ${session.id}`,
520
- );
381
+ this._logDebug(`${colors.blue(`(Unregistering connection for room ${this.id}:`)} ${session.id}`);
521
382
  this._sessions.delete(session.id);
522
383
 
523
- this._platform.persistance
524
- .deleteUser(this.id, session.id)
525
- .finally(() => {
526
- this._broadcast({
527
- message: {
528
- type: "$EXIT",
529
- data: { sessionId: session.id },
530
- },
531
- senderId: session.id,
532
- });
384
+ this._platform.persistance.deleteUser(this.id, session.id).finally(() => {
385
+ this._broadcast({
386
+ message: {
387
+ type: "$EXIT",
388
+ data: { sessionId: session.id },
389
+ },
390
+ senderId: session.id,
391
+ });
533
392
 
534
- callback?.();
393
+ callback?.();
535
394
 
536
- const size = this.getSize();
395
+ const size = this.getSize();
537
396
 
538
- this._logDebug(
539
- `${colors.blue(
540
- `Unregistered connection for room ${this.id}:`,
541
- )} ${session.id}`,
542
- );
543
- this._logDebug(
544
- `${colors.blue(`Room ${this.id} size:`)} ${size}`,
545
- );
397
+ this._logDebug(`${colors.blue(`Unregistered connection for room ${this.id}:`)} ${session.id}`);
398
+ this._logDebug(`${colors.blue(`Room ${this.id} size:`)} ${size}`);
546
399
 
547
- if (size) return;
400
+ if (size) return;
548
401
 
549
- this._uninitialize?.();
550
- });
402
+ this._uninitialize?.();
403
+ });
551
404
  };
552
405
  }
553
406
 
554
407
  private _onMessage(
555
- session: WebSocketSession,
408
+ session: WebSocketSession<TAuthorize>,
556
409
  platformEventContext: InferPlatformEventContextType<TPlatform>,
557
410
  ): (event: AbstractMessageEvent) => void {
558
411
  return (event: AbstractMessageEvent): void => {
559
- const baseContext: EventResolverContext<TContext> = {
412
+ const baseContext: EventResolverContext<TPlatform, TAuthorize, TContext> = {
560
413
  context: this._context,
561
414
  doc: this._doc,
562
415
  room: this.id,
@@ -576,12 +429,14 @@ export class IORoom<
576
429
 
577
430
  if (!message) return;
578
431
 
579
- const resolver = this._getEventResolverObject(message);
432
+ const procedure = this._getProcedure(message);
433
+
434
+ if (!procedure) return;
580
435
 
581
- let inputs: TInput[string];
436
+ let inputs: InferIOInput<this>[keyof TEvents];
582
437
 
583
438
  try {
584
- inputs = this._getEventInputs(message);
439
+ inputs = this._getProcedureInputs(message);
585
440
  } catch (error) {
586
441
  session?.webSocket.handleError({
587
442
  error,
@@ -593,18 +448,18 @@ export class IORoom<
593
448
  }
594
449
 
595
450
  const extendedContext: EventResolverContext<
596
- TContext &
597
- InferPlatformRoomContextType<TPlatform> &
598
- InferPlatformEventContextType<TPlatform>
451
+ TPlatform,
452
+ TAuthorize,
453
+ TContext & InferPlatformRoomContextType<TPlatform> & InferPlatformEventContextType<TPlatform>
599
454
  > = {
600
455
  ...baseContext,
601
456
  context: { ...this._context, ...platformEventContext },
602
457
  };
603
458
 
604
459
  Promise.all([
605
- resolver.broadcast?.(inputs, extendedContext),
606
- resolver.self?.(inputs, extendedContext),
607
- resolver.sync?.(inputs, baseContext),
460
+ procedure.config.broadcast?.(inputs, extendedContext),
461
+ procedure.config.self?.(inputs, extendedContext),
462
+ procedure.config.sync?.(inputs, baseContext),
608
463
  ]).then(([broadcast, self, sync]) => {
609
464
  if (broadcast) {
610
465
  Object.entries(broadcast).forEach(([type, data]: any) => {
@@ -638,9 +493,7 @@ export class IORoom<
638
493
  };
639
494
  }
640
495
 
641
- private _parseMessage(message: {
642
- data: string | ArrayBuffer;
643
- }): EventMessage<string, any> | null {
496
+ private _parseMessage(message: { data: string | ArrayBuffer }): EventMessage<string, any> | null {
644
497
  try {
645
498
  const parsed = this._platform.parseData(message.data);
646
499
 
@@ -691,7 +544,7 @@ export class IORoom<
691
544
  const _session = this._sessions.get(id);
692
545
 
693
546
  return _session ? dict.set(id, _session) : dict;
694
- }, new Map<string, WebSocketSession>()) ?? this._sessions;
547
+ }, new Map<string, WebSocketSession<TAuthorize>>()) ?? this._sessions;
695
548
 
696
549
  Array.from(sessions.values()).forEach((_session) => {
697
550
  _session.webSocket.sendMessage({
@@ -703,10 +556,7 @@ export class IORoom<
703
556
  });
704
557
  }
705
558
 
706
- private _sendSelfMessage(
707
- message: EventMessage<string, any>,
708
- sender: SendMessageSender | null,
709
- ): void {
559
+ private _sendSelfMessage(message: EventMessage<string, any>, sender: SendMessageSender | null): void {
710
560
  const senderId = sender?.id;
711
561
 
712
562
  if (!senderId) return;
@@ -723,15 +573,12 @@ export class IORoom<
723
573
  });
724
574
  }
725
575
 
726
- private _sendSyncMessage(
727
- message: EventMessage<string, any>,
728
- sender: SendMessageSender | null,
729
- ): void {
576
+ private _sendSyncMessage(message: EventMessage<string, any>, sender: SendMessageSender | null): void {
730
577
  const senderId = sender?.id;
731
578
 
732
579
  if (!senderId) return;
733
580
 
734
- const context: EventResolverContext<TContext> = {
581
+ const context: EventResolverContext<TPlatform, TAuthorize, TContext> = {
735
582
  context: this._context,
736
583
  doc: this._doc,
737
584
  room: this.id,
@@ -739,14 +586,14 @@ export class IORoom<
739
586
  sessions: this._sessions,
740
587
  };
741
588
 
742
- const resolver = this._getEventResolverObject(message).sync;
589
+ const resolver = this._getProcedure(message)?.config.sync;
743
590
 
744
591
  if (!resolver) return;
745
592
 
746
- let inputs: TInput[string];
593
+ let inputs: InferIOInput<this>[keyof TEvents];
747
594
 
748
595
  try {
749
- inputs = this._getEventInputs(message);
596
+ inputs = this._getProcedureInputs(message);
750
597
  } catch {
751
598
  return;
752
599
  }
@@ -5,13 +5,8 @@ export class Persistance extends AbstractPersistance {
5
5
  private _storages = new Map<string, string>();
6
6
  private _users = new Map<string, Map<string, JsonObject | null>>();
7
7
 
8
- public addUser(
9
- room: string,
10
- connectionId: string,
11
- user: JsonObject | null,
12
- ): Promise<void> {
13
- const users =
14
- this._users.get(room) ?? new Map<string, JsonObject | null>();
8
+ public addUser(room: string, connectionId: string, user: JsonObject | null): Promise<void> {
9
+ const users = this._users.get(room) ?? new Map<string, JsonObject | null>();
15
10
 
16
11
  this._users.set(room, users);
17
12
  users.set(connectionId, user);
@@ -56,10 +51,7 @@ export class Persistance extends AbstractPersistance {
56
51
  return Promise.resolve(storage);
57
52
  }
58
53
 
59
- public getUser(
60
- room: string,
61
- connectionId: string,
62
- ): Promise<JsonObject | null> {
54
+ public getUser(room: string, connectionId: string): Promise<JsonObject | null> {
63
55
  const user = this._users.get(room)?.get(connectionId);
64
56
 
65
57
  return Promise.resolve(user ?? null);