import { readFileSync, writeFileSync, existsSync, mkdirSync } from "node:fs"; import { join } from "node:path"; import { tmpdir } from "node:os"; export interface JobData { id: string; status: "pending" | "running" | "completed" | "failed"; input: { text: string; template: string; platform?: string; platforms?: string[]; ttsProvider: string; voiceId?: string; }; error?: string; outputFiles?: Array<{ filePath: string; fileSizeBytes: number; width: number; height: number; durationSeconds: number; }>; createdAt: number; updatedAt: number; } const STORE_DIR = join(tmpdir(), "pipeline-jobs"); const STORE_FILE = join(STORE_DIR, "jobs.json"); function ensureStore(): Map { if (!existsSync(STORE_DIR)) { mkdirSync(STORE_DIR, { recursive: true }); } if (!existsSync(STORE_FILE)) { writeFileSync(STORE_FILE, "{}", "utf-8"); } try { const raw = readFileSync(STORE_FILE, "utf-8"); const obj = JSON.parse(raw) as Record; return new Map(Object.entries(obj)); } catch { return new Map(); } } function flushStore(jobs: Map): void { const obj: Record = {}; for (const [k, v] of jobs) { obj[k] = v; } writeFileSync(STORE_FILE, JSON.stringify(obj), "utf-8"); } export function getAllJobs(): JobData[] { const jobs = ensureStore(); return Array.from(jobs.values()).sort( (a, b) => b.createdAt - a.createdAt ); } export function getJob(id: string): JobData | undefined { const jobs = ensureStore(); return jobs.get(id); } export function createJob(input: JobData["input"]): JobData { const jobs = ensureStore(); const now = Date.now(); const job: JobData = { id: crypto.randomUUID(), status: "pending", input, createdAt: now, updatedAt: now, }; jobs.set(job.id, job); flushStore(jobs); return job; } export function updateJob(id: string, updates: Partial): JobData | undefined { const jobs = ensureStore(); const job = jobs.get(id); if (!job) return undefined; Object.assign(job, updates, { updatedAt: Date.now() }); flushStore(jobs); return job; }