import type { FileInspection } from "./protocol"; export interface FileRecord { name: string; path: string; size: number; type: string; lastModified: number; inspection?: FileInspection; inspectionStatus?: "queued" | "inspecting" | "inspected" | "error" | "cancelled"; inspectionError?: string; sha256?: string; sha512?: string; } function inspectionStatus( record: FileRecord, ): NonNullable { return ( record.inspectionStatus ?? (record.inspection ? "inspected" : "queued") ); } export function manifestJson(records: FileRecord[]): string { return JSON.stringify( { schemaVersion: 2, generatedBy: "add-ideas File Tools 0.2.0", inspectionCoverage: { total: records.length, inspected: records.filter( (record) => inspectionStatus(record) === "inspected", ).length, failed: records.filter((record) => inspectionStatus(record) === "error") .length, cancelled: records.filter( (record) => inspectionStatus(record) === "cancelled", ).length, pending: records.filter((record) => ["queued", "inspecting"].includes(inspectionStatus(record)), ).length, }, files: [...records] .sort((left, right) => left.path.localeCompare(right.path)) .map((record) => ({ path: record.path, size: record.size, lastModified: new Date(record.lastModified).toISOString(), claimedMime: record.type || null, detectedMime: record.inspection?.detected?.mime ?? null, inspectionStatus: inspectionStatus(record), inspectionError: record.inspectionError ?? null, sha256: record.sha256 ?? null, sha512: record.sha512 ?? null, findings: record.inspection?.findings ?? [], })), }, null, 2, ); } function csv(value: unknown): string { const text = String(value ?? ""); const safe = /^[=+\-@\t\r]/u.test(text) ? `'${text}` : text; return `"${safe.replaceAll('"', '""')}"`; } export function manifestCsv(records: FileRecord[]): string { const lines = [ [ "path", "size", "lastModified", "claimedMime", "detectedMime", "inspectionStatus", "inspectionError", "sha256", "sha512", ] .map(csv) .join(","), ]; for (const record of [...records].sort((left, right) => left.path.localeCompare(right.path), )) lines.push( [ record.path, record.size, new Date(record.lastModified).toISOString(), record.type, record.inspection?.detected?.mime, inspectionStatus(record), record.inspectionError, record.sha256, record.sha512, ] .map(csv) .join(","), ); return lines.join("\r\n") + "\r\n"; }