import "server-only"; import type { Paths } from "yt-dlp-transcript-common/lib/paths"; import { readJsonFile } from "yt-dlp-transcript-common/lib/jsonFile-server"; import type { Site } from "yt-dlp-transcript-common/lib/site"; import { listReportDirs, siteReportFile } from "yt-dlp-transcript-common/publish/reportMedia"; import { publishableReportExports, readReportExportManifest, type PublishableReportExports, type ReportExportManifest, } from "yt-dlp-transcript-common/publish/reportExportFiles"; import { getRegistry } from "yt-dlp-transcript-common/jobs/registry"; import { listAllJobs, type JobListEntry } from "yt-dlp-transcript-common/jobs/listJobs"; import { readJobMeta } from "yt-dlp-transcript-common/jobs/jobMeta"; import { reportRows, type ReportFileRead, type ReportRow } from "./reportList"; // Every report of the site, published (in order) then drafts, each read and // validated. export async function readSiteReportRows(paths: Paths, site: Site): Promise { const published = site.reports ?? []; const dirIds = await listReportDirs(paths, site.siteId); const ids = [...new Set([...published, ...dirIds])]; const reads = new Map( await Promise.all( ids.map(async (id) => [id, await readJsonFile(siteReportFile(paths, site.siteId, id))] as const), ), ); return reportRows(published, dirIds, reads); } // How far back the tab looks for the site's last prepare job: the newest jobs, // as /jobs lists them. A prepare older than that is not linked. const PREPARE_JOB_LOOKBACK = 100; // The newest job of `kind` for this site (a reports job's spec's slug is the // site id — reportsPrepareAction.ts, reportsExportAction.ts), live or from an // earlier server lifetime, or null. export async function latestSiteReportsJob( paths: Paths, siteId: string, kind: "reports-prepare" | "reports-export", ): Promise { const page = await listAllJobs(paths, { limit: PREPARE_JOB_LOOKBACK }); const registry = getRegistry(); for (const entry of page.entries) { if (entry.kind !== kind) continue; const spec = registry.get(entry.id)?.spec ?? (await readJobMeta(paths, entry.id))?.spec; if (spec?.slug === siteId) return entry; } return null; } // One published report's exports, as the tab shows them: the manifest of the // last export (or null), and which files compose would publish now. export type ReportExportsRow = { reportId: string; manifest: ReportExportManifest | null; publishable: PublishableReportExports; }; export async function readSiteReportExports(paths: Paths, site: Site): Promise { return Promise.all( (site.reports ?? []).map(async (reportId) => ({ reportId, manifest: await readReportExportManifest(paths, site.siteId, reportId), publishable: await publishableReportExports(paths, site.siteId, reportId), })), ); }