master
noah Publish 1.0.0 a09b9ee 2mo ago
#!/usr/bin/env node
// Minimal static server for the Wire Harness Designer webview app.
// Everything (preview, PDF, JSON save/load) runs client-side; this only serves files.
const http = require('http');
const fs = require('fs');
const path = require('path');

const PORT = process.env.PORT || 8765;
const ROOT = path.join(__dirname, 'public');

const MIME = {
  '.html': 'text/html; charset=utf-8',
  '.js': 'text/javascript; charset=utf-8',
  '.css': 'text/css; charset=utf-8',
  '.json': 'application/json; charset=utf-8',
  '.svg': 'image/svg+xml',
  '.ico': 'image/x-icon',
  '.woff2': 'font/woff2',
  '.png': 'image/png',
};

const server = http.createServer((req, res) => {
  try {
    let urlPath = decodeURIComponent((req.url || '/').split('?')[0]);
    if (urlPath === '/' || urlPath === '') urlPath = '/index.html';
    // prevent path traversal
    const safe = path.normalize(urlPath).replace(/^(\.\.[/\\])+/, '');
    const filePath = path.join(ROOT, safe);
    if (!filePath.startsWith(ROOT)) {
      res.writeHead(403); res.end('Forbidden'); return;
    }
    fs.readFile(filePath, (err, data) => {
      if (err) {
        res.writeHead(404, { 'Content-Type': 'text/plain' });
        res.end('Not found: ' + safe);
        return;
      }
      const ext = path.extname(filePath).toLowerCase();
      // Bust asset caches: stamp a fresh version onto ?v=DEV refs each time
      // index.html is served, so the browser always fetches the latest CSS/JS.
      if (ext === '.html') {
        data = Buffer.from(String(data).replace(/\?v=DEV/g, '?v=' + Date.now()));
      }
      res.writeHead(200, {
        'Content-Type': MIME[ext] || 'application/octet-stream',
        'Cache-Control': 'no-store, must-revalidate',
      });
      res.end(data);
    });
  } catch (e) {
    res.writeHead(500); res.end('Server error');
  }
});

server.listen(PORT, '0.0.0.0', () => {
  console.log('Wire Harness Designer running on port ' + PORT);
});