@mesh-kit/server 2.0.0 → 2.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,1129 @@
1
+ import { ServerOptions, WebSocket, WebSocketServer } from 'ws';
2
+ export { ServerOptions } from 'ws';
3
+ import { LogLevel, Status, Command } from '@mesh-kit/shared';
4
+ import { EventEmitter } from 'node:events';
5
+ import { IncomingMessage } from 'node:http';
6
+ import Redis, { RedisOptions, Redis as Redis$1 } from 'ioredis';
7
+ import { Operation } from 'fast-json-patch';
8
+ import { EventEmitter as EventEmitter$1 } from 'events';
9
+
10
+ declare class Latency {
11
+ start: number;
12
+ end: number;
13
+ ms: number;
14
+ interval?: ReturnType<typeof setTimeout>;
15
+ onRequest(): void;
16
+ onResponse(): void;
17
+ }
18
+
19
+ declare class Ping {
20
+ interval?: ReturnType<typeof setTimeout>;
21
+ }
22
+
23
+ declare class MeshContext<T = any> {
24
+ server: MeshServer;
25
+ command: string;
26
+ connection: Connection;
27
+ payload: T;
28
+ constructor(server: MeshServer, command: string, connection: Connection, payload: T);
29
+ }
30
+
31
+ interface PersistenceAdapter {
32
+ initialize(): Promise<void>;
33
+ storeMessages(messages: PersistedMessage[]): Promise<void>;
34
+ getMessages(channel: string, since?: string | number, limit?: number): Promise<PersistedMessage[]>;
35
+ storeRecords?(records: PersistedRecord[]): Promise<void>;
36
+ getRecords?(pattern: string): Promise<PersistedRecord[]>;
37
+ close(): Promise<void>;
38
+ }
39
+ interface PersistedMessage {
40
+ id: string;
41
+ channel: string;
42
+ message: string;
43
+ instanceId: string;
44
+ timestamp: number;
45
+ metadata?: Record<string, any>;
46
+ }
47
+ interface ChannelPersistenceOptions {
48
+ /**
49
+ * Maximum number of messages to retain per channel
50
+ * @default 50
51
+ */
52
+ historyLimit?: number;
53
+ /**
54
+ * Function to filter messages for persistence
55
+ * Return false to skip persistence for a specific message
56
+ */
57
+ filter?: (message: string, channel: string) => boolean;
58
+ /**
59
+ * Optional adapter override for this pattern
60
+ */
61
+ adapter?: PersistenceAdapter;
62
+ /**
63
+ * How often (in ms) to flush buffered messages to the database
64
+ * @default 500
65
+ */
66
+ flushInterval?: number;
67
+ /**
68
+ * Maximum number of messages to hold in memory per channel
69
+ * If this limit is reached, the buffer is flushed immediately
70
+ * @default 100
71
+ */
72
+ maxBufferSize?: number;
73
+ }
74
+ interface RecordPersistenceOptions {
75
+ /**
76
+ * Optional adapter override for this pattern
77
+ */
78
+ adapter?: PersistenceAdapter;
79
+ /**
80
+ * How often (in ms) to flush buffered records to the database
81
+ * @default 500
82
+ */
83
+ flushInterval?: number;
84
+ /**
85
+ * Maximum number of records to hold in memory before flushing
86
+ * If this limit is reached, the buffer is flushed immediately
87
+ * @default 100
88
+ */
89
+ maxBufferSize?: number;
90
+ }
91
+ interface PersistedRecord {
92
+ recordId: string;
93
+ version: number;
94
+ value: string;
95
+ timestamp: number;
96
+ }
97
+ interface PersistenceAdapterOptions {
98
+ /**
99
+ * Database file path for file-based adapters
100
+ * @default ":memory:"
101
+ */
102
+ filename?: string;
103
+ }
104
+ interface PostgreSQLAdapterOptions extends PersistenceAdapterOptions {
105
+ connectionString?: string;
106
+ host?: string;
107
+ port?: number;
108
+ database?: string;
109
+ user?: string;
110
+ password?: string;
111
+ ssl?: boolean;
112
+ max?: number;
113
+ }
114
+
115
+ type SocketMiddleware = (context: MeshContext<any>) => any | Promise<any>;
116
+ interface MeshServerOptions extends ServerOptions {
117
+ /**
118
+ * The interval at which to send ping messages to the client.
119
+ *
120
+ * @default 30000
121
+ */
122
+ pingInterval?: number;
123
+ /**
124
+ * The interval at which to send both latency requests and updates to the client.
125
+ *
126
+ * @default 5000
127
+ */
128
+ latencyInterval?: number;
129
+ redisOptions: RedisOptions;
130
+ /**
131
+ * Whether to enable Redis keyspace notifications for presence expiration.
132
+ * When enabled, connections will be automatically marked as offline when their presence TTL expires.
133
+ *
134
+ * @default true
135
+ */
136
+ enablePresenceExpirationEvents?: boolean;
137
+ /**
138
+ * The maximum number of consecutive ping intervals the server will wait
139
+ * for a pong response before considering the client disconnected.
140
+ * A value of 1 means the client must respond within roughly 2 * pingInterval
141
+ * before being disconnected. Setting it to 0 is not recommended as it will
142
+ * immediately disconnect the client if it doesn't respond to the first ping in
143
+ * exactly `pingInterval` milliseconds, which doesn't provide wiggle room for
144
+ * network latency.
145
+ *
146
+ * @see pingInterval
147
+ * @default 1
148
+ */
149
+ maxMissedPongs?: number;
150
+ /**
151
+ * The log level for server-side logs.
152
+ * Controls which messages are displayed in the console.
153
+ *
154
+ * @default LogLevel.ERROR
155
+ */
156
+ logLevel?: LogLevel;
157
+ /**
158
+ * Options for the persistence layer.
159
+ * By default, persistence uses an in-memory SQLite database.
160
+ * To persist data across restarts, specify a file path.
161
+ *
162
+ * @example
163
+ * ```
164
+ * persistenceOptions: {
165
+ * filename: "./data/channels.db"
166
+ * }
167
+ * ```
168
+ */
169
+ persistenceOptions?: PersistenceAdapterOptions | PostgreSQLAdapterOptions;
170
+ /**
171
+ * Adapter type for persistence layer.
172
+ * @default "sqlite"
173
+ */
174
+ persistenceAdapter?: "sqlite" | "postgres";
175
+ }
176
+ type ChannelPattern$1 = string | RegExp;
177
+
178
+ declare class Connection extends EventEmitter {
179
+ id: string;
180
+ socket: WebSocket;
181
+ alive: boolean;
182
+ missedPongs: number;
183
+ latency: Latency;
184
+ ping: Ping;
185
+ remoteAddress: string;
186
+ connectionOptions: MeshServerOptions;
187
+ status: Status;
188
+ server: MeshServer;
189
+ constructor(socket: WebSocket, req: IncomingMessage, options: MeshServerOptions, server: MeshServer);
190
+ get isDead(): boolean;
191
+ private startIntervals;
192
+ stopIntervals(): void;
193
+ private applyListeners;
194
+ send(cmd: Command): boolean;
195
+ close(): Promise<boolean>;
196
+ }
197
+
198
+ declare class RoomManager {
199
+ private redis;
200
+ constructor(options: {
201
+ redis: Redis;
202
+ });
203
+ private roomKey;
204
+ private connectionsRoomKey;
205
+ private roomMetadataKey;
206
+ /**
207
+ * Retrieves all connection IDs associated with the specified room.
208
+ *
209
+ * @param {string} roomName - The name of the room for which to fetch connection IDs.
210
+ * @returns {Promise<string[]>} A promise that resolves to an array of connection IDs in the room.
211
+ * @throws {Error} If there is an issue communicating with Redis or retrieving the data, the promise will be rejected with an error.
212
+ */
213
+ getRoomConnectionIds(roomName: string): Promise<string[]>;
214
+ /**
215
+ * Checks whether a given connection (by object or ID) is a member of a specified room.
216
+ *
217
+ * @param {string} roomName - The name of the room to check for membership.
218
+ * @param {Connection | string} connection - The connection object or connection ID to check.
219
+ * @returns {Promise<boolean>} A promise that resolves to true if the connection is in the room, false otherwise.
220
+ * @throws {Error} If there is an issue communicating with Redis or processing the request, the promise may be rejected with an error.
221
+ */
222
+ connectionIsInRoom(roomName: string, connection: Connection | string): Promise<boolean>;
223
+ /**
224
+ * Adds a connection to a specified room, associating the connection ID with the room name
225
+ * in Redis. Supports both `Connection` objects and connection IDs as strings.
226
+ *
227
+ * @param {string} roomName - The name of the room to add the connection to.
228
+ * @param {Connection | string} connection - The connection object or connection ID to add to the room.
229
+ * @returns {Promise<void>} A promise that resolves when the operation is complete.
230
+ * @throws {Error} If an error occurs while updating Redis, the promise will be rejected with the error.
231
+ */
232
+ addToRoom(roomName: string, connection: Connection | string): Promise<void>;
233
+ /**
234
+ * Retrieves a list of rooms that the specified connection is currently a member of.
235
+ *
236
+ * @param {Connection | string} connection - The connection object or connection ID for which to retrieve room memberships.
237
+ * @returns {Promise<string[]>} A promise that resolves to an array of room names associated with the connection.
238
+ * @throws {Error} If the underlying Redis operation fails, the promise will be rejected with an error.
239
+ */
240
+ getRoomsForConnection(connection: Connection | string): Promise<string[]>;
241
+ /**
242
+ * Retrieves all room names from Redis.
243
+ *
244
+ * @returns {Promise<string[]>} A promise that resolves to an array of all room names.
245
+ * @throws {Error} If there is an issue communicating with Redis, the promise will be rejected with an error.
246
+ */
247
+ getAllRooms(): Promise<string[]>;
248
+ /**
249
+ * Removes a connection from a specified room and updates Redis accordingly.
250
+ * Accepts either a Connection object or a string representing the connection ID.
251
+ * Updates both the room's set of connections and the connection's set of rooms in Redis.
252
+ *
253
+ * @param {string} roomName - The name of the room from which to remove the connection.
254
+ * @param {Connection | string} connection - The connection to be removed, specified as either a Connection object or a connection ID string.
255
+ * @returns {Promise<void>} A promise that resolves when the removal is complete.
256
+ * @throws {Error} If there is an error executing the Redis pipeline, the promise will be rejected with the error.
257
+ */
258
+ removeFromRoom(roomName: string, connection: Connection | string): Promise<void>;
259
+ /**
260
+ * Removes the specified connection from all rooms it is a member of and deletes its room membership record.
261
+ *
262
+ * @param {Connection | string} connection - The connection object or its unique identifier to be removed from all rooms.
263
+ * @returns {Promise<void>} A promise that resolves once the removal from all rooms is complete.
264
+ * @throws {Error} If an error occurs during Redis operations, the promise will be rejected with the error.
265
+ */
266
+ removeFromAllRooms(connection: Connection | string): Promise<void>;
267
+ /**
268
+ * Removes all connections from the specified room but preserves room metadata.
269
+ * This clears the room occupants without destroying the room's configuration.
270
+ *
271
+ * @param {string} roomName - The name of the room to be cleared of occupants.
272
+ * @returns {Promise<void>} A promise that resolves when all occupants have been removed from the room.
273
+ * @throws {Error} If an error occurs while interacting with Redis, the promise will be rejected with the error.
274
+ */
275
+ clearRoom(roomName: string): Promise<void>;
276
+ /**
277
+ * Completely deletes the specified room, removing all occupants and destroying
278
+ * all associated room metadata. This permanently removes the room from the system.
279
+ *
280
+ * @param {string} roomName - The name of the room to be completely deleted.
281
+ * @returns {Promise<void>} A promise that resolves when the room has been completely deleted.
282
+ * @throws {Error} If an error occurs while interacting with Redis, the promise will be rejected with the error.
283
+ */
284
+ deleteRoom(roomName: string): Promise<void>;
285
+ /**
286
+ * Cleans up all Redis references for a given connection by removing the connection
287
+ * from all rooms it is associated with and deleting the connection's room key.
288
+ *
289
+ * @param {Connection} connection - The connection object whose references should be cleaned up.
290
+ * @returns {Promise<void>} A promise that resolves when the cleanup is complete.
291
+ * @throws {Error} If an error occurs while interacting with Redis, the promise will be rejected with the error.
292
+ */
293
+ cleanupConnection(connection: Connection): Promise<void>;
294
+ /**
295
+ * Sets the metadata for a given room by storing the serialized metadata
296
+ * object in Redis under the room's metadata key.
297
+ *
298
+ * @param {string} roomName - The unique name of the room whose metadata is being set.
299
+ * @param {any} metadata - The metadata object to associate with the room, or partial metadata when using merge strategy.
300
+ * @param {{ strategy?: "replace" | "merge" | "deepMerge" }} [options] - Update options: strategy defaults to "replace" which replaces the entire metadata, "merge" merges with existing metadata properties, "deepMerge" recursively merges nested objects.
301
+ * @returns {Promise<void>} A promise that resolves when the metadata has been successfully set.
302
+ * @throws {Error} If an error occurs while storing metadata in Redis, the promise will be rejected with the error.
303
+ */
304
+ setMetadata(roomName: string, metadata: any, options?: {
305
+ strategy?: "replace" | "merge" | "deepMerge";
306
+ }): Promise<void>;
307
+ /**
308
+ * Retrieves and parses metadata associated with the specified room from Redis storage.
309
+ *
310
+ * @param {string} roomName - The name of the room whose metadata is to be retrieved.
311
+ * @returns {Promise<any | null>} A promise that resolves to the parsed metadata object if found,
312
+ * or null if no metadata exists for the given room.
313
+ * @throws {SyntaxError} If the retrieved data is not valid JSON and cannot be parsed.
314
+ * @throws {Error} If there is an issue communicating with Redis.
315
+ */
316
+ getMetadata(roomName: string): Promise<any | null>;
317
+ /**
318
+ * Retrieves and returns all room metadata stored in Redis.
319
+ * Fetches all keys matching the pattern "mesh:roommeta:*", retrieves their "data" fields,
320
+ * parses them as JSON, and returns an array of room objects with id and metadata.
321
+ *
322
+ * @returns {Promise<Array<{ id: string, metadata: any }>>} A promise that resolves to an array of room objects.
323
+ * @throws {SyntaxError} If the stored metadata cannot be parsed as JSON, an error is logged and the room is omitted from the result.
324
+ */
325
+ getAllMetadata(): Promise<Array<{
326
+ id: string;
327
+ metadata: any;
328
+ }>>;
329
+ }
330
+
331
+ declare class ConnectionManager {
332
+ private redis;
333
+ private instanceId;
334
+ private localConnections;
335
+ private roomManager;
336
+ constructor(options: {
337
+ redis: Redis;
338
+ instanceId: string;
339
+ roomManager: RoomManager;
340
+ });
341
+ getLocalConnections(): Connection[];
342
+ getLocalConnection(id: string): Connection | null;
343
+ registerConnection(connection: Connection): Promise<void>;
344
+ private getInstanceConnectionsKey;
345
+ private deregisterConnection;
346
+ private getInstanceIdForConnection;
347
+ getInstanceIdsForConnections(connectionIds: string[]): Promise<{
348
+ [connectionId: string]: string | null;
349
+ }>;
350
+ getAllConnectionIds(): Promise<string[]>;
351
+ getLocalConnectionIds(): Promise<string[]>;
352
+ /**
353
+ * Sets metadata for a given connection in the Redis hash.
354
+ * Serializes the metadata as a JSON string and stores it under the connection's ID.
355
+ *
356
+ * @param {Connection} connection - The connection object whose metadata is being set.
357
+ * @param {any} metadata - The metadata to associate with the connection, or partial metadata when using merge strategy.
358
+ * @param {{ strategy?: "replace" | "merge" | "deepMerge" }} [options] - Update options: strategy defaults to "replace" which replaces the entire metadata, "merge" merges with existing metadata properties, "deepMerge" recursively merges nested objects.
359
+ * @returns {Promise<void>} A promise that resolves when the metadata has been successfully set.
360
+ * @throws {Error} If an error occurs while executing the Redis pipeline.
361
+ */
362
+ setMetadata(connection: Connection, metadata: any, options?: {
363
+ strategy?: "replace" | "merge" | "deepMerge";
364
+ }): Promise<void>;
365
+ /**
366
+ * Retrieves and parses metadata for the given connection from Redis.
367
+ *
368
+ * @param {Connection} connection - The connection object whose metadata is to be retrieved.
369
+ * @returns {Promise<any|null>} A promise that resolves to the parsed metadata object if found, or null if no metadata exists.
370
+ * @throws {SyntaxError} If the stored metadata is not valid JSON and fails to parse.
371
+ * @throws {Error} If a Redis error occurs during retrieval.
372
+ */
373
+ getMetadata(connection: Connection): Promise<any | null>;
374
+ /**
375
+ * Retrieves metadata for all available connections by fetching all connection IDs,
376
+ * obtaining their associated metadata, and parsing the metadata as JSON.
377
+ *
378
+ * @returns {Promise<Array<{ id: string, metadata: any }>>}
379
+ * A promise that resolves to an array of connection objects with id and metadata properties.
380
+ * @throws {Error} If an error occurs while fetching connection IDs, retrieving metadata, or parsing JSON.
381
+ */
382
+ getAllMetadata(): Promise<Array<{
383
+ id: string;
384
+ metadata: any;
385
+ }>>;
386
+ /**
387
+ * Retrieves all metadata objects for each connection in the specified room.
388
+ * Returns an array of connection objects with id and metadata properties.
389
+ * If no metadata is found for a connection, the metadata value is set to null.
390
+ *
391
+ * @param {string} roomName - The name of the room for which to retrieve connection metadata.
392
+ * @returns {Promise<Array<{ id: string, metadata: any }>>} A promise that resolves to an array of
393
+ * connection objects with id and metadata properties (metadata is null if not available).
394
+ * @throws {Error} If there is an error retrieving connection IDs or metadata, the promise will be rejected with the error.
395
+ */
396
+ getAllMetadataForRoom(roomName: string): Promise<Array<{
397
+ id: string;
398
+ metadata: any;
399
+ }>>;
400
+ cleanupConnection(connection: Connection): Promise<void>;
401
+ }
402
+
403
+ declare class RedisManager {
404
+ private _redis;
405
+ private _pubClient;
406
+ private _subClient;
407
+ private _isShuttingDown;
408
+ /**
409
+ * Initializes Redis connections with the provided options
410
+ *
411
+ * @param options - Redis connection options
412
+ * @param onError - Error handler callback
413
+ */
414
+ initialize(options: RedisOptions, onError: (err: Error) => void): void;
415
+ /**
416
+ * Gets the main Redis client
417
+ *
418
+ * @returns The Redis client
419
+ * @throws Error if Redis is not initialized
420
+ */
421
+ get redis(): Redis$1;
422
+ /**
423
+ * Gets the Redis client for publishing
424
+ *
425
+ * @returns The publishing Redis client
426
+ * @throws Error if Redis is not initialized
427
+ */
428
+ get pubClient(): Redis$1;
429
+ /**
430
+ * Gets the Redis client for subscribing
431
+ *
432
+ * @returns The subscribing Redis client
433
+ * @throws Error if Redis is not initialized
434
+ */
435
+ get subClient(): Redis$1;
436
+ /**
437
+ * Disconnects all Redis clients
438
+ */
439
+ disconnect(): void;
440
+ /**
441
+ * Checks if Redis is shutting down
442
+ *
443
+ * @returns true if Redis is shutting down, false otherwise
444
+ */
445
+ get isShuttingDown(): boolean;
446
+ /**
447
+ * Sets the shutting down state
448
+ *
449
+ * @param value - The new shutting down state
450
+ */
451
+ set isShuttingDown(value: boolean);
452
+ /**
453
+ * Enables Redis keyspace notifications for expired events by updating the
454
+ * "notify-keyspace-events" configuration. Ensures that both keyevent ('E')
455
+ * and expired event ('x') notifications are enabled. If they are not already
456
+ * present, the method appends them to the current configuration.
457
+ *
458
+ * @returns {Promise<void>} A promise that resolves when the configuration has been updated.
459
+ * @throws {Error} If the Redis CONFIG commands fail or the connection encounters an error.
460
+ */
461
+ enableKeyspaceNotifications(): Promise<void>;
462
+ }
463
+
464
+ type ChannelPattern = string | RegExp;
465
+ declare class PresenceManager {
466
+ private redis;
467
+ private roomManager;
468
+ private redisManager;
469
+ private presenceExpirationEventsEnabled;
470
+ private getExpiredEventsPattern;
471
+ private readonly PRESENCE_KEY_PATTERN;
472
+ private readonly PRESENCE_STATE_KEY_PATTERN;
473
+ private trackedRooms;
474
+ private roomGuards;
475
+ private roomTTLs;
476
+ private defaultTTL;
477
+ constructor(options: {
478
+ redis: Redis$1;
479
+ roomManager: RoomManager;
480
+ redisManager: RedisManager;
481
+ enableExpirationEvents?: boolean;
482
+ });
483
+ /**
484
+ * Subscribes to Redis keyspace notifications for expired presence keys
485
+ */
486
+ private subscribeToExpirationEvents;
487
+ /**
488
+ * Handles an expired key notification
489
+ */
490
+ private handleExpiredKey;
491
+ trackRoom(roomPattern: ChannelPattern, guardOrOptions?: ((connection: Connection, roomName: string) => Promise<boolean> | boolean) | {
492
+ ttl?: number;
493
+ guard?: (connection: Connection, roomName: string) => Promise<boolean> | boolean;
494
+ }): void;
495
+ isRoomTracked(roomName: string, connection?: Connection): Promise<boolean>;
496
+ getRoomTTL(roomName: string): number;
497
+ private presenceRoomKey;
498
+ private presenceConnectionKey;
499
+ private presenceStateKey;
500
+ markOnline(connectionId: string, roomName: string): Promise<void>;
501
+ markOffline(connectionId: string, roomName: string): Promise<void>;
502
+ refreshPresence(connectionId: string, roomName: string): Promise<void>;
503
+ getPresentConnections(roomName: string): Promise<string[]>;
504
+ private publishPresenceUpdate;
505
+ /**
506
+ * Publishes a presence state for a connection in a room
507
+ *
508
+ * @param connectionId The ID of the connection
509
+ * @param roomName The name of the room
510
+ * @param state The state object to publish
511
+ * @param expireAfter Optional TTL in milliseconds
512
+ */
513
+ publishPresenceState(connectionId: string, roomName: string, state: Record<string, any>, expireAfter?: number, silent?: boolean): Promise<void>;
514
+ /**
515
+ * Clears the presence state for a connection in a room
516
+ *
517
+ * @param connectionId The ID of the connection
518
+ * @param roomName The name of the room
519
+ */
520
+ clearPresenceState(connectionId: string, roomName: string): Promise<void>;
521
+ /**
522
+ * Gets the current presence state for a connection in a room
523
+ *
524
+ * @param connectionId The ID of the connection
525
+ * @param roomName The name of the room
526
+ * @returns The presence state or null if not found
527
+ */
528
+ getPresenceState(connectionId: string, roomName: string): Promise<Record<string, any> | null>;
529
+ /**
530
+ * Gets all presence states for a room
531
+ *
532
+ * @param roomName The name of the room
533
+ * @returns A map of connection IDs to their presence states
534
+ */
535
+ getAllPresenceStates(roomName: string): Promise<Map<string, Record<string, any>>>;
536
+ /**
537
+ * Publishes a presence state update to Redis
538
+ *
539
+ * @param roomName The name of the room
540
+ * @param connectionId The ID of the connection
541
+ * @param state The state object or null
542
+ */
543
+ private publishPresenceStateUpdate;
544
+ cleanupConnection(connection: Connection): Promise<void>;
545
+ /**
546
+ * Cleans up Redis subscriptions when the PresenceManager is being destroyed.
547
+ */
548
+ cleanup(): Promise<void>;
549
+ }
550
+
551
+ declare class RecordManager {
552
+ private redis;
553
+ private recordUpdateCallbacks;
554
+ private recordRemovedCallbacks;
555
+ private server;
556
+ constructor(options: {
557
+ redis: Redis$1;
558
+ server: MeshServer;
559
+ });
560
+ /**
561
+ * Gets the server instance associated with this record manager
562
+ */
563
+ getServer(): MeshServer;
564
+ /**
565
+ * Gets the Redis instance used by this record manager
566
+ * This is used by the persistence manager to restore records
567
+ */
568
+ getRedis(): Redis$1;
569
+ recordKey(recordId: string): string;
570
+ recordVersionKey(recordId: string): string;
571
+ /**
572
+ * Retrieves a record from Redis by its unique identifier. Attempts to parse
573
+ * the stored data as JSON before returning. If the record does not exist,
574
+ * returns null.
575
+ *
576
+ * @param {string} recordId - The unique identifier of the record to retrieve.
577
+ * @returns {Promise<any | null>} A promise that resolves to the parsed record object,
578
+ * or null if the record does not exist.
579
+ * @throws {SyntaxError} If the stored data is not valid JSON and cannot be parsed.
580
+ * @throws {Error} If an error occurs during the Redis operation.
581
+ */
582
+ getRecord(recordId: string): Promise<any | null>;
583
+ /**
584
+ * Retrieves the version number associated with the specified record ID from Redis.
585
+ * If no version is found, returns 0.
586
+ *
587
+ * @param {string} recordId - The unique identifier for the record whose version is to be retrieved.
588
+ * @returns {Promise<number>} A promise that resolves to the version number of the record. Returns 0 if not found.
589
+ * @throws {Error} If there is an issue communicating with Redis or parsing the version.
590
+ */
591
+ getVersion(recordId: string): Promise<number>;
592
+ /**
593
+ * Retrieves a record and its associated version from Redis.
594
+ * Fetches both the record data and its version by their respective keys.
595
+ *
596
+ * @param {string} recordId - The unique identifier for the record to retrieve.
597
+ * @returns {Promise<{ record: any | null; version: number }>}
598
+ * A promise that resolves to an object containing the parsed record (or null if not found)
599
+ * and its version number (0 if version data is not found or invalid).
600
+ * @throws {Error} If there is a Redis error or if JSON parsing fails for the record data.
601
+ */
602
+ getRecordAndVersion(recordId: string): Promise<{
603
+ record: any | null;
604
+ version: number;
605
+ }>;
606
+ /**
607
+ * Publishes an update to a record by computing and applying a JSON Patch,
608
+ * incrementing the version, and persisting the updated value and version in Redis.
609
+ * If there are no changes between the old and new value, returns null.
610
+ *
611
+ * @param {string} recordId - The unique identifier of the record to update.
612
+ * @param {any} newValue - The new value to set for the record, or partial value when using merge strategy.
613
+ * @param {"replace" | "merge" | "deepMerge"} [strategy="replace"] - Update strategy: "replace" (default) replaces the entire record, "merge" merges with existing object properties, "deepMerge" recursively merges nested objects.
614
+ * @returns {Promise<{ patch: Operation[]; version: number; finalValue: any } | null>}
615
+ * A promise resolving to an object containing the JSON Patch operations, new version number, and final merged value,
616
+ * or null if there were no changes to publish.
617
+ * @throws {Error} If there is a failure reading or writing to Redis, or during patch computation, the promise will be rejected with the error.
618
+ */
619
+ publishUpdate(recordId: string, newValue: any, strategy?: "replace" | "merge" | "deepMerge"): Promise<{
620
+ patch: Operation[];
621
+ version: number;
622
+ finalValue: any;
623
+ } | null>;
624
+ /**
625
+ * Deletes a record and its associated version from Redis storage.
626
+ *
627
+ * @param {string} recordId - The unique identifier of the record to be deleted.
628
+ * @returns {Promise<{ version: number }|null>} A promise that resolves to the final version of the deleted record, or null if the record didn't exist.
629
+ * @throws {Error} If an error occurs during the Redis pipeline execution, the promise will be rejected with the error.
630
+ */
631
+ deleteRecord(recordId: string): Promise<{
632
+ version: number;
633
+ } | null>;
634
+ /**
635
+ * Registers a callback function to be called when a record is updated.
636
+ *
637
+ * @param {(data: { recordId: string; value: any }) => Promise<void> | void} callback - The callback function to execute when a record is updated.
638
+ * @returns {() => void} A function that, when called, will unregister the callback.
639
+ */
640
+ onRecordUpdate(callback: (data: {
641
+ recordId: string;
642
+ value: any;
643
+ }) => Promise<void> | void): () => void;
644
+ /**
645
+ * Registers a callback function to be called when a record is removed.
646
+ *
647
+ * @param {(data: { recordId: string; value: any }) => Promise<void> | void} callback - The callback function to execute when a record is removed.
648
+ * @returns {() => void} A function that, when called, will unregister the callback.
649
+ */
650
+ onRecordRemoved(callback: (data: {
651
+ recordId: string;
652
+ value: any;
653
+ }) => Promise<void> | void): () => void;
654
+ }
655
+
656
+ declare class MeshServer extends WebSocketServer {
657
+ readonly instanceId: string;
658
+ private redisManager;
659
+ private instanceManager;
660
+ private commandManager;
661
+ private channelManager;
662
+ private pubSubManager;
663
+ private recordSubscriptionManager;
664
+ private collectionManager;
665
+ private broadcastManager;
666
+ private persistenceManager;
667
+ roomManager: RoomManager;
668
+ recordManager: RecordManager;
669
+ connectionManager: ConnectionManager;
670
+ presenceManager: PresenceManager;
671
+ serverOptions: MeshServerOptions;
672
+ status: Status;
673
+ private _listening;
674
+ get listening(): boolean;
675
+ set listening(value: boolean);
676
+ get port(): number;
677
+ constructor(opts: MeshServerOptions);
678
+ /**
679
+ * Waits until the service is ready by ensuring it is listening, the instance channel subscription is established,
680
+ * and the persistence manager is fully initialized.
681
+ *
682
+ * @returns {Promise<void>} A promise that resolves when the service is fully ready.
683
+ * @throws {Error} If the readiness process fails or if any awaited promise rejects.
684
+ */
685
+ ready(): Promise<void>;
686
+ private applyListeners;
687
+ /**
688
+ * Registers a command with an associated callback and optional middleware.
689
+ *
690
+ * @template T The type for `MeshContext.payload`. Defaults to `any`.
691
+ * @template U The command's return value type. Defaults to `any`.
692
+ * @param {string} command - The unique identifier for the command to register.
693
+ * @param {(context: MeshContext<T>) => Promise<U> | U} callback - The function to execute when the command is invoked. It receives a `MeshContext` of type `T` and may return a value of type `U` or a `Promise` resolving to `U`.
694
+ * @param {SocketMiddleware[]} [middlewares=[]] - An optional array of middleware functions to apply to the command. Defaults to an empty array.
695
+ * @throws {Error} May throw an error if the command registration or middleware addition fails.
696
+ */
697
+ exposeCommand<T = any, U = any>(command: string, callback: (context: MeshContext<T>) => Promise<U> | U, middlewares?: SocketMiddleware[]): void;
698
+ /**
699
+ * Adds one or more middleware functions to the global middleware stack.
700
+ *
701
+ * @param {SocketMiddleware[]} middlewares - An array of middleware functions to be added. Each middleware
702
+ * is expected to conform to the `SocketMiddleware` type.
703
+ * @returns {void}
704
+ * @throws {Error} If the provided middlewares are not valid or fail validation (if applicable).
705
+ */
706
+ useMiddleware(...middlewares: SocketMiddleware[]): void;
707
+ /**
708
+ * Adds an array of middleware functions to a specific command.
709
+ *
710
+ * @param {string} command - The name of the command to associate the middleware with.
711
+ * @param {SocketMiddleware[]} middlewares - An array of middleware functions to be added to the command.
712
+ * @returns {void}
713
+ */
714
+ useMiddlewareWithCommand(command: string, middlewares: SocketMiddleware[]): void;
715
+ /**
716
+ * Exposes a channel for external access and optionally associates a guard function
717
+ * to control access to that channel. The guard function determines whether a given
718
+ * connection is permitted to access the channel.
719
+ *
720
+ * @param {ChannelPattern} channel - The channel or pattern to expose.
721
+ * @param {(connection: Connection, channel: string) => Promise<boolean> | boolean} [guard] -
722
+ * Optional guard function that receives the connection and channel name, returning
723
+ * a boolean or a promise that resolves to a boolean indicating whether access is allowed.
724
+ * @returns {void}
725
+ */
726
+ exposeChannel(channel: ChannelPattern$1, guard?: (connection: Connection, channel: string) => Promise<boolean> | boolean): void;
727
+ /**
728
+ * Publishes a message to a specified channel and optionally maintains a history of messages.
729
+ *
730
+ * @param {string} channel - The name of the channel to which the message will be published.
731
+ * @param {any} message - The message to be published. Will not be stringified automatically for you. You need to do that yourself.
732
+ * @param {number} [history=0] - The number of historical messages to retain for the channel. Defaults to 0, meaning no history is retained.
733
+ * If greater than 0, the message will be added to the channel's history and the history will be trimmed to the specified size.
734
+ * @returns {Promise<void>} A Promise that resolves once the message has been published and, if applicable, the history has been updated.
735
+ * @throws {Error} This function may throw an error if the underlying `pubClient` operations (e.g., `lpush`, `ltrim`, `publish`) fail.
736
+ */
737
+ writeChannel(channel: string, message: any, history?: number): Promise<void>;
738
+ /**
739
+ * Enables persistence for channels matching the specified pattern.
740
+ *
741
+ * @param {ChannelPattern} pattern - The channel pattern to enable persistence for.
742
+ * @param {ChannelPersistenceOptions} [options] - Options for persistence.
743
+ * @throws {Error} If persistence is not enabled for this server instance.
744
+ */
745
+ enableChannelPersistence(pattern: ChannelPattern$1, options?: ChannelPersistenceOptions): void;
746
+ /**
747
+ * Enables persistence for records matching the specified pattern.
748
+ *
749
+ * @param {ChannelPattern} pattern - The record ID pattern to enable persistence for.
750
+ * @param {RecordPersistenceOptions} [options] - Options for persistence.
751
+ * @throws {Error} If persistence is not enabled for this server instance.
752
+ */
753
+ enableRecordPersistence(pattern: ChannelPattern$1, options?: RecordPersistenceOptions): void;
754
+ /**
755
+ * Exposes a record or pattern for client subscriptions, optionally adding a guard function.
756
+ *
757
+ * @param {ChannelPattern} recordPattern - The record ID or pattern to expose.
758
+ * @param {(connection: Connection, recordId: string) => Promise<boolean> | boolean} [guard] - Optional guard function.
759
+ */
760
+ exposeRecord(recordPattern: ChannelPattern$1, guard?: (connection: Connection, recordId: string) => Promise<boolean> | boolean): void;
761
+ /**
762
+ * Exposes a record or pattern for client writes, optionally adding a guard function.
763
+ *
764
+ * @param {ChannelPattern} recordPattern - The record ID or pattern to expose as writable.
765
+ * @param {(connection: Connection, recordId: string) => Promise<boolean> | boolean} [guard] - Optional guard function.
766
+ */
767
+ exposeWritableRecord(recordPattern: ChannelPattern$1, guard?: (connection: Connection, recordId: string) => Promise<boolean> | boolean): void;
768
+ /**
769
+ * Updates a record, persists it to Redis, increments its version, computes a patch,
770
+ * and publishes the update via Redis pub/sub.
771
+ *
772
+ * @param {string} recordId - The ID of the record to update.
773
+ * @param {any} newValue - The new value for the record, or partial value when using merge strategy.
774
+ * @param {{ strategy?: "replace" | "merge" | "deepMerge" }} [options] - Update options: strategy defaults to "replace" which replaces the entire record, "merge" merges with existing object properties, "deepMerge" recursively merges nested objects.
775
+ * @returns {Promise<void>}
776
+ * @throws {Error} If the update fails.
777
+ *
778
+ * @example
779
+ * // Replace strategy (default) - replaces entire record
780
+ * await server.writeRecord("user:123", { name: "John", age: 30 });
781
+ *
782
+ * // Merge strategy - merges with existing record
783
+ * // If record currently contains: { name: "old name", age: 30, city: "NYC" }
784
+ * await server.writeRecord("user:123", { name: "new name" }, { strategy: "merge" });
785
+ * // Result: { name: "new name", age: 30, city: "NYC" }
786
+ *
787
+ * // Deep merge strategy - recursively merges nested objects
788
+ * // If record currently contains: { name: "John", profile: { age: 30, city: "NYC", preferences: { theme: "dark" } } }
789
+ * await server.writeRecord("user:123", { profile: { age: 31 } }, { strategy: "deepMerge" });
790
+ * // Result: { name: "John", profile: { age: 31, city: "NYC", preferences: { theme: "dark" } } }
791
+ */
792
+ writeRecord(recordId: string, newValue: any, options?: {
793
+ strategy?: "replace" | "merge" | "deepMerge";
794
+ }): Promise<void>;
795
+ /**
796
+ * Retrieves the value of a record by its ID.
797
+ *
798
+ * @param {string} recordId - The ID of the record to retrieve.
799
+ * @returns {Promise<any>} A promise that resolves to the value of the record, or null if not found.
800
+ */
801
+ getRecord(recordId: string): Promise<any>;
802
+ deleteRecord(recordId: string): Promise<void>;
803
+ /**
804
+ * Lists and processes records matching a pattern. Designed for use in collection resolvers.
805
+ * Returns transformed records that will be sent to subscribed clients.
806
+ *
807
+ * @param {string} pattern - Redis glob pattern to match record IDs against (e.g., "user:*", "post:?", "[abc]*").
808
+ * @param {Object} [options] - Processing options.
809
+ * @param {Function} [options.map] - Transform each record before sorting/slicing.
810
+ * @param {Function} [options.sort] - Sort function for the records.
811
+ * @param {Object} [options.slice] - Pagination slice.
812
+ * @param {number} [options.slice.start] - Start index.
813
+ * @param {number} [options.slice.count] - Number of records to return.
814
+ * @returns {Promise<any[]>} The processed records to send to clients.
815
+ */
816
+ listRecordsMatching(pattern: string, options?: {
817
+ map?: (record: any) => any;
818
+ sort?: (a: any, b: any) => number;
819
+ slice?: {
820
+ start: number;
821
+ count: number;
822
+ };
823
+ }): Promise<any[]>;
824
+ /**
825
+ * Exposes a collection pattern for client subscriptions with a resolver function
826
+ * that determines which records belong to the collection.
827
+ *
828
+ * @param {ChannelPattern} pattern - The collection ID or pattern to expose.
829
+ * @param {(connection: Connection, collectionId: string) => Promise<any[]> | any[]} resolver -
830
+ * Function that resolves which records belong to the collection.
831
+ */
832
+ exposeCollection(pattern: ChannelPattern$1, resolver: (connection: Connection, collectionId: string) => Promise<any[]> | any[]): void;
833
+ isInRoom(roomName: string, connection: Connection | string): Promise<boolean>;
834
+ addToRoom(roomName: string, connection: Connection | string): Promise<void>;
835
+ removeFromRoom(roomName: string, connection: Connection | string): Promise<void>;
836
+ removeFromAllRooms(connection: Connection | string): Promise<void>;
837
+ clearRoom(roomName: string): Promise<void>;
838
+ deleteRoom(roomName: string): Promise<void>;
839
+ getRoomMembers(roomName: string): Promise<string[]>;
840
+ getRoomMembersWithMetadata(roomName: string): Promise<Array<{
841
+ id: string;
842
+ metadata: any;
843
+ }>>;
844
+ getAllRooms(): Promise<string[]>;
845
+ /**
846
+ * Broadcasts a command and payload to a set of connections or all available connections.
847
+ *
848
+ * @param {string} command - The command to be broadcasted.
849
+ * @param {any} payload - The data associated with the command.
850
+ * @param {Connection[]=} connections - (Optional) A specific list of connections to broadcast to. If not provided, the command will be sent to all connections.
851
+ *
852
+ * @throws {Error} Emits an "error" event if broadcasting fails.
853
+ */
854
+ broadcast(command: string, payload: any, connections?: Connection[]): Promise<void>;
855
+ /**
856
+ * Broadcasts a command and associated payload to all active connections within the specified room.
857
+ *
858
+ * @param {string} roomName - The name of the room whose connections will receive the broadcast.
859
+ * @param {string} command - The command to be broadcasted to the connections.
860
+ * @param {unknown} payload - The data payload associated with the command.
861
+ * @returns {Promise<void>} A promise that resolves when the broadcast operation is complete.
862
+ * @throws {Error} If the broadcast operation fails, an error is thrown and the promise is rejected.
863
+ */
864
+ broadcastRoom(roomName: string, command: string, payload: any): Promise<void>;
865
+ /**
866
+ * Broadcasts a command and payload to all active connections except for the specified one(s).
867
+ * Excludes the provided connection(s) from receiving the broadcast.
868
+ *
869
+ * @param {string} command - The command to broadcast to connections.
870
+ * @param {any} payload - The payload to send along with the command.
871
+ * @param {Connection | Connection[]} exclude - A single connection or an array of connections to exclude from the broadcast.
872
+ * @returns {Promise<void>} A promise that resolves when the broadcast is complete.
873
+ * @emits {Error} Emits an "error" event if broadcasting the command fails.
874
+ */
875
+ broadcastExclude(command: string, payload: any, exclude: Connection | Connection[]): Promise<void>;
876
+ /**
877
+ * Broadcasts a command with a payload to all connections in a specified room,
878
+ * excluding one or more given connections. If the broadcast fails, emits an error event.
879
+ *
880
+ * @param {string} roomName - The name of the room to broadcast to.
881
+ * @param {string} command - The command to broadcast.
882
+ * @param {any} payload - The payload to send with the command.
883
+ * @param {Connection | Connection[]} exclude - A connection or array of connections to exclude from the broadcast.
884
+ * @returns {Promise<void>} A promise that resolves when the broadcast is complete.
885
+ * @emits {Error} Emits an error event if broadcasting fails.
886
+ */
887
+ broadcastRoomExclude(roomName: string, command: string, payload: any, exclude: Connection | Connection[]): Promise<void>;
888
+ trackPresence(roomPattern: string | RegExp, guardOrOptions?: ((connection: Connection, roomName: string) => Promise<boolean> | boolean) | {
889
+ ttl?: number;
890
+ guard?: (connection: Connection, roomName: string) => Promise<boolean> | boolean;
891
+ }): void;
892
+ private registerBuiltinCommands;
893
+ private registerRecordCommands;
894
+ cleanupConnection(connection: Connection): Promise<void>;
895
+ /**
896
+ * Gracefully closes all active connections, cleans up resources,
897
+ * and shuts down the service. Optionally accepts a callback function
898
+ * that will be invoked once shutdown is complete or if an error occurs.
899
+ *
900
+ * @param {((err?: Error) => void)=} callback - Optional callback to be invoked when closing is complete or if an error occurs.
901
+ * @returns {Promise<void>} A promise that resolves when shutdown is complete.
902
+ * @throws {Error} If an error occurs during shutdown, the promise will be rejected with the error.
903
+ */
904
+ close(callback?: (err?: Error) => void): Promise<void>;
905
+ /**
906
+ * Registers a callback function to be executed when a new connection is established.
907
+ *
908
+ * @param {(connection: Connection) => Promise<void> | void} callback - The function to execute when a new connection is established.
909
+ * @returns {MeshServer} The server instance for method chaining.
910
+ */
911
+ onConnection(callback: (connection: Connection) => Promise<void> | void): MeshServer;
912
+ /**
913
+ * Registers a callback function to be executed when a connection is closed.
914
+ *
915
+ * @param {(connection: Connection) => Promise<void> | void} callback - The function to execute when a connection is closed.
916
+ * @returns {MeshServer} The server instance for method chaining.
917
+ */
918
+ onDisconnection(callback: (connection: Connection) => Promise<void> | void): MeshServer;
919
+ /**
920
+ * Registers a callback function to be executed when a record is updated.
921
+ *
922
+ * @param {(data: { recordId: string; value: any }) => Promise<void> | void} callback - The function to execute when a record is updated.
923
+ * @returns {() => void} A function that, when called, will unregister the callback.
924
+ */
925
+ onRecordUpdate(callback: (data: {
926
+ recordId: string;
927
+ value: any;
928
+ }) => Promise<void> | void): () => void;
929
+ /**
930
+ * Registers a callback function to be executed when a record is removed.
931
+ *
932
+ * @param {(data: { recordId: string; value: any }) => Promise<void> | void} callback - The function to execute when a record is removed.
933
+ * @returns {() => void} A function that, when called, will unregister the callback.
934
+ */
935
+ onRecordRemoved(callback: (data: {
936
+ recordId: string;
937
+ value: any;
938
+ }) => Promise<void> | void): () => void;
939
+ }
940
+
941
+ declare class SQLitePersistenceAdapter implements PersistenceAdapter {
942
+ private db;
943
+ private options;
944
+ private initialized;
945
+ constructor(options?: PersistenceAdapterOptions);
946
+ initialize(): Promise<void>;
947
+ private createTables;
948
+ storeMessages(messages: PersistedMessage[]): Promise<void>;
949
+ getMessages(channel: string, since?: string | number, limit?: number): Promise<PersistedMessage[]>;
950
+ close(): Promise<void>;
951
+ /**
952
+ * Store records in the database
953
+ * @param records Array of records to store
954
+ */
955
+ storeRecords(records: PersistedRecord[]): Promise<void>;
956
+ /**
957
+ * Get records matching a pattern
958
+ * @param pattern Pattern to match record IDs against
959
+ * @returns Array of matching records
960
+ */
961
+ getRecords(pattern: string): Promise<PersistedRecord[]>;
962
+ }
963
+
964
+ declare class PostgreSQLPersistenceAdapter implements PersistenceAdapter {
965
+ private pool;
966
+ private options;
967
+ private initialized;
968
+ constructor(options?: PostgreSQLAdapterOptions);
969
+ initialize(): Promise<void>;
970
+ private createTables;
971
+ storeMessages(messages: PersistedMessage[]): Promise<void>;
972
+ getMessages(channel: string, since?: string | number, limit?: number): Promise<PersistedMessage[]>;
973
+ storeRecords(records: PersistedRecord[]): Promise<void>;
974
+ getRecords(pattern: string): Promise<PersistedRecord[]>;
975
+ close(): Promise<void>;
976
+ }
977
+
978
+ /**
979
+ * MessageStream provides a unified internal event stream for channel messages.
980
+ * It decouples channel message delivery from persistence.
981
+ */
982
+ declare class MessageStream extends EventEmitter$1 {
983
+ private static instance;
984
+ /**
985
+ * Get the MessageStream singleton
986
+ */
987
+ static getInstance(): MessageStream;
988
+ private constructor();
989
+ /**
990
+ * Publish a message to the stream
991
+ * @param channel The channel the message was published to
992
+ * @param message The message content
993
+ * @param instanceId ID of the server instance
994
+ */
995
+ publishMessage(channel: string, message: string, instanceId: string): void;
996
+ /**
997
+ * Subscribe to all messages in the stream
998
+ * @param callback Function to call for each message
999
+ */
1000
+ subscribeToMessages(callback: (message: {
1001
+ channel: string;
1002
+ message: string;
1003
+ instanceId: string;
1004
+ timestamp: number;
1005
+ }) => void): void;
1006
+ /**
1007
+ * Unsubscribe from messages
1008
+ * @param callback The callback function to remove
1009
+ */
1010
+ unsubscribeFromMessages(callback: (message: {
1011
+ channel: string;
1012
+ message: string;
1013
+ instanceId: string;
1014
+ timestamp: number;
1015
+ }) => void): void;
1016
+ }
1017
+
1018
+ declare class PersistenceManager extends EventEmitter$1 {
1019
+ private defaultAdapter;
1020
+ private channelPatterns;
1021
+ private recordPatterns;
1022
+ private messageBuffer;
1023
+ private recordBuffer;
1024
+ private flushTimers;
1025
+ private recordFlushTimer;
1026
+ private isShuttingDown;
1027
+ private initialized;
1028
+ private recordManager;
1029
+ private pendingRecordUpdates;
1030
+ private messageStream;
1031
+ constructor(options: {
1032
+ defaultAdapterOptions?: any;
1033
+ adapterType?: "sqlite" | "postgres";
1034
+ });
1035
+ /**
1036
+ * Sets the record manager reference for record restoration
1037
+ * @param recordManager The record manager instance
1038
+ */
1039
+ setRecordManager(recordManager: RecordManager): void;
1040
+ /**
1041
+ * Waits until the persistence manager is fully ready and initialized.
1042
+ *
1043
+ * @returns {Promise<void>} A promise that resolves when persistence is ready.
1044
+ */
1045
+ ready(): Promise<void>;
1046
+ /**
1047
+ * Processes any record updates that were buffered during initialization
1048
+ */
1049
+ private processPendingRecordUpdates;
1050
+ initialize(): Promise<void>;
1051
+ /**
1052
+ * Restores persisted records from storage into Redis on startup
1053
+ */
1054
+ private restorePersistedRecords;
1055
+ /**
1056
+ * Handle a message received from the internal message stream.
1057
+ */
1058
+ private handleStreamMessage;
1059
+ /**
1060
+ * Enable persistence for channels matching the given pattern.
1061
+ * @param pattern string or regexp pattern to match channel names
1062
+ * @param options persistence options
1063
+ */
1064
+ enableChannelPersistence(pattern: string | RegExp, options?: ChannelPersistenceOptions): void;
1065
+ /**
1066
+ * Enable persistence for records matching the given pattern.
1067
+ * @param pattern string or regexp pattern to match record IDs
1068
+ * @param options persistence options
1069
+ */
1070
+ enableRecordPersistence(pattern: string | RegExp, options?: RecordPersistenceOptions): void;
1071
+ /**
1072
+ * Check if a channel has persistence enabled and return its options.
1073
+ * @param channel channel name to check
1074
+ * @returns the persistence options if enabled, undefined otherwise
1075
+ */
1076
+ getChannelPersistenceOptions(channel: string): Required<ChannelPersistenceOptions> | undefined;
1077
+ /**
1078
+ * Check if a record has persistence enabled and return its options.
1079
+ * @param recordId record ID to check
1080
+ * @returns the persistence options if enabled, undefined otherwise
1081
+ */
1082
+ getRecordPersistenceOptions(recordId: string): Required<RecordPersistenceOptions> | undefined;
1083
+ /**
1084
+ * Handle an incoming message for potential persistence.
1085
+ * @param channel channel the message was published to
1086
+ * @param message the message content
1087
+ * @param instanceId id of the server instance
1088
+ */
1089
+ handleChannelMessage(channel: string, message: string, instanceId: string, timestamp?: number): void;
1090
+ /**
1091
+ * Flush buffered messages for a specific channel to its adapter.
1092
+ * @param channel channel to flush
1093
+ */
1094
+ private flushChannel;
1095
+ /**
1096
+ * Flush all buffered messages across all channels.
1097
+ */
1098
+ flushAll(): Promise<void>;
1099
+ /**
1100
+ * Get persisted messages for a channel.
1101
+ * @param channel channel to get messages for
1102
+ * @param since optional cursor (timestamp or message id) to retrieve messages after
1103
+ * @param limit maximum number of messages to retrieve
1104
+ */
1105
+ getMessages(channel: string, since?: string | number, limit?: number): Promise<PersistedMessage[]>;
1106
+ /**
1107
+ * Handles a record update for potential persistence
1108
+ * @param recordId ID of the record
1109
+ * @param value record value (will be stringified)
1110
+ * @param version record version
1111
+ */
1112
+ handleRecordUpdate(recordId: string, value: any, version: number): void;
1113
+ /**
1114
+ * Flush all buffered records to storage
1115
+ */
1116
+ flushRecords(): Promise<void>;
1117
+ /**
1118
+ * Retrieve persisted records matching a pattern
1119
+ * @param pattern pattern to match record IDs
1120
+ * @returns array of persisted records
1121
+ */
1122
+ getPersistedRecords(pattern: string): Promise<PersistedRecord[]>;
1123
+ /**
1124
+ * Shutdown the persistence manager, flushing pending messages and closing adapters.
1125
+ */
1126
+ shutdown(): Promise<void>;
1127
+ }
1128
+
1129
+ export { type ChannelPattern$1 as ChannelPattern, Connection, ConnectionManager, MeshContext, MeshServer, type MeshServerOptions, MessageStream, type PersistenceAdapter, type PersistenceAdapterOptions, PersistenceManager, type PostgreSQLAdapterOptions, PostgreSQLPersistenceAdapter, PresenceManager, RecordManager, RoomManager, SQLitePersistenceAdapter, type SocketMiddleware };