@pluv/client 2.1.0 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +8 -8
- package/CHANGELOG.md +44 -0
- package/dist/index.d.mts +49 -56
- package/dist/index.d.ts +49 -56
- package/dist/index.js +80 -27
- package/dist/index.mjs +82 -29
- package/package.json +5 -5
- package/src/CrdtManager.ts +9 -13
- package/src/ListenerManager.ts +21 -0
- package/src/MockedRoom.ts +36 -16
- package/src/PluvClient.ts +8 -8
- package/src/PluvProcedure.ts +27 -25
- package/src/PluvRoom.ts +76 -25
- package/src/PluvRouter.ts +31 -22
- package/src/StateNotifier.ts +2 -2
- package/src/UsersManager.ts +18 -4
- package/src/UsersNotifier.ts +1 -1
- package/src/constants.ts +1 -0
- package/src/createClient.ts +2 -2
- package/src/index.ts +2 -1
- package/src/types.ts +10 -31
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { AbstractCrdtDocFactory, InferDocLike, NoopCrdtDocFactory, InferStorage, InferDoc, InferCrdtJson } from '@pluv/crdt';
|
|
2
2
|
export { CrdtType, InferCrdtJson } from '@pluv/crdt';
|
|
3
|
-
import { IOLike, JsonObject, EventRecord, CrdtDocLike, UserInfo, MaybePromise, Id,
|
|
4
|
-
export { BaseUser, ConnectionState, EventMessage, EventNotifierSubscriptionCallback, EventRecord, IOEventMessage, MergeEvents, RoomLike, UserInfo, WebSocketState } from '@pluv/types';
|
|
3
|
+
import { IOLike, JsonObject, EventRecord, CrdtDocLike, UserInfo, MaybePromise, Id, ProcedureLike, InputZodLike, IORouterLike, InferIOAuthorizeUser, InferIOAuthorize, BaseUser, RoomLike, InferIOOutput, InferIOInput, RoomEventListenerMap, BroadcastProxy, EventProxy, WebSocketConnection, OtherSubscriptionCallback, StorageProxy, SubscribeProxy, UpdateMyPresenceAction, MergeEvents } from '@pluv/types';
|
|
4
|
+
export { BaseUser, ConnectionState, EventMessage, EventNotifierSubscriptionCallback, EventRecord, IOEventMessage, MergeEvents, RoomLike, UserInfo, WebSocketConnection, WebSocketState } from '@pluv/types';
|
|
5
5
|
|
|
6
6
|
declare abstract class AbstractStorageStore {
|
|
7
7
|
room: string;
|
|
@@ -21,9 +21,9 @@ type InferCallback<TIO extends IOLike<any, any>> = (i: typeof identity) => {
|
|
|
21
21
|
};
|
|
22
22
|
declare const infer: <TIO extends IOLike<any, any>>(callback: InferCallback<TIO>) => InferCallback<TIO>;
|
|
23
23
|
|
|
24
|
-
type EventResolver<TIO extends IOLike
|
|
25
|
-
interface EventResolverContext<TIO extends IOLike
|
|
26
|
-
doc:
|
|
24
|
+
type EventResolver<TIO extends IOLike, TInput extends JsonObject, TOutput extends EventRecord<string, any>, TPresence extends Record<string, any>, TDocLike extends CrdtDocLike<any, any>> = (data: TInput, context: EventResolverContext<TIO, TPresence, TDocLike>) => MaybePromise<TOutput | void>;
|
|
25
|
+
interface EventResolverContext<TIO extends IOLike, TPresence extends Record<string, any>, TDocLike extends CrdtDocLike<any, any>> {
|
|
26
|
+
doc: TDocLike;
|
|
27
27
|
others: readonly UserInfo<TIO, TPresence>[];
|
|
28
28
|
room: string;
|
|
29
29
|
user: UserInfo<TIO, TPresence>;
|
|
@@ -45,65 +45,47 @@ interface PublicKeyParams<TMetadata extends JsonObject> {
|
|
|
45
45
|
metadata: TMetadata;
|
|
46
46
|
}
|
|
47
47
|
type PublicKey<TMetadata extends JsonObject> = string | ((params: PublicKeyParams<TMetadata>) => string);
|
|
48
|
-
interface WebSocketConnection {
|
|
49
|
-
/**
|
|
50
|
-
* @description How many times a connection attempt was made. This will increment upon each
|
|
51
|
-
* unsuccessful attempt, and will reset upon a successful connection.
|
|
52
|
-
* @date April 13, 2025
|
|
53
|
-
*/
|
|
54
|
-
attempts: number;
|
|
55
|
-
/**
|
|
56
|
-
* @description How many times the user has connected to the room. This can be more than 1 in
|
|
57
|
-
* the case of reconnects. This is tracked because on the very first connection (i.e. when
|
|
58
|
-
* count is 0) we don't want to send the storage state as an update to the room and overwrite
|
|
59
|
-
* the upstream state.
|
|
60
|
-
* @date April 13, 2025
|
|
61
|
-
*/
|
|
62
|
-
count: number;
|
|
63
|
-
id: string | null;
|
|
64
|
-
state: ConnectionState;
|
|
65
|
-
}
|
|
66
48
|
type WithMetadata<TMetadata extends JsonObject = {}> = keyof TMetadata extends never ? {
|
|
67
49
|
metadata?: undefined;
|
|
68
50
|
} : {
|
|
69
51
|
metadata: TMetadata;
|
|
70
52
|
};
|
|
71
53
|
|
|
72
|
-
interface PluvProcedureConfig<TIO extends IOLike
|
|
73
|
-
broadcast?: EventResolver<TIO, TInput, TOutput, TPresence,
|
|
54
|
+
interface PluvProcedureConfig<TIO extends IOLike, TInput extends JsonObject, TOutput extends EventRecord<string, any>, TPresence extends Record<string, any>, TCrdt extends AbstractCrdtDocFactory<any, any>> {
|
|
55
|
+
broadcast?: EventResolver<TIO, TInput, TOutput, TPresence, InferDocLike<TCrdt>> | null;
|
|
74
56
|
input?: InputZodLike<TInput>;
|
|
75
57
|
}
|
|
76
|
-
declare class PluvProcedure<TIO extends IOLike
|
|
58
|
+
declare class PluvProcedure<TIO extends IOLike, TInput extends JsonObject, TOutput extends EventRecord<string, any>, TPresence extends Record<string, any>, TCrdt extends AbstractCrdtDocFactory<any, any>, TFilled extends "input" | "broadcast" | ""> implements ProcedureLike<TInput, TOutput> {
|
|
77
59
|
private _broadcast;
|
|
78
60
|
private _input;
|
|
79
61
|
get config(): ProcedureLike<TInput, TOutput>["config"];
|
|
80
|
-
constructor(config?: PluvProcedureConfig<TIO, TInput, TOutput, TPresence,
|
|
81
|
-
broadcast<TResult extends EventRecord<string, any> = {}>(resolver: EventResolver<TIO, TInput, TResult, TPresence,
|
|
82
|
-
input<TData extends JsonObject>(input: InputZodLike<TData>): Omit<PluvProcedure<TIO, TData, {}, TPresence,
|
|
62
|
+
constructor(config?: PluvProcedureConfig<TIO, TInput, TOutput, TPresence, TCrdt>);
|
|
63
|
+
broadcast<TResult extends EventRecord<string, any> = {}>(resolver: EventResolver<TIO, TInput, TResult, TPresence, InferDocLike<TCrdt>>): Omit<PluvProcedure<TIO, TInput, MergeEventRecords<[TOutput, TResult]>, TPresence, TCrdt, TFilled | "input" | "broadcast">, TFilled | "input" | "broadcast">;
|
|
64
|
+
input<TData extends JsonObject>(input: InputZodLike<TData>): Omit<PluvProcedure<TIO, TData, {}, TPresence, TCrdt, TFilled | "input">, TFilled | "input">;
|
|
83
65
|
private _resolver;
|
|
84
66
|
}
|
|
85
67
|
|
|
86
|
-
type CrdtManagerOptions<TCrdt extends AbstractCrdtDocFactory<any>> = {
|
|
68
|
+
type CrdtManagerOptions<TCrdt extends AbstractCrdtDocFactory<any, any>> = {
|
|
87
69
|
initialStorage?: TCrdt;
|
|
88
70
|
};
|
|
89
71
|
|
|
90
|
-
type PluvRouterEventConfig<TIO extends IOLike
|
|
91
|
-
[P: string]: Pick<PluvProcedure<TIO, any, any, TPresence,
|
|
72
|
+
type PluvRouterEventConfig<TIO extends IOLike, TPresence extends Record<string, any>, TCrdt extends AbstractCrdtDocFactory<any, any>> = {
|
|
73
|
+
[P: string]: Pick<PluvProcedure<TIO, any, any, TPresence, TCrdt, "">, "config">;
|
|
92
74
|
};
|
|
93
|
-
type MergedRouter<TRouters extends PluvRouter<TIO, TPresence,
|
|
94
|
-
infer IHead extends PluvRouter<TIO, TPresence,
|
|
95
|
-
...infer ITail extends PluvRouter<TIO, TPresence,
|
|
96
|
-
] ? MergedRouter<ITail, TIO, TPresence,
|
|
97
|
-
declare class PluvRouter<TIO extends IOLike
|
|
75
|
+
type MergedRouter<TRouters extends PluvRouter<TIO, TPresence, TCrdt, any>[], TIO extends IOLike, TPresence extends Record<string, any>, TCrdt extends AbstractCrdtDocFactory<any, any>, TRoot extends TRouters[0]["_defs"]["events"]> = TRouters extends [
|
|
76
|
+
infer IHead extends PluvRouter<TIO, TPresence, TCrdt, any>,
|
|
77
|
+
...infer ITail extends PluvRouter<TIO, TPresence, TCrdt, any>[]
|
|
78
|
+
] ? MergedRouter<ITail, TIO, TPresence, TCrdt, TRoot & IHead["_defs"]["events"]> : PluvRouter<TIO, TPresence, TCrdt, TRoot>;
|
|
79
|
+
declare class PluvRouter<TIO extends IOLike, TPresence extends Record<string, any>, TCrdt extends AbstractCrdtDocFactory<any, any>, TEvents extends PluvRouterEventConfig<TIO, TPresence, TCrdt> = {}> implements IORouterLike<TEvents> {
|
|
98
80
|
readonly _defs: {
|
|
99
81
|
events: TEvents;
|
|
100
82
|
};
|
|
101
83
|
constructor(events: TEvents);
|
|
102
|
-
static merge<TRouters extends PluvRouter<
|
|
84
|
+
static merge<TRouters extends PluvRouter<TIO, TPresence, TCrdt, any>[], TIO extends IOLike, TPresence extends Record<string, any>, TCrdt extends AbstractCrdtDocFactory<any, any>>(...routers: TRouters): MergedRouter<TRouters, TIO, TPresence, TCrdt, {}>;
|
|
103
85
|
private _isValidEventName;
|
|
104
86
|
}
|
|
105
87
|
|
|
106
|
-
type UsersManagerConfig<TPresence extends
|
|
88
|
+
type UsersManagerConfig<TPresence extends Record<string, any> = {}> = {
|
|
107
89
|
initialPresence?: TPresence;
|
|
108
90
|
limits: PluvClientLimits;
|
|
109
91
|
presence?: InputZodLike<TPresence>;
|
|
@@ -133,8 +115,8 @@ type RoomEndpoints<TIO extends IOLike<any, any>, TMetadata extends JsonObject> =
|
|
|
133
115
|
} : {
|
|
134
116
|
authEndpoint?: undefined;
|
|
135
117
|
});
|
|
136
|
-
type PluvRoomAddon<TIO extends IOLike, TMetadata extends JsonObject, TPresence extends
|
|
137
|
-
interface PluvRoomAddonInput<TIO extends IOLike, TMetadata extends JsonObject, TPresence extends
|
|
118
|
+
type PluvRoomAddon<TIO extends IOLike, TMetadata extends JsonObject, TPresence extends Record<string, any>, TCrdt extends AbstractCrdtDocFactory<any, any>> = (input: PluvRoomAddonInput<TIO, TMetadata, TPresence, TCrdt>) => Partial<PluvRoomAddonResult>;
|
|
119
|
+
interface PluvRoomAddonInput<TIO extends IOLike, TMetadata extends JsonObject, TPresence extends Record<string, any>, TCrdt extends AbstractCrdtDocFactory<any, any>> {
|
|
138
120
|
room: PluvRoom<TIO, TMetadata, TPresence, TCrdt>;
|
|
139
121
|
}
|
|
140
122
|
interface PluvRoomAddonResult {
|
|
@@ -149,7 +131,7 @@ interface ReconnectTimeoutMsParams {
|
|
|
149
131
|
attempts: number;
|
|
150
132
|
}
|
|
151
133
|
type ReconnectTimeoutMs = number | ((params: ReconnectTimeoutMsParams) => number);
|
|
152
|
-
type RoomConfig<TIO extends IOLike, TMetadata extends JsonObject, TPresence extends
|
|
134
|
+
type RoomConfig<TIO extends IOLike, TMetadata extends JsonObject, TPresence extends Record<string, any>, TCrdt extends AbstractCrdtDocFactory<any, any>, TEvents extends PluvRouterEventConfig<TIO, TPresence, InferStorage<TCrdt>>> = Id<{
|
|
153
135
|
addons?: readonly PluvRoomAddon<TIO, TMetadata, TPresence, TCrdt>[];
|
|
154
136
|
debug?: boolean | PluvRoomDebug<TIO>;
|
|
155
137
|
limits: PluvClientLimits;
|
|
@@ -159,7 +141,7 @@ type RoomConfig<TIO extends IOLike, TMetadata extends JsonObject, TPresence exte
|
|
|
159
141
|
reconnectTimeoutMs?: ReconnectTimeoutMs;
|
|
160
142
|
router?: PluvRouter<TIO, TPresence, InferStorage<TCrdt>, TEvents>;
|
|
161
143
|
} & RoomEndpoints<TIO, TMetadata> & Pick<CrdtManagerOptions<TCrdt>, "initialStorage"> & UsersManagerConfig<TPresence>>;
|
|
162
|
-
declare class PluvRoom<TIO extends IOLike<any, any>, TMetadata extends JsonObject = {}, TPresence extends
|
|
144
|
+
declare class PluvRoom<TIO extends IOLike<any, any>, TMetadata extends JsonObject = {}, TPresence extends Record<string, any> = {}, TCrdt extends AbstractCrdtDocFactory<any, any> = NoopCrdtDocFactory, TEvents extends PluvRouterEventConfig<TIO, TPresence, InferStorage<TCrdt>> = {}> implements RoomLike<TIO, InferDoc<TCrdt>, TPresence, InferStorage<TCrdt>> {
|
|
163
145
|
readonly _endpoints: RoomEndpoints<TIO, TMetadata>;
|
|
164
146
|
readonly id: string;
|
|
165
147
|
readonly metadata?: InputZodLike<TMetadata>;
|
|
@@ -169,6 +151,7 @@ declare class PluvRoom<TIO extends IOLike<any, any>, TMetadata extends JsonObjec
|
|
|
169
151
|
private readonly _eventNotifier;
|
|
170
152
|
private readonly _intervals;
|
|
171
153
|
private readonly _limits;
|
|
154
|
+
private readonly _listenerManager;
|
|
172
155
|
private readonly _listeners;
|
|
173
156
|
private readonly _publicKey;
|
|
174
157
|
private readonly _reconnectTimeoutMs;
|
|
@@ -184,8 +167,12 @@ declare class PluvRoom<TIO extends IOLike<any, any>, TMetadata extends JsonObjec
|
|
|
184
167
|
private _windowListeners;
|
|
185
168
|
private _wsListeners;
|
|
186
169
|
constructor(room: string, options: RoomConfig<TIO, TMetadata, TPresence, TCrdt, TEvents>);
|
|
170
|
+
/**
|
|
171
|
+
* @deprecated To be removed in v3. Use `getStorageLoaded` instead.
|
|
172
|
+
*/
|
|
187
173
|
get storageLoaded(): boolean;
|
|
188
174
|
get webSocket(): WebSocket | null;
|
|
175
|
+
addEventListener<TKind extends keyof RoomEventListenerMap>(kind: TKind, handler: RoomEventListenerMap[TKind]): () => void;
|
|
189
176
|
broadcast: BroadcastProxy<TIO, TEvents>;
|
|
190
177
|
canRedo: () => boolean;
|
|
191
178
|
canUndo: () => boolean;
|
|
@@ -196,7 +183,7 @@ declare class PluvRoom<TIO extends IOLike<any, any>, TMetadata extends JsonObjec
|
|
|
196
183
|
*/
|
|
197
184
|
event: EventProxy<TIO, TEvents>;
|
|
198
185
|
getConnection: () => WebSocketConnection;
|
|
199
|
-
getDoc: () => CrdtDocLike<InferStorage<TCrdt>>;
|
|
186
|
+
getDoc: () => CrdtDocLike<InferDoc<TCrdt>, InferStorage<TCrdt>>;
|
|
200
187
|
getMyPresence: () => TPresence;
|
|
201
188
|
getMyself: () => Id<UserInfo<TIO, TPresence>> | null;
|
|
202
189
|
getOther: (connectionId: string) => Id<UserInfo<TIO, TPresence>> | null;
|
|
@@ -204,13 +191,14 @@ declare class PluvRoom<TIO extends IOLike<any, any>, TMetadata extends JsonObjec
|
|
|
204
191
|
getStorage: <TKey extends keyof InferStorage<TCrdt>>(type: TKey) => InferStorage<TCrdt>[TKey] | null;
|
|
205
192
|
getStorageJson(): InferCrdtJson<InferStorage<TCrdt>> | null;
|
|
206
193
|
getStorageJson<TKey extends keyof InferStorage<TCrdt>>(type: TKey): InferCrdtJson<InferStorage<TCrdt>[TKey]> | null;
|
|
194
|
+
getStorageLoaded: () => boolean;
|
|
207
195
|
/**
|
|
208
196
|
* @deprecated To be removed in v3. Use PluvRoom.subscribe.other instead
|
|
209
197
|
*/
|
|
210
198
|
other: (connectionId: string, callback: OtherSubscriptionCallback<TIO, TPresence>) => (() => void);
|
|
211
199
|
redo: () => void;
|
|
212
200
|
/**
|
|
213
|
-
* @deprecated To be removed in v3.
|
|
201
|
+
* @deprecated To be removed in v3. Use PluvRoom.subscribe.storage instead
|
|
214
202
|
*/
|
|
215
203
|
storage: StorageProxy<InferStorage<TCrdt>>;
|
|
216
204
|
/**
|
|
@@ -270,7 +258,7 @@ declare class PluvRoom<TIO extends IOLike<any, any>, TMetadata extends JsonObjec
|
|
|
270
258
|
private _updateState;
|
|
271
259
|
}
|
|
272
260
|
|
|
273
|
-
type PluvClientOptions<TIO extends IOLike<any, any>, TPresence extends
|
|
261
|
+
type PluvClientOptions<TIO extends IOLike<any, any>, TPresence extends Record<string, any>, TCrdt extends AbstractCrdtDocFactory<any, any>, TMetadata extends JsonObject> = RoomEndpoints<TIO, TMetadata> & {
|
|
274
262
|
debug?: boolean;
|
|
275
263
|
initialStorage?: TCrdt;
|
|
276
264
|
/**
|
|
@@ -283,7 +271,7 @@ type PluvClientOptions<TIO extends IOLike<any, any>, TPresence extends JsonObjec
|
|
|
283
271
|
publicKey?: PublicKey<TMetadata>;
|
|
284
272
|
types: InferCallback<TIO>;
|
|
285
273
|
};
|
|
286
|
-
type CreateRoomOptions<TIO extends IOLike<any, any>, TPresence extends
|
|
274
|
+
type CreateRoomOptions<TIO extends IOLike<any, any>, TPresence extends Record<string, any>, TCrdt extends AbstractCrdtDocFactory<any, any>, TMetadata extends JsonObject, TEvents extends PluvRouterEventConfig<TIO, TPresence, InferStorage<TCrdt>> = {}> = {
|
|
287
275
|
addons?: readonly PluvRoomAddon<TIO, TMetadata, TPresence, InferStorage<TCrdt>>[];
|
|
288
276
|
debug?: boolean | PluvRoomDebug<TIO>;
|
|
289
277
|
initialPresence?: TPresence;
|
|
@@ -293,7 +281,7 @@ type CreateRoomOptions<TIO extends IOLike<any, any>, TPresence extends JsonObjec
|
|
|
293
281
|
router?: PluvRouter<TIO, TPresence, InferStorage<TCrdt>, TEvents>;
|
|
294
282
|
};
|
|
295
283
|
type EnterRoomParams<TMetadata extends JsonObject = {}> = keyof TMetadata extends never ? [] : [WithMetadata<TMetadata>];
|
|
296
|
-
declare class PluvClient<TIO extends IOLike<any, any>, TPresence extends
|
|
284
|
+
declare class PluvClient<TIO extends IOLike<any, any>, TPresence extends Record<string, any> = {}, TCrdt extends AbstractCrdtDocFactory<any, any> = NoopCrdtDocFactory, TMetadata extends JsonObject = {}> {
|
|
297
285
|
readonly metadata?: InputZodLike<TMetadata>;
|
|
298
286
|
private readonly _authEndpoint;
|
|
299
287
|
private readonly _debug;
|
|
@@ -306,7 +294,7 @@ declare class PluvClient<TIO extends IOLike<any, any>, TPresence extends JsonObj
|
|
|
306
294
|
get _defs(): {
|
|
307
295
|
initialStorage: TCrdt | undefined;
|
|
308
296
|
};
|
|
309
|
-
get procedure(): PluvProcedure<TIO, {}, {}, TPresence,
|
|
297
|
+
get procedure(): PluvProcedure<TIO, {}, {}, TPresence, TCrdt, "">;
|
|
310
298
|
constructor(options: PluvClientOptions<TIO, TPresence, TCrdt, TMetadata>);
|
|
311
299
|
createRoom: <TEvents extends PluvRouterEventConfig<TIO, TPresence, InferStorage<TCrdt>> = {}>(room: string, options?: CreateRoomOptions<TIO, TPresence, TCrdt, TMetadata, TEvents>) => PluvRoom<TIO, TMetadata, TPresence, TCrdt, TEvents>;
|
|
312
300
|
enter: (room: string | PluvRoom<TIO, TMetadata, any, any, any>, ...args: EnterRoomParams<TMetadata>) => Promise<PluvRoom<TIO, TMetadata, TPresence, TCrdt, any>>;
|
|
@@ -317,18 +305,22 @@ declare class PluvClient<TIO extends IOLike<any, any>, TPresence extends JsonObj
|
|
|
317
305
|
private _logDebug;
|
|
318
306
|
}
|
|
319
307
|
|
|
320
|
-
declare const createClient: <TIO extends IOLike<any, any>, TPresence extends
|
|
308
|
+
declare const createClient: <TIO extends IOLike<any, any>, TPresence extends Record<string, any> = {}, TCrdt extends AbstractCrdtDocFactory<any, any> = NoopCrdtDocFactory, TMetadata extends JsonObject = {}>(options: PluvClientOptions<TIO, TPresence, TCrdt, TMetadata>) => PluvClient<TIO, TPresence, TCrdt, TMetadata>;
|
|
321
309
|
|
|
322
310
|
type MockedRoomEvents<TIO extends IOLike> = Partial<{
|
|
323
311
|
[P in keyof InferIOInput<TIO>]: (data: Id<InferIOInput<TIO>[P]>) => Partial<InferIOOutput<TIO>>;
|
|
324
312
|
}>;
|
|
325
|
-
type MockedRoomConfig<TIO extends IOLike, TPresence extends
|
|
313
|
+
type MockedRoomConfig<TIO extends IOLike, TPresence extends Record<string, any>, TCrdt extends AbstractCrdtDocFactory<any, any>, TEvents extends PluvRouterEventConfig<TIO, TPresence, InferStorage<TCrdt>>> = {
|
|
326
314
|
events?: MockedRoomEvents<MergeEvents<TEvents, TIO>>;
|
|
327
315
|
limits?: PluvClientLimits;
|
|
328
316
|
router?: PluvRouter<TIO, TPresence, InferStorage<TCrdt>, TEvents>;
|
|
329
317
|
} & Pick<CrdtManagerOptions<TCrdt>, "initialStorage"> & Omit<UsersManagerConfig<TPresence>, "limits">;
|
|
330
|
-
declare class MockedRoom<TIO extends IOLike, TPresence extends
|
|
318
|
+
declare class MockedRoom<TIO extends IOLike, TPresence extends Record<string, any>, TCrdt extends AbstractCrdtDocFactory<any, any>, TEvents extends PluvRouterEventConfig<TIO, TPresence, InferStorage<TCrdt>>> implements RoomLike<TIO, InferDoc<TCrdt>, TPresence, InferStorage<TCrdt>> {
|
|
331
319
|
readonly id: string;
|
|
320
|
+
/**
|
|
321
|
+
* @deprecated To be removed in v3. Use `getStorageLoaded` instead.
|
|
322
|
+
*/
|
|
323
|
+
readonly storageLoaded: boolean;
|
|
332
324
|
private readonly _crdtManager;
|
|
333
325
|
private readonly _crdtNotifier;
|
|
334
326
|
private readonly _eventNotifier;
|
|
@@ -341,13 +333,13 @@ declare class MockedRoom<TIO extends IOLike, TPresence extends JsonObject, TCrdt
|
|
|
341
333
|
private readonly _subscriptions;
|
|
342
334
|
private readonly _usersManager;
|
|
343
335
|
constructor(room: string, options: MockedRoomConfig<TIO, TPresence, TCrdt, TEvents>);
|
|
344
|
-
|
|
336
|
+
addEventListener<TKind extends keyof RoomEventListenerMap>(kind: TKind, handler: RoomEventListenerMap[TKind]): () => void;
|
|
345
337
|
broadcast: BroadcastProxy<TIO, TEvents>;
|
|
346
338
|
canRedo: () => boolean;
|
|
347
339
|
canUndo: () => boolean;
|
|
348
340
|
event: EventProxy<TIO, TEvents>;
|
|
349
341
|
getConnection: () => WebSocketConnection;
|
|
350
|
-
getDoc(): CrdtDocLike<InferStorage<TCrdt>>;
|
|
342
|
+
getDoc(): CrdtDocLike<InferDoc<TCrdt>, InferStorage<TCrdt>>;
|
|
351
343
|
getMyPresence: () => TPresence;
|
|
352
344
|
getMyself: () => Id<UserInfo<TIO, TPresence>> | null;
|
|
353
345
|
getOther: (connectionId: string) => Id<UserInfo<TIO, TPresence>> | null;
|
|
@@ -355,6 +347,7 @@ declare class MockedRoom<TIO extends IOLike, TPresence extends JsonObject, TCrdt
|
|
|
355
347
|
getStorage: <TKey extends keyof InferStorage<TCrdt>>(type: TKey) => InferStorage<TCrdt>[TKey] | null;
|
|
356
348
|
getStorageJson(): InferCrdtJson<InferStorage<TCrdt>> | null;
|
|
357
349
|
getStorageJson<TKey extends keyof InferStorage<TCrdt>>(type: TKey): InferCrdtJson<InferStorage<TCrdt>[TKey]> | null;
|
|
350
|
+
getStorageLoaded(): boolean;
|
|
358
351
|
other: (connectionId: string, callback: OtherSubscriptionCallback<TIO, TPresence>) => (() => void);
|
|
359
352
|
redo: () => void;
|
|
360
353
|
storage: StorageProxy<InferStorage<TCrdt>>;
|
|
@@ -377,4 +370,4 @@ declare const register: <TMetadata extends JsonObject>(params: RegisterParams<TM
|
|
|
377
370
|
wsEndpoint: (params: EndpointParams<TMetadata>) => string;
|
|
378
371
|
};
|
|
379
372
|
|
|
380
|
-
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,
|
|
373
|
+
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, createClient, infer, register };
|
package/dist/index.js
CHANGED
|
@@ -78,6 +78,7 @@ var AbstractStorageStore = class {
|
|
|
78
78
|
|
|
79
79
|
// src/constants.ts
|
|
80
80
|
var MAX_PRESENCE_SIZE_BYTES = 512;
|
|
81
|
+
var PLUV_PRESENCE_META_KEY = "__pluv";
|
|
81
82
|
|
|
82
83
|
// src/PluvProcedure.ts
|
|
83
84
|
var PluvProcedure = class _PluvProcedure {
|
|
@@ -124,7 +125,7 @@ var CrdtManager = class {
|
|
|
124
125
|
this.initialized = false;
|
|
125
126
|
const { initialStorage = import_crdt.noop.doc({}) } = options;
|
|
126
127
|
this._docFactory = initialStorage;
|
|
127
|
-
this.doc =
|
|
128
|
+
this.doc = this._docFactory.getEmpty();
|
|
128
129
|
}
|
|
129
130
|
/**
|
|
130
131
|
* !HACK
|
|
@@ -164,11 +165,7 @@ var CrdtManager = class {
|
|
|
164
165
|
if (!updates.length) return this;
|
|
165
166
|
const initialized = this._docFactory.getInitialized();
|
|
166
167
|
const reference = initialized.get();
|
|
167
|
-
this.doc = this._applyDocUpdates(
|
|
168
|
-
this._docFactory.getEmpty(),
|
|
169
|
-
updates,
|
|
170
|
-
origin
|
|
171
|
-
).rebuildStorage(reference);
|
|
168
|
+
this.doc = this._applyDocUpdates(this.doc, updates, origin).rebuildStorage(reference);
|
|
172
169
|
this.initialized = true;
|
|
173
170
|
initialized.destroy();
|
|
174
171
|
return this;
|
|
@@ -228,6 +225,25 @@ var EventNotifier = class {
|
|
|
228
225
|
}
|
|
229
226
|
};
|
|
230
227
|
|
|
228
|
+
// src/ListenerManager.ts
|
|
229
|
+
var import_wonka3 = require("wonka");
|
|
230
|
+
var ListenerManager = class {
|
|
231
|
+
constructor() {
|
|
232
|
+
this.subjects = {
|
|
233
|
+
close: (0, import_wonka3.makeSubject)(),
|
|
234
|
+
error: (0, import_wonka3.makeSubject)(),
|
|
235
|
+
message: (0, import_wonka3.makeSubject)(),
|
|
236
|
+
open: (0, import_wonka3.makeSubject)()
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
subscribe(kind, callback) {
|
|
240
|
+
var _a;
|
|
241
|
+
const source = (_a = this.subjects[kind]) == null ? void 0 : _a.source;
|
|
242
|
+
if (!source) return () => void 0;
|
|
243
|
+
return (0, import_wonka3.subscribe)(callback)(source).unsubscribe;
|
|
244
|
+
}
|
|
245
|
+
};
|
|
246
|
+
|
|
231
247
|
// src/PluvRouter.ts
|
|
232
248
|
var PluvRouter = class _PluvRouter {
|
|
233
249
|
constructor(events) {
|
|
@@ -256,22 +272,22 @@ var PluvRouter = class _PluvRouter {
|
|
|
256
272
|
};
|
|
257
273
|
|
|
258
274
|
// src/StateNotifier.ts
|
|
259
|
-
var
|
|
275
|
+
var import_wonka4 = require("wonka");
|
|
260
276
|
var StateNotifier = class {
|
|
261
277
|
constructor() {
|
|
262
278
|
this.subjects = {
|
|
263
|
-
connection: (0,
|
|
264
|
-
"my-presence": (0,
|
|
265
|
-
myself: (0,
|
|
266
|
-
others: (0,
|
|
267
|
-
"storage-loaded": (0,
|
|
279
|
+
connection: (0, import_wonka4.makeSubject)(),
|
|
280
|
+
"my-presence": (0, import_wonka4.makeSubject)(),
|
|
281
|
+
myself: (0, import_wonka4.makeSubject)(),
|
|
282
|
+
others: (0, import_wonka4.makeSubject)(),
|
|
283
|
+
"storage-loaded": (0, import_wonka4.makeSubject)()
|
|
268
284
|
};
|
|
269
285
|
}
|
|
270
286
|
subscribe(name, callback) {
|
|
271
287
|
var _a;
|
|
272
288
|
const source = (_a = this.subjects[name]) == null ? void 0 : _a.source;
|
|
273
289
|
if (!source) throw new Error(`Could not subscribe to source: ${name}`);
|
|
274
|
-
return (0,
|
|
290
|
+
return (0, import_wonka4.subscribe)(callback)(source).unsubscribe;
|
|
275
291
|
}
|
|
276
292
|
};
|
|
277
293
|
|
|
@@ -444,6 +460,9 @@ var UsersManager = class {
|
|
|
444
460
|
);
|
|
445
461
|
const presence = __spreadValues(__spreadValues(__spreadValues({}, this.initialPresence), cleanedPresence), cleanedPatch);
|
|
446
462
|
const validated = this._presence ? this._presence.parse(presence) : presence;
|
|
463
|
+
if (!!presence[PLUV_PRESENCE_META_KEY]) {
|
|
464
|
+
validated[PLUV_PRESENCE_META_KEY] = presence[PLUV_PRESENCE_META_KEY];
|
|
465
|
+
}
|
|
447
466
|
this._others.set(clientId, __spreadProps(__spreadValues({}, other), { presence: validated }));
|
|
448
467
|
return validated;
|
|
449
468
|
}
|
|
@@ -522,10 +541,10 @@ var UsersManager = class {
|
|
|
522
541
|
};
|
|
523
542
|
|
|
524
543
|
// src/UsersNotifier.ts
|
|
525
|
-
var
|
|
544
|
+
var import_wonka5 = require("wonka");
|
|
526
545
|
var UsersNotifier = class {
|
|
527
546
|
constructor() {
|
|
528
|
-
this.others = (0,
|
|
547
|
+
this.others = (0, import_wonka5.makeSubject)();
|
|
529
548
|
this._otherSubjects = /* @__PURE__ */ new Map();
|
|
530
549
|
}
|
|
531
550
|
clear() {
|
|
@@ -541,17 +560,17 @@ var UsersNotifier = class {
|
|
|
541
560
|
other(clientId) {
|
|
542
561
|
const subject = this._otherSubjects.get(clientId);
|
|
543
562
|
if (subject) return subject;
|
|
544
|
-
const newSubject = (0,
|
|
563
|
+
const newSubject = (0, import_wonka5.makeSubject)();
|
|
545
564
|
this._otherSubjects.set(clientId, newSubject);
|
|
546
565
|
return newSubject;
|
|
547
566
|
}
|
|
548
567
|
subscribeOther(clientId, callback) {
|
|
549
568
|
const source = this.other(clientId).source;
|
|
550
|
-
const subscription = (0,
|
|
569
|
+
const subscription = (0, import_wonka5.subscribe)(callback)(source);
|
|
551
570
|
return subscription.unsubscribe;
|
|
552
571
|
}
|
|
553
572
|
subscribeOthers(callback) {
|
|
554
|
-
const subscription = (0,
|
|
573
|
+
const subscription = (0, import_wonka5.subscribe)(
|
|
555
574
|
({ others, event }) => callback(others, event)
|
|
556
575
|
)(this.others.source);
|
|
557
576
|
return subscription.unsubscribe;
|
|
@@ -577,6 +596,7 @@ var PluvRoom = class {
|
|
|
577
596
|
this._intervals = {
|
|
578
597
|
heartbeat: null
|
|
579
598
|
};
|
|
599
|
+
this._listenerManager = new ListenerManager();
|
|
580
600
|
this._publicKey = null;
|
|
581
601
|
this._stateNotifier = new StateNotifier();
|
|
582
602
|
this._subscriptions = {
|
|
@@ -595,10 +615,12 @@ var PluvRoom = class {
|
|
|
595
615
|
},
|
|
596
616
|
connection: {
|
|
597
617
|
attempts: 0,
|
|
598
|
-
count: 0,
|
|
599
618
|
id: null,
|
|
600
619
|
state: import_types.ConnectionState.Untouched
|
|
601
620
|
},
|
|
621
|
+
storage: {
|
|
622
|
+
state: import_types.StorageState.Unavailable
|
|
623
|
+
},
|
|
602
624
|
webSocket: null
|
|
603
625
|
};
|
|
604
626
|
this._windowListeners = null;
|
|
@@ -675,6 +697,9 @@ var PluvRoom = class {
|
|
|
675
697
|
if (typeof sharedType === "undefined") return null;
|
|
676
698
|
return sharedType;
|
|
677
699
|
};
|
|
700
|
+
this.getStorageLoaded = () => {
|
|
701
|
+
return this._state.storage.state === import_types.StorageState.Offline || this._state.storage.state === import_types.StorageState.Synced;
|
|
702
|
+
};
|
|
678
703
|
/**
|
|
679
704
|
* @deprecated To be removed in v3. Use PluvRoom.subscribe.other instead
|
|
680
705
|
*/
|
|
@@ -687,7 +712,7 @@ var PluvRoom = class {
|
|
|
687
712
|
this._crdtManager.doc.redo();
|
|
688
713
|
};
|
|
689
714
|
/**
|
|
690
|
-
* @deprecated To be removed in v3.
|
|
715
|
+
* @deprecated To be removed in v3. Use PluvRoom.subscribe.storage instead
|
|
691
716
|
*/
|
|
692
717
|
this.storage = new Proxy(
|
|
693
718
|
(key, callback) => this._crdtNotifier.subscribe(key, callback),
|
|
@@ -825,12 +850,18 @@ var PluvRoom = class {
|
|
|
825
850
|
});
|
|
826
851
|
this._crdtManager = new CrdtManager({ initialStorage });
|
|
827
852
|
}
|
|
853
|
+
/**
|
|
854
|
+
* @deprecated To be removed in v3. Use `getStorageLoaded` instead.
|
|
855
|
+
*/
|
|
828
856
|
get storageLoaded() {
|
|
829
|
-
return this.
|
|
857
|
+
return this.getStorageLoaded();
|
|
830
858
|
}
|
|
831
859
|
get webSocket() {
|
|
832
860
|
return this._state.webSocket;
|
|
833
861
|
}
|
|
862
|
+
addEventListener(kind, handler) {
|
|
863
|
+
return this._listenerManager.subscribe(kind, handler);
|
|
864
|
+
}
|
|
834
865
|
connect(...args) {
|
|
835
866
|
return __async(this, null, function* () {
|
|
836
867
|
var _a;
|
|
@@ -872,6 +903,7 @@ var PluvRoom = class {
|
|
|
872
903
|
this._updateState((oldState) => {
|
|
873
904
|
oldState.connection.attempts = 0;
|
|
874
905
|
oldState.authorization.token = authToken;
|
|
906
|
+
oldState.storage.state = import_types.StorageState.Loading;
|
|
875
907
|
oldState.webSocket = webSocket;
|
|
876
908
|
return oldState;
|
|
877
909
|
});
|
|
@@ -892,6 +924,7 @@ var PluvRoom = class {
|
|
|
892
924
|
this._updateState((oldState) => {
|
|
893
925
|
oldState.authorization.token = null;
|
|
894
926
|
oldState.connection.state = import_types.ConnectionState.Closed;
|
|
927
|
+
oldState.storage.state = oldState.storage.state === import_types.StorageState.Synced ? import_types.StorageState.Offline : import_types.StorageState.Unavailable;
|
|
895
928
|
oldState.webSocket = null;
|
|
896
929
|
return oldState;
|
|
897
930
|
});
|
|
@@ -1138,7 +1171,6 @@ var PluvRoom = class {
|
|
|
1138
1171
|
const data = message.data;
|
|
1139
1172
|
const state = data.state;
|
|
1140
1173
|
this._updateState((oldState) => {
|
|
1141
|
-
oldState.connection.count += 1;
|
|
1142
1174
|
oldState.connection.id = connectionId;
|
|
1143
1175
|
oldState.authorization.user = user != null ? user : null;
|
|
1144
1176
|
return oldState;
|
|
@@ -1190,6 +1222,10 @@ var PluvRoom = class {
|
|
|
1190
1222
|
const encodedState = this._crdtManager.doc.getEncodedState();
|
|
1191
1223
|
this._emitSharedTypes();
|
|
1192
1224
|
this._observeCrdt();
|
|
1225
|
+
this._updateState((oldState) => {
|
|
1226
|
+
oldState.storage.state = import_types.StorageState.Synced;
|
|
1227
|
+
return oldState;
|
|
1228
|
+
});
|
|
1193
1229
|
this._stateNotifier.subjects["storage-loaded"].next(true);
|
|
1194
1230
|
this._sendMessage({
|
|
1195
1231
|
type: "$updateStorage",
|
|
@@ -1302,11 +1338,13 @@ var PluvRoom = class {
|
|
|
1302
1338
|
this._listeners.onAuthorizationFail(authError);
|
|
1303
1339
|
this._updateState((oldState) => {
|
|
1304
1340
|
oldState.connection.state = import_types.ConnectionState.Unavailable;
|
|
1341
|
+
oldState.storage.state = import_types.StorageState.Unavailable;
|
|
1305
1342
|
return oldState;
|
|
1306
1343
|
});
|
|
1307
1344
|
}
|
|
1308
1345
|
_onClose(event) {
|
|
1309
1346
|
return __async(this, null, function* () {
|
|
1347
|
+
this._listenerManager.subjects.close.next(event);
|
|
1310
1348
|
this._logDebug("WebSocket closed");
|
|
1311
1349
|
if (!!event.reason) this._logDebug(event.reason);
|
|
1312
1350
|
const shouldRetry = [
|
|
@@ -1334,6 +1372,7 @@ var PluvRoom = class {
|
|
|
1334
1372
|
*/
|
|
1335
1373
|
import_types.ConnectionState.Closed
|
|
1336
1374
|
);
|
|
1375
|
+
oldState.storage.state = oldState.storage.state === import_types.StorageState.Synced ? import_types.StorageState.Offline : import_types.StorageState.Unavailable;
|
|
1337
1376
|
oldState.webSocket = null;
|
|
1338
1377
|
return oldState;
|
|
1339
1378
|
});
|
|
@@ -1350,9 +1389,11 @@ var PluvRoom = class {
|
|
|
1350
1389
|
* @description Handle websocket errors in a meaningful way, should they occur
|
|
1351
1390
|
* @date August 19, 2022
|
|
1352
1391
|
*/
|
|
1353
|
-
_onError() {
|
|
1392
|
+
_onError(event) {
|
|
1393
|
+
this._listenerManager.subjects.error.next(event);
|
|
1354
1394
|
}
|
|
1355
1395
|
_onMessage(event) {
|
|
1396
|
+
this._listenerManager.subjects.message.next(event);
|
|
1356
1397
|
const message = this._parseMessage(event);
|
|
1357
1398
|
if (!message) return;
|
|
1358
1399
|
const shouldLog = typeof this._debug === "boolean" ? this._debug : this._debug.output.find((value) => value === message.type);
|
|
@@ -1400,7 +1441,8 @@ var PluvRoom = class {
|
|
|
1400
1441
|
default:
|
|
1401
1442
|
}
|
|
1402
1443
|
}
|
|
1403
|
-
_onOpen() {
|
|
1444
|
+
_onOpen(event) {
|
|
1445
|
+
this._listenerManager.subjects.open.next(event);
|
|
1404
1446
|
if (this._state.connection.state !== import_types.ConnectionState.Connecting) return;
|
|
1405
1447
|
this._logDebug("WebSocket connected");
|
|
1406
1448
|
this._updateState((oldState) => {
|
|
@@ -1418,6 +1460,7 @@ var PluvRoom = class {
|
|
|
1418
1460
|
if (this._state.connection.state === import_types.ConnectionState.Closed) return;
|
|
1419
1461
|
this._updateState((oldState) => {
|
|
1420
1462
|
oldState.connection.state = import_types.ConnectionState.Unavailable;
|
|
1463
|
+
oldState.storage.state = oldState.storage.state === import_types.StorageState.Synced ? import_types.StorageState.Offline : import_types.StorageState.Unavailable;
|
|
1421
1464
|
return oldState;
|
|
1422
1465
|
});
|
|
1423
1466
|
});
|
|
@@ -1517,6 +1560,7 @@ var PluvRoom = class {
|
|
|
1517
1560
|
const oldState = __spreadProps(__spreadValues({}, this._state), {
|
|
1518
1561
|
authorization,
|
|
1519
1562
|
connection: JSON.parse(JSON.stringify(this._state.connection)),
|
|
1563
|
+
storage: JSON.parse(JSON.stringify(this._state.storage)),
|
|
1520
1564
|
webSocket: this._state.webSocket
|
|
1521
1565
|
});
|
|
1522
1566
|
const newState = updater(oldState);
|
|
@@ -1633,6 +1677,10 @@ var infer = (callback) => callback;
|
|
|
1633
1677
|
var import_types2 = require("@pluv/types");
|
|
1634
1678
|
var MockedRoom = class {
|
|
1635
1679
|
constructor(room, options) {
|
|
1680
|
+
/**
|
|
1681
|
+
* @deprecated To be removed in v3. Use `getStorageLoaded` instead.
|
|
1682
|
+
*/
|
|
1683
|
+
this.storageLoaded = true;
|
|
1636
1684
|
this._crdtNotifier = new CrdtNotifier();
|
|
1637
1685
|
this._eventNotifier = new EventNotifier();
|
|
1638
1686
|
this._usersNotifier = new UsersNotifier();
|
|
@@ -1643,10 +1691,12 @@ var MockedRoom = class {
|
|
|
1643
1691
|
},
|
|
1644
1692
|
connection: {
|
|
1645
1693
|
attempts: 0,
|
|
1646
|
-
count: 1,
|
|
1647
1694
|
id: null,
|
|
1648
1695
|
state: import_types2.ConnectionState.Untouched
|
|
1649
1696
|
},
|
|
1697
|
+
storage: {
|
|
1698
|
+
state: import_types2.StorageState.Unavailable
|
|
1699
|
+
},
|
|
1650
1700
|
webSocket: null
|
|
1651
1701
|
};
|
|
1652
1702
|
this._stateNotifier = new StateNotifier();
|
|
@@ -1821,8 +1871,8 @@ var MockedRoom = class {
|
|
|
1821
1871
|
});
|
|
1822
1872
|
this._observeCrdt();
|
|
1823
1873
|
}
|
|
1824
|
-
|
|
1825
|
-
return
|
|
1874
|
+
addEventListener(kind, handler) {
|
|
1875
|
+
return () => void 0;
|
|
1826
1876
|
}
|
|
1827
1877
|
getDoc() {
|
|
1828
1878
|
return this._crdtManager.doc;
|
|
@@ -1832,6 +1882,9 @@ var MockedRoom = class {
|
|
|
1832
1882
|
if (typeof type === "undefined") return this._crdtManager.doc.toJson();
|
|
1833
1883
|
return this._crdtManager.doc.toJson(type);
|
|
1834
1884
|
}
|
|
1885
|
+
getStorageLoaded() {
|
|
1886
|
+
return true;
|
|
1887
|
+
}
|
|
1835
1888
|
_observeCrdt() {
|
|
1836
1889
|
var _a, _b;
|
|
1837
1890
|
(_b = (_a = this._subscriptions).observeCrdt) == null ? void 0 : _b.call(_a);
|