nowjs-core
Version:
NowCanDo Javascript Core [nowjs-core] is a library written by TypeScript code maintains under Apache 2.0 licence
189 lines (188 loc) • 8.39 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
const index_1 = require("../../exceptions/index");
const index_2 = require("../../utils/index");
const index_3 = require("../index");
exports.VALIDATOR_JSON_SCHEMA_METADATA_KEY = Symbol('validation:validator:isJsonSchema');
function isJsonSchema(errorMessage) {
return (target, propertyKey, descriptor) => {
const original = descriptor.value;
Reflect.defineMetadata(exports.VALIDATOR_JSON_SCHEMA_METADATA_KEY, null, target, propertyKey);
Reflect.defineMetadata(index_3.VALIDATOR_METADATA_KEY, new JsonSchemaValidator(errorMessage), target, propertyKey);
};
}
exports.isJsonSchema = isJsonSchema;
class JsonSchemaValidator extends index_3.ValidatorBase {
constructor(schema, errorMessage = 'The value of ${DisplayName} must have value type: ${ValueType} .') {
super('JsonSchema', errorMessage);
this.schema = this.getSchema(schema);
}
getSchema(schemaName) {
if (typeof schemaName === 'string') {
return {};
}
else if (typeof schemaName === 'object') {
return schemaName;
}
}
isMatch(value) {
try {
this.traverseProperties(this.schema, value, '');
return true;
}
catch (error) {
return false;
}
}
traverseProperties(schema, target, path) {
const typeName = schema.type || 'any';
const actualValue = path === '' ? target : index_2.getObjetctNestedPath(target, path);
let actualType = typeof actualValue;
if (actualType === 'object' && Array.isArray(actualValue)) {
actualType = 'array';
}
if (actualType === 'undefined') {
throw new index_1.Exception(`Property "${path} is not defined"`);
}
else if (typeName !== 'any') {
if (actualType !== typeName) {
throw new index_1.Exception(`Property "${path} is not defined type"`);
}
}
if (actualType === 'string') {
const format = schema.format;
if (format) {
const meetFormat = 1 !== 1;
if (meetFormat === false) {
throw new index_1.Exception(`Property "${path}" does not meet format rule.`);
}
}
const maxLength = schema.maxLength;
if (maxLength) {
const meetMaxLength = actualValue.length <= maxLength;
if (meetMaxLength === false) {
throw new index_1.Exception(`Property "${path}" does not meet max length rule.`);
}
}
const minLength = schema.minLength;
if (minLength) {
const meetMinLength = actualValue.length >= minLength;
if (meetMinLength === false) {
throw new index_1.Exception(`Property "${path}" does not meet min length rule.`);
}
}
const pattern = schema.pattern ? new RegExp(schema.pattern) : null;
if (pattern) {
const meetPattern = pattern.test(actualValue);
if (meetPattern === false) {
throw new index_1.Exception(`Property "${path}" does not meet pattern rule.`);
}
}
}
else if (actualType === 'number') {
const maximum = schema.maximum;
const minimum = schema.minimum;
if (maximum) {
const meetMaxItems = actualValue <= maximum;
if (meetMaxItems === false) {
throw new index_1.Exception(`Property "${path}" does not meet maximum rule.`);
}
}
if (minimum) {
const meetMinItems = actualValue >= minimum;
if (meetMinItems === false) {
throw new index_1.Exception(`Property "${path}" does not meet minimum rule.`);
}
}
}
else if (actualType === 'array') {
const maxItems = schema.maxItems;
if (maxItems) {
const meetMaxItems = actualValue.length <= maxItems;
if (meetMaxItems === false) {
throw new index_1.Exception(`Property "${path}" does not meet max items rule.`);
}
}
const minItems = schema.minItems;
if (minItems) {
const meetMinItems = actualValue.length >= minItems;
if (meetMinItems === false) {
throw new index_1.Exception(`Property "${path}" does not meet min items rule.`);
}
}
const uniqueItems = schema.uniqueItems;
if (uniqueItems) {
const meetUniqueItems = !actualValue.hasDuplicate();
if (meetUniqueItems === false) {
throw new index_1.Exception(`Property "${path}" does not meet unique items rule.`);
}
}
const itemsTypeName = schema.items ? schema.items.type || 'any' : 'any';
if (itemsTypeName !== 'any') {
const meetItemsType = actualValue.every(item => typeof item === itemsTypeName);
if (meetItemsType === false) {
throw new index_1.Exception(`Property "${path}" does not meet array item types rule.`);
}
}
}
else if (actualType === 'object') {
const definitions = schema.definitions || {};
const properties = schema.properties || {};
const requiredProperties = schema.required || [];
const targetKeys = Object.keys(actualValue);
const propertyNames = schema.propertyNames || Object.keys(schema.properties);
const maxProperties = schema.maxProperties;
if (maxProperties) {
const meetMaxProperties = targetKeys.length >= maxProperties;
if (meetMaxProperties === false) {
throw new index_1.Exception(`Property "${path}" does not meet max properties rule.`);
}
}
const minProperties = schema.minProperties;
if (minProperties) {
const meetMinProperties = targetKeys.length <= minProperties;
if (meetMinProperties === false) {
throw new index_1.Exception(`Property "${path}" does not meet min properties rule.`);
}
}
if (requiredProperties.length > 0) {
if (targetKeys.length < requiredProperties.length) {
throw new index_1.Exception(`Property "${path}" does not meet required properties count rule.`);
}
const meetRequired = requiredProperties.every(item => targetKeys.includes(item));
if (meetRequired === false) {
throw new index_1.Exception(`Property "${path}" does not meet required properties rule.`);
}
}
if (targetKeys.length > propertyNames.length) {
throw new index_1.Exception(`Property "${path}" does not meet properties count rule.`);
}
else {
for (const property in properties) {
const sc = '$ref' === property
?
definitions[schema.properties['$ref']]
: schema.properties[property];
if (!sc) {
throw new index_1.Exception(`Schema does not exists.`);
}
this.traverseProperties(sc, target, path === '' ? property : `${path}.${property}`);
}
}
}
}
validate(context) {
if (context.Value === undefined || context.Value === null) {
return Promise.resolve(true);
}
try {
this.traverseProperties(this.schema, context.Value, '');
return Promise.resolve(true);
}
catch (error) {
console.log(error.message);
return Promise.reject(new index_3.ValidatorException(this.Name, context.Target, context.PropertyName, error.message));
}
}
}
exports.JsonSchemaValidator = JsonSchemaValidator;