UNPKG

yaml-to-json-schema

Version:

Generate json schema from yaml (swagger, openapi, asyncapi)

117 lines (116 loc) 3.16 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.parse = void 0; const path_1 = require("path"); const fs_1 = require("fs"); const js_yaml_1 = __importDefault(require("js-yaml")); let basedir; const keys = {}; const setKey = (key, ref, src) => { if (!ref) { return; } const file = path_1.normalize(ref); keys[file] = key; }; const getKey = (ref, src) => { if (ref.startsWith('#')) { return path_1.basename(ref); } const file = path_1.resolve(path_1.dirname(src), ref); const path = path_1.relative(basedir, file); const key = keys[path]; if (!key) console.error('WARNING:', key, path); return key; }; const fixOf = (refs, src) => { refs.forEach((item) => { fixProperty(item, src); }); }; const fixAddons = (doc, src) => { if (doc.allOf) { fixOf(doc.allOf, src); } else if (doc.oneOf) { fixOf(doc.oneOf, src); } else if (doc.anyOf) { fixOf(doc.anyOf, src); } else if (doc.not) { fixProperty(doc.not, src); } }; const fixProperty = (prop, src) => { if (prop.$ref) { prop.$ref = '#definitions/' + getKey(prop.$ref, src); } else if (prop.type === 'object') { fixRef(prop, src); } else if (prop.type === 'array') { fixProperty(prop.items, src); } fixAddons(prop, src); return prop; }; const fixRef = (doc, src) => { fixAddons(doc, src); for (const key in doc.properties) { fixProperty(doc.properties[key], src); } return doc; }; const loadYamlFile = async (file) => { const content = await fs_1.promises.readFile(file, 'utf8'); return js_yaml_1.default.load(content); }; const loadPath = async (ref, src) => { const dir = path_1.dirname(src); const file = path_1.resolve(dir, ref); const doc = await loadYamlFile(file); if (!doc) { throw new Error('Empty doc'); } if (typeof doc === 'string' || typeof doc === 'number') { throw new Error('Unsupported doc'); } // @ts-ignore return fixRef(doc, file); }; const loadSchema = async (doc, src) => { if (doc.$ref) { return loadPath(doc.$ref, src); } return fixRef(doc, src); }; const prepare = async (doc, src) => { const definitions = {}; const properties = {}; const { schemas } = doc.components ?? {}; basedir = path_1.dirname(src); for (const key in schemas) { setKey(key, schemas[key].$ref, src); } for (const key in schemas) { definitions[key] = await loadSchema(schemas[key], src); // @ts-ignore // @TODO fix this issue. Error TS2740: Type '{ $ref: string; }' properties[key] = { $ref: '#definitions/' + key }; } return { type: 'object', definitions, properties }; }; async function parse(options) { const { input } = options; const doc = await loadYamlFile(input); return prepare(doc, input); } exports.parse = parse;