diff --git a/package-lock.json b/package-lock.json index 061bbc3..1f7a453 100644 --- a/package-lock.json +++ b/package-lock.json @@ -26,6 +26,7 @@ "react": "19.2.3", "react-dom": "19.2.3", "recharts": "^2.15.4", + "systeminformation": "^5.28.2", "tailwind-merge": "^3.4.0" }, "devDependencies": { @@ -3982,6 +3983,32 @@ } } }, + "node_modules/systeminformation": { + "version": "5.28.2", + "resolved": "https://registry.npmjs.org/systeminformation/-/systeminformation-5.28.2.tgz", + "integrity": "sha512-AWrPnmbIcfjLX7wiQMd7r6bl3PDaGoqvrfn8pCLJbk9CiB+vQXTk8RVxNs2vQRTezYlhb9skxEIyAPTm1If5bQ==", + "license": "MIT", + "os": [ + "darwin", + "linux", + "win32", + "freebsd", + "openbsd", + "netbsd", + "sunos", + "android" + ], + "bin": { + "systeminformation": "lib/cli.js" + }, + "engines": { + "node": ">=8.0.0" + }, + "funding": { + "type": "Buy me a coffee", + "url": "https://www.buymeacoffee.com/systeminfo" + } + }, "node_modules/tailwind-merge": { "version": "3.4.0", "resolved": "https://registry.npmjs.org/tailwind-merge/-/tailwind-merge-3.4.0.tgz", diff --git a/package.json b/package.json index 2d826e4..1c255a6 100644 --- a/package.json +++ b/package.json @@ -26,6 +26,7 @@ "react": "19.2.3", "react-dom": "19.2.3", "recharts": "^2.15.4", + "systeminformation": "^5.28.2", "tailwind-merge": "^3.4.0" }, "devDependencies": { diff --git a/src/app/api/status/route.ts b/src/app/api/status/route.ts index e69de29..da426a0 100644 --- a/src/app/api/status/route.ts +++ b/src/app/api/status/route.ts @@ -0,0 +1,52 @@ +import { NextRequest, NextResponse } from "next/server"; +import testAuth from "../auth"; +import { StatusCodes } from "http-status-codes"; +import si from "systeminformation"; + +export async function GET(req: NextRequest): Promise { + const auth = await testAuth(req); + + if (auth) { + return NextResponse.json( + { message: auth }, + { status: StatusCodes.UNAUTHORIZED } + ); + } + + const [cpu, mem, load, disk, network] = await Promise.all([ + si.cpu(), + si.mem(), + si.currentLoad(), + si.fsSize(), + si.networkStats(), + ]); + + return NextResponse.json({ + message: "ok", + liveData: { + cpu: { + manufacturer: cpu.manufacturer, + brand: cpu.brand, + cores: cpu.cores, + usage: load.currentLoad, + }, + memory: { + total: mem.total, + used: mem.used, + free: mem.free, + usage: ((mem.total - mem.free) / mem.total) * 100, + }, + disk: disk.map((d) => ({ + fs: d.fs, + size: d.size, + used: d.used, + usage: d.use, + })), + network: network.map((n) => ({ + iface: n.iface, + rx: n.rx_bytes, + tx: n.tx_bytes, + })), + }, + }); +} diff --git a/src/app/overview/page.tsx b/src/app/overview/page.tsx index 719dec7..5672b1f 100644 --- a/src/app/overview/page.tsx +++ b/src/app/overview/page.tsx @@ -87,13 +87,19 @@ const applications = [ memory: 48, status: "pending" as const, }, -]; +].slice(-5); export default function OverviewPage() { const [nodes, setNodes] = useState([]); useEffect(() => { - getLiveNodes().then(setNodes); + const fetchNodes = async () => { + const nodes = await getLiveNodes(); + setNodes(nodes); + }; + fetchNodes(); + const interval = setInterval(fetchNodes, 3000); + return () => clearInterval(interval); }, []); return ( @@ -228,7 +234,7 @@ export default function OverviewPage() { >
- + {node.name}
@@ -238,25 +244,27 @@ export default function OverviewPage() {
CPU - {node.liveData.cpu}% + + {node.liveData.cpu.usage.toFixed(0)}% +
Memory - {node.liveData.memory}% + + {node.liveData.memory.usage.toFixed(0)}% +
Containers - - {node.liveData.containers} - + {6}
diff --git a/src/lib/types.ts b/src/lib/types.ts index abb3b06..e8f981b 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -11,10 +11,28 @@ export interface NodeLiveData { ip: string; key: string; liveData: { - status: "running" | "pending" | "error"; - cpu: number; - memory: number; - disk: number; - containers: number; + cpu: { + manufacturer: string; + brand: string; + cores: number; + usage: number; + }; + memory: { + total: number; + used: number; + free: number; + usage: number; + }; + disk: { + fs: string; + size: number; + used: number; + usage: number; + }[]; + network: { + iface: string; + rx: number; + tx: number; + }[]; }; }