dialogue-ts 0.0.1

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/README.md ADDED
@@ -0,0 +1,446 @@
1
+ # Dialogue Ts
2
+
3
+ An event-based realtime communication library based on Socket.IO, Hono, and Bun.
4
+
5
+ Dialogue is basically asking how do we scale to different real time use cases using same mental model and api.
6
+
7
+ ## 📚 Documentation
8
+
9
+ **[📖 View Full Documentation →](https://hussseinkizz.github.io/dialogue/)**
10
+
11
+ Complete guides, API references, and examples available at: **https://hussseinkizz.github.io/dialogue/**
12
+
13
+ ## Prerequisites
14
+
15
+ - [Bun](https://bun.sh/) - Fast all-in-one JavaScript runtime (required for server)
16
+ - [Zod](https://zod.dev/) - TypeScript-first schema validation
17
+
18
+ ## Installation
19
+
20
+ ```bash
21
+ bun add dialogue-ts zod
22
+ ```
23
+
24
+ ## Key Concepts
25
+
26
+ ### Events
27
+
28
+ Events are the core building blocks. Each event has a name and an optional Zod schema for validation:
29
+
30
+ ```typescript
31
+ import { defineEvent } from "dialogue-ts";
32
+ import { z } from "zod";
33
+
34
+ const Message = defineEvent("message", {
35
+ schema: z.object({
36
+ text: z.string().min(1).max(1000),
37
+ senderId: z.string(),
38
+ }),
39
+ });
40
+
41
+ const Typing = defineEvent("typing", {
42
+ schema: z.object({ isTyping: z.boolean() }),
43
+ });
44
+ ```
45
+
46
+ ### Rooms
47
+
48
+ Rooms are channels where events are broadcast. Clients join rooms to send and receive events:
49
+
50
+ ```typescript
51
+ const dialogue = createDialogue({
52
+ port: 3000,
53
+ rooms: {
54
+ chat: {
55
+ name: "Chat Room",
56
+ events: [Message, Typing],
57
+ defaultSubscriptions: ["message"],
58
+ maxSize: 100, // Optional capacity limit
59
+ },
60
+ },
61
+ });
62
+ ```
63
+
64
+ ### Subscriptions
65
+
66
+ Clients can subscribe to specific event types within a room. Only subscribed events are received, reducing unnecessary traffic.
67
+
68
+ ## Quick Start: Chat Example
69
+
70
+ ### Server (Bun)
71
+
72
+ ```typescript
73
+ // server.ts
74
+ import { createDialogue, defineEvent } from "dialogue-ts";
75
+ import { z } from "zod";
76
+
77
+ // Define events
78
+ const Message = defineEvent("message", {
79
+ schema: z.object({
80
+ text: z.string().min(1),
81
+ username: z.string(),
82
+ }),
83
+ });
84
+
85
+ const UserJoined = defineEvent("user-joined", {
86
+ schema: z.object({ username: z.string() }),
87
+ });
88
+
89
+ // Create dialogue instance
90
+ const dialogue = createDialogue({
91
+ port: 3000,
92
+ rooms: {
93
+ general: {
94
+ name: "General Chat",
95
+ events: [Message, UserJoined],
96
+ defaultSubscriptions: ["message", "user-joined"],
97
+ },
98
+ },
99
+ hooks: {
100
+ clients: {
101
+ onConnected: (client) => {
102
+ console.log(`Client connected: ${client.userId}`);
103
+ client.join("general");
104
+
105
+ // Notify others
106
+ dialogue.trigger("general", UserJoined, {
107
+ username: client.userId,
108
+ });
109
+ },
110
+ onDisconnected: (client) => {
111
+ console.log(`Client disconnected: ${client.userId}`);
112
+ },
113
+ },
114
+ },
115
+ });
116
+
117
+ // Start server
118
+ await dialogue.start();
119
+ console.log("Chat server running on http://localhost:3000");
120
+ ```
121
+
122
+ Run with:
123
+
124
+ ```bash
125
+ bun run server.ts
126
+ ```
127
+
128
+ ### Client (Browser/Node)
129
+
130
+ ```typescript
131
+ // client.ts
132
+ import { createDialogueClient } from "dialogue-ts/client";
133
+
134
+ const client = createDialogueClient({
135
+ url: "ws://localhost:3000",
136
+ auth: { userId: "alice" },
137
+ });
138
+
139
+ // Connect and join room
140
+ await client.connect();
141
+ const chat = await client.join("general");
142
+
143
+ // Listen for messages
144
+ chat.on("message", (msg) => {
145
+ console.log(`${msg.data.username}: ${msg.data.text}`);
146
+ });
147
+
148
+ // Listen for users joining
149
+ chat.on("user-joined", (msg) => {
150
+ console.log(`${msg.data.username} joined the chat`);
151
+ });
152
+
153
+ // Send a message
154
+ chat.trigger("message", {
155
+ text: "Hello everyone!",
156
+ username: "alice",
157
+ });
158
+ ```
159
+
160
+ ## Server API
161
+
162
+ ### createDialogue(config)
163
+
164
+ Creates a Dialogue server instance.
165
+
166
+ ```typescript
167
+ const dialogue = createDialogue({
168
+ port: 3000,
169
+ rooms: { /* room configs */ },
170
+ hooks: {
171
+ clients: {
172
+ onConnected: (client) => { /* handle connection */ },
173
+ onDisconnected: (client) => { /* handle disconnection */ },
174
+ },
175
+ },
176
+ logger: createDefaultLogger(), // Optional custom logger
177
+ });
178
+ ```
179
+
180
+ ### dialogue.start()
181
+
182
+ Starts the server. Returns a promise.
183
+
184
+ ### dialogue.trigger(roomId, event, data, from?)
185
+
186
+ Triggers an event from the server to all subscribers in a room.
187
+
188
+ ```typescript
189
+ dialogue.trigger("general", Message, { text: "Hello!", username: "system" });
190
+ ```
191
+
192
+ ### dialogue.getRoom(roomId)
193
+
194
+ Gets a room instance for direct manipulation.
195
+
196
+ ### dialogue.createRoom(id, config, createdById?)
197
+
198
+ Creates a new room at runtime.
199
+
200
+ ```typescript
201
+ const room = dialogue.createRoom("project-123", {
202
+ name: "Project Discussion",
203
+ events: [Message, UserJoined],
204
+ defaultSubscriptions: ["message"],
205
+ maxSize: 50,
206
+ }, "user-456");
207
+ ```
208
+
209
+ ### dialogue.deleteRoom(id)
210
+
211
+ Deletes a room. Returns `true` if successful.
212
+
213
+ ```typescript
214
+ dialogue.deleteRoom("project-123");
215
+ ```
216
+
217
+ ### User Management
218
+
219
+ ```typescript
220
+ // Get all connections for a user
221
+ const clients = dialogue.getClients("user-123");
222
+
223
+ // Get rooms a user is in
224
+ const rooms = dialogue.getClientRooms("user-123");
225
+
226
+ // Check if user is in a room
227
+ if (dialogue.isInRoom("user-123", "vip-room")) { ... }
228
+
229
+ // Remove user from all rooms (with notifications)
230
+ dialogue.getClientRooms("user-123").leaveAll((roomId) => {
231
+ dialogue.trigger(roomId, UserLeft, { username: "user-123" });
232
+ });
233
+ ```
234
+
235
+ ## Client API
236
+
237
+ ### DialogueClient
238
+
239
+ ```typescript
240
+ import { createDialogueClient } from "dialogue-ts/client";
241
+
242
+ const client = createDialogueClient({
243
+ url: "ws://localhost:3000",
244
+ auth: { userId: "user-123", token: "jwt-token" },
245
+ });
246
+ ```
247
+
248
+ ### client.connect() / client.disconnect()
249
+
250
+ Connect to or disconnect from the server.
251
+
252
+ ### client.join(roomId)
253
+
254
+ Joins a room and returns a `RoomContext`.
255
+
256
+ ### client.createRoom(options)
257
+
258
+ Creates a new room on the server.
259
+
260
+ ```typescript
261
+ const roomInfo = await client.createRoom({
262
+ id: "tech-talk",
263
+ name: "Tech Talk",
264
+ description: "Discuss technology",
265
+ maxSize: 100,
266
+ });
267
+ ```
268
+
269
+ ### client.deleteRoom(roomId)
270
+
271
+ Deletes a room (only creator can delete).
272
+
273
+ ### client.onRoomCreated(handler) / client.onRoomDeleted(handler)
274
+
275
+ Listen for room lifecycle events.
276
+
277
+ ```typescript
278
+ client.onRoomCreated((room) => console.log("New room:", room.name));
279
+ client.onRoomDeleted((roomId) => console.log("Deleted:", roomId));
280
+ ```
281
+
282
+ ### RoomContext
283
+
284
+ ```typescript
285
+ const room = await client.join("chat");
286
+
287
+ // Listen for events
288
+ const unsubscribe = room.on("message", (msg) => {
289
+ console.log(msg.data);
290
+ });
291
+
292
+ // Send events
293
+ room.trigger("message", { text: "Hello!" });
294
+
295
+ // Subscribe/unsubscribe from event types
296
+ room.subscribe("typing");
297
+ room.unsubscribe("typing");
298
+
299
+ // Leave room
300
+ room.leave();
301
+ ```
302
+
303
+ ## Hooks
304
+
305
+ Hooks provide lifecycle callbacks for clients, rooms, and events.
306
+
307
+ ### Client Hooks
308
+
309
+ ```typescript
310
+ const dialogue = createDialogue({
311
+ rooms: { /* ... */ },
312
+ hooks: {
313
+ clients: {
314
+ onConnected: (client) => {
315
+ console.log(`${client.userId} connected`);
316
+ client.join("general");
317
+ },
318
+ onDisconnected: (client) => {
319
+ console.log(`${client.userId} disconnected`);
320
+ },
321
+ onJoined: (client, roomId) => {
322
+ dialogue.trigger(roomId, UserJoined, { username: client.userId });
323
+ },
324
+ onLeft: (client, roomId) => {
325
+ dialogue.trigger(roomId, UserLeft, { username: client.userId });
326
+ },
327
+ },
328
+ },
329
+ });
330
+ ```
331
+
332
+ ### Room Hooks
333
+
334
+ ```typescript
335
+ hooks: {
336
+ rooms: {
337
+ onCreated: (room) => {
338
+ console.log(`Room ${room.name} created`);
339
+ },
340
+ onDeleted: (roomId) => {
341
+ console.log(`Room ${roomId} deleted`);
342
+ },
343
+ },
344
+ }
345
+ ```
346
+
347
+ ### Event Hooks (for persistence)
348
+
349
+ ```typescript
350
+ hooks: {
351
+ events: {
352
+ onTriggered: (roomId, event) => {
353
+ // Called for every event
354
+ analytics.track(event.event, event.data);
355
+ },
356
+ onCleanup: async (roomId, eventName, events) => {
357
+ // Called when events are evicted from memory
358
+ await db.events.insertMany(events);
359
+ },
360
+ onLoad: async (roomId, eventName, start, end) => {
361
+ // Load historical events from database for pagination
362
+ return db.events.find({ roomId, eventName }).skip(start).limit(end - start);
363
+ },
364
+ },
365
+ }
366
+ ```
367
+
368
+ ## Event History
369
+
370
+ Store and retrieve historical events per room. Useful for chat history, activity feeds, etc.
371
+
372
+ ### Enabling History
373
+
374
+ Enable history per event type:
375
+
376
+ ```typescript
377
+ const Message = defineEvent("message", {
378
+ schema: z.object({ text: z.string(), username: z.string() }),
379
+ history: { enabled: true, limit: 100 }, // Keep last 100 messages
380
+ });
381
+ ```
382
+
383
+ ### Auto-sync on Join
384
+
385
+ Automatically send history when clients join a room:
386
+
387
+ ```typescript
388
+ const dialogue = createDialogue({
389
+ rooms: {
390
+ chat: {
391
+ name: "Chat",
392
+ events: [Message],
393
+ syncHistoryOnJoin: true, // Send all history
394
+ // syncHistoryOnJoin: 50, // Or limit to 50 events
395
+ },
396
+ },
397
+ });
398
+ ```
399
+
400
+ ### Client-side History
401
+
402
+ ```typescript
403
+ // Automatic history on join
404
+ client.onHistory((roomId, events) => {
405
+ events.forEach((event) => renderMessage(event));
406
+ });
407
+
408
+ // Manual pagination
409
+ const room = await client.join("chat");
410
+ const olderMessages = await room.getHistory("message", 50, 100); // Skip 50, get 50
411
+ ```
412
+
413
+ ### Server-side History Access
414
+
415
+ ```typescript
416
+ const room = dialogue.room("chat");
417
+ const recentMessages = await room.history("message", 0, 20); // Last 20 messages
418
+ ```
419
+
420
+ ## Documentation
421
+
422
+ For complete documentation, visit **[hussseinkizz.github.io/dialogue](https://hussseinkizz.github.io/dialogue/)**
423
+
424
+ Quick links:
425
+ - [Getting Started](https://hussseinkizz.github.io/dialogue/guide/start/getting-started) - Installation and basic setup
426
+ - [Configuration Guide](https://hussseinkizz.github.io/dialogue/guide/api/configuration/) - Detailed configuration options
427
+ - [Backend API](https://hussseinkizz.github.io/dialogue/guide/api/backend-api) - Server-side API reference
428
+ - [Client API](https://hussseinkizz.github.io/dialogue/guide/api/client-api) - Client SDK reference
429
+ - [Examples](https://hussseinkizz.github.io/dialogue/guide/examples/chat-application) - Complete use-case implementations
430
+ - [Architecture](https://hussseinkizz.github.io/dialogue/guide/others/architecture) - Internal design and patterns
431
+
432
+ ## Example App
433
+
434
+ A working chat application is included in the [`example/`](./example) folder. See the [example README](./example/README.md) for setup instructions.
435
+
436
+ ## Built With
437
+
438
+ - [Socket.IO](https://socket.io/) - Real-time bidirectional event-based communication
439
+ - [Slang Ts](https://github.com/Hussseinkizz/slang-ts) - Pattern Matching And Functional Utilities
440
+ - [Hono](https://hono.dev/) - Ultrafast web framework for the Edge
441
+ - [Bun](https://bun.sh/) - Fast all-in-one JavaScript runtime
442
+ - [Zod](https://zod.dev/) - TypeScript-first schema validation
443
+
444
+ ## License
445
+
446
+ MIT