@decaf-ts/db-decorators
Version:
Agnostic database decorators and repository
128 lines (127 loc) • 6.13 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.validateCompare = validateCompare;
const decorator_validation_1 = require("@decaf-ts/decorator-validation");
const reflection_1 = require("@decaf-ts/reflection");
const validation_1 = require("../validation/index.cjs");
const identity_1 = require("../identity/index.cjs");
/**
* @summary Validates the update of a model
*
* @param {T} oldModel
* @param {T} newModel
* @param {string[]} [exceptions]
*
* @function validateCompare
* @return {ModelErrorDefinition | undefined}
*
* @memberOf module:db-decorators.Model
*/
function validateCompare(oldModel, newModel, ...exceptions) {
const decoratedProperties = [];
for (const prop in newModel)
if (Object.prototype.hasOwnProperty.call(newModel, prop) &&
exceptions.indexOf(prop) === -1)
decoratedProperties.push(reflection_1.Reflection.getPropertyDecorators(validation_1.UpdateValidationKeys.REFLECT, newModel, prop));
let result = undefined;
for (const decoratedProperty of decoratedProperties) {
const { prop, decorators } = decoratedProperty;
decorators.shift(); // remove the design:type decorator, since the type will already be checked
if (!decorators || !decorators.length)
continue;
let errs = undefined;
for (const decorator of decorators) {
const validator = decorator_validation_1.Validation.get(decorator.key);
if (!validator) {
console.error(`Could not find Matching validator for ${decorator.key} for property ${String(decoratedProperty.prop)}`);
continue;
}
const err = validator.updateHasErrors(newModel[prop.toString()], oldModel[prop.toString()], ...Object.values(decorator.props));
if (err) {
errs = errs || {};
errs[decorator.key] = err;
}
}
if (errs) {
result = result || {};
result[decoratedProperty.prop.toString()] = errs;
}
}
// tests nested classes
for (const prop of Object.keys(newModel).filter((k) => {
if (exceptions.includes(k))
return false;
return !result || !result[k];
})) {
let err;
// if a nested Model
const allDecorators = reflection_1.Reflection.getPropertyDecorators(decorator_validation_1.ValidationKeys.REFLECT, newModel, prop).decorators;
const decorators = reflection_1.Reflection.getPropertyDecorators(decorator_validation_1.ValidationKeys.REFLECT, newModel, prop).decorators.filter((d) => [decorator_validation_1.ModelKeys.TYPE, decorator_validation_1.ValidationKeys.TYPE].indexOf(d.key) !== -1);
if (!decorators || !decorators.length)
continue;
const dec = decorators.pop();
const clazz = dec.props.name
? [dec.props.name]
: Array.isArray(dec.props.customTypes)
? dec.props.customTypes
: [dec.props.customTypes];
const reserved = Object.values(decorator_validation_1.ReservedModels).map((v) => v.toLowerCase());
for (const c of clazz) {
if (reserved.indexOf(c.toLowerCase()) === -1) {
switch (c) {
case Array.name:
case Set.name:
if (allDecorators.length) {
const listDec = allDecorators.find((d) => d.key === decorator_validation_1.ValidationKeys.LIST);
if (listDec) {
let currentList, oldList;
switch (c) {
case Array.name:
currentList = newModel[prop];
oldList = oldModel[prop];
break;
case Set.name:
currentList = newModel[prop].values();
oldList = oldModel[prop].values();
break;
default:
throw new Error(`Invalid attribute type ${c}`);
}
err = currentList
.map((v) => {
const id = (0, identity_1.findModelId)(v, true);
if (!id)
return "Failed to find model id";
const oldModel = oldList.find((el) => id === (0, identity_1.findModelId)(el, true));
if (!oldModel)
return; // nothing to compare with
return v.hasErrors(oldModel);
})
.filter((e) => !!e);
if (!err?.length) {
// if the result is an empty list...
err = undefined;
}
}
}
break;
default:
try {
if (newModel[prop] &&
oldModel[prop])
err = newModel[prop].hasErrors(oldModel[prop]);
// eslint-disable-next-line @typescript-eslint/no-unused-vars
}
catch (e) {
console.warn((0, decorator_validation_1.sf)("Model should be validatable but its not"));
}
}
}
if (err) {
result = result || {};
result[prop] = err;
}
}
}
return result ? new decorator_validation_1.ModelErrorDefinition(result) : undefined;
}