driftdetect-dashboard 0.8.1 → 0.8.3

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,64 @@
1
+ /**
2
+ * DashboardServer
3
+ *
4
+ * Main server class that orchestrates Express and WebSocket servers
5
+ * for the Drift Dashboard.
6
+ *
7
+ * @requirements 1.1 - Start an Express server on localhost:3847
8
+ * @requirements 1.2 - Start on the specified port
9
+ * @requirements 1.3 - Automatically open the default browser to the dashboard URL
10
+ * @requirements 1.5 - Handle port conflict errors gracefully
11
+ */
12
+ import { type DashboardViolation } from './drift-data-reader.js';
13
+ export interface DashboardServerOptions {
14
+ /** Port to listen on (default: 3847) */
15
+ port: number;
16
+ /** Path to the .drift directory */
17
+ driftDir: string;
18
+ /** Whether to automatically open browser on start */
19
+ openBrowser: boolean;
20
+ }
21
+ export declare class DashboardServer {
22
+ private readonly options;
23
+ private readonly reader;
24
+ private readonly wsManager;
25
+ private readonly patternWatcher;
26
+ private server;
27
+ constructor(options: DashboardServerOptions);
28
+ /**
29
+ * Get the configured port
30
+ */
31
+ get port(): number;
32
+ /**
33
+ * Get the drift directory path
34
+ */
35
+ get driftDir(): string;
36
+ /**
37
+ * Check if the server is running
38
+ */
39
+ get isRunning(): boolean;
40
+ /**
41
+ * Get the number of connected WebSocket clients
42
+ */
43
+ get connectedClients(): number;
44
+ /**
45
+ * Start the dashboard server
46
+ * @requirements 1.1, 1.2, 1.3
47
+ */
48
+ start(): Promise<void>;
49
+ /**
50
+ * Stop the dashboard server
51
+ */
52
+ stop(): Promise<void>;
53
+ /**
54
+ * Broadcast a violation to all connected WebSocket clients
55
+ * @requirements 2.3
56
+ */
57
+ broadcastViolation(violation: DashboardViolation): void;
58
+ /**
59
+ * Open the default browser to the dashboard URL
60
+ * @requirements 1.3
61
+ */
62
+ private openBrowser;
63
+ }
64
+ //# sourceMappingURL=dashboard-server.d.ts.map
@@ -0,0 +1,154 @@
1
+ /**
2
+ * DashboardServer
3
+ *
4
+ * Main server class that orchestrates Express and WebSocket servers
5
+ * for the Drift Dashboard.
6
+ *
7
+ * @requirements 1.1 - Start an Express server on localhost:3847
8
+ * @requirements 1.2 - Start on the specified port
9
+ * @requirements 1.3 - Automatically open the default browser to the dashboard URL
10
+ * @requirements 1.5 - Handle port conflict errors gracefully
11
+ */
12
+ import * as path from 'node:path';
13
+ import { fileURLToPath } from 'node:url';
14
+ import { DriftDataReader } from './drift-data-reader.js';
15
+ import { createExpressApp } from './express-app.js';
16
+ import { WebSocketManager } from './websocket-server.js';
17
+ import { PatternWatcher } from './pattern-watcher.js';
18
+ // Get the directory of this file for resolving static files
19
+ const __filename = fileURLToPath(import.meta.url);
20
+ const __dirname = path.dirname(__filename);
21
+ export class DashboardServer {
22
+ options;
23
+ reader;
24
+ wsManager;
25
+ patternWatcher;
26
+ server = null;
27
+ constructor(options) {
28
+ this.options = options;
29
+ this.reader = new DriftDataReader(options.driftDir);
30
+ this.wsManager = new WebSocketManager();
31
+ this.patternWatcher = new PatternWatcher({ driftDir: options.driftDir });
32
+ // Wire up pattern watcher to WebSocket broadcasts
33
+ this.patternWatcher.on('change', (event) => {
34
+ this.wsManager.broadcastPatternsChanged({
35
+ type: event.type,
36
+ category: event.category,
37
+ status: event.status,
38
+ });
39
+ });
40
+ }
41
+ /**
42
+ * Get the configured port
43
+ */
44
+ get port() {
45
+ return this.options.port;
46
+ }
47
+ /**
48
+ * Get the drift directory path
49
+ */
50
+ get driftDir() {
51
+ return this.options.driftDir;
52
+ }
53
+ /**
54
+ * Check if the server is running
55
+ */
56
+ get isRunning() {
57
+ return this.server !== null;
58
+ }
59
+ /**
60
+ * Get the number of connected WebSocket clients
61
+ */
62
+ get connectedClients() {
63
+ return this.wsManager.clientCount;
64
+ }
65
+ /**
66
+ * Start the dashboard server
67
+ * @requirements 1.1, 1.2, 1.3
68
+ */
69
+ async start() {
70
+ if (this.server) {
71
+ throw new Error('Server is already running');
72
+ }
73
+ // Resolve static files directory (dist/client relative to dist/server)
74
+ const staticDir = path.resolve(__dirname, '..', 'client');
75
+ // Create Express app
76
+ const app = createExpressApp({
77
+ reader: this.reader,
78
+ staticDir,
79
+ enableCors: true,
80
+ });
81
+ // Create HTTP server
82
+ return new Promise((resolve, reject) => {
83
+ this.server = app.listen(this.options.port, async () => {
84
+ console.log(`Dashboard server running at http://localhost:${this.options.port}`);
85
+ // Attach WebSocket server
86
+ this.wsManager.attach(this.server);
87
+ // Start pattern watcher for realtime updates
88
+ this.patternWatcher.start();
89
+ // Open browser if requested
90
+ if (this.options.openBrowser) {
91
+ try {
92
+ await this.openBrowser();
93
+ }
94
+ catch (error) {
95
+ // Don't fail if browser can't be opened
96
+ console.warn('Could not open browser:', error);
97
+ }
98
+ }
99
+ resolve();
100
+ });
101
+ this.server.on('error', (error) => {
102
+ this.server = null;
103
+ if (error.code === 'EADDRINUSE') {
104
+ reject(new Error(`Port ${this.options.port} is already in use. Try a different port with --port <number>`));
105
+ }
106
+ else {
107
+ reject(error);
108
+ }
109
+ });
110
+ });
111
+ }
112
+ /**
113
+ * Stop the dashboard server
114
+ */
115
+ async stop() {
116
+ if (!this.server) {
117
+ return;
118
+ }
119
+ // Stop pattern watcher
120
+ this.patternWatcher.stop();
121
+ // Close WebSocket connections
122
+ this.wsManager.close();
123
+ // Close HTTP server
124
+ return new Promise((resolve, reject) => {
125
+ this.server.close((error) => {
126
+ this.server = null;
127
+ if (error) {
128
+ reject(error);
129
+ }
130
+ else {
131
+ console.log('Dashboard server stopped');
132
+ resolve();
133
+ }
134
+ });
135
+ });
136
+ }
137
+ /**
138
+ * Broadcast a violation to all connected WebSocket clients
139
+ * @requirements 2.3
140
+ */
141
+ broadcastViolation(violation) {
142
+ this.wsManager.broadcastViolation(violation);
143
+ }
144
+ /**
145
+ * Open the default browser to the dashboard URL
146
+ * @requirements 1.3
147
+ */
148
+ async openBrowser() {
149
+ // Dynamic import to avoid issues with ESM
150
+ const open = await import('open');
151
+ await open.default(`http://localhost:${this.options.port}`);
152
+ }
153
+ }
154
+ //# sourceMappingURL=dashboard-server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dashboard-server.js","sourceRoot":"","sources":["../../src/server/dashboard-server.ts"],"names":[],"mappings":"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"}