Skip to content

Commit

Permalink
Using ts-json-schema-generator to generate schema from TypeScript (#78)
Browse files Browse the repository at this point in the history
  • Loading branch information
CatChen authored Jan 7, 2023
1 parent 57d1f84 commit 38faa88
Show file tree
Hide file tree
Showing 4 changed files with 82 additions and 58 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
node_modules
**.js
**.d.ts
schema.json
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"typescript": "^4.9.4"
},
"scripts": {
"build": "npx tsc",
"build": "touch ./schemas.json && ts-json-schema-generator -f tsconfig.json -o ./schemas.json && npx tsc",
"validate": "node --experimental-json-modules validate.js"
}
}
71 changes: 71 additions & 0 deletions schemas.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"Company": {
"additionalProperties": false,
"properties": {
"jobs": {
"additionalProperties": false,
"properties": {
"dataScientist": {
"$ref": "#/definitions/Job"
},
"productManager": {
"$ref": "#/definitions/Job"
},
"softwareEngineer": {
"$ref": "#/definitions/Job"
}
},
"type": "object"
},
"url": {
"type": "string"
}
},
"required": [
"jobs"
],
"type": "object"
},
"Job": {
"additionalProperties": false,
"properties": {
"intern": {
"$ref": "#/definitions/Opening"
},
"manager": {
"$ref": "#/definitions/Opening"
},
"newGrad": {
"$ref": "#/definitions/Opening"
},
"senior": {
"$ref": "#/definitions/Opening"
}
},
"type": "object"
},
"JobsData": {
"additionalProperties": {
"$ref": "#/definitions/Company"
},
"type": "object"
},
"Opening": {
"additionalProperties": false,
"properties": {
"available": {
"type": "boolean"
},
"url": {
"type": "string"
}
},
"required": [
"available"
],
"type": "object"
}
}
}
66 changes: 9 additions & 57 deletions validate.ts
Original file line number Diff line number Diff line change
@@ -1,60 +1,12 @@
import Ajv, { JSONSchemaType, DefinedError } from "ajv";
import type { Opening, Job, Company, JobsData } from "./index";
import data from "./data.json" assert { type: "json" };

const openingSchema: JSONSchemaType<Opening> = {
type: "object",
required: ["available"],
properties: {
available: { type: "boolean" },
url: { type: "string", nullable: true },
},
additionalProperties: false,
};

const jobSchema: JSONSchemaType<Job> = {
type: "object",
required: [],
properties: {
intern: { ...openingSchema, nullable: true },
newGrad: { ...openingSchema, nullable: true },
senior: { ...openingSchema, nullable: true },
manager: { ...openingSchema, nullable: true },
},
additionalProperties: false,
};

const companySchema: JSONSchemaType<Company> = {
type: "object",
required: ["jobs"],
properties: {
url: { type: "string", nullable: true },
jobs: {
type: "object",
required: [],
properties: {
softwareEngineer: { ...jobSchema, nullable: true },
dataScientist: { ...jobSchema, nullable: true },
productManager: { ...jobSchema, nullable: true },
},
additionalProperties: false,
},
},
additionalProperties: false,
};

const schema: JSONSchemaType<JobsData> = {
type: "object",
required: [],
additionalProperties: companySchema,
};

// @ts-ignore
const ajv: Ajv = new Ajv.default();
const validate = ajv.compile(schema);
if (!validate(data)) {
for (const error of validate.errors as DefinedError[]) {
import Ajv, { DefinedError, Schema } from 'ajv';
import data from './data.json' assert { type: 'json' };
import schemas from './schemas.json' assert { type: 'json' };

const ajv = new Ajv();
ajv.addSchema(schemas as Schema);
if (!ajv.validate('#/definitions/JobsData', data)) {
for (const error of ajv.errors as DefinedError[]) {
console.error(error);
}
throw new Error("Validation failure");
throw new Error('Validation failure');
}

0 comments on commit 38faa88

Please sign in to comment.