UNPKG

@northscaler/service-support

Version:

Artifacts that assist in writing service layers effectively

60 lines (51 loc) 3.17 kB
'use strict' const formatDate = require('../formatters/date-formatter') const formatEnumeration = require('../formatters/enumeration-formatter') const DateFormat = require('../enums/DateFormat') const Enumeration = require('@northscaler/enum-support') /** * Extracts a [data transfer object (DTO)](https://martinfowler.com/eaaCatalog/dataTransferObject.html) from the given entity. * The entity normally is an instance of a class with data properties whose names begin with the underscore character (`_`). * By default, this will descend recursively through the given object and drop the leading underscore prefix from its keys and convert any convertible values, mainly `Date`s to ISO-8601 strings and [`Enumeration` instances](https://www.npmjs.com/package/@northscaler/enum-support) to just their `name`s. * All methods found are excluded from the returned DTO. * Each formatter is customizable. * * @param {*} entity The entity from which to extract a data transfer object (DTO). * @param {object} arg1 The argument to be deconstructed. * @param {string|RegExp} [arg1.keyReplacementRegEx=/^_/] The key replacement regular expression given to the `replace` method of `String`; if falsey, no key replacement is performed. * @param {string|function} [arg1.keyReplacement=''] The key replacement given to the `replace` method of `String`. * @param {function} [arg1.dateFormatter] The formatter of `Date`s; defaults to `toISOString()` on `Date`. * @param {function} [arg1.enumerationFormatter] The formatter of [`Enumeration` instances](https://www.npmjs.com/package/@northscaler/enum-support); defaults to returning the `name`. */ function extractDtoFromEntity (entity, { keyReplacementRegEx = /^_/, keyReplacement = '', dateFormatter = date => formatDate({ date, format: DateFormat.ISO_8601 }), enumerationFormatter = enumeration => formatEnumeration({ enumeration, useName: true }) } = {}) { if (keyReplacementRegEx) keyReplacementRegEx = new RegExp(keyReplacementRegEx) function recurse (entity) { // makes the code below more readable return extractDtoFromEntity(entity, { keyReplacementRegEx, keyReplacement, dateFormatter, enumerationFormatter }) } if (!entity) return entity if (Array.isArray(entity)) return entity.map(it => recurse(it)) if (Enumeration.isEnumerationInstance(entity)) return enumerationFormatter(entity) if (typeof entity !== 'object') return entity return Object.keys(entity).reduce((dto, key) => { const newKey = keyReplacementRegEx ? key.replace(keyReplacementRegEx, keyReplacement) : key const type = typeof entity[key] if (!entity[key]) dto[newKey] = entity[key] else if (Array.isArray(entity[key])) dto[newKey] = entity[key].map(it => recurse(it)) else if (entity[key] instanceof Date) dto[newKey] = dateFormatter(entity[key]) else if (Enumeration.isEnumerationInstance(entity[key])) dto[newKey] = enumerationFormatter(entity[key]) else if (type === 'object') dto[newKey] = recurse(entity[key]) else if (type !== 'function') dto[newKey] = entity[key] // skip functions return dto }, {}) } module.exports = extractDtoFromEntity