Files
puter/extensions/serverInfo/index.ts
T
Lui DuarteandDaniel Salazar bbe6f9dc27 Feat: Add system info (Client + Server metrics) (#2311)
* Add ststem info to user options extensions - Add UIWindowSystemInfo, add ui sections for client and server, add basic getClientinfo function

* Fix typo

* Replace accidentally deleted es.js file

* Refactor client information to be consistant with project standard

* Complete Client information in ststem information window

* Remove console logs

* Add basic api functionality for getting server system information

* Structure return data from system server information endpoint | Add copyright to UIWindowSystemInfo

* Add function to format server system api data | Add loading element to server container while waiting for data | Complete System Information

* fix: disallow non admin for backend + move to extensions

---------

Co-authored-by: Daniel Salazar <daniel.salazar@puter.com>
2026-01-27 10:29:02 -08:00

63 lines
2.1 KiB
TypeScript

import fs from 'fs/promises';
import os from 'os';
const { Controller, Get, ExtensionController } = extension.import('extensionController');
@Controller('/serverInfo', [...config.allowedUsernames])
class ServerInfoController extends ExtensionController {
@Get('', { subdomain: 'api' })
async getServerInfo (req, res) {
const osData = {
platform: os.platform(),
type: os.type(),
release: os.release(),
pretty: `${os.type()} ${os.release()}`,
};
const cpus = os.cpus();
const cpuData = {
model: cpus[0]?.model || 'Unknown',
cores: cpus.length,
};
const ramData = {
total: os.totalmem(),
free: os.freemem(),
totalGB: (os.totalmem() / 1073741824).toFixed(2),
freeGB: (os.freemem() / 1073741824).toFixed(2),
};
const uptimeSeconds = os.uptime();
const uptimeData = {
seconds: uptimeSeconds,
days: Math.floor(uptimeSeconds / 86400),
hours: Math.floor((uptimeSeconds % 86400) / 3600),
minutes: Math.floor((uptimeSeconds % 3600) / 60),
pretty: `${Math.floor(uptimeSeconds / 86400)}d ${Math.floor((uptimeSeconds % 86400) / 3600)}h ${Math.floor((uptimeSeconds % 3600) / 60)}m`,
};
let diskData = { total: 'N/A', free: 'N/A', used: 'N/A' };
try {
const stats = await fs.statfs('/');
const totalGB = (stats.blocks * stats.bsize / 1073741824);
const freeGB = (stats.bfree * stats.bsize / 1073741824);
const usedGB = (totalGB - freeGB).toFixed(2);
diskData = { total: totalGB.toFixed(2), free: freeGB.toFixed(2), used: usedGB };
} catch ( err ) {
console.error('Disk stats error:', err);
}
const response = {
os: osData,
cpu: cpuData,
ram: ramData,
uptime: uptimeData,
disk: diskData,
loadavg: os.loadavg(),
hostname: os.hostname(),
};
res.json(response);
}
}
(new ServerInfoController()).registerRoutes();