mirror of
https://github.com/vrtmrz/obsidian-livesync.git
synced 2026-07-17 01:56:00 +00:00
72 lines
2.6 KiB
TypeScript
72 lines
2.6 KiB
TypeScript
import type { DatasetEntry } from "./dataset.ts";
|
|
|
|
export type BenchmarkVerificationMode = "all" | "sample";
|
|
|
|
export type BenchmarkVerificationResult = {
|
|
verificationMode: BenchmarkVerificationMode;
|
|
verifiedFiles: number;
|
|
verificationComplete: boolean;
|
|
datasetDigestSha256: string;
|
|
};
|
|
|
|
function toHex(bytes: ArrayBuffer): string {
|
|
return [...new Uint8Array(bytes)].map((value) => value.toString(16).padStart(2, "0")).join("");
|
|
}
|
|
|
|
async function sha256(bytes: Uint8Array): Promise<string> {
|
|
const input = new ArrayBuffer(bytes.byteLength);
|
|
new Uint8Array(input).set(bytes);
|
|
return toHex(await crypto.subtle.digest("SHA-256", input));
|
|
}
|
|
|
|
export function parseBenchmarkVerificationMode(
|
|
raw: string | undefined,
|
|
fallback: BenchmarkVerificationMode = "sample"
|
|
): BenchmarkVerificationMode {
|
|
const value = raw?.trim().toLowerCase();
|
|
if (!value) return fallback;
|
|
if (value === "all" || value === "sample") return value;
|
|
throw new Error(`BENCH_VERIFY_MODE must be 'all' or 'sample', got '${raw}'`);
|
|
}
|
|
|
|
export function selectVerificationEntries(entries: DatasetEntry[], mode: BenchmarkVerificationMode): DatasetEntry[] {
|
|
if (mode === "all" || entries.length === 0) return [...entries];
|
|
|
|
const md = entries.find((entry) => entry.kind === "md");
|
|
const bin = entries.find((entry) => entry.kind === "bin");
|
|
const middle = entries[Math.floor(entries.length / 2)];
|
|
const last = entries[entries.length - 1];
|
|
const selected = new Map<string, DatasetEntry>();
|
|
for (const entry of [md, bin, middle, last]) {
|
|
if (entry) selected.set(entry.relativePath, entry);
|
|
}
|
|
return [...selected.values()];
|
|
}
|
|
|
|
export async function computeDatasetDigestSha256(entries: DatasetEntry[]): Promise<string> {
|
|
const manifest: string[] = [];
|
|
for (const entry of entries) {
|
|
const contentDigest = await sha256(await Deno.readFile(entry.absolutePath));
|
|
manifest.push(`${entry.kind}\t${entry.relativePath}\t${entry.size}\t${contentDigest}`);
|
|
}
|
|
return await sha256(new TextEncoder().encode(manifest.join("\n")));
|
|
}
|
|
|
|
export async function verifyBenchmarkDataset(
|
|
entries: DatasetEntry[],
|
|
mode: BenchmarkVerificationMode,
|
|
verifyEntry: (entry: DatasetEntry) => Promise<void>
|
|
): Promise<BenchmarkVerificationResult> {
|
|
const selected = selectVerificationEntries(entries, mode);
|
|
for (const entry of selected) {
|
|
await verifyEntry(entry);
|
|
}
|
|
|
|
return {
|
|
verificationMode: mode,
|
|
verifiedFiles: selected.length,
|
|
verificationComplete: selected.length === entries.length,
|
|
datasetDigestSha256: await computeDatasetDigestSha256(entries),
|
|
};
|
|
}
|