@principal-ai/control-tower-core 0.1.0 → 0.1.2

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.
Files changed (84) hide show
  1. package/README.md +84 -0
  2. package/dist/abstractions/AuthAdapter.d.ts +9 -0
  3. package/dist/abstractions/AuthAdapter.d.ts.map +1 -0
  4. package/dist/abstractions/AuthAdapter.js +1 -0
  5. package/dist/abstractions/DefaultLockManager.d.ts +18 -0
  6. package/dist/abstractions/DefaultLockManager.d.ts.map +1 -0
  7. package/dist/abstractions/DefaultLockManager.js +152 -0
  8. package/dist/abstractions/DefaultRoomManager.d.ts +15 -0
  9. package/dist/abstractions/DefaultRoomManager.d.ts.map +1 -0
  10. package/dist/abstractions/DefaultRoomManager.js +91 -0
  11. package/dist/abstractions/EventEmitter.d.ts +14 -0
  12. package/dist/abstractions/EventEmitter.d.ts.map +1 -0
  13. package/dist/abstractions/EventEmitter.js +56 -0
  14. package/dist/abstractions/LockManager.d.ts +16 -0
  15. package/dist/abstractions/LockManager.d.ts.map +1 -0
  16. package/dist/abstractions/LockManager.js +9 -0
  17. package/dist/abstractions/RoomManager.d.ts +15 -0
  18. package/dist/abstractions/RoomManager.d.ts.map +1 -0
  19. package/dist/abstractions/RoomManager.js +5 -0
  20. package/dist/abstractions/StorageAdapter.d.ts +25 -0
  21. package/dist/abstractions/StorageAdapter.d.ts.map +1 -0
  22. package/dist/abstractions/StorageAdapter.js +1 -0
  23. package/dist/abstractions/TransportAdapter.d.ts +17 -0
  24. package/dist/abstractions/TransportAdapter.d.ts.map +1 -0
  25. package/dist/abstractions/TransportAdapter.js +1 -0
  26. package/dist/abstractions/index.d.ts +9 -0
  27. package/dist/abstractions/index.d.ts.map +1 -0
  28. package/dist/abstractions/index.js +5 -0
  29. package/dist/adapters/mock/MockAuthAdapter.d.ts +27 -0
  30. package/dist/adapters/mock/MockAuthAdapter.d.ts.map +1 -0
  31. package/dist/adapters/mock/MockAuthAdapter.js +161 -0
  32. package/dist/adapters/mock/MockStorageAdapter.d.ts +27 -0
  33. package/dist/adapters/mock/MockStorageAdapter.d.ts.map +1 -0
  34. package/dist/adapters/mock/MockStorageAdapter.js +162 -0
  35. package/dist/adapters/mock/MockTransportAdapter.d.ts +31 -0
  36. package/dist/adapters/mock/MockTransportAdapter.d.ts.map +1 -0
  37. package/dist/adapters/mock/MockTransportAdapter.js +90 -0
  38. package/dist/adapters/mock/index.d.ts +4 -0
  39. package/dist/adapters/mock/index.d.ts.map +1 -0
  40. package/dist/adapters/mock/index.js +3 -0
  41. package/dist/adapters/websocket/WebSocketTransportAdapter.d.ts +40 -0
  42. package/dist/adapters/websocket/WebSocketTransportAdapter.d.ts.map +1 -0
  43. package/dist/adapters/websocket/WebSocketTransportAdapter.js +204 -0
  44. package/dist/adapters/websocket/index.d.ts +2 -0
  45. package/dist/adapters/websocket/index.d.ts.map +1 -0
  46. package/dist/adapters/websocket/index.js +1 -0
  47. package/dist/client/BaseClient.d.ts +103 -0
  48. package/dist/client/BaseClient.d.ts.map +1 -0
  49. package/dist/client/BaseClient.js +282 -0
  50. package/dist/client/ClientBuilder.d.ts +16 -0
  51. package/dist/client/ClientBuilder.d.ts.map +1 -0
  52. package/dist/client/ClientBuilder.js +37 -0
  53. package/dist/client/index.d.ts +3 -0
  54. package/dist/client/index.d.ts.map +1 -0
  55. package/dist/client/index.js +3 -0
  56. package/dist/index.d.ts +7 -0
  57. package/dist/index.d.ts.map +1 -0
  58. package/dist/index.js +9 -1205
  59. package/dist/index.js.map +23 -6
  60. package/dist/server/BaseServer.d.ts +116 -0
  61. package/dist/server/BaseServer.d.ts.map +1 -0
  62. package/dist/server/BaseServer.js +422 -0
  63. package/dist/server/ServerBuilder.d.ts +32 -0
  64. package/dist/server/ServerBuilder.d.ts.map +1 -0
  65. package/dist/server/ServerBuilder.js +66 -0
  66. package/dist/server/index.d.ts +3 -0
  67. package/dist/server/index.d.ts.map +1 -0
  68. package/dist/server/index.js +3 -0
  69. package/dist/types/auth.d.ts +40 -0
  70. package/dist/types/auth.d.ts.map +1 -0
  71. package/dist/types/auth.js +1 -0
  72. package/dist/types/events.d.ts +66 -0
  73. package/dist/types/events.d.ts.map +1 -0
  74. package/dist/types/events.js +1 -0
  75. package/dist/types/index.d.ts +23 -0
  76. package/dist/types/index.d.ts.map +1 -0
  77. package/dist/types/index.js +1 -0
  78. package/dist/types/lock.d.ts +35 -0
  79. package/dist/types/lock.d.ts.map +1 -0
  80. package/dist/types/lock.js +1 -0
  81. package/dist/types/room.d.ts +40 -0
  82. package/dist/types/room.d.ts.map +1 -0
  83. package/dist/types/room.js +1 -0
  84. package/package.json +7 -3
package/README.md ADDED
@@ -0,0 +1,84 @@
1
+ # Control Tower Core
2
+
3
+ Centralized, runtime-agnostic library for real-time collaboration and synchronization.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @principal-ai/control-tower-core
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```typescript
14
+ import {
15
+ ServerBuilder,
16
+ DefaultRoomManager,
17
+ DefaultLockManager,
18
+ MockTransportAdapter
19
+ } from '@principal-ai/control-tower-core';
20
+
21
+ // Create a server with default implementations
22
+ const server = new ServerBuilder()
23
+ .withTransport(new MockTransportAdapter())
24
+ .withRoomManager(new DefaultRoomManager())
25
+ .withLockManager(new DefaultLockManager())
26
+ .build();
27
+
28
+ await server.start(8080);
29
+ console.log('Server started on port 8080');
30
+ ```
31
+
32
+ ## Features
33
+
34
+ - **Room Management**: Create, join, and manage collaborative rooms
35
+ - **Lock Management**: File/directory locking with queue support
36
+ - **Real-time Events**: Event broadcasting and history
37
+ - **Extensible**: Abstract interfaces for custom implementations
38
+ - **TypeScript**: Full type safety with generated declarations
39
+
40
+ ## API Reference
41
+
42
+ ### ServerBuilder
43
+
44
+ The main entry point for creating servers:
45
+
46
+ ```typescript
47
+ const server = new ServerBuilder()
48
+ .withTransport(transportAdapter)
49
+ .withRoomManager(roomManager)
50
+ .withLockManager(lockManager)
51
+ .withAuth(authAdapter) // optional
52
+ .withStorage(storageAdapter) // optional
53
+ .withDefaultRoomConfig({
54
+ maxUsers: 50,
55
+ maxHistory: 100,
56
+ permissions: ['read', 'write']
57
+ })
58
+ .build();
59
+ ```
60
+
61
+ ### Default Implementations
62
+
63
+ - `DefaultRoomManager`: In-memory room management
64
+ - `DefaultLockManager`: In-memory locking with queue support
65
+ - `MockTransportAdapter`: Mock transport for testing
66
+
67
+ ### Custom Implementations
68
+
69
+ Implement the abstract interfaces to create custom adapters:
70
+
71
+ ```typescript
72
+ import { RoomManager } from '@principal-ai/control-tower-core';
73
+
74
+ class CustomRoomManager extends RoomManager {
75
+ async createRoom(id: string, config: RoomConfig): Promise<Room> {
76
+ // Your implementation
77
+ }
78
+ // ... implement other methods
79
+ }
80
+ ```
81
+
82
+ ## License
83
+
84
+ MIT
@@ -0,0 +1,9 @@
1
+ import type { TokenPayload, AuthResult, Credentials } from '../types';
2
+ export interface IAuthAdapter {
3
+ validateToken(token: string): Promise<TokenPayload>;
4
+ generateToken(payload: TokenPayload): Promise<string>;
5
+ refreshToken(token: string): Promise<string>;
6
+ revokeToken(token: string): Promise<void>;
7
+ authenticate(credentials: Credentials): Promise<AuthResult>;
8
+ }
9
+ //# sourceMappingURL=AuthAdapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AuthAdapter.d.ts","sourceRoot":"","sources":["../../src/abstractions/AuthAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EACZ,UAAU,EACV,WAAW,EACZ,MAAM,UAAU,CAAC;AAElB,MAAM,WAAW,YAAY;IAC3B,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAAC;IACpD,aAAa,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACtD,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC7C,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1C,YAAY,CAAC,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;CAC7D"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,18 @@
1
+ import type { Lock, LockRequest } from '../types';
2
+ import { LockManager } from './LockManager';
3
+ export declare class DefaultLockManager extends LockManager {
4
+ acquireLock(userId: string, username: string, request: LockRequest): Promise<Lock>;
5
+ releaseLock(lockId: string): Promise<void>;
6
+ releaseUserLocks(userId: string): Promise<void>;
7
+ getLock(path: string): Promise<Lock | null>;
8
+ getUserLocks(userId: string): Promise<Lock[]>;
9
+ getAllLocks(): Promise<Lock[]>;
10
+ isLocked(path: string): Promise<boolean>;
11
+ getQueueLength(path: string): Promise<number>;
12
+ extendLock(lockId: string, ttl: number): Promise<Lock>;
13
+ addToQueue(userId: string, username: string, request: LockRequest): Promise<void>;
14
+ removeFromQueue(path: string, userId: string): Promise<void>;
15
+ private generateId;
16
+ private processQueue;
17
+ }
18
+ //# sourceMappingURL=DefaultLockManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DefaultLockManager.d.ts","sourceRoot":"","sources":["../../src/abstractions/DefaultLockManager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,IAAI,EACJ,WAAW,EAEZ,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,qBAAa,kBAAmB,SAAQ,WAAW;IAC3C,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAyClF,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAsB1C,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAe/C,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IAS3C,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IAK7C,WAAW,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;IAI9B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAIxC,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAK7C,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAUtD,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAiBjF,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAelE,OAAO,CAAC,UAAU;YAIJ,YAAY;CA2B3B"}
@@ -0,0 +1,152 @@
1
+ import { LockManager } from './LockManager';
2
+ export class DefaultLockManager extends LockManager {
3
+ async acquireLock(userId, username, request) {
4
+ const { path, type = 'file', priority = 'normal', ttl, branch, metadata } = request;
5
+ // Check if user already has a lock on this path
6
+ const userLocks = this.lockState.userLocks.get(userId) || new Set();
7
+ if (userLocks.has(path)) {
8
+ throw new Error(`User ${username} already has a lock on ${path}`);
9
+ }
10
+ // Check if path is already locked
11
+ const existingLock = await this.getLock(path);
12
+ if (existingLock) {
13
+ // Add to queue
14
+ await this.addToQueue(userId, username, request);
15
+ throw new Error(`Path ${path} is already locked by ${existingLock.username}, added to queue`);
16
+ }
17
+ // Generate lock ID
18
+ const lockId = this.generateId();
19
+ // Create lock
20
+ const lock = {
21
+ id: lockId,
22
+ type,
23
+ path,
24
+ userId,
25
+ username,
26
+ acquiredAt: Date.now(),
27
+ expiresAt: ttl ? Date.now() + ttl : undefined,
28
+ priority,
29
+ branch,
30
+ metadata
31
+ };
32
+ // Store lock
33
+ this.lockState.locks.set(lockId, lock);
34
+ this.lockState.userLocks.set(userId, userLocks.add(path));
35
+ return lock;
36
+ }
37
+ async releaseLock(lockId) {
38
+ const lock = this.lockState.locks.get(lockId);
39
+ if (!lock) {
40
+ throw new Error(`Lock ${lockId} not found`);
41
+ }
42
+ // Remove from user locks
43
+ const userLocks = this.lockState.userLocks.get(lock.userId);
44
+ if (userLocks) {
45
+ userLocks.delete(lock.path);
46
+ if (userLocks.size === 0) {
47
+ this.lockState.userLocks.delete(lock.userId);
48
+ }
49
+ }
50
+ // Remove lock
51
+ this.lockState.locks.delete(lockId);
52
+ // Process queue for this path
53
+ await this.processQueue(lock.path);
54
+ }
55
+ async releaseUserLocks(userId) {
56
+ const userLocks = this.lockState.userLocks.get(userId);
57
+ if (!userLocks) {
58
+ return;
59
+ }
60
+ const lockIds = Array.from(this.lockState.locks.entries())
61
+ .filter(([, lock]) => lock.userId === userId)
62
+ .map(([lockId]) => lockId);
63
+ for (const lockId of lockIds) {
64
+ await this.releaseLock(lockId);
65
+ }
66
+ }
67
+ async getLock(path) {
68
+ for (const lock of this.lockState.locks.values()) {
69
+ if (lock.path === path) {
70
+ return lock;
71
+ }
72
+ }
73
+ return null;
74
+ }
75
+ async getUserLocks(userId) {
76
+ return Array.from(this.lockState.locks.values())
77
+ .filter(lock => lock.userId === userId);
78
+ }
79
+ async getAllLocks() {
80
+ return Array.from(this.lockState.locks.values());
81
+ }
82
+ async isLocked(path) {
83
+ return await this.getLock(path) !== null;
84
+ }
85
+ async getQueueLength(path) {
86
+ const queue = this.lockState.queue.get(path);
87
+ return queue ? queue.length : 0;
88
+ }
89
+ async extendLock(lockId, ttl) {
90
+ const lock = this.lockState.locks.get(lockId);
91
+ if (!lock) {
92
+ throw new Error(`Lock ${lockId} not found`);
93
+ }
94
+ lock.expiresAt = Date.now() + ttl;
95
+ return lock;
96
+ }
97
+ async addToQueue(userId, username, request) {
98
+ const { path } = request;
99
+ const queue = this.lockState.queue.get(path) || [];
100
+ const queueItem = {
101
+ ...request,
102
+ userId,
103
+ username,
104
+ requestedAt: Date.now(),
105
+ resolve: () => { },
106
+ reject: () => { }
107
+ };
108
+ queue.push(queueItem);
109
+ this.lockState.queue.set(path, queue);
110
+ }
111
+ async removeFromQueue(path, userId) {
112
+ const queue = this.lockState.queue.get(path);
113
+ if (!queue) {
114
+ return;
115
+ }
116
+ const index = queue.findIndex(item => item.userId === userId);
117
+ if (index !== -1) {
118
+ queue.splice(index, 1);
119
+ if (queue.length === 0) {
120
+ this.lockState.queue.delete(path);
121
+ }
122
+ }
123
+ }
124
+ generateId() {
125
+ return Math.random().toString(36).substring(2) + Date.now().toString(36);
126
+ }
127
+ async processQueue(path) {
128
+ const queue = this.lockState.queue.get(path);
129
+ if (!queue || queue.length === 0) {
130
+ return;
131
+ }
132
+ // Process first item in queue
133
+ const item = queue.shift();
134
+ if (queue.length === 0) {
135
+ this.lockState.queue.delete(path);
136
+ }
137
+ try {
138
+ const lock = await this.acquireLock(item.userId, item.username, {
139
+ path: item.path,
140
+ type: item.type,
141
+ priority: item.priority,
142
+ ttl: item.ttl,
143
+ branch: item.branch,
144
+ metadata: item.metadata
145
+ });
146
+ item.resolve(lock);
147
+ }
148
+ catch (error) {
149
+ item.reject(error);
150
+ }
151
+ }
152
+ }
@@ -0,0 +1,15 @@
1
+ import type { Room, RoomUser, RoomState, RoomConfig, Event } from '../types';
2
+ import { RoomManager } from './RoomManager';
3
+ export declare class DefaultRoomManager extends RoomManager {
4
+ createRoom(id: string, config: RoomConfig): Promise<Room>;
5
+ deleteRoom(id: string): Promise<void>;
6
+ joinRoom(roomId: string, user: RoomUser): Promise<void>;
7
+ leaveRoom(roomId: string, userId: string): Promise<void>;
8
+ broadcastToRoom(roomId: string, event: Event, _excludeUserId?: string): Promise<void>;
9
+ getRoomState(roomId: string): Promise<RoomState | null>;
10
+ getUsersInRoom(roomId: string): Promise<RoomUser[]>;
11
+ addEventToHistory(roomId: string, event: Event): Promise<void>;
12
+ getEventHistory(roomId: string, limit?: number): Promise<Event[]>;
13
+ updateUserStatus(roomId: string, userId: string, status: RoomUser['status']): Promise<void>;
14
+ }
15
+ //# sourceMappingURL=DefaultRoomManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DefaultRoomManager.d.ts","sourceRoot":"","sources":["../../src/abstractions/DefaultRoomManager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,IAAI,EACJ,QAAQ,EACR,SAAS,EACT,UAAU,EACV,KAAK,EACN,MAAM,UAAU,CAAC;AAClB,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAE5C,qBAAa,kBAAmB,SAAQ,WAAW;IAC3C,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAsBzD,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIrC,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAavD,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IASxD,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,cAAc,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAWrF,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC;IAIvD,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IASnD,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC;IAc9D,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IAUjE,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;CAYlG"}
@@ -0,0 +1,91 @@
1
+ import { RoomManager } from './RoomManager';
2
+ export class DefaultRoomManager extends RoomManager {
3
+ async createRoom(id, config) {
4
+ const room = {
5
+ id,
6
+ name: config.name || id,
7
+ createdAt: Date.now(),
8
+ maxUsers: config.maxUsers,
9
+ maxHistory: config.maxHistory,
10
+ permissions: config.permissions,
11
+ metadata: config.metadata || {}
12
+ };
13
+ const roomState = {
14
+ room,
15
+ users: new Map(),
16
+ eventHistory: [],
17
+ locks: new Map()
18
+ };
19
+ this.rooms.set(id, roomState);
20
+ return room;
21
+ }
22
+ async deleteRoom(id) {
23
+ this.rooms.delete(id);
24
+ }
25
+ async joinRoom(roomId, user) {
26
+ const roomState = this.rooms.get(roomId);
27
+ if (!roomState) {
28
+ throw new Error(`Room ${roomId} not found`);
29
+ }
30
+ if (roomState.room.maxUsers && roomState.users.size >= roomState.room.maxUsers) {
31
+ throw new Error(`Room ${roomId} is full`);
32
+ }
33
+ roomState.users.set(user.id, user);
34
+ }
35
+ async leaveRoom(roomId, userId) {
36
+ const roomState = this.rooms.get(roomId);
37
+ if (!roomState) {
38
+ return; // Room doesn't exist, nothing to do
39
+ }
40
+ roomState.users.delete(userId);
41
+ }
42
+ async broadcastToRoom(roomId, event, _excludeUserId) {
43
+ const roomState = this.rooms.get(roomId);
44
+ if (!roomState) {
45
+ throw new Error(`Room ${roomId} not found`);
46
+ }
47
+ // In a real implementation, this would broadcast to connected clients
48
+ // For now, we'll just store the event in history
49
+ await this.addEventToHistory(roomId, event);
50
+ }
51
+ async getRoomState(roomId) {
52
+ return this.rooms.get(roomId) || null;
53
+ }
54
+ async getUsersInRoom(roomId) {
55
+ const roomState = this.rooms.get(roomId);
56
+ if (!roomState) {
57
+ return [];
58
+ }
59
+ return Array.from(roomState.users.values());
60
+ }
61
+ async addEventToHistory(roomId, event) {
62
+ const roomState = this.rooms.get(roomId);
63
+ if (!roomState) {
64
+ throw new Error(`Room ${roomId} not found`);
65
+ }
66
+ roomState.eventHistory.push(event);
67
+ // Trim history if needed
68
+ if (roomState.room.maxHistory && roomState.eventHistory.length > roomState.room.maxHistory) {
69
+ roomState.eventHistory = roomState.eventHistory.slice(-roomState.room.maxHistory);
70
+ }
71
+ }
72
+ async getEventHistory(roomId, limit) {
73
+ const roomState = this.rooms.get(roomId);
74
+ if (!roomState) {
75
+ return [];
76
+ }
77
+ const history = roomState.eventHistory;
78
+ return limit ? history.slice(-limit) : history;
79
+ }
80
+ async updateUserStatus(roomId, userId, status) {
81
+ const roomState = this.rooms.get(roomId);
82
+ if (!roomState) {
83
+ throw new Error(`Room ${roomId} not found`);
84
+ }
85
+ const user = roomState.users.get(userId);
86
+ if (user) {
87
+ user.status = status;
88
+ user.lastActivity = Date.now();
89
+ }
90
+ }
91
+ }
@@ -0,0 +1,14 @@
1
+ export type EventData = unknown;
2
+ export type EventListener<T = EventData> = (data: T) => void | Promise<void>;
3
+ export type UnsubscribeFn = () => void;
4
+ export declare class TypedEventEmitter<TEvents extends Record<string, EventData>> {
5
+ private listeners;
6
+ private onceListeners;
7
+ on<K extends keyof TEvents>(event: K, listener: EventListener<TEvents[K]>): UnsubscribeFn;
8
+ once<K extends keyof TEvents>(event: K, listener: EventListener<TEvents[K]>): UnsubscribeFn;
9
+ off<K extends keyof TEvents>(event: K, listener: EventListener<TEvents[K]>): void;
10
+ emit<K extends keyof TEvents>(event: K, data: TEvents[K]): Promise<void>;
11
+ removeAllListeners(event?: keyof TEvents): void;
12
+ listenerCount(event: keyof TEvents): number;
13
+ }
14
+ //# sourceMappingURL=EventEmitter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"EventEmitter.d.ts","sourceRoot":"","sources":["../../src/abstractions/EventEmitter.ts"],"names":[],"mappings":"AACA,MAAM,MAAM,SAAS,GAAG,OAAO,CAAC;AAEhC,MAAM,MAAM,aAAa,CAAC,CAAC,GAAG,SAAS,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAC7E,MAAM,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC;AAEvC,qBAAa,iBAAiB,CAAC,OAAO,SAAS,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC;IAEtE,OAAO,CAAC,SAAS,CAA2D;IAC5E,OAAO,CAAC,aAAa,CAA2D;IAEhF,EAAE,CAAC,CAAC,SAAS,MAAM,OAAO,EACxB,KAAK,EAAE,CAAC,EACR,QAAQ,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAClC,aAAa;IAShB,IAAI,CAAC,CAAC,SAAS,MAAM,OAAO,EAC1B,KAAK,EAAE,CAAC,EACR,QAAQ,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAClC,aAAa;IAShB,GAAG,CAAC,CAAC,SAAS,MAAM,OAAO,EACzB,KAAK,EAAE,CAAC,EACR,QAAQ,EAAE,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,GAClC,IAAI;IAKD,IAAI,CAAC,CAAC,SAAS,MAAM,OAAO,EAChC,KAAK,EAAE,CAAC,EACR,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,GACf,OAAO,CAAC,IAAI,CAAC;IAmBhB,kBAAkB,CAAC,KAAK,CAAC,EAAE,MAAM,OAAO,GAAG,IAAI;IAU/C,aAAa,CAAC,KAAK,EAAE,MAAM,OAAO,GAAG,MAAM;CAK5C"}
@@ -0,0 +1,56 @@
1
+ export class TypedEventEmitter {
2
+ constructor() {
3
+ // Use unknown type for storage, will be cast appropriately when called
4
+ this.listeners = new Map();
5
+ this.onceListeners = new Map();
6
+ }
7
+ on(event, listener) {
8
+ if (!this.listeners.has(event)) {
9
+ this.listeners.set(event, new Set());
10
+ }
11
+ this.listeners.get(event).add(listener);
12
+ return () => this.off(event, listener);
13
+ }
14
+ once(event, listener) {
15
+ if (!this.onceListeners.has(event)) {
16
+ this.onceListeners.set(event, new Set());
17
+ }
18
+ this.onceListeners.get(event).add(listener);
19
+ return () => this.off(event, listener);
20
+ }
21
+ off(event, listener) {
22
+ this.listeners.get(event)?.delete(listener);
23
+ this.onceListeners.get(event)?.delete(listener);
24
+ }
25
+ async emit(event, data) {
26
+ const listeners = this.listeners.get(event);
27
+ const onceListeners = this.onceListeners.get(event);
28
+ if (onceListeners) {
29
+ const listenersToCall = Array.from(onceListeners);
30
+ this.onceListeners.delete(event);
31
+ for (const listener of listenersToCall) {
32
+ await listener(data);
33
+ }
34
+ }
35
+ if (listeners) {
36
+ for (const listener of Array.from(listeners)) {
37
+ await listener(data);
38
+ }
39
+ }
40
+ }
41
+ removeAllListeners(event) {
42
+ if (event) {
43
+ this.listeners.delete(event);
44
+ this.onceListeners.delete(event);
45
+ }
46
+ else {
47
+ this.listeners.clear();
48
+ this.onceListeners.clear();
49
+ }
50
+ }
51
+ listenerCount(event) {
52
+ const regular = this.listeners.get(event)?.size ?? 0;
53
+ const once = this.onceListeners.get(event)?.size ?? 0;
54
+ return regular + once;
55
+ }
56
+ }
@@ -0,0 +1,16 @@
1
+ import type { Lock, LockRequest, LockState } from '../types';
2
+ export declare abstract class LockManager {
3
+ protected lockState: LockState;
4
+ abstract acquireLock(userId: string, username: string, request: LockRequest): Promise<Lock>;
5
+ abstract releaseLock(lockId: string): Promise<void>;
6
+ abstract releaseUserLocks(userId: string): Promise<void>;
7
+ abstract getLock(path: string): Promise<Lock | null>;
8
+ abstract getUserLocks(userId: string): Promise<Lock[]>;
9
+ abstract getAllLocks(): Promise<Lock[]>;
10
+ abstract isLocked(path: string): Promise<boolean>;
11
+ abstract getQueueLength(path: string): Promise<number>;
12
+ abstract extendLock(lockId: string, ttl: number): Promise<Lock>;
13
+ abstract addToQueue(userId: string, username: string, request: LockRequest): Promise<void>;
14
+ abstract removeFromQueue(path: string, userId: string): Promise<void>;
15
+ }
16
+ //# sourceMappingURL=LockManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LockManager.d.ts","sourceRoot":"","sources":["../../src/abstractions/LockManager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,IAAI,EACJ,WAAW,EACX,SAAS,EACV,MAAM,UAAU,CAAC;AAElB,8BAAsB,WAAW;IAC/B,SAAS,CAAC,SAAS,EAAE,SAAS,CAI5B;IAEF,QAAQ,CAAC,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAC3F,QAAQ,CAAC,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IACnD,QAAQ,CAAC,gBAAgB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IACxD,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC;IACpD,QAAQ,CAAC,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IACtD,QAAQ,CAAC,WAAW,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;IACvC,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IACjD,QAAQ,CAAC,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IACtD,QAAQ,CAAC,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAC/D,QAAQ,CAAC,UAAU,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAC1F,QAAQ,CAAC,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CACtE"}
@@ -0,0 +1,9 @@
1
+ export class LockManager {
2
+ constructor() {
3
+ this.lockState = {
4
+ locks: new Map(),
5
+ queue: new Map(),
6
+ userLocks: new Map()
7
+ };
8
+ }
9
+ }
@@ -0,0 +1,15 @@
1
+ import type { Room, RoomUser, RoomState, RoomConfig, Event } from '../types';
2
+ export declare abstract class RoomManager {
3
+ protected rooms: Map<string, RoomState>;
4
+ abstract createRoom(id: string, config: RoomConfig): Promise<Room>;
5
+ abstract deleteRoom(id: string): Promise<void>;
6
+ abstract joinRoom(roomId: string, user: RoomUser): Promise<void>;
7
+ abstract leaveRoom(roomId: string, userId: string): Promise<void>;
8
+ abstract broadcastToRoom(roomId: string, event: Event, excludeUserId?: string): Promise<void>;
9
+ abstract getRoomState(roomId: string): Promise<RoomState | null>;
10
+ abstract getUsersInRoom(roomId: string): Promise<RoomUser[]>;
11
+ abstract addEventToHistory(roomId: string, event: Event): Promise<void>;
12
+ abstract getEventHistory(roomId: string, limit?: number): Promise<Event[]>;
13
+ abstract updateUserStatus(roomId: string, userId: string, status: RoomUser['status']): Promise<void>;
14
+ }
15
+ //# sourceMappingURL=RoomManager.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RoomManager.d.ts","sourceRoot":"","sources":["../../src/abstractions/RoomManager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,IAAI,EACJ,QAAQ,EACR,SAAS,EACT,UAAU,EACV,KAAK,EACN,MAAM,UAAU,CAAC;AAElB,8BAAsB,WAAW;IAC/B,SAAS,CAAC,KAAK,yBAAgC;IAE/C,QAAQ,CAAC,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC;IAClE,QAAQ,CAAC,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAC9C,QAAQ,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAChE,QAAQ,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IACjE,QAAQ,CAAC,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,aAAa,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAC7F,QAAQ,CAAC,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC;IAChE,QAAQ,CAAC,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAC5D,QAAQ,CAAC,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC;IACvE,QAAQ,CAAC,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC;IAC1E,QAAQ,CAAC,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,QAAQ,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;CACrG"}
@@ -0,0 +1,5 @@
1
+ export class RoomManager {
2
+ constructor() {
3
+ this.rooms = new Map();
4
+ }
5
+ }
@@ -0,0 +1,25 @@
1
+ export type StorageOperation = {
2
+ type: 'get';
3
+ key: string;
4
+ } | {
5
+ type: 'set';
6
+ key: string;
7
+ value: unknown;
8
+ ttl?: number;
9
+ } | {
10
+ type: 'delete';
11
+ key: string;
12
+ } | {
13
+ type: 'exists';
14
+ key: string;
15
+ };
16
+ export interface IStorageAdapter {
17
+ get<T>(key: string): Promise<T | null>;
18
+ set<T>(key: string, value: T, ttl?: number): Promise<void>;
19
+ delete(key: string): Promise<void>;
20
+ exists(key: string): Promise<boolean>;
21
+ scan(pattern: string): Promise<string[]>;
22
+ clear(): Promise<void>;
23
+ transaction<T>(operations: StorageOperation[]): Promise<T>;
24
+ }
25
+ //# sourceMappingURL=StorageAdapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StorageAdapter.d.ts","sourceRoot":"","sources":["../../src/abstractions/StorageAdapter.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,gBAAgB,GACxB;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAC5B;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAC1D;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAC/B;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC;AAEpC,MAAM,WAAW,eAAe;IAC9B,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,GAAG,IAAI,CAAC,CAAC;IACvC,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3D,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnC,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACtC,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IACzC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,WAAW,CAAC,CAAC,EAAE,UAAU,EAAE,gBAAgB,EAAE,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;CAC5D"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,17 @@
1
+ import type { ConnectionState, ConnectionOptions, Message, MessageHandler, ErrorHandler, CloseHandler } from '../types';
2
+ import type { Server as HttpServer } from 'http';
3
+ import type { Server as HttpsServer } from 'https';
4
+ import type { WebSocketServer } from 'ws';
5
+ export interface ITransportAdapter {
6
+ connect(url: string, options?: ConnectionOptions): Promise<void>;
7
+ disconnect(): Promise<void>;
8
+ send(message: Message): Promise<void>;
9
+ onMessage(handler: MessageHandler): void;
10
+ onError(handler: ErrorHandler): void;
11
+ onClose(handler: CloseHandler): void;
12
+ getState(): ConnectionState;
13
+ isConnected(): boolean;
14
+ attach?(server: HttpServer | HttpsServer, path?: string): Promise<void>;
15
+ attachToWebSocketServer?(wss: WebSocketServer): Promise<void>;
16
+ }
17
+ //# sourceMappingURL=TransportAdapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TransportAdapter.d.ts","sourceRoot":"","sources":["../../src/abstractions/TransportAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,eAAe,EACf,iBAAiB,EACjB,OAAO,EACP,cAAc,EACd,YAAY,EACZ,YAAY,EACb,MAAM,UAAU,CAAC;AAClB,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,MAAM,WAAW,iBAAiB;IAEhC,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,iBAAiB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACjE,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5B,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC,SAAS,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI,CAAC;IACzC,OAAO,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI,CAAC;IACrC,OAAO,CAAC,OAAO,EAAE,YAAY,GAAG,IAAI,CAAC;IACrC,QAAQ,IAAI,eAAe,CAAC;IAC5B,WAAW,IAAI,OAAO,CAAC;IAGvB,MAAM,CAAC,CAAC,MAAM,EAAE,UAAU,GAAG,WAAW,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxE,uBAAuB,CAAC,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/D"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,9 @@
1
+ export { ITransportAdapter } from './TransportAdapter';
2
+ export { IStorageAdapter, StorageOperation } from './StorageAdapter';
3
+ export { IAuthAdapter } from './AuthAdapter';
4
+ export { TypedEventEmitter, EventListener, UnsubscribeFn } from './EventEmitter';
5
+ export { RoomManager } from './RoomManager';
6
+ export { LockManager } from './LockManager';
7
+ export { DefaultRoomManager } from './DefaultRoomManager';
8
+ export { DefaultLockManager } from './DefaultLockManager';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/abstractions/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACrE,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACjF,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC"}
@@ -0,0 +1,5 @@
1
+ export { TypedEventEmitter } from './EventEmitter';
2
+ export { RoomManager } from './RoomManager';
3
+ export { LockManager } from './LockManager';
4
+ export { DefaultRoomManager } from './DefaultRoomManager';
5
+ export { DefaultLockManager } from './DefaultLockManager';
@@ -0,0 +1,27 @@
1
+ import type { IAuthAdapter } from '../../abstractions/AuthAdapter';
2
+ import type { TokenPayload, AuthResult, Credentials } from '../../types';
3
+ export declare class MockAuthAdapter implements IAuthAdapter {
4
+ private tokens;
5
+ private revokedTokens;
6
+ private users;
7
+ private simulateLatency;
8
+ private shouldFailAuth;
9
+ private tokenCounter;
10
+ constructor(options?: {
11
+ simulateLatency?: number;
12
+ shouldFailAuth?: boolean;
13
+ });
14
+ validateToken(token: string): Promise<TokenPayload>;
15
+ generateToken(payload: TokenPayload): Promise<string>;
16
+ refreshToken(token: string): Promise<string>;
17
+ revokeToken(token: string): Promise<void>;
18
+ authenticate(credentials: Credentials): Promise<AuthResult>;
19
+ private simulateDelay;
20
+ addUser(username: string, password: string, payload: TokenPayload): void;
21
+ removeUser(username: string): void;
22
+ getTokenCount(): number;
23
+ getRevokedTokenCount(): number;
24
+ clearTokens(): void;
25
+ setFailAuth(fail: boolean): void;
26
+ }
27
+ //# sourceMappingURL=MockAuthAdapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MockAuthAdapter.d.ts","sourceRoot":"","sources":["../../../src/adapters/mock/MockAuthAdapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AACnE,OAAO,KAAK,EACV,YAAY,EACZ,UAAU,EACV,WAAW,EACZ,MAAM,aAAa,CAAC;AAErB,qBAAa,eAAgB,YAAW,YAAY;IAClD,OAAO,CAAC,MAAM,CAAwC;IACtD,OAAO,CAAC,aAAa,CAA0B;IAC/C,OAAO,CAAC,KAAK,CAAuE;IACpF,OAAO,CAAC,eAAe,CAAa;IACpC,OAAO,CAAC,cAAc,CAAkB;IACxC,OAAO,CAAC,YAAY,CAAa;gBAErB,OAAO,CAAC,EAAE;QACpB,eAAe,CAAC,EAAE,MAAM,CAAC;QACzB,cAAc,CAAC,EAAE,OAAO,CAAC;KAC1B;IAoBK,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC;IAyBnD,aAAa,CAAC,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC;IAgBrD,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAqB5C,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAWzC,YAAY,CAAC,WAAW,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,CAAC;YAuEnD,aAAa;IAM3B,OAAO,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,IAAI;IAIxE,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAIlC,aAAa,IAAI,MAAM;IAIvB,oBAAoB,IAAI,MAAM;IAI9B,WAAW,IAAI,IAAI;IAKnB,WAAW,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI;CAGjC"}