let Ajv = require("ajv");
const {Config} = require("./Config");
const {checkType, resolveFileOrString} = require("./Utility");
let ajv = null;
// let validateFn = null;
let aliasMap = new Map();
/**
* JSON schema validation
*/
class Schema {
/**
* Loads a new JSON schema for future reference. Since JSON schemes can cross-reference each other
* through $id and $ref, all relevant schemas must be loaded so that references resolve before
* attempting to validate data.
*
* @param {string} name The human-readable name of the schema for future reference in the `validate` method.
* @param {string} str The name of a file to load or a string representing a JSON schema
*/
static loadSchema(name, str) {
ajvCheck("Schema.loadSchema");
checkType("Schema.loadSchema", "name", name, "string");
checkType("Schema.loadSchema", "str", str, "string");
let basedir = Config.get("schema-dir");
let ext = ".json";
let schemaStr = resolveFileOrString(str);
let schemaJson;
try {
schemaJson = JSON.parse(schemaStr);
} catch (e) {
throw new Error(`Schema.loadSchema couldn't load schema: ${str}`);
}
ajv.addSchema(schemaJson, name, {basedir, ext});
}
/**
* Validates data based on the name of the schema.
*
* @param {string} name Then name (specified during `loadSchema`) or JSON Schema $id of the schema to use for validation.
* @param {any} data The data to validate
* @returns {boolean} `true` if data is valid for the specified schema, `false` otherwise.
*/
static validate(name, data) {
ajvCheck("Schema.validate");
if (Config.get("schema-disable-validation")) {
return true;
}
// if (aliasMap.has(name)) {
// name = aliasMap.get(name);
// }
// return validateFn(data);
let validateFn = ajv.getSchema(name);
if (!validateFn) {
throw new Error(`Schema.validate doesn't recognize the schema: ${name}`);
}
return validateFn(data);
}
/**
* Initialize the schema system
*
* @returns {Promise} A Promise that resolves when initialization is complete.
*/
static async init() {
// TODO: load files from schemaDir
//
// Config.get("schema-disable-validation");
ajv = new Ajv({
// allErrors: false,
allErrors: true,
verbose: true,
// TODO: create new logger
// logger: {
// log: console.log.bind(console),
// warn: console.warn.bind(console),
// error: console.error.bind(console),
// }
});
}
/**
* Shutdown the schema system
*
* @returns {Promise} A Promise that resolves when shutdown is complete.
*/
static async shutdown() {
ajv.removeSchema();
ajv = null;
aliasMap.clear();
}
}
function ajvCheck(fnName) {
if (!ajv) {
throw new Error(`${fnName}: JSON validator (AJV) not initialized`);
}
}
module.exports = {
Schema,
};