chore: remove old .mjs files after TypeScript migration
CI / check (pull_request) Successful in 4m39s
CI / check (pull_request) Successful in 4m39s
小橘 <xiaoju@shazhou.work>
This commit is contained in:
@@ -1,149 +0,0 @@
|
||||
import { mkdir, readFile, readdir, unlink, writeFile } from "node:fs/promises";
|
||||
import { createServer } from "node:http";
|
||||
import { dirname, join } from "node:path";
|
||||
import { fileURLToPath } from "node:url";
|
||||
import express from "express";
|
||||
import { WebSocketServer } from "ws";
|
||||
import { MSG, WS } from "./protocol.mjs";
|
||||
|
||||
const __dirname = dirname(fileURLToPath(import.meta.url));
|
||||
const DATA_DIR = join(__dirname, "../data/records");
|
||||
const FRONTEND_DIR = join(__dirname, "../../frontend/dist");
|
||||
const PORT = 3800;
|
||||
const THREE_DAYS = 3 * 24 * 60 * 60 * 1000;
|
||||
|
||||
await mkdir(DATA_DIR, { recursive: true });
|
||||
|
||||
const records = new Map();
|
||||
const workers = new Map();
|
||||
const dashboardClients = new Set();
|
||||
|
||||
async function loadRecords() {
|
||||
try {
|
||||
const files = await readdir(DATA_DIR);
|
||||
for (const f of files) {
|
||||
if (!f.endsWith(".json")) continue;
|
||||
try {
|
||||
const data = JSON.parse(await readFile(join(DATA_DIR, f), "utf8"));
|
||||
records.set(data.id, data);
|
||||
} catch {}
|
||||
}
|
||||
} catch {}
|
||||
}
|
||||
|
||||
async function cleanup() {
|
||||
const now = Date.now();
|
||||
for (const [id, rec] of records) {
|
||||
if (now - new Date(rec.startedAt).getTime() > THREE_DAYS) {
|
||||
records.delete(id);
|
||||
await unlink(join(DATA_DIR, `${id}.json`)).catch(() => {});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await loadRecords();
|
||||
await cleanup();
|
||||
setInterval(cleanup, 60 * 60 * 1000);
|
||||
|
||||
const app = express();
|
||||
app.use(express.json());
|
||||
|
||||
app.get("/api/records", (req, res) => {
|
||||
let recs = [...records.values()];
|
||||
if (req.query.device) recs = recs.filter((r) => r.device === req.query.device);
|
||||
recs.sort((a, b) => new Date(b.startedAt) - new Date(a.startedAt));
|
||||
res.json(recs.map(({ stdout, stderr, ...r }) => r));
|
||||
});
|
||||
|
||||
app.get("/api/records/:id", (req, res) => {
|
||||
const rec = records.get(req.params.id);
|
||||
if (!rec) return res.status(404).json({ error: "Not found" });
|
||||
res.json(rec);
|
||||
});
|
||||
|
||||
app.get("/api/devices", (req, res) => {
|
||||
const devices = new Map();
|
||||
for (const rec of records.values()) {
|
||||
const d = devices.get(rec.device) || { name: rec.device, recordCount: 0, lastSeen: null };
|
||||
d.recordCount++;
|
||||
if (!d.lastSeen || new Date(rec.startedAt) > new Date(d.lastSeen)) d.lastSeen = rec.startedAt;
|
||||
devices.set(rec.device, d);
|
||||
}
|
||||
const result = [...devices.values()].map((d) => ({
|
||||
...d,
|
||||
online: [...workers.values()].some((w) => w.device === d.name),
|
||||
}));
|
||||
res.json(result);
|
||||
});
|
||||
|
||||
app.use(express.static(FRONTEND_DIR));
|
||||
app.get(/^\/(?!api|ws).*/, (req, res) => {
|
||||
res.sendFile(join(FRONTEND_DIR, "index.html"));
|
||||
});
|
||||
|
||||
const server = createServer(app);
|
||||
|
||||
const workerWss = new WebSocketServer({ noServer: true });
|
||||
const dashboardWss = new WebSocketServer({ noServer: true });
|
||||
|
||||
server.on("upgrade", (req, socket, head) => {
|
||||
if (req.url === WS.WORKER) {
|
||||
workerWss.handleUpgrade(req, socket, head, (ws) => workerWss.emit("connection", ws));
|
||||
} else if (req.url === WS.DASHBOARD) {
|
||||
dashboardWss.handleUpgrade(req, socket, head, (ws) => dashboardWss.emit("connection", ws));
|
||||
} else {
|
||||
socket.destroy();
|
||||
}
|
||||
});
|
||||
|
||||
function broadcastWorkers() {
|
||||
const workerList = [...workers.values()];
|
||||
for (const client of dashboardClients) {
|
||||
if (client.readyState === 1)
|
||||
client.send(JSON.stringify({ type: MSG.WORKERS, workers: workerList }));
|
||||
}
|
||||
}
|
||||
|
||||
workerWss.on("connection", (ws) => {
|
||||
let workerId = null;
|
||||
ws.on("message", async (raw) => {
|
||||
try {
|
||||
const msg = JSON.parse(raw);
|
||||
if (msg.type === MSG.REGISTER) {
|
||||
workerId = `${msg.device}-${Date.now()}`;
|
||||
workers.set(workerId, {
|
||||
id: workerId,
|
||||
device: msg.device,
|
||||
connectedAt: new Date().toISOString(),
|
||||
lastSeen: new Date().toISOString(),
|
||||
});
|
||||
broadcastWorkers();
|
||||
} else if (msg.type === MSG.RECORD) {
|
||||
const rec = msg.record;
|
||||
records.set(rec.id, rec);
|
||||
await writeFile(join(DATA_DIR, `${rec.id}.json`), JSON.stringify(rec, null, 2));
|
||||
if (workerId) workers.get(workerId).lastSeen = new Date().toISOString();
|
||||
for (const client of dashboardClients) {
|
||||
if (client.readyState === 1) {
|
||||
const { stdout, stderr, ...summary } = rec;
|
||||
client.send(JSON.stringify({ type: MSG.NEW_RECORD, record: summary }));
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch {}
|
||||
});
|
||||
ws.on("close", () => {
|
||||
if (workerId) {
|
||||
workers.delete(workerId);
|
||||
broadcastWorkers();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
dashboardWss.on("connection", (ws) => {
|
||||
dashboardClients.add(ws);
|
||||
ws.send(JSON.stringify({ type: MSG.WORKERS, workers: [...workers.values()] }));
|
||||
ws.on("close", () => dashboardClients.delete(ws));
|
||||
});
|
||||
|
||||
server.listen(PORT, () => console.log(`Dashboard server on port ${PORT}`));
|
||||
@@ -1,17 +0,0 @@
|
||||
export const MSG = {
|
||||
REGISTER: "register",
|
||||
RECORD: "record",
|
||||
WORKERS: "workers",
|
||||
NEW_RECORD: "newRecord",
|
||||
};
|
||||
|
||||
export const API = {
|
||||
RECORDS: "/api/records",
|
||||
RECORD: "/api/records/:id",
|
||||
DEVICES: "/api/devices",
|
||||
};
|
||||
|
||||
export const WS = {
|
||||
WORKER: "/ws/worker",
|
||||
DASHBOARD: "/ws/dashboard",
|
||||
};
|
||||
Reference in New Issue
Block a user