@pluv/react 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 +76 -0
- package/dist/index.d.mts +23 -22
- package/dist/index.d.ts +23 -22
- package/dist/index.js +28 -22
- package/dist/index.mjs +38 -23
- package/package.json +8 -9
- package/src/createBundle.tsx +77 -156
- package/src/index.ts +2 -1
- package/src/types.ts +151 -0
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
> @pluv/react@2.0
|
|
2
|
+
> @pluv/react@2.2.0 build /home/runner/work/pluv/pluv/packages/react
|
|
3
3
|
> tsup src/index.ts --format esm,cjs --dts --external react
|
|
4
4
|
|
|
5
5
|
[34mCLI[39m Building entry: src/index.ts
|
|
@@ -8,11 +8,11 @@
|
|
|
8
8
|
[34mCLI[39m Target: es6
|
|
9
9
|
[34mESM[39m Build start
|
|
10
10
|
[34mCJS[39m Build start
|
|
11
|
-
[32mESM[39m [1mdist/index.mjs [22m[
|
|
12
|
-
[32mESM[39m ⚡️ Build success in
|
|
13
|
-
[32mCJS[39m [1mdist/index.js [22m[32m19.
|
|
14
|
-
[32mCJS[39m ⚡️ Build success in
|
|
11
|
+
[32mESM[39m [1mdist/index.mjs [22m[32m17.27 KB[39m
|
|
12
|
+
[32mESM[39m ⚡️ Build success in 86ms
|
|
13
|
+
[32mCJS[39m [1mdist/index.js [22m[32m19.66 KB[39m
|
|
14
|
+
[32mCJS[39m ⚡️ Build success in 86ms
|
|
15
15
|
[34mDTS[39m Build start
|
|
16
|
-
[32mDTS[39m ⚡️ Build success in
|
|
17
|
-
[32mDTS[39m [1mdist/index.d.mts [22m[
|
|
18
|
-
[32mDTS[39m [1mdist/index.d.ts [22m[
|
|
16
|
+
[32mDTS[39m ⚡️ Build success in 6218ms
|
|
17
|
+
[32mDTS[39m [1mdist/index.d.mts [22m[32m6.00 KB[39m
|
|
18
|
+
[32mDTS[39m [1mdist/index.d.ts [22m[32m6.00 KB[39m
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,81 @@
|
|
|
1
1
|
# @pluv/react
|
|
2
2
|
|
|
3
|
+
## 2.2.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 3ce1547: Updated typings for `useDoc` to be narrower to get the native doc type.
|
|
8
|
+
|
|
9
|
+
```ts
|
|
10
|
+
import { createClient } from "@pluv/client";
|
|
11
|
+
import { yjs } from "@pluv/crdt-yjs";
|
|
12
|
+
import { createBundle } from "@pluv/react";
|
|
13
|
+
import type { Doc as YDoc } from "yjs";
|
|
14
|
+
|
|
15
|
+
const client = createClient({
|
|
16
|
+
// ...
|
|
17
|
+
crdt: yjs,
|
|
18
|
+
});
|
|
19
|
+
const { useDoc } = createBundle(client);
|
|
20
|
+
|
|
21
|
+
const doc = useDoc();
|
|
22
|
+
|
|
23
|
+
// This is now typed as the native YDoc
|
|
24
|
+
doc.value;
|
|
25
|
+
// ^? const value: YDoc
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
- b999c1c: Added a new type `InferBundleRoom` to get the type of the `PluvRoom` from the react bundle that is created.
|
|
29
|
+
|
|
30
|
+
```ts
|
|
31
|
+
import { createClient } from "@pluv/client";
|
|
32
|
+
import type { InferBundleRoom } from "@pluv/react";
|
|
33
|
+
import { createBundle } from "@pluv/react";
|
|
34
|
+
|
|
35
|
+
const client = createclient({
|
|
36
|
+
/* ... */
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
const bundle = createBundle(client);
|
|
40
|
+
|
|
41
|
+
type RoomType = InferBundleRoom<typeof bundle>;
|
|
42
|
+
|
|
43
|
+
const { useStorage } = bundle;
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Patch Changes
|
|
47
|
+
|
|
48
|
+
- cb660cd: Fixed the room not changing if the room name was changed on the `PluvRoomProvider` without first unmounting the component.
|
|
49
|
+
- 4916c27: Fixed `useConnection` requiring a selector function (this is now optional).
|
|
50
|
+
- 48191fa: Fixed `useDoc` not returning a stable doc reference for a single connection.
|
|
51
|
+
- Updated dependencies [3ce1547]
|
|
52
|
+
- Updated dependencies [fd3bfe2]
|
|
53
|
+
- Updated dependencies [aee40cb]
|
|
54
|
+
- Updated dependencies [edd1789]
|
|
55
|
+
- Updated dependencies [48191fa]
|
|
56
|
+
- @pluv/client@2.2.0
|
|
57
|
+
- @pluv/crdt@2.2.0
|
|
58
|
+
- @pluv/types@2.2.0
|
|
59
|
+
|
|
60
|
+
## 2.1.0
|
|
61
|
+
|
|
62
|
+
### Minor Changes
|
|
63
|
+
|
|
64
|
+
- 8931f7b: Moved `@pluv/client` from `peerDependencies` to `dependencies` due to an unfortunate [changesets design decision](https://github.com/changesets/changesets/issues/1011).
|
|
65
|
+
|
|
66
|
+
### Patch Changes
|
|
67
|
+
|
|
68
|
+
- e8d8fbc: Updated the internals of various hooks to use the new `PluvRoom.subscribe` object.
|
|
69
|
+
- Updated dependencies [e8d8fbc]
|
|
70
|
+
- Updated dependencies [a86ff5e]
|
|
71
|
+
- Updated dependencies [d5ac29e]
|
|
72
|
+
- Updated dependencies [5ca5cb6]
|
|
73
|
+
- Updated dependencies [4acbe1e]
|
|
74
|
+
- Updated dependencies [e8d8fbc]
|
|
75
|
+
- @pluv/client@2.1.0
|
|
76
|
+
- @pluv/crdt@2.1.0
|
|
77
|
+
- @pluv/types@2.1.0
|
|
78
|
+
|
|
3
79
|
## 2.0.2
|
|
4
80
|
|
|
5
81
|
### Patch Changes
|
package/dist/index.d.mts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { PluvRouterEventConfig,
|
|
2
|
-
import { AbstractCrdtDocFactory, NoopCrdtDocFactory, InferStorage, InferInitialStorageFn, InferCrdtJson } from '@pluv/crdt';
|
|
3
|
-
import { IOLike, JsonObject, MaybePromise, InferIOOutput, Id, IOEventMessage, InferIOInput, CrdtDocLike, RoomLike } from '@pluv/types';
|
|
1
|
+
import { PluvRouterEventConfig, MockedRoomEvents, MergeEvents, PluvRoomDebug, PluvClient, WebSocketConnection, UserInfo, PluvRoomAddon, PluvRouter } from '@pluv/client';
|
|
2
|
+
import { AbstractCrdtDocFactory, NoopCrdtDocFactory, InferStorage, InferInitialStorageFn, InferDoc, InferCrdtJson } from '@pluv/crdt';
|
|
3
|
+
import { IOLike, JsonObject, MaybePromise, InferIOOutput, Id, IOEventMessage, InferIOInput, CrdtDocLike, UpdateMyPresenceAction, RoomLike } from '@pluv/types';
|
|
4
4
|
import { FC, ReactNode, Dispatch } from 'react';
|
|
5
5
|
|
|
6
6
|
interface PluvProviderProps {
|
|
7
7
|
children?: ReactNode;
|
|
8
8
|
}
|
|
9
|
-
type BaseRoomProviderProps<TPresence extends
|
|
9
|
+
type BaseRoomProviderProps<TPresence extends Record<string, any>, TCrdt extends AbstractCrdtDocFactory<any, any>> = {
|
|
10
10
|
children?: ReactNode;
|
|
11
11
|
initialStorage?: keyof InferStorage<TCrdt> extends never ? never : InferInitialStorageFn<TCrdt>;
|
|
12
12
|
room: string;
|
|
@@ -15,11 +15,19 @@ type BaseRoomProviderProps<TPresence extends JsonObject, TCrdt extends AbstractC
|
|
|
15
15
|
} : {
|
|
16
16
|
initialPresence: TPresence;
|
|
17
17
|
});
|
|
18
|
-
type MockedRoomProviderProps<TIO extends IOLike, TPresence extends
|
|
18
|
+
type MockedRoomProviderProps<TIO extends IOLike, TPresence extends Record<string, any>, TCrdt extends AbstractCrdtDocFactory<any, any>, TEvents extends PluvRouterEventConfig<TIO, TPresence, InferStorage<TCrdt>> = {}> = BaseRoomProviderProps<TPresence, TCrdt> & {
|
|
19
19
|
events?: MockedRoomEvents<MergeEvents<TEvents, TIO>>;
|
|
20
20
|
};
|
|
21
|
+
type BroadcastProxy<TIO extends IOLike> = (<TEvent extends keyof InferIOInput<TIO>>(event: TEvent, data: Id<InferIOInput<TIO>[TEvent]>) => void) & {
|
|
22
|
+
[event in keyof InferIOInput<TIO>]: (input: Id<InferIOInput<TIO>[event]>) => void;
|
|
23
|
+
};
|
|
24
|
+
type EventProxy<TIO extends IOLike> = {
|
|
25
|
+
[event in keyof InferIOOutput<TIO>]: {
|
|
26
|
+
useEvent: (callback: (data: Id<IOEventMessage<TIO, event>>) => void) => void;
|
|
27
|
+
};
|
|
28
|
+
};
|
|
21
29
|
type MetadataGetter<TMetadata extends JsonObject> = TMetadata | (() => MaybePromise<TMetadata>);
|
|
22
|
-
type PluvRoomProviderProps<TIO extends IOLike<any, any>, TMetadata extends JsonObject, TPresence extends
|
|
30
|
+
type PluvRoomProviderProps<TIO extends IOLike<any, any>, TMetadata extends JsonObject, TPresence extends Record<string, any>, TCrdt extends AbstractCrdtDocFactory<any, any>> = BaseRoomProviderProps<TPresence, TCrdt> & {
|
|
23
31
|
connect?: boolean;
|
|
24
32
|
debug?: boolean | PluvRoomDebug<TIO>;
|
|
25
33
|
onAuthorizationFail?: (error: Error) => void;
|
|
@@ -31,16 +39,7 @@ type PluvRoomProviderProps<TIO extends IOLike<any, any>, TMetadata extends JsonO
|
|
|
31
39
|
interface SubscriptionHookOptions<T extends unknown> {
|
|
32
40
|
isEqual?: (a: T, b: T) => boolean;
|
|
33
41
|
}
|
|
34
|
-
|
|
35
|
-
type BroadcastProxy<TIO extends IOLike> = (<TEvent extends keyof InferIOInput<TIO>>(event: TEvent, data: Id<InferIOInput<TIO>[TEvent]>) => void) & {
|
|
36
|
-
[event in keyof InferIOInput<TIO>]: (input: Id<InferIOInput<TIO>[event]>) => void;
|
|
37
|
-
};
|
|
38
|
-
type EventProxy<TIO extends IOLike> = {
|
|
39
|
-
[event in keyof InferIOOutput<TIO>]: {
|
|
40
|
-
useEvent: (callback: (data: Id<IOEventMessage<TIO, event>>) => void) => void;
|
|
41
|
-
};
|
|
42
|
-
};
|
|
43
|
-
interface CreateBundle<TIO extends IOLike, TMetadata extends JsonObject, TPresence extends JsonObject = {}, TCrdt extends AbstractCrdtDocFactory<any> = NoopCrdtDocFactory, TEvents extends PluvRouterEventConfig<TIO, TPresence, InferStorage<TCrdt>> = {}> {
|
|
42
|
+
interface CreateBundle<TIO extends IOLike<any>, TMetadata extends JsonObject, TPresence extends Record<string, any> = {}, TCrdt extends AbstractCrdtDocFactory<any, any> = NoopCrdtDocFactory, TEvents extends PluvRouterEventConfig<TIO, TPresence, InferStorage<TCrdt>> = {}> {
|
|
44
43
|
MockedRoomProvider: FC<MockedRoomProviderProps<TIO, TPresence, TCrdt>>;
|
|
45
44
|
PluvProvider: FC<PluvProviderProps>;
|
|
46
45
|
PluvRoomProvider: FC<PluvRoomProviderProps<TIO, TMetadata, TPresence, TCrdt>>;
|
|
@@ -49,23 +48,25 @@ interface CreateBundle<TIO extends IOLike, TMetadata extends JsonObject, TPresen
|
|
|
49
48
|
useCanRedo: () => boolean;
|
|
50
49
|
useCanUndo: () => boolean;
|
|
51
50
|
useClient: () => PluvClient<TIO, TPresence, TCrdt, TMetadata>;
|
|
52
|
-
useConnection: <T extends unknown = WebSocketConnection>(selector
|
|
53
|
-
useDoc: () => CrdtDocLike<InferStorage<TCrdt>>;
|
|
51
|
+
useConnection: <T extends unknown = WebSocketConnection>(selector?: (connection: WebSocketConnection) => T, options?: SubscriptionHookOptions<Id<T>>) => Id<T>;
|
|
52
|
+
useDoc: () => CrdtDocLike<InferDoc<TCrdt>, InferStorage<TCrdt>>;
|
|
54
53
|
useEvent: <TType extends keyof InferIOOutput<MergeEvents<TEvents, TIO>>>(type: TType, callback: (data: Id<IOEventMessage<MergeEvents<TEvents, TIO>, TType>>) => void) => void;
|
|
55
54
|
useMyPresence: <T extends unknown = TPresence>(selector?: (myPresence: TPresence) => T, options?: SubscriptionHookOptions<Id<T> | null>) => [myPresence: Id<T>, updateMyPresence: Dispatch<UpdateMyPresenceAction<TPresence>>];
|
|
56
55
|
useMyself: <T extends unknown = UserInfo<TIO, TPresence>>(selector?: (myself: Id<UserInfo<TIO, TPresence>>) => T, options?: SubscriptionHookOptions<Id<T> | null>) => Id<T> | null;
|
|
57
56
|
useOther: <T extends unknown = UserInfo<TIO, TPresence>>(connectionId: string, selector?: (other: UserInfo<TIO, TPresence>) => T, options?: SubscriptionHookOptions<T | null>) => T | null;
|
|
58
57
|
useOthers: <T extends unknown = readonly UserInfo<TIO, TPresence>[]>(selector?: (other: readonly Id<UserInfo<TIO, TPresence>>[]) => T, options?: SubscriptionHookOptions<T>) => T;
|
|
59
58
|
useRedo: () => () => void;
|
|
60
|
-
useRoom: () => RoomLike<TIO, TPresence, InferStorage<TCrdt
|
|
59
|
+
useRoom: () => RoomLike<TIO, InferDoc<TCrdt>, TPresence, InferStorage<TCrdt>, TEvents>;
|
|
61
60
|
useStorage: <TKey extends keyof InferStorage<TCrdt>, TData extends unknown = InferCrdtJson<InferStorage<TCrdt>[TKey]>>(key: TKey, selector?: (data: InferCrdtJson<InferStorage<TCrdt>[TKey]>) => TData, options?: SubscriptionHookOptions<TData | null>) => [data: TData | null, sharedType: InferStorage<TCrdt>[TKey] | null];
|
|
62
61
|
useTransact: () => (fn: (storage: InferStorage<TCrdt>) => void, origin?: string) => void;
|
|
63
62
|
useUndo: () => () => void;
|
|
64
63
|
}
|
|
65
|
-
type
|
|
64
|
+
type InferBundleRoom<TBundle extends CreateBundle<any, any, any, any, any>> = TBundle extends CreateBundle<infer IIO, any, infer IPresence, infer ICrdt, infer IEvents> ? RoomLike<IIO, InferDoc<ICrdt>, IPresence, InferStorage<ICrdt>, IEvents> : never;
|
|
65
|
+
|
|
66
|
+
type CreateBundleOptions<TIO extends IOLike<any>, TMetadata extends JsonObject = {}, TPresence extends Record<string, any> = {}, TCrdt extends AbstractCrdtDocFactory<any, any> = NoopCrdtDocFactory, TEvents extends PluvRouterEventConfig<TIO, TPresence, InferStorage<TCrdt>> = {}> = {
|
|
66
67
|
addons?: readonly PluvRoomAddon<TIO, TMetadata, TPresence, TCrdt>[];
|
|
67
68
|
router?: PluvRouter<TIO, TPresence, InferStorage<TCrdt>, TEvents>;
|
|
68
69
|
};
|
|
69
|
-
declare const createBundle: <TIO extends IOLike<any, any>, TMetadata extends JsonObject = {}, TPresence extends
|
|
70
|
+
declare const createBundle: <TIO extends IOLike<any, any>, TMetadata extends JsonObject = {}, TPresence extends Record<string, any> = {}, TCrdt extends AbstractCrdtDocFactory<any, any> = NoopCrdtDocFactory, TEvents extends PluvRouterEventConfig<TIO, TPresence, InferStorage<TCrdt>> = {}>(client: PluvClient<TIO, TPresence, TCrdt, TMetadata>, options?: CreateBundleOptions<TIO, TMetadata, TPresence, TCrdt, TEvents>) => CreateBundle<TIO, TMetadata, TPresence, TCrdt, TEvents>;
|
|
70
71
|
|
|
71
|
-
export { type CreateBundle, type EventProxy, type PluvProviderProps, type PluvRoomProviderProps, type SubscriptionHookOptions, createBundle };
|
|
72
|
+
export { type CreateBundle, type EventProxy, type InferBundleRoom, type PluvProviderProps, type PluvRoomProviderProps, type SubscriptionHookOptions, createBundle };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import { PluvRouterEventConfig,
|
|
2
|
-
import { AbstractCrdtDocFactory, NoopCrdtDocFactory, InferStorage, InferInitialStorageFn, InferCrdtJson } from '@pluv/crdt';
|
|
3
|
-
import { IOLike, JsonObject, MaybePromise, InferIOOutput, Id, IOEventMessage, InferIOInput, CrdtDocLike, RoomLike } from '@pluv/types';
|
|
1
|
+
import { PluvRouterEventConfig, MockedRoomEvents, MergeEvents, PluvRoomDebug, PluvClient, WebSocketConnection, UserInfo, PluvRoomAddon, PluvRouter } from '@pluv/client';
|
|
2
|
+
import { AbstractCrdtDocFactory, NoopCrdtDocFactory, InferStorage, InferInitialStorageFn, InferDoc, InferCrdtJson } from '@pluv/crdt';
|
|
3
|
+
import { IOLike, JsonObject, MaybePromise, InferIOOutput, Id, IOEventMessage, InferIOInput, CrdtDocLike, UpdateMyPresenceAction, RoomLike } from '@pluv/types';
|
|
4
4
|
import { FC, ReactNode, Dispatch } from 'react';
|
|
5
5
|
|
|
6
6
|
interface PluvProviderProps {
|
|
7
7
|
children?: ReactNode;
|
|
8
8
|
}
|
|
9
|
-
type BaseRoomProviderProps<TPresence extends
|
|
9
|
+
type BaseRoomProviderProps<TPresence extends Record<string, any>, TCrdt extends AbstractCrdtDocFactory<any, any>> = {
|
|
10
10
|
children?: ReactNode;
|
|
11
11
|
initialStorage?: keyof InferStorage<TCrdt> extends never ? never : InferInitialStorageFn<TCrdt>;
|
|
12
12
|
room: string;
|
|
@@ -15,11 +15,19 @@ type BaseRoomProviderProps<TPresence extends JsonObject, TCrdt extends AbstractC
|
|
|
15
15
|
} : {
|
|
16
16
|
initialPresence: TPresence;
|
|
17
17
|
});
|
|
18
|
-
type MockedRoomProviderProps<TIO extends IOLike, TPresence extends
|
|
18
|
+
type MockedRoomProviderProps<TIO extends IOLike, TPresence extends Record<string, any>, TCrdt extends AbstractCrdtDocFactory<any, any>, TEvents extends PluvRouterEventConfig<TIO, TPresence, InferStorage<TCrdt>> = {}> = BaseRoomProviderProps<TPresence, TCrdt> & {
|
|
19
19
|
events?: MockedRoomEvents<MergeEvents<TEvents, TIO>>;
|
|
20
20
|
};
|
|
21
|
+
type BroadcastProxy<TIO extends IOLike> = (<TEvent extends keyof InferIOInput<TIO>>(event: TEvent, data: Id<InferIOInput<TIO>[TEvent]>) => void) & {
|
|
22
|
+
[event in keyof InferIOInput<TIO>]: (input: Id<InferIOInput<TIO>[event]>) => void;
|
|
23
|
+
};
|
|
24
|
+
type EventProxy<TIO extends IOLike> = {
|
|
25
|
+
[event in keyof InferIOOutput<TIO>]: {
|
|
26
|
+
useEvent: (callback: (data: Id<IOEventMessage<TIO, event>>) => void) => void;
|
|
27
|
+
};
|
|
28
|
+
};
|
|
21
29
|
type MetadataGetter<TMetadata extends JsonObject> = TMetadata | (() => MaybePromise<TMetadata>);
|
|
22
|
-
type PluvRoomProviderProps<TIO extends IOLike<any, any>, TMetadata extends JsonObject, TPresence extends
|
|
30
|
+
type PluvRoomProviderProps<TIO extends IOLike<any, any>, TMetadata extends JsonObject, TPresence extends Record<string, any>, TCrdt extends AbstractCrdtDocFactory<any, any>> = BaseRoomProviderProps<TPresence, TCrdt> & {
|
|
23
31
|
connect?: boolean;
|
|
24
32
|
debug?: boolean | PluvRoomDebug<TIO>;
|
|
25
33
|
onAuthorizationFail?: (error: Error) => void;
|
|
@@ -31,16 +39,7 @@ type PluvRoomProviderProps<TIO extends IOLike<any, any>, TMetadata extends JsonO
|
|
|
31
39
|
interface SubscriptionHookOptions<T extends unknown> {
|
|
32
40
|
isEqual?: (a: T, b: T) => boolean;
|
|
33
41
|
}
|
|
34
|
-
|
|
35
|
-
type BroadcastProxy<TIO extends IOLike> = (<TEvent extends keyof InferIOInput<TIO>>(event: TEvent, data: Id<InferIOInput<TIO>[TEvent]>) => void) & {
|
|
36
|
-
[event in keyof InferIOInput<TIO>]: (input: Id<InferIOInput<TIO>[event]>) => void;
|
|
37
|
-
};
|
|
38
|
-
type EventProxy<TIO extends IOLike> = {
|
|
39
|
-
[event in keyof InferIOOutput<TIO>]: {
|
|
40
|
-
useEvent: (callback: (data: Id<IOEventMessage<TIO, event>>) => void) => void;
|
|
41
|
-
};
|
|
42
|
-
};
|
|
43
|
-
interface CreateBundle<TIO extends IOLike, TMetadata extends JsonObject, TPresence extends JsonObject = {}, TCrdt extends AbstractCrdtDocFactory<any> = NoopCrdtDocFactory, TEvents extends PluvRouterEventConfig<TIO, TPresence, InferStorage<TCrdt>> = {}> {
|
|
42
|
+
interface CreateBundle<TIO extends IOLike<any>, TMetadata extends JsonObject, TPresence extends Record<string, any> = {}, TCrdt extends AbstractCrdtDocFactory<any, any> = NoopCrdtDocFactory, TEvents extends PluvRouterEventConfig<TIO, TPresence, InferStorage<TCrdt>> = {}> {
|
|
44
43
|
MockedRoomProvider: FC<MockedRoomProviderProps<TIO, TPresence, TCrdt>>;
|
|
45
44
|
PluvProvider: FC<PluvProviderProps>;
|
|
46
45
|
PluvRoomProvider: FC<PluvRoomProviderProps<TIO, TMetadata, TPresence, TCrdt>>;
|
|
@@ -49,23 +48,25 @@ interface CreateBundle<TIO extends IOLike, TMetadata extends JsonObject, TPresen
|
|
|
49
48
|
useCanRedo: () => boolean;
|
|
50
49
|
useCanUndo: () => boolean;
|
|
51
50
|
useClient: () => PluvClient<TIO, TPresence, TCrdt, TMetadata>;
|
|
52
|
-
useConnection: <T extends unknown = WebSocketConnection>(selector
|
|
53
|
-
useDoc: () => CrdtDocLike<InferStorage<TCrdt>>;
|
|
51
|
+
useConnection: <T extends unknown = WebSocketConnection>(selector?: (connection: WebSocketConnection) => T, options?: SubscriptionHookOptions<Id<T>>) => Id<T>;
|
|
52
|
+
useDoc: () => CrdtDocLike<InferDoc<TCrdt>, InferStorage<TCrdt>>;
|
|
54
53
|
useEvent: <TType extends keyof InferIOOutput<MergeEvents<TEvents, TIO>>>(type: TType, callback: (data: Id<IOEventMessage<MergeEvents<TEvents, TIO>, TType>>) => void) => void;
|
|
55
54
|
useMyPresence: <T extends unknown = TPresence>(selector?: (myPresence: TPresence) => T, options?: SubscriptionHookOptions<Id<T> | null>) => [myPresence: Id<T>, updateMyPresence: Dispatch<UpdateMyPresenceAction<TPresence>>];
|
|
56
55
|
useMyself: <T extends unknown = UserInfo<TIO, TPresence>>(selector?: (myself: Id<UserInfo<TIO, TPresence>>) => T, options?: SubscriptionHookOptions<Id<T> | null>) => Id<T> | null;
|
|
57
56
|
useOther: <T extends unknown = UserInfo<TIO, TPresence>>(connectionId: string, selector?: (other: UserInfo<TIO, TPresence>) => T, options?: SubscriptionHookOptions<T | null>) => T | null;
|
|
58
57
|
useOthers: <T extends unknown = readonly UserInfo<TIO, TPresence>[]>(selector?: (other: readonly Id<UserInfo<TIO, TPresence>>[]) => T, options?: SubscriptionHookOptions<T>) => T;
|
|
59
58
|
useRedo: () => () => void;
|
|
60
|
-
useRoom: () => RoomLike<TIO, TPresence, InferStorage<TCrdt
|
|
59
|
+
useRoom: () => RoomLike<TIO, InferDoc<TCrdt>, TPresence, InferStorage<TCrdt>, TEvents>;
|
|
61
60
|
useStorage: <TKey extends keyof InferStorage<TCrdt>, TData extends unknown = InferCrdtJson<InferStorage<TCrdt>[TKey]>>(key: TKey, selector?: (data: InferCrdtJson<InferStorage<TCrdt>[TKey]>) => TData, options?: SubscriptionHookOptions<TData | null>) => [data: TData | null, sharedType: InferStorage<TCrdt>[TKey] | null];
|
|
62
61
|
useTransact: () => (fn: (storage: InferStorage<TCrdt>) => void, origin?: string) => void;
|
|
63
62
|
useUndo: () => () => void;
|
|
64
63
|
}
|
|
65
|
-
type
|
|
64
|
+
type InferBundleRoom<TBundle extends CreateBundle<any, any, any, any, any>> = TBundle extends CreateBundle<infer IIO, any, infer IPresence, infer ICrdt, infer IEvents> ? RoomLike<IIO, InferDoc<ICrdt>, IPresence, InferStorage<ICrdt>, IEvents> : never;
|
|
65
|
+
|
|
66
|
+
type CreateBundleOptions<TIO extends IOLike<any>, TMetadata extends JsonObject = {}, TPresence extends Record<string, any> = {}, TCrdt extends AbstractCrdtDocFactory<any, any> = NoopCrdtDocFactory, TEvents extends PluvRouterEventConfig<TIO, TPresence, InferStorage<TCrdt>> = {}> = {
|
|
66
67
|
addons?: readonly PluvRoomAddon<TIO, TMetadata, TPresence, TCrdt>[];
|
|
67
68
|
router?: PluvRouter<TIO, TPresence, InferStorage<TCrdt>, TEvents>;
|
|
68
69
|
};
|
|
69
|
-
declare const createBundle: <TIO extends IOLike<any, any>, TMetadata extends JsonObject = {}, TPresence extends
|
|
70
|
+
declare const createBundle: <TIO extends IOLike<any, any>, TMetadata extends JsonObject = {}, TPresence extends Record<string, any> = {}, TCrdt extends AbstractCrdtDocFactory<any, any> = NoopCrdtDocFactory, TEvents extends PluvRouterEventConfig<TIO, TPresence, InferStorage<TCrdt>> = {}>(client: PluvClient<TIO, TPresence, TCrdt, TMetadata>, options?: CreateBundleOptions<TIO, TMetadata, TPresence, TCrdt, TEvents>) => CreateBundle<TIO, TMetadata, TPresence, TCrdt, TEvents>;
|
|
70
71
|
|
|
71
|
-
export { type CreateBundle, type EventProxy, type PluvProviderProps, type PluvRoomProviderProps, type SubscriptionHookOptions, createBundle };
|
|
72
|
+
export { type CreateBundle, type EventProxy, type InferBundleRoom, type PluvProviderProps, type PluvRoomProviderProps, type SubscriptionHookOptions, createBundle };
|
package/dist/index.js
CHANGED
|
@@ -225,12 +225,8 @@ var useSyncExternalStoreWithSelector = (subscribe, getClientSnapshot, getServerS
|
|
|
225
225
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
226
226
|
var createBundle = (client, options = {}) => {
|
|
227
227
|
const PluvContext = (0, import_react6.createContext)(null);
|
|
228
|
-
const PluvRoomContext = (0, import_react6.createContext)(
|
|
229
|
-
|
|
230
|
-
);
|
|
231
|
-
const MockedRoomContext = (0, import_react6.createContext)(
|
|
232
|
-
null
|
|
233
|
-
);
|
|
228
|
+
const PluvRoomContext = (0, import_react6.createContext)(null);
|
|
229
|
+
const MockedRoomContext = (0, import_react6.createContext)(null);
|
|
234
230
|
const MockedRoomProvider = (0, import_react6.memo)((props) => {
|
|
235
231
|
const { children, events, initialPresence, initialStorage, room: _room } = props;
|
|
236
232
|
const [room] = (0, import_react6.useState)(() => {
|
|
@@ -265,7 +261,7 @@ var createBundle = (client, options = {}) => {
|
|
|
265
261
|
);
|
|
266
262
|
return !!room.metadata ? room.metadata.parse(resolved) : resolved;
|
|
267
263
|
}));
|
|
268
|
-
const
|
|
264
|
+
const createRoom = (0, import_react6.useCallback)(() => {
|
|
269
265
|
var _a;
|
|
270
266
|
return client.createRoom(_room, {
|
|
271
267
|
addons: options.addons,
|
|
@@ -276,9 +272,14 @@ var createBundle = (client, options = {}) => {
|
|
|
276
272
|
onAuthorizationFail,
|
|
277
273
|
router: options.router
|
|
278
274
|
});
|
|
279
|
-
});
|
|
275
|
+
}, [_room, debug, initialPresence, initialStorage, metadata, onAuthorizationFail]);
|
|
276
|
+
const [room, setRoom] = (0, import_react6.useState)(() => createRoom());
|
|
280
277
|
(0, import_react6.useEffect)(() => {
|
|
281
|
-
|
|
278
|
+
if (room.id === _room) return;
|
|
279
|
+
setRoom(createRoom());
|
|
280
|
+
}, [_room, createRoom, room]);
|
|
281
|
+
(0, import_react6.useEffect)(() => {
|
|
282
|
+
const unsubscribe = room.subscribe.connection(() => {
|
|
282
283
|
rerender();
|
|
283
284
|
});
|
|
284
285
|
return () => {
|
|
@@ -351,7 +352,7 @@ var createBundle = (client, options = {}) => {
|
|
|
351
352
|
const useCanRedo = () => {
|
|
352
353
|
const room = useRoom();
|
|
353
354
|
const subscribe = (0, import_react6.useCallback)(
|
|
354
|
-
(onStoreChange) => room.
|
|
355
|
+
(onStoreChange) => room.subscribe.storage(onStoreChange),
|
|
355
356
|
[room]
|
|
356
357
|
);
|
|
357
358
|
const getSnapshot = (0, import_react6.useCallback)(() => room.canRedo(), [room]);
|
|
@@ -366,7 +367,7 @@ var createBundle = (client, options = {}) => {
|
|
|
366
367
|
const useCanUndo = () => {
|
|
367
368
|
const room = useRoom();
|
|
368
369
|
const subscribe = (0, import_react6.useCallback)(
|
|
369
|
-
(onStoreChange) => room.
|
|
370
|
+
(onStoreChange) => room.subscribe.storage(onStoreChange),
|
|
370
371
|
[room]
|
|
371
372
|
);
|
|
372
373
|
const getSnapshot = (0, import_react6.useCallback)(() => room.canUndo(), [room]);
|
|
@@ -383,7 +384,7 @@ var createBundle = (client, options = {}) => {
|
|
|
383
384
|
const room = useRoom();
|
|
384
385
|
const subscribe = (0, import_react6.useCallback)(
|
|
385
386
|
(onStoreChange) => {
|
|
386
|
-
return room.subscribe(
|
|
387
|
+
return room.subscribe.connection(onStoreChange);
|
|
387
388
|
},
|
|
388
389
|
[room]
|
|
389
390
|
);
|
|
@@ -402,12 +403,19 @@ var createBundle = (client, options = {}) => {
|
|
|
402
403
|
};
|
|
403
404
|
const useDoc = () => {
|
|
404
405
|
const room = useRoom();
|
|
405
|
-
|
|
406
|
+
const subscribe = (0, import_react6.useCallback)(
|
|
407
|
+
(onStoreChange) => {
|
|
408
|
+
return room.subscribe.storageLoaded(onStoreChange);
|
|
409
|
+
},
|
|
410
|
+
[room]
|
|
411
|
+
);
|
|
412
|
+
const getSnapshot = room.getDoc;
|
|
413
|
+
return (0, import_react6.useSyncExternalStore)(subscribe, getSnapshot, getSnapshot);
|
|
406
414
|
};
|
|
407
415
|
const useEvent = (type, callback) => {
|
|
408
416
|
const room = useRoom();
|
|
409
417
|
(0, import_react6.useEffect)(() => {
|
|
410
|
-
const unsubscribe = room.event(type, callback);
|
|
418
|
+
const unsubscribe = room.subscribe.event(type, callback);
|
|
411
419
|
return () => {
|
|
412
420
|
unsubscribe();
|
|
413
421
|
};
|
|
@@ -432,7 +440,7 @@ var createBundle = (client, options = {}) => {
|
|
|
432
440
|
const room = useRoom();
|
|
433
441
|
const subscribe = (0, import_react6.useCallback)(
|
|
434
442
|
(onStoreChange) => {
|
|
435
|
-
return room.subscribe(
|
|
443
|
+
return room.subscribe.myPresence(onStoreChange);
|
|
436
444
|
},
|
|
437
445
|
[room]
|
|
438
446
|
);
|
|
@@ -455,7 +463,7 @@ var createBundle = (client, options = {}) => {
|
|
|
455
463
|
const room = useRoom();
|
|
456
464
|
const subscribe = (0, import_react6.useCallback)(
|
|
457
465
|
(onStoreChange) => {
|
|
458
|
-
return room.subscribe(
|
|
466
|
+
return room.subscribe.myself(onStoreChange);
|
|
459
467
|
},
|
|
460
468
|
[room]
|
|
461
469
|
);
|
|
@@ -478,9 +486,7 @@ var createBundle = (client, options = {}) => {
|
|
|
478
486
|
var _a;
|
|
479
487
|
const room = useRoom();
|
|
480
488
|
const subscribe = (0, import_react6.useCallback)(
|
|
481
|
-
(onStoreChange) =>
|
|
482
|
-
return room.other(connectionId, onStoreChange);
|
|
483
|
-
},
|
|
489
|
+
(onStoreChange) => room.subscribe.other(connectionId, onStoreChange),
|
|
484
490
|
[room, connectionId]
|
|
485
491
|
);
|
|
486
492
|
const getSnapshot = (0, import_react6.useCallback)(() => room.getOther(connectionId), [room, connectionId]);
|
|
@@ -503,7 +509,7 @@ var createBundle = (client, options = {}) => {
|
|
|
503
509
|
const room = useRoom();
|
|
504
510
|
const subscribe = (0, import_react6.useCallback)(
|
|
505
511
|
(onStoreChange) => {
|
|
506
|
-
return room.subscribe(
|
|
512
|
+
return room.subscribe.others(onStoreChange);
|
|
507
513
|
},
|
|
508
514
|
[room]
|
|
509
515
|
);
|
|
@@ -529,11 +535,11 @@ var createBundle = (client, options = {}) => {
|
|
|
529
535
|
var _a, _b;
|
|
530
536
|
const room = useRoom();
|
|
531
537
|
const rerender = useRerender();
|
|
532
|
-
room.subscribe(
|
|
538
|
+
room.subscribe.storageLoaded(() => {
|
|
533
539
|
rerender();
|
|
534
540
|
});
|
|
535
541
|
const subscribe = (0, import_react6.useCallback)(
|
|
536
|
-
(onStoreChange) => room.storage(key, onStoreChange),
|
|
542
|
+
(onStoreChange) => room.subscribe.storage(key, onStoreChange),
|
|
537
543
|
[key, room]
|
|
538
544
|
);
|
|
539
545
|
const getSnapshot = (0, import_react6.useCallback)(() => {
|
package/dist/index.mjs
CHANGED
|
@@ -41,7 +41,16 @@ var __async = (__this, __arguments, generator) => {
|
|
|
41
41
|
// src/createBundle.tsx
|
|
42
42
|
import { MockedRoom } from "@pluv/client";
|
|
43
43
|
import fastDeepEqual2 from "fast-deep-equal";
|
|
44
|
-
import {
|
|
44
|
+
import {
|
|
45
|
+
createContext,
|
|
46
|
+
memo,
|
|
47
|
+
useCallback as useCallback4,
|
|
48
|
+
useContext,
|
|
49
|
+
useEffect as useEffect3,
|
|
50
|
+
useMemo as useMemo2,
|
|
51
|
+
useState as useState4,
|
|
52
|
+
useSyncExternalStore as useSyncExternalStore2
|
|
53
|
+
} from "react";
|
|
45
54
|
|
|
46
55
|
// src/internal/hooks/useAsyncQueue.ts
|
|
47
56
|
import { useCallback, useMemo, useRef } from "react";
|
|
@@ -192,12 +201,8 @@ var useSyncExternalStoreWithSelector = (subscribe, getClientSnapshot, getServerS
|
|
|
192
201
|
import { jsx } from "react/jsx-runtime";
|
|
193
202
|
var createBundle = (client, options = {}) => {
|
|
194
203
|
const PluvContext = createContext(null);
|
|
195
|
-
const PluvRoomContext = createContext(
|
|
196
|
-
|
|
197
|
-
);
|
|
198
|
-
const MockedRoomContext = createContext(
|
|
199
|
-
null
|
|
200
|
-
);
|
|
204
|
+
const PluvRoomContext = createContext(null);
|
|
205
|
+
const MockedRoomContext = createContext(null);
|
|
201
206
|
const MockedRoomProvider = memo((props) => {
|
|
202
207
|
const { children, events, initialPresence, initialStorage, room: _room } = props;
|
|
203
208
|
const [room] = useState4(() => {
|
|
@@ -232,7 +237,7 @@ var createBundle = (client, options = {}) => {
|
|
|
232
237
|
);
|
|
233
238
|
return !!room.metadata ? room.metadata.parse(resolved) : resolved;
|
|
234
239
|
}));
|
|
235
|
-
const
|
|
240
|
+
const createRoom = useCallback4(() => {
|
|
236
241
|
var _a;
|
|
237
242
|
return client.createRoom(_room, {
|
|
238
243
|
addons: options.addons,
|
|
@@ -243,9 +248,14 @@ var createBundle = (client, options = {}) => {
|
|
|
243
248
|
onAuthorizationFail,
|
|
244
249
|
router: options.router
|
|
245
250
|
});
|
|
246
|
-
});
|
|
251
|
+
}, [_room, debug, initialPresence, initialStorage, metadata, onAuthorizationFail]);
|
|
252
|
+
const [room, setRoom] = useState4(() => createRoom());
|
|
247
253
|
useEffect3(() => {
|
|
248
|
-
|
|
254
|
+
if (room.id === _room) return;
|
|
255
|
+
setRoom(createRoom());
|
|
256
|
+
}, [_room, createRoom, room]);
|
|
257
|
+
useEffect3(() => {
|
|
258
|
+
const unsubscribe = room.subscribe.connection(() => {
|
|
249
259
|
rerender();
|
|
250
260
|
});
|
|
251
261
|
return () => {
|
|
@@ -318,7 +328,7 @@ var createBundle = (client, options = {}) => {
|
|
|
318
328
|
const useCanRedo = () => {
|
|
319
329
|
const room = useRoom();
|
|
320
330
|
const subscribe = useCallback4(
|
|
321
|
-
(onStoreChange) => room.
|
|
331
|
+
(onStoreChange) => room.subscribe.storage(onStoreChange),
|
|
322
332
|
[room]
|
|
323
333
|
);
|
|
324
334
|
const getSnapshot = useCallback4(() => room.canRedo(), [room]);
|
|
@@ -333,7 +343,7 @@ var createBundle = (client, options = {}) => {
|
|
|
333
343
|
const useCanUndo = () => {
|
|
334
344
|
const room = useRoom();
|
|
335
345
|
const subscribe = useCallback4(
|
|
336
|
-
(onStoreChange) => room.
|
|
346
|
+
(onStoreChange) => room.subscribe.storage(onStoreChange),
|
|
337
347
|
[room]
|
|
338
348
|
);
|
|
339
349
|
const getSnapshot = useCallback4(() => room.canUndo(), [room]);
|
|
@@ -350,7 +360,7 @@ var createBundle = (client, options = {}) => {
|
|
|
350
360
|
const room = useRoom();
|
|
351
361
|
const subscribe = useCallback4(
|
|
352
362
|
(onStoreChange) => {
|
|
353
|
-
return room.subscribe(
|
|
363
|
+
return room.subscribe.connection(onStoreChange);
|
|
354
364
|
},
|
|
355
365
|
[room]
|
|
356
366
|
);
|
|
@@ -369,12 +379,19 @@ var createBundle = (client, options = {}) => {
|
|
|
369
379
|
};
|
|
370
380
|
const useDoc = () => {
|
|
371
381
|
const room = useRoom();
|
|
372
|
-
|
|
382
|
+
const subscribe = useCallback4(
|
|
383
|
+
(onStoreChange) => {
|
|
384
|
+
return room.subscribe.storageLoaded(onStoreChange);
|
|
385
|
+
},
|
|
386
|
+
[room]
|
|
387
|
+
);
|
|
388
|
+
const getSnapshot = room.getDoc;
|
|
389
|
+
return useSyncExternalStore2(subscribe, getSnapshot, getSnapshot);
|
|
373
390
|
};
|
|
374
391
|
const useEvent = (type, callback) => {
|
|
375
392
|
const room = useRoom();
|
|
376
393
|
useEffect3(() => {
|
|
377
|
-
const unsubscribe = room.event(type, callback);
|
|
394
|
+
const unsubscribe = room.subscribe.event(type, callback);
|
|
378
395
|
return () => {
|
|
379
396
|
unsubscribe();
|
|
380
397
|
};
|
|
@@ -399,7 +416,7 @@ var createBundle = (client, options = {}) => {
|
|
|
399
416
|
const room = useRoom();
|
|
400
417
|
const subscribe = useCallback4(
|
|
401
418
|
(onStoreChange) => {
|
|
402
|
-
return room.subscribe(
|
|
419
|
+
return room.subscribe.myPresence(onStoreChange);
|
|
403
420
|
},
|
|
404
421
|
[room]
|
|
405
422
|
);
|
|
@@ -422,7 +439,7 @@ var createBundle = (client, options = {}) => {
|
|
|
422
439
|
const room = useRoom();
|
|
423
440
|
const subscribe = useCallback4(
|
|
424
441
|
(onStoreChange) => {
|
|
425
|
-
return room.subscribe(
|
|
442
|
+
return room.subscribe.myself(onStoreChange);
|
|
426
443
|
},
|
|
427
444
|
[room]
|
|
428
445
|
);
|
|
@@ -445,9 +462,7 @@ var createBundle = (client, options = {}) => {
|
|
|
445
462
|
var _a;
|
|
446
463
|
const room = useRoom();
|
|
447
464
|
const subscribe = useCallback4(
|
|
448
|
-
(onStoreChange) =>
|
|
449
|
-
return room.other(connectionId, onStoreChange);
|
|
450
|
-
},
|
|
465
|
+
(onStoreChange) => room.subscribe.other(connectionId, onStoreChange),
|
|
451
466
|
[room, connectionId]
|
|
452
467
|
);
|
|
453
468
|
const getSnapshot = useCallback4(() => room.getOther(connectionId), [room, connectionId]);
|
|
@@ -470,7 +485,7 @@ var createBundle = (client, options = {}) => {
|
|
|
470
485
|
const room = useRoom();
|
|
471
486
|
const subscribe = useCallback4(
|
|
472
487
|
(onStoreChange) => {
|
|
473
|
-
return room.subscribe(
|
|
488
|
+
return room.subscribe.others(onStoreChange);
|
|
474
489
|
},
|
|
475
490
|
[room]
|
|
476
491
|
);
|
|
@@ -496,11 +511,11 @@ var createBundle = (client, options = {}) => {
|
|
|
496
511
|
var _a, _b;
|
|
497
512
|
const room = useRoom();
|
|
498
513
|
const rerender = useRerender();
|
|
499
|
-
room.subscribe(
|
|
514
|
+
room.subscribe.storageLoaded(() => {
|
|
500
515
|
rerender();
|
|
501
516
|
});
|
|
502
517
|
const subscribe = useCallback4(
|
|
503
|
-
(onStoreChange) => room.storage(key, onStoreChange),
|
|
518
|
+
(onStoreChange) => room.subscribe.storage(key, onStoreChange),
|
|
504
519
|
[key, room]
|
|
505
520
|
);
|
|
506
521
|
const getSnapshot = useCallback4(() => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pluv/react",
|
|
3
|
-
"version": "2.0
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"description": "@pluv/client React.js bindings",
|
|
5
5
|
"author": "leedavidcs",
|
|
6
6
|
"license": "MIT",
|
|
@@ -18,23 +18,22 @@
|
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
20
|
"fast-deep-equal": "^3.1.3",
|
|
21
|
-
"@pluv/
|
|
22
|
-
"@pluv/
|
|
21
|
+
"@pluv/client": "^2.2.0",
|
|
22
|
+
"@pluv/crdt": "^2.2.0",
|
|
23
|
+
"@pluv/types": "^2.2.0"
|
|
23
24
|
},
|
|
24
25
|
"peerDependencies": {
|
|
25
26
|
"@types/react": "^18.0.0 || ^19.0.0",
|
|
26
|
-
"react": "^18.0.0 || ^19.0.0"
|
|
27
|
-
"@pluv/client": "^2.0.2"
|
|
27
|
+
"react": "^18.0.0 || ^19.0.0"
|
|
28
28
|
},
|
|
29
29
|
"devDependencies": {
|
|
30
|
-
"@types/react": "^19.1.
|
|
30
|
+
"@types/react": "^19.1.4",
|
|
31
31
|
"eslint": "^9.26.0",
|
|
32
32
|
"react": "^19.1.0",
|
|
33
33
|
"tsup": "^8.4.0",
|
|
34
34
|
"typescript": "^5.8.3",
|
|
35
|
-
"@pluv/
|
|
36
|
-
"
|
|
37
|
-
"eslint-config-pluv": "^2.0.2"
|
|
35
|
+
"@pluv/tsconfig": "^2.2.0",
|
|
36
|
+
"eslint-config-pluv": "^2.2.0"
|
|
38
37
|
},
|
|
39
38
|
"scripts": {
|
|
40
39
|
"build": "tsup src/index.ts --format esm,cjs --dts --external react",
|
package/src/createBundle.tsx
CHANGED
|
@@ -2,37 +2,44 @@ import type {
|
|
|
2
2
|
CreateRoomOptions,
|
|
3
3
|
EnterRoomParams,
|
|
4
4
|
MergeEvents,
|
|
5
|
-
MockedRoomEvents,
|
|
6
5
|
PluvClient,
|
|
6
|
+
PluvRoom,
|
|
7
7
|
PluvRoomAddon,
|
|
8
|
-
PluvRoomDebug,
|
|
9
8
|
PluvRouter,
|
|
10
9
|
PluvRouterEventConfig,
|
|
11
10
|
UserInfo,
|
|
12
11
|
WebSocketConnection,
|
|
13
12
|
} from "@pluv/client";
|
|
14
|
-
import { MockedRoom
|
|
13
|
+
import { MockedRoom } from "@pluv/client";
|
|
15
14
|
import type {
|
|
16
15
|
AbstractCrdtDocFactory,
|
|
17
16
|
InferCrdtJson,
|
|
18
|
-
|
|
17
|
+
InferDoc,
|
|
19
18
|
InferStorage,
|
|
20
19
|
NoopCrdtDocFactory,
|
|
21
20
|
} from "@pluv/crdt";
|
|
22
21
|
import type {
|
|
23
|
-
CrdtDocLike,
|
|
24
22
|
Id,
|
|
25
23
|
InferIOInput,
|
|
26
24
|
InferIOOutput,
|
|
27
25
|
IOEventMessage,
|
|
28
26
|
IOLike,
|
|
29
27
|
JsonObject,
|
|
30
|
-
MaybePromise,
|
|
31
28
|
RoomLike,
|
|
29
|
+
UpdateMyPresenceAction,
|
|
32
30
|
} from "@pluv/types";
|
|
33
31
|
import fastDeepEqual from "fast-deep-equal";
|
|
34
|
-
import type { Dispatch
|
|
35
|
-
import {
|
|
32
|
+
import type { Dispatch } from "react";
|
|
33
|
+
import {
|
|
34
|
+
createContext,
|
|
35
|
+
memo,
|
|
36
|
+
useCallback,
|
|
37
|
+
useContext,
|
|
38
|
+
useEffect,
|
|
39
|
+
useMemo,
|
|
40
|
+
useState,
|
|
41
|
+
useSyncExternalStore,
|
|
42
|
+
} from "react";
|
|
36
43
|
import {
|
|
37
44
|
identity,
|
|
38
45
|
shallowArrayEqual,
|
|
@@ -41,132 +48,21 @@ import {
|
|
|
41
48
|
useRerender,
|
|
42
49
|
useSyncExternalStoreWithSelector,
|
|
43
50
|
} from "./internal";
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
children?: ReactNode;
|
|
54
|
-
initialStorage?: keyof InferStorage<TCrdt> extends never ? never : InferInitialStorageFn<TCrdt>;
|
|
55
|
-
room: string;
|
|
56
|
-
} & (keyof TPresence extends never ? { initialPresence?: never } : { initialPresence: TPresence });
|
|
57
|
-
|
|
58
|
-
export type MockedRoomProviderProps<
|
|
59
|
-
TIO extends IOLike,
|
|
60
|
-
TPresence extends JsonObject,
|
|
61
|
-
TCrdt extends AbstractCrdtDocFactory<any>,
|
|
62
|
-
TEvents extends PluvRouterEventConfig<TIO, TPresence, InferStorage<TCrdt>> = {},
|
|
63
|
-
> = BaseRoomProviderProps<TPresence, TCrdt> & {
|
|
64
|
-
events?: MockedRoomEvents<MergeEvents<TEvents, TIO>>;
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
export type MetadataGetter<TMetadata extends JsonObject> =
|
|
68
|
-
| TMetadata
|
|
69
|
-
| (() => MaybePromise<TMetadata>);
|
|
70
|
-
|
|
71
|
-
export type PluvRoomProviderProps<
|
|
72
|
-
TIO extends IOLike<any, any>,
|
|
73
|
-
TMetadata extends JsonObject,
|
|
74
|
-
TPresence extends JsonObject,
|
|
75
|
-
TCrdt extends AbstractCrdtDocFactory<any>,
|
|
76
|
-
> = BaseRoomProviderProps<TPresence, TCrdt> & {
|
|
77
|
-
connect?: boolean;
|
|
78
|
-
debug?: boolean | PluvRoomDebug<TIO>;
|
|
79
|
-
onAuthorizationFail?: (error: Error) => void;
|
|
80
|
-
} & (keyof TMetadata extends never
|
|
81
|
-
? { metadata?: undefined }
|
|
82
|
-
: { metadata: MetadataGetter<TMetadata> });
|
|
83
|
-
|
|
84
|
-
export interface SubscriptionHookOptions<T extends unknown> {
|
|
85
|
-
isEqual?: (a: T, b: T) => boolean;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
export type UpdateMyPresenceAction<TPresence extends JsonObject> =
|
|
89
|
-
| Partial<TPresence>
|
|
90
|
-
| ((oldPresence: TPresence | null) => Partial<TPresence>);
|
|
91
|
-
|
|
92
|
-
export type BroadcastProxy<TIO extends IOLike> = (<TEvent extends keyof InferIOInput<TIO>>(
|
|
93
|
-
event: TEvent,
|
|
94
|
-
data: Id<InferIOInput<TIO>[TEvent]>,
|
|
95
|
-
) => void) & {
|
|
96
|
-
[event in keyof InferIOInput<TIO>]: (input: Id<InferIOInput<TIO>[event]>) => void;
|
|
97
|
-
};
|
|
98
|
-
|
|
99
|
-
export type EventProxy<TIO extends IOLike> = {
|
|
100
|
-
[event in keyof InferIOOutput<TIO>]: {
|
|
101
|
-
useEvent: (callback: (data: Id<IOEventMessage<TIO, event>>) => void) => void;
|
|
102
|
-
};
|
|
103
|
-
};
|
|
104
|
-
|
|
105
|
-
export interface CreateBundle<
|
|
106
|
-
TIO extends IOLike,
|
|
107
|
-
TMetadata extends JsonObject,
|
|
108
|
-
TPresence extends JsonObject = {},
|
|
109
|
-
TCrdt extends AbstractCrdtDocFactory<any> = NoopCrdtDocFactory,
|
|
110
|
-
TEvents extends PluvRouterEventConfig<TIO, TPresence, InferStorage<TCrdt>> = {},
|
|
111
|
-
> {
|
|
112
|
-
// components
|
|
113
|
-
MockedRoomProvider: FC<MockedRoomProviderProps<TIO, TPresence, TCrdt>>;
|
|
114
|
-
PluvProvider: FC<PluvProviderProps>;
|
|
115
|
-
PluvRoomProvider: FC<PluvRoomProviderProps<TIO, TMetadata, TPresence, TCrdt>>;
|
|
116
|
-
|
|
117
|
-
// proxies
|
|
118
|
-
event: EventProxy<MergeEvents<TEvents, TIO>>;
|
|
119
|
-
|
|
120
|
-
// hooks
|
|
121
|
-
useBroadcast: () => BroadcastProxy<MergeEvents<TEvents, TIO>>;
|
|
122
|
-
useCanRedo: () => boolean;
|
|
123
|
-
useCanUndo: () => boolean;
|
|
124
|
-
useClient: () => PluvClient<TIO, TPresence, TCrdt, TMetadata>;
|
|
125
|
-
useConnection: <T extends unknown = WebSocketConnection>(
|
|
126
|
-
selector: (connection: WebSocketConnection) => T,
|
|
127
|
-
options?: SubscriptionHookOptions<Id<T>>,
|
|
128
|
-
) => Id<T>;
|
|
129
|
-
useDoc: () => CrdtDocLike<InferStorage<TCrdt>>;
|
|
130
|
-
useEvent: <TType extends keyof InferIOOutput<MergeEvents<TEvents, TIO>>>(
|
|
131
|
-
type: TType,
|
|
132
|
-
callback: (data: Id<IOEventMessage<MergeEvents<TEvents, TIO>, TType>>) => void,
|
|
133
|
-
) => void;
|
|
134
|
-
useMyPresence: <T extends unknown = TPresence>(
|
|
135
|
-
selector?: (myPresence: TPresence) => T,
|
|
136
|
-
options?: SubscriptionHookOptions<Id<T> | null>,
|
|
137
|
-
) => [myPresence: Id<T>, updateMyPresence: Dispatch<UpdateMyPresenceAction<TPresence>>];
|
|
138
|
-
useMyself: <T extends unknown = UserInfo<TIO, TPresence>>(
|
|
139
|
-
selector?: (myself: Id<UserInfo<TIO, TPresence>>) => T,
|
|
140
|
-
options?: SubscriptionHookOptions<Id<T> | null>,
|
|
141
|
-
) => Id<T> | null;
|
|
142
|
-
useOther: <T extends unknown = UserInfo<TIO, TPresence>>(
|
|
143
|
-
connectionId: string,
|
|
144
|
-
selector?: (other: UserInfo<TIO, TPresence>) => T,
|
|
145
|
-
options?: SubscriptionHookOptions<T | null>,
|
|
146
|
-
) => T | null;
|
|
147
|
-
useOthers: <T extends unknown = readonly UserInfo<TIO, TPresence>[]>(
|
|
148
|
-
selector?: (other: readonly Id<UserInfo<TIO, TPresence>>[]) => T,
|
|
149
|
-
options?: SubscriptionHookOptions<T>,
|
|
150
|
-
) => T;
|
|
151
|
-
useRedo: () => () => void;
|
|
152
|
-
useRoom: () => RoomLike<TIO, TPresence, InferStorage<TCrdt>>;
|
|
153
|
-
useStorage: <
|
|
154
|
-
TKey extends keyof InferStorage<TCrdt>,
|
|
155
|
-
TData extends unknown = InferCrdtJson<InferStorage<TCrdt>[TKey]>,
|
|
156
|
-
>(
|
|
157
|
-
key: TKey,
|
|
158
|
-
selector?: (data: InferCrdtJson<InferStorage<TCrdt>[TKey]>) => TData,
|
|
159
|
-
options?: SubscriptionHookOptions<TData | null>,
|
|
160
|
-
) => [data: TData | null, sharedType: InferStorage<TCrdt>[TKey] | null];
|
|
161
|
-
useTransact: () => (fn: (storage: InferStorage<TCrdt>) => void, origin?: string) => void;
|
|
162
|
-
useUndo: () => () => void;
|
|
163
|
-
}
|
|
51
|
+
import type {
|
|
52
|
+
BroadcastProxy,
|
|
53
|
+
CreateBundle,
|
|
54
|
+
EventProxy,
|
|
55
|
+
MockedRoomProviderProps,
|
|
56
|
+
PluvProviderProps,
|
|
57
|
+
PluvRoomProviderProps,
|
|
58
|
+
SubscriptionHookOptions,
|
|
59
|
+
} from "./types";
|
|
164
60
|
|
|
165
61
|
export type CreateBundleOptions<
|
|
166
|
-
TIO extends IOLike
|
|
62
|
+
TIO extends IOLike<any>,
|
|
167
63
|
TMetadata extends JsonObject = {},
|
|
168
|
-
TPresence extends
|
|
169
|
-
TCrdt extends AbstractCrdtDocFactory<any> = NoopCrdtDocFactory,
|
|
64
|
+
TPresence extends Record<string, any> = {},
|
|
65
|
+
TCrdt extends AbstractCrdtDocFactory<any, any> = NoopCrdtDocFactory,
|
|
170
66
|
TEvents extends PluvRouterEventConfig<TIO, TPresence, InferStorage<TCrdt>> = {},
|
|
171
67
|
> = {
|
|
172
68
|
addons?: readonly PluvRoomAddon<TIO, TMetadata, TPresence, TCrdt>[];
|
|
@@ -176,8 +72,8 @@ export type CreateBundleOptions<
|
|
|
176
72
|
export const createBundle = <
|
|
177
73
|
TIO extends IOLike<any, any>,
|
|
178
74
|
TMetadata extends JsonObject = {},
|
|
179
|
-
TPresence extends
|
|
180
|
-
TCrdt extends AbstractCrdtDocFactory<any> = NoopCrdtDocFactory,
|
|
75
|
+
TPresence extends Record<string, any> = {},
|
|
76
|
+
TCrdt extends AbstractCrdtDocFactory<any, any> = NoopCrdtDocFactory,
|
|
181
77
|
TEvents extends PluvRouterEventConfig<TIO, TPresence, InferStorage<TCrdt>> = {},
|
|
182
78
|
>(
|
|
183
79
|
client: PluvClient<TIO, TPresence, TCrdt, TMetadata>,
|
|
@@ -197,13 +93,17 @@ export const createBundle = <
|
|
|
197
93
|
* and let the users deal with it.
|
|
198
94
|
* @date November 11, 2022
|
|
199
95
|
*/
|
|
200
|
-
const PluvRoomContext = createContext<
|
|
201
|
-
|
|
202
|
-
);
|
|
203
|
-
|
|
204
|
-
const MockedRoomContext = createContext<RoomLike<
|
|
205
|
-
|
|
206
|
-
|
|
96
|
+
const PluvRoomContext = createContext<
|
|
97
|
+
RoomLike<TIO, InferDoc<TCrdt>, TPresence, InferStorage<TCrdt>, TEvents>
|
|
98
|
+
>(null as any);
|
|
99
|
+
|
|
100
|
+
const MockedRoomContext = createContext<RoomLike<
|
|
101
|
+
TIO,
|
|
102
|
+
InferDoc<TCrdt>,
|
|
103
|
+
TPresence,
|
|
104
|
+
InferStorage<TCrdt>,
|
|
105
|
+
TEvents
|
|
106
|
+
> | null>(null);
|
|
207
107
|
|
|
208
108
|
const MockedRoomProvider = memo<MockedRoomProviderProps<TIO, TPresence, TCrdt>>((props) => {
|
|
209
109
|
const { children, events, initialPresence, initialStorage, room: _room } = props;
|
|
@@ -253,7 +153,13 @@ export const createBundle = <
|
|
|
253
153
|
return !!room.metadata ? room.metadata.parse(resolved) : resolved;
|
|
254
154
|
});
|
|
255
155
|
|
|
256
|
-
const
|
|
156
|
+
const createRoom = useCallback((): PluvRoom<
|
|
157
|
+
TIO,
|
|
158
|
+
TMetadata,
|
|
159
|
+
TPresence,
|
|
160
|
+
TCrdt,
|
|
161
|
+
TEvents
|
|
162
|
+
> => {
|
|
257
163
|
return client.createRoom(_room, {
|
|
258
164
|
addons: options.addons,
|
|
259
165
|
debug,
|
|
@@ -266,10 +172,18 @@ export const createBundle = <
|
|
|
266
172
|
onAuthorizationFail,
|
|
267
173
|
router: options.router,
|
|
268
174
|
} as CreateRoomOptions<TIO, TPresence, TCrdt, TMetadata, TEvents>);
|
|
269
|
-
});
|
|
175
|
+
}, [_room, debug, initialPresence, initialStorage, metadata, onAuthorizationFail]);
|
|
176
|
+
|
|
177
|
+
const [room, setRoom] = useState(() => createRoom());
|
|
270
178
|
|
|
271
179
|
useEffect(() => {
|
|
272
|
-
|
|
180
|
+
if (room.id === _room) return;
|
|
181
|
+
|
|
182
|
+
setRoom(createRoom());
|
|
183
|
+
}, [_room, createRoom, room]);
|
|
184
|
+
|
|
185
|
+
useEffect(() => {
|
|
186
|
+
const unsubscribe = room.subscribe.connection(() => {
|
|
273
187
|
rerender();
|
|
274
188
|
});
|
|
275
189
|
|
|
@@ -378,7 +292,7 @@ export const createBundle = <
|
|
|
378
292
|
const room = useRoom();
|
|
379
293
|
|
|
380
294
|
const subscribe = useCallback(
|
|
381
|
-
(onStoreChange: () => void) => room.
|
|
295
|
+
(onStoreChange: () => void) => room.subscribe.storage(onStoreChange),
|
|
382
296
|
[room],
|
|
383
297
|
);
|
|
384
298
|
|
|
@@ -398,7 +312,7 @@ export const createBundle = <
|
|
|
398
312
|
const room = useRoom();
|
|
399
313
|
|
|
400
314
|
const subscribe = useCallback(
|
|
401
|
-
(onStoreChange: () => void) => room.
|
|
315
|
+
(onStoreChange: () => void) => room.subscribe.storage(onStoreChange),
|
|
402
316
|
[room],
|
|
403
317
|
);
|
|
404
318
|
|
|
@@ -422,7 +336,7 @@ export const createBundle = <
|
|
|
422
336
|
|
|
423
337
|
const subscribe = useCallback(
|
|
424
338
|
(onStoreChange: () => void) => {
|
|
425
|
-
return room.subscribe(
|
|
339
|
+
return room.subscribe.connection(onStoreChange);
|
|
426
340
|
},
|
|
427
341
|
[room],
|
|
428
342
|
);
|
|
@@ -446,7 +360,16 @@ export const createBundle = <
|
|
|
446
360
|
const useDoc = () => {
|
|
447
361
|
const room = useRoom();
|
|
448
362
|
|
|
449
|
-
|
|
363
|
+
const subscribe = useCallback(
|
|
364
|
+
(onStoreChange: () => void) => {
|
|
365
|
+
return room.subscribe.storageLoaded(onStoreChange);
|
|
366
|
+
},
|
|
367
|
+
[room],
|
|
368
|
+
);
|
|
369
|
+
|
|
370
|
+
const getSnapshot = room.getDoc;
|
|
371
|
+
|
|
372
|
+
return useSyncExternalStore(subscribe, getSnapshot, getSnapshot);
|
|
450
373
|
};
|
|
451
374
|
|
|
452
375
|
const useEvent = <TType extends keyof InferIOOutput<MergeEvents<TEvents, TIO>>>(
|
|
@@ -456,7 +379,7 @@ export const createBundle = <
|
|
|
456
379
|
const room = useRoom();
|
|
457
380
|
|
|
458
381
|
useEffect(() => {
|
|
459
|
-
const unsubscribe = room.event(type, callback);
|
|
382
|
+
const unsubscribe = room.subscribe.event(type, callback);
|
|
460
383
|
|
|
461
384
|
return () => {
|
|
462
385
|
unsubscribe();
|
|
@@ -497,7 +420,7 @@ export const createBundle = <
|
|
|
497
420
|
|
|
498
421
|
const subscribe = useCallback(
|
|
499
422
|
(onStoreChange: () => void) => {
|
|
500
|
-
return room.subscribe(
|
|
423
|
+
return room.subscribe.myPresence(onStoreChange);
|
|
501
424
|
},
|
|
502
425
|
[room],
|
|
503
426
|
);
|
|
@@ -528,7 +451,7 @@ export const createBundle = <
|
|
|
528
451
|
|
|
529
452
|
const subscribe = useCallback(
|
|
530
453
|
(onStoreChange: () => void) => {
|
|
531
|
-
return room.subscribe(
|
|
454
|
+
return room.subscribe.myself(onStoreChange);
|
|
532
455
|
},
|
|
533
456
|
[room],
|
|
534
457
|
);
|
|
@@ -559,9 +482,7 @@ export const createBundle = <
|
|
|
559
482
|
const room = useRoom();
|
|
560
483
|
|
|
561
484
|
const subscribe = useCallback(
|
|
562
|
-
(onStoreChange: () => void) =>
|
|
563
|
-
return room.other(connectionId, onStoreChange);
|
|
564
|
-
},
|
|
485
|
+
(onStoreChange: () => void) => room.subscribe.other(connectionId, onStoreChange),
|
|
565
486
|
[room, connectionId],
|
|
566
487
|
);
|
|
567
488
|
|
|
@@ -591,7 +512,7 @@ export const createBundle = <
|
|
|
591
512
|
|
|
592
513
|
const subscribe = useCallback(
|
|
593
514
|
(onStoreChange: () => void) => {
|
|
594
|
-
return room.subscribe(
|
|
515
|
+
return room.subscribe.others(onStoreChange);
|
|
595
516
|
},
|
|
596
517
|
[room],
|
|
597
518
|
);
|
|
@@ -639,12 +560,12 @@ export const createBundle = <
|
|
|
639
560
|
const room = useRoom();
|
|
640
561
|
const rerender = useRerender();
|
|
641
562
|
|
|
642
|
-
room.subscribe(
|
|
563
|
+
room.subscribe.storageLoaded(() => {
|
|
643
564
|
rerender();
|
|
644
565
|
});
|
|
645
566
|
|
|
646
567
|
const subscribe = useCallback(
|
|
647
|
-
(onStoreChange: () => void) => room.storage(key, onStoreChange),
|
|
568
|
+
(onStoreChange: () => void) => room.subscribe.storage(key, onStoreChange),
|
|
648
569
|
[key, room],
|
|
649
570
|
);
|
|
650
571
|
|
package/src/index.ts
CHANGED
package/src/types.ts
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
MergeEvents,
|
|
3
|
+
MockedRoomEvents,
|
|
4
|
+
PluvClient,
|
|
5
|
+
PluvRoomDebug,
|
|
6
|
+
PluvRouterEventConfig,
|
|
7
|
+
UserInfo,
|
|
8
|
+
WebSocketConnection,
|
|
9
|
+
} from "@pluv/client";
|
|
10
|
+
import type {
|
|
11
|
+
AbstractCrdtDocFactory,
|
|
12
|
+
InferCrdtJson,
|
|
13
|
+
InferDoc,
|
|
14
|
+
InferInitialStorageFn,
|
|
15
|
+
InferStorage,
|
|
16
|
+
NoopCrdtDocFactory,
|
|
17
|
+
} from "@pluv/crdt";
|
|
18
|
+
import type {
|
|
19
|
+
CrdtDocLike,
|
|
20
|
+
Id,
|
|
21
|
+
InferIOInput,
|
|
22
|
+
InferIOOutput,
|
|
23
|
+
IOEventMessage,
|
|
24
|
+
IOLike,
|
|
25
|
+
JsonObject,
|
|
26
|
+
MaybePromise,
|
|
27
|
+
RoomLike,
|
|
28
|
+
UpdateMyPresenceAction,
|
|
29
|
+
} from "@pluv/types";
|
|
30
|
+
import type { Dispatch, FC, ReactNode } from "react";
|
|
31
|
+
|
|
32
|
+
export interface PluvProviderProps {
|
|
33
|
+
children?: ReactNode;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
type BaseRoomProviderProps<
|
|
37
|
+
TPresence extends Record<string, any>,
|
|
38
|
+
TCrdt extends AbstractCrdtDocFactory<any, any>,
|
|
39
|
+
> = {
|
|
40
|
+
children?: ReactNode;
|
|
41
|
+
initialStorage?: keyof InferStorage<TCrdt> extends never ? never : InferInitialStorageFn<TCrdt>;
|
|
42
|
+
room: string;
|
|
43
|
+
} & (keyof TPresence extends never ? { initialPresence?: never } : { initialPresence: TPresence });
|
|
44
|
+
|
|
45
|
+
export type MockedRoomProviderProps<
|
|
46
|
+
TIO extends IOLike,
|
|
47
|
+
TPresence extends Record<string, any>,
|
|
48
|
+
TCrdt extends AbstractCrdtDocFactory<any, any>,
|
|
49
|
+
TEvents extends PluvRouterEventConfig<TIO, TPresence, InferStorage<TCrdt>> = {},
|
|
50
|
+
> = BaseRoomProviderProps<TPresence, TCrdt> & {
|
|
51
|
+
events?: MockedRoomEvents<MergeEvents<TEvents, TIO>>;
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export type BroadcastProxy<TIO extends IOLike> = (<TEvent extends keyof InferIOInput<TIO>>(
|
|
55
|
+
event: TEvent,
|
|
56
|
+
data: Id<InferIOInput<TIO>[TEvent]>,
|
|
57
|
+
) => void) & {
|
|
58
|
+
[event in keyof InferIOInput<TIO>]: (input: Id<InferIOInput<TIO>[event]>) => void;
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
export type EventProxy<TIO extends IOLike> = {
|
|
62
|
+
[event in keyof InferIOOutput<TIO>]: {
|
|
63
|
+
useEvent: (callback: (data: Id<IOEventMessage<TIO, event>>) => void) => void;
|
|
64
|
+
};
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
export type MetadataGetter<TMetadata extends JsonObject> =
|
|
68
|
+
| TMetadata
|
|
69
|
+
| (() => MaybePromise<TMetadata>);
|
|
70
|
+
|
|
71
|
+
export type PluvRoomProviderProps<
|
|
72
|
+
TIO extends IOLike<any, any>,
|
|
73
|
+
TMetadata extends JsonObject,
|
|
74
|
+
TPresence extends Record<string, any>,
|
|
75
|
+
TCrdt extends AbstractCrdtDocFactory<any, any>,
|
|
76
|
+
> = BaseRoomProviderProps<TPresence, TCrdt> & {
|
|
77
|
+
connect?: boolean;
|
|
78
|
+
debug?: boolean | PluvRoomDebug<TIO>;
|
|
79
|
+
onAuthorizationFail?: (error: Error) => void;
|
|
80
|
+
} & (keyof TMetadata extends never
|
|
81
|
+
? { metadata?: undefined }
|
|
82
|
+
: { metadata: MetadataGetter<TMetadata> });
|
|
83
|
+
|
|
84
|
+
export interface SubscriptionHookOptions<T extends unknown> {
|
|
85
|
+
isEqual?: (a: T, b: T) => boolean;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
export interface CreateBundle<
|
|
89
|
+
TIO extends IOLike<any>,
|
|
90
|
+
TMetadata extends JsonObject,
|
|
91
|
+
TPresence extends Record<string, any> = {},
|
|
92
|
+
TCrdt extends AbstractCrdtDocFactory<any, any> = NoopCrdtDocFactory,
|
|
93
|
+
TEvents extends PluvRouterEventConfig<TIO, TPresence, InferStorage<TCrdt>> = {},
|
|
94
|
+
> {
|
|
95
|
+
// components
|
|
96
|
+
MockedRoomProvider: FC<MockedRoomProviderProps<TIO, TPresence, TCrdt>>;
|
|
97
|
+
PluvProvider: FC<PluvProviderProps>;
|
|
98
|
+
PluvRoomProvider: FC<PluvRoomProviderProps<TIO, TMetadata, TPresence, TCrdt>>;
|
|
99
|
+
|
|
100
|
+
// proxies
|
|
101
|
+
event: EventProxy<MergeEvents<TEvents, TIO>>;
|
|
102
|
+
|
|
103
|
+
// hooks
|
|
104
|
+
useBroadcast: () => BroadcastProxy<MergeEvents<TEvents, TIO>>;
|
|
105
|
+
useCanRedo: () => boolean;
|
|
106
|
+
useCanUndo: () => boolean;
|
|
107
|
+
useClient: () => PluvClient<TIO, TPresence, TCrdt, TMetadata>;
|
|
108
|
+
useConnection: <T extends unknown = WebSocketConnection>(
|
|
109
|
+
selector?: (connection: WebSocketConnection) => T,
|
|
110
|
+
options?: SubscriptionHookOptions<Id<T>>,
|
|
111
|
+
) => Id<T>;
|
|
112
|
+
useDoc: () => CrdtDocLike<InferDoc<TCrdt>, InferStorage<TCrdt>>;
|
|
113
|
+
useEvent: <TType extends keyof InferIOOutput<MergeEvents<TEvents, TIO>>>(
|
|
114
|
+
type: TType,
|
|
115
|
+
callback: (data: Id<IOEventMessage<MergeEvents<TEvents, TIO>, TType>>) => void,
|
|
116
|
+
) => void;
|
|
117
|
+
useMyPresence: <T extends unknown = TPresence>(
|
|
118
|
+
selector?: (myPresence: TPresence) => T,
|
|
119
|
+
options?: SubscriptionHookOptions<Id<T> | null>,
|
|
120
|
+
) => [myPresence: Id<T>, updateMyPresence: Dispatch<UpdateMyPresenceAction<TPresence>>];
|
|
121
|
+
useMyself: <T extends unknown = UserInfo<TIO, TPresence>>(
|
|
122
|
+
selector?: (myself: Id<UserInfo<TIO, TPresence>>) => T,
|
|
123
|
+
options?: SubscriptionHookOptions<Id<T> | null>,
|
|
124
|
+
) => Id<T> | null;
|
|
125
|
+
useOther: <T extends unknown = UserInfo<TIO, TPresence>>(
|
|
126
|
+
connectionId: string,
|
|
127
|
+
selector?: (other: UserInfo<TIO, TPresence>) => T,
|
|
128
|
+
options?: SubscriptionHookOptions<T | null>,
|
|
129
|
+
) => T | null;
|
|
130
|
+
useOthers: <T extends unknown = readonly UserInfo<TIO, TPresence>[]>(
|
|
131
|
+
selector?: (other: readonly Id<UserInfo<TIO, TPresence>>[]) => T,
|
|
132
|
+
options?: SubscriptionHookOptions<T>,
|
|
133
|
+
) => T;
|
|
134
|
+
useRedo: () => () => void;
|
|
135
|
+
useRoom: () => RoomLike<TIO, InferDoc<TCrdt>, TPresence, InferStorage<TCrdt>, TEvents>;
|
|
136
|
+
useStorage: <
|
|
137
|
+
TKey extends keyof InferStorage<TCrdt>,
|
|
138
|
+
TData extends unknown = InferCrdtJson<InferStorage<TCrdt>[TKey]>,
|
|
139
|
+
>(
|
|
140
|
+
key: TKey,
|
|
141
|
+
selector?: (data: InferCrdtJson<InferStorage<TCrdt>[TKey]>) => TData,
|
|
142
|
+
options?: SubscriptionHookOptions<TData | null>,
|
|
143
|
+
) => [data: TData | null, sharedType: InferStorage<TCrdt>[TKey] | null];
|
|
144
|
+
useTransact: () => (fn: (storage: InferStorage<TCrdt>) => void, origin?: string) => void;
|
|
145
|
+
useUndo: () => () => void;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export type InferBundleRoom<TBundle extends CreateBundle<any, any, any, any, any>> =
|
|
149
|
+
TBundle extends CreateBundle<infer IIO, any, infer IPresence, infer ICrdt, infer IEvents>
|
|
150
|
+
? RoomLike<IIO, InferDoc<ICrdt>, IPresence, InferStorage<ICrdt>, IEvents>
|
|
151
|
+
: never;
|