Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
e82b93d
refactor: Improve pricing in schema
bristermitten May 10, 2026
936cbb7
refactor: Improve file structure
bristermitten May 11, 2026
f1aee92
feat: Setup TS scema
bristermitten May 11, 2026
e905b58
chore: Update VSCode Config to apply schema to new file structure
bristermitten May 11, 2026
4499178
feat: Add Zod-generated JSON schema and meta field
bristermitten May 11, 2026
cb0a687
start moving to new improved schema
bristermitten May 11, 2026
ea393e7
ci: Make yaml action run on any branch
bristermitten May 11, 2026
5a5067c
start refactoring to new resources format
bristermitten May 11, 2026
6a09cd0
refactor: Big refactor of file structure and separate schemas
bristermitten May 11, 2026
03260c9
feat: add database compilation script
bristermitten May 11, 2026
75a116e
ci: Update GH action versio
bristermitten May 11, 2026
82ab39e
feat: better schemas
bristermitten May 11, 2026
d74d321
ci: update validate action
bristermitten May 11, 2026
ab36710
Merge branch 'master' into feat/improvements
bristermitten May 11, 2026
e66c635
chore: remove trailing comma
bristermitten May 11, 2026
f583372
Potential fix for pull request finding
bristermitten May 11, 2026
7572143
Potential fix for pull request finding
bristermitten May 11, 2026
6310b71
refactor: make schemas strict
bristermitten May 11, 2026
1590718
build: improve vscode config
bristermitten May 11, 2026
c0e1352
fix: improve cli
bristermitten May 11, 2026
b9adea8
build: fix gen-database command
bristermitten May 11, 2026
a78c9b0
fix: fix the gen-database script again
bristermitten May 11, 2026
0d0ab35
fix: make compile-database deterministic
bristermitten May 11, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 12 additions & 11 deletions .github/workflows/validate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,26 @@ name: Validate YAMLs against JSON Schema

on:
push:
branches:
- master
pull_request:
workflow_dispatch:

permissions:
contents: read
pull-requests: write # enable write permissions for pull request comments

jobs:
verify-yaml:
validate:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- name: Checkout repository
uses: actions/checkout@v6

- name: Validate JSON
uses: GrantBirki/json-yaml-validate@v1.5.0
- name: Setup Bun
uses: oven-sh/setup-bun@v2.2.0
with:
base_dir: resources
json_schema: "resource.schema.json"
yaml_as_json: "true" # enable YAML to JSON conversion
comment: "true" # enable comment mode
bun-version: latest

- name: Install dependencies
run: bun install

- name: Run validation suite
run: bun run validate
34 changes: 34 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
# dependencies (bun install)
node_modules

# output
out
dist
*.tgz

# code coverage
coverage
*.lcov

# logs
logs
_.log
report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json

# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local

# caches
.eslintcache
.cache
*.tsbuildinfo

# IntelliJ based IDEs
.idea

# Finder (MacOS) folder config
.DS_Store
11 changes: 6 additions & 5 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
{
"yaml.schemas": {
// apply schema to all resources
"resource.schema.json": "resources/*.yaml"
}
}
"yaml.schemas": {
"resource.schema.jsonc": "resources/**/*.yaml",
"metadata.schema.jsonc": "metadata/**/*.yaml",
Comment thread
bristermitten marked this conversation as resolved.
"database.schema.jsonc": "database.json"
}
}
34 changes: 34 additions & 0 deletions biome.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
"$schema": "https://biomejs.dev/schemas/2.4.15/schema.json",
"vcs": {
"enabled": true,
"clientKind": "git",
"useIgnoreFile": true
},
"files": {
"ignoreUnknown": false
},
"formatter": {
"enabled": true,
"indentStyle": "tab"
},
"linter": {
"enabled": true,
"rules": {
"recommended": true
}
},
"javascript": {
"formatter": {
"quoteStyle": "double"
}
},
"assist": {
"enabled": true,
"actions": {
"source": {
"organizeImports": "on"
}
}
}
}
87 changes: 87 additions & 0 deletions bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

93 changes: 93 additions & 0 deletions compile-database.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import path from "path";
import fs from "fs";
import { readdir } from "node:fs/promises";
import { DatabaseSchema, MetaSchema, ResourceSchema, type Database, type Meta, type Resource } from ".";
import { YAML } from "bun";

type DatabaseMetadata = {
id: string;
} & Meta


async function buildDatabase() {
const metaDir = path.join(__dirname, "./metadata");
const resourcesDir = path.join(__dirname, "./resources");

const allMetaFiles = (await readdir(metaDir, { recursive: true, })).toSorted();
const allResourceFiles = (await readdir(resourcesDir, { recursive: true, })).toSorted();

const database = {
metadata: [] as DatabaseMetadata[],
resources: [] as Resource[]
} satisfies Database;
let hasErrors = false;

for (const file of allMetaFiles.filter(f => f.endsWith(".yaml"))) {
const filePath = path.join(metaDir, file);
const fileContent = await fs.promises.readFile(filePath, "utf-8");

const entityId = path.basename(file, ".yaml");

const data = YAML.parse(fileContent);
const result = MetaSchema.safeParse(data);

if (!result.success) {
console.error(`Validation Error in Metadata: ${file}`);
console.error(result.error.issues);
hasErrors = true;
} else {
database.metadata.push({ id: entityId, ...result.data });
}
}

const validTags = new Set(database.metadata.map(meta => meta.id));

for (const file of allResourceFiles.filter(f => f.endsWith(".yaml"))) {
const filePath = path.join(resourcesDir, file);
const fileContent = await fs.promises.readFile(filePath, "utf-8");

const data = YAML.parse(fileContent);
const result = ResourceSchema.safeParse(data);

if (!result.success) {
console.error(`Validation Error in Resource: ${file}`);
console.error(result.error.issues);
hasErrors = true;
continue;
}

const invalidTags = result.data.teaches.filter(tag => !validTags.has(tag));
if (invalidTags.length > 0) {
console.error(`Relational Error in Resource: ${file}`);
console.error(`Unknown tags in 'teaches': [${invalidTags.join(", ")}]`);
console.error(`Ensure a corresponding metadata file exists.`);
hasErrors = true;
continue;
}

database.resources.push(result.data);
}

if (hasErrors) {
console.error("Build failed due to validation errors.");
process.exit(1);
}

// verify the entire database against the schema before writing
const finalResult = DatabaseSchema.safeParse(database);
if (!finalResult.success) {
console.error("Final Database Validation Error:");
console.error(finalResult.error.issues);
process.exit(1);
}

const outputPath = path.join(__dirname, "./database.json");
await fs.promises.writeFile(outputPath, JSON.stringify(database, null, 2));

console.log(`Success! Compiled ${database.metadata.length} entities and ${database.resources.length} resources.`);
}

buildDatabase().catch(err => {
console.error("Unexpected error during build:", err);
process.exit(1);
});
Loading