Skip to content

Mapper DTO Options

Overview

All toDto methods on mappers accept an optional IMapperOptions parameter that controls runtime behavior when converting a domain entity to a response DTO. The default is to validate the output via Zod schema parse.

Interface

Defined in apps/api/src/shared/infrastructure/mapper/mapper.base.ts:

ts
export interface IMapperOptions {
  validate?: boolean;
}

export const DefaultMapperOptions: IMapperOptions = {
  validate: true,
};

Usage Pattern

Every mapper's toDto method follows this signature:

ts
static toDto(
  domain: SomeEntity,
  options: IMapperOptions = DefaultMapperOptions,
): SomeResponseDto {
  const dto = { /* map fields */ };
  return options.validate ? someResponseSchema.parse(dto) : dto;
}

validate: true (default)

The assembled plain object is passed through schema.parse(dto). This throws a ZodError if the output does not conform to the schema, acting as a runtime contract check before the DTO leaves the server.

validate: false

Skips schema parsing. Useful in internal pipelines or tests where the caller already guarantees shape correctness and the overhead or strict coercion of Zod is undesirable.

Examples

Session mapper (session.mapper.ts):

ts
static toDto(
  domain: Session,
  isCurrent: boolean,
  options: IMapperOptions = DefaultMapperOptions,
): SessionResponseDto {
  const dto = { id: domain.id, isCurrent, ... };
  return options.validate ? sessionResponseSchema.parse(dto) : dto;
}

Agency mapper (agency.mapper.ts):

ts
static toDto(
  domain: Agency,
  options: IMapperOptions = DefaultMapperOptions,
): AgencyResponseDto {
  const dto = { id: domain.id, name: domain.name, ... };
  return options.validate ? agencyResponseSchema.parse(dto) : dto;
}

Decision Rationale

  • Validation by default prevents malformed DTOs from reaching the HTTP response layer.
  • The opt-out flag avoids double-parsing in contexts that already validated upstream (e.g., test fixtures, internal service calls).
  • Keeping the interface in mapper.base.ts ensures consistent options across all modules.