-
Notifications
You must be signed in to change notification settings - Fork 3
Operation configuration
The operation configuration lets you define a configuration for a single map, defining which properties should be mapped and how.
The available methods are:
mapFrom(selector: (source: Source) => any)
ignore()
mapAs(selector: (source: Source) => any, signature: MapSignature)
immutably(value: boolean = true)
- `getParent<ParentSource, ParentDestination>() => IOperationConfiguration<ParentSource, ParentDestination>;
The available properties are:
depth: number
source: Source
destination: Destination
signature: Signature
These properties can be used to access the source and destination objects directly.
The mapFrom
method is used to enable copying a property from the source to the destination object.
e.g.
mapper.createMap<Source, Destination>(signature, Destination)
.forMember('a', operation => operation
.mapFrom(source => source.a)
);
Simply ignore the property.
It enables nested mappings: an object containing another complex object can be mapped referring to a previously set map.
e.g.
Given these classes:
class ProductEntity {
productName: string;
prices: Array<PriceEntity>;
}
class PriceEntity {
price: number;
}
class ProductModel {
name: string;
prices: Array<PriceModel>;
}
class PriceModel {
amount: number;
product: ProductModel;
}
We want to map from entities to models, so we create two maps:
const productSign = {
source: Symbol('ProductEntity'),
destination: Symbol('ProductModel')
};
const priceSign = {
source: Symbol('PriceEntity'),
destination: Symbol('PriceModel')
};
const mapper = new Mapper();
mapper
.withConfiguration(conf => conf
.shouldRequireExplicitlySetProperties(true) // Explicitly set properties only
.shouldAutomaticallyMapArrays(true)); // Map arrays also
mapper.createMap<ProductEntity, ProductModel>(productSign, ProductModel)
.forMember('name', opt => opt.mapFrom(src => src.productName))
.forMember('prices', opt => opt.mapAs(src => src.prices, priceSign));
mapper.createMap<PriceEntity, PriceModel>(priceSign, PriceModel)
.forMember('amount', opt => opt.mapFrom(src => src.price))
.forMember('product', opt => opt
.mapFrom(() => {
const parent = opt.getParent<ProductEntity, ProductModel>();
// preserve a reference of the product in which this price is contained
return parent && parent.destination;
})
.withPrecondition(() => {
// Precondition not required but recommended
const parent = opt.getParent<ProductEntity, ProductModel>();
return parent && (parent.source instanceof ProductEntity);
})
);
This configuration will map ProductEntity into a ProductModel, and the source's PriceEntity's into PriceModel's.
As a bonus, PriceModel preserves a reference to the parent ProductModel in which the price is contained.
Defines if a property should be mapped immutably.
The getParent
method returns the parent operation configuration object, set if the current map action is triggered by another mapping (e.g. with a mapAs
).
So the result of the method can be undefined.
The parent object contains its depth, source entity, destination entity and signature.
A usage example has been shown here
The source operation configuration is accessed when using the forSourceMember
method in the Map configuration.
It supports only the ignore
method.
e.g.
mapper.createMap<Source, Destination>(signature, Destination)
.withConfiguration(configuration => configuration
.shouldRequireExplicitlySetProperties(false)
.shouldIgnoreSourcePropertiesIfNotInDestination(false))
.forMember('a', operation => operation
.mapFrom(source => source.a)
.withPrecondition(() => operation.destination.a === undefined)
.immutably()
)
.forSourceMember('z', operation => operation.ignore());
const dest = mapper.map<Source, Destination>(signature, src);
console.log((dest as any).z);
// logs 'undefined' even if shouldRequireExplicitlySetProperties and
// shouldIgnoreSourcePropertiesIfNotInDestination are set to false because
// the property is set to be ignored