seeder

package module
v1.0.3 Latest Latest
Warning

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

Go to latest
Published: Jul 30, 2026 License: MIT Imports: 10 Imported by: 0

README

go-seeder

A pluggable database seeder for Go — seed your PostgreSQL, MySQL, or MongoDB databases using SQL files, JSON files, or Go code with versioned up/down migrations.

Go Reference Go Report Card CI Status


Features

  • 🗄️ Multi-database — PostgreSQL, MySQL, MongoDB
  • 📁 Multi-format — SQL files, JSON files, Go code
  • ⬆️ Up / Down — Apply and rollback seeds with version tracking
  • 🔢 Version tracking — Tracks applied seeds in seeder_versions table/collection with execution dirty state check
  • 🖥️ CLI tool — Install globally, run from any project
  • 📦 Go library — Import and use programmatically
  • 🔍 Dry-run mode — Preview operations without executing

Installation

CLI Tool
go install github.com/jindalpeeyush/go-seeder/cmd/seeder@latest
Go Library
go get github.com/jindalpeeyush/go-seeder

Quick Start

1. Create Seed Files

Use seeder create to generate paired Up and Down seed files:

# Create a SQL seed for PostgreSQL
seeder create -driver=postgres -ext=sql -dir=database/seeders create_users

# Create a JSON seed for MongoDB
seeder create -driver=mongodb -ext=json -dir=database/seeders dummy_users

# Create Go seeds for MySQL (default ext is go)
seeder create -driver=mysql -dir=database/seeders add_admin

This generates timestamped file pairs:

database/seeders/
├── 1720310400_create_users.up.sql
├── 1720310400_create_users.down.sql
├── 1720310401_dummy_users.up.json
├── 1720310401_dummy_users.down.json
├── 1720310402_add_admin.up.go
└── 1720310402_add_admin.down.go
2. Edit Seed Files
SQL Files

SQL files include a driver header on the first line.

Up file (1720310400_create_users.up.sql):

-- driver: postgres
INSERT INTO users (name, email) VALUES ('Alice', 'alice@example.com');

Down file (1720310400_create_users.down.sql):

-- driver: postgres
DELETE FROM users WHERE email = 'alice@example.com';
JSON Files

JSON files require a "driver" and a "table" property.

Up file (1720310401_dummy_users.up.json):

{
  "driver": "mongodb",
  "table": "users",
  "records": [
    {"name": "Alice", "email": "alice@example.com"}
  ]
}

Down file (1720310401_dummy_users.down.json):

{
  "driver": "mongodb",
  "table": "users",
  "truncate": true
}
Go Files

Go files register with the global seeder registry on import.

Up file (1720310402_add_admin.up.go):

package seeds

import (
	"context"
	"github.com/jindalpeeyush/go-seeder"
)

func init() {
	seeder.Register(&seeder.Seed{
		Version:   1720310402,
		Name:      "add_admin",
		Direction: seeder.Up,
		Driver:    "mysql",
		Run: func(ctx context.Context, db seeder.DB) error {
			return db.InsertJSON(ctx, "users", []map[string]interface{}{
				{"name": "Admin", "role": "admin"},
			})
		},
	})
}

Down file (1720310402_add_admin.down.go):

package seeds

import (
	"context"
	"github.com/jindalpeeyush/go-seeder"
)

func init() {
	seeder.Register(&seeder.Seed{
		Version:   1720310402,
		Name:      "add_admin",
		Direction: seeder.Down,
		Driver:    "mysql",
		Run: func(ctx context.Context, db seeder.DB) error {
			return db.ExecSQL(ctx, "DELETE FROM users WHERE role = 'admin'")
		},
	})
}
3. Run Seeds
# Apply all pending seeds
seeder -path=database/seeders -database "postgres://user:pass@localhost:5432/mydb?sslmode=disable" up

# Rollback last seed
seeder -path=database/seeders -database "postgres://user:pass@localhost:5432/mydb?sslmode=disable" down 1

# Rollback all seeds
seeder -path=database/seeders -database "postgres://user:pass@localhost:5432/mydb?sslmode=disable" down

# Force set version (marks target version as clean, clears later versions)
seeder -path=database/seeders -database "postgres://user:pass@localhost:5432/mydb?sslmode=disable" force 1720310400

CLI Reference

seeder create -driver=<driver> [-ext=<ext>] [-dir=<dir>] <seed_name>
seeder -path=<path> -database <uri> [-verbose] [--dry-run] up
seeder -path=<path> -database <uri> [-verbose] [--dry-run] down [N]
seeder -path=<path> -database <uri> [-verbose] [--dry-run] force <version>
seeder -help
Commands
Command Description
create Create a new pair of up and down seed files
up Apply all pending seeds
down [N] Roll back applied seeds (last N, or all)
force <ver> Force set database version and clear dirty state
Create Flags
Flag Description Required Default
-driver Database driver: postgres, mysql, mongodb Yes
-ext File extension: go, sql, json No go
-dir Output directory No database/seeders
Global Flags
Flag Description
-path Path to seed files directory
-database Database connection URI
-verbose Enable verbose output
--dry-run Preview operations without executing

Connection Strings

Database DSN Format
PostgreSQL postgres://user:password@localhost:5432/dbname?sslmode=disable
MySQL user:password@tcp(localhost:3306)/dbname?parseTime=true
MongoDB mongodb://user:password@localhost:27017/dbname

Note: The driver is auto-detected from the DSN for up/down/force commands. The -driver flag is only required for create.


Seed File Formats

SQL Files

Supports PostgreSQL and MySQL. Must contain a -- driver: comment line.

Up/Down file content example:

-- driver: postgres
CREATE TABLE IF NOT EXISTS products (
    id SERIAL PRIMARY KEY,
    name VARCHAR(100)
);
JSON Files

Supports PostgreSQL, MySQL, and MongoDB.

Up file content properties:

  • driver: must be "mongodb"
  • table: collection name
  • records: slice of document maps to insert

Down file content properties:

  • driver: must be "mongodb"
  • table: collection name
  • truncate: set to true to drop/truncate the collection
  • delete: filter document mapping to remove specific records
Go Files

Go seed files use init() to register seeds with the global registry. To execute them in your application, build a custom binary that imports your seed package:

// cmd/seed/main.go
package main

import (
    "context"
    "log"
    "os"

    "github.com/jindalpeeyush/go-seeder"
    _ "yourproject/database/seeders" // imports seeds to trigger init()
)

func main() {
    s, err := seeder.New(seeder.Options{
        DSN: os.Getenv("DATABASE_URL"),
    })
    if err != nil {
        log.Fatal(err)
    }
    defer s.Close()

    if err := s.RunUp(context.Background()); err != nil {
        log.Fatal(err)
    }
}

Go Library API

Use go-seeder programmatically in your Go application:

import "github.com/jindalpeeyush/go-seeder"

// Create a seeder
s, err := seeder.New(seeder.Options{
    Driver: "postgres",
    DSN:    "postgres://localhost:5432/mydb?sslmode=disable",
})
defer s.Close()

// Register seeds programmatically
seeder.Register(&seeder.Seed{
    Version:   1720310400,
    Name:      "users",
    Direction: seeder.Up,
    Driver:    "postgres",
    Run: func(ctx context.Context, db seeder.DB) error {
        return db.InsertJSON(ctx, "users", []map[string]interface{}{
            {"name": "Alice", "email": "alice@example.com"},
        })
    },
})

// Apply pending seeds
s.RunUp(context.Background())

// Rollback last 2 seeds
s.RunDown(context.Background(), 2)

Version Tracking

go-seeder automatically creates a seeder_versions table (or collection in MongoDB) to track applied version states:

Column Type Description
version BIGINT Seed timestamp (primary key)
seed_name TEXT Seed name
dirty BOOLEAN Flag indicating if version execution failed
why_dirty TEXT / string Error message if execution failed (dirty is true)
applied_at TIMESTAMP When the seed was applied
Dirty State & Recovery Behavior

If a seed execution fails, go-seeder marks the version as dirty = true and records the error description in why_dirty.

  • Applying Seeds (up): If any seed version is currently dirty, running up will fail immediately and display the reason (why_dirty) so that you know what failed.
  • Rolling Back (down): Unlike other migration engines that block entirely when a dirty state occurs, go-seeder allows you to run down to roll back the latest applied seed even if it is dirty. If that rollback succeeds, the dirty version is deleted and the database state becomes clean again.
  • Rollback Failures: If a rollback step itself fails, the version remains dirty (with the new rollback error message stored in why_dirty) and execution stops immediately without processing subsequent rollback steps.

Technical Details & Design Constraints

  • Driver limits: MongoDB only supports .json and .go extensions. SQL databases support .sql, .json, and .go extensions.
  • Transactions: SQL databases execute batches inside database transactions (auto-rollbacks on failures).
  • Ordering: Seeds are executed in ascending timestamp version order.
  • File naming: <unix_timestamp>_<seed_name>.<direction>.<ext> — generated automatically on create.

License

MIT License — see LICENSE for details.

Documentation

Overview

Package seeder provides the core engine for versioned seed operations.

Package seeder provides the public Go API for programmatic database seeding.

Users create Go seed files that register seeds via init() functions. Each seed has a direction (Up or Down) and a Run function.

Example

func init() {
    seeder.Register(&seeder.Seed{
        Version:   1720310400,
        Name:      "add_admin",
        Direction: seeder.Up,
        Driver:    "postgres",
        Run: func(ctx context.Context, db seeder.DB) error {
            return db.InsertJSON(ctx, "users", []map[string]interface{}{
                {"name": "Admin", "role": "admin"},
            })
        },
    })
}

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ClearRegistry

func ClearRegistry()

ClearRegistry clears all registered seeds (for testing).

func Register

func Register(seed *Seed)

Register adds a seed to the global registry.

Types

type Config added in v1.0.2

type Config struct {
	Path     string
	Database string
	Verbose  bool
	DryRun   bool
}

Config holds runtime configuration.

type DB

type DB interface {
	// ExecSQL executes a raw SQL query statement (PostgreSQL and MySQL only).
	ExecSQL(ctx context.Context, query string) error
	// InsertJSON inserts a slice of records/documents into the specified table/collection.
	InsertJSON(ctx context.Context, table string, records []map[string]interface{}) error
	// DeleteJSON removes records/documents matching the filter map from the specified table/collection.
	DeleteJSON(ctx context.Context, table string, filter map[string]interface{}) error
	// Truncate deletes all records/documents from the specified tables/collections.
	Truncate(ctx context.Context, tables ...string) error
}

DB defines the database operations interface available inside a seed function.

type Direction

type Direction string

Direction represents the execution direction of a seed operation (Up or Down).

const (
	// Up indicates applying database seed data.
	Up Direction = "up"
	// Down indicates rolling back/removing database seed data.
	Down Direction = "down"
)

type Engine added in v1.0.2

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

Engine is the core seeder orchestrator.

func NewEngine added in v1.0.2

func NewEngine(cfg Config) *Engine

NewEngine creates a new Engine with the given configuration.

func (*Engine) Down added in v1.0.2

func (e *Engine) Down(ctx context.Context, steps int) error

Down rolls back seeds. steps=0 means all.

func (*Engine) Force added in v1.0.2

func (e *Engine) Force(ctx context.Context, version int64) error

Force sets the version without running seeds.

func (*Engine) SetOutput added in v1.0.2

func (e *Engine) SetOutput(w io.Writer)

SetOutput sets logger output (for testing).

func (*Engine) Up added in v1.0.2

func (e *Engine) Up(ctx context.Context) error

Up applies all pending seeds.

type Options

type Options struct {
	// Driver specifies the database driver. If empty, the driver is auto-detected from DSN.
	Driver string
	// DSN is the connection URI string.
	DSN string
}

Options contains configuration options for initializing a new Seeder.

type Seed

type Seed struct {
	// Version is the unique version identifier of the seed (usually a Unix timestamp).
	Version int64
	// Name is the descriptive name of the seed.
	Name string
	// Direction specifies if the seed is an Up or Down migration.
	Direction Direction
	// Driver specifies the target database engine: "postgres", "mysql", or "mongodb".
	// If empty, the seed runs on any connected database.
	Driver string // postgres, mysql, mongodb
	// Run is the function hook executed during the seed operation.
	Run SeedFunc
}

Seed represents a single registered seed containing version metadata and execution logic.

func GetRegistered

func GetRegistered() []*Seed

GetRegistered returns all registered seeds sorted by version.

type SeedFunc

type SeedFunc func(ctx context.Context, db DB) error

SeedFunc defines the signature of a seed function execution hook.

type Seeder

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

Seeder provides direct programmatic control over database seed versions and execution.

func New

func New(opts Options) (*Seeder, error)

New creates and initializes a Seeder, establishes a database connection, and ensures the version tracking schema is created.

func (*Seeder) Close

func (s *Seeder) Close() error

Close releases any database connections and resources held by the Seeder.

func (*Seeder) DB

func (s *Seeder) DB() DB

DB returns a DB adapter wrapping the active database connection for manual seeding operations.

func (*Seeder) RunDown

func (s *Seeder) RunDown(ctx context.Context, steps int) error

RunDown rolls back the last N applied seeds in descending version order. If steps is <= 0, it rolls back all applied seeds. It permits rolling back the latest version even if it is dirty, but returns an error if any older version in the list is dirty.

func (*Seeder) RunUp

func (s *Seeder) RunUp(ctx context.Context) error

RunUp executes all pending registered Up seeds matching this database driver in ascending version order. It fails immediately if any applied version in the database is currently marked dirty.

Directories

Path Synopsis
cmd
seeder command
Package driver defines the database driver interface and provides factory functions to create drivers by name or auto-detect from DSN.
Package driver defines the database driver interface and provides factory functions to create drivers by name or auto-detect from DSN.
examples
basic command
internal
cli
Package cli implements the flag-based CLI for go-seeder.
Package cli implements the flag-based CLI for go-seeder.
Package loader provides seed file parsing for go-seeder.
Package loader provides seed file parsing for go-seeder.
pkg

Jump to

Keyboard shortcuts

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