Skip to content

Commit 5949fd1

Browse files
committed
docs: update readme
1 parent 905f1cb commit 5949fd1

File tree

1 file changed

+124
-1
lines changed

1 file changed

+124
-1
lines changed

README.md

Lines changed: 124 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ A Nuxt module aimed to simplify the use of WebSockets.
1313

1414
## Features
1515

16-
- `useWS` ([demo](https://reactive-ws.s94.dev/)): A WebSocket implementation with built-in shared state management, channel subscriptions, and type safety.
16+
- `useWS` ([demo](https://reactive-ws.s94.dev/)): A WebSocket implementation with built-in shared state management, topic subscriptions, and type safety.
1717
- `defineReactiveWSHandler`: wraps Nitro's `defineWebSocketHandler` to provide additional configuration, hooks and automatic topic subscription.
1818

1919
## Quick Setup
@@ -36,6 +36,129 @@ export default defineNuxtConfig({
3636
})
3737
```
3838

39+
## Real-time Remote State Management
40+
41+
A WebSocket implementation with built-in shared state management, topic subscriptions, and type safety.
42+
43+
- 🔄 Automatic reconnection
44+
- 📦 Built-in shared state management per-topic
45+
- 🤖 Build-in validation with [Standard Schema](https://github.com/standard-schema/standard-schema)
46+
- 🔐 Type-safe messages and topics
47+
- 📢 Hooking system to trigger messages globaly
48+
- ⛓️ Integrates easily with other Nuxt modules
49+
50+
Take in example the following setup:
51+
52+
```ts
53+
// nuxt.config.ts
54+
export default defineNuxtConfig({
55+
modules: ['nuxt-ws'],
56+
ws: {
57+
route: '/_ws', // WebSocket endpoint to auto-connect
58+
topics: {
59+
defaults: ['session'], // Auto-subscribed topics
60+
}
61+
}
62+
})
63+
```
64+
65+
Client-Side (`pages/chat.client.vue`):
66+
```vue
67+
<template>
68+
<div>
69+
<div v-if="status === 'OPEN'">
70+
Connected, Users: {{ states['session'].users }}
71+
</div>
72+
<div v-else>
73+
Disconnected
74+
</div>
75+
<div v-for="({ user, text }, key) in states['chat']" :key>
76+
{{ user }}: {{ text }}
77+
</div>
78+
<input v-model="textRef" @keyup.enter="sendMessage()">
79+
</div>
80+
</template>
81+
82+
<script setup lang="ts">
83+
const textRef = ref('')
84+
const { states, status, send } = useWS<{
85+
chat: {
86+
user?: string
87+
text: string
88+
}[]
89+
session: {
90+
users: number
91+
}
92+
}>(['chat'])
93+
94+
function sendMessage() {
95+
send('publish', 'chat', {
96+
text: textRef.value,
97+
})
98+
textRef.value = ''
99+
}
100+
</script>
101+
```
102+
103+
Server-Side (`server/routes/_ws.ts`):
104+
```ts
105+
import * as v from 'valibot'
106+
107+
export default defineReactiveWSHandler({
108+
async open(peer) {
109+
// Update peer with 'chat' data from storage
110+
const chat = await useStorage('ws').getItem('chat')
111+
if (chat)
112+
peer.send(JSON.stringify({
113+
topic: 'chat',
114+
payload: chat,
115+
}), { compress: true })
116+
117+
// Update everyone's session metadata
118+
const payload = JSON.stringify({ topic: 'session', payload: { users: peer.peers.size } })
119+
peer.send(payload, { compress: true })
120+
peer.publish('session', payload, { compress: true })
121+
},
122+
123+
async message(peer, message) {
124+
// Validate the incoming chat message
125+
const parsedMessage = await wsValidateMessage( // built-in validation util
126+
v.object({
127+
type: v.literal('publish'),
128+
topic: v.literal('chat'),
129+
payload: v.object({ text: v.string() }),
130+
}),
131+
message,
132+
)
133+
134+
// Update chat data in storage
135+
const mem = useStorage('ws')
136+
const { topic, payload } = parsedMessage
137+
const _chat = await mem.getItem<Array<{ user: string, text: string }>>('chat') || []
138+
const newChat = [..._chat, { ...payload, user: peer.id }]
139+
await mem.setItem(topic, newChat)
140+
141+
// Broadcast the new chat message to everyone
142+
peer.send(JSON.stringify({ topic, payload: newChat }), { compress: true })
143+
peer.publish(topic, JSON.stringify({ topic, payload: newChat }), { compress: true })
144+
},
145+
146+
close(peer) {
147+
// Update everyone's session metadata
148+
peer.publish(
149+
'session',
150+
JSON.stringify({
151+
topic: 'session',
152+
payload: {
153+
users: peer.peers.size,
154+
},
155+
}),
156+
{ compress: true },
157+
)
158+
},
159+
})
160+
```
161+
39162
## Contribution
40163

41164
<details>

0 commit comments

Comments
 (0)