Documentation
¶
Overview ¶
Package orm provides a generics-based ORM with auto-registration, auto-serialization of underscore fields, lifecycle hooks, and optional KV cache. It is designed to be extracted from and remain backward-compatible with github.com/hanzoai/commerce.
Index ¶
- Constants
- Variables
- func ApplyDefaults[T any](entity *T)
- func CloneFromJSON[T any](data []byte) (*T, error)
- func DeserializeFields(entity interface{}) error
- func EntityCacheKey(namespace, kind, id string) string
- func Get[T any](db DB, id string) (*T, error)
- func GetOrCreate[T any](db DB, id string, defaults func(*T)) (*T, bool, error)
- func GetOrUpdate[T any](db DB, id string, fn func(*T)) (*T, error)
- func HashQuery(queryStr string) string
- func Kind[T any]() string
- func Kinds() []string
- func MustGet[T any](db DB, id string) *T
- func New[T any](db DB) *T
- func QueryCacheKey(namespace, kind, queryHash string) string
- func Register[T any](kind string, opts ...Option[T])
- func SerializeFields(entity interface{}) error
- func SetCache(cache CacheLayer)
- func Zero[T any]() *T
- type AfterCreator
- type AfterDeleter
- type AfterUpdater
- type BeforeCreator
- type BeforeDeleter
- type BeforeUpdater
- type CacheConfig
- type CacheLayer
- type DB
- type Defaulter
- type Iterator
- type KVCache
- func (c *KVCache) Close() error
- func (c *KVCache) GetEntity(ctx context.Context, kind, id string) ([]byte, bool, error)
- func (c *KVCache) GetQuery(ctx context.Context, kind, queryHash string) ([]byte, bool, error)
- func (c *KVCache) InvalidateEntity(ctx context.Context, kind, id string) error
- func (c *KVCache) InvalidateKind(ctx context.Context, kind string) error
- func (c *KVCache) SetEntity(ctx context.Context, kind, id string, data []byte, ttl time.Duration) error
- func (c *KVCache) SetQuery(ctx context.Context, kind, queryHash string, data []byte, ttl time.Duration) error
- type KVCacheConfig
- type Key
- type LegacyEntity
- type LegacyKind
- type MemoryCache
- func (c *MemoryCache) Close() error
- func (c *MemoryCache) GetEntity(_ context.Context, kind, id string) ([]byte, bool, error)
- func (c *MemoryCache) GetQuery(_ context.Context, kind, queryHash string) ([]byte, bool, error)
- func (c *MemoryCache) InvalidateEntity(_ context.Context, kind, id string) error
- func (c *MemoryCache) InvalidateKind(_ context.Context, kind string) error
- func (c *MemoryCache) Len() int
- func (c *MemoryCache) SetEntity(_ context.Context, kind, id string, data []byte, ttl time.Duration) error
- func (c *MemoryCache) SetQuery(_ context.Context, kind, queryHash string, data []byte, ttl time.Duration) error
- type Model
- func (m *Model[T]) Clone() *T
- func (m *Model[T]) Create() error
- func (m *Model[T]) CreateCtx(ctx context.Context) error
- func (m *Model[T]) Created() bool
- func (m *Model[T]) DB() DB
- func (m *Model[T]) Delete() error
- func (m *Model[T]) DeleteCtx(ctx context.Context) error
- func (m *Model[T]) Exists() (bool, error)
- func (m *Model[T]) Get(key Key) error
- func (m *Model[T]) GetById(id string) error
- func (m *Model[T]) Id() string
- func (m *Model[T]) Init(db DB)
- func (m *Model[T]) IsMock() bool
- func (m *Model[T]) JSON() []byte
- func (m *Model[T]) JSONString() string
- func (m *Model[T]) Key() Key
- func (m Model[T]) Kind() string
- func (m *Model[T]) MustCreate()
- func (m *Model[T]) MustDelete()
- func (m *Model[T]) MustUpdate()
- func (m *Model[T]) Namespace() string
- func (m *Model[T]) Parent() Key
- func (m *Model[T]) Put() error
- func (m *Model[T]) PutCtx(ctx context.Context) error
- func (m *Model[T]) Query() *ModelQuery[T]
- func (m *Model[T]) SetDB(db DB)
- func (m *Model[T]) SetId(id string)
- func (m *Model[T]) SetKey(key Key)
- func (m *Model[T]) SetMock(mock bool)
- func (m *Model[T]) SetNamespace(ns string)
- func (m *Model[T]) SetParent(parent Key)
- func (m *Model[T]) Update() error
- func (m *Model[T]) UpdateCtx(ctx context.Context) error
- type ModelMeta
- type ModelQuery
- func (q *ModelQuery[T]) Ancestor(key Key) *ModelQuery[T]
- func (q *ModelQuery[T]) ById(id string) (bool, error)
- func (q *ModelQuery[T]) Count(ctx context.Context) (int, error)
- func (q *ModelQuery[T]) Filter(filterStr string, value interface{}) *ModelQuery[T]
- func (q *ModelQuery[T]) First() (*T, error)
- func (q *ModelQuery[T]) Get() (bool, error)
- func (q *ModelQuery[T]) GetAll(ctx context.Context) ([]*T, error)
- func (q *ModelQuery[T]) IdExists(id string) (Key, bool, error)
- func (q *ModelQuery[T]) Inner() Query
- func (q *ModelQuery[T]) KeyExists(key Key) (bool, error)
- func (q *ModelQuery[T]) Limit(limit int) *ModelQuery[T]
- func (q *ModelQuery[T]) Offset(offset int) *ModelQuery[T]
- func (q *ModelQuery[T]) Order(fieldPath string) *ModelQuery[T]
- type NoopCache
- func (c *NoopCache) Close() error
- func (c *NoopCache) GetEntity(_ context.Context, _, _ string) ([]byte, bool, error)
- func (c *NoopCache) GetQuery(_ context.Context, _, _ string) ([]byte, bool, error)
- func (c *NoopCache) InvalidateEntity(_ context.Context, _, _ string) error
- func (c *NoopCache) InvalidateKind(_ context.Context, _ string) error
- func (c *NoopCache) SetEntity(_ context.Context, _, _ string, _ []byte, _ time.Duration) error
- func (c *NoopCache) SetQuery(_ context.Context, _, _ string, _ []byte, _ time.Duration) error
- type Option
- type Query
Constants ¶
const CacheKeyPrefix = "orm"
CacheKeyPrefix is prepended to all cache keys.
const DefaultEntityTTL = 5 * time.Minute
DefaultEntityTTL is the default TTL for cached entities.
const DefaultQueryTTL = 1 * time.Minute
DefaultQueryTTL is the default TTL for cached query results.
Variables ¶
var ( // ErrNotFound is returned when an entity is not found. ErrNotFound = errors.New("orm: entity not found") // ErrAlreadyRegistered is returned when a kind is registered twice. ErrAlreadyRegistered = errors.New("orm: kind already registered") )
var OpenPostgres = OpenSQL
OpenPostgres is an alias for OpenSQL (backward compatibility).
Functions ¶
func ApplyDefaults ¶
func ApplyDefaults[T any](entity *T)
ApplyDefaults sets default values on entity from: 1. orm:"default:value" struct tags (parsed at registration) 2. Defaulter interface (custom Defaults() method)
func CloneFromJSON ¶ added in v0.3.0
CloneFromJSON creates a new T from JSON data.
func DeserializeFields ¶
func DeserializeFields(entity interface{}) error
DeserializeFields unmarshals all registered serialized fields (Foo_ → Foo). Called automatically after Get/GetById.
For each pair in ModelMeta.Serialized:
- Read the string from the underscore field
- Unmarshal into the JSON field
func EntityCacheKey ¶
EntityCacheKey returns the cache key for an entity.
func GetOrCreate ¶ added in v0.3.0
GetOrCreate retrieves an entity by ID, or creates it with defaults if not found. Returns (entity, created, error).
func GetOrUpdate ¶ added in v0.3.0
GetOrUpdate retrieves an entity by ID, applies fn, and updates it.
func New ¶
New creates a new instance of T, wired to db, with defaults applied. This replaces the per-model New() function and model.go boilerplate.
func QueryCacheKey ¶
QueryCacheKey returns the cache key for a query.
func Register ¶
Register records type T under the given kind string. Must be called from init() or before any ORM operations.
func SerializeFields ¶
func SerializeFields(entity interface{}) error
SerializeFields marshals all registered serialized fields (Foo → Foo_). Called automatically before Put().
For each pair in ModelMeta.Serialized:
- Marshal the JSON field value to a JSON string
- Store the string in the underscore field
Types ¶
type AfterCreator ¶
type AfterCreator interface {
AfterCreate() error
}
AfterCreator is called after a new entity is persisted.
type AfterDeleter ¶
type AfterDeleter interface {
AfterDelete() error
}
AfterDeleter is called after an entity is deleted.
type AfterUpdater ¶
AfterUpdater is called after an entity update, receiving a clone of the previous state.
type BeforeCreator ¶
type BeforeCreator interface {
BeforeCreate() error
}
BeforeCreator is called before a new entity is persisted.
type BeforeDeleter ¶
type BeforeDeleter interface {
BeforeDelete() error
}
BeforeDeleter is called before an entity is deleted.
type BeforeUpdater ¶
BeforeUpdater is called before an entity update, receiving a clone of the previous state. The type parameter allows strongly-typed prev values.
type CacheConfig ¶
type CacheConfig struct {
Enabled bool
EntityTTL int // seconds, 0 = use global default
QueryTTL int // seconds, 0 = use global default
}
CacheConfig controls per-model caching behavior.
type CacheLayer ¶
type CacheLayer interface {
// GetEntity returns a cached entity, or false if not found.
GetEntity(ctx context.Context, kind, id string) ([]byte, bool, error)
// SetEntity caches an entity.
SetEntity(ctx context.Context, kind, id string, data []byte, ttl time.Duration) error
// InvalidateEntity removes a cached entity and all queries for its kind.
InvalidateEntity(ctx context.Context, kind, id string) error
// InvalidateKind removes all cached queries for a kind.
InvalidateKind(ctx context.Context, kind string) error
// GetQuery returns cached query results, or false if not found.
GetQuery(ctx context.Context, kind, queryHash string) ([]byte, bool, error)
// SetQuery caches query results.
SetQuery(ctx context.Context, kind, queryHash string, data []byte, ttl time.Duration) error
// Close releases resources.
Close() error
}
CacheLayer provides read-through/write-through caching for entities and queries.
type DB ¶
type DB interface {
// Get loads the entity identified by key into dst.
Get(ctx context.Context, key Key, dst interface{}) error
// Put persists src under key, returning the (possibly updated) key.
Put(ctx context.Context, key Key, src interface{}) (Key, error)
// Delete removes the entity identified by key.
Delete(ctx context.Context, key Key) error
// Query returns a new query builder for the given kind.
Query(kind string) Query
// NewKey creates a key with the given kind, string ID, int ID, and parent.
NewKey(kind string, stringID string, intID int64, parent Key) Key
// NewIncompleteKey creates an incomplete key (ID allocated on put).
NewIncompleteKey(kind string, parent Key) Key
// AllocateIDs pre-allocates n IDs for the given kind.
AllocateIDs(kind string, parent Key, n int) ([]Key, error)
// RunInTransaction executes fn inside a transaction.
RunInTransaction(ctx context.Context, fn func(tx DB) error) error
// Close releases resources.
Close() error
}
DB is the minimal database interface the ORM requires. Implementations exist for SQLite, PostgreSQL, MongoDB, and the legacy Hanzo Datastore. Commerce's datastore.Datastore satisfies this via a thin adapter.
func OpenSQLite ¶
func OpenSQLite(cfg *ormdb.SQLiteDBConfig) (DB, error)
OpenSQLite creates an orm.DB backed by SQLite.
type Defaulter ¶
type Defaulter interface {
Defaults()
}
Defaulter is implemented by models that need custom default values beyond what orm:"default:..." tags provide.
type KVCache ¶
type KVCache struct {
// contains filtered or unexported fields
}
KVCache is a Redis/Valkey-backed cache layer using hanzoai/kv-go.
func NewKVCache ¶
func NewKVCache(cfg KVCacheConfig) (*KVCache, error)
NewKVCache creates a new Redis/Valkey cache layer.
func NewKVCacheFromClient ¶
NewKVCacheFromClient creates a KVCache from an existing kv.Client.
func (*KVCache) InvalidateEntity ¶
func (*KVCache) InvalidateKind ¶
type KVCacheConfig ¶
type KVCacheConfig struct {
Addr string
Password string
DB int
Prefix string // key prefix, default "orm"
PoolSize int
}
KVCacheConfig configures the Redis/Valkey cache backend.
type Key ¶
type Key interface {
Kind() string
StringID() string
IntID() int64
Parent() Key
Namespace() string
Encode() string
}
Key identifies an entity in the datastore.
type LegacyEntity ¶
type LegacyEntity interface {
LegacyKind
Id() string
JSON() []byte
JSONString() string
}
LegacyEntity matches the subset of mixin.Entity needed for interop. Commerce's REST layer and query system use this interface.
type LegacyKind ¶
type LegacyKind interface {
Kind() string
}
LegacyKind matches the mixin.Kind interface.
type MemoryCache ¶
type MemoryCache struct {
// contains filtered or unexported fields
}
MemoryCache is an in-memory LRU cache layer.
func NewMemoryCache ¶
func NewMemoryCache(maxSize int) *MemoryCache
NewMemoryCache creates a new in-memory cache with the given maximum number of entries.
func (*MemoryCache) Close ¶
func (c *MemoryCache) Close() error
func (*MemoryCache) InvalidateEntity ¶
func (c *MemoryCache) InvalidateEntity(_ context.Context, kind, id string) error
func (*MemoryCache) InvalidateKind ¶
func (c *MemoryCache) InvalidateKind(_ context.Context, kind string) error
func (*MemoryCache) Len ¶
func (c *MemoryCache) Len() int
Len returns the number of entries in the cache.
type Model ¶
type Model[T any] struct { // Persisted fields Id_ string `json:"id,omitempty"` CreatedAt time.Time `json:"createdAt,omitempty"` UpdatedAt time.Time `json:"updatedAt,omitempty"` Deleted bool `json:"deleted,omitempty"` // contains filtered or unexported fields }
Model is a generic mixin embedded in every ORM entity. It replaces mixin.Model from commerce with type-safe generics.
Usage:
type PaymentIntent struct {
orm.Model[PaymentIntent]
Amount int64 `json:"amount"`
Currency string `json:"currency" orm:"default:usd"`
}
func init() { orm.Register[PaymentIntent]("payment-intent") }
func (*Model[T]) Clone ¶
func (m *Model[T]) Clone() *T
Clone creates a deep copy of the entity via JSON round-trip.
func (*Model[T]) CreateCtx ¶ added in v0.3.0
CreateCtx persists a new entity with context, executing Before/AfterCreate hooks.
func (*Model[T]) DeleteCtx ¶ added in v0.3.0
DeleteCtx removes the entity with context, executing Before/AfterDelete hooks.
func (*Model[T]) Init ¶
Init wires the model to a database. Called by New[T] and by the compat layer.
func (*Model[T]) JSONString ¶
JSONString serializes the entity to a JSON string.
func (*Model[T]) MustCreate ¶ added in v0.3.0
func (m *Model[T]) MustCreate()
MustCreate persists a new entity or panics.
func (*Model[T]) MustDelete ¶ added in v0.3.0
func (m *Model[T]) MustDelete()
MustDelete removes the entity or panics.
func (*Model[T]) MustUpdate ¶ added in v0.3.0
func (m *Model[T]) MustUpdate()
MustUpdate persists changes or panics.
func (*Model[T]) Namespace ¶ added in v0.3.0
Namespace returns the entity's namespace for multi-tenant isolation.
func (*Model[T]) PutCtx ¶ added in v0.3.0
PutCtx persists the entity with context, setting timestamps.
func (*Model[T]) Query ¶
func (m *Model[T]) Query() *ModelQuery[T]
Query returns a typed model query for this entity.
func (*Model[T]) SetNamespace ¶ added in v0.3.0
SetNamespace sets the entity's namespace for multi-tenant isolation.
type ModelMeta ¶
type ModelMeta struct {
Kind string
Type reflect.Type // the concrete struct type T (not *T)
StringKey bool
ParentFn func(DB) Key // optional parent key factory
InitFn func(DB, interface{}) // optional custom init
DefaultsFn func(interface{}) // optional custom defaults
Defaults map[string]string // field name → default value from tags
Serialized map[string]string // JSON field name → underscore field name
CacheConfig *CacheConfig // per-model cache settings (nil = use global)
}
ModelMeta holds parsed metadata for a registered model type.
func LookupType ¶
LookupType returns the metadata for the given type.
func MustLookup ¶
MustLookup returns the metadata for kind or panics.
type ModelQuery ¶
type ModelQuery[T any] struct { // contains filtered or unexported fields }
ModelQuery is a typed query wrapper for a single model type. It provides a fluent interface for filtering, ordering, and retrieving entities.
func TypedQuery ¶
func TypedQuery[T any](db DB) *ModelQuery[T]
TypedQuery returns a new query builder for type T.
func (*ModelQuery[T]) Ancestor ¶
func (q *ModelQuery[T]) Ancestor(key Key) *ModelQuery[T]
Ancestor restricts the query to descendants of the given key.
func (*ModelQuery[T]) ById ¶
func (q *ModelQuery[T]) ById(id string) (bool, error)
ById retrieves an entity by its string ID.
func (*ModelQuery[T]) Count ¶ added in v0.3.0
func (q *ModelQuery[T]) Count(ctx context.Context) (int, error)
Count returns the number of matching entities.
func (*ModelQuery[T]) Filter ¶
func (q *ModelQuery[T]) Filter(filterStr string, value interface{}) *ModelQuery[T]
Filter adds a filter condition.
func (*ModelQuery[T]) First ¶ added in v0.3.0
func (q *ModelQuery[T]) First() (*T, error)
First returns the first matching entity as a new instance, or ErrNotFound.
func (*ModelQuery[T]) Get ¶
func (q *ModelQuery[T]) Get() (bool, error)
Get retrieves the first matching entity into the model.
func (*ModelQuery[T]) GetAll ¶ added in v0.3.0
func (q *ModelQuery[T]) GetAll(ctx context.Context) ([]*T, error)
GetAll returns all matching entities.
func (*ModelQuery[T]) IdExists ¶
func (q *ModelQuery[T]) IdExists(id string) (Key, bool, error)
IdExists checks if the given ID exists.
func (*ModelQuery[T]) Inner ¶
func (q *ModelQuery[T]) Inner() Query
Inner returns the underlying Query for advanced operations.
func (*ModelQuery[T]) KeyExists ¶
func (q *ModelQuery[T]) KeyExists(key Key) (bool, error)
KeyExists checks if the given key exists.
func (*ModelQuery[T]) Limit ¶
func (q *ModelQuery[T]) Limit(limit int) *ModelQuery[T]
Limit sets the maximum number of results.
func (*ModelQuery[T]) Offset ¶
func (q *ModelQuery[T]) Offset(offset int) *ModelQuery[T]
Offset sets the number of results to skip.
func (*ModelQuery[T]) Order ¶
func (q *ModelQuery[T]) Order(fieldPath string) *ModelQuery[T]
Order adds an ordering clause.
type NoopCache ¶
type NoopCache struct{}
NoopCache is a cache layer that does nothing. Used when caching is disabled.
func (*NoopCache) InvalidateEntity ¶
func (*NoopCache) InvalidateKind ¶
type Option ¶
type Option[T any] interface { // contains filtered or unexported methods }
Option configures model registration.
func WithCache ¶
func WithCache[T any](cfg CacheConfig) Option[T]
WithCache configures per-model cache settings.
func WithDefaults ¶
WithDefaults sets a custom defaults function called on New().
func WithParent ¶
WithParent sets a function that returns the parent key for new entities.
func WithStringKey ¶
WithStringKey configures the model to use string IDs instead of auto-allocated int64 IDs.
type Query ¶
type Query interface {
Filter(filterStr string, value interface{}) Query
Order(fieldPath string) Query
Limit(limit int) Query
Offset(offset int) Query
Ancestor(ancestor Key) Query
KeysOnly() Query
// GetAll executes the query, populating dst (pointer to slice).
// Returns the matching keys.
GetAll(ctx context.Context, dst interface{}) ([]Key, error)
// First returns the first matching entity.
First(dst interface{}) (Key, bool, error)
// Count returns the number of matching entities.
Count(ctx context.Context) (int, error)
// ById finds an entity by its encoded ID.
ById(id string, dst interface{}) (Key, bool, error)
// IdExists checks whether the given ID exists.
IdExists(id string) (Key, bool, error)
// KeyExists checks whether the given key exists.
KeyExists(key Key) (bool, error)
}
Query is a fluent query builder.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package db provides a multi-layer database abstraction supporting: - User-level SQLite with sqlite-vec for personal data and vector search - Organization-level SQLite for shared tenant data - PostgreSQL with pgvector for scalable deployments - MongoDB/FerretDB for document storage - Hanzo Datastore (ClickHouse) for deep analytics
|
Package db provides a multi-layer database abstraction supporting: - User-level SQLite with sqlite-vec for personal data and vector search - Organization-level SQLite for shared tenant data - PostgreSQL with pgvector for scalable deployments - MongoDB/FerretDB for document storage - Hanzo Datastore (ClickHouse) for deep analytics |
|
Package engine provides an xorm-compatible API layer for hanzo/orm.
|
Package engine provides an xorm-compatible API layer for hanzo/orm. |
|
internal
|
|
|
json
Package json provides JSON encoding/decoding utilities.
|
Package json provides JSON encoding/decoding utilities. |
|
reflect
Package reflect provides reflection utilities for struct manipulation.
|
Package reflect provides reflection utilities for struct manipulation. |
|
Package names provides naming convention mappers for converting between Go struct field names and database column/table names.
|
Package names provides naming convention mappers for converting between Go struct field names and database column/table names. |
|
Package val provides struct field validation utilities.
|
Package val provides struct field validation utilities. |