hermes-chat-react 0.1.1 → 0.1.2
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.
- package/package.json +1 -1
- package/readme.md +367 -0
package/package.json
CHANGED
package/readme.md
ADDED
|
@@ -0,0 +1,367 @@
|
|
|
1
|
+
# hermes-chat-react
|
|
2
|
+
|
|
3
|
+
> Real-time chat SDK for React — hooks, components, and typed events out of the box.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
npm install hermes-chat-react
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## What is this?
|
|
12
|
+
|
|
13
|
+
`hermes-chat-react` is the official React SDK for the **Hermes** real-time messaging engine. Drop in a fully working chat system — rooms, messages, typing indicators, presence, reactions, file uploads, read receipts — without building any of it yourself.
|
|
14
|
+
|
|
15
|
+
Built on **Socket.IO**, typed end-to-end with **TypeScript**, and designed to be styled however you want.
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Quick Start
|
|
20
|
+
|
|
21
|
+
```tsx
|
|
22
|
+
import { HermesClient } from "hermes-chat-react";
|
|
23
|
+
import {
|
|
24
|
+
useMessages,
|
|
25
|
+
useRooms,
|
|
26
|
+
ChatInput,
|
|
27
|
+
MessageList,
|
|
28
|
+
} from "hermes-chat-react/react";
|
|
29
|
+
|
|
30
|
+
// 1. Create and connect a client
|
|
31
|
+
const client = new HermesClient({
|
|
32
|
+
endpoint: "https://your-hermes-server.com",
|
|
33
|
+
apiKey: "YOUR_API_KEY",
|
|
34
|
+
secret: "YOUR_SECRET",
|
|
35
|
+
userId: "user_123",
|
|
36
|
+
displayName: "Jane Doe",
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
await client.connect();
|
|
40
|
+
|
|
41
|
+
// 2. Use hooks in your components
|
|
42
|
+
function Chat() {
|
|
43
|
+
const { rooms } = useRooms(client);
|
|
44
|
+
const { messages, sendMessage } = useMessages(client, rooms[0]?._id);
|
|
45
|
+
|
|
46
|
+
return (
|
|
47
|
+
<>
|
|
48
|
+
<MessageList messages={messages} currentUser={client.currentUser!} />
|
|
49
|
+
<ChatInput
|
|
50
|
+
onSendText={(text) => sendMessage({ type: "text", text })}
|
|
51
|
+
onSendFile={() => {}}
|
|
52
|
+
/>
|
|
53
|
+
</>
|
|
54
|
+
);
|
|
55
|
+
}
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
---
|
|
59
|
+
|
|
60
|
+
## Two Ways to Authenticate
|
|
61
|
+
|
|
62
|
+
**Option A — API Key + Secret** _(server-to-server auth, recommended for production)_
|
|
63
|
+
|
|
64
|
+
```ts
|
|
65
|
+
const client = new HermesClient({
|
|
66
|
+
endpoint: "https://your-hermes-server.com",
|
|
67
|
+
apiKey: "YOUR_API_KEY",
|
|
68
|
+
secret: "YOUR_SECRET",
|
|
69
|
+
userId: "user_123",
|
|
70
|
+
displayName: "Jane Doe",
|
|
71
|
+
avatar: "https://...", // optional
|
|
72
|
+
email: "jane@example.com", // optional
|
|
73
|
+
});
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
**Option B — Pre-issued Token** _(exchange credentials yourself, pass the token)_
|
|
77
|
+
|
|
78
|
+
```ts
|
|
79
|
+
const client = new HermesClient({
|
|
80
|
+
endpoint: "https://your-hermes-server.com",
|
|
81
|
+
token: "eyJhbGci...", // JWT from your auth flow
|
|
82
|
+
});
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## Hooks
|
|
88
|
+
|
|
89
|
+
All hooks take a connected `HermesClient` instance.
|
|
90
|
+
|
|
91
|
+
### `useRooms(client)`
|
|
92
|
+
|
|
93
|
+
Manage rooms — list, create direct messages, create groups.
|
|
94
|
+
|
|
95
|
+
```ts
|
|
96
|
+
const {
|
|
97
|
+
rooms, // Room[]
|
|
98
|
+
loading, // boolean
|
|
99
|
+
createDirect, // (input: CreateDirectRoomInput) => Promise<Room>
|
|
100
|
+
createGroup, // (input: CreateGroupRoomInput) => Promise<Room>
|
|
101
|
+
} = useRooms(client);
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### `useMessages(client, roomId)`
|
|
105
|
+
|
|
106
|
+
Send, edit, delete, and paginate messages in a room.
|
|
107
|
+
|
|
108
|
+
```ts
|
|
109
|
+
const {
|
|
110
|
+
messages, // Message[]
|
|
111
|
+
loading, // boolean
|
|
112
|
+
loadingMore, // boolean
|
|
113
|
+
hasMore, // boolean
|
|
114
|
+
loadMore, // () => void
|
|
115
|
+
sendMessage, // (input: SendMessageInput) => Promise<Message>
|
|
116
|
+
editMessage, // (messageId, roomId, text) => Promise<Message>
|
|
117
|
+
deleteMessage, // (messageId, roomId) => Promise<void>
|
|
118
|
+
addReaction, // (messageId, roomId, emoji) => Promise<void>
|
|
119
|
+
} = useMessages(client, roomId);
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### `useTyping(client, roomId)`
|
|
123
|
+
|
|
124
|
+
Typing indicators — start, stop, and listen for others.
|
|
125
|
+
|
|
126
|
+
```ts
|
|
127
|
+
const {
|
|
128
|
+
typingText, // string — e.g. "Jane is typing..."
|
|
129
|
+
startTyping, // () => void
|
|
130
|
+
stopTyping, // () => void
|
|
131
|
+
} = useTyping(client, roomId);
|
|
132
|
+
```
|
|
133
|
+
|
|
134
|
+
### `usePresence(client)`
|
|
135
|
+
|
|
136
|
+
Track who's online in real time.
|
|
137
|
+
|
|
138
|
+
```ts
|
|
139
|
+
const { isOnline } = usePresence(client);
|
|
140
|
+
|
|
141
|
+
isOnline("user_123"); // boolean
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
### `useReadReceipts(client, roomId)`
|
|
145
|
+
|
|
146
|
+
Mark messages as seen and track who has read what.
|
|
147
|
+
|
|
148
|
+
```ts
|
|
149
|
+
const {
|
|
150
|
+
markSeen, // (lastMessageId: string) => Promise<void>
|
|
151
|
+
seenBy, // (messageId: string) => string[]
|
|
152
|
+
receipts, // Map<string, Set<string>>
|
|
153
|
+
} = useReadReceipts(client, roomId);
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### `useUpload(client)`
|
|
157
|
+
|
|
158
|
+
Upload files and send them as messages.
|
|
159
|
+
|
|
160
|
+
```ts
|
|
161
|
+
const {
|
|
162
|
+
sendFile, // (roomId, file, replyTo?) => Promise<void>
|
|
163
|
+
uploading, // boolean
|
|
164
|
+
} = useUpload(client);
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## Components
|
|
170
|
+
|
|
171
|
+
Pre-built components you can drop in and style with CSS.
|
|
172
|
+
|
|
173
|
+
### `<MessageList />`
|
|
174
|
+
|
|
175
|
+
```tsx
|
|
176
|
+
<MessageList
|
|
177
|
+
messages={messages}
|
|
178
|
+
currentUser={currentUser}
|
|
179
|
+
loading={loading}
|
|
180
|
+
loadingMore={loadingMore}
|
|
181
|
+
hasMore={hasMore}
|
|
182
|
+
onLoadMore={loadMore}
|
|
183
|
+
onEdit={editMessage}
|
|
184
|
+
onDelete={deleteMessage}
|
|
185
|
+
onReact={addReaction}
|
|
186
|
+
onReply={(msg) => setReplyingTo(msg)}
|
|
187
|
+
autoScroll
|
|
188
|
+
/>
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### `<ChatInput />`
|
|
192
|
+
|
|
193
|
+
```tsx
|
|
194
|
+
<ChatInput
|
|
195
|
+
onSendText={async (text) => sendMessage({ type: "text", text })}
|
|
196
|
+
onSendFile={async (file) => sendFile(roomId, file)}
|
|
197
|
+
onTypingStart={startTyping}
|
|
198
|
+
onTypingStop={stopTyping}
|
|
199
|
+
replyingTo={replyingTo}
|
|
200
|
+
onCancelReply={() => setReplyingTo(null)}
|
|
201
|
+
placeholder="Type a message..."
|
|
202
|
+
/>
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### `<TypingIndicator />`
|
|
206
|
+
|
|
207
|
+
```tsx
|
|
208
|
+
<TypingIndicator typingText={typingText} />
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### `<RoomList />` · `<OnlineBadge />` · `<ReactionPicker />` · `<MediaMessage />`
|
|
212
|
+
|
|
213
|
+
Additional utility components — import from `hermes-chat-react/react`.
|
|
214
|
+
|
|
215
|
+
---
|
|
216
|
+
|
|
217
|
+
## Styling
|
|
218
|
+
|
|
219
|
+
All components expose BEM class names so you can override any style.
|
|
220
|
+
|
|
221
|
+
```css
|
|
222
|
+
/* Message bubbles */
|
|
223
|
+
.hermes-message--own .hermes-message__bubble {
|
|
224
|
+
background: #your-color;
|
|
225
|
+
}
|
|
226
|
+
.hermes-message--other .hermes-message__bubble {
|
|
227
|
+
background: #your-color;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/* Input area */
|
|
231
|
+
.hermes-chat-input textarea {
|
|
232
|
+
border-radius: 12px;
|
|
233
|
+
}
|
|
234
|
+
.hermes-chat-input button {
|
|
235
|
+
background: #your-brand-color;
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/* Typing indicator */
|
|
239
|
+
.hermes-typing-indicator {
|
|
240
|
+
color: #your-color;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/* Load more button */
|
|
244
|
+
.hermes-load-more {
|
|
245
|
+
border-radius: 8px;
|
|
246
|
+
}
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
---
|
|
250
|
+
|
|
251
|
+
## Events
|
|
252
|
+
|
|
253
|
+
Listen to real-time events directly on the client.
|
|
254
|
+
|
|
255
|
+
```ts
|
|
256
|
+
client.on("message:receive", (message) => console.log("New message", message));
|
|
257
|
+
client.on("user:online", (event) =>
|
|
258
|
+
console.log(event.displayName, "came online"),
|
|
259
|
+
);
|
|
260
|
+
client.on("user:offline", (event) => console.log(event.userId, "went offline"));
|
|
261
|
+
client.on("typing:started", (event) =>
|
|
262
|
+
console.log(event.displayName, "is typing"),
|
|
263
|
+
);
|
|
264
|
+
client.on("reaction:updated", (event) => console.log("Reaction update", event));
|
|
265
|
+
client.on("disconnected", (reason) => console.log("Lost connection:", reason));
|
|
266
|
+
client.on("error", (err) => console.error(err));
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
Full event reference:
|
|
270
|
+
|
|
271
|
+
| Event | Payload |
|
|
272
|
+
| -------------------- | ----------------------- |
|
|
273
|
+
| `connected` | — |
|
|
274
|
+
| `disconnected` | `reason: string` |
|
|
275
|
+
| `error` | `Error` |
|
|
276
|
+
| `message:receive` | `Message` |
|
|
277
|
+
| `message:edited` | `Message` |
|
|
278
|
+
| `message:deleted` | `{ messageId, roomId }` |
|
|
279
|
+
| `room:created` | `Room` |
|
|
280
|
+
| `room:deleted` | `{ roomId }` |
|
|
281
|
+
| `room:member:joined` | `{ roomId, userId }` |
|
|
282
|
+
| `room:member:left` | `{ roomId, userId }` |
|
|
283
|
+
| `user:online` | `PresenceEvent` |
|
|
284
|
+
| `user:offline` | `LastSeenEvent` |
|
|
285
|
+
| `typing:started` | `TypingEvent` |
|
|
286
|
+
| `typing:stopped` | `TypingEvent` |
|
|
287
|
+
| `receipt:updated` | `ReceiptEvent` |
|
|
288
|
+
| `reaction:updated` | `ReactionEvent` |
|
|
289
|
+
|
|
290
|
+
---
|
|
291
|
+
|
|
292
|
+
## TypeScript
|
|
293
|
+
|
|
294
|
+
Everything is typed. Import types directly:
|
|
295
|
+
|
|
296
|
+
```ts
|
|
297
|
+
import type {
|
|
298
|
+
HermesConfig,
|
|
299
|
+
HermesUser,
|
|
300
|
+
Room,
|
|
301
|
+
Message,
|
|
302
|
+
SendMessageInput,
|
|
303
|
+
MessageType,
|
|
304
|
+
ConnectionStatus,
|
|
305
|
+
PresenceEvent,
|
|
306
|
+
TypingEvent,
|
|
307
|
+
ReceiptEvent,
|
|
308
|
+
ReactionEvent,
|
|
309
|
+
UploadResult,
|
|
310
|
+
} from "hermes-chat-react";
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
---
|
|
314
|
+
|
|
315
|
+
## Client API
|
|
316
|
+
|
|
317
|
+
```ts
|
|
318
|
+
// Connection
|
|
319
|
+
client.connect() // Promise<HermesUser>
|
|
320
|
+
client.disconnect() // void
|
|
321
|
+
client.isConnected // boolean
|
|
322
|
+
client.currentUser // HermesUser | null
|
|
323
|
+
client.status // ConnectionStatus
|
|
324
|
+
|
|
325
|
+
// Messaging
|
|
326
|
+
client.sendMessage(input) // Promise<Message>
|
|
327
|
+
client.editMessage(messageId, roomId, text) // Promise<Message>
|
|
328
|
+
client.deleteMessage(messageId, roomId) // Promise<void>
|
|
329
|
+
client.getHistory(roomId, before?, limit?) // Promise<MessageHistoryResult>
|
|
330
|
+
|
|
331
|
+
// Rooms
|
|
332
|
+
client.getRooms() // Promise<Room[]>
|
|
333
|
+
client.createDirectRoom({ targetUserId }) // Promise<Room>
|
|
334
|
+
client.createGroupRoom({ name, memberIds }) // Promise<Room>
|
|
335
|
+
client.deleteRoom(roomId) // Promise<void>
|
|
336
|
+
client.addMember(roomId, userId) // Promise<void>
|
|
337
|
+
client.removeMember(roomId, userId) // Promise<void>
|
|
338
|
+
|
|
339
|
+
// Presence & Typing
|
|
340
|
+
client.pingPresence(roomId) // void
|
|
341
|
+
client.startTyping(roomId) // void
|
|
342
|
+
client.stopTyping(roomId) // void
|
|
343
|
+
|
|
344
|
+
// Reactions & Receipts
|
|
345
|
+
client.addReaction(messageId, roomId, emoji) // Promise<void>
|
|
346
|
+
client.markSeen(roomId, lastMessageId) // Promise<void>
|
|
347
|
+
|
|
348
|
+
// File Upload
|
|
349
|
+
client.uploadFile(file) // Promise<UploadResult>
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
---
|
|
353
|
+
|
|
354
|
+
## Peer Dependencies
|
|
355
|
+
|
|
356
|
+
```json
|
|
357
|
+
{
|
|
358
|
+
"react": ">=17.0.0",
|
|
359
|
+
"react-dom": ">=17.0.0"
|
|
360
|
+
}
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
---
|
|
364
|
+
|
|
365
|
+
## License
|
|
366
|
+
|
|
367
|
+
MIT © Harshavardanan Moorthy
|