lagodev

module
v0.19.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 4, 2026 License: MIT

README

lagodev

Go Reference Go Report Card Tests Discussions

Laravel-grade developer experience for Go. lagodev is a full backend toolkit — migrations, an Eloquent-style ORM, factories, an Artisan-style CLI, and a native HTTP framework — that you can drop into any Go project. Use the whole stack, or pick the parts that fit.

No router required. lagodev's web package is a complete Laravel-style HTTP framework. Already on Gin/Fiber/Echo? The ORM works identically there — see docs/FRAMEWORK_INTEGRATION.md.

Why lagodev?

One cohesive stack instead of gluing five libraries together — the ORM, migrations, factories, scheduler, queue, mailer, and HTTP framework all share the same DB connection, logger, and config object. The developer experience reads like Laravel; the ORM is generics-based, so Query[T] gives you compile-time-typed rows without code generation. The web package is secure-by-default — CSRF, security headers, body limits, rate-limit middleware, and validation are one line each, not a weekend of integration.


Highlights

  • Web frameworkweb.App, web.Router, web.Context. Handlers return (any, error) and the framework turns them into JSON responses, including the 404 / 500 / 204 status mapping. Resource routes register in a single call: app.Resource("posts", ctrl).
  • Secure by defaultweb.SecurityHeaders() (CSP / X-Frame-Options / Referrer-Policy / Permissions-Policy / nosniff), web.CSRF() with double-submit cookie + constant-time compare, web.RateLimit() / web.Throttle() per IP, web.BodyLimit() against payload-DoS, web.RequestID() for tracing, hardened web.CORS() (rejects unsafe wildcard + credentials), c.SetCookie() with HttpOnly/Secure/ SameSite=Lax defaults. See SECURITY.md.
  • Validationc.BindAndValidate(&dst) with struct-tag rules (required,min=N,max=N,email,url,oneof=...,uuid,...). Failures auto-map to HTTP 422 with {"errors": {field: msg}}.
  • Schema builderschema.Create("users", func(t *schema.Blueprint) { … }) compiles to PostgreSQL, MySQL, or SQLite. Extensible via database.Grammar.
  • Migration engine — transactional up/rollback/refresh/fresh/ reset/status/step, batching, advisory locking, checksums, SQL preview, dry-run mode.
  • ORMorm.Model base type, generic orm.Query[T], hooks (BeforeCreate/AfterUpdate/…), soft deletes, casts, allocation- conscious reflection cache.
  • Query builder — chainable Where/OrWhere/WhereIn/OrderBy/ Latest/Join/GroupBy/Having/LockForUpdate with dialect-correct placeholders.
  • RelationsHasOne / HasMany / BelongsTo / BelongsToMany / polymorphic Morph* with single-query eager-loading.
  • Factories & seedersfactory.New[T] with states + faker, topologically-ordered seeders, transactional execution.
  • Artisan CLImake:model, make:migration, make:seeder, make:factory, make:test, make:service, make:controller, make:crud, migrate*, db:*, env*, init. Stub-based, with override hooks. Two interchangeable binaries: lago and artisan.
  • Driver-agnostic — PostgreSQL (pgx), MySQL (mysql), SQLite (mattn/go-sqlite3) ship in-box. Add your own with a Grammar implementation.

Quick tour — the full stack in 60 lines

package main

import (
    "github.com/devituz/lagodev/database"
    _ "github.com/devituz/lagodev/drivers/sqlite"
    "github.com/devituz/lagodev/migrations"
    "github.com/devituz/lagodev/orm"
    "github.com/devituz/lagodev/schema"
    "github.com/devituz/lagodev/web"
)

type Post struct {
    orm.Model
    Title string
    Body  string
}

func init() {
    migrations.Register(migrations.Define("0001_posts",
        func(c *migrations.Context) error {
            return c.Schema(schema.Create("posts", func(t *schema.Blueprint) {
                t.ID(); t.String("title"); t.Text("body")
                t.Timestamps()
            }))
        },
        func(c *migrations.Context) error {
            return c.Schema(schema.DropIfExists("posts"))
        },
    ))
}

type PostController struct{ Conn *database.Connection }

func (p *PostController) Index(c *web.Context) (any, error) {
    var out []Post
    return out, orm.Query[Post](p.Conn).OrderBy("id", "desc").Get(c.Ctx(), &out)
}
func (p *PostController) Show(c *web.Context) (any, error) {
    return orm.Query[Post](p.Conn).Find(c.Ctx(), c.ParamUint("id"))
}
func (p *PostController) Store(c *web.Context) (any, error) {
    var x Post
    if err := c.Bind(&x); err != nil { return nil, err }
    return c.Created(x), orm.Save(c.Ctx(), p.Conn, &x)
}
func (p *PostController) Update(c *web.Context) (any, error)  { return nil, nil }
func (p *PostController) Destroy(c *web.Context) (any, error) { return nil, nil }

func main() {
    conn, _ := database.Global.Open("default", database.Config{
        Driver: "sqlite", DSN: "file::memory:?cache=shared",
    })

    app := web.New(
        web.WithDatabase(conn),
        web.WithMigrations(nil),
    )
    app.Resource("posts", &PostController{Conn: conn})
    app.MustRun(":8080")
}
go run .
curl -X POST http://localhost:8080/posts -d '{"title":"hi","body":"x"}'
curl http://localhost:8080/posts

Installation

go get github.com/devituz/lagodev@latest

Blank-import the driver you want:

_ "github.com/devituz/lagodev/drivers/postgres"  // pgx
_ "github.com/devituz/lagodev/drivers/mysql"     // go-sql-driver/mysql
_ "github.com/devituz/lagodev/drivers/sqlite"    // mattn/go-sqlite3

The CLI ships as two interchangeable binaries:

go install github.com/devituz/lagodev/cmd/lago@latest      # → lago
# or
go install github.com/devituz/lagodev/cmd/artisan@latest   # → artisan

lago init                                       # lago.json + config/ + routes/
lago env:init                                   # starter .env
lago make:model Post -mfsc \
    --fields="title:string,body:text,published:bool:default(false)"
lago migrate
lago migrate:fresh --seed
lago db:show

Live reload (Laravel-style php artisan serve --watch)

lagodev ships a ready-to-use air config at the repo root. Install once:

go install github.com/air-verse/air@latest

Then from any lagodev project root:

air

Every save under the watched directories rebuilds the binary and restarts the process — no manual Ctrl+C / go run cycle. The shipped .air.toml targets examples/secure so contributors can iterate on framework changes immediately; copy the file into your own project and adjust the cmd / bin lines to point at your main package.

Scaffolded layout — Laravel-style

myapp/
├── main.go                       — ~30 lines; calls routes.Register(app)
├── lago.json                     — directory layout for the generators
├── .env                          — DB_CONNECTION, DB_*, APP_*
├── config/
│   ├── app.go                    — AppConfig from env
│   └── database.go               — database.Config from env
├── routes/
│   └── api.go                    — routes.Register(app)
├── models/                       — embed orm.Model
├── migrations/                   — schema.Create("...")
├── factories/                    — faker-driven builders
├── seeders/                      — Seeder interface impls
├── services/                     — framework-agnostic CRUD
└── controllers/                  — *web.Context handlers, (any, error)

Documentation

Topic File
Getting started (10-minute intro) docs/GETTING_STARTED.md
Web framework — routing, middleware, controllers docs/WEB.md
ORM cookbook — Query[T], hooks, casts, transactions docs/ORM.md
Migrations & schema DSL docs/MIGRATIONS.md
Factories & seeders docs/FACTORIES.md
lago / artisan CLI reference docs/CLI.md
.env and lago.json configuration docs/CONFIGURATION.md
Integration with Gin / Fiber / Echo / Chi / gRPC docs/FRAMEWORK_INTEGRATION.md
Architecture deep-dive docs/ARCHITECTURE.md
Release notes CHANGELOG.md

Examples

Folder What it shows
examples/basic/ Connection → migrations → ORM → query, ~30 lines
examples/blog/ Full showcase — 3 models, FKs, services, factories, seeders
examples/gin/ Real Gin v1 wrapping the same service layer
examples/fiber/ Fiber v2 — identical service, swapped HTTP layer
examples/echo/ Echo v4
examples/chi/ Chi v5
examples/microservice/ Queue worker with LockForUpdate + transactions
cd examples/blog && go mod tidy && go run .
curl http://localhost:8080/posts

Testing

go test ./...                     # full suite (in-memory SQLite)
go test -race ./...
go test -bench=. -benchmem ./benchmarks

A test using the harness:

import lagotest "github.com/devituz/lagodev/testing"

func TestSomething(t *testing.T) {
    conn, cleanup := lagotest.SQLite(t)
    defer cleanup()

    // Migrations already applied. ORM, factory, service — all work.
}

Roadmap

Area Planned
Web WebSockets, HTML templates, request validation objects
Drivers SQL Server, CockroachDB, TiDB grammars
ORM Pluck / Chunk / cursor pagination, JSON path queries
CLI make:request, make:command, project scaffolding (new)
Tooling OpenTelemetry spans on every query, structured query logger sink
Schema Online ALTERs, native Postgres types (cidr, tsvector, hstore)

Community

Contributing

See CONTRIBUTING.md. Run make check (or go test ./... + go vet ./...) before opening a PR. New features should ship with a test and a one-paragraph update to the relevant doc.

License

MIT — see LICENSE.

⭐ Star the project

If lagodev saved you time, a star helps other Go developers find it.

Star History Chart

Directories

Path Synopsis
adapters
gin module
Package auth provides framework-agnostic JWT signing/parsing and password hashing for lagodev-based applications.
Package auth provides framework-agnostic JWT signing/parsing and password hashing for lagodev-based applications.
Package authz provides Gate (function-based) and Policy (struct-based) authorisation primitives modelled on Laravel's Gate facade.
Package authz provides Gate (function-based) and Policy (struct-based) authorisation primitives modelled on Laravel's Gate facade.
Package broadcasting provides a pub/sub abstraction modelled on Laravel's Broadcasting facade.
Package broadcasting provides a pub/sub abstraction modelled on Laravel's Broadcasting facade.
Package cache provides a key-value cache abstraction with a built-in in-memory store.
Package cache provides a key-value cache abstraction with a built-in in-memory store.
Package carbon is a small ergonomic wrapper around time.Time modelled on Laravel's Carbon helper.
Package carbon is a small ergonomic wrapper around time.Time modelled on Laravel's Carbon helper.
Package casts provides a small attribute-casting layer the ORM applies on reads and writes.
Package casts provides a small attribute-casting layer the ORM applies on reads and writes.
cli
Package cli implements the Artisan-style command-line interface.
Package cli implements the Artisan-style command-line interface.
cmd
Package cmd contains the implementation of each Artisan subcommand.
Package cmd contains the implementation of each Artisan subcommand.
cmd
artisan command
Command artisan is the default lagodev Artisan-style CLI binary.
Command artisan is the default lagodev Artisan-style CLI binary.
lago command
Command lago is the alternative name for the lagodev CLI.
Command lago is the alternative name for the lagodev CLI.
Package config loads framework configuration from environment variables and .env files.
Package config loads framework configuration from environment variables and .env files.
Package crypt provides symmetric encryption and HMAC signing helpers modelled on Laravel's Crypt facade.
Package crypt provides symmetric encryption and HMAC signing helpers modelled on Laravel's Crypt facade.
drivers
mysql
Package mysql registers the MySQL/MariaDB driver and grammar.
Package mysql registers the MySQL/MariaDB driver and grammar.
postgres
Package postgres registers the PostgreSQL driver and grammar.
Package postgres registers the PostgreSQL driver and grammar.
sqlite
Package sqlite registers the SQLite driver (via mattn/go-sqlite3) and provides a Grammar implementation.
Package sqlite registers the SQLite driver (via mattn/go-sqlite3) and provides a Grammar implementation.
Package events provides an in-process event dispatcher modelled on Laravel's Event facade.
Package events provides an in-process event dispatcher modelled on Laravel's Event facade.
examples
basic command
Example: end-to-end usage of lagodev with an in-memory SQLite database.
Example: end-to-end usage of lagodev with an in-memory SQLite database.
microservice command
Example: a microservice-style worker that reads jobs from a queue table.
Example: a microservice-style worker that reads jobs from a queue table.
secure command
Example: secure-by-default lagodev HTTP service.
Example: secure-by-default lagodev HTTP service.
Package factory provides a generic, type-safe model factory inspired by Laravel's factories.
Package factory provides a generic, type-safe model factory inspired by Laravel's factories.
Package filesystem provides a Disk abstraction modelled on Laravel's Storage facade.
Package filesystem provides a Disk abstraction modelled on Laravel's Storage facade.
Package httpclient is a fluent wrapper around net/http modelled on Laravel's Http facade.
Package httpclient is a fluent wrapper around net/http modelled on Laravel's Http facade.
Package i18n provides translation primitives modelled on Laravel's Lang facade.
Package i18n provides translation primitives modelled on Laravel's Lang facade.
internal
inflect
Package inflect provides minimal, allocation-conscious string transformations used across the framework (snake_case, plural table names, etc.).
Package inflect provides minimal, allocation-conscious string transformations used across the framework (snake_case, plural table names, etc.).
reflectutil
Package reflectutil provides a thread-safe, allocation-amortized reflection cache.
Package reflectutil provides a thread-safe, allocation-amortized reflection cache.
Package logger provides a small, dependency-free structured logger used across the framework.
Package logger provides a small, dependency-free structured logger used across the framework.
Package mail provides a Mailer abstraction with an SMTP driver modelled on Laravel's Mail facade.
Package mail provides a Mailer abstraction with an SMTP driver modelled on Laravel's Mail facade.
mailgun
Package mailgun implements mail.Mailer against Mailgun's HTTP API (https://documentation.mailgun.com/en/latest/api-sending.html).
Package mailgun implements mail.Mailer against Mailgun's HTTP API (https://documentation.mailgun.com/en/latest/api-sending.html).
sendgrid
Package sendgrid implements mail.Mailer against SendGrid's v3 HTTP API (https://docs.sendgrid.com/api-reference/mail-send/mail-send).
Package sendgrid implements mail.Mailer against SendGrid's v3 HTTP API (https://docs.sendgrid.com/api-reference/mail-send/mail-send).
Package migrations implements a Laravel-style migration engine.
Package migrations implements a Laravel-style migration engine.
Package mock provides small testing helpers modelled on Laravel's Mock facade — the bits applications reach for over and over in tests without pulling in a full mocking framework.
Package mock provides small testing helpers modelled on Laravel's Mock facade — the bits applications reach for over and over in tests without pulling in a full mocking framework.
Package notifications provides multi-channel notification delivery modelled on Laravel's Notification facade.
Package notifications provides multi-channel notification delivery modelled on Laravel's Notification facade.
Package orm provides an ActiveRecord-style Model, a fluent query builder, hooks, casts, and relationships.
Package orm provides an ActiveRecord-style Model, a fluent query builder, hooks, casts, and relationships.
Package process wraps os/exec with a fluent builder modelled on Laravel's Process facade.
Package process wraps os/exec with a fluent builder modelled on Laravel's Process facade.
Package query provides a fluent, driver-aware SQL builder.
Package query provides a fluent, driver-aware SQL builder.
Package queue provides a job queue abstraction modelled on Laravel's Queue facade.
Package queue provides a job queue abstraction modelled on Laravel's Queue facade.
sqlqueue
Package sqlqueue implements a database-backed Queue driver that survives process restarts and works across replicas.
Package sqlqueue implements a database-backed Queue driver that survives process restarts and works across replicas.
Package relations implements model relationships with eager-loading.
Package relations implements model relationships with eager-loading.
Package router provides Laravel-style declarative routing that is independent of any HTTP framework.
Package router provides Laravel-style declarative routing that is independent of any HTTP framework.
Package scheduling provides a task scheduler modelled on Laravel's Task Scheduling.
Package scheduling provides a task scheduler modelled on Laravel's Task Scheduling.
Package schema provides a fluent table-builder DSL (Blueprint) and a driver-agnostic Builder that compiles blueprints into SQL via a Grammar implementation provided by the database driver.
Package schema provides a fluent table-builder DSL (Blueprint) and a driver-agnostic Builder that compiles blueprints into SQL via a Grammar implementation provided by the database driver.
Package seeder runs database seeders with dependency ordering and transactional execution.
Package seeder runs database seeders with dependency ordering and transactional execution.
Package session provides cookie-backed sessions modelled on Laravel's Session facade.
Package session provides cookie-backed sessions modelled on Laravel's Session facade.
Package testing provides helpers for running migrations against an ephemeral SQLite database, useful for unit and integration tests.
Package testing provides helpers for running migrations against an ephemeral SQLite database, useful for unit and integration tests.
Package web is the Laravel-style HTTP framework for lagodev.
Package web is the Laravel-style HTTP framework for lagodev.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL