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.
@@ -0,0 +1,664 @@
1
+ import { Hono } from 'hono';
2
+ import { Result } from 'slang-ts';
3
+ import { Socket, Server } from 'socket.io';
4
+ import { z } from 'zod';
5
+
6
+ /**
7
+ * Structured log entry for Dialogue logging.
8
+ */
9
+ interface LogEntry {
10
+ /** The message describing what happened */
11
+ message: string;
12
+ /** The function or location where the log originated */
13
+ atFunction: string;
14
+ /** Additional data for context */
15
+ data: unknown;
16
+ }
17
+ /**
18
+ * Logger interface for Dialogue.
19
+ * Implement this interface to provide custom logging behavior.
20
+ * By default, Dialogue uses a console-based logger.
21
+ */
22
+ interface Logger {
23
+ /** Log debug information (verbose, development only) */
24
+ debug: (entry: LogEntry) => void;
25
+ /** Log informational messages */
26
+ info: (entry: LogEntry) => void;
27
+ /** Log warning messages (non-critical issues) */
28
+ warn: (entry: LogEntry) => void;
29
+ /** Log error messages (critical issues) */
30
+ error: (entry: LogEntry) => void;
31
+ }
32
+ /**
33
+ * Event definition - defines a named event with optional schema validation.
34
+ * Events are first-class citizens in Dialogue, not just message payloads.
35
+ *
36
+ * @template T - The data type this event carries
37
+ */
38
+ interface EventDefinition<T = unknown> {
39
+ readonly name: string;
40
+ readonly description?: string;
41
+ readonly schema?: z.ZodType<T>;
42
+ readonly history?: EventHistoryConfig;
43
+ }
44
+ /**
45
+ * Configuration for event history storage.
46
+ * When enabled, events of this type are stored in memory per room.
47
+ */
48
+ interface EventHistoryConfig {
49
+ /** Whether to store this event type in history */
50
+ enabled: boolean;
51
+ /** Maximum number of events to keep in memory per room */
52
+ limit: number;
53
+ }
54
+ /**
55
+ * Room configuration - defines a room's properties and allowed events.
56
+ * Used when creating rooms in DialogueConfig.
57
+ */
58
+ interface RoomConfig {
59
+ name: string;
60
+ description?: string;
61
+ /** Max concurrent connections. Undefined means unlimited. */
62
+ maxSize?: number;
63
+ /** Events allowed in this room. Empty array means any event allowed. */
64
+ events: EventDefinition<unknown>[];
65
+ /** Event names to auto-subscribe clients to on join */
66
+ defaultSubscriptions?: string[];
67
+ /** User ID of room creator for ownership tracking */
68
+ createdById?: string;
69
+ /** Auto-send history on join. true = all history, number = limit per event type */
70
+ syncHistoryOnJoin?: boolean | number;
71
+ }
72
+ /**
73
+ * CORS configuration for Socket.IO server.
74
+ * Set to true to allow all origins, or specify allowed origins.
75
+ */
76
+ interface CorsConfig {
77
+ /** Allowed origins. Use "*" or true for all origins. */
78
+ origin: string | string[] | boolean;
79
+ /** Allowed HTTP methods */
80
+ methods?: string[];
81
+ /** Whether to allow credentials (cookies, auth headers) */
82
+ credentials?: boolean;
83
+ }
84
+ /**
85
+ * JWT claims structure for client authentication.
86
+ * Standard JWT payload format with extensibility.
87
+ */
88
+ interface JwtClaims {
89
+ /** Subject - typically the user ID */
90
+ sub: string;
91
+ /** Expiration timestamp (Unix time in seconds) */
92
+ exp?: number;
93
+ /** Issued at timestamp (Unix time in seconds) */
94
+ iat?: number;
95
+ /** Additional custom claims */
96
+ [key: string]: unknown;
97
+ }
98
+ /**
99
+ * Authentication data stored on each client after successful authentication.
100
+ * Supports JWT-based auth with room for future authentication methods.
101
+ */
102
+ interface AuthData {
103
+ /** JWT claims/payload */
104
+ jwt: JwtClaims;
105
+ /** Future authentication-related fields can be added here */
106
+ [key: string]: unknown;
107
+ }
108
+ /**
109
+ * Result of a successful authentication.
110
+ * Provides the resolved user identity and metadata.
111
+ */
112
+ interface AuthenticateResult {
113
+ /** Resolved application user ID */
114
+ userId: string;
115
+ /** Additional metadata (role, permissions, etc.) */
116
+ meta: Record<string, unknown>;
117
+ }
118
+ /**
119
+ * Global runtime context representing the current state of the Dialogue server.
120
+ * Provides awareness of all connected clients, active rooms, and the Socket.IO server.
121
+ * This context is passed to all hooks alongside case-specific data.
122
+ */
123
+ interface DialogueContext {
124
+ /** The Socket.IO server instance */
125
+ io: Server;
126
+ /** Map of all connected clients, keyed by client ID */
127
+ clients: Record<string, ConnectedClient>;
128
+ /** Map of all active rooms, keyed by room ID */
129
+ rooms: Record<string, Room>;
130
+ }
131
+ /**
132
+ * Hooks configuration for lifecycle events.
133
+ * Use hooks to respond to room, client, and event lifecycle events.
134
+ *
135
+ * Hooks prefixed with "before" run before the action and can block it (return Err to deny).
136
+ * Hooks prefixed with "after" run after the action for side-effects (fire-and-forget).
137
+ * Hooks prefixed with "on" are legacy notification hooks (fire-and-forget).
138
+ *
139
+ * All hooks receive a DialogueContext containing global runtime state (io, clients, rooms)
140
+ * along with case-specific data relevant to that particular hook.
141
+ */
142
+ interface HooksConfig {
143
+ socket?: {
144
+ /**
145
+ * Called during Socket.IO handshake before connection is accepted.
146
+ * Return Ok(authData) with JWT claims to accept, Err("reason") to reject.
147
+ * The authData will be stored in the client's auth field.
148
+ */
149
+ authenticate?: (params: {
150
+ context: DialogueContext;
151
+ clientSocket: Socket;
152
+ authData: unknown;
153
+ }) => Result<AuthData, string> | Promise<Result<AuthData, string>>;
154
+ /**
155
+ * Called when a client socket connects.
156
+ * Receives the global context and the newly connected client socket.
157
+ */
158
+ onConnect?: (params: {
159
+ context: DialogueContext;
160
+ clientSocket: Socket;
161
+ }) => void | Promise<void>;
162
+ /**
163
+ * Called when a client socket disconnects.
164
+ * Receives the global context and the disconnecting client socket.
165
+ */
166
+ onDisconnect?: (params: {
167
+ context: DialogueContext;
168
+ clientSocket: Socket;
169
+ }) => void | Promise<void>;
170
+ };
171
+ rooms?: {
172
+ /** Called when a room is created */
173
+ onCreated?: (room: Room) => void | Promise<void>;
174
+ /** Called when a room is updated */
175
+ onUpdated?: (room: Room) => void | Promise<void>;
176
+ /** Called when a room is deleted */
177
+ onDeleted?: (roomId: string) => void | Promise<void>;
178
+ };
179
+ clients?: {
180
+ /**
181
+ * Called synchronously before a client joins a room. Can deny room access.
182
+ * Return Ok(undefined) to allow, Err("reason") to deny.
183
+ * When denied, the client receives a dialogue:error with code JOIN_DENIED.
184
+ * Must be synchronous to preserve real-time performance.
185
+ */
186
+ beforeJoin?: (params: {
187
+ context: DialogueContext;
188
+ client: ConnectedClient;
189
+ roomId: string;
190
+ room: Room;
191
+ }) => Result<void, string>;
192
+ /** Called when a client connects */
193
+ onConnected?: (client: ConnectedClient) => void | Promise<void>;
194
+ /** Called when a client disconnects */
195
+ onDisconnected?: (client: ConnectedClient) => void | Promise<void>;
196
+ /** Called when a client joins a room */
197
+ onJoined?: (client: ConnectedClient, roomId: string) => void | Promise<void>;
198
+ /** Called when a client leaves a room */
199
+ onLeft?: (client: ConnectedClient, roomId: string) => void | Promise<void>;
200
+ };
201
+ events?: {
202
+ /**
203
+ * Called synchronously before each event is broadcast. Can block or transform events.
204
+ * Return Ok(message) with the (possibly modified) message to proceed.
205
+ * Return Err("reason") to block the event from being broadcast.
206
+ * Must be synchronous to preserve real-time performance.
207
+ */
208
+ beforeEach?: (params: {
209
+ context: DialogueContext;
210
+ roomId: string;
211
+ message: EventMessage;
212
+ from: string;
213
+ }) => Result<EventMessage, string>;
214
+ /**
215
+ * Called synchronously after each event is broadcast. Fire-and-forget for side-effects.
216
+ * Useful for logging, analytics, metrics, etc.
217
+ * Must be synchronous to preserve real-time performance.
218
+ */
219
+ afterEach?: (params: {
220
+ context: DialogueContext;
221
+ roomId: string;
222
+ message: EventMessage;
223
+ recipientCount: number;
224
+ }) => void;
225
+ /** Called when an event is triggered */
226
+ onTriggered?: (roomId: string, event: EventMessage) => void | Promise<void>;
227
+ /** Called when events are evicted from in-memory history (oldest first) */
228
+ onCleanup?: (roomId: string, eventName: string, events: EventMessage[]) => void | Promise<void>;
229
+ /** Called to load historical events beyond in-memory (for pagination) */
230
+ onLoad?: (roomId: string, eventName: string, start: number, end: number) => Promise<EventMessage[]>;
231
+ };
232
+ }
233
+ /**
234
+ * Main dialogue configuration - passed to createDialogue.
235
+ * Defines all rooms and their events upfront for config-first approach.
236
+ */
237
+ interface DialogueConfig {
238
+ /** Port to run server on. Optional if using existing app. */
239
+ port?: number;
240
+ /** Existing Hono app to attach to. Creates new one if not provided. */
241
+ app?: Hono;
242
+ /** Room configurations keyed by room ID */
243
+ rooms: Record<string, RoomConfig>;
244
+ /** Lifecycle hooks for rooms, clients, and events */
245
+ hooks?: HooksConfig;
246
+ /** Custom logger implementation. Uses default console logger if not provided. */
247
+ logger?: Logger;
248
+ /** CORS configuration. Defaults to allowing all origins in development. */
249
+ cors?: CorsConfig | boolean;
250
+ }
251
+ /**
252
+ * Message envelope - the shape of all messages sent between clients and server.
253
+ * Same structure for both directions (incoming and outgoing).
254
+ *
255
+ * @template T - The data payload type
256
+ */
257
+ interface EventMessage<T = unknown> {
258
+ event: string;
259
+ roomId: string;
260
+ data: T;
261
+ /** User ID of sender */
262
+ from: string;
263
+ timestamp: number;
264
+ /** Optional metadata for flexible additional context */
265
+ meta?: Record<string, unknown>;
266
+ }
267
+ /**
268
+ * Room instance - runtime representation of a room with methods.
269
+ * Manages connections, subscriptions, and event broadcasting.
270
+ */
271
+ interface Room {
272
+ readonly id: string;
273
+ readonly name: string;
274
+ readonly description?: string;
275
+ readonly maxSize?: number;
276
+ readonly events: EventDefinition<unknown>[];
277
+ readonly defaultSubscriptions: string[];
278
+ readonly createdById?: string;
279
+ /**
280
+ * Trigger event to all subscribers in this room.
281
+ * Validates data against schema if event has one.
282
+ * @returns Result<void, string> - Ok if successful, Err with validation message if failed
283
+ */
284
+ trigger<T>(event: EventDefinition<T>, data: T, from?: string, meta?: Record<string, unknown>): Result<void, string>;
285
+ /**
286
+ * Subscribe to events in this room with a callback.
287
+ * For backend side-effects like logging, persistence, notifications.
288
+ * @returns Unsubscribe function
289
+ */
290
+ on<T>(event: EventDefinition<T>, handler: (msg: EventMessage<T>) => void | Promise<void>): () => void;
291
+ /** Current connection count */
292
+ size(): number;
293
+ /** Check if room is at maxSize capacity */
294
+ isFull(): boolean;
295
+ /** Get all participants in this room */
296
+ participants(): ConnectedClient[];
297
+ /**
298
+ * Get historical events for this room (paginated, newest first).
299
+ * @param eventName - Event type to get history for
300
+ * @param start - Starting index (0 = most recent)
301
+ * @param end - Ending index (exclusive)
302
+ * @returns Events from start to end, empty array if event has no history
303
+ */
304
+ history(eventName: string, start: number, end: number): Promise<EventMessage[]>;
305
+ }
306
+ /**
307
+ * Connected client - represents a connected socket with user context.
308
+ * Provides methods for room management and event subscriptions.
309
+ */
310
+ interface ConnectedClient {
311
+ /** Unique client/session ID */
312
+ readonly id: string;
313
+ /** Application user ID from auth */
314
+ readonly userId: string;
315
+ /** Underlying Socket.IO socket */
316
+ readonly socket: Socket;
317
+ /** Additional user metadata (role, permissions, etc.) */
318
+ readonly meta: Record<string, unknown>;
319
+ /** Authentication data (JWT claims and related info) */
320
+ readonly auth?: AuthData;
321
+ /** Join a room by ID */
322
+ join(roomId: string): void;
323
+ /** Leave a room by ID */
324
+ leave(roomId: string): void;
325
+ /** Subscribe to specific event in a room */
326
+ subscribe(roomId: string, eventName: string): void;
327
+ /** Subscribe to all events in a room (wildcard) */
328
+ subscribeAll(roomId: string): void;
329
+ /** Unsubscribe from event in a room */
330
+ unsubscribe(roomId: string, eventName: string): void;
331
+ /** Get list of room IDs this client is in */
332
+ rooms(): string[];
333
+ /** Get subscribed event names for a room */
334
+ subscriptions(roomId: string): string[];
335
+ /** Send data directly to this client only */
336
+ send<T>(event: string, data: T): void;
337
+ /** Disconnect this client */
338
+ disconnect(): void;
339
+ }
340
+ /**
341
+ * Represents a user's rooms with helper methods.
342
+ * Returned by dialogue.getClientRooms() for managing user room membership.
343
+ */
344
+ interface ClientRooms {
345
+ /** Array of room IDs the user is currently in */
346
+ readonly ids: string[];
347
+ /**
348
+ * Execute a callback for each room the user is in.
349
+ * Does not modify room membership - use for broadcasting, logging, etc.
350
+ * @param callback - Function called for each room
351
+ */
352
+ forAll(callback: (roomId: string) => void): void;
353
+ /**
354
+ * Remove the user from all rooms.
355
+ * Optionally execute a callback for each room before leaving.
356
+ * @param callback - Optional function called for each room before leaving
357
+ */
358
+ leaveAll(callback?: (roomId: string) => void): void;
359
+ }
360
+ /**
361
+ * Main Dialogue instance - the core API returned by createDialogue.
362
+ * Use this to trigger events, subscribe to events, and manage rooms.
363
+ */
364
+ interface Dialogue {
365
+ /** The Hono app instance (provided or created) */
366
+ readonly app: Hono;
367
+ /** The Socket.IO server instance */
368
+ readonly io: Server;
369
+ /**
370
+ * Trigger event to all subscribers in a room.
371
+ * Call this from anywhere in your backend (API routes, jobs, webhooks).
372
+ * @returns Result<void, string> - Ok if successful, Err with validation message if failed
373
+ */
374
+ trigger<T>(roomId: string, event: EventDefinition<T>, data: T, from?: string, meta?: Record<string, unknown>): Result<void, string>;
375
+ /**
376
+ * Subscribe with callback for backend side-effects.
377
+ * Useful for logging, persistence, triggering other events.
378
+ * @returns Unsubscribe function
379
+ */
380
+ on<T>(roomId: string, event: EventDefinition<T>, handler: (msg: EventMessage<T>) => void | Promise<void>): () => void;
381
+ /** Get room by ID */
382
+ room(id: string): Room | null;
383
+ /** Get all rooms */
384
+ rooms(): Room[];
385
+ /**
386
+ * Create a new room at runtime
387
+ * @param id - Unique room identifier
388
+ * @param config - Room configuration
389
+ * @returns The created Room instance, or null if room already exists
390
+ */
391
+ createRoom(id: string, config: RoomConfig): Room | null;
392
+ /**
393
+ * Delete a room at runtime
394
+ * @param id - Room ID to delete
395
+ * @returns true if room was deleted, false if it didn't exist
396
+ */
397
+ deleteRoom(id: string): boolean;
398
+ /**
399
+ * Get a connected client by user ID.
400
+ * Returns array since a user may have multiple connections (tabs/devices).
401
+ * @param userId - The user ID to look up
402
+ * @returns Array of connected clients for this user
403
+ */
404
+ getClients(userId: string): ConnectedClient[];
405
+ /**
406
+ * Get all connected clients
407
+ * @returns Array of all connected clients
408
+ */
409
+ getAllClients(): ConnectedClient[];
410
+ /**
411
+ * Get rooms that a user is currently in with helper methods.
412
+ * Aggregates rooms across all connections for this user.
413
+ * @param userId - The user ID to look up
414
+ * @returns ClientRooms object with room IDs and utility methods
415
+ */
416
+ getClientRooms(userId: string): ClientRooms;
417
+ /**
418
+ * Check if a user is in a specific room
419
+ * @param userId - The user ID to check
420
+ * @param roomId - The room ID to check
421
+ * @returns true if the user is in the room
422
+ */
423
+ isInRoom(userId: string, roomId: string): boolean;
424
+ /** Start the server */
425
+ start(): Promise<void>;
426
+ /** Stop the server */
427
+ stop(): Promise<void>;
428
+ }
429
+ /**
430
+ * Internal room manager interface - used internally to coordinate rooms.
431
+ */
432
+ interface RoomManager {
433
+ get(id: string): Room | null;
434
+ all(): Room[];
435
+ addParticipant(roomId: string, client: ConnectedClient): boolean;
436
+ removeParticipant(roomId: string, clientId: string): void;
437
+ }
438
+
439
+ /**
440
+ * Creates a Dialogue instance from configuration.
441
+ * This is the main entry point for the library.
442
+ *
443
+ * @param config - Dialogue configuration with rooms, events, and handlers
444
+ * @returns Dialogue instance for triggering events, subscribing, and server control
445
+ *
446
+ * @example
447
+ * // Basic setup with rooms defined upfront
448
+ * const dialogue = createDialogue({
449
+ * port: 3000,
450
+ * rooms: {
451
+ * chat: {
452
+ * name: 'Chat Room',
453
+ * events: [Message, Typing],
454
+ * defaultSubscriptions: ['message'],
455
+ * syncHistoryOnJoin: true,
456
+ * }
457
+ * },
458
+ * hooks: {
459
+ * clients: {
460
+ * onConnected: (client) => {
461
+ * client.join('chat')
462
+ * },
463
+ * onDisconnected: (client) => {
464
+ * console.log('Client disconnected:', client.userId)
465
+ * }
466
+ * },
467
+ * events: {
468
+ * onCleanup: async (roomId, eventName, events) => {
469
+ * await db.events.insertMany(events)
470
+ * }
471
+ * }
472
+ * }
473
+ * })
474
+ *
475
+ * // Use elsewhere in your app
476
+ * dialogue.trigger('chat', Message, { text: 'Hello!' })
477
+ *
478
+ * // Start the server
479
+ * await dialogue.start()
480
+ */
481
+ declare function createDialogue(config: DialogueConfig): Dialogue;
482
+
483
+ /**
484
+ * Options for defining an event
485
+ */
486
+ interface DefineEventOptions<T> {
487
+ /** Zod schema for validating event data */
488
+ schema?: z.ZodType<T>;
489
+ /** Human-readable description of the event */
490
+ description?: string;
491
+ /** History configuration - when enabled, events are stored in memory */
492
+ history?: EventHistoryConfig;
493
+ }
494
+ /**
495
+ * Creates a typed event definition for use in rooms.
496
+ * Events are immutable once created.
497
+ *
498
+ * @param name - Unique event name (e.g., 'message', 'order:updated')
499
+ * @param options - Optional schema and description
500
+ * @returns Frozen event definition object
501
+ *
502
+ * @example
503
+ * // Simple event without validation
504
+ * const Typing = defineEvent('typing')
505
+ *
506
+ * @example
507
+ * // Event with Zod schema validation
508
+ * const Message = defineEvent('message', {
509
+ * schema: z.object({
510
+ * text: z.string().min(1).max(1000),
511
+ * senderId: z.string()
512
+ * }),
513
+ * description: 'Chat message sent by a user',
514
+ * history: { enabled: true, limit: 50 }
515
+ * })
516
+ *
517
+ * @example
518
+ * // Event with inferred type from schema
519
+ * const OrderUpdated = defineEvent('order:updated', {
520
+ * schema: z.object({
521
+ * orderId: z.string(),
522
+ * status: z.enum(['pending', 'shipped', 'delivered'])
523
+ * })
524
+ * })
525
+ * // Type of data is inferred as { orderId: string, status: 'pending' | 'shipped' | 'delivered' }
526
+ */
527
+ declare function defineEvent<T = unknown>(name: string, options?: DefineEventOptions<T>): EventDefinition<T>;
528
+ /**
529
+ * Validates event data against its schema if one exists.
530
+ * Returns a Result with either parsed data or error message.
531
+ *
532
+ * @param event - The event definition with optional schema
533
+ * @param data - Data to validate
534
+ * @returns Result<T, string> - Ok with data or Err with validation message
535
+ */
536
+ declare function validateEventData<T>(event: EventDefinition<T>, data: unknown): Result<T, string>;
537
+ /**
538
+ * Checks if an event is allowed in a room based on its event definitions.
539
+ * - Empty array: No events allowed (reject all)
540
+ * - Wildcard "*": All events allowed (accept all)
541
+ * - Specific events: Only listed events allowed
542
+ *
543
+ * @param eventName - Name of the event to check
544
+ * @param allowedEvents - List of allowed events for the room
545
+ * @returns True if event is allowed (explicit match or wildcard)
546
+ */
547
+ declare function isEventAllowed(eventName: string, allowedEvents: EventDefinition<unknown>[]): boolean;
548
+ /**
549
+ * Gets an event definition by name from a list of events.
550
+ *
551
+ * @param eventName - Name of the event to find
552
+ * @param events - List of event definitions to search
553
+ * @returns The event definition or undefined if not found
554
+ */
555
+ declare function getEventByName(eventName: string, events: EventDefinition<unknown>[]): EventDefinition<unknown> | undefined;
556
+
557
+ /**
558
+ * Configuration for the history manager
559
+ */
560
+ interface HistoryManagerConfig {
561
+ /** Called when events are evicted from in-memory history (oldest first) */
562
+ onCleanup?: (roomId: string, eventName: string, events: EventMessage[]) => void | Promise<void>;
563
+ /** Called to load historical events beyond in-memory (for pagination) */
564
+ onLoad?: (roomId: string, eventName: string, start: number, end: number) => Promise<EventMessage[]>;
565
+ }
566
+ /**
567
+ * History manager instance returned by createHistoryManager
568
+ */
569
+ interface HistoryManager {
570
+ /** Add an event to history, evict oldest if exceeds limit */
571
+ push(roomId: string, eventName: string, event: EventMessage, limit: number): void;
572
+ /** Get events (0 = newest, reads backward) */
573
+ get(roomId: string, eventName: string, start: number, end: number): EventMessage[];
574
+ /** Get all events for a room across all event types, sorted newest first */
575
+ getAll(roomId: string, limit?: number): EventMessage[];
576
+ /** Get total count of events for a specific event type in a room */
577
+ count(roomId: string, eventName: string): number;
578
+ /** Clear all history for a room */
579
+ clearRoom(roomId: string): void;
580
+ /** Get event names that have history for a room */
581
+ getEventNames(roomId: string): string[];
582
+ }
583
+ /**
584
+ * Creates a history manager for storing events in memory.
585
+ * Stores per-room, per-event-type with FIFO eviction (oldest first).
586
+ *
587
+ * @param config - Configuration with optional cleanup and load callbacks
588
+ * @returns HistoryManager instance
589
+ *
590
+ * @example
591
+ * const history = createHistoryManager({
592
+ * onCleanup: async (roomId, eventName, events) => {
593
+ * await db.events.insertMany(events);
594
+ * }
595
+ * });
596
+ *
597
+ * // Push an event
598
+ * history.push("room-1", "message", eventMessage, 50);
599
+ *
600
+ * // Get last 10 messages (newest first)
601
+ * const recent = history.get("room-1", "message", 0, 10);
602
+ */
603
+ declare function createHistoryManager(config?: HistoryManagerConfig): HistoryManager;
604
+
605
+ /**
606
+ * Creates the default console-based logger for Dialogue.
607
+ * Outputs structured log entries as JSON-like objects.
608
+ *
609
+ * @returns Logger implementation using console methods
610
+ */
611
+ declare function createDefaultLogger(): Logger;
612
+ /**
613
+ * Creates a silent logger that does not output anything.
614
+ * Useful for testing or when logging is not desired.
615
+ *
616
+ * @returns Logger implementation that does nothing
617
+ */
618
+ declare function createSilentLogger(): Logger;
619
+
620
+ /**
621
+ * Rate limiter configuration
622
+ */
623
+ interface RateLimiterConfig {
624
+ /** Maximum number of requests allowed in the window */
625
+ maxRequests: number;
626
+ /** Time window in milliseconds */
627
+ windowMs: number;
628
+ }
629
+ /**
630
+ * Rate limiter instance returned by createRateLimiter
631
+ */
632
+ interface RateLimiter {
633
+ /**
634
+ * Check if a request is allowed for the given key.
635
+ * Returns true if allowed, false if rate limited.
636
+ */
637
+ isAllowed(key: string): boolean;
638
+ /**
639
+ * Get remaining requests for the given key
640
+ */
641
+ remaining(key: string): number;
642
+ /**
643
+ * Clear all rate limit data (useful for testing)
644
+ */
645
+ clear(): void;
646
+ }
647
+ /**
648
+ * Creates a simple in-memory rate limiter using sliding window algorithm.
649
+ * Tracks requests per key (typically socket ID or user ID) and enforces limits.
650
+ *
651
+ * @param config - Rate limiter configuration
652
+ * @returns RateLimiter instance
653
+ *
654
+ * @example
655
+ * const limiter = createRateLimiter({ maxRequests: 10, windowMs: 60000 });
656
+ *
657
+ * if (!limiter.isAllowed(socketId)) {
658
+ * socket.emit("dialogue:error", { code: "RATE_LIMITED" });
659
+ * return;
660
+ * }
661
+ */
662
+ declare function createRateLimiter(config: RateLimiterConfig): RateLimiter;
663
+
664
+ export { type AuthData, type AuthenticateResult, type ConnectedClient, type CorsConfig, type Dialogue, type DialogueConfig, type DialogueContext, type EventDefinition, type EventHistoryConfig, type EventMessage, type HistoryManager, type HistoryManagerConfig, type HooksConfig, type JwtClaims, type LogEntry, type Logger, type RateLimiter, type RateLimiterConfig, type Room, type RoomConfig, type RoomManager, createDefaultLogger, createDialogue, createHistoryManager, createRateLimiter, createSilentLogger, defineEvent, getEventByName, isEventAllowed, validateEventData };