@pluv/react 0.15.0 → 0.16.1

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.15.0 build /home/runner/work/pluv/pluv/packages/react
2
+ > @pluv/react@0.16.1 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
- CJS dist/index.js 12.57 KB
12
- CJS ⚡️ Build success in 95ms
13
- ESM dist/index.mjs 9.98 KB
14
- ESM ⚡️ Build success in 109ms
11
+ CJS dist/index.js 12.53 KB
12
+ CJS ⚡️ Build success in 80ms
13
+ ESM dist/index.mjs 9.96 KB
14
+ ESM ⚡️ Build success in 80ms
15
15
  DTS Build start
16
- DTS ⚡️ Build success in 3737ms
17
- DTS dist/index.d.mts 4.77 KB
18
- DTS dist/index.d.ts 4.77 KB
16
+ DTS ⚡️ Build success in 3703ms
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,179 @@
1
1
  # @pluv/react
2
2
 
3
+ ## 0.16.1
4
+
5
+ ### Patch Changes
6
+
7
+ - @pluv/client@0.16.1
8
+ - @pluv/crdt@0.16.1
9
+ - @pluv/types@0.16.1
10
+
11
+ ## 0.16.0
12
+
13
+ ### Minor Changes
14
+
15
+ - 995aa9c: Renamed all hooks from `@pluv/react` to be simply prefixed with `use` instead of `usePluv` (e.g. `usePluvStorage` is now just `useStorage`).
16
+
17
+ Hooks can be aliased to retain the same names if preferred:
18
+
19
+ ```ts
20
+ export const {
21
+ // ...
22
+ useStorage: usePluvStorage,
23
+ useTransact: usePluvTransact,
24
+ // ...
25
+ } = createRoomBundle(/* */);
26
+ ```
27
+
28
+ - 4280220: ## Breaking Changes
29
+
30
+ - Storage types are now kept on the root of the document.
31
+ - 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.
32
+ - `@pluv/client` and `@pluv/react` no-longer re-export `@pluv/crdt-yjs`. This package will now need to be installed separately.
33
+
34
+ ```bash
35
+ # if installing @pluv/client
36
+ npm install @pluv/client @pluv/crdt-yjs
37
+ # if installing @pluv/react
38
+ npm install @pluv/react @pluv/crdt-yjs
39
+ ```
40
+
41
+ ```ts
42
+ // Before:
43
+ import { createClient, y } from "@pluv/client";
44
+ // After:
45
+ import { createClient } from "@pluv/client";
46
+ import { yjs } from "@pluv/crdt-yjs"; // y renamed to yjs
47
+ ```
48
+
49
+ - The `y` import has been renamed to `yjs`.
50
+ ```ts
51
+ // Before:
52
+ import { y } from "@pluv/crdt-yjs";
53
+ // After:
54
+ import { yjs } from "@pluv/crdt-yjs";
55
+ ```
56
+ - `@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`.
57
+
58
+ ```ts
59
+ // Before:
60
+ import { y } from "@pluv/crdt-yjs";
61
+ import type { Array as YArray, Map as YMap } from "yjs";
62
+
63
+ const array: YArray<YMap<{ message: string }>> = y.array([
64
+ y.object({ message: "Hello" }),
65
+ ]);
66
+
67
+ array.push([y.object({ message: "World!" })]);
68
+
69
+ // After:
70
+ import type { CrdtYjsArray, CrdtYjsObject } from "@pluv/crdt-yjs";
71
+ import { yjs } from "@pluv/crdt-yjs";
72
+ import type { Array as YArray } from "yjs";
73
+
74
+ const array: CrdtYjsArray<CrdtYjsObject<{ message: string }>> = yjs.array([
75
+ yjs.object({ message: "Hello" }),
76
+ ]);
77
+
78
+ array.push(yjs.object({ message: "World!" }));
79
+
80
+ // use .value to get the underlying yjs type
81
+ const yarray: YArray<YMap<{ message: string }>> = array.value;
82
+ ```
83
+
84
+ - `initialStorage` must now use the `doc` function from `@pluv/crdt-yjs` to be defined. This also affects `@pluv/react`.
85
+
86
+ ```ts
87
+ // Before:
88
+ import { createClient, y } from "@pluv/client";
89
+
90
+ const client = createClient({
91
+ /* ... */
92
+ });
93
+
94
+ client.createRoom({
95
+ // ...
96
+ initialStorage: () => ({
97
+ messages: y.array([y.object({ message: "Hello world!" })]),
98
+ }),
99
+ });
100
+
101
+ // After:
102
+ import { createClient } from "@pluv/client";
103
+ // This is now imported separately
104
+ import { yjs } from "@pluv/crdt-yjs";
105
+
106
+ const client = createClient({
107
+ /* ... */
108
+ });
109
+
110
+ client.createRoom({
111
+ // ...
112
+ initialStorage: yjs.doc(() => ({
113
+ messages: yjs.array([yjs.object({ message: "Hello world!" })]),
114
+ })),
115
+ });
116
+ ```
117
+
118
+ - `@pluv/client` can now instead use [loro](https://github.com/loro-dev/loro) instead of [yjs](https://github.com/yjs/yjs).
119
+ ```bash
120
+ npm install @pluv/client @pluv/crdt-loro loro-crdt
121
+ ```
122
+ - 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.
123
+
124
+ ```ts
125
+ import { loro } from "@pluv/crdt-loro";
126
+ import { yjs } from "@pluv/crdt-yjs";
127
+ import { createIO } from "@pluv/io";
128
+
129
+ const io = createIO({
130
+ // ...
131
+ // If using loro
132
+ crdt: loro,
133
+ // If using yjs
134
+ crdt: yjs,
135
+ });
136
+ ```
137
+
138
+ - `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`.
139
+
140
+ ```ts
141
+ // Before:
142
+ import { Doc as YDoc } from "yjs";
143
+
144
+ const room: PluvRoom = client.createRoom({
145
+ /* ... */
146
+ });
147
+
148
+ const doc: YDoc = room.getDoc();
149
+
150
+ // After:
151
+ import { CrdtYjsDoc } from "@pluv/crdt-yjs";
152
+ import { Doc as YDoc } from "yjs";
153
+
154
+ const room: PluvRoom = client.createRoom({
155
+ /* ... */
156
+ });
157
+
158
+ const doc: CrdtYjsDoc<any> = room.getDoc();
159
+ const ydoc: YDoc = doc.value;
160
+ ```
161
+
162
+ - `@pluv/client` and `@pluv/react` now may return `null` when retrieving storage while storage is being initialized.
163
+
164
+ ```ts
165
+ const sharedType = room.getStorage("messages"); // This may be null
166
+
167
+ const [data, sharedType] = useStorage("messages"); // data and sharedType may both be null
168
+ ```
169
+
170
+ ### Patch Changes
171
+
172
+ - Updated dependencies [4280220]
173
+ - @pluv/client@0.16.0
174
+ - @pluv/crdt@0.16.0
175
+ - @pluv/types@0.16.0
176
+
3
177
  ## 0.15.0
4
178
 
5
179
  ### Patch Changes
@@ -25,12 +199,12 @@
25
199
 
26
200
  ### Minor Changes
27
201
 
28
- - 4c4b47f: Added `usePluvDoc` to access the root Yjs doc.
202
+ - 4c4b47f: Added `useDoc` to access the root Yjs doc.
29
203
 
30
204
  ```ts
31
205
  import type { Doc } from "yjs";
32
206
 
33
- const doc: Doc = usePluvDoc();
207
+ const doc: Doc = useDoc();
34
208
  ```
35
209
 
36
210
  ### Patch Changes
@@ -216,7 +390,7 @@
216
390
 
217
391
  ## @pluv/react
218
392
 
219
- `@pluv/react`'s `createRoomBundle` now exposes 5 new react hooks: `usePluvCanRedo`, `usePluvCanUndo`, `usePluvRedo`, `usePluvUndo` and `usePluvTransact`.
393
+ `@pluv/react`'s `createRoomBundle` now exposes 5 new react hooks: `useCanRedo`, `useCanUndo`, `useRedo`, `useUndo` and `useTransact`.
220
394
 
221
395
  Refer to the code-example below to better understand how to undo and redo with your `createRoomBundle`.
222
396
 
@@ -228,47 +402,41 @@
228
402
 
229
403
  const { createRoomBundle } = createBundle(client);
230
404
 
231
- const {
232
- usePluvCanRedo,
233
- usePluvCanUndo,
234
- usePluvRedo,
235
- usePluvStorage,
236
- usePluvTransact,
237
- usePluvUndo,
238
- } = createRoomBundle({
239
- initialStorage: () => ({
240
- messages: y.array<string>([]),
241
- }),
242
- /**
243
- * @description This is the same `captureTimeout` option from yjs's UndoManager.
244
- * This specifies a number in ms, during which edits are merged together to be
245
- * undone together. Set this to 0, to track each transacted change individually.
246
- * @see (@link https://docs.yjs.dev/api/undo-manager)
247
- * @default 500
248
- */
249
- captureTimeout: 500,
250
- /**
251
- * @desription This is the same `trackedOrigins` option from yjs's UndoManager.
252
- * This specifies transaction origins (strings only) to filter which transactions
253
- * can be undone.
254
- * When omitted, the user's connection id will be tracked. When provided,
255
- * specifies additional tracked origins besides the user's connection id.
256
- * @see (@link https://docs.yjs.dev/api/undo-manager)
257
- * @default undefined
258
- */
259
- trackedOrigins: ["user-123"],
260
- });
405
+ const { useCanRedo, useCanUndo, useRedo, useStorage, useTransact, useUndo } =
406
+ createRoomBundle({
407
+ initialStorage: () => ({
408
+ messages: y.array<string>([]),
409
+ }),
410
+ /**
411
+ * @description This is the same `captureTimeout` option from yjs's UndoManager.
412
+ * This specifies a number in ms, during which edits are merged together to be
413
+ * undone together. Set this to 0, to track each transacted change individually.
414
+ * @see (@link https://docs.yjs.dev/api/undo-manager)
415
+ * @default 500
416
+ */
417
+ captureTimeout: 500,
418
+ /**
419
+ * @desription This is the same `trackedOrigins` option from yjs's UndoManager.
420
+ * This specifies transaction origins (strings only) to filter which transactions
421
+ * can be undone.
422
+ * When omitted, the user's connection id will be tracked. When provided,
423
+ * specifies additional tracked origins besides the user's connection id.
424
+ * @see (@link https://docs.yjs.dev/api/undo-manager)
425
+ * @default undefined
426
+ */
427
+ trackedOrigins: ["user-123"],
428
+ });
261
429
 
262
430
  /**
263
431
  * @description Check whether calling undo will mutate storage
264
432
  */
265
- const canUndo: boolean = usePluvCanUndo();
433
+ const canUndo: boolean = useCanUndo();
266
434
  /**
267
435
  * @description Check whether calling redo will mutate storage
268
436
  */
269
- const canRedo: boolean = usePluvCanRedo();
437
+ const canRedo: boolean = useCanRedo();
270
438
 
271
- const [messages, sharedType] = usePluvStorage("messages");
439
+ const [messages, sharedType] = useStorage("messages");
272
440
 
273
441
  /**
274
442
  * @description Calling transact will enable a storage mutation to be undone/redone.
@@ -277,7 +445,7 @@
277
445
  *
278
446
  * You can specify a 2nd parameter to transact with a different transaction origin.
279
447
  */
280
- const transact = usePluvTransact();
448
+ const transact = useTransact();
281
449
 
282
450
  transact(() => {
283
451
  sharedType.push(["hello world!"]);
@@ -291,14 +459,14 @@
291
459
  /**
292
460
  * @description Undoes the last valid mutation to storage
293
461
  */
294
- const undo = usePluvUndo();
462
+ const undo = useUndo();
295
463
 
296
464
  undo();
297
465
 
298
466
  /**
299
467
  * @description Re-applies the last undone mutation to storage
300
468
  */
301
- const redo = usePluvRedo();
469
+ const redo = useRedo();
302
470
 
303
471
  redo();
304
472
  ```
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 };