feat: integrate all 10 skills into homelab-topology

- Added api-security-hardening (helmet, rate limits)
- Added nodejs-backend-patterns (error handling)
- Added observability-monitoring (pino logging)
- Added websocket-engineer (socket.io real-time updates)
- Added docker (Multi-stage build, compose)
- Added vitest (testing configuration and store tests)
- Added data-visualizer (MetricsBar and HostChart)
- Added infrastructure-monitoring/proxmox-admin/network-engineer types
- Fixed UI accessibility and styling
- Cleaned up node_modules tracking
This commit is contained in:
2026-02-20 20:35:08 -08:00
parent 3dc5d236a2
commit 6dd679b8e0
14455 changed files with 3862 additions and 2194786 deletions

View File

@@ -1,40 +1,107 @@
import express from 'express';
import cors from 'cors';
import helmet from 'helmet';
import rateLimit from 'express-rate-limit';
import { createServer } from 'http';
import { Server, Socket } from 'socket.io';
import discoverRouter from './routes/discover';
import configRouter from './routes/config';
import statsRouter from './routes/stats';
import filesRouter from './routes/files';
import terminalRouter from './routes/terminal';
import { getHostConfigs } from './config';
import { requestLogger, logger } from './middleware/requestLogger';
import { errorHandler } from './middleware/errorHandler';
const app = express();
const httpServer = createServer(app);
const PORT = 3001;
// CORS middleware for frontend communication
// --- Socket.IO setup (websocket-engineer skill) ---
const io = new Server(httpServer, {
cors: {
origin: process.env.CORS_ORIGIN || 'http://localhost:3000',
credentials: true,
},
pingInterval: 25000,
pingTimeout: 10000,
});
io.on('connection', (socket: Socket) => {
logger.info({ socketId: socket.id }, 'Client connected via WebSocket');
socket.on('disconnect', (reason: string) => {
logger.info({ socketId: socket.id, reason }, 'Client disconnected');
});
});
// Export io so routes can emit events
export { io };
// --- Security middleware (api-security-hardening skill) ---
app.use(helmet({
contentSecurityPolicy: false, // Disable CSP for dev — configure per-environment in production
}));
// CORS — restrict to configured origins
app.use(cors({
origin: 'http://localhost:3000',
origin: process.env.CORS_ORIGIN || 'http://localhost:3000',
credentials: true,
}));
app.use(express.json());
// Rate limiting — general API
app.use('/api/', rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 200,
message: { status: 'error', message: 'Too many requests, please try again later' },
standardHeaders: true,
legacyHeaders: false,
}));
// Health check endpoint
app.get('/api/health', (req, res) => {
res.json({ status: 'ok' });
// Stricter rate limiting for discovery (expensive operation)
app.use('/api/discover', rateLimit({
windowMs: 1 * 60 * 1000, // 1 minute
max: 10,
message: { status: 'error', message: 'Discovery rate limited — max 10 per minute' },
standardHeaders: true,
legacyHeaders: false,
}));
// --- Body parsing ---
app.use(express.json({ limit: '1mb' }));
// --- Observability (observability-monitoring skill) ---
app.use(requestLogger);
// --- Health check ---
app.get('/api/health', (_req, res) => {
res.json({
status: 'ok',
uptime: process.uptime(),
timestamp: new Date().toISOString(),
connections: io.engine.clientsCount,
});
});
// Debug endpoint to check config
app.get('/api/debug-config', (req, res) => {
const hosts = getHostConfigs();
res.json({ hosts });
});
// --- Debug endpoint (dev only) ---
if (process.env.NODE_ENV !== 'production') {
app.get('/api/debug-config', (_req, res) => {
const hosts = getHostConfigs();
res.json({ hosts });
});
}
// --- Routes ---
app.use('/api', discoverRouter);
app.use('/api', configRouter);
app.use('/api', statsRouter);
app.use('/api', filesRouter);
app.use('/api', terminalRouter);
app.listen(PORT, () => {
console.log(`Server running on http://localhost:${PORT}`);
// --- Global error handler (must be last) ---
app.use(errorHandler);
// --- Start server ---
httpServer.listen(PORT, () => {
logger.info(`Server running on http://localhost:${PORT}`);
});