Claude-skill-registry add-domain-entity

install
source · Clone the upstream repo
git clone https://github.com/majiayu000/claude-skill-registry
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/add-domain-entity" ~/.claude/skills/majiayu000-claude-skill-registry-add-domain-entity && rm -rf "$T"
manifest: skills/data/add-domain-entity/SKILL.md
source content

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:

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

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