Files
emdash-cms--emdash/packages/plugin-cli/tests/schema-drift.test.ts
T
wehub-resource-sync b3a7f98e5a
CI / E2E Cloudflare (4/8) (push) Failing after 0s
CI / E2E Cloudflare (8/8) (push) Failing after 1s
CI / Lint (push) Failing after 1s
Auto Extract / Extract (push) Failing after 4s
CI / Version Check (push) Failing after 9s
CI / Integration Tests (push) Failing after 1s
CI / E2E tests (1/8) (push) Failing after 1s
CI / E2E tests (2/8) (push) Failing after 2s
CI / E2E tests (3/8) (push) Failing after 2s
CI / Browser Tests (push) Failing after 1s
CI / E2E tests (5/8) (push) Failing after 1s
CI / E2E Cloudflare (2/8) (push) Failing after 2s
CI / Typecheck (push) Failing after 1s
CI / Changeset Validation (push) Failing after 2s
CI / E2E Cloudflare (5/8) (push) Failing after 1s
CI / E2E Cloudflare (6/8) (push) Failing after 1s
CI / E2E Cloudflare (7/8) (push) Failing after 1s
CodeQL / Analyze (javascript-typescript) (push) Failing after 1s
Format / Format (push) Failing after 0s
CodeQL / Analyze (actions) (push) Failing after 4s
CI / E2E tests (4/8) (push) Failing after 1s
CI / E2E tests (6/8) (push) Failing after 1s
CI / E2E tests (7/8) (push) Failing after 2s
CI / E2E tests (8/8) (push) Failing after 1s
CI / E2E Cloudflare (1/8) (push) Failing after 1s
CI / E2E Cloudflare (3/8) (push) Failing after 2s
Preview Releases / Publish Preview (push) Failing after 0s
zizmor / Run zizmor (push) Failing after 1s
Release / Release (push) Failing after 2s
CI / Smoke Tests (push) Failing after 5m36s
CI / Tests (push) Failing after 6m36s
Release / Sync Templates (push) Has been skipped
CI / E2E Tests (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:23:53 +08:00

61 lines
2.4 KiB
TypeScript

/**
* Guard against drift between the Zod source of truth and the committed
* JSON Schema at `schemas/emdash-plugin.schema.json`.
*
* The committed JSON Schema is shipped to users via
* `node_modules/@emdash-cms/plugin-cli/schemas/emdash-plugin.schema.json`
* so editors can offer completion and validation without running our CLI.
* If a contributor changes the Zod schema and forgets to regenerate, this
* test fails with a clear "run pnpm gen-schema" instruction.
*
* We assert byte-for-byte equality after re-running the same `toJSONSchema`
* call the generator script uses. The generator's wrapping fields (`$id`,
* `title`, `description`) are added on top so we replicate them here.
*/
import { readFile } from "node:fs/promises";
import { resolve } from "node:path";
import { fileURLToPath } from "node:url";
import { describe, expect, it } from "vitest";
import { z } from "zod";
import { ManifestSchema } from "../src/manifest/schema.js";
const HERE = fileURLToPath(new URL(".", import.meta.url));
const COMMITTED_SCHEMA_PATH = resolve(HERE, "..", "schemas", "emdash-plugin.schema.json");
describe("JSON Schema drift", () => {
it("matches the output of z.toJSONSchema(ManifestSchema)", async () => {
const committed = await readFile(COMMITTED_SCHEMA_PATH, "utf8");
// Reproduce the generator script's emit. If this diverges from
// `scripts/gen-schema.ts`, update both (the script is the
// canonical version users run; this is its mirror).
const jsonSchema = z.toJSONSchema(ManifestSchema, {
target: "draft-2020-12",
reused: "ref",
});
const document = {
$schema: "https://json-schema.org/draft/2020-12/schema",
$id: "https://emdashcms.com/schemas/emdash-plugin.schema.json",
title: "EmDash plugin manifest (emdash-plugin.jsonc)",
description:
"Authoring format for publishing plugins to the EmDash plugin registry. Translated to the on-wire atproto record format at publish time. See https://github.com/emdash-cms/emdash/issues/1028.",
...jsonSchema,
};
const regenerated = `${JSON.stringify(document, null, "\t")}\n`;
// On failure, the diff is enormous and unreadable. Surface a
// pointer to the fix command instead.
if (committed !== regenerated) {
throw new Error(
"schemas/emdash-plugin.schema.json is out of date with the Zod schema.\n" +
"Run: pnpm --filter @emdash-cms/plugin-cli gen-schema\n" +
"Then commit the result.",
);
}
expect(committed).toBe(regenerated);
});
});