@pluv/client 1.0.2 → 2.0.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,5 +1,5 @@
1
1
 
2
- > @pluv/client@1.0.2 build /home/runner/work/pluv/pluv/packages/client
2
+ > @pluv/client@2.0.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
@@ -8,11 +8,11 @@
8
8
  CLI Target: es6
9
9
  ESM Build start
10
10
  CJS Build start
11
- ESM dist/index.mjs 57.31 KB
12
- ESM ⚡️ Build success in 126ms
13
- CJS dist/index.js 58.63 KB
14
- CJS ⚡️ Build success in 126ms
11
+ ESM dist/index.mjs 57.21 KB
12
+ ESM ⚡️ Build success in 99ms
13
+ CJS dist/index.js 58.71 KB
14
+ CJS ⚡️ Build success in 100ms
15
15
  DTS Build start
16
- DTS ⚡️ Build success in 3638ms
17
- DTS dist/index.d.mts 25.31 KB
18
- DTS dist/index.d.ts 25.31 KB
16
+ DTS ⚡️ Build success in 4382ms
17
+ DTS dist/index.d.mts 21.88 KB
18
+ DTS dist/index.d.ts 21.88 KB
package/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # @pluv/client
2
2
 
3
+ ## 2.0.0
4
+
5
+ ### Patch Changes
6
+
7
+ - 047a1d8: Moved several internal types to `@pluv/types`.
8
+ - 0806212: Fix the room's id not being defined during the initialization of addons.
9
+ - 3a34dbb: Fixed `initialStorage` on `PluvClient.createRoom` not overwriting the `initialStorage` from the `PluvClient` constructor.
10
+ - Updated dependencies [047a1d8]
11
+ - @pluv/types@2.0.0
12
+ - @pluv/crdt@2.0.0
13
+
3
14
  ## 1.0.2
4
15
 
5
16
  ### Patch Changes
package/dist/index.d.mts CHANGED
@@ -1,19 +1,19 @@
1
- import { CrdtType, AbstractCrdtDocFactory, AbstractCrdtDoc, InferCrdtJson } from '@pluv/crdt';
1
+ import { CrdtType, AbstractCrdtDocFactory, NoopCrdtDocFactory, InferStorage, InferCrdtJson } from '@pluv/crdt';
2
2
  export { CrdtType, InferCrdtJson } from '@pluv/crdt';
3
- import { IOLike, InferIOOutput, Id, IOEventMessage, JsonObject, EventRecord, ProcedureLike, InputZodLike, IORouterLike, InferIOAuthorizeUser, InferIOAuthorize, BaseUser, InferIOInput, MaybePromise } from '@pluv/types';
4
- export { BaseUser, EventMessage, EventRecord, IOEventMessage } from '@pluv/types';
3
+ import { IOLike, JsonObject, EventRecord, CrdtDocLike, UserInfo, MaybePromise, Id, ConnectionState, ProcedureLike, InputZodLike, IORouterLike, WebSocketState, InferIOAuthorizeUser, InferIOAuthorize, BaseUser, RoomLike, InferIOOutput, InferIOInput, MergeEvents, EventNotifierSubscriptionCallback, OtherNotifierSubscriptionCallback, UpdateMyPresenceAction } from '@pluv/types';
4
+ export { BaseUser, ConnectionState, EventMessage, EventNotifierSubscriptionCallback, EventRecord, IOEventMessage, MergeEvents, RoomLike, UserInfo, WebSocketState } from '@pluv/types';
5
5
  import { Subject } from 'wonka';
6
6
 
7
- type EventNotifierSubscriptionCallback<TIO extends IOLike<any, any>, TEvent extends keyof InferIOOutput<TIO>> = (value: Id<IOEventMessage<TIO, TEvent>>) => void;
8
-
9
- declare const ConnectionState: {
10
- readonly Closed: "Closed";
11
- readonly Connecting: "Connecting";
12
- readonly Open: "Open";
13
- readonly Unavailable: "Unavailable";
14
- readonly Untouched: "Untouched";
15
- };
16
- type ConnectionState = (typeof ConnectionState)[keyof typeof ConnectionState];
7
+ declare abstract class AbstractStorageStore {
8
+ room: string;
9
+ constructor(room: string);
10
+ abstract addUpdate(update: string): Promise<void>;
11
+ abstract destroy(): Promise<void>;
12
+ abstract flatten(encodedState: string): Promise<void>;
13
+ abstract getShouldFlatten(): Promise<boolean>;
14
+ abstract getUpdates(start?: number): Promise<readonly string[]>;
15
+ abstract initialize(): Promise<void>;
16
+ }
17
17
 
18
18
  declare const identity: <T extends unknown>(x: T) => T;
19
19
 
@@ -22,11 +22,59 @@ type InferCallback<TIO extends IOLike<any, any>> = (i: typeof identity) => {
22
22
  };
23
23
  declare const infer: <TIO extends IOLike<any, any>>(callback: InferCallback<TIO>) => InferCallback<TIO>;
24
24
 
25
+ 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>;
26
+ interface EventResolverContext<TIO extends IOLike = IOLike, TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}> {
27
+ doc: CrdtDocLike<TStorage>;
28
+ others: readonly UserInfo<TIO, TPresence>[];
29
+ room: string;
30
+ user: UserInfo<TIO, TPresence>;
31
+ }
32
+ type InferMetadata<TClient extends PluvClient<any, any, any, any>> = TClient extends PluvClient<any, any, any, infer IMetadata> ? IMetadata : never;
33
+ type MergeEventRecords<TEventRecords extends EventRecord<string, any>[], TRoot extends EventRecord<string, any> = {}> = TEventRecords extends [
34
+ infer IHead extends EventRecord<string, any>,
35
+ ...infer ITail extends EventRecord<string, any>[]
36
+ ] ? MergeEventRecords<ITail, Omit<TRoot, keyof IHead> & {
37
+ [P in keyof IHead]: TRoot extends Record<P, any> ? TRoot[P] | IHead[P] : IHead[P];
38
+ }> : Id<TRoot>;
39
+ interface PluvClientLimits {
40
+ /**
41
+ * @description Maximum size of presence object in bytes
42
+ */
43
+ presenceMaxSize?: number | null;
44
+ }
45
+ interface PublicKeyParams<TMetadata extends JsonObject> {
46
+ metadata: TMetadata;
47
+ }
48
+ type PublicKey<TMetadata extends JsonObject> = string | ((params: PublicKeyParams<TMetadata>) => string);
49
+ interface WebSocketConnection {
50
+ /**
51
+ * @description How many times a connection attempt was made. This will increment upon each
52
+ * unsuccessful attempt, and will reset upon a successful connection.
53
+ * @date April 13, 2025
54
+ */
55
+ attempts: number;
56
+ /**
57
+ * @description How many times the user has connected to the room. This can be more than 1 in
58
+ * the case of reconnects. This is tracked because on the very first connection (i.e. when
59
+ * count is 0) we don't want to send the storage state as an update to the room and overwrite
60
+ * the upstream state.
61
+ * @date April 13, 2025
62
+ */
63
+ count: number;
64
+ id: string | null;
65
+ state: ConnectionState;
66
+ }
67
+ type WithMetadata<TMetadata extends JsonObject = {}> = keyof TMetadata extends never ? {
68
+ metadata?: undefined;
69
+ } : {
70
+ metadata: TMetadata;
71
+ };
72
+
25
73
  interface PluvProcedureConfig<TIO extends IOLike = IOLike, TInput extends JsonObject = {}, TOutput extends EventRecord<string, any> = {}, TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}> {
26
74
  broadcast?: EventResolver<TIO, TInput, TOutput, TPresence, TStorage> | null;
27
75
  input?: InputZodLike<TInput>;
28
76
  }
29
- 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" | "" = ""> {
77
+ 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" | "" = ""> implements ProcedureLike<TInput, TOutput> {
30
78
  private _broadcast;
31
79
  private _input;
32
80
  get config(): ProcedureLike<TInput, TOutput>["config"];
@@ -36,19 +84,8 @@ declare class PluvProcedure<TIO extends IOLike = IOLike, TInput extends JsonObje
36
84
  private _resolver;
37
85
  }
38
86
 
39
- declare abstract class AbstractStorageStore {
40
- room: string;
41
- constructor(room: string);
42
- abstract addUpdate(update: string): Promise<void>;
43
- abstract destroy(): Promise<void>;
44
- abstract flatten(encodedState: string): Promise<void>;
45
- abstract getShouldFlatten(): Promise<boolean>;
46
- abstract getUpdates(start?: number): Promise<readonly string[]>;
47
- abstract initialize(): Promise<void>;
48
- }
49
-
50
- type CrdtManagerOptions<TStorage extends Record<string, CrdtType<any, any>> = {}> = {
51
- initialStorage?: AbstractCrdtDocFactory<TStorage>;
87
+ type CrdtManagerOptions<TCrdt extends AbstractCrdtDocFactory<any>> = {
88
+ initialStorage?: TCrdt;
52
89
  };
53
90
 
54
91
  type PluvRouterEventConfig<TIO extends IOLike = IOLike, TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}> = {
@@ -58,11 +95,6 @@ type MergedRouter<TRouters extends PluvRouter<TIO, TPresence, TStorage, any>[] =
58
95
  infer IHead extends PluvRouter<TIO, TPresence, TStorage, any>,
59
96
  ...infer ITail extends PluvRouter<TIO, TPresence, TStorage, any>[]
60
97
  ] ? MergedRouter<ITail, TIO, TPresence, TStorage, TRoot & IHead["_defs"]["events"]> : PluvRouter<TIO, TPresence, TStorage, TRoot>;
61
- type MergeEvents<TClientEvents extends PluvRouterEventConfig<any, any, any>, TServerIO extends IOLike<any, any>> = TServerIO extends IOLike<infer IAuthorize, infer IServerEvents> ? IOLike<IAuthorize, {
62
- [P in keyof TClientEvents]: TClientEvents[P] extends ProcedureLike<infer IClientInput, infer IClientOutput> ? {
63
- [K in keyof IClientOutput]: K extends keyof IServerEvents ? IServerEvents[K] : ProcedureLike<IClientInput, Id<Pick<IClientOutput, K>>>;
64
- }[keyof IClientOutput] : never;
65
- } & IServerEvents> : never;
66
98
  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> {
67
99
  readonly _defs: {
68
100
  events: TEvents;
@@ -112,9 +144,9 @@ type RoomEndpoints<TIO extends IOLike<any, any>, TMetadata extends JsonObject> =
112
144
  } : {
113
145
  authEndpoint?: undefined;
114
146
  });
115
- type PluvRoomAddon<TIO extends IOLike = IOLike, TMetadata extends JsonObject = {}, TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}> = (input: PluvRoomAddonInput<TIO, TMetadata, TPresence, TStorage>) => Partial<PluvRoomAddonResult>;
116
- interface PluvRoomAddonInput<TIO extends IOLike = IOLike, TMetadata extends JsonObject = {}, TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}> {
117
- room: PluvRoom<TIO, TMetadata, TPresence, TStorage>;
147
+ type PluvRoomAddon<TIO extends IOLike, TMetadata extends JsonObject, TPresence extends JsonObject, TCrdt extends AbstractCrdtDocFactory<any>> = (input: PluvRoomAddonInput<TIO, TMetadata, TPresence, TCrdt>) => Partial<PluvRoomAddonResult>;
148
+ interface PluvRoomAddonInput<TIO extends IOLike, TMetadata extends JsonObject, TPresence extends JsonObject, TCrdt extends AbstractCrdtDocFactory<any>> {
149
+ room: PluvRoom<TIO, TMetadata, TPresence, TCrdt>;
118
150
  }
119
151
  interface PluvRoomAddonResult {
120
152
  storage: AbstractStorageStore;
@@ -128,18 +160,19 @@ interface ReconnectTimeoutMsParams {
128
160
  attempts: number;
129
161
  }
130
162
  type ReconnectTimeoutMs = number | ((params: ReconnectTimeoutMsParams) => number);
131
- 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<{
132
- addons?: readonly PluvRoomAddon<TIO, TMetadata, TPresence, TStorage>[];
163
+ type RoomConfig<TIO extends IOLike, TMetadata extends JsonObject, TPresence extends JsonObject, TCrdt extends AbstractCrdtDocFactory<any>, TEvents extends PluvRouterEventConfig<TIO, TPresence, InferStorage<TCrdt>>> = Id<{
164
+ addons?: readonly PluvRoomAddon<TIO, TMetadata, TPresence, TCrdt>[];
133
165
  debug?: boolean | PluvRoomDebug<TIO>;
134
166
  limits: PluvClientLimits;
135
167
  onAuthorizationFail?: (error: Error) => void;
136
168
  metadata?: InputZodLike<TMetadata>;
137
169
  publicKey?: PublicKey<TMetadata>;
138
170
  reconnectTimeoutMs?: ReconnectTimeoutMs;
139
- router?: PluvRouter<TIO, TPresence, TStorage, TEvents>;
140
- } & RoomEndpoints<TIO, TMetadata> & Pick<CrdtManagerOptions<TStorage>, "initialStorage"> & UsersManagerConfig<TPresence>>;
141
- declare class PluvRoom<TIO extends IOLike<any, any>, TMetadata extends JsonObject = {}, TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}, TEvents extends PluvRouterEventConfig<TIO, TPresence, TStorage> = {}> extends AbstractRoom<TIO, TPresence, TStorage> {
171
+ router?: PluvRouter<TIO, TPresence, InferStorage<TCrdt>, TEvents>;
172
+ } & RoomEndpoints<TIO, TMetadata> & Pick<CrdtManagerOptions<TCrdt>, "initialStorage"> & UsersManagerConfig<TPresence>>;
173
+ declare class PluvRoom<TIO extends IOLike<any, any>, TMetadata extends JsonObject = {}, TPresence extends JsonObject = {}, TCrdt extends AbstractCrdtDocFactory<any> = NoopCrdtDocFactory, TEvents extends PluvRouterEventConfig<TIO, TPresence, InferStorage<TCrdt>> = {}> implements RoomLike<TIO, TPresence, InferStorage<TCrdt>> {
142
174
  readonly _endpoints: RoomEndpoints<TIO, TMetadata>;
175
+ readonly id: string;
143
176
  readonly metadata?: InputZodLike<TMetadata>;
144
177
  private readonly _crdtManager;
145
178
  private readonly _crdtNotifier;
@@ -161,7 +194,7 @@ declare class PluvRoom<TIO extends IOLike<any, any>, TMetadata extends JsonObjec
161
194
  private _state;
162
195
  private _windowListeners;
163
196
  private _wsListeners;
164
- constructor(room: string, options: RoomConfig<TIO, TMetadata, TPresence, TStorage, TEvents>);
197
+ constructor(room: string, options: RoomConfig<TIO, TMetadata, TPresence, TCrdt, TEvents>);
165
198
  get storageLoaded(): boolean;
166
199
  get webSocket(): WebSocket | null;
167
200
  broadcast: (<TEvent extends keyof InferIOInput<MergeEvents<TEvents, TIO>>>(event: TEvent, data: Id<InferIOInput<MergeEvents<TEvents, TIO>>[TEvent]>) => Promise<void>) & { [PEvent in keyof InferIOInput<MergeEvents<TEvents, TIO>>]: (data: Id<InferIOInput<MergeEvents<TEvents, TIO>>[PEvent]>) => Promise<void>; };
@@ -171,20 +204,20 @@ declare class PluvRoom<TIO extends IOLike<any, any>, TMetadata extends JsonObjec
171
204
  disconnect(): Promise<void>;
172
205
  event: (<TEvent extends keyof InferIOOutput<MergeEvents<TEvents, TIO>>>(event: TEvent, callback: EventNotifierSubscriptionCallback<MergeEvents<TEvents, TIO>, TEvent>) => () => void) & { [PEvent in keyof InferIOOutput<MergeEvents<TEvents, TIO>>]: (callback: EventNotifierSubscriptionCallback<MergeEvents<TEvents, TIO>, PEvent>) => () => void; };
173
206
  getConnection: () => WebSocketConnection;
174
- getDoc: () => AbstractCrdtDoc<TStorage>;
207
+ getDoc: () => CrdtDocLike<InferStorage<TCrdt>>;
175
208
  getMyPresence: () => TPresence;
176
209
  getMyself: () => Id<UserInfo<TIO, TPresence>> | null;
177
210
  getOther: (connectionId: string) => Id<UserInfo<TIO, TPresence>> | null;
178
211
  getOthers: () => readonly Id<UserInfo<TIO, TPresence>>[];
179
- getStorage: <TKey extends keyof TStorage>(type: TKey) => TStorage[TKey] | null;
180
- getStorageJson(): InferCrdtJson<TStorage> | null;
181
- getStorageJson<TKey extends keyof TStorage>(type: TKey): InferCrdtJson<TStorage[TKey]> | null;
212
+ getStorage: <TKey extends keyof InferStorage<TCrdt>>(type: TKey) => InferStorage<TCrdt>[TKey] | null;
213
+ getStorageJson(): InferCrdtJson<InferStorage<TCrdt>> | null;
214
+ getStorageJson<TKey extends keyof InferStorage<TCrdt>>(type: TKey): InferCrdtJson<InferStorage<TCrdt>[TKey]> | null;
182
215
  other: (connectionId: string, callback: OtherNotifierSubscriptionCallback<TIO, TPresence>) => (() => void);
183
216
  redo: () => void;
184
- storage: <TKey extends keyof TStorage>(key: TKey, fn: (value: InferCrdtJson<TStorage[TKey]>) => void) => (() => void);
185
- storageRoot: (fn: (value: { [P in keyof TStorage]: InferCrdtJson<TStorage[P]>; }) => void) => (() => void);
217
+ storage: <TKey extends keyof InferStorage<TCrdt>>(key: TKey, fn: (value: InferCrdtJson<InferStorage<TCrdt>[TKey]>) => void) => (() => void);
218
+ storageRoot: (fn: (value: { [P in keyof InferStorage<TCrdt>]: InferCrdtJson<InferStorage<TCrdt>[P]>; }) => void) => (() => void);
186
219
  subscribe: <TSubject extends keyof StateNotifierSubjects<TIO, TPresence>>(name: TSubject, callback: SubscriptionCallback<TIO, TPresence, TSubject>) => (() => void);
187
- transact: (fn: (storage: TStorage) => void, origin?: string) => void;
220
+ transact: (fn: (storage: InferStorage<TCrdt>) => void, origin?: string) => void;
188
221
  undo: () => void;
189
222
  updateMyPresence: (presence: UpdateMyPresenceAction<TPresence>) => void;
190
223
  private _addToStorageStore;
@@ -235,9 +268,9 @@ declare class PluvRoom<TIO extends IOLike<any, any>, TMetadata extends JsonObjec
235
268
  private _updateState;
236
269
  }
237
270
 
238
- type PluvClientOptions<TIO extends IOLike<any, any>, TPresence extends JsonObject, TStorage extends Record<string, CrdtType<any, any>>, TMetadata extends JsonObject> = RoomEndpoints<TIO, TMetadata> & {
271
+ type PluvClientOptions<TIO extends IOLike<any, any>, TPresence extends JsonObject, TCrdt extends AbstractCrdtDocFactory<any>, TMetadata extends JsonObject> = RoomEndpoints<TIO, TMetadata> & {
239
272
  debug?: boolean;
240
- initialStorage?: AbstractCrdtDocFactory<TStorage>;
273
+ initialStorage?: TCrdt;
241
274
  /**
242
275
  * @description Configurable limits defined for client-side validation. You should only set
243
276
  * this if you control the server and have changed the limits there.
@@ -248,17 +281,17 @@ type PluvClientOptions<TIO extends IOLike<any, any>, TPresence extends JsonObjec
248
281
  publicKey?: PublicKey<TMetadata>;
249
282
  types: InferCallback<TIO>;
250
283
  };
251
- type CreateRoomOptions<TIO extends IOLike<any, any>, TPresence extends JsonObject, TStorage extends Record<string, CrdtType<any, any>>, TMetadata extends JsonObject, TEvents extends PluvRouterEventConfig<TIO, TPresence, TStorage> = {}> = {
252
- addons?: readonly PluvRoomAddon<TIO, TMetadata, TPresence, TStorage>[];
284
+ type CreateRoomOptions<TIO extends IOLike<any, any>, TPresence extends JsonObject, TCrdt extends AbstractCrdtDocFactory<any>, TMetadata extends JsonObject, TEvents extends PluvRouterEventConfig<TIO, TPresence, InferStorage<TCrdt>> = {}> = {
285
+ addons?: readonly PluvRoomAddon<TIO, TMetadata, TPresence, InferStorage<TCrdt>>[];
253
286
  debug?: boolean | PluvRoomDebug<TIO>;
254
287
  initialPresence?: TPresence;
255
- initialStorage?: AbstractCrdtDocFactory<TStorage>;
288
+ initialStorage?: TCrdt;
256
289
  onAuthorizationFail?: (error: Error) => void;
257
290
  reconnectTimeoutMs?: ReconnectTimeoutMs;
258
- router?: PluvRouter<TIO, TPresence, TStorage, TEvents>;
291
+ router?: PluvRouter<TIO, TPresence, InferStorage<TCrdt>, TEvents>;
259
292
  };
260
293
  type EnterRoomParams<TMetadata extends JsonObject = {}> = keyof TMetadata extends never ? [] : [WithMetadata<TMetadata>];
261
- declare class PluvClient<TIO extends IOLike<any, any>, TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}, TMetadata extends JsonObject = {}> {
294
+ declare class PluvClient<TIO extends IOLike<any, any>, TPresence extends JsonObject = {}, TCrdt extends AbstractCrdtDocFactory<any> = NoopCrdtDocFactory, TMetadata extends JsonObject = {}> {
262
295
  readonly metadata?: InputZodLike<TMetadata>;
263
296
  private readonly _authEndpoint;
264
297
  private readonly _debug;
@@ -269,124 +302,31 @@ declare class PluvClient<TIO extends IOLike<any, any>, TPresence extends JsonObj
269
302
  private readonly _rooms;
270
303
  private readonly _wsEndpoint;
271
304
  get _defs(): {
272
- initialStorage: AbstractCrdtDocFactory<TStorage> | undefined;
305
+ initialStorage: TCrdt | undefined;
273
306
  };
274
- get procedure(): PluvProcedure<TIO, {}, {}, TPresence, TStorage>;
275
- constructor(options: PluvClientOptions<TIO, TPresence, TStorage, TMetadata>);
276
- createRoom: <TEvents extends PluvRouterEventConfig<TIO, TPresence, TStorage> = {}>(room: string, options?: CreateRoomOptions<TIO, TPresence, TStorage, TMetadata, TEvents>) => PluvRoom<TIO, TMetadata, TPresence, TStorage, TEvents>;
277
- enter: (room: string | PluvRoom<TIO, TMetadata, any, any, any>, ...args: EnterRoomParams<TMetadata>) => Promise<PluvRoom<TIO, TMetadata, TPresence, TStorage, any>>;
278
- getRoom: (room: string) => PluvRoom<TIO, TMetadata, TPresence, TStorage, any> | null;
279
- getRooms: () => readonly PluvRoom<TIO, TMetadata, TPresence, TStorage, any>[];
307
+ get procedure(): PluvProcedure<TIO, {}, {}, TPresence, InferStorage<TCrdt>>;
308
+ constructor(options: PluvClientOptions<TIO, TPresence, TCrdt, TMetadata>);
309
+ createRoom: <TEvents extends PluvRouterEventConfig<TIO, TPresence, InferStorage<TCrdt>> = {}>(room: string, options?: CreateRoomOptions<TIO, TPresence, TCrdt, TMetadata, TEvents>) => PluvRoom<TIO, TMetadata, TPresence, TCrdt, TEvents>;
310
+ enter: (room: string | PluvRoom<TIO, TMetadata, any, any, any>, ...args: EnterRoomParams<TMetadata>) => Promise<PluvRoom<TIO, TMetadata, TPresence, TCrdt, any>>;
311
+ getRoom: (room: string) => PluvRoom<TIO, TMetadata, TPresence, TCrdt, any> | null;
312
+ getRooms: () => readonly PluvRoom<TIO, TMetadata, TPresence, TCrdt, any>[];
280
313
  leave: (room: string | PluvRoom<TIO, any, any, any>) => Promise<void>;
281
- router<TEvents extends PluvRouterEventConfig<TIO, TPresence, TStorage> = {}>(events: TEvents): PluvRouter<TIO, TPresence, TStorage, TEvents>;
314
+ router<TEvents extends PluvRouterEventConfig<TIO, TPresence, InferStorage<TCrdt>> = {}>(events: TEvents): PluvRouter<TIO, TPresence, InferStorage<TCrdt>, TEvents>;
282
315
  private _logDebug;
283
316
  }
284
317
 
285
- interface AuthorizationState<TIO extends IOLike> {
286
- token: string | null;
287
- user: Id<InferIOAuthorizeUser<InferIOAuthorize<TIO>>> | null;
288
- }
289
- 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>;
290
- interface EventResolverContext<TIO extends IOLike = IOLike, TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}> {
291
- doc: AbstractCrdtDoc<TStorage>;
292
- others: readonly UserInfo<TIO, TPresence>[];
293
- room: string;
294
- user: UserInfo<TIO, TPresence>;
295
- }
296
- type InferMetadata<TClient extends PluvClient<any, any, any, any>> = TClient extends PluvClient<any, any, any, infer IMetadata> ? IMetadata : never;
297
- type MergeEventRecords<TEventRecords extends EventRecord<string, any>[], TRoot extends EventRecord<string, any> = {}> = TEventRecords extends [
298
- infer IHead extends EventRecord<string, any>,
299
- ...infer ITail extends EventRecord<string, any>[]
300
- ] ? MergeEventRecords<ITail, Omit<TRoot, keyof IHead> & {
301
- [P in keyof IHead]: TRoot extends Record<P, any> ? TRoot[P] | IHead[P] : IHead[P];
302
- }> : Id<TRoot>;
303
- interface PluvClientLimits {
304
- /**
305
- * @description Maximum size of presence object in bytes
306
- */
307
- presenceMaxSize?: number | null;
308
- }
309
- interface PublicKeyParams<TMetadata extends JsonObject> {
310
- metadata: TMetadata;
311
- }
312
- type PublicKey<TMetadata extends JsonObject> = string | ((params: PublicKeyParams<TMetadata>) => string);
313
- type UpdateMyPresenceAction<TPresence extends JsonObject> = Partial<TPresence> | ((oldPresence: TPresence | null) => Partial<TPresence>);
314
- interface UserInfo<TIO extends IOLike, TPresence extends JsonObject = {}> {
315
- connectionId: string;
316
- presence: TPresence;
317
- user: Id<InferIOAuthorizeUser<InferIOAuthorize<TIO>>>;
318
- }
319
- interface WebSocketConnection {
320
- /**
321
- * @description How many times a connection attempt was made. This will increment upon each
322
- * unsuccessful attempt, and will reset upon a successful connection.
323
- * @date April 13, 2025
324
- */
325
- attempts: number;
326
- /**
327
- * @description How many times the user has connected to the room. This can be more than 1 in
328
- * the case of reconnects. This is tracked because on the very first connection (i.e. when
329
- * count is 0) we don't want to send the storage state as an update to the room and overwrite
330
- * the upstream state.
331
- * @date April 13, 2025
332
- */
333
- count: number;
334
- id: string | null;
335
- state: ConnectionState;
336
- }
337
- interface WebSocketState<TIO extends IOLike> {
338
- authorization: AuthorizationState<TIO>;
339
- connection: WebSocketConnection;
340
- webSocket: WebSocket | null;
341
- }
342
- type WithMetadata<TMetadata extends JsonObject = {}> = keyof TMetadata extends never ? {
343
- metadata?: undefined;
344
- } : {
345
- metadata: TMetadata;
346
- };
347
-
348
- type OtherNotifierSubscriptionCallback<TIO extends IOLike, TPresence extends JsonObject> = (value: Id<UserInfo<TIO, TPresence>> | null) => void;
349
-
350
- declare abstract class AbstractRoom<TIO extends IOLike, TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}, TEvents extends PluvRouterEventConfig<TIO, TPresence, TStorage> = {}> {
351
- readonly id: string;
352
- constructor(room: string);
353
- abstract storageLoaded: boolean;
354
- abstract broadcast<TEvent extends keyof InferIOInput<MergeEvents<TEvents, TIO>>>(event: TEvent, data: Id<InferIOInput<MergeEvents<TEvents, TIO>>[TEvent]>): void;
355
- abstract canRedo(): boolean;
356
- abstract canUndo(): boolean;
357
- abstract getDoc(): AbstractCrdtDoc<TStorage>;
358
- abstract event<TEvent extends keyof InferIOOutput<MergeEvents<TEvents, TIO>>>(event: TEvent, callback: EventNotifierSubscriptionCallback<MergeEvents<TEvents, TIO>, TEvent>): () => void;
359
- abstract getConnection(): WebSocketConnection;
360
- abstract getMyPresence(): TPresence;
361
- abstract getMyself(): Id<UserInfo<TIO, TPresence>> | null;
362
- abstract getOther(connectionId: string): Id<UserInfo<TIO, TPresence>> | null;
363
- abstract getOthers(): readonly Id<UserInfo<TIO, TPresence>>[];
364
- abstract getStorage<TKey extends keyof TStorage>(type: TKey): TStorage[TKey] | null;
365
- abstract getStorageJson(): InferCrdtJson<TStorage> | null;
366
- abstract getStorageJson<TKey extends keyof TStorage>(type: TKey): InferCrdtJson<TStorage[TKey]> | null;
367
- abstract other(connectionId: string, callback: OtherNotifierSubscriptionCallback<TIO, TPresence>): () => void;
368
- abstract redo(): void;
369
- abstract storage<TKey extends keyof TStorage>(key: TKey, fn: (value: InferCrdtJson<TStorage[TKey]>) => void): () => void;
370
- abstract storageRoot(fn: (value: {
371
- [P in keyof TStorage]: InferCrdtJson<TStorage[P]>;
372
- }) => void): () => void;
373
- abstract subscribe<TSubject extends keyof StateNotifierSubjects<TIO, TPresence>>(name: TSubject, callback: SubscriptionCallback<TIO, TPresence, TSubject>): () => void;
374
- abstract transact(fn: (storage: TStorage) => void, origin?: string): void;
375
- abstract undo(): void;
376
- abstract updateMyPresence(presence: UpdateMyPresenceAction<TPresence>): void;
377
- }
378
-
379
- declare const createClient: <TIO extends IOLike<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>;
318
+ declare const createClient: <TIO extends IOLike<any, any>, TPresence extends JsonObject = {}, TCrdt extends AbstractCrdtDocFactory<any> = NoopCrdtDocFactory, TMetadata extends JsonObject = {}>(options: PluvClientOptions<TIO, TPresence, TCrdt, TMetadata>) => PluvClient<TIO, TPresence, TCrdt, TMetadata>;
380
319
 
381
320
  type MockedRoomEvents<TIO extends IOLike> = Partial<{
382
321
  [P in keyof InferIOInput<TIO>]: (data: Id<InferIOInput<TIO>[P]>) => Partial<InferIOOutput<TIO>>;
383
322
  }>;
384
- type MockedRoomConfig<TIO extends IOLike, TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}, TEvents extends PluvRouterEventConfig<TIO, TPresence, TStorage> = {}> = {
323
+ type MockedRoomConfig<TIO extends IOLike, TPresence extends JsonObject, TCrdt extends AbstractCrdtDocFactory<any>, TEvents extends PluvRouterEventConfig<TIO, TPresence, InferStorage<TCrdt>>> = {
385
324
  events?: MockedRoomEvents<MergeEvents<TEvents, TIO>>;
386
325
  limits?: PluvClientLimits;
387
- router?: PluvRouter<TIO, TPresence, TStorage, TEvents>;
388
- } & Pick<CrdtManagerOptions<TStorage>, "initialStorage"> & Omit<UsersManagerConfig<TPresence>, "limits">;
389
- 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> {
326
+ router?: PluvRouter<TIO, TPresence, InferStorage<TCrdt>, TEvents>;
327
+ } & Pick<CrdtManagerOptions<TCrdt>, "initialStorage"> & Omit<UsersManagerConfig<TPresence>, "limits">;
328
+ declare class MockedRoom<TIO extends IOLike, TPresence extends JsonObject, TCrdt extends AbstractCrdtDocFactory<any>, TEvents extends PluvRouterEventConfig<TIO, TPresence, InferStorage<TCrdt>>> implements RoomLike<TIO, TPresence, InferStorage<TCrdt>> {
329
+ readonly id: string;
390
330
  private readonly _crdtManager;
391
331
  private readonly _crdtNotifier;
392
332
  private readonly _eventNotifier;
@@ -398,27 +338,27 @@ declare class MockedRoom<TIO extends IOLike, TPresence extends JsonObject = {},
398
338
  private readonly _stateNotifier;
399
339
  private readonly _subscriptions;
400
340
  private readonly _usersManager;
401
- constructor(room: string, options: MockedRoomConfig<TIO, TPresence, TStorage, TEvents>);
341
+ constructor(room: string, options: MockedRoomConfig<TIO, TPresence, TCrdt, TEvents>);
402
342
  get storageLoaded(): boolean;
403
343
  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>; };
404
344
  canRedo: () => boolean;
405
345
  canUndo: () => boolean;
406
346
  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; };
407
347
  getConnection: () => WebSocketConnection;
408
- getDoc(): AbstractCrdtDoc<TStorage>;
348
+ getDoc(): CrdtDocLike<InferStorage<TCrdt>>;
409
349
  getMyPresence: () => TPresence;
410
350
  getMyself: () => Id<UserInfo<TIO, TPresence>> | null;
411
351
  getOther: (connectionId: string) => Id<UserInfo<TIO, TPresence>> | null;
412
352
  getOthers: () => readonly Id<UserInfo<TIO, TPresence>>[];
413
- getStorage: <TKey extends keyof TStorage>(type: TKey) => TStorage[TKey] | null;
414
- getStorageJson(): InferCrdtJson<TStorage> | null;
415
- getStorageJson<TKey extends keyof TStorage>(type: TKey): InferCrdtJson<TStorage[TKey]> | null;
353
+ getStorage: <TKey extends keyof InferStorage<TCrdt>>(type: TKey) => InferStorage<TCrdt>[TKey] | null;
354
+ getStorageJson(): InferCrdtJson<InferStorage<TCrdt>> | null;
355
+ getStorageJson<TKey extends keyof InferStorage<TCrdt>>(type: TKey): InferCrdtJson<InferStorage<TCrdt>[TKey]> | null;
416
356
  other: (connectionId: string, callback: OtherNotifierSubscriptionCallback<TIO, TPresence>) => (() => void);
417
357
  redo: () => void;
418
- storage: <TKey extends keyof TStorage>(key: TKey, fn: (value: InferCrdtJson<TStorage[TKey]>) => void) => (() => void);
419
- storageRoot: (fn: (value: { [P in keyof TStorage]: InferCrdtJson<TStorage[P]>; }) => void) => (() => void);
358
+ storage: <TKey extends keyof InferStorage<TCrdt>>(key: TKey, fn: (value: InferCrdtJson<InferStorage<TCrdt>[TKey]>) => void) => (() => void);
359
+ storageRoot: (fn: (value: { [P in keyof InferStorage<TCrdt>]: InferCrdtJson<InferStorage<TCrdt>[P]>; }) => void) => (() => void);
420
360
  subscribe: <TSubject extends keyof StateNotifierSubjects<TIO, TPresence>>(name: TSubject, callback: SubscriptionCallback<TIO, TPresence, TSubject>) => (() => void);
421
- transact: (fn: (storage: TStorage) => void, origin?: string) => void;
361
+ transact: (fn: (storage: InferStorage<TCrdt>) => void, origin?: string) => void;
422
362
  undo: () => void;
423
363
  updateMyPresence: (presence: UpdateMyPresenceAction<TPresence>) => void;
424
364
  private _observeCrdt;
@@ -435,4 +375,4 @@ declare const register: <TMetadata extends JsonObject>(params: RegisterParams<TM
435
375
  wsEndpoint: (params: EndpointParams<TMetadata>) => string;
436
376
  };
437
377
 
438
- export { AbstractRoom, AbstractStorageStore, ConnectionState, type CreateRoomOptions, type EnterRoomParams, type InferCallback, type InferMetadata, 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 PublicKey, type PublicKeyParams, type RegisterParams, type RoomConnectParams, type RoomEndpoints, type UserInfo, type WebSocketConnection, type WebSocketState, createClient, infer, register };
378
+ export { AbstractStorageStore, type CreateRoomOptions, type EnterRoomParams, type InferCallback, type InferMetadata, MockedRoom, type MockedRoomConfig, type MockedRoomEvents, PluvClient, type PluvClientOptions, type PluvProcedureConfig, PluvRoom, type PluvRoomAddon, type PluvRoomAddonInput, type PluvRoomAddonResult, type PluvRoomDebug, PluvRouter, type PluvRouterEventConfig, type PublicKey, type PublicKeyParams, type RegisterParams, type RoomConnectParams, type RoomEndpoints, type WebSocketConnection, createClient, infer, register };