@pluv/client 0.26.0 → 0.27.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.
@@ -1,18 +1,18 @@
1
1
 
2
- > @pluv/client@0.26.0 build /home/runner/work/pluv/pluv/packages/client
2
+ > @pluv/client@0.27.0 build /home/runner/work/pluv/pluv/packages/client
3
3
  > tsup src/index.ts --format esm,cjs --dts
4
4
 
5
5
  CLI Building entry: src/index.ts
6
6
  CLI Using tsconfig: tsconfig.json
7
- CLI tsup v8.2.4
7
+ CLI tsup v8.3.0
8
8
  CLI Target: es6
9
9
  ESM Build start
10
10
  CJS Build start
11
- ESM dist/index.mjs 42.38 KB
12
- ESM ⚡️ Build success in 133ms
13
- CJS dist/index.js 43.65 KB
14
- CJS ⚡️ Build success in 134ms
11
+ CJS dist/index.js 47.68 KB
12
+ CJS ⚡️ Build success in 129ms
13
+ ESM dist/index.mjs 46.42 KB
14
+ ESM ⚡️ Build success in 130ms
15
15
  DTS Build start
16
- DTS ⚡️ Build success in 3009ms
17
- DTS dist/index.d.mts 15.43 KB
18
- DTS dist/index.d.ts 15.43 KB
16
+ DTS ⚡️ Build success in 3681ms
17
+ DTS dist/index.d.mts 21.97 KB
18
+ DTS dist/index.d.ts 21.97 KB
package/CHANGELOG.md CHANGED
@@ -1,5 +1,130 @@
1
1
  # @pluv/client
2
2
 
3
+ ## 0.27.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 19ed36c: **BREAKNG**
8
+
9
+ Updated `createClient` and `PluvClient.createRoom` object params to better support automatic type inference.
10
+
11
+ ```ts
12
+ // Before
13
+ import { createClient } from "@pluv/client";
14
+ import { yjs } from "@pluv/crdt-yjs";
15
+ import { z } from "zod";
16
+ import type { ioServer } from "./server/ioServer";
17
+
18
+ const client = createClient<typeof ioServer>({
19
+ authEndpoint: ({ room }) => "MY_AUTH_URL",
20
+ wsEndpoint: ({ room }) => "MY_WEBSOCKET_URL",
21
+ });
22
+
23
+ client.createRoom("my-example-room", {
24
+ presence: z.object({
25
+ selectionId: z.string().nullish(),
26
+ }),
27
+ initialPresence: {
28
+ selectionId: null,
29
+ },
30
+ initialStorage: yjs.doc(() => ({
31
+ messages: yjs.array<string>([]),
32
+ })),
33
+ });
34
+
35
+ // After
36
+ const client = createClient({
37
+ authEndpoint: ({ room }) => "MY_AUTH_URL",
38
+ wsEndpoint: ({ room }) => "MY_WEBSOCKET_URL",
39
+ /**
40
+ * @description The ioServer type now needs to be inferred on this property
41
+ * instead of within the generic on `createClient`. This is because of
42
+ * limitations with TypeScript not yet supporting partial type-inference
43
+ * for generics. Ensure to no-loonger include any generics on `createClient`
44
+ */
45
+ infer: (i) => ({ io: i<typeof ioServer> }),
46
+ // Now moved to `createClient` from `PluvClient.createRoom`
47
+ presence: z.object({
48
+ selectionId: z.string().nullish(),
49
+ }),
50
+ /**
51
+ * @description Now added to `createClient` to specify defaults for all
52
+ * rooms, and to infer types for storage. This value will be overwritten by
53
+ * `PluvClient.createRoom`.
54
+ */
55
+ initialStorage: yjs.doc(() => ({
56
+ messages: yjs.array<string>([]),
57
+ })),
58
+ });
59
+
60
+ const room = client.createRoom("my-example-room", {
61
+ initialPresence: {
62
+ selectionId: null,
63
+ },
64
+ initialStorage: yjs.doc(() => ({
65
+ messages: yjs.array<string>([]),
66
+ })),
67
+ });
68
+ ```
69
+
70
+ ### Patch Changes
71
+
72
+ - 19ed36c: Added client-side event router. This more-or-less mirrors the server-side event router. You can use both the server-side and client-side router simultaneously, but you should generally prefer only using one or the other.
73
+
74
+ ```ts
75
+ // Backend Server
76
+ import { createIO } from "@pluv/io";
77
+
78
+ const io = createIO({
79
+ /* ... */
80
+ });
81
+ const ioServer = io.server({
82
+ router: io.router({
83
+ multiply2: io.procedure
84
+ .input(z.object({ value: z.number() }))
85
+ .broadcast(({ value }) => ({
86
+ multiplied2: { value: value * 2 },
87
+ })),
88
+ }),
89
+ });
90
+
91
+ // Frontend Client
92
+ import { createClient } from "@pluv/client";
93
+
94
+ const io = createClient({
95
+ /* ... */
96
+ });
97
+
98
+ const room = io.createRoom("my-example-room", {
99
+ // ...
100
+ router: io.router({
101
+ add5: io.procedure
102
+ .input(z.object({ value: z.number() }))
103
+ .broadcast(({ value }) => ({
104
+ /**
105
+ * @description Because `ioServer` does not specify `added5`,
106
+ * this will be forwarded to connected peers.
107
+ */
108
+ added5: { value: value + 5 },
109
+ })),
110
+ /**
111
+ * @description This is possible, but not recommended to do. Because
112
+ * `multiply2` is a procedure on `ioServer`, this will trigger the
113
+ * `multiply2` procedure on `ioServer`. Connected peers will not
114
+ * receive `multiply2`, but rather `multipled2`.
115
+ */
116
+ subtract5Multiply2: io.procedure
117
+ .input(z.object({ value: z.number() }))
118
+ .broadcast(({ value }) => ({
119
+ multiply2: { value: value - 5 },
120
+ })),
121
+ }),
122
+ });
123
+ ```
124
+
125
+ - @pluv/crdt@0.27.0
126
+ - @pluv/types@0.27.0
127
+
3
128
  ## 0.26.0
4
129
 
5
130
  ### Minor Changes
package/dist/index.d.mts CHANGED
@@ -1,16 +1,12 @@
1
1
  import { CrdtType, AbstractCrdtDoc, InferCrdtJson, AbstractCrdtDocFactory } from '@pluv/crdt';
2
2
  export { CrdtType, InferCrdtJson } from '@pluv/crdt';
3
3
  import * as _pluv_types from '@pluv/types';
4
- import { IOLike, InferIOOutput, Id, IOEventMessage, JsonObject, InferIOAuthorizeUser, InferIOAuthorize, InferIOInput, InputZodLike, InferIOAuthorizeRequired } from '@pluv/types';
4
+ import { IOLike, InferIOOutput, Id, IOEventMessage, JsonObject, InferIOAuthorizeUser, InferIOAuthorize, EventRecord, MaybePromise, InputZodLike, ProcedureLike, IORouterLike, InferIOInput, InferIOAuthorizeRequired } from '@pluv/types';
5
5
  export { BaseUser, EventMessage, EventRecord, IOEventMessage } from '@pluv/types';
6
6
  import { Subject } from 'wonka';
7
7
 
8
8
  type EventNotifierSubscriptionCallback<TIO extends IOLike, TEvent extends keyof InferIOOutput<TIO>> = (value: Id<IOEventMessage<TIO, TEvent>>) => void;
9
9
 
10
- interface AuthorizationState<TIO extends IOLike> {
11
- token: string | null;
12
- user: InferIOAuthorizeUser<InferIOAuthorize<TIO>> | null;
13
- }
14
10
  declare enum ConnectionState {
15
11
  Closed = "Closed",
16
12
  Connecting = "Connecting",
@@ -18,6 +14,24 @@ declare enum ConnectionState {
18
14
  Unavailable = "Unavailable",
19
15
  Untouched = "Untouched"
20
16
  }
17
+
18
+ interface AuthorizationState<TIO extends IOLike> {
19
+ token: string | null;
20
+ user: InferIOAuthorizeUser<InferIOAuthorize<TIO>> | null;
21
+ }
22
+ type EventResolver<TIO extends IOLike = IOLike, TInput extends JsonObject = {}, TOutput extends EventRecord<string, any> = {}, TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}> = (data: TInput, context: EventResolverContext<TIO, TPresence, TStorage>) => MaybePromise<TOutput | void>;
23
+ interface EventResolverContext<TIO extends IOLike = IOLike, TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}> {
24
+ doc: AbstractCrdtDoc<TStorage>;
25
+ others: readonly UserInfo<TIO, TPresence>[];
26
+ room: string;
27
+ user: UserInfo<TIO, TPresence>;
28
+ }
29
+ type MergeEventRecords<TEventRecords extends EventRecord<string, any>[], TRoot extends EventRecord<string, any> = {}> = TEventRecords extends [
30
+ infer IHead extends EventRecord<string, any>,
31
+ ...infer ITail extends EventRecord<string, any>[]
32
+ ] ? MergeEventRecords<ITail, Omit<TRoot, keyof IHead> & {
33
+ [P in keyof IHead]: TRoot extends Record<P, any> ? TRoot[P] | IHead[P] : IHead[P];
34
+ }> : Id<TRoot>;
21
35
  type UpdateMyPresenceAction<TPresence extends JsonObject> = Partial<TPresence> | ((oldPresence: TPresence | null) => Partial<TPresence>);
22
36
  interface UserInfo<TIO extends IOLike, TPresence extends JsonObject = {}> {
23
37
  connectionId: string;
@@ -37,6 +51,40 @@ interface WebSocketState<TIO extends IOLike> {
37
51
 
38
52
  type OtherNotifierSubscriptionCallback<TIO extends IOLike> = (value: Id<UserInfo<TIO>> | null) => void;
39
53
 
54
+ interface PluvProcedureConfig<TIO extends IOLike = IOLike, TInput extends JsonObject = {}, TOutput extends EventRecord<string, any> = {}, TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}> {
55
+ broadcast?: EventResolver<TIO, TInput, TOutput, TPresence, TStorage> | null;
56
+ input?: InputZodLike<TInput>;
57
+ }
58
+ declare class PluvProcedure<TIO extends IOLike = IOLike, TInput extends JsonObject = {}, TOutput extends EventRecord<string, any> = {}, TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}, TFilled extends "input" | "broadcast" | "" = ""> {
59
+ private _broadcast;
60
+ private _input;
61
+ get config(): ProcedureLike<TInput, TOutput>["config"];
62
+ constructor(config?: PluvProcedureConfig<TIO, TInput, TOutput, TPresence, TStorage>);
63
+ broadcast<TResult extends EventRecord<string, any> = {}>(resolver: EventResolver<TIO, TInput, TResult, TPresence, TStorage>): Omit<PluvProcedure<TIO, TInput, MergeEventRecords<[TOutput, TResult]>, TPresence, TStorage, TFilled | "input" | "broadcast">, TFilled | "input" | "broadcast">;
64
+ input<TData extends JsonObject>(input: InputZodLike<TData>): Omit<PluvProcedure<TIO, TData, {}, TPresence, TStorage, TFilled | "input">, TFilled | "input">;
65
+ private _resolver;
66
+ }
67
+
68
+ type PluvRouterEventConfig<TIO extends IOLike = IOLike, TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}> = {
69
+ [P: string]: Pick<PluvProcedure<TIO, any, any, TPresence, TStorage>, "config">;
70
+ };
71
+ type MergedRouter<TRouters extends PluvRouter<TIO, TPresence, TStorage, any>[] = [], TIO extends IOLike = IOLike, TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}, TRoot extends TRouters[0]["_defs"]["events"] = {}> = TRouters extends [
72
+ infer IHead extends PluvRouter<TIO, TPresence, TStorage, any>,
73
+ ...infer ITail extends PluvRouter<TIO, TPresence, TStorage, any>[]
74
+ ] ? MergedRouter<ITail, TIO, TPresence, TStorage, TRoot & IHead["_defs"]["events"]> : PluvRouter<TIO, TPresence, TStorage, TRoot>;
75
+ type MergeEvents<TClientEvents extends PluvRouterEventConfig<any, any, any>, TServerIO extends IOLike<any, any>> = TServerIO extends IOLike<infer IAuthorize, infer IServerEvents> ? IOLike<IAuthorize, {
76
+ [P in keyof TClientEvents]: TClientEvents[P] extends ProcedureLike<infer IClientInput, infer IClientOutput> ? {
77
+ [K in keyof IClientOutput]: K extends keyof IServerEvents ? IServerEvents[K] : ProcedureLike<IClientInput, Id<Pick<IClientOutput, K>>>;
78
+ }[keyof IClientOutput] : never;
79
+ } & IServerEvents> : never;
80
+ declare class PluvRouter<TIO extends IOLike = IOLike, TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}, TEvents extends PluvRouterEventConfig<TIO, TPresence, TStorage> = {}> implements IORouterLike<TEvents> {
81
+ readonly _defs: {
82
+ events: TEvents;
83
+ };
84
+ constructor(events: TEvents);
85
+ static merge<TRouters extends PluvRouter<any, any, any, any>[]>(...routers: TRouters): MergedRouter<TRouters>;
86
+ }
87
+
40
88
  interface StateNotifierSubjects<TIO extends IOLike, TPresence extends JsonObject> {
41
89
  connection: Subject<Id<WebSocketState<TIO>>>;
42
90
  "my-presence": Subject<TPresence | null>;
@@ -47,15 +95,15 @@ interface StateNotifierSubjects<TIO extends IOLike, TPresence extends JsonObject
47
95
  type InferSubjectValue<TIO extends IOLike, TPresence extends JsonObject, TSubject extends keyof StateNotifierSubjects<TIO, TPresence>> = StateNotifierSubjects<TIO, TPresence>[TSubject] extends Subject<infer IValue> ? Id<IValue> : never;
48
96
  type SubscriptionCallback<TIO extends IOLike, TPresence extends JsonObject, TSubject extends keyof StateNotifierSubjects<TIO, TPresence>> = (value: InferSubjectValue<TIO, TPresence, TSubject>) => void;
49
97
 
50
- declare abstract class AbstractRoom<TIO extends IOLike, TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}> {
98
+ declare abstract class AbstractRoom<TIO extends IOLike, TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}, TEvents extends PluvRouterEventConfig<TIO, TPresence, TStorage> = {}> {
51
99
  readonly id: string;
52
100
  constructor(room: string);
53
101
  abstract storageLoaded: boolean;
54
- abstract broadcast<TEvent extends keyof InferIOInput<TIO>>(event: TEvent, data: Id<InferIOInput<TIO>[TEvent]>): void;
102
+ abstract broadcast<TEvent extends keyof InferIOInput<MergeEvents<TEvents, TIO>>>(event: TEvent, data: Id<InferIOInput<MergeEvents<TEvents, TIO>>[TEvent]>): void;
55
103
  abstract canRedo(): boolean;
56
104
  abstract canUndo(): boolean;
57
105
  abstract getDoc(): AbstractCrdtDoc<TStorage>;
58
- abstract event<TEvent extends keyof InferIOOutput<TIO>>(event: TEvent, callback: EventNotifierSubscriptionCallback<TIO, TEvent>): () => void;
106
+ abstract event<TEvent extends keyof InferIOOutput<MergeEvents<TEvents, TIO>>>(event: TEvent, callback: EventNotifierSubscriptionCallback<MergeEvents<TEvents, TIO>, TEvent>): () => void;
59
107
  abstract getConnection(): WebSocketConnection;
60
108
  abstract getMyPresence(): TPresence;
61
109
  abstract getMyself(): Id<UserInfo<TIO, TPresence>> | null;
@@ -132,17 +180,17 @@ type PluvRoomDebug<TIO extends IOLike> = Id<{
132
180
  output: readonly (keyof InferIOOutput<TIO>)[];
133
181
  input: readonly (keyof InferIOInput<TIO>)[];
134
182
  }>;
135
- type PluvRoomOptions<TIO extends IOLike, TMetadata extends JsonObject = {}, TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}> = {
183
+ type RoomConfig<TIO extends IOLike, TMetadata extends JsonObject = {}, TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}, TEvents extends PluvRouterEventConfig<TIO, TPresence, TStorage> = {}> = Id<{
136
184
  addons?: readonly PluvRoomAddon<TIO, TMetadata, TPresence, TStorage>[];
137
185
  debug?: boolean | PluvRoomDebug<TIO>;
138
186
  onAuthorizationFail?: (error: Error) => void;
139
- } & Omit<CrdtManagerOptions<TStorage>, "encodedState"> & UsersManagerConfig<TPresence> & (keyof TMetadata extends never ? {
187
+ router?: PluvRouter<TIO, TPresence, TStorage, TEvents>;
188
+ } & RoomEndpoints<TIO, TMetadata> & Pick<CrdtManagerOptions<TStorage>, "initialStorage"> & UsersManagerConfig<TPresence> & (keyof TMetadata extends never ? {
140
189
  metadata?: undefined;
141
190
  } : {
142
191
  metadata: TMetadata;
143
- });
144
- type RoomConfig<TIO extends IOLike, TMetadata extends JsonObject = {}, TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}> = RoomEndpoints<TIO, TMetadata> & PluvRoomOptions<TIO, TMetadata, TPresence, TStorage>;
145
- declare class PluvRoom<TIO extends IOLike, TMetadata extends JsonObject = {}, TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}> extends AbstractRoom<TIO, TPresence, TStorage> {
192
+ })>;
193
+ declare class PluvRoom<TIO extends IOLike, TMetadata extends JsonObject = {}, TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}, TEvents extends PluvRouterEventConfig<TIO, TPresence, TStorage> = {}> extends AbstractRoom<TIO, TPresence, TStorage> {
146
194
  readonly _endpoints: RoomEndpoints<TIO, TMetadata>;
147
195
  private _crdtManager;
148
196
  private _crdtNotifier;
@@ -152,6 +200,7 @@ declare class PluvRoom<TIO extends IOLike, TMetadata extends JsonObject = {}, TP
152
200
  private _listeners;
153
201
  private _metadata;
154
202
  private _otherNotifier;
203
+ private _router;
155
204
  private _state;
156
205
  private _stateNotifier;
157
206
  private _storageStore;
@@ -160,15 +209,15 @@ declare class PluvRoom<TIO extends IOLike, TMetadata extends JsonObject = {}, TP
160
209
  private _windowListeners;
161
210
  private _wsListeners;
162
211
  private _usersManager;
163
- constructor(room: string, options: RoomConfig<TIO, TMetadata, TPresence, TStorage>);
212
+ constructor(room: string, options: RoomConfig<TIO, TMetadata, TPresence, TStorage, TEvents>);
164
213
  get storageLoaded(): boolean;
165
214
  get webSocket(): WebSocket | null;
166
- broadcast: (<TEvent extends keyof InferIOInput<TIO>>(event: TEvent, data: Id<InferIOInput<TIO>[TEvent]>) => void) & { [event in keyof InferIOInput<TIO>]: (data: Id<InferIOInput<TIO>[event]>) => void; };
215
+ broadcast: (<TEvent extends keyof InferIOInput<MergeEvents<TEvents, TIO>>>(event: TEvent, data: Id<InferIOInput<MergeEvents<TEvents, TIO>>[TEvent]>) => Promise<void>) & { [event in keyof InferIOInput<TIO>]: (data: Id<InferIOInput<TIO>[event]>) => Promise<void>; };
167
216
  canRedo: () => boolean;
168
217
  canUndo: () => boolean;
169
218
  connect(): Promise<void>;
170
219
  disconnect(): Promise<void>;
171
- event: (<TEvent extends keyof InferIOOutput<TIO>>(event: TEvent, callback: EventNotifierSubscriptionCallback<TIO, TEvent>) => () => void) & { [event in keyof InferIOOutput<TIO>]: (callback: EventNotifierSubscriptionCallback<TIO, event>) => () => void; };
220
+ event: (<TEvent extends keyof InferIOOutput<MergeEvents<TEvents, TIO>>>(event: TEvent, callback: EventNotifierSubscriptionCallback<MergeEvents<TEvents, TIO>, TEvent>) => () => void) & { [event in keyof InferIOOutput<MergeEvents<TEvents, TIO>>]: (callback: EventNotifierSubscriptionCallback<MergeEvents<TEvents, TIO>, any>) => () => void; };
172
221
  getConnection: () => WebSocketConnection;
173
222
  getDoc: () => AbstractCrdtDoc<TStorage>;
174
223
  getMyPresence: () => TPresence;
@@ -237,47 +286,74 @@ declare class PluvRoom<TIO extends IOLike, TMetadata extends JsonObject = {}, TP
237
286
  private _updateState;
238
287
  }
239
288
 
240
- type PluvClientOptions<TIO extends IOLike, TMetadata extends JsonObject> = RoomEndpoints<TIO, TMetadata> & {
289
+ declare const identity: <T extends unknown>(x: T) => T;
290
+
291
+ type InferCallback<TIO extends IOLike> = (i: typeof identity) => {
292
+ io: (io: TIO) => TIO;
293
+ };
294
+ type PluvClientOptions<TIO extends IOLike, TPresence extends JsonObject, TStorage extends Record<string, CrdtType<any, any>>, TMetadata extends JsonObject> = RoomEndpoints<TIO, TMetadata> & {
241
295
  debug?: boolean;
296
+ infer: InferCallback<TIO>;
297
+ initialStorage?: AbstractCrdtDocFactory<TStorage>;
298
+ metadata?: InputZodLike<TMetadata>;
299
+ presence?: InputZodLike<TPresence>;
242
300
  };
243
- declare class PluvClient<TIO extends IOLike = IOLike, TMetadata extends JsonObject = {}> {
301
+ type CreateRoomOptions<TIO extends IOLike, TPresence extends JsonObject, TStorage extends Record<string, CrdtType<any, any>>, TMetadata extends JsonObject, TEvents extends PluvRouterEventConfig<TIO, TPresence, TStorage> = {}> = {
302
+ addons?: readonly PluvRoomAddon<TIO, TMetadata, TPresence, TStorage>[];
303
+ debug?: boolean | PluvRoomDebug<TIO>;
304
+ initialPresence?: TPresence;
305
+ initialStorage?: AbstractCrdtDocFactory<TStorage>;
306
+ onAuthorizationFail?: (error: Error) => void;
307
+ router?: PluvRouter<TIO, TPresence, TStorage, TEvents>;
308
+ } & (keyof TMetadata extends never ? {
309
+ metadata?: undefined;
310
+ } : {
311
+ metadata: TMetadata;
312
+ });
313
+ declare class PluvClient<TIO extends IOLike = IOLike, TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}, TMetadata extends JsonObject = {}> {
244
314
  private _authEndpoint;
245
315
  private _debug;
316
+ private _initialStorage?;
317
+ private _presence?;
246
318
  private _wsEndpoint;
247
319
  private _rooms;
248
- constructor(options: PluvClientOptions<TIO, TMetadata>);
249
- createRoom: <TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}>(room: string, options: PluvRoomOptions<TIO, TMetadata, TPresence, TStorage>) => PluvRoom<TIO, TMetadata, TPresence, TStorage>;
250
- enter: (room: string | PluvRoom<TIO, any, any, any>) => Promise<PluvRoom<TIO, TMetadata, JsonObject, any>>;
251
- getRoom: <TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}>(room: string) => PluvRoom<TIO, TMetadata, TPresence, TStorage> | null;
252
- getRooms: () => readonly PluvRoom<TIO, TMetadata, JsonObject, any>[];
320
+ get procedure(): PluvProcedure<TIO, {}, {}, TPresence, TStorage>;
321
+ constructor(options: PluvClientOptions<TIO, TPresence, TStorage, TMetadata>);
322
+ createRoom: <TEvents extends PluvRouterEventConfig<TIO, TPresence, TStorage> = {}>(room: string, options: CreateRoomOptions<TIO, TPresence, TStorage, TMetadata, TEvents>) => PluvRoom<TIO, TMetadata, TPresence, TStorage>;
323
+ enter: (room: string | PluvRoom<TIO, any, any, any>) => Promise<PluvRoom<TIO, TMetadata, TPresence, TStorage, any>>;
324
+ getRoom: (room: string) => PluvRoom<TIO, TMetadata, TPresence, TStorage, any> | null;
325
+ getRooms: () => readonly PluvRoom<TIO, TMetadata, TPresence, TStorage, any>[];
253
326
  leave: (room: string | PluvRoom<TIO, any, any, any>) => Promise<void>;
327
+ router<TEvents extends PluvRouterEventConfig<TIO, TPresence, TStorage> = {}>(events: TEvents): PluvRouter<TIO, TPresence, TStorage, TEvents>;
254
328
  private _logDebug;
255
329
  }
256
330
 
257
- declare const createClient: <TIO extends IOLike = IOLike<_pluv_types.IOAuthorize<any, any, any>, {}>, TMetadata extends JsonObject = {}>(options: PluvClientOptions<TIO, TMetadata>) => PluvClient<TIO, TMetadata>;
331
+ declare const createClient: <TIO extends IOLike = IOLike<_pluv_types.IOAuthorize<any, any, any>, {}>, TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}, TMetadata extends JsonObject = {}>(options: PluvClientOptions<TIO, TPresence, TStorage, TMetadata>) => PluvClient<TIO, TPresence, TStorage, TMetadata>;
258
332
 
259
333
  type MockedRoomEvents<TIO extends IOLike> = Partial<{
260
334
  [P in keyof InferIOInput<TIO>]: (data: Id<InferIOInput<TIO>[P]>) => Partial<InferIOOutput<TIO>>;
261
335
  }>;
262
- type MockedRoomConfig<TIO extends IOLike, TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}> = {
263
- events?: MockedRoomEvents<TIO>;
264
- } & Omit<CrdtManagerOptions<TStorage>, "encodedState"> & UsersManagerConfig<TPresence>;
265
- declare class MockedRoom<TIO extends IOLike, TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}> extends AbstractRoom<TIO, TPresence, TStorage> {
336
+ type MockedRoomConfig<TIO extends IOLike, TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}, TEvents extends PluvRouterEventConfig<TIO, TPresence, TStorage> = {}> = {
337
+ events?: MockedRoomEvents<MergeEvents<TEvents, TIO>>;
338
+ router?: PluvRouter<TIO, TPresence, TStorage, TEvents>;
339
+ } & Pick<CrdtManagerOptions<TStorage>, "initialStorage"> & UsersManagerConfig<TPresence>;
340
+ declare class MockedRoom<TIO extends IOLike, TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}, TEvents extends PluvRouterEventConfig<TIO, TPresence, TStorage> = {}> extends AbstractRoom<TIO, TPresence, TStorage> {
266
341
  private _crdtManager;
267
342
  private _crdtNotifier;
268
343
  private _eventNotifier;
269
344
  private _events?;
270
345
  private _otherNotifier;
346
+ private _router;
271
347
  private _state;
272
348
  private _stateNotifier;
273
349
  private _subscriptions;
274
350
  private _usersManager;
275
- constructor(room: string, options: MockedRoomConfig<TIO, TPresence, TStorage>);
351
+ constructor(room: string, options: MockedRoomConfig<TIO, TPresence, TStorage, TEvents>);
276
352
  get storageLoaded(): boolean;
277
- broadcast<TEvent extends keyof InferIOInput<TIO>>(event: TEvent, data: Id<InferIOInput<TIO>[TEvent]>): void;
353
+ broadcast: (<TEvent extends keyof InferIOInput<MergeEvents<TEvents, TIO>>>(event: TEvent, data: Id<InferIOInput<MergeEvents<TEvents, TIO>>[TEvent]>) => Promise<void>) & { [event in keyof InferIOInput<TIO>]: (data: Id<InferIOInput<TIO>[event]>) => Promise<void>; };
278
354
  canRedo: () => boolean;
279
355
  canUndo: () => boolean;
280
- event: <TEvent extends keyof InferIOOutput<TIO>>(event: TEvent, callback: EventNotifierSubscriptionCallback<TIO, TEvent>) => (() => void);
356
+ event: (<TEvent extends keyof InferIOOutput<MergeEvents<TEvents, TIO>>>(event: TEvent, callback: EventNotifierSubscriptionCallback<MergeEvents<TEvents, TIO>, TEvent>) => () => void) & { [event in keyof InferIOOutput<MergeEvents<TEvents, TIO>>]: (callback: EventNotifierSubscriptionCallback<MergeEvents<TEvents, TIO>, any>) => () => void; };
281
357
  getConnection: () => WebSocketConnection;
282
358
  getDoc(): AbstractCrdtDoc<TStorage>;
283
359
  getMyPresence: () => TPresence;
@@ -296,6 +372,7 @@ declare class MockedRoom<TIO extends IOLike, TPresence extends JsonObject = {},
296
372
  undo: () => void;
297
373
  updateMyPresence: (presence: UpdateMyPresenceAction<TPresence>) => void;
298
374
  private _observeCrdt;
375
+ private _simulateEvent;
299
376
  }
300
377
 
301
- export { AbstractRoom, AbstractStorageStore, ConnectionState, MockedRoom, type MockedRoomConfig, type MockedRoomEvents, PluvClient, type PluvClientOptions, PluvRoom, type PluvRoomAddon, type PluvRoomAddonInput, type PluvRoomAddonResult, type PluvRoomDebug, type PluvRoomOptions, type UserInfo, type WebSocketConnection, type WebSocketState, createClient };
378
+ export { AbstractRoom, AbstractStorageStore, ConnectionState, type CreateRoomOptions, type MergeEvents, MockedRoom, type MockedRoomConfig, type MockedRoomEvents, PluvClient, type PluvClientOptions, type PluvProcedureConfig, PluvRoom, type PluvRoomAddon, type PluvRoomAddonInput, type PluvRoomAddonResult, type PluvRoomDebug, PluvRouter, type PluvRouterEventConfig, type UserInfo, type WebSocketConnection, type WebSocketState, createClient };