Skip to content

Commit

Permalink
feat: map nil properties to null instead of undefined
Browse files Browse the repository at this point in the history
  • Loading branch information
jsantha committed Oct 19, 2019
1 parent a07748f commit 57ae23d
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 21 deletions.
2 changes: 1 addition & 1 deletion src/configuration/member-configuration-expression.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export class MemberConfigurationExpression<TSource, TDestination, TMember>
this.propertyMapActions.push(pm => pm.precondition = condition);
}

nullSubstitute(nullSubstitute: ((src: TSource) => TMember) | TMember | null): void {
nullSubstitute(nullSubstitute: ((src: TSource) => TMember) | TMember): void {
this.propertyMapActions.push(pm => pm.nullSubstitute = nullSubstitute);
}

Expand Down
23 changes: 9 additions & 14 deletions src/execution/type-map-plan-builder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,24 +160,19 @@ export class TypeMapPlanBuilder {
throw new Error(`Unable to detect source member for destination member "${memberMap.destinationMember.toString()}"`);
}

if (typeof memberMap.nullSubstitute !== 'undefined') {
const prevResolver = resolver;
resolver = (source: any, destination: any, context: ResolutionContext) => {
const value = prevResolver(source, destination, context);

if (value == null) {
if (typeof memberMap.nullSubstitute === 'function') {
return memberMap.nullSubstitute(source);
}
return (source: any, destination: any, context: ResolutionContext) => {
const value = resolver(source, destination, context);

return memberMap.nullSubstitute;
if (value == null && typeof memberMap.nullSubstitute !== 'undefined') {
if (typeof memberMap.nullSubstitute === 'function') {
return memberMap.nullSubstitute(source);
}

return value;
};
}
return memberMap.nullSubstitute;
}

return resolver;
return value == null ? null : value;
};
}

private getIgnoredSourceMembers(): ReadonlyArray<MemberInfo> {
Expand Down
4 changes: 2 additions & 2 deletions src/interface.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ export interface IMemberMap {
valueTransformers: ReadonlyArray<ValueTransformer<any>>;
sourceMembers: ReadonlyArray<MemberInfo>;
destinationMember: MemberInfo;
nullSubstitute: any | null;
nullSubstitute: any;
pair: MappingPair<any, any> | undefined;
}

Expand Down Expand Up @@ -154,7 +154,7 @@ export interface IMemberConfigurationExpression<TSource, TDestination, TMember>
/**
* Substitute a custom value when the source member resolves as null or undefined.
*/
nullSubstitute(nullSubstitute: ((src: TSource) => TMember) | TMember | null): void;
nullSubstitute(nullSubstitute: ((src: TSource) => TMember) | TMember): void;

/**
* Ignore this member during mapping.
Expand Down
2 changes: 1 addition & 1 deletion src/property-map.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export class PropertyMap implements IMemberMap {

public customMappingFunction: MappingFunction;

public nullSubstitute: any | null;
public nullSubstitute: any;

public ignored: boolean;

Expand Down
33 changes: 33 additions & 0 deletions test/general.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,37 @@ describe('General mapping', () => {
expect(destination[1].someValue).toBe('bar');
});
});

describe('when mapping nil properties', () => {
class ModelObject {
value: string | null;
}

class ModelDto {
value: string | null;
}

const pair = new MappingPair(ModelObject, ModelDto);

const mapper = new MapperConfiguration(cfg => {
cfg.createMap(pair, {
value: opt => opt.auto()
});
}).createMapper();

it('should map to null', () => {
const source = new ModelObject();

expect(mapper.map(pair, source)).toEqual({
value: null
});

source.value = null;

expect(mapper.map(pair, source)).toEqual({
value: null
});
});
});

});
6 changes: 3 additions & 3 deletions test/strict-map-all-member-config.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,14 @@ describe('Strict map with all member config', () => {
opt.auto();
opt.nullSubstitute(123);
}
}, opt => opt.nullSubstitute(null));
}, opt => opt.nullSubstitute('empty'));
}).createMapper();

it('should substitute all nil members to null', () => {
it('should substitute all nil members to custom value', () => {
const destination = mapper.map(pair, new Source());

expect(destination).toEqual({
another: null,
another: 'empty',
other: 123
});
});
Expand Down

0 comments on commit 57ae23d

Please sign in to comment.