Agent skill

add-domain-entity

Create domain layer components: models, repository interfaces, marshallers, and implementations. Use when: (1) adding domain model in internal/domain/model/, (2) creating repository interface in internal/domain/repository/, (3) implementing repository with marshaller in internal/infrastructure/{db}/. This is Step 2 of CRUD workflow (after add-database-table, before add-api-endpoint).

Stars 163
Forks 31

Install this agent skill to your Project

npx add-skill https://github.com/majiayu000/claude-skill-registry/tree/main/skills/data/add-domain-entity

SKILL.md

Add Domain Entity

Create domain layer components for a new entity following DDD patterns.

Prerequisites

  • Database table created (use add-database-table skill first)
  • SQLBoiler model generated via make migrate.up

Quick Workflow

1. Domain Model     → internal/domain/model/{entity}.go
2. Domain Error     → internal/domain/errors/errors.go
3. Repository Interface → internal/domain/repository/{entity}.go
4. Marshaller       → internal/infrastructure/{db}/internal/marshaller/{entity}.go
5. Repository Impl  → internal/infrastructure/{db}/repository/{entity}.go
6. Generate Mocks   → make generate.mock

Step 1: Create Domain Model

Location: internal/domain/model/{entity}.go

Create the entity struct, constructor, update methods, and type aliases.

Key requirements:

  • Use id.New() for ID generation in constructor
  • Set both CreatedAt and UpdatedAt to the same time parameter
  • Define ReadonlyReference for relations (always nil in constructor)
  • Create slice type alias: type Examples []*Example

See: references/domain-model-patterns.md

Step 2: Add Domain Error

Location: internal/domain/errors/errors.go

Add a not-found error for the entity:

go
ExampleNotFoundErr = NewNotFoundError("E2xxxxx", "Example not found")

Follow error code conventions from .claude/rules/domain-errors.md.

Step 3: Create Repository Interface

Location: internal/domain/repository/{entity}.go

Define the repository interface with standard CRUD operations and query structs.

Key requirements:

  • Add //go:generate directive for mock generation
  • Use nullable.Type[T] for optional enum/custom type filter fields
  • Embed BaseGetOptions / BaseListOptions in query structs

See: references/repository-patterns.md

Step 4: Create Marshaller

Location: internal/infrastructure/{mysql|postgresql|spanner}/internal/marshaller/{entity}.go

Convert between DB models and domain models.

Key requirements:

  • Related entity's ReadonlyReference must remain nil (no recursive loading)
  • Use var declaration pattern for nullable timestamp fields
  • Include both ToModel and ToDBModel functions

See: references/marshaller-patterns.md

Step 5: Create Repository Implementation

Location: internal/infrastructure/{mysql|postgresql|spanner}/repository/{entity}.go

Implement the repository interface using SQLBoiler.

Key requirements:

  • Use transactable.GetContextExecutor(ctx) for all DB operations
  • Implement buildListQuery helper for reusable filter logic
  • Implement buildPreload helper for relation loading
  • Use base helper functions: addForUpdateFromBaseGetOptions, addForUpdateFromBaseListOptions

See: references/repository-patterns.md

Step 6: Generate Mocks

bash
make generate.mock

This generates mock implementations in internal/domain/repository/mock/.

Checklist

Domain Model

  • Entity struct with all fields
  • ReadonlyReference for relations (if any)
  • Constructor with id.New() and ReadonlyReference: nil
  • Update method using null.* types for optional fields
  • Slice type alias (Examples []*Example)
  • Helper methods on slice (IDs(), MapByID())

Status/Enum Types (if needed)

  • Type definition with Unknown as first constant
  • String() and Valid() methods
  • New{Type}(str string) constructor

Repository

  • Interface with //go:generate directive
  • Query structs with nullable.Type[T] for optional enums
  • Domain error added for not-found case

Implementation

  • Marshaller with ToModel, ToDBModel, ToModels, ToDBModels
  • Marshaller handles ReadonlyReference correctly
  • Repository implementation with all CRUD methods
  • buildListQuery and buildPreload helpers
  • Mocks generated

Next Steps

After creating domain entity, use add-api-endpoint skill to create:

  • Usecase input/output structs
  • Interactor interface and implementation
  • Protocol Buffers definition
  • gRPC handler

Didn't find tool you were looking for?

Be as detailed as possible for better results