@pluv/react 0.14.1 → 0.16.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.14.1 build /home/runner/work/pluv/pluv/packages/react
2
+ > @pluv/react@0.16.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.0.1
7
+ CLI tsup v8.0.2
8
8
  CLI Target: es6
9
9
  ESM Build start
10
10
  CJS Build start
11
- ESM dist/index.mjs 9.98 KB
12
- ESM ⚡️ Build success in 93ms
13
- CJS dist/index.js 12.57 KB
14
- CJS ⚡️ Build success in 93ms
11
+ CJS dist/index.js 12.53 KB
12
+ CJS ⚡️ Build success in 112ms
13
+ ESM dist/index.mjs 9.96 KB
14
+ ESM ⚡️ Build success in 112ms
15
15
  DTS Build start
16
- DTS ⚡️ Build success in 4209ms
17
- DTS dist/index.d.mts 4.77 KB
18
- DTS dist/index.d.ts 4.77 KB
16
+ DTS ⚡️ Build success in 3801ms
17
+ DTS dist/index.d.mts 5.05 KB
18
+ DTS dist/index.d.ts 5.05 KB
package/CHANGELOG.md CHANGED
@@ -1,5 +1,178 @@
1
1
  # @pluv/react
2
2
 
3
+ ## 0.16.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 995aa9c: Renamed all hooks from `@pluv/react` to be simply prefixed with `use` instead of `usePluv` (e.g. `usePluvStorage` is now just `useStorage`).
8
+
9
+ Hooks can be aliased to retain the same names if preferred:
10
+
11
+ ```ts
12
+ export const {
13
+ // ...
14
+ useStorage: usePluvStorage,
15
+ useTransact: usePluvTransact,
16
+ // ...
17
+ } = createRoomBundle(/* */);
18
+ ```
19
+
20
+ - 4280220: ## Breaking Changes
21
+
22
+ - Storage types are now kept on the root of the document.
23
+ - Previously, `@pluv/crdt-yjs` kept all shared-types on a hidden Yjs Map called `storage` on the root of the Yjs Doc. Now all shared-types are kept on the root of the Yjs Doc instead. This behavior should be more in-line with how shared-types are documented to be used from Yjs.
24
+ - `@pluv/client` and `@pluv/react` no-longer re-export `@pluv/crdt-yjs`. This package will now need to be installed separately.
25
+
26
+ ```bash
27
+ # if installing @pluv/client
28
+ npm install @pluv/client @pluv/crdt-yjs
29
+ # if installing @pluv/react
30
+ npm install @pluv/react @pluv/crdt-yjs
31
+ ```
32
+
33
+ ```ts
34
+ // Before:
35
+ import { createClient, y } from "@pluv/client";
36
+ // After:
37
+ import { createClient } from "@pluv/client";
38
+ import { yjs } from "@pluv/crdt-yjs"; // y renamed to yjs
39
+ ```
40
+
41
+ - The `y` import has been renamed to `yjs`.
42
+ ```ts
43
+ // Before:
44
+ import { y } from "@pluv/crdt-yjs";
45
+ // After:
46
+ import { yjs } from "@pluv/crdt-yjs";
47
+ ```
48
+ - `@pluv/crdt-yjs` functions no-longer return Yjs shared-types directly, but instead return an `AbstractCrdtType` from `@pluv/crdt` (new package). This also affects methods that return storage shared types in both `@pluv/client` and `@pluv/react` from functions like `PluvRoom.getStorage` and `PluvRoom.useStorage`.
49
+
50
+ ```ts
51
+ // Before:
52
+ import { y } from "@pluv/crdt-yjs";
53
+ import type { Array as YArray, Map as YMap } from "yjs";
54
+
55
+ const array: YArray<YMap<{ message: string }>> = y.array([
56
+ y.object({ message: "Hello" }),
57
+ ]);
58
+
59
+ array.push([y.object({ message: "World!" })]);
60
+
61
+ // After:
62
+ import type { CrdtYjsArray, CrdtYjsObject } from "@pluv/crdt-yjs";
63
+ import { yjs } from "@pluv/crdt-yjs";
64
+ import type { Array as YArray } from "yjs";
65
+
66
+ const array: CrdtYjsArray<CrdtYjsObject<{ message: string }>> = yjs.array([
67
+ yjs.object({ message: "Hello" }),
68
+ ]);
69
+
70
+ array.push(yjs.object({ message: "World!" }));
71
+
72
+ // use .value to get the underlying yjs type
73
+ const yarray: YArray<YMap<{ message: string }>> = array.value;
74
+ ```
75
+
76
+ - `initialStorage` must now use the `doc` function from `@pluv/crdt-yjs` to be defined. This also affects `@pluv/react`.
77
+
78
+ ```ts
79
+ // Before:
80
+ import { createClient, y } from "@pluv/client";
81
+
82
+ const client = createClient({
83
+ /* ... */
84
+ });
85
+
86
+ client.createRoom({
87
+ // ...
88
+ initialStorage: () => ({
89
+ messages: y.array([y.object({ message: "Hello world!" })]),
90
+ }),
91
+ });
92
+
93
+ // After:
94
+ import { createClient } from "@pluv/client";
95
+ // This is now imported separately
96
+ import { yjs } from "@pluv/crdt-yjs";
97
+
98
+ const client = createClient({
99
+ /* ... */
100
+ });
101
+
102
+ client.createRoom({
103
+ // ...
104
+ initialStorage: yjs.doc(() => ({
105
+ messages: yjs.array([yjs.object({ message: "Hello world!" })]),
106
+ })),
107
+ });
108
+ ```
109
+
110
+ - `@pluv/client` can now instead use [loro](https://github.com/loro-dev/loro) instead of [yjs](https://github.com/yjs/yjs).
111
+ ```bash
112
+ npm install @pluv/client @pluv/crdt-loro loro-crdt
113
+ ```
114
+ - If you are using storage features with pluv, `@pluv/io` must now specify which crdt library (i.e. `@pluv/crdt-yjs` or `@pluv/crdt-loro`) it is meant to use.
115
+
116
+ ```ts
117
+ import { loro } from "@pluv/crdt-loro";
118
+ import { yjs } from "@pluv/crdt-yjs";
119
+ import { createIO } from "@pluv/io";
120
+
121
+ const io = createIO({
122
+ // ...
123
+ // If using loro
124
+ crdt: loro,
125
+ // If using yjs
126
+ crdt: yjs,
127
+ });
128
+ ```
129
+
130
+ - `PluvRoom.getDoc()` from `@pluv/client` no-longer returns the Yjs Doc instance, but rather a `AbstractCrdtDoc` instance from `@pluv/crdt`. This also affects the hook from `@pluv/react`.
131
+
132
+ ```ts
133
+ // Before:
134
+ import { Doc as YDoc } from "yjs";
135
+
136
+ const room: PluvRoom = client.createRoom({
137
+ /* ... */
138
+ });
139
+
140
+ const doc: YDoc = room.getDoc();
141
+
142
+ // After:
143
+ import { CrdtYjsDoc } from "@pluv/crdt-yjs";
144
+ import { Doc as YDoc } from "yjs";
145
+
146
+ const room: PluvRoom = client.createRoom({
147
+ /* ... */
148
+ });
149
+
150
+ const doc: CrdtYjsDoc<any> = room.getDoc();
151
+ const ydoc: YDoc = doc.value;
152
+ ```
153
+
154
+ - `@pluv/client` and `@pluv/react` now may return `null` when retrieving storage while storage is being initialized.
155
+
156
+ ```ts
157
+ const sharedType = room.getStorage("messages"); // This may be null
158
+
159
+ const [data, sharedType] = useStorage("messages"); // data and sharedType may both be null
160
+ ```
161
+
162
+ ### Patch Changes
163
+
164
+ - Updated dependencies [4280220]
165
+ - @pluv/client@0.16.0
166
+ - @pluv/crdt@0.16.0
167
+ - @pluv/types@0.16.0
168
+
169
+ ## 0.15.0
170
+
171
+ ### Patch Changes
172
+
173
+ - @pluv/client@0.15.0
174
+ - @pluv/types@0.15.0
175
+
3
176
  ## 0.14.1
4
177
 
5
178
  ### Patch Changes
@@ -18,12 +191,12 @@
18
191
 
19
192
  ### Minor Changes
20
193
 
21
- - 4c4b47f: Added `usePluvDoc` to access the root Yjs doc.
194
+ - 4c4b47f: Added `useDoc` to access the root Yjs doc.
22
195
 
23
196
  ```ts
24
197
  import type { Doc } from "yjs";
25
198
 
26
- const doc: Doc = usePluvDoc();
199
+ const doc: Doc = useDoc();
27
200
  ```
28
201
 
29
202
  ### Patch Changes
@@ -209,7 +382,7 @@
209
382
 
210
383
  ## @pluv/react
211
384
 
212
- `@pluv/react`'s `createRoomBundle` now exposes 5 new react hooks: `usePluvCanRedo`, `usePluvCanUndo`, `usePluvRedo`, `usePluvUndo` and `usePluvTransact`.
385
+ `@pluv/react`'s `createRoomBundle` now exposes 5 new react hooks: `useCanRedo`, `useCanUndo`, `useRedo`, `useUndo` and `useTransact`.
213
386
 
214
387
  Refer to the code-example below to better understand how to undo and redo with your `createRoomBundle`.
215
388
 
@@ -221,47 +394,41 @@
221
394
 
222
395
  const { createRoomBundle } = createBundle(client);
223
396
 
224
- const {
225
- usePluvCanRedo,
226
- usePluvCanUndo,
227
- usePluvRedo,
228
- usePluvStorage,
229
- usePluvTransact,
230
- usePluvUndo,
231
- } = createRoomBundle({
232
- initialStorage: () => ({
233
- messages: y.array<string>([]),
234
- }),
235
- /**
236
- * @description This is the same `captureTimeout` option from yjs's UndoManager.
237
- * This specifies a number in ms, during which edits are merged together to be
238
- * undone together. Set this to 0, to track each transacted change individually.
239
- * @see (@link https://docs.yjs.dev/api/undo-manager)
240
- * @default 500
241
- */
242
- captureTimeout: 500,
243
- /**
244
- * @desription This is the same `trackedOrigins` option from yjs's UndoManager.
245
- * This specifies transaction origins (strings only) to filter which transactions
246
- * can be undone.
247
- * When omitted, the user's connection id will be tracked. When provided,
248
- * specifies additional tracked origins besides the user's connection id.
249
- * @see (@link https://docs.yjs.dev/api/undo-manager)
250
- * @default undefined
251
- */
252
- trackedOrigins: ["user-123"],
253
- });
397
+ const { useCanRedo, useCanUndo, useRedo, useStorage, useTransact, useUndo } =
398
+ createRoomBundle({
399
+ initialStorage: () => ({
400
+ messages: y.array<string>([]),
401
+ }),
402
+ /**
403
+ * @description This is the same `captureTimeout` option from yjs's UndoManager.
404
+ * This specifies a number in ms, during which edits are merged together to be
405
+ * undone together. Set this to 0, to track each transacted change individually.
406
+ * @see (@link https://docs.yjs.dev/api/undo-manager)
407
+ * @default 500
408
+ */
409
+ captureTimeout: 500,
410
+ /**
411
+ * @desription This is the same `trackedOrigins` option from yjs's UndoManager.
412
+ * This specifies transaction origins (strings only) to filter which transactions
413
+ * can be undone.
414
+ * When omitted, the user's connection id will be tracked. When provided,
415
+ * specifies additional tracked origins besides the user's connection id.
416
+ * @see (@link https://docs.yjs.dev/api/undo-manager)
417
+ * @default undefined
418
+ */
419
+ trackedOrigins: ["user-123"],
420
+ });
254
421
 
255
422
  /**
256
423
  * @description Check whether calling undo will mutate storage
257
424
  */
258
- const canUndo: boolean = usePluvCanUndo();
425
+ const canUndo: boolean = useCanUndo();
259
426
  /**
260
427
  * @description Check whether calling redo will mutate storage
261
428
  */
262
- const canRedo: boolean = usePluvCanRedo();
429
+ const canRedo: boolean = useCanRedo();
263
430
 
264
- const [messages, sharedType] = usePluvStorage("messages");
431
+ const [messages, sharedType] = useStorage("messages");
265
432
 
266
433
  /**
267
434
  * @description Calling transact will enable a storage mutation to be undone/redone.
@@ -270,7 +437,7 @@
270
437
  *
271
438
  * You can specify a 2nd parameter to transact with a different transaction origin.
272
439
  */
273
- const transact = usePluvTransact();
440
+ const transact = useTransact();
274
441
 
275
442
  transact(() => {
276
443
  sharedType.push(["hello world!"]);
@@ -284,14 +451,14 @@
284
451
  /**
285
452
  * @description Undoes the last valid mutation to storage
286
453
  */
287
- const undo = usePluvUndo();
454
+ const undo = useUndo();
288
455
 
289
456
  undo();
290
457
 
291
458
  /**
292
459
  * @description Re-applies the last undone mutation to storage
293
460
  */
294
- const redo = usePluvRedo();
461
+ const redo = useRedo();
295
462
 
296
463
  redo();
297
464
  ```
package/README.md CHANGED
@@ -5,12 +5,12 @@
5
5
  <br />
6
6
  <img src="https://github.com/pluv-io/pluv/blob/master/assets/pluv-icon-192x192.png?raw=true" alt="Pluv.IO" width="180" style="border-radius:16px" />
7
7
  <br />
8
- Pluv.IO (preview)
8
+ <a href="https://pluv.io/docs/introduction">Pluv.IO (preview)</a>
9
9
  <br />
10
10
  </h1>
11
11
 
12
12
  <h3 align="center">Multi-platform, E2E type-safe realtime packages</h3>
13
- <h4 align="center">💕 Inspired by <a href="https://trpc.io">trpc</a> 💕 Built with <a href="https://docs.yjs.dev/">yjs</a> 💕</h4>
13
+ <h4 align="center">💕 Inspired by <a href="https://trpc.io">trpc</a> 💕 <a href="https://docs.yjs.dev/">yjs</a> 💕 and <a href="https://developers.cloudflare.com/">Cloudflare</a> 💕 </h4>
14
14
 
15
15
  <p align="center">
16
16
  <a href="https://www.npmjs.com/package/@pluv/react">
@@ -19,14 +19,10 @@
19
19
  <a href="https://github.com/pluv-io/pluv/blob/master/LICENSE">
20
20
  <img alt="GitHub" src="https://img.shields.io/github/license/pluv-io/pluv" alt="License MIT" />
21
21
  </a>
22
- <img src="https://badgen.net/badge/-/TypeScript?icon=typescript&label&labelColor=blue&color=555555" alt="TypeScript" />
23
22
  <a href="https://commitizen.github.io/cz-cli/">
24
23
  <img src="https://img.shields.io/badge/commitizen-friendly-brightgreen.svg" alt="Commitizen friendly" />
25
24
  </a>
26
- </p>
27
-
28
- <p align="center">
29
- <img src="https://github.com/pluv-io/pluv/blob/master/assets/demo-events.gif?raw=true" alt="Demo" />
25
+ <img src="https://badgen.net/badge/-/TypeScript?icon=typescript&label&labelColor=blue&color=555555" alt="TypeScript" />
30
26
  </p>
31
27
 
32
28
  ## `@pluv/react`
@@ -39,21 +35,20 @@
39
35
 
40
36
  ```bash
41
37
  # npm
42
- npm install @pluv/react yjs
38
+ npm install @pluv/react @pluv/crdt-yjs yjs zod
43
39
 
44
40
  # yarn
45
- yarn add @pluv/react yjs
41
+ yarn add @pluv/react @pluv/crdt-yjs yjs zod
46
42
 
47
43
  # pnpm
48
- pnpm add @pluv/react yjs
44
+ pnpm add @pluv/react @pluv/crdt-yjs yjs zod
49
45
  ```
50
46
 
51
- If you plan on using presence and/or storage, make sure to also install `zod`.
52
-
53
47
  ## Basic Example
54
48
 
55
49
  ```tsx
56
- import { createBundle, createClient, y } from "@pluv/react";
50
+ import { yjs } from "@pluv/crdt-yjs";
51
+ import { createBundle, createClient } from "@pluv/react";
57
52
  import { z } from "zod";
58
53
  // Import the PluvIO instance as a type from your server file
59
54
  import { type io } from "./server";
@@ -76,7 +71,7 @@ export const {
76
71
  PluvProvider,
77
72
 
78
73
  // hooks
79
- usePluvClient,
74
+ useClient,
80
75
  } = createBundle(client);
81
76
 
82
77
  export const {
@@ -84,24 +79,24 @@ export const {
84
79
  PluvRoomProvider,
85
80
 
86
81
  // hooks
87
- usePluvBroadcast,
88
- usePluvConnection,
89
- usePluvEvent,
90
- usePluvMyPresence,
91
- usePluvMyself,
92
- usePluvOther,
93
- usePluvOthers,
94
- usePluvRoom,
95
- usePluvStorage,
82
+ useBroadcast,
83
+ useConnection,
84
+ useEvent,
85
+ useMyPresence,
86
+ useMyself,
87
+ useOther,
88
+ useOthers,
89
+ useRoom,
90
+ useStorage,
96
91
  } = createRoomBundle({
97
- initialStorage: () => ({
98
- messages: y.array([
99
- y.object({
92
+ initialStorage: yjs.doc(() => ({
93
+ messages: yjs.array([
94
+ yjs.object({
100
95
  message: "Hello World!",
101
96
  name: "johnathan_doe",
102
97
  }),
103
98
  ]),
104
- }),
99
+ })),
105
100
  presence: z.object({
106
101
  cursor: z.nullable(
107
102
  z.object({
@@ -123,9 +118,9 @@ export const MyPage: FC<Record<string, never>> = () => {
123
118
  };
124
119
 
125
120
  export const MyRoom: FC<Record<string, never>> = () => {
126
- const broadcast = usePluvBroadcast();
121
+ const broadcast = useBroadcast();
127
122
 
128
- usePluvEvent("RECEIVE_MESSAGE", ({ data }) => {
123
+ useEvent("RECEIVE_MESSAGE", ({ data }) => {
129
124
  // data is typed as { message: string }
130
125
  console.log(data.message);
131
126
  });
package/dist/index.d.mts CHANGED
@@ -1,17 +1,18 @@
1
- import { PluvRoomAddon, TrackOriginOptions, PluvRoomDebug, WebSocketConnection, UserInfo, AbstractRoom, InferYjsSharedTypeJson, MockedRoomEvents, PluvClient } from '@pluv/client';
2
- export { AbstractType, ConnectionState, createClient, y } from '@pluv/client';
1
+ import { PluvRoomAddon, PluvRoomDebug, WebSocketConnection, UserInfo, AbstractRoom, MockedRoomEvents, PluvClient } from '@pluv/client';
2
+ export { ConnectionState, createClient } from '@pluv/client';
3
+ import { AbstractCrdtType, AbstractCrdtDocFactory, AbstractCrdtDoc, InferCrdtStorageJson } from '@pluv/crdt';
4
+ export { AbstractCrdtType, InferCrdtStorageJson } from '@pluv/crdt';
3
5
  import * as _pluv_types from '@pluv/types';
4
6
  import { IOLike, JsonObject, InputZodLike, InferIOInput, Id, InferIOOutput, IOEventMessage } from '@pluv/types';
5
7
  export { BaseUser, EventMessage, EventRecord, IOEventMessage } from '@pluv/types';
6
8
  import { FC, Dispatch, ReactNode } from 'react';
7
- import { AbstractType, Doc } from 'yjs';
8
9
 
9
- type CreateRoomBundleOptions<TIO extends IOLike, TPresence extends JsonObject = {}, TStorage extends Record<string, AbstractType<any>> = {}> = {
10
+ type CreateRoomBundleOptions<TIO extends IOLike, TPresence extends JsonObject = {}, TStorage extends Record<string, AbstractCrdtType<any, any>> = {}> = {
10
11
  addons?: readonly PluvRoomAddon<TIO, TPresence, TStorage>[];
11
- initialStorage?: () => TStorage;
12
+ initialStorage?: AbstractCrdtDocFactory<TStorage>;
12
13
  presence?: InputZodLike<TPresence>;
13
- } & TrackOriginOptions;
14
- type BaseRoomProviderProps<TPresence extends JsonObject, TStorage extends Record<string, AbstractType<any>>> = {
14
+ };
15
+ type BaseRoomProviderProps<TPresence extends JsonObject, TStorage extends Record<string, AbstractCrdtType<any, any>>> = {
15
16
  children?: ReactNode;
16
17
  initialStorage?: keyof TStorage extends never ? never : () => TStorage;
17
18
  room: string;
@@ -20,10 +21,10 @@ type BaseRoomProviderProps<TPresence extends JsonObject, TStorage extends Record
20
21
  } : {
21
22
  initialPresence: TPresence;
22
23
  });
23
- type MockedRoomProviderProps<TIO extends IOLike, TPresence extends JsonObject, TStorage extends Record<string, AbstractType<any>>> = BaseRoomProviderProps<TPresence, TStorage> & {
24
+ type MockedRoomProviderProps<TIO extends IOLike, TPresence extends JsonObject, TStorage extends Record<string, AbstractCrdtType<any, any>>> = BaseRoomProviderProps<TPresence, TStorage> & {
24
25
  events?: MockedRoomEvents<TIO>;
25
26
  };
26
- type PluvRoomProviderProps<TIO extends IOLike, TPresence extends JsonObject, TStorage extends Record<string, AbstractType<any>>> = BaseRoomProviderProps<TPresence, TStorage> & {
27
+ type PluvRoomProviderProps<TIO extends IOLike, TPresence extends JsonObject, TStorage extends Record<string, AbstractCrdtType<any, any>>> = BaseRoomProviderProps<TPresence, TStorage> & {
27
28
  debug?: boolean | PluvRoomDebug<TIO>;
28
29
  onAuthorizationFail?: (error: Error) => void;
29
30
  };
@@ -31,37 +32,38 @@ interface SubscriptionHookOptions<T extends unknown> {
31
32
  isEqual?: (a: T, b: T) => boolean;
32
33
  }
33
34
  type UpdateMyPresenceAction<TPresence extends JsonObject> = Partial<TPresence> | ((oldPresence: TPresence | null) => Partial<TPresence>);
34
- interface CreateRoomBundle<TIO extends IOLike, TPresence extends JsonObject, TStorage extends Record<string, AbstractType<any>>> {
35
+ interface CreateRoomBundle<TIO extends IOLike, TPresence extends JsonObject, TStorage extends Record<string, AbstractCrdtType<any, any>>> {
35
36
  MockedRoomProvider: FC<MockedRoomProviderProps<TIO, TPresence, TStorage>>;
36
37
  PluvRoomProvider: FC<PluvRoomProviderProps<TIO, TPresence, TStorage>>;
37
- usePluvBroadcast: () => <TEvent extends keyof InferIOInput<TIO>>(event: TEvent, data: Id<InferIOInput<TIO>[TEvent]>) => void;
38
- usePluvCanRedo: () => boolean;
39
- usePluvCanUndo: () => boolean;
40
- usePluvConnection: <T extends unknown = WebSocketConnection>(selector: (connection: WebSocketConnection) => T, options?: SubscriptionHookOptions<Id<T>>) => Id<T>;
41
- usePluvDoc: () => Doc;
42
- usePluvEvent: <TType extends keyof InferIOOutput<TIO>>(type: TType, callback: (data: Id<IOEventMessage<TIO, TType>>) => void) => void;
43
- usePluvMyPresence: <T extends unknown = TPresence>(selector?: (myPresence: TPresence) => T, options?: SubscriptionHookOptions<Id<T> | null>) => [
38
+ useBroadcast: () => <TEvent extends keyof InferIOInput<TIO>>(event: TEvent, data: Id<InferIOInput<TIO>[TEvent]>) => void;
39
+ useCanRedo: () => boolean;
40
+ useCanUndo: () => boolean;
41
+ useConnection: <T extends unknown = WebSocketConnection>(selector: (connection: WebSocketConnection) => T, options?: SubscriptionHookOptions<Id<T>>) => Id<T>;
42
+ useDoc: () => AbstractCrdtDoc<TStorage>;
43
+ useEvent: <TType extends keyof InferIOOutput<TIO>>(type: TType, callback: (data: Id<IOEventMessage<TIO, TType>>) => void) => void;
44
+ useMyPresence: <T extends unknown = TPresence>(selector?: (myPresence: TPresence) => T, options?: SubscriptionHookOptions<Id<T> | null>) => [
44
45
  myPresence: Id<T>,
45
46
  updateMyPresence: Dispatch<UpdateMyPresenceAction<TPresence>>
46
47
  ];
47
- usePluvMyself: <T extends unknown = UserInfo<TIO, TPresence>>(selector?: (myself: Id<UserInfo<TIO, TPresence>>) => T, options?: SubscriptionHookOptions<Id<T> | null>) => Id<T> | null;
48
- usePluvOther: <T extends unknown = UserInfo<TIO, TPresence>>(connectionId: string, selector?: (other: UserInfo<TIO, TPresence>) => T, options?: SubscriptionHookOptions<Id<T> | null>) => Id<T> | null;
49
- usePluvOthers: <T extends unknown = UserInfo<TIO, TPresence>>(selector?: (other: readonly Id<UserInfo<TIO, TPresence>>[]) => T[], options?: SubscriptionHookOptions<readonly Id<T>[]>) => readonly Id<T>[];
50
- usePluvRedo: () => () => void;
51
- usePluvRoom: () => AbstractRoom<TIO, TPresence, TStorage>;
52
- usePluvStorage: <TKey extends keyof TStorage, TData extends unknown = InferYjsSharedTypeJson<TStorage[TKey]>>(key: TKey, selector?: (data: InferYjsSharedTypeJson<TStorage[TKey]>) => TData, options?: SubscriptionHookOptions<TData>) => [data: TData, sharedType: TStorage[TKey]];
53
- usePluvTransact: () => (fn: (storage: TStorage) => void, origin?: string) => void;
54
- usePluvUndo: () => () => void;
48
+ useMyself: <T extends unknown = UserInfo<TIO, TPresence>>(selector?: (myself: Id<UserInfo<TIO, TPresence>>) => T, options?: SubscriptionHookOptions<Id<T> | null>) => Id<T> | null;
49
+ useOther: <T extends unknown = UserInfo<TIO, TPresence>>(connectionId: string, selector?: (other: UserInfo<TIO, TPresence>) => T, options?: SubscriptionHookOptions<Id<T> | null>) => Id<T> | null;
50
+ useOthers: <T extends unknown = UserInfo<TIO, TPresence>>(selector?: (other: readonly Id<UserInfo<TIO, TPresence>>[]) => T[], options?: SubscriptionHookOptions<readonly Id<T>[]>) => readonly Id<T>[];
51
+ useRedo: () => () => void;
52
+ useRoom: () => AbstractRoom<TIO, TPresence, TStorage>;
53
+ useStorage: <TKey extends keyof TStorage, TData extends unknown = InferCrdtStorageJson<TStorage[TKey]>>(key: TKey, selector?: (data: InferCrdtStorageJson<TStorage[TKey]>) => TData, options?: SubscriptionHookOptions<TData | null>) => [data: TData | null, sharedType: TStorage[TKey] | null];
54
+ useTransact: () => (fn: (storage: TStorage) => void, origin?: string) => void;
55
+ useUndo: () => () => void;
55
56
  }
57
+ type InferRoomStorage<TRoomBundle extends CreateRoomBundle<any, any, any>> = TRoomBundle extends CreateRoomBundle<any, any, infer IStorage> ? IStorage : never;
56
58
 
57
59
  interface PluvProviderProps {
58
60
  children?: ReactNode;
59
61
  }
60
62
  interface CreateBundle<TIO extends IOLike> {
61
- createRoomBundle: <TPresence extends JsonObject = {}, TStorage extends Record<string, AbstractType<any>> = {}>(options?: CreateRoomBundleOptions<TIO, TPresence, TStorage>) => CreateRoomBundle<TIO, TPresence, TStorage>;
63
+ createRoomBundle: <TPresence extends JsonObject = {}, TStorage extends Record<string, AbstractCrdtType<any, any>> = {}>(options: CreateRoomBundleOptions<TIO, TPresence, TStorage>) => CreateRoomBundle<TIO, TPresence, TStorage>;
62
64
  PluvProvider: FC<PluvProviderProps>;
63
- usePluvClient: () => PluvClient<TIO>;
65
+ useClient: () => PluvClient<TIO>;
64
66
  }
65
67
  declare const createBundle: <TIO extends IOLike<_pluv_types.IOAuthorize<any, any>, {}, {}, {}, {}>>(client: PluvClient<TIO>) => CreateBundle<TIO>;
66
68
 
67
- export { type CreateBundle, type CreateRoomBundle, type CreateRoomBundleOptions, type PluvProviderProps, type PluvRoomProviderProps, type SubscriptionHookOptions, createBundle };
69
+ export { type CreateBundle, type CreateRoomBundle, type CreateRoomBundleOptions, type InferRoomStorage, type PluvProviderProps, type PluvRoomProviderProps, type SubscriptionHookOptions, createBundle };
package/dist/index.d.ts CHANGED
@@ -1,17 +1,18 @@
1
- import { PluvRoomAddon, TrackOriginOptions, PluvRoomDebug, WebSocketConnection, UserInfo, AbstractRoom, InferYjsSharedTypeJson, MockedRoomEvents, PluvClient } from '@pluv/client';
2
- export { AbstractType, ConnectionState, createClient, y } from '@pluv/client';
1
+ import { PluvRoomAddon, PluvRoomDebug, WebSocketConnection, UserInfo, AbstractRoom, MockedRoomEvents, PluvClient } from '@pluv/client';
2
+ export { ConnectionState, createClient } from '@pluv/client';
3
+ import { AbstractCrdtType, AbstractCrdtDocFactory, AbstractCrdtDoc, InferCrdtStorageJson } from '@pluv/crdt';
4
+ export { AbstractCrdtType, InferCrdtStorageJson } from '@pluv/crdt';
3
5
  import * as _pluv_types from '@pluv/types';
4
6
  import { IOLike, JsonObject, InputZodLike, InferIOInput, Id, InferIOOutput, IOEventMessage } from '@pluv/types';
5
7
  export { BaseUser, EventMessage, EventRecord, IOEventMessage } from '@pluv/types';
6
8
  import { FC, Dispatch, ReactNode } from 'react';
7
- import { AbstractType, Doc } from 'yjs';
8
9
 
9
- type CreateRoomBundleOptions<TIO extends IOLike, TPresence extends JsonObject = {}, TStorage extends Record<string, AbstractType<any>> = {}> = {
10
+ type CreateRoomBundleOptions<TIO extends IOLike, TPresence extends JsonObject = {}, TStorage extends Record<string, AbstractCrdtType<any, any>> = {}> = {
10
11
  addons?: readonly PluvRoomAddon<TIO, TPresence, TStorage>[];
11
- initialStorage?: () => TStorage;
12
+ initialStorage?: AbstractCrdtDocFactory<TStorage>;
12
13
  presence?: InputZodLike<TPresence>;
13
- } & TrackOriginOptions;
14
- type BaseRoomProviderProps<TPresence extends JsonObject, TStorage extends Record<string, AbstractType<any>>> = {
14
+ };
15
+ type BaseRoomProviderProps<TPresence extends JsonObject, TStorage extends Record<string, AbstractCrdtType<any, any>>> = {
15
16
  children?: ReactNode;
16
17
  initialStorage?: keyof TStorage extends never ? never : () => TStorage;
17
18
  room: string;
@@ -20,10 +21,10 @@ type BaseRoomProviderProps<TPresence extends JsonObject, TStorage extends Record
20
21
  } : {
21
22
  initialPresence: TPresence;
22
23
  });
23
- type MockedRoomProviderProps<TIO extends IOLike, TPresence extends JsonObject, TStorage extends Record<string, AbstractType<any>>> = BaseRoomProviderProps<TPresence, TStorage> & {
24
+ type MockedRoomProviderProps<TIO extends IOLike, TPresence extends JsonObject, TStorage extends Record<string, AbstractCrdtType<any, any>>> = BaseRoomProviderProps<TPresence, TStorage> & {
24
25
  events?: MockedRoomEvents<TIO>;
25
26
  };
26
- type PluvRoomProviderProps<TIO extends IOLike, TPresence extends JsonObject, TStorage extends Record<string, AbstractType<any>>> = BaseRoomProviderProps<TPresence, TStorage> & {
27
+ type PluvRoomProviderProps<TIO extends IOLike, TPresence extends JsonObject, TStorage extends Record<string, AbstractCrdtType<any, any>>> = BaseRoomProviderProps<TPresence, TStorage> & {
27
28
  debug?: boolean | PluvRoomDebug<TIO>;
28
29
  onAuthorizationFail?: (error: Error) => void;
29
30
  };
@@ -31,37 +32,38 @@ interface SubscriptionHookOptions<T extends unknown> {
31
32
  isEqual?: (a: T, b: T) => boolean;
32
33
  }
33
34
  type UpdateMyPresenceAction<TPresence extends JsonObject> = Partial<TPresence> | ((oldPresence: TPresence | null) => Partial<TPresence>);
34
- interface CreateRoomBundle<TIO extends IOLike, TPresence extends JsonObject, TStorage extends Record<string, AbstractType<any>>> {
35
+ interface CreateRoomBundle<TIO extends IOLike, TPresence extends JsonObject, TStorage extends Record<string, AbstractCrdtType<any, any>>> {
35
36
  MockedRoomProvider: FC<MockedRoomProviderProps<TIO, TPresence, TStorage>>;
36
37
  PluvRoomProvider: FC<PluvRoomProviderProps<TIO, TPresence, TStorage>>;
37
- usePluvBroadcast: () => <TEvent extends keyof InferIOInput<TIO>>(event: TEvent, data: Id<InferIOInput<TIO>[TEvent]>) => void;
38
- usePluvCanRedo: () => boolean;
39
- usePluvCanUndo: () => boolean;
40
- usePluvConnection: <T extends unknown = WebSocketConnection>(selector: (connection: WebSocketConnection) => T, options?: SubscriptionHookOptions<Id<T>>) => Id<T>;
41
- usePluvDoc: () => Doc;
42
- usePluvEvent: <TType extends keyof InferIOOutput<TIO>>(type: TType, callback: (data: Id<IOEventMessage<TIO, TType>>) => void) => void;
43
- usePluvMyPresence: <T extends unknown = TPresence>(selector?: (myPresence: TPresence) => T, options?: SubscriptionHookOptions<Id<T> | null>) => [
38
+ useBroadcast: () => <TEvent extends keyof InferIOInput<TIO>>(event: TEvent, data: Id<InferIOInput<TIO>[TEvent]>) => void;
39
+ useCanRedo: () => boolean;
40
+ useCanUndo: () => boolean;
41
+ useConnection: <T extends unknown = WebSocketConnection>(selector: (connection: WebSocketConnection) => T, options?: SubscriptionHookOptions<Id<T>>) => Id<T>;
42
+ useDoc: () => AbstractCrdtDoc<TStorage>;
43
+ useEvent: <TType extends keyof InferIOOutput<TIO>>(type: TType, callback: (data: Id<IOEventMessage<TIO, TType>>) => void) => void;
44
+ useMyPresence: <T extends unknown = TPresence>(selector?: (myPresence: TPresence) => T, options?: SubscriptionHookOptions<Id<T> | null>) => [
44
45
  myPresence: Id<T>,
45
46
  updateMyPresence: Dispatch<UpdateMyPresenceAction<TPresence>>
46
47
  ];
47
- usePluvMyself: <T extends unknown = UserInfo<TIO, TPresence>>(selector?: (myself: Id<UserInfo<TIO, TPresence>>) => T, options?: SubscriptionHookOptions<Id<T> | null>) => Id<T> | null;
48
- usePluvOther: <T extends unknown = UserInfo<TIO, TPresence>>(connectionId: string, selector?: (other: UserInfo<TIO, TPresence>) => T, options?: SubscriptionHookOptions<Id<T> | null>) => Id<T> | null;
49
- usePluvOthers: <T extends unknown = UserInfo<TIO, TPresence>>(selector?: (other: readonly Id<UserInfo<TIO, TPresence>>[]) => T[], options?: SubscriptionHookOptions<readonly Id<T>[]>) => readonly Id<T>[];
50
- usePluvRedo: () => () => void;
51
- usePluvRoom: () => AbstractRoom<TIO, TPresence, TStorage>;
52
- usePluvStorage: <TKey extends keyof TStorage, TData extends unknown = InferYjsSharedTypeJson<TStorage[TKey]>>(key: TKey, selector?: (data: InferYjsSharedTypeJson<TStorage[TKey]>) => TData, options?: SubscriptionHookOptions<TData>) => [data: TData, sharedType: TStorage[TKey]];
53
- usePluvTransact: () => (fn: (storage: TStorage) => void, origin?: string) => void;
54
- usePluvUndo: () => () => void;
48
+ useMyself: <T extends unknown = UserInfo<TIO, TPresence>>(selector?: (myself: Id<UserInfo<TIO, TPresence>>) => T, options?: SubscriptionHookOptions<Id<T> | null>) => Id<T> | null;
49
+ useOther: <T extends unknown = UserInfo<TIO, TPresence>>(connectionId: string, selector?: (other: UserInfo<TIO, TPresence>) => T, options?: SubscriptionHookOptions<Id<T> | null>) => Id<T> | null;
50
+ useOthers: <T extends unknown = UserInfo<TIO, TPresence>>(selector?: (other: readonly Id<UserInfo<TIO, TPresence>>[]) => T[], options?: SubscriptionHookOptions<readonly Id<T>[]>) => readonly Id<T>[];
51
+ useRedo: () => () => void;
52
+ useRoom: () => AbstractRoom<TIO, TPresence, TStorage>;
53
+ useStorage: <TKey extends keyof TStorage, TData extends unknown = InferCrdtStorageJson<TStorage[TKey]>>(key: TKey, selector?: (data: InferCrdtStorageJson<TStorage[TKey]>) => TData, options?: SubscriptionHookOptions<TData | null>) => [data: TData | null, sharedType: TStorage[TKey] | null];
54
+ useTransact: () => (fn: (storage: TStorage) => void, origin?: string) => void;
55
+ useUndo: () => () => void;
55
56
  }
57
+ type InferRoomStorage<TRoomBundle extends CreateRoomBundle<any, any, any>> = TRoomBundle extends CreateRoomBundle<any, any, infer IStorage> ? IStorage : never;
56
58
 
57
59
  interface PluvProviderProps {
58
60
  children?: ReactNode;
59
61
  }
60
62
  interface CreateBundle<TIO extends IOLike> {
61
- createRoomBundle: <TPresence extends JsonObject = {}, TStorage extends Record<string, AbstractType<any>> = {}>(options?: CreateRoomBundleOptions<TIO, TPresence, TStorage>) => CreateRoomBundle<TIO, TPresence, TStorage>;
63
+ createRoomBundle: <TPresence extends JsonObject = {}, TStorage extends Record<string, AbstractCrdtType<any, any>> = {}>(options: CreateRoomBundleOptions<TIO, TPresence, TStorage>) => CreateRoomBundle<TIO, TPresence, TStorage>;
62
64
  PluvProvider: FC<PluvProviderProps>;
63
- usePluvClient: () => PluvClient<TIO>;
65
+ useClient: () => PluvClient<TIO>;
64
66
  }
65
67
  declare const createBundle: <TIO extends IOLike<_pluv_types.IOAuthorize<any, any>, {}, {}, {}, {}>>(client: PluvClient<TIO>) => CreateBundle<TIO>;
66
68
 
67
- export { type CreateBundle, type CreateRoomBundle, type CreateRoomBundleOptions, type PluvProviderProps, type PluvRoomProviderProps, type SubscriptionHookOptions, createBundle };
69
+ export { type CreateBundle, type CreateRoomBundle, type CreateRoomBundleOptions, type InferRoomStorage, type PluvProviderProps, type PluvRoomProviderProps, type SubscriptionHookOptions, createBundle };