@pluv/client 1.0.1 → 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.1 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
- CJS dist/index.js 58.07 KB
12
- CJS ⚡️ Build success in 125ms
13
- ESM dist/index.mjs 56.75 KB
14
- ESM ⚡️ Build success in 127ms
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 3647ms
17
- DTS dist/index.d.mts 25.34 KB
18
- DTS dist/index.d.ts 25.34 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,24 @@
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
+
14
+ ## 1.0.2
15
+
16
+ ### Patch Changes
17
+
18
+ - d87159c: Restored `@pluv/addon-indexeddb` functionality, and fixed `@pluv/addon-indexeddb` sometimes duplicating storage operations based on `initialStorage` values.
19
+ - @pluv/crdt@1.0.2
20
+ - @pluv/types@1.0.2
21
+
3
22
  ## 1.0.1
4
23
 
5
24
  ### 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,24 +204,23 @@ 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;
191
- private _applyStorageStore;
192
224
  private _attachWindowListeners;
193
225
  private _attachWsListeners;
194
226
  private _clearInterval;
@@ -236,9 +268,9 @@ declare class PluvRoom<TIO extends IOLike<any, any>, TMetadata extends JsonObjec
236
268
  private _updateState;
237
269
  }
238
270
 
239
- 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> & {
240
272
  debug?: boolean;
241
- initialStorage?: AbstractCrdtDocFactory<TStorage>;
273
+ initialStorage?: TCrdt;
242
274
  /**
243
275
  * @description Configurable limits defined for client-side validation. You should only set
244
276
  * this if you control the server and have changed the limits there.
@@ -249,17 +281,17 @@ type PluvClientOptions<TIO extends IOLike<any, any>, TPresence extends JsonObjec
249
281
  publicKey?: PublicKey<TMetadata>;
250
282
  types: InferCallback<TIO>;
251
283
  };
252
- 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> = {}> = {
253
- 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>>[];
254
286
  debug?: boolean | PluvRoomDebug<TIO>;
255
287
  initialPresence?: TPresence;
256
- initialStorage?: AbstractCrdtDocFactory<TStorage>;
288
+ initialStorage?: TCrdt;
257
289
  onAuthorizationFail?: (error: Error) => void;
258
290
  reconnectTimeoutMs?: ReconnectTimeoutMs;
259
- router?: PluvRouter<TIO, TPresence, TStorage, TEvents>;
291
+ router?: PluvRouter<TIO, TPresence, InferStorage<TCrdt>, TEvents>;
260
292
  };
261
293
  type EnterRoomParams<TMetadata extends JsonObject = {}> = keyof TMetadata extends never ? [] : [WithMetadata<TMetadata>];
262
- 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 = {}> {
263
295
  readonly metadata?: InputZodLike<TMetadata>;
264
296
  private readonly _authEndpoint;
265
297
  private readonly _debug;
@@ -270,124 +302,31 @@ declare class PluvClient<TIO extends IOLike<any, any>, TPresence extends JsonObj
270
302
  private readonly _rooms;
271
303
  private readonly _wsEndpoint;
272
304
  get _defs(): {
273
- initialStorage: AbstractCrdtDocFactory<TStorage> | undefined;
305
+ initialStorage: TCrdt | undefined;
274
306
  };
275
- get procedure(): PluvProcedure<TIO, {}, {}, TPresence, TStorage>;
276
- constructor(options: PluvClientOptions<TIO, TPresence, TStorage, TMetadata>);
277
- createRoom: <TEvents extends PluvRouterEventConfig<TIO, TPresence, TStorage> = {}>(room: string, options?: CreateRoomOptions<TIO, TPresence, TStorage, TMetadata, TEvents>) => PluvRoom<TIO, TMetadata, TPresence, TStorage, TEvents>;
278
- enter: (room: string | PluvRoom<TIO, TMetadata, any, any, any>, ...args: EnterRoomParams<TMetadata>) => Promise<PluvRoom<TIO, TMetadata, TPresence, TStorage, any>>;
279
- getRoom: (room: string) => PluvRoom<TIO, TMetadata, TPresence, TStorage, any> | null;
280
- 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>[];
281
313
  leave: (room: string | PluvRoom<TIO, any, any, any>) => Promise<void>;
282
- 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>;
283
315
  private _logDebug;
284
316
  }
285
317
 
286
- interface AuthorizationState<TIO extends IOLike> {
287
- token: string | null;
288
- user: Id<InferIOAuthorizeUser<InferIOAuthorize<TIO>>> | null;
289
- }
290
- 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>;
291
- interface EventResolverContext<TIO extends IOLike = IOLike, TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}> {
292
- doc: AbstractCrdtDoc<TStorage>;
293
- others: readonly UserInfo<TIO, TPresence>[];
294
- room: string;
295
- user: UserInfo<TIO, TPresence>;
296
- }
297
- type InferMetadata<TClient extends PluvClient<any, any, any, any>> = TClient extends PluvClient<any, any, any, infer IMetadata> ? IMetadata : never;
298
- type MergeEventRecords<TEventRecords extends EventRecord<string, any>[], TRoot extends EventRecord<string, any> = {}> = TEventRecords extends [
299
- infer IHead extends EventRecord<string, any>,
300
- ...infer ITail extends EventRecord<string, any>[]
301
- ] ? MergeEventRecords<ITail, Omit<TRoot, keyof IHead> & {
302
- [P in keyof IHead]: TRoot extends Record<P, any> ? TRoot[P] | IHead[P] : IHead[P];
303
- }> : Id<TRoot>;
304
- interface PluvClientLimits {
305
- /**
306
- * @description Maximum size of presence object in bytes
307
- */
308
- presenceMaxSize?: number | null;
309
- }
310
- interface PublicKeyParams<TMetadata extends JsonObject> {
311
- metadata: TMetadata;
312
- }
313
- type PublicKey<TMetadata extends JsonObject> = string | ((params: PublicKeyParams<TMetadata>) => string);
314
- type UpdateMyPresenceAction<TPresence extends JsonObject> = Partial<TPresence> | ((oldPresence: TPresence | null) => Partial<TPresence>);
315
- interface UserInfo<TIO extends IOLike, TPresence extends JsonObject = {}> {
316
- connectionId: string;
317
- presence: TPresence;
318
- user: Id<InferIOAuthorizeUser<InferIOAuthorize<TIO>>>;
319
- }
320
- interface WebSocketConnection {
321
- /**
322
- * @description How many times a connection attempt was made. This will increment upon each
323
- * unsuccessful attempt, and will reset upon a successful connection.
324
- * @date April 13, 2025
325
- */
326
- attempts: number;
327
- /**
328
- * @description How many times the user has connected to the room. This can be more than 1 in
329
- * the case of reconnects. This is tracked because on the very first connection (i.e. when
330
- * count is 0) we don't want to send the storage state as an update to the room and overwrite
331
- * the upstream state.
332
- * @date April 13, 2025
333
- */
334
- count: number;
335
- id: string | null;
336
- state: ConnectionState;
337
- }
338
- interface WebSocketState<TIO extends IOLike> {
339
- authorization: AuthorizationState<TIO>;
340
- connection: WebSocketConnection;
341
- webSocket: WebSocket | null;
342
- }
343
- type WithMetadata<TMetadata extends JsonObject = {}> = keyof TMetadata extends never ? {
344
- metadata?: undefined;
345
- } : {
346
- metadata: TMetadata;
347
- };
348
-
349
- type OtherNotifierSubscriptionCallback<TIO extends IOLike, TPresence extends JsonObject> = (value: Id<UserInfo<TIO, TPresence>> | null) => void;
350
-
351
- declare abstract class AbstractRoom<TIO extends IOLike, TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}, TEvents extends PluvRouterEventConfig<TIO, TPresence, TStorage> = {}> {
352
- readonly id: string;
353
- constructor(room: string);
354
- abstract storageLoaded: boolean;
355
- abstract broadcast<TEvent extends keyof InferIOInput<MergeEvents<TEvents, TIO>>>(event: TEvent, data: Id<InferIOInput<MergeEvents<TEvents, TIO>>[TEvent]>): void;
356
- abstract canRedo(): boolean;
357
- abstract canUndo(): boolean;
358
- abstract getDoc(): AbstractCrdtDoc<TStorage>;
359
- abstract event<TEvent extends keyof InferIOOutput<MergeEvents<TEvents, TIO>>>(event: TEvent, callback: EventNotifierSubscriptionCallback<MergeEvents<TEvents, TIO>, TEvent>): () => void;
360
- abstract getConnection(): WebSocketConnection;
361
- abstract getMyPresence(): TPresence;
362
- abstract getMyself(): Id<UserInfo<TIO, TPresence>> | null;
363
- abstract getOther(connectionId: string): Id<UserInfo<TIO, TPresence>> | null;
364
- abstract getOthers(): readonly Id<UserInfo<TIO, TPresence>>[];
365
- abstract getStorage<TKey extends keyof TStorage>(type: TKey): TStorage[TKey] | null;
366
- abstract getStorageJson(): InferCrdtJson<TStorage> | null;
367
- abstract getStorageJson<TKey extends keyof TStorage>(type: TKey): InferCrdtJson<TStorage[TKey]> | null;
368
- abstract other(connectionId: string, callback: OtherNotifierSubscriptionCallback<TIO, TPresence>): () => void;
369
- abstract redo(): void;
370
- abstract storage<TKey extends keyof TStorage>(key: TKey, fn: (value: InferCrdtJson<TStorage[TKey]>) => void): () => void;
371
- abstract storageRoot(fn: (value: {
372
- [P in keyof TStorage]: InferCrdtJson<TStorage[P]>;
373
- }) => void): () => void;
374
- abstract subscribe<TSubject extends keyof StateNotifierSubjects<TIO, TPresence>>(name: TSubject, callback: SubscriptionCallback<TIO, TPresence, TSubject>): () => void;
375
- abstract transact(fn: (storage: TStorage) => void, origin?: string): void;
376
- abstract undo(): void;
377
- abstract updateMyPresence(presence: UpdateMyPresenceAction<TPresence>): void;
378
- }
379
-
380
- 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>;
381
319
 
382
320
  type MockedRoomEvents<TIO extends IOLike> = Partial<{
383
321
  [P in keyof InferIOInput<TIO>]: (data: Id<InferIOInput<TIO>[P]>) => Partial<InferIOOutput<TIO>>;
384
322
  }>;
385
- 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>>> = {
386
324
  events?: MockedRoomEvents<MergeEvents<TEvents, TIO>>;
387
325
  limits?: PluvClientLimits;
388
- router?: PluvRouter<TIO, TPresence, TStorage, TEvents>;
389
- } & Pick<CrdtManagerOptions<TStorage>, "initialStorage"> & Omit<UsersManagerConfig<TPresence>, "limits">;
390
- 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;
391
330
  private readonly _crdtManager;
392
331
  private readonly _crdtNotifier;
393
332
  private readonly _eventNotifier;
@@ -399,27 +338,27 @@ declare class MockedRoom<TIO extends IOLike, TPresence extends JsonObject = {},
399
338
  private readonly _stateNotifier;
400
339
  private readonly _subscriptions;
401
340
  private readonly _usersManager;
402
- constructor(room: string, options: MockedRoomConfig<TIO, TPresence, TStorage, TEvents>);
341
+ constructor(room: string, options: MockedRoomConfig<TIO, TPresence, TCrdt, TEvents>);
403
342
  get storageLoaded(): boolean;
404
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>; };
405
344
  canRedo: () => boolean;
406
345
  canUndo: () => boolean;
407
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; };
408
347
  getConnection: () => WebSocketConnection;
409
- getDoc(): AbstractCrdtDoc<TStorage>;
348
+ getDoc(): CrdtDocLike<InferStorage<TCrdt>>;
410
349
  getMyPresence: () => TPresence;
411
350
  getMyself: () => Id<UserInfo<TIO, TPresence>> | null;
412
351
  getOther: (connectionId: string) => Id<UserInfo<TIO, TPresence>> | null;
413
352
  getOthers: () => readonly Id<UserInfo<TIO, TPresence>>[];
414
- getStorage: <TKey extends keyof TStorage>(type: TKey) => TStorage[TKey] | null;
415
- getStorageJson(): InferCrdtJson<TStorage> | null;
416
- 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;
417
356
  other: (connectionId: string, callback: OtherNotifierSubscriptionCallback<TIO, TPresence>) => (() => void);
418
357
  redo: () => void;
419
- storage: <TKey extends keyof TStorage>(key: TKey, fn: (value: InferCrdtJson<TStorage[TKey]>) => void) => (() => void);
420
- 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);
421
360
  subscribe: <TSubject extends keyof StateNotifierSubjects<TIO, TPresence>>(name: TSubject, callback: SubscriptionCallback<TIO, TPresence, TSubject>) => (() => void);
422
- transact: (fn: (storage: TStorage) => void, origin?: string) => void;
361
+ transact: (fn: (storage: InferStorage<TCrdt>) => void, origin?: string) => void;
423
362
  undo: () => void;
424
363
  updateMyPresence: (presence: UpdateMyPresenceAction<TPresence>) => void;
425
364
  private _observeCrdt;
@@ -436,4 +375,4 @@ declare const register: <TMetadata extends JsonObject>(params: RegisterParams<TM
436
375
  wsEndpoint: (params: EndpointParams<TMetadata>) => string;
437
376
  };
438
377
 
439
- 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 };