Skip to content

Commit

Permalink
chore: add json schema validation
Browse files Browse the repository at this point in the history
noticed while updating the enabler content JSON files that the feedback was too late if i wait to run astro to see if the JSON is valid. we can show linting marks with vscode and JSON schema definitions

this sets up that linting config and adds a script to generate the schema JSON files off the Zod source of truth that's used by astro
  • Loading branch information
sterlingwes committed Feb 1, 2024
1 parent 4a4dec3 commit 29b2954
Show file tree
Hide file tree
Showing 10 changed files with 144 additions and 9 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ jobs:
run: bun install
- name: run type check
run: bun run types
- name: run schema scheck
run: bun run schemas
- name: setup data fixture
run: mkdir -p site/src/generated && cp site/src/lib/server/__fixtures__/data.json site/src/generated/data.json
- name: run unit tests
Expand Down
8 changes: 8 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"json.schemas": [
{
"fileMatch": ["/site/src/content/enabler/*.json"],
"url": "./site/src/schemas/enabler.json"
}
]
}
Binary file modified bun.lockb
Binary file not shown.
8 changes: 6 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
"build": "cd site && bun run build",
"preview": "cd site && bun run preview",
"test": "TZ=America/New_York vitest",
"types": "tsc --noEmit"
"types": "tsc --noEmit",
"gen-schemas": "bun run scripts/zod-json-schema.ts",
"schemas": "bun run ajv validate -s site/src/schemas/enabler -d \"site/src/content/enabler/*.json\""
},
"devDependencies": {
"@types/bun": "latest"
Expand All @@ -21,10 +23,12 @@
"typescript": "^5.0.0"
},
"dependencies": {
"ajv-cli": "^5.0.0",
"d3-node": "^3.0.0",
"date-fns": "^3.3.0",
"point-at-length": "^1.1.0",
"reading-time": "^1.5.0",
"vitest": "^1.2.1"
"vitest": "^1.2.1",
"zod-to-json-schema": "^3.22.4"
}
}
21 changes: 21 additions & 0 deletions scripts/zod-json-schema.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import fs from "fs";
// @ts-expect-error bun types not up to date on alpha api (?)
import { $ } from "bun";
import { zodToJsonSchema } from "zod-to-json-schema";

const zodFiles = await $`ls site/src/schemas`;
const modules = zodFiles.stdout
.toString()
.split("\n")
.map((line: string) => line.trim());

modules.forEach((fileName: string) => {
if (fileName) {
const { schema, name } = require(`../site/src/schemas/${fileName}`);
const jsonSchema = zodToJsonSchema(schema, name);
fs.writeFileSync(
`site/src/schemas/${name}.json`,
JSON.stringify(jsonSchema, null, 2)
);
}
});
4 changes: 2 additions & 2 deletions site/src/content/config.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { defineCollection } from "astro:content";
import { enablerSchema } from "../schemas/enabler";
import { schema } from "../schemas/enabler";

export const collections = {
enabler: defineCollection({
type: "data",
schema: enablerSchema,
schema,
}),
};
6 changes: 4 additions & 2 deletions site/src/content/enabler/anthony-housefather.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,10 @@
"href": ""
},
{
"text": "Marking 100 days since Hamas attacked Israel and brutally murdered 1200 people, including eight Canadians. 100 days since Hamas took 240 hostages, and still holds over 130 in captivity. The world may have moved on since October 7, but we will #NeverForget. #BringThemHomeNow",
"author": "@marcomendicino",
"quote": {
"text": "Marking 100 days since Hamas attacked Israel and brutally murdered 1200 people, including eight Canadians. 100 days since Hamas took 240 hostages, and still holds over 130 in captivity. The world may have moved on since October 7, but we will #NeverForget. #BringThemHomeNow",
"author": "@marcomendicino"
},
"date": "2024-01-14T17:19:00.000Z",
"type": "twitter",
"href": ""
Expand Down
3 changes: 3 additions & 0 deletions site/src/schemas/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# zod schemas

Astro uses Zod to enforce content JSON schema. We use JSON schemas to make editing easier, and you can generate the json schemas in this folder with `bun run gen-schemas` from the root of the repo.
89 changes: 89 additions & 0 deletions site/src/schemas/enabler.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
{
"$ref": "#/definitions/enabler",
"definitions": {
"enabler": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"bio": {
"type": "string"
},
"image": {
"type": "string"
},
"posts": {
"type": "array",
"items": {
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": [
"twitter"
]
},
"href": {
"type": "string"
},
"text": {
"type": "string"
},
"date": {
"type": "string"
},
"image": {
"type": "string"
},
"imageCaption": {
"type": "string"
},
"commentary": {
"type": "string"
},
"skip": {
"type": "boolean"
},
"quote": {
"type": "object",
"properties": {
"text": {
"type": "string"
},
"author": {
"type": "string"
},
"image": {
"type": "string"
},
"imageCaption": {
"type": "string"
}
},
"required": [
"text",
"author"
],
"additionalProperties": false
}
},
"required": [
"type",
"href",
"date"
],
"additionalProperties": false
}
}
},
"required": [
"name",
"bio",
"posts"
],
"additionalProperties": false
}
},
"$schema": "http://json-schema.org/draft-07/schema#"
}
12 changes: 9 additions & 3 deletions site/src/schemas/enabler.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import { z } from "astro:content";
import { z } from "zod";

export const enablerSchema = z.object({
/**
* run "bun run gen-schemas" to update the matching JSON schema if changed
*/

export const schema = z.object({
name: z.string(),
bio: z.string(),
image: z.string().optional(),
Expand All @@ -26,5 +30,7 @@ export const enablerSchema = z.object({
),
});

export type Enabler = z.infer<typeof enablerSchema>;
export const name = "enabler";

export type Enabler = z.infer<typeof schema>;
export type EnablerPost = Enabler["posts"][0];

0 comments on commit 29b2954

Please sign in to comment.