Repository Public
1/** Fails the build if any content record is malformed or internally inconsistent. */2import { readFile } from "node:fs/promises";3import { z } from "zod";4import { benchmarkSchema, nodeSchema, photoSchema, plannedSchema, researchSchema, siteSchema, timelineSchema } from "../src/lib/schemas.ts";56const load = async (f: string) => JSON.parse(await readFile(`data/${f}.json`, "utf8"));7const nodes = z.array(nodeSchema).parse(await load("nodes"));8const photos = z.array(photoSchema).parse(await load("photos"));9z.array(researchSchema).parse(await load("research"));10const benchmarks = z.array(benchmarkSchema).parse(await load("benchmarks"));11z.array(timelineSchema).parse(await load("timeline"));12z.array(plannedSchema).parse(await load("planned"));13siteSchema.parse(await load("site"));1415const errors: string[] = [];16const photoIds = new Set(photos.map((p) => p.id));17const nodeIds = new Set(nodes.map((n) => n.id));18if (nodeIds.size !== nodes.length) errors.push("duplicate node id");19for (const n of nodes) {20 for (const id of n.imageIds) if (!photoIds.has(id)) errors.push(`${n.id}: unknown photo ${id}`);21 if (!n.verifiedAt || !n.source) errors.push(`${n.id}: missing provenance`);22 if (!n.description.en || !n.description.fr) errors.push(`${n.id}: missing description`);23}24for (const b of benchmarks) {25 if (!nodeIds.has(b.nodeId)) errors.push(`benchmark ${b.id}: unknown node`);26 if (b.preview) errors.push(`benchmark ${b.id}: preview data must not be committed to the published dataset`);27}28if (errors.length) {29 console.error(errors.join("\n"));30 process.exit(1);31}32console.log(`data ok: ${nodes.length} nodes, ${photos.length} photographs, ${benchmarks.length} benchmark observations`);33