Claude-skill-registry kratos-mapper
Generates bidirectional mapper functions (transformers/converters/adapters) between protobuf DTOs and business domain models for go-kratos services. Creates type-safe conversions with proper field mapping, handles timestamps, enums, optional fields, and pagination metadata transformations. Use when converting DTOs to domain models, transforming proto to biz models, mapping requests/responses, implementing type conversions, creating entity transformers, or handling DTO transformations between layers.
git clone https://github.com/majiayu000/claude-skill-registry
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/kratos-mapper" ~/.claude/skills/majiayu000-claude-skill-registry-kratos-mapper && rm -rf "$T"
skills/data/kratos-mapper/SKILL.md<quick_start> For an entity, create mappers in
internal/service/mapper.go:
// Request → Business Model func {Entity}FromCreateRequest(req *pb.Create{Entity}Request) *domain.{Entity} { return &domain.{Entity}{ Name: req.Name, // Map fields... } } // Business Model → Proto Response func toProto{Entity}(e *domain.{Entity}) *pb.{Entity} { return &pb.{Entity}{ Id: e.ID, Name: e.Name, // Map fields... } } **Import**: `import "{service}/internal/biz/domain"`
</quick_start>
<mapper_patterns>
Common Mapper Patterns
Request to Business Model:
func {Entity}FromCreateRequest(req *pb.Create{Entity}Request) *domain.{Entity} func {Entity}FromUpdateRequest(req *pb.Update{Entity}Request, id uint64) *domain.{Entity}
Business Model to Proto:
func toProto{Entity}(e *domain.{Entity}) *pb.{Entity} func toProto{Entities}(list []*domain.{Entity}) []*pb.{Entity}
List Options:
func NewList{Entities}Options(req *pb.List{Entities}Request) *domain.List{Entities}Options { return &domain.List{Entities}Options{ Pagination: pagination.OffsetPaginationParams{ Offset: req.Offset, Limit: req.Limit, }, } }
Pagination Meta:
func toProtoPaginationMeta(meta *pagination.PaginationMeta) *pb.PaginationMeta { return &pb.PaginationMeta{ Total: meta.Total, Offset: meta.Offset, Limit: meta.Limit, } }
</mapper_patterns>
<naming_conventions>
Naming Rules
Proto → Business:
{Entity}From{Operation}Request
- Example:
,SymbolFromCreateRequestProductFromUpdateRequest
Business → Proto:
toProto{Entity} or toProto{Entities}
- Example:
,toProtoSymboltoProtoSymbols
Options:
NewList{Entities}Options
Helpers:
toProto{Type} for common types
- Example:
,toProtoPaginationMeta
</naming_conventions>toProtoTimestamp
<type_conversions>
Common Type Conversions
IDs:
uint64 ↔ uint64 (direct)
Strings: string ↔ string (direct)
Timestamps: time.Time ↔ *timestamppb.Timestamp
CreatedAt: timestamppb.New(e.CreatedAt)
Optional Fields: Use pointers
// Business has *string, proto has string Email: func() string { if e.Email != nil { return *e.Email } return "" }()
Enums: Map string to proto enum
Status: pb.Status(pb.Status_value[e.Status])
</type_conversions>
<file_organization>
Where to Put Mappers
Single entity:
internal/service/mapper.go (all mappers)
Multiple entities: internal/service/{entity}_mapper.go (per entity)
Keep mapper functions close to service handlers for easy reference. </file_organization>
<success_criteria> Mapper functions are correct when:
- Naming follows conventions ({Entity}From* vs toProto*)
- All proto fields mapped to business model fields
- Type conversions handled (timestamps, optionals, enums)
- Nil checks for optional/pointer fields
- List mappers use range loops
- Pagination helpers created if needed
- Functions are pure (no side effects) </success_criteria>