automapper/pojos
Overview
@automapper/pojos
is an official strategy that works with TS Interface-based projects.
Installation
npm i @automapper/core @automapper/pojos
yarn add @automapper/core @automapper/pojos
Usage
Different from @automapper/classes
, @automapper/pojos
exports a singleton PojosMetadataMap
so we can provide the metadata for pojos
.
interface User {
firstName: string;
lastName: string;
}
interface UserDto {
firstName: string;
lastName: string;
fullName: string;
}
export function createUserMetadata() {
PojosMetadataMap.create<User>('User', {
firstName: String,
lastName: String,
});
PojosMetadataMap.create<UserDto>('UserDto', {
firstName: String,
lastName: String,
fullName: String,
});
}
createUserMetadata();
const mapper = createMapper({ strategyInitializer: pojos() });
createMap<User, UserDto>(
mapper,
'User', // this needs to match what we passed in PojosMetadataMap.create()
'UserDto', // this needs to match what we passed in PojosMetadataMap.create()
forMember(
(destination) => destination.fullName,
mapFrom((source) => source.firstName + ' ' + source.lastName)
)
);
const dto = mapper.map<User, UserDto>(
{ firstName: 'Chau', lastName: 'Tran' },
'User', // this needs to match what we passed in PojosMetadataMap.create()
'UserDto' // this needs to match what we passed in PojosMetadataMap.create()
); // { firstName: 'Chau', lastName: 'Tran', fullName: 'Chau Tran'
caution
PojosMetadataMap.create()
needs to be called before we attempt to call createMap()
Metadata
As seen above, PojosMetadataMap
is a way that @automapper/pojos
use to keep track of the Interface's metadata.
PojosMetadataMap.create()
PojosMetadataMap.create()
accepts a string
or a symbol
as the identifier and a metadata object.
PojosMetadataMap.create<User>('User', {
firstName: String,
lastName: String,
});
tip
Supply the type parameter PojosMetadataMap.create<User>()
will provide intellisense for the fields in the metadata object
Nested model
Nested model's metadata needs to be created before the parent model.
interface Bio {
birthday: Date;
}
interface User {
firstName: string;
lastName: string;
bio: Bio;
}
PojosMetadataMap.create<Bio>('Bio', {
birthday: Date,
});
PojosMetadataMap.create<User>('User', {
firstName: String,
lastName: String,
bio: 'Bio', // <-- use what we passed in PojosMetadataMap.create() for Bio
});
Enum
Same as @automapper/classes
, we still need to explicitly supply the Enum type
enum Role {
Admin = 'admin',
User = 'user',
}
interface User {
role: Role;
}
PojosMetadataMap.create<User>('User', {
role: String,
});
Array type
Same as @automapper/classes
, we still need to explicitly supply the Array type
interface Address {
street: string;
}
interface Bio {
birthday: Date;
addresses: Address[];
}
interface User {
firstName: string;
lastName: string;
bio: Bio;
logins: Date[];
}
PojosMetadataMap.create<Address>('Address', {
street: String,
});
PojosMetadataMap.create<Bio>('Bio', {
birthday: Date,
addresses: ['Address'], // <-- array of the identifier
});
PojosMetadataMap.create<User>('User', {
firstName: String,
lastName: String,
bio: 'Bio',
logins: [Date], // <-- array of the Date constructor
});
Circular Dependency
Same as @automapper/classes
, we can also have circular dependency with Interfaces.
PojosMetadataMap.create<Bio>('Bio', {
birthday: Date,
addresses: ['Address'],
});
PojosMetadataMap.create<User>('User', {
firstName: String,
lastName: String,
bio: {
// pass in an object instead
type: () => 'Bio',
depth: 2, // default to 1
},
logins: [Date],
});
PojosMetadataMap.reset()
To clear all the metadata, we can call PojosMetadataMap.reset()
. This is useful in testing environment where we want to start fresh for each test suite.