collab/mermaid/.build/jsonSchema.tsblame
View source
6dd74de1import { load, JSON_SCHEMA } from 'js-yaml';
6dd74de2import assert from 'node:assert';
6dd74de3import Ajv2019, { type JSONSchemaType } from 'ajv/dist/2019.js';
6dd74de4import type { MermaidConfig, BaseDiagramConfig } from '../packages/mermaid/src/config.type.js';
6dd74de5
6dd74de6/**
6dd74de7 * All of the keys in the mermaid config that have a mermaid diagram config.
6dd74de8 */
6dd74de9const MERMAID_CONFIG_DIAGRAM_KEYS = [
6dd74de10 'flowchart',
6dd74de11 'sequence',
6dd74de12 'gantt',
6dd74de13 'journey',
6dd74de14 'class',
6dd74de15 'state',
6dd74de16 'er',
6dd74de17 'pie',
6dd74de18 'quadrantChart',
6dd74de19 'xyChart',
6dd74de20 'requirement',
6dd74de21 'mindmap',
6dd74de22 'kanban',
6dd74de23 'timeline',
6dd74de24 'gitGraph',
6dd74de25 'c4',
6dd74de26 'sankey',
6dd74de27 'block',
6dd74de28 'packet',
6dd74de29 'architecture',
6dd74de30 'radar',
6dd74de31] as const;
6dd74de32
6dd74de33/**
6dd74de34 * Generate default values from the JSON Schema.
6dd74de35 *
6dd74de36 * AJV does not support nested default values yet (or default values with $ref),
6dd74de37 * so we need to manually find them (this may be fixed in ajv v9).
6dd74de38 *
6dd74de39 * @param mermaidConfigSchema - The Mermaid JSON Schema to use.
6dd74de40 * @returns The default mermaid config object.
6dd74de41 */
6dd74de42function generateDefaults(mermaidConfigSchema: JSONSchemaType<MermaidConfig>) {
6dd74de43 const ajv = new Ajv2019({
6dd74de44 useDefaults: true,
6dd74de45 allowUnionTypes: true,
6dd74de46 strict: true,
6dd74de47 });
6dd74de48
6dd74de49 ajv.addKeyword({
6dd74de50 keyword: 'meta:enum', // used by jsonschema2md
6dd74de51 errors: false,
6dd74de52 });
6dd74de53 ajv.addKeyword({
6dd74de54 keyword: 'tsType', // used by json-schema-to-typescript
6dd74de55 errors: false,
6dd74de56 });
6dd74de57
6dd74de58 // ajv currently doesn't support nested default values, see https://github.com/ajv-validator/ajv/issues/1718
6dd74de59 // (may be fixed in v9) so we need to manually use sub-schemas
6dd74de60 const mermaidDefaultConfig = {};
6dd74de61
6dd74de62 assert.ok(mermaidConfigSchema.$defs);
6dd74de63 const baseDiagramConfig = mermaidConfigSchema.$defs.BaseDiagramConfig;
6dd74de64
6dd74de65 for (const key of MERMAID_CONFIG_DIAGRAM_KEYS) {
6dd74de66 const subSchemaRef = mermaidConfigSchema.properties[key].$ref;
6dd74de67 const [root, defs, defName] = subSchemaRef.split('/');
6dd74de68 assert.strictEqual(root, '#');
6dd74de69 assert.strictEqual(defs, '$defs');
6dd74de70 const subSchema = {
6dd74de71 $schema: mermaidConfigSchema.$schema,
6dd74de72 $defs: mermaidConfigSchema.$defs,
6dd74de73 ...mermaidConfigSchema.$defs[defName],
6dd74de74 } as JSONSchemaType<BaseDiagramConfig>;
6dd74de75
6dd74de76 const validate = ajv.compile(subSchema);
6dd74de77
6dd74de78 mermaidDefaultConfig[key] = {};
6dd74de79
6dd74de80 for (const required of subSchema.required ?? []) {
6dd74de81 if (subSchema.properties[required] === undefined && baseDiagramConfig.properties[required]) {
6dd74de82 mermaidDefaultConfig[key][required] = baseDiagramConfig.properties[required].default;
6dd74de83 }
6dd74de84 }
6dd74de85 if (!validate(mermaidDefaultConfig[key])) {
6dd74de86 throw new Error(
6dd74de87 `schema for subconfig ${key} does not have valid defaults! Errors were ${JSON.stringify(
6dd74de88 validate.errors,
6dd74de89 undefined,
6dd74de90 2
6dd74de91 )}`
6dd74de92 );
6dd74de93 }
6dd74de94 }
6dd74de95
6dd74de96 const validate = ajv.compile(mermaidConfigSchema);
6dd74de97
6dd74de98 if (!validate(mermaidDefaultConfig)) {
6dd74de99 throw new Error(
6dd74de100 `Mermaid config JSON Schema does not have valid defaults! Errors were ${JSON.stringify(
6dd74de101 validate.errors,
6dd74de102 undefined,
6dd74de103 2
6dd74de104 )}`
6dd74de105 );
6dd74de106 }
6dd74de107
6dd74de108 return mermaidDefaultConfig;
6dd74de109}
6dd74de110
6dd74de111export const loadSchema = (src: string, filename: string): JSONSchemaType<MermaidConfig> => {
6dd74de112 const jsonSchema = load(src, {
6dd74de113 filename,
6dd74de114 // only allow JSON types in our YAML doc (will probably be default in YAML 1.3)
6dd74de115 // e.g. `true` will be parsed a boolean `true`, `True` will be parsed as string `"True"`.
6dd74de116 schema: JSON_SCHEMA,
6dd74de117 }) as JSONSchemaType<MermaidConfig>;
6dd74de118 return jsonSchema;
6dd74de119};
6dd74de120
6dd74de121export const getDefaults = (schema: JSONSchemaType<MermaidConfig>) => {
6dd74de122 return `export default ${JSON.stringify(generateDefaults(schema), undefined, 2)};`;
6dd74de123};
6dd74de124
6dd74de125export const getSchema = (schema: JSONSchemaType<MermaidConfig>) => {
6dd74de126 return `export default ${JSON.stringify(schema, undefined, 2)};`;
6dd74de127};