@pluv/react 0.17.3 → 0.19.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.17.3 build /home/runner/work/pluv/pluv/packages/react
2
+ > @pluv/react@0.19.0 build /home/runner/work/pluv/pluv/packages/react
3
3
  > tsup src/index.ts --format esm,cjs --dts --external react
4
4
 
5
- CLI Building entry: src/index.ts
6
- CLI Using tsconfig: tsconfig.json
7
- CLI tsup v8.0.2
8
- CLI Target: es6
9
- ESM Build start
10
- CJS Build start
11
- ESM dist/index.mjs 9.96 KB
12
- ESM ⚡️ Build success in 80ms
13
- CJS dist/index.js 12.53 KB
14
- CJS ⚡️ Build success in 81ms
15
- DTS Build start
16
- DTS ⚡️ Build success in 4595ms
17
- DTS dist/index.d.mts 5.05 KB
18
- DTS dist/index.d.ts 5.05 KB
5
+ CLI Building entry: src/index.ts
6
+ CLI Using tsconfig: tsconfig.json
7
+ CLI tsup v8.1.0
8
+ CLI Target: es6
9
+ ESM Build start
10
+ CJS Build start
11
+ ESM dist/index.mjs 11.61 KB
12
+ ESM ⚡️ Build success in 85ms
13
+ CJS dist/index.js 14.02 KB
14
+ CJS ⚡️ Build success in 86ms
15
+ DTS Build start
16
+ DTS ⚡️ Build success in 4322ms
17
+ DTS dist/index.d.mts 5.35 KB
18
+ DTS dist/index.d.ts 5.35 KB
package/CHANGELOG.md CHANGED
@@ -1,5 +1,178 @@
1
1
  # @pluv/react
2
2
 
3
+ ## 0.19.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 798e32d: **Breaking**: useOthers now allows returning any data besides arrays when using a custom selector.
8
+ - 8450306: **Breaking**: Require minimum react version of ^18.0.0.
9
+
10
+ ### Patch Changes
11
+
12
+ - 607afe3: Update the `updateMyPresence` function from `useMyPresence` to simply forward the function from the `PluvRoom`. This means all `updateMyPresence` functions should be the same underlying reference across all `useMyPresence` hooks.
13
+ - Updated dependencies [137444b]
14
+ - Updated dependencies [f5e4370]
15
+ - @pluv/client@0.19.0
16
+ - @pluv/crdt@0.19.0
17
+ - @pluv/types@0.19.0
18
+
19
+ ## 0.18.0
20
+
21
+ ### Minor Changes
22
+
23
+ - 99b5ca9: ## Breaking Changes
24
+
25
+ - `@pluv/io` has been updated to introduce `PluvProcedure`, `PluvRouter` and `PluvServer`. This change is intended to improve the ergonomics of declaring events and simplifying inferences of event types.
26
+
27
+ ### Before:
28
+
29
+ ```ts
30
+ // backend/io.ts
31
+
32
+ import { createIO } from "@pluv/io";
33
+ import { createPluvHandler, platformNode } from "@pluv/platform-node";
34
+ import { z } from "zod";
35
+
36
+ export const io = createIO({
37
+ platform: platformNode(),
38
+ })
39
+ .event("SEND_MESSAGE", {
40
+ input: z.object({ message: z.string() }),
41
+ resolver: ({ message }) => ({ RECEIVE_MESSAGE: { message } }),
42
+ })
43
+ .event("DOUBLE_VALUE", {
44
+ input: z.object({ value: z.number() }),
45
+ resolver: ({ value }) => ({ VALUE_DOUBLED: { value: value * 2 } }),
46
+ });
47
+
48
+ const Pluv = createPluvHandler({
49
+ io,
50
+ /* ... */
51
+ });
52
+ ```
53
+
54
+ ```ts
55
+ // frontend/pluv.ts
56
+
57
+ import { createClient } from "@pluv/react";
58
+ import type { io } from "../backend/io";
59
+
60
+ const client = createClient<typeof io>({
61
+ /* ... */
62
+ });
63
+ ```
64
+
65
+ ### Now:
66
+
67
+ ```ts
68
+ import { createIO } from "@pluv/io";
69
+ import { createPluvHandler, platformNode } from "@pluv/platform-node";
70
+ import { z } from "zod";
71
+
72
+ const io = createIO({
73
+ platform: platformNode(),
74
+ });
75
+
76
+ const router = io.router({
77
+ SEND_MESSAGE: io.procedure
78
+ .input(z.object({ message: z.string() }))
79
+ .broadcast(({ message }) => ({
80
+ RECEIVE_MESSAGE: { message },
81
+ })),
82
+ DOUBLE_VALUE: io.procedure
83
+ .input(z.object({ value: z.number() }))
84
+ .broadcast(({ value }) => ({
85
+ VALUE_DOUBLED: { value: value * 2 },
86
+ })),
87
+ });
88
+
89
+ export const ioServer = io.server({ router });
90
+
91
+ const Pluv = createPluvHandler({
92
+ io: ioServer, // <- This uses the PluvServer now
93
+ /* ... */
94
+ });
95
+ ```
96
+
97
+ ```ts
98
+ // frontend/pluv.ts
99
+
100
+ import { createClient } from "@pluv/react";
101
+ import type { ioServer } from "../backend/io";
102
+
103
+ // This users the PluvServer type now
104
+ const client = createClient<typeof ioServer>({
105
+ /* ... */
106
+ });
107
+ ```
108
+
109
+ - `PluvRouter` instances can also be merged via the `mergeRouters` method, which effectively performs an `Object.assign` of the events object and returns a new `PluvRouter` with the correct types:
110
+
111
+ ```ts
112
+ const router = io.mergeRouters(router1, router2);
113
+ ```
114
+
115
+ - 07a7725: Added broadcast proxy as a new way to broadcast events to other users.
116
+
117
+ ```tsx
118
+ // backend
119
+
120
+ const router = io.router({
121
+ SEND_MESSAGE: io.procedure
122
+ .input(z.object({ message: z.string() }))
123
+ .broadcast(({ message }) => ({ RECEIVE_MESSAGE: { message } })),
124
+ });
125
+
126
+ // frontend
127
+ const pluv = createRoomBundle(/* ... */);
128
+
129
+ const broadcast = pluv.useBroadcast();
130
+
131
+ // Both of the examples below are equivalent.
132
+
133
+ broadcast("SEND_MESSAGE", { message: "Hello world~!" });
134
+
135
+ broadcast.SEND_MESSAGE({ message: "Hello world~!" });
136
+ ```
137
+
138
+ ### Patch Changes
139
+
140
+ - e587c18: Added event proxy as a new way to listen to events.
141
+
142
+ ```tsx
143
+ // backend
144
+
145
+ const router = io.router({
146
+ SEND_MESSAGE: io.procedure
147
+ .input(z.object({ message: z.string() }))
148
+ .broadcast(({ message }) => ({ RECEIVE_MESSAGE: { message } })),
149
+ });
150
+
151
+ // frontend
152
+ const pluv = createRoomBundle(/* ... */);
153
+
154
+ // Both of the examples below are equivalent.
155
+
156
+ pluv.useEvent("RECEIVE_MESSAGE", ({ data }) => {
157
+ const { message } = data;
158
+
159
+ console.log(message);
160
+ });
161
+
162
+ pluv.event.RECEIVE_MESSAGE.useEvent(({ data }) => {
163
+ const { message } = data;
164
+
165
+ console.log(message);
166
+ });
167
+ ```
168
+
169
+ - Updated dependencies [06c67be]
170
+ - Updated dependencies [99b5ca9]
171
+ - Updated dependencies [df1342c]
172
+ - @pluv/client@0.18.0
173
+ - @pluv/types@0.18.0
174
+ - @pluv/crdt@0.18.0
175
+
3
176
  ## 0.17.3
4
177
 
5
178
  ### Patch Changes
package/README.md CHANGED
@@ -76,18 +76,28 @@ export const {
76
76
 
77
77
  export const {
78
78
  // components
79
+ MockedRoomProvider,
79
80
  PluvRoomProvider,
80
81
 
82
+ // utils
83
+ event,
84
+
81
85
  // hooks
82
86
  useBroadcast,
87
+ useCanRedo,
88
+ useCanUndo,
83
89
  useConnection,
90
+ useDoc,
84
91
  useEvent,
85
92
  useMyPresence,
86
93
  useMyself,
87
94
  useOther,
88
95
  useOthers,
96
+ useRedo,
89
97
  useRoom,
90
98
  useStorage,
99
+ useTransact,
100
+ useUndo,
91
101
  } = createRoomBundle({
92
102
  initialStorage: yjs.doc(() => ({
93
103
  messages: yjs.array([
@@ -120,7 +130,7 @@ export const MyPage: FC<Record<string, never>> = () => {
120
130
  export const MyRoom: FC<Record<string, never>> = () => {
121
131
  const broadcast = useBroadcast();
122
132
 
123
- useEvent("RECEIVE_MESSAGE", ({ data }) => {
133
+ event.RECEIVE_MESSAGE.useEvent(({ data }) => {
124
134
  // data is typed as { message: string }
125
135
  console.log(data.message);
126
136
  });
@@ -128,7 +138,7 @@ export const MyRoom: FC<Record<string, never>> = () => {
128
138
  return (
129
139
  <button
130
140
  onClick={() => {
131
- broadcast("SEND_MESSAGE", {
141
+ broadcast.SEND_MESSAGE({
132
142
  // TypeScript will require that message is typed as string
133
143
  message: "Hello world!",
134
144
  });
package/dist/index.d.mts CHANGED
@@ -3,7 +3,7 @@ export { ConnectionState, createClient } from '@pluv/client';
3
3
  import { AbstractCrdtType, AbstractCrdtDocFactory, AbstractCrdtDoc, InferCrdtStorageJson } from '@pluv/crdt';
4
4
  export { AbstractCrdtType, InferCrdtStorageJson } from '@pluv/crdt';
5
5
  import * as _pluv_types from '@pluv/types';
6
- import { IOLike, JsonObject, InputZodLike, InferIOInput, Id, InferIOOutput, IOEventMessage } from '@pluv/types';
6
+ import { IOLike, JsonObject, InputZodLike, Id, InferIOOutput, IOEventMessage, InferIOInput } from '@pluv/types';
7
7
  export { BaseUser, EventMessage, EventRecord, IOEventMessage } from '@pluv/types';
8
8
  import { FC, Dispatch, ReactNode } from 'react';
9
9
 
@@ -32,22 +32,28 @@ interface SubscriptionHookOptions<T extends unknown> {
32
32
  isEqual?: (a: T, b: T) => boolean;
33
33
  }
34
34
  type UpdateMyPresenceAction<TPresence extends JsonObject> = Partial<TPresence> | ((oldPresence: TPresence | null) => Partial<TPresence>);
35
+ type BroadcastProxy<TIO extends IOLike> = (<TEvent extends keyof InferIOInput<TIO>>(event: TEvent, data: Id<InferIOInput<TIO>[TEvent]>) => void) & {
36
+ [event in keyof InferIOInput<TIO>]: (input: Id<InferIOInput<TIO>[event]>) => void;
37
+ };
38
+ type EventProxy<TIO extends IOLike> = {
39
+ [event in keyof InferIOOutput<TIO>]: {
40
+ useEvent: (callback: (data: Id<IOEventMessage<TIO, event>>) => void) => void;
41
+ };
42
+ };
35
43
  interface CreateRoomBundle<TIO extends IOLike, TPresence extends JsonObject, TStorage extends Record<string, AbstractCrdtType<any, any>>> {
36
44
  MockedRoomProvider: FC<MockedRoomProviderProps<TIO, TPresence, TStorage>>;
37
45
  PluvRoomProvider: FC<PluvRoomProviderProps<TIO, TPresence, TStorage>>;
38
- useBroadcast: () => <TEvent extends keyof InferIOInput<TIO>>(event: TEvent, data: Id<InferIOInput<TIO>[TEvent]>) => void;
46
+ event: EventProxy<TIO>;
47
+ useBroadcast: () => BroadcastProxy<TIO>;
39
48
  useCanRedo: () => boolean;
40
49
  useCanUndo: () => boolean;
41
50
  useConnection: <T extends unknown = WebSocketConnection>(selector: (connection: WebSocketConnection) => T, options?: SubscriptionHookOptions<Id<T>>) => Id<T>;
42
51
  useDoc: () => AbstractCrdtDoc<TStorage>;
43
52
  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>) => [
45
- myPresence: Id<T>,
46
- updateMyPresence: Dispatch<UpdateMyPresenceAction<TPresence>>
47
- ];
53
+ useMyPresence: <T extends unknown = TPresence>(selector?: (myPresence: TPresence) => T, options?: SubscriptionHookOptions<Id<T> | null>) => [myPresence: Id<T>, updateMyPresence: Dispatch<UpdateMyPresenceAction<TPresence>>];
48
54
  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>[];
55
+ useOther: <T extends unknown = UserInfo<TIO, TPresence>>(connectionId: string, selector?: (other: UserInfo<TIO, TPresence>) => T, options?: SubscriptionHookOptions<T | null>) => T | null;
56
+ useOthers: <T extends unknown = readonly UserInfo<TIO, TPresence>[]>(selector?: (other: readonly Id<UserInfo<TIO, TPresence>>[]) => T, options?: SubscriptionHookOptions<T>) => T;
51
57
  useRedo: () => () => void;
52
58
  useRoom: () => AbstractRoom<TIO, TPresence, TStorage>;
53
59
  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];
@@ -64,6 +70,6 @@ interface CreateBundle<TIO extends IOLike> {
64
70
  PluvProvider: FC<PluvProviderProps>;
65
71
  useClient: () => PluvClient<TIO>;
66
72
  }
67
- declare const createBundle: <TIO extends IOLike<_pluv_types.IOAuthorize<any, any, any>, {}, {}, {}, {}>>(client: PluvClient<TIO>) => CreateBundle<TIO>;
73
+ declare const createBundle: <TIO extends IOLike<_pluv_types.IOAuthorize<any, any, any>, {}>>(client: PluvClient<TIO>) => CreateBundle<TIO>;
68
74
 
69
75
  export { type CreateBundle, type CreateRoomBundle, type CreateRoomBundleOptions, type InferRoomStorage, type PluvProviderProps, type PluvRoomProviderProps, type SubscriptionHookOptions, createBundle };
package/dist/index.d.ts CHANGED
@@ -3,7 +3,7 @@ export { ConnectionState, createClient } from '@pluv/client';
3
3
  import { AbstractCrdtType, AbstractCrdtDocFactory, AbstractCrdtDoc, InferCrdtStorageJson } from '@pluv/crdt';
4
4
  export { AbstractCrdtType, InferCrdtStorageJson } from '@pluv/crdt';
5
5
  import * as _pluv_types from '@pluv/types';
6
- import { IOLike, JsonObject, InputZodLike, InferIOInput, Id, InferIOOutput, IOEventMessage } from '@pluv/types';
6
+ import { IOLike, JsonObject, InputZodLike, Id, InferIOOutput, IOEventMessage, InferIOInput } from '@pluv/types';
7
7
  export { BaseUser, EventMessage, EventRecord, IOEventMessage } from '@pluv/types';
8
8
  import { FC, Dispatch, ReactNode } from 'react';
9
9
 
@@ -32,22 +32,28 @@ interface SubscriptionHookOptions<T extends unknown> {
32
32
  isEqual?: (a: T, b: T) => boolean;
33
33
  }
34
34
  type UpdateMyPresenceAction<TPresence extends JsonObject> = Partial<TPresence> | ((oldPresence: TPresence | null) => Partial<TPresence>);
35
+ type BroadcastProxy<TIO extends IOLike> = (<TEvent extends keyof InferIOInput<TIO>>(event: TEvent, data: Id<InferIOInput<TIO>[TEvent]>) => void) & {
36
+ [event in keyof InferIOInput<TIO>]: (input: Id<InferIOInput<TIO>[event]>) => void;
37
+ };
38
+ type EventProxy<TIO extends IOLike> = {
39
+ [event in keyof InferIOOutput<TIO>]: {
40
+ useEvent: (callback: (data: Id<IOEventMessage<TIO, event>>) => void) => void;
41
+ };
42
+ };
35
43
  interface CreateRoomBundle<TIO extends IOLike, TPresence extends JsonObject, TStorage extends Record<string, AbstractCrdtType<any, any>>> {
36
44
  MockedRoomProvider: FC<MockedRoomProviderProps<TIO, TPresence, TStorage>>;
37
45
  PluvRoomProvider: FC<PluvRoomProviderProps<TIO, TPresence, TStorage>>;
38
- useBroadcast: () => <TEvent extends keyof InferIOInput<TIO>>(event: TEvent, data: Id<InferIOInput<TIO>[TEvent]>) => void;
46
+ event: EventProxy<TIO>;
47
+ useBroadcast: () => BroadcastProxy<TIO>;
39
48
  useCanRedo: () => boolean;
40
49
  useCanUndo: () => boolean;
41
50
  useConnection: <T extends unknown = WebSocketConnection>(selector: (connection: WebSocketConnection) => T, options?: SubscriptionHookOptions<Id<T>>) => Id<T>;
42
51
  useDoc: () => AbstractCrdtDoc<TStorage>;
43
52
  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>) => [
45
- myPresence: Id<T>,
46
- updateMyPresence: Dispatch<UpdateMyPresenceAction<TPresence>>
47
- ];
53
+ useMyPresence: <T extends unknown = TPresence>(selector?: (myPresence: TPresence) => T, options?: SubscriptionHookOptions<Id<T> | null>) => [myPresence: Id<T>, updateMyPresence: Dispatch<UpdateMyPresenceAction<TPresence>>];
48
54
  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>[];
55
+ useOther: <T extends unknown = UserInfo<TIO, TPresence>>(connectionId: string, selector?: (other: UserInfo<TIO, TPresence>) => T, options?: SubscriptionHookOptions<T | null>) => T | null;
56
+ useOthers: <T extends unknown = readonly UserInfo<TIO, TPresence>[]>(selector?: (other: readonly Id<UserInfo<TIO, TPresence>>[]) => T, options?: SubscriptionHookOptions<T>) => T;
51
57
  useRedo: () => () => void;
52
58
  useRoom: () => AbstractRoom<TIO, TPresence, TStorage>;
53
59
  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];
@@ -64,6 +70,6 @@ interface CreateBundle<TIO extends IOLike> {
64
70
  PluvProvider: FC<PluvProviderProps>;
65
71
  useClient: () => PluvClient<TIO>;
66
72
  }
67
- declare const createBundle: <TIO extends IOLike<_pluv_types.IOAuthorize<any, any, any>, {}, {}, {}, {}>>(client: PluvClient<TIO>) => CreateBundle<TIO>;
73
+ declare const createBundle: <TIO extends IOLike<_pluv_types.IOAuthorize<any, any, any>, {}>>(client: PluvClient<TIO>) => CreateBundle<TIO>;
68
74
 
69
75
  export { type CreateBundle, type CreateRoomBundle, type CreateRoomBundleOptions, type InferRoomStorage, type PluvProviderProps, type PluvRoomProviderProps, type SubscriptionHookOptions, createBundle };