Documentation
¶
Overview ¶
Package enginefile is the filesystem CRUD engine: it reads and writes entities to JSON or YAML files and evaluates every query feature (filters, sorts, pagination, field selection, soft-delete) in memory. Serialization goes through a pluggable Codec; two layout modes are supported:
- Single-file mode (default): one file per collection (e.g. cities.json)
- Directory mode: one file per entity (e.g. cities/1.json, cities/2.json)
Usage:
repo, err := enginefile.New[City, int](
enginefile.WithBaseDir("./data"),
enginefile.WithCodec(enginefile.JSONCodec()),
enginefile.WithIDGenerator(enginefile.IncrementIDGen[int]()),
)
Codecs can wrap an alternative JSON library via NewCodec.
Index ¶
- func IsNotFound(err error) bool
- func NewQuerier[T any, ID comparable](idGen IDGenerator[ID], opts ...Option) (r3.Querier[T, ID], error)
- type BaseCRUD
- func (r *BaseCRUD[T, ID]) Aggregate(_ context.Context, qarg ...r3.Query) ([]r3.AggregateRow, error)
- func (r *BaseCRUD[T, ID]) Count(_ context.Context, qarg ...r3.Query) (int64, error)
- func (r *BaseCRUD[T, ID]) Create(_ context.Context, entity T) (T, error)
- func (r *BaseCRUD[T, ID]) Delete(_ context.Context, id ID) error
- func (r *BaseCRUD[T, ID]) Get(_ context.Context, id ID, qarg ...r3.Query) (T, error)
- func (r *BaseCRUD[T, ID]) HardDelete(_ context.Context, id ID) error
- func (r *BaseCRUD[T, ID]) List(_ context.Context, qarg ...r3.Query) ([]T, int64, error)
- func (r *BaseCRUD[T, ID]) Patch(_ context.Context, entity T, fields r3.Fields) (T, error)
- func (r *BaseCRUD[T, ID]) Restore(_ context.Context, id ID) error
- func (r *BaseCRUD[T, ID]) Update(_ context.Context, entity T) (T, error)
- type Codec
- type Decoder
- type Encoder
- type IDGenerator
- type IDGeneratorFunc
- type Option
- type StructMeta
- func (m *StructMeta) CopyFieldValues(dst, src any, fieldNames []string)
- func (m *StructMeta) GetFieldValue(entity any, fieldName string) (any, bool)
- func (m *StructMeta) PKValue(entity any) any
- func (m *StructMeta) SetFieldValue(entityPtr any, fieldName string, val any) bool
- func (m *StructMeta) SetPKValue(entityPtr, val any)
- func (m *StructMeta) SoftDeleteFieldIdx() int
- func (m *StructMeta) ValidatePatchFields(fields []string) ([]string, error)
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func IsNotFound ¶
IsNotFound returns true if the error indicates that an entity was not found.
func NewQuerier ¶
func NewQuerier[T any, ID comparable](idGen IDGenerator[ID], opts ...Option) (r3.Querier[T, ID], error)
NewQuerier creates a read-only file-based repository: it builds a full BaseCRUD but returns only r3.Querier, so callers cannot write.
Types ¶
type BaseCRUD ¶
type BaseCRUD[T any, ID comparable] struct { r3.DefaultsManager Meta StructMeta Config r3.Config // contains filtered or unexported fields }
BaseCRUD implements r3.CRUD for file-based storage.
func New ¶
func New[T any, ID comparable](idGen IDGenerator[ID], opts ...Option) (*BaseCRUD[T, ID], error)
New creates a file-based CRUD instance. An IDGenerator must be provided.
func (*BaseCRUD[T, ID]) Aggregate ¶ added in v0.0.3
Aggregate computes grouped aggregates in memory. See r3.Aggregator for the query semantics.
func (*BaseCRUD[T, ID]) HardDelete ¶
HardDelete permanently removes an entity regardless of soft-delete configuration.
func (*BaseCRUD[T, ID]) Patch ¶
Patch performs a partial update, modifying only the specified fields.
type Codec ¶
type Codec interface {
// NewEncoder returns an encoder writing to w.
NewEncoder(w io.Writer) Encoder
// NewDecoder returns a decoder reading from r.
NewDecoder(r io.Reader) Decoder
// FileExtension returns the extension including the dot (e.g. ".json").
FileExtension() string
}
Codec serializes entity slices to and from files over streaming io.Reader/io.Writer.
func JSONCodec ¶
func JSONCodec() Codec
JSONCodec returns a Codec that uses encoding/json with pretty-printed output.
func JSONCodecCompact ¶
func JSONCodecCompact() Codec
JSONCodecCompact returns a Codec that uses encoding/json without indentation.
func NewCodec ¶
func NewCodec(ext string, newEncoder func(w io.Writer) Encoder, newDecoder func(r io.Reader) Decoder) Codec
NewCodec builds a custom Codec from encoder/decoder factories, for plugging in an alternative JSON library (goccy/go-json, json-iterator, ...) or any other format.
Example with goccy/go-json:
import goccy "github.com/goccy/go-json"
codec := enginefile.NewCodec(".json",
func(w io.Writer) enginefile.Encoder { return goccy.NewEncoder(w) },
func(r io.Reader) enginefile.Decoder { return goccy.NewDecoder(r) },
)
type IDGenerator ¶
type IDGenerator[ID comparable] interface { Generate(existing []ID) (ID, error) }
IDGenerator produces a new unique ID. Generate receives the existing IDs so an implementation can avoid collisions (e.g. auto-increment).
func IncrementIDGen ¶
func IncrementIDGen[ID interface {
~int | ~int8 | ~int16 | ~int32 | ~int64 |
~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64
}]() IDGenerator[ID]
IncrementIDGen returns an IDGenerator that auto-increments from the highest existing ID.
func UUIDStringIDGen ¶
func UUIDStringIDGen() IDGenerator[string]
UUIDStringIDGen returns an IDGenerator producing UUID v4 strings via crypto/rand (no external UUID dependency).
type IDGeneratorFunc ¶
type IDGeneratorFunc[ID comparable] func(existing []ID) (ID, error)
IDGeneratorFunc is a function adapter for IDGenerator.
func (IDGeneratorFunc[ID]) Generate ¶
func (f IDGeneratorFunc[ID]) Generate(existing []ID) (ID, error)
Generate implements IDGenerator by calling the function.
type Option ¶
type Option func(*config)
Option configures a BaseCRUD instance.
func WithBaseDir ¶
WithBaseDir sets the base directory; each entity type gets a file (or subdirectory) under it.
func WithDirectoryMode ¶
func WithDirectoryMode() Option
WithDirectoryMode stores each entity in its own file under a resource-named directory (cities/1.json, cities/2.json) instead of a single cities.json.
func WithFilePath ¶
WithFilePath overrides the auto-derived path (resource name + codec extension). Single-file mode only.
func WithR3Options ¶
WithR3Options passes framework-level r3.Option values (e.g. r3.WithConfig) to the file-based CRUD constructor.
type StructMeta ¶
type StructMeta struct {
// ResourceName is the derived collection/resource name (e.g. "cities").
// Used as the filename stem or directory name.
ResourceName string
// Fields holds the storage field names in order (derived from json/yaml/r3/db tags).
Fields []string
// FieldIndices holds the corresponding struct field indices for each field.
FieldIndices []int
// PKField is the primary key field name (defaults to "id").
PKField string
// PKFieldIdx is the index into Fields/FieldIndices for the PK entry.
PKFieldIdx int
// SoftDeleteField is the field name used for soft-delete (e.g. "deleted_at").
// Empty string means soft-delete is not enabled.
SoftDeleteField string
}
StructMeta holds reflection-based metadata about a struct type T for file storage.
func GetStructMeta ¶
func GetStructMeta[T any]() StructMeta
GetStructMeta derives the resource name and field info for T. Field-name priority: `r3`, then `json`, then `yaml`, then `db`, then snake_case.
func (*StructMeta) CopyFieldValues ¶
func (m *StructMeta) CopyFieldValues(dst, src any, fieldNames []string)
CopyFieldValues copies the specified fields from src to dst (both must be pointers).
func (*StructMeta) GetFieldValue ¶
func (m *StructMeta) GetFieldValue(entity any, fieldName string) (any, bool)
GetFieldValue extracts a field value from an entity by field name (storage name).
func (*StructMeta) PKValue ¶
func (m *StructMeta) PKValue(entity any) any
PKValue extracts the primary key value from an entity.
func (*StructMeta) SetFieldValue ¶
func (m *StructMeta) SetFieldValue(entityPtr any, fieldName string, val any) bool
SetFieldValue sets a field value on an entity (via pointer) by field name.
func (*StructMeta) SetPKValue ¶
func (m *StructMeta) SetPKValue(entityPtr, val any)
SetPKValue sets the primary key value on an entity (via pointer).
func (*StructMeta) SoftDeleteFieldIdx ¶
func (m *StructMeta) SoftDeleteFieldIdx() int
SoftDeleteFieldIdx returns the struct field index for the soft-delete field, or -1.
func (*StructMeta) ValidatePatchFields ¶
func (m *StructMeta) ValidatePatchFields(fields []string) ([]string, error)
ValidatePatchFields checks that the given field names are valid for a Patch operation.