UNPKG

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
"use strict"; 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;