@pluv/io 0.33.0 → 0.34.1

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.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { JsonObject, MaybePromise, IOAuthorize, IOEventMessage, EventRecord, InputZodLike, ProcedureLike, BaseIOAuthorize, IORouterLike, InferIOAuthorizeUser, Id, Maybe, InferEventMessage, InferEventsOutput, IOLike, InferIOOutput, BaseUser, InferIOInput, InferIOAuthorize } from '@pluv/types';
1
+ import { JsonObject, MaybePromise, IOAuthorize, IOEventMessage, EventRecord, InputZodLike, ProcedureLike, IORouterLike, BaseIOAuthorize, InferIOAuthorizeUser, Id, Maybe, BaseUser, UndefinedProps, InferEventMessage, InferEventsOutput, IOLike, InferIOOutput, InferIOInput, InferIOAuthorize } from '@pluv/types';
2
2
  export { BaseUser, EventMessage, EventRecord, IOEventMessage } from '@pluv/types';
3
3
  import { AbstractCrdtDocFactory, AbstractCrdtDoc } from '@pluv/crdt';
4
4
 
@@ -83,10 +83,10 @@ declare abstract class AbstractWebSocket<TWebSocket = any> {
83
83
  }
84
84
 
85
85
  interface PluvProcedureConfig<TPlatform extends AbstractPlatform<any>, TAuthorize extends IOAuthorize<any, any, InferInitContextType<TPlatform>>, TContext extends Record<string, any>, TInput extends JsonObject = {}, TOutput extends EventRecord<string, any> = {}> {
86
- broadcast?: EventResolver<TPlatform, TAuthorize, TContext, TInput, Partial<TOutput>> | null;
86
+ broadcast?: EventResolver<"broadcast", TPlatform, TAuthorize, TContext, TInput, Partial<TOutput>> | null;
87
87
  input?: InputZodLike<TInput>;
88
- self?: EventResolver<TPlatform, TAuthorize, TContext, TInput, Partial<TOutput>> | null;
89
- sync?: EventResolver<TPlatform, TAuthorize, TContext, TInput, Partial<TOutput>> | null;
88
+ self?: EventResolver<"self", TPlatform, TAuthorize, TContext, TInput, Partial<TOutput>> | null;
89
+ sync?: EventResolver<"sync", TPlatform, TAuthorize, TContext, TInput, Partial<TOutput>> | null;
90
90
  }
91
91
  declare class PluvProcedure<TPlatform extends AbstractPlatform<any>, TAuthorize extends IOAuthorize<any, any, InferInitContextType<TPlatform>>, TContext extends Record<string, any>, TInput extends JsonObject = {}, TOutput extends EventRecord<string, any> = {}, TFilled extends "input" | "broadcast" | "self" | "sync" | "" = ""> {
92
92
  private _broadcast;
@@ -95,21 +95,21 @@ declare class PluvProcedure<TPlatform extends AbstractPlatform<any>, TAuthorize
95
95
  private _sync;
96
96
  get config(): ProcedureLike<TInput, TOutput>["config"];
97
97
  constructor(config?: PluvProcedureConfig<TPlatform, TAuthorize, TContext, TInput, TOutput>);
98
- broadcast<TResult extends EventRecord<string, any> = {}>(resolver: EventResolver<TPlatform, TAuthorize, TContext, TInput, TResult>): Omit<PluvProcedure<TPlatform, TAuthorize, TContext, TInput, MergeEventRecords<[TOutput, TResult]>, TFilled | "input" | "broadcast">, TFilled | "input" | "broadcast">;
98
+ broadcast<TResult extends EventRecord<string, any> = {}>(resolver: EventResolver<"broadcast", TPlatform, TAuthorize, TContext, TInput, TResult>): Omit<PluvProcedure<TPlatform, TAuthorize, TContext, TInput, MergeEventRecords<[TOutput, TResult]>, TFilled | "input" | "broadcast">, TFilled | "input" | "broadcast">;
99
99
  input<TData extends JsonObject>(input: InputZodLike<TData>): Omit<PluvProcedure<TPlatform, TAuthorize, TContext, TData, {}, TFilled | "input">, TFilled | "input">;
100
- self<TResult extends EventRecord<string, any> = {}>(resolver: EventResolver<TPlatform, TAuthorize, TContext, TInput, TResult>): Omit<PluvProcedure<TPlatform, TAuthorize, TContext, TInput, MergeEventRecords<[TOutput, TResult]>, TFilled | "input" | "self">, TFilled | "input" | "self">;
101
- sync<TResult extends EventRecord<string, any> = {}>(resolver: EventResolver<TPlatform, TAuthorize, TContext, TInput, TResult>): Omit<PluvProcedure<TPlatform, TAuthorize, TContext, TInput, MergeEventRecords<[TOutput, TResult]>, TFilled | "input" | "sync">, TFilled | "input" | "sync">;
100
+ self<TResult extends EventRecord<string, any> = {}>(resolver: EventResolver<"self", TPlatform, TAuthorize, TContext, TInput, TResult>): Omit<PluvProcedure<TPlatform, TAuthorize, TContext, TInput, MergeEventRecords<[TOutput, TResult]>, TFilled | "input" | "self">, TFilled | "input" | "self">;
101
+ sync<TResult extends EventRecord<string, any> = {}>(resolver: EventResolver<"sync", TPlatform, TAuthorize, TContext, TInput, TResult>): Omit<PluvProcedure<TPlatform, TAuthorize, TContext, TInput, MergeEventRecords<[TOutput, TResult]>, TFilled | "input" | "sync">, TFilled | "input" | "sync">;
102
102
  private _resolver;
103
103
  }
104
104
 
105
- type PluvRouterEventConfig<TPlatform extends AbstractPlatform<any> = AbstractPlatform<any>, TAuthorize extends IOAuthorize<any, any, InferInitContextType<TPlatform>> = BaseIOAuthorize, TContext extends Record<string, any> = {}> = {
105
+ type PluvRouterEventConfig<TPlatform extends AbstractPlatform<any> = AbstractPlatform<any>, TAuthorize extends PluvIOAuthorize<TPlatform, any, any, InferInitContextType<TPlatform>> = any, TContext extends Record<string, any> = {}> = {
106
106
  [P: string]: Pick<PluvProcedure<TPlatform, TAuthorize, TContext, any, any>, "config">;
107
107
  };
108
- type MergedRouter<TRouters extends PluvRouter<TPlatform, TAuthorize, TContext, any>[] = [], TPlatform extends AbstractPlatform<any> = AbstractPlatform<any>, TAuthorize extends IOAuthorize<any, any, InferInitContextType<TPlatform>> = BaseIOAuthorize, TContext extends Record<string, any> = {}, TRoot extends TRouters[0]["_defs"]["events"] = {}> = TRouters extends [
108
+ type MergedRouter<TRouters extends PluvRouter<TPlatform, TAuthorize, TContext, any>[] = [], TPlatform extends AbstractPlatform<any> = AbstractPlatform<any>, TAuthorize extends PluvIOAuthorize<TPlatform, any, any, InferInitContextType<TPlatform>> = any, TContext extends Record<string, any> = {}, TRoot extends TRouters[0]["_defs"]["events"] = {}> = TRouters extends [
109
109
  infer IHead extends PluvRouter<TPlatform, TAuthorize, TContext, any>,
110
110
  ...infer ITail extends PluvRouter<TPlatform, TAuthorize, TContext, any>[]
111
111
  ] ? MergedRouter<ITail, TPlatform, TAuthorize, TContext, TRoot & IHead["_defs"]["events"]> : PluvRouter<TPlatform, TAuthorize, TContext, TRoot>;
112
- declare class PluvRouter<TPlatform extends AbstractPlatform<any> = AbstractPlatform<any>, TAuthorize extends IOAuthorize<any, any, InferInitContextType<TPlatform>> = BaseIOAuthorize, TContext extends Record<string, any> = {}, TEvents extends PluvRouterEventConfig<TPlatform, TAuthorize, TContext> = {}> implements IORouterLike<TEvents> {
112
+ declare class PluvRouter<TPlatform extends AbstractPlatform<any> = AbstractPlatform<any>, TAuthorize extends PluvIOAuthorize<TPlatform, any, any, InferInitContextType<TPlatform>> = any, TContext extends Record<string, any> = {}, TEvents extends PluvRouterEventConfig<TPlatform, TAuthorize, TContext> = {}> implements IORouterLike<TEvents> {
113
113
  readonly _defs: {
114
114
  events: TEvents;
115
115
  };
@@ -127,24 +127,13 @@ interface CrdtLibraryType {
127
127
  doc: (value: any) => AbstractCrdtDocFactory<any>;
128
128
  kind: "loro" | "yjs";
129
129
  }
130
- type EventResolver<TPlatform extends AbstractPlatform = AbstractPlatform, TAuthorize extends IOAuthorize<any, any, InferInitContextType<TPlatform>> = BaseIOAuthorize, TContext extends Record<string, any> = {}, TInput extends JsonObject = {}, TOutput extends EventRecord<string, any> = {}> = (data: TInput, context: EventResolverContext<TPlatform, TAuthorize, TContext>) => MaybePromise<TOutput | void>;
131
- interface EventResolverContext<TPlatform extends AbstractPlatform = AbstractPlatform, TAuthorize extends IOAuthorize<any, any, InferInitContextType<TPlatform>> = BaseIOAuthorize, TContext extends Record<string, any> = {}> {
130
+ type EventResolverKind = "broadcast" | "self" | "sync";
131
+ type EventResolver<TKind extends EventResolverKind = EventResolverKind, TPlatform extends AbstractPlatform = AbstractPlatform, TAuthorize extends IOAuthorize<any, any, InferInitContextType<TPlatform>> = BaseIOAuthorize, TContext extends Record<string, any> = {}, TInput extends JsonObject = {}, TOutput extends EventRecord<string, any> = {}> = (data: TInput, context: EventResolverContext<TKind, TPlatform, TAuthorize, TContext>) => MaybePromise<TOutput | void>;
132
+ interface EventResolverContext<TKind extends EventResolverKind = EventResolverKind, TPlatform extends AbstractPlatform = AbstractPlatform, TAuthorize extends IOAuthorize<any, any, InferInitContextType<TPlatform>> = BaseIOAuthorize, TContext extends Record<string, any> = {}> {
132
133
  context: TContext;
133
134
  doc: AbstractCrdtDoc<any>;
134
135
  room: string;
135
- /**
136
- * !HACK
137
- * @description Session should only not exist when invoking the event as a
138
- * "sync" event on another machine where the session doesn't exist. There must
139
- * be a better way to handle this, but going to make this nullable for ease
140
- * for now.
141
- *
142
- * `session` should not be referenced most of the time anyhow (outside of
143
- * internal to this library).
144
- * @author leedavidcs
145
- * @date December 25, 2022
146
- */
147
- session: WebSocketSession<TAuthorize> | null;
136
+ session: TKind extends "sync" ? WebSocketSession<TAuthorize> | null : WebSocketSession<TAuthorize>;
148
137
  sessions: readonly WebSocketSession<TAuthorize>[];
149
138
  }
150
139
  type SendMessageOptions = {
@@ -180,19 +169,52 @@ type GetInitialStorageEvent<TContext extends Record<string, any>> = {
180
169
  room: string;
181
170
  };
182
171
  type GetInitialStorageFn<TContext extends Record<string, any>> = (event: GetInitialStorageEvent<TContext>) => MaybePromise<Maybe<string>>;
183
- interface PluvIOListeners<TPlatform extends AbstractPlatform<any>, TAuthorize extends IOAuthorize<any, any, InferInitContextType<TPlatform>>, TContext extends Record<string, any>, TEvents extends PluvRouterEventConfig<TPlatform, TAuthorize, TContext>> {
172
+ type HandleMode = "io" | "fetch";
173
+ type WebSocketRegistrationMode = "attached" | "detached";
174
+ interface PlatformConfig {
175
+ authorize: {
176
+ required?: boolean;
177
+ secret?: boolean;
178
+ };
179
+ requireAuth?: boolean;
180
+ handleMode: HandleMode;
181
+ registrationMode: WebSocketRegistrationMode;
182
+ listeners: {
183
+ onRoomDeleted?: boolean;
184
+ onRoomMessage?: boolean;
185
+ onStorageUpdated?: boolean;
186
+ onUserConnected?: boolean;
187
+ onUserDisconnected?: boolean;
188
+ };
189
+ }
190
+ type ResolvedPluvIOAuthorize<TPlatform extends AbstractPlatform<any, any, any, any>, TUser extends BaseUser = any, TRequired extends boolean = false> = {
191
+ user: InputZodLike<TUser>;
192
+ required?: TRequired;
193
+ } & UndefinedProps<{
194
+ secret?: string;
195
+ }, Exclude<"secret", InferPlatformAuthorizeProperties<TPlatform>>>;
196
+ type PluvIOAuthorize<TPlatform extends AbstractPlatform<any, any, any, any>, TUser extends BaseUser = any, TRequired extends boolean = false, TContext extends Record<string, unknown> = {}> = ResolvedPluvIOAuthorize<TPlatform, TUser, TRequired> | ((context: TContext) => ResolvedPluvIOAuthorize<TPlatform, TUser, TRequired>);
197
+ type BasePluvIOListeners<TPlatform extends AbstractPlatform<any, any, any, any>, TAuthorize extends PluvIOAuthorize<TPlatform, any, any, InferInitContextType<TPlatform>>, TContext extends Record<string, any>, TEvents extends PluvRouterEventConfig<TPlatform, TAuthorize, TContext>> = {
184
198
  onRoomDeleted: (event: IORoomListenerEvent<TContext>) => void;
185
199
  onRoomMessage: (event: IORoomMessageEvent<TPlatform, TAuthorize, TContext, TEvents>) => void;
186
200
  onStorageUpdated: (event: IOStorageUpdatedEvent<TPlatform, TAuthorize, TContext>) => void;
187
201
  onUserConnected: (event: IOUserConnectedEvent<TPlatform, TAuthorize, TContext>) => void;
188
202
  onUserDisconnected: (event: IOUserDisconnectedEvent<TPlatform, TAuthorize, TContext>) => void;
189
- }
203
+ };
204
+ type PluvIOListeners<TPlatform extends AbstractPlatform<any, any, any, any>, TAuthorize extends PluvIOAuthorize<TPlatform, any, any, InferInitContextType<TPlatform>>, TContext extends Record<string, any>, TEvents extends PluvRouterEventConfig<TPlatform, TAuthorize, TContext>> = UndefinedProps<BasePluvIOListeners<TPlatform, TAuthorize, TContext, TEvents>, Exclude<keyof BasePluvIOListeners<TPlatform, TAuthorize, TContext, TEvents>, InferPlatformListeners<TPlatform>>>;
205
+ type InferPlatformConfig<TPlatform extends AbstractPlatform<any, any, any, any>> = TPlatform extends AbstractPlatform<any, any, any, infer IConfig> ? IConfig : never;
206
+ type InferPlatformAuthorizeProperties<TPlatform extends AbstractPlatform<any, any, any, any>> = keyof {
207
+ [P in keyof PlatformConfig["authorize"] as InferPlatformConfig<TPlatform>["authorize"][P] extends true | undefined ? P : never]: true;
208
+ };
209
+ type InferPlatformListeners<TPlatform extends AbstractPlatform<any, any, any, any>> = keyof {
210
+ [P in keyof PlatformConfig["listeners"] as InferPlatformConfig<TPlatform>["listeners"][P] extends true | undefined ? P : never]: true;
211
+ };
190
212
  type IORoomListenerEvent<TContext extends Record<string, any>> = {
191
213
  context: TContext;
192
214
  encodedState: string | null;
193
215
  room: string;
194
216
  };
195
- type IORoomMessageEvent<TPlatform extends AbstractPlatform<any>, TAuthorize extends IOAuthorize<any, any, InferInitContextType<TPlatform>>, TContext extends Record<string, any>, TEvents extends PluvRouterEventConfig<TPlatform, TAuthorize, TContext>> = IORoomListenerEvent<TContext> & {
217
+ type IORoomMessageEvent<TPlatform extends AbstractPlatform<any>, TAuthorize extends PluvIOAuthorize<TPlatform, any, any, InferInitContextType<TPlatform>>, TContext extends Record<string, any>, TEvents extends PluvRouterEventConfig<TPlatform, TAuthorize, TContext>> = IORoomListenerEvent<TContext> & {
196
218
  message: InferEventMessage<InferEventsOutput<TEvents>, keyof InferEventsOutput<TEvents>>;
197
219
  user?: InferIOAuthorizeUser<TAuthorize>;
198
220
  webSocket?: InferPlatformWebSocketSource<TPlatform>;
@@ -219,7 +241,29 @@ declare abstract class AbstractPubSub {
219
241
  abstract unsubscribe(subscriptionId: number): void;
220
242
  }
221
243
 
222
- type WebSocketRegistrationMode = "attached" | "detached";
244
+ interface JWT<TUser extends BaseUser> {
245
+ room: string;
246
+ sub: string;
247
+ user: TUser;
248
+ }
249
+ type JWTEncodeParams<TUser extends BaseUser, TPlatform extends AbstractPlatform> = {
250
+ maxAge?: number;
251
+ room: string;
252
+ user: TUser;
253
+ } & InferInitContextType<TPlatform>;
254
+ interface AuthorizeParams {
255
+ platform: AbstractPlatform;
256
+ secret: string;
257
+ }
258
+ interface AuthorizeModule {
259
+ decode: <TUser extends BaseUser>(jwt: string) => Promise<TUser | null>;
260
+ encode: <TUser extends BaseUser, TPlatform extends AbstractPlatform>(params: JWTEncodeParams<TUser, TPlatform>) => Promise<string>;
261
+ }
262
+ declare const authorize: (params: AuthorizeParams) => {
263
+ decode: <TUser extends BaseUser>(jwt: string) => Promise<JWT<TUser> | null>;
264
+ encode: <TUser extends BaseUser, TPlatform extends AbstractPlatform>(encodeParams: JWTEncodeParams<TUser, TPlatform>) => Promise<string>;
265
+ };
266
+
223
267
  type InferPlatformWebSocketType<TPlatform extends AbstractPlatform> = TPlatform extends AbstractPlatform<infer IAbstractWebSocket> ? IAbstractWebSocket : never;
224
268
  type InferPlatformWebSocketSource<TPlatform> = TPlatform extends AbstractPlatform<infer IAbstractWebSocket> ? InferWebSocketSource<IAbstractWebSocket> : never;
225
269
  type InferInitContextType<TPlatform extends AbstractPlatform> = TPlatform extends AbstractPlatform<any, infer IInitContext> ? IInitContext : never;
@@ -232,13 +276,16 @@ type AbstractPlatformConfig<TRoomContext extends Record<string, any> = {}> = {
232
276
  interface ConvertWebSocketConfig {
233
277
  room: string;
234
278
  }
235
- declare abstract class AbstractPlatform<TWebSocket extends AbstractWebSocket = AbstractWebSocket, TInitContext extends Record<string, any> = {}, TRoomContext extends Record<string, any> = {}> {
279
+ declare abstract class AbstractPlatform<TWebSocket extends AbstractWebSocket = AbstractWebSocket, TInitContext extends Record<string, any> = {}, TRoomContext extends Record<string, any> = {}, TConfig extends PlatformConfig = PlatformConfig> {
236
280
  protected readonly _initContext: TInitContext | undefined;
237
281
  protected readonly _roomContext: TRoomContext | undefined;
238
282
  private _initialized;
239
283
  persistence: AbstractPersistence;
240
284
  pubSub: AbstractPubSub;
241
- abstract readonly _registrationMode: WebSocketRegistrationMode;
285
+ readonly _createToken?: (params: JWTEncodeParams<any, any>) => Promise<string>;
286
+ _fetch?: (req: any) => Promise<any>;
287
+ abstract readonly _config: TConfig;
288
+ abstract readonly _name: string;
242
289
  constructor(config?: AbstractPlatformConfig<TRoomContext>);
243
290
  abstract acceptWebSocket(webSocket: AbstractWebSocket): Promise<void>;
244
291
  abstract convertWebSocket(webSocket: InferWebSocketSource<TWebSocket>, config: ConvertWebSocketConfig): AbstractWebSocket;
@@ -250,33 +297,11 @@ declare abstract class AbstractPlatform<TWebSocket extends AbstractWebSocket = A
250
297
  abstract parseData(data: string | ArrayBuffer): Record<string, any>;
251
298
  abstract randomUUID(): string;
252
299
  abstract setSerializedState(webSocket: AbstractWebSocket, state: WebSocketSerializedState): void;
300
+ validateConfig(config: any): void;
253
301
  protected _initialize(): this;
254
302
  }
255
303
 
256
- interface JWT<TUser extends BaseUser> {
257
- room: string;
258
- sub: string;
259
- user: TUser;
260
- }
261
- type JWTEncodeParams<TUser extends BaseUser, TPlatform extends AbstractPlatform> = {
262
- maxAge?: number;
263
- room: string;
264
- user: TUser;
265
- } & InferInitContextType<TPlatform>;
266
- interface AuthorizeParams {
267
- platform: AbstractPlatform;
268
- secret: string;
269
- }
270
- interface AuthorizeModule {
271
- decode: <TUser extends BaseUser>(jwt: string) => Promise<TUser | null>;
272
- encode: <TUser extends BaseUser, TPlatform extends AbstractPlatform>(params: JWTEncodeParams<TUser, TPlatform>) => Promise<string>;
273
- }
274
- declare const authorize: (params: AuthorizeParams) => {
275
- decode: <TUser extends BaseUser>(jwt: string) => Promise<JWT<TUser> | null>;
276
- encode: <TUser extends BaseUser, TPlatform extends AbstractPlatform>(encodeParams: JWTEncodeParams<TUser, TPlatform>) => Promise<string>;
277
- };
278
-
279
- interface IORoomListeners<TPlatform extends AbstractPlatform<any>, TAuthorize extends IOAuthorize<any, any, InferInitContextType<TPlatform>>, TContext extends Record<string, any>, TEvents extends PluvRouterEventConfig<TPlatform, TAuthorize, TContext>> {
304
+ interface IORoomListeners<TPlatform extends AbstractPlatform<any>, TAuthorize extends PluvIOAuthorize<TPlatform, any, any, InferInitContextType<TPlatform>>, TContext extends Record<string, any>, TEvents extends PluvRouterEventConfig<TPlatform, TAuthorize, TContext>> {
280
305
  onDestroy: (event: IORoomListenerEvent<TContext>) => void;
281
306
  onMessage: (event: IORoomMessageEvent<TPlatform, TAuthorize, TContext, TEvents>) => void;
282
307
  onUserConnected: (event: IOUserConnectedEvent<TPlatform, TAuthorize, TContext>) => void;
@@ -285,7 +310,7 @@ interface IORoomListeners<TPlatform extends AbstractPlatform<any>, TAuthorize ex
285
310
  type BroadcastProxy<TIO extends IORoom<any, any, any, any>> = (<TEvent extends keyof InferIOInput<TIO>>(event: TEvent, data: Id<InferIOInput<TIO>[TEvent]>) => Promise<void>) & {
286
311
  [event in keyof InferIOInput<TIO>]: (data: Id<InferIOInput<TIO>>[event]) => Promise<void>;
287
312
  };
288
- type IORoomConfig<TPlatform extends AbstractPlatform<any> = AbstractPlatform<any>, TAuthorize extends IOAuthorize<any, any, InferInitContextType<TPlatform>> = BaseIOAuthorize, TContext extends Record<string, any> = {}, TEvents extends PluvRouterEventConfig<TPlatform, TAuthorize, TContext> = {}> = Partial<IORoomListeners<TPlatform, TAuthorize, TContext, TEvents>> & {
313
+ type IORoomConfig<TPlatform extends AbstractPlatform<any> = AbstractPlatform<any>, TAuthorize extends PluvIOAuthorize<TPlatform, any, any, InferInitContextType<TPlatform>> = any, TContext extends Record<string, any> = {}, TEvents extends PluvRouterEventConfig<TPlatform, TAuthorize, TContext> = {}> = Partial<IORoomListeners<TPlatform, TAuthorize, TContext, TEvents>> & {
289
314
  authorize?: TAuthorize;
290
315
  context: TContext;
291
316
  crdt?: {
@@ -299,7 +324,7 @@ type IORoomConfig<TPlatform extends AbstractPlatform<any> = AbstractPlatform<any
299
324
  type WebsocketRegisterConfig<TPlatform extends AbstractPlatform<any> = AbstractPlatform<any>> = {
300
325
  token?: string | null;
301
326
  } & InferInitContextType<TPlatform>;
302
- declare class IORoom<TPlatform extends AbstractPlatform<any> = AbstractPlatform<any>, TAuthorize extends IOAuthorize<any, any, InferInitContextType<TPlatform>> = BaseIOAuthorize, TContext extends Record<string, any> = {}, TEvents extends PluvRouterEventConfig<TPlatform, TAuthorize, TContext> = {}> implements IOLike<TAuthorize, TEvents> {
327
+ declare class IORoom<TPlatform extends AbstractPlatform<any> = AbstractPlatform<any>, TAuthorize extends PluvIOAuthorize<TPlatform, any, any, InferInitContextType<TPlatform>> = any, TContext extends Record<string, any> = {}, TEvents extends PluvRouterEventConfig<TPlatform, TAuthorize, TContext> = {}> implements IOLike<TAuthorize, TEvents> {
303
328
  readonly id: string;
304
329
  private _doc;
305
330
  private _uninitialize;
@@ -367,7 +392,7 @@ declare class IORoom<TPlatform extends AbstractPlatform<any> = AbstractPlatform<
367
392
  }
368
393
 
369
394
  type InferIORoom<TServer extends PluvServer<any, any, any, any>> = TServer extends PluvServer<infer IPlatform, infer IAuthorize, infer IContext, infer IEvents> ? IORoom<IPlatform, IAuthorize, IContext, IEvents> : never;
370
- type PluvServerConfig<TPlatform extends AbstractPlatform<any> = AbstractPlatform<any>, TAuthorize extends IOAuthorize<any, any, InferInitContextType<TPlatform>> = BaseIOAuthorize, TContext extends Record<string, any> = {}, TEvents extends PluvRouterEventConfig<TPlatform, TAuthorize, TContext> = {}> = Partial<PluvIOListeners<TPlatform, TAuthorize, TContext, TEvents>> & {
395
+ type PluvServerConfig<TPlatform extends AbstractPlatform<any> = AbstractPlatform<any>, TAuthorize extends PluvIOAuthorize<TPlatform, any, any, InferInitContextType<TPlatform>> = any, TContext extends Record<string, any> = {}, TEvents extends PluvRouterEventConfig<TPlatform, TAuthorize, TContext> = {}> = Partial<PluvIOListeners<TPlatform, TAuthorize, TContext, TEvents>> & {
371
396
  authorize?: TAuthorize;
372
397
  context?: PluvContext<TPlatform, TContext>;
373
398
  crdt?: {
@@ -378,11 +403,11 @@ type PluvServerConfig<TPlatform extends AbstractPlatform<any> = AbstractPlatform
378
403
  platform: TPlatform;
379
404
  router?: PluvRouter<TPlatform, TAuthorize, TContext, TEvents>;
380
405
  };
381
- type BaseCreateRoomOptions<TPlatform extends AbstractPlatform<any>, TAuthorize extends IOAuthorize<any, any, InferInitContextType<TPlatform>>, TContext extends Record<string, any>, TEvents extends PluvRouterEventConfig<TPlatform, TAuthorize, TContext>> = Partial<IORoomListeners<TPlatform, TAuthorize, TContext, TEvents>> & {
406
+ type BaseCreateRoomOptions<TPlatform extends AbstractPlatform<any>, TAuthorize extends PluvIOAuthorize<TPlatform, any, any, InferInitContextType<TPlatform>>, TContext extends Record<string, any>, TEvents extends PluvRouterEventConfig<TPlatform, TAuthorize, TContext>> = Partial<IORoomListeners<TPlatform, TAuthorize, TContext, TEvents>> & {
382
407
  debug?: boolean;
383
408
  };
384
- type CreateRoomOptions<TPlatform extends AbstractPlatform<any>, TAuthorize extends IOAuthorize<any, any, InferInitContextType<TPlatform>>, TContext extends Record<string, any>, TEvents extends PluvRouterEventConfig<TPlatform, TAuthorize, TContext>> = keyof InferRoomContextType<TPlatform> extends never ? [BaseCreateRoomOptions<TPlatform, TAuthorize, TContext, TEvents>] | [] : [Id<BaseCreateRoomOptions<TPlatform, TAuthorize, TContext, TEvents> & InferRoomContextType<TPlatform>>];
385
- declare class PluvServer<TPlatform extends AbstractPlatform<any> = AbstractPlatform<any>, TAuthorize extends IOAuthorize<any, any, InferInitContextType<TPlatform>> = BaseIOAuthorize, TContext extends Record<string, any> = {}, TEvents extends PluvRouterEventConfig<TPlatform, TAuthorize, TContext> = {}> implements IOLike<TAuthorize, TEvents> {
409
+ type CreateRoomOptions<TPlatform extends AbstractPlatform<any>, TAuthorize extends PluvIOAuthorize<TPlatform, any, any, InferInitContextType<TPlatform>>, TContext extends Record<string, any>, TEvents extends PluvRouterEventConfig<TPlatform, TAuthorize, TContext>> = keyof InferRoomContextType<TPlatform> extends never ? [BaseCreateRoomOptions<TPlatform, TAuthorize, TContext, TEvents>] | [] : [Id<BaseCreateRoomOptions<TPlatform, TAuthorize, TContext, TEvents> & InferRoomContextType<TPlatform>>];
410
+ declare class PluvServer<TPlatform extends AbstractPlatform<any> = AbstractPlatform<any>, TAuthorize extends PluvIOAuthorize<TPlatform, any, any, InferInitContextType<TPlatform>> = any, TContext extends Record<string, any> = {}, TEvents extends PluvRouterEventConfig<TPlatform, TAuthorize, TContext> = {}> implements IOLike<TAuthorize, TEvents> {
386
411
  readonly version: string;
387
412
  private readonly _authorize;
388
413
  private readonly _baseRouter;
@@ -392,6 +417,7 @@ declare class PluvServer<TPlatform extends AbstractPlatform<any> = AbstractPlatf
392
417
  private readonly _getInitialStorage;
393
418
  private readonly _platform;
394
419
  private readonly _router;
420
+ get fetch(): (req: any) => Promise<any>;
395
421
  /**
396
422
  * @ignore
397
423
  * @readonly
@@ -407,22 +433,26 @@ declare class PluvServer<TPlatform extends AbstractPlatform<any> = AbstractPlatf
407
433
  constructor(options: PluvServerConfig<TPlatform, TAuthorize, TContext, TEvents>);
408
434
  createRoom(room: string, ...options: CreateRoomOptions<TPlatform, TAuthorize, TContext, TEvents>): IORoom<TPlatform, TAuthorize, TContext, TEvents>;
409
435
  createToken(params: JWTEncodeParams<InferIOAuthorizeUser<InferIOAuthorize<this>>, TPlatform>): Promise<string>;
436
+ private _getIOAuthorize;
410
437
  private _getListeners;
411
438
  private _logDebug;
412
439
  }
413
440
 
414
441
  type PluvIOConfig<TPlatform extends AbstractPlatform<any>, TAuthorize extends IOAuthorize<any, any, InferInitContextType<TPlatform>>, TContext extends Record<string, any>> = {
415
- authorize?: TAuthorize;
416
442
  context?: PluvContext<TPlatform, TContext>;
417
443
  crdt?: CrdtLibraryType;
418
444
  debug?: boolean;
419
445
  platform: TPlatform;
420
- };
421
- type ServerConfig<TPlatform extends AbstractPlatform<any> = AbstractPlatform<any>, TAuthorize extends IOAuthorize<any, any, InferInitContextType<TPlatform>> = BaseIOAuthorize, TContext extends Record<string, any> = {}, TEvents extends PluvRouterEventConfig<TPlatform, TAuthorize, TContext> = {}> = Partial<PluvIOListeners<TPlatform, TAuthorize, TContext, TEvents>> & {
446
+ } & (InferPlatformConfig<TPlatform>["requireAuth"] extends true ? {
447
+ authorize: TAuthorize;
448
+ } : {
449
+ authorize?: TAuthorize;
450
+ });
451
+ type ServerConfig<TPlatform extends AbstractPlatform<any> = AbstractPlatform<any>, TAuthorize extends PluvIOAuthorize<TPlatform, any, any, InferInitContextType<TPlatform>> = any, TContext extends Record<string, any> = {}, TEvents extends PluvRouterEventConfig<TPlatform, TAuthorize, TContext> = {}> = Partial<PluvIOListeners<TPlatform, TAuthorize, TContext, TEvents>> & {
422
452
  getInitialStorage?: GetInitialStorageFn<TContext>;
423
453
  router?: PluvRouter<TPlatform, TAuthorize, TContext, TEvents>;
424
454
  };
425
- declare class PluvIO<TPlatform extends AbstractPlatform<any> = AbstractPlatform<any>, TAuthorize extends IOAuthorize<any, any, InferInitContextType<TPlatform>> = BaseIOAuthorize, TContext extends Record<string, any> = {}> {
455
+ declare class PluvIO<TPlatform extends AbstractPlatform<any> = AbstractPlatform<any>, TAuthorize extends PluvIOAuthorize<TPlatform, any, any, InferInitContextType<TPlatform>> = any, TContext extends Record<string, any> = {}> {
426
456
  readonly version: string;
427
457
  private readonly _authorize;
428
458
  private readonly _context;
@@ -435,15 +465,16 @@ declare class PluvIO<TPlatform extends AbstractPlatform<any> = AbstractPlatform<
435
465
  mergeRouters<TRouters extends PluvRouter<TPlatform, TAuthorize, TContext, any>[]>(...routers: TRouters): MergedRouter<TRouters>;
436
466
  router<TEvents extends PluvRouterEventConfig<TPlatform, TAuthorize, TContext>>(events: TEvents): PluvRouter<TPlatform, TAuthorize, TContext, TEvents>;
437
467
  server<TEvents extends PluvRouterEventConfig<TPlatform, TAuthorize, TContext>>(config?: ServerConfig<TPlatform, TAuthorize, TContext, TEvents>): PluvServer<TPlatform, TAuthorize, TContext, TEvents>;
468
+ private _getIOAuthorize;
438
469
  }
439
470
 
440
471
  type CreateIOParams<TPlatform extends AbstractPlatform<any> = AbstractPlatform<any>, TContext extends Record<string, any> = {}, TAuthorizeUser extends BaseUser = BaseUser, TAuthorizeRequired extends boolean = false> = {
441
- authorize?: IOAuthorize<TAuthorizeUser, TAuthorizeRequired, InferInitContextType<TPlatform>>;
472
+ authorize?: PluvIOAuthorize<TPlatform, TAuthorizeUser, TAuthorizeRequired, InferInitContextType<TPlatform>>;
442
473
  context?: PluvContext<TPlatform, TContext>;
443
474
  crdt?: CrdtLibraryType;
444
475
  debug?: boolean;
445
476
  platform: TPlatform;
446
477
  };
447
- declare const createIO: <TPlatform extends AbstractPlatform<any> = AbstractPlatform<any, {}, {}>, TContext extends Record<string, any> = {}, TAuthorizeUser extends BaseUser = BaseUser, TAuthorizeRequired extends boolean = false>(params: CreateIOParams<TPlatform, TContext, TAuthorizeUser, TAuthorizeRequired>) => PluvIO<TPlatform, IOAuthorize<TAuthorizeUser, TAuthorizeRequired, InferInitContextType<TPlatform>>, TContext>;
478
+ declare const createIO: <TPlatform extends AbstractPlatform<any> = AbstractPlatform<any, {}, {}, PlatformConfig>, TContext extends Record<string, any> = {}, TAuthorizeUser extends BaseUser = BaseUser, TAuthorizeRequired extends boolean = false>(params: CreateIOParams<TPlatform, TContext, TAuthorizeUser, TAuthorizeRequired>) => PluvIO<TPlatform, PluvIOAuthorize<TPlatform, TAuthorizeUser, TAuthorizeRequired, InferInitContextType<TPlatform>>, TContext>;
448
479
 
449
- export { type AbstractCloseEvent, type AbstractErrorEvent, type AbstractEvent, type AbstractEventMap, type AbstractListener, type AbstractMessageEvent, AbstractPersistence, AbstractPlatform, type AbstractPlatformConfig, AbstractPubSub, AbstractWebSocket, type AbstractWebSocketConfig, type AbstractWebSocketHandleErrorParams, type AuthorizeModule, type AuthorizeParams, type ConvertWebSocketConfig, type CrdtLibraryType, type CreateIOParams, type CreateRoomOptions, type GetInitialStorageFn, type IOPubSubEventMessage, IORoom, type IORoomListenerEvent, type IORoomMessageEvent, type IOStorageUpdatedEvent, type IOUserConnectedEvent, type IOUserDisconnectedEvent, type InferIORoom, type InferInitContextType, type InferPlatformWebSocketType, type InferRoomContextType, type JWT, type JWTEncodeParams, type MergedRouter, PluvIO, type PluvIOConfig, type PluvIOListeners, PluvProcedure, type PluvProcedureConfig, PluvRouter, type PluvRouterEventConfig, PluvServer, type PluvServerConfig, type ServerConfig, type WebSocketRegistrationMode, type WebSocketSerializedState, type WebSocketSession, authorize, createIO };
480
+ export { type AbstractCloseEvent, type AbstractErrorEvent, type AbstractEvent, type AbstractEventMap, type AbstractListener, type AbstractMessageEvent, AbstractPersistence, AbstractPlatform, type AbstractPlatformConfig, AbstractPubSub, AbstractWebSocket, type AbstractWebSocketConfig, type AbstractWebSocketHandleErrorParams, type AuthorizeModule, type AuthorizeParams, type ConvertWebSocketConfig, type CrdtLibraryType, type CreateIOParams, type CreateRoomOptions, type GetInitialStorageFn, type HandleMode, type IOPubSubEventMessage, IORoom, type IORoomListenerEvent, type IORoomMessageEvent, type IOStorageUpdatedEvent, type IOUserConnectedEvent, type IOUserDisconnectedEvent, type InferIORoom, type InferInitContextType, type InferPlatformWebSocketType, type InferRoomContextType, type JWT, type JWTEncodeParams, type MergedRouter, type PlatformConfig, PluvIO, type PluvIOConfig, type PluvIOListeners, PluvProcedure, type PluvProcedureConfig, PluvRouter, type PluvRouterEventConfig, PluvServer, type PluvServerConfig, type ServerConfig, type WebSocketRegistrationMode, type WebSocketSerializedState, type WebSocketSession, authorize, createIO };
package/dist/index.js CHANGED
@@ -77,8 +77,8 @@ var __async = (__this, __arguments, generator) => {
77
77
  };
78
78
 
79
79
  // src/index.ts
80
- var src_exports = {};
81
- __export(src_exports, {
80
+ var index_exports = {};
81
+ __export(index_exports, {
82
82
  AbstractPersistence: () => AbstractPersistence,
83
83
  AbstractPlatform: () => AbstractPlatform,
84
84
  AbstractPubSub: () => AbstractPubSub,
@@ -90,7 +90,7 @@ __export(src_exports, {
90
90
  authorize: () => authorize,
91
91
  createIO: () => createIO
92
92
  });
93
- module.exports = __toCommonJS(src_exports);
93
+ module.exports = __toCommonJS(index_exports);
94
94
 
95
95
  // src/AbstractPersistence.ts
96
96
  var AbstractPersistence = class {
@@ -224,6 +224,8 @@ var AbstractPlatform = class {
224
224
  this.persistence = persistence != null ? persistence : new Persistence();
225
225
  this.pubSub = pubSub != null ? pubSub : new PubSub();
226
226
  }
227
+ validateConfig(config) {
228
+ }
227
229
  _initialize() {
228
230
  if (this._initialized) throw new Error("Platform is already initialized");
229
231
  this._initialized = true;
@@ -553,7 +555,7 @@ var IORoom = class {
553
555
  }
554
556
  this._sessions.set(pluvWs.sessionId, pluvWs);
555
557
  yield this._platform.persistence.addUser(this.id, pluvWs.sessionId, user != null ? user : {});
556
- if (this._platform._registrationMode === "attached") {
558
+ if (this._platform._config.registrationMode === "attached") {
557
559
  const onClose = this._onClose(pluvWs).bind(this);
558
560
  const onMessage = this._onMessage(pluvWs).bind(this);
559
561
  pluvWs.addEventListener("close", onClose);
@@ -590,13 +592,7 @@ var IORoom = class {
590
592
  this._sessions.delete(pluvWs.sessionId);
591
593
  });
592
594
  const promises = quitters.map((quitter) => __async(this, null, function* () {
593
- yield this._broadcast({
594
- message: {
595
- type: "$EXIT",
596
- data: { sessionId: quitter.sessionId }
597
- },
598
- senderId: quitter.sessionId
599
- });
595
+ yield this._exitWebsocket(quitter);
600
596
  }));
601
597
  yield Promise.all(promises);
602
598
  });
@@ -624,7 +620,7 @@ var IORoom = class {
624
620
  });
625
621
  }
626
622
  _ensureDetached() {
627
- if (this._platform._registrationMode === "detached") return;
623
+ if (this._platform._config.registrationMode === "detached") return;
628
624
  throw new Error("Platform must use detached mode");
629
625
  }
630
626
  _exitWebsocket(webSocket) {
@@ -669,6 +665,7 @@ var IORoom = class {
669
665
  const ioAuthorize = this._getIOAuthorize(options);
670
666
  if (!ioAuthorize) return null;
671
667
  if (!token) return null;
668
+ if (!ioAuthorize.secret) throw new Error("`authorize` was specified without a valid secret");
672
669
  const payload = yield authorize({
673
670
  platform: this._platform,
674
671
  secret: ioAuthorize.secret
@@ -795,13 +792,7 @@ var IORoom = class {
795
792
  this._logDebug(`${import_kleur.default.blue(`Unregistering connection for room ${this.id}:`)} ${webSocket.sessionId}`);
796
793
  this._sessions.delete(webSocket.sessionId);
797
794
  this._platform.persistence.deleteUser(this.id, webSocket.sessionId).finally(() => __async(this, null, function* () {
798
- yield this._broadcast({
799
- message: {
800
- type: "$EXIT",
801
- data: { sessionId: webSocket.sessionId }
802
- },
803
- senderId: webSocket.sessionId
804
- });
795
+ yield this._exitWebsocket(webSocket);
805
796
  const size = this.getSize();
806
797
  this._logDebug(`${import_kleur.default.blue(`Unregistered connection for room ${this.id}:`)} ${webSocket.sessionId}`);
807
798
  this._logDebug(`${import_kleur.default.blue(`Room ${this.id} size:`)} ${size}`);
@@ -1002,7 +993,7 @@ var IORoom = class {
1002
993
  };
1003
994
 
1004
995
  // src/version.generated.ts
1005
- var version = "0.33.0";
996
+ var version = "0.34.1";
1006
997
 
1007
998
  // src/PluvServer.ts
1008
999
  var PluvServer = class {
@@ -1106,14 +1097,11 @@ var PluvServer = class {
1106
1097
  crdt = import_crdt2.noop,
1107
1098
  debug = false,
1108
1099
  getInitialStorage,
1109
- onRoomDeleted,
1110
- onRoomMessage,
1111
- onStorageUpdated,
1112
- onUserConnected,
1113
- onUserDisconnected,
1114
1100
  platform,
1115
1101
  router = new PluvRouter({})
1116
1102
  } = options;
1103
+ const { onRoomDeleted, onRoomMessage, onStorageUpdated, onUserConnected, onUserDisconnected } = options;
1104
+ platform.validateConfig(options);
1117
1105
  this._crdt = crdt;
1118
1106
  this._debug = debug;
1119
1107
  this._platform = platform;
@@ -1129,6 +1117,10 @@ var PluvServer = class {
1129
1117
  onUserDisconnected: (event) => onUserDisconnected == null ? void 0 : onUserDisconnected(event)
1130
1118
  };
1131
1119
  }
1120
+ get fetch() {
1121
+ if (!this._platform._fetch) throw new Error(`\`${this._platform._name}\` does not support \`fetch\``);
1122
+ return this._platform._fetch;
1123
+ }
1132
1124
  /**
1133
1125
  * @ignore
1134
1126
  * @readonly
@@ -1148,6 +1140,9 @@ var PluvServer = class {
1148
1140
  createRoom(room, ...options) {
1149
1141
  var _a, _c;
1150
1142
  const _b = (_a = options[0]) != null ? _a : {}, { _meta, debug, onDestroy, onMessage } = _b, platformRoomContext = __objRest(_b, ["_meta", "debug", "onDestroy", "onMessage"]);
1143
+ if (this._platform._config.handleMode !== "io") {
1144
+ throw new Error(`\`createRoom' is unsupported for \`${this._platform._name}\``);
1145
+ }
1151
1146
  if (!/^[a-z0-9]+[a-z0-9\-_]+[a-z0-9]+$/i.test(room)) throw new Error("Unsupported room name");
1152
1147
  const roomContext = platformRoomContext;
1153
1148
  const context = typeof this._context === "function" ? this._context(roomContext) : this._context;
@@ -1182,17 +1177,23 @@ var PluvServer = class {
1182
1177
  }
1183
1178
  createToken(params) {
1184
1179
  return __async(this, null, function* () {
1180
+ var _a;
1185
1181
  if (!this._authorize) {
1186
1182
  throw new Error("IO does not specify authorize during initialization.");
1187
1183
  }
1188
- const ioAuthorize = typeof this._authorize === "function" ? this._authorize(params) : this._authorize;
1189
- const secret = ioAuthorize.secret;
1190
- return yield authorize({
1191
- platform: this._platform,
1192
- secret
1193
- }).encode(params);
1184
+ if (this._platform._createToken) return yield this._platform._createToken(params);
1185
+ const ioAuthorize = this._getIOAuthorize(params);
1186
+ const secret = (_a = ioAuthorize == null ? void 0 : ioAuthorize.secret) != null ? _a : null;
1187
+ if (!secret) throw new Error("`authorize` was specified without a valid secret");
1188
+ return yield authorize({ platform: this._platform, secret }).encode(params);
1194
1189
  });
1195
1190
  }
1191
+ _getIOAuthorize(options) {
1192
+ if (typeof this._authorize === "function") {
1193
+ return this._authorize(options);
1194
+ }
1195
+ return this._authorize;
1196
+ }
1196
1197
  _getListeners() {
1197
1198
  return this._listeners;
1198
1199
  }
@@ -1219,13 +1220,12 @@ var PluvIO = class {
1219
1220
  }
1220
1221
  createToken(params) {
1221
1222
  return __async(this, null, function* () {
1223
+ var _a;
1222
1224
  if (!this._authorize) throw new Error("IO does not specify authorize during initialization.");
1223
- const ioAuthorize = typeof this._authorize === "function" ? this._authorize(params) : this._authorize;
1224
- const secret = ioAuthorize.secret;
1225
- return yield authorize({
1226
- platform: this._platform,
1227
- secret
1228
- }).encode(params);
1225
+ const ioAuthorize = this._getIOAuthorize(params);
1226
+ const secret = (_a = ioAuthorize == null ? void 0 : ioAuthorize.secret) != null ? _a : null;
1227
+ if (!secret) throw new Error("`authorize` was specified without a valid secret");
1228
+ return yield authorize({ platform: this._platform, secret }).encode(params);
1229
1229
  });
1230
1230
  }
1231
1231
  mergeRouters(...routers) {
@@ -1244,6 +1244,12 @@ var PluvIO = class {
1244
1244
  platform: this._platform
1245
1245
  }));
1246
1246
  }
1247
+ _getIOAuthorize(options) {
1248
+ if (typeof this._authorize === "function") {
1249
+ return this._authorize(options);
1250
+ }
1251
+ return this._authorize;
1252
+ }
1247
1253
  };
1248
1254
 
1249
1255
  // src/createIO.ts