1// Checks every connection template in connection-templates/ two ways: against2// the schema, for the editor's sake, and with the relay's own parser3// (src/connections.ts), which is the last word on placeholders. A template4// whose link names a placeholder the relay cannot fill, or an input it does5// not declare, would show a visitor a broken link, so it fails here instead.6import { readdirSync, readFileSync } from "node:fs";7import { buildSync } from "esbuild";8import Ajv from "ajv";9import { stripComments } from "./jsonc.mjs";1011const ROOT = new URL("../../", import.meta.url);12const DIR = new URL("connection-templates/", ROOT);13const schema = JSON.parse(readFileSync(new URL("connection-template.schema.json", ROOT), "utf8"));14const validate = new Ajv({ allErrors: true }).compile(schema);15const js = buildSync({ entryPoints: [new URL("src/connections.ts", ROOT).pathname], bundle: true, format: "esm", platform: "neutral", write: false, logLevel: "silent", external: ["cloudflare:*"] }).outputFiles[0].text;16const { parseConnectionTemplate } = await import("data:text/javascript;base64," + Buffer.from(js).toString("base64"));1718const files = readdirSync(DIR).filter((f) => f.endsWith(".jsonc")).sort();19let failed = false;20for (const f of files) {21 const label = `connection-templates/${f}`;22 const problems = [];23 let doc;24 try {25 doc = JSON.parse(stripComments(readFileSync(new URL(f, DIR), "utf8")));26 } catch (e) {27 problems.push(`${label}: ${e.message}`);28 }29 if (doc) {30 if (!validate(doc)) for (const e of validate.errors) problems.push(`${label}: ${e.instancePath || "/"} ${e.message}`);31 const parsed = parseConnectionTemplate(f.replace(/^\d+-/, "").replace(/\.jsonc$/, ""), doc);32 if (typeof parsed === "string") problems.push(`${label}: ${parsed}`);33 }34 if (problems.length) {35 failed = true;36 console.error(problems.join("\n"));37 } else console.log(`${label}: ok`);38}39process.exit(failed ? 1 : 0);