script-volume-auto/src/runs/database.service.ts
Nicolas Fryder 79daa30a8a Implementation initiale : calcul de volume 2.5D CloudCompare et test de robustesse par decimation spatiale progressive
- Backend NestJS orchestrant CloudCompare CLI (stats, decimation x2 sur 5 etapes, volume, assemblage .bin)
- Scripts Python (laspy, scipy, matplotlib) pour la conversion LAS/LAZ et la generation d'images
- Frontend web simple (Tailwind CDN) avec historique des runs
- Image Docker (debian:trixie-slim + cloudcompare apt + xvfb) prete pour deploiement Coolify
- Lint/typecheck/tests unitaires integres comme portes de qualite au build Docker
- CLAUDE.md documentant les comportements CloudCompare CLI verifies empiriquement
2026-07-10 13:55:25 +02:00

78 lines
2.4 KiB
TypeScript

import { Injectable, OnModuleInit } from '@nestjs/common';
import Database from 'better-sqlite3';
import * as fs from 'fs';
import { config, dbPath } from '../config';
export interface RunRow {
id: string;
original_filename: string;
status: 'pending' | 'running' | 'done' | 'error';
created_at: string;
finished_at: string | null;
params_json: string | null;
report_json: string | null;
log: string;
error: string | null;
}
@Injectable()
export class DatabaseService implements OnModuleInit {
private db!: Database.Database;
onModuleInit() {
fs.mkdirSync(config.dataDir, { recursive: true });
this.db = new Database(dbPath());
this.db.pragma('journal_mode = WAL');
this.db.exec(`
CREATE TABLE IF NOT EXISTS runs (
id TEXT PRIMARY KEY,
original_filename TEXT NOT NULL,
status TEXT NOT NULL,
created_at TEXT NOT NULL,
finished_at TEXT,
params_json TEXT,
report_json TEXT,
log TEXT NOT NULL DEFAULT '',
error TEXT
);
`);
}
insert(row: Pick<RunRow, 'id' | 'original_filename' | 'status' | 'created_at' | 'params_json'>) {
this.db
.prepare(
`INSERT INTO runs (id, original_filename, status, created_at, params_json, log) VALUES (?, ?, ?, ?, ?, '')`,
)
.run(row.id, row.original_filename, row.status, row.created_at, row.params_json);
}
updateStatus(id: string, status: RunRow['status']) {
this.db.prepare(`UPDATE runs SET status = ? WHERE id = ?`).run(status, id);
}
appendLog(id: string, line: string) {
this.db.prepare(`UPDATE runs SET log = log || ? WHERE id = ?`).run(`[${new Date().toISOString()}] ${line}\n`, id);
}
complete(id: string, reportJson: string) {
this.db
.prepare(`UPDATE runs SET status = 'done', report_json = ?, finished_at = ? WHERE id = ?`)
.run(reportJson, new Date().toISOString(), id);
}
fail(id: string, error: string) {
this.db.prepare(`UPDATE runs SET status = 'error', error = ?, finished_at = ? WHERE id = ?`).run(error, new Date().toISOString(), id);
}
get(id: string): RunRow | undefined {
return this.db.prepare(`SELECT * FROM runs WHERE id = ?`).get(id) as RunRow | undefined;
}
list(): RunRow[] {
return this.db.prepare(`SELECT * FROM runs ORDER BY created_at DESC`).all() as RunRow[];
}
remove(id: string) {
this.db.prepare(`DELETE FROM runs WHERE id = ?`).run(id);
}
}