| name | api-add-domain-entity |
| description | Creates a complete domain entity in a NestJS hexagonal module — entity, repository interface, test builder, unit tests, SQL repository, in-memory repository, mapper, and optionally domain events. Supports both standalone entities and AggregateRoot entities with domain event publishing. Use when adding a new aggregate to a module's domain layer. |
api-add-domain-entity
Creates the full domain + infrastructure stack for one entity. Run before /api-add-command or /api-add-query.
Project context
Read the ## Configuration section in .claude/CLAUDE.md for {SHARED_ROOT} and {MODULE_ROOT}.
Prerequisites
Run these skills first (in order):
/api-init-project — project scaffold
/api-setup-shared — shared base classes (DomainEvent, SqlRepositoryBase, IDateProvider, etc.)
/api-add-module — module scaffold (tokens file, application module)
Steps
-
Determine entity type — Ask: "Does this entity publish domain events?"
- Yes → use AggregateRoot variant (extends
AggregateRoot from @nestjs/cqrs)
- No → use standard variant (standalone class)
-
Domain entity — domain/{entity-name}/{entity-name}.ts
Load references/entity-template.md.
Use the AggregateRoot variant if the entity publishes domain events, standard variant otherwise.
-
Domain events (AggregateRoot entities only) — domain/events/{entity}-{action}.event.ts
Load references/domain-event-template.md.
Create one event class per domain action (e.g., XxxCreatedEvent, XxxUpdatedEvent).
-
Repository interface — domain/{entity-name}/{entity-name}.repository.ts
Load references/repository-template.md.
For read-only access: {entity-name}.reader.ts with IXxxReader.
-
Test builder — domain/{entity-name}/{entity-name}.builder.ts
Load references/builder-template.md.
-
Unit tests — domain/{entity-name}/{entity-name}.spec.ts
Load references/entity-template.md (spec section) for the pattern.
Test business methods using the builder.
For AggregateRoot entities, also test that domain events are emitted correctly.
-
SQL repository — infrastructure/{entity-name}/sql-{entity-name}.repository.ts
Load references/sql-repository-template.md.
- AggregateRoot entities: use
SqlRepositoryBase variant (inherits save(), findById(), delete() with auto event publishing)
- Standard entities: use standalone variant
-
In-memory repository — infrastructure/{entity-name}/in-memory-{entity-name}.repository.ts
Load references/in-memory-repository-template.md.
- AggregateRoot entities: use variant with
entity.uncommit() after save
- Standard entities: use standard variant
-
Mapper — infrastructure/{entity-name}/sql-{entity-name}.mapper.ts
Load references/mapper-template.md.
- AggregateRoot entities: use
EntityMapper instance variant (implements EntityMapper<E, R>)
- Standard entities: use static methods variant
-
DI token — add XXX_REPOSITORY: Symbol("{MODULE_UPPER}_XXX_REPOSITORY") to {module}.tokens.ts.
-
Register provider — add the SQL repository binding to application/{module}.module.ts providers.
Limitations
- Does not create Prisma schema migrations — add the model to
schema.prisma and run prisma migrate dev separately.
IDateProvider is created by /api-setup-shared — pass it as a parameter to createNew() factories (domain code does not use DI).