diff --git a/packages/core/src/lib/initialize-utils/get-path-recursive.util.ts b/packages/core/src/lib/initialize-utils/get-path-recursive.util.ts index 8a741b2c1..225158937 100644 --- a/packages/core/src/lib/initialize-utils/get-path-recursive.util.ts +++ b/packages/core/src/lib/initialize-utils/get-path-recursive.util.ts @@ -1,5 +1,20 @@ import { uniquePaths } from '../utils'; +const EXCLUDE_KEYS = [ + 'constructor', + '__defineGetter__', + '__defineSetter__', + 'hasOwnProperty', + '__lookupGetter__', + '__lookupSetter__', + 'isPrototypeOf', + 'propertyIsEnumerable', + 'toString', + 'valueOf', + '__proto__', + 'toLocaleString', +]; + /** * Loop through an object and recursively get paths of each property * @@ -19,7 +34,17 @@ export function getPathRecursive( const result = prev; let hadChildPaths = false; - const keys = Object.getOwnPropertyNames(node); + const ownPropertyNames = Object.getOwnPropertyNames(node); + const prototype = Object.getPrototypeOf(node); + const prototypeOwnPropertyNames = prototype + ? Object.keys(Object.getOwnPropertyDescriptors(prototype)).filter( + (key) => !EXCLUDE_KEYS.includes(key) + ) + : []; + + const keys = Array.from( + new Set([...ownPropertyNames, ...prototypeOwnPropertyNames]) + ); for (let i = 0, len = keys.length; i < len; i++) { const key = keys[i]; const path: string[] = [...prefix, key]; diff --git a/packages/core/src/lib/initialize-utils/specs/get-path-recursive.spec.ts b/packages/core/src/lib/initialize-utils/specs/get-path-recursive.spec.ts index 06592ec55..b45b8d9fa 100644 --- a/packages/core/src/lib/initialize-utils/specs/get-path-recursive.spec.ts +++ b/packages/core/src/lib/initialize-utils/specs/get-path-recursive.spec.ts @@ -23,6 +23,10 @@ describe('getPathRecursive', () => { ['.startDot']: undefined, ['endDot.']: undefined, }, + _privateFoo: undefined, + get privateFoo() { + return this._privateFoo; + }, }; const resultPaths = [ @@ -36,6 +40,8 @@ describe('getPathRecursive', () => { ['mid.Dot'], ['mid.Dot', '.startDot'], ['mid.Dot', 'endDot.'], + ['_privateFoo'], + ['privateFoo'], ]; it('should work', () => { diff --git a/packages/integration-test/src/lib/with-classes/variants.spec.ts b/packages/integration-test/src/lib/with-classes/variants.spec.ts index 703734979..5fdb2d7b5 100644 --- a/packages/integration-test/src/lib/with-classes/variants.spec.ts +++ b/packages/integration-test/src/lib/with-classes/variants.spec.ts @@ -27,6 +27,18 @@ describe('Variants', () => { expect(vm.fullName).toEqual(user.firstName + ' ' + user.lastName); }); + it('should map back to model with getters', () => { + mapper.createMap(SimpleUserVm, UserWithGetter); + + const simpleUser = new SimpleUserVm(); + simpleUser.firstName = 'Chau'; + simpleUser.lastName = 'Tran'; + + const user = mapper.map(simpleUser, UserWithGetter, SimpleUserVm); + expect(user.firstName).toEqual(simpleUser.firstName); + expect(user.lastName).toEqual(simpleUser.lastName); + }); + it('should map with model with ONLY getters', () => { mapper.createMap(UserWithOnlyGetter, SimpleUserVm).forMember( (d) => d.fullName,