UNPKG

@decaf-ts/db-decorators

Version:

Agnostic database decorators and repository

128 lines (127 loc) 6.13 kB
"use strict"; 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; }