Skip to content

platform-mapping

Type-safe object-to-object mapping framework for transforming domain entities into response DTOs. Extracted from platform-core to provide a focused, independently versionable mapping module.

Package: @breadstone/archipel-platform-mapping

npm install @breadstone/archipel-platform-mapping

Installation

typescript
import {
  MappingModule,
  MappingService,
  MappingProfileBase,
  MappingKey,
  MappingError,
  MappingNotRegisteredError,
  TypeMappingNotRegisteredError,
} from '@breadstone/archipel-platform-mapping';

Defining Mapping Keys

Mapping keys are branded constants that provide compile-time safety for source → destination pairs:

typescript
import { MappingKey } from '@breadstone/archipel-platform-mapping';
import type { IUserEntity } from './entities';
import type { UserResponse } from './responses';

export const USER_TO_RESPONSE = new MappingKey<IUserEntity, UserResponse>('UserEntity→UserResponse');
export const USER_TO_SUMMARY = new MappingKey<IUserEntity, UserSummary>('UserEntity→UserSummary');

Creating a Mapping Profile

Profiles group related mappings into cohesive, injectable classes:

typescript
import { Injectable } from '@nestjs/common';
import { MappingProfileBase, type IMappingBuilder } from '@breadstone/archipel-platform-mapping';
import { USER_TO_RESPONSE, USER_TO_SUMMARY } from './mapping-keys';

@Injectable()
export class UserMappingProfile extends MappingProfileBase {
  public override configure(builder: IMappingBuilder): void {
    builder.createKeyedMap(USER_TO_RESPONSE, (source) => ({
      id: source.id,
      name: source.userName,
      email: source.email,
      verified: source.isVerified,
      roles: [...source.roles],
    }));

    builder.createKeyedMap(USER_TO_SUMMARY, (source) => ({
      id: source.id,
      displayName: source.userName ?? source.email ?? 'Anonymous',
    }));
  }
}

Registering Profiles in a Module

typescript
import { Module } from '@nestjs/common';
import { MappingModule } from '@breadstone/archipel-platform-mapping';
import { UserMappingProfile } from './mappers/UserMappingProfile';

@Module({
  imports: [MappingModule.withProfiles([UserMappingProfile])],
})
export class AppModule {}

Using in a Controller

typescript
import { Controller, Get, Param } from '@nestjs/common';
import { MappingService } from '@breadstone/archipel-platform-mapping';
import { USER_TO_RESPONSE } from './mapping-keys';

@Controller('users')
export class UserController {
  constructor(
    private readonly _userService: UserService,
    private readonly _mappingService: MappingService,
  ) {}

  @Get(':id')
  public async getUser(@Param('id') id: string): Promise<UserResponse> {
    const entity = await this._userService.findById(id);
    return this._mappingService.map(USER_TO_RESPONSE, entity);
  }
}

Error Classes

ErrorDescription
MappingErrorBase error for all mapping failures
MappingNotRegisteredErrorThrown when a mapping key has no registered map
TypeMappingNotRegisteredErrorThrown when a type-based mapping is not found

API Reference

The auto-generated API reference is published when API docs are generated for this package.

Released under the MIT License.