neat

package module
v0.4.0 Latest Latest
Warning

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

Go to latest
Published: May 30, 2026 License: AGPL-3.0 Imports: 6 Imported by: 0

README

Neat ORM

A powerful and elegant ORM (Object-Relational Mapping) library for Go, designed to provide a clean and intuitive interface for database operations. Neat aims to feature parity with Laravel's Eloquent ORM while being built from scratch without GORM dependencies.

Features

  • Query Builder: Fluent and intuitive query building interface
  • ORM: Full ORM support with models and relationships
  • Schema Builder: Database schema creation and modification
  • Migrations: Database migration system (ORM driver supported)
  • Seeders: Database seeding for test and initial data
  • Factories: Test data generation with factory pattern
  • Multiple Database Support: MySQL, PostgreSQL, SQLite, SQL Server, Turso
  • Transactions: Robust transaction support
  • Observers: Model lifecycle event system
  • Soft Deletes: Soft delete functionality
  • Associations: BelongsTo, HasMany, HasOne relationships
  • Connection Pooling: Efficient connection management
  • Context Support: Full context.Context support throughout

Installation

go get github.com/dracory/neat

Quick Start

package main

import (
    "context"
    "log"
    
    "github.com/dracory/neat"
)

type User struct {
    ID       uint   `json:"id"`
    Name     string `json:"name"`
    Email    string `json:"email"`
}

func main() {
    // Create database connection
    db, err := neat.NewFromDSN("mysql://user:password@localhost:3306/mydb")
    if err != nil {
        log.Fatal(err)
    }
    defer db.Close()
    
    // Query users
    var users []User
    err = db.Query().Where("name", "John").Get(&users)
    if err != nil {
        log.Fatal(err)
    }
    
    log.Printf("Found %d users", len(users))
}

Configuration

Using DSN String
db, err := neat.NewFromDSN("mysql://user:password@localhost:3306/mydb")
Using DBConfig
config := neat.DBConfig{
    Default: "default",
    Connections: map[string]neat.ConnectionConfig{
        "default": {
            Driver:   "mysql",
            Host:     "localhost",
            Port:     3306,
            Database: "mydb",
            Username: "user",
            Password: "password",
        },
    },
}

db, err := neat.New(config)
Supported DSN Formats
  • MySQL: mysql://user:password@localhost:3306/database
  • PostgreSQL: postgres://user:password@localhost:5432/database?sslmode=disable
  • SQLite: sqlite:///path/to/database.db
  • SQL Server: sqlserver://user:password@localhost:1433?database=database

ORM Usage

Creating Records
user := User{
    Name:  "John Doe",
    Email: "john@example.com",
}
err := db.Query().Create(&user)
Querying Records
var user User
err := db.Query().Where("id", 1).First(&user)

var users []User
err := db.Query().Where("name", "John").Get(&users)
Updating Records
err := db.Query().Where("id", 1).Update("name", "Jane")
Deleting Records
result, err := db.Query().Where("id", 1).Delete()
Transactions
err := db.Transaction(func(tx neat.Query) error {
    err := tx.Create(&user1)
    if err != nil {
        return err
    }
    
    err = tx.Create(&user2)
    if err != nil {
        return err
    }
    
    return nil
})

Schema Builder

err := db.Schema().Create("users", func(table neat.Blueprint) {
    table.ID()
    table.String("name")
    table.String("email").Unique()
    table.Timestamps()
})

Observers

type UserObserver struct{}

func (o *UserObserver) Creating(event neat.Event) error {
    log.Println("Creating user")
    return nil
}

func (o *UserObserver) Created(event neat.Event) error {
    log.Println("User created")
    return nil
}

// Register observer
db.Orm().Observe([]neat.ModelToObserver{
    {Model: User{}, Observer: UserObserver{}},
})

Soft Deletes

type User struct {
    neat.SoftDeletes
    ID   uint
    Name string
}

// Soft delete
db.Query().Where("id", 1).Delete()

// Include soft-deleted records
db.Query().WithTrashed().Where("id", 1).First(&user)

// Only soft-deleted records
db.Query().OnlyTrashed().Where("id", 1).First(&user)

// Restore soft-deleted record
db.Query().Restore(&user)

// Force delete (permanent)
db.Query().ForceDelete(&user)

Associations

type Post struct {
    ID     uint
    Title  string
    UserID uint
}

type User struct {
    ID    uint
    Name  string
    Posts []Post
}

// Eager loading
db.Query().With("posts").Where("id", 1).First(&user)

// Lazy loading
db.Query().Load(&user, "posts")

// Association operations
db.Query().Association("posts").Append(&user, &post)

Supported Databases

  • MySQL 5.7+
  • PostgreSQL 12+
  • SQLite 3+
  • SQL Server 2017+
  • Turso (SQLite edge)

API Documentation

For detailed API documentation, see the docs directory.

Examples

For more examples, see the examples directory.

License

This project is licensed under the GNU Affero General Public License v3.0 - see the LICENSE file for details.

Testing

Running Integration Tests with Docker Compose

The project includes a Docker Compose configuration for running integration tests locally with MySQL and PostgreSQL:

# Start the database containers
docker-compose up -d

# Run MySQL integration tests
go test -v -tags=integration ./integration_tests/mysql/...

# Run PostgreSQL integration tests
go test -v -tags=integration ./integration_tests/postgres/...

# Stop the containers when done
docker-compose down

The Docker Compose setup includes:

  • MySQL 8.0 on port 3306 (user: root, password: root, database: test)
  • PostgreSQL 15 on port 55432 (user: test, password: test, database: test)
Running Unit Tests
go test ./...
Running All Tests
go test -v ./...

Contributing

Contributions are welcome! Please open an issue or submit a pull request. For detailed contribution guidelines, see CONTRIBUTING.md.

Roadmap

Current Status

Neat ORM is actively developed with the following features implemented:

  • ✅ Query Builder with fluent interface
  • ✅ ORM with model support
  • ✅ Schema Builder for database operations
  • ✅ Migration system (ORM driver)
  • ✅ Seeder system for data seeding
  • ✅ Factory pattern for test data
  • ✅ Multiple database support (MySQL, PostgreSQL, SQLite, SQL Server, Turso)
  • ✅ Transaction support
  • ✅ Observer system for model events
  • ✅ Soft deletes
  • ✅ Associations (BelongsTo, HasMany, HasOne)
  • ✅ Connection pooling
  • ✅ Context support
Planned Features
  • Additional migration drivers (SQL, custom drivers)
  • More relationship types (HasManyThrough, BelongsToMany)
  • Query caching
  • Full-text search support
  • Polymorphic relationships
  • Scopes and global scopes
  • Mutators and accessors
  • Model casting
  • Validation integration
  • Query builder debugging tools
  • Additional database drivers

For detailed implementation plans, see docs/implementation/plan.md.

Documentation

Index

Constants

View Source
const (
	EventCreating  = "model.creating"
	EventCreated   = "model.created"
	EventUpdating  = "model.updating"
	EventUpdated   = "model.updated"
	EventSaving    = "model.saving"
	EventSaved     = "model.saved"
	EventDeleting  = "model.deleting"
	EventDeleted   = "model.deleted"
	EventRestoring = "model.restoring"
	EventRestored  = "model.restored"
)

Event names for model lifecycle events.

Variables

This section is empty.

Functions

func New added in v0.2.0

func New(cfg DBConfig, opts ...database.Option) (*database.Database, error)

New creates a new Database instance from a DBConfig.

func NewFromDSN added in v0.2.0

func NewFromDSN(dsn string, opts ...database.Option) (*database.Database, error)

NewFromDSN creates a new Database instance from a DSN string.

Types

type ConnectionConfig

type ConnectionConfig struct {
	Driver       string // "postgres", "mysql", "sqlite", "sqlserver", "turso"
	Dsn          string
	Host         string
	Port         int
	Database     string
	Username     string
	Password     string
	Charset      string
	Schema       string // postgres only
	SSLMode      string // postgres only
	Loc          string // mysql only
	Timezone     string // postgres only
	Prefix       string
	Singular     bool
	NoLowerCase  bool
	NameReplacer any
	Read         []ReplicaConfig
	Write        []ReplicaConfig
}

ConnectionConfig holds configuration for a single database connection.

type DBConfig

type DBConfig struct {
	// Default connection name
	Default string
	// Connection configurations
	Connections map[string]ConnectionConfig
	// Migration configuration
	Migrations MigrationConfig
	// Pool configuration
	Pool PoolConfig
	// Debug mode
	Debug bool
	// Slow query threshold in milliseconds
	SlowThreshold int
}

DBConfig holds the database configuration for the standalone module.

func (*DBConfig) Add

func (c *DBConfig) Add(name string, configuration any)

Add implements config.Config interface for DBConfig (stub).

func (*DBConfig) Env

func (c *DBConfig) Env(envName string, defaultValue ...any) any

Env implements config.Config interface for DBConfig (stub).

func (*DBConfig) Get

func (c *DBConfig) Get(path string, defaultValue ...any) any

Get implements config.Config interface for DBConfig.

func (*DBConfig) GetBool

func (c *DBConfig) GetBool(path string, defaultValue ...any) bool

GetBool implements config.Config interface for DBConfig.

func (*DBConfig) GetInt

func (c *DBConfig) GetInt(path string, defaultValue ...any) int

GetInt implements config.Config interface for DBConfig.

func (*DBConfig) GetString

func (c *DBConfig) GetString(path string, defaultValue ...any) string

GetString implements config.Config interface for DBConfig.

type Database added in v0.2.0

type Database = database.Database

Database is an alias for the database.Database type.

type EventBus added in v0.2.0

type EventBus struct {
	// contains filtered or unexported fields
}

EventBus is a lightweight internal event bus for model lifecycle events.

func NewEventBus added in v0.2.0

func NewEventBus() *EventBus

NewEventBus creates a new EventBus.

func (*EventBus) Dispatch added in v0.2.0

func (e *EventBus) Dispatch(eventName string, event any)

Dispatch dispatches an event to all registered listeners.

func (*EventBus) Forget added in v0.2.0

func (e *EventBus) Forget(eventName string)

Forget removes all listeners for the given event name.

func (*EventBus) Listen added in v0.2.0

func (e *EventBus) Listen(eventName string, handler EventHandler)

Listen registers a handler for the given event name.

type EventHandler added in v0.2.0

type EventHandler func(event any)

EventHandler is a function that handles an event.

type MigrationConfig

type MigrationConfig struct {
	Driver string // "sql" or "orm"
	Table  string // default: "migrations"
}

MigrationConfig holds migration configuration.

type PoolConfig

type PoolConfig struct {
	MaxIdleConns    int
	MaxOpenConns    int
	ConnMaxLifetime time.Duration
	ConnMaxIdleTime time.Duration
}

PoolConfig holds connection pool configuration.

type ReplicaConfig added in v0.2.0

type ReplicaConfig struct {
	Host     string
	Port     int
	Database string
	Username string
	Password string
}

ReplicaConfig holds connection details for a single read or write replica.

Jump to

Keyboard shortcuts

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