@principal-ai/control-tower-core 0.1.7 → 0.1.8

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.
@@ -4,6 +4,7 @@ import type { IAuthAdapter } from '../abstractions/AuthAdapter.js';
4
4
  import type { IStorageAdapter } from '../abstractions/StorageAdapter.js';
5
5
  import type { RoomManager } from '../abstractions/RoomManager.js';
6
6
  import type { LockManager } from '../abstractions/LockManager.js';
7
+ import type { PresenceManager } from '../abstractions/PresenceManager.js';
7
8
  import { TypedEventEmitter } from '../abstractions/EventEmitter.js';
8
9
  import { ExperimentalAPI } from './ExperimentalAPI.js';
9
10
  import type { Server as HttpServer } from 'http';
@@ -15,6 +16,7 @@ export interface ServerConfig {
15
16
  storage?: IStorageAdapter;
16
17
  roomManager: RoomManager;
17
18
  lockManager: LockManager;
19
+ presenceManager?: PresenceManager;
18
20
  defaultRoomConfig?: Partial<RoomConfig>;
19
21
  httpServer?: HttpServer | HttpsServer;
20
22
  webSocketPath?: string;
@@ -24,6 +26,21 @@ export interface ServerConfig {
24
26
  export interface ConnectedClient {
25
27
  id: string;
26
28
  userId: string;
29
+ /**
30
+ * Set of room IDs the client is currently in
31
+ *
32
+ * Multi-room support: A client can be in multiple rooms simultaneously.
33
+ * This enables the two-tier architecture where clients can maintain
34
+ * global presence while participating in multiple repository rooms.
35
+ */
36
+ roomIds: Set<string>;
37
+ /**
38
+ * Legacy single-room accessor for backward compatibility
39
+ *
40
+ * Returns the first room the client is in, or null if not in any rooms.
41
+ *
42
+ * @deprecated Use roomIds for multi-room support
43
+ */
27
44
  roomId: string | null;
28
45
  authenticated: boolean;
29
46
  connectedAt: number;
@@ -76,6 +93,26 @@ export interface ServerEvents {
76
93
  context?: string;
77
94
  };
78
95
  experimental_usage: ExperimentalUsageEvent;
96
+ presence_changed: {
97
+ userId: string;
98
+ status: string;
99
+ timestamp: number;
100
+ };
101
+ presence_device_connected: {
102
+ userId: string;
103
+ deviceId: string;
104
+ timestamp: number;
105
+ };
106
+ presence_device_disconnected: {
107
+ userId: string;
108
+ deviceId: string;
109
+ timestamp: number;
110
+ };
111
+ presence_activity: {
112
+ userId: string;
113
+ deviceId: string;
114
+ timestamp: number;
115
+ };
79
116
  [key: string]: unknown;
80
117
  }
81
118
  export declare class BaseServer extends TypedEventEmitter<ServerEvents> {
@@ -84,12 +121,14 @@ export declare class BaseServer extends TypedEventEmitter<ServerEvents> {
84
121
  private storage?;
85
122
  private roomManager;
86
123
  private lockManager;
124
+ private presenceManager?;
87
125
  private config;
88
126
  private clients;
89
127
  private clientMessageHandlers;
90
128
  private running;
91
129
  private initialized;
92
130
  private mode;
131
+ private heartbeatIntervalId?;
93
132
  /**
94
133
  * Experimental APIs namespace
95
134
  *
@@ -100,6 +139,14 @@ export declare class BaseServer extends TypedEventEmitter<ServerEvents> {
100
139
  */
101
140
  readonly experimental: ExperimentalAPI;
102
141
  constructor(config: ServerConfig);
142
+ /**
143
+ * Start periodic heartbeat processing for presence management
144
+ */
145
+ private startHeartbeatProcessor;
146
+ /**
147
+ * Stop heartbeat processor
148
+ */
149
+ private stopHeartbeatProcessor;
103
150
  start(port?: number): Promise<void>;
104
151
  initialize(): Promise<void>;
105
152
  stop(): Promise<void>;
@@ -126,5 +173,17 @@ export declare class BaseServer extends TypedEventEmitter<ServerEvents> {
126
173
  isRunning(): boolean;
127
174
  getMode(): 'standalone' | 'integration';
128
175
  isInitialized(): boolean;
176
+ /**
177
+ * Update presence activity for a user's device
178
+ *
179
+ * @param userId - User identifier
180
+ * @param deviceId - Device/client identifier
181
+ * @param activityType - Type of activity
182
+ */
183
+ private updatePresenceActivity;
184
+ /**
185
+ * Get presence manager (if configured)
186
+ */
187
+ getPresenceManager(): PresenceManager | undefined;
129
188
  }
130
189
  //# sourceMappingURL=BaseServer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"BaseServer.d.ts","sourceRoot":"","sources":["../../src/server/BaseServer.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"BaseServer.d.ts","sourceRoot":"","sources":["../../src/server/BaseServer.ts"],"names":[],"mappings":"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"}
@@ -16,6 +16,7 @@ class BaseServer extends EventEmitter_js_1.TypedEventEmitter {
16
16
  this.storage = config.storage;
17
17
  this.roomManager = config.roomManager;
18
18
  this.lockManager = config.lockManager;
19
+ this.presenceManager = config.presenceManager;
19
20
  // Initialize experimental API namespace
20
21
  this.experimental = new ExperimentalAPI_js_1.ExperimentalAPI({
21
22
  config: config.experimental || {
@@ -43,6 +44,60 @@ class BaseServer extends EventEmitter_js_1.TypedEventEmitter {
43
44
  this.transport.onMessage(this.handleTransportMessage.bind(this));
44
45
  this.transport.onError(this.handleTransportError.bind(this));
45
46
  this.transport.onClose(this.handleTransportClose.bind(this));
47
+ // Start heartbeat processor if presence is enabled
48
+ if (this.presenceManager?.isEnabled()) {
49
+ this.startHeartbeatProcessor();
50
+ }
51
+ }
52
+ /**
53
+ * Start periodic heartbeat processing for presence management
54
+ */
55
+ startHeartbeatProcessor() {
56
+ if (!this.presenceManager) {
57
+ return;
58
+ }
59
+ const config = this.presenceManager.getConfig();
60
+ const interval = config.heartbeatInterval;
61
+ this.heartbeatIntervalId = setInterval(async () => {
62
+ try {
63
+ const changes = await this.presenceManager.processHeartbeats();
64
+ // Emit presence change events
65
+ for (const change of changes) {
66
+ await this.emit('presence_changed', {
67
+ userId: change.userId,
68
+ status: change.status,
69
+ timestamp: change.timestamp
70
+ });
71
+ // Broadcast presence updates if enabled
72
+ if (config.broadcastPresenceUpdates) {
73
+ await this.experimental.broadcastAuthenticated({
74
+ type: 'presence:status_changed',
75
+ payload: {
76
+ userId: change.userId,
77
+ status: change.status,
78
+ previousStatus: change.previousStatus,
79
+ reason: change.reason
80
+ }
81
+ });
82
+ }
83
+ }
84
+ }
85
+ catch (error) {
86
+ await this.emit('error', {
87
+ error: error,
88
+ context: 'heartbeat_processor'
89
+ });
90
+ }
91
+ }, interval);
92
+ }
93
+ /**
94
+ * Stop heartbeat processor
95
+ */
96
+ stopHeartbeatProcessor() {
97
+ if (this.heartbeatIntervalId) {
98
+ clearInterval(this.heartbeatIntervalId);
99
+ this.heartbeatIntervalId = undefined;
100
+ }
46
101
  }
47
102
  // Server Lifecycle
48
103
  async start(port) {
@@ -110,6 +165,8 @@ class BaseServer extends EventEmitter_js_1.TypedEventEmitter {
110
165
  return;
111
166
  }
112
167
  this.running = false;
168
+ // Stop heartbeat processor
169
+ this.stopHeartbeatProcessor();
113
170
  // Disconnect all clients
114
171
  for (const [clientId] of Array.from(this.clients)) {
115
172
  await this.disconnectClient(clientId, 'Server shutting down');
@@ -122,6 +179,10 @@ class BaseServer extends EventEmitter_js_1.TypedEventEmitter {
122
179
  }
123
180
  this.clients.clear();
124
181
  this.clientMessageHandlers.clear();
182
+ // Clear presence data
183
+ if (this.presenceManager) {
184
+ await this.presenceManager.clear();
185
+ }
125
186
  await this.emit('stopped', {});
126
187
  }
127
188
  // Client Management
@@ -135,12 +196,17 @@ class BaseServer extends EventEmitter_js_1.TypedEventEmitter {
135
196
  await this.handleClientAuthenticatedMessage(message);
136
197
  return;
137
198
  }
199
+ if (message.type === 'disconnect') {
200
+ const payload = message.payload;
201
+ await this.disconnectClient(payload.clientId, payload.reason || 'Client disconnected');
202
+ return;
203
+ }
138
204
  // Transport messages contain clientId in the payload for routing
139
205
  const payload = message.payload;
140
- const { clientId, ...clientMessage } = payload;
206
+ const { clientId, type, ...clientMessage } = payload;
141
207
  const clientMsg = {
142
208
  id: message.id,
143
- type: message.type,
209
+ type: type || message.type, // Use inner type if present, otherwise outer type
144
210
  payload: clientMessage,
145
211
  timestamp: message.timestamp
146
212
  };
@@ -165,16 +231,53 @@ class BaseServer extends EventEmitter_js_1.TypedEventEmitter {
165
231
  async handleConnectionMessage(message) {
166
232
  const payload = message.payload;
167
233
  // Add the client with initial auth state
234
+ const roomIds = new Set();
168
235
  const client = {
169
236
  id: payload.clientId,
170
237
  userId: payload.userId || '',
171
- roomId: null,
238
+ roomIds,
239
+ get roomId() {
240
+ return roomIds.size > 0 ? (roomIds.values().next().value || null) : null;
241
+ },
172
242
  authenticated: payload.authenticated,
173
243
  connectedAt: Date.now()
174
244
  };
175
245
  this.clients.set(payload.clientId, client);
176
246
  this.clientMessageHandlers.set(payload.clientId, this.createClientMessageHandler(payload.clientId));
177
247
  await this.emit('client_connected', { client });
248
+ // Register with presence manager if authenticated
249
+ if (payload.authenticated && this.presenceManager?.isEnabled() && payload.userId) {
250
+ try {
251
+ await this.presenceManager.connectDevice(payload.userId, payload.clientId, {
252
+ connectedAt: Date.now(),
253
+ lastActivity: Date.now(),
254
+ metadata: payload.metadata
255
+ });
256
+ await this.emit('presence_device_connected', {
257
+ userId: payload.userId,
258
+ deviceId: payload.clientId,
259
+ timestamp: Date.now()
260
+ });
261
+ // Broadcast presence update
262
+ const presenceConfig = this.presenceManager.getConfig();
263
+ if (presenceConfig.broadcastPresenceUpdates) {
264
+ await this.experimental.broadcastAuthenticated({
265
+ type: 'presence:user_online',
266
+ payload: {
267
+ userId: payload.userId,
268
+ deviceId: payload.clientId,
269
+ status: 'online'
270
+ }
271
+ });
272
+ }
273
+ }
274
+ catch (error) {
275
+ await this.emit('error', {
276
+ error: error,
277
+ context: 'presence_connect_device'
278
+ });
279
+ }
280
+ }
178
281
  if (payload.authenticated) {
179
282
  await this.emit('client_authenticated', {
180
283
  clientId: payload.clientId,
@@ -204,10 +307,14 @@ class BaseServer extends EventEmitter_js_1.TypedEventEmitter {
204
307
  }
205
308
  }
206
309
  async addClient(clientId) {
310
+ const roomIds = new Set();
207
311
  const client = {
208
312
  id: clientId,
209
313
  userId: '',
210
- roomId: null,
314
+ roomIds,
315
+ get roomId() {
316
+ return roomIds.size > 0 ? (roomIds.values().next().value || null) : null;
317
+ },
211
318
  authenticated: false,
212
319
  connectedAt: Date.now()
213
320
  };
@@ -221,10 +328,40 @@ class BaseServer extends EventEmitter_js_1.TypedEventEmitter {
221
328
  if (!client) {
222
329
  return;
223
330
  }
224
- // Leave room if in one
225
- if (client.roomId) {
226
- await this.roomManager.leaveRoom(client.roomId, client.userId);
227
- await this.emit('client_left_room', { clientId, roomId: client.roomId });
331
+ // Unregister from presence manager
332
+ if (this.presenceManager?.isEnabled() && client.userId) {
333
+ try {
334
+ const presence = await this.presenceManager.disconnectDevice(client.userId, clientId);
335
+ await this.emit('presence_device_disconnected', {
336
+ userId: client.userId,
337
+ deviceId: clientId,
338
+ timestamp: Date.now()
339
+ });
340
+ // Broadcast presence update if user went offline or into grace period
341
+ const presenceConfig = this.presenceManager.getConfig();
342
+ if (presenceConfig.broadcastPresenceUpdates && (!presence || presence.status === 'offline')) {
343
+ await this.experimental.broadcastAuthenticated({
344
+ type: 'presence:user_offline',
345
+ payload: {
346
+ userId: client.userId,
347
+ deviceId: clientId,
348
+ status: presence?.status || 'offline',
349
+ gracePeriod: presenceConfig.gracePeriod
350
+ }
351
+ });
352
+ }
353
+ }
354
+ catch (error) {
355
+ await this.emit('error', {
356
+ error: error,
357
+ context: 'presence_disconnect_device'
358
+ });
359
+ }
360
+ }
361
+ // Leave all rooms the client is in
362
+ for (const roomId of client.roomIds) {
363
+ await this.roomManager.leaveRoom(roomId, client.userId);
364
+ await this.emit('client_left_room', { clientId, roomId });
228
365
  }
229
366
  // Release all locks held by this client
230
367
  await this.lockManager.releaseUserLocks(client.userId);
@@ -248,7 +385,7 @@ class BaseServer extends EventEmitter_js_1.TypedEventEmitter {
248
385
  await this.handleJoinRoom(clientId, message.payload);
249
386
  break;
250
387
  case 'leave_room':
251
- await this.handleLeaveRoom(clientId);
388
+ await this.handleLeaveRoom(clientId, message.payload);
252
389
  break;
253
390
  case 'broadcast_event':
254
391
  await this.handleBroadcastEvent(clientId, message.payload);
@@ -261,6 +398,10 @@ class BaseServer extends EventEmitter_js_1.TypedEventEmitter {
261
398
  break;
262
399
  case 'ping':
263
400
  await this.sendToClient(clientId, { type: 'pong', timestamp: Date.now() });
401
+ // Update presence activity on ping
402
+ if (this.presenceManager?.isEnabled() && client.userId) {
403
+ await this.updatePresenceActivity(client.userId, clientId, 'heartbeat');
404
+ }
264
405
  break;
265
406
  default:
266
407
  await this.sendToClient(clientId, {
@@ -312,10 +453,10 @@ class BaseServer extends EventEmitter_js_1.TypedEventEmitter {
312
453
  return;
313
454
  }
314
455
  try {
315
- // Leave current room if any
316
- if (client.roomId) {
317
- await this.roomManager.leaveRoom(client.roomId, client.userId);
318
- await this.emit('client_left_room', { clientId, roomId: client.roomId });
456
+ // Check if already in the room
457
+ if (client.roomIds.has(payload.roomId)) {
458
+ await this.sendToClient(clientId, { type: 'error', error: 'Already in this room' });
459
+ return;
319
460
  }
320
461
  // Get or create room
321
462
  let roomState = await this.roomManager.getRoomState(payload.roomId);
@@ -338,7 +479,7 @@ class BaseServer extends EventEmitter_js_1.TypedEventEmitter {
338
479
  permissions: roomState.room.permissions || ['read', 'write']
339
480
  };
340
481
  await this.roomManager.joinRoom(payload.roomId, user);
341
- client.roomId = payload.roomId;
482
+ client.roomIds.add(payload.roomId);
342
483
  await this.emit('client_joined_room', { clientId, roomId: payload.roomId });
343
484
  // Send room state to client
344
485
  await this.sendToClient(clientId, {
@@ -359,20 +500,32 @@ class BaseServer extends EventEmitter_js_1.TypedEventEmitter {
359
500
  await this.sendToClient(clientId, { type: 'error', error: error.message });
360
501
  }
361
502
  }
362
- async handleLeaveRoom(clientId) {
503
+ async handleLeaveRoom(clientId, payload) {
363
504
  const client = this.clients.get(clientId);
364
- if (!client || !client.roomId) {
505
+ if (!client) {
365
506
  return;
366
507
  }
367
- const roomId = client.roomId;
368
- await this.roomManager.leaveRoom(roomId, client.userId);
369
- client.roomId = null;
370
- await this.emit('client_left_room', { clientId, roomId });
371
- await this.sendToClient(clientId, { type: 'room_left', roomId });
508
+ // If roomId is specified, leave that specific room
509
+ // Otherwise, leave all rooms (backward compatibility)
510
+ const roomsToLeave = payload?.roomId
511
+ ? [payload.roomId]
512
+ : Array.from(client.roomIds);
513
+ if (roomsToLeave.length === 0) {
514
+ return;
515
+ }
516
+ for (const roomId of roomsToLeave) {
517
+ if (!client.roomIds.has(roomId)) {
518
+ continue;
519
+ }
520
+ await this.roomManager.leaveRoom(roomId, client.userId);
521
+ client.roomIds.delete(roomId);
522
+ await this.emit('client_left_room', { clientId, roomId });
523
+ await this.sendToClient(clientId, { type: 'room_left', roomId });
524
+ }
372
525
  }
373
526
  async handleBroadcastEvent(clientId, payload) {
374
527
  const client = this.clients.get(clientId);
375
- if (!client || client.roomId !== payload.roomId) {
528
+ if (!client || !client.roomIds.has(payload.roomId)) {
376
529
  await this.sendToClient(clientId, { type: 'error', error: 'Not in specified room' });
377
530
  return;
378
531
  }
@@ -398,7 +551,7 @@ class BaseServer extends EventEmitter_js_1.TypedEventEmitter {
398
551
  }
399
552
  async handleLockRequest(clientId, payload) {
400
553
  const client = this.clients.get(clientId);
401
- if (!client || client.roomId !== payload.roomId) {
554
+ if (!client || !client.roomIds.has(payload.roomId)) {
402
555
  await this.sendToClient(clientId, { type: 'error', error: 'Not in specified room' });
403
556
  return;
404
557
  }
@@ -430,16 +583,16 @@ class BaseServer extends EventEmitter_js_1.TypedEventEmitter {
430
583
  await this.lockManager.releaseLock(payload.lockId);
431
584
  await this.emit('lock_released', { lockId: payload.lockId, clientId });
432
585
  await this.sendToClient(clientId, { type: 'lock_released', lockId: payload.lockId });
433
- // Broadcast lock status to room if client is in one
434
- if (client.roomId) {
435
- await this.roomManager.broadcastToRoom(client.roomId, {
586
+ // Broadcast lock status to all rooms the client is in
587
+ for (const roomId of client.roomIds) {
588
+ await this.roomManager.broadcastToRoom(roomId, {
436
589
  id: this.generateId(),
437
590
  type: 'lock_status',
438
591
  timestamp: Date.now(),
439
592
  userId: client.userId,
440
- roomId: client.roomId,
593
+ roomId,
441
594
  data: { lockId: payload.lockId, action: 'released' },
442
- metadata: { userId: client.userId, timestamp: Date.now(), roomId: client.roomId }
595
+ metadata: { userId: client.userId, timestamp: Date.now(), roomId }
443
596
  });
444
597
  }
445
598
  }
@@ -485,5 +638,43 @@ class BaseServer extends EventEmitter_js_1.TypedEventEmitter {
485
638
  isInitialized() {
486
639
  return this.initialized;
487
640
  }
641
+ /**
642
+ * Update presence activity for a user's device
643
+ *
644
+ * @param userId - User identifier
645
+ * @param deviceId - Device/client identifier
646
+ * @param activityType - Type of activity
647
+ */
648
+ async updatePresenceActivity(userId, deviceId, activityType) {
649
+ if (!this.presenceManager?.isEnabled()) {
650
+ return;
651
+ }
652
+ try {
653
+ await this.presenceManager.updateActivity({
654
+ userId,
655
+ deviceId,
656
+ timestamp: Date.now(),
657
+ activityType
658
+ });
659
+ await this.emit('presence_activity', {
660
+ userId,
661
+ deviceId,
662
+ timestamp: Date.now()
663
+ });
664
+ }
665
+ catch (error) {
666
+ // Don't throw, just log the error
667
+ await this.emit('error', {
668
+ error: error,
669
+ context: 'presence_update_activity'
670
+ });
671
+ }
672
+ }
673
+ /**
674
+ * Get presence manager (if configured)
675
+ */
676
+ getPresenceManager() {
677
+ return this.presenceManager;
678
+ }
488
679
  }
489
680
  exports.BaseServer = BaseServer;
@@ -3,6 +3,7 @@ import type { IAuthAdapter } from '../abstractions/AuthAdapter.js';
3
3
  import type { IStorageAdapter } from '../abstractions/StorageAdapter.js';
4
4
  import type { RoomManager } from '../abstractions/RoomManager.js';
5
5
  import type { LockManager } from '../abstractions/LockManager.js';
6
+ import type { PresenceManager } from '../abstractions/PresenceManager.js';
6
7
  import type { RoomConfig, ExperimentalFeatureConfig } from '../types/index.js';
7
8
  import { BaseServer } from './BaseServer.js';
8
9
  import type { Server as HttpServer } from 'http';
@@ -14,6 +15,7 @@ export declare class ServerBuilder {
14
15
  private storage?;
15
16
  private roomManager?;
16
17
  private lockManager?;
18
+ private presenceManager?;
17
19
  private defaultRoomConfig?;
18
20
  private httpServer?;
19
21
  private webSocketPath?;
@@ -24,6 +26,15 @@ export declare class ServerBuilder {
24
26
  withStorage(storage: IStorageAdapter): this;
25
27
  withRoomManager(roomManager: RoomManager): this;
26
28
  withLockManager(lockManager: LockManager): this;
29
+ /**
30
+ * Configure presence management for global user tracking
31
+ *
32
+ * Enables two-tier connection architecture where users maintain
33
+ * global presence while participating in multiple rooms.
34
+ *
35
+ * @param presenceManager - PresenceManager implementation
36
+ */
37
+ withPresenceManager(presenceManager: PresenceManager): this;
27
38
  withDefaultRoomConfig(config: Partial<RoomConfig>): this;
28
39
  withHttpServer(server: HttpServer | HttpsServer): this;
29
40
  withWebSocketPath(path: string): this;
@@ -1 +1 @@
1
- {"version":3,"file":"ServerBuilder.d.ts","sourceRoot":"","sources":["../../src/server/ServerBuilder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qCAAqC,CAAC;AAC7E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AACzE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAClE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAClE,OAAO,KAAK,EAAE,UAAU,EAAE,yBAAyB,EAAE,MAAM,mBAAmB,CAAC;AAC/E,OAAO,EAAE,UAAU,EAAqB,MAAM,iBAAiB,CAAC;AAChE,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,MAAM,CAAC;AACjD,OAAO,KAAK,EAAE,MAAM,IAAI,WAAW,EAAE,MAAM,OAAO,CAAC;AACnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,IAAI,CAAC;AAE1C,qBAAa,aAAa;IACxB,OAAO,CAAC,SAAS,CAAC,CAAoB;IACtC,OAAO,CAAC,IAAI,CAAC,CAAe;IAC5B,OAAO,CAAC,OAAO,CAAC,CAAkB;IAClC,OAAO,CAAC,WAAW,CAAC,CAAc;IAClC,OAAO,CAAC,WAAW,CAAC,CAAc;IAClC,OAAO,CAAC,iBAAiB,CAAC,CAAsB;IAChD,OAAO,CAAC,UAAU,CAAC,CAA2B;IAC9C,OAAO,CAAC,aAAa,CAAC,CAAS;IAC/B,OAAO,CAAC,eAAe,CAAC,CAAkB;IAC1C,OAAO,CAAC,oBAAoB,CAAC,CAA4B;IAEzD,aAAa,CAAC,SAAS,EAAE,iBAAiB,GAAG,IAAI;IAKjD,QAAQ,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI;IAKlC,WAAW,CAAC,OAAO,EAAE,eAAe,GAAG,IAAI;IAK3C,eAAe,CAAC,WAAW,EAAE,WAAW,GAAG,IAAI;IAK/C,eAAe,CAAC,WAAW,EAAE,WAAW,GAAG,IAAI;IAK/C,qBAAqB,CAAC,MAAM,EAAE,OAAO,CAAC,UAAU,CAAC,GAAG,IAAI;IAKxD,cAAc,CAAC,MAAM,EAAE,UAAU,GAAG,WAAW,GAAG,IAAI;IAKtD,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAKrC,mBAAmB,CAAC,GAAG,EAAE,eAAe,GAAG,IAAI;IAK/C;;;;;;;OAOG;IACH,wBAAwB,CAAC,QAAQ,EAAE,yBAAyB,GAAG,IAAI;IAKnE,KAAK,IAAI,UAAU;CAoCpB"}
1
+ {"version":3,"file":"ServerBuilder.d.ts","sourceRoot":"","sources":["../../src/server/ServerBuilder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qCAAqC,CAAC;AAC7E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AACzE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAClE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gCAAgC,CAAC;AAClE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,oCAAoC,CAAC;AAC1E,OAAO,KAAK,EAAE,UAAU,EAAE,yBAAyB,EAAE,MAAM,mBAAmB,CAAC;AAC/E,OAAO,EAAE,UAAU,EAAqB,MAAM,iBAAiB,CAAC;AAChE,OAAO,KAAK,EAAE,MAAM,IAAI,UAAU,EAAE,MAAM,MAAM,CAAC;AACjD,OAAO,KAAK,EAAE,MAAM,IAAI,WAAW,EAAE,MAAM,OAAO,CAAC;AACnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,IAAI,CAAC;AAE1C,qBAAa,aAAa;IACxB,OAAO,CAAC,SAAS,CAAC,CAAoB;IACtC,OAAO,CAAC,IAAI,CAAC,CAAe;IAC5B,OAAO,CAAC,OAAO,CAAC,CAAkB;IAClC,OAAO,CAAC,WAAW,CAAC,CAAc;IAClC,OAAO,CAAC,WAAW,CAAC,CAAc;IAClC,OAAO,CAAC,eAAe,CAAC,CAAkB;IAC1C,OAAO,CAAC,iBAAiB,CAAC,CAAsB;IAChD,OAAO,CAAC,UAAU,CAAC,CAA2B;IAC9C,OAAO,CAAC,aAAa,CAAC,CAAS;IAC/B,OAAO,CAAC,eAAe,CAAC,CAAkB;IAC1C,OAAO,CAAC,oBAAoB,CAAC,CAA4B;IAEzD,aAAa,CAAC,SAAS,EAAE,iBAAiB,GAAG,IAAI;IAKjD,QAAQ,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI;IAKlC,WAAW,CAAC,OAAO,EAAE,eAAe,GAAG,IAAI;IAK3C,eAAe,CAAC,WAAW,EAAE,WAAW,GAAG,IAAI;IAK/C,eAAe,CAAC,WAAW,EAAE,WAAW,GAAG,IAAI;IAK/C;;;;;;;OAOG;IACH,mBAAmB,CAAC,eAAe,EAAE,eAAe,GAAG,IAAI;IAK3D,qBAAqB,CAAC,MAAM,EAAE,OAAO,CAAC,UAAU,CAAC,GAAG,IAAI;IAKxD,cAAc,CAAC,MAAM,EAAE,UAAU,GAAG,WAAW,GAAG,IAAI;IAKtD,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI;IAKrC,mBAAmB,CAAC,GAAG,EAAE,eAAe,GAAG,IAAI;IAK/C;;;;;;;OAOG;IACH,wBAAwB,CAAC,QAAQ,EAAE,yBAAyB,GAAG,IAAI;IAKnE,KAAK,IAAI,UAAU;CAqCpB"}
@@ -23,6 +23,18 @@ class ServerBuilder {
23
23
  this.lockManager = lockManager;
24
24
  return this;
25
25
  }
26
+ /**
27
+ * Configure presence management for global user tracking
28
+ *
29
+ * Enables two-tier connection architecture where users maintain
30
+ * global presence while participating in multiple rooms.
31
+ *
32
+ * @param presenceManager - PresenceManager implementation
33
+ */
34
+ withPresenceManager(presenceManager) {
35
+ this.presenceManager = presenceManager;
36
+ return this;
37
+ }
26
38
  withDefaultRoomConfig(config) {
27
39
  this.defaultRoomConfig = config;
28
40
  return this;
@@ -67,6 +79,7 @@ class ServerBuilder {
67
79
  storage: this.storage,
68
80
  roomManager: this.roomManager,
69
81
  lockManager: this.lockManager,
82
+ presenceManager: this.presenceManager,
70
83
  defaultRoomConfig: this.defaultRoomConfig || {
71
84
  maxUsers: 50,
72
85
  maxHistory: 100,
@@ -21,4 +21,5 @@ export type MessageHandler = (message: Message) => void | Promise<void>;
21
21
  export type ErrorHandler = (error: Error) => void;
22
22
  export type CloseHandler = (code: number, reason: string) => void;
23
23
  export { ExperimentalFeatureConfig, ClientPredicate, BroadcastResult, BroadcastOptions, ExperimentalUsageEvent, ExperimentalFeatureError } from './experimental.js';
24
+ export { PresenceStatus, DeviceInfo, UserPresence, PresenceConfig, PresenceChangeEvent, ActivityUpdate } from './presence.js';
24
25
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,SAAS,EACT,UAAU,EACV,eAAe,EACf,cAAc,EACd,WAAW,EACX,iBAAiB,EACjB,mBAAmB,EACnB,KAAK,EACN,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,YAAY,EACZ,UAAU,EACV,cAAc,EACd,aAAa,EACb,WAAW,EACX,SAAS,EACT,WAAW,EACX,YAAY,EACb,MAAM,WAAW,CAAC;AAEnB,OAAO,EACL,cAAc,EACd,IAAI,EACJ,QAAQ,EACR,UAAU,EACV,SAAS,EACT,UAAU,EACX,MAAM,WAAW,CAAC;AAEnB,OAAO,EACL,QAAQ,EACR,YAAY,EACZ,IAAI,EACJ,WAAW,EACX,aAAa,EACb,SAAS,EACV,MAAM,WAAW,CAAC;AAEnB,MAAM,MAAM,eAAe,GAAG,YAAY,GAAG,WAAW,GAAG,eAAe,GAAG,cAAc,CAAC;AAE5F,MAAM,WAAW,iBAAiB;IAChC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AACxE,MAAM,MAAM,YAAY,GAAG,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;AAClD,MAAM,MAAM,YAAY,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;AAElE,OAAO,EACL,yBAAyB,EACzB,eAAe,EACf,eAAe,EACf,gBAAgB,EAChB,sBAAsB,EACtB,wBAAwB,EACzB,MAAM,mBAAmB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,SAAS,EACT,UAAU,EACV,eAAe,EACf,cAAc,EACd,WAAW,EACX,iBAAiB,EACjB,mBAAmB,EACnB,KAAK,EACN,MAAM,aAAa,CAAC;AAErB,OAAO,EACL,YAAY,EACZ,UAAU,EACV,cAAc,EACd,aAAa,EACb,WAAW,EACX,SAAS,EACT,WAAW,EACX,YAAY,EACb,MAAM,WAAW,CAAC;AAEnB,OAAO,EACL,cAAc,EACd,IAAI,EACJ,QAAQ,EACR,UAAU,EACV,SAAS,EACT,UAAU,EACX,MAAM,WAAW,CAAC;AAEnB,OAAO,EACL,QAAQ,EACR,YAAY,EACZ,IAAI,EACJ,WAAW,EACX,aAAa,EACb,SAAS,EACV,MAAM,WAAW,CAAC;AAEnB,MAAM,MAAM,eAAe,GAAG,YAAY,GAAG,WAAW,GAAG,eAAe,GAAG,cAAc,CAAC;AAE5F,MAAM,WAAW,iBAAiB;IAChC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AACxE,MAAM,MAAM,YAAY,GAAG,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;AAClD,MAAM,MAAM,YAAY,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;AAElE,OAAO,EACL,yBAAyB,EACzB,eAAe,EACf,eAAe,EACf,gBAAgB,EAChB,sBAAsB,EACtB,wBAAwB,EACzB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,cAAc,EACd,UAAU,EACV,YAAY,EACZ,cAAc,EACd,mBAAmB,EACnB,cAAc,EACf,MAAM,eAAe,CAAC"}