@pluv/client 2.0.2 → 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 +141 -0
- package/dist/index.d.mts +74 -79
- package/dist/index.d.ts +74 -79
- package/dist/index.js +267 -68
- package/dist/index.mjs +269 -70
- package/package.json +5 -5
- package/src/CrdtManager.ts +9 -13
- package/src/CrdtNotifier.ts +2 -1
- package/src/ListenerManager.ts +21 -0
- package/src/MockedRoom.ts +118 -48
- package/src/PluvClient.ts +8 -8
- package/src/PluvProcedure.ts +27 -25
- package/src/PluvRoom.ts +235 -82
- package/src/PluvRouter.ts +31 -22
- package/src/StateNotifier.ts +13 -19
- package/src/UsersManager.ts +18 -4
- package/src/UsersNotifier.ts +66 -0
- 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/src/OtherNotifier.ts +0 -50
package/src/CrdtManager.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type { AbstractCrdtDocFactory,
|
|
1
|
+
import type { AbstractCrdtDocFactory, InferDocLike, InferStorage } from "@pluv/crdt";
|
|
2
2
|
import { noop } from "@pluv/crdt";
|
|
3
3
|
|
|
4
|
-
export type CrdtManagerOptions<TCrdt extends AbstractCrdtDocFactory<any>> = {
|
|
4
|
+
export type CrdtManagerOptions<TCrdt extends AbstractCrdtDocFactory<any, any>> = {
|
|
5
5
|
initialStorage?: TCrdt;
|
|
6
6
|
};
|
|
7
7
|
|
|
@@ -15,8 +15,8 @@ interface ApplyUpdateParams {
|
|
|
15
15
|
update: string | readonly string[];
|
|
16
16
|
}
|
|
17
17
|
|
|
18
|
-
export class CrdtManager<TCrdt extends AbstractCrdtDocFactory<any>> {
|
|
19
|
-
public doc:
|
|
18
|
+
export class CrdtManager<TCrdt extends AbstractCrdtDocFactory<any, any>> {
|
|
19
|
+
public doc: InferDocLike<TCrdt>;
|
|
20
20
|
public initialized: boolean = false;
|
|
21
21
|
|
|
22
22
|
private readonly _docFactory: TCrdt;
|
|
@@ -25,7 +25,7 @@ export class CrdtManager<TCrdt extends AbstractCrdtDocFactory<any>> {
|
|
|
25
25
|
const { initialStorage = noop.doc({}) as any } = options;
|
|
26
26
|
|
|
27
27
|
this._docFactory = initialStorage;
|
|
28
|
-
this.doc =
|
|
28
|
+
this.doc = this._docFactory.getEmpty() as InferDocLike<TCrdt>;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
31
|
/**
|
|
@@ -49,7 +49,7 @@ export class CrdtManager<TCrdt extends AbstractCrdtDocFactory<any>> {
|
|
|
49
49
|
public destroy(): void {
|
|
50
50
|
this.initialized = false;
|
|
51
51
|
this.doc.destroy();
|
|
52
|
-
this.doc = this._docFactory.getEmpty()
|
|
52
|
+
this.doc = this._docFactory.getEmpty() as InferDocLike<TCrdt>;
|
|
53
53
|
}
|
|
54
54
|
|
|
55
55
|
public get<TKey extends keyof InferStorage<TCrdt>>(key: TKey): InferStorage<TCrdt>[TKey] {
|
|
@@ -94,11 +94,7 @@ export class CrdtManager<TCrdt extends AbstractCrdtDocFactory<any>> {
|
|
|
94
94
|
const initialized = this._docFactory.getInitialized();
|
|
95
95
|
const reference = initialized.get();
|
|
96
96
|
|
|
97
|
-
this.doc = this._applyDocUpdates(
|
|
98
|
-
this._docFactory.getEmpty(),
|
|
99
|
-
updates,
|
|
100
|
-
origin,
|
|
101
|
-
).rebuildStorage(reference);
|
|
97
|
+
this.doc = this._applyDocUpdates(this.doc, updates, origin).rebuildStorage(reference);
|
|
102
98
|
this.initialized = true;
|
|
103
99
|
initialized.destroy();
|
|
104
100
|
|
|
@@ -110,10 +106,10 @@ export class CrdtManager<TCrdt extends AbstractCrdtDocFactory<any>> {
|
|
|
110
106
|
}
|
|
111
107
|
|
|
112
108
|
private _applyDocUpdates(
|
|
113
|
-
doc:
|
|
109
|
+
doc: InferDocLike<TCrdt>,
|
|
114
110
|
updates: readonly string[],
|
|
115
111
|
origin?: string,
|
|
116
|
-
):
|
|
112
|
+
): InferDocLike<TCrdt> {
|
|
117
113
|
doc.transact(() => {
|
|
118
114
|
doc.batchApplyEncodedState({ origin, updates });
|
|
119
115
|
}, origin);
|
package/src/CrdtNotifier.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { CrdtType, InferCrdtJson } from "@pluv/crdt";
|
|
2
|
+
import type { StorageSubscriptionCallback } from "@pluv/types";
|
|
2
3
|
import type { Subject } from "wonka";
|
|
3
4
|
import { makeSubject, subscribe } from "wonka";
|
|
4
5
|
|
|
@@ -36,7 +37,7 @@ export class CrdtNotifier<TStorage extends Record<string, CrdtType<any, any>>> {
|
|
|
36
37
|
|
|
37
38
|
public subscribe<TKey extends keyof TStorage>(
|
|
38
39
|
key: TKey,
|
|
39
|
-
callback:
|
|
40
|
+
callback: StorageSubscriptionCallback<TStorage, TKey>,
|
|
40
41
|
): () => void {
|
|
41
42
|
const subject = this.subject(key);
|
|
42
43
|
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { makeSubject, subscribe, TypeOfSource } from "wonka";
|
|
2
|
+
|
|
3
|
+
export class ListenerManager {
|
|
4
|
+
public subjects = {
|
|
5
|
+
close: makeSubject<CloseEvent>(),
|
|
6
|
+
error: makeSubject<Event>(),
|
|
7
|
+
message: makeSubject<MessageEvent<any>>(),
|
|
8
|
+
open: makeSubject<Event>(),
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
public subscribe<TKind extends keyof typeof this.subjects>(
|
|
12
|
+
kind: TKind,
|
|
13
|
+
callback: (event: TypeOfSource<(typeof this.subjects)[TKind]["source"]>) => void,
|
|
14
|
+
): () => void {
|
|
15
|
+
const source = this.subjects[kind]?.source;
|
|
16
|
+
|
|
17
|
+
if (!source) return () => undefined;
|
|
18
|
+
|
|
19
|
+
return subscribe(callback)(source as any).unsubscribe;
|
|
20
|
+
}
|
|
21
|
+
}
|
package/src/MockedRoom.ts
CHANGED
|
@@ -1,39 +1,53 @@
|
|
|
1
|
-
import type { AbstractCrdtDocFactory, CrdtType, InferCrdtJson, InferStorage } from "@pluv/crdt";
|
|
2
1
|
import type {
|
|
2
|
+
AbstractCrdtDocFactory,
|
|
3
|
+
InferCrdtJson,
|
|
4
|
+
InferDoc,
|
|
5
|
+
InferDocLike,
|
|
6
|
+
InferStorage,
|
|
7
|
+
} from "@pluv/crdt";
|
|
8
|
+
import type {
|
|
9
|
+
BroadcastProxy,
|
|
3
10
|
CrdtDocLike,
|
|
4
11
|
EventNotifierSubscriptionCallback,
|
|
12
|
+
EventProxy,
|
|
5
13
|
IOLike,
|
|
6
14
|
Id,
|
|
7
15
|
InferIOInput,
|
|
8
16
|
InferIOOutput,
|
|
9
|
-
JsonObject,
|
|
10
17
|
MergeEvents,
|
|
11
|
-
|
|
18
|
+
OtherSubscriptionCallback,
|
|
19
|
+
OthersSubscriptionCallback,
|
|
20
|
+
RoomEventListenerMap,
|
|
12
21
|
RoomLike,
|
|
22
|
+
StateNotifierSubjects,
|
|
23
|
+
StorageProxy,
|
|
24
|
+
StorageRootSubscriptionCallback,
|
|
25
|
+
StorageSubscriptionCallback,
|
|
26
|
+
SubscribeProxy,
|
|
27
|
+
SubscriptionCallback,
|
|
13
28
|
UpdateMyPresenceAction,
|
|
14
29
|
UserInfo,
|
|
30
|
+
WebSocketConnection,
|
|
15
31
|
WebSocketState,
|
|
16
32
|
} from "@pluv/types";
|
|
17
|
-
import { ConnectionState } from "@pluv/types";
|
|
33
|
+
import { ConnectionState, StorageState } from "@pluv/types";
|
|
18
34
|
import type { CrdtManagerOptions } from "./CrdtManager";
|
|
19
35
|
import { CrdtManager } from "./CrdtManager";
|
|
20
36
|
import { CrdtNotifier } from "./CrdtNotifier";
|
|
21
37
|
import { EventNotifier } from "./EventNotifier";
|
|
22
|
-
import { OtherNotifier } from "./OtherNotifier";
|
|
23
38
|
import { PluvProcedure } from "./PluvProcedure";
|
|
24
39
|
import type { PluvRouterEventConfig } from "./PluvRouter";
|
|
25
40
|
import { PluvRouter } from "./PluvRouter";
|
|
26
|
-
import type { StateNotifierSubjects, SubscriptionCallback } from "./StateNotifier";
|
|
27
41
|
import { StateNotifier } from "./StateNotifier";
|
|
28
42
|
import type { UsersManagerConfig } from "./UsersManager";
|
|
29
43
|
import { UsersManager } from "./UsersManager";
|
|
44
|
+
import { UsersNotifier } from "./UsersNotifier";
|
|
30
45
|
import { MAX_PRESENCE_SIZE_BYTES } from "./constants";
|
|
31
46
|
import type {
|
|
32
47
|
EventResolver,
|
|
33
48
|
EventResolverContext,
|
|
34
49
|
InternalSubscriptions,
|
|
35
50
|
PluvClientLimits,
|
|
36
|
-
WebSocketConnection,
|
|
37
51
|
} from "./types";
|
|
38
52
|
|
|
39
53
|
export type MockedRoomEvents<TIO extends IOLike> = Partial<{
|
|
@@ -42,8 +56,8 @@ export type MockedRoomEvents<TIO extends IOLike> = Partial<{
|
|
|
42
56
|
|
|
43
57
|
export type MockedRoomConfig<
|
|
44
58
|
TIO extends IOLike,
|
|
45
|
-
TPresence extends
|
|
46
|
-
TCrdt extends AbstractCrdtDocFactory<any>,
|
|
59
|
+
TPresence extends Record<string, any>,
|
|
60
|
+
TCrdt extends AbstractCrdtDocFactory<any, any>,
|
|
47
61
|
TEvents extends PluvRouterEventConfig<TIO, TPresence, InferStorage<TCrdt>>,
|
|
48
62
|
> = {
|
|
49
63
|
events?: MockedRoomEvents<MergeEvents<TEvents, TIO>>;
|
|
@@ -54,19 +68,24 @@ export type MockedRoomConfig<
|
|
|
54
68
|
|
|
55
69
|
export class MockedRoom<
|
|
56
70
|
TIO extends IOLike,
|
|
57
|
-
TPresence extends
|
|
58
|
-
TCrdt extends AbstractCrdtDocFactory<any>,
|
|
71
|
+
TPresence extends Record<string, any>,
|
|
72
|
+
TCrdt extends AbstractCrdtDocFactory<any, any>,
|
|
59
73
|
TEvents extends PluvRouterEventConfig<TIO, TPresence, InferStorage<TCrdt>>,
|
|
60
|
-
> implements RoomLike<TIO, TPresence, InferStorage<TCrdt>>
|
|
74
|
+
> implements RoomLike<TIO, InferDoc<TCrdt>, TPresence, InferStorage<TCrdt>>
|
|
61
75
|
{
|
|
62
76
|
public readonly id: string;
|
|
63
77
|
|
|
78
|
+
/**
|
|
79
|
+
* @deprecated To be removed in v3. Use `getStorageLoaded` instead.
|
|
80
|
+
*/
|
|
81
|
+
public readonly storageLoaded: boolean = true;
|
|
82
|
+
|
|
64
83
|
private readonly _crdtManager: CrdtManager<TCrdt>;
|
|
65
84
|
private readonly _crdtNotifier = new CrdtNotifier<InferStorage<TCrdt>>();
|
|
66
85
|
private readonly _eventNotifier = new EventNotifier<MergeEvents<TEvents, TIO>>();
|
|
67
86
|
private readonly _events?: MockedRoomEvents<MergeEvents<TEvents, TIO>>;
|
|
68
87
|
private readonly _limits: PluvClientLimits;
|
|
69
|
-
private readonly
|
|
88
|
+
private readonly _usersNotifier = new UsersNotifier<TIO, TPresence>();
|
|
70
89
|
private readonly _router: PluvRouter<TIO, TPresence, InferStorage<TCrdt>, TEvents>;
|
|
71
90
|
private _state: WebSocketState<TIO> = {
|
|
72
91
|
authorization: {
|
|
@@ -75,10 +94,12 @@ export class MockedRoom<
|
|
|
75
94
|
},
|
|
76
95
|
connection: {
|
|
77
96
|
attempts: 0,
|
|
78
|
-
count: 1,
|
|
79
97
|
id: null,
|
|
80
98
|
state: ConnectionState.Untouched,
|
|
81
99
|
},
|
|
100
|
+
storage: {
|
|
101
|
+
state: StorageState.Unavailable,
|
|
102
|
+
},
|
|
82
103
|
webSocket: null,
|
|
83
104
|
};
|
|
84
105
|
private readonly _stateNotifier = new StateNotifier<TIO, TPresence>();
|
|
@@ -113,8 +134,11 @@ export class MockedRoom<
|
|
|
113
134
|
this._observeCrdt();
|
|
114
135
|
}
|
|
115
136
|
|
|
116
|
-
public
|
|
117
|
-
|
|
137
|
+
public addEventListener<TKind extends keyof RoomEventListenerMap>(
|
|
138
|
+
kind: TKind,
|
|
139
|
+
handler: RoomEventListenerMap[TKind],
|
|
140
|
+
): () => void {
|
|
141
|
+
return () => undefined;
|
|
118
142
|
}
|
|
119
143
|
|
|
120
144
|
public broadcast = new Proxy(
|
|
@@ -132,7 +156,8 @@ export class MockedRoom<
|
|
|
132
156
|
any,
|
|
133
157
|
any,
|
|
134
158
|
TPresence,
|
|
135
|
-
|
|
159
|
+
TCrdt,
|
|
160
|
+
""
|
|
136
161
|
> | null;
|
|
137
162
|
|
|
138
163
|
if (!procedure?.config.broadcast) {
|
|
@@ -146,7 +171,7 @@ export class MockedRoom<
|
|
|
146
171
|
if (!myself) return;
|
|
147
172
|
|
|
148
173
|
const parsed = procedure.config.input ? procedure.config.input.parse(data) : data;
|
|
149
|
-
const context: EventResolverContext<TIO, TPresence,
|
|
174
|
+
const context: EventResolverContext<TIO, TPresence, InferDocLike<TCrdt>> = {
|
|
150
175
|
doc: this._crdtManager.doc,
|
|
151
176
|
others: this._usersManager.getOthers(),
|
|
152
177
|
room: this.id,
|
|
@@ -176,12 +201,7 @@ export class MockedRoom<
|
|
|
176
201
|
};
|
|
177
202
|
},
|
|
178
203
|
},
|
|
179
|
-
) as
|
|
180
|
-
event: TEvent,
|
|
181
|
-
data: Id<InferIOInput<MergeEvents<TEvents, TIO>>[TEvent]>,
|
|
182
|
-
) => Promise<void>) & {
|
|
183
|
-
[event in keyof InferIOInput<TIO>]: (data: Id<InferIOInput<TIO>[event]>) => Promise<void>;
|
|
184
|
-
};
|
|
204
|
+
) as BroadcastProxy<TIO, TEvents>;
|
|
185
205
|
|
|
186
206
|
public canRedo = (): boolean => {
|
|
187
207
|
return !!this._crdtManager.doc.canRedo();
|
|
@@ -203,21 +223,14 @@ export class MockedRoom<
|
|
|
203
223
|
): (() => void) => fn(prop as any, callback);
|
|
204
224
|
},
|
|
205
225
|
},
|
|
206
|
-
) as
|
|
207
|
-
event: TEvent,
|
|
208
|
-
callback: EventNotifierSubscriptionCallback<MergeEvents<TEvents, TIO>, TEvent>,
|
|
209
|
-
) => () => void) & {
|
|
210
|
-
[event in keyof InferIOOutput<MergeEvents<TEvents, TIO>>]: (
|
|
211
|
-
callback: EventNotifierSubscriptionCallback<MergeEvents<TEvents, TIO>, any>,
|
|
212
|
-
) => () => void;
|
|
213
|
-
};
|
|
226
|
+
) as EventProxy<TIO, TEvents>;
|
|
214
227
|
|
|
215
228
|
public getConnection = (): WebSocketConnection => {
|
|
216
229
|
// Create a read-only clone of the connection state
|
|
217
230
|
return Object.freeze(JSON.parse(JSON.stringify(this._state.connection)));
|
|
218
231
|
};
|
|
219
232
|
|
|
220
|
-
public getDoc(): CrdtDocLike<InferStorage<TCrdt>> {
|
|
233
|
+
public getDoc(): CrdtDocLike<InferDoc<TCrdt>, InferStorage<TCrdt>> {
|
|
221
234
|
return this._crdtManager.doc;
|
|
222
235
|
}
|
|
223
236
|
|
|
@@ -253,33 +266,51 @@ export class MockedRoom<
|
|
|
253
266
|
): InferCrdtJson<InferStorage<TCrdt>[TKey]> | null;
|
|
254
267
|
public getStorageJson<TKey extends keyof InferStorage<TCrdt>>(type?: TKey) {
|
|
255
268
|
if (this._state.connection.id === null) return null;
|
|
256
|
-
|
|
257
269
|
if (typeof type === "undefined") return this._crdtManager.doc.toJson();
|
|
258
270
|
|
|
259
271
|
return this._crdtManager.doc.toJson(type);
|
|
260
272
|
}
|
|
261
273
|
|
|
274
|
+
public getStorageLoaded(): boolean {
|
|
275
|
+
return true;
|
|
276
|
+
}
|
|
277
|
+
|
|
262
278
|
public other = (
|
|
263
279
|
connectionId: string,
|
|
264
|
-
callback:
|
|
280
|
+
callback: OtherSubscriptionCallback<TIO, TPresence>,
|
|
265
281
|
): (() => void) => {
|
|
266
282
|
const clientId = this._usersManager.getClientId(connectionId);
|
|
267
283
|
|
|
268
284
|
if (!clientId) return () => undefined;
|
|
269
285
|
|
|
270
|
-
return this.
|
|
286
|
+
return this._usersNotifier.subscribeOther(clientId, callback);
|
|
271
287
|
};
|
|
272
288
|
|
|
273
289
|
public redo = (): void => {
|
|
274
290
|
this._crdtManager.doc.redo();
|
|
275
291
|
};
|
|
276
292
|
|
|
277
|
-
public storage =
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
293
|
+
public storage = new Proxy(
|
|
294
|
+
<TKey extends keyof InferStorage<TCrdt>>(
|
|
295
|
+
key: TKey,
|
|
296
|
+
callback: StorageSubscriptionCallback<InferStorage<TCrdt>, TKey>,
|
|
297
|
+
): (() => void) => this._crdtNotifier.subscribe(key, callback),
|
|
298
|
+
{
|
|
299
|
+
get: (fn, prop) => {
|
|
300
|
+
type _Storage = InferStorage<TCrdt>;
|
|
301
|
+
|
|
302
|
+
if (!!prop) {
|
|
303
|
+
return (callback: StorageRootSubscriptionCallback<_Storage>) => {
|
|
304
|
+
return this._crdtNotifier.subcribeRoot(callback);
|
|
305
|
+
};
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
return (callback: StorageSubscriptionCallback<_Storage, keyof _Storage>) => {
|
|
309
|
+
return fn(prop as keyof InferStorage<TCrdt>, callback);
|
|
310
|
+
};
|
|
311
|
+
},
|
|
312
|
+
},
|
|
313
|
+
) as StorageProxy<InferStorage<TCrdt>>;
|
|
283
314
|
|
|
284
315
|
public storageRoot = (
|
|
285
316
|
fn: (value: {
|
|
@@ -289,12 +320,51 @@ export class MockedRoom<
|
|
|
289
320
|
return this._crdtNotifier.subcribeRoot(fn);
|
|
290
321
|
};
|
|
291
322
|
|
|
292
|
-
public subscribe =
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
323
|
+
public subscribe = new Proxy(
|
|
324
|
+
<TSubject extends keyof StateNotifierSubjects<TIO, TPresence>>(
|
|
325
|
+
name: TSubject,
|
|
326
|
+
callback: SubscriptionCallback<TIO, TPresence, TSubject>,
|
|
327
|
+
): (() => void) => {
|
|
328
|
+
return this._stateNotifier.subscribe(name, callback);
|
|
329
|
+
},
|
|
330
|
+
{
|
|
331
|
+
get: (fn, prop) => {
|
|
332
|
+
if (prop === "connection") {
|
|
333
|
+
return (callback: SubscriptionCallback<TIO, TPresence, "connection">) => {
|
|
334
|
+
return fn("connection", callback);
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
if (prop === "myPresence") {
|
|
339
|
+
return (callback: SubscriptionCallback<TIO, TPresence, "my-presence">) => {
|
|
340
|
+
return fn("my-presence", callback);
|
|
341
|
+
};
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
if (prop === "myself") {
|
|
345
|
+
return (callback: SubscriptionCallback<TIO, TPresence, "myself">) => {
|
|
346
|
+
return fn("myself", callback);
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
if (prop === "others") {
|
|
351
|
+
return (callback: OthersSubscriptionCallback<TIO, TPresence>) => {
|
|
352
|
+
return this._usersNotifier.subscribeOthers(callback);
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
if (prop === "storageLoaded") {
|
|
357
|
+
return (callback: SubscriptionCallback<TIO, TPresence, "storage-loaded">) => {
|
|
358
|
+
return fn("storage-loaded", callback);
|
|
359
|
+
};
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
if (prop === "event") return this.event;
|
|
363
|
+
if (prop === "other") return this.other;
|
|
364
|
+
if (prop === "storage") return this.storage;
|
|
365
|
+
},
|
|
366
|
+
},
|
|
367
|
+
) as SubscribeProxy<TIO, TPresence, InferStorage<TCrdt>, TEvents>;
|
|
298
368
|
|
|
299
369
|
public transact = (fn: (storage: InferStorage<TCrdt>) => void, origin?: string): void => {
|
|
300
370
|
const _origin = origin ?? this._state.connection.id;
|
package/src/PluvClient.ts
CHANGED
|
@@ -24,8 +24,8 @@ import type { PluvClientLimits, PublicKey, WithMetadata } from "./types";
|
|
|
24
24
|
|
|
25
25
|
export type PluvClientOptions<
|
|
26
26
|
TIO extends IOLike<any, any>,
|
|
27
|
-
TPresence extends
|
|
28
|
-
TCrdt extends AbstractCrdtDocFactory<any>,
|
|
27
|
+
TPresence extends Record<string, any>,
|
|
28
|
+
TCrdt extends AbstractCrdtDocFactory<any, any>,
|
|
29
29
|
TMetadata extends JsonObject,
|
|
30
30
|
> = RoomEndpoints<TIO, TMetadata> & {
|
|
31
31
|
debug?: boolean;
|
|
@@ -43,8 +43,8 @@ export type PluvClientOptions<
|
|
|
43
43
|
|
|
44
44
|
export type CreateRoomOptions<
|
|
45
45
|
TIO extends IOLike<any, any>,
|
|
46
|
-
TPresence extends
|
|
47
|
-
TCrdt extends AbstractCrdtDocFactory<any>,
|
|
46
|
+
TPresence extends Record<string, any>,
|
|
47
|
+
TCrdt extends AbstractCrdtDocFactory<any, any>,
|
|
48
48
|
TMetadata extends JsonObject,
|
|
49
49
|
TEvents extends PluvRouterEventConfig<TIO, TPresence, InferStorage<TCrdt>> = {},
|
|
50
50
|
> = {
|
|
@@ -63,8 +63,8 @@ export type EnterRoomParams<TMetadata extends JsonObject = {}> = keyof TMetadata
|
|
|
63
63
|
|
|
64
64
|
export class PluvClient<
|
|
65
65
|
TIO extends IOLike<any, any>,
|
|
66
|
-
TPresence extends
|
|
67
|
-
TCrdt extends AbstractCrdtDocFactory<any> = NoopCrdtDocFactory,
|
|
66
|
+
TPresence extends Record<string, any> = {},
|
|
67
|
+
TCrdt extends AbstractCrdtDocFactory<any, any> = NoopCrdtDocFactory,
|
|
68
68
|
TMetadata extends JsonObject = {},
|
|
69
69
|
> {
|
|
70
70
|
public readonly metadata?: InputZodLike<TMetadata>;
|
|
@@ -84,8 +84,8 @@ export class PluvClient<
|
|
|
84
84
|
};
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
-
public get procedure(): PluvProcedure<TIO, {}, {}, TPresence,
|
|
88
|
-
return new PluvProcedure<TIO, {}, {}, TPresence,
|
|
87
|
+
public get procedure(): PluvProcedure<TIO, {}, {}, TPresence, TCrdt, ""> {
|
|
88
|
+
return new PluvProcedure<TIO, {}, {}, TPresence, TCrdt, "">();
|
|
89
89
|
}
|
|
90
90
|
|
|
91
91
|
constructor(options: PluvClientOptions<TIO, TPresence, TCrdt, TMetadata>) {
|
package/src/PluvProcedure.ts
CHANGED
|
@@ -1,29 +1,34 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { AbstractCrdtDocFactory, InferDocLike } from "@pluv/crdt";
|
|
2
2
|
import type { EventRecord, IOLike, InputZodLike, JsonObject, ProcedureLike } from "@pluv/types";
|
|
3
3
|
import type { EventResolver, MergeEventRecords } from "./types";
|
|
4
4
|
|
|
5
5
|
export interface PluvProcedureConfig<
|
|
6
|
-
TIO extends IOLike
|
|
7
|
-
TInput extends JsonObject
|
|
8
|
-
TOutput extends EventRecord<string, any
|
|
9
|
-
TPresence extends
|
|
10
|
-
|
|
6
|
+
TIO extends IOLike,
|
|
7
|
+
TInput extends JsonObject,
|
|
8
|
+
TOutput extends EventRecord<string, any>,
|
|
9
|
+
TPresence extends Record<string, any>,
|
|
10
|
+
TCrdt extends AbstractCrdtDocFactory<any, any>,
|
|
11
11
|
> {
|
|
12
|
-
broadcast?: EventResolver<TIO, TInput, TOutput, TPresence,
|
|
12
|
+
broadcast?: EventResolver<TIO, TInput, TOutput, TPresence, InferDocLike<TCrdt>> | null;
|
|
13
13
|
input?: InputZodLike<TInput>;
|
|
14
14
|
}
|
|
15
15
|
|
|
16
16
|
export class PluvProcedure<
|
|
17
|
-
TIO extends IOLike
|
|
18
|
-
TInput extends JsonObject
|
|
19
|
-
TOutput extends EventRecord<string, any
|
|
20
|
-
TPresence extends
|
|
21
|
-
|
|
22
|
-
TFilled extends "input" | "broadcast" | ""
|
|
17
|
+
TIO extends IOLike,
|
|
18
|
+
TInput extends JsonObject,
|
|
19
|
+
TOutput extends EventRecord<string, any>,
|
|
20
|
+
TPresence extends Record<string, any>,
|
|
21
|
+
TCrdt extends AbstractCrdtDocFactory<any, any>,
|
|
22
|
+
TFilled extends "input" | "broadcast" | "",
|
|
23
23
|
> implements ProcedureLike<TInput, TOutput>
|
|
24
24
|
{
|
|
25
|
-
private _broadcast: EventResolver<
|
|
26
|
-
|
|
25
|
+
private _broadcast: EventResolver<
|
|
26
|
+
TIO,
|
|
27
|
+
TInput,
|
|
28
|
+
Partial<TOutput>,
|
|
29
|
+
TPresence,
|
|
30
|
+
InferDocLike<TCrdt>
|
|
31
|
+
> | null = null;
|
|
27
32
|
private _input: InputZodLike<TInput> | null = null;
|
|
28
33
|
|
|
29
34
|
public get config(): ProcedureLike<TInput, TOutput>["config"] {
|
|
@@ -34,7 +39,7 @@ export class PluvProcedure<
|
|
|
34
39
|
} as ProcedureLike<TInput, TOutput>["config"];
|
|
35
40
|
}
|
|
36
41
|
|
|
37
|
-
constructor(config: PluvProcedureConfig<TIO, TInput, TOutput, TPresence,
|
|
42
|
+
constructor(config: PluvProcedureConfig<TIO, TInput, TOutput, TPresence, TCrdt> = {}) {
|
|
38
43
|
const { broadcast, input } = config;
|
|
39
44
|
|
|
40
45
|
this._broadcast = broadcast ?? null;
|
|
@@ -42,14 +47,14 @@ export class PluvProcedure<
|
|
|
42
47
|
}
|
|
43
48
|
|
|
44
49
|
public broadcast<TResult extends EventRecord<string, any> = {}>(
|
|
45
|
-
resolver: EventResolver<TIO, TInput, TResult, TPresence,
|
|
50
|
+
resolver: EventResolver<TIO, TInput, TResult, TPresence, InferDocLike<TCrdt>>,
|
|
46
51
|
): Omit<
|
|
47
52
|
PluvProcedure<
|
|
48
53
|
TIO,
|
|
49
54
|
TInput,
|
|
50
55
|
MergeEventRecords<[TOutput, TResult]>,
|
|
51
56
|
TPresence,
|
|
52
|
-
|
|
57
|
+
TCrdt,
|
|
53
58
|
TFilled | "input" | "broadcast"
|
|
54
59
|
>,
|
|
55
60
|
TFilled | "input" | "broadcast"
|
|
@@ -63,7 +68,7 @@ export class PluvProcedure<
|
|
|
63
68
|
TInput,
|
|
64
69
|
MergeEventRecords<[TOutput, TResult]>,
|
|
65
70
|
TPresence,
|
|
66
|
-
|
|
71
|
+
TCrdt,
|
|
67
72
|
TFilled | "input" | "broadcast"
|
|
68
73
|
>({
|
|
69
74
|
...(this.config as any),
|
|
@@ -73,14 +78,11 @@ export class PluvProcedure<
|
|
|
73
78
|
|
|
74
79
|
public input<TData extends JsonObject>(
|
|
75
80
|
input: InputZodLike<TData>,
|
|
76
|
-
): Omit<
|
|
77
|
-
PluvProcedure<TIO, TData, {}, TPresence,
|
|
78
|
-
TFilled | "input"
|
|
79
|
-
> {
|
|
80
|
-
return new PluvProcedure<TIO, TData, {}, TPresence, TStorage, TFilled | "input">({ input });
|
|
81
|
+
): Omit<PluvProcedure<TIO, TData, {}, TPresence, TCrdt, TFilled | "input">, TFilled | "input"> {
|
|
82
|
+
return new PluvProcedure<TIO, TData, {}, TPresence, TCrdt, TFilled | "input">({ input });
|
|
81
83
|
}
|
|
82
84
|
|
|
83
|
-
private _resolver(): EventResolver<TIO, TInput, TOutput, TPresence,
|
|
85
|
+
private _resolver(): EventResolver<TIO, TInput, TOutput, TPresence, InferDocLike<TCrdt>> {
|
|
84
86
|
return (data, context) => this._broadcast?.(data, context) as TOutput;
|
|
85
87
|
}
|
|
86
88
|
}
|