56 lines
1.9 KiB
JavaScript
56 lines
1.9 KiB
JavaScript
// Build-Protokolle je Projekt: upload-data/preview-logs/<projectId>/<runFile>, maskiert, letzte 5
|
|
import crypto from 'node:crypto'
|
|
import fs from 'node:fs/promises'
|
|
import path from 'node:path'
|
|
import { config } from '../config.js'
|
|
import { maskLog } from './previewEnv.js'
|
|
|
|
const KEEP = 5
|
|
const MAX_LINES = 300
|
|
const PROJECT_RE = /^[A-Za-z0-9][A-Za-z0-9._-]{0,35}$/
|
|
const FILE_RE = /^\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}-\d{3}Z-[0-9a-f]{6}\.log$/
|
|
|
|
const projectDir = (projectId) => {
|
|
if (!PROJECT_RE.test(String(projectId || '')) || String(projectId).includes('..')) {
|
|
throw new Error('Ungültige Projekt-ID')
|
|
}
|
|
return path.join(config.previewRunner.logDir, projectId)
|
|
}
|
|
|
|
export async function saveRunLog(projectId, lines, env) {
|
|
const dir = projectDir(projectId)
|
|
await fs.mkdir(dir, { recursive: true })
|
|
const stamp = new Date().toISOString().replace(/[:.]/g, '-')
|
|
const runFile = `${stamp}-${crypto.randomBytes(3).toString('hex')}.log`
|
|
const text = maskLog((Array.isArray(lines) ? lines : []).slice(-MAX_LINES).join('\n'), env)
|
|
await fs.writeFile(path.join(dir, runFile), text + '\n', 'utf8')
|
|
const all = (await fs.readdir(dir)).filter((f) => FILE_RE.test(f)).sort()
|
|
for (const old of all.slice(0, Math.max(0, all.length - KEEP))) {
|
|
await fs.rm(path.join(dir, old), { force: true })
|
|
}
|
|
return runFile
|
|
}
|
|
|
|
// Neueste zuerst
|
|
export async function listRunLogs(projectId) {
|
|
let files
|
|
try { files = await fs.readdir(projectDir(projectId)) } catch { return [] }
|
|
return files
|
|
.filter((f) => FILE_RE.test(f))
|
|
.sort()
|
|
.reverse()
|
|
.map((runFile) => ({
|
|
runFile,
|
|
at: runFile.slice(0, 24).replace(/^(.{13})-(.{2})-(.{2})-/, '$1:$2:$3.'),
|
|
}))
|
|
}
|
|
|
|
export async function readRunLog(projectId, runFile) {
|
|
if (!FILE_RE.test(String(runFile || ''))) return null
|
|
try {
|
|
return await fs.readFile(path.join(projectDir(projectId), runFile), 'utf8')
|
|
} catch {
|
|
return null
|
|
}
|
|
}
|