go-create-repository

Generate repository port interfaces and implementations for Pingo GO modular architechture conventions.

Safety Notice

This listing is imported from skills.sh public index metadata. Review upstream SKILL.md and repository scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "go-create-repository" with this command: npx skills add cristiano-pacheco/ai-rules/cristiano-pacheco-ai-rules-go-create-repository

Go Create Repository

Generate repository port interfaces and implementations for Pingo GO modular architechture conventions.

Two-File Pattern

Every repository requires two files:

  • Port interface: internal/modules/<module>/ports/<entity>_repository.go

  • Repository implementation: internal/modules/<module>/repository/<entity>_repository.go

Port Interface Structure

Location: internal/modules/<module>/ports/<entity>_repository.go

package ports

import ( "context" "github.com/cristiano-pacheco/pingo/internal/modules/<module>/model" )

type EntityRepository interface { FindAll(ctx context.Context) ([]model.EntityModel, error) FindByID(ctx context.Context, id uint64) (model.EntityModel, error) Create(ctx context.Context, entity model.EntityModel) (model.EntityModel, error) Update(ctx context.Context, entity model.EntityModel) (model.EntityModel, error) Delete(ctx context.Context, id uint64) error }

Pagination variant:

FindAll(ctx context.Context, page, pageSize int) ([]model.EntityModel, int64, error)

Custom methods: Add domain-specific queries as needed (e.g., FindByName , AssignContacts ).

Repository Implementation Structure

Location: internal/modules/<module>/repository/<entity>_repository.go

package repository

import ( "context" "errors"

"github.com/cristiano-pacheco/bricks/pkg/errs"
"github.com/cristiano-pacheco/bricks/pkg/otel/trace"
"github.com/cristiano-pacheco/pingo/internal/modules/&#x3C;module>/model"
"github.com/cristiano-pacheco/pingo/internal/modules/&#x3C;module>/ports"
"github.com/cristiano-pacheco/pingo/internal/shared/database"
"gorm.io/gorm"

)

type EntityRepository struct { *database.PingoDB }

var _ ports.EntityRepository = (*EntityRepository)(nil)

func NewEntityRepository(db *database.PingoDB) *EntityRepository { return &EntityRepository{db} }

Method Implementations

FindAll (Simple)

func (r *EntityRepository) FindAll(ctx context.Context) ([]model.EntityModel, error) { ctx, otelSpan := trace.Span(ctx, "EntityRepository.FindAll") defer otelSpan.End()

entities, err := gorm.G[model.EntityModel](r.DB).Find(ctx)
if err != nil {
	return nil, err
}
return entities, nil

}

FindAll (Paginated)

func (r *EntityRepository) FindAll(ctx context.Context, page, pageSize int) ([]model.EntityModel, int64, error) { ctx, otelSpan := trace.Span(ctx, "EntityRepository.FindAll") defer otelSpan.End()

offset := (page - 1) * pageSize

var total int64
if err := r.DB.Model(&#x26;model.EntityModel{}).Count(&#x26;total).Error; err != nil {
	return nil, 0, err
}

entities, err := gorm.G[model.EntityModel](r.DB).
	Limit(pageSize).
	Offset(offset).
	Find(ctx)
if err != nil {
	return nil, 0, err
}

return entities, total, nil

}

FindByID

func (r *EntityRepository) FindByID(ctx context.Context, id uint64) (model.EntityModel, error) { ctx, otelSpan := trace.Span(ctx, "EntityRepository.FindByID") defer otelSpan.End()

entity, err := gorm.G[model.EntityModel](r.DB).
	Where("id = ?", id).
	Limit(1).
	First(ctx)
if err != nil {
	if errors.Is(err, gorm.ErrRecordNotFound) {
		return model.EntityModel{}, errs.ErrRecordNotFound
	}
	return model.EntityModel{}, err
}
return entity, nil

}

Create

func (r *EntityRepository) Create(ctx context.Context, entity model.EntityModel) (model.EntityModel, error) { ctx, otelSpan := trace.Span(ctx, "EntityRepository.Create") defer otelSpan.End()

err := gorm.G[model.EntityModel](r.DB).Create(ctx, &#x26;entity)
return entity, err

}

Update

func (r *EntityRepository) Update(ctx context.Context, entity model.EntityModel) (model.EntityModel, error) { ctx, otelSpan := trace.Span(ctx, "EntityRepository.Update") defer otelSpan.End()

_, err := gorm.G[model.EntityModel](r.DB).Updates(ctx, entity)
if err != nil {
	return model.EntityModel{}, err
}
return entity, nil

}

Delete

func (r *EntityRepository) Delete(ctx context.Context, id uint64) error { ctx, otelSpan := trace.Span(ctx, "EntityRepository.Delete") defer otelSpan.End()

rowsAffected, err := gorm.G[model.EntityModel](r.DB).
	Where("id = ?", id).
	Delete(ctx)
if err != nil {
	return err
}
if rowsAffected == 0 {
	return errs.ErrRecordNotFound
}
return nil

}

Custom Query (by field)

func (r *EntityRepository) FindByName(ctx context.Context, name string) (model.EntityModel, error) { ctx, otelSpan := trace.Span(ctx, "EntityRepository.FindByName") defer otelSpan.End()

entity, err := gorm.G[model.EntityModel](r.DB).
	Where("name = ?", name).
	Limit(1).
	First(ctx)
if err != nil {
	if errors.Is(err, gorm.ErrRecordNotFound) {
		return model.EntityModel{}, errs.ErrRecordNotFound
	}
	return model.EntityModel{}, err
}
return entity, nil

}

Transaction (relationship operations)

func (r *EntityRepository) AssignRelated(ctx context.Context, entityID uint64, relatedIDs []uint64) error { ctx, otelSpan := trace.Span(ctx, "EntityRepository.AssignRelated") defer otelSpan.End()

tx := r.DB.Begin()

_, err := gorm.G[model.EntityRelationModel](tx).
	Where("entity_id = ?", entityID).
	Delete(ctx)
if err != nil {
	tx.Rollback()
	return err
}

var relations []model.EntityRelationModel
for _, relatedID := range relatedIDs {
	relations = append(relations, model.EntityRelationModel{
		EntityID:  entityID,
		RelatedID: relatedID,
	})
}

err = gorm.G[model.EntityRelationModel](tx).CreateInBatches(ctx, &#x26;relations, len(relations))
if err != nil {
	tx.Rollback()
	return err
}

if commitErr := tx.Commit().Error; commitErr != nil {
	return commitErr
}

return nil

}

Fx Wiring

Add to internal/modules/<module>/fx.go :

fx.Provide( fx.Annotate( repository.NewEntityRepository, fx.As(new(ports.EntityRepository)), ), ),

Critical Rules

  • Struct: Embed *database.PingoDB only

  • Constructor: MUST return pointer *EntityRepository

  • Interface assertion: Add var _ ports.EntityRepository = (*EntityRepository)(nil) below struct

  • Tracing: Every method MUST start with ctx, otelSpan := trace.Span(ctx, "Repo.Method") and defer otelSpan.End()

  • Queries: Use gorm.GModel pattern for all queries

  • First queries: Add .Limit(1) before .First(ctx)

  • Not found: Return errs.ErrRecordNotFound when errors.Is(err, gorm.ErrRecordNotFound)

  • Delete: Check rowsAffected == 0 and return errs.ErrRecordNotFound

  • Transactions: Use tx := r.DB.Begin() , rollback on error, commit at end

  • No comments: Do not add redundant comments above methods

  • Validation: Run make lint and make nilaway after generation

  • Add detailed comment on interfaces: Provide comprehensive comments on the port interfaces to describe their purpose and usage

Workflow

  • Create port interface in ports/<entity>_repository.go

  • Create repository implementation in repository/<entity>_repository.go

  • Add Fx wiring to module's fx.go

  • Run make lint to verify

  • Run make nilaway for static analysis

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

go-chi-handler

No summary provided by upstream source.

Repository SourceNeeds Review
General

go-unit-tests

No summary provided by upstream source.

Repository SourceNeeds Review
General

go-integration-tests

No summary provided by upstream source.

Repository SourceNeeds Review
General

go-cache

No summary provided by upstream source.

Repository SourceNeeds Review