Refactor, Added documentation, moved from avj-cli to avj, update script and added tests
This commit is contained in:
71
scripts/generate-schema.ts
Normal file
71
scripts/generate-schema.ts
Normal file
@@ -0,0 +1,71 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
/**
|
||||
* Generates a JSON Schema file from the template schema, see source/template/schemas.ts for the schema definition.
|
||||
*
|
||||
* To provide support for types that JSON Schema cannot natively represent (e.g. bigint, Uint8Array), this script uses
|
||||
* Zod's override functionality.
|
||||
*
|
||||
* The generated schema file (source/template/xo-template.schema.json) is not directly used anywhere in the xo project, but can be consumed by other JSON Schema validators
|
||||
* to perform validations and help development of xo templates but it is important to note that they do not guarantee the support for bigint and
|
||||
* other types support in the future. Hence, for XO compatible templates, it's a requirement that the provided template (json or typescript) is validated against
|
||||
* the current template schema (source/template/schemas.ts) and validator.
|
||||
*/
|
||||
|
||||
import { writeFileSync } from 'node:fs';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { dirname, join } from 'node:path';
|
||||
import { ZodBigInt } from 'zod';
|
||||
import { xoTemplateSchema, uint8ArraySchema } from '../source/template/schemas.ts';
|
||||
|
||||
// Gets the directory of this script file.
|
||||
const scriptDirectory = dirname(fileURLToPath(import.meta.url));
|
||||
|
||||
// Gets the root directory of the package.
|
||||
const rootDirectory = join(scriptDirectory, '..');
|
||||
|
||||
// The output path for the generated JSON Schema file, placed alongside the template schemas.
|
||||
const schemaOutputPath = join(rootDirectory, 'source/template/xo-template.schema.json');
|
||||
|
||||
/**
|
||||
* Generates the JSON Schema from the zod's template validation schema.
|
||||
*
|
||||
* - Bigint fields are mapped to `{ "type": "integer", "format": "bigint" }` because JSON Schema has no native bigint type.
|
||||
* - Uint8Array fields are mapped to `{ "type": "string", "format": "uint8array" }` because JSON Schema has no byte array type.
|
||||
*
|
||||
* @returns The generated JSON Schema object.
|
||||
*/
|
||||
const generateSchema = (): Record<string, unknown> => {
|
||||
return xoTemplateSchema.toJSONSchema({
|
||||
// With "throw", Zod throws for any type it cannot represent in JSON Schema natively, unless the
|
||||
// override below handles it first. This ensures new unrepresentable types added to the schema are
|
||||
// caught immediately rather than silently producing an empty schema node.
|
||||
unrepresentable: 'throw',
|
||||
|
||||
override: ({ zodSchema, jsonSchema: schemaNode }): void => {
|
||||
// Override for bigint
|
||||
if (zodSchema instanceof ZodBigInt) {
|
||||
Object.assign(schemaNode, { type: 'integer', format: 'bigint' });
|
||||
}
|
||||
|
||||
// Override for Uint8Array
|
||||
if (zodSchema === uint8ArraySchema) {
|
||||
Object.assign(schemaNode, { type: 'string', format: 'uint8array' });
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
try {
|
||||
const schema = generateSchema();
|
||||
|
||||
writeFileSync(schemaOutputPath, JSON.stringify(schema, null, 4) + '\n', 'utf8');
|
||||
|
||||
console.log('Schema generated:', schemaOutputPath);
|
||||
} catch (thrownValue) {
|
||||
const errorMessage = thrownValue instanceof Error ? thrownValue.message : String(thrownValue);
|
||||
|
||||
console.error('Schema generation failed:', errorMessage);
|
||||
|
||||
process.exit(1);
|
||||
}
|
||||
Reference in New Issue
Block a user