Skip to content

Contracts

Contract declarations keep typings for handlers in one place.
Both QueryContract and CommandContract are supported.

Strict Contract in One Place

Each handler defines its contract within itself:

typescript
import type { QueryContract, CommandContract } from "awilixify";

export class GetUserQueryHandler {
  static readonly key = "users/get-user";
  declare readonly contract: QueryContract<
    typeof GetUserQueryHandler.key,
    { userId: string },
    User
  >;
}

export class CreateUserCommandHandler {
  static readonly key = "users/create-user";
  declare readonly contract: CommandContract<
    typeof CreateUserCommandHandler.key,
    { email: string; name: string },
    { id: string }
  >;
}

Why contracts matter

Contracts are the single source of truth for typing a use-case:

  • key (use-case identifier)
  • payload shape
  • return/response shape
  • context shape(this['contract']['context']) inferred from pre-handlers
  • scenario-based context/return variations

Mediator uses module-registered contracts to know which handlers are available in that module and to type execute(...) calls correctly.