claire-framework
Version:
- được viết bằng TypeScript - hỗ trợ websocket và HTTP request - hỗ trợ CLI để generate base project (claire-cli)
201 lines • 18.6 kB
JavaScript
;
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
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 });
const AbstractDataValidator_1 = require("../validator/AbstractDataValidator");
const errors_1 = require("../system/errors");
const DataType_1 = require("../enum/DataType");
const AbstractLogger_1 = require("../logger/AbstractLogger");
const core_1 = require("../decorator/core");
class DefaultDataValidator extends AbstractDataValidator_1.AbstractDataValidator {
constructor() {
super();
}
validate(meta, data, strictTypeCheck) {
return __awaiter(this, void 0, void 0, function* () {
// this.logger.debug("validating", meta, data);
if (!meta || !meta.needValidate) {
return true;
}
let validationReport = [];
let dataKeys = Object.keys(data || {});
//-- check if keys are allowed
dataKeys.forEach((key) => {
if (!meta.getFieldByLogicName(key)) {
//-- this field is not allowed
validationReport.push({ field: key, message: errors_1.FIELD_NOT_ALLOWED });
}
});
if (validationReport.length) {
return validationReport;
}
meta.fields.forEach((field) => {
let value = data[field.fieldLogicName];
//-- parsing data
if ((!field.nullable && field.defaultValue === undefined) || (value !== null && value !== undefined)) {
switch (field.dataType) {
case DataType_1.DataType.ARRAY: {
if (!Array.isArray(value)) {
if (strictTypeCheck) {
validationReport.push({
field: field.fieldLogicName,
message: errors_1.DATA_TYPE_ERROR
});
break;
}
else if (typeof value === "string") {
//-- try parse
try {
value = JSON.parse(value);
if (!Array.isArray(value)) {
validationReport.push({
field: field.fieldLogicName,
message: errors_1.DATA_TYPE_ERROR
});
break;
}
}
catch (err) {
//-- error parsing
validationReport.push({
field: field.fieldLogicName,
message: errors_1.DATA_TYPE_ERROR
});
break;
}
}
}
if (!field.allowEmptyArray && (!value || !value.length)) {
validationReport.push({
field: field.fieldLogicName,
message: errors_1.EMPTINESS_NOT_ALLOWED
});
break;
}
data[field.fieldLogicName] = value;
break;
}
case DataType_1.DataType.STRING:
//-- small "s"
if (strictTypeCheck && typeof value !== "string") {
validationReport.push({
field: field.fieldLogicName,
message: errors_1.DATA_TYPE_ERROR
});
break;
}
data[field.fieldLogicName] = String(value);
break;
case DataType_1.DataType.BOOL:
// @ts-ignore
if (!(strictTypeCheck && [true, false].includes(value)) && !(!strictTypeCheck && [true, false, "true", "false"].includes(value))) {
validationReport.push({
field: field.fieldLogicName,
message: errors_1.DATA_TYPE_ERROR
});
break;
}
data[field.fieldLogicName] = value === true || value === "true";
break;
case DataType_1.DataType.FLOAT:
case DataType_1.DataType.INTEGER:
// @ts-ignore
if ((isNaN(value) && (!field.nullable || value !== "undefined")) || (strictTypeCheck && typeof value !== "number")) {
validationReport.push({
field: field.fieldLogicName,
message: errors_1.DATA_TYPE_ERROR
});
break;
}
data[field.fieldLogicName] = value === "undefined" ? undefined : Number(value);
break;
default:
if (field.isFile && (!value.data)) {
validationReport.push({
field: field.fieldLogicName,
message: errors_1.FILE_EXPECTED
});
}
break;
}
}
//-- if parsing success then continue to validate the value
if (!validationReport.length) {
if (!field.nullable && field.defaultValue === undefined && (value === undefined || value === null || (value === '' && [DataType_1.DataType.STRING, DataType_1.DataType.TEXT].includes(field.dataType)))) {
validationReport.push({ field: field.fieldLogicName, message: errors_1.FIELD_REQUIRED });
}
if (value !== null && value !== undefined) {
if (field.match) {
let regex = new RegExp(field.match);
if (!regex.exec(value)) {
validationReport.push({
field: field.fieldLogicName,
message: errors_1.PATTERN_NOT_MATCHED
});
}
}
if (field.isInteger && parseInt(value) !== Number(value)) {
validationReport.push({
field: field.fieldLogicName,
message: errors_1.MUST_BE_INTEGER
});
}
if (field.lessThan !== undefined && value >= field.lessThan) {
validationReport.push({
field: field.fieldLogicName,
message: errors_1.VALUE_NOT_IN_RANGE
});
}
if (field.greaterThan !== undefined && value <= field.greaterThan) {
validationReport.push({
field: field.fieldLogicName,
message: errors_1.VALUE_NOT_IN_RANGE
});
}
if (field.inRange !== undefined && ((value < field.inRange.from) || (value > field.inRange.to))) {
validationReport.push({
field: field.fieldLogicName,
message: errors_1.VALUE_NOT_IN_RANGE
});
}
if (field.inSet !== undefined && (!field.inSet.indexOf || field.inSet.indexOf(value) < 0)) {
validationReport.push({
field: field.fieldLogicName,
message: errors_1.VALUE_OUT_OF_SET
});
}
if (field.subSet !== undefined && (value.some((v) => field.subSet.indexOf(v) < 0))) {
validationReport.push({
field: field.fieldLogicName,
message: errors_1.VALUE_IS_NOT_SUBSET
});
}
}
}
});
return validationReport.length ? validationReport : true;
});
}
}
__decorate([
core_1.Inject(),
__metadata("design:type", AbstractLogger_1.AbstractLogger)
], DefaultDataValidator.prototype, "logger", void 0);
exports.DefaultDataValidator = DefaultDataValidator;
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiRGVmYXVsdERhdGFWYWxpZGF0b3IuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9saWIvZGVmYXVsdC1pbXBsZW1lbnRhdGlvbnMvRGVmYXVsdERhdGFWYWxpZGF0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7QUFBQSw4RUFBeUU7QUFHekUsNkNBVzBCO0FBQzFCLCtDQUEwQztBQUMxQyw2REFBd0Q7QUFDeEQsNENBQXlDO0FBRXpDLE1BQWEsb0JBQXFCLFNBQVEsNkNBQXFCO0lBSzNEO1FBQ0ksS0FBSyxFQUFFLENBQUM7SUFDWixDQUFDO0lBRVksUUFBUSxDQUFDLElBQW1CLEVBQUUsSUFBUyxFQUFFLGVBQXdCOztZQUUxRSwrQ0FBK0M7WUFFL0MsSUFBSSxDQUFDLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxZQUFZLEVBQUU7Z0JBQzdCLE9BQU8sSUFBSSxDQUFDO2FBQ2Y7WUFFRCxJQUFJLGdCQUFnQixHQUF1QixFQUFFLENBQUM7WUFDOUMsSUFBSSxRQUFRLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLElBQUksRUFBRSxDQUFDLENBQUM7WUFFdkMsOEJBQThCO1lBQzlCLFFBQVEsQ0FBQyxPQUFPLENBQUMsQ0FBQyxHQUFHLEVBQUUsRUFBRTtnQkFDckIsSUFBSSxDQUFDLElBQUksQ0FBQyxtQkFBbUIsQ0FBQyxHQUFHLENBQUMsRUFBRTtvQkFDaEMsOEJBQThCO29CQUM5QixnQkFBZ0IsQ0FBQyxJQUFJLENBQUMsRUFBQyxLQUFLLEVBQUUsR0FBRyxFQUFFLE9BQU8sRUFBRSwwQkFBaUIsRUFBQyxDQUFDLENBQUM7aUJBQ25FO1lBQ0wsQ0FBQyxDQUFDLENBQUM7WUFFSCxJQUFJLGdCQUFnQixDQUFDLE1BQU0sRUFBRTtnQkFDekIsT0FBTyxnQkFBZ0IsQ0FBQzthQUMzQjtZQUVELElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLENBQUMsS0FBSyxFQUFFLEVBQUU7Z0JB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