import { AnyJson } from '~/types/interfaces' /** * @category Services/utils * @class ObjectProperties * Classe aidant à manipuler des Objets */ class ObjectProperties { /** * Flatten un objet nested en un objet avec un seul niveau avec des noms de propriétés transformées comme cela 'foo.bar' * L'objet passé en paramètre reste inchangé car il est cloné * @example cloneAndFlatten({ a: 1, b: { c: 2 }, d: { e: 3, f: { g: 4, h: 5 } }, i: { j: 6 } }, ['i']) => { a: 1, 'b.c': 2, 'd.e': 3, 'd.f.g': 4, 'd.f.h': 5, i: { j: 6 } } } * @param {AnyJson} object * @param {Array} excludedProperties * @param excludedProperties * @return {AnyJson} */ cloneAndFlatten (object: AnyJson, excludedProperties: Array = []): AnyJson { if (typeof object !== 'object') { throw new TypeError('Expecting an object parameter') } return Object.keys(object).reduce( (values: AnyJson, name: string) => { if (!object.hasOwnProperty(name)) { return values } if (this.isObject(object[name])) { if (!excludedProperties.includes(name)) { const flatObject = this.cloneAndFlatten(object[name]) Object.keys(flatObject).forEach((flatObjectKey) => { if (!flatObject.hasOwnProperty(flatObjectKey)) { return } values[name + '.' + flatObjectKey] = flatObject[flatObjectKey] }) } else { values[name] = this.clone(object[name]) } } else { values[name] = object[name] } return values }, {} ) }; /** * Transforme un objet flattened en un objet nested. L'objet passé en paramètre reste inchangé * @example cloneAndNest({ a: 1, 'b.c': 2, 'd.e': 3, 'd.f.g': 4, 'd.f.h': 5 } ) => { a: 1, b: { c: 2 }, d: { e: 3, f: { g: 4, h: 5 } } } * @param {AnyJson} object * @return {AnyJson} */ cloneAndNest (object: AnyJson): AnyJson { if (typeof object !== 'object') { throw new TypeError('Expecting an object parameter') } return Object.keys(object).reduce((values, name) => { if (!object.hasOwnProperty(name)) { return values } name.split('.').reduce((previous: AnyJson, current: string, index: number, list: Array) => { if (previous != null) { if (typeof previous[current] === 'undefined') { previous[current] = {} } if (index < (list.length - 1)) { return previous[current] } previous[current] = object[name] } }, values) return values }, {}) } /** * Teste si le paramètre est un objet * @param {AnyJson} value * @return {boolean} */ isObject (value: any): boolean { return value !== null && typeof value === 'object' && !Array.isArray(value) && Object.prototype.toString.call(value) !== '[object Date]' } /** * Clône l'objet et ses propriétés. * @param {Object} object * @return {Object} */ clone (object: AnyJson): AnyJson { return Object.keys(object).reduce((values: AnyJson, name: string) => { if (object.hasOwnProperty(name)) { values[name] = object[name] } return values }, {}) } /** * Tri un objet par rapport à ses clés (par ordre alpha) * @example sortObjectByKey({b:1, d:2, c:3, a:4}) => {a:4, b:1, c:3, d:2} * @param toSort */ sortObjectByKey (toSort: any): any { if (typeof toSort !== 'object') { throw new TypeError('Expecting an object parameter') } return Object.keys(toSort).sort().reduce( (obj:any, key:string) => { obj[key] = toSort[key] return obj }, {} ) } } export const $objectProperties = new ObjectProperties()