Coder Social home page Coder Social logo

nartc / mapper Goto Github PK

View Code? Open in Web Editor NEW
965.0 8.0 85.0 30.42 MB

๐Ÿ”ฅ An Object-Object AutoMapper for TypeScript ๐Ÿ”ฅ

Home Page: https://automapperts.netlify.app/

License: MIT License

TypeScript 76.41% JavaScript 4.40% CSS 0.36% MDX 18.84%
typescript automapper nodejs javascript mapper nx hacktoberfest hacktoberfest-accepted

mapper's Introduction

AutoMapper TypeScript

All Contributors

Lines of Code Maintainability Rating Quality Gate Status Reliability Rating Security Rating

This is a monorepo of @automapper/core and official packages.

Packages

Project Package Version Links
core @automapper/core npm (scoped) README npm bundle size (scoped) NPM
classes @automapper/classes npm (scoped) README npm bundle size (scoped) NPM
mapped-types @automapper/classes/mapped-types - README
transformer-plugin @automapper/classes/transformer-plugin - README
pojos @automapper/pojos npm (scoped) README npm bundle size (scoped) NPM
mikro @automapper/mikro npm (scoped) README npm bundle size (scoped) NPM
sequelize @automapper/sequelize npm (scoped) README npm bundle size (scoped) NPM
nestjs @automapper/nestjs npm (scoped) README npm bundle size (scoped) NPM

Others

Project Description Links
integration-test Integration tests of Core and the official plugins README
nestjs-integration-test Integration tests for NestJS -

Documentations

See Documentations

Miscellaneous

@automapper/* is a later iteration of the legacy @nartc/automapper. @nartc/automapper is archived and is placed in this repo under legacy branch

Contributors โœจ

Thanks goes to these wonderful people (emoji key):


Chau Tran

๐Ÿ’ป ๐Ÿค”

Micael Levi L. Cavalcante

๐Ÿ’ป

Ali Yusuf

๐Ÿ’ป

Robson Hermes

๐Ÿ“–

Huybn

๐Ÿ’ป

Jason Merino

๐Ÿ“–

roblopz

๐Ÿ’ป ๐Ÿ›

Lennart Hensler

๐Ÿ’ป

jmplahitko

๐Ÿ’ป

Hoa Truong

๐Ÿ“–

Vincent Pecquerie

๐Ÿ’ป

Alwin J. Schuster

๐Ÿ’ป

This project follows the all-contributors specification. Contributions of any kind welcome! Please check out our contributing guide

mapper's People

Contributors

aliyusuf95 avatar alwinator avatar dtap001 avatar elsieej avatar gabrielkim13 avatar hoa00 avatar huybn5776 avatar jasonmerino avatar jmplahitko avatar lennarth avatar micalevisk avatar nartc avatar nonara avatar pradiev avatar roblopz avatar robsonhermes avatar timonmasberg avatar vpecquerie avatar zgid123 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mapper's Issues

Is that possible that the mapper can base on the source type to map?

I used AutoMapper (and mediatr which is also developed by Jimmy Bogard) in dotnet core before. It's pretty nice that see it again in typescript.

However, the code base currently use the destination class to found out the source class is pretty strange.

Thats mean if we have two different source class to project to same vm model will get wrong.

Here is the example that

class User {
  @Expose()
  firstName!: string;
  @Expose()
  lastName!: string;
  @ExposedType(() => Profile)
  profile!: Profile;
}

class User2 {
  @Expose()
  firstName!: string;
  @Expose()
  lastName!: string;
  @ExposedType(() => Profile)
  profile!: Profile;
}

    mapper
      .createMap(User, UserVm)
      .forMember(d => d.first, opts => opts.mapFrom(s => "Khang"))
      .forMember(d => d.last, opts => opts.mapFrom(s => s.lastName))
      .forMember(
        d => d.full,
        opts => opts.mapFrom(s => s.firstName + " " + s.lastName)
      );
    mapper
      .createMap(User2, UserVm)
      .forMember(d => d.first, opts => opts.fromValue("a"))
      .forMember(d => d.last, opts => opts.fromValue("B"))
      .forMember(
        d => d.full,
        opts => opts.mapFrom(s => s.firstName + " " + s.lastName)
      );

Now if we project a User2 obj to UserVm it will still keep using the first mapping

refs:
https://codesandbox.io/s/automapper-demo-b3d7p

get undefined in output properties

I'm submitting a...


[ ] Regression 
[x] Bug report
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request

Current behavior

at first thanks for your great library
I have a strange problem (get undefined in output properties)
The following steps are to reproduce:

@Entity()
class Country {
  @PrimaryGeneratedColumn('uuid')
  id: string;

  @Column({ nullable: false, unique: true })
  @AutoMap()
  name: string;

  @OneToMany(() => City, (city) => city.country)
  cities: City[];
}

@Entity()
class City {
  @PrimaryGeneratedColumn('uuid')
  id: string;

  @Column({ nullable: false })
  @AutoMap()
  name: string;

  @ManyToOne(() => Country, (country) => country.cities, { eager: true })
  country: Country;

  @OneToMany(() => Address, (address) => address.city)
  addresses: Address[];
}

@Entity()
class Address {
  @PrimaryGeneratedColumn('uuid')
  @AutoMap()
  id: string;

  @Column({ nullable: false })
  @AutoMap()
  descriptiveAddress: string;

  @Column({
    type: 'double precision',
    array: true,
    nullable: true,
    unique: true,
  })
  @AutoMap()
  coordinateAddress: number[];

  @Column({ nullable: true, unique: true })
  @AutoMap()
  postalCode: string;

  @ManyToOne(() => City, (city) => city.addresses, { eager: true })
  city: City;
}

class AddressRoDto {
  @AutoMap()
  id: string;

  @AutoMap()
  descriptiveAddress: string;

  @AutoMap()
  coordinateAddress: number[];

  @AutoMap()
  postalCode: string;

  @AutoMap()
  cityName: string;

  @AutoMap()
  countryName: string;
}

class AddressProfile extends ProfileBase {
  constructor(mapper: AutoMapper) {
    super();
    mapper
      .createMap(Address, AddressRoDto)
      .forMember(
        (d) => d.cityName,
        mapFrom((s) => s.city.name),
      )
      .forMember(
        (d) => d.countryName,
        mapFrom((s) => s.city.country.name),
      );
  }
}

class University {
  @PrimaryGeneratedColumn('uuid')
  @AutoMap()
  id: string;

  @Column({ nullable: true })
  @AutoMap()
  name: string;

  @OneToMany(() => Professor, (professor) => professor.univerity)
  @AutoMap(() => Professor)
  professors: Professor[];

  @OneToOne(() => Address)
  @JoinColumn()
  @AutoMap(() => Address)
  address: Address;
}

class UniversityRoDto {
  @AutoMap()
  id: string;

  @AutoMap()
  name: string;

  @AutoMap(() => AddressRoDto)
  address: AddressRoDto;

  @AutoMap(() => ProfessorRoDto)
  professors: ProfessorRoDto[];
}

@Profile()
class UniversityProfile extends ProfileBase {
  constructor(mapper: AutoMapper) {
    super();
    mapper.createMap(University, UniversityRoDto);
  }
}


class User {
  @PrimaryGeneratedColumn('uuid')
  @AutoMap()
  id: string;

  @Column({ nullable: false })
  @AutoMap()
  name: string;

  @Column({ nullable: true, unique: true })
  @AutoMap()
  email: string;

  @Column({ nullable: true })
  @AutoMap()
  emailConfirm: boolean;

  @Column({ nullable: true, unique: true })
  @AutoMap()
  phone: string;

  @Column({ nullable: false })
  @AutoMap()
  password: string;
}

class UserRoDto {
  @AutoMap()
  id: string;

  @AutoMap()
  name: string;

  @AutoMap()
  email: string;

  @AutoMap()
  phone: string;
}

@Profile()
class UserProfile extends ProfileBase {
  constructor(mapper: AutoMapper) {
    super();
    mapper.createMap(User, UserRoDto);
  }
}


@Entity()
class Professor {
  @PrimaryGeneratedColumn('uuid')
  @AutoMap()
  id: string;

  @Column({ nullable: false })
  @AutoMap()
  inUniversityAddress: string;

  @Column({ nullable: false })
  @AutoMap()
  grade: string;

  @OneToOne(() => User)
  @JoinColumn()
  @AutoMap(() => User)
  user: User;

  @ManyToOne(() => University, (university) => university.professors)
  @AutoMap(() => University)
  univerity: University;
}

class ProfessorRoDto {
  @AutoMap()
  id: string;

  @AutoMap(() => UserRoDto)
  user: UserRoDto;

  @AutoMap()
  grade: string;

  @AutoMap(() => UniversityRoDto)
  university: UniversityRoDto;

  @AutoMap()
  inUniversityAddress: string;
}

@Profile()
class ProfessorProfile extends ProfileBase {
  constructor(mapper: AutoMapper) {
    super();
    mapper.createMap(Professor, ProfessorRoDto);
  }
}

when I want to map Professor to ProfessorRoDto I get undefined properties in ProfessorRoDto .university although
when I map Professor.University to UniversityRoDto every thing is ok

console.log(this.mapper.map(professor, ProfessorRoDto, Professor)) log this result

ProfessorRoDto {
  id: '3374df70-60b0-43d8-8755-6735bbd55a2a',
  user: UserRoDto {
    id: 'd1e514fa-53d5-4405-b131-e46b621b9396',
    name: 'faridkh95',
    email: '[email protected]',
    phone: '09195877368'
  },
  grade: 'visiting_professor',
  university: UniversityRoDto {
    id: undefined,
    name: undefined,
    address: AddressRoDto {
      id: undefined,
      descriptiveAddress: undefined,
      coordinateAddress: [],
      postalCode: undefined,
      cityName: undefined,
      countryName: undefined
    }
  },
  inUniversityAddress: 'string'
} 

but console.log(this.mapper.map(university, UniversityRoDto, University)) log this result that is true

UniversityRoDto {
  id: '5fe20251-94c5-475f-a278-3428a21c0a5d',
  name: 'ุฏุงู†ุดฺฏุงู‡ ฺฉุงุดุงู†',
  address: null,
  professors: null
}

I user nestjs-automapper and every profiles loaded corectlly

Environment


node: 12.0.0
typesript:3.9.3
nestjs:7.0.13
 

name/value pairs are in reverse order in JSON after mapping

Hello @nartc ,

I must thank you for the excellent job you do with this module. It fills a huge gap in Nest/Ng context.

I have just started to use the module, and I have a minor issue. Maybe I am doing something wrong.

I am developing a simple todo Nest.js API, and I use Automapper to map entity class to Dto class. Everything works fine, but after mapping something strange happens: the JSON name/value pairs are in reverse order as they were defined in the class.

Can I somehow get them in the right order?

Todo Entity class:

export class TodoEntity {
    @AutoMap()
    id: string;
    @AutoMap()
    name: string;
    @AutoMap()
    description?: string;
}

Todo Dto class:

export class TodoDto {
    @AutoMap()
    id: string;
    @AutoMap()
    name: string;
    @AutoMap()
    description?: string;
}

The profile:

@Profile()
export class TodoProfile extends ProfileBase {
  constructor(mapper: AutoMapper) {
    super();
    mapper.createMap(TodoEntity, TodoDto).reverseMap();
  }
}

And the service which is used by the controller:

@Injectable()
export class TodoService {
    todos: TodoEntity[] = todos;

    constructor(@InjectMapper() private readonly mapper: AutoMapper) { }
    
    async getAllTodo(): Promise<TodoDto[]>{
        return toPromise(this.mapper.mapArray(this.todos, TodoDto, TodoEntity));
    }
    ...
}

The controller part:

@Controller("api/todos")export class TodoController {
    constructor(private readonly todoService: TodoService) {}
    
    @Get()
    async findAll(): Promise<TodoListDto> {
      const todos = await this.todoService.getAllTodo();
      return toPromise({ todos });
    }
    ...
}

And the response from the API is:

{
    "todos": [
        {
            "description": null,
            "name": "Supermarket Todo list",
            "id": "eac400ba-3c78-11e9-b210-d663bd873d93"
        }
    ]
}

But is should be:

{
    "todos": [
        {
            "id": "eac400ba-3c78-11e9-b210-d663bd873d93",
            "name": "Supermarket Todo list",
            "description": null,
        }
    ]
}

The source can be found on: https://github.com/He-Wolf/NGNestApp/tree/4e9752175c6559bd0433f2a7aa6650e82b10e5bc/server

Thank you for your help in advance!

Strange behaviour when test coverage active.

I'm submitting a...


[ ] Regression 
[X] Bug report
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request

Current behavior

I think this is happening because istanbul adds some extra fields for calculating coverage.
Gives errors related to some fields are not mapped.

Also some mapping not executed. Have you met any issue related that?

Expected behavior

Should work same without coverage active

Minimal reproduction of the problem with instructions

What is the motivation / use case for changing the behavior?

Environment


Version: X.Y.Z
 
For Tooling issues:
- Node version: XX  
- Platform:  

Others:

Support for transforming plain objects to classes

I'm submitting a...


[ ] Regression
[ ] Bug report
[x] Feature request
[ ] Documentation issue or request
[x] Support request

Current behavior

I'm trying to convert a plain object, coming from a web request, to a dto.
Basically I'm trying to avoid class-transformer and I've written the following transform pipe for nestJs:

@Injectable()
export class DtoPipe implements PipeTransform {
    @InjectMapper()
    private automapper: AutoMapper;
    public transform(value: any, metadata: ArgumentMetadata) {
        return this.automapper.map(value, metadata.metatype, metadata.metatype);
  }
}

To make this work I had to add the mapping:

     mapper.createMap(RegisterUserDto, RegisterUserDto);

for each of my dtos. It works but feels like a hack. I wish there was a more intuitive way with options like forbidUnknownValues.

Expected behavior

Introduce some of class-transformer features to this library or let me know if there is another way to do this

What is the motivation / use case for changing the behavior?

Avoiding class-transformer dependency since this library already satisfies most of the typical requirements.

fix: rework circular dependencies

I'm submitting a...


[ ] Regression 
[x] Bug report
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request

Current behavior

Current behavior of Circular Dependencies (aka InstanceStorage) only handles the following case:

class SourceA {
  @AutoMap()
  id: number;
  @AutoMap(() => SourceB)
  sourceB: SourceB;
}
class SourceB {
  @AutoMap()
  id: number;
  @AutoMap(() => SourceA)
  sourceA: SourceA;
}

or SourceA <-> SourceB

And also the way the depth works isn't really consistent (confusing) which makes maintain and fix bug way too hard and time consuming.

The following case won't work:

SourceA -> SourceB -> *multiple level of other Sources* -> SourceA

This case will eventually hit a Maximum Call stack error depending on the models.

Expected behavior

Should work correctly

Minimal reproduction of the problem with instructions

What is the motivation / use case for changing the behavior?

AutoMapper should at least handle rudimentary circular dependencies cases.

Environment


Version: X.Y.Z
 
For Tooling issues:
- Node version: XX  
- Platform:  

Others:

Mapping from class that don't have extra properties

I'm submitting a...


[ ] Regression 
[x] Bug report
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request

Current behavior

When I try to map from a class that extends another class without having extra property the mapping failed with Error: Mapping not found for source ....

I tried to override a property so I can use @AutoMap() on it to create mapping data, but that not work either but the error changed

Error: Mapping for {class1} <-- my overridden property
cannot be found. Consider manual map this property with MapWith

Expected behavior

Able to map extended classes without having new extra properties and the ability to override properties without manual mapping for them.

Minimal reproduction of the problem with instructions

https://github.com/AliYusuf95/ng-automapper/tree/extend

Environment


Version: 6.3.9
 
For Tooling issues:
- Node version: 12.13.1
- Platform:  Mac

Others:
- Typescript: 3.8.3
- Angular: 9.1.9

How to map moment to number?

Hi again :)

This time I am wondering how to map between moment object and number

Here is my snippet

import "reflect-metadata";
import { AutoMap, Mapper } from "@nartc/automapper";
var moment = require("moment");

class Foo {
  @AutoMap()
  public get foo(): Moment {
    return this._foo;
  }

  public set foo(value: Moment) {
    this._foo = value;
  }

  private _foo!: Moment;
}

class FooDTO {
  @AutoMap()
  public foo!: number; // the unix timestamp
}

Mapper.initialize(cfg => {
  cfg.createMap(FooDTO, Foo).forMember(
    (dest: Foo) => dest.foo,
    (opts: any) => opts.mapFrom((source) => {
      return moment(source.foo);
    }),
);
});

const foo = Mapper.map({ foo: 1111234567890}, Foo, FooDTO);
console.log(foo);

This fails with the error "TypeError Cannot read property '_isAMomentObject' of undefined".
The issue is related to class-transformer (see typestack/class-transformer#176) but I don't know how to get this to work using your mapper lib.

Uncaught TypeError: Cannot convert undefined or null to object.

Hi, I've encountered issue on Object.getOwnPropertyNames(node) under getPathRecursive function when the node is null or undefined. Here is the screenshot.

image

It happens when trying to map, FormControl to String Type variable.

class TestDto {
   public id: string
}

class TestVm {
   public formControlId = new FormControl('');
}

/// Mapping TestDto <=> TestVm
Mapper.createMap(TestDto, TestVm).reverseMap();

I think it might be better if you would check first if the node is null or undefined? and ignore it if its the case?

Access to already resolved destination properties when using resolve

Hello @nartc,
I'm curious about the purpose of the destination object in the resolver. Is there any way for e.g. User (title, first, last) to UserVm(first, last, fullName, fullTitle) where the mappings are:

  • d.first -> s.first
  • d.last -> s.last
  • d.fullName -> s.first + ' ' + s.last
  • d.fullTitle -> s.title + ' ' + d.fullName (option 1)

I know there is always (option 2) where d.fullTitle can be defined as s.title + ' ' + s.first + ' ' + s.last.

I'm asking this to know if there is any possiblity to

  • avoid defining the fullname part twice when using option 2
  • for more complex examples to re-use an already evaluated mapping in the same destination object

`convertUsing` value selector must not return a falsy value?

I'm submitting a...

[ ] Regression <!--(a behavior that used to work and stopped working in a new release)-->
[x] Bug report
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request

Current behavior

Due to the code snippet below -- where value is a Selector<TSource, TConvertSource>

source =>
converter.convert(
value?.(source) || ((source as unknown) as TConvertSource)
),

if the value selector return some falsy value, Converter.convert will receive the whole source object instead of the destination.<some_member> and this can leads to TypeError errors (eg: sourceDate.toISOString is not a function).

Expected behavior

Should preserve the src.<some_member> falsy value (from convertUsing's selector) instead of passing the src to converter.convert() method.

Minimal reproduction of the problem with instructions

class DateTimeConverter implements Converter<Date | null, string | null> {
  convert(sourceDate: Date | null): string | null {
    return sourceDate?.toISOString() || null;
  }
}
// ....
Mapper.createMap(Foo, FooVm).forMember(
  dest => dest.deletedAt, // `Date | null`
  convertUsing(new DateTimeConverter(), src => src.deletedAt)
                                             // this ^^^ can be `Date | null` as well
)

What is the motivation / use case for changing the behavior?

I don't understand the current behavior because there's nothing on convertUsing typings nor on docs to prevent errors that could be thrown due to the wrong types defs (null in my example) among another issues. And I want to use converters with implementations the DateTimeConverter above instead of use preCondition (should I? I'm not sure).

Environment

Version: 6.3.15
 
For Tooling issues:
- Node version: 12.14.1
- Platform: Linux

Mapping with both null and undefined

This mapper is the most powerful and maintained that I've seen and I appreciate all the job done.

I have a question regarding this mapper.
My app architecture consists of 3 layers: API, domain and database.
While using PATCH I'd like to be able to differentiate null and undefined on the database layer entities.

So my question: is it possible to keep undefined properties as undefined and null properties as null while mapping?

[Feature Request] Type Converters

Hey there. I've been searching for a library to handle the data conversion for a while and found this.
Unfortunaly it is missing the Type Converters compared to the .NET version.

For example, I would like to be able to convert between luxon's DateTime and @google-cloud/firestore's Timestamp without having to define the mappings for every field manually. From my understanding that's what Type Converters are for.

I figured I could try to implement it and send a PR, but I found that code was too complicated for my tastes, so I decided to open an issue instead.

Is there some work on this direction?

Announcement: Changes and Project status

Hi all,

Thank you all for using/giving @nartc/automapper a try. I have some announcement to make regarding the project status.

First and foremost, the updates for the project have been slow. The reason is I've just changed job recently and I'm still adapting to the new workplace so there's less time on my part to work on personal projects like @nartc/automapper. Also, my wife and I are expecting our first baby so there's been a lot of preparations around the house to welcome our baby.

Second, I have some visions for the project. Currently, @nartc/automapper works well for my use-cases (and some others' use-cases) as I built it based on my needs about a year ago. That said, it's not very extensible. Almost the fixes I put in @nartc/automapper have been more like patches rather than actual fixes.

To counter this (and also to welcome more contributors), I've decided to rework on the core of @nartc/automapper with the following list of upcoming changes:

  • AutoMapper will be a monorepo and will be plugin-based. A side note on plugins, I don't envision there's a lot of extensibility to AutoMapper because the concept itself is very opinionated. However, plugin-based model allows me (or contributors) to stay focus on specific areas of the library when problem arises.
  • There will be documentation on how to create your own Custom Plugin
  • AutoMapper will provide the following libraries:
    • core: This is the core of AutoMapper which will handle the actual mapping configurations and operations. Core will not dictate how it will store Mappings, Metadata like it's doing now with @nartc/automapper. Plugins will do so on their own and provide the Mappings when Core asks for them.
    • classes (plugin): This is a plugin that would make AutoMapper work with Classes. This is exactly like how AutoMapper works today but with improvements to typings and overall performance. classes plugin provides its own way of storing the Mapping and Metadata.
    • interfaces (plugin, name is subject to change): This is a plugin that would allow AutoMapper to work with Interfaces. With the plugin providing its own Metadata storing mechanism, making interfaces work is an easier feat than the current state of @nartc/automapper.
    • nest (wrapper for NestJS): As the name said, it will be a wrapper for NestJS, with improvements to usability.
  • AutoMapper Transformer Plugin's status is TBD. I'm not sure how I want to provide this as of the moment
  • About NamingConvention and a couple of default settings that @nartc/automapper currently sets right now, I'll be addressing these to be less opinionated and less strict as well. This is to address #208 and #215
  • AutoMapper will provide a way to map a sourceObj to a destinationObj. This is to address #244
  • AutoMapper will provide the core and its official plugins via @automapper/* npm scope following Semantic Versioning for all provided packages. This is to give consumers a sense of somewhat official. And I really want to welcome other contributors.

With all of these in mind, I'll not be adding new features to current @nartc/automapper as of the moment. I'll still try to address bugs and help out with issues (in terms of usage) if my availability permits. Once again, thank you all and I'll see you around.

Null Substitution support

Hi @nartc,

You state in the README that null substitution feature may not be added, in favor of fromValue(). However, as I understand, the use cases of these two are different.

  1. In the original library, Jimmy Bogard says:

Null substitution allows you to supply an alternate value for a destination member if the source value is null anywhere along the member chain. This means that instead of mapping from null, it will map from the value you supply.

It means the mapper will only assign the value you provide if the source member is null.

  1. fromValue() allows you to map a raw value to a destination member, regardless of the source member value.

Am I wrong anywhere?

I have a question about reverseMap() function.

I create a profile by using function createMap(), and i need to convert some field has type Date to string. Now, I want to when i receive data from client using reverseMap() with convert again string to Date. Pls help me provide some example. Thanks

_removeExtraForFunction will incorrectly parse member name if member name includes 'return'

Example: Given a member name of 'returnUrl' on a destination model:
Calling mapper.createMap(Dest, Source).forMember(dest => dest.returnUrl, [expression]) will result in a destination object containing a 'Url' member.

I've stepped through and found that the _removeExtraForFunction util is splitting on 'return', which will split on not only the keyword 'return', but also any other part of the stringified function that contains 'return', including 'dest => dest.returnUrl'

Angular: Error while registering profiles from lazy loaded modules

I'm submitting a...


[ ] Regression
[x] Bug report
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request

Current behavior

After building my angular app with optimizing flag, the mapper throws this error
Error: u is already existed on the current Mapper instance

Expected behavior

It should work in angular

Minimal reproduction of the problem with instructions

https://github.com/AliYusuf95/ng-automapper/tree/profile

Environment


Version: 5.0.10

For Tooling issues:
Node version: 12.13.1
Platform: Mac

Others:
Typescript: 3.8.2
Nx: 9.1.0
Angular: 9.0.6
Nestjs: 6.11.11

Mapping key not unique when the code minified

I'm submitting a...


[ ] Regression
[x] Bug report
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request

Current behavior

After building my angular app with optimizing flag, the mapper throws this error
Uncaught Error: Mapping for source n and destination n is already existed
It seems that the compiler change classes names angular/angular-cli#12887

Expected behavior

It should work in angular

What is the motivation / use case for changing the behavior?

I think the mapping key should not rely on the class name as string.

export function _getMappingKey(
sourceKey: string,
destinationKey: string
): string {
return sourceKey + '->' + destinationKey;
}

Maybe using the class function it's self would solve the problem.

Environment

Version: 5.0.9

For Tooling issues:

  • Node version: 12.13.1
  • Platform: Mac

Others:

  • Typescript: 3.8.2
  • Nx: 9.0.2
  • Angular: 9.0.3
  • Nestjs: 6.11.8

Error when try to map plain object with properties of class type

I'm submitting a...


[ ] Regression 
[x] Bug report
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request

Current behavior

I can't map an object to class that has properties of type class

export class UserModel extends BaseModel {
  @AutoMap()
  name: string;
  @AutoMap()
  isAdult: boolean;
  @AutoMap(() => ProfileModel)
  profile: ProfileModel; // <- this property cause the error
}

export class UserDto extends BaseDto {
  @AutoMap()
  name: string;
  @AutoMap()
  age: number;
  @AutoMap(() => ProfileDto)
  profile: ProfileDto;
}

const dto: UserDto = {
      id: '2',
      name: 'user name',
      age: 15,
      createdAt: new Date(),
      updatedAt: new Date(),
      profile: {
        logoUrl: '',
        updatedAt: new Date(),
      }
};

// add profile base mapping
Mapper.createMap(BaseProfileDto, BaseProfileModel);
// add profile mapping
Mapper.createMap(ProfileDto, ProfileModel, {includeBase: [BaseProfileDto, BaseProfileModel]});

// add base mapping
Mapper.createMap(BaseDto, BaseModel);
// add user mapping
Mapper.createMap(UserDto, UserModel, {includeBase: [BaseDto, BaseModel]})
  .forMember(dist => dist.isAdult, mapFrom(src => src.age >= 18));

// try to map object
Mapper.map(dto, UserModel, UserDto);
core.js:6185 ERROR Error: Mapping not found for source function Object() { [native code] } and destination class ProfileModel extends _base_profile_model__WEBPACK_IMPORTED_MODULE_2__["BaseProfileModel"] {
}
    at getMappingForDestination (automapper.esm.js:167)
    at map (automapper.esm.js:1011)
    at AutoMapper.map$1 [as map] (automapper.esm.js:1214)
    at Comp1Component.ngOnInit (comp1.component.ts:32)

Expected behavior

Able to map pain object

Minimal reproduction of the problem with instructions

To reproduce the issue: https://github.com/AliYusuf95/ng-automapper/tree/extend

Environment


Version: 6.0.2
 
For Tooling issues:
- Node version: 12.13.1
- Platform:  Mac

Others:
- Typescript: 3.7.5
- Angular: 9.0.7

How to use getMapperToken in jest/nestjs test module?

Hi, so far the only way I've been getting unit tests to work is importing AutomapperModule, and mocking Automapper with ts-mockito


 const mockMapper = mock(AutoMapper)
 const module: TestingModule = await Test.createTestingModule({
      imports: [AutomapperModule.withMapper()],
      providers: [
        ...
        {
          provide: AutoMapper,
          useValue: instance(mockMapper),
        },
      ],

Thats pretty slow. I noticed there is a getMapperToken method, but I don't know how to use it. It doesn't seem to work.

Thanks!

When setting useUndefined to true, null value are mapped to undefined.

Hi,
I'm having an issue trying to map objects that have null values, here is my example:

export class Setting {
  @AutoMap()
  name: string;

  @AutoMap()
  displayName: string;

  @AutoMap()
  value?: any;

  @AutoMap()
  description?: string;

  @AutoMap()
  type: string;

  @AutoMap()
   createdAt?: Date()
}

export class SettingVm {
  @AutoMap()
  name: string;

  @AutoMap()
  displayName: string;

  @AutoMap()
  description?: string;

  @AutoMap()
  value: any;

  @AutoMap()
  type?: string;

  @AutoMap()
  createdAt?: Date()

}


const settings = [
      {
        name: 'setting1',
        value: 1,
        displayName: 'Setting 1',
        type: 'string',
        description: null,
        id: '13',
      },
      {
        name: 'setting2',
        value: '2',
        displayName: 'Setting 2',
        type: 'string',
        description: null,
        id: '12',
      },
    ];

Mapper.createMap(Setting, SettingVm, { useUndefined: true });
const result = Mapper.map(settings, SettingVm, Setting);

And here is the resulting mapping:

[
   {
      "createdAt":"2020-12-07T12:28:52.521Z",
      "id":"13",
      "name":"setting1",
      "displayName":"Setting 1",
      "value":1,
      "type":"string",
      "description": undefined
   },
   {
      "createdAt":"2020-12-07T12:28:52.522Z",
      "id":"12",
      "name":"setting2",
      "displayName":"Setting 2",
      "value":"2",
      "type":"string",
      "description": undefined
   }
]

The issue here is that the description field was changed to undefined, and the createdAt was initialized with new Date().
How should I configure automapper, so that undefined values stay undefined, null values stay null, without ignoring them because it's not what I'm looking for, just I want them to keep the value from the source.

SnakeCaseNamingConvention not found

I'm submitting a...


[ ] Regression 
[ ] Bug report
[ ] Feature request
[ ] Documentation issue or request
[ x ] Support request

Current behavior

SnakeCaseNamingConvention not found when trying to set global settings config. Where can I find it?

Error when try to map two classes

I'm submitting a...


[ ] Regression 
[x] Bug report
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request

Current behavior

I want to try this library so I decide to map this class
`
class CreateProjectDto {
@isnotempty()
@AutoMap()
title: string;

@isnotempty()
@AutoMap()
description: string;

@isnotempty()
@AutoMap()
requestExpireDate: Date;

@isnotempty()
@AutoMap()
deadlineInDay: number;

@isnotempty()
@AutoMap()
deadlineDate: Date;

@isnotempty()
@AutoMap()
managerPhone: string;

@isnotempty()
@AutoMap()
managerName: string;

@isnotempty()
@AutoMap()
tagId: string;

@isnotempty()
@AutoMap()
companyId: string;

@isnotempty()
@AutoMap()
projectOwnerId: string;

@isnotempty()
@AutoMap()
price: number;
}
to this class
class ProjectRoDto {
@AutoMap()
id: string;

@AutoMap()
title: string;

@AutoMap()
description: string;

@AutoMap()
requestExpireDate: Date;

@AutoMap()
deadlineInDay: number;

@AutoMap()
deadlineDate: Date;

@AutoMap()
managerPhone: string;

@AutoMap()
managerName: string;

@AutoMap()
tagId: string;

@AutoMap()
companyId: string;

@AutoMap()
projectOwnerId: string;

@AutoMap()
price: number;
}
with this profile
@Profile()
export class ProjectProfile extends ProfileBase {
constructor(mapper: AutoMapper) {
super();
mapper
.createMap(CreateProjectDto, ProjectRoDto)
.forMember((d) => d.id, ignore());
}
}
but I get this error
Error: Mapping not found for source function Object() { [native code] } and destination class ProjectRoDto {
static _OPENAPI_METADATA_FACTORY() {
return { id: { required: true, type: () => String }, title: { required: true, type: () => String }, description: { required: true, type: () => String }, requestExpireDate: { required: true, type: () => Date }, deadlineInDay: { required: true, type: () => Number }, deadlineDate: { required: true, type: () => Date }, managerPhone: { required: true, type: () => String }, managerName: { required: true, type: () => String }, tagId: { required: true, type: () => String }, companyId: { required: true, type: () => String }, projectOwnerId: { required: true, type: () => String }, price: { required: true, type: () => Number } };
}
}
`
also I use nestjs module of this library("nestjsx-automapper": "3.0.10")
and nestjs version is 7.0.13

Environment


node :12.16.3

Inject into custom profile class

Hi!
Short question: can (how) it is possible to inject into the profile (class extends ProfileBase) an additional object apart from the mapper?

Angular 8 project using automapper

Hi,

I am trying to use nartc/mapper 6.1.2, in my angular 8.1.2 project, but i get errors like:

ERROR in node_modules/@nartc/automapper/dist/automapper.d.ts:106:9 - error TS1086: An accessor cannot be declared in an ambient context.

106     get mappingStorage(): MappingStorage;
            ~~~~~~~~~~~~~~
node_modules/@nartc/automapper/dist/automapper.d.ts:110:9 - error TS1086: An accessor cannot be declared in an ambient context.

110     get profileStorage(): ProfileStorage;
            ~~~~~~~~~~~~~~
node_modules/@nartc/automapper/dist/types.d.ts:84:216 - error TS2577: Return type annotation circularly references itself.

84 export declare type DeferFunction<TSource extends Dict<TSource> = any, TDestination extends Dict<TDestination> = any, TSelectorReturn = SelectorReturn<TDestination>> = (source: TSource, sourceMemberPath: string) => ReturnType<Exclude<MemberMapFunction<TSource, TDestination, TSelectorReturn>, MapDeferFunction<TSource, TDestination, TSelectorReturn>>>;
                                                                                                                                                                                                                          ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Below my user.profile.ts file

// AutoMapper
import "reflect-metadata";
import {
    AutoMapper,
    ProfileBase,
    mapFrom,
    Mapper,
    convertUsing,
    Converter
} from "@nartc/automapper";

// Models
import { UserDto } from 'app/_models/user.dto';
import { UserVm } from 'app/_models/user.vm';

class FullNameConverter implements Converter<UserDto, string> {
    convert(source: UserDto): string {
        return source.firstName + " " + source.lastName;
    }
}

export class UserProfile extends ProfileBase {
    constructor(mapper: AutoMapper) {
        super();

        mapper
            .createMap(UserDto, UserVm)
            .forMember(
                d => d.firstName,
                mapFrom(s => "Khang"))
            .forMember(
                d => d.lastName,
                mapFrom(s => s.lastName))
            .forMember(
                d => d.fullName,
                mapFrom(s => s.firstName + " " + s.lastName))
            .forMember(d => d.fullName, convertUsing(new FullNameConverter(), s => s));

        mapper
            .createMap(UserVm, UserDto)
            .forMember(
                d => d.firstName,
                mapFrom(s => s.firstName))
            .forMember(
                d => d.lastName,
                mapFrom(s => s.lastName));
    }
}

user.vm.ts:

// AutoMapper
import { AutoMap } from '@nartc/automapper';

// Vm
import { ProfileVm } from 'app/_models/profile.vm';

export class UserVm {
    @AutoMap() fullName: string;
    @AutoMap() firstName?: string
    @AutoMap() lastName?: string
    @AutoMap(() => ProfileVm) profile!: ProfileVm;
}

user.dto.ts:

// AutoMapper
import { AutoMap } from '@nartc/automapper';

// Dto
import { ProfileDto } from 'app/_models/profile.dto';

export class UserDto {
    @AutoMap() firstName: string;
    @AutoMap() lastName: string;
    @AutoMap() password: string;
    @AutoMap(() => ProfileDto) profile!: ProfileDto;
}

Map object to object

I'm submitting a...


[ ] Regression 
[ ] Bug report
[x] Feature request
[ ] Documentation issue or request
[ ] Support request

The map function accept a source object and the definition of Source and Destination
It would be great if there is another map function that accept the source object + destination object.
My goal is instead of map source object to a new created destination, you map the source object to an existant destination object (so it will be updated)

Mapping uppercase properties and case sensitivity

I'm submitting a...


[ ] Regression
[x] Bug report
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request

Current behavior

1- If I have a property key UpperCase in both source and destination classes it'll throw an Error

Unmapped properties:
-------------------
UpperCase

2- If I have a property key upperCase and UpperCase it'll map both properties with upperCase value.

Expected behavior

Ability to mapping properties that started with uppercase letters, and be case sensitivity in properties names

Minimal reproduction of the problem with instructions

Check this branch case_sensitivity

Environment


Version: 7.0.2
 
For Tooling issues:
- Node version: 12.13.1
- Platform: Mac

Others:

[question] Move `class-transformer` to peer deps

Hi, thanks for this library, I'm really interesting in it, and thinking of using it soon, so I have one minor question/suggestion about moving class-transformer to peer deps, because when using this library via nestjsx-automapper there is a chance that class-transformer is using already in nestjs project. What do you think?

Handle promises inside mapWith TransformationType callback

I'm submitting a...


[ ] Regression
[ ] Bug report
[x] Feature request
[ ] Documentation issue or request
[ ] Support request

Current behavior

When mapping a property wrapped in a promise, mapper cannot retrieve the actual value of it. The only workaround that I've found is implement a mapWith transformation inside Profile and manage promise there. However, as the callback expects to return an actual value, is completely impossible to await promise and return its result.

Expected behavior

Callback inside mapWith (and all others transformation type functions) could expect to receive a raw value or a promise and await its result. This way it could be possible to have lazy loading of entities and, at the same time, map those properties correctly.

Minimal reproduction of the problem with instructions

Here's a Stack Overflow question where I described the problem: https://stackoverflow.com/questions/63439664/how-to-handle-promises-in-mapwith-transformationtype-nartc-automapper

What is the motivation / use case for changing the behavior?

In combination with NestJS and TypeORM, main goal would be to benefit from lazy loading and at the same time map properties to their corresponding nested models.

Environment


"nestjsx-automapper": "^3.0.23"
"@nartc/automapper-transformer-plugin": "^1.0.20"
 
- Node version: v12.18.3
- Platform:  Windows

Generic Mapping

How to map generic classes

For example:

mapper(PagedModel<GetCustomerBase>,GetCustomerResponse)

;

Any way to work with mapped types from `@nestjs/swagger`

I want to use utility functions like OmitType (provided by @nestjs/swagger lib) to do something like this:

import { ApiPropertyOptional, OmitType } from '@nestjs/swagger';

class UserVm { // assuming that each prop can have some kind of ApiProperty decorator
  @AutoMap()
  firstName: string;
  @AutoMap()
  lastName: string;
  @AutoMap()
  about: string;
  @AutoMap()
  @ApiPropertyOptional({ type: String, format: 'date-time' })
  deletedAt?: Date
  @AutoMap()
  deletedBy?: number;
  // ...
}

class NonDeletableUserVm extends OmitType(UserVm, ['deletedAt', 'deletedBy']) {}
// ^ this class will be a swagger schema/model as well

but the annotations generated by @AutoMap() decorator are not inherited when using these helpers functions, so all props annotated with @AutoMap() will not be auto mapped by the mapper (since they're aren't identified).

Maybe this is a limitation of @nestjs/swagger (or TS?) but I'm not sure.

Any thoughts?

Great lib btw ๐Ÿฅฐ


minimal reproduction

https://codesandbox.io/s/nartcautomapper-issue-173-wv1s0

Any mapping always returns an empty object, without any errors

I'm submitting a...


[ x ] Regression
[ ] Bug report
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request

Current behavior

Any mapping always returns an empty object, without any errors

Expected behavior

Correct mapping

Minimal reproduction of the problem with instructions

In versions @nartc/[email protected], [email protected] mapping works as expected.
In versions @nartc/[email protected], [email protected] mapping returns {} (the same code).

What is the motivation / use case for changing the behavior?

Incorrect behavior

Environment

Windows 10
Nest.js
@nartc/[email protected]
[email protected]

i dont know why i can do mapper 2 object without @AutoMap()

i have two object called user and userDto.

user {
@AutoMap()
name: string;

@AutoMap()
password: string;

@AutoMap()
addrId: number;
}
Addr {
id: number,
addr: string
}
userDto {
@AutoMap()
name: string;

@AutoMap()
addr: string
}

when i perform sql by using SELECT user.id, user.passowrd, Addr.addr FROM user LEFT JOIN Addr ON Addr.id = user.addrId. I receive object {id, name, addr}

although I don't have any @AutoMap() for addr, but when I do Mapper.map(userObject, userDtoObject, User). i also have value addr for userDTO.

AutoMapper thinks the string "0.00" is an empty value and maps to `null`

I'm submitting a...


[ ] Regression 
[x] Bug report
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request

Current behavior

AutoMapper thinks the string "0.00" on a source property is an empty value. So, when mapping to the destination, it gets converted to null.

Expected behavior

AutoMapper should preserve this string value and copy it to the destination object's property.

Minimal reproduction of the problem with instructions


// Given this model: 
class Product  {
	@AutoMap() price!: string;
}

// map some object:
const dest = mapper.map({ price: '0.00' }, Product, Product)
// dest === { price: null }

What is the motivation / use case for changing the behavior?

While 0.00 as a number is an "empty" value, the string "0.00" is not. There is a difference between 0.00 and "0.00", as well as "0.00" and "".

Environment


Version: 6.2.0
 
For Tooling issues:
- Node version: 10.15.3
- Platform:  Mac

Others:

Can this work with getter/setter?

Hi! :)

I was wondering, can this mapper work by mapping public attributes to their appropriate setter or getter (depending on the map direction).

Consider this example

class User {
  private _firstname: string;
  public set firstname(value: string) { this._firstname = value; }
  public get firstname(value: string) { return this._firstname; }
}

class UserVm {
  @AutoMap()
  public firstname: string;
}

My questoini is how to get a bi-directional map between User and UserVm? Hopefully not by manually assigning every public property to a setter/getter :)

Thanks!

Source property with value of `false` will map to destination property as `null`.

I'm submitting a...


[ ] Regression 
[x] Bug report
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request

Current behavior

Source property with value of false will map to destination property as null.

Expected behavior

Source property with value of false should map to destination property as false.

Minimal reproduction of the problem with instructions


// Given this model...
class Product {
	@AutoMap() isBundle!: boolean;
}

// map some object
const dest = mapper.map({ isBundle: false }, Product, Product);
// dest = { isBundle: null } 

What is the motivation / use case for changing the behavior?

Boolean values should be preserved during mapping.

Environment


Version: 6.2.0
 
For Tooling issues:
- Node version: 10.15.3
- Platform:  Mac

Others:

Can't build project with Automapper imported in --prod

When you're trying to build project in Production, the following error will occur:
ERROR in ./src/app/app.module.ngfactory.js Module not found: Error: Can't resolve '@nartc/automapper/dist/automapper' in 'D:\test\Automapper\src\app' resolve '@nartc/automapper/dist/automapper' in 'D:\test\Automapper\src\app'

How to reproduce:

  1. Create a new project with 'ng new'
  2. Import Automapper
  3. Create 2 models and a mapping profile for it
  4. Initialize it in app.module constructor
  5. Try to build project

But at last - It building good with 'ng build'.

Full error bellow:

ERROR in ./src/app/app.module.ngfactory.js Module not found: Error: Can't resolve '@nartc/automapper/dist/automapper' in 'D:\test\Automapper\src\app' resolve '@nartc/automapper/dist/automapper' in 'D:\test\Automapper\src\app' Parsed request is a module using description file: D:\test\Automapper\package.json (relative path: ./src/app) Field 'browser' doesn't contain a valid alias configuration resolve as module looking for modules in D:/test/Automapper/ using description file: D:\test\Automapper\package.json (relative path: .) Field 'browser' doesn't contain a valid alias configuration using description file: D:\test\Automapper\package.json (relative path: ./@nartc/automapper/dist/automapper) no extension Field 'browser' doesn't contain a valid alias configuration D:\test\Automapper\@nartc\automapper\dist\automapper doesn't exist .ts Field 'browser' doesn't contain a valid alias configuration D:\test\Automapper\@nartc\automapper\dist\automapper.ts doesn't exist .tsx Field 'browser' doesn't contain a valid alias configuration D:\test\Automapper\@nartc\automapper\dist\automapper.tsx doesn't exist .mjs Field 'browser' doesn't contain a valid alias configuration D:\test\Automapper\@nartc\automapper\dist\automapper.mjs doesn't exist .js Field 'browser' doesn't contain a valid alias configuration D:\test\Automapper\@nartc\automapper\dist\automapper.js doesn't exist as directory D:\test\Automapper\@nartc\automapper\dist\automapper doesn't exist D:\test\Automapper\src\app\node_modules doesn't exist or is not a directory D:\test\Automapper\src\node_modules doesn't exist or is not a directory D:\test\node_modules doesn't exist or is not a directory D:\node_modules doesn't exist or is not a directory looking for modules in D:\test\Automapper\node_modules using description file: D:\test\Automapper\package.json (relative path: ./node_modules) Field 'browser' doesn't contain a valid alias configuration using description file: D:\test\Automapper\node_modules\@nartc\automapper\package.json (relative path: ./dist/automapper) no extension Field 'browser' doesn't contain a valid alias configuration D:\test\Automapper\node_modules\@nartc\automapper\dist\automapper doesn't exist .ts Field 'browser' doesn't contain a valid alias configuration D:\test\Automapper\node_modules\@nartc\automapper\dist\automapper.ts doesn't exist .tsx Field 'browser' doesn't contain a valid alias configuration D:\test\Automapper\node_modules\@nartc\automapper\dist\automapper.tsx doesn't exist .mjs Field 'browser' doesn't contain a valid alias configuration D:\test\Automapper\node_modules\@nartc\automapper\dist\automapper.mjs doesn't exist .js Field 'browser' doesn't contain a valid alias configuration D:\test\Automapper\node_modules\@nartc\automapper\dist\automapper.js doesn't exist as directory D:\test\Automapper\node_modules\@nartc\automapper\dist\automapper doesn't exist [D:\test\Automapper\@nartc\automapper\dist\automapper] [D:\test\Automapper\@nartc\automapper\dist\automapper.ts] [D:\test\Automapper\@nartc\automapper\dist\automapper.tsx] [D:\test\Automapper\@nartc\automapper\dist\automapper.mjs] [D:\test\Automapper\@nartc\automapper\dist\automapper.js] [D:\test\Automapper\src\app\node_modules] [D:\test\Automapper\src\node_modules] [D:\test\node_modules] [D:\node_modules] [D:\test\Automapper\node_modules\@nartc\automapper\dist\automapper] [D:\test\Automapper\node_modules\@nartc\automapper\dist\automapper.ts] [D:\test\Automapper\node_modules\@nartc\automapper\dist\automapper.tsx] [D:\test\Automapper\node_modules\@nartc\automapper\dist\automapper.mjs] [D:\test\Automapper\node_modules\@nartc\automapper\dist\automapper.js] @ ./src/app/app.module.ngfactory.js 13:0-56 14:2665-2678 @ ./src/main.ts @ multi ./src/main.ts

please disable not map assertion error in inherited classes when the base class not included in createMap function

I'm submitting a...


[ ] Regression 
[X] Bug report
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request

Current behavior

throw not map assertion error for inherited class although base class not included.
I have this entity


@Entity()
export class Customer extends BaseEntity {
  @OneToOne(() => User, { eager: true, primary: true })
  @JoinColumn({ name: 'id' })
  @AutoMap(() => User)
  user: User;
}

that extends BaseEntity
I want to map this dto to Customer entity


export class CreateCustomerDto{
  @IsNotEmpty({ always: true })
  @ValidateNested({ always: true })
  @Type(() => CreateUserDto)
  @AutoMap(() => CreateUserDto)
  user: CreateUserDto;
}

when I try to do that I get assertion error for createdAt and updatedAt (fields of BaseEntity) although I dont include BaseEntity in createMap


mapper
      .createMap(CreateCustomerDto, Customer);

Expected behavior

disable not map assertion error in inherited classes when the base class not included in createMap function

Environment


Version: 6.4
 

strange problem when I use auto mapper in docker container

I'm submitting a...


[ ] Regression 
[X] Bug report
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request

Current behavior

Hi thanks for your great library I have strange problem when I use auto mapper in docker container
whereas when I use auomapper in my host os every thing is okey
when I run my project in docker container I get this error
Mapping not found for source class CreateUserDto
but I add this mappings in to profile and import it into module file
profile file:user.profile.ts


import { ProfileBase, Profile, AutoMapper } from 'nestjsx-automapper';
import { CreateUserDto, UserRoDto } from './dto';
import { User } from './user.entity';

@Profile()
export class UserProfile extends ProfileBase {
  constructor(mapper: AutoMapper) {
    super();
    mapper.createMap(User, UserRoDto);
    mapper.createMap(CreateUserDto, User);
  }
}

module file:user.module.ts


import { Module } from '@nestjs/common';
import { TypeOrmModule } from '@nestjs/typeorm';
import { User } from './user.entity';
import { UserService } from './user.service';
import { userProviders } from './user.provider';
import './user.profile';

@Module({
  imports: [TypeOrmModule.forFeature([User])],
  providers: userProviders,
  exports: [UserService],
})
export class UserModule {}

also this is my docker file


FROM node:lts As development

WORKDIR /usr/src/app

COPY package.json ./

RUN yarn install --production=false

COPY . .

RUN yarn build

FROM node:lts as production

WORKDIR /usr/src/app

COPY package.json ./

RUN yarn install --production

COPY . .

COPY --from=development /usr/src/app/dist ./dist

EXPOSE 8090

CMD ["yarn", "start:prod"]

Environment


"@nartc/automapper": "^6.3.11",
"nestjsx-automapper": "^3.0.13",
"@nestjs/core": "^7.2.0",
"ts-node": "^8.10.2",
"typescript": "^3.9.5"
For Tooling issues:
- Node version: 12.18
env variables:
NODE_ENV:production

Error when map from extended class

I'm submitting a...


[ ] Regression 
[x] Bug report
[ ] Feature request
[ ] Documentation issue or request
[ ] Support request

Current behavior

I cant convert to a class that extends a base class, I got this error:

Uncaught Error: Mapping not found for source Object
    at AutoMapper._getMappingForNestedKey (automapper.esm.js:1497)
    at AutoMapper._mapMember (automapper.esm.js:1372)
    at AutoMapper._map (automapper.esm.js:1241)
    at AutoMapper.map (automapper.esm.js:1683)
....

Expected behavior

Able to map values from inheritance classes.

Minimal reproduction of the problem with instructions

class BaseProfile {
    @AutoMap()
    bio: string;
    @AutoMap()
    age: number;
}

class Profile extends BaseProfile {
    other?: any;
}

class User {
    @AutoMap()
    firstName: string;
    @AutoMap()
    lastName: string;
    @AutoMap(() => Profile)
    profile: Profile;
}
class ProfileVm {
    @AutoMap()
    bio: string;
    @AutoMap()
    isAdult: boolean;
}
class UserVm {
    @AutoMap()
    firstName: string;
    @AutoMap()
    lastName: string;
    @AutoMap(() => ProfileVm)
    profile: ProfileVm;
}

Mapper.createMap(Profile, ProfileVm).forMember(
    dest => dest.isAdult,
    opts => opts.mapFrom(src => src.age > 18),
);
Mapper.createMap(User, UserVm);

const user: User = {
    firstName: 'firstName',
    lastName: 'lastName',
    profile: {
        bio: 'bio',
        age: 12,
    },
};

const res = Mapper.map(user, UserVm, User);

What is the motivation / use case for changing the behavior?

to solve this I have to add mapping to some property in the destination:

class Profile extends BaseProfile {
    @AutoMap() // <=== This solve it
    other?: any;
}

Environment


Version: 5.0.8
 
For Tooling issues:
- Node version: 12.13.1
- Platform:  Mac

Others:
- Typescript: 3.8.2
- Nx: 9.0.2
- Angular: 9.0.3
- Nestjs: 6.11.8

Naming convention does not exist (version 6.3.14)

I'm submitting a...


[   ] Regression 
[ X ] Bug report
[   ] Feature request
[ X ] Documentation issue or request
[ X ] Support request

Current behavior

I got two models:

export class User {
  ID: number;
  Name: string
}

and

export class UserDTO {
   name: string;
}

when I try to map them like this:

mapper.createMap(User, UserDTO, { sourceMemberNamingConvention: PascalCaseNamingConvention });

it gives me the following error: Cannot find name 'PascalCaseNamingConvention'.ts(2304) - Which (of course) means it's not imported, however I can't seem to import it from anywhere.. I only have a /dist folder with the types for it, but I can't use it since they are types..

Expected behavior

I would expect it to just import it and make the mapping work. It also isn't described in the documentation where to import it from.

Minimal reproduction of the problem with instructions

See snippet above

What is the motivation / use case for changing the behavior?

Not applicable

Environment

Visual Studio Code 2019
Version: 2019
 
For Tooling issues:
- Node version: 12.16.3 
- Yarn version: 1.22.4 (I use yarn as a PM)
- Platform:  Windows 

Others:

[refactor] Remove class-transformer from dependencies list

I'm submitting a...


[ ] Regression 
[ ] Bug report
[x] Feature request
[ ] Documentation issue or request
[ ] Support request

Current behavior

Currently, @nartc/automapper depends on class-transformer to initialize a new instance of a model. Although this is working well and not bringing too much overhead but it lacks customizability.

Expected behavior

Replace class-transformer with built-in metadata tracker to instantiate models.

Minimal reproduction of the problem with instructions

What is the motivation / use case for changing the behavior?

Lacks of customizability make it hard to grow @nartc/automapper in terms of features and also be bound with class-transformer limitation. There's one issue with moment object right now that there's no way we can fix it unless we come up with our own replacement for class-transformer

Environment


Version: X.Y.Z
 
For Tooling issues:
- Node version: XX  
- Platform:  

Others:

[core] Refactor MappingProfileBase to not having to have an empty constructor

Current:

class UserProfile extends MappingProfileBase {
   constructor() {
      super();
   }

   configure(mapper: AutoMapper): void {
      // configure mapping
   }
}

This approach works fine but it feels boiler-plate-y. Possible solution:

  1. Get rid of configure() method
  2. Turn constructor() into constructor(mapper: AutoMapper) {} and use constructor() to configure the mapping. This will make it feel more inline with .NET AutoMapper API.
  3. Adjust the interfaces and addProfile() method on the AutoMapper.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.