Skip to content

Commit

Permalink
feat(react): event proxy (#621)
Browse files Browse the repository at this point in the history
  • Loading branch information
pluvrt authored May 22, 2024
1 parent df1342c commit e587c18
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 5 deletions.
32 changes: 32 additions & 0 deletions .changeset/purple-gorillas-raise.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
---
"@pluv/react": patch
---

Added event proxy as a new way to listen to events.

```tsx
// backend

const router = io.router({
SEND_MESSAGE: io.procedure
.input(z.object({ message: z.string() }))
.broadcast(({ message }) => ({ RECEIVE_MESSAGE: { message } })),
});

// frontend
const pluv = createRoomBundle(/* ... */);

// Both of the examples below are equivalent.

pluv.useEvent("RECEIVE_MESSAGE", ({ data }) => {
const { message } = data;

console.log(message);
});

pluv.event.RECEIVE_MESSAGE.useEvent(({ data }) => {
const { message } = data;

console.log(message);
});
```
2 changes: 1 addition & 1 deletion .changeset/smooth-kings-swim.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"@pluv/client": patch
---

Added event proxy as a new way to invoke event procedures.
Added event proxy as a new way to listen to events.

```ts
// backend
Expand Down
27 changes: 27 additions & 0 deletions packages/react/src/createRoomBundle.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,12 @@ export type UpdateMyPresenceAction<TPresence extends JsonObject> =
| Partial<TPresence>
| ((oldPresence: TPresence | null) => Partial<TPresence>);

export type EventProxy<TIO extends IOLike> = {
[event in keyof InferIOOutput<TIO>]: {
useEvent: (callback: (data: Id<IOEventMessage<TIO, event>>) => void) => void;
};
};

export interface CreateRoomBundle<
TIO extends IOLike,
TPresence extends JsonObject,
Expand All @@ -70,6 +76,9 @@ export interface CreateRoomBundle<
MockedRoomProvider: FC<MockedRoomProviderProps<TIO, TPresence, TStorage>>;
PluvRoomProvider: FC<PluvRoomProviderProps<TIO, TPresence, TStorage>>;

// proxies
event: EventProxy<TIO>;

// hooks
useBroadcast: () => <TEvent extends keyof InferIOInput<TIO>>(
event: TEvent,
Expand Down Expand Up @@ -290,6 +299,21 @@ export const createRoomBundle = <
}, [callback, room, type]);
};

const event = new Proxy(
{},
{
get(fn, prop) {
const useProxyEvent = (
callback: (data: Id<IOEventMessage<TIO, keyof InferIOOutput<TIO>>>) => void,
): void => {
return useEvent(prop as keyof InferIOOutput<TIO>, callback);
};

return { useEvent: useProxyEvent };
},
},
) as EventProxy<TIO>;

const useMyPresence = <T extends unknown = TPresence>(
selector = identity as (myPresence: TPresence) => T,
options?: SubscriptionHookOptions<Id<T> | null>,
Expand Down Expand Up @@ -475,6 +499,9 @@ export const createRoomBundle = <
MockedRoomProvider,
PluvRoomProvider,

// proxies
event,

// hooks
useBroadcast,
useCanRedo,
Expand Down
6 changes: 3 additions & 3 deletions tests/e2e/src/demo/ChatRoom.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { FC, useCallback, useState } from "react";
import { useBroadcast, useEvent } from "./pluv";
import { pluv } from "./pluv";

export const ChatRoom: FC<Record<string, never>> = () => {
const [messages, setMessages] = useState<readonly string[]>([]);
const broadcast = useBroadcast();
const broadcast = pluv.useBroadcast();

useEvent("RECEIVE_MESSAGE", ({ data }) => {
pluv.event.RECEIVE_MESSAGE.useEvent(({ data }) => {
setMessages((oldMessages) => [...oldMessages, data.message]);
});

Expand Down
2 changes: 1 addition & 1 deletion tests/e2e/src/demo/pluv.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@ const client = createClient<typeof ioServer>({

export const { createRoomBundle } = createBundle(client);

export const { useBroadcast, useEvent, useMyself } = createRoomBundle({
export const pluv = createRoomBundle({
initialStorage: yjs.doc(),
});

0 comments on commit e587c18

Please sign in to comment.