mapper icon indicating copy to clipboard operation
mapper copied to clipboard

Ability to chain mappers via config

Open samboylett opened this issue 2 years ago • 3 comments

Hey this is a great package and I've been using it all over my projects!

I was wondering if there was a way to configure mappers to chain? I.e., I have a map from A -> B, and B -> C, rather than create a map from A -> C I just want it to run through the 2 existing mappers, rather than having to map A -> B -> C manually.

Thanks :)

samboylett avatar Mar 01 '23 15:03 samboylett

I see. Do you have any proposed API of what the feature could look like?

nartc avatar Mar 10 '23 02:03 nartc

Given it's based off of the c# automapper, maybe ConvertUsing would work? Based off of this stack overflow answer: https://stackoverflow.com/questions/68664720/automapper-map-using-linked-maps-transitive-mapping-chain-maps

samboylett avatar Mar 10 '23 09:03 samboylett

Hm...convertUsing is already a MemberMapFunction, making another convertUsing as MappingConfigurationFunction will be confusing.

That said, constructUsing seems to work fine.

class A {
  @AutoMap()
  a!: string;
}

class B {
  @AutoMap()
  b!: string;
}

class C {
  @AutoMap()
  c!: string;
  extraC!: string;
}

createMap(
  mapper,
  A,
  B,
  forMember(
    (d) => d.b,
    mapFrom((s) => s.a + "!!!")
  )
);
createMap(
  mapper,
  B,
  C,
  forMember(
    (d) => d.c,
    mapFrom((s) => s.b + "!!!")
  )
);
createMap(
  mapper,
  A,
  C,
  constructUsing((sourceObject) => {
    const intermediate = mapper.map(sourceObject, A, B);
    return mapper.map(intermediate, B, C);
  }),
  forMember(
    (d) => d.extraC,
    mapFrom((s) => s.a + " extra!!")
  )
);

const a = new A();
a.a = "value";

const c = mapper.map(a, A, C);
console.log(c);
expect(c.c).toEqual("value!!!!!!");
expect(c.extraC).toEqual("value extra!!");

We only need to make sure that Mapping<A, B> and Mapping<B, C> are available. Maybe you can test it out for your scenario and report back?

nartc avatar Mar 10 '23 22:03 nartc

It might have taken over a year, but I can confirm constructUsing works for my use case! Thanks :)

samboylett avatar Apr 11 '24 09:04 samboylett