feat: add daily logging and improve workspace UI and ROS status

This commit is contained in:
2026-09-29 16:42:34 +09:00
parent 0a15102f8c
commit fb8c15dfd3
25 changed files with 328 additions and 283 deletions
+51
View File
@@ -0,0 +1,51 @@
import { appendFileSync, closeSync, mkdirSync, openSync, readdirSync, unlinkSync } from 'fs'
import { join } from 'path'
export function redactLog(value: string): string {
return value
.replace(/(https?:\/\/)[^\s/@]+@/gi, '$1[REDACTED]@')
.replace(/\bBearer\s+[^\s"',;]+/gi, 'Bearer [REDACTED]')
.replace(/((?:[?&]|--)(?:[^\s=&]*token|password|secret|code|key)=)[^\s&#"']+/gi, '$1[REDACTED]')
.replace(/(["']?(?:[\w-]*token|password|secret|authorization|api[_-]?key)["']?\s*[:=]\s*)(?:"[^"]*"|'[^']*'|[^\s,;}]+)/gi, '$1[REDACTED]')
}
function localDate(now: Date): string {
return `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}-${String(now.getDate()).padStart(2, '0')}`
}
export function createDailyLog(directories: string[], now: () => Date = () => new Date()) {
let activePath = ''
let activeDay = ''
function selectFile(): string {
const day = localDate(now())
if (activePath && activeDay === day) return activePath
for (const directory of [...new Set(directories)]) {
try {
mkdirSync(directory, { recursive: true })
const path = join(directory, `lms-${day}.log`)
closeSync(openSync(path, 'a', 0o600))
activePath = path
activeDay = day
for (const name of readdirSync(directory)) {
if (/^lms-\d{4}-\d{2}-\d{2}\.log$/.test(name) && name < `lms-${day}.log`) {
try { unlinkSync(join(directory, name)) } catch { /* Retention must not block startup. */ }
}
}
return path
} catch { /* Try the user-writable fallback directory. */ }
}
return ''
}
return {
path: selectFile,
write(kind: string, message: string): void {
try {
const path = selectFile()
if (!path) return
appendFileSync(path, `[${now().toISOString()}] [${redactLog(kind)}] ${redactLog(message)}\n`, { mode: 0o600 })
} catch { /* Diagnostics must not interrupt the app. */ }
}
}
}