@pluv/react 2.1.0 → 2.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +8 -8
- package/CHANGELOG.md +57 -0
- package/dist/index.d.mts +23 -22
- package/dist/index.d.ts +23 -22
- package/dist/index.js +17 -9
- package/dist/index.mjs +27 -10
- package/package.json +7 -7
- package/src/createBundle.tsx +66 -143
- 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.
|
|
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,62 @@
|
|
|
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
|
+
|
|
3
60
|
## 2.1.0
|
|
4
61
|
|
|
5
62
|
### Minor 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,7 +272,12 @@ 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());
|
|
277
|
+
(0, import_react6.useEffect)(() => {
|
|
278
|
+
if (room.id === _room) return;
|
|
279
|
+
setRoom(createRoom());
|
|
280
|
+
}, [_room, createRoom, room]);
|
|
280
281
|
(0, import_react6.useEffect)(() => {
|
|
281
282
|
const unsubscribe = room.subscribe.connection(() => {
|
|
282
283
|
rerender();
|
|
@@ -402,7 +403,14 @@ 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();
|
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,7 +248,12 @@ 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());
|
|
253
|
+
useEffect3(() => {
|
|
254
|
+
if (room.id === _room) return;
|
|
255
|
+
setRoom(createRoom());
|
|
256
|
+
}, [_room, createRoom, room]);
|
|
247
257
|
useEffect3(() => {
|
|
248
258
|
const unsubscribe = room.subscribe.connection(() => {
|
|
249
259
|
rerender();
|
|
@@ -369,7 +379,14 @@ 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();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pluv/react",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.2.0",
|
|
4
4
|
"description": "@pluv/client React.js bindings",
|
|
5
5
|
"author": "leedavidcs",
|
|
6
6
|
"license": "MIT",
|
|
@@ -18,22 +18,22 @@
|
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
20
|
"fast-deep-equal": "^3.1.3",
|
|
21
|
-
"@pluv/client": "^2.
|
|
22
|
-
"@pluv/crdt": "^2.
|
|
23
|
-
"@pluv/types": "^2.
|
|
21
|
+
"@pluv/client": "^2.2.0",
|
|
22
|
+
"@pluv/crdt": "^2.2.0",
|
|
23
|
+
"@pluv/types": "^2.2.0"
|
|
24
24
|
},
|
|
25
25
|
"peerDependencies": {
|
|
26
26
|
"@types/react": "^18.0.0 || ^19.0.0",
|
|
27
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/tsconfig": "^2.
|
|
36
|
-
"eslint-config-pluv": "^2.
|
|
35
|
+
"@pluv/tsconfig": "^2.2.0",
|
|
36
|
+
"eslint-config-pluv": "^2.2.0"
|
|
37
37
|
},
|
|
38
38
|
"scripts": {
|
|
39
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,7 +172,15 @@ 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());
|
|
178
|
+
|
|
179
|
+
useEffect(() => {
|
|
180
|
+
if (room.id === _room) return;
|
|
181
|
+
|
|
182
|
+
setRoom(createRoom());
|
|
183
|
+
}, [_room, createRoom, room]);
|
|
270
184
|
|
|
271
185
|
useEffect(() => {
|
|
272
186
|
const unsubscribe = room.subscribe.connection(() => {
|
|
@@ -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>>>(
|
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;
|