106 lines
2.8 KiB
TypeScript
106 lines
2.8 KiB
TypeScript
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<FileRecord["inspectionStatus"]> {
|
|
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";
|
|
}
|