dynorm

package module
v0.0.0-...-4f9170d Latest Latest
Warning

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

Go to latest
Published: Dec 22, 2025 License: MIT Imports: 3 Imported by: 0

README

Dynorm

Go Reference Tests Go Report Card

A type-safe DynamoDB abstraction layer for Go, optimized for AWS Lambda. Dynorm provides a Laravel Eloquent-style fluent API with automatic ID generation, timestamps, relationships, and snake_case marshalling.

Features

  • Type-Safe Generics - Full Go generics support for compile-time type safety
  • Automatic IDs - ULID-based, sortable, immutable identifiers
  • Timestamps - Automatic CreatedAt and UpdatedAt management
  • Relationships - HasOne, HasMany, BelongsTo, BelongsToMany, polymorphic
  • Fluent Queries - Chainable query builder with automatic GSI selection
  • Batch Operations - Efficient bulk read/write with automatic chunking
  • Transactions - ACID transactions across multiple tables
  • Soft Deletes - Built-in soft delete support with restore capability
  • Validation - Struct tag-based validation rules
  • Events - Lifecycle hooks for entities (Creating, Updating, Deleting, etc.)

Installation

go get github.com/go-gamma/dynorm

Quick Start

Define an Entity
type User struct {
    dynorm.Entity // Provides ID, CreatedAt, UpdatedAt, DeletedAt

    Email     string `dynorm:"gsi:ByEmail" validate:"required,email"`
    Username  string `validate:"required,min=3,max=20"`
    FirstName string
    LastName  string
    Status    string `validate:"enum=active|inactive|pending"`
}
Define a Repository
type UserRepository struct {
    dynorm.Repository[User]
}

var UserRepo = &UserRepository{}
Use It
// Create
user := &User{
    Email:     "alice@example.com",
    Username:  "alice",
    FirstName: "Alice",
    LastName:  "Smith",
    Status:    "active",
}
err := UserRepo.Save(user)
// user.ID is now set to a ULID like "01HQ3K4N5M6P7Q8R9S0T1U2V3W"

// Find
found, err := UserRepo.Find(user.ID)

// Query
activeUsers, err := UserRepo.
    Where("Status", "=", "active").
    OrderBy("CreatedAt", "desc").
    Limit(10).
    GetAll()

// Update
user.Status = "inactive"
err = UserRepo.Save(user)

// Delete
err = UserRepo.Delete(user)

Relationships

Dynorm supports Laravel-style relationships:

type User struct {
    dynorm.Entity
    Name  string
    Posts dynorm.HasMany[*PostRepository]
    Roles dynorm.BelongsToMany[*RoleRepository]
}

type Post struct {
    dynorm.Entity
    Title  string
    UserID string
    Author dynorm.BelongsTo[*UserRepository]
}

// Usage
user, _ := UserRepo.Find(userID)
posts, _ := user.Posts.Get()

// Eager loading (prevents N+1)
users, _ := UserRepo.With("Posts", "Roles").GetAll()

Configuration

export AWS_REGION=us-east-1
export DYNORM_TABLE_PREFIX=prod-

Or programmatically:

dynorm.SetTablePrefix("prod-")
dynorm.SetClient(customClient)

Documentation

Full documentation is available at go-gamma.github.io/dynorm

Requirements

  • Go 1.24+
  • AWS SDK for Go v2
  • DynamoDB tables with appropriate schema

License

MIT License - see LICENSE.md for details.

Documentation

Overview

Package dynorm provides a type-safe DynamoDB abstraction layer for Go.

Basic usage:

import "github.com/go-gamma/dynorm"

type User struct {
    dynorm.Entity
    Email string `dynorm:"gsi:ByEmail"`
    Name  string
}

type UserRepository struct {
    dynorm.Repository[User]
}

var UserRepo = &UserRepository{}

For local development with DynamoDB Local:

dynorm.SetEndpoint("http://localhost:8000")

For more examples, see the examples/ directory.

Index

Constants

View Source
const (
	// MaxBatchGetItems is the maximum items per BatchGetItem request.
	MaxBatchGetItems = impl.MaxBatchGetItems

	// MaxBatchWriteItems is the maximum items per BatchWriteItem request.
	MaxBatchWriteItems = impl.MaxBatchWriteItems

	// MaxTransactionItems is the maximum items per transaction.
	MaxTransactionItems = impl.MaxTransactionItems
)

Batch operation limits

Variables

View Source
var (
	// ErrRepositoryNotFound is returned when a relationship's repository cannot be found.
	ErrRepositoryNotFound = impl.ErrRepositoryNotFound

	// ErrPivotNotInitialized is returned when the pivot repository is not available.
	ErrPivotNotInitialized = impl.ErrPivotNotInitialized

	// ErrParentNotSaved is returned when trying to use a relationship before the parent is saved.
	ErrParentNotSaved = impl.ErrParentNotSaved

	// ErrEntityNil is returned when a nil entity is passed to a relationship method.
	ErrEntityNil = impl.ErrEntityNil

	// ErrEntityNotSaved is returned when trying to attach/relate an unsaved entity.
	ErrEntityNotSaved = impl.ErrEntityNotSaved

	// ErrForeignKeyNotSet is returned when a foreign key field cannot be set.
	ErrForeignKeyNotSet = impl.ErrForeignKeyNotSet

	// ErrMethodNotFound is returned when a required method doesn't exist on a repository.
	ErrMethodNotFound = impl.ErrMethodNotFound

	// ErrNoRepository is returned when a collection operation requires a repository
	// but the collection was created without one.
	ErrNoRepository = impl.ErrNoRepository
)

Relationship errors provide consistent error messages across all relationship types.

Functions

func GetEndpoint

func GetEndpoint() string

GetEndpoint returns the current custom DynamoDB endpoint. Returns an empty string if using the default AWS endpoint.

func GetTablePrefix

func GetTablePrefix() string

GetTablePrefix returns the current table prefix.

func Reset

func Reset()

Reset clears all global state. This is primarily useful for testing.

func SetClient

func SetClient(client *dynamodb.Client)

SetClient sets a custom DynamoDB client. This is primarily useful for testing with a mock client.

func SetContext

func SetContext(ctx context.Context)

SetContext sets the global context for all operations. This is typically called at the start of a Lambda handler.

func SetEndpoint

func SetEndpoint(endpoint string)

SetEndpoint sets a custom DynamoDB endpoint URL. This is primarily used for DynamoDB Local or other local development setups. This must be called BEFORE any repository operations, or after Reset().

Example:

dynorm.SetEndpoint("http://localhost:8000")

func SetTablePrefix

func SetTablePrefix(prefix string)

SetTablePrefix sets the table prefix for all tables. Normally, use the DYNORM_TABLE_PREFIX environment variable instead.

Types

type BelongsTo

type BelongsTo[R impl.RepositoryInterface] = impl.BelongsTo[R]

BelongsTo represents the inverse of a HasOne/HasMany relationship where the foreign key is on this entity (e.g., Post belongs to User via Post.UserID).

type BelongsToMany

type BelongsToMany[R impl.RepositoryInterface] = impl.BelongsToMany[R]

BelongsToMany represents a many-to-many relationship via a pivot table (e.g., User belongs to many Roles, Role belongs to many Users).

type Collection

type Collection[T any] = impl.Collection[T]

Collection wraps a slice of entities with utility methods for enumeration, filtering, sorting, and bulk operations.

type Created

type Created = impl.Created

Created is called after a new entity is successfully inserted.

type Creating

type Creating = impl.Creating

Creating is called before a new entity is inserted into the database.

type Cursor

type Cursor = impl.Cursor

Cursor represents an opaque pagination cursor.

type Deleted

type Deleted = impl.Deleted

Deleted is called after an entity is successfully deleted.

type Deleting

type Deleting = impl.Deleting

Deleting is called before an entity is deleted (soft or hard).

type Entity

type Entity = impl.Entity

Entity is the base struct that all entities should embed. It provides automatic ID generation (ULID), and timestamp management.

type ForceDeleted

type ForceDeleted = impl.ForceDeleted

ForceDeleted is called after an entity is permanently deleted.

type ForceDeleting

type ForceDeleting = impl.ForceDeleting

ForceDeleting is called before an entity is permanently deleted.

type HasMany

type HasMany[R impl.RepositoryInterface] = impl.HasMany[R]

HasMany represents a one-to-many relationship where the foreign key is on the related entities (e.g., User has many Posts via Post.UserID).

type HasManyThrough

type HasManyThrough[R impl.RepositoryInterface, Through impl.RepositoryInterface] = impl.HasManyThrough[R, Through]

HasManyThrough represents a has-many-through relationship (e.g., Country has many Posts through Users).

type HasOne

type HasOne[R impl.RepositoryInterface] = impl.HasOne[R]

HasOne represents a one-to-one relationship where the foreign key is on the related entity (e.g., User has one Profile via Profile.UserID).

type MorphMany

type MorphMany[R impl.RepositoryInterface] = impl.MorphMany[R]

MorphMany represents a polymorphic one-to-many relationship.

type MorphOne

type MorphOne[R impl.RepositoryInterface] = impl.MorphOne[R]

MorphOne represents a polymorphic one-to-one relationship.

type MorphToMany

type MorphToMany[R impl.RepositoryInterface] = impl.MorphToMany[R]

MorphToMany represents a polymorphic many-to-many relationship.

type MorphedByMany

type MorphedByMany[R impl.RepositoryInterface] = impl.MorphedByMany[R]

MorphedByMany represents the inverse of a polymorphic many-to-many relationship.

type PivotData

type PivotData = impl.PivotData

PivotData holds extra attributes on a pivot record.

type Query

type Query[T any] = impl.Query[T]

Query provides a fluent interface for building DynamoDB queries.

type RelationshipState

type RelationshipState = impl.RelationshipState

RelationshipState holds common state for all relationship types.

type Replicated

type Replicated = impl.Replicated

Replicated is called after an entity is replicated.

type Replicating

type Replicating = impl.Replicating

Replicating is called before an entity is replicated (copied).

type Repository

type Repository[T any] = impl.Repository[T]

Repository is the base repository struct that should be embedded. It provides CRUD operations and query building for entities of type T.

type RepositoryInterface

type RepositoryInterface = impl.RepositoryInterface

RepositoryInterface is the interface that all repositories must implement. This is needed for relationship type parameters.

type RepositoryTransaction

type RepositoryTransaction[T any] = impl.RepositoryTransaction[T]

RepositoryTransaction provides type-safe transaction operations for a repository.

type Restored

type Restored = impl.Restored

Restored is called after an entity is restored from soft delete.

type Restoring

type Restoring = impl.Restoring

Restoring is called before a soft-deleted entity is restored.

type Retrieved

type Retrieved = impl.Retrieved

Retrieved is called after an entity is loaded from the database.

type Retrieving

type Retrieving = impl.Retrieving

Retrieving is called before an entity is loaded from the database.

type Saved

type Saved = impl.Saved

Saved is called after any successful save operation.

type Saving

type Saving = impl.Saving

Saving is called before any save operation (create or update).

type Trashed

type Trashed = impl.Trashed

Trashed is called after an entity is soft deleted.

type Trashing

type Trashing = impl.Trashing

Trashing is called before an entity is soft deleted.

type UpdateBuilder

type UpdateBuilder = impl.UpdateBuilder

UpdateBuilder provides a fluent interface for building update operations.

func Update

func Update() *UpdateBuilder

Update creates a new UpdateBuilder for fluent update operations.

type Updated

type Updated = impl.Updated

Updated is called after an entity is successfully updated.

type Updating

type Updating = impl.Updating

Updating is called before an existing entity is updated in the database.

type Versioned

type Versioned = impl.Versioned

Versioned is an optional trait that provides optimistic locking support. Embed this in your entity struct to enable automatic version checking on save.

Directories

Path Synopsis
examples
basic command
Example basic demonstrates basic dynorm usage with a simple User entity.
Example basic demonstrates basic dynorm usage with a simple User entity.
caching command
Example caching demonstrates dynorm's query caching feature.
Example caching demonstrates dynorm's query caching feature.
lambda command
Example lambda demonstrates dynorm usage in AWS Lambda functions.
Example lambda demonstrates dynorm usage in AWS Lambda functions.
relationships command
Example relationships demonstrates dynorm relationship patterns.
Example relationships demonstrates dynorm relationship patterns.
internal
batch
Package batch provides internal batch operation utilities for dynorm.
Package batch provides internal batch operation utilities for dynorm.
collection
Package collection provides internal collection utilities for dynorm.
Package collection provides internal collection utilities for dynorm.
events
Package events provides internal event dispatching for dynorm.
Package events provides internal event dispatching for dynorm.
marshal
Package marshal provides internal marshaling utilities for dynorm.
Package marshal provides internal marshaling utilities for dynorm.
pagination
Package pagination provides internal pagination utilities for dynorm.
Package pagination provides internal pagination utilities for dynorm.
pivot
Package pivot provides internal pivot table helpers for dynorm.
Package pivot provides internal pivot table helpers for dynorm.
pluralize
Package pluralize provides internal pluralization utilities for dynorm.
Package pluralize provides internal pluralization utilities for dynorm.
query
Package query provides internal query utilities for dynorm.
Package query provides internal query utilities for dynorm.
reflect
Package reflect provides internal reflection utilities for dynorm.
Package reflect provides internal reflection utilities for dynorm.
registry
Package registry provides internal repository registry for dynorm.
Package registry provides internal repository registry for dynorm.
relationship
Package relationship provides internal relationship helpers for dynorm.
Package relationship provides internal relationship helpers for dynorm.
transaction
Package transaction provides internal transaction utilities for dynorm.
Package transaction provides internal transaction utilities for dynorm.
pkg
cache
Package cache provides a pluggable caching layer for dynorm queries.
Package cache provides a pluggable caching layer for dynorm queries.
dynorm
Package dynorm provides a type-safe DynamoDB abstraction layer for Go.
Package dynorm provides a type-safe DynamoDB abstraction layer for Go.
dynormtest
Package dynormtest provides mock implementations for unit testing.
Package dynormtest provides mock implementations for unit testing.
dynormtest/local
Package local provides utilities for testing with DynamoDB Local.
Package local provides utilities for testing with DynamoDB Local.
errors
Package errors provides custom error types for dynorm.
Package errors provides custom error types for dynorm.
relationship
Package relationship provides patterns for modeling entity relationships in DynamoDB.
Package relationship provides patterns for modeling entity relationships in DynamoDB.
schema
Package schema handles parsing of dynorm struct tags and schema extraction.
Package schema handles parsing of dynorm struct tags and schema extraction.
validation
Package validation provides field validation for dynorm entities.
Package validation provides field validation for dynorm entities.

Jump to

Keyboard shortcuts

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