| name | echonext-database |
| description | Work with EchoNext's database layer: GORM models, the generic Repository[T] pattern from pkg/contrib/database, and Atlas migrations/seeds via the CLI. Use when defining models, querying/persisting data, or creating and applying migrations in an echonext project. |
| license | MIT |
| metadata | {"version":"0.1.0"} |
EchoNext Database
EchoNext uses GORM for persistence and Atlas for migrations. The optional
pkg/contrib/database package adds a generic, type-safe Repository[T] so you
don't rewrite CRUD per model.
Models
Plain GORM structs (see the echonext-domain skill for the conventional layout):
type User struct {
ID uint `gorm:"primaryKey"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt gorm.DeletedAt `gorm:"index"`
Email string `gorm:"unique;not null"`
Name string `gorm:"not null"`
}
func (User) TableName() string { return "users" }
Repository[T]
pkg/contrib/database provides a generic repository. Construct it with the
model type and a *gorm.DB:
import "github.com/abdussamadbello/echonext/pkg/contrib/database"
repo := database.NewRepository[User](db)
Core methods (from the Repository[T] interface):
repo.Create(&user)
user, err := repo.Find(1)
users, err := repo.FindAll()
repo.Update(&user)
repo.Delete(1)
count, err := repo.Count()
Chainable query builders return the repository so you can compose, then call a
terminal method:
recent, err := repo.
Where("active = ?", true).
Order("created_at DESC").
Limit(20).
Offset(20).
FindAll()
err := db.Transaction(func(tx *gorm.DB) error {
return repo.WithTx(tx).Create(&user)
})
Available builders: Where(query, args...), Order(value), Limit(n),
Offset(n), WithTx(tx); DB() returns the underlying *gorm.DB for anything
the repository doesn't cover.
Use Repository[T] for generic CRUD. The default echonext generate domain
service holds a raw *gorm.DB instead — either is fine; pick one per project
and stay consistent.
Migrations (Atlas via the CLI)
echonext db init
echonext db migrate:diff add_users
echonext db migrate
echonext db migrate:status
echonext db migrate:down
echonext db migrate:new add_index
echonext db migrate:lint
echonext db schema:inspect
Typical loop: edit model.go → db migrate:diff <name> → review the generated
SQL → db migrate.
Seeding
echonext db seed
For loading fixtures in tests, use the contrib testing helpers instead (see
the echonext-testing skill), not the seed command.
Checklist
- Models are GORM structs with a
TableName(); use pointers/omitempty only
where semantics require it.
- Prefer
database.NewRepository[T](db) for CRUD; drop to repo.DB() for
bespoke queries.
- After any model change, run
db migrate:diff <name> then db migrate.
- Review generated migration SQL before applying it.