SPB Git

Repository Public

validate-data.mts 1.7 KB 33 lines typescript

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
Files main
Menu

Theme