@pluv/io 0.23.0 → 0.24.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
@@ -40,7 +40,7 @@ interface BroadcastParams<TIO extends IORoom<any, any, any, any>> {
40
40
  senderId?: string;
41
41
  }
42
42
 
43
- interface IORoomListeners<
43
+ export interface IORoomListeners<
44
44
  TPlatform extends AbstractPlatform<any>,
45
45
  TAuthorize extends IOAuthorize<any, any, InferRoomContextType<TPlatform>>,
46
46
  TContext extends JsonObject,
@@ -90,8 +90,8 @@ export class IORoom<
90
90
  public readonly id: string;
91
91
  public readonly _authorize: TAuthorize | null = null;
92
92
 
93
- private _doc: AbstractCrdtDoc<any>;
94
- private _uninitialize: (() => Promise<void>) | null = null;
93
+ private _doc: Promise<AbstractCrdtDoc<any>>;
94
+ private _uninitialize: Promise<() => Promise<void>> | null = null;
95
95
 
96
96
  private readonly _context: TContext & InferRoomContextType<TPlatform>;
97
97
  private readonly _debug: boolean;
@@ -122,18 +122,21 @@ export class IORoom<
122
122
  }) as BroadcastProxy<this>;
123
123
  }
124
124
 
125
+ private get _initialized(): Promise<boolean> {
126
+ return Promise.resolve(!!this._uninitialize?.then((result) => !!result));
127
+ }
128
+
125
129
  constructor(id: string, config: IORoomConfig<TPlatform, TAuthorize, TContext, TEvents>) {
126
130
  const { authorize, context, crdt = noop, debug, onDestroy, onMessage, platform, router } = config;
127
131
 
132
+ this.id = id;
133
+
128
134
  this._context = context;
129
135
  this._debug = debug;
130
136
  this._docFactory = crdt.doc(() => ({}));
131
- this._doc = this._docFactory.getEmpty();
132
137
  this._router = router;
133
138
  this._platform = platform.initialize({ context });
134
139
 
135
- this.id = id;
136
-
137
140
  this._listeners = {
138
141
  onDestroy: (event) => onDestroy?.(event),
139
142
  onMessage: (event) => onMessage?.(event),
@@ -143,8 +146,6 @@ export class IORoom<
143
146
 
144
147
  const webSockets = this._platform.getWebSockets() as readonly InferPlatformWebSocketSource<TPlatform>[];
145
148
 
146
- if (!webSockets.length) return;
147
-
148
149
  webSockets.forEach((webSocket) => {
149
150
  const deserialized = this._platform.getSerializedState(webSocket);
150
151
  const sessionId = this._platform.getSessionId(webSocket);
@@ -152,8 +153,15 @@ export class IORoom<
152
153
  if (!deserialized) return;
153
154
  if (typeof sessionId !== "string") return;
154
155
 
155
- this._sessions.set(sessionId, this._platform.convertWebSocket(webSocket, { room: this.id }));
156
+ const pluvWs = this._platform.convertWebSocket(webSocket, { room: this.id });
157
+
158
+ this._sessions.set(sessionId, pluvWs);
156
159
  });
160
+
161
+ const { doc, uninitialize } = this._initialize();
162
+
163
+ this._doc = doc;
164
+ this._uninitialize = uninitialize;
157
165
  }
158
166
 
159
167
  public getSize(): number {
@@ -174,32 +182,32 @@ export class IORoom<
174
182
  }, 0);
175
183
  }
176
184
 
177
- public onClose(webSocket: WebSocketType<TPlatform>): (event: AbstractCloseEvent) => void {
185
+ public onClose(webSocket: WebSocketType<TPlatform>): (event: AbstractCloseEvent) => Promise<void> {
178
186
  this._ensureDetached();
179
187
 
180
188
  const wsSession = this._getAbstractWs(webSocket);
181
189
 
182
- if (!wsSession) return (): void => undefined;
190
+ if (!wsSession) return async () => undefined;
183
191
 
184
192
  return this._onClose(wsSession);
185
193
  }
186
194
 
187
- public onError(webSocket: WebSocketType<TPlatform>): (event: AbstractErrorEvent) => void {
195
+ public onError(webSocket: WebSocketType<TPlatform>): (event: AbstractErrorEvent) => Promise<void> {
188
196
  this._ensureDetached();
189
197
 
190
198
  const wsSession = this._getAbstractWs(webSocket);
191
199
 
192
- if (!wsSession) return (): void => undefined;
200
+ if (!wsSession) return async () => undefined;
193
201
 
194
202
  return this._onClose(wsSession);
195
203
  }
196
204
 
197
- public onMessage(webSocket: WebSocketType<TPlatform>): (event: AbstractMessageEvent) => void {
205
+ public onMessage(webSocket: WebSocketType<TPlatform>): (event: AbstractMessageEvent) => Promise<void> {
198
206
  this._ensureDetached();
199
207
 
200
208
  const wsSession = this._getAbstractWs(webSocket);
201
209
 
202
- if (!wsSession) return (): void => undefined;
210
+ if (!wsSession) return async () => undefined;
203
211
 
204
212
  return this._onMessage(wsSession);
205
213
  }
@@ -210,7 +218,15 @@ export class IORoom<
210
218
  ): Promise<void> {
211
219
  const { token } = options;
212
220
 
213
- if (!this._uninitialize) await this._initialize();
221
+ const sessionId = this._platform.getSessionId(webSocket);
222
+ const sessionExists = typeof sessionId === "string" && this._sessions.has(sessionId);
223
+
224
+ if (sessionExists) return;
225
+ if (!(await this._initialized)) {
226
+ this._initialize();
227
+
228
+ await this._initialized;
229
+ }
214
230
 
215
231
  const user = await this._getAuthorizedUser(token);
216
232
  const ioAuthorize = this._getIOAuthorize();
@@ -221,7 +237,7 @@ export class IORoom<
221
237
  !!user &&
222
238
  (await this._getSessions().then((sessions) => sessions.some((session) => session.user?.id === user.id)));
223
239
 
224
- const pluvWs = await this._platform.convertWebSocket(webSocket, { room: this.id });
240
+ const pluvWs = this._platform.convertWebSocket(webSocket, { room: this.id });
225
241
 
226
242
  this._logDebug(`${colors.blue(`Registering connection for room ${this.id}:`)} ${pluvWs.sessionId}`);
227
243
 
@@ -326,14 +342,6 @@ export class IORoom<
326
342
  return sessions.find((pluvWs) => pluvWs.webSocket === webSocket) ?? null;
327
343
  }
328
344
 
329
- private async _getSession(webSocket: WebSocketType<TPlatform>): Promise<WebSocketSession<TAuthorize>> {
330
- const pluvWs = this._getAbstractWs(webSocket);
331
-
332
- if (!pluvWs) throw new Error("Session could not be found");
333
-
334
- return await pluvWs.getSession<TAuthorize>();
335
- }
336
-
337
345
  private async _getAuthorizedUser(token: Maybe<string>): Promise<InferIOAuthorizeUser<InferIOAuthorize<this>>> {
338
346
  const ioAuthorize = this._getIOAuthorize();
339
347
 
@@ -369,6 +377,15 @@ export class IORoom<
369
377
  }
370
378
  }
371
379
 
380
+ private async _getInitialDoc(): Promise<AbstractCrdtDoc<any>> {
381
+ const doc = this._docFactory.getEmpty();
382
+ const encodedState = await this._platform.persistance.getStorageState(this.id);
383
+
384
+ if (typeof encodedState === "string") doc.applyEncodedState({ update: encodedState });
385
+
386
+ return doc;
387
+ }
388
+
372
389
  private _getIOAuthorize() {
373
390
  if (typeof this._authorize === "function") {
374
391
  return this._authorize(this._context);
@@ -395,77 +412,97 @@ export class IORoom<
395
412
  return procedure.config.input ? procedure.config.input.parse(message.data) : message.data;
396
413
  }
397
414
 
415
+ private async _getSession(webSocket: WebSocketType<TPlatform>): Promise<WebSocketSession<TAuthorize>> {
416
+ const pluvWs = this._getAbstractWs(webSocket);
417
+
418
+ if (!pluvWs) throw new Error("Session could not be found");
419
+
420
+ return await pluvWs.getSession<TAuthorize>();
421
+ }
422
+
398
423
  private async _getSessions() {
399
424
  const promises = Array.from(this._sessions.values()).map(async (pluvWs) => await pluvWs.getSession());
400
425
 
401
426
  return await Promise.all(promises);
402
427
  }
403
428
 
404
- private async _initialize(): Promise<void> {
405
- this._logDebug(`${colors.blue(`Initializing room ${this.id}:`)}`);
406
-
407
- if (!!this._uninitialize) {
408
- await this._uninitialize();
409
-
410
- this._uninitialize = null;
411
- }
429
+ private _initialize() {
430
+ const promise = (async () => {
431
+ this._logDebug(`${colors.blue(`Initializing room ${this.id}:`)}`);
412
432
 
413
- const pubSubId = await this._platform.pubSub.subscribe(
414
- this.id,
415
- async ({ options = {}, ...message }): Promise<void> => {
416
- const sender: SendMessageSender = {
417
- sessionId: message.connectionId,
418
- user: message.user,
419
- };
433
+ if (!!this._uninitialize) {
434
+ const uninitialize = (await this._uninitialize).bind(this);
435
+ await uninitialize();
420
436
 
421
- switch (options.type) {
422
- case "self": {
423
- await this._sendSelfMessage(message, sender);
437
+ this._uninitialize = null;
438
+ }
424
439
 
425
- return;
440
+ const pubSubId = await this._platform.pubSub.subscribe(
441
+ this.id,
442
+ async ({ options = {}, ...message }): Promise<void> => {
443
+ const sender: SendMessageSender = {
444
+ sessionId: message.connectionId,
445
+ user: message.user,
446
+ };
447
+
448
+ switch (options.type) {
449
+ case "self": {
450
+ await this._sendSelfMessage(message, sender);
451
+
452
+ return;
453
+ }
454
+ case "sync": {
455
+ await this._sendSyncMessage(message, sender);
456
+
457
+ return;
458
+ }
459
+ case "broadcast":
460
+ default: {
461
+ const sessionIds = options.sessionIds;
462
+
463
+ await this._sendBroadcastMessage(message, sender, sessionIds);
464
+ }
426
465
  }
427
- case "sync": {
428
- await this._sendSyncMessage(message, sender);
466
+ },
467
+ );
429
468
 
430
- return;
431
- }
432
- case "broadcast":
433
- default: {
434
- const sessionIds = options.sessionIds;
469
+ const doc = await this._getInitialDoc();
470
+ const uninitialize = async () => {
471
+ this._platform.pubSub.unsubscribe(pubSubId);
435
472
 
436
- await this._sendBroadcastMessage(message, sender, sessionIds);
437
- }
438
- }
439
- },
440
- );
473
+ const doc = await this._doc;
474
+ const encodedState = doc.getEncodedState();
441
475
 
442
- this._uninitialize = async () => {
443
- this._platform.pubSub.unsubscribe(pubSubId);
476
+ doc.destroy();
477
+ this._doc = Promise.resolve(this._docFactory.getEmpty());
444
478
 
445
- const encodedState = this._doc.getEncodedState();
479
+ this._listeners.onDestroy({
480
+ context: this._context,
481
+ encodedState,
482
+ room: this.id,
483
+ });
446
484
 
447
- this._doc.destroy();
448
- this._doc = this._docFactory.getEmpty();
485
+ this._uninitialize = null;
486
+ };
449
487
 
450
- this._listeners.onDestroy({
451
- context: this._context,
452
- encodedState,
453
- room: this.id,
454
- });
488
+ return { doc, uninitialize };
489
+ })();
455
490
 
456
- this._uninitialize = null;
457
- };
491
+ this._doc = promise.then((result) => result.doc);
492
+ this._uninitialize = promise.then((result) => result.uninitialize);
493
+
494
+ return { doc: this._doc, uninitialize: this._uninitialize };
458
495
  }
459
496
 
460
497
  private _logDebug(...data: any[]): void {
461
498
  this._debug && console.log(...data);
462
499
  }
463
500
 
464
- private _onClose(webSocket: AbstractWebSocket): () => void {
465
- return (): void => {
466
- if (!this._uninitialize) return;
501
+ private _onClose(webSocket: AbstractWebSocket): () => Promise<void> {
502
+ return async (): Promise<void> => {
503
+ if (!(await this._initialized)) return;
467
504
 
468
- webSocket.state.quit = true;
505
+ webSocket.state = { ...webSocket.state, quit: true };
469
506
 
470
507
  this._logDebug(`${colors.blue(`Unregistering connection for room ${this.id}:`)} ${webSocket.sessionId}`);
471
508
  this._sessions.delete(webSocket.sessionId);
@@ -486,13 +523,18 @@ export class IORoom<
486
523
 
487
524
  if (size) return;
488
525
 
489
- this._uninitialize?.();
526
+ if (this._uninitialize) {
527
+ const uninitialize = (await this._uninitialize).bind(this);
528
+ await uninitialize();
529
+ }
490
530
  });
491
531
  };
492
532
  }
493
533
 
494
- private _onMessage(webSocket: AbstractWebSocket): (event: AbstractMessageEvent) => void {
534
+ private _onMessage(webSocket: AbstractWebSocket): (event: AbstractMessageEvent) => Promise<void> {
495
535
  return async (event: AbstractMessageEvent): Promise<void> => {
536
+ if (!(await this._initialized)) return;
537
+
496
538
  const pluvWs = this._getAbstractWs(webSocket as WebSocketType<TPlatform>);
497
539
 
498
540
  if (!pluvWs) throw new Error("Could not get session");
@@ -502,16 +544,15 @@ export class IORoom<
502
544
  this._getSessions(),
503
545
  ]);
504
546
 
547
+ const doc = await this._doc;
505
548
  const baseContext: EventResolverContext<TPlatform, TAuthorize, TContext> = {
506
549
  context: this._context,
507
- doc: this._doc,
550
+ doc,
508
551
  room: this.id,
509
552
  session,
510
553
  sessions,
511
554
  };
512
555
 
513
- if (!this._uninitialize) return;
514
-
515
556
  if (pluvWs.state.quit) {
516
557
  pluvWs.close(1011, "WebSocket broken.");
517
558
 
@@ -547,7 +588,7 @@ export class IORoom<
547
588
  TContext & InferRoomContextType<TPlatform>
548
589
  > = { ...baseContext, context: { ...this._context } };
549
590
 
550
- Promise.all([
591
+ await Promise.all([
551
592
  procedure.config.broadcast?.(inputs, extendedContext),
552
593
  procedure.config.self?.(inputs, extendedContext),
553
594
  procedure.config.sync?.(inputs, baseContext),
@@ -555,25 +596,33 @@ export class IORoom<
555
596
  const sessionId = session.id;
556
597
  const user = session.user;
557
598
 
558
- if (broadcast) {
559
- Object.entries(broadcast).forEach(([type, data]: any) => {
560
- this._broadcast({
561
- message: { data, type },
562
- senderId: sessionId,
563
- });
564
- });
565
- }
599
+ const handleBroadcast = async () => {
600
+ if (!broadcast) return;
601
+
602
+ await Promise.all(
603
+ Object.entries(broadcast).map(async ([type, data]: any) => {
604
+ await this._broadcast({
605
+ message: { data, type },
606
+ senderId: sessionId,
607
+ });
608
+ }),
609
+ );
610
+ };
611
+
612
+ const handleSelf = async () => {
613
+ if (!self) return;
566
614
 
567
- if (self) {
568
615
  await Promise.all(
569
616
  Object.entries(self).map(async ([type, data]) => {
570
617
  await this._sendSelfMessage({ data, type }, { sessionId, user });
571
618
  }),
572
619
  );
573
- }
620
+ };
574
621
 
575
- if (sync) {
576
- this._platform.pubSub.publish(this.id, {
622
+ const handleSync = async () => {
623
+ if (!sync) return;
624
+
625
+ await this._platform.pubSub.publish(this.id, {
577
626
  connectionId: session.id,
578
627
  options: { type: "sync" },
579
628
  room: this.id,
@@ -586,7 +635,9 @@ export class IORoom<
586
635
  await this._sendSelfMessage({ data, type }, { sessionId, user });
587
636
  }),
588
637
  );
589
- }
638
+ };
639
+
640
+ await Promise.all([handleBroadcast(), handleSelf(), handleSync()]);
590
641
  });
591
642
  };
592
643
  }
@@ -608,9 +659,13 @@ export class IORoom<
608
659
  private async _sendMessage(pluvWs: AbstractWebSocket<any>, message: IOEventMessage<any>): Promise<void> {
609
660
  const { data, type } = message;
610
661
 
662
+ if (!(await this._initialized)) return;
663
+
664
+ const doc = await this._doc;
665
+
611
666
  this._listeners.onMessage({
612
667
  context: this._context,
613
- encodedState: this._doc.getEncodedState(),
668
+ encodedState: doc.getEncodedState(),
614
669
  message: { data, type } as InferEventMessage<InferEventsOutput<TEvents>, keyof InferEventsOutput<TEvents>>,
615
670
  room: this.id,
616
671
  user: message.user,
@@ -675,9 +730,10 @@ export class IORoom<
675
730
  ): Promise<void> {
676
731
  if (!sender) return;
677
732
 
733
+ const doc = await this._doc;
678
734
  const context: EventResolverContext<TPlatform, TAuthorize, TContext> = {
679
735
  context: this._context,
680
- doc: this._doc,
736
+ doc,
681
737
  room: this.id,
682
738
  session: null,
683
739
  sessions: await this._getSessions(),
package/src/PluvServer.ts CHANGED
@@ -17,6 +17,7 @@ import type {
17
17
  InferRoomContextType,
18
18
  WebSocketRegistrationMode,
19
19
  } from "./AbstractPlatform";
20
+ import type { IORoomListeners } from "./IORoom";
20
21
  import { IORoom } from "./IORoom";
21
22
  import { PluvProcedure } from "./PluvProcedure";
22
23
  import type { PluvRouterEventConfig } from "./PluvRouter";
@@ -47,9 +48,23 @@ export type PluvServerConfig<
47
48
  router?: PluvRouter<TPlatform, TAuthorize, TContext, TEvents>;
48
49
  };
49
50
 
50
- export type GetRoomOptions<TPlatform extends AbstractPlatform> = keyof InferRoomContextType<TPlatform> extends never
51
- ? [{ debug?: boolean }] | []
52
- : [Id<{ debug?: boolean } & InferRoomContextType<TPlatform>>];
51
+ type BaseCreateRoomOptions<
52
+ TPlatform extends AbstractPlatform<any>,
53
+ TAuthorize extends IOAuthorize<any, any, InferPlatformContextType<TPlatform>>,
54
+ TContext extends JsonObject,
55
+ TEvents extends PluvRouterEventConfig<TPlatform, TAuthorize, TContext>,
56
+ > = Partial<IORoomListeners<TPlatform, TAuthorize, TContext, TEvents>> & {
57
+ debug?: boolean;
58
+ };
59
+
60
+ export type CreateRoomOptions<
61
+ TPlatform extends AbstractPlatform<any>,
62
+ TAuthorize extends IOAuthorize<any, any, InferPlatformContextType<TPlatform>>,
63
+ TContext extends JsonObject,
64
+ TEvents extends PluvRouterEventConfig<TPlatform, TAuthorize, TContext>,
65
+ > = keyof InferRoomContextType<TPlatform> extends never
66
+ ? [BaseCreateRoomOptions<TPlatform, TAuthorize, TContext, TEvents>] | []
67
+ : [Id<BaseCreateRoomOptions<TPlatform, TAuthorize, TContext, TEvents> & InferRoomContextType<TPlatform>>];
53
68
 
54
69
  export class PluvServer<
55
70
  TPlatform extends AbstractPlatform<any> = AbstractPlatform<any>,
@@ -117,12 +132,7 @@ export class PluvServer<
117
132
  const update = (data as any)?.update as Maybe<string>;
118
133
 
119
134
  const updates: readonly Maybe<string>[] = [
120
- oldState
121
- ? null
122
- : await this._getInitialStorage?.({
123
- ...context,
124
- room,
125
- }),
135
+ oldState ? null : await this._getInitialStorage?.({ ...context, room }),
126
136
  update,
127
137
  ];
128
138
 
@@ -169,9 +179,7 @@ export class PluvServer<
169
179
  const origin = (data as any)?.origin as Maybe<string>;
170
180
  const update: string | null = (data as any)?.update ?? null;
171
181
 
172
- if (origin === "$INITIALIZED" && Object.keys(doc.toJson()).length) {
173
- return {};
174
- }
182
+ if (origin === "$INITIALIZED" && Object.keys(doc.toJson()).length) return {};
175
183
 
176
184
  const updated = update === null ? doc : doc.applyEncodedState({ update });
177
185
  const encodedState = updated.getEncodedState();
@@ -192,7 +200,6 @@ export class PluvServer<
192
200
  private readonly _debug: boolean;
193
201
  private readonly _getInitialStorage: GetInitialStorageFn<TPlatform> | null = null;
194
202
  private readonly _platform: TPlatform;
195
- private readonly _rooms = new Map<string, IORoom<TPlatform, TAuthorize, TContext, TEvents>>();
196
203
  private readonly _router: PluvRouter<TPlatform, TAuthorize, TContext, TEvents>;
197
204
 
198
205
  public get _events() {
@@ -242,41 +249,16 @@ export class PluvServer<
242
249
  };
243
250
  }
244
251
 
245
- public async createToken(
246
- params: JWTEncodeParams<InferIOAuthorizeUser<InferIOAuthorize<this>>, TPlatform>,
247
- ): Promise<string> {
248
- if (!this._authorize) {
249
- throw new Error("IO does not specify authorize during initialization.");
250
- }
251
-
252
- const ioAuthorize =
253
- typeof this._authorize === "function" ? this._authorize(params) : (this._authorize as { secret: string });
254
-
255
- const secret = ioAuthorize.secret;
256
-
257
- return await authorize({
258
- platform: this._platform,
259
- secret,
260
- }).encode(params);
261
- }
262
-
263
- public getRoom(
252
+ public createRoom(
264
253
  room: string,
265
- ...options: GetRoomOptions<TPlatform>
254
+ ...options: CreateRoomOptions<TPlatform, TAuthorize, TContext, TEvents>
266
255
  ): IORoom<TPlatform, TAuthorize, TContext, TEvents> {
267
- const { debug, ...platformRoomContext } = options[0] ?? {};
268
-
269
- this._purgeEmptyRooms();
256
+ const { debug, onDestroy, onMessage, ...platformRoomContext } = options[0] ?? {};
270
257
 
271
258
  if (!/^[a-z0-9]+[a-z0-9\-_]+[a-z0-9]+$/i.test(room)) {
272
259
  throw new Error("Unsupported room name");
273
260
  }
274
261
 
275
- const platform = this._platform;
276
- const oldRoom = this._rooms.get(room);
277
-
278
- if (oldRoom) return oldRoom;
279
-
280
262
  const roomContext = {
281
263
  ...this._context,
282
264
  ...platformRoomContext,
@@ -289,48 +271,45 @@ export class PluvServer<
289
271
  debug: debug ?? this._debug,
290
272
  onDestroy: async (event) => {
291
273
  this._logDebug(`${colors.blue("Deleting empty room:")} ${room}`);
292
- this._rooms.delete(room);
293
274
 
275
+ await Promise.resolve(onDestroy?.(event));
294
276
  await Promise.resolve(this._listeners.onRoomDeleted(event));
295
277
  await this._platform.persistance.deleteStorageState(room);
296
278
 
297
- if (this._debug) {
298
- const rooms = Array.from(this._rooms.keys());
299
-
300
- this._logDebug(`${colors.blue("Deleted room:")} ${room}`);
301
- this._logDebug(`${colors.blue("Rooms available:")} ${rooms.join(", ")}`);
302
- }
279
+ this._logDebug(`${colors.blue("Deleted room:")} ${room}`);
303
280
  },
304
281
  onMessage: async (event) => {
282
+ await Promise.resolve(onMessage?.(event));
305
283
  await Promise.resolve(this._listeners.onRoomMessage(event));
306
284
  },
307
- platform,
285
+ platform: this._platform,
308
286
  router: this._router,
309
287
  });
310
288
 
311
- this._rooms.set(room, newRoom);
289
+ this._logDebug(`${colors.blue("Created room:")} ${room}`);
312
290
 
313
- if (this._debug) {
314
- const rooms = Array.from(this._rooms.keys());
291
+ return newRoom;
292
+ }
315
293
 
316
- this._logDebug(`${colors.blue("Created room:")} ${room}`);
317
- this._logDebug(`${colors.blue("Rooms available:")} ${rooms.join(", ")}`);
294
+ public async createToken(
295
+ params: JWTEncodeParams<InferIOAuthorizeUser<InferIOAuthorize<this>>, TPlatform>,
296
+ ): Promise<string> {
297
+ if (!this._authorize) {
298
+ throw new Error("IO does not specify authorize during initialization.");
318
299
  }
319
300
 
320
- return newRoom;
301
+ const ioAuthorize =
302
+ typeof this._authorize === "function" ? this._authorize(params) : (this._authorize as { secret: string });
303
+
304
+ const secret = ioAuthorize.secret;
305
+
306
+ return await authorize({
307
+ platform: this._platform,
308
+ secret,
309
+ }).encode(params);
321
310
  }
322
311
 
323
312
  private _logDebug(...data: any[]): void {
324
313
  this._debug && console.log(...data);
325
314
  }
326
-
327
- private _purgeEmptyRooms(): void {
328
- const rooms = Array.from(this._rooms.entries());
329
-
330
- rooms.forEach(([id, room]) => {
331
- if (!!room?.getSize()) return;
332
-
333
- this._rooms.delete(id);
334
- });
335
- }
336
315
  }
package/src/index.ts CHANGED
@@ -33,5 +33,5 @@ export type { PluvProcedureConfig } from "./PluvProcedure";
33
33
  export { PluvRouter } from "./PluvRouter";
34
34
  export type { MergedRouter, PluvRouterEventConfig } from "./PluvRouter";
35
35
  export { PluvServer } from "./PluvServer";
36
- export type { GetRoomOptions, InferIORoom, PluvServerConfig } from "./PluvServer";
36
+ export type { CreateRoomOptions, InferIORoom, PluvServerConfig } from "./PluvServer";
37
37
  export type { WebSocketSerializedState, WebSocketSession } from "./types";
package/src/types.ts CHANGED
@@ -3,12 +3,10 @@ import type {
3
3
  BaseIOAuthorize,
4
4
  EventRecord,
5
5
  IOAuthorize,
6
- IORouterLike,
7
6
  Id,
8
7
  InferEventMessage,
9
8
  InferEventsOutput,
10
9
  InferIOAuthorizeUser,
11
- InferIOOutput,
12
10
  JsonObject,
13
11
  Maybe,
14
12
  MaybePromise,
@@ -1,2 +1,2 @@
1
1
  // Generated by genversion.
2
- export const version = '0.23.0'
2
+ export const version = '0.24.0'