const jobs = {}; const MAX_LOG_LINES = 120; function listJobs() { return Object.values(jobs) .sort((a, b) => String(b.startedAt || "").localeCompare(String(a.startedAt || ""))); } function getJob(jobId) { return jobs[jobId] || null; } function canStartJob(shop) { if (!shop) { return false; } const existing = jobs[shop]; return !existing || existing.status === "done" || existing.status === "error"; } function createJob(payload = {}) { const id = String(payload.shop || "").trim(); if (!id) { throw new Error("Shop is required to create a job."); } jobs[id] = { id, status: "queued", step: "queued", stepIndex: 0, totalSteps: 6, detail: null, summary: null, error: null, logs: [], liveStats: {}, payload, startedAt: new Date().toISOString(), updatedAt: new Date().toISOString(), }; return jobs[id]; } function updateJob(jobId, patch) { const current = jobs[jobId]; if (!current) { return null; } jobs[jobId] = { ...current, ...patch, liveStats: { ...(current.liveStats || {}), ...(patch.liveStats || {}), }, updatedAt: new Date().toISOString(), }; return jobs[jobId]; } function appendJobLog(jobId, line, extraPatch = {}) { const current = jobs[jobId]; if (!current) { return null; } const nextLogs = [...(current.logs || []), { at: new Date().toISOString(), line, }].slice(-MAX_LOG_LINES); jobs[jobId] = { ...current, ...extraPatch, liveStats: { ...(current.liveStats || {}), ...(extraPatch.liveStats || {}), }, logs: nextLogs, updatedAt: new Date().toISOString(), }; return jobs[jobId]; } module.exports = { listJobs, getJob, canStartJob, createJob, updateJob, appendJobLog, };