vulcain-corejs
Version:
Vulcain micro-service framework
207 lines (205 loc) • 9.45 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
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) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments)).next());
});
};
class Validator {
constructor(domain, container) {
this.domain = domain;
this.container = container;
}
validateAsync(ctx, schemaDesc, val) {
return __awaiter(this, void 0, void 0, function* () {
let errors = [];
if (!schemaDesc || !val)
return errors;
if (schemaDesc.extends) {
let base = this.domain.resolveSchemaDescription(schemaDesc.extends);
if (base) {
(yield this.validateAsync(ctx, base, val)).forEach(e => { errors.push(e); });
}
}
let id = val && val[this.domain.getIdProperty(schemaDesc)];
let formatContext = { element: val, schemaElement: schemaDesc, id: id };
// Properties checks
for (const ps in schemaDesc.properties) {
if (!schemaDesc.properties.hasOwnProperty(ps))
continue;
formatContext.propertyName = ps;
formatContext.propertySchema = schemaDesc.properties[ps];
formatContext.propertyValue = val[ps];
try {
let err = yield this.validatePropertyAsync(ctx, formatContext, schemaDesc.properties[ps], val[ps], val);
if (err) {
errors.push({ message: err, property: ps, id: formatContext.id });
}
}
catch (e) {
errors.push({ message: this.__formatMessage("Validation error for property {$propertyName} : " + e, formatContext), id: formatContext.id, property: ps });
}
}
// References checks
for (const rs in schemaDesc.references) {
if (!schemaDesc.references.hasOwnProperty(rs))
continue;
formatContext.propertyName = rs;
formatContext.propertySchema = schemaDesc.references[rs];
formatContext.propertyValue = val[rs];
try {
let ref = schemaDesc.references[rs];
if (ref.item === "any" && formatContext.propertyValue && formatContext.propertyValue.__schema) {
if (ref && ref.dependsOn && !ref.dependsOn(val))
continue;
let schema = this.domain.getSchema(formatContext.propertyValue.__schema);
if (!schema)
continue;
errors = errors.concat(yield this.validateAsync(ctx, schema.description, formatContext.propertyValue));
}
else {
let errors2 = yield this.validateReferenceAsync(ctx, formatContext, ref, val[rs], val);
if (errors2)
errors = errors.concat(errors2);
}
}
catch (e) {
errors.push({ message: this.__formatMessage("Validation error for reference {$propertyName} : " + e, formatContext), id: formatContext.id, property: rs });
}
}
// Entity check
if (schemaDesc.validate) {
formatContext.propertyName = formatContext.propertySchema = formatContext.propertyValue = null;
try {
let err = yield schemaDesc.validate(val, ctx);
if (err)
errors.push({ message: this.__formatMessage(err, formatContext, schemaDesc), id: formatContext.id });
}
catch (e) {
errors.push({ message: this.__formatMessage("Validation error for element {__schema} : " + e, formatContext), id: formatContext.id });
}
}
return errors;
});
}
validateReferenceAsync(ctx, formatContext, schema, val, entity) {
return __awaiter(this, void 0, void 0, function* () {
if (!schema)
return;
if (schema.dependsOn && !schema.dependsOn(entity))
return;
if (!val) {
if (schema.required) {
return [{
message: this.__formatMessage("Reference '{$propertyName}' is required.", formatContext, schema),
id: formatContext.id,
property: formatContext.propertyName
}];
}
return null;
}
if (schema.validators) {
for (let validator of schema.validators) {
let msg = validator.validate && (yield validator.validate(val, ctx));
if (msg)
return [{
message: this.__formatMessage(msg, formatContext, schema),
id: formatContext.id,
property: formatContext.propertyName
}];
}
}
let err = schema.validate && (yield schema.validate(val, ctx));
if (err)
return [err];
let values = schema.cardinality === "one" ? [val] : val;
let baseItemSchema = schema.item && schema.item !== "any" && this.domain.getSchema(schema.item, true);
let errors = [];
for (let val of values) {
if (val) {
let currentItemSchema = baseItemSchema;
if (val.__schema && (!currentItemSchema || val.__schema !== currentItemSchema.name)) {
currentItemSchema = this.domain.getSchema(val.__schema, true);
if (!baseItemSchema)
baseItemSchema = currentItemSchema;
}
if (currentItemSchema) {
errors = errors.concat(yield this.validateAsync(ctx, currentItemSchema.description, val));
}
}
}
return errors;
});
}
validatePropertyAsync(ctx, formatContext, schema, val, entity) {
return __awaiter(this, void 0, void 0, function* () {
if (typeof schema === "string") {
let type = this.domain._findType(schema);
if (!type) {
return null;
}
schema = type;
}
if (schema.dependsOn && !schema.dependsOn(entity))
return;
if (val === undefined || val === null) {
if (schema.required) {
return this.__formatMessage("Property '{$propertyName}' is required.", formatContext, schema);
}
return null;
}
if (schema.validators) {
for (let validator of schema.validators) {
let err = validator.validate && (yield validator.validate(val, ctx));
if (err)
return this.__formatMessage(err, formatContext, validator);
}
}
if (schema.validate) {
let err = yield schema.validate(val, ctx);
if (err)
return this.__formatMessage(err, formatContext, schema);
}
});
}
/**
* Format an error message
* @param message
* @param ctx
* @returns {string}
* @private
*/
__formatMessage(message, ctx, validator) {
const regex = /{\s*([^}\s]*)\s*}/g;
return message.replace(regex, function (match, name) {
switch (name) {
case "$value":
return ctx.propertyValue;
case "$schema":
return ctx.propertyName ? ctx.propertySchema : ctx.schemaElement;
case "$id":
return ctx.id;
case "$propertyName":
return ctx.propertyName;
default:
if (!name)
return null;
// Name beginning with $ belongs to schema
if (name[0] === "$" && validator) {
let p = validator[name] || validator[name.substring(1)];
return (typeof p === "function" && p(validator)) || p;
}
// Else it's an element's property
if (ctx.element) {
let p = ctx.element[name];
return (typeof p === "function" && p(ctx.element)) || p;
}
return null;
}
});
}
}
exports.Validator = Validator;
//# sourceMappingURL=validator.js.map