Skip to content

Commit

Permalink
feat: allow to use pre-condition and condition on auto mapping pairs
Browse files Browse the repository at this point in the history
  • Loading branch information
jsantha committed May 6, 2020
1 parent 91f8d8b commit 46e9d88
Show file tree
Hide file tree
Showing 4 changed files with 98 additions and 34 deletions.
8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,13 @@
"devDependencies": {
"@types/jest": "^24.0.22",
"generate-changelog": "^1.8.0",
"jest": "^24.9.0",
"jest": "^25.5.4",
"rollup": "^1.26.3",
"rollup-plugin-terser": "^5.1.2",
"rollup-plugin-terser": "^5.3.0",
"rollup-plugin-typescript2": "^0.24.3",
"ts-jest": "^24.1.0",
"ts-jest": "^25.5.0",
"ts-node": "^8.4.1",
"tslint": "^5.20.1",
"typescript": "~3.6.4"
"typescript": "~3.8.3"
}
}
43 changes: 13 additions & 30 deletions src/execution/type-map-plan-builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,6 @@ export class TypeMapPlanBuilder {
...this.typeMap.profile.valueTransformers
]);

const ignoredSourceMembers = this.typeMap.implicitAutoMapping ? this.getIgnoredSourceMembers() : [];
const ignoredDestinationMembers =
this.typeMap.implicitAutoMapping ? this.ignoredOrCustomResolverDestinationMembers() : [];

return (source, destination, context) => {
const subtypeMap = this.typeMap.subtypeMaps.find(map => map.condition(source));

Expand All @@ -49,8 +45,19 @@ export class TypeMapPlanBuilder {

if (this.typeMap.implicitAutoMapping && source) {
for (const key of Object.keys(source)) {
// auto map only when both source and destination are not ignored
if (!ignoredSourceMembers.includes(key) && !ignoredDestinationMembers.includes(key)) {
const sourceMap = this.typeMap.sourceMemberConfigs.get(key);

if (sourceMap?.isIgnored()) {
continue;
}

const propertyMap = this.typeMap.propertyMaps.get(key);

if (propertyMap) {
if (propertyMap.canResolveValue && !propertyMap.isResolveConfigured) {
this.tryPropertyMap(propertyMap, propertyMap.destinationMember)(source, dest, context);
}
} else {
dest[key] = transformerFunc(source[key]);
}
}
Expand Down Expand Up @@ -171,28 +178,4 @@ export class TypeMapPlanBuilder {
return value == null ? null : value;
};
}

private getIgnoredSourceMembers(): ReadonlyArray<MemberInfo> {
const members: MemberInfo[] = [];

this.typeMap.sourceMemberConfigs.forEach(cfg => {
if (cfg.isIgnored()) {
members.push(cfg.sourceMember);
}
});

return members;
}

private ignoredOrCustomResolverDestinationMembers(): ReadonlyArray<MemberInfo> {
const members: MemberInfo[] = [];

this.typeMap.propertyMaps.forEach(cfg => {
if (!cfg.canResolveValue || cfg.isResolveConfigured) {
members.push(cfg.destinationMember);
}
});

return members;
}
}
42 changes: 42 additions & 0 deletions test/auto-mapping-map-using.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import { MapperConfiguration, MappingPair } from '../src';

describe('Auto mapping - map using', () => {

class SourceValue {
code: number;
}

class Source {
value: SourceValue[];
}

class DestinationValue {
code: string;
}

class Destination {
value: DestinationValue[];
}

const SourceToDestination = new MappingPair(Source, Destination);
const ValueMap = new MappingPair<SourceValue, DestinationValue>();

const mapper = new MapperConfiguration(cfg => {
cfg.createAutoMap(SourceToDestination, {
value: opt => opt.mapFromUsing(src => src.value, ValueMap)
});

cfg.createMap(ValueMap, {
code: opt => opt.mapFrom(x => x.code.toString())
});
}).createMapper();

it('should correctly handle auto map with nested pair', () => {
const source = new Source();
source.value = [{ code: 123 }];

const destination = mapper.map(SourceToDestination, source);

expect(destination.value).toEqual([{ code: '123' }]);
});
});
39 changes: 39 additions & 0 deletions test/bugs/auto-map-pre-condition.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { MapperConfiguration, MappingPair } from '../../src';

describe('Auto map with pre condition', () => {
interface Source {
id: number;
}

interface Destination {
id: number;
}

const SourceToDestination = new MappingPair<Source, Destination>();

const mapper = new MapperConfiguration(cfg => {
cfg.createAutoMap(SourceToDestination, {
id: opt => opt.preCondition(src => src.id > 2)
});
}).createMapper();

it('should not map property when precondition is not met', () => {
const source: Source = {
id: 1
};

const destination = mapper.map(SourceToDestination, source);
expect(destination).toEqual({});
});

it('should map when precondition is met', () => {
const source: Source = {
id: 3
};

const destination = mapper.map(SourceToDestination, source);
expect(destination).toEqual({
id: 3
});
});
});

0 comments on commit 46e9d88

Please sign in to comment.