### Quick Start: Chat Server Setup (Bun/TypeScript) Source: https://github.com/hussseinkizz/dialogue/blob/main/README.md A complete example of setting up a chat server using Dialogue Ts with Bun. It defines 'message' and 'user-joined' events, configures a 'general' room, and implements connection/disconnection hooks. ```typescript // server.ts import { createDialogue, defineEvent } from "dialogue-ts"; import { z } from "zod"; // Define events const Message = defineEvent("message", { schema: z.object({ text: z.string().min(1), username: z.string(), }), }); const UserJoined = defineEvent("user-joined", { schema: z.object({ username: z.string() }), }); // Create dialogue instance const dialogue = createDialogue({ port: 3000, rooms: { general: { name: "General Chat", events: [Message, UserJoined], defaultSubscriptions: ["message", "user-joined"], }, }, hooks: { clients: { onConnected: (client) => { console.log(`Client connected: ${client.userId}`); client.join("general"); // Notify others dialogue.trigger("general", UserJoined, { username: client.userId, }); }, onDisconnected: (client) => { console.log(`Client disconnected: ${client.userId}`); }, }, }, }); // Start server await dialogue.start(); console.log("Chat server running on http://localhost:3000"); ``` -------------------------------- ### Hybrid Room Creation Example (TypeScript) Source: https://github.com/hussseinkizz/dialogue/blob/main/web/docs/public/llms-full.txt Presents a hybrid approach combining predefined system-wide rooms with dynamically created user-specific rooms, illustrating a practical application of Dialogue's flexibility. ```typescript // Predefined: System-wide rooms const systemRooms = [ { id: 'global-chat', name: 'Chat', events: [chatEvent] }, { id: 'notifications', name: 'Notifications', events: [notifEvent] } ]; const dialogue = createDialogue({ rooms: systemRooms }); // Dynamic: User-specific rooms app.post('/games', async (c) => { const gameId = nanoid(); dialogue.createRoom({ id: `game-${gameId}`, name: 'Game Session', events: [moveEvent, scoreEvent], maxSize: 4 }); return c.json({ gameId }); }); ``` -------------------------------- ### Install Dialogue and Zod with Bun, npm, or pnpm Source: https://github.com/hussseinkizz/dialogue/blob/main/web/docs/guide/start/getting-started.md Installs the dialogue-ts and zod packages. These are the core dependencies for using Dialogue and its schema validation features. ```bash bun add dialogue-ts zod ``` ```bash npm install dialogue-ts zod ``` ```bash pnpm add dialogue-ts zod ``` -------------------------------- ### Complete Example: Dialogue Client Usage Source: https://github.com/hussseinkizz/dialogue/blob/main/web/docs/public/llms-full.txt Demonstrates the full lifecycle of using the Dialogue client, including connection, message handling, and room management. It requires the 'createDialogueClient' function and sets up event listeners for connection status and messages. ```typescript import { createDialogueClient } from "./client"; async function main() { // Create client with authentication const client = createDialogueClient({ url: "ws://localhost:3000", auth: { userId: "user-123", token: "my-jwt-token", }, }); // Set up connection handlers client.onConnect(() => { console.log("Connected as:", client.userId); }); client.onDisconnect((reason) => { console.log("Disconnected:", reason); }); client.onError((error) => { console.error("Error:", error.message); }); // Connect to server await client.connect(); // List available rooms const rooms = await client.listRooms(); console.log("Available rooms:", rooms); // Join chat room const chat = await client.join("chat"); console.log(`Joined: ${chat.roomName}`); // Listen for messages chat.on<{ text: string; senderId: string }>("message", (msg) => { console.log(`[${msg.from}] ${msg.data.text}`); }); // Listen for typing indicators chat.on<{ isTyping: boolean }>("typing", (msg) => { if (msg.data.isTyping) { console.log(`${msg.from} is typing...`); } }); // Send a message chat.trigger("message", { text: "Hello, everyone!", senderId: client.userId, }); // Send typing indicator chat.trigger("typing", { isTyping: true }); // Later: leave room and disconnect // chat.leave(); // client.disconnect(); } main().catch(console.error); ``` -------------------------------- ### Start Dialogue Server with Bun or Node.js Source: https://github.com/hussseinkizz/dialogue/blob/main/web/docs/guide/start/getting-started.md Starts the Dialogue server. It can be run using Bun directly or with Node.js via tsx or ts-node. Dialogue auto-detects the runtime. ```typescript // server.ts import { dialogue } from "./dialogue.config"; await dialogue.start(); // Server running on http://localhost:3000 ``` ```bash bun run server.ts ``` ```bash npx tsx server.ts ``` -------------------------------- ### Configuring Lifecycle Hooks in Dialogue Source: https://github.com/hussseinkizz/dialogue/blob/main/web/docs/public/llms-full.txt Illustrates how to configure lifecycle hooks for client and room events when creating a Dialogue instance. This example shows hooks for client connections, disconnections, joining/leaving rooms, and room creation/deletion. ```typescript const dialogue = createDialogue({ rooms: { chat: { name: "Chat", events: [Message, UserLeft], }, }, hooks: { clients: { onConnected: (client) => { client.join("chat"); dialogue.trigger("chat", UserJoined, { username: client.userId }); }, onDisconnected: (client) => { dialogue.trigger("chat", UserLeft, { username: client.userId }); console.log(`${client.userId} disconnected`); }, onJoined: (client, roomId) => { console.log(`${client.userId} joined ${roomId}`); }, onLeft: (client, roomId) => { console.log(`${client.userId} left ${roomId}`); }, }, rooms: { onCreated: (room) => { console.log(`Room ${room.name} created`); }, onDeleted: (roomId) => { console.log(`Room ${roomId} deleted`); }, }, }, }); ``` -------------------------------- ### Dialogue Instance Creation Source: https://github.com/hussseinkizz/dialogue/blob/main/web/docs/public/llms-full.txt Demonstrates how to create a new Dialogue instance with specified port and rooms configuration. ```APIDOC ## Creating a Dialogue Instance ### Description Creates a new Dialogue instance, allowing configuration of the server port and initial rooms with their associated events. ### Method `createDialogue(config)` ### Parameters #### Request Body - **`port`** (number) - Required - The port number for the Dialogue server. - **`rooms`** (object) - Required - An object defining the initial rooms. - **`[roomId]`** (object) - Required - Configuration for a specific room. - **`name`** (string) - Required - The display name of the room. - **`events`** (array) - Required - An array of event definitions for the room. ### Request Example ```typescript import { createDialogue, defineEvent } from "./dialogue"; import { z } from "zod"; const Message = defineEvent("message", { schema: z.object({ text: z.string() }), }); const dialogue = createDialogue({ port: 3000, rooms: { chat: { name: "Chat", events: [Message], }, }, }); ``` ``` -------------------------------- ### dialogue.start() Source: https://github.com/hussseinkizz/dialogue/blob/main/web/docs/public/llms-full.txt Initiates the Dialogue server, making it ready to accept connections and handle messages. ```APIDOC ## POST /dialogue/start ### Description Starts the Dialogue server. ### Method POST ### Endpoint /dialogue/start ### Parameters None ### Request Example ```json {} ``` ### Response #### Success Response (200 OK) Indicates the server has started successfully. #### Response Example ```json { "status": "Server started successfully" } ``` ``` -------------------------------- ### Dialogue Instance Properties Source: https://github.com/hussseinkizz/dialogue/blob/main/web/docs/public/llms-full.txt Details the properties available on a Dialogue instance. ```APIDOC ## Dialogue Properties ### Description Properties available on the created Dialogue instance. ### Properties - **`app`** (`Hono`) - The Hono application instance used by Dialogue. - **`io`** (`Server`) - The Socket.IO server instance managing real-time connections. ``` -------------------------------- ### dialogue.on() Source: https://github.com/hussseinkizz/dialogue/blob/main/web/docs/public/llms-full.txt Subscribes to events for backend-side processing. ```APIDOC ## dialogue.on() ### Description Subscribes to specific events within a room to enable backend-side logic such as logging, data persistence, or triggering other actions in response to events. ### Method `dialogue.on(roomId: string, event: EventDefinition, handler: (msg: EventMessage) => void | Promise): () => void` ### Parameters #### Path Parameters - **`roomId`** (string) - Required - The ID of the room to listen for events in. - **`event`** (`EventDefinition`) - Required - The definition of the event to subscribe to. - **`handler`** (`(msg: EventMessage) => void | Promise`) - Required - The callback function to execute when the event is received. It receives the `EventMessage` object. ### Returns - `() => void` - A function that, when called, unsubscribes the handler from the event. ### Example ```typescript import { dialogue, Message } from "./dialogue.config"; // Log all messages received in the 'chat' room const unsubscribe = dialogue.on("chat", Message, (msg) => { console.log(`[${msg.roomId}] ${msg.from}: ${msg.data.text}`); }); // Persist messages to a database dialogue.on("chat", Message, async (msg) => { await db.messages.create({ roomId: msg.roomId, text: msg.data.text, senderId: msg.from, createdAt: new Date(msg.timestamp), }); }); // Send push notifications for 'Alert' events dialogue.on("notifications", Alert, async (msg) => { const users = await getOfflineUsers(msg.roomId); await sendPushNotifications(users, msg.data); }); // To stop listening to events: unsubscribe(); ``` ``` -------------------------------- ### Start Development Client Source: https://github.com/hussseinkizz/dialogue/blob/main/example/README.md Starts the Vite development client, typically accessible at http://localhost:5173. ```bash pnpm dev:client ``` -------------------------------- ### dialogue.getAllClients() Source: https://github.com/hussseinkizz/dialogue/blob/main/web/docs/public/llms-full.txt Fetches a list of all currently connected clients across the entire Dialogue system. ```APIDOC ## GET /dialogue/clients ### Description Gets all currently connected clients. ### Method GET ### Endpoint /dialogue/clients ### Parameters None ### Request Example ```json {} ``` ### Response #### Success Response (200 OK) - **clients** (ConnectedClient[]) - An array of all ConnectedClient objects. #### Response Example ```json [ { "clientId": "client-abc", "userId": "user-123", "roomId": "room-1" }, { "clientId": "client-xyz", "userId": "user-789", "roomId": "room-3" } ] ``` ``` -------------------------------- ### Example Usage of DialogueContext in Hooks Source: https://github.com/hussseinkizz/dialogue/blob/main/web/docs/public/llms-full.txt Demonstrates how to access and utilize the DialogueContext within a hook function. It shows how to get the total number of clients, access a specific room by its ID, and emit a global event using the Socket.IO server instance. ```typescript beforeEach: ({ context, roomId, message }) => { const totalClients = Object.keys(context.clients).length; const room = context.rooms[roomId]; context.io.emit("global-event", { data: "..." }); return Ok(message); } ``` -------------------------------- ### Install Dependencies with pnpm Source: https://github.com/hussseinkizz/dialogue/blob/main/example/README.md Installs all project dependencies for both the server and client using the pnpm package manager. ```bash pnpm install:all ``` -------------------------------- ### Backend Initialization Flow Source: https://github.com/hussseinkizz/dialogue/blob/main/web/docs/public/llms-full.txt Illustrates the step-by-step process of initializing the Dialogue backend server, including setting up the Hono app, Socket.IO server, RoomManager, and connection handlers. ```mermaid graph TD 1. createDialogue(config) --> Create or use existing Hono app 2. createDialogue(config) --> setupServer(app, config) 3. setupServer --> Create Socket.IO server 4. setupServer --> Create BunEngine adapter 5. setupServer --> io.bind(engine) 6. setupServer --> createRoomManager(io) 7. createRoomManager --> For each room in config: roomManager.register(id, config) 8. setupServer --> Set up connection handler 9. setupServer --> io.on("connection", ...) 10. setupServer --> Return { io, roomManager, start, stop } 11. createDialogue --> Return Dialogue instance ``` -------------------------------- ### dialogue.room() Source: https://github.com/hussseinkizz/dialogue/blob/main/web/docs/public/llms-full.txt Retrieves a room instance by its ID. ```APIDOC ## dialogue.room() ### Description Retrieves a `Room` object instance associated with the provided room ID. ### Method `dialogue.room(id: string): Room | null` ### Parameters #### Path Parameters - **`id`** (string) - Required - The ID of the room to retrieve. ### Returns - `Room | null` - The `Room` object if found, otherwise `null`. ### Example ```typescript const chatRoom = dialogue.room("chat"); if (chatRoom) { console.log(`${chatRoom.name} has ${chatRoom.size()} participants`); } ``` ``` -------------------------------- ### Start Development Server Source: https://github.com/hussseinkizz/dialogue/blob/main/example/README.md Starts the dialogue-ts server in development mode, typically listening on port 3000. ```bash pnpm dev:server ``` -------------------------------- ### Backend Module Structure (File Paths) Source: https://github.com/hussseinkizz/dialogue/blob/main/web/docs/public/llms-full.txt Lists the core files and their purposes within the backend module structure of the Dialogue project. This includes type definitions, event factories, room management, client handling, server setup, and main factory functions. ```text dialogue/ types.ts # Type definitions (interfaces, no implementation) define-event.ts # Event definition factory with Zod validation room.ts # Room creation and room manager client-handler.ts # Connected client wrapper server.ts # Socket.IO + Hono + Bun server setup create-dialogue.ts # Main factory function index.ts # Barrel exports ``` -------------------------------- ### dialogue.trigger() Source: https://github.com/hussseinkizz/dialogue/blob/main/web/docs/public/llms-full.txt Triggers an event to all subscribers within a specified room. ```APIDOC ## dialogue.trigger() ### Description Triggers an event to all subscribers in a specified room. This method can be called from anywhere within the backend application. ### Method `dialogue.trigger(roomId: string, event: EventDefinition, data: T, from?: string): void` ### Parameters #### Path Parameters - **`roomId`** (string) - Required - The ID of the room to broadcast the event to. - **`event`** (`EventDefinition`) - Required - The definition of the event being triggered. - **`data`** (T) - Required - The payload of the event. This data will be validated against the event's schema if one is defined. - **`from`** (string) - Optional - An identifier for the sender of the event. Defaults to "system". ### Request Example ```typescript import { dialogue, Message } from "./dialogue.config"; // Example usage within an API route app.post("/messages", async (c) => { const { text, userId } = await c.req.json(); dialogue.trigger("chat", Message, { text, senderId: userId }, userId); return c.json({ status: true }); }); // Example usage within a webhook handler app.post("/webhooks/payment", async (c) => { const event = await c.req.json(); dialogue.trigger("orders", OrderUpdated, { orderId: event.orderId, status: "paid", }); return c.json({ received: true }); }); ``` ``` -------------------------------- ### Create Dialogue Room Dynamically Source: https://github.com/hussseinkizz/dialogue/blob/main/web/docs/guide/start/getting-started.md Demonstrates how to create a new room at runtime, providing flexibility beyond predefined configurations. This is useful for temporary or user-generated sessions. ```typescript // Create room on-demand dialogue.createRoom({ id: `game-${gameId}`, name: 'Game Session', events: [ { name: 'move', schema: z.object({ x: z.number(), y: z.number() }) }, { name: 'chat', schema: z.object({ message: z.string() }) } ] }); ``` -------------------------------- ### Client Authentication and Auth Data Access (TypeScript) Source: https://github.com/hussseinkizz/dialogue/blob/main/web/docs/public/llms-full.txt Shows how clients authenticate by passing `auth` data during connection and how this data is accessed within the `onConnected` hook. It includes examples of validating tokens and performing actions based on client roles. ```typescript // Frontend const client = createDialogueClient({ url: "ws://localhost:3000", auth: { userId: "user-123", token: "jwt-token-here", role: "admin", }, }); ``` ```typescript const dialogue = createDialogue({ rooms: { /* ... */ }, hooks: { clients: { onConnected: (client) => { console.log(client.userId); // "user-123" or socket.id if not provided console.log(client.meta); // { token: "jwt-token-here", role: "admin" } // Validate token and permissions if (!isValidToken(client.meta.token)) { client.disconnect(); return; } // Join rooms based on role if (client.meta.role === "admin") { client.join("admin-dashboard"); } }, }, }, }); ``` -------------------------------- ### room.leave() Source: https://github.com/hussseinkizz/dialogue/blob/main/web/docs/public/llms-full.txt Allows a client to leave a room, automatically cleaning up all associated event handlers. ```APIDOC ## POST /room/leave ### Description Leaves the room and cleans up all event handlers. ### Method POST ### Endpoint `/room/leave` ### Request Example ```javascript // Leave the room when closing a chat interface room.leave(); ``` ### Response #### Success Response (200) - **`status`** (string) - Indicates that the client has successfully left the room. #### Response Example ```json { "status": "left", "message": "Successfully left the room." } ``` ``` -------------------------------- ### Connect to Dialogue Server from Frontend Source: https://github.com/hussseinkizz/dialogue/blob/main/web/docs/guide/start/getting-started.md Establishes a connection to the Dialogue server from a client application. It includes joining a room, listening for events, and sending events. ```typescript import { createDialogueClient } from "dialogue-ts/client"; const client = createDialogueClient({ url: "ws://localhost:3000", auth: { userId: "user-123" }, }); await client.connect(); // Join a room const chat = await client.join("chat"); // Listen for events chat.on("message", (msg) => { console.log(`${msg.from}: ${msg.data.text}`); }); // Send events chat.trigger("message", { text: "Hello, everyone!", senderId: "user-123", }); ``` -------------------------------- ### Client Methods Source: https://github.com/hussseinkizz/dialogue/blob/main/web/docs/public/llms-full.txt Methods for interacting with the Dialogue client, including unsubscribing from events, managing rooms, and sending messages. ```APIDOC ## POST /client/unsubscribe ### Description Unsubscribes from an event in a room. ### Method POST ### Endpoint /client/unsubscribe ### Parameters #### Path Parameters - **roomId** (string) - Required - The ID of the room to unsubscribe from. - **eventName** (string) - Required - The name of the event to unsubscribe from. ### Request Body None ### Response #### Success Response (200) - **status** (string) - Indicates success or failure of the unsubscribe operation. #### Response Example ```json { "status": "unsubscribed" } ``` ## GET /client/rooms ### Description Returns a list of room IDs that the client has joined. ### Method GET ### Endpoint /client/rooms ### Parameters None ### Response #### Success Response (200) - **roomIds** (string[]) - An array of room IDs. #### Response Example ```json { "roomIds": ["room1", "room2"] } ``` ## GET /client/subscriptions ### Description Returns a list of subscribed event names for a specific room. ### Method GET ### Endpoint /client/subscriptions ### Parameters #### Query Parameters - **roomId** (string) - Required - The ID of the room to get subscriptions for. ### Response #### Success Response (200) - **eventNames** (string[]) - An array of subscribed event names. #### Response Example ```json { "eventNames": ["message", "typing"] } ``` ## POST /client/send ### Description Sends data directly to this client only. ### Method POST ### Endpoint /client/send ### Parameters #### Request Body - **event** (string) - Required - The name of the event to send. - **data** (any) - Required - The data payload for the event. ### Request Example ```json { "event": "welcome", "data": { "message": "Welcome to the server!", "serverTime": 1678886400000 } } ``` ### Response #### Success Response (200) - **status** (string) - Indicates success of the send operation. #### Response Example ```json { "status": "sent" } ``` ## POST /client/disconnect ### Description Disconnects this client. ### Method POST ### Endpoint /client/disconnect ### Parameters None ### Response #### Success Response (200) - **status** (string) - Indicates successful disconnection. #### Response Example ```json { "status": "disconnected" } ``` ``` -------------------------------- ### room.onAny() Source: https://github.com/hussseinkizz/dialogue/blob/main/web/docs/public/llms-full.txt Listens for all events occurring within the room. This is useful for logging or debugging purposes. ```APIDOC ## POST /room/onAny ### Description Listens for all events in the room. Useful for logging or debugging. ### Method POST ### Endpoint `/room/onAny` ### Parameters #### Request Body - **`handler`** (function) - Required - The callback function to execute for any event. It receives the `eventName` (string) and the `msg` (`EventMessage`) as arguments. ### Request Example ```javascript room.onAny((eventName, msg) => { console.log(`Event: ${eventName}`, msg.data); }); ``` ### Response #### Success Response (200) - **`status`** (string) - Indicates the successful registration of the listener. #### Response Example ```json { "status": "subscribed_all", "message": "Successfully subscribed to all events." } ``` ``` -------------------------------- ### room.subscribeAll() Source: https://github.com/hussseinkizz/dialogue/blob/main/web/docs/public/llms-full.txt Subscribes to all events within the room using a wildcard pattern. This is useful for scenarios requiring comprehensive event monitoring. ```APIDOC ## POST /room/subscribeAll ### Description Subscribe to **all events** in the room using the wildcard pattern (`*`). ### Method POST ### Endpoint `/room/subscribeAll` ### Request Example ```javascript // Subscribe to all events in the current room room.subscribeAll(); ``` ### Response #### Success Response (200) - **`status`** (string) - Indicates the successful subscription to all events. #### Response Example ```json { "status": "subscribed_all", "message": "Successfully subscribed to all events." } ``` ``` -------------------------------- ### dialogue.createRoom() Source: https://github.com/hussseinkizz/dialogue/blob/main/web/docs/public/llms-full.txt Creates a new room dynamically at runtime. This is ideal for scenarios where rooms need to be generated based on user actions or specific events. ```APIDOC ## POST /dialogue/rooms ### Description Creates a new room at runtime. ### Method POST ### Endpoint /dialogue/rooms ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body - **id** (string) - Required - Unique room identifier. - **config** (object) - Required - Configuration for the room. - **name** (string) - Required - Human-readable room name. - **description** (string) - Optional - Room description. - **events** (EventDefinition[]) - Required - Array of allowed event definitions. - **defaultSubscriptions** (string[]) - Optional - Event names to auto-subscribe on join. - **maxSize** (number) - Optional - Maximum participants. - **createdById** (string) - Optional - User ID of the room creator. ### Request Example ```json { "id": "project-123", "config": { "name": "Project Discussion", "description": "Chat for project #123", "events": [ {"name": "message"}, {"name": "user-joined"} ], "defaultSubscriptions": ["message", "user-joined"], "maxSize": 50 }, "createdById": "user-456" } ``` ### Response #### Success Response (201 Created) - **room** (Room) - The created Room instance. #### Response Example ```json { "id": "project-123", "name": "Project Discussion", "description": "Chat for project #123", "participantCount": 0 } ``` ``` -------------------------------- ### room.on() Source: https://github.com/hussseinkizz/dialogue/blob/main/web/docs/public/llms-full.txt Listens for a specific event within a room. It returns a function that can be called to unsubscribe from the event. ```APIDOC ## POST /room/on ### Description Listens for a specific event within the room. Returns an unsubscribe function. ### Method POST ### Endpoint `/room/on` ### Parameters #### Query Parameters - **`eventName`** (string) - Required - The name of the event to listen for. #### Request Body - **`handler`** (function) - Required - The callback function to execute when the event is received. This function receives an `EventMessage` object. ### EventMessage Structure ```typescript interface EventMessage { event: string; roomId: string; data: T; from: string; timestamp: number; meta?: Record; } ``` ### Request Example ```javascript // Subscribe to 'message' events room.on('message', (msg) => { console.log(`[${msg.from}] ${msg.data.text}`); console.log(`Received at: ${new Date(msg.timestamp)}`); }); // To unsubscribe later: // const unsubscribe = room.on(...); // unsubscribe(); ``` ### Response #### Success Response (200) - **`unsubscribe`** (function) - A function that, when called, will stop listening for the specified event. #### Response Example (Note: The actual unsubscribe function cannot be represented in JSON. The response indicates the successful registration of the listener.) ```json { "status": "subscribed", "message": "Successfully subscribed to event." } ``` ``` -------------------------------- ### Get Client Rooms and Manage Membership (TypeScript) Source: https://github.com/hussseinkizz/dialogue/blob/main/web/docs/public/llms-full.txt Retrieves all room IDs a user is in and provides methods to iterate or leave these rooms. Useful for managing user presence across multiple connections and handling disconnections. ```typescript const rooms = dialogue.getClientRooms("user-123"); // Access room IDs console.log(`User is in rooms: ${rooms.ids.join(", ")}`); // Do something for all rooms (without leaving) rooms.forAll((roomId) => { dialogue.trigger(roomId, UserTyping, { userId: "user-123", isTyping: false }); }); // Leave all rooms with notification rooms.leaveAll((roomId) => { dialogue.trigger(roomId, UserLeft, { username: "user-123" }); }); // Or just leave without notification rooms.leaveAll(); ``` ```typescript onDisconnect: (client) => { dialogue.getClientRooms(client.userId).leaveAll((roomId) => { dialogue.trigger(roomId, UserLeft, { username: client.userId }); }); } ``` -------------------------------- ### room.getHistory() Source: https://github.com/hussseinkizz/dialogue/blob/main/web/docs/public/llms-full.txt Fetches historical events for a specific event type within the room, supporting pagination for efficient data retrieval. ```APIDOC ## GET /room/history ### Description Fetches historical events for a specific event type with pagination. ### Method GET ### Endpoint `/room/history` ### Parameters #### Query Parameters - **`eventName`** (string) - Required - The event type to fetch history for. - **`start`** (number) - Optional - Starting index (0 = most recent). Defaults to 0. - **`end`** (number) - Optional - Ending index (exclusive). Defaults to 50. ### Request Example ```javascript // Get the last 20 messages const recentMessages = await room.getHistory('message', 0, 20); // Paginate: skip first 20, get next 20 const olderMessages = await room.getHistory('message', 20, 40); ``` ### Response #### Success Response (200) - **`events`** (array) - An array of historical `EventMessage` objects, sorted newest first. #### Response Example ```json [ { "event": "message", "roomId": "room123", "data": { "text": "Hello again!", "senderId": "user456" }, "from": "user456", "timestamp": 1678886400000, "meta": {} }, { "event": "message", "roomId": "room123", "data": { "text": "Hello, everyone!", "senderId": "user123" }, "from": "user123", "timestamp": 1678886300000, "meta": {} } ] ``` ``` -------------------------------- ### Trigger Dialogue Event from Backend Source: https://github.com/hussseinkizz/dialogue/blob/main/web/docs/guide/start/getting-started.md Sends an event from the server-side to connected clients. This example triggers a 'message' event to the 'chat' room. ```typescript import { dialogue, Message } from "./dialogue.config"; // From an API route, webhook, or background job dialogue.trigger("chat", Message, { text: "Welcome to the chat!", senderId: "system", }); ``` -------------------------------- ### Start Development Server with Bun Source: https://github.com/hussseinkizz/dialogue/blob/main/web/README.md Starts the development server using Bun, allowing for live preview and hot-reloading of the documentation site. The site will be accessible at http://localhost:3000. ```bash bun run dev ``` -------------------------------- ### Preview Production Build Locally with Bun Source: https://github.com/hussseinkizz/dialogue/blob/main/web/README.md Starts a local server to preview the production build of the documentation site. This is useful for testing the final output before deployment. ```bash bun run preview ``` -------------------------------- ### Configure Dialogue with Persistence (TypeScript) Source: https://github.com/hussseinkizz/dialogue/blob/main/web/docs/public/llms-full.txt Defines chat events and configures the Dialogue server to persist messages to a database using onCleanup and load them using onLoad hooks. It uses Zod for schema validation and dialogue-ts for server setup. ```typescript // dialogue.config.ts import { createDialogue, defineEvent } from "dialogue-ts"; import { z } from "zod"; import { insertMessages, loadMessages } from "./db/messages"; export const Message = defineEvent("message", { schema: z.object({ text: z.string().min(1).max(2000), username: z.string(), }), history: { enabled: true, limit: 100 }, // Keep 100 in memory }); export const dialogue = createDialogue({ port: 3000, rooms: { general: { name: "General Chat", events: [Message], syncHistoryOnJoin: 50, // Send last 50 on join }, }, hooks: { clients: { onConnected: (client) => { client.join("general"); }, }, events: { // Persist events when evicted from memory onCleanup: async (roomId, eventName, events) => { console.log(`Persisting ${events.length} ${eventName} events from ${roomId}`); await insertMessages(roomId, eventName, events); }, // Load older events from database for pagination onLoad: async (roomId, eventName, start, end) => { console.log(`Loading ${eventName} events ${start}-${end} from ${roomId}`); return loadMessages(roomId, eventName, start, end); }, }, }, }); ``` -------------------------------- ### Quick Start: Chat Client Implementation (TypeScript) Source: https://github.com/hussseinkizz/dialogue/blob/main/README.md Provides a client-side implementation for the chat example using `createDialogueClient`. It shows how to connect to the server, join a room, listen for messages and user join events, and send messages. ```typescript // client.ts import { createDialogueClient } from "dialogue-ts/client"; const client = createDialogueClient({ url: "ws://localhost:3000", auth: { userId: "alice" }, }); // Connect and join room await client.connect(); const chat = await client.join("general"); // Listen for messages chat.on("message", (msg) => { console.log(`${msg.data.username}: ${msg.data.text}`); }); // Listen for users joining chat.on("user-joined", (msg) => { console.log(`${msg.data.username} joined the chat`); }); // Send a message chat.trigger("message", { text: "Hello everyone!", username: "alice", }); ``` -------------------------------- ### Configure IoT Monitoring Backend with Dialogue Source: https://github.com/hussseinkizz/dialogue/blob/main/web/docs/public/llms-full.txt Sets up an IoT monitoring backend using Dialogue, defining events for sensor readings, device status, and alerts. It configures a 'sensors' room and includes logic to process incoming sensor data and trigger alerts based on predefined thresholds. ```typescript // iot.config.ts import { createDialogue, defineEvent } from "./dialogue"; import { z } from "zod"; export const SensorReading = defineEvent("sensor:reading", { schema: z.object({ deviceId: z.string(), temperature: z.number(), humidity: z.number(), pressure: z.number(), battery: z.number().min(0).max(100), timestamp: z.number(), }), }); export const DeviceStatus = defineEvent("device:status", { schema: z.object({ deviceId: z.string(), status: z.enum(["online", "offline", "error", "maintenance"]), lastSeen: z.number(), }), }); export const DeviceAlert = defineEvent("device:alert", { schema: z.object({ deviceId: z.string(), alertType: z.enum(["temperature", "battery", "connectivity", "error"]), message: z.string(), value: z.number().optional(), threshold: z.number().optional(), }), }); export const dialogue = createDialogue({ port: 3000, rooms: { sensors: { name: "Sensor Data", description: "Real-time sensor readings", events: [SensorReading, DeviceStatus, DeviceAlert], defaultSubscriptions: ["sensor:reading", "device:status", "device:alert"], }, }, }); // Process incoming sensor data (e.g., from MQTT bridge) export function processSensorData(data: { deviceId: string; temperature: number; humidity: number; pressure: number; battery: number; }): void { const reading = { ...data, timestamp: Date.now(), }; // Broadcast to dashboard dialogue.trigger("sensors", SensorReading, reading, data.deviceId); // Check for alerts if (data.temperature > 40) { dialogue.trigger( "sensors", DeviceAlert, { deviceId: data.deviceId, alertType: "temperature", message: `High temperature detected: ${data.temperature}°C`, value: data.temperature, threshold: 40, }, "system" ); } if (data.battery < 20) { dialogue.trigger( "sensors", DeviceAlert, { deviceId: data.deviceId, alertType: "battery", message: `Low battery: ${data.battery}%`, value: data.battery, threshold: 20, }, "system" ); } } ``` -------------------------------- ### Install Dependencies with Bun Source: https://github.com/hussseinkizz/dialogue/blob/main/web/README.md Installs the necessary project dependencies using the Bun package manager. This is a prerequisite for running the development server or building the project. ```bash bun install ``` -------------------------------- ### Get Room Participants (TypeScript) Source: https://github.com/hussseinkizz/dialogue/blob/main/web/docs/public/llms-full.txt Retrieves a list of all currently connected clients within a specific room. Useful for iterating over participants or displaying user lists. ```typescript const room = dialogue.room("chat"); const participants = room?.participants() ?? []; for (const client of participants) { console.log(`- ${client.userId}`); } ``` -------------------------------- ### Build Production Website with Bun Source: https://github.com/hussseinkizz/dialogue/blob/main/web/README.md Builds the documentation site for production deployment using Bun. This command generates optimized static assets for deployment. ```bash bun run build ``` -------------------------------- ### Room Properties Source: https://github.com/hussseinkizz/dialogue/blob/main/web/docs/public/llms-full.txt Defines the properties associated with a room, such as its identifier and human-readable name. ```APIDOC ## Room Properties ### Description Represents the properties of a chat room. ### Properties #### `roomId` - **Type**: `string` - **Description**: Room identifier. #### `roomName` - **Type**: `string` - **Description**: Human-readable room name. ``` -------------------------------- ### dialogue.stop() Source: https://github.com/hussseinkizz/dialogue/blob/main/web/docs/public/llms-full.txt Shuts down the Dialogue server and disconnects all currently connected clients gracefully. ```APIDOC ## POST /dialogue/stop ### Description Stops the Dialogue server and disconnects all clients. ### Method POST ### Endpoint /dialogue/stop ### Parameters None ### Request Example ```json {} ``` ### Response #### Success Response (200 OK) Indicates the server has stopped successfully. #### Response Example ```json { "status": "Server stopped successfully" } ``` ``` -------------------------------- ### Complete Dialogue Client Example (TypeScript) Source: https://github.com/hussseinkizz/dialogue/blob/main/web/docs/guide/api/client-api.md A comprehensive example demonstrating how to create a Dialogue client, connect to a server, list rooms, join a specific room, set up event handlers for messages and typing indicators, send messages, and manage connection states. It utilizes `async/await` for asynchronous operations. ```typescript import { createDialogueClient } from "./client"; async function main() { // Create client with authentication const client = createDialogueClient({ url: "ws://localhost:3000", auth: { userId: "user-123", token: "my-jwt-token", }, }); // Set up connection handlers client.onConnect(() => { console.log("Connected as:", client.userId); }); client.onDisconnect((reason) => { console.log("Disconnected:", reason); }); client.onError((error) => { console.error("Error:", error.message); }); // Connect to server await client.connect(); // List available rooms const rooms = await client.listRooms(); console.log("Available rooms:", rooms); // Join chat room const chat = await client.join("chat"); console.log(`Joined: ${chat.roomName}`); // Listen for messages chat.on<{ text: string; senderId: string }>("message", (msg) => { console.log(`[${msg.from}] ${msg.data.text}`); }); // Listen for typing indicators chat.on<{ isTyping: boolean }>("typing", (msg) => { if (msg.data.isTyping) { console.log(`${msg.from} is typing...`); } }); // Send a message chat.trigger("message", { text: "Hello, everyone!", senderId: client.userId, }); // Send typing indicator chat.trigger("typing", { isTyping: true }); // Later: leave room and disconnect // chat.leave(); // client.disconnect(); } main().catch(console.error); ``` -------------------------------- ### Full Dialogue Server Configuration Example (TypeScript) Source: https://github.com/hussseinkizz/dialogue/blob/main/web/docs/guide/api/configuration/dialogue-config.md Demonstrates a complete configuration for creating a Dialogue server, including defining events, setting up rooms, and implementing client hooks. It utilizes Hono for HTTP routing and Zod for schema validation. ```typescript import { Hono } from "hono"; import { createDialogue, defineEvent } from "./dialogue"; import { z } from "zod"; const Message = defineEvent("message", { schema: z.object({ text: z.string(), senderId: z.string() }), history: { enabled: true, limit: 100 }, // Enable history storage }); const app = new Hono(); // Add HTTP routes app.get("/health", (c) => c.json({ status: "ok" })); const dialogue = createDialogue({ port: 3000, app, rooms: { chat: { name: "Chat", events: [Message], defaultSubscriptions: ["message"], syncHistoryOnJoin: true, // Auto-send history on join }, }, hooks: { clients: { onConnected: async (client) => { // Called when a client connects console.log(`Client ${client.userId} connected`); // Auto-join rooms based on user permissions const userRooms = await getUserRooms(client.userId); for (const roomId of userRooms) { client.join(roomId); } // Send initial data client.send("sync", { timestamp: Date.now() }); }, onDisconnected: (client) => { console.log(`Client ${client.userId} disconnected`); }, }, }, }); ``` -------------------------------- ### EventMessage Structure Source: https://github.com/hussseinkizz/dialogue/blob/main/web/docs/public/llms-full.txt Defines the standard structure for all event messages sent through Dialogue. ```APIDOC ## EventMessage Structure ### Description All events transmitted via Dialogue adhere to this standardized `EventMessage` structure. This envelope is managed by Dialogue and is not customizable, except for the `data` payload. ### Interface ```typescript interface EventMessage { event: string; // Event name roomId: string; // Room ID where event occurred data: T; // Your custom payload (validated by schema) from: string; // User ID of sender (or "system") timestamp: number; // Unix timestamp (milliseconds) meta?: Record; // Optional flexible metadata } ``` ### The `meta` Field The `meta` field is an optional object that allows for the inclusion of arbitrary contextual information with an event message. It does not have a predefined schema and is not validated by Dialogue, offering flexibility for use cases such as request metadata, permission context, or debugging information. **Example:** ```typescript // Adding request context dialogue.trigger('chat', chatMessage, { event: 'message', data: { text: 'Hello world' }, from: 'user-123', timestamp: Date.now(), meta: { ip: '192.168.1.1', userAgent: 'Mozilla/5.0...', correlationId: 'abc-123' } }); // Adding permission context room.trigger(updateEvent, data, userId, { permissions: ['admin', 'write'], sessionId: 'xyz-789' }); ``` ``` -------------------------------- ### Client Authentication Setup (TypeScript) Source: https://github.com/hussseinkizz/dialogue/blob/main/web/docs/guide/api/configuration/authentication.md Demonstrates how to configure a client with authentication data, including user ID, token, and role, when establishing a WebSocket connection. ```typescript const client = createDialogueClient({ url: "ws://localhost:3000", auth: { userId: "user-123", token: "jwt-token-here", role: "admin", }, }); ```