bobby

package module
v0.0.0-...-913b77b Latest Latest
Warning

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

Go to latest
Published: Nov 30, 2025 License: MIT Imports: 22 Imported by: 0

README

Bobby

Bobby is a lightweight, generic repository pattern library for Bob ORM, providing common CRUD operations with type-safe generics.

Installation

go get github.com/eiicon-company/bobby

Quick Start

import (
    "context"
    "database/sql"

	"go.uber.org/dig"
    "github.com/eiicon-company/bobby"
    "github.com/stephenafamo/scan"

    // Your Bob ORM generated models
    "yourproject/models"
)

type (
	UserRepo interface {
		bobby.BaseRepo[*models.User, models.UserSlice, *models.UserSetter]
		// Custom method for this repository
		ListByState(context.Context, bob.Executor, string, ...bobby.SelMod) (models.UserSlice, error)
	}

	userRepo struct {
		bobby.BaseRepo[*models.User, models.UserSlice, *models.UserSetter]
	}
)

// ListByState retrieves by state
func (b *userRepo) ListByState(ctx context.Context, exec bob.Executor, state string, loads ...bobby.SelMod) (models.UserSlice, error) {
	if state == "" {
		return nil, xerrors.Errorf("no state arg found: %w", sql.ErrNoRows)
	}

	mods := []bobby.SelMod{
		sm.Where(models.Users.Columns.State.EQ(mysql.Arg(state))),
	}

	return b.ListBy(ctx, exec, mods, loads...)
}

type newUserRepoIn struct {
	dig.In
	DB  *sql.DB
}

func newUserRepo(in newUserRepoIn) UserRepo {
	return &userRepo{
		in: in,
		BaseRepo: NewBaseRepo[*models.User, models.UserSlice, *models.UserSetter](
			in.DB,
			models.Users,
			models.Users.Columns.ID,
			scan.StructMapper[*models.User](), // Mapper for cursor operations
			dbinfo.Users,                      // Table info for column defaults
		),
	}
}

License

MIT License - see LICENSE file for details

Documentation

Overview

Package bobby base type definitions and interfaces

Package bobby base reader implementation

Package bobby base writer implementation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type BannerRepo

type BannerRepo interface {
	BaseRepo[*models.Banner, models.BannerSlice, *models.BannerSetter]
}

BannerRepo is a test repository for Banner model

type BaseGenerator

type BaseGenerator[S any] struct {
	Rows S     // Batch of rows (typically 1000 rows per batch)
	Err  error // Error if any occurred during generation
}

BaseGenerator is used as channel result for streaming large datasets This matches the apirepo.BaseGenerator pattern but uses Bob ORM's Cursor for efficient streaming

type BaseModel

type BaseModel[TSet any] interface {
	Update(context.Context, bob.Executor, TSet) error
	Delete(context.Context, bob.Executor) error
	Reload(context.Context, bob.Executor) error
}

BaseModel represents a Bob ORM generated model with Update, Delete, and Reload methods All Bob ORM models implement this interface

type BaseReader

type BaseReader[M any, S ~[]T, T any] interface {
	// Connection
	Conn() *sql.DB

	// Find retrieves a single record by ID
	Find(context.Context, bob.Executor, int, ...SelMod) (T, error)
	// FindBy retrieves a single record by conditions
	FindBy(context.Context, bob.Executor, []SelMod, ...SelMod) (T, error)
	// FindPreload retrieves a single record with eager loading [DEPRECATED] use Find instead.
	FindPreload(context.Context, bob.Executor, int, ...SelMod) (T, error)
	// FirstBy picks the first row up
	FirstBy(context.Context, bob.Executor, []SelMod, ...SelMod) (T, error)
	// LastBy picks the last row up
	LastBy(context.Context, bob.Executor, []SelMod, ...SelMod) (T, error)

	// All returns all records with ordering
	All(context.Context, bob.Executor, ...SelMod) (S, error)
	// AllPreload returns all records with eager loading
	AllPreload(context.Context, bob.Executor, ...SelMod) (S, error)
	// ListBy retrieves records by conditions with ordering
	ListBy(context.Context, bob.Executor, []SelMod, ...SelMod) (S, error)
	// SliceBy retrieves records by conditions without default ordering
	SliceBy(context.Context, bob.Executor, []SelMod, ...SelMod) (S, error)
	// ListByIDs retrieves records by IDs
	ListByIDs(context.Context, bob.Executor, []int, ...SelMod) (S, error)
	// ListPagerBy is pagination retriever with eager preloading
	ListPagerBy(context.Context, bob.Executor, []SelMod, int, int, ...SelMod) (S, int, error)
	// SlicePagerBy is pagination retriever without default ordering
	SlicePagerBy(context.Context, bob.Executor, []SelMod, int, int, ...SelMod) (S, int, error)

	// Exists checks if a record exists
	Exists(context.Context, bob.Executor, int) (bool, error)

	// Generator returns an iterator channel that streams large datasets efficiently
	// Uses Bob ORM's Cursor for streaming with batching (1000 rows per batch)
	// base: base query modifiers (WHERE, etc.)
	// loads: additional modifiers for eager loading
	Generator(context.Context, bob.Executor, []SelMod, ...SelMod) chan *BaseGenerator[S]
}

BaseReader provides common read operations for Bob ORM repositories

func NewBaseReader

func NewBaseReader[T any, S ~[]T](
	db *sql.DB,
	table TableQuerier[T, S],
	idColumn mysql.Expression,
	mapper scan.Mapper[T],
) BaseReader[T, S, T]

NewBaseReader creates a new base reader

type BaseRepo

type BaseRepo[T BaseModel[TSet], S ~[]T, TSet BaseSetter[T]] interface {
	BaseReader[T, S, T]
	BaseWriter[T, S, TSet]
}

BaseRepo combines read and write operations for Bob ORM repositories

func NewBaseRepo

func NewBaseRepo[T BaseModel[TSet], S ~[]T, TSet BaseSetter[T], C bob.Expression](
	db *sql.DB,
	table *mysql.Table[T, S, TSet, C],
	idColumn mysql.Expression,
	mapper scan.Mapper[T],
	infos any,
) BaseRepo[T, S, TSet]

NewBaseRepo creates a new base repository with both read and write capabilities table should be a Bob ORM generated table (e.g., models.Banners) mapper should be the Bob ORM generated mapper function (e.g., models.BannerMapper())

type BaseSetter

type BaseSetter[T any] = orm.Setter[T, *dialect.InsertQuery, *dialect.UpdateQuery]

BaseSetter is a type alias for Bob ORM Setter with generic type constraints

type BaseWriter

type BaseWriter[T BaseModel[TSet], S ~[]T, TSet BaseSetter[T]] interface {
	// Create inserts a new record
	Create(context.Context, bob.Executor, T) error
	// Update updates an existing record
	Update(context.Context, bob.Executor, T) error
	// Upsert inserts or updates a record
	Upsert(context.Context, bob.Executor, T) error
	// UpsertLegacy uses Create or Update based on ID
	UpsertLegacy(context.Context, bob.Executor, T) error
	// Delete removes a record by ID
	Delete(context.Context, bob.Executor, int) error
}

BaseWriter provides common write operations for Bob ORM repositories

func NewBaseWriter

func NewBaseWriter[T BaseModel[TSet], S ~[]T, TSet BaseSetter[T], C bob.Expression](
	db *sql.DB,
	table *mysql.Table[T, S, TSet, C],
	idColumn mysql.Expression,
	reader BaseReader[T, S, T],
	infos any,
) BaseWriter[T, S, TSet]

NewBaseWriter creates a new base writer

type DelMod

type DelMod = bob.Mod[*dialect.DeleteQuery]

DelMod is a type alias for DELETE query modifier

type InsMod

type InsMod = bob.Mod[*dialect.InsertQuery]

InsMod is a type alias for INSERT query modifier

type OrganizationPlanRepo

OrganizationPlanRepo is a test repository for OrganizationPlan model

type SelMod

type SelMod = bob.Mod[*dialect.SelectQuery]

SelMod is a type alias for SELECT query modifier

type TableQuerier

type TableQuerier[T any, S ~[]T] interface {
	Query(...SelMod) *mysql.ViewQuery[T, S]
}

TableQuerier represents the Query method that Bob ORM tables have This is what models.Banners and other tables implement

type UpdMod

type UpdMod = bob.Mod[*dialect.UpdateQuery]

UpdMod is a type alias for UPDATE query modifier

Directories

Path Synopsis
internal

Jump to

Keyboard shortcuts

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