feat(settings): add about system information

This commit is contained in:
Deploy
2026-08-25 22:08:20 +02:00
parent 3917c8d6de
commit ed031f8a94
14 changed files with 255 additions and 27 deletions

View File

@@ -1,3 +1,6 @@
import { readFileSync } from 'node:fs';
import os from 'node:os';
import path from 'node:path';
import type { FastifyInstance } from 'fastify';
import type { FastifySchema } from 'fastify';
import type pg from 'pg';
@@ -62,6 +65,50 @@ export function parseCouriers(raw: string | undefined | null): string[] {
}
}
type ServiceVersion = {
id: string;
name: string;
version: string;
};
function readTextIfExists(filePath: string): string | null {
try {
return readFileSync(filePath, 'utf8').trim();
} catch {
return null;
}
}
function readPackageVersion(id: string, label: string, packagePath: string): ServiceVersion {
try {
const raw = readFileSync(packagePath, 'utf8');
const pkg = JSON.parse(raw) as { name?: string; version?: string };
return {
id,
name: pkg.name ?? label,
version: pkg.version ?? 'unknown',
};
} catch {
return { id, name: label, version: 'unknown' };
}
}
function collectServiceVersions(): { productVersion: string; services: ServiceVersion[] } {
const root = process.cwd();
return {
productVersion: readTextIfExists(path.join(root, 'VERSION')) ?? 'unknown',
services: [
readPackageVersion('backend', 'Backend API', path.join(root, 'package.json')),
readPackageVersion('admin', 'Admin', path.join(root, 'apps/admin/package.json')),
readPackageVersion('tpv', 'TPV', path.join(root, 'apps/pos/package.json')),
readPackageVersion('frontend', 'Frontend', path.join(root, 'frontend/package.json')),
readPackageVersion('storefront', 'Storefront SEO', path.join(root, 'storefront/package.json')),
],
};
}
const PROCESS_STARTED_AT = new Date();
const SETTING_KEYS: Record<string, string> = {
storeName: 'store_name',
storeTagline: 'store_tagline',
@@ -96,6 +143,53 @@ export async function registerStoreSettingsRoutes(
app: FastifyInstance,
deps: StoreSettingsRoutesDeps,
): Promise<void> {
// GET /admin/about — versions and safe server diagnostics for admin UI
const getAboutSchema: FastifySchema = {
tags: ['Admin'],
summary: 'Get service versions and server info (admin)',
response: { 401: errorSchema, 403: errorSchema },
};
app.get('/admin/about', { schema: getAboutSchema }, async (request, reply) => {
const user = await deps.authenticate(request);
requireRole(user, 'admin');
const { productVersion, services } = collectServiceVersions();
const dbVersion = await deps.pool
.query<{ server_version: string }>('SHOW server_version')
.then((result) => result.rows[0]?.server_version ?? 'unknown')
.catch(() => 'unavailable');
const memory = process.memoryUsage();
return reply.send({
productVersion,
generatedAt: new Date().toISOString(),
services,
server: {
hostname: os.hostname(),
platform: os.platform(),
arch: os.arch(),
release: os.release(),
uptimeSeconds: Math.floor(os.uptime()),
processUptimeSeconds: Math.floor(process.uptime()),
processStartedAt: PROCESS_STARTED_AT.toISOString(),
nodeVersion: process.version,
pid: process.pid,
cpuCount: os.cpus().length,
totalMemoryMb: Math.round(os.totalmem() / 1024 / 1024),
freeMemoryMb: Math.round(os.freemem() / 1024 / 1024),
processMemoryMb: {
rss: Math.round(memory.rss / 1024 / 1024),
heapUsed: Math.round(memory.heapUsed / 1024 / 1024),
heapTotal: Math.round(memory.heapTotal / 1024 / 1024),
},
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
},
database: {
postgresVersion: dbVersion,
},
});
});
// GET /admin/settings — fetch all settings
const getSettingsSchema: FastifySchema = {
tags: ['Admin'],