@pluv/react 0.26.0 → 0.28.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.
@@ -1,18 +1,18 @@
1
1
 
2
- > @pluv/react@0.26.0 build /home/runner/work/pluv/pluv/packages/react
2
+ > @pluv/react@0.28.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
  CLI Building entry: src/index.ts
6
6
  CLI Using tsconfig: tsconfig.json
7
- CLI tsup v8.2.4
7
+ CLI tsup v8.3.0
8
8
  CLI Target: es6
9
9
  ESM Build start
10
10
  CJS Build start
11
- CJS dist/index.js 14.30 KB
12
- CJS ⚡️ Build success in 127ms
13
- ESM dist/index.mjs 11.89 KB
14
- ESM ⚡️ Build success in 128ms
11
+ ESM dist/index.mjs 11.84 KB
12
+ ESM ⚡️ Build success in 141ms
13
+ CJS dist/index.js 14.23 KB
14
+ CJS ⚡️ Build success in 141ms
15
15
  DTS Build start
16
- DTS ⚡️ Build success in 4697ms
17
- DTS dist/index.d.mts 5.50 KB
18
- DTS dist/index.d.ts 5.50 KB
16
+ DTS ⚡️ Build success in 4997ms
17
+ DTS dist/index.d.mts 6.04 KB
18
+ DTS dist/index.d.ts 6.04 KB
package/CHANGELOG.md CHANGED
@@ -1,5 +1,137 @@
1
1
  # @pluv/react
2
2
 
3
+ ## 0.28.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 778b43e: Remove the `initialStorage` option from `createRoomBundle`. This has been moved to `createClient`.
8
+
9
+ ### Patch Changes
10
+
11
+ - @pluv/client@0.28.0
12
+ - @pluv/crdt@0.28.0
13
+ - @pluv/types@0.28.0
14
+
15
+ ## 0.27.0
16
+
17
+ ### Minor Changes
18
+
19
+ - 19ed36c: Updated `createClient` and `createRoomBundle` object params to better support automatic type inference.
20
+
21
+ ```ts
22
+ // Before
23
+ import { createClient } from "@pluv/react";
24
+ import { yjs } from "@pluv/crdt-yjs";
25
+ import { z } from "zod";
26
+ import type { ioServer } from "./server/ioServer";
27
+
28
+ const client = createClient<typeof ioServer>({
29
+ authEndpoint: ({ room }) => "MY_AUTH_URL",
30
+ wsEndpoint: ({ room }) => "MY_WEBSOCKET_URL",
31
+ });
32
+
33
+ client.createRoom("my-example-room", {
34
+ presence: z.object({
35
+ selectionId: z.string().nullish(),
36
+ }),
37
+ initialPresence: {
38
+ selectionId: null,
39
+ },
40
+ initialStorage: yjs.doc(() => ({
41
+ messages: yjs.array<string>([]),
42
+ })),
43
+ });
44
+
45
+ // After
46
+
47
+ import { createBundle, createClient } from "@pluv/react";
48
+
49
+ const client = createClient({
50
+ authEndpoint: ({ room }) => "MY_AUTH_URL",
51
+ wsEndpoint: ({ room }) => "MY_WEBSOCKET_URL",
52
+ /**
53
+ * @description The ioServer type now needs to be inferred on this property
54
+ * instead of within the generic on `createClient`. This is because of
55
+ * limitations with TypeScript not yet supporting partial type-inference
56
+ * for generics. Ensure to no-loonger include any generics on `createClient`
57
+ */
58
+ infer: (i) => ({ io: i<typeof ioServer> }),
59
+ // Now moved to `createClient` from `PluvClient.createRoom`
60
+ presence: z.object({
61
+ selectionId: z.string().nullish(),
62
+ }),
63
+ /**
64
+ * @description Now added to `createClient` to specify defaults for all
65
+ * rooms, and to infer types for storage. This value will be overwritten by
66
+ * `PluvClient.createRoom`.
67
+ */
68
+ initialStorage: yjs.doc(() => ({
69
+ messages: yjs.array<string>([]),
70
+ })),
71
+ });
72
+
73
+ const { createRoomBundle } = createBundle(client);
74
+ const pluv = createRoomBundle({});
75
+ ```
76
+
77
+ ### Patch Changes
78
+
79
+ - 19ed36c: Added client-side event router. This more-or-less mirrors the server-side event router. You can use both the server-side and client-side router simultaneously, but you should generally prefer only using one or the other.
80
+
81
+ ```ts
82
+ // Backend Server
83
+ import { createIO } from "@pluv/io";
84
+
85
+ const io = createIO({ /* ... */ });
86
+ const ioServer = io.server({
87
+ router: io.router({
88
+ multiply2: io.procedure
89
+ .input(z.object({ value: z.number() }))
90
+ .broadcast(({ value }) => ({
91
+ multiplied2: { value: value * 2 },
92
+ })),
93
+ }),
94
+ });
95
+
96
+ // Frontend Client
97
+ import { createBundle createClient } from "@pluv/react";
98
+
99
+ const io = createClient({ /* ... */ });
100
+
101
+ const { createRoomBundle } = createBundle(io);
102
+ const pluv = createRoomBundle({
103
+ // ...
104
+ router: io.router({
105
+ add5: io.procedure
106
+ .input(z.object({ value: z.number() }))
107
+ .broadcast(({ value }) => ({
108
+ /**
109
+ * @description Because `ioServer` does not specify `added5`,
110
+ * this will be forwarded to connected peers.
111
+ */
112
+ added5: { value: value + 5 },
113
+ })),
114
+ /**
115
+ * @description This is possible, but not recommended to do. Because
116
+ * `multiply2` is a procedure on `ioServer`, this will trigger the
117
+ * `multiply2` procedure on `ioServer`. Connected peers will not
118
+ * receive `multiply2`, but rather `multipled2`.
119
+ */
120
+ subtract5Multiply2: io.procedure
121
+ .input(z.object({ value: z.number() }))
122
+ .broadcast(({ value }) => ({
123
+ multiply2: { value: value - 5 },
124
+ })),
125
+ }),
126
+ });
127
+ ```
128
+
129
+ - Updated dependencies [19ed36c]
130
+ - Updated dependencies [19ed36c]
131
+ - @pluv/client@0.27.0
132
+ - @pluv/crdt@0.27.0
133
+ - @pluv/types@0.27.0
134
+
3
135
  ## 0.26.0
4
136
 
5
137
  ### Minor Changes
package/dist/index.d.mts CHANGED
@@ -1,15 +1,14 @@
1
- import { PluvRoomAddon, PluvRoomDebug, WebSocketConnection, UserInfo, AbstractRoom, MockedRoomEvents, PluvClient } from '@pluv/client';
1
+ import { PluvRouterEventConfig, PluvRoomAddon, PluvRouter, PluvRoomDebug, MergeEvents, WebSocketConnection, UserInfo, AbstractRoom, MockedRoomEvents, PluvClient } from '@pluv/client';
2
2
  export { ConnectionState, createClient } from '@pluv/client';
3
- import { CrdtType, AbstractCrdtDocFactory, AbstractCrdtDoc, InferCrdtJson } from '@pluv/crdt';
3
+ import { CrdtType, AbstractCrdtDoc, InferCrdtJson } from '@pluv/crdt';
4
4
  export { CrdtType, InferCrdtJson } from '@pluv/crdt';
5
- import { IOLike, JsonObject, InputZodLike, Id, InferIOOutput, IOEventMessage, InferIOInput } from '@pluv/types';
5
+ import { IOLike, JsonObject, Id, InferIOOutput, IOEventMessage, InferIOInput } from '@pluv/types';
6
6
  export { BaseUser, EventMessage, EventRecord, IOEventMessage } from '@pluv/types';
7
7
  import { FC, Dispatch, ReactNode } from 'react';
8
8
 
9
- type CreateRoomBundleOptions<TIO extends IOLike, TMetadata extends JsonObject = {}, TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}> = {
9
+ type CreateRoomBundleOptions<TIO extends IOLike, TMetadata extends JsonObject = {}, TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}, TEvents extends PluvRouterEventConfig<TIO, TPresence, TStorage> = {}> = {
10
10
  addons?: readonly PluvRoomAddon<TIO, TMetadata, TPresence, TStorage>[];
11
- initialStorage?: AbstractCrdtDocFactory<TStorage>;
12
- presence?: InputZodLike<TPresence>;
11
+ router?: PluvRouter<TIO, TPresence, TStorage, TEvents>;
13
12
  };
14
13
  type BaseRoomProviderProps<TPresence extends JsonObject, TStorage extends Record<string, CrdtType<any, any>>> = {
15
14
  children?: ReactNode;
@@ -20,8 +19,8 @@ type BaseRoomProviderProps<TPresence extends JsonObject, TStorage extends Record
20
19
  } : {
21
20
  initialPresence: TPresence;
22
21
  });
23
- type MockedRoomProviderProps<TIO extends IOLike, TPresence extends JsonObject, TStorage extends Record<string, CrdtType<any, any>>> = BaseRoomProviderProps<TPresence, TStorage> & {
24
- events?: MockedRoomEvents<TIO>;
22
+ type MockedRoomProviderProps<TIO extends IOLike, TPresence extends JsonObject, TStorage extends Record<string, CrdtType<any, any>>, TEvents extends PluvRouterEventConfig<TIO, TPresence, TStorage> = {}> = BaseRoomProviderProps<TPresence, TStorage> & {
23
+ events?: MockedRoomEvents<MergeEvents<TEvents, TIO>>;
25
24
  };
26
25
  type PluvRoomProviderProps<TIO extends IOLike, TMetadata extends JsonObject, TPresence extends JsonObject, TStorage extends Record<string, CrdtType<any, any>>> = BaseRoomProviderProps<TPresence, TStorage> & {
27
26
  debug?: boolean | PluvRoomDebug<TIO>;
@@ -43,16 +42,16 @@ type EventProxy<TIO extends IOLike> = {
43
42
  useEvent: (callback: (data: Id<IOEventMessage<TIO, event>>) => void) => void;
44
43
  };
45
44
  };
46
- interface CreateRoomBundle<TIO extends IOLike, TMetadata extends JsonObject, TPresence extends JsonObject, TStorage extends Record<string, CrdtType<any, any>>> {
45
+ interface CreateRoomBundle<TIO extends IOLike, TMetadata extends JsonObject, TPresence extends JsonObject, TStorage extends Record<string, CrdtType<any, any>>, TEvents extends PluvRouterEventConfig<TIO, TPresence, TStorage> = {}> {
47
46
  MockedRoomProvider: FC<MockedRoomProviderProps<TIO, TPresence, TStorage>>;
48
47
  PluvRoomProvider: FC<PluvRoomProviderProps<TIO, TMetadata, TPresence, TStorage>>;
49
- event: EventProxy<TIO>;
50
- useBroadcast: () => BroadcastProxy<TIO>;
48
+ event: EventProxy<MergeEvents<TEvents, TIO>>;
49
+ useBroadcast: () => BroadcastProxy<MergeEvents<TEvents, TIO>>;
51
50
  useCanRedo: () => boolean;
52
51
  useCanUndo: () => boolean;
53
52
  useConnection: <T extends unknown = WebSocketConnection>(selector: (connection: WebSocketConnection) => T, options?: SubscriptionHookOptions<Id<T>>) => Id<T>;
54
53
  useDoc: () => AbstractCrdtDoc<TStorage>;
55
- useEvent: <TType extends keyof InferIOOutput<TIO>>(type: TType, callback: (data: Id<IOEventMessage<TIO, TType>>) => void) => void;
54
+ useEvent: <TType extends keyof InferIOOutput<MergeEvents<TEvents, TIO>>>(type: TType, callback: (data: Id<IOEventMessage<MergeEvents<TEvents, TIO>, TType>>) => void) => void;
56
55
  useMyPresence: <T extends unknown = TPresence>(selector?: (myPresence: TPresence) => T, options?: SubscriptionHookOptions<Id<T> | null>) => [myPresence: Id<T>, updateMyPresence: Dispatch<UpdateMyPresenceAction<TPresence>>];
57
56
  useMyself: <T extends unknown = UserInfo<TIO, TPresence>>(selector?: (myself: Id<UserInfo<TIO, TPresence>>) => T, options?: SubscriptionHookOptions<Id<T> | null>) => Id<T> | null;
58
57
  useOther: <T extends unknown = UserInfo<TIO, TPresence>>(connectionId: string, selector?: (other: UserInfo<TIO, TPresence>) => T, options?: SubscriptionHookOptions<T | null>) => T | null;
@@ -63,16 +62,16 @@ interface CreateRoomBundle<TIO extends IOLike, TMetadata extends JsonObject, TPr
63
62
  useTransact: () => (fn: (storage: TStorage) => void, origin?: string) => void;
64
63
  useUndo: () => () => void;
65
64
  }
66
- type InferRoomStorage<TRoomBundle extends CreateRoomBundle<any, any, any, any>> = TRoomBundle extends CreateRoomBundle<any, any, any, infer IStorage> ? IStorage : never;
65
+ type InferRoomStorage<TRoomBundle extends CreateRoomBundle<any, any, any, any, any>> = TRoomBundle extends CreateRoomBundle<any, any, any, infer IStorage> ? IStorage : never;
67
66
 
68
67
  interface PluvProviderProps {
69
68
  children?: ReactNode;
70
69
  }
71
- interface CreateBundle<TIO extends IOLike, TMetadata extends JsonObject> {
72
- createRoomBundle: <TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}>(options: CreateRoomBundleOptions<TIO, TMetadata, TPresence, TStorage>) => CreateRoomBundle<TIO, TMetadata, TPresence, TStorage>;
70
+ interface CreateBundle<TIO extends IOLike, TMetadata extends JsonObject, TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}> {
71
+ createRoomBundle: <TEvents extends PluvRouterEventConfig<TIO, TPresence, TStorage> = {}>(options: CreateRoomBundleOptions<TIO, TMetadata, TPresence, TStorage, TEvents>) => CreateRoomBundle<TIO, TMetadata, TPresence, TStorage, TEvents>;
73
72
  PluvProvider: FC<PluvProviderProps>;
74
- useClient: () => PluvClient<TIO, TMetadata>;
73
+ useClient: () => PluvClient<TIO, TPresence, TStorage, TMetadata>;
75
74
  }
76
- declare const createBundle: <TIO extends IOLike, TMetadata extends JsonObject>(client: PluvClient<TIO, TMetadata>) => CreateBundle<TIO, TMetadata>;
75
+ declare const createBundle: <TIO extends IOLike, TMetadata extends JsonObject = {}, TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}>(client: PluvClient<TIO, TPresence, TStorage, TMetadata>) => CreateBundle<TIO, TMetadata, TPresence, TStorage>;
77
76
 
78
77
  export { type CreateBundle, type CreateRoomBundle, type CreateRoomBundleOptions, type InferRoomStorage, type PluvProviderProps, type PluvRoomProviderProps, type SubscriptionHookOptions, createBundle };
package/dist/index.d.ts CHANGED
@@ -1,15 +1,14 @@
1
- import { PluvRoomAddon, PluvRoomDebug, WebSocketConnection, UserInfo, AbstractRoom, MockedRoomEvents, PluvClient } from '@pluv/client';
1
+ import { PluvRouterEventConfig, PluvRoomAddon, PluvRouter, PluvRoomDebug, MergeEvents, WebSocketConnection, UserInfo, AbstractRoom, MockedRoomEvents, PluvClient } from '@pluv/client';
2
2
  export { ConnectionState, createClient } from '@pluv/client';
3
- import { CrdtType, AbstractCrdtDocFactory, AbstractCrdtDoc, InferCrdtJson } from '@pluv/crdt';
3
+ import { CrdtType, AbstractCrdtDoc, InferCrdtJson } from '@pluv/crdt';
4
4
  export { CrdtType, InferCrdtJson } from '@pluv/crdt';
5
- import { IOLike, JsonObject, InputZodLike, Id, InferIOOutput, IOEventMessage, InferIOInput } from '@pluv/types';
5
+ import { IOLike, JsonObject, Id, InferIOOutput, IOEventMessage, InferIOInput } from '@pluv/types';
6
6
  export { BaseUser, EventMessage, EventRecord, IOEventMessage } from '@pluv/types';
7
7
  import { FC, Dispatch, ReactNode } from 'react';
8
8
 
9
- type CreateRoomBundleOptions<TIO extends IOLike, TMetadata extends JsonObject = {}, TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}> = {
9
+ type CreateRoomBundleOptions<TIO extends IOLike, TMetadata extends JsonObject = {}, TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}, TEvents extends PluvRouterEventConfig<TIO, TPresence, TStorage> = {}> = {
10
10
  addons?: readonly PluvRoomAddon<TIO, TMetadata, TPresence, TStorage>[];
11
- initialStorage?: AbstractCrdtDocFactory<TStorage>;
12
- presence?: InputZodLike<TPresence>;
11
+ router?: PluvRouter<TIO, TPresence, TStorage, TEvents>;
13
12
  };
14
13
  type BaseRoomProviderProps<TPresence extends JsonObject, TStorage extends Record<string, CrdtType<any, any>>> = {
15
14
  children?: ReactNode;
@@ -20,8 +19,8 @@ type BaseRoomProviderProps<TPresence extends JsonObject, TStorage extends Record
20
19
  } : {
21
20
  initialPresence: TPresence;
22
21
  });
23
- type MockedRoomProviderProps<TIO extends IOLike, TPresence extends JsonObject, TStorage extends Record<string, CrdtType<any, any>>> = BaseRoomProviderProps<TPresence, TStorage> & {
24
- events?: MockedRoomEvents<TIO>;
22
+ type MockedRoomProviderProps<TIO extends IOLike, TPresence extends JsonObject, TStorage extends Record<string, CrdtType<any, any>>, TEvents extends PluvRouterEventConfig<TIO, TPresence, TStorage> = {}> = BaseRoomProviderProps<TPresence, TStorage> & {
23
+ events?: MockedRoomEvents<MergeEvents<TEvents, TIO>>;
25
24
  };
26
25
  type PluvRoomProviderProps<TIO extends IOLike, TMetadata extends JsonObject, TPresence extends JsonObject, TStorage extends Record<string, CrdtType<any, any>>> = BaseRoomProviderProps<TPresence, TStorage> & {
27
26
  debug?: boolean | PluvRoomDebug<TIO>;
@@ -43,16 +42,16 @@ type EventProxy<TIO extends IOLike> = {
43
42
  useEvent: (callback: (data: Id<IOEventMessage<TIO, event>>) => void) => void;
44
43
  };
45
44
  };
46
- interface CreateRoomBundle<TIO extends IOLike, TMetadata extends JsonObject, TPresence extends JsonObject, TStorage extends Record<string, CrdtType<any, any>>> {
45
+ interface CreateRoomBundle<TIO extends IOLike, TMetadata extends JsonObject, TPresence extends JsonObject, TStorage extends Record<string, CrdtType<any, any>>, TEvents extends PluvRouterEventConfig<TIO, TPresence, TStorage> = {}> {
47
46
  MockedRoomProvider: FC<MockedRoomProviderProps<TIO, TPresence, TStorage>>;
48
47
  PluvRoomProvider: FC<PluvRoomProviderProps<TIO, TMetadata, TPresence, TStorage>>;
49
- event: EventProxy<TIO>;
50
- useBroadcast: () => BroadcastProxy<TIO>;
48
+ event: EventProxy<MergeEvents<TEvents, TIO>>;
49
+ useBroadcast: () => BroadcastProxy<MergeEvents<TEvents, TIO>>;
51
50
  useCanRedo: () => boolean;
52
51
  useCanUndo: () => boolean;
53
52
  useConnection: <T extends unknown = WebSocketConnection>(selector: (connection: WebSocketConnection) => T, options?: SubscriptionHookOptions<Id<T>>) => Id<T>;
54
53
  useDoc: () => AbstractCrdtDoc<TStorage>;
55
- useEvent: <TType extends keyof InferIOOutput<TIO>>(type: TType, callback: (data: Id<IOEventMessage<TIO, TType>>) => void) => void;
54
+ useEvent: <TType extends keyof InferIOOutput<MergeEvents<TEvents, TIO>>>(type: TType, callback: (data: Id<IOEventMessage<MergeEvents<TEvents, TIO>, TType>>) => void) => void;
56
55
  useMyPresence: <T extends unknown = TPresence>(selector?: (myPresence: TPresence) => T, options?: SubscriptionHookOptions<Id<T> | null>) => [myPresence: Id<T>, updateMyPresence: Dispatch<UpdateMyPresenceAction<TPresence>>];
57
56
  useMyself: <T extends unknown = UserInfo<TIO, TPresence>>(selector?: (myself: Id<UserInfo<TIO, TPresence>>) => T, options?: SubscriptionHookOptions<Id<T> | null>) => Id<T> | null;
58
57
  useOther: <T extends unknown = UserInfo<TIO, TPresence>>(connectionId: string, selector?: (other: UserInfo<TIO, TPresence>) => T, options?: SubscriptionHookOptions<T | null>) => T | null;
@@ -63,16 +62,16 @@ interface CreateRoomBundle<TIO extends IOLike, TMetadata extends JsonObject, TPr
63
62
  useTransact: () => (fn: (storage: TStorage) => void, origin?: string) => void;
64
63
  useUndo: () => () => void;
65
64
  }
66
- type InferRoomStorage<TRoomBundle extends CreateRoomBundle<any, any, any, any>> = TRoomBundle extends CreateRoomBundle<any, any, any, infer IStorage> ? IStorage : never;
65
+ type InferRoomStorage<TRoomBundle extends CreateRoomBundle<any, any, any, any, any>> = TRoomBundle extends CreateRoomBundle<any, any, any, infer IStorage> ? IStorage : never;
67
66
 
68
67
  interface PluvProviderProps {
69
68
  children?: ReactNode;
70
69
  }
71
- interface CreateBundle<TIO extends IOLike, TMetadata extends JsonObject> {
72
- createRoomBundle: <TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}>(options: CreateRoomBundleOptions<TIO, TMetadata, TPresence, TStorage>) => CreateRoomBundle<TIO, TMetadata, TPresence, TStorage>;
70
+ interface CreateBundle<TIO extends IOLike, TMetadata extends JsonObject, TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}> {
71
+ createRoomBundle: <TEvents extends PluvRouterEventConfig<TIO, TPresence, TStorage> = {}>(options: CreateRoomBundleOptions<TIO, TMetadata, TPresence, TStorage, TEvents>) => CreateRoomBundle<TIO, TMetadata, TPresence, TStorage, TEvents>;
73
72
  PluvProvider: FC<PluvProviderProps>;
74
- useClient: () => PluvClient<TIO, TMetadata>;
73
+ useClient: () => PluvClient<TIO, TPresence, TStorage, TMetadata>;
75
74
  }
76
- declare const createBundle: <TIO extends IOLike, TMetadata extends JsonObject>(client: PluvClient<TIO, TMetadata>) => CreateBundle<TIO, TMetadata>;
75
+ declare const createBundle: <TIO extends IOLike, TMetadata extends JsonObject = {}, TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}>(client: PluvClient<TIO, TPresence, TStorage, TMetadata>) => CreateBundle<TIO, TMetadata, TPresence, TStorage>;
77
76
 
78
77
  export { type CreateBundle, type CreateRoomBundle, type CreateRoomBundleOptions, type InferRoomStorage, type PluvProviderProps, type PluvRoomProviderProps, type SubscriptionHookOptions, createBundle };
package/dist/index.js CHANGED
@@ -42,7 +42,6 @@ var import_react5 = require("react");
42
42
 
43
43
  // src/createRoomBundle.tsx
44
44
  var import_client = require("@pluv/client");
45
- var import_crdt = require("@pluv/crdt");
46
45
  var import_fast_deep_equal = __toESM(require("fast-deep-equal"));
47
46
  var import_react4 = require("react");
48
47
 
@@ -112,18 +111,16 @@ var useSyncExternalStoreWithSelector = (subscribe, getClientSnapshot, getServerS
112
111
  // src/createRoomBundle.tsx
113
112
  var import_jsx_runtime = require("react/jsx-runtime");
114
113
  var createRoomBundle = (client, options) => {
115
- var _a;
116
- const _initialStorage = (_a = options.initialStorage) != null ? _a : import_crdt.noop.doc();
117
114
  const PluvRoomContext = (0, import_react4.createContext)(null);
118
115
  const MockedRoomContext = (0, import_react4.createContext)({ room: null });
119
116
  const MockedRoomProvider = (0, import_react4.memo)((props) => {
120
117
  const { children, events, initialPresence, initialStorage, room: _room } = props;
121
118
  const [room] = (0, import_react4.useState)(() => {
119
+ var _a;
122
120
  return new import_client.MockedRoom(_room, {
123
121
  events,
124
122
  initialPresence,
125
- initialStorage: typeof initialStorage === "function" ? _initialStorage.getFactory(initialStorage) : _initialStorage,
126
- presence: options.presence
123
+ initialStorage: typeof initialStorage === "function" ? (_a = client._defs.initialStorage) == null ? void 0 : _a.getFactory(initialStorage) : client._defs.initialStorage
127
124
  });
128
125
  });
129
126
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(MockedRoomContext.Provider, { value: { room }, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)(PluvRoomContext.Provider, { value: room, children }) });
@@ -134,14 +131,15 @@ var createRoomBundle = (client, options) => {
134
131
  const rerender = useRerender();
135
132
  const { room: mockedRoom } = (0, import_react4.useContext)(MockedRoomContext);
136
133
  const [room] = (0, import_react4.useState)(() => {
134
+ var _a;
137
135
  return client.createRoom(_room, {
138
136
  addons: options.addons,
139
137
  debug,
140
138
  initialPresence,
141
- initialStorage: typeof initialStorage === "function" ? _initialStorage.getFactory(initialStorage) : _initialStorage,
139
+ initialStorage: typeof initialStorage === "function" ? (_a = client._defs.initialStorage) == null ? void 0 : _a.getFactory(initialStorage) : client._defs.initialStorage,
142
140
  metadata,
143
- presence: options.presence,
144
- onAuthorizationFail
141
+ onAuthorizationFail,
142
+ router: options.router
145
143
  });
146
144
  });
147
145
  (0, import_react4.useEffect)(() => {
@@ -195,7 +193,7 @@ var createRoomBundle = (client, options) => {
195
193
  return canUndo;
196
194
  };
197
195
  const useConnection = (selector = identity, options2) => {
198
- var _a2;
196
+ var _a;
199
197
  const room = useRoom();
200
198
  const subscribe = (0, import_react4.useCallback)(
201
199
  (onStoreChange) => {
@@ -210,7 +208,7 @@ var createRoomBundle = (client, options) => {
210
208
  getSnapshot,
211
209
  getSnapshot,
212
210
  _selector,
213
- (_a2 = options2 == null ? void 0 : options2.isEqual) != null ? _a2 : import_fast_deep_equal.default
211
+ (_a = options2 == null ? void 0 : options2.isEqual) != null ? _a : import_fast_deep_equal.default
214
212
  );
215
213
  };
216
214
  const useDoc = () => {
@@ -238,7 +236,7 @@ var createRoomBundle = (client, options) => {
238
236
  }
239
237
  );
240
238
  const useMyPresence = (selector = identity, options2) => {
241
- var _a2;
239
+ var _a;
242
240
  const room = useRoom();
243
241
  const subscribe = (0, import_react4.useCallback)(
244
242
  (onStoreChange) => {
@@ -253,12 +251,12 @@ var createRoomBundle = (client, options) => {
253
251
  getSnapshot,
254
252
  getSnapshot,
255
253
  _selector,
256
- (_a2 = options2 == null ? void 0 : options2.isEqual) != null ? _a2 : import_fast_deep_equal.default
254
+ (_a = options2 == null ? void 0 : options2.isEqual) != null ? _a : import_fast_deep_equal.default
257
255
  );
258
256
  return [myPresence, room.updateMyPresence];
259
257
  };
260
258
  const useMyself = (selector = identity, options2) => {
261
- var _a2;
259
+ var _a;
262
260
  const room = useRoom();
263
261
  const subscribe = (0, import_react4.useCallback)(
264
262
  (onStoreChange) => {
@@ -278,11 +276,11 @@ var createRoomBundle = (client, options) => {
278
276
  getSnapshot,
279
277
  getSnapshot,
280
278
  _selector,
281
- (_a2 = options2 == null ? void 0 : options2.isEqual) != null ? _a2 : import_fast_deep_equal.default
279
+ (_a = options2 == null ? void 0 : options2.isEqual) != null ? _a : import_fast_deep_equal.default
282
280
  );
283
281
  };
284
282
  const useOther = (connectionId, selector = identity, options2) => {
285
- var _a2;
283
+ var _a;
286
284
  const room = useRoom();
287
285
  const subscribe = (0, import_react4.useCallback)(
288
286
  (onStoreChange) => {
@@ -302,11 +300,11 @@ var createRoomBundle = (client, options) => {
302
300
  getSnapshot,
303
301
  getSnapshot,
304
302
  _selector,
305
- (_a2 = options2 == null ? void 0 : options2.isEqual) != null ? _a2 : import_fast_deep_equal.default
303
+ (_a = options2 == null ? void 0 : options2.isEqual) != null ? _a : import_fast_deep_equal.default
306
304
  );
307
305
  };
308
306
  const useOthers = (selector = identity, options2) => {
309
- var _a2;
307
+ var _a;
310
308
  const room = useRoom();
311
309
  const subscribe = (0, import_react4.useCallback)(
312
310
  (onStoreChange) => {
@@ -320,7 +318,7 @@ var createRoomBundle = (client, options) => {
320
318
  getSnapshot,
321
319
  getSnapshot,
322
320
  selector,
323
- (_a2 = options2 == null ? void 0 : options2.isEqual) != null ? _a2 : (a, b) => {
321
+ (_a = options2 == null ? void 0 : options2.isEqual) != null ? _a : (a, b) => {
324
322
  if (Array.isArray(a) && Array.isArray(b) && a.length === b.length) {
325
323
  return shallowArrayEqual(a, b);
326
324
  }
@@ -333,7 +331,7 @@ var createRoomBundle = (client, options) => {
333
331
  return room.redo;
334
332
  };
335
333
  const useStorage = (key, selector = identity, options2) => {
336
- var _a2, _b;
334
+ var _a, _b;
337
335
  const room = useRoom();
338
336
  const rerender = useRerender();
339
337
  room.subscribe("storage-loaded", () => {
@@ -354,7 +352,7 @@ var createRoomBundle = (client, options) => {
354
352
  getSnapshot,
355
353
  getSnapshot,
356
354
  _selector,
357
- (_a2 = options2 == null ? void 0 : options2.isEqual) != null ? _a2 : import_fast_deep_equal.default
355
+ (_a = options2 == null ? void 0 : options2.isEqual) != null ? _a : import_fast_deep_equal.default
358
356
  );
359
357
  const sharedType = (_b = room.getStorage(key)) != null ? _b : null;
360
358
  return [data, sharedType];
package/dist/index.mjs CHANGED
@@ -6,7 +6,6 @@ import { createContext as createContext2, memo as memo2, useContext as useContex
6
6
 
7
7
  // src/createRoomBundle.tsx
8
8
  import { MockedRoom } from "@pluv/client";
9
- import { noop } from "@pluv/crdt";
10
9
  import fastDeepEqual from "fast-deep-equal";
11
10
  import { createContext, memo, useCallback as useCallback3, useContext, useEffect as useEffect2, useMemo, useState as useState3 } from "react";
12
11
 
@@ -76,18 +75,16 @@ var useSyncExternalStoreWithSelector = (subscribe, getClientSnapshot, getServerS
76
75
  // src/createRoomBundle.tsx
77
76
  import { jsx } from "react/jsx-runtime";
78
77
  var createRoomBundle = (client, options) => {
79
- var _a;
80
- const _initialStorage = (_a = options.initialStorage) != null ? _a : noop.doc();
81
78
  const PluvRoomContext = createContext(null);
82
79
  const MockedRoomContext = createContext({ room: null });
83
80
  const MockedRoomProvider = memo((props) => {
84
81
  const { children, events, initialPresence, initialStorage, room: _room } = props;
85
82
  const [room] = useState3(() => {
83
+ var _a;
86
84
  return new MockedRoom(_room, {
87
85
  events,
88
86
  initialPresence,
89
- initialStorage: typeof initialStorage === "function" ? _initialStorage.getFactory(initialStorage) : _initialStorage,
90
- presence: options.presence
87
+ initialStorage: typeof initialStorage === "function" ? (_a = client._defs.initialStorage) == null ? void 0 : _a.getFactory(initialStorage) : client._defs.initialStorage
91
88
  });
92
89
  });
93
90
  return /* @__PURE__ */ jsx(MockedRoomContext.Provider, { value: { room }, children: /* @__PURE__ */ jsx(PluvRoomContext.Provider, { value: room, children }) });
@@ -98,14 +95,15 @@ var createRoomBundle = (client, options) => {
98
95
  const rerender = useRerender();
99
96
  const { room: mockedRoom } = useContext(MockedRoomContext);
100
97
  const [room] = useState3(() => {
98
+ var _a;
101
99
  return client.createRoom(_room, {
102
100
  addons: options.addons,
103
101
  debug,
104
102
  initialPresence,
105
- initialStorage: typeof initialStorage === "function" ? _initialStorage.getFactory(initialStorage) : _initialStorage,
103
+ initialStorage: typeof initialStorage === "function" ? (_a = client._defs.initialStorage) == null ? void 0 : _a.getFactory(initialStorage) : client._defs.initialStorage,
106
104
  metadata,
107
- presence: options.presence,
108
- onAuthorizationFail
105
+ onAuthorizationFail,
106
+ router: options.router
109
107
  });
110
108
  });
111
109
  useEffect2(() => {
@@ -159,7 +157,7 @@ var createRoomBundle = (client, options) => {
159
157
  return canUndo;
160
158
  };
161
159
  const useConnection = (selector = identity, options2) => {
162
- var _a2;
160
+ var _a;
163
161
  const room = useRoom();
164
162
  const subscribe = useCallback3(
165
163
  (onStoreChange) => {
@@ -174,7 +172,7 @@ var createRoomBundle = (client, options) => {
174
172
  getSnapshot,
175
173
  getSnapshot,
176
174
  _selector,
177
- (_a2 = options2 == null ? void 0 : options2.isEqual) != null ? _a2 : fastDeepEqual
175
+ (_a = options2 == null ? void 0 : options2.isEqual) != null ? _a : fastDeepEqual
178
176
  );
179
177
  };
180
178
  const useDoc = () => {
@@ -202,7 +200,7 @@ var createRoomBundle = (client, options) => {
202
200
  }
203
201
  );
204
202
  const useMyPresence = (selector = identity, options2) => {
205
- var _a2;
203
+ var _a;
206
204
  const room = useRoom();
207
205
  const subscribe = useCallback3(
208
206
  (onStoreChange) => {
@@ -217,12 +215,12 @@ var createRoomBundle = (client, options) => {
217
215
  getSnapshot,
218
216
  getSnapshot,
219
217
  _selector,
220
- (_a2 = options2 == null ? void 0 : options2.isEqual) != null ? _a2 : fastDeepEqual
218
+ (_a = options2 == null ? void 0 : options2.isEqual) != null ? _a : fastDeepEqual
221
219
  );
222
220
  return [myPresence, room.updateMyPresence];
223
221
  };
224
222
  const useMyself = (selector = identity, options2) => {
225
- var _a2;
223
+ var _a;
226
224
  const room = useRoom();
227
225
  const subscribe = useCallback3(
228
226
  (onStoreChange) => {
@@ -242,11 +240,11 @@ var createRoomBundle = (client, options) => {
242
240
  getSnapshot,
243
241
  getSnapshot,
244
242
  _selector,
245
- (_a2 = options2 == null ? void 0 : options2.isEqual) != null ? _a2 : fastDeepEqual
243
+ (_a = options2 == null ? void 0 : options2.isEqual) != null ? _a : fastDeepEqual
246
244
  );
247
245
  };
248
246
  const useOther = (connectionId, selector = identity, options2) => {
249
- var _a2;
247
+ var _a;
250
248
  const room = useRoom();
251
249
  const subscribe = useCallback3(
252
250
  (onStoreChange) => {
@@ -266,11 +264,11 @@ var createRoomBundle = (client, options) => {
266
264
  getSnapshot,
267
265
  getSnapshot,
268
266
  _selector,
269
- (_a2 = options2 == null ? void 0 : options2.isEqual) != null ? _a2 : fastDeepEqual
267
+ (_a = options2 == null ? void 0 : options2.isEqual) != null ? _a : fastDeepEqual
270
268
  );
271
269
  };
272
270
  const useOthers = (selector = identity, options2) => {
273
- var _a2;
271
+ var _a;
274
272
  const room = useRoom();
275
273
  const subscribe = useCallback3(
276
274
  (onStoreChange) => {
@@ -284,7 +282,7 @@ var createRoomBundle = (client, options) => {
284
282
  getSnapshot,
285
283
  getSnapshot,
286
284
  selector,
287
- (_a2 = options2 == null ? void 0 : options2.isEqual) != null ? _a2 : (a, b) => {
285
+ (_a = options2 == null ? void 0 : options2.isEqual) != null ? _a : (a, b) => {
288
286
  if (Array.isArray(a) && Array.isArray(b) && a.length === b.length) {
289
287
  return shallowArrayEqual(a, b);
290
288
  }
@@ -297,7 +295,7 @@ var createRoomBundle = (client, options) => {
297
295
  return room.redo;
298
296
  };
299
297
  const useStorage = (key, selector = identity, options2) => {
300
- var _a2, _b;
298
+ var _a, _b;
301
299
  const room = useRoom();
302
300
  const rerender = useRerender();
303
301
  room.subscribe("storage-loaded", () => {
@@ -318,7 +316,7 @@ var createRoomBundle = (client, options) => {
318
316
  getSnapshot,
319
317
  getSnapshot,
320
318
  _selector,
321
- (_a2 = options2 == null ? void 0 : options2.isEqual) != null ? _a2 : fastDeepEqual
319
+ (_a = options2 == null ? void 0 : options2.isEqual) != null ? _a : fastDeepEqual
322
320
  );
323
321
  const sharedType = (_b = room.getStorage(key)) != null ? _b : null;
324
322
  return [data, sharedType];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pluv/react",
3
- "version": "0.26.0",
3
+ "version": "0.28.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": "^0.26.0",
22
- "@pluv/crdt": "^0.26.0",
23
- "@pluv/types": "^0.26.0"
21
+ "@pluv/client": "^0.28.0",
22
+ "@pluv/crdt": "^0.28.0",
23
+ "@pluv/types": "^0.28.0"
24
24
  },
25
25
  "peerDependencies": {
26
26
  "@types/react": "^18.0.0",
27
27
  "react": "^18.0.0"
28
28
  },
29
29
  "devDependencies": {
30
- "@types/react": "^18.3.4",
30
+ "@types/react": "^18.3.6",
31
31
  "eslint": "^8.57.0",
32
32
  "react": "^18.3.1",
33
- "tsup": "^8.2.4",
34
- "typescript": "^5.5.4",
35
- "@pluv/tsconfig": "^0.26.0",
36
- "eslint-config-pluv": "^0.26.0"
33
+ "tsup": "^8.3.0",
34
+ "typescript": "^5.6.2",
35
+ "@pluv/tsconfig": "^0.28.0",
36
+ "eslint-config-pluv": "^0.28.0"
37
37
  },
38
38
  "scripts": {
39
39
  "build": "tsup src/index.ts --format esm,cjs --dts --external react",
@@ -1,4 +1,4 @@
1
- import type { PluvClient } from "@pluv/client";
1
+ import type { PluvClient, PluvRouterEventConfig } from "@pluv/client";
2
2
  import type { CrdtType } from "@pluv/crdt";
3
3
  import type { IOLike, JsonObject } from "@pluv/types";
4
4
  import type { FC, ReactNode } from "react";
@@ -10,22 +10,32 @@ export interface PluvProviderProps {
10
10
  children?: ReactNode;
11
11
  }
12
12
 
13
- export interface CreateBundle<TIO extends IOLike, TMetadata extends JsonObject> {
13
+ export interface CreateBundle<
14
+ TIO extends IOLike,
15
+ TMetadata extends JsonObject,
16
+ TPresence extends JsonObject = {},
17
+ TStorage extends Record<string, CrdtType<any, any>> = {},
18
+ > {
14
19
  // factories
15
- createRoomBundle: <TPresence extends JsonObject = {}, TStorage extends Record<string, CrdtType<any, any>> = {}>(
16
- options: CreateRoomBundleOptions<TIO, TMetadata, TPresence, TStorage>,
17
- ) => CreateRoomBundle<TIO, TMetadata, TPresence, TStorage>;
20
+ createRoomBundle: <TEvents extends PluvRouterEventConfig<TIO, TPresence, TStorage> = {}>(
21
+ options: CreateRoomBundleOptions<TIO, TMetadata, TPresence, TStorage, TEvents>,
22
+ ) => CreateRoomBundle<TIO, TMetadata, TPresence, TStorage, TEvents>;
18
23
 
19
24
  // components
20
25
  PluvProvider: FC<PluvProviderProps>;
21
26
 
22
27
  // hooks
23
- useClient: () => PluvClient<TIO, TMetadata>;
28
+ useClient: () => PluvClient<TIO, TPresence, TStorage, TMetadata>;
24
29
  }
25
30
 
26
- export const createBundle = <TIO extends IOLike, TMetadata extends JsonObject>(
27
- client: PluvClient<TIO, TMetadata>,
28
- ): CreateBundle<TIO, TMetadata> => {
31
+ export const createBundle = <
32
+ TIO extends IOLike,
33
+ TMetadata extends JsonObject = {},
34
+ TPresence extends JsonObject = {},
35
+ TStorage extends Record<string, CrdtType<any, any>> = {},
36
+ >(
37
+ client: PluvClient<TIO, TPresence, TStorage, TMetadata>,
38
+ ): CreateBundle<TIO, TMetadata, TPresence, TStorage> => {
29
39
  /**
30
40
  * !HACK
31
41
  * @description We'll let the context error out if client is not provided,
@@ -33,7 +43,7 @@ export const createBundle = <TIO extends IOLike, TMetadata extends JsonObject>(
33
43
  * @author leedavidcs
34
44
  * @date October 27, 2022
35
45
  */
36
- const PluvContext = createContext<PluvClient<TIO, TMetadata>>(null as any);
46
+ const PluvContext = createContext<PluvClient<TIO, TPresence, TStorage, TMetadata>>(null as any);
37
47
 
38
48
  const PluvProvider = memo<PluvProviderProps>((props) => {
39
49
  const { children } = props;
@@ -43,14 +53,11 @@ export const createBundle = <TIO extends IOLike, TMetadata extends JsonObject>(
43
53
 
44
54
  PluvProvider.displayName = "PluvProvider";
45
55
 
46
- const useClient = (): PluvClient<TIO, TMetadata> => useContext(PluvContext);
56
+ const useClient = (): PluvClient<TIO, TPresence, TStorage, TMetadata> => useContext(PluvContext);
47
57
 
48
- const createRoomBundle = <
49
- TPresence extends JsonObject = {},
50
- TStorage extends Record<string, CrdtType<any, any>> = {},
51
- >(
52
- options: CreateRoomBundleOptions<TIO, TMetadata, TPresence, TStorage>,
53
- ): CreateRoomBundle<TIO, TMetadata, TPresence, TStorage> => _createRoomBundle(client, options);
58
+ const createRoomBundle = <TEvents extends PluvRouterEventConfig<TIO, TPresence, TStorage> = {}>(
59
+ options: CreateRoomBundleOptions<TIO, TMetadata, TPresence, TStorage, TEvents>,
60
+ ): CreateRoomBundle<TIO, TMetadata, TPresence, TStorage, TEvents> => _createRoomBundle(client, options);
54
61
 
55
62
  return {
56
63
  createRoomBundle,
@@ -1,18 +1,20 @@
1
1
  import type {
2
2
  AbstractRoom,
3
+ CreateRoomOptions,
4
+ MergeEvents,
3
5
  MockedRoomEvents,
4
6
  PluvClient,
5
7
  PluvRoom,
6
8
  PluvRoomAddon,
7
9
  PluvRoomDebug,
8
- PluvRoomOptions,
10
+ PluvRouter,
11
+ PluvRouterEventConfig,
9
12
  UserInfo,
10
13
  WebSocketConnection,
11
14
  } from "@pluv/client";
12
15
  import { MockedRoom } from "@pluv/client";
13
- import type { AbstractCrdtDoc, AbstractCrdtDocFactory, CrdtType, InferCrdtJson } from "@pluv/crdt";
14
- import { noop } from "@pluv/crdt";
15
- import type { IOEventMessage, IOLike, Id, InferIOInput, InferIOOutput, InputZodLike, JsonObject } from "@pluv/types";
16
+ import type { AbstractCrdtDoc, CrdtType, InferCrdtJson } from "@pluv/crdt";
17
+ import type { IOEventMessage, IOLike, Id, InferIOInput, InferIOOutput, JsonObject } from "@pluv/types";
16
18
  import fastDeepEqual from "fast-deep-equal";
17
19
  import type { Dispatch, FC, ReactNode } from "react";
18
20
  import { createContext, memo, useCallback, useContext, useEffect, useMemo, useState } from "react";
@@ -23,10 +25,10 @@ export type CreateRoomBundleOptions<
23
25
  TMetadata extends JsonObject = {},
24
26
  TPresence extends JsonObject = {},
25
27
  TStorage extends Record<string, CrdtType<any, any>> = {},
28
+ TEvents extends PluvRouterEventConfig<TIO, TPresence, TStorage> = {},
26
29
  > = {
27
30
  addons?: readonly PluvRoomAddon<TIO, TMetadata, TPresence, TStorage>[];
28
- initialStorage?: AbstractCrdtDocFactory<TStorage>;
29
- presence?: InputZodLike<TPresence>;
31
+ router?: PluvRouter<TIO, TPresence, TStorage, TEvents>;
30
32
  };
31
33
 
32
34
  type BaseRoomProviderProps<TPresence extends JsonObject, TStorage extends Record<string, CrdtType<any, any>>> = {
@@ -39,8 +41,9 @@ export type MockedRoomProviderProps<
39
41
  TIO extends IOLike,
40
42
  TPresence extends JsonObject,
41
43
  TStorage extends Record<string, CrdtType<any, any>>,
44
+ TEvents extends PluvRouterEventConfig<TIO, TPresence, TStorage> = {},
42
45
  > = BaseRoomProviderProps<TPresence, TStorage> & {
43
- events?: MockedRoomEvents<TIO>;
46
+ events?: MockedRoomEvents<MergeEvents<TEvents, TIO>>;
44
47
  };
45
48
 
46
49
  export type PluvRoomProviderProps<
@@ -79,16 +82,17 @@ export interface CreateRoomBundle<
79
82
  TMetadata extends JsonObject,
80
83
  TPresence extends JsonObject,
81
84
  TStorage extends Record<string, CrdtType<any, any>>,
85
+ TEvents extends PluvRouterEventConfig<TIO, TPresence, TStorage> = {},
82
86
  > {
83
87
  // components
84
88
  MockedRoomProvider: FC<MockedRoomProviderProps<TIO, TPresence, TStorage>>;
85
89
  PluvRoomProvider: FC<PluvRoomProviderProps<TIO, TMetadata, TPresence, TStorage>>;
86
90
 
87
91
  // proxies
88
- event: EventProxy<TIO>;
92
+ event: EventProxy<MergeEvents<TEvents, TIO>>;
89
93
 
90
94
  // hooks
91
- useBroadcast: () => BroadcastProxy<TIO>;
95
+ useBroadcast: () => BroadcastProxy<MergeEvents<TEvents, TIO>>;
92
96
  useCanRedo: () => boolean;
93
97
  useCanUndo: () => boolean;
94
98
  useConnection: <T extends unknown = WebSocketConnection>(
@@ -96,9 +100,9 @@ export interface CreateRoomBundle<
96
100
  options?: SubscriptionHookOptions<Id<T>>,
97
101
  ) => Id<T>;
98
102
  useDoc: () => AbstractCrdtDoc<TStorage>;
99
- useEvent: <TType extends keyof InferIOOutput<TIO>>(
103
+ useEvent: <TType extends keyof InferIOOutput<MergeEvents<TEvents, TIO>>>(
100
104
  type: TType,
101
- callback: (data: Id<IOEventMessage<TIO, TType>>) => void,
105
+ callback: (data: Id<IOEventMessage<MergeEvents<TEvents, TIO>, TType>>) => void,
102
106
  ) => void;
103
107
  useMyPresence: <T extends unknown = TPresence>(
104
108
  selector?: (myPresence: TPresence) => T,
@@ -128,7 +132,7 @@ export interface CreateRoomBundle<
128
132
  useUndo: () => () => void;
129
133
  }
130
134
 
131
- export type InferRoomStorage<TRoomBundle extends CreateRoomBundle<any, any, any, any>> =
135
+ export type InferRoomStorage<TRoomBundle extends CreateRoomBundle<any, any, any, any, any>> =
132
136
  TRoomBundle extends CreateRoomBundle<any, any, any, infer IStorage> ? IStorage : never;
133
137
 
134
138
  export const createRoomBundle = <
@@ -136,12 +140,11 @@ export const createRoomBundle = <
136
140
  TMetadata extends JsonObject = {},
137
141
  TPresence extends JsonObject = {},
138
142
  TStorage extends Record<string, CrdtType<any, any>> = {},
143
+ TEvents extends PluvRouterEventConfig<TIO, TPresence, TStorage> = {},
139
144
  >(
140
- client: PluvClient<TIO, TMetadata>,
141
- options: CreateRoomBundleOptions<TIO, TMetadata, TPresence, TStorage>,
142
- ): CreateRoomBundle<TIO, TMetadata, TPresence, TStorage> => {
143
- const _initialStorage = (options.initialStorage ?? noop.doc()) as AbstractCrdtDocFactory<TStorage>;
144
-
145
+ client: PluvClient<TIO, TPresence, TStorage, TMetadata>,
146
+ options: CreateRoomBundleOptions<TIO, TMetadata, TPresence, TStorage, TEvents>,
147
+ ): CreateRoomBundle<TIO, TMetadata, TPresence, TStorage, TEvents> => {
145
148
  /**
146
149
  * !HACK
147
150
  * @description We'll let the context error out if the room is not provided,
@@ -158,13 +161,14 @@ export const createRoomBundle = <
158
161
  const MockedRoomProvider = memo<MockedRoomProviderProps<TIO, TPresence, TStorage>>((props) => {
159
162
  const { children, events, initialPresence, initialStorage, room: _room } = props;
160
163
 
161
- const [room] = useState<MockedRoom<TIO, TPresence, TStorage>>(() => {
162
- return new MockedRoom<TIO, TPresence, TStorage>(_room, {
164
+ const [room] = useState<MockedRoom<TIO, TPresence, TStorage, TEvents>>(() => {
165
+ return new MockedRoom<TIO, TPresence, TStorage, TEvents>(_room, {
163
166
  events,
164
167
  initialPresence,
165
168
  initialStorage:
166
- typeof initialStorage === "function" ? _initialStorage.getFactory(initialStorage) : _initialStorage,
167
- presence: options.presence,
169
+ typeof initialStorage === "function"
170
+ ? client._defs.initialStorage?.getFactory(initialStorage)
171
+ : client._defs.initialStorage,
168
172
  });
169
173
  });
170
174
 
@@ -183,17 +187,19 @@ export const createRoomBundle = <
183
187
  const rerender = useRerender();
184
188
  const { room: mockedRoom } = useContext(MockedRoomContext);
185
189
 
186
- const [room] = useState<PluvRoom<TIO, TMetadata, TPresence, TStorage>>(() => {
187
- return client.createRoom<TPresence, TStorage>(_room, {
190
+ const [room] = useState<PluvRoom<TIO, TMetadata, TPresence, TStorage, TEvents>>(() => {
191
+ return client.createRoom(_room, {
188
192
  addons: options.addons,
189
193
  debug,
190
194
  initialPresence,
191
195
  initialStorage:
192
- typeof initialStorage === "function" ? _initialStorage.getFactory(initialStorage) : _initialStorage,
196
+ typeof initialStorage === "function"
197
+ ? client._defs.initialStorage?.getFactory(initialStorage)
198
+ : client._defs.initialStorage,
193
199
  metadata,
194
- presence: options.presence,
195
200
  onAuthorizationFail,
196
- } as PluvRoomOptions<TIO, TMetadata, TPresence, TStorage>);
201
+ router: options.router,
202
+ } as CreateRoomOptions<TIO, TPresence, TStorage, TMetadata, TEvents>);
197
203
  });
198
204
 
199
205
  useEffect(() => {
@@ -221,24 +227,31 @@ export const createRoomBundle = <
221
227
 
222
228
  const useRoom = () => useContext(PluvRoomContext);
223
229
 
224
- const useBroadcast = (): BroadcastProxy<TIO> => {
230
+ const useBroadcast = (): BroadcastProxy<MergeEvents<TEvents, TIO>> => {
225
231
  const room = useRoom();
226
232
 
227
233
  const broadcast = useCallback(
228
- <TEvent extends keyof InferIOInput<TIO>>(event: TEvent, data: Id<InferIOInput<TIO>[TEvent]>) => {
234
+ <TEvent extends keyof InferIOInput<MergeEvents<TEvents, TIO>>>(
235
+ event: TEvent,
236
+ data: Id<InferIOInput<MergeEvents<TEvents, TIO>>[TEvent]>,
237
+ ) => {
229
238
  room.broadcast(event, data);
230
239
  },
231
240
  [room],
232
241
  );
233
242
 
234
- return useMemo((): BroadcastProxy<TIO> => {
243
+ return useMemo((): BroadcastProxy<MergeEvents<TEvents, TIO>> => {
235
244
  return new Proxy(broadcast, {
236
245
  get(fn, prop) {
237
- return (data: Id<InferIOInput<TIO>[keyof InferIOInput<TIO>]>): void => {
238
- return fn(prop as keyof InferIOInput<TIO>, data);
246
+ return (
247
+ data: Id<
248
+ InferIOInput<MergeEvents<TEvents, TIO>>[keyof InferIOInput<MergeEvents<TEvents, TIO>>]
249
+ >,
250
+ ): void => {
251
+ return fn(prop as keyof InferIOInput<MergeEvents<TEvents, TIO>>, data);
239
252
  };
240
253
  },
241
- }) as BroadcastProxy<TIO>;
254
+ }) as BroadcastProxy<MergeEvents<TEvents, TIO>>;
242
255
  }, [broadcast]);
243
256
  };
244
257
 
@@ -298,9 +311,9 @@ export const createRoomBundle = <
298
311
  return room.getDoc();
299
312
  };
300
313
 
301
- const useEvent = <TType extends keyof InferIOOutput<TIO>>(
314
+ const useEvent = <TType extends keyof InferIOOutput<MergeEvents<TEvents, TIO>>>(
302
315
  type: TType,
303
- callback: (data: Id<IOEventMessage<TIO, TType>>) => void,
316
+ callback: (data: Id<IOEventMessage<MergeEvents<TEvents, TIO>, TType>>) => void,
304
317
  ): void => {
305
318
  const room = useRoom();
306
319
 
@@ -318,15 +331,19 @@ export const createRoomBundle = <
318
331
  {
319
332
  get(_, prop) {
320
333
  const useProxyEvent = (
321
- callback: (data: Id<IOEventMessage<TIO, keyof InferIOOutput<TIO>>>) => void,
334
+ callback: (
335
+ data: Id<
336
+ IOEventMessage<MergeEvents<TEvents, TIO>, keyof InferIOOutput<MergeEvents<TEvents, TIO>>>
337
+ >,
338
+ ) => void,
322
339
  ): void => {
323
- return useEvent(prop as keyof InferIOOutput<TIO>, callback);
340
+ return useEvent(prop as keyof InferIOOutput<MergeEvents<TEvents, TIO>>, callback);
324
341
  };
325
342
 
326
343
  return { useEvent: useProxyEvent };
327
344
  },
328
345
  },
329
- ) as EventProxy<TIO>;
346
+ ) as EventProxy<MergeEvents<TEvents, TIO>>;
330
347
 
331
348
  const useMyPresence = <T extends unknown = TPresence>(
332
349
  selector = identity as (myPresence: TPresence) => T,
@@ -26,7 +26,7 @@ export const useSyncExternalStoreWithSelector = <TSnapshot, TSelection>(
26
26
  * @description Memoize only the last snapshot so that we can only rerender on changes
27
27
  * @date June 22, 2024
28
28
  */
29
- cacheRef.current = isUnchanged ? cached ?? snapshot : snapshot;
29
+ cacheRef.current = isUnchanged ? (cached ?? snapshot) : snapshot;
30
30
 
31
31
  return cacheRef.current;
32
32
  }
@@ -45,7 +45,7 @@ export const useSyncExternalStoreWithSelector = <TSnapshot, TSelection>(
45
45
  * @description Memoize only the last snapshot so that we can only rerender on changes
46
46
  * @date June 22, 2024
47
47
  */
48
- cacheRef.current = isUnchanged ? cached ?? snapshot : snapshot;
48
+ cacheRef.current = isUnchanged ? (cached ?? snapshot) : snapshot;
49
49
 
50
50
  return cacheRef.current;
51
51
  };
@@ -1,2 +1,2 @@
1
- export { useRerender, useSyncExternalStore, useSyncExternalStoreWithSelector } from "./hooks";
1
+ export { useRerender, useSyncExternalStoreWithSelector } from "./hooks";
2
2
  export { identity, shallowArrayEqual } from "./utils";