Newer
Older
TelosDB / tools / serve-frontend.mjs
#!/usr/bin/env node
/**
 * src/frontend を 8474 で静的配信する。Puppeteer での UI 確認用。
 * 用途: npm run debug-ui で Tauri を起動せずにレイアウト確認するときの代替。
 */
import http from 'http';
import fs from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';

const __dirname = path.dirname(fileURLToPath(import.meta.url));
const root = path.resolve(__dirname, '..');
const frontendDir = path.join(root, 'src', 'frontend');
const PORT = 8474;

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

const server = http.createServer((req, res) => {
  let p = req.url === '/' ? '/index.html' : req.url;
  p = p.replace(/\?.*$/, '');
  if (p.includes('..')) {
    res.writeHead(400);
    res.end();
    return;
  }
  const file = path.join(frontendDir, p);
  if (!file.startsWith(frontendDir)) {
    res.writeHead(403);
    res.end();
    return;
  }
  fs.readFile(file, (err, data) => {
    if (err) {
      if (err.code === 'ENOENT') {
        res.writeHead(404);
        res.end('Not Found');
        return;
      }
      res.writeHead(500);
      res.end(String(err));
      return;
    }
    const ext = path.extname(file);
    const ct = MIMES[ext] || 'application/octet-stream';
    res.writeHead(200, { 'Content-Type': ct });
    res.end(data);
  });
});

server.listen(PORT, '127.0.0.1', () => {
  console.log(`Frontend serving at http://127.0.0.1:${PORT}`);
});

server.on('error', (e) => {
  console.error('Server error:', e.message);
  process.exit(1);
});