Sindbad~EG File Manager
"use strict";
require("./Polyfills");
var get = require("lodash.get");
var Report = require("./Report");
var FormatValidators = require("./FormatValidators");
var JsonValidation = require("./JsonValidation");
var SchemaCache = require("./SchemaCache");
var SchemaCompilation = require("./SchemaCompilation");
var SchemaValidation = require("./SchemaValidation");
var Utils = require("./Utils");
var Draft4Schema = require("./schemas/schema.json");
var Draft4HyperSchema = require("./schemas/hyper-schema.json");
/**
* default options
*/
var defaultOptions = {
// default timeout for all async tasks
asyncTimeout: 2000,
// force additionalProperties and additionalItems to be defined on "object" and "array" types
forceAdditional: false,
// assume additionalProperties and additionalItems are defined as "false" where appropriate
assumeAdditional: false,
// do case insensitive comparison for enums
enumCaseInsensitiveComparison: false,
// force items to be defined on "array" types
forceItems: false,
// force minItems to be defined on "array" types
forceMinItems: false,
// force maxItems to be defined on "array" types
forceMaxItems: false,
// force minLength to be defined on "string" types
forceMinLength: false,
// force maxLength to be defined on "string" types
forceMaxLength: false,
// force properties or patternProperties to be defined on "object" types
forceProperties: false,
// ignore references that cannot be resolved (remote schemas) // TODO: make sure this is only for remote schemas, not local ones
ignoreUnresolvableReferences: false,
// disallow usage of keywords that this validator can't handle
noExtraKeywords: false,
// disallow usage of schema's without "type" defined
noTypeless: false,
// disallow zero length strings in validated objects
noEmptyStrings: false,
// disallow zero length arrays in validated objects
noEmptyArrays: false,
// forces "uri" format to be in fully rfc3986 compliant
strictUris: false,
// turn on some of the above
strictMode: false,
// report error paths as an array of path segments to get to the offending node
reportPathAsArray: false,
// stop validation as soon as an error is found
breakOnFirstError: false,
// check if schema follows best practices and common sense
pedanticCheck: false,
// ignore unknown formats (do not report them as an error)
ignoreUnknownFormats: false,
// function to be called on every schema
customValidator: null
};
function normalizeOptions(options) {
var normalized;
// options
if (typeof options === "object") {
var keys = Object.keys(options),
idx = keys.length,
key;
// check that the options are correctly configured
while (idx--) {
key = keys[idx];
if (defaultOptions[key] === undefined) {
throw new Error("Unexpected option passed to constructor: " + key);
}
}
// copy the default options into passed options
keys = Object.keys(defaultOptions);
idx = keys.length;
while (idx--) {
key = keys[idx];
if (options[key] === undefined) {
options[key] = Utils.clone(defaultOptions[key]);
}
}
normalized = options;
} else {
normalized = Utils.clone(defaultOptions);
}
if (normalized.strictMode === true) {
normalized.forceAdditional = true;
normalized.forceItems = true;
normalized.forceMaxLength = true;
normalized.forceProperties = true;
normalized.noExtraKeywords = true;
normalized.noTypeless = true;
normalized.noEmptyStrings = true;
normalized.noEmptyArrays = true;
}
return normalized;
}
/**
* @class
*
* @param {*} [options]
*/
function ZSchema(options) {
this.cache = {};
this.referenceCache = [];
this.validateOptions = {};
this.options = normalizeOptions(options);
// Disable strict validation for the built-in schemas
var metaschemaOptions = normalizeOptions({ });
this.setRemoteReference("http://json-schema.org/draft-04/schema", Draft4Schema, metaschemaOptions);
this.setRemoteReference("http://json-schema.org/draft-04/hyper-schema", Draft4HyperSchema, metaschemaOptions);
}
/**
* instance methods
*
* @param {*} schema
*
* @returns {boolean}
*/
ZSchema.prototype.compileSchema = function (schema) {
var report = new Report(this.options);
schema = SchemaCache.getSchema.call(this, report, schema);
SchemaCompilation.compileSchema.call(this, report, schema);
this.lastReport = report;
return report.isValid();
};
/**
*
* @param {*} schema
*
* @returns {boolean}
*/
ZSchema.prototype.validateSchema = function (schema) {
if (Array.isArray(schema) && schema.length === 0) {
throw new Error(".validateSchema was called with an empty array");
}
var report = new Report(this.options);
schema = SchemaCache.getSchema.call(this, report, schema);
var compiled = SchemaCompilation.compileSchema.call(this, report, schema);
if (compiled) { SchemaValidation.validateSchema.call(this, report, schema); }
this.lastReport = report;
return report.isValid();
};
/**
*
* @param {*} json
* @param {*} schema
* @param {*} [options]
* @param {function(*, *)} [callback]
*
* @returns {boolean}
*/
ZSchema.prototype.validate = function (json, schema, options, callback) {
if (Utils.whatIs(options) === "function") {
callback = options;
options = {};
}
if (!options) { options = {}; }
this.validateOptions = options;
var whatIs = Utils.whatIs(schema);
if (whatIs !== "string" && whatIs !== "object") {
var e = new Error("Invalid .validate call - schema must be a string or object but " + whatIs + " was passed!");
if (callback) {
process.nextTick(function () {
callback(e, false);
});
return;
}
throw e;
}
var foundError = false;
var report = new Report(this.options);
report.json = json;
if (typeof schema === "string") {
var schemaName = schema;
schema = SchemaCache.getSchema.call(this, report, schemaName);
if (!schema) {
throw new Error("Schema with id '" + schemaName + "' wasn't found in the validator cache!");
}
} else {
schema = SchemaCache.getSchema.call(this, report, schema);
}
var compiled = false;
if (!foundError) {
compiled = SchemaCompilation.compileSchema.call(this, report, schema);
}
if (!compiled) {
this.lastReport = report;
foundError = true;
}
var validated = false;
if (!foundError) {
validated = SchemaValidation.validateSchema.call(this, report, schema);
}
if (!validated) {
this.lastReport = report;
foundError = true;
}
if (options.schemaPath) {
report.rootSchema = schema;
schema = get(schema, options.schemaPath);
if (!schema) {
throw new Error("Schema path '" + options.schemaPath + "' wasn't found in the schema!");
}
}
if (!foundError) {
JsonValidation.validate.call(this, report, schema, json);
}
if (callback) {
report.processAsyncTasks(this.options.asyncTimeout, callback);
return;
} else if (report.asyncTasks.length > 0) {
throw new Error("This validation has async tasks and cannot be done in sync mode, please provide callback argument.");
}
// assign lastReport so errors are retrievable in sync mode
this.lastReport = report;
return report.isValid();
};
ZSchema.prototype.getLastError = function () {
if (this.lastReport.errors.length === 0) {
return null;
}
var e = new Error();
e.name = "z-schema validation error";
e.message = this.lastReport.commonErrorMessage;
e.details = this.lastReport.errors;
return e;
};
ZSchema.prototype.getLastErrors = function () {
return this.lastReport && this.lastReport.errors.length > 0 ? this.lastReport.errors : null;
};
ZSchema.prototype.getMissingReferences = function (arr) {
arr = arr || this.lastReport.errors;
var res = [],
idx = arr.length;
while (idx--) {
var error = arr[idx];
if (error.code === "UNRESOLVABLE_REFERENCE") {
var reference = error.params[0];
if (res.indexOf(reference) === -1) {
res.push(reference);
}
}
if (error.inner) {
res = res.concat(this.getMissingReferences(error.inner));
}
}
return res;
};
ZSchema.prototype.getMissingRemoteReferences = function () {
var missingReferences = this.getMissingReferences(),
missingRemoteReferences = [],
idx = missingReferences.length;
while (idx--) {
var remoteReference = SchemaCache.getRemotePath(missingReferences[idx]);
if (remoteReference && missingRemoteReferences.indexOf(remoteReference) === -1) {
missingRemoteReferences.push(remoteReference);
}
}
return missingRemoteReferences;
};
ZSchema.prototype.setRemoteReference = function (uri, schema, validationOptions) {
if (typeof schema === "string") {
schema = JSON.parse(schema);
} else {
schema = Utils.cloneDeep(schema);
}
if (validationOptions) {
schema.__$validationOptions = normalizeOptions(validationOptions);
}
SchemaCache.cacheSchemaByUri.call(this, uri, schema);
};
ZSchema.prototype.getResolvedSchema = function (schema) {
var report = new Report(this.options);
schema = SchemaCache.getSchema.call(this, report, schema);
// clone before making any modifications
schema = Utils.cloneDeep(schema);
var visited = [];
// clean-up the schema and resolve references
var cleanup = function (schema) {
var key,
typeOf = Utils.whatIs(schema);
if (typeOf !== "object" && typeOf !== "array") {
return;
}
if (schema.___$visited) {
return;
}
schema.___$visited = true;
visited.push(schema);
if (schema.$ref && schema.__$refResolved) {
var from = schema.__$refResolved;
var to = schema;
delete schema.$ref;
delete schema.__$refResolved;
for (key in from) {
if (from.hasOwnProperty(key)) {
to[key] = from[key];
}
}
}
for (key in schema) {
if (schema.hasOwnProperty(key)) {
if (key.indexOf("__$") === 0) {
delete schema[key];
} else {
cleanup(schema[key]);
}
}
}
};
cleanup(schema);
visited.forEach(function (s) {
delete s.___$visited;
});
this.lastReport = report;
if (report.isValid()) {
return schema;
} else {
throw this.getLastError();
}
};
/**
*
* @param {*} schemaReader
*
* @returns {void}
*/
ZSchema.prototype.setSchemaReader = function (schemaReader) {
return ZSchema.setSchemaReader(schemaReader);
};
ZSchema.prototype.getSchemaReader = function () {
return ZSchema.schemaReader;
};
ZSchema.schemaReader = undefined;
/*
static methods
*/
ZSchema.setSchemaReader = function (schemaReader) {
ZSchema.schemaReader = schemaReader;
};
ZSchema.registerFormat = function (formatName, validatorFunction) {
FormatValidators[formatName] = validatorFunction;
};
ZSchema.unregisterFormat = function (formatName) {
delete FormatValidators[formatName];
};
ZSchema.getRegisteredFormats = function () {
return Object.keys(FormatValidators);
};
ZSchema.getDefaultOptions = function () {
return Utils.cloneDeep(defaultOptions);
};
ZSchema.schemaSymbol = Utils.schemaSymbol;
ZSchema.jsonSymbol = Utils.jsonSymbol;
module.exports = ZSchema;
Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists