Mapping system

AutoMap, createMap, AutoMapper, and mapping registration between classes.

Koala Nest includes a mapping system inspired by AutoMapper (.NET). It converts objects between entities, requests, responses, and DTOs declaratively.

Component Function
@AutoMap() Marks mappable properties on a class
createMap() Registers mapping between source and destination
forMember() Customizes mapping of specific properties
AutoMapper.map() Performs conversion between two classes
MappingStore Stores mapping metadata in memory
MappingProvider Registers mappings on application startup
typescript
export function AutoMap<T>(config?: AutoMapConfig<T>) {
  return function (target: any, propertyKey: string) {
    const compositionType: (() => any) | undefined = config?.type;

    MappingStore.setProp(target.constructor, propertyKey, compositionType);
  };
}

Usage in entity:

typescript
@OneToMany(() => PersonContact, (contact) => contact.person, {
  cascade: true,
  onDelete: 'CASCADE',
})
@AutoMap({ type: () => PersonContact })
contacts: PersonContact[];

Create one mapper class per resource with a static createMap() method:

typescript
export class PersonMapper {
  static createMap() {
    createMap(Person, CreatePersonResponse);

    createMap(Person, ReadPersonResponse);
    createMap(PersonAddress, ReadPersonAddressResponse);
    createMap(PersonContact, ReadPersonContactResponse);

    createMap(CreatePersonRequest, Person);
    createMap(CreatePersonAddressRequest, PersonAddress);
    createMap(CreatePersonContactRequest, PersonContact);

    createMap(UpdatePersonRequest, Person);
    createMap(UpdatePersonAddressRequest, PersonAddress);
    createMap(UpdatePersonContactRequest, PersonContact);

    createMap(ReadManyPersonRequest, PersonQueryDto);
    createMap(Person, ReadManyPersonResponseItem);
  }
}

Register in MappingProvider (loaded by ControllerModule):

typescript
@Injectable()
export class MappingProvider {
  constructor() {
    PersonMapper.createMap();
  }
}
typescript
const person = AutoMapper.map(
  new CreatePersonValidator(req).validate(),
  CreatePersonRequest,
  Person,
);

return AutoMapper.map(createdPerson, Person, CreatePersonResponse);

AutoMapper resolves properties by name, maps nested objects recursively, and iterates arrays automatically.

For updates, load the entity from the database and apply the payload manually (as in UpdatePersonHandler). Persisted collections must be replaced by the request list — the expected behavior with TypeORM cascade + orphanedRowAction: 'delete': on save, items missing from the collection become orphans and are removed.

typescript
person.contacts = validated.contacts.map((contactRequest) => {
  if (contactRequest.id) {
    const existing = person.contacts.find((c) => c.id === contactRequest.id);
    if (existing) {
      existing.contact = contactRequest.contact;
      return existing;
    }
  }
  const contact = new PersonContact();
  contact.contact = contactRequest.contact;
  contact.person = person;
  return contact;
});

Do not append to persisted collections; save treats the list as the full state.

The forMember function allows customizing the mapping of a property. It is not used in the template's PersonMapper, but is available in src/core/tools/mapping/for-member.ts:

typescript
export function forMember<TTarget, TSource>(
  targetProp: keyof TTarget,
  map: (source: TSource) => TTarget[keyof TTarget],
): Partial<ForMemberResult<TTarget, TSource>> {
  return {
    [targetProp]: map,
  } as Partial<ForMemberResult<TTarget, TSource>>;
}

Pass the result as the third argument to createMap().

  • Mapping not found for {TargetClass}: the source→destination pair was not registered with createMap().
  • Target properties not found for {TargetClass}: the destination class has no properties marked with @AutoMap().

Always register new mapping pairs when adding requests, responses, or entities.

Koala Nest

A facilitator for building NestJS APIs with DDD architecture. Code copied into your repository — readable, adaptable, and under your control.

Creator

igordrangel.com.br

Design, back-end, and product strategy.

Quick Commands

Global CLI and scripts in the generated project

  • bun install -g @koalarx/nest
  • kl-nest new
  • kl-nest add cache
  • bun run migration:run # CRUD template
  • kl-nest --help
© 2026 Koala NestBuilt for NestJS developers and AI-assisted workflows.