@pluv/client 0.19.0 → 0.20.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 +77 -0
- package/README.md +0 -92
- package/dist/index.d.mts +28 -22
- package/dist/index.d.ts +28 -22
- package/dist/index.js +26 -14
- package/dist/index.mjs +26 -14
- package/package.json +5 -5
- package/src/AbstractRoom.ts +8 -5
- package/src/CrdtManager.ts +3 -3
- package/src/CrdtNotifier.ts +10 -10
- package/src/MockedRoom.ts +22 -12
- package/src/PluvClient.ts +5 -10
- package/src/PluvRoom.ts +33 -21
- package/src/index.ts +1 -1
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
> @pluv/client@0.
|
|
2
|
+
> @pluv/client@0.20.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 @@ CLI tsup v8.1.0
|
|
|
8
8
|
CLI Target: es6
|
|
9
9
|
ESM Build start
|
|
10
10
|
CJS Build start
|
|
11
|
-
ESM dist/index.mjs
|
|
12
|
-
ESM ⚡️ Build success in
|
|
13
|
-
CJS dist/index.js 42.
|
|
14
|
-
CJS ⚡️ Build success in
|
|
11
|
+
ESM dist/index.mjs 41.48 KB
|
|
12
|
+
ESM ⚡️ Build success in 74ms
|
|
13
|
+
CJS dist/index.js 42.74 KB
|
|
14
|
+
CJS ⚡️ Build success in 87ms
|
|
15
15
|
DTS Build start
|
|
16
|
-
DTS ⚡️ Build success in
|
|
17
|
-
DTS dist/index.d.mts 14.
|
|
18
|
-
DTS dist/index.d.ts 14.
|
|
16
|
+
DTS ⚡️ Build success in 3234ms
|
|
17
|
+
DTS dist/index.d.mts 14.64 KB
|
|
18
|
+
DTS dist/index.d.ts 14.64 KB
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,82 @@
|
|
|
1
1
|
# @pluv/client
|
|
2
2
|
|
|
3
|
+
## 0.20.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 9492085: **BREAKING**: `@pluv/crdt-yjs` and `@pluv/crdt-loro` have been updated so that the utilities to create shared-types/containers no-longer return a wrapper around the underlying shared-types and containers, but rather return the shared-types/containers directly.
|
|
8
|
+
|
|
9
|
+
This means that for methods such as `getStorage` from `@pluv/client` and `useStorage` from `@pluv/react`, the shared-types/containers are also returned instead of the wrapper types.
|
|
10
|
+
|
|
11
|
+
The motivation for these changes are so that pluv.io is supplementary to `yjs` and `loro-crdt`, instead of having these libraries be an internal implementation of pluv.io.
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
// Before
|
|
15
|
+
|
|
16
|
+
import { yjs } from "@pluv/crdt-yjs";
|
|
17
|
+
|
|
18
|
+
yjs.array([]); // Returns CrdtYjsArray
|
|
19
|
+
yjs.object([]); // Returns CrdtYjsObject
|
|
20
|
+
|
|
21
|
+
const room: PluvRoom = /* ... */;
|
|
22
|
+
|
|
23
|
+
room.getStorage("messages"); // Returns AbstractCrdtType
|
|
24
|
+
|
|
25
|
+
const [, sharedType] = useStorage("messages"); // sharedType is an AbstractCrdtType
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
```ts
|
|
29
|
+
// Now
|
|
30
|
+
|
|
31
|
+
import { yjs } from "@pluv/crdt-yjs";
|
|
32
|
+
|
|
33
|
+
yjs.array([]); // Returns yjs.Array
|
|
34
|
+
yjs.object([]); // Returns yjs.Map
|
|
35
|
+
|
|
36
|
+
const room: PluvRoom = /* ... */;
|
|
37
|
+
|
|
38
|
+
room.getStorage("messages"); // Returns yjs.AbstractType
|
|
39
|
+
|
|
40
|
+
const [, sharedType] = useStorage("messages"); // sharedType is a yjs.AbstractType
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
For `@pluv/crdt-loro` specifically, `@pluv/client` relies on [loro events and subscriptions](https://www.loro.dev/docs/tutorial/get_started#event) to detect changes. The `AbstractLoroCrdt` types previously called `Loro.commit` after each change as an abstraction, but now this no-longer happens. To ensure that changes to loro containers are properly handled in `@pluv/react`, make sure to commit your changes whenever possible:
|
|
44
|
+
|
|
45
|
+
```ts
|
|
46
|
+
// Before
|
|
47
|
+
|
|
48
|
+
const [data, container] = useStorage("messages");
|
|
49
|
+
|
|
50
|
+
// This automatically called Loro.commit under the hood and rerendered the page with updated data.
|
|
51
|
+
container.push(loro.object({ name: "John Doe", age: 35 }));
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
```ts
|
|
55
|
+
// Now
|
|
56
|
+
|
|
57
|
+
const [data, container] = useStorage("messages");
|
|
58
|
+
|
|
59
|
+
const doc = useDoc();
|
|
60
|
+
const transact = useTransact();
|
|
61
|
+
|
|
62
|
+
// Updates need to be committed back to the doc whenever the changes need to be emitted to other users
|
|
63
|
+
// The returned data also will not update until the changes are commited
|
|
64
|
+
|
|
65
|
+
// The two operations below are functionally equivalent
|
|
66
|
+
transact(() => {
|
|
67
|
+
container.push(loro.object({ name: "John Doe", age: 35 }));
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
container.push(loro.object({ name: "John Doe", age: 35 }));
|
|
71
|
+
doc.value.commit();
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Patch Changes
|
|
75
|
+
|
|
76
|
+
- Updated dependencies [9492085]
|
|
77
|
+
- @pluv/crdt@0.20.0
|
|
78
|
+
- @pluv/types@0.20.0
|
|
79
|
+
|
|
3
80
|
## 0.19.0
|
|
4
81
|
|
|
5
82
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -1,30 +1,3 @@
|
|
|
1
|
-
> **Disclaimer:**
|
|
2
|
-
> This package is currently in preview and may have breaking changes between versions. Please wait for a `v1.0.0` stable release before using this in production.
|
|
3
|
-
|
|
4
|
-
<h1 align="center">
|
|
5
|
-
<br />
|
|
6
|
-
<img src="https://github.com/pluv-io/pluv/blob/master/assets/pluv-icon-192x192.png?raw=true" alt="Pluv.IO" width="180" style="border-radius:16px" />
|
|
7
|
-
<br />
|
|
8
|
-
<a href="https://pluv.io/docs/introduction">Pluv.IO (preview)</a>
|
|
9
|
-
<br />
|
|
10
|
-
</h1>
|
|
11
|
-
|
|
12
|
-
<h3 align="center">Multi-platform, E2E type-safe realtime packages</h3>
|
|
13
|
-
<h4 align="center">💕 Inspired by <a href="https://trpc.io">trpc</a> 💕 <a href="https://docs.yjs.dev/">yjs</a> 💕 and <a href="https://developers.cloudflare.com/">Cloudflare</a> 💕 </h4>
|
|
14
|
-
|
|
15
|
-
<p align="center">
|
|
16
|
-
<a href="https://www.npmjs.com/package/@pluv/client">
|
|
17
|
-
<img src="https://img.shields.io/npm/v/@pluv/client" alt="npm @pluv/client" />
|
|
18
|
-
</a>
|
|
19
|
-
<a href="https://github.com/pluv-io/pluv/blob/master/LICENSE">
|
|
20
|
-
<img alt="GitHub" src="https://img.shields.io/github/license/pluv-io/pluv" alt="License MIT" />
|
|
21
|
-
</a>
|
|
22
|
-
<a href="https://commitizen.github.io/cz-cli/">
|
|
23
|
-
<img src="https://img.shields.io/badge/commitizen-friendly-brightgreen.svg" alt="Commitizen friendly" />
|
|
24
|
-
</a>
|
|
25
|
-
<img src="https://badgen.net/badge/-/TypeScript?icon=typescript&label&labelColor=blue&color=555555" alt="TypeScript" />
|
|
26
|
-
</p>
|
|
27
|
-
|
|
28
1
|
## `@pluv/client`
|
|
29
2
|
|
|
30
3
|
> Framework agnostic frontend client for [@pluv/io](https://www.npmjs.com/package/@pluv/io)
|
|
@@ -43,68 +16,3 @@ yarn add @pluv/client @pluv/crdt-yjs yjs
|
|
|
43
16
|
# pnpm
|
|
44
17
|
pnpm add @pluv/client @pluv/crdt-yjs yjs
|
|
45
18
|
```
|
|
46
|
-
|
|
47
|
-
If you plan on using presence and/or storage, make sure to also install `zod`.
|
|
48
|
-
|
|
49
|
-
## Basic Example
|
|
50
|
-
|
|
51
|
-
```ts
|
|
52
|
-
import { createClient } from "@pluv/client";
|
|
53
|
-
import { yjs } from "@pluv/crdt-yjs";
|
|
54
|
-
import { z } from "zod";
|
|
55
|
-
// Import the PluvIO instance as a type from your server file
|
|
56
|
-
import { type io } from "./server";
|
|
57
|
-
|
|
58
|
-
// Initialize the @pluv/client client
|
|
59
|
-
const client = createClient<typeof io>({
|
|
60
|
-
authEndpoint: (room) => {
|
|
61
|
-
return `https://localhost:3000/api/authorize?room=${room}`;
|
|
62
|
-
},
|
|
63
|
-
wsEndpoint: (room) => {
|
|
64
|
-
return `ws://localhost:3000/api/room/${room}`;
|
|
65
|
-
},
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
interface Presence {
|
|
69
|
-
cursor: { x: number; y: number } | null;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
interface Storage {
|
|
73
|
-
messages: readonly { name: string; message: string }[]
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// Create a room to join
|
|
77
|
-
const room = client.createRoom<Presence, Storage>("my-room", {
|
|
78
|
-
initialPresence: { cursor: null },
|
|
79
|
-
initialStorage: yjs.doc(() => ({ messages: yjs.array([]) })),
|
|
80
|
-
onAuthorizationFail: (error) => {
|
|
81
|
-
console.log(error.message);
|
|
82
|
-
},
|
|
83
|
-
presence: z.object({
|
|
84
|
-
cursor: z.nullable(
|
|
85
|
-
z.object({
|
|
86
|
-
x: z.number(),
|
|
87
|
-
y: z.number(),
|
|
88
|
-
})
|
|
89
|
-
),
|
|
90
|
-
}),
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
const main = async () => {
|
|
94
|
-
await client.enter(room);
|
|
95
|
-
|
|
96
|
-
const unsubscribe = client.event.RECEIVE_MESSAGE(({ data }) => {
|
|
97
|
-
console.log(data.message);
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
client.broadcast.SEND_MESSAGE({ message: "Hello world!" });
|
|
101
|
-
|
|
102
|
-
unsubscribe();
|
|
103
|
-
|
|
104
|
-
client.leave(room);
|
|
105
|
-
};
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
## Reference
|
|
109
|
-
|
|
110
|
-
Check us out on [GitHub](https://github.com/pluv-io/pluv) for more information on how to use `@pluv/io`.
|
package/dist/index.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export {
|
|
1
|
+
import { CrdtType, AbstractCrdtDoc, InferCrdtJson, AbstractCrdtDocFactory } from '@pluv/crdt';
|
|
2
|
+
export { CrdtType, InferCrdtJson } from '@pluv/crdt';
|
|
3
3
|
import * as _pluv_types from '@pluv/types';
|
|
4
4
|
import { IOLike, InferIOOutput, Id, IOEventMessage, JsonObject, InferIOAuthorizeUser, InferIOAuthorize, InferIOInput, InputZodLike, InferIOAuthorizeRequired } from '@pluv/types';
|
|
5
5
|
export { BaseUser, EventMessage, EventRecord, IOEventMessage } from '@pluv/types';
|
|
@@ -47,7 +47,7 @@ interface StateNotifierSubjects<TIO extends IOLike, TPresence extends JsonObject
|
|
|
47
47
|
type InferSubjectValue<TIO extends IOLike, TPresence extends JsonObject, TSubject extends keyof StateNotifierSubjects<TIO, TPresence>> = StateNotifierSubjects<TIO, TPresence>[TSubject] extends Subject<infer IValue> ? Id<IValue> : never;
|
|
48
48
|
type SubscriptionCallback<TIO extends IOLike, TPresence extends JsonObject, TSubject extends keyof StateNotifierSubjects<TIO, TPresence>> = (value: InferSubjectValue<TIO, TPresence, TSubject>) => void;
|
|
49
49
|
|
|
50
|
-
declare abstract class AbstractRoom<TIO extends IOLike, TPresence extends JsonObject = {}, TStorage extends Record<string,
|
|
50
|
+
declare abstract class AbstractRoom<TIO extends IOLike, TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}> {
|
|
51
51
|
readonly id: string;
|
|
52
52
|
constructor(room: string);
|
|
53
53
|
abstract storageLoaded: boolean;
|
|
@@ -61,12 +61,14 @@ declare abstract class AbstractRoom<TIO extends IOLike, TPresence extends JsonOb
|
|
|
61
61
|
abstract getMyself(): Id<UserInfo<TIO, TPresence>> | null;
|
|
62
62
|
abstract getOther(connectionId: string): Id<UserInfo<TIO, TPresence>> | null;
|
|
63
63
|
abstract getOthers(): readonly Id<UserInfo<TIO, TPresence>>[];
|
|
64
|
-
abstract getStorage<TKey extends keyof TStorage>(
|
|
64
|
+
abstract getStorage<TKey extends keyof TStorage>(type: TKey): TStorage[TKey] | null;
|
|
65
|
+
abstract getStorageJson(): InferCrdtJson<TStorage> | null;
|
|
66
|
+
abstract getStorageJson<TKey extends keyof TStorage>(type: TKey): InferCrdtJson<TStorage[TKey]> | null;
|
|
65
67
|
abstract other(connectionId: string, callback: OtherNotifierSubscriptionCallback<TIO>): () => void;
|
|
66
68
|
abstract redo(): void;
|
|
67
|
-
abstract storage<TKey extends keyof TStorage>(key: TKey, fn: (value:
|
|
69
|
+
abstract storage<TKey extends keyof TStorage>(key: TKey, fn: (value: InferCrdtJson<TStorage[TKey]>) => void): () => void;
|
|
68
70
|
abstract storageRoot(fn: (value: {
|
|
69
|
-
[P in keyof TStorage]:
|
|
71
|
+
[P in keyof TStorage]: InferCrdtJson<TStorage[P]>;
|
|
70
72
|
}) => void): () => void;
|
|
71
73
|
abstract subscribe<TSubject extends keyof StateNotifierSubjects<TIO, TPresence>>(name: TSubject, callback: SubscriptionCallback<TIO, TPresence, TSubject>): () => void;
|
|
72
74
|
abstract transact(fn: (storage: TStorage) => void, origin?: string): void;
|
|
@@ -85,7 +87,7 @@ declare abstract class AbstractStorageStore {
|
|
|
85
87
|
abstract initialize(): Promise<void>;
|
|
86
88
|
}
|
|
87
89
|
|
|
88
|
-
type CrdtManagerOptions<TStorage extends Record<string,
|
|
90
|
+
type CrdtManagerOptions<TStorage extends Record<string, CrdtType<any, any>> = {}> = {
|
|
89
91
|
encodedState?: string | Uint8Array | null;
|
|
90
92
|
initialStorage?: AbstractCrdtDocFactory<TStorage>;
|
|
91
93
|
};
|
|
@@ -98,10 +100,10 @@ type UsersManagerConfig<TPresence extends JsonObject = {}> = {
|
|
|
98
100
|
type MockedRoomEvents<TIO extends IOLike> = Partial<{
|
|
99
101
|
[P in keyof InferIOInput<TIO>]: (data: Id<InferIOInput<TIO>[P]>) => Partial<InferIOOutput<TIO>>;
|
|
100
102
|
}>;
|
|
101
|
-
type MockedRoomConfig<TIO extends IOLike, TPresence extends JsonObject = {}, TStorage extends Record<string,
|
|
103
|
+
type MockedRoomConfig<TIO extends IOLike, TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}> = {
|
|
102
104
|
events?: MockedRoomEvents<TIO>;
|
|
103
105
|
} & Omit<CrdtManagerOptions<TStorage>, "encodedState"> & UsersManagerConfig<TPresence>;
|
|
104
|
-
declare class MockedRoom<TIO extends IOLike, TPresence extends JsonObject = {}, TStorage extends Record<string,
|
|
106
|
+
declare class MockedRoom<TIO extends IOLike, TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}> extends AbstractRoom<TIO, TPresence, TStorage> {
|
|
105
107
|
private _crdtManager;
|
|
106
108
|
private _crdtNotifier;
|
|
107
109
|
private _eventNotifier;
|
|
@@ -123,11 +125,13 @@ declare class MockedRoom<TIO extends IOLike, TPresence extends JsonObject = {},
|
|
|
123
125
|
getMyself: () => Id<UserInfo<TIO, TPresence>> | null;
|
|
124
126
|
getOther: (connectionId: string) => Id<UserInfo<TIO, TPresence>> | null;
|
|
125
127
|
getOthers: () => readonly Id<UserInfo<TIO, TPresence>>[];
|
|
126
|
-
getStorage: <TKey extends keyof TStorage>(
|
|
128
|
+
getStorage: <TKey extends keyof TStorage>(type: TKey) => TStorage[TKey] | null;
|
|
129
|
+
getStorageJson(): InferCrdtJson<TStorage> | null;
|
|
130
|
+
getStorageJson<TKey extends keyof TStorage>(type: TKey): InferCrdtJson<TStorage[TKey]> | null;
|
|
127
131
|
other: (connectionId: string, callback: OtherNotifierSubscriptionCallback<TIO>) => (() => void);
|
|
128
132
|
redo: () => void;
|
|
129
|
-
storage: <TKey extends keyof TStorage>(key: TKey, fn: (value:
|
|
130
|
-
storageRoot: (fn: (value: { [P in keyof TStorage]:
|
|
133
|
+
storage: <TKey extends keyof TStorage>(key: TKey, fn: (value: InferCrdtJson<TStorage[TKey]>) => void) => (() => void);
|
|
134
|
+
storageRoot: (fn: (value: { [P in keyof TStorage]: InferCrdtJson<TStorage[P]>; }) => void) => (() => void);
|
|
131
135
|
subscribe: <TSubject extends keyof StateNotifierSubjects<TIO, TPresence>>(name: TSubject, callback: SubscriptionCallback<TIO, TPresence, TSubject>) => (() => void);
|
|
132
136
|
transact: (fn: (storage: TStorage) => void, origin?: string) => void;
|
|
133
137
|
undo: () => void;
|
|
@@ -155,8 +159,8 @@ type RoomEndpoints<TIO extends IOLike> = {
|
|
|
155
159
|
} : {
|
|
156
160
|
authEndpoint?: undefined;
|
|
157
161
|
});
|
|
158
|
-
type PluvRoomAddon<TIO extends IOLike = IOLike, TPresence extends JsonObject = {}, TStorage extends Record<string,
|
|
159
|
-
interface PluvRoomAddonInput<TIO extends IOLike = IOLike, TPresence extends JsonObject = {}, TStorage extends Record<string,
|
|
162
|
+
type PluvRoomAddon<TIO extends IOLike = IOLike, TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}> = (input: PluvRoomAddonInput<TIO, TPresence, TStorage>) => Partial<PluvRoomAddonResult>;
|
|
163
|
+
interface PluvRoomAddonInput<TIO extends IOLike = IOLike, TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}> {
|
|
160
164
|
room: PluvRoom<TIO, TPresence, TStorage>;
|
|
161
165
|
}
|
|
162
166
|
interface PluvRoomAddonResult {
|
|
@@ -166,13 +170,13 @@ type PluvRoomDebug<TIO extends IOLike> = Id<{
|
|
|
166
170
|
output: readonly (keyof InferIOOutput<TIO>)[];
|
|
167
171
|
input: readonly (keyof InferIOInput<TIO>)[];
|
|
168
172
|
}>;
|
|
169
|
-
type PluvRoomOptions<TIO extends IOLike, TPresence extends JsonObject = {}, TStorage extends Record<string,
|
|
173
|
+
type PluvRoomOptions<TIO extends IOLike, TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}> = {
|
|
170
174
|
addons?: readonly PluvRoomAddon<TIO, TPresence, TStorage>[];
|
|
171
175
|
debug?: boolean | PluvRoomDebug<TIO>;
|
|
172
176
|
onAuthorizationFail?: (error: Error) => void;
|
|
173
177
|
} & Omit<CrdtManagerOptions<TStorage>, "encodedState"> & UsersManagerConfig<TPresence>;
|
|
174
|
-
type RoomConfig<TIO extends IOLike, TPresence extends JsonObject = {}, TStorage extends Record<string,
|
|
175
|
-
declare class PluvRoom<TIO extends IOLike, TPresence extends JsonObject = {}, TStorage extends Record<string,
|
|
178
|
+
type RoomConfig<TIO extends IOLike, TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}> = RoomEndpoints<TIO> & PluvRoomOptions<TIO, TPresence, TStorage>;
|
|
179
|
+
declare class PluvRoom<TIO extends IOLike, TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}> extends AbstractRoom<TIO, TPresence, TStorage> {
|
|
176
180
|
readonly _endpoints: RoomEndpoints<TIO>;
|
|
177
181
|
private _crdtManager;
|
|
178
182
|
private _crdtNotifier;
|
|
@@ -204,11 +208,13 @@ declare class PluvRoom<TIO extends IOLike, TPresence extends JsonObject = {}, TS
|
|
|
204
208
|
getMyself: () => Id<UserInfo<TIO, TPresence>> | null;
|
|
205
209
|
getOther: (connectionId: string) => Id<UserInfo<TIO, TPresence>> | null;
|
|
206
210
|
getOthers: () => readonly Id<UserInfo<TIO, TPresence>>[];
|
|
207
|
-
getStorage: <TKey extends keyof TStorage>(
|
|
211
|
+
getStorage: <TKey extends keyof TStorage>(type: TKey) => TStorage[TKey] | null;
|
|
212
|
+
getStorageJson(): InferCrdtJson<TStorage> | null;
|
|
213
|
+
getStorageJson<TKey extends keyof TStorage>(type: TKey): InferCrdtJson<TStorage[TKey]> | null;
|
|
208
214
|
other: (connectionId: string, callback: OtherNotifierSubscriptionCallback<TIO>) => (() => void);
|
|
209
215
|
redo: () => void;
|
|
210
|
-
storage: <TKey extends keyof TStorage>(key: TKey, fn: (value:
|
|
211
|
-
storageRoot: (fn: (value: { [P in keyof TStorage]:
|
|
216
|
+
storage: <TKey extends keyof TStorage>(key: TKey, fn: (value: InferCrdtJson<TStorage[TKey]>) => void) => (() => void);
|
|
217
|
+
storageRoot: (fn: (value: { [P in keyof TStorage]: InferCrdtJson<TStorage[P]>; }) => void) => (() => void);
|
|
212
218
|
subscribe: <TSubject extends keyof StateNotifierSubjects<TIO, TPresence>>(name: TSubject, callback: SubscriptionCallback<TIO, TPresence, TSubject>) => (() => void);
|
|
213
219
|
transact: (fn: (storage: TStorage) => void, origin?: string) => void;
|
|
214
220
|
undo: () => void;
|
|
@@ -273,9 +279,9 @@ declare class PluvClient<TIO extends IOLike = IOLike> {
|
|
|
273
279
|
private _wsEndpoint;
|
|
274
280
|
private _rooms;
|
|
275
281
|
constructor(options: PluvClientOptions<TIO>);
|
|
276
|
-
createRoom: <TPresence extends JsonObject = {}, TStorage extends Record<string,
|
|
282
|
+
createRoom: <TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}>(room: string, options: PluvRoomOptions<TIO, TPresence, TStorage>) => PluvRoom<TIO, TPresence, TStorage>;
|
|
277
283
|
enter: (room: string | PluvRoom<TIO, any, any>) => Promise<PluvRoom<TIO, JsonObject, any>>;
|
|
278
|
-
getRoom: <TPresence extends JsonObject = {}, TStorage extends Record<string,
|
|
284
|
+
getRoom: <TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}>(room: string) => PluvRoom<TIO, TPresence, TStorage> | null;
|
|
279
285
|
getRooms: () => readonly PluvRoom<TIO, JsonObject, any>[];
|
|
280
286
|
leave: (room: string | PluvRoom<TIO, any, any>) => Promise<void>;
|
|
281
287
|
private _logDebug;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export {
|
|
1
|
+
import { CrdtType, AbstractCrdtDoc, InferCrdtJson, AbstractCrdtDocFactory } from '@pluv/crdt';
|
|
2
|
+
export { CrdtType, InferCrdtJson } from '@pluv/crdt';
|
|
3
3
|
import * as _pluv_types from '@pluv/types';
|
|
4
4
|
import { IOLike, InferIOOutput, Id, IOEventMessage, JsonObject, InferIOAuthorizeUser, InferIOAuthorize, InferIOInput, InputZodLike, InferIOAuthorizeRequired } from '@pluv/types';
|
|
5
5
|
export { BaseUser, EventMessage, EventRecord, IOEventMessage } from '@pluv/types';
|
|
@@ -47,7 +47,7 @@ interface StateNotifierSubjects<TIO extends IOLike, TPresence extends JsonObject
|
|
|
47
47
|
type InferSubjectValue<TIO extends IOLike, TPresence extends JsonObject, TSubject extends keyof StateNotifierSubjects<TIO, TPresence>> = StateNotifierSubjects<TIO, TPresence>[TSubject] extends Subject<infer IValue> ? Id<IValue> : never;
|
|
48
48
|
type SubscriptionCallback<TIO extends IOLike, TPresence extends JsonObject, TSubject extends keyof StateNotifierSubjects<TIO, TPresence>> = (value: InferSubjectValue<TIO, TPresence, TSubject>) => void;
|
|
49
49
|
|
|
50
|
-
declare abstract class AbstractRoom<TIO extends IOLike, TPresence extends JsonObject = {}, TStorage extends Record<string,
|
|
50
|
+
declare abstract class AbstractRoom<TIO extends IOLike, TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}> {
|
|
51
51
|
readonly id: string;
|
|
52
52
|
constructor(room: string);
|
|
53
53
|
abstract storageLoaded: boolean;
|
|
@@ -61,12 +61,14 @@ declare abstract class AbstractRoom<TIO extends IOLike, TPresence extends JsonOb
|
|
|
61
61
|
abstract getMyself(): Id<UserInfo<TIO, TPresence>> | null;
|
|
62
62
|
abstract getOther(connectionId: string): Id<UserInfo<TIO, TPresence>> | null;
|
|
63
63
|
abstract getOthers(): readonly Id<UserInfo<TIO, TPresence>>[];
|
|
64
|
-
abstract getStorage<TKey extends keyof TStorage>(
|
|
64
|
+
abstract getStorage<TKey extends keyof TStorage>(type: TKey): TStorage[TKey] | null;
|
|
65
|
+
abstract getStorageJson(): InferCrdtJson<TStorage> | null;
|
|
66
|
+
abstract getStorageJson<TKey extends keyof TStorage>(type: TKey): InferCrdtJson<TStorage[TKey]> | null;
|
|
65
67
|
abstract other(connectionId: string, callback: OtherNotifierSubscriptionCallback<TIO>): () => void;
|
|
66
68
|
abstract redo(): void;
|
|
67
|
-
abstract storage<TKey extends keyof TStorage>(key: TKey, fn: (value:
|
|
69
|
+
abstract storage<TKey extends keyof TStorage>(key: TKey, fn: (value: InferCrdtJson<TStorage[TKey]>) => void): () => void;
|
|
68
70
|
abstract storageRoot(fn: (value: {
|
|
69
|
-
[P in keyof TStorage]:
|
|
71
|
+
[P in keyof TStorage]: InferCrdtJson<TStorage[P]>;
|
|
70
72
|
}) => void): () => void;
|
|
71
73
|
abstract subscribe<TSubject extends keyof StateNotifierSubjects<TIO, TPresence>>(name: TSubject, callback: SubscriptionCallback<TIO, TPresence, TSubject>): () => void;
|
|
72
74
|
abstract transact(fn: (storage: TStorage) => void, origin?: string): void;
|
|
@@ -85,7 +87,7 @@ declare abstract class AbstractStorageStore {
|
|
|
85
87
|
abstract initialize(): Promise<void>;
|
|
86
88
|
}
|
|
87
89
|
|
|
88
|
-
type CrdtManagerOptions<TStorage extends Record<string,
|
|
90
|
+
type CrdtManagerOptions<TStorage extends Record<string, CrdtType<any, any>> = {}> = {
|
|
89
91
|
encodedState?: string | Uint8Array | null;
|
|
90
92
|
initialStorage?: AbstractCrdtDocFactory<TStorage>;
|
|
91
93
|
};
|
|
@@ -98,10 +100,10 @@ type UsersManagerConfig<TPresence extends JsonObject = {}> = {
|
|
|
98
100
|
type MockedRoomEvents<TIO extends IOLike> = Partial<{
|
|
99
101
|
[P in keyof InferIOInput<TIO>]: (data: Id<InferIOInput<TIO>[P]>) => Partial<InferIOOutput<TIO>>;
|
|
100
102
|
}>;
|
|
101
|
-
type MockedRoomConfig<TIO extends IOLike, TPresence extends JsonObject = {}, TStorage extends Record<string,
|
|
103
|
+
type MockedRoomConfig<TIO extends IOLike, TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}> = {
|
|
102
104
|
events?: MockedRoomEvents<TIO>;
|
|
103
105
|
} & Omit<CrdtManagerOptions<TStorage>, "encodedState"> & UsersManagerConfig<TPresence>;
|
|
104
|
-
declare class MockedRoom<TIO extends IOLike, TPresence extends JsonObject = {}, TStorage extends Record<string,
|
|
106
|
+
declare class MockedRoom<TIO extends IOLike, TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}> extends AbstractRoom<TIO, TPresence, TStorage> {
|
|
105
107
|
private _crdtManager;
|
|
106
108
|
private _crdtNotifier;
|
|
107
109
|
private _eventNotifier;
|
|
@@ -123,11 +125,13 @@ declare class MockedRoom<TIO extends IOLike, TPresence extends JsonObject = {},
|
|
|
123
125
|
getMyself: () => Id<UserInfo<TIO, TPresence>> | null;
|
|
124
126
|
getOther: (connectionId: string) => Id<UserInfo<TIO, TPresence>> | null;
|
|
125
127
|
getOthers: () => readonly Id<UserInfo<TIO, TPresence>>[];
|
|
126
|
-
getStorage: <TKey extends keyof TStorage>(
|
|
128
|
+
getStorage: <TKey extends keyof TStorage>(type: TKey) => TStorage[TKey] | null;
|
|
129
|
+
getStorageJson(): InferCrdtJson<TStorage> | null;
|
|
130
|
+
getStorageJson<TKey extends keyof TStorage>(type: TKey): InferCrdtJson<TStorage[TKey]> | null;
|
|
127
131
|
other: (connectionId: string, callback: OtherNotifierSubscriptionCallback<TIO>) => (() => void);
|
|
128
132
|
redo: () => void;
|
|
129
|
-
storage: <TKey extends keyof TStorage>(key: TKey, fn: (value:
|
|
130
|
-
storageRoot: (fn: (value: { [P in keyof TStorage]:
|
|
133
|
+
storage: <TKey extends keyof TStorage>(key: TKey, fn: (value: InferCrdtJson<TStorage[TKey]>) => void) => (() => void);
|
|
134
|
+
storageRoot: (fn: (value: { [P in keyof TStorage]: InferCrdtJson<TStorage[P]>; }) => void) => (() => void);
|
|
131
135
|
subscribe: <TSubject extends keyof StateNotifierSubjects<TIO, TPresence>>(name: TSubject, callback: SubscriptionCallback<TIO, TPresence, TSubject>) => (() => void);
|
|
132
136
|
transact: (fn: (storage: TStorage) => void, origin?: string) => void;
|
|
133
137
|
undo: () => void;
|
|
@@ -155,8 +159,8 @@ type RoomEndpoints<TIO extends IOLike> = {
|
|
|
155
159
|
} : {
|
|
156
160
|
authEndpoint?: undefined;
|
|
157
161
|
});
|
|
158
|
-
type PluvRoomAddon<TIO extends IOLike = IOLike, TPresence extends JsonObject = {}, TStorage extends Record<string,
|
|
159
|
-
interface PluvRoomAddonInput<TIO extends IOLike = IOLike, TPresence extends JsonObject = {}, TStorage extends Record<string,
|
|
162
|
+
type PluvRoomAddon<TIO extends IOLike = IOLike, TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}> = (input: PluvRoomAddonInput<TIO, TPresence, TStorage>) => Partial<PluvRoomAddonResult>;
|
|
163
|
+
interface PluvRoomAddonInput<TIO extends IOLike = IOLike, TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}> {
|
|
160
164
|
room: PluvRoom<TIO, TPresence, TStorage>;
|
|
161
165
|
}
|
|
162
166
|
interface PluvRoomAddonResult {
|
|
@@ -166,13 +170,13 @@ type PluvRoomDebug<TIO extends IOLike> = Id<{
|
|
|
166
170
|
output: readonly (keyof InferIOOutput<TIO>)[];
|
|
167
171
|
input: readonly (keyof InferIOInput<TIO>)[];
|
|
168
172
|
}>;
|
|
169
|
-
type PluvRoomOptions<TIO extends IOLike, TPresence extends JsonObject = {}, TStorage extends Record<string,
|
|
173
|
+
type PluvRoomOptions<TIO extends IOLike, TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}> = {
|
|
170
174
|
addons?: readonly PluvRoomAddon<TIO, TPresence, TStorage>[];
|
|
171
175
|
debug?: boolean | PluvRoomDebug<TIO>;
|
|
172
176
|
onAuthorizationFail?: (error: Error) => void;
|
|
173
177
|
} & Omit<CrdtManagerOptions<TStorage>, "encodedState"> & UsersManagerConfig<TPresence>;
|
|
174
|
-
type RoomConfig<TIO extends IOLike, TPresence extends JsonObject = {}, TStorage extends Record<string,
|
|
175
|
-
declare class PluvRoom<TIO extends IOLike, TPresence extends JsonObject = {}, TStorage extends Record<string,
|
|
178
|
+
type RoomConfig<TIO extends IOLike, TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}> = RoomEndpoints<TIO> & PluvRoomOptions<TIO, TPresence, TStorage>;
|
|
179
|
+
declare class PluvRoom<TIO extends IOLike, TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}> extends AbstractRoom<TIO, TPresence, TStorage> {
|
|
176
180
|
readonly _endpoints: RoomEndpoints<TIO>;
|
|
177
181
|
private _crdtManager;
|
|
178
182
|
private _crdtNotifier;
|
|
@@ -204,11 +208,13 @@ declare class PluvRoom<TIO extends IOLike, TPresence extends JsonObject = {}, TS
|
|
|
204
208
|
getMyself: () => Id<UserInfo<TIO, TPresence>> | null;
|
|
205
209
|
getOther: (connectionId: string) => Id<UserInfo<TIO, TPresence>> | null;
|
|
206
210
|
getOthers: () => readonly Id<UserInfo<TIO, TPresence>>[];
|
|
207
|
-
getStorage: <TKey extends keyof TStorage>(
|
|
211
|
+
getStorage: <TKey extends keyof TStorage>(type: TKey) => TStorage[TKey] | null;
|
|
212
|
+
getStorageJson(): InferCrdtJson<TStorage> | null;
|
|
213
|
+
getStorageJson<TKey extends keyof TStorage>(type: TKey): InferCrdtJson<TStorage[TKey]> | null;
|
|
208
214
|
other: (connectionId: string, callback: OtherNotifierSubscriptionCallback<TIO>) => (() => void);
|
|
209
215
|
redo: () => void;
|
|
210
|
-
storage: <TKey extends keyof TStorage>(key: TKey, fn: (value:
|
|
211
|
-
storageRoot: (fn: (value: { [P in keyof TStorage]:
|
|
216
|
+
storage: <TKey extends keyof TStorage>(key: TKey, fn: (value: InferCrdtJson<TStorage[TKey]>) => void) => (() => void);
|
|
217
|
+
storageRoot: (fn: (value: { [P in keyof TStorage]: InferCrdtJson<TStorage[P]>; }) => void) => (() => void);
|
|
212
218
|
subscribe: <TSubject extends keyof StateNotifierSubjects<TIO, TPresence>>(name: TSubject, callback: SubscriptionCallback<TIO, TPresence, TSubject>) => (() => void);
|
|
213
219
|
transact: (fn: (storage: TStorage) => void, origin?: string) => void;
|
|
214
220
|
undo: () => void;
|
|
@@ -273,9 +279,9 @@ declare class PluvClient<TIO extends IOLike = IOLike> {
|
|
|
273
279
|
private _wsEndpoint;
|
|
274
280
|
private _rooms;
|
|
275
281
|
constructor(options: PluvClientOptions<TIO>);
|
|
276
|
-
createRoom: <TPresence extends JsonObject = {}, TStorage extends Record<string,
|
|
282
|
+
createRoom: <TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}>(room: string, options: PluvRoomOptions<TIO, TPresence, TStorage>) => PluvRoom<TIO, TPresence, TStorage>;
|
|
277
283
|
enter: (room: string | PluvRoom<TIO, any, any>) => Promise<PluvRoom<TIO, JsonObject, any>>;
|
|
278
|
-
getRoom: <TPresence extends JsonObject = {}, TStorage extends Record<string,
|
|
284
|
+
getRoom: <TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}>(room: string) => PluvRoom<TIO, TPresence, TStorage> | null;
|
|
279
285
|
getRooms: () => readonly PluvRoom<TIO, JsonObject, any>[];
|
|
280
286
|
leave: (room: string | PluvRoom<TIO, any, any>) => Promise<void>;
|
|
281
287
|
private _logDebug;
|
package/dist/index.js
CHANGED
|
@@ -369,10 +369,10 @@ var MockedRoom = class extends AbstractRoom {
|
|
|
369
369
|
this.getOthers = () => {
|
|
370
370
|
return this._usersManager.getOthers();
|
|
371
371
|
};
|
|
372
|
-
this.getStorage = (
|
|
373
|
-
const sharedType = this._crdtManager.get(
|
|
372
|
+
this.getStorage = (type) => {
|
|
373
|
+
const sharedType = this._crdtManager.get(type);
|
|
374
374
|
if (typeof sharedType === "undefined") return null;
|
|
375
|
-
return sharedType
|
|
375
|
+
return sharedType;
|
|
376
376
|
};
|
|
377
377
|
this.other = (connectionId, callback) => {
|
|
378
378
|
return this._otherNotifier.subscribe(connectionId, callback);
|
|
@@ -439,6 +439,11 @@ var MockedRoom = class extends AbstractRoom {
|
|
|
439
439
|
getDoc() {
|
|
440
440
|
return this._crdtManager.doc;
|
|
441
441
|
}
|
|
442
|
+
getStorageJson(type) {
|
|
443
|
+
if (this._state.connection.id === null) return null;
|
|
444
|
+
if (typeof type === "undefined") return this._crdtManager.doc.toJson();
|
|
445
|
+
return this._crdtManager.doc.toJson(type);
|
|
446
|
+
}
|
|
442
447
|
_observeCrdt() {
|
|
443
448
|
var _a, _b;
|
|
444
449
|
(_b = (_a = this._subscriptions).observeCrdt) == null ? void 0 : _b.call(_a);
|
|
@@ -449,10 +454,10 @@ var MockedRoom = class extends AbstractRoom {
|
|
|
449
454
|
if (!this._crdtManager) return;
|
|
450
455
|
if (origin === "$STORAGE_UPDATED") return;
|
|
451
456
|
const sharedTypes = this._crdtManager.doc.get();
|
|
452
|
-
const storageRoot = Object.
|
|
453
|
-
(acc,
|
|
457
|
+
const storageRoot = Object.keys(sharedTypes).reduce(
|
|
458
|
+
(acc, prop) => {
|
|
454
459
|
if (!this._crdtManager) return acc;
|
|
455
|
-
const serialized =
|
|
460
|
+
const serialized = this._crdtManager.doc.toJson(prop);
|
|
456
461
|
this._crdtNotifier.subject(prop).next(serialized);
|
|
457
462
|
return __spreadProps(__spreadValues({}, acc), { [prop]: serialized });
|
|
458
463
|
},
|
|
@@ -606,8 +611,8 @@ var PluvRoom = class extends AbstractRoom {
|
|
|
606
611
|
this.getOthers = () => {
|
|
607
612
|
return this._usersManager.getOthers();
|
|
608
613
|
};
|
|
609
|
-
this.getStorage = (
|
|
610
|
-
const sharedType = this._crdtManager.get(
|
|
614
|
+
this.getStorage = (type) => {
|
|
615
|
+
const sharedType = this._crdtManager.get(type);
|
|
611
616
|
if (typeof sharedType === "undefined") return null;
|
|
612
617
|
return sharedType;
|
|
613
618
|
};
|
|
@@ -744,6 +749,13 @@ var PluvRoom = class extends AbstractRoom {
|
|
|
744
749
|
this._stateNotifier.subjects["my-presence"].next(null);
|
|
745
750
|
});
|
|
746
751
|
}
|
|
752
|
+
getStorageJson(type) {
|
|
753
|
+
if (this._state.connection.id === null) return null;
|
|
754
|
+
if (typeof type === "undefined") return this._crdtManager.doc.toJson();
|
|
755
|
+
const sharedType = this._crdtManager.get(type);
|
|
756
|
+
if (typeof sharedType === "undefined") return null;
|
|
757
|
+
return this._crdtManager.doc.toJson(type);
|
|
758
|
+
}
|
|
747
759
|
_addToStorageStore(update) {
|
|
748
760
|
return __async(this, null, function* () {
|
|
749
761
|
yield this._storageStore.addUpdate(update);
|
|
@@ -830,9 +842,9 @@ var PluvRoom = class extends AbstractRoom {
|
|
|
830
842
|
}
|
|
831
843
|
_emitSharedTypes() {
|
|
832
844
|
const sharedTypes = this._crdtManager.doc.get();
|
|
833
|
-
const storageRoot = Object.
|
|
834
|
-
(acc,
|
|
835
|
-
const serialized =
|
|
845
|
+
const storageRoot = Object.keys(sharedTypes).reduce(
|
|
846
|
+
(acc, prop) => {
|
|
847
|
+
const serialized = this._crdtManager.doc.toJson(prop);
|
|
836
848
|
this._crdtNotifier.subject(prop).next(serialized);
|
|
837
849
|
return __spreadProps(__spreadValues({}, acc), { [prop]: serialized });
|
|
838
850
|
},
|
|
@@ -985,10 +997,10 @@ var PluvRoom = class extends AbstractRoom {
|
|
|
985
997
|
update: data.state
|
|
986
998
|
});
|
|
987
999
|
const sharedTypes = this._crdtManager.doc.get();
|
|
988
|
-
const storageRoot = Object.
|
|
989
|
-
(acc,
|
|
1000
|
+
const storageRoot = Object.keys(sharedTypes).reduce(
|
|
1001
|
+
(acc, prop) => {
|
|
990
1002
|
if (!this._crdtManager) return acc;
|
|
991
|
-
const serialized =
|
|
1003
|
+
const serialized = this._crdtManager.doc.toJson(prop);
|
|
992
1004
|
this._crdtNotifier.subject(prop).next(serialized);
|
|
993
1005
|
return __spreadProps(__spreadValues({}, acc), { [prop]: serialized });
|
|
994
1006
|
},
|
package/dist/index.mjs
CHANGED
|
@@ -340,10 +340,10 @@ var MockedRoom = class extends AbstractRoom {
|
|
|
340
340
|
this.getOthers = () => {
|
|
341
341
|
return this._usersManager.getOthers();
|
|
342
342
|
};
|
|
343
|
-
this.getStorage = (
|
|
344
|
-
const sharedType = this._crdtManager.get(
|
|
343
|
+
this.getStorage = (type) => {
|
|
344
|
+
const sharedType = this._crdtManager.get(type);
|
|
345
345
|
if (typeof sharedType === "undefined") return null;
|
|
346
|
-
return sharedType
|
|
346
|
+
return sharedType;
|
|
347
347
|
};
|
|
348
348
|
this.other = (connectionId, callback) => {
|
|
349
349
|
return this._otherNotifier.subscribe(connectionId, callback);
|
|
@@ -410,6 +410,11 @@ var MockedRoom = class extends AbstractRoom {
|
|
|
410
410
|
getDoc() {
|
|
411
411
|
return this._crdtManager.doc;
|
|
412
412
|
}
|
|
413
|
+
getStorageJson(type) {
|
|
414
|
+
if (this._state.connection.id === null) return null;
|
|
415
|
+
if (typeof type === "undefined") return this._crdtManager.doc.toJson();
|
|
416
|
+
return this._crdtManager.doc.toJson(type);
|
|
417
|
+
}
|
|
413
418
|
_observeCrdt() {
|
|
414
419
|
var _a, _b;
|
|
415
420
|
(_b = (_a = this._subscriptions).observeCrdt) == null ? void 0 : _b.call(_a);
|
|
@@ -420,10 +425,10 @@ var MockedRoom = class extends AbstractRoom {
|
|
|
420
425
|
if (!this._crdtManager) return;
|
|
421
426
|
if (origin === "$STORAGE_UPDATED") return;
|
|
422
427
|
const sharedTypes = this._crdtManager.doc.get();
|
|
423
|
-
const storageRoot = Object.
|
|
424
|
-
(acc,
|
|
428
|
+
const storageRoot = Object.keys(sharedTypes).reduce(
|
|
429
|
+
(acc, prop) => {
|
|
425
430
|
if (!this._crdtManager) return acc;
|
|
426
|
-
const serialized =
|
|
431
|
+
const serialized = this._crdtManager.doc.toJson(prop);
|
|
427
432
|
this._crdtNotifier.subject(prop).next(serialized);
|
|
428
433
|
return __spreadProps(__spreadValues({}, acc), { [prop]: serialized });
|
|
429
434
|
},
|
|
@@ -577,8 +582,8 @@ var PluvRoom = class extends AbstractRoom {
|
|
|
577
582
|
this.getOthers = () => {
|
|
578
583
|
return this._usersManager.getOthers();
|
|
579
584
|
};
|
|
580
|
-
this.getStorage = (
|
|
581
|
-
const sharedType = this._crdtManager.get(
|
|
585
|
+
this.getStorage = (type) => {
|
|
586
|
+
const sharedType = this._crdtManager.get(type);
|
|
582
587
|
if (typeof sharedType === "undefined") return null;
|
|
583
588
|
return sharedType;
|
|
584
589
|
};
|
|
@@ -715,6 +720,13 @@ var PluvRoom = class extends AbstractRoom {
|
|
|
715
720
|
this._stateNotifier.subjects["my-presence"].next(null);
|
|
716
721
|
});
|
|
717
722
|
}
|
|
723
|
+
getStorageJson(type) {
|
|
724
|
+
if (this._state.connection.id === null) return null;
|
|
725
|
+
if (typeof type === "undefined") return this._crdtManager.doc.toJson();
|
|
726
|
+
const sharedType = this._crdtManager.get(type);
|
|
727
|
+
if (typeof sharedType === "undefined") return null;
|
|
728
|
+
return this._crdtManager.doc.toJson(type);
|
|
729
|
+
}
|
|
718
730
|
_addToStorageStore(update) {
|
|
719
731
|
return __async(this, null, function* () {
|
|
720
732
|
yield this._storageStore.addUpdate(update);
|
|
@@ -801,9 +813,9 @@ var PluvRoom = class extends AbstractRoom {
|
|
|
801
813
|
}
|
|
802
814
|
_emitSharedTypes() {
|
|
803
815
|
const sharedTypes = this._crdtManager.doc.get();
|
|
804
|
-
const storageRoot = Object.
|
|
805
|
-
(acc,
|
|
806
|
-
const serialized =
|
|
816
|
+
const storageRoot = Object.keys(sharedTypes).reduce(
|
|
817
|
+
(acc, prop) => {
|
|
818
|
+
const serialized = this._crdtManager.doc.toJson(prop);
|
|
807
819
|
this._crdtNotifier.subject(prop).next(serialized);
|
|
808
820
|
return __spreadProps(__spreadValues({}, acc), { [prop]: serialized });
|
|
809
821
|
},
|
|
@@ -956,10 +968,10 @@ var PluvRoom = class extends AbstractRoom {
|
|
|
956
968
|
update: data.state
|
|
957
969
|
});
|
|
958
970
|
const sharedTypes = this._crdtManager.doc.get();
|
|
959
|
-
const storageRoot = Object.
|
|
960
|
-
(acc,
|
|
971
|
+
const storageRoot = Object.keys(sharedTypes).reduce(
|
|
972
|
+
(acc, prop) => {
|
|
961
973
|
if (!this._crdtManager) return acc;
|
|
962
|
-
const serialized =
|
|
974
|
+
const serialized = this._crdtManager.doc.toJson(prop);
|
|
963
975
|
this._crdtNotifier.subject(prop).next(serialized);
|
|
964
976
|
return __spreadProps(__spreadValues({}, acc), { [prop]: serialized });
|
|
965
977
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pluv/client",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.20.0",
|
|
4
4
|
"description": "@pluv/io frontend client",
|
|
5
5
|
"author": "leedavidcs",
|
|
6
6
|
"license": "MIT",
|
|
@@ -18,15 +18,15 @@
|
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
20
|
"wonka": "^6.3.4",
|
|
21
|
-
"@pluv/crdt": "^0.
|
|
22
|
-
"@pluv/types": "^0.
|
|
21
|
+
"@pluv/crdt": "^0.20.0",
|
|
22
|
+
"@pluv/types": "^0.20.0"
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
25
|
"eslint": "^8.57.0",
|
|
26
26
|
"tsup": "^8.1.0",
|
|
27
27
|
"typescript": "^5.4.5",
|
|
28
|
-
"@pluv/tsconfig": "^0.
|
|
29
|
-
"eslint-config-pluv": "^0.
|
|
28
|
+
"@pluv/tsconfig": "^0.20.0",
|
|
29
|
+
"eslint-config-pluv": "^0.20.0"
|
|
30
30
|
},
|
|
31
31
|
"scripts": {
|
|
32
32
|
"build": "tsup src/index.ts --format esm,cjs --dts",
|
package/src/AbstractRoom.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AbstractCrdtDoc,
|
|
1
|
+
import type { AbstractCrdtDoc, CrdtType, InferCrdtJson } from "@pluv/crdt";
|
|
2
2
|
import type { IOLike, Id, InferIOInput, InferIOOutput, JsonObject } from "@pluv/types";
|
|
3
3
|
import type { EventNotifierSubscriptionCallback } from "./EventNotifier";
|
|
4
4
|
import type { OtherNotifierSubscriptionCallback } from "./OtherNotifier";
|
|
@@ -8,7 +8,7 @@ import type { UpdateMyPresenceAction, UserInfo, WebSocketConnection } from "./ty
|
|
|
8
8
|
export abstract class AbstractRoom<
|
|
9
9
|
TIO extends IOLike,
|
|
10
10
|
TPresence extends JsonObject = {},
|
|
11
|
-
TStorage extends Record<string,
|
|
11
|
+
TStorage extends Record<string, CrdtType<any, any>> = {},
|
|
12
12
|
> {
|
|
13
13
|
public readonly id: string;
|
|
14
14
|
|
|
@@ -44,7 +44,10 @@ export abstract class AbstractRoom<
|
|
|
44
44
|
|
|
45
45
|
public abstract getOthers(): readonly Id<UserInfo<TIO, TPresence>>[];
|
|
46
46
|
|
|
47
|
-
public abstract getStorage<TKey extends keyof TStorage>(
|
|
47
|
+
public abstract getStorage<TKey extends keyof TStorage>(type: TKey): TStorage[TKey] | null;
|
|
48
|
+
|
|
49
|
+
public abstract getStorageJson(): InferCrdtJson<TStorage> | null;
|
|
50
|
+
public abstract getStorageJson<TKey extends keyof TStorage>(type: TKey): InferCrdtJson<TStorage[TKey]> | null;
|
|
48
51
|
|
|
49
52
|
public abstract other(connectionId: string, callback: OtherNotifierSubscriptionCallback<TIO>): () => void;
|
|
50
53
|
|
|
@@ -52,12 +55,12 @@ export abstract class AbstractRoom<
|
|
|
52
55
|
|
|
53
56
|
public abstract storage<TKey extends keyof TStorage>(
|
|
54
57
|
key: TKey,
|
|
55
|
-
fn: (value:
|
|
58
|
+
fn: (value: InferCrdtJson<TStorage[TKey]>) => void,
|
|
56
59
|
): () => void;
|
|
57
60
|
|
|
58
61
|
public abstract storageRoot(
|
|
59
62
|
fn: (value: {
|
|
60
|
-
[P in keyof TStorage]:
|
|
63
|
+
[P in keyof TStorage]: InferCrdtJson<TStorage[P]>;
|
|
61
64
|
}) => void,
|
|
62
65
|
): () => void;
|
|
63
66
|
|
package/src/CrdtManager.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import type { AbstractCrdtDoc, AbstractCrdtDocFactory,
|
|
1
|
+
import type { AbstractCrdtDoc, AbstractCrdtDocFactory, CrdtType } from "@pluv/crdt";
|
|
2
2
|
import { noop } from "@pluv/crdt";
|
|
3
3
|
|
|
4
|
-
export type CrdtManagerOptions<TStorage extends Record<string,
|
|
4
|
+
export type CrdtManagerOptions<TStorage extends Record<string, CrdtType<any, any>> = {}> = {
|
|
5
5
|
encodedState?: string | Uint8Array | null;
|
|
6
6
|
initialStorage?: AbstractCrdtDocFactory<TStorage>;
|
|
7
7
|
};
|
|
@@ -12,7 +12,7 @@ type CrdtManagerInitializeParams = {
|
|
|
12
12
|
update: string | readonly string[];
|
|
13
13
|
};
|
|
14
14
|
|
|
15
|
-
export class CrdtManager<TStorage extends Record<string,
|
|
15
|
+
export class CrdtManager<TStorage extends Record<string, CrdtType<any, any>>> {
|
|
16
16
|
public doc: AbstractCrdtDoc<TStorage>;
|
|
17
17
|
public initialized: boolean = false;
|
|
18
18
|
|
package/src/CrdtNotifier.ts
CHANGED
|
@@ -1,31 +1,31 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { CrdtType, InferCrdtJson } from "@pluv/crdt";
|
|
2
2
|
import type { Subject } from "wonka";
|
|
3
3
|
import { makeSubject, subscribe } from "wonka";
|
|
4
4
|
|
|
5
|
-
export class CrdtNotifier<TStorage extends Record<string,
|
|
5
|
+
export class CrdtNotifier<TStorage extends Record<string, CrdtType<any, any>>> {
|
|
6
6
|
public rootSubject = makeSubject<{
|
|
7
|
-
[P in keyof TStorage]:
|
|
7
|
+
[P in keyof TStorage]: InferCrdtJson<TStorage[P]>;
|
|
8
8
|
}>();
|
|
9
9
|
|
|
10
|
-
public subjects = new Map<keyof TStorage, Subject<
|
|
10
|
+
public subjects = new Map<keyof TStorage, Subject<InferCrdtJson<TStorage[keyof TStorage]>> | null>();
|
|
11
11
|
|
|
12
|
-
public subject<TKey extends keyof TStorage>(key: TKey): Subject<
|
|
12
|
+
public subject<TKey extends keyof TStorage>(key: TKey): Subject<InferCrdtJson<TStorage[TKey]>> {
|
|
13
13
|
const subject = this.subjects.get(key);
|
|
14
14
|
|
|
15
15
|
if (subject) {
|
|
16
|
-
return subject as Subject<
|
|
16
|
+
return subject as Subject<InferCrdtJson<TStorage[TKey]>>;
|
|
17
17
|
}
|
|
18
18
|
|
|
19
|
-
const newSubject = makeSubject<
|
|
19
|
+
const newSubject = makeSubject<InferCrdtJson<TStorage[TKey]>>();
|
|
20
20
|
|
|
21
21
|
this.subjects.set(key, newSubject);
|
|
22
22
|
|
|
23
|
-
return newSubject as Subject<
|
|
23
|
+
return newSubject as Subject<InferCrdtJson<TStorage[TKey]>>;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
public subcribeRoot(
|
|
27
27
|
callback: (value: {
|
|
28
|
-
[P in keyof TStorage]:
|
|
28
|
+
[P in keyof TStorage]: InferCrdtJson<TStorage[P]>;
|
|
29
29
|
}) => void,
|
|
30
30
|
): () => void {
|
|
31
31
|
return subscribe(callback)(this.rootSubject.source).unsubscribe;
|
|
@@ -33,7 +33,7 @@ export class CrdtNotifier<TStorage extends Record<string, AbstractCrdtType<any,
|
|
|
33
33
|
|
|
34
34
|
public subscribe<TKey extends keyof TStorage>(
|
|
35
35
|
key: TKey,
|
|
36
|
-
callback: (value:
|
|
36
|
+
callback: (value: InferCrdtJson<TStorage[TKey]>) => void,
|
|
37
37
|
): () => void {
|
|
38
38
|
const subject = this.subject(key);
|
|
39
39
|
|
package/src/MockedRoom.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AbstractCrdtDoc,
|
|
1
|
+
import type { AbstractCrdtDoc, CrdtType, InferCrdtJson } from "@pluv/crdt";
|
|
2
2
|
import type { IOLike, Id, InferIOInput, InferIOOutput, JsonObject } from "@pluv/types";
|
|
3
3
|
import { AbstractRoom } from "./AbstractRoom";
|
|
4
4
|
import type { CrdtManagerOptions } from "./CrdtManager";
|
|
@@ -28,14 +28,14 @@ export type MockedRoomEvents<TIO extends IOLike> = Partial<{
|
|
|
28
28
|
export type MockedRoomConfig<
|
|
29
29
|
TIO extends IOLike,
|
|
30
30
|
TPresence extends JsonObject = {},
|
|
31
|
-
TStorage extends Record<string,
|
|
31
|
+
TStorage extends Record<string, CrdtType<any, any>> = {},
|
|
32
32
|
> = { events?: MockedRoomEvents<TIO> } & Omit<CrdtManagerOptions<TStorage>, "encodedState"> &
|
|
33
33
|
UsersManagerConfig<TPresence>;
|
|
34
34
|
|
|
35
35
|
export class MockedRoom<
|
|
36
36
|
TIO extends IOLike,
|
|
37
37
|
TPresence extends JsonObject = {},
|
|
38
|
-
TStorage extends Record<string,
|
|
38
|
+
TStorage extends Record<string, CrdtType<any, any>> = {},
|
|
39
39
|
> extends AbstractRoom<TIO, TPresence, TStorage> {
|
|
40
40
|
private _crdtManager: CrdtManager<TStorage>;
|
|
41
41
|
private _crdtNotifier = new CrdtNotifier<TStorage>();
|
|
@@ -142,14 +142,24 @@ export class MockedRoom<
|
|
|
142
142
|
return this._usersManager.getOthers();
|
|
143
143
|
};
|
|
144
144
|
|
|
145
|
-
public getStorage = <TKey extends keyof TStorage>(
|
|
146
|
-
const sharedType = this._crdtManager.get(
|
|
145
|
+
public getStorage = <TKey extends keyof TStorage>(type: TKey): TStorage[TKey] | null => {
|
|
146
|
+
const sharedType = this._crdtManager.get(type);
|
|
147
147
|
|
|
148
148
|
if (typeof sharedType === "undefined") return null;
|
|
149
149
|
|
|
150
|
-
return sharedType
|
|
150
|
+
return sharedType;
|
|
151
151
|
};
|
|
152
152
|
|
|
153
|
+
public getStorageJson(): InferCrdtJson<TStorage> | null;
|
|
154
|
+
public getStorageJson<TKey extends keyof TStorage>(type: TKey): InferCrdtJson<TStorage[TKey]> | null;
|
|
155
|
+
public getStorageJson<TKey extends keyof TStorage>(type?: TKey) {
|
|
156
|
+
if (this._state.connection.id === null) return null;
|
|
157
|
+
|
|
158
|
+
if (typeof type === "undefined") return this._crdtManager.doc.toJson();
|
|
159
|
+
|
|
160
|
+
return this._crdtManager.doc.toJson(type);
|
|
161
|
+
}
|
|
162
|
+
|
|
153
163
|
public other = (connectionId: string, callback: OtherNotifierSubscriptionCallback<TIO>): (() => void) => {
|
|
154
164
|
return this._otherNotifier.subscribe(connectionId, callback);
|
|
155
165
|
};
|
|
@@ -160,14 +170,14 @@ export class MockedRoom<
|
|
|
160
170
|
|
|
161
171
|
public storage = <TKey extends keyof TStorage>(
|
|
162
172
|
key: TKey,
|
|
163
|
-
fn: (value:
|
|
173
|
+
fn: (value: InferCrdtJson<TStorage[TKey]>) => void,
|
|
164
174
|
): (() => void) => {
|
|
165
175
|
return this._crdtNotifier.subscribe(key, fn);
|
|
166
176
|
};
|
|
167
177
|
|
|
168
178
|
public storageRoot = (
|
|
169
179
|
fn: (value: {
|
|
170
|
-
[P in keyof TStorage]:
|
|
180
|
+
[P in keyof TStorage]: InferCrdtJson<TStorage[P]>;
|
|
171
181
|
}) => void,
|
|
172
182
|
): (() => void) => {
|
|
173
183
|
return this._crdtNotifier.subcribeRoot(fn);
|
|
@@ -230,18 +240,18 @@ export class MockedRoom<
|
|
|
230
240
|
|
|
231
241
|
const sharedTypes = this._crdtManager.doc.get();
|
|
232
242
|
|
|
233
|
-
const storageRoot = Object.
|
|
234
|
-
(acc,
|
|
243
|
+
const storageRoot = Object.keys(sharedTypes).reduce(
|
|
244
|
+
(acc, prop) => {
|
|
235
245
|
if (!this._crdtManager) return acc;
|
|
236
246
|
|
|
237
|
-
const serialized =
|
|
247
|
+
const serialized = this._crdtManager.doc.toJson(prop);
|
|
238
248
|
|
|
239
249
|
this._crdtNotifier.subject(prop).next(serialized);
|
|
240
250
|
|
|
241
251
|
return { ...acc, [prop]: serialized };
|
|
242
252
|
},
|
|
243
253
|
{} as {
|
|
244
|
-
[P in keyof TStorage]:
|
|
254
|
+
[P in keyof TStorage]: InferCrdtJson<TStorage[P]>;
|
|
245
255
|
},
|
|
246
256
|
);
|
|
247
257
|
|
package/src/PluvClient.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { CrdtType } from "@pluv/crdt";
|
|
2
2
|
import type { IOLike, JsonObject } from "@pluv/types";
|
|
3
|
-
import { AuthEndpoint,
|
|
3
|
+
import type { AuthEndpoint, PluvRoomOptions, RoomConfig, RoomEndpoints, WsEndpoint } from "./PluvRoom";
|
|
4
|
+
import { PluvRoom } from "./PluvRoom";
|
|
4
5
|
|
|
5
6
|
export type PluvClientOptions<TIO extends IOLike> = RoomEndpoints<TIO> & {
|
|
6
7
|
debug?: boolean;
|
|
@@ -21,10 +22,7 @@ export class PluvClient<TIO extends IOLike = IOLike> {
|
|
|
21
22
|
this._wsEndpoint = wsEndpoint;
|
|
22
23
|
}
|
|
23
24
|
|
|
24
|
-
public createRoom = <
|
|
25
|
-
TPresence extends JsonObject = {},
|
|
26
|
-
TStorage extends Record<string, AbstractCrdtType<any, any>> = {},
|
|
27
|
-
>(
|
|
25
|
+
public createRoom = <TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}>(
|
|
28
26
|
room: string,
|
|
29
27
|
options: PluvRoomOptions<TIO, TPresence, TStorage>,
|
|
30
28
|
): PluvRoom<TIO, TPresence, TStorage> => {
|
|
@@ -65,10 +63,7 @@ export class PluvClient<TIO extends IOLike = IOLike> {
|
|
|
65
63
|
return toEnter;
|
|
66
64
|
};
|
|
67
65
|
|
|
68
|
-
public getRoom = <
|
|
69
|
-
TPresence extends JsonObject = {},
|
|
70
|
-
TStorage extends Record<string, AbstractCrdtType<any, any>> = {},
|
|
71
|
-
>(
|
|
66
|
+
public getRoom = <TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}>(
|
|
72
67
|
room: string,
|
|
73
68
|
): PluvRoom<TIO, TPresence, TStorage> | null => {
|
|
74
69
|
const found = this._rooms.get(room) as PluvRoom<TIO, TPresence, TStorage> | undefined;
|
package/src/PluvRoom.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { AbstractCrdtDoc,
|
|
1
|
+
import type { AbstractCrdtDoc, CrdtType, InferCrdtJson } from "@pluv/crdt";
|
|
2
2
|
import type {
|
|
3
3
|
BaseIOEventRecord,
|
|
4
4
|
EventMessage,
|
|
@@ -47,7 +47,7 @@ const ORIGIN_STORAGE_UPDATED = "$STORAGE_UPDATED";
|
|
|
47
47
|
export const DEFAULT_PLUV_CLIENT_ADDON = <
|
|
48
48
|
TIO extends IOLike = IOLike,
|
|
49
49
|
TPresence extends JsonObject = {},
|
|
50
|
-
TStorage extends Record<string,
|
|
50
|
+
TStorage extends Record<string, CrdtType<any, any>> = {},
|
|
51
51
|
>(
|
|
52
52
|
input: PluvRoomAddonInput<TIO, TPresence, TStorage>,
|
|
53
53
|
): PluvRoomAddonResult => ({
|
|
@@ -101,13 +101,13 @@ interface InternalListeners {
|
|
|
101
101
|
export type PluvRoomAddon<
|
|
102
102
|
TIO extends IOLike = IOLike,
|
|
103
103
|
TPresence extends JsonObject = {},
|
|
104
|
-
TStorage extends Record<string,
|
|
104
|
+
TStorage extends Record<string, CrdtType<any, any>> = {},
|
|
105
105
|
> = (input: PluvRoomAddonInput<TIO, TPresence, TStorage>) => Partial<PluvRoomAddonResult>;
|
|
106
106
|
|
|
107
107
|
export interface PluvRoomAddonInput<
|
|
108
108
|
TIO extends IOLike = IOLike,
|
|
109
109
|
TPresence extends JsonObject = {},
|
|
110
|
-
TStorage extends Record<string,
|
|
110
|
+
TStorage extends Record<string, CrdtType<any, any>> = {},
|
|
111
111
|
> {
|
|
112
112
|
room: PluvRoom<TIO, TPresence, TStorage>;
|
|
113
113
|
}
|
|
@@ -124,7 +124,7 @@ export type PluvRoomDebug<TIO extends IOLike> = Id<{
|
|
|
124
124
|
export type PluvRoomOptions<
|
|
125
125
|
TIO extends IOLike,
|
|
126
126
|
TPresence extends JsonObject = {},
|
|
127
|
-
TStorage extends Record<string,
|
|
127
|
+
TStorage extends Record<string, CrdtType<any, any>> = {},
|
|
128
128
|
> = {
|
|
129
129
|
addons?: readonly PluvRoomAddon<TIO, TPresence, TStorage>[];
|
|
130
130
|
debug?: boolean | PluvRoomDebug<TIO>;
|
|
@@ -135,13 +135,13 @@ export type PluvRoomOptions<
|
|
|
135
135
|
export type RoomConfig<
|
|
136
136
|
TIO extends IOLike,
|
|
137
137
|
TPresence extends JsonObject = {},
|
|
138
|
-
TStorage extends Record<string,
|
|
138
|
+
TStorage extends Record<string, CrdtType<any, any>> = {},
|
|
139
139
|
> = RoomEndpoints<TIO> & PluvRoomOptions<TIO, TPresence, TStorage>;
|
|
140
140
|
|
|
141
141
|
export class PluvRoom<
|
|
142
142
|
TIO extends IOLike,
|
|
143
143
|
TPresence extends JsonObject = {},
|
|
144
|
-
TStorage extends Record<string,
|
|
144
|
+
TStorage extends Record<string, CrdtType<any, any>> = {},
|
|
145
145
|
> extends AbstractRoom<TIO, TPresence, TStorage> {
|
|
146
146
|
readonly _endpoints: RoomEndpoints<TIO>;
|
|
147
147
|
|
|
@@ -379,14 +379,28 @@ export class PluvRoom<
|
|
|
379
379
|
return this._usersManager.getOthers();
|
|
380
380
|
};
|
|
381
381
|
|
|
382
|
-
public getStorage = <TKey extends keyof TStorage>(
|
|
383
|
-
const sharedType = this._crdtManager.get(
|
|
382
|
+
public getStorage = <TKey extends keyof TStorage>(type: TKey): TStorage[TKey] | null => {
|
|
383
|
+
const sharedType = this._crdtManager.get(type);
|
|
384
384
|
|
|
385
385
|
if (typeof sharedType === "undefined") return null;
|
|
386
386
|
|
|
387
387
|
return sharedType;
|
|
388
388
|
};
|
|
389
389
|
|
|
390
|
+
public getStorageJson(): InferCrdtJson<TStorage> | null;
|
|
391
|
+
public getStorageJson<TKey extends keyof TStorage>(type: TKey): InferCrdtJson<TStorage[TKey]> | null;
|
|
392
|
+
public getStorageJson<TKey extends keyof TStorage>(type?: TKey) {
|
|
393
|
+
if (this._state.connection.id === null) return null;
|
|
394
|
+
|
|
395
|
+
if (typeof type === "undefined") return this._crdtManager.doc.toJson();
|
|
396
|
+
|
|
397
|
+
const sharedType = this._crdtManager.get(type);
|
|
398
|
+
|
|
399
|
+
if (typeof sharedType === "undefined") return null;
|
|
400
|
+
|
|
401
|
+
return this._crdtManager.doc.toJson(type);
|
|
402
|
+
}
|
|
403
|
+
|
|
390
404
|
public other = (connectionId: string, callback: OtherNotifierSubscriptionCallback<TIO>): (() => void) => {
|
|
391
405
|
return this._otherNotifier.subscribe(connectionId, callback);
|
|
392
406
|
};
|
|
@@ -397,14 +411,14 @@ export class PluvRoom<
|
|
|
397
411
|
|
|
398
412
|
public storage = <TKey extends keyof TStorage>(
|
|
399
413
|
key: TKey,
|
|
400
|
-
fn: (value:
|
|
414
|
+
fn: (value: InferCrdtJson<TStorage[TKey]>) => void,
|
|
401
415
|
): (() => void) => {
|
|
402
416
|
return this._crdtNotifier.subscribe(key, fn);
|
|
403
417
|
};
|
|
404
418
|
|
|
405
419
|
public storageRoot = (
|
|
406
420
|
fn: (value: {
|
|
407
|
-
[P in keyof TStorage]:
|
|
421
|
+
[P in keyof TStorage]: InferCrdtJson<TStorage[P]>;
|
|
408
422
|
}) => void,
|
|
409
423
|
): (() => void) => {
|
|
410
424
|
return this._crdtNotifier.subcribeRoot(fn);
|
|
@@ -562,17 +576,15 @@ export class PluvRoom<
|
|
|
562
576
|
private _emitSharedTypes(): void {
|
|
563
577
|
const sharedTypes = this._crdtManager.doc.get();
|
|
564
578
|
|
|
565
|
-
const storageRoot = Object.
|
|
566
|
-
(acc,
|
|
567
|
-
const serialized =
|
|
579
|
+
const storageRoot = Object.keys(sharedTypes).reduce(
|
|
580
|
+
(acc, prop) => {
|
|
581
|
+
const serialized = this._crdtManager.doc.toJson(prop);
|
|
568
582
|
|
|
569
583
|
this._crdtNotifier.subject(prop).next(serialized);
|
|
570
584
|
|
|
571
585
|
return { ...acc, [prop]: serialized };
|
|
572
586
|
},
|
|
573
|
-
{} as {
|
|
574
|
-
[P in keyof TStorage]: InferCrdtStorageJson<TStorage[P]>;
|
|
575
|
-
},
|
|
587
|
+
{} as { [P in keyof TStorage]: InferCrdtJson<TStorage[P]> },
|
|
576
588
|
);
|
|
577
589
|
|
|
578
590
|
this._crdtNotifier.rootSubject.next(storageRoot);
|
|
@@ -812,18 +824,18 @@ export class PluvRoom<
|
|
|
812
824
|
|
|
813
825
|
const sharedTypes = this._crdtManager.doc.get();
|
|
814
826
|
|
|
815
|
-
const storageRoot = Object.
|
|
816
|
-
(acc,
|
|
827
|
+
const storageRoot = Object.keys(sharedTypes).reduce(
|
|
828
|
+
(acc, prop) => {
|
|
817
829
|
if (!this._crdtManager) return acc;
|
|
818
830
|
|
|
819
|
-
const serialized =
|
|
831
|
+
const serialized = this._crdtManager.doc.toJson(prop);
|
|
820
832
|
|
|
821
833
|
this._crdtNotifier.subject(prop).next(serialized);
|
|
822
834
|
|
|
823
835
|
return { ...acc, [prop]: serialized };
|
|
824
836
|
},
|
|
825
837
|
{} as {
|
|
826
|
-
[P in keyof TStorage]:
|
|
838
|
+
[P in keyof TStorage]: InferCrdtJson<TStorage[P]>;
|
|
827
839
|
},
|
|
828
840
|
);
|
|
829
841
|
|
package/src/index.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type {
|
|
1
|
+
export type { CrdtType, InferCrdtJson } from "@pluv/crdt";
|
|
2
2
|
export type { BaseUser, EventMessage, EventRecord, IOEventMessage } from "@pluv/types";
|
|
3
3
|
export { AbstractRoom } from "./AbstractRoom";
|
|
4
4
|
export { AbstractStorageStore } from "./AbstractStorageStore";
|