UNPKG

mvom

Version:

Multivalue Object Mapper

206 lines (178 loc) 5.9 kB
"use strict"; var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault"); Object.defineProperty(exports, "__esModule", { value: true }); exports.default = void 0; var _lodash = require("lodash"); var _errors = require("../errors"); var _BaseSchemaType = _interopRequireDefault(require("./BaseSchemaType")); // #region Types // #endregion /** Abstract Scalar Schema Type */ class BaseScalarType extends _BaseSchemaType.default { /** Data definition which this schema type was constructed from */ /** 0-indexed Array path */ /** Multivalue dictionary id */ /** Required validation value for the schema type */ /** Indicates whether data should be encrypted/decrypted */ /** Encrypt function to call on sensitive data before writing to the database */ /** Decrypt function to call on sensitive data encrypted in the database */ /** Data transformer */ constructor(definition, { encrypt, decrypt } = {}) { super(); const { path, dictionary = null, required = false, encrypted = false } = definition; if (encrypted) { if (typeof encrypt !== 'function') { throw new _errors.InvalidParameterError({ message: 'Encrypt function required to process encrypted fields', parameterName: 'encrypt' }); } if (typeof decrypt !== 'function') { throw new _errors.InvalidParameterError({ message: 'Decrypt function required to process encrypted fields', parameterName: 'decrypt' }); } } this.definition = definition; this.dictionary = dictionary; this.path = this.normalizeMvPath(path); this.required = required; this.encrypted = encrypted; this.encrypt = encrypt; this.decrypt = decrypt; } /** Get value from mv data */ get(record) { const value = this.getFromMvData(record); return this.transformFromDb(value); } /** Transform into multivalue format and set specified value into mv record */ set(originalRecord, value) { return this.setIntoMvData(originalRecord, this.transformToDb(value)); } /** Transform from mv data to externally formatted data */ transformFromDb(value) { return this.dataTransformer.transformFromDb(value); } /** Transform from externally formatted data to mv data */ transformToDb(value) { return this.dataTransformer.transformToDb(value); } /** Transform query constants to the format schema */ transformToQuery(value) { return this.dataTransformer.transformToQuery(value); } /** Validate the scalar type */ validate(value) { const validators = this.validators.concat(this.createRequiredValidator(), this.createTypeValidator()); return validators.reduce((acc, { validationFn, message }) => { const isValid = validationFn(value); if (!isValid) { acc.push(message); } return acc; }, []); } /** Get data from the specified keypath */ getFromMvData(record) { const value = this.getFromMvArray(this.path, record); return this.decryptData(value); } /** Set specified value into mv record */ setIntoMvData(originalRecord, setValue) { const encryptedSetValue = this.encryptData(setValue); return (0, _lodash.set)((0, _lodash.cloneDeep)(originalRecord), this.path, encryptedSetValue); } /** Required validator */ validateRequired = value => !this.required || value != null; /** Type validator */ // eslint-disable-next-line @typescript-eslint/no-unused-vars validateType = value => true; /** Create validation object for required validation */ createRequiredValidator() { const message = 'Property is required'; return { validationFn: this.validateRequired, message }; } /** Create validation object for type validation */ createTypeValidator() { const message = 'Property cannot be cast into the defined type'; return { validationFn: this.validateType, message }; } /** * Convert a 1-index string array path definition (e.g. '1.1.1') to a 0-index array path definition (e.g. [0, 0, 0]) * @throws {@link InvalidParameterError} Path definition must be a string of integers split by periods */ normalizeMvPath(path) { return (0, _lodash.toPath)(path).slice(0, 3).map(val => { const numVal = +val; if (!Number.isInteger(numVal) || numVal < 1) { throw new _errors.InvalidParameterError({ message: 'Path definition must be a string of integers split by periods', parameterName: 'path' }); } return numVal - 1; }); } /** Encrypt a transformed property */ encryptData(data) { if (!this.encrypted) { return data; } if (Array.isArray(data)) { return data.map(value => { if (Array.isArray(value)) { return value.map(innerValue => this.encryptSingle(innerValue)); } return this.encryptSingle(value); }); } return this.encryptSingle(data); } /** Encrypt a single value */ encryptSingle(value) { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion return value == null ? value : this.encrypt(value); } /** Decrypt a multivalue attribute */ decryptData(data) { if (!this.encrypted) { return data; } if (Array.isArray(data)) { return data.map(value => { if (Array.isArray(value)) { return value.map(innerValue => this.decryptSingle(innerValue)); } return this.decryptSingle(value); }); } return this.decryptSingle(data); } /** Decrypt a single value */ decryptSingle(value) { // eslint-disable-next-line @typescript-eslint/no-non-null-assertion return typeof value !== 'string' ? value : this.decrypt(value); } } var _default = exports.default = BaseScalarType;