UNPKG

rich-domain

Version:

This package provide utils file and interfaces to assistant build a complex application with domain driving design

206 lines 9.45 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.AutoMapper = void 0; const utils_1 = require("../utils"); /** * @description The AutoMapper class is responsible for transforming domain resources (entities, value objects) * into plain objects or primitive values. It provides methods to recursively process nested value objects, IDs, * entities, and arrays, ensuring all complex data structures are serialized into a consistent object format. */ class AutoMapper { validator = utils_1.Validator.create(); /** * @description Converts a value object into a plain object or a primitive value. * This method handles multiple scenarios, including: * - Null values * - Symbol values * - ID values * - Simple data types (strings, numbers, booleans, dates, objects) * - Nested value objects * - Arrays containing complex data * @param valueObject An instance representing a value object to be transformed. * @returns A plain object, primitive value, or serialized structure derived from the given value object. */ valueObjectToObj(valueObject) { // Handle null or special cases if (valueObject === null) return null; if (typeof valueObject === 'undefined') return undefined; if (this.validator.isSymbol(valueObject)) return valueObject.description; if (this.validator.isID(valueObject)) return valueObject?.value(); // Check if the object is a simple value (e.g., boolean, number, string, date) const isSimpleValue = this.validator.isBoolean(valueObject) || this.validator.isNumber(valueObject) || this.validator.isString(valueObject) || this.validator.isDate(valueObject); const isSimpleObject = this.validator.isObject(valueObject); // check each object key-value if (isSimpleObject) { let result = {}; const keys = Object.keys(valueObject); keys.forEach((key) => { const value = this.entityToObj(valueObject[key]); result = { ...result, [key]: value }; }); return result; } if (isSimpleValue) return valueObject; // At this point, treat it as a potential value object with props const voProps = valueObject?.['props']; const isSimpleProp = this.validator.isBoolean(voProps) || this.validator.isNumber(voProps) || this.validator.isString(voProps) || this.validator.isDate(voProps); if (isSimpleProp) return voProps; if (this.validator.isSymbol(voProps)) { return voProps.description; } if (this.validator.isArray(valueObject)) { const result = Object.keys(valueObject).map((key) => { return this.valueObjectToObj(valueObject[key]); }); return result; } // If voProps is an object, recursively convert each property if (this.validator.isObject(voProps)) { const keys = Object.keys(voProps); const values = keys.map((key) => { const isVo = this.validator.isValueObject(voProps?.[key]); if (isVo) return this.valueObjectToObj(voProps?.[key]); const isSimpleValue = this.validator.isBoolean(voProps?.[key]) || this.validator.isNumber(voProps?.[key]) || this.validator.isString(voProps?.[key]) || this.validator.isObject(voProps?.[key]) || this.validator.isDate(voProps?.[key]) || voProps?.[key] === null; if (isSimpleValue) return voProps?.[key]; if (this.validator.isSymbol(voProps?.[key])) return voProps?.[key]?.description; const isID = this.validator.isID(voProps?.[key]); if (isID) return (voProps?.[key]).value(); const isArray = this.validator.isArray(voProps?.[key]); if (isArray) { const arr = voProps?.[key]; const results = []; arr.forEach((data) => { const result = this.valueObjectToObj(data); results.push(result); }); return results; } }); // If props are array-like, return as an array of values; otherwise, rebuild as an object if (this.validator.isArray(voProps)) return values; let props = {}; values.forEach((value, i) => { props = Object.assign({}, { ...props }, { [keys[i]]: value }); }); return props; } return this.entityToObj(voProps); } /** * @description Transforms an entity into a plain object, including its associated meta properties * (`id`, `createdAt`, `updatedAt`). This method: * - Resolves IDs to their primitive value forms. * - Recursively converts nested entities, aggregates, and value objects to plain objects. * - Preserves arrays and transforms their elements as needed. * @param entity The entity instance to be transformed into a plain object. * @returns A plain object representing the entity, including its metadata and serialized properties. */ entityToObj(entity) { if (this.validator.isID(entity)) return entity?.value(); if (this.validator.isSymbol(entity)) return entity?.description; let result = {}; const isEntity = this.validator.isEntity(entity); const isAggregate = this.validator.isAggregate(entity); const props = entity?.['props'] ?? {}; const isValueObject = this.validator.isValueObject(entity); // If it's a value object return calling conversion if (isValueObject) return this.valueObjectToObj(entity); const isSimpleValue = this.validator.isBoolean(entity) || this.validator.isNumber(entity) || this.validator.isString(entity) || this.validator.isDate(entity) || entity === null; // If it's a simple value or a value object, directly convert if (isSimpleValue) return entity; const isSimpleObject = this.validator.isObject(entity); // check each object key-value if (isSimpleObject) { let result = {}; const keys = Object.keys(entity); keys.forEach((key) => { const value = this.entityToObj(entity[key]); result = { ...result, [key]: value }; }); return result; } if (this.validator.isArray(entity)) { const result = Object.keys(entity).map((key) => { return this.valueObjectToObj(entity[key]); }); return result; } // If it's an entity or an aggregate, extract meta properties and iterate over its props if (isEntity || isAggregate) { const id = entity?.id?.value(); const createdAt = entity['props']['createdAt']; const updatedAt = entity['props']['updatedAt']; result = Object.assign({}, { ...result }, { id, createdAt, updatedAt }); const keys = Object.keys(props); keys.forEach((key) => { const value = props[key]; const isArray = this.validator.isArray(value); // Handle IDs if (this.validator.isID(value)) { result = Object.assign({}, { ...result }, { [key]: value?.value() }); } // Handle arrays if (isArray) { const arr = value ?? []; const subProps = arr.map((item) => this.entityToObj(item)); result = Object.assign({}, { ...result }, { [key]: subProps }); } // Check if it's simple or a nested entity/value object const isSimple = this.validator.isValueObject(value) || this.validator.isBoolean(value) || this.validator.isNumber(value) || this.validator.isString(value) || this.validator.isObject(value) || this.validator.isDate(value) || value === null; const isEntity = this.validator.isEntity(value); if (isEntity) { const data = this.entityToObj(value); result = Object.assign({}, { ...result }, { [key]: data }); } else if (isSimple) { const data = this.valueObjectToObj(value); result = Object.assign({}, { ...result }, { [key]: data }); } else if (this.validator.isSymbol(props)) { const description = props?.description ?? ''; result = { ...result, [key]: description }; } }); } return result; } } exports.AutoMapper = AutoMapper; exports.default = AutoMapper; //# sourceMappingURL=auto-mapper.js.map