@pluv/client 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/client@0.17.3 build /home/runner/work/pluv/pluv/packages/client
2
+ > @pluv/client@0.19.0 build /home/runner/work/pluv/pluv/packages/client
3
3
  > tsup src/index.ts --format esm,cjs --dts
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
- CJS dist/index.js 42.79 KB
12
- CJS ⚡️ Build success in 125ms
13
- ESM dist/index.mjs 41.52 KB
14
- ESM ⚡️ Build success in 127ms
15
- DTS Build start
16
- DTS ⚡️ Build success in 3588ms
17
- DTS dist/index.d.mts 13.95 KB
18
- DTS dist/index.d.ts 13.95 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 40.97 KB
12
+ ESM ⚡️ Build success in 85ms
13
+ CJS dist/index.js 42.24 KB
14
+ CJS ⚡️ Build success in 108ms
15
+ DTS Build start
16
+ DTS ⚡️ Build success in 3379ms
17
+ DTS dist/index.d.mts 14.33 KB
18
+ DTS dist/index.d.ts 14.33 KB
package/CHANGELOG.md CHANGED
@@ -1,5 +1,181 @@
1
1
  # @pluv/client
2
2
 
3
+ ## 0.19.0
4
+
5
+ ### Patch Changes
6
+
7
+ - 137444b: Updated PluvRoom.updateMyPresence to allow passing in a callback function that exposes the previous presence value and returns a presence update.
8
+
9
+ ```ts
10
+ type Presence = {
11
+ selectionId: string | null;
12
+ };
13
+
14
+ const room: PluvRoom = /* ... */;
15
+ const newSelectionId: string | null = /* ... */;
16
+
17
+ room.updateMyPresence({ selectionId: newSelection });
18
+
19
+ // You can reference the previous presence and return a new presence based on it
20
+ room.updateMyPresence((previousPresence) => ({ selectionId: newSelection ?? previousPresence.selectionId }));
21
+ ```
22
+
23
+ - f5e4370: Fix others' presence not getting tracked in PluvRoom when the user is unauthorized.
24
+ - @pluv/crdt@0.19.0
25
+ - @pluv/types@0.19.0
26
+
27
+ ## 0.18.0
28
+
29
+ ### Minor Changes
30
+
31
+ - 99b5ca9: ## Breaking Changes
32
+
33
+ - `@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.
34
+
35
+ ### Before:
36
+
37
+ ```ts
38
+ // backend/io.ts
39
+
40
+ import { createIO } from "@pluv/io";
41
+ import { createPluvHandler, platformNode } from "@pluv/platform-node";
42
+ import { z } from "zod";
43
+
44
+ export const io = createIO({
45
+ platform: platformNode(),
46
+ })
47
+ .event("SEND_MESSAGE", {
48
+ input: z.object({ message: z.string() }),
49
+ resolver: ({ message }) => ({ RECEIVE_MESSAGE: { message } }),
50
+ })
51
+ .event("DOUBLE_VALUE", {
52
+ input: z.object({ value: z.number() }),
53
+ resolver: ({ value }) => ({ VALUE_DOUBLED: { value: value * 2 } }),
54
+ });
55
+
56
+ const Pluv = createPluvHandler({
57
+ io,
58
+ /* ... */
59
+ });
60
+ ```
61
+
62
+ ```ts
63
+ // frontend/pluv.ts
64
+
65
+ import { createClient } from "@pluv/react";
66
+ import type { io } from "../backend/io";
67
+
68
+ const client = createClient<typeof io>({
69
+ /* ... */
70
+ });
71
+ ```
72
+
73
+ ### Now:
74
+
75
+ ```ts
76
+ import { createIO } from "@pluv/io";
77
+ import { createPluvHandler, platformNode } from "@pluv/platform-node";
78
+ import { z } from "zod";
79
+
80
+ const io = createIO({
81
+ platform: platformNode(),
82
+ });
83
+
84
+ const router = io.router({
85
+ SEND_MESSAGE: io.procedure
86
+ .input(z.object({ message: z.string() }))
87
+ .broadcast(({ message }) => ({
88
+ RECEIVE_MESSAGE: { message },
89
+ })),
90
+ DOUBLE_VALUE: io.procedure
91
+ .input(z.object({ value: z.number() }))
92
+ .broadcast(({ value }) => ({
93
+ VALUE_DOUBLED: { value: value * 2 },
94
+ })),
95
+ });
96
+
97
+ export const ioServer = io.server({ router });
98
+
99
+ const Pluv = createPluvHandler({
100
+ io: ioServer, // <- This uses the PluvServer now
101
+ /* ... */
102
+ });
103
+ ```
104
+
105
+ ```ts
106
+ // frontend/pluv.ts
107
+
108
+ import { createClient } from "@pluv/react";
109
+ import type { ioServer } from "../backend/io";
110
+
111
+ // This users the PluvServer type now
112
+ const client = createClient<typeof ioServer>({
113
+ /* ... */
114
+ });
115
+ ```
116
+
117
+ - `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:
118
+
119
+ ```ts
120
+ const router = io.mergeRouters(router1, router2);
121
+ ```
122
+
123
+ ### Patch Changes
124
+
125
+ - 06c67be: Added broadcast proxy as a new way to broadcast events.
126
+
127
+ ```ts
128
+ // backend
129
+
130
+ const router = io.router({
131
+ SEND_MESSAGE: io.procedure
132
+ .input(z.object({ message: z.string() }))
133
+ .broadcast(({ message }) => ({ RECEIVE_MESSAGE: { message } })),
134
+ });
135
+
136
+ // frontend
137
+ const client = createClient(/* ... */);
138
+
139
+ // Both of the examples below are equivalent.
140
+
141
+ client.broadcast("SEND_MESSAGE", { message: "Hello world~!" });
142
+
143
+ client.broadcast.SEND_MESSAGE({ message: "Hello world~!" });
144
+ ```
145
+
146
+ - df1342c: Added event proxy as a new way to listen to events.
147
+
148
+ ```ts
149
+ // backend
150
+
151
+ const router = io.router({
152
+ SEND_MESSAGE: io.procedure
153
+ .input(z.object({ message: z.string() }))
154
+ .broadcast(({ message }) => ({ RECEIVE_MESSAGE: { message } })),
155
+ });
156
+
157
+ // frontend
158
+ const client = createClient(/* ... */);
159
+
160
+ // Both of the examples below are equivalent.
161
+
162
+ client.event("RECEIVE_MESSAGE", ({ data }) => {
163
+ const { message } = data;
164
+
165
+ console.log(message);
166
+ });
167
+
168
+ client.event.RECEIVE_MESSAGE(({ data }) => {
169
+ const { message } = data;
170
+
171
+ console.log(message);
172
+ });
173
+ ```
174
+
175
+ - Updated dependencies [99b5ca9]
176
+ - @pluv/types@0.18.0
177
+ - @pluv/crdt@0.18.0
178
+
3
179
  ## 0.17.3
4
180
 
5
181
  ### Patch Changes
package/README.md CHANGED
@@ -93,14 +93,11 @@ const room = client.createRoom<Presence, Storage>("my-room", {
93
93
  const main = async () => {
94
94
  await client.enter(room);
95
95
 
96
- const unsubscribe = client.event("RECEIVE_MESSAGE", ({ data }) => {
96
+ const unsubscribe = client.event.RECEIVE_MESSAGE(({ data }) => {
97
97
  console.log(data.message);
98
98
  });
99
99
 
100
- client.broadcast({
101
- type: "SEND_MESSAGE",
102
- data: { message: "Hello world!" },
103
- });
100
+ client.broadcast.SEND_MESSAGE({ message: "Hello world!" });
104
101
 
105
102
  unsubscribe();
106
103
 
package/dist/index.d.mts CHANGED
@@ -18,6 +18,12 @@ declare enum ConnectionState {
18
18
  Unavailable = "Unavailable",
19
19
  Untouched = "Untouched"
20
20
  }
21
+ type UpdateMyPresenceAction<TPresence extends JsonObject> = Partial<TPresence> | ((oldPresence: TPresence | null) => Partial<TPresence>);
22
+ interface UserInfo<TIO extends IOLike, TPresence extends JsonObject = {}> {
23
+ connectionId: string;
24
+ presence: TPresence;
25
+ user: Id<InferIOAuthorizeUser<InferIOAuthorize<TIO>>>;
26
+ }
21
27
  interface WebSocketConnection {
22
28
  count: number;
23
29
  id: string | null;
@@ -28,11 +34,6 @@ interface WebSocketState<TIO extends IOLike> {
28
34
  connection: WebSocketConnection;
29
35
  webSocket: WebSocket | null;
30
36
  }
31
- interface UserInfo<TIO extends IOLike, TPresence extends JsonObject = {}> {
32
- connectionId: string;
33
- presence: TPresence;
34
- user: Id<InferIOAuthorizeUser<InferIOAuthorize<TIO>>>;
35
- }
36
37
 
37
38
  type OtherNotifierSubscriptionCallback<TIO extends IOLike> = (value: Id<UserInfo<TIO>> | null) => void;
38
39
 
@@ -70,7 +71,7 @@ declare abstract class AbstractRoom<TIO extends IOLike, TPresence extends JsonOb
70
71
  abstract subscribe<TSubject extends keyof StateNotifierSubjects<TIO, TPresence>>(name: TSubject, callback: SubscriptionCallback<TIO, TPresence, TSubject>): () => void;
71
72
  abstract transact(fn: (storage: TStorage) => void, origin?: string): void;
72
73
  abstract undo(): void;
73
- abstract updateMyPresence(presence: Partial<TPresence>): void;
74
+ abstract updateMyPresence(presence: UpdateMyPresenceAction<TPresence>): void;
74
75
  }
75
76
 
76
77
  declare abstract class AbstractStorageStore {
@@ -116,7 +117,7 @@ declare class MockedRoom<TIO extends IOLike, TPresence extends JsonObject = {},
116
117
  canRedo: () => boolean;
117
118
  canUndo: () => boolean;
118
119
  event: <TEvent extends keyof InferIOOutput<TIO>>(event: TEvent, callback: EventNotifierSubscriptionCallback<TIO, TEvent>) => (() => void);
119
- getConnection(): WebSocketConnection;
120
+ getConnection: () => WebSocketConnection;
120
121
  getDoc(): AbstractCrdtDoc<TStorage>;
121
122
  getMyPresence: () => TPresence;
122
123
  getMyself: () => Id<UserInfo<TIO, TPresence>> | null;
@@ -130,7 +131,7 @@ declare class MockedRoom<TIO extends IOLike, TPresence extends JsonObject = {},
130
131
  subscribe: <TSubject extends keyof StateNotifierSubjects<TIO, TPresence>>(name: TSubject, callback: SubscriptionCallback<TIO, TPresence, TSubject>) => (() => void);
131
132
  transact: (fn: (storage: TStorage) => void, origin?: string) => void;
132
133
  undo: () => void;
133
- updateMyPresence: (presence: Partial<TPresence>) => void;
134
+ updateMyPresence: (presence: UpdateMyPresenceAction<TPresence>) => void;
134
135
  private _observeCrdt;
135
136
  }
136
137
 
@@ -191,14 +192,14 @@ declare class PluvRoom<TIO extends IOLike, TPresence extends JsonObject = {}, TS
191
192
  constructor(room: string, options: RoomConfig<TIO, TPresence, TStorage>);
192
193
  get storageLoaded(): boolean;
193
194
  get webSocket(): WebSocket | null;
194
- broadcast<TEvent extends keyof InferIOInput<TIO>>(event: TEvent, data: Id<InferIOInput<TIO>[TEvent]>): void;
195
+ broadcast: (<TEvent extends keyof InferIOInput<TIO>>(event: TEvent, data: Id<InferIOInput<TIO>[TEvent]>) => void) & { [event in keyof InferIOInput<TIO>]: (data: Id<InferIOInput<TIO>[event]>) => void; };
195
196
  canRedo: () => boolean;
196
197
  canUndo: () => boolean;
197
198
  connect(): Promise<void>;
198
199
  disconnect(): Promise<void>;
199
- event: <TEvent extends keyof InferIOOutput<TIO>>(event: TEvent, callback: EventNotifierSubscriptionCallback<TIO, TEvent>) => (() => void);
200
- getConnection(): WebSocketConnection;
201
- getDoc(): AbstractCrdtDoc<TStorage>;
200
+ event: (<TEvent extends keyof InferIOOutput<TIO>>(event: TEvent, callback: EventNotifierSubscriptionCallback<TIO, TEvent>) => () => void) & { [event in keyof InferIOOutput<TIO>]: (callback: EventNotifierSubscriptionCallback<TIO, event>) => () => void; };
201
+ getConnection: () => WebSocketConnection;
202
+ getDoc: () => AbstractCrdtDoc<TStorage>;
202
203
  getMyPresence: () => TPresence;
203
204
  getMyself: () => Id<UserInfo<TIO, TPresence>> | null;
204
205
  getOther: (connectionId: string) => Id<UserInfo<TIO, TPresence>> | null;
@@ -211,7 +212,7 @@ declare class PluvRoom<TIO extends IOLike, TPresence extends JsonObject = {}, TS
211
212
  subscribe: <TSubject extends keyof StateNotifierSubjects<TIO, TPresence>>(name: TSubject, callback: SubscriptionCallback<TIO, TPresence, TSubject>) => (() => void);
212
213
  transact: (fn: (storage: TStorage) => void, origin?: string) => void;
213
214
  undo: () => void;
214
- updateMyPresence: (presence: Partial<TPresence>) => void;
215
+ updateMyPresence: (presence: UpdateMyPresenceAction<TPresence>) => void;
215
216
  private _addToStorageStore;
216
217
  private _applyStorageStore;
217
218
  private _attachWindowListeners;
@@ -280,6 +281,6 @@ declare class PluvClient<TIO extends IOLike = IOLike> {
280
281
  private _logDebug;
281
282
  }
282
283
 
283
- declare const createClient: <TIO extends IOLike<_pluv_types.IOAuthorize<any, any, any>, {}, {}, {}, {}> = IOLike<_pluv_types.IOAuthorize<any, any, any>, {}, {}, {}, {}>>(options: PluvClientOptions<TIO>) => PluvClient<TIO>;
284
+ declare const createClient: <TIO extends IOLike<_pluv_types.IOAuthorize<any, any, any>, {}> = IOLike<_pluv_types.IOAuthorize<any, any, any>, {}>>(options: PluvClientOptions<TIO>) => PluvClient<TIO>;
284
285
 
285
286
  export { AbstractRoom, AbstractStorageStore, ConnectionState, MockedRoom, type MockedRoomConfig, type MockedRoomEvents, PluvClient, type PluvClientOptions, PluvRoom, type PluvRoomAddon, type PluvRoomAddonInput, type PluvRoomAddonResult, type PluvRoomDebug, type UserInfo, type WebSocketConnection, type WebSocketState, createClient };
package/dist/index.d.ts CHANGED
@@ -18,6 +18,12 @@ declare enum ConnectionState {
18
18
  Unavailable = "Unavailable",
19
19
  Untouched = "Untouched"
20
20
  }
21
+ type UpdateMyPresenceAction<TPresence extends JsonObject> = Partial<TPresence> | ((oldPresence: TPresence | null) => Partial<TPresence>);
22
+ interface UserInfo<TIO extends IOLike, TPresence extends JsonObject = {}> {
23
+ connectionId: string;
24
+ presence: TPresence;
25
+ user: Id<InferIOAuthorizeUser<InferIOAuthorize<TIO>>>;
26
+ }
21
27
  interface WebSocketConnection {
22
28
  count: number;
23
29
  id: string | null;
@@ -28,11 +34,6 @@ interface WebSocketState<TIO extends IOLike> {
28
34
  connection: WebSocketConnection;
29
35
  webSocket: WebSocket | null;
30
36
  }
31
- interface UserInfo<TIO extends IOLike, TPresence extends JsonObject = {}> {
32
- connectionId: string;
33
- presence: TPresence;
34
- user: Id<InferIOAuthorizeUser<InferIOAuthorize<TIO>>>;
35
- }
36
37
 
37
38
  type OtherNotifierSubscriptionCallback<TIO extends IOLike> = (value: Id<UserInfo<TIO>> | null) => void;
38
39
 
@@ -70,7 +71,7 @@ declare abstract class AbstractRoom<TIO extends IOLike, TPresence extends JsonOb
70
71
  abstract subscribe<TSubject extends keyof StateNotifierSubjects<TIO, TPresence>>(name: TSubject, callback: SubscriptionCallback<TIO, TPresence, TSubject>): () => void;
71
72
  abstract transact(fn: (storage: TStorage) => void, origin?: string): void;
72
73
  abstract undo(): void;
73
- abstract updateMyPresence(presence: Partial<TPresence>): void;
74
+ abstract updateMyPresence(presence: UpdateMyPresenceAction<TPresence>): void;
74
75
  }
75
76
 
76
77
  declare abstract class AbstractStorageStore {
@@ -116,7 +117,7 @@ declare class MockedRoom<TIO extends IOLike, TPresence extends JsonObject = {},
116
117
  canRedo: () => boolean;
117
118
  canUndo: () => boolean;
118
119
  event: <TEvent extends keyof InferIOOutput<TIO>>(event: TEvent, callback: EventNotifierSubscriptionCallback<TIO, TEvent>) => (() => void);
119
- getConnection(): WebSocketConnection;
120
+ getConnection: () => WebSocketConnection;
120
121
  getDoc(): AbstractCrdtDoc<TStorage>;
121
122
  getMyPresence: () => TPresence;
122
123
  getMyself: () => Id<UserInfo<TIO, TPresence>> | null;
@@ -130,7 +131,7 @@ declare class MockedRoom<TIO extends IOLike, TPresence extends JsonObject = {},
130
131
  subscribe: <TSubject extends keyof StateNotifierSubjects<TIO, TPresence>>(name: TSubject, callback: SubscriptionCallback<TIO, TPresence, TSubject>) => (() => void);
131
132
  transact: (fn: (storage: TStorage) => void, origin?: string) => void;
132
133
  undo: () => void;
133
- updateMyPresence: (presence: Partial<TPresence>) => void;
134
+ updateMyPresence: (presence: UpdateMyPresenceAction<TPresence>) => void;
134
135
  private _observeCrdt;
135
136
  }
136
137
 
@@ -191,14 +192,14 @@ declare class PluvRoom<TIO extends IOLike, TPresence extends JsonObject = {}, TS
191
192
  constructor(room: string, options: RoomConfig<TIO, TPresence, TStorage>);
192
193
  get storageLoaded(): boolean;
193
194
  get webSocket(): WebSocket | null;
194
- broadcast<TEvent extends keyof InferIOInput<TIO>>(event: TEvent, data: Id<InferIOInput<TIO>[TEvent]>): void;
195
+ broadcast: (<TEvent extends keyof InferIOInput<TIO>>(event: TEvent, data: Id<InferIOInput<TIO>[TEvent]>) => void) & { [event in keyof InferIOInput<TIO>]: (data: Id<InferIOInput<TIO>[event]>) => void; };
195
196
  canRedo: () => boolean;
196
197
  canUndo: () => boolean;
197
198
  connect(): Promise<void>;
198
199
  disconnect(): Promise<void>;
199
- event: <TEvent extends keyof InferIOOutput<TIO>>(event: TEvent, callback: EventNotifierSubscriptionCallback<TIO, TEvent>) => (() => void);
200
- getConnection(): WebSocketConnection;
201
- getDoc(): AbstractCrdtDoc<TStorage>;
200
+ event: (<TEvent extends keyof InferIOOutput<TIO>>(event: TEvent, callback: EventNotifierSubscriptionCallback<TIO, TEvent>) => () => void) & { [event in keyof InferIOOutput<TIO>]: (callback: EventNotifierSubscriptionCallback<TIO, event>) => () => void; };
201
+ getConnection: () => WebSocketConnection;
202
+ getDoc: () => AbstractCrdtDoc<TStorage>;
202
203
  getMyPresence: () => TPresence;
203
204
  getMyself: () => Id<UserInfo<TIO, TPresence>> | null;
204
205
  getOther: (connectionId: string) => Id<UserInfo<TIO, TPresence>> | null;
@@ -211,7 +212,7 @@ declare class PluvRoom<TIO extends IOLike, TPresence extends JsonObject = {}, TS
211
212
  subscribe: <TSubject extends keyof StateNotifierSubjects<TIO, TPresence>>(name: TSubject, callback: SubscriptionCallback<TIO, TPresence, TSubject>) => (() => void);
212
213
  transact: (fn: (storage: TStorage) => void, origin?: string) => void;
213
214
  undo: () => void;
214
- updateMyPresence: (presence: Partial<TPresence>) => void;
215
+ updateMyPresence: (presence: UpdateMyPresenceAction<TPresence>) => void;
215
216
  private _addToStorageStore;
216
217
  private _applyStorageStore;
217
218
  private _attachWindowListeners;
@@ -280,6 +281,6 @@ declare class PluvClient<TIO extends IOLike = IOLike> {
280
281
  private _logDebug;
281
282
  }
282
283
 
283
- declare const createClient: <TIO extends IOLike<_pluv_types.IOAuthorize<any, any, any>, {}, {}, {}, {}> = IOLike<_pluv_types.IOAuthorize<any, any, any>, {}, {}, {}, {}>>(options: PluvClientOptions<TIO>) => PluvClient<TIO>;
284
+ declare const createClient: <TIO extends IOLike<_pluv_types.IOAuthorize<any, any, any>, {}> = IOLike<_pluv_types.IOAuthorize<any, any, any>, {}>>(options: PluvClientOptions<TIO>) => PluvClient<TIO>;
284
285
 
285
286
  export { AbstractRoom, AbstractStorageStore, ConnectionState, MockedRoom, type MockedRoomConfig, type MockedRoomEvents, PluvClient, type PluvClientOptions, PluvRoom, type PluvRoomAddon, type PluvRoomAddonInput, type PluvRoomAddonResult, type PluvRoomDebug, type UserInfo, type WebSocketConnection, type WebSocketState, createClient };