@pluv/client 0.15.0 → 0.16.1
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 +9 -9
- package/CHANGELOG.md +189 -37
- package/README.md +9 -12
- package/dist/index.d.mts +65 -77
- package/dist/index.d.ts +65 -77
- package/dist/index.js +271 -303
- package/dist/index.mjs +270 -313
- package/package.json +7 -11
- package/src/AbstractRoom.ts +13 -8
- package/src/CrdtManager.ts +55 -57
- package/src/CrdtNotifier.ts +12 -12
- package/src/MockedRoom.ts +44 -40
- package/src/OtherNotifier.ts +1 -1
- package/src/PluvClient.ts +4 -4
- package/src/PluvRoom.ts +67 -76
- package/src/StateNotifier.ts +8 -5
- package/src/index.ts +6 -11
- package/src/y.ts +0 -9
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pluv/client",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.16.1",
|
|
4
4
|
"description": "@pluv/io frontend client",
|
|
5
5
|
"author": "leedavidcs",
|
|
6
6
|
"license": "MIT",
|
|
@@ -18,19 +18,15 @@
|
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
20
|
"wonka": "^6.3.4",
|
|
21
|
-
"@pluv/crdt
|
|
22
|
-
"@pluv/types": "^0.
|
|
23
|
-
},
|
|
24
|
-
"peerDependencies": {
|
|
25
|
-
"yjs": "^13.0.0"
|
|
21
|
+
"@pluv/crdt": "^0.16.1",
|
|
22
|
+
"@pluv/types": "^0.16.1"
|
|
26
23
|
},
|
|
27
24
|
"devDependencies": {
|
|
28
25
|
"eslint": "^8.56.0",
|
|
29
|
-
"tsup": "^8.0.
|
|
30
|
-
"typescript": "^5.
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"eslint-config-pluv": "^0.15.0"
|
|
26
|
+
"tsup": "^8.0.2",
|
|
27
|
+
"typescript": "^5.3.3",
|
|
28
|
+
"@pluv/tsconfig": "^0.16.1",
|
|
29
|
+
"eslint-config-pluv": "^0.16.1"
|
|
34
30
|
},
|
|
35
31
|
"scripts": {
|
|
36
32
|
"build": "tsup src/index.ts --format esm,cjs --dts",
|
package/src/AbstractRoom.ts
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
|
-
import type { InferYjsSharedTypeJson } from "@pluv/crdt-yjs";
|
|
2
1
|
import type {
|
|
2
|
+
AbstractCrdtDoc,
|
|
3
|
+
AbstractCrdtType,
|
|
4
|
+
InferCrdtStorageJson,
|
|
5
|
+
} from "@pluv/crdt";
|
|
6
|
+
import type {
|
|
7
|
+
IOLike,
|
|
3
8
|
Id,
|
|
4
9
|
InferIOInput,
|
|
5
10
|
InferIOOutput,
|
|
6
|
-
IOLike,
|
|
7
11
|
JsonObject,
|
|
8
12
|
} from "@pluv/types";
|
|
9
|
-
import type { AbstractType, Doc } from "yjs";
|
|
10
13
|
import type { EventNotifierSubscriptionCallback } from "./EventNotifier";
|
|
11
14
|
import type { OtherNotifierSubscriptionCallback } from "./OtherNotifier";
|
|
12
15
|
import type {
|
|
@@ -18,7 +21,7 @@ import type { UserInfo, WebSocketConnection } from "./types";
|
|
|
18
21
|
export abstract class AbstractRoom<
|
|
19
22
|
TIO extends IOLike,
|
|
20
23
|
TPresence extends JsonObject = {},
|
|
21
|
-
TStorage extends Record<string,
|
|
24
|
+
TStorage extends Record<string, AbstractCrdtType<any, any>> = {},
|
|
22
25
|
> {
|
|
23
26
|
public readonly id: string;
|
|
24
27
|
|
|
@@ -26,6 +29,8 @@ export abstract class AbstractRoom<
|
|
|
26
29
|
this.id = room;
|
|
27
30
|
}
|
|
28
31
|
|
|
32
|
+
public abstract storageLoaded: boolean;
|
|
33
|
+
|
|
29
34
|
public abstract broadcast<TEvent extends keyof InferIOInput<TIO>>(
|
|
30
35
|
event: TEvent,
|
|
31
36
|
data: Id<InferIOInput<TIO>[TEvent]>,
|
|
@@ -35,7 +40,7 @@ export abstract class AbstractRoom<
|
|
|
35
40
|
|
|
36
41
|
public abstract canUndo(): boolean;
|
|
37
42
|
|
|
38
|
-
public abstract getDoc():
|
|
43
|
+
public abstract getDoc(): AbstractCrdtDoc<TStorage>;
|
|
39
44
|
|
|
40
45
|
public abstract event<TEvent extends keyof InferIOOutput<TIO>>(
|
|
41
46
|
event: TEvent,
|
|
@@ -56,7 +61,7 @@ export abstract class AbstractRoom<
|
|
|
56
61
|
|
|
57
62
|
public abstract getStorage<TKey extends keyof TStorage>(
|
|
58
63
|
key: TKey,
|
|
59
|
-
): TStorage[TKey];
|
|
64
|
+
): TStorage[TKey] | null;
|
|
60
65
|
|
|
61
66
|
public abstract other(
|
|
62
67
|
connectionId: string,
|
|
@@ -67,12 +72,12 @@ export abstract class AbstractRoom<
|
|
|
67
72
|
|
|
68
73
|
public abstract storage<TKey extends keyof TStorage>(
|
|
69
74
|
key: TKey,
|
|
70
|
-
fn: (value:
|
|
75
|
+
fn: (value: InferCrdtStorageJson<TStorage[TKey]>) => void,
|
|
71
76
|
): () => void;
|
|
72
77
|
|
|
73
78
|
public abstract storageRoot(
|
|
74
79
|
fn: (value: {
|
|
75
|
-
[P in keyof TStorage]:
|
|
80
|
+
[P in keyof TStorage]: InferCrdtStorageJson<TStorage[P]>;
|
|
76
81
|
}) => void,
|
|
77
82
|
): () => void;
|
|
78
83
|
|
package/src/CrdtManager.ts
CHANGED
|
@@ -1,47 +1,44 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import type {
|
|
2
|
+
AbstractCrdtDoc,
|
|
3
|
+
AbstractCrdtDocFactory,
|
|
4
|
+
AbstractCrdtType,
|
|
5
|
+
} from "@pluv/crdt";
|
|
6
|
+
import { noop } from "@pluv/crdt";
|
|
4
7
|
|
|
5
8
|
export type CrdtManagerOptions<
|
|
6
|
-
TStorage extends Record<string,
|
|
9
|
+
TStorage extends Record<string, AbstractCrdtType<any, any>> = {},
|
|
7
10
|
> = {
|
|
8
11
|
encodedState?: string | Uint8Array | null;
|
|
9
|
-
initialStorage?:
|
|
10
|
-
}
|
|
12
|
+
initialStorage?: AbstractCrdtDocFactory<TStorage>;
|
|
13
|
+
};
|
|
11
14
|
|
|
12
15
|
type CrdtManagerInitializeParams = {
|
|
13
|
-
onInitialized?: () => void;
|
|
16
|
+
onInitialized?: (state: string) => void;
|
|
14
17
|
origin?: any;
|
|
15
18
|
update: string | readonly string[];
|
|
16
|
-
}
|
|
19
|
+
};
|
|
17
20
|
|
|
18
|
-
export class CrdtManager<
|
|
19
|
-
|
|
21
|
+
export class CrdtManager<
|
|
22
|
+
TStorage extends Record<string, AbstractCrdtType<any, any>>,
|
|
23
|
+
> {
|
|
24
|
+
public doc: AbstractCrdtDoc<TStorage>;
|
|
20
25
|
public initialized: boolean = false;
|
|
21
26
|
|
|
22
|
-
|
|
27
|
+
private readonly _docFactory: AbstractCrdtDocFactory<TStorage>;
|
|
28
|
+
|
|
29
|
+
constructor(options: CrdtManagerOptions<TStorage>) {
|
|
23
30
|
const {
|
|
24
|
-
captureTimeout,
|
|
25
31
|
encodedState,
|
|
26
|
-
initialStorage
|
|
27
|
-
trackedOrigins = [],
|
|
32
|
+
initialStorage = noop.doc({}) as AbstractCrdtDocFactory<TStorage>,
|
|
28
33
|
} = options;
|
|
29
34
|
|
|
30
|
-
|
|
31
|
-
? doc<TStorage>().applyUpdate(encodedState)
|
|
32
|
-
: null;
|
|
33
|
-
|
|
34
|
-
if (_doc && !!Object.keys(_doc.toJSON()).length) {
|
|
35
|
-
this.doc = _doc;
|
|
36
|
-
this.trackOrigins({ captureTimeout, trackedOrigins });
|
|
37
|
-
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
_doc?.destroy();
|
|
35
|
+
this._docFactory = initialStorage;
|
|
42
36
|
|
|
43
|
-
this.doc =
|
|
44
|
-
|
|
37
|
+
this.doc = encodedState
|
|
38
|
+
? initialStorage
|
|
39
|
+
.getFresh()
|
|
40
|
+
.applyEncodedState({ update: encodedState })
|
|
41
|
+
: initialStorage.getFresh();
|
|
45
42
|
}
|
|
46
43
|
|
|
47
44
|
/**
|
|
@@ -70,58 +67,59 @@ export class CrdtManager<TStorage extends Record<string, AbstractType<any>>> {
|
|
|
70
67
|
}
|
|
71
68
|
|
|
72
69
|
public initialize(params: CrdtManagerInitializeParams): this {
|
|
73
|
-
const {
|
|
74
|
-
captureTimeout,
|
|
75
|
-
onInitialized,
|
|
76
|
-
origin,
|
|
77
|
-
trackedOrigins,
|
|
78
|
-
update,
|
|
79
|
-
} = params;
|
|
70
|
+
const { onInitialized, origin, update } = params;
|
|
80
71
|
|
|
81
72
|
const updates = typeof update === "string" ? [update] : update;
|
|
82
73
|
|
|
83
|
-
this.trackOrigins({ captureTimeout, trackedOrigins });
|
|
84
|
-
|
|
85
74
|
if (!updates.length) return this;
|
|
86
75
|
|
|
87
76
|
if (this.initialized) {
|
|
88
|
-
this._applyDocUpdates(this.doc, updates, origin);
|
|
77
|
+
this.doc = this._applyDocUpdates(this.doc, updates, origin).track();
|
|
89
78
|
|
|
90
79
|
return this;
|
|
91
80
|
}
|
|
92
81
|
|
|
93
|
-
const
|
|
82
|
+
const onEmpty = this._applyDocUpdates(
|
|
83
|
+
this._docFactory.getEmpty(),
|
|
84
|
+
updates,
|
|
85
|
+
origin,
|
|
86
|
+
);
|
|
94
87
|
|
|
95
|
-
|
|
88
|
+
if (!onEmpty.isEmpty()) {
|
|
89
|
+
onEmpty.destroy();
|
|
96
90
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
91
|
+
this.doc = this._applyDocUpdates(
|
|
92
|
+
this._docFactory.getFresh(),
|
|
93
|
+
updates,
|
|
94
|
+
origin,
|
|
95
|
+
).track();
|
|
96
|
+
this.initialized = true;
|
|
102
97
|
|
|
103
|
-
|
|
98
|
+
onInitialized?.(this.doc.getEncodedState());
|
|
104
99
|
|
|
105
|
-
|
|
100
|
+
return this;
|
|
101
|
+
}
|
|
106
102
|
|
|
107
|
-
|
|
108
|
-
|
|
103
|
+
onEmpty.destroy();
|
|
104
|
+
this.doc = this._docFactory.getInitialized().track();
|
|
105
|
+
this.initialized = true;
|
|
109
106
|
|
|
110
|
-
|
|
111
|
-
const { captureTimeout, trackedOrigins } = options;
|
|
107
|
+
onInitialized?.(this.doc.getEncodedState());
|
|
112
108
|
|
|
113
|
-
this
|
|
109
|
+
return this;
|
|
114
110
|
}
|
|
115
111
|
|
|
116
112
|
private _applyDocUpdates(
|
|
117
|
-
|
|
113
|
+
doc: AbstractCrdtDoc<TStorage>,
|
|
118
114
|
updates: readonly string[],
|
|
119
115
|
origin?: string,
|
|
120
|
-
):
|
|
121
|
-
|
|
122
|
-
|
|
116
|
+
): AbstractCrdtDoc<TStorage> {
|
|
117
|
+
doc.transact(() => {
|
|
118
|
+
doc.batchApplyEncodedState(
|
|
119
|
+
updates.map((update) => ({ origin, update })),
|
|
120
|
+
);
|
|
123
121
|
}, origin);
|
|
124
122
|
|
|
125
|
-
return
|
|
123
|
+
return doc;
|
|
126
124
|
}
|
|
127
125
|
}
|
package/src/CrdtNotifier.ts
CHANGED
|
@@ -1,37 +1,37 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { AbstractCrdtType, InferCrdtStorageJson } from "@pluv/crdt";
|
|
2
2
|
import { makeSubject, Subject, subscribe } from "wonka";
|
|
3
|
-
import type { AbstractType } from "yjs";
|
|
4
3
|
|
|
5
|
-
export class CrdtNotifier<
|
|
4
|
+
export class CrdtNotifier<
|
|
5
|
+
TStorage extends Record<string, AbstractCrdtType<any, any>>,
|
|
6
|
+
> {
|
|
6
7
|
public rootSubject = makeSubject<{
|
|
7
|
-
[P in keyof TStorage]:
|
|
8
|
+
[P in keyof TStorage]: InferCrdtStorageJson<TStorage[P]>;
|
|
8
9
|
}>();
|
|
9
10
|
|
|
10
11
|
public subjects = new Map<
|
|
11
12
|
keyof TStorage,
|
|
12
|
-
Subject<
|
|
13
|
+
Subject<InferCrdtStorageJson<TStorage[keyof TStorage]>> | null
|
|
13
14
|
>();
|
|
14
15
|
|
|
15
16
|
public subject<TKey extends keyof TStorage>(
|
|
16
17
|
key: TKey,
|
|
17
|
-
): Subject<
|
|
18
|
+
): Subject<InferCrdtStorageJson<TStorage[TKey]>> {
|
|
18
19
|
const subject = this.subjects.get(key);
|
|
19
20
|
|
|
20
21
|
if (subject) {
|
|
21
|
-
return subject as Subject<
|
|
22
|
+
return subject as Subject<InferCrdtStorageJson<TStorage[TKey]>>;
|
|
22
23
|
}
|
|
23
24
|
|
|
24
|
-
const newSubject =
|
|
25
|
-
makeSubject<InferYjsSharedTypeJson<TStorage[TKey]>>();
|
|
25
|
+
const newSubject = makeSubject<InferCrdtStorageJson<TStorage[TKey]>>();
|
|
26
26
|
|
|
27
27
|
this.subjects.set(key, newSubject);
|
|
28
28
|
|
|
29
|
-
return newSubject as Subject<
|
|
29
|
+
return newSubject as Subject<InferCrdtStorageJson<TStorage[TKey]>>;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
32
|
public subcribeRoot(
|
|
33
33
|
callback: (value: {
|
|
34
|
-
[P in keyof TStorage]:
|
|
34
|
+
[P in keyof TStorage]: InferCrdtStorageJson<TStorage[P]>;
|
|
35
35
|
}) => void,
|
|
36
36
|
): () => void {
|
|
37
37
|
return subscribe(callback)(this.rootSubject.source).unsubscribe;
|
|
@@ -39,7 +39,7 @@ export class CrdtNotifier<TStorage extends Record<string, AbstractType<any>>> {
|
|
|
39
39
|
|
|
40
40
|
public subscribe<TKey extends keyof TStorage>(
|
|
41
41
|
key: TKey,
|
|
42
|
-
callback: (value:
|
|
42
|
+
callback: (value: InferCrdtStorageJson<TStorage[TKey]>) => void,
|
|
43
43
|
): () => void {
|
|
44
44
|
const subject = this.subject(key);
|
|
45
45
|
|
package/src/MockedRoom.ts
CHANGED
|
@@ -1,14 +1,18 @@
|
|
|
1
|
-
import type { InferYjsSharedTypeJson } from "@pluv/crdt-yjs";
|
|
2
1
|
import type {
|
|
2
|
+
AbstractCrdtDoc,
|
|
3
|
+
AbstractCrdtType,
|
|
4
|
+
InferCrdtStorageJson,
|
|
5
|
+
} from "@pluv/crdt";
|
|
6
|
+
import type {
|
|
7
|
+
IOLike,
|
|
3
8
|
Id,
|
|
4
9
|
InferIOInput,
|
|
5
10
|
InferIOOutput,
|
|
6
|
-
IOLike,
|
|
7
11
|
JsonObject,
|
|
8
12
|
} from "@pluv/types";
|
|
9
|
-
import type { AbstractType, Doc } from "yjs";
|
|
10
13
|
import { AbstractRoom } from "./AbstractRoom";
|
|
11
|
-
import {
|
|
14
|
+
import type { CrdtManagerOptions } from "./CrdtManager";
|
|
15
|
+
import { CrdtManager } from "./CrdtManager";
|
|
12
16
|
import { CrdtNotifier } from "./CrdtNotifier";
|
|
13
17
|
import type { EventNotifierSubscriptionCallback } from "./EventNotifier";
|
|
14
18
|
import { EventNotifier } from "./EventNotifier";
|
|
@@ -19,6 +23,8 @@ import type {
|
|
|
19
23
|
SubscriptionCallback,
|
|
20
24
|
} from "./StateNotifier";
|
|
21
25
|
import { StateNotifier } from "./StateNotifier";
|
|
26
|
+
import type { UsersManagerConfig } from "./UsersManager";
|
|
27
|
+
import { UsersManager } from "./UsersManager";
|
|
22
28
|
import type {
|
|
23
29
|
InternalSubscriptions,
|
|
24
30
|
UserInfo,
|
|
@@ -26,8 +32,6 @@ import type {
|
|
|
26
32
|
WebSocketState,
|
|
27
33
|
} from "./types";
|
|
28
34
|
import { ConnectionState } from "./types";
|
|
29
|
-
import type { UsersManagerConfig } from "./UsersManager";
|
|
30
|
-
import { UsersManager } from "./UsersManager";
|
|
31
35
|
|
|
32
36
|
export type MockedRoomEvents<TIO extends IOLike> = Partial<{
|
|
33
37
|
[P in keyof InferIOInput<TIO>]: (
|
|
@@ -38,7 +42,7 @@ export type MockedRoomEvents<TIO extends IOLike> = Partial<{
|
|
|
38
42
|
export type MockedRoomConfig<
|
|
39
43
|
TIO extends IOLike,
|
|
40
44
|
TPresence extends JsonObject = {},
|
|
41
|
-
TStorage extends Record<string,
|
|
45
|
+
TStorage extends Record<string, AbstractCrdtType<any, any>> = {},
|
|
42
46
|
> = { events?: MockedRoomEvents<TIO> } & Omit<
|
|
43
47
|
CrdtManagerOptions<TStorage>,
|
|
44
48
|
"encodedState"
|
|
@@ -48,7 +52,7 @@ export type MockedRoomConfig<
|
|
|
48
52
|
export class MockedRoom<
|
|
49
53
|
TIO extends IOLike,
|
|
50
54
|
TPresence extends JsonObject = {},
|
|
51
|
-
TStorage extends Record<string,
|
|
55
|
+
TStorage extends Record<string, AbstractCrdtType<any, any>> = {},
|
|
52
56
|
> extends AbstractRoom<TIO, TPresence, TStorage> {
|
|
53
57
|
private _crdtManager: CrdtManager<TStorage>;
|
|
54
58
|
private _crdtNotifier = new CrdtNotifier<TStorage>();
|
|
@@ -95,6 +99,10 @@ export class MockedRoom<
|
|
|
95
99
|
this._observeCrdt();
|
|
96
100
|
}
|
|
97
101
|
|
|
102
|
+
public get storageLoaded(): boolean {
|
|
103
|
+
return true;
|
|
104
|
+
}
|
|
105
|
+
|
|
98
106
|
public broadcast<TEvent extends keyof InferIOInput<TIO>>(
|
|
99
107
|
event: TEvent,
|
|
100
108
|
data: Id<InferIOInput<TIO>[TEvent]>,
|
|
@@ -139,8 +147,8 @@ export class MockedRoom<
|
|
|
139
147
|
);
|
|
140
148
|
}
|
|
141
149
|
|
|
142
|
-
public getDoc():
|
|
143
|
-
return this._crdtManager.doc
|
|
150
|
+
public getDoc(): AbstractCrdtDoc<TStorage> {
|
|
151
|
+
return this._crdtManager.doc;
|
|
144
152
|
}
|
|
145
153
|
|
|
146
154
|
public getMyPresence = (): TPresence => {
|
|
@@ -163,14 +171,12 @@ export class MockedRoom<
|
|
|
163
171
|
|
|
164
172
|
public getStorage = <TKey extends keyof TStorage>(
|
|
165
173
|
key: TKey,
|
|
166
|
-
): TStorage[TKey] => {
|
|
174
|
+
): TStorage[TKey] | null => {
|
|
167
175
|
const sharedType = this._crdtManager.get(key);
|
|
168
176
|
|
|
169
|
-
if (typeof sharedType === "undefined")
|
|
170
|
-
throw new Error(`Could not find storege: ${key.toString()}`);
|
|
171
|
-
}
|
|
177
|
+
if (typeof sharedType === "undefined") return null;
|
|
172
178
|
|
|
173
|
-
return sharedType;
|
|
179
|
+
return sharedType.value;
|
|
174
180
|
};
|
|
175
181
|
|
|
176
182
|
public other = (
|
|
@@ -186,14 +192,14 @@ export class MockedRoom<
|
|
|
186
192
|
|
|
187
193
|
public storage = <TKey extends keyof TStorage>(
|
|
188
194
|
key: TKey,
|
|
189
|
-
fn: (value:
|
|
195
|
+
fn: (value: InferCrdtStorageJson<TStorage[TKey]>) => void,
|
|
190
196
|
): (() => void) => {
|
|
191
197
|
return this._crdtNotifier.subscribe(key, fn);
|
|
192
198
|
};
|
|
193
199
|
|
|
194
200
|
public storageRoot = (
|
|
195
201
|
fn: (value: {
|
|
196
|
-
[P in keyof TStorage]:
|
|
202
|
+
[P in keyof TStorage]: InferCrdtStorageJson<TStorage[P]>;
|
|
197
203
|
}) => void,
|
|
198
204
|
): (() => void) => {
|
|
199
205
|
return this._crdtNotifier.subcribeRoot(fn);
|
|
@@ -226,7 +232,9 @@ export class MockedRoom<
|
|
|
226
232
|
if (!crdtManager) return;
|
|
227
233
|
|
|
228
234
|
crdtManager.doc.transact(() => {
|
|
229
|
-
|
|
235
|
+
const storage = crdtManager.doc.get();
|
|
236
|
+
|
|
237
|
+
fn(storage);
|
|
230
238
|
}, _origin);
|
|
231
239
|
};
|
|
232
240
|
|
|
@@ -249,35 +257,31 @@ export class MockedRoom<
|
|
|
249
257
|
|
|
250
258
|
if (!this._crdtManager) return;
|
|
251
259
|
|
|
252
|
-
const unsubscribe = this._crdtManager.doc.subscribe(
|
|
253
|
-
|
|
254
|
-
const origin = _origin ?? null;
|
|
260
|
+
const unsubscribe = this._crdtManager.doc.subscribe((event) => {
|
|
261
|
+
const origin = event.origin ?? null;
|
|
255
262
|
|
|
256
|
-
|
|
257
|
-
|
|
263
|
+
if (!this._crdtManager) return;
|
|
264
|
+
if (origin === "$STORAGE_UPDATED") return;
|
|
258
265
|
|
|
259
|
-
|
|
266
|
+
const sharedTypes = this._crdtManager.doc.get();
|
|
260
267
|
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
268
|
+
const storageRoot = Object.entries(sharedTypes).reduce(
|
|
269
|
+
(acc, [prop, sharedType]) => {
|
|
270
|
+
if (!this._crdtManager) return acc;
|
|
264
271
|
|
|
265
|
-
|
|
272
|
+
const serialized = sharedType.toJson();
|
|
266
273
|
|
|
267
|
-
|
|
274
|
+
this._crdtNotifier.subject(prop).next(serialized);
|
|
268
275
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
},
|
|
276
|
-
);
|
|
276
|
+
return { ...acc, [prop]: serialized };
|
|
277
|
+
},
|
|
278
|
+
{} as {
|
|
279
|
+
[P in keyof TStorage]: InferCrdtStorageJson<TStorage[P]>;
|
|
280
|
+
},
|
|
281
|
+
);
|
|
277
282
|
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
);
|
|
283
|
+
this._crdtNotifier.rootSubject.next(storageRoot);
|
|
284
|
+
});
|
|
281
285
|
|
|
282
286
|
this._subscriptions.observeCrdt = unsubscribe;
|
|
283
287
|
}
|
package/src/OtherNotifier.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { Id, IOLike } from "@pluv/types";
|
|
2
2
|
import type { Subject } from "wonka";
|
|
3
3
|
import { makeSubject, subscribe } from "wonka";
|
|
4
|
-
import { UserInfo } from "./types";
|
|
4
|
+
import type { UserInfo } from "./types";
|
|
5
5
|
|
|
6
6
|
export type OtherNotifierSubscriptionCallback<TIO extends IOLike> = (
|
|
7
7
|
value: Id<UserInfo<TIO>> | null,
|
package/src/PluvClient.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
+
import type { AbstractCrdtType } from "@pluv/crdt";
|
|
1
2
|
import type { IOLike, JsonObject } from "@pluv/types";
|
|
2
|
-
import { AbstractType } from "yjs";
|
|
3
3
|
import {
|
|
4
4
|
AuthEndpoint,
|
|
5
5
|
PluvRoom,
|
|
@@ -30,10 +30,10 @@ export class PluvClient<TIO extends IOLike = IOLike> {
|
|
|
30
30
|
|
|
31
31
|
public createRoom = <
|
|
32
32
|
TPresence extends JsonObject = {},
|
|
33
|
-
TStorage extends Record<string,
|
|
33
|
+
TStorage extends Record<string, AbstractCrdtType<any, any>> = {},
|
|
34
34
|
>(
|
|
35
35
|
room: string,
|
|
36
|
-
options: PluvRoomOptions<TIO, TPresence, TStorage
|
|
36
|
+
options: PluvRoomOptions<TIO, TPresence, TStorage>,
|
|
37
37
|
): PluvRoom<TIO, TPresence, TStorage> => {
|
|
38
38
|
const oldRoom = this.getRoom<TPresence, TStorage>(room);
|
|
39
39
|
|
|
@@ -76,7 +76,7 @@ export class PluvClient<TIO extends IOLike = IOLike> {
|
|
|
76
76
|
|
|
77
77
|
public getRoom = <
|
|
78
78
|
TPresence extends JsonObject = {},
|
|
79
|
-
TStorage extends Record<string,
|
|
79
|
+
TStorage extends Record<string, AbstractCrdtType<any, any>> = {},
|
|
80
80
|
>(
|
|
81
81
|
room: string,
|
|
82
82
|
): PluvRoom<TIO, TPresence, TStorage> | null => {
|