feat(web): T-WEB-001 NestJS 骨架 + 连接现有 MySQL 实例

This commit is contained in:
2026-09-14 19:00:55 +08:00
parent 9b8fc6be96
commit bd6cb9fa90
18 changed files with 7763 additions and 0 deletions
@@ -0,0 +1,86 @@
import { Controller, Get, Res, ServiceUnavailableException } from '@nestjs/common';
import { InjectDataSource } from '@nestjs/typeorm';
import { Response } from 'express';
import { DataSource } from 'typeorm';
import { AppConfig } from '../config/configuration';
import { detectAssimp } from '../preprocess/assimp';
export interface HealthReport {
status: 'ok' | 'degraded';
uptimeSec: number;
version: string;
contractVersion: Record<string, string>;
database: {
connected: boolean;
server: string | null;
database: string | null;
migrationsPending: number | null;
error?: string;
};
storage: {
dir: string;
files: number;
totalBytes: number;
};
assimp: {
available: boolean;
version?: string;
error?: string;
};
}
@Controller('health')
export class HealthController {
constructor(
@InjectDataSource() private readonly dataSource: DataSource,
private readonly config: AppConfig,
) {}
/**
* 健康检查:必须真实探测数据库连通性(T-WEB-010 验收要求
* `curl http://localhost:3000/health` 通过)。
*/
@Get()
async check(@Res({ passthrough: true }) res: Response): Promise<HealthReport> {
const database: HealthReport['database'] = {
connected: false,
server: null,
database: null,
migrationsPending: null,
};
try {
const rows = await this.dataSource.query<Array<{ version: string; db: string }>>(
'SELECT VERSION() AS version, DATABASE() AS db',
);
database.connected = true;
database.server = rows[0]?.version ?? null;
database.database = rows[0]?.db ?? null;
const pending = await this.dataSource.showMigrations();
database.migrationsPending = pending ? 1 : 0;
} catch (error) {
database.error = error instanceof Error ? error.message : String(error);
}
const assimp = await detectAssimp(this.config.assimpBin);
const report: HealthReport = {
status: database.connected ? 'ok' : 'degraded',
uptimeSec: Math.round(process.uptime() * 1000) / 1000,
version: process.env.npm_package_version ?? '0.1.0',
contractVersion: this.config.contractVersions,
database,
storage: {
dir: this.config.storageDir,
files: 0,
totalBytes: 0,
},
assimp,
};
if (!database.connected) {
res.status(503);
}
return report;
}
}
+7
View File
@@ -0,0 +1,7 @@
import { Module } from '@nestjs/common';
import { HealthController } from './health.controller';
@Module({
controllers: [HealthController],
})
export class HealthModule {}