Comparing version 0.1.3 to 0.1.4
import { IConstraint, EvalError } from '../model/schema'; | ||
export declare class FunctionConstraint implements IConstraint { | ||
private func; | ||
constructor(func: (value: any, path: string) => Promise<EvalError[]>); | ||
eval(value: any, path: string): Promise<EvalError[]>; | ||
constructor(func: (value: any, path: string) => EvalError[]); | ||
eval(value: any, path: string): EvalError[]; | ||
} | ||
@@ -10,3 +10,3 @@ export declare class AndConstraint implements IConstraint { | ||
constructor(constraints: IConstraint[]); | ||
eval(value: any, path: string): Promise<EvalError[]>; | ||
eval(value: any, path: string): EvalError[]; | ||
} |
"use strict"; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -18,5 +9,3 @@ exports.AndConstraint = exports.FunctionConstraint = void 0; | ||
eval(value, path) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
return this.func(value, path); | ||
}); | ||
return this.func(value, path); | ||
} | ||
@@ -30,12 +19,10 @@ } | ||
eval(value, path) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const errors = []; | ||
for (const constraint of this.constraints) { | ||
const childErrors = yield constraint.eval(value, path); | ||
if (childErrors.length > 0) { | ||
errors.push(...childErrors); | ||
} | ||
const errors = []; | ||
for (const constraint of this.constraints) { | ||
const childErrors = constraint.eval(value, path); | ||
if (childErrors.length > 0) { | ||
errors.push(...childErrors); | ||
} | ||
return errors; | ||
}); | ||
} | ||
return errors; | ||
} | ||
@@ -42,0 +29,0 @@ } |
@@ -8,3 +8,3 @@ import { Schema, IConstraint, IConstraintBuilder, IConstraintManager } from './../model/schema'; | ||
apply(rule: Schema): boolean; | ||
build(root: Schema, rule: Schema): Promise<IConstraint>; | ||
build(root: Schema, rule: Schema): IConstraint; | ||
private formatDatetime; | ||
@@ -15,23 +15,23 @@ private getType; | ||
apply(rule: Schema): boolean; | ||
build(root: Schema, rule: Schema): Promise<IConstraint>; | ||
build(root: Schema, rule: Schema): IConstraint; | ||
} | ||
export declare class MinMaxPropertiesConstraintBuilder implements IConstraintBuilder { | ||
apply(rule: Schema): boolean; | ||
build(root: Schema, rule: Schema): Promise<IConstraint>; | ||
build(root: Schema, rule: Schema): IConstraint; | ||
} | ||
export declare class MinMaxItemsConstraintBuilder implements IConstraintBuilder { | ||
apply(rule: Schema): boolean; | ||
build(root: Schema, rule: Schema): Promise<IConstraint>; | ||
build(root: Schema, rule: Schema): IConstraint; | ||
} | ||
export declare class UniqueItemsConstraintBuilder implements IConstraintBuilder { | ||
apply(rule: Schema): boolean; | ||
build(root: Schema, rule: Schema): Promise<IConstraint>; | ||
build(root: Schema, rule: Schema): IConstraint; | ||
} | ||
export declare class MinMaxLengthConstraintBuilder implements IConstraintBuilder { | ||
apply(rule: Schema): boolean; | ||
build(root: Schema, rule: Schema): Promise<IConstraint>; | ||
build(root: Schema, rule: Schema): IConstraint; | ||
} | ||
export declare class MinMaxConstraintBuilder implements IConstraintBuilder { | ||
apply(rule: Schema): boolean; | ||
build(root: Schema, rule: Schema): Promise<IConstraint>; | ||
build(root: Schema, rule: Schema): IConstraint; | ||
} | ||
@@ -42,11 +42,11 @@ export declare class PrefixItemsConstraintBuilder implements IConstraintBuilder { | ||
apply(rule: Schema): boolean; | ||
build(root: Schema, rule: Schema): Promise<IConstraint>; | ||
build(root: Schema, rule: Schema): IConstraint; | ||
} | ||
export declare class RequiredConstraintBuilder implements IConstraintBuilder { | ||
apply(rule: Schema): boolean; | ||
build(root: Schema, rule: Schema): Promise<IConstraint>; | ||
build(root: Schema, rule: Schema): IConstraint; | ||
} | ||
export declare class EnumConstraintBuilder implements IConstraintBuilder { | ||
apply(rule: Schema): boolean; | ||
build(root: Schema, rule: Schema): Promise<IConstraint>; | ||
build(root: Schema, rule: Schema): IConstraint; | ||
} | ||
@@ -57,14 +57,8 @@ export declare class FormatConstraintBuilder implements IConstraintBuilder { | ||
apply(rule: Schema): boolean; | ||
build(root: Schema, rule: Schema): Promise<IConstraint>; | ||
build(root: Schema, rule: Schema): IConstraint; | ||
} | ||
export declare class PatternConstraintBuilder implements IConstraintBuilder { | ||
apply(rule: Schema): boolean; | ||
build(root: Schema, rule: Schema): Promise<IConstraint>; | ||
build(root: Schema, rule: Schema): IConstraint; | ||
} | ||
export declare class PatternPropertyConstraintBuilder implements IConstraintBuilder { | ||
private constraints; | ||
constructor(constraints: IConstraintManager); | ||
apply(rule: Schema): boolean; | ||
build(root: Schema, rule: Schema): Promise<IConstraint>; | ||
} | ||
export declare class ContainsConstraintBuilder implements IConstraintBuilder { | ||
@@ -74,11 +68,11 @@ private constraints; | ||
apply(rule: Schema): boolean; | ||
build(root: Schema, rule: Schema): Promise<IConstraint>; | ||
build(root: Schema, rule: Schema): IConstraint; | ||
} | ||
export declare class ConstConstraintBuilder implements IConstraintBuilder { | ||
apply(rule: Schema): boolean; | ||
build(root: Schema, rule: Schema): Promise<IConstraint>; | ||
build(root: Schema, rule: Schema): IConstraint; | ||
} | ||
export declare class BooleanSchemaConstraintBuilder implements IConstraintBuilder { | ||
apply(rule: Schema): boolean; | ||
build(root: Schema, rule: Schema): Promise<IConstraint>; | ||
build(root: Schema, rule: Schema): IConstraint; | ||
} | ||
@@ -89,3 +83,3 @@ export declare class IfConstraintBuilder implements IConstraintBuilder { | ||
apply(rule: Schema): boolean; | ||
build(root: Schema, rule: Schema): Promise<IConstraint>; | ||
build(root: Schema, rule: Schema): IConstraint; | ||
} | ||
@@ -96,10 +90,4 @@ export declare class NotConstraintBuilder implements IConstraintBuilder { | ||
apply(rule: Schema): boolean; | ||
build(root: Schema, rule: Schema): Promise<IConstraint>; | ||
build(root: Schema, rule: Schema): IConstraint; | ||
} | ||
export declare class PropertiesConstraintBuilder implements IConstraintBuilder { | ||
private constraints; | ||
constructor(constraints: IConstraintManager); | ||
apply(rule: Schema): boolean; | ||
build(root: Schema, rule: Schema): Promise<IConstraint>; | ||
} | ||
export declare class ItemsConstraintBuilder implements IConstraintBuilder { | ||
@@ -109,3 +97,3 @@ private constraints; | ||
apply(rule: Schema): boolean; | ||
build(root: Schema, rule: Schema): Promise<IConstraint>; | ||
build(root: Schema, rule: Schema): IConstraint; | ||
} | ||
@@ -118,7 +106,10 @@ export declare class RefConstraintBuilder implements IConstraintBuilder { | ||
apply(rule: Schema): boolean; | ||
build(root: Schema, rule: Schema): Promise<IConstraint>; | ||
build(root: Schema, rule: Schema): IConstraint; | ||
private getKey; | ||
private findSchema; | ||
private findRule; | ||
private findById; | ||
} | ||
export declare class PropertiesConstraintBuilder implements IConstraintBuilder { | ||
private constraints; | ||
constructor(constraints: IConstraintManager); | ||
apply(rule: Schema): boolean; | ||
build(root: Schema, rule: Schema): IConstraint; | ||
} |
"use strict"; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.RefConstraintBuilder = exports.ItemsConstraintBuilder = exports.PropertiesConstraintBuilder = exports.NotConstraintBuilder = exports.IfConstraintBuilder = exports.BooleanSchemaConstraintBuilder = exports.ConstConstraintBuilder = exports.ContainsConstraintBuilder = exports.PatternPropertyConstraintBuilder = exports.PatternConstraintBuilder = exports.FormatConstraintBuilder = exports.EnumConstraintBuilder = exports.RequiredConstraintBuilder = exports.PrefixItemsConstraintBuilder = exports.MinMaxConstraintBuilder = exports.MinMaxLengthConstraintBuilder = exports.UniqueItemsConstraintBuilder = exports.MinMaxItemsConstraintBuilder = exports.MinMaxPropertiesConstraintBuilder = exports.MultipleOfConstraintBuilder = exports.TypeConstraintBuilder = void 0; | ||
exports.PropertiesConstraintBuilder = exports.RefConstraintBuilder = exports.ItemsConstraintBuilder = exports.NotConstraintBuilder = exports.IfConstraintBuilder = exports.BooleanSchemaConstraintBuilder = exports.ConstConstraintBuilder = exports.ContainsConstraintBuilder = exports.PatternConstraintBuilder = exports.FormatConstraintBuilder = exports.EnumConstraintBuilder = exports.RequiredConstraintBuilder = exports.PrefixItemsConstraintBuilder = exports.MinMaxConstraintBuilder = exports.MinMaxLengthConstraintBuilder = exports.UniqueItemsConstraintBuilder = exports.MinMaxItemsConstraintBuilder = exports.MinMaxPropertiesConstraintBuilder = exports.MultipleOfConstraintBuilder = exports.TypeConstraintBuilder = void 0; | ||
/* eslint-disable @typescript-eslint/ban-types */ | ||
@@ -25,87 +16,85 @@ const schema_1 = require("./../model/schema"); | ||
build(root, rule) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (rule.type === undefined) { | ||
throw new Error('type not define'); | ||
if (rule.type === undefined) { | ||
throw new Error('type not define'); | ||
} | ||
let func; | ||
if (typeof rule.type === 'string') { | ||
switch (rule.type) { | ||
case schema_1.PropertyType.null: | ||
func = (value, path) => { | ||
return value === null ? [] : [{ path: path, message: `invalid type ${rule.type}` }]; | ||
}; | ||
break; | ||
case schema_1.PropertyType.boolean: | ||
func = (value, path) => { | ||
return value !== null && typeof value === 'boolean' ? [] : [{ path: path, message: `invalid type ${rule.type}` }]; | ||
}; | ||
break; | ||
case schema_1.PropertyType.string: | ||
func = (value, path) => { | ||
return value !== null && typeof value === 'string' ? [] : [{ path: path, message: `invalid type ${rule.type}` }]; | ||
}; | ||
break; | ||
case schema_1.PropertyType.integer: | ||
func = (value, path) => { | ||
return value !== null && Number.isInteger(value) ? [] : [{ path: path, message: `invalid type ${rule.type}` }]; | ||
}; | ||
break; | ||
case schema_1.PropertyType.decimal: | ||
func = (value, path) => { | ||
return value !== null && !isNaN(value) ? [] : [{ path: path, message: `invalid type ${rule.type}` }]; | ||
}; | ||
break; | ||
case schema_1.PropertyType.number: | ||
func = (value, path) => { | ||
return value !== null && typeof value === 'number' ? [] : [{ path: path, message: `invalid type ${rule.type}` }]; | ||
}; | ||
break; | ||
case schema_1.PropertyType.date: | ||
func = this.formatDatetime('date'); | ||
break; | ||
case schema_1.PropertyType.datetime: | ||
func = this.formatDatetime('datetime'); | ||
break; | ||
case schema_1.PropertyType.time: | ||
func = this.formatDatetime('time'); | ||
break; | ||
case schema_1.PropertyType.object: | ||
func = (value, path) => { | ||
return value !== null && typeof value === 'object' && !Array.isArray(value) ? [] : [{ path: path, message: `invalid type ${rule.type}` }]; | ||
}; | ||
break; | ||
case schema_1.PropertyType.array: | ||
func = (value, path) => { | ||
return value !== null && Array.isArray(value) ? [] : [{ path: path, message: `invalid type ${rule.type}` }]; | ||
}; | ||
break; | ||
default: | ||
func = (value, path) => { | ||
return value !== null ? [] : [{ path: path, message: `invalid type ${rule.type}` }]; | ||
}; | ||
break; | ||
} | ||
let func; | ||
if (typeof rule.type === 'string') { | ||
switch (rule.type) { | ||
case schema_1.PropertyType.null: | ||
func = (value, path) => __awaiter(this, void 0, void 0, function* () { | ||
return value === null ? [] : [{ path: path, message: `invalid type ${rule.type}` }]; | ||
}); | ||
break; | ||
case schema_1.PropertyType.boolean: | ||
func = (value, path) => __awaiter(this, void 0, void 0, function* () { | ||
return value !== null && typeof value === 'boolean' ? [] : [{ path: path, message: `invalid type ${rule.type}` }]; | ||
}); | ||
break; | ||
case schema_1.PropertyType.string: | ||
func = (value, path) => __awaiter(this, void 0, void 0, function* () { | ||
return value !== null && typeof value === 'string' ? [] : [{ path: path, message: `invalid type ${rule.type}` }]; | ||
}); | ||
break; | ||
case schema_1.PropertyType.integer: | ||
func = (value, path) => __awaiter(this, void 0, void 0, function* () { | ||
return value !== null && Number.isInteger(value) ? [] : [{ path: path, message: `invalid type ${rule.type}` }]; | ||
}); | ||
break; | ||
case schema_1.PropertyType.decimal: | ||
func = (value, path) => __awaiter(this, void 0, void 0, function* () { | ||
return value !== null && !isNaN(value) ? [] : [{ path: path, message: `invalid type ${rule.type}` }]; | ||
}); | ||
break; | ||
case schema_1.PropertyType.number: | ||
func = (value, path) => __awaiter(this, void 0, void 0, function* () { | ||
return value !== null && typeof value === 'number' ? [] : [{ path: path, message: `invalid type ${rule.type}` }]; | ||
}); | ||
break; | ||
case schema_1.PropertyType.date: | ||
func = this.formatDatetime('date'); | ||
break; | ||
case schema_1.PropertyType.datetime: | ||
func = this.formatDatetime('datetime'); | ||
break; | ||
case schema_1.PropertyType.time: | ||
func = this.formatDatetime('time'); | ||
break; | ||
case schema_1.PropertyType.object: | ||
func = (value, path) => __awaiter(this, void 0, void 0, function* () { | ||
return value !== null && typeof value === 'object' && !Array.isArray(value) ? [] : [{ path: path, message: `invalid type ${rule.type}` }]; | ||
}); | ||
break; | ||
case schema_1.PropertyType.array: | ||
func = (value, path) => __awaiter(this, void 0, void 0, function* () { | ||
return value !== null && Array.isArray(value) ? [] : [{ path: path, message: `invalid type ${rule.type}` }]; | ||
}); | ||
break; | ||
default: | ||
func = (value, path) => __awaiter(this, void 0, void 0, function* () { | ||
return value !== null ? [] : [{ path: path, message: `invalid type ${rule.type}` }]; | ||
}); | ||
break; | ||
} | ||
else if (Array.isArray(rule.type)) { | ||
const types = rule.type; | ||
func = (value, path) => { | ||
const type = this.getType(value); | ||
if ((type === schema_1.PropertyType.integer || type === schema_1.PropertyType.decimal) && types.includes(schema_1.PropertyType.number)) { | ||
return []; | ||
} | ||
} | ||
else if (Array.isArray(rule.type)) { | ||
const types = rule.type; | ||
func = (value, path) => __awaiter(this, void 0, void 0, function* () { | ||
const type = this.getType(value); | ||
if ((type === schema_1.PropertyType.integer || type === schema_1.PropertyType.decimal) && types.includes(schema_1.PropertyType.number)) { | ||
return []; | ||
} | ||
else { | ||
return types.includes(type) ? [] : [{ path: path, message: `invalid type ${rule.type}` }]; | ||
} | ||
}); | ||
} | ||
else { | ||
func = (value, path) => __awaiter(this, void 0, void 0, function* () { | ||
return value !== null ? [] : [{ path: path, message: `invalid type ${rule.type}` }]; | ||
}); | ||
} | ||
return new constraint_1.FunctionConstraint(func); | ||
}); | ||
else { | ||
return types.includes(type) ? [] : [{ path: path, message: `invalid type ${rule.type}` }]; | ||
} | ||
}; | ||
} | ||
else { | ||
func = (value, path) => { | ||
return value !== null ? [] : [{ path: path, message: `invalid type ${rule.type}` }]; | ||
}; | ||
} | ||
return new constraint_1.FunctionConstraint(func); | ||
} | ||
formatDatetime(format) { | ||
return (value, path) => __awaiter(this, void 0, void 0, function* () { | ||
return (value, path) => { | ||
if (value === null) { | ||
@@ -120,3 +109,3 @@ return [{ path: path, message: 'value is null' }]; | ||
} | ||
}); | ||
}; | ||
} | ||
@@ -165,24 +154,22 @@ getType(value) { | ||
build(root, rule) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (rule.multipleOf === undefined) { | ||
throw new Error('multipleOf not define'); | ||
} | ||
let func; | ||
const multipleOf = rule.multipleOf; | ||
if (Math.floor(multipleOf.valueOf()) === multipleOf.valueOf()) { | ||
func = (value, path) => __awaiter(this, void 0, void 0, function* () { | ||
return isNaN(value) || value % multipleOf === 0 ? [] : [{ path: path, message: `is not multiple of ${rule.multipleOf}` }]; | ||
}); | ||
} | ||
else { | ||
// number with decimals | ||
const decimals = multipleOf.toString().split('.')[1].length; | ||
const shift = Math.pow(10, decimals); | ||
const multipleOfShift = multipleOf * shift; | ||
func = (value, path) => __awaiter(this, void 0, void 0, function* () { | ||
return isNaN(value) || (value * shift) % multipleOfShift === 0 ? [] : [{ path: path, message: `is not multiple of ${rule.multipleOf}` }]; | ||
}); | ||
} | ||
return new constraint_1.FunctionConstraint(func); | ||
}); | ||
if (rule.multipleOf === undefined) { | ||
throw new Error('multipleOf not define'); | ||
} | ||
let func; | ||
const multipleOf = rule.multipleOf; | ||
if (Math.floor(multipleOf.valueOf()) === multipleOf.valueOf()) { | ||
func = (value, path) => { | ||
return isNaN(value) || value % multipleOf === 0 ? [] : [{ path: path, message: `is not multiple of ${rule.multipleOf}` }]; | ||
}; | ||
} | ||
else { | ||
// number with decimals | ||
const decimals = multipleOf.toString().split('.')[1].length; | ||
const shift = Math.pow(10, decimals); | ||
const multipleOfShift = multipleOf * shift; | ||
func = (value, path) => { | ||
return isNaN(value) || (value * shift) % multipleOfShift === 0 ? [] : [{ path: path, message: `is not multiple of ${rule.multipleOf}` }]; | ||
}; | ||
} | ||
return new constraint_1.FunctionConstraint(func); | ||
} | ||
@@ -196,32 +183,30 @@ } | ||
build(root, rule) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const min = rule.minProperties; | ||
const max = rule.maxProperties; | ||
if (min !== undefined && max !== undefined) { | ||
return new constraint_1.FunctionConstraint((value, path) => __awaiter(this, void 0, void 0, function* () { | ||
if (typeof value !== 'object' || Array.isArray(value)) { | ||
return []; | ||
} | ||
const properties = Object.keys(value).length; | ||
return properties >= min && properties <= max ? [] : [{ path: path, message: `outside the range from ${min} inclusive to ${max} inclusive properties` }]; | ||
})); | ||
} | ||
else if (min !== undefined) { | ||
return new constraint_1.FunctionConstraint((value, path) => __awaiter(this, void 0, void 0, function* () { | ||
if (typeof value !== 'object' || Array.isArray(value)) { | ||
return []; | ||
} | ||
return Object.keys(value).length >= min ? [] : [{ path: path, message: `should be less or equal than ${min}` }]; | ||
})); | ||
} | ||
else if (max !== undefined) { | ||
return new constraint_1.FunctionConstraint((value, path) => __awaiter(this, void 0, void 0, function* () { | ||
if (typeof value !== 'object' || Array.isArray(value)) { | ||
return []; | ||
} | ||
return Object.keys(value).length <= max ? [] : [{ path: path, message: `should be greater or equal than ${max}` }]; | ||
})); | ||
} | ||
throw new Error('constraint minProperties or maxProperties undefined'); | ||
}); | ||
const min = rule.minProperties; | ||
const max = rule.maxProperties; | ||
if (min !== undefined && max !== undefined) { | ||
return new constraint_1.FunctionConstraint((value, path) => { | ||
if (typeof value !== 'object' || Array.isArray(value)) { | ||
return []; | ||
} | ||
const properties = Object.keys(value).length; | ||
return properties >= min && properties <= max ? [] : [{ path: path, message: `outside the range from ${min} inclusive to ${max} inclusive properties` }]; | ||
}); | ||
} | ||
else if (min !== undefined) { | ||
return new constraint_1.FunctionConstraint((value, path) => { | ||
if (typeof value !== 'object' || Array.isArray(value)) { | ||
return []; | ||
} | ||
return Object.keys(value).length >= min ? [] : [{ path: path, message: `should be less or equal than ${min}` }]; | ||
}); | ||
} | ||
else if (max !== undefined) { | ||
return new constraint_1.FunctionConstraint((value, path) => { | ||
if (typeof value !== 'object' || Array.isArray(value)) { | ||
return []; | ||
} | ||
return Object.keys(value).length <= max ? [] : [{ path: path, message: `should be greater or equal than ${max}` }]; | ||
}); | ||
} | ||
throw new Error('constraint minProperties or maxProperties undefined'); | ||
} | ||
@@ -235,22 +220,20 @@ } | ||
build(root, rule) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const min = rule.minItems; | ||
const max = rule.maxItems; | ||
if (min !== undefined && max !== undefined) { | ||
return new constraint_1.FunctionConstraint((value, path) => __awaiter(this, void 0, void 0, function* () { | ||
return !Array.isArray(value) || (value.length >= min && value.length <= max) ? [] : [{ path: path, message: `outside the range from ${min} to ${max} items` }]; | ||
})); | ||
} | ||
else if (min !== undefined) { | ||
return new constraint_1.FunctionConstraint((value, path) => __awaiter(this, void 0, void 0, function* () { | ||
return !Array.isArray(value) || value.length >= min ? [] : [{ path: path, message: `should be less or equal than ${min}` }]; | ||
})); | ||
} | ||
else if (max !== undefined) { | ||
return new constraint_1.FunctionConstraint((value, path) => __awaiter(this, void 0, void 0, function* () { | ||
return !Array.isArray(value) || value.length <= max ? [] : [{ path: path, message: `should be greater or equal than ${max}` }]; | ||
})); | ||
} | ||
throw new Error('constraint minItems or maxItems undefined'); | ||
}); | ||
const min = rule.minItems; | ||
const max = rule.maxItems; | ||
if (min !== undefined && max !== undefined) { | ||
return new constraint_1.FunctionConstraint((value, path) => { | ||
return !Array.isArray(value) || (value.length >= min && value.length <= max) ? [] : [{ path: path, message: `outside the range from ${min} to ${max} items` }]; | ||
}); | ||
} | ||
else if (min !== undefined) { | ||
return new constraint_1.FunctionConstraint((value, path) => { | ||
return !Array.isArray(value) || value.length >= min ? [] : [{ path: path, message: `should be less or equal than ${min}` }]; | ||
}); | ||
} | ||
else if (max !== undefined) { | ||
return new constraint_1.FunctionConstraint((value, path) => { | ||
return !Array.isArray(value) || value.length <= max ? [] : [{ path: path, message: `should be greater or equal than ${max}` }]; | ||
}); | ||
} | ||
throw new Error('constraint minItems or maxItems undefined'); | ||
} | ||
@@ -264,29 +247,27 @@ } | ||
build(root, rule) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (rule.uniqueItems === undefined) { | ||
throw new Error('Unique items not define'); | ||
if (rule.uniqueItems === undefined) { | ||
throw new Error('Unique items not define'); | ||
} | ||
const unique = (source) => { | ||
// in the case of serializing add _ to be able to differentiate a string "{}" from a serialized object {} | ||
const array = source.map(p => p !== null && typeof p === 'object' ? '_' + JSON.stringify(_1.Helper.obj.sortObject(source)) : p); | ||
const uniques = []; | ||
for (let i = 0; i < array.length; i++) { | ||
if (!uniques.includes(array[i])) { | ||
uniques.push(array[i]); | ||
} | ||
else { | ||
return false; | ||
} | ||
} | ||
const unique = (source) => { | ||
// in the case of serializing add _ to be able to differentiate a string "{}" from a serialized object {} | ||
const array = source.map(p => p !== null && typeof p === 'object' ? '_' + JSON.stringify(_1.Helper.sortObject(source)) : p); | ||
const uniques = []; | ||
for (let i = 0; i < array.length; i++) { | ||
if (!uniques.includes(array[i])) { | ||
uniques.push(array[i]); | ||
} | ||
else { | ||
return false; | ||
} | ||
} | ||
return true; | ||
return true; | ||
}; | ||
const func = rule.uniqueItems | ||
? (value, path) => { | ||
return !Array.isArray(value) || unique(value) ? [] : [{ path: path, message: 'Invalid unique items' }]; | ||
} | ||
: () => { | ||
return []; | ||
}; | ||
const func = rule.uniqueItems | ||
? (value, path) => __awaiter(this, void 0, void 0, function* () { | ||
return !Array.isArray(value) || unique(value) ? [] : [{ path: path, message: 'Invalid unique items' }]; | ||
}) | ||
: () => __awaiter(this, void 0, void 0, function* () { | ||
return []; | ||
}); | ||
return new constraint_1.FunctionConstraint(func); | ||
}); | ||
return new constraint_1.FunctionConstraint(func); | ||
} | ||
@@ -300,45 +281,43 @@ } | ||
build(root, rule) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
// https://www.acuriousanimal.com/blog/20211205/javascript-handle-unicode | ||
// https://stackoverflow.com/questions/48009201/how-to-get-the-unicode-code-point-for-a-character-in-javascript | ||
const min = rule.minLength; | ||
const max = rule.maxLength; | ||
if (min !== undefined && max !== undefined) { | ||
return new constraint_1.FunctionConstraint((value, path) => __awaiter(this, void 0, void 0, function* () { | ||
if (typeof value !== 'string') { | ||
return []; | ||
} | ||
if (value === undefined || value === null) { | ||
return [{ path: path, message: 'undefined value' }]; | ||
} | ||
const length = Array.from(value).length; | ||
return length >= min && length <= max ? [] : [{ path: path, message: `outside the range of ${min} to ${max}` }]; | ||
})); | ||
} | ||
else if (min !== undefined) { | ||
return new constraint_1.FunctionConstraint((value, path) => __awaiter(this, void 0, void 0, function* () { | ||
if (typeof value !== 'string') { | ||
return []; | ||
} | ||
if (value === undefined || value === null) { | ||
return [{ path: path, message: 'undefined value' }]; | ||
} | ||
const length = Array.from(value).length; | ||
return length >= min ? [] : [{ path: path, message: `should be less than ${min}` }]; | ||
})); | ||
} | ||
else if (max !== undefined) { | ||
return new constraint_1.FunctionConstraint((value, path) => __awaiter(this, void 0, void 0, function* () { | ||
if (typeof value !== 'string') { | ||
return []; | ||
} | ||
if (value === undefined || value === null) { | ||
return [{ path: path, message: 'undefined value' }]; | ||
} | ||
const length = Array.from(value).length; | ||
return length <= max ? [] : [{ path: path, message: `should be greater than ${max}` }]; | ||
})); | ||
} | ||
throw new Error('constraint minLength or maxLength undefined'); | ||
}); | ||
// https://www.acuriousanimal.com/blog/20211205/javascript-handle-unicode | ||
// https://stackoverflow.com/questions/48009201/how-to-get-the-unicode-code-point-for-a-character-in-javascript | ||
const min = rule.minLength; | ||
const max = rule.maxLength; | ||
if (min !== undefined && max !== undefined) { | ||
return new constraint_1.FunctionConstraint((value, path) => { | ||
if (typeof value !== 'string') { | ||
return []; | ||
} | ||
if (value === undefined || value === null) { | ||
return [{ path: path, message: 'undefined value' }]; | ||
} | ||
const length = Array.from(value).length; | ||
return length >= min && length <= max ? [] : [{ path: path, message: `outside the range of ${min} to ${max}` }]; | ||
}); | ||
} | ||
else if (min !== undefined) { | ||
return new constraint_1.FunctionConstraint((value, path) => { | ||
if (typeof value !== 'string') { | ||
return []; | ||
} | ||
if (value === undefined || value === null) { | ||
return [{ path: path, message: 'undefined value' }]; | ||
} | ||
const length = Array.from(value).length; | ||
return length >= min ? [] : [{ path: path, message: `should be less than ${min}` }]; | ||
}); | ||
} | ||
else if (max !== undefined) { | ||
return new constraint_1.FunctionConstraint((value, path) => { | ||
if (typeof value !== 'string') { | ||
return []; | ||
} | ||
if (value === undefined || value === null) { | ||
return [{ path: path, message: 'undefined value' }]; | ||
} | ||
const length = Array.from(value).length; | ||
return length <= max ? [] : [{ path: path, message: `should be greater than ${max}` }]; | ||
}); | ||
} | ||
throw new Error('constraint minLength or maxLength undefined'); | ||
} | ||
@@ -352,49 +331,47 @@ } | ||
build(root, rule) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const min = rule.minimum; | ||
const max = rule.maximum; | ||
const exclusiveMinimum = rule.exclusiveMinimum; | ||
const exclusiveMaximum = rule.exclusiveMaximum; | ||
if (min !== undefined && max !== undefined) { | ||
return new constraint_1.FunctionConstraint((value, path) => __awaiter(this, void 0, void 0, function* () { | ||
return isNaN(value) || (value >= min && value) <= max ? [] : [{ path: path, message: `outside the range form ${min} to ${max}` }]; | ||
})); | ||
} | ||
else if (exclusiveMinimum !== undefined && exclusiveMaximum !== undefined) { | ||
return new constraint_1.FunctionConstraint((value, path) => __awaiter(this, void 0, void 0, function* () { | ||
return isNaN(value) || (value > exclusiveMinimum && value < exclusiveMaximum) ? [] : [{ path: path, message: `outside the range form ${exclusiveMinimum} exclusive to ${exclusiveMaximum} exclusive` }]; | ||
})); | ||
} | ||
else if (min !== undefined && exclusiveMaximum !== undefined) { | ||
return new constraint_1.FunctionConstraint((value, path) => __awaiter(this, void 0, void 0, function* () { | ||
return isNaN(value) || (value >= min && value < exclusiveMaximum) ? [] : [{ path: path, message: `outside the range form ${min} to ${exclusiveMaximum} exclusive` }]; | ||
})); | ||
} | ||
else if (exclusiveMinimum !== undefined && max !== undefined) { | ||
return new constraint_1.FunctionConstraint((value, path) => __awaiter(this, void 0, void 0, function* () { | ||
return isNaN(value) || (value > exclusiveMinimum && value <= max) ? [] : [{ path: path, message: `outside the range form ${exclusiveMinimum} exclusive to ${max}` }]; | ||
})); | ||
} | ||
else if (min !== undefined) { | ||
return new constraint_1.FunctionConstraint((value, path) => __awaiter(this, void 0, void 0, function* () { | ||
return isNaN(value) || value >= min ? [] : [{ path: path, message: `should be less or equal than ${min}` }]; | ||
})); | ||
} | ||
else if (exclusiveMinimum !== undefined) { | ||
return new constraint_1.FunctionConstraint((value, path) => __awaiter(this, void 0, void 0, function* () { | ||
return isNaN(value) || value > exclusiveMinimum ? [] : [{ path: path, message: `should be less than ${exclusiveMinimum}` }]; | ||
})); | ||
} | ||
else if (max !== undefined) { | ||
return new constraint_1.FunctionConstraint((value, path) => __awaiter(this, void 0, void 0, function* () { | ||
return isNaN(value) || value <= max ? [] : [{ path: path, message: `should be greater or equal than ${max}` }]; | ||
})); | ||
} | ||
else if (exclusiveMaximum !== undefined) { | ||
return new constraint_1.FunctionConstraint((value, path) => __awaiter(this, void 0, void 0, function* () { | ||
return isNaN(value) || value < exclusiveMaximum ? [] : [{ path: path, message: `should be greater than ${exclusiveMaximum}` }]; | ||
})); | ||
} | ||
throw new Error('constraint minimum or maximum undefined'); | ||
}); | ||
const min = rule.minimum; | ||
const max = rule.maximum; | ||
const exclusiveMinimum = rule.exclusiveMinimum; | ||
const exclusiveMaximum = rule.exclusiveMaximum; | ||
if (min !== undefined && max !== undefined) { | ||
return new constraint_1.FunctionConstraint((value, path) => { | ||
return isNaN(value) || (value >= min && value) <= max ? [] : [{ path: path, message: `outside the range form ${min} to ${max}` }]; | ||
}); | ||
} | ||
else if (exclusiveMinimum !== undefined && exclusiveMaximum !== undefined) { | ||
return new constraint_1.FunctionConstraint((value, path) => { | ||
return isNaN(value) || (value > exclusiveMinimum && value < exclusiveMaximum) ? [] : [{ path: path, message: `outside the range form ${exclusiveMinimum} exclusive to ${exclusiveMaximum} exclusive` }]; | ||
}); | ||
} | ||
else if (min !== undefined && exclusiveMaximum !== undefined) { | ||
return new constraint_1.FunctionConstraint((value, path) => { | ||
return isNaN(value) || (value >= min && value < exclusiveMaximum) ? [] : [{ path: path, message: `outside the range form ${min} to ${exclusiveMaximum} exclusive` }]; | ||
}); | ||
} | ||
else if (exclusiveMinimum !== undefined && max !== undefined) { | ||
return new constraint_1.FunctionConstraint((value, path) => { | ||
return isNaN(value) || (value > exclusiveMinimum && value <= max) ? [] : [{ path: path, message: `outside the range form ${exclusiveMinimum} exclusive to ${max}` }]; | ||
}); | ||
} | ||
else if (min !== undefined) { | ||
return new constraint_1.FunctionConstraint((value, path) => { | ||
return isNaN(value) || value >= min ? [] : [{ path: path, message: `should be less or equal than ${min}` }]; | ||
}); | ||
} | ||
else if (exclusiveMinimum !== undefined) { | ||
return new constraint_1.FunctionConstraint((value, path) => { | ||
return isNaN(value) || value > exclusiveMinimum ? [] : [{ path: path, message: `should be less than ${exclusiveMinimum}` }]; | ||
}); | ||
} | ||
else if (max !== undefined) { | ||
return new constraint_1.FunctionConstraint((value, path) => { | ||
return isNaN(value) || value <= max ? [] : [{ path: path, message: `should be greater or equal than ${max}` }]; | ||
}); | ||
} | ||
else if (exclusiveMaximum !== undefined) { | ||
return new constraint_1.FunctionConstraint((value, path) => { | ||
return isNaN(value) || value < exclusiveMaximum ? [] : [{ path: path, message: `should be greater than ${exclusiveMaximum}` }]; | ||
}); | ||
} | ||
throw new Error('constraint minimum or maximum undefined'); | ||
} | ||
@@ -411,30 +388,28 @@ } | ||
build(root, rule) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (rule.prefixItems === undefined) { | ||
throw new Error('Prefix items not define'); | ||
if (rule.prefixItems === undefined) { | ||
throw new Error('Prefix items not define'); | ||
} | ||
const itemsConstraint = []; | ||
for (const item of rule.prefixItems) { | ||
const constraint = this.constraints.build(root, item); | ||
if (constraint === undefined) { | ||
throw new Error(`Prefix items constraint ${JSON.stringify(rule)} undefined`); | ||
} | ||
const itemsConstraint = []; | ||
for (const item of rule.prefixItems) { | ||
const constraint = yield this.constraints.build(root, item); | ||
if (constraint === undefined) { | ||
throw new Error(`Prefix items constraint ${JSON.stringify(rule)} undefined`); | ||
} | ||
itemsConstraint.push(constraint); | ||
itemsConstraint.push(constraint); | ||
} | ||
return new constraint_1.FunctionConstraint((value, path) => { | ||
if (!Array.isArray(value)) { | ||
return []; | ||
} | ||
return new constraint_1.FunctionConstraint((value, path) => __awaiter(this, void 0, void 0, function* () { | ||
if (!Array.isArray(value)) { | ||
return []; | ||
const errors = []; | ||
for (let i = 0; i < value.length; i++) { | ||
if (i >= itemsConstraint.length) { | ||
break; | ||
} | ||
const errors = []; | ||
for (let i = 0; i < value.length; i++) { | ||
if (i >= itemsConstraint.length) { | ||
break; | ||
} | ||
const childErrors = yield itemsConstraint[i].eval(value[i], path + '.' + i); | ||
if (childErrors.length > 0) { | ||
errors.push(...errors); | ||
} | ||
const childErrors = itemsConstraint[i].eval(value[i], path + '.' + i); | ||
if (childErrors.length > 0) { | ||
errors.push(...errors); | ||
} | ||
return errors; | ||
})); | ||
} | ||
return errors; | ||
}); | ||
@@ -449,21 +424,19 @@ } | ||
build(root, rule) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (rule.required === undefined) { | ||
throw new Error('required not define'); | ||
if (rule.required === undefined) { | ||
throw new Error('required not define'); | ||
} | ||
const required = rule.required; | ||
return new constraint_1.FunctionConstraint((value, path) => { | ||
if (typeof value !== 'object' || Array.isArray(value)) { | ||
return []; | ||
} | ||
const required = rule.required; | ||
return new constraint_1.FunctionConstraint((value, path) => __awaiter(this, void 0, void 0, function* () { | ||
if (typeof value !== 'object' || Array.isArray(value)) { | ||
return []; | ||
let count = 0; | ||
for (const key of Object.keys(value)) { | ||
if (required.includes(key)) { | ||
count++; | ||
} | ||
let count = 0; | ||
for (const key of Object.keys(value)) { | ||
if (required.includes(key)) { | ||
count++; | ||
} | ||
} | ||
return count === required.length | ||
? [] | ||
: [{ path: path, message: `the following fields are required [${required.join(', ')}]` }]; | ||
})); | ||
} | ||
return count === required.length | ||
? [] | ||
: [{ path: path, message: `the following fields are required [${required.join(', ')}]` }]; | ||
}); | ||
@@ -478,17 +451,15 @@ } | ||
build(root, rule) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (rule.enum === undefined) { | ||
throw new Error('Enum not define'); | ||
} | ||
let values; | ||
if (Array.isArray(rule.enum)) { | ||
values = rule.enum; | ||
} | ||
else { | ||
throw new Error('Invalid enum define'); | ||
} | ||
const showValues = values.join(','); | ||
return new constraint_1.FunctionConstraint((value, path) => __awaiter(this, void 0, void 0, function* () { | ||
return values.includes(value) ? [] : [{ path: path, message: `not in [${showValues}]` }]; | ||
})); | ||
if (rule.enum === undefined) { | ||
throw new Error('Enum not define'); | ||
} | ||
let values; | ||
if (Array.isArray(rule.enum)) { | ||
values = rule.enum; | ||
} | ||
else { | ||
throw new Error('Invalid enum define'); | ||
} | ||
const showValues = values.join(','); | ||
return new constraint_1.FunctionConstraint((value, path) => { | ||
return values.includes(value) ? [] : [{ path: path, message: `not in [${showValues}]` }]; | ||
}); | ||
@@ -506,16 +477,14 @@ } | ||
build(root, rule) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (rule.format === undefined) { | ||
throw new Error('Format not define'); | ||
if (rule.format === undefined) { | ||
throw new Error('Format not define'); | ||
} | ||
const format = this.formats.get(rule.format); | ||
if (!format) { | ||
throw new Error(`Format ${rule.format} not found`); | ||
} | ||
return new constraint_1.FunctionConstraint((value, path) => { | ||
if (typeof value !== 'string') { | ||
return []; | ||
} | ||
const format = this.formats.get(rule.format); | ||
if (!format) { | ||
throw new Error(`Format ${rule.format} not found`); | ||
} | ||
return new constraint_1.FunctionConstraint((value, path) => __awaiter(this, void 0, void 0, function* () { | ||
if (typeof value !== 'string') { | ||
return []; | ||
} | ||
return format.test(value) ? [] : [{ path: path, message: `does not comply with the format ${rule.format}` }]; | ||
})); | ||
return format.test(value) ? [] : [{ path: path, message: `does not comply with the format ${rule.format}` }]; | ||
}); | ||
@@ -530,10 +499,8 @@ } | ||
build(root, rule) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (rule.pattern === undefined) { | ||
throw new Error('Pattern not define'); | ||
} | ||
const regExp = new RegExp(rule.pattern); | ||
return new constraint_1.FunctionConstraint((value, path) => __awaiter(this, void 0, void 0, function* () { | ||
return typeof value !== 'string' || regExp.test(value) ? [] : [{ path: path, message: `does not comply with the format ${rule.pattern}` }]; | ||
})); | ||
if (rule.pattern === undefined) { | ||
throw new Error('Pattern not define'); | ||
} | ||
const regExp = new RegExp(rule.pattern); | ||
return new constraint_1.FunctionConstraint((value, path) => { | ||
return typeof value !== 'string' || regExp.test(value) ? [] : [{ path: path, message: `does not comply with the format ${rule.pattern}` }]; | ||
}); | ||
@@ -543,3 +510,3 @@ } | ||
exports.PatternConstraintBuilder = PatternConstraintBuilder; | ||
class PatternPropertyConstraintBuilder { | ||
class ContainsConstraintBuilder { | ||
constructor(constraints) { | ||
@@ -549,176 +516,129 @@ this.constraints = constraints; | ||
apply(rule) { | ||
return rule.patternProperties !== undefined; | ||
return rule.contains !== undefined || rule.minContains !== undefined || rule.maxContains !== undefined; | ||
} | ||
build(root, rule) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (rule.patternProperties === undefined) { | ||
throw new Error('patternProperties not define'); | ||
const min = rule.minContains; | ||
const max = rule.maxContains; | ||
if (rule.contains === undefined) { | ||
if (min !== undefined && max !== undefined) { | ||
return new constraint_1.FunctionConstraint((value, path) => { | ||
return !Array.isArray(value) || value.length === 0 || (value.length >= min && value.length <= max) | ||
? [] | ||
: [{ path: path, message: `contains outside the range from ${min} to ${max} items` }]; | ||
}); | ||
} | ||
const patternProperties = []; | ||
for (const entry of Object.entries(rule.patternProperties)) { | ||
let constraint; | ||
if (typeof entry[1] === 'object') { | ||
constraint = yield this.constraints.build(root, entry[1]); | ||
else if (min !== undefined) { | ||
return new constraint_1.FunctionConstraint((value, path) => { | ||
return !Array.isArray(value) || value.length === 0 || value.length >= min | ||
? [] | ||
: [{ path: path, message: `contains should be less or equal than ${min}` }]; | ||
}); | ||
} | ||
else if (max !== undefined) { | ||
return new constraint_1.FunctionConstraint((value, path) => { | ||
return !Array.isArray(value) || value.length === 0 || value.length <= max | ||
? [] | ||
: [{ path: path, message: `contains should be greater or equal than ${max}` }]; | ||
}); | ||
} | ||
} | ||
else if (rule.contains !== undefined && typeof rule.contains === 'boolean') { | ||
if (min !== undefined && max !== undefined) { | ||
return new constraint_1.FunctionConstraint((value, path) => { | ||
return !Array.isArray(value) || (value.length >= min && value.length <= max) | ||
? [] | ||
: [{ path: path, message: `contains outside the range from ${min} to ${max} items` }]; | ||
}); | ||
} | ||
else if (min !== undefined) { | ||
return new constraint_1.FunctionConstraint((value, path) => { | ||
return !Array.isArray(value) || value.length >= min | ||
? [] | ||
: [{ path: path, message: `contains should be less or equal than ${min}` }]; | ||
}); | ||
} | ||
else if (max !== undefined) { | ||
return new constraint_1.FunctionConstraint((value, path) => { | ||
return !Array.isArray(value) || value.length <= max | ||
? [] | ||
: [{ path: path, message: `contains should be greater or equal than ${max}` }]; | ||
}); | ||
} | ||
else { | ||
return new constraint_1.FunctionConstraint((value, path) => { | ||
return !Array.isArray(value) || value.length > 0 | ||
? [] | ||
: [{ path: path, message: 'must contain at least one item' }]; | ||
}); | ||
} | ||
} | ||
else if (rule.contains !== undefined) { | ||
const contains = rule.contains; | ||
if (contains) { | ||
const constraint = this.constraints.build(root, contains); | ||
if (constraint === undefined) { | ||
throw new Error(`Contains constraint ${JSON.stringify(rule)} undefined`); | ||
} | ||
else if (typeof entry[1] === 'boolean') { | ||
constraint = new constraint_1.FunctionConstraint((value, path) => __awaiter(this, void 0, void 0, function* () { | ||
return entry[1] ? [] : [{ path: path, message: 'Pattern properties exists' }]; | ||
})); | ||
} | ||
if (constraint) { | ||
patternProperties.push({ regExp: new RegExp(entry[0]), constraint: constraint }); | ||
} | ||
} | ||
return new constraint_1.FunctionConstraint((value, path) => __awaiter(this, void 0, void 0, function* () { | ||
const errors = []; | ||
for (const entry of Object.entries(value)) { | ||
for (const patternProperty of patternProperties) { | ||
if (patternProperty.regExp.test(entry[0])) { | ||
const childErrors = yield patternProperty.constraint.eval(entry[1], path); | ||
if (childErrors.length) { | ||
errors.push(...childErrors); | ||
} | ||
const getCount = (value, path) => { | ||
let count = 0; | ||
for (let i = 0; i < value.length; i++) { | ||
const errors = constraint.eval(value[i], path); | ||
if (errors.length === 0) { | ||
count++; | ||
} | ||
} | ||
} | ||
return errors; | ||
})); | ||
}); | ||
} | ||
} | ||
exports.PatternPropertyConstraintBuilder = PatternPropertyConstraintBuilder; | ||
class ContainsConstraintBuilder { | ||
constructor(constraints) { | ||
this.constraints = constraints; | ||
} | ||
apply(rule) { | ||
return rule.contains !== undefined || rule.minContains !== undefined || rule.maxContains !== undefined; | ||
} | ||
build(root, rule) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const min = rule.minContains; | ||
const max = rule.maxContains; | ||
if (rule.contains === undefined) { | ||
return count; | ||
}; | ||
if (min !== undefined && max !== undefined) { | ||
return new constraint_1.FunctionConstraint((value, path) => __awaiter(this, void 0, void 0, function* () { | ||
return !Array.isArray(value) || value.length === 0 || (value.length >= min && value.length <= max) | ||
return new constraint_1.FunctionConstraint((value, path) => { | ||
if (!Array.isArray(value)) { | ||
return []; | ||
} | ||
const count = getCount(value, path); | ||
return count >= min && count <= max | ||
? [] | ||
: [{ path: path, message: `contains outside the range from ${min} to ${max} items` }]; | ||
})); | ||
}); | ||
} | ||
else if (min !== undefined) { | ||
return new constraint_1.FunctionConstraint((value, path) => __awaiter(this, void 0, void 0, function* () { | ||
return !Array.isArray(value) || value.length === 0 || value.length >= min | ||
? [] | ||
: [{ path: path, message: `contains should be less or equal than ${min}` }]; | ||
})); | ||
return new constraint_1.FunctionConstraint((value, path) => { | ||
if (!Array.isArray(value)) { | ||
return []; | ||
} | ||
const count = getCount(value, path); | ||
return count >= min ? [] : [{ path: path, message: `contains constraint should be less or equal than ${min}` }]; | ||
}); | ||
} | ||
else if (max !== undefined) { | ||
return new constraint_1.FunctionConstraint((value, path) => __awaiter(this, void 0, void 0, function* () { | ||
return !Array.isArray(value) || value.length === 0 || value.length <= max | ||
? [] | ||
: [{ path: path, message: `contains should be greater or equal than ${max}` }]; | ||
})); | ||
return new constraint_1.FunctionConstraint((value, path) => { | ||
if (!Array.isArray(value)) { | ||
return []; | ||
} | ||
const count = getCount(value, path); | ||
return count <= max ? [] : [{ path: path, message: `contains should be greater or equal than ${max}` }]; | ||
}); | ||
} | ||
} | ||
else if (rule.contains !== undefined && typeof rule.contains === 'boolean') { | ||
if (min !== undefined && max !== undefined) { | ||
return new constraint_1.FunctionConstraint((value, path) => __awaiter(this, void 0, void 0, function* () { | ||
return !Array.isArray(value) || (value.length >= min && value.length <= max) | ||
? [] | ||
: [{ path: path, message: `contains outside the range from ${min} to ${max} items` }]; | ||
})); | ||
} | ||
else if (min !== undefined) { | ||
return new constraint_1.FunctionConstraint((value, path) => __awaiter(this, void 0, void 0, function* () { | ||
return !Array.isArray(value) || value.length >= min | ||
? [] | ||
: [{ path: path, message: `contains should be less or equal than ${min}` }]; | ||
})); | ||
} | ||
else if (max !== undefined) { | ||
return new constraint_1.FunctionConstraint((value, path) => __awaiter(this, void 0, void 0, function* () { | ||
return !Array.isArray(value) || value.length <= max | ||
? [] | ||
: [{ path: path, message: `contains should be greater or equal than ${max}` }]; | ||
})); | ||
} | ||
else { | ||
return new constraint_1.FunctionConstraint((value, path) => __awaiter(this, void 0, void 0, function* () { | ||
return !Array.isArray(value) || value.length > 0 | ||
? [] | ||
: [{ path: path, message: 'must contain at least one item' }]; | ||
})); | ||
} | ||
} | ||
else if (rule.contains !== undefined) { | ||
const contains = rule.contains; | ||
if (contains) { | ||
const constraint = yield this.constraints.build(root, contains); | ||
if (constraint === undefined) { | ||
throw new Error(`Contains constraint ${JSON.stringify(rule)} undefined`); | ||
} | ||
const getCount = (value, path) => __awaiter(this, void 0, void 0, function* () { | ||
let count = 0; | ||
return new constraint_1.FunctionConstraint((value, path) => { | ||
const errors = []; | ||
if (!Array.isArray(value)) { | ||
return []; | ||
} | ||
// at least one item must meet the constraint | ||
for (let i = 0; i < value.length; i++) { | ||
const errors = yield constraint.eval(value[i], path); | ||
if (errors.length === 0) { | ||
count++; | ||
const childErrors = constraint.eval(value[i], path); | ||
if (childErrors.length === 0) { | ||
return []; | ||
} | ||
else { | ||
errors.push(...childErrors); | ||
} | ||
} | ||
return count; | ||
errors.push({ path: path, message: 'does not meet at least one of the contain rules' }); | ||
return errors; | ||
}); | ||
if (min !== undefined && max !== undefined) { | ||
return new constraint_1.FunctionConstraint((value, path) => __awaiter(this, void 0, void 0, function* () { | ||
if (!Array.isArray(value)) { | ||
return []; | ||
} | ||
const count = yield getCount(value, path); | ||
return count >= min && count <= max | ||
? [] | ||
: [{ path: path, message: `contains outside the range from ${min} to ${max} items` }]; | ||
})); | ||
} | ||
else if (min !== undefined) { | ||
return new constraint_1.FunctionConstraint((value, path) => __awaiter(this, void 0, void 0, function* () { | ||
if (!Array.isArray(value)) { | ||
return []; | ||
} | ||
const count = yield getCount(value, path); | ||
return count >= min ? [] : [{ path: path, message: `contains constraint should be less or equal than ${min}` }]; | ||
})); | ||
} | ||
else if (max !== undefined) { | ||
return new constraint_1.FunctionConstraint((value, path) => __awaiter(this, void 0, void 0, function* () { | ||
if (!Array.isArray(value)) { | ||
return []; | ||
} | ||
const count = yield getCount(value, path); | ||
return count <= max ? [] : [{ path: path, message: `contains should be greater or equal than ${max}` }]; | ||
})); | ||
} | ||
else { | ||
return new constraint_1.FunctionConstraint((value, path) => __awaiter(this, void 0, void 0, function* () { | ||
const errors = []; | ||
if (!Array.isArray(value)) { | ||
return []; | ||
} | ||
// at least one item must meet the constraint | ||
for (let i = 0; i < value.length; i++) { | ||
const childErrors = yield constraint.eval(value[i], path); | ||
if (childErrors.length === 0) { | ||
return []; | ||
} | ||
else { | ||
errors.push(...childErrors); | ||
} | ||
} | ||
errors.push({ path: path, message: 'does not meet at least one of the contain rules' }); | ||
return errors; | ||
})); | ||
} | ||
} | ||
} | ||
throw new Error('constraint contains undefined'); | ||
}); | ||
} | ||
throw new Error('constraint contains undefined'); | ||
} | ||
@@ -732,32 +652,30 @@ } | ||
build(root, rule) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (rule.const === undefined) { | ||
throw new Error('Const not define'); | ||
if (rule.const === undefined) { | ||
throw new Error('Const not define'); | ||
} | ||
const type = typeof rule.const; | ||
let _const; | ||
let isArray = false; | ||
if (type === 'object' && Array.isArray(rule.const)) { | ||
_const = JSON.stringify(rule.const); | ||
isArray = true; | ||
} | ||
else if (type === 'object' && rule.const !== null) { | ||
_const = JSON.stringify(_1.Helper.obj.sortObject(rule.const)); | ||
} | ||
else { | ||
_const = rule.const; | ||
} | ||
return new constraint_1.FunctionConstraint((value, path) => { | ||
if (type === 'object' && isArray) { | ||
const array = JSON.stringify(value); | ||
return array === _const ? [] : [{ path: path, message: `Is not ${JSON.stringify(rule.const)}` }]; | ||
} | ||
const type = typeof rule.const; | ||
let _const; | ||
let isArray = false; | ||
if (type === 'object' && Array.isArray(rule.const)) { | ||
_const = JSON.stringify(rule.const); | ||
isArray = true; | ||
else if (type === 'object' && value !== null) { | ||
const array = JSON.stringify(_1.Helper.obj.sortObject(value)); | ||
return array === _const ? [] : [{ path: path, message: `Is not ${JSON.stringify(rule.const)}` }]; | ||
} | ||
else if (type === 'object' && rule.const !== null) { | ||
_const = JSON.stringify(_1.Helper.sortObject(rule.const)); | ||
} | ||
else { | ||
_const = rule.const; | ||
return _const === value ? [] : [{ path: path, message: `Is not ${JSON.stringify(rule.const)}` }]; | ||
} | ||
return new constraint_1.FunctionConstraint((value, path) => __awaiter(this, void 0, void 0, function* () { | ||
if (type === 'object' && isArray) { | ||
const array = JSON.stringify(value); | ||
return array === _const ? [] : [{ path: path, message: `Is not ${JSON.stringify(rule.const)}` }]; | ||
} | ||
else if (type === 'object' && value !== null) { | ||
const array = JSON.stringify(_1.Helper.sortObject(value)); | ||
return array === _const ? [] : [{ path: path, message: `Is not ${JSON.stringify(rule.const)}` }]; | ||
} | ||
else { | ||
return _const === value ? [] : [{ path: path, message: `Is not ${JSON.stringify(rule.const)}` }]; | ||
} | ||
})); | ||
}); | ||
@@ -772,9 +690,7 @@ } | ||
build(root, rule) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (typeof rule !== 'boolean') { | ||
throw new Error('boolean schema not define'); | ||
} | ||
return new constraint_1.FunctionConstraint((value, path) => __awaiter(this, void 0, void 0, function* () { | ||
return rule ? [] : [{ path: path, message: 'Boolean schema invalid' }]; | ||
})); | ||
if (typeof rule !== 'boolean') { | ||
throw new Error('boolean schema not define'); | ||
} | ||
return new constraint_1.FunctionConstraint((value, path) => { | ||
return rule ? [] : [{ path: path, message: 'Boolean schema invalid' }]; | ||
}); | ||
@@ -792,27 +708,25 @@ } | ||
build(root, rule) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (rule.if === undefined) { | ||
throw new Error('if not define'); | ||
if (rule.if === undefined) { | ||
throw new Error('if not define'); | ||
} | ||
if (rule.then === undefined && rule.else === undefined) { | ||
throw new Error('then or else not define'); | ||
} | ||
const _if = this.constraints.build(root, rule.if); | ||
if (_if === undefined) { | ||
throw new Error(`constraint ${JSON.stringify(rule)} undefined`); | ||
} | ||
const _then = rule.then !== undefined ? this.constraints.build(root, rule.then) : undefined; | ||
const _else = rule.else !== undefined ? this.constraints.build(root, rule.else) : undefined; | ||
return new constraint_1.FunctionConstraint((value, path) => { | ||
const ifErrors = _if.eval(value, path); | ||
if (ifErrors.length === 0 && _then !== undefined) { | ||
return _then !== undefined ? _then.eval(value, path) : []; | ||
} | ||
if (rule.then === undefined && rule.else === undefined) { | ||
throw new Error('then or else not define'); | ||
else if (ifErrors.length > 0 && _else !== undefined) { | ||
return _else.eval(value, path); | ||
} | ||
const _if = yield this.constraints.build(root, rule.if); | ||
if (_if === undefined) { | ||
throw new Error(`constraint ${JSON.stringify(rule)} undefined`); | ||
else { | ||
return []; | ||
} | ||
const _then = rule.then !== undefined ? yield this.constraints.build(root, rule.then) : undefined; | ||
const _else = rule.else !== undefined ? yield this.constraints.build(root, rule.else) : undefined; | ||
return new constraint_1.FunctionConstraint((value, path) => __awaiter(this, void 0, void 0, function* () { | ||
const ifErrors = yield _if.eval(value, path); | ||
if (ifErrors.length === 0 && _then !== undefined) { | ||
return _then !== undefined ? _then.eval(value, path) : []; | ||
} | ||
else if (ifErrors.length > 0 && _else !== undefined) { | ||
return _else.eval(value, path); | ||
} | ||
else { | ||
return []; | ||
} | ||
})); | ||
}); | ||
@@ -830,14 +744,12 @@ } | ||
build(root, rule) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (rule.not === undefined) { | ||
throw new Error('Not rule not define'); | ||
if (rule.not === undefined) { | ||
throw new Error('Not rule not define'); | ||
} | ||
const notConstraint = this.constraints.build(root, rule.not); | ||
return new constraint_1.FunctionConstraint((value, path) => { | ||
if (notConstraint) { | ||
const errors = notConstraint.eval(value, path); | ||
return errors.length > 0 ? [] : [{ path: path, message: 'not rule is invalid' }]; | ||
} | ||
const notConstraint = yield this.constraints.build(root, rule.not); | ||
return new constraint_1.FunctionConstraint((value, path) => __awaiter(this, void 0, void 0, function* () { | ||
if (notConstraint) { | ||
const errors = yield notConstraint.eval(value, path); | ||
return errors.length > 0 ? [] : [{ path: path, message: 'not rule is invalid' }]; | ||
} | ||
return []; | ||
})); | ||
return []; | ||
}); | ||
@@ -847,48 +759,2 @@ } | ||
exports.NotConstraintBuilder = NotConstraintBuilder; | ||
class PropertiesConstraintBuilder { | ||
constructor(constraints) { | ||
this.constraints = constraints; | ||
} | ||
apply(rule) { | ||
return rule.properties !== undefined; | ||
} | ||
build(root, rule) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (rule.properties === undefined) { | ||
throw new Error('Properties rule not define'); | ||
} | ||
if (Array.isArray(rule.properties)) { | ||
throw new Error('Properties should be object and not array'); | ||
} | ||
const propertiesConstraint = []; | ||
if (typeof rule.properties === 'object') { | ||
for (const entry of Object.entries(rule.properties)) { | ||
const propertyConstraint = yield this.constraints.build(root, entry[1]); | ||
if (propertyConstraint) { | ||
propertiesConstraint.push({ name: entry[0], constraint: propertyConstraint }); | ||
} | ||
} | ||
} | ||
return new constraint_1.FunctionConstraint((obj, path) => __awaiter(this, void 0, void 0, function* () { | ||
const errors = []; | ||
if (obj && typeof obj === 'object' && !Array.isArray(obj)) { | ||
for (const propertyConstraint of propertiesConstraint) { | ||
const value = obj[propertyConstraint.name]; | ||
if (value === undefined) { | ||
errors.push({ path: path, message: `Property ${propertyConstraint.name} not fount` }); | ||
} | ||
else { | ||
const childErrors = yield propertyConstraint.constraint.eval(value, path + '.' + propertyConstraint.name); | ||
if (childErrors.length > 0) { | ||
errors.push(...childErrors); | ||
} | ||
} | ||
} | ||
} | ||
return errors; | ||
})); | ||
}); | ||
} | ||
} | ||
exports.PropertiesConstraintBuilder = PropertiesConstraintBuilder; | ||
class ItemsConstraintBuilder { | ||
@@ -902,26 +768,24 @@ constructor(constraints) { | ||
build(root, rule) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (rule.items === undefined) { | ||
throw new Error('Items rule not define'); | ||
} | ||
if (Array.isArray(rule.items)) { | ||
throw new Error('Items should be object and not array'); | ||
} | ||
if (typeof rule.items !== 'object') { | ||
throw new Error('Items should be object'); | ||
} | ||
const constraint = yield this.constraints.build(root, rule.items); | ||
return new constraint_1.FunctionConstraint((array, path) => __awaiter(this, void 0, void 0, function* () { | ||
const errors = []; | ||
if (constraint && array && Array.isArray(array)) { | ||
for (let i = 0; i < array.length; i++) { | ||
const item = array[i]; | ||
const childErrors = yield constraint.eval(item, path + '.' + i); | ||
if (childErrors.length > 0) { | ||
errors.push(...childErrors); | ||
} | ||
if (rule.items === undefined) { | ||
throw new Error('Items rule not define'); | ||
} | ||
if (Array.isArray(rule.items)) { | ||
throw new Error('Items should be object and not array'); | ||
} | ||
if (typeof rule.items !== 'object') { | ||
throw new Error('Items should be object'); | ||
} | ||
const constraint = this.constraints.build(root, rule.items); | ||
return new constraint_1.FunctionConstraint((array, path) => { | ||
const errors = []; | ||
if (constraint && array && Array.isArray(array)) { | ||
for (let i = 0; i < array.length; i++) { | ||
const item = array[i]; | ||
const childErrors = constraint.eval(item, path + '.' + i); | ||
if (childErrors.length > 0) { | ||
errors.push(...childErrors); | ||
} | ||
} | ||
return errors; | ||
})); | ||
} | ||
return errors; | ||
}); | ||
@@ -938,76 +802,39 @@ } | ||
apply(rule) { | ||
return rule.$ref !== undefined; | ||
return rule.$ref !== undefined && typeof rule.$ref === 'string'; | ||
} | ||
build(root, rule) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (rule.$ref === undefined) { | ||
throw new Error('Reference not define'); | ||
if (rule.$ref === undefined) { | ||
throw new Error('Reference not define'); | ||
} | ||
let key; | ||
try { | ||
key = this.getKey(root, rule.$ref); | ||
let constraint = this.built[key]; | ||
if (constraint) { | ||
return constraint; | ||
} | ||
let key; | ||
try { | ||
key = this.getKey(root, rule.$ref); | ||
let constraint = this.built[key]; | ||
const refInfo = this.schemaManager.solveRef(root, rule.$ref); | ||
if (refInfo === undefined || refInfo.schema === undefined || refInfo.referenced === undefined) { | ||
throw new Error(`Ref ${rule.$ref} not found`); | ||
} | ||
const referencedSchema = refInfo.schema; | ||
const referencedRule = refInfo.referenced; | ||
constraint = new constraint_1.FunctionConstraint((value, path) => { | ||
const constraint = this.constraints.build(referencedSchema, referencedRule); | ||
if (constraint) { | ||
return constraint; | ||
return constraint.eval(value, path); | ||
} | ||
let referencedSchema; | ||
let referencedRule; | ||
if (rule.$ref.startsWith('#')) { | ||
referencedSchema = root; | ||
referencedRule = this.findRule(root, rule.$ref); | ||
if (referencedRule === undefined) { | ||
referencedRule = this.findRule(rule, rule.$ref); | ||
if (referencedRule === undefined) { | ||
throw new Error(`Ref ${rule.$ref} in schema not found `); | ||
} | ||
} | ||
} | ||
else if ((/\w/g).test(rule.$ref) && root.$defs && Object.keys(root.$defs).includes(rule.$ref)) { | ||
referencedSchema = root; | ||
const found = this.findById(root, rule.$ref); | ||
if (found === undefined) { | ||
referencedRule = root.$defs[_1.Helper.decodeUrl(rule.$ref)]; | ||
if (referencedRule === undefined) { | ||
throw new Error(`Ref ${rule.$ref} schema not found `); | ||
} | ||
} | ||
} | ||
else { | ||
const parts = rule.$ref.split('#'); | ||
referencedSchema = yield this.findSchema(root, parts[0]); | ||
if (parts.length === 1) { | ||
referencedRule = referencedSchema; | ||
} | ||
else if (parts.length === 2) { | ||
referencedRule = this.findRule(referencedSchema, '#' + parts[1]); | ||
if (referencedRule === undefined) { | ||
throw new Error(`Ref ${parts[1]} in ${parts[0]} schema not found`); | ||
} | ||
} | ||
else { | ||
throw new Error(`Ref ${rule.$ref} is invalid`); | ||
} | ||
} | ||
constraint = new constraint_1.FunctionConstraint((value, path) => __awaiter(this, void 0, void 0, function* () { | ||
if (referencedRule === undefined) { | ||
throw new Error(`Ref ${rule.$ref} not found `); | ||
} | ||
const constraint = yield this.constraints.build(referencedSchema, referencedRule); | ||
if (constraint) { | ||
return constraint.eval(value, path); | ||
} | ||
return []; | ||
})); | ||
this.built[key] = constraint; | ||
return constraint; | ||
return []; | ||
}); | ||
this.built[key] = constraint; | ||
return constraint; | ||
} | ||
catch (error) { | ||
if (key !== undefined) { | ||
throw Error(`Ref ${rule.$ref} in ${key} error: ${error.message} `); | ||
} | ||
catch (error) { | ||
if (key !== undefined) { | ||
throw Error(`Ref ${rule.$ref} in ${key} error: ${error.message} `); | ||
} | ||
else { | ||
throw Error(`Ref ${rule.$ref} error: ${error.message} `); | ||
} | ||
else { | ||
throw Error(`Ref ${rule.$ref} error: ${error.message} `); | ||
} | ||
}); | ||
} | ||
} | ||
@@ -1018,3 +845,3 @@ getKey(current, path) { | ||
} | ||
const schemaId = current.$id || _1.Helper.createKey(current); | ||
const schemaId = current.$id || _1.Helper.obj.createKey(current); | ||
if (path.startsWith('#') || path.startsWith('/')) { | ||
@@ -1024,3 +851,3 @@ return `${schemaId}/${path}`; | ||
else if (current.$id) { | ||
return _1.Helper.urlJoin(current.$id, path); | ||
return _1.Helper.http.urlJoin(current.$id, path); | ||
} | ||
@@ -1031,81 +858,98 @@ else { | ||
} | ||
findSchema(current, path) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (path.startsWith('http')) { | ||
return this.schemaManager.solve(path); | ||
} | ||
else { | ||
if (!current.$id) { | ||
throw Error('$id not defined in current schema'); | ||
} | ||
// check if the path matches any $id within the current schema | ||
let found = this.findById(current, path); | ||
if (found !== undefined) { | ||
return found; | ||
} | ||
const uri = _1.Helper.urlJoin(current.$id, path); | ||
if (uri === path || uri === current.$id) { | ||
return current; | ||
} | ||
// check if the uri matches any $id within the current schema | ||
found = this.findById(current, uri); | ||
if (found !== undefined) { | ||
return found; | ||
} | ||
return this.schemaManager.solve(uri); | ||
} | ||
}); | ||
} | ||
exports.RefConstraintBuilder = RefConstraintBuilder; | ||
class PropertiesConstraintBuilder { | ||
constructor(constraints) { | ||
this.constraints = constraints; | ||
} | ||
findRule(schema, ref) { | ||
if (!ref.startsWith('#')) { | ||
// throw Error(`${ref} invalid internal ref`) | ||
return undefined; | ||
} | ||
if (ref === '#' || schema.$id === ref) { | ||
return schema; | ||
} | ||
else if (ref.startsWith('#/')) { | ||
const parts = ref.replace('#/', '').split('/'); | ||
let _current = schema; | ||
for (let i = 0; i < parts.length; i++) { | ||
let part = parts[i]; | ||
part = _1.Helper.decodeUrl(part); | ||
const child = _current[part]; | ||
if (child === undefined) { | ||
// throw Error(`path ${parts.splice(0, i).join('.')} not fount in ${ref} ref`) | ||
return undefined; | ||
} | ||
_current = child; | ||
apply(rule) { | ||
return rule.properties !== undefined || | ||
rule.patternProperties !== undefined || | ||
rule.additionalProperties !== undefined; | ||
} | ||
build(root, rule) { | ||
const propertiesConstraint = []; | ||
const patternProperties = []; | ||
if (rule.properties !== undefined && typeof rule.properties === 'object') { | ||
for (const entry of Object.entries(rule.properties)) { | ||
const propertyConstraint = this.constraints.build(root, entry[1]); | ||
propertiesConstraint.push({ name: entry[0], constraint: propertyConstraint }); | ||
} | ||
return _current; | ||
} | ||
else { | ||
// throw Error(`Invalid ${ref} ref`) | ||
return undefined; | ||
} | ||
} | ||
findById(schema, id) { | ||
if (Array.isArray(schema)) { | ||
for (const item of schema) { | ||
const found = this.findById(item, id); | ||
if (found) { | ||
return found; | ||
if (rule.patternProperties !== undefined) { | ||
for (const entry of Object.entries(rule.patternProperties)) { | ||
let constraint; | ||
if (typeof entry[1] === 'object') { | ||
constraint = this.constraints.build(root, entry[1]); | ||
} | ||
else if (typeof entry[1] === 'boolean') { | ||
constraint = new constraint_1.FunctionConstraint((value, path) => { | ||
return entry[1] ? [] : [{ path: path, message: 'Pattern properties exists' }]; | ||
}); | ||
} | ||
patternProperties.push({ regExp: new RegExp(entry[0]), constraint: constraint }); | ||
} | ||
} | ||
else if (typeof schema === 'object') { | ||
if (schema.$id && schema.$id === id) { | ||
return schema; | ||
} | ||
for (const property of Object.values(schema)) { | ||
const found = this.findById(property, id); | ||
if (found) { | ||
return found; | ||
const additionalProperties = rule.additionalProperties === undefined || | ||
typeof rule.additionalProperties !== 'boolean' || | ||
rule.additionalProperties; | ||
const additionalPropertiesConstraint = rule.additionalProperties !== undefined && typeof rule.additionalProperties !== 'boolean' | ||
? this.constraints.build(root, rule.additionalProperties) | ||
: undefined; | ||
return new constraint_1.FunctionConstraint((obj, path) => { | ||
const errors = []; | ||
if (obj && typeof obj === 'object' && !Array.isArray(obj)) { | ||
for (const entry of Object.entries(obj)) { | ||
const propertyErrors = []; | ||
const patternErrors = []; | ||
let isAdditional = true; | ||
const propertyConstraint = propertiesConstraint.find(p => p.name === entry[0]); | ||
if (propertyConstraint) { | ||
isAdditional = false; | ||
if (propertyConstraint.constraint) { | ||
const childErrors = propertyConstraint.constraint.eval(entry[1], path + '.' + propertyConstraint.name); | ||
if (childErrors.length) { | ||
propertyErrors.push(...childErrors); | ||
} | ||
} | ||
} | ||
for (const patternProperty of patternProperties) { | ||
if (patternProperty.regExp.test(entry[0])) { | ||
isAdditional = false; | ||
if (patternProperty.constraint) { | ||
const childErrors = patternProperty.constraint.eval(entry[1], path); | ||
if (childErrors.length) { | ||
patternErrors.push(...childErrors); | ||
} | ||
} | ||
} | ||
} | ||
if (propertyConstraint && patternProperties.length > 0) { | ||
// en el caso que están las dos reglas definidas , con que cumpla una alcanza | ||
if (propertyErrors.length > 0 && patternErrors.length > 0) { | ||
errors.push(...propertyErrors, ...patternErrors); | ||
} | ||
} | ||
else if (propertyConstraint && propertyErrors.length > 0) { | ||
errors.push(...propertyErrors); | ||
} | ||
else if (patternProperties.length > 0 && patternErrors.length > 0) { | ||
errors.push(...patternErrors); | ||
} | ||
if (!additionalProperties && isAdditional) { | ||
errors.push({ path: path, message: `The additional property ${entry[0]} is not allowed` }); | ||
} | ||
if (additionalPropertiesConstraint !== undefined && isAdditional) { | ||
const childErrors = additionalPropertiesConstraint.eval(entry[1], path); | ||
if (childErrors.length) { | ||
errors.push(...childErrors); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
return undefined; | ||
return errors; | ||
}); | ||
} | ||
} | ||
exports.RefConstraintBuilder = RefConstraintBuilder; | ||
exports.PropertiesConstraintBuilder = PropertiesConstraintBuilder; | ||
//# sourceMappingURL=constraintBuilders.js.map |
@@ -5,3 +5,3 @@ import { Schema, IConstraint, IConstraintBuilder, IConstraintManager } from '../model/schema'; | ||
addBuilder(constraintBuilder: IConstraintBuilder): void; | ||
build(root: Schema, rule: Schema): Promise<IConstraint | undefined>; | ||
build(root: Schema, rule: Schema): IConstraint | undefined; | ||
} |
"use strict"; | ||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { | ||
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } | ||
return new (P || (P = Promise))(function (resolve, reject) { | ||
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } | ||
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } | ||
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } | ||
step((generator = generator.apply(thisArg, _arguments || [])).next()); | ||
}); | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
@@ -22,14 +13,12 @@ exports.ConstraintManager = void 0; | ||
build(root, rule) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
const constraints = []; | ||
for (const constraintBuilder of this.builders) { | ||
if (constraintBuilder.apply(rule)) { | ||
constraints.push(yield constraintBuilder.build(root, rule)); | ||
} | ||
const constraints = []; | ||
for (const constraintBuilder of this.builders) { | ||
if (constraintBuilder.apply(rule)) { | ||
constraints.push(constraintBuilder.build(root, rule)); | ||
} | ||
if (constraints.length === 0) { | ||
return undefined; | ||
} | ||
return new constraint_1.AndConstraint(constraints); | ||
}); | ||
} | ||
if (constraints.length === 0) { | ||
return undefined; | ||
} | ||
return new constraint_1.AndConstraint(constraints); | ||
} | ||
@@ -36,0 +25,0 @@ } |
@@ -5,4 +5,3 @@ import { JemvHelper } from './helper'; | ||
export * from './constraint'; | ||
export * from './schemaBuilder'; | ||
export * from './constraintManager'; | ||
export declare const Helper: JemvHelper; |
@@ -22,5 +22,4 @@ "use strict"; | ||
__exportStar(require("./constraint"), exports); | ||
__exportStar(require("./schemaBuilder"), exports); | ||
__exportStar(require("./constraintManager"), exports); | ||
exports.Helper = new helper_1.JemvHelper(); | ||
//# sourceMappingURL=index.js.map |
@@ -1,2 +0,2 @@ | ||
import { ValidationResult, Schema, IConstraintBuilder, ISchemaBuilder, IConstraintManager } from '../model/schema'; | ||
import { ValidationResult, Schema, IConstraintBuilder, IConstraintManager } from '../model/schema'; | ||
import { FormatCollection } from './formatCollection'; | ||
@@ -10,7 +10,7 @@ import { ISchemaManager } from 'schema-manager'; | ||
export declare class Jemv { | ||
private built; | ||
private formats; | ||
private builder; | ||
private constraints; | ||
private schemas; | ||
constructor(formats: FormatCollection, constraints: IConstraintManager, builder: ISchemaBuilder, schemas: ISchemaManager); | ||
constructor(formats: FormatCollection, constraints: IConstraintManager, schemas: ISchemaManager); | ||
private static _instance; | ||
@@ -24,3 +24,4 @@ static get instance(): Jemv; | ||
normalize(schema: Schema): Schema; | ||
validate(value: string | Schema, data: any): Promise<ValidationResult>; | ||
validate(value: string | Schema, data: any): ValidationResult; | ||
private buildConstraint; | ||
} |
@@ -21,8 +21,7 @@ "use strict"; | ||
const constraints = new _1.ConstraintManager(); | ||
const builder = new _1.SchemaBuilder(constraints); | ||
this.addCoreFormats(formats); | ||
this.addCoreConstraintsBuilder(constraints, formats, schema_manager_1.schemas); | ||
return new Jemv(formats, constraints, builder, schema_manager_1.schemas); | ||
return new Jemv(formats, constraints, schema_manager_1.schemas); | ||
} | ||
addCoreConstraintsBuilder(constraints, formats, manager) { | ||
addCoreConstraintsBuilder(constraints, formats, schemas) { | ||
constraints.addBuilder(new constraintBuilders_1.ItemsConstraintBuilder(constraints)); | ||
@@ -35,3 +34,3 @@ constraints.addBuilder(new constraintBuilders_1.PropertiesConstraintBuilder(constraints)); | ||
constraints.addBuilder(new constraintBuilders_1.UniqueItemsConstraintBuilder()); | ||
constraints.addBuilder(new constraintBuilders_1.RefConstraintBuilder(manager, constraints)); | ||
constraints.addBuilder(new constraintBuilders_1.RefConstraintBuilder(schemas, constraints)); | ||
constraints.addBuilder(new constraintBuilders_1.MinMaxPropertiesConstraintBuilder()); | ||
@@ -44,3 +43,3 @@ constraints.addBuilder(new constraintBuilders_1.MinMaxItemsConstraintBuilder()); | ||
constraints.addBuilder(new constraintBuilders_1.PatternConstraintBuilder()); | ||
constraints.addBuilder(new constraintBuilders_1.PatternPropertyConstraintBuilder(constraints)); | ||
// constraints.addBuilder(new PatternPropertyConstraintBuilder(constraints)) | ||
constraints.addBuilder(new constraintBuilders_1.ContainsConstraintBuilder(constraints)); | ||
@@ -80,6 +79,6 @@ constraints.addBuilder(new constraintBuilders_1.ConstConstraintBuilder()); | ||
class Jemv { | ||
constructor(formats, constraints, builder, schemas) { | ||
constructor(formats, constraints, schemas) { | ||
this.built = {}; | ||
this.formats = formats; | ||
this.constraints = constraints; | ||
this.builder = builder; | ||
this.schemas = schemas; | ||
@@ -114,11 +113,34 @@ } | ||
validate(value, data) { | ||
return __awaiter(this, void 0, void 0, function* () { | ||
if (data === undefined) { | ||
return { valid: false, errors: [{ path: '.', message: 'data is empty' }] }; | ||
if (data === undefined) { | ||
return { valid: false, errors: [{ path: '.', message: 'data is empty' }] }; | ||
} | ||
const schema = this.schemas.solve(value); | ||
const constraint = this.buildConstraint(schema); | ||
const errors = constraint ? constraint.eval(data, '.') : []; | ||
return { valid: errors.length === 0, errors: errors }; | ||
} | ||
buildConstraint(schema) { | ||
if (schema === undefined || schema === null) { | ||
throw new Error('schema is empty'); | ||
} | ||
// get a key that uniquely identifies a schema | ||
const key = schema.$id ? schema.$id : _1.Helper.obj.createKey(schema); | ||
// look for the schema in the cache list | ||
let builded = this.built[key]; | ||
if (builded === undefined) { | ||
// if it doesn't exist in cache, add it | ||
if (typeof schema === 'object') { | ||
builded = { $id: schema.$id }; | ||
// this.addDef(builded, schema) | ||
} | ||
const schema = this.schemas.solve(value); | ||
const builded = yield this.builder.build(schema); | ||
const errors = builded.constraint ? yield builded.constraint.eval(data, '.') : []; | ||
return { valid: errors.length === 0, errors: errors }; | ||
}); | ||
else if (typeof schema === 'boolean') { | ||
builded = {}; | ||
} | ||
else { | ||
throw new Error(`Schema ${schema} is invalid`); | ||
} | ||
builded.constraint = this.constraints.build(schema, schema); | ||
this.built[key] = builded; | ||
} | ||
return builded.constraint; | ||
} | ||
@@ -125,0 +147,0 @@ } |
@@ -74,4 +74,2 @@ import { Schema as SchemaBase } from 'schema-manager'; | ||
else?: Schema; | ||
$id2?: string; | ||
$ref2?: string; | ||
} | ||
@@ -87,3 +85,3 @@ export interface EvalError { | ||
export interface IConstraint { | ||
eval(value: any, path: string): Promise<EvalError[]>; | ||
eval(value: any, path: string): EvalError[]; | ||
} | ||
@@ -96,10 +94,7 @@ export interface BuildedSchema { | ||
apply(rule: Schema): boolean; | ||
build(root: Schema, rule: Schema): Promise<IConstraint>; | ||
build(root: Schema, rule: Schema): IConstraint; | ||
} | ||
export interface IConstraintManager { | ||
addBuilder(constraintBuilder: IConstraintBuilder): any; | ||
build(root: Schema, rule: Schema): Promise<IConstraint | undefined>; | ||
build(root: Schema, rule: Schema): IConstraint | undefined; | ||
} | ||
export interface ISchemaBuilder { | ||
build(schema: Schema): Promise<BuildedSchema>; | ||
} |
{ | ||
"name": "jemv", | ||
"version": "0.1.3", | ||
"version": "0.1.4", | ||
"description": "Json Schema validator", | ||
@@ -20,4 +20,4 @@ "author": "Flavio Lionel Rita <flaviolrita@hotmail.com>", | ||
"dependencies": { | ||
"h3lp": "^0.0.10", | ||
"schema-manager": "^0.0.4" | ||
"h3lp": "^0.1.8", | ||
"schema-manager": "0.1.0" | ||
}, | ||
@@ -24,0 +24,0 @@ "keywords": [ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
125670
33
1556
+ Addedh3lp@0.1.11(transitive)
+ Addedschema-manager@0.1.0(transitive)
- Removedh3lp@0.0.10(transitive)
- Removedschema-manager@0.0.4(transitive)
Updatedh3lp@^0.1.8
Updatedschema-manager@0.1.0