This commit is contained in:
seb
2026-10-13 17:49:36 +02:00
parent c3d4fa5cd9
commit b7b5d554d8
9 changed files with 39 additions and 34 deletions

View File

@@ -2,8 +2,8 @@
PORT=4208
# HTTPS server port (defaults to 8443, set to 0 or false to disable)
HTTPS_PORT=8443
# SQL Studio port (served when backend is started with npm run dev)
SQL_STUDIO_PORT=4210
# Backend Monitor Interface port (served when backend is started with npm run dev)
MONITOR_PORT=4210
# Optional custom TLS cert/key paths (defaults to auto-generated certs/key.pem and certs/cert.pem)
# HTTPS_KEY_PATH=./certs/key.pem
# HTTPS_CERT_PATH=./certs/cert.pem

View File

@@ -8,7 +8,7 @@
"main": "index.js",
"scripts": {
"start": "node src/index.js",
"dev": "cross-env DEV_SQL_STUDIO=true node --watch-path=./src --watch-path=./.env --watch-path=../dashdbschema/src --watch-path=../llmorbiter/src src/index.js",
"dev": "cross-env DEV_BACKEND_MONITOR=true node --watch-path=./src --watch-path=./.env --watch-path=../dashdbschema/src --watch-path=../llmorbiter/src src/index.js",
"manage-users": "node scripts/manageUsers.js",
"wipe-company": "node scripts/wipeCompany.js",
"docs:api": "node scripts/generateApiDocs.js",

View File

@@ -17,7 +17,7 @@ import { shutdownJavascriptSandboxWorkers } from '../services/javascriptSandbox.
import { getOrCreateCert } from '../util/cert.js';
import { createLogger } from '../util/logger.js';
import v1Router from '../v1/index.js';
import { startSqlStudio, stopSqlStudio, isDevMode } from '../sqlstudio/server.js';
import { startBackendMonitor, stopBackendMonitor, isDevMode } from '../backendmonitor/server.js';
const apiLog = createLogger('api');
@@ -239,9 +239,9 @@ export async function startApi() {
if (isDevMode()) {
try {
await startSqlStudio();
await startBackendMonitor();
} catch (err) {
apiLog.error('Failed to start SQL Studio:', err.message);
apiLog.error('Failed to start Backend Monitor Interface:', err.message);
}
}
@@ -256,7 +256,7 @@ export async function startApi() {
}
export async function stopApi() {
await stopSqlStudio();
await stopBackendMonitor();
if (!server && !httpsServer) return;
// Long-lived SSE (and keep-alive) sockets otherwise block server.close()
// forever — node --watch hangs on "Waiting for graceful termination...".

View File

@@ -37,7 +37,7 @@ export async function getDatabaseInfo() {
dialect,
database: dialect === 'sqlite' ? env.sqlite.filename : env.mssql.database,
server: dialect === 'sqlite' ? 'local' : (env.mssql.server || 'localhost'),
port: env.sqlStudioPort,
port: env.monitorPort,
};
}

View File

@@ -1,5 +1,5 @@
/**
* Dash SQL Studio — Web Database Studio
* Backend Monitor Interface — Web Database Studio
*/
(function () {
@@ -15,7 +15,7 @@
let queryHistory = [];
try {
const saved = localStorage.getItem('dash_sql_studio_history');
const saved = localStorage.getItem('dash_backend_monitor_history') || localStorage.getItem('dash_sql_studio_history');
if (saved) queryHistory = JSON.parse(saved);
} catch (e) {
queryHistory = [];
@@ -1159,7 +1159,7 @@
queryHistory.unshift(item);
if (queryHistory.length > 50) queryHistory.pop();
try {
localStorage.setItem('dash_sql_studio_history', JSON.stringify(queryHistory));
localStorage.setItem('dash_backend_monitor_history', JSON.stringify(queryHistory));
} catch (e) {
// ignore
}
@@ -1319,7 +1319,7 @@
await loadDbStatus();
await loadTables();
// Default initial query tab
openQueryTab('-- Dash SQL Studio\nSELECT 1 as connected;');
openQueryTab('-- Backend Monitor Interface\nSELECT 1 as connected;');
}
init();

View File

@@ -3,7 +3,7 @@
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Dash SQL Studio</title>
<title>Backend Monitor Interface</title>
<!-- Google Fonts: Inter & JetBrains Mono -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
@@ -23,7 +23,7 @@
<path d="M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5"></path>
</svg>
</div>
<span class="brand-title">Dash SQL Studio</span>
<span class="brand-title">Backend Monitor Interface</span>
</div>
<div class="dev-badge">DEV MODE • NO AUTH</div>
</div>

View File

@@ -1,5 +1,5 @@
/* ==========================================================================
Dash SQL Studio — Modern SSMS Dark Theme
Backend Monitor Interface — Modern SSMS Dark Theme
========================================================================== */
:root {

View File

@@ -6,15 +6,16 @@ import env from '../config/env.js';
import { createLogger } from '../util/logger.js';
import * as dbHelper from './dbHelper.js';
const studioLog = createLogger('sqlstudio');
const monitorLog = createLogger('backendmonitor');
const __dirname = path.dirname(fileURLToPath(import.meta.url));
let studioServer;
let studioApp;
let monitorServer;
let monitorApp;
export function isDevMode() {
return (
process.env.npm_lifecycle_event === 'dev' ||
process.env.DEV_BACKEND_MONITOR === 'true' ||
process.env.DEV_SQL_STUDIO === 'true' ||
process.env.DEV_MODE === 'true'
);
@@ -138,39 +139,43 @@ export function buildStudioApp() {
return app;
}
export async function startSqlStudio() {
if (studioServer) {
return studioServer;
export async function startBackendMonitor() {
if (monitorServer) {
return monitorServer;
}
const app = buildStudioApp();
studioApp = app;
monitorApp = app;
const serverInstance = http.createServer(app);
await new Promise((resolve, reject) => {
serverInstance.once('listening', () => resolve());
serverInstance.once('error', (err) => {
studioLog.error(`Failed to listen on port ${env.sqlStudioPort}:`, err.message);
monitorLog.error(`Failed to listen on port ${env.monitorPort}:`, err.message);
reject(err);
});
serverInstance.listen(env.sqlStudioPort);
serverInstance.listen(env.monitorPort);
});
studioServer = serverInstance;
studioLog.info(`SQL Studio running on http://localhost:${env.sqlStudioPort} (dev mode, no auth)`);
return studioServer;
monitorServer = serverInstance;
monitorLog.info(`Backend Monitor Interface running on http://localhost:${env.monitorPort} (dev mode, no auth)`);
return monitorServer;
}
export async function stopSqlStudio() {
if (!studioServer) return;
const s = studioServer;
studioServer = undefined;
studioApp = undefined;
export async function stopBackendMonitor() {
if (!monitorServer) return;
const s = monitorServer;
monitorServer = undefined;
monitorApp = undefined;
await new Promise((resolve, reject) => {
s.close((err) => (err ? reject(err) : resolve()));
s.closeAllConnections();
});
studioLog.info('SQL Studio stopped');
monitorLog.info('Backend Monitor Interface stopped');
}
// Aliases for compatibility
export const startSqlStudio = startBackendMonitor;
export const stopSqlStudio = stopBackendMonitor;

View File

@@ -15,7 +15,7 @@ function parseHttpsPort(val) {
export default {
port: Number(process.env.PORT) || 4208,
httpsPort: parseHttpsPort(process.env.HTTPS_PORT),
sqlStudioPort: Number(process.env.SQL_STUDIO_PORT) || 4210,
monitorPort: Number(process.env.MONITOR_PORT || process.env.SQL_STUDIO_PORT) || 4210,
httpsKeyPath: process.env.HTTPS_KEY_PATH || resolve(__dirname, '../../certs/key.pem'),
httpsCertPath: process.env.HTTPS_CERT_PATH || resolve(__dirname, '../../certs/cert.pem'),
logLevel: process.env.LOG_LEVEL || 'debug',