Skip to content

SImple to use library to map DTO using typescript decorators

Notifications You must be signed in to change notification settings

Bassintag/dto-mapper

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

50 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

dto-mapper

SImple to use library to map DTO using typescript decorators

NPM Version Circle CI Codecov

Install

This node module is available through npm.

This package is meant to be used inside a Typescript project as it leverages decorators to work.

npm i dto-mapper

This package has a peer dependency to reflect-metadata and will require it to function properly. It can be installed from npm using the following command:

npm i reflect-metadata

You will need to enable experimental decorators and emitting decorator metadata inside your tsconfig.json:

{
  "compilerOptions": {
    "experimentalDecorators": true,
    "emitDecoratorMetadata": true
  }
}

Usage

Defining DTOs

@dto()
export class UserDto {

    @include()
    id: number;

    @include()
    email: string;
}

DTOs must be annotated by @dto() in order to be accepted by the builder function.

Child class inheriting from class annotated by @dto() must also be explicitly decorated by the @dto().

Every field that need to be mapped inside the DTO must be explicitly decorated by @include() or they will be ignored by default.

Binding fields

By default fields from the DTO will expect a field with the same name inside the object being serialized. When being deserialized they will also map to a field with the same name by default.

For example the above DTO will expect an object similar to:

const toSerialize = {
    id: 0,
    email: "[email protected]",
};

There are various decorators available to customize this behavior:

@mapTo

This decorator allows to define the name of the field the property is mapped to.

Example:

@dto()
export class UserDto {

    @include()
    id: number;

    @include()
    @mapTo('userEmail')
    email: string;
}

This DTO will expect an object similar to:

const toSerialize = {
    id: 0,
    userEmail: "[email protected]",
};

@accessMode

This decorator allows to restrict the access to the property, it accepts a value from the AccessMode enum:

Value Effect
AccessMode.NONE Property will be ignored.
AccessMode.READ Property will be only serialized but not deserialized.
AccessMode.WRITE Property will be only deserialized but not serialized.
AccessMode.ALL (default) Property will be ignored.

@readOnly

Shortcut for @accessMode(AccessMode.READ)

@writeOnly

Shortcut for @accessMode(AccessMode.WRITE)

@transform

Allows to modify a property before serializing and deserializing it.

Example:

@dto()
export class UserDto {

    @include()
    id: number;

    @include()
    @transform({
        toDto: (name) => name.toUpperCase(),
        fromDto: (name) => name.toLowerCase(),
    })
    name: string;
}

In this example the name property will be serialized in uppercase but will be deserialized in lowercase.

@scope

Defines the scopes that can access this property. The scope can be passed to the mapper when serializing or deserializing.

This can be used to hide fields to user with insufficient permissions

Example:

@dto()
export class UserDto {

    @include()
    id: number;

    @include()
    @scope('admin', 'moderator')
    name: string;
}

In this example the name property will only be serialized and deserialized if the 'admin' OR the 'moderator' scope is passed to the mapper.

@nested

Allows to map a property to another DTO.

Example:

@dto()
export class RoleDto {

    @include()
    name: string;
}

@dto()
export class UserDto {

    @include()
    id: number;

    @include()
    @nested(
        () => RoleDto,
        true /* Set to true if this is an array otherwise false */
    )
    roles: RoleDto[];
}

In this example the UserDto includes an array of RoleDto.

Creating the mapper

Once your DTO class has been defined you can create a mapper to actually start serializing and deserializing data.

In order to do so you can use the buildMapper function.

Example:

const mapper = buildMapper(UserDto); // Magic !

Important: this function is expensive and should be called only once per DTO, you should cache the mapper and reuse it.

Mapping data

Finally, when your mapper is ready you can call the serialize method to serialize data:

// No scope
const serialized = mapper.serialize({ id: 0, userEmail: '[email protected]' });

// Admin scope
const serializedWithScope = mapper.serialize({ id: 0, userEmail: '[email protected]' }, 'admin');

You can deserialize data using the deserialize method:

// No scope
const deserialized = mapper.deserialize({ id: 0, email: '[email protected]' });

// Admin scope
const deserializedWithScope = mapper.deserialize({ id: 0, email: '[email protected]' }, 'admin');

License

MIT

About

SImple to use library to map DTO using typescript decorators

Resources

Stars

Watchers

Forks

Packages

No packages published