@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/src/PluvIO.ts CHANGED
@@ -15,23 +15,24 @@ import type {
15
15
  Spread,
16
16
  } from "@pluv/types";
17
17
  import colors from "kleur";
18
- import type { AbstractPlatform } from "./AbstractPlatform";
19
- import { IORoom } from "./IORoom";
18
+ import type {
19
+ AbstractPlatform,
20
+ InferPlatformRoomContextType,
21
+ } from "./AbstractPlatform";
22
+ import { IORoom, IORoomListenerEvent } from "./IORoom";
20
23
  import type { JWTEncodeParams } from "./authorize";
21
24
  import { authorize } from "./authorize";
22
25
  import type { EventConfig, InferEventConfig } from "./types";
23
26
 
24
- export type InferIOContext<
25
- TIO extends PluvIO<any, any, any, any, any, any, any>
26
- > = TIO extends PluvIO<any, any, infer IContext, any, any, any, any>
27
- ? IContext
28
- : never;
27
+ type InferIOContext<TIO extends PluvIO<any, any, any, any, any, any, any>> =
28
+ TIO extends PluvIO<any, any, infer IContext, any, any, any, any>
29
+ ? IContext
30
+ : never;
29
31
 
30
- export type InferIOPlatform<
31
- TIO extends PluvIO<any, any, any, any, any, any, any>
32
- > = TIO extends PluvIO<infer IPlatform, any, any, any, any, any, any>
33
- ? IPlatform
34
- : never;
32
+ type InferIOPlatform<TIO extends PluvIO<any, any, any, any, any, any, any>> =
33
+ TIO extends PluvIO<infer IPlatform, any, any, any, any, any, any>
34
+ ? IPlatform
35
+ : never;
35
36
 
36
37
  export type InferIORoom<TIO extends PluvIO<any, any, any, any, any, any, any>> =
37
38
  TIO extends PluvIO<
@@ -54,13 +55,17 @@ export type InferIORoom<TIO extends PluvIO<any, any, any, any, any, any, any>> =
54
55
  >
55
56
  : never;
56
57
 
57
- export interface PluvIORegisterOptions {
58
- token?: string;
59
- }
58
+ type GetInitialStorageEvent<TPlatform extends AbstractPlatform> = {
59
+ room: string;
60
+ } & InferPlatformRoomContextType<TPlatform>;
61
+
62
+ export type GetInitialStorageFn<TPlatform extends AbstractPlatform> = (
63
+ event: GetInitialStorageEvent<TPlatform>
64
+ ) => MaybePromise<Maybe<string>>;
60
65
 
61
- export interface PluvIOListeners {
62
- onRoomDeleted: (room: string, encodedState: string) => void;
63
- onStorageUpdated: (room: string, encodedState: string) => void;
66
+ export interface PluvIOListeners<TPlatform extends AbstractPlatform> {
67
+ onRoomDeleted: (event: IORoomListenerEvent<TPlatform>) => void;
68
+ onStorageUpdated: (event: IORoomListenerEvent<TPlatform>) => void;
64
69
  }
65
70
 
66
71
  export type PluvIOConfig<
@@ -71,24 +76,25 @@ export type PluvIOConfig<
71
76
  TOutputBroadcast extends EventRecord<string, any> = {},
72
77
  TOutputSelf extends EventRecord<string, any> = {},
73
78
  TOutputSync extends EventRecord<string, any> = {}
74
- > = Partial<PluvIOListeners> & {
79
+ > = Partial<PluvIOListeners<TPlatform>> & {
75
80
  authorize?: TAuthorize;
76
81
  context?: TContext;
77
82
  debug?: boolean;
78
83
  events?: InferEventConfig<
84
+ TPlatform,
79
85
  TContext,
80
86
  TInput,
81
87
  TOutputBroadcast,
82
88
  TOutputSelf,
83
89
  TOutputSync
84
90
  >;
85
- initialStorage?: (room: string) => MaybePromise<Maybe<string>>;
91
+ getInitialStorage?: GetInitialStorageFn<TPlatform>;
86
92
  platform: TPlatform;
87
93
  };
88
94
 
89
- export interface GetRoomOptions {
95
+ export type GetRoomOptions<TPlatform extends AbstractPlatform> = {
90
96
  debug?: boolean;
91
- }
97
+ } & InferPlatformRoomContextType<TPlatform>;
92
98
 
93
99
  export class PluvIO<
94
100
  TPlatform extends AbstractPlatform<any> = AbstractPlatform<any>,
@@ -102,9 +108,7 @@ export class PluvIO<
102
108
  IOLike<TAuthorize, TInput, TOutputBroadcast, TOutputSelf, TOutputSync>
103
109
  {
104
110
  private _context: TContext = {} as TContext;
105
- private _initialStorage:
106
- | ((room: string) => MaybePromise<Maybe<string>>)
107
- | null = null;
111
+ private _getInitialStorage: GetInitialStorageFn<TPlatform> | null = null;
108
112
  private _rooms = new Map<
109
113
  string,
110
114
  IORoom<
@@ -121,6 +125,7 @@ export class PluvIO<
121
125
  readonly _authorize: TAuthorize | null = null;
122
126
  readonly _debug: boolean;
123
127
  readonly _events: InferEventConfig<
128
+ TPlatform,
124
129
  TContext,
125
130
  TInput,
126
131
  TOutputBroadcast,
@@ -170,26 +175,35 @@ export class PluvIO<
170
175
  },
171
176
  };
172
177
  },
173
- self: async ({ update }, { doc, room }) => {
178
+ self: async ({ update }, { context, doc, room }) => {
174
179
  const oldState =
175
180
  await this._platform.persistance.getStorageState(room);
176
181
 
177
182
  const updates: readonly Maybe<string>[] = [
178
- oldState ? null : await this._initialStorage?.(room),
183
+ oldState
184
+ ? null
185
+ : await this._getInitialStorage?.({
186
+ ...context,
187
+ room,
188
+ }),
179
189
  update,
180
190
  ];
181
191
 
182
192
  if (updates.some((_update) => !!_update)) {
183
- const state = updates
193
+ const encodedState = updates
184
194
  .reduce((_doc, _up) => _doc.applyUpdate(_up), doc)
185
195
  .encodeStateAsUpdate();
186
196
 
187
197
  await this._platform.persistance.setStorageState(
188
198
  room,
189
- state
199
+ encodedState
190
200
  );
191
201
 
192
- this._listeners.onStorageUpdated(room, state);
202
+ this._listeners.onStorageUpdated({
203
+ ...context,
204
+ encodedState,
205
+ room,
206
+ });
193
207
  }
194
208
 
195
209
  const state =
@@ -228,7 +242,7 @@ export class PluvIO<
228
242
  },
229
243
  },
230
244
  $UPDATE_STORAGE: {
231
- resolver: ({ origin, update }, { doc, room }) => {
245
+ resolver: ({ origin, update }, { context, doc, room }) => {
232
246
  if (
233
247
  origin === "$STORAGE_RECEIVED" &&
234
248
  Object.keys(doc.toJSON()).length
@@ -237,25 +251,30 @@ export class PluvIO<
237
251
  }
238
252
 
239
253
  const updated = doc.applyUpdate(update);
240
- const state = updated.encodeStateAsUpdate();
254
+ const encodedState = updated.encodeStateAsUpdate();
241
255
 
242
256
  this._platform.persistance
243
- .setStorageState(room, state)
257
+ .setStorageState(room, encodedState)
244
258
  .then(() => {
245
- this._listeners.onStorageUpdated(room, state);
259
+ this._listeners.onStorageUpdated({
260
+ ...context,
261
+ encodedState,
262
+ room,
263
+ });
246
264
  });
247
265
 
248
- return { $STORAGE_UPDATED: { state } };
266
+ return { $STORAGE_UPDATED: { state: encodedState } };
249
267
  },
250
268
  },
251
269
  } as InferEventConfig<
270
+ TPlatform,
252
271
  TContext,
253
272
  TInput,
254
273
  TOutputBroadcast,
255
274
  TOutputSelf,
256
275
  TOutputSync
257
276
  >;
258
- readonly _listeners: PluvIOListeners;
277
+ readonly _listeners: PluvIOListeners<TPlatform>;
259
278
  readonly _platform: TPlatform;
260
279
 
261
280
  constructor(
@@ -274,7 +293,7 @@ export class PluvIO<
274
293
  context,
275
294
  debug = false,
276
295
  events,
277
- initialStorage,
296
+ getInitialStorage,
278
297
  onRoomDeleted,
279
298
  onStorageUpdated,
280
299
  platform,
@@ -286,15 +305,11 @@ export class PluvIO<
286
305
  if (authorize) this._authorize = authorize;
287
306
  if (context) this._context = context;
288
307
  if (events) this._events = events;
289
- if (initialStorage) this._initialStorage = initialStorage;
308
+ if (getInitialStorage) this._getInitialStorage = getInitialStorage;
290
309
 
291
310
  this._listeners = {
292
- onRoomDeleted: (room, encodedState) => {
293
- return onRoomDeleted?.(room, encodedState);
294
- },
295
- onStorageUpdated: (room, encodedState) => {
296
- return onStorageUpdated?.(room, encodedState);
297
- },
311
+ onRoomDeleted: (event) => onRoomDeleted?.(event),
312
+ onStorageUpdated: (event) => onStorageUpdated?.(event),
298
313
  };
299
314
  }
300
315
 
@@ -322,6 +337,7 @@ export class PluvIO<
322
337
  >(
323
338
  event: TEvent,
324
339
  config: EventConfig<
340
+ TPlatform,
325
341
  TContext,
326
342
  TData,
327
343
  TResultBroadcast,
@@ -344,6 +360,7 @@ export class PluvIO<
344
360
  const newEvent = {
345
361
  [event]: config,
346
362
  } as InferEventConfig<
363
+ TPlatform,
347
364
  TContext,
348
365
  EventRecord<TEvent, TData>,
349
366
  TResultBroadcast extends EventRecord<string, any>
@@ -377,7 +394,7 @@ export class PluvIO<
377
394
 
378
395
  public getRoom(
379
396
  room: string,
380
- options: GetRoomOptions = {}
397
+ options: GetRoomOptions<TPlatform>
381
398
  ): IORoom<
382
399
  TPlatform,
383
400
  TAuthorize,
@@ -387,7 +404,7 @@ export class PluvIO<
387
404
  TOutputSelf,
388
405
  TOutputSync
389
406
  > {
390
- const { debug } = options;
407
+ const { debug, ...platformRoomContext } = options;
391
408
 
392
409
  this._purgeEmptyRooms();
393
410
 
@@ -400,6 +417,11 @@ export class PluvIO<
400
417
 
401
418
  if (oldRoom) return oldRoom;
402
419
 
420
+ const roomContext = {
421
+ ...this._context,
422
+ ...platformRoomContext,
423
+ } as TContext & InferPlatformRoomContextType<TPlatform>;
424
+
403
425
  const newRoom = new IORoom<
404
426
  TPlatform,
405
427
  TAuthorize,
@@ -410,16 +432,23 @@ export class PluvIO<
410
432
  TOutputSync
411
433
  >(room, {
412
434
  authorize: this._authorize ?? undefined,
413
- context: this._context,
435
+ context: roomContext,
414
436
  debug: debug ?? this._debug,
415
437
  events: this._events,
416
- onDestroy: (encodedState) => {
438
+ onDestroy: ({ encodedState, room }) => {
417
439
  this._logDebug(
418
440
  `${colors.blue("Deleting empty room:")} ${room}`
419
441
  );
420
442
 
443
+ const roomContext = {
444
+ room,
445
+ encodedState,
446
+ ...platformRoomContext,
447
+ } as IORoomListenerEvent<TPlatform> &
448
+ InferPlatformRoomContextType<TPlatform>;
449
+
421
450
  this._rooms.delete(room);
422
- this._listeners.onRoomDeleted(room, encodedState);
451
+ this._listeners.onRoomDeleted(roomContext);
423
452
 
424
453
  if (this._debug) {
425
454
  const rooms = Array.from(this._rooms.keys());
package/src/createIO.ts CHANGED
@@ -8,7 +8,7 @@ import type {
8
8
  MaybePromise,
9
9
  } from "@pluv/types";
10
10
  import type { AbstractPlatform } from "./AbstractPlatform";
11
- import type { PluvIOListeners } from "./PluvIO";
11
+ import type { GetInitialStorageFn, PluvIOListeners } from "./PluvIO";
12
12
  import { PluvIO } from "./PluvIO";
13
13
 
14
14
  export type CreateIOParams<
@@ -16,11 +16,11 @@ export type CreateIOParams<
16
16
  TContext extends JsonObject = {},
17
17
  TAuthorizeUser extends BaseUser = BaseUser,
18
18
  TAuthorizeRequired extends boolean = false
19
- > = Partial<PluvIOListeners> & {
19
+ > = Partial<PluvIOListeners<TPlatform>> & {
20
20
  authorize?: IOAuthorize<TAuthorizeUser, TAuthorizeRequired>;
21
21
  context?: TContext;
22
22
  debug?: boolean;
23
- initialStorage?: (room: string) => MaybePromise<Maybe<string>>;
23
+ getInitialStorage?: GetInitialStorageFn<TPlatform>;
24
24
  platform: TPlatform;
25
25
  };
26
26
 
@@ -47,7 +47,7 @@ export const createIO = <
47
47
  authorize,
48
48
  context,
49
49
  debug,
50
- initialStorage,
50
+ getInitialStorage,
51
51
  onRoomDeleted,
52
52
  onStorageUpdated,
53
53
  platform,
@@ -63,7 +63,7 @@ export const createIO = <
63
63
  authorize,
64
64
  context,
65
65
  debug,
66
- initialStorage,
66
+ getInitialStorage,
67
67
  onRoomDeleted,
68
68
  onStorageUpdated,
69
69
  platform,
package/src/index.ts CHANGED
@@ -4,32 +4,39 @@ export type {
4
4
  EventRecord,
5
5
  IOEventMessage,
6
6
  } from "@pluv/types";
7
+ export { AbstractPersistance } from "./AbstractPersistance";
8
+ export { AbstractPlatform } from "./AbstractPlatform";
7
9
  export type {
8
10
  ConvertWebSocketConfig,
9
- InferWebSocketType,
11
+ InferPlatformEventContextType,
12
+ InferPlatformRoomContextType,
13
+ InferPlatformWebSocketType,
10
14
  } from "./AbstractPlatform";
11
- export { AbstractPersistance } from "./AbstractPersistance";
12
- export { AbstractPlatform } from "./AbstractPlatform";
13
- export type { IOPubSubEventMessage } from "./AbstractPubSub";
14
15
  export { AbstractPubSub } from "./AbstractPubSub";
16
+ export type { IOPubSubEventMessage } from "./AbstractPubSub";
17
+ export { AbstractWebSocket } from "./AbstractWebSocket";
15
18
  export type {
16
19
  AbstractCloseEvent,
17
20
  AbstractErrorEvent,
18
21
  AbstractEvent,
19
- AbstractMessageEvent,
20
22
  AbstractEventMap,
21
23
  AbstractListener,
24
+ AbstractMessageEvent,
22
25
  AbstractWebSocketConfig,
23
26
  AbstractWebSocketHandleErrorParams,
24
27
  } from "./AbstractWebSocket";
25
- export { AbstractWebSocket } from "./AbstractWebSocket";
28
+ export type { IORoom } from "./IORoom";
29
+ export type {
30
+ GetRoomOptions,
31
+ InferIORoom,
32
+ PluvIO,
33
+ PluvIOConfig,
34
+ } from "./PluvIO";
26
35
  export type {
27
36
  AuthorizeModule,
28
37
  AuthorizeParams,
29
38
  JWT,
30
39
  JWTEncodeParams,
31
40
  } from "./authorize";
32
- export type { CreateIOParams } from "./createIO";
33
41
  export { createIO } from "./createIO";
34
- export type { IORoom } from "./IORoom";
35
- export type { GetRoomOptions, InferIORoom, PluvIO } from "./PluvIO";
42
+ export type { CreateIOParams } from "./createIO";
package/src/types.ts CHANGED
@@ -6,6 +6,11 @@ import type {
6
6
  JsonObject,
7
7
  MaybePromise,
8
8
  } from "@pluv/types";
9
+ import {
10
+ AbstractPlatform,
11
+ InferPlatformEventContextType,
12
+ InferPlatformRoomContextType,
13
+ } from "./AbstractPlatform";
9
14
  import type { AbstractWebSocket } from "./AbstractWebSocket";
10
15
 
11
16
  export interface Console {
@@ -23,7 +28,8 @@ declare global {
23
28
  }
24
29
 
25
30
  export interface EventConfig<
26
- TContext extends JsonObject = {},
31
+ TPlatform extends AbstractPlatform = AbstractPlatform,
32
+ TContext extends Record<string, any> = {},
27
33
  TData extends JsonObject = {},
28
34
  TResultBroadcast extends EventRecord<string, any> = {},
29
35
  TResultSelf extends EventRecord<string, any> = {},
@@ -31,8 +37,15 @@ export interface EventConfig<
31
37
  > {
32
38
  input?: InputZodLike<TData>;
33
39
  resolver:
34
- | EventResolver<TContext, TData, TResultBroadcast>
40
+ | EventResolver<
41
+ TContext &
42
+ InferPlatformRoomContextType<TPlatform> &
43
+ InferPlatformEventContextType<TPlatform>,
44
+ TData,
45
+ TResultBroadcast
46
+ >
35
47
  | EventResolverObject<
48
+ TPlatform,
36
49
  TContext,
37
50
  TData,
38
51
  TResultBroadcast,
@@ -43,8 +56,17 @@ export interface EventConfig<
43
56
 
44
57
  export type EventConfigType = "broadcast" | "self" | "sync";
45
58
 
59
+ export type SyncEventResolver<
60
+ TContext extends Record<string, any> = {},
61
+ TData extends JsonObject = {},
62
+ TResultBroadcast extends EventRecord<string, any> = {}
63
+ > = (
64
+ data: TData,
65
+ context: EventResolverContext<TContext>
66
+ ) => MaybePromise<TResultBroadcast | void>;
67
+
46
68
  export type EventResolver<
47
- TContext extends JsonObject = {},
69
+ TContext extends Record<string, any> = {},
48
70
  TData extends JsonObject = {},
49
71
  TResultBroadcast extends EventRecord<string, any> = {}
50
72
  > = (
@@ -52,7 +74,9 @@ export type EventResolver<
52
74
  context: EventResolverContext<TContext>
53
75
  ) => MaybePromise<TResultBroadcast | void>;
54
76
 
55
- export interface EventResolverContext<TContext extends JsonObject = {}> {
77
+ export interface EventResolverContext<
78
+ TContext extends Record<string, any> = {}
79
+ > {
56
80
  context: TContext;
57
81
  doc: YjsDoc<any>;
58
82
  room: string;
@@ -73,19 +97,33 @@ export interface EventResolverContext<TContext extends JsonObject = {}> {
73
97
  }
74
98
 
75
99
  export type EventResolverObject<
76
- TContext extends JsonObject = {},
100
+ TPlatform extends AbstractPlatform = AbstractPlatform,
101
+ TContext extends Record<string, any> = {},
77
102
  TData extends JsonObject = {},
78
103
  TResultBroadcast extends EventRecord<string, any> = {},
79
104
  TResultSelf extends EventRecord<string, any> = {},
80
105
  TResultSync extends EventRecord<string, any> = {}
81
106
  > = {
82
- broadcast?: EventResolver<TContext, TData, TResultBroadcast>;
83
- self?: EventResolver<TContext, TData, TResultSelf>;
84
- sync?: EventResolver<TContext, TData, TResultSync>;
107
+ broadcast?: EventResolver<
108
+ TContext &
109
+ InferPlatformRoomContextType<TPlatform> &
110
+ InferPlatformEventContextType<TPlatform>,
111
+ TData,
112
+ TResultBroadcast
113
+ >;
114
+ self?: EventResolver<
115
+ TContext &
116
+ InferPlatformRoomContextType<TPlatform> &
117
+ InferPlatformEventContextType<TPlatform>,
118
+ TData,
119
+ TResultSelf
120
+ >;
121
+ sync?: SyncEventResolver<TContext, TData, TResultSync>;
85
122
  };
86
123
 
87
124
  export type InferEventConfig<
88
- TContext extends JsonObject = {},
125
+ TPlatform extends AbstractPlatform = AbstractPlatform,
126
+ TContext extends Record<string, any> = {},
89
127
  TInput extends EventRecord<string, any> = {},
90
128
  TOutputBroadcast extends EventRecord<string, any> = {},
91
129
  TOutputSelf extends EventRecord<string, any> = {},
@@ -94,6 +132,7 @@ export type InferEventConfig<
94
132
  [P in keyof TInput]: P extends string
95
133
  ? Id<
96
134
  EventConfig<
135
+ TPlatform,
97
136
  TContext,
98
137
  TInput[P],
99
138
  TOutputBroadcast,