Nigiri/collection.go
2025-08-15 22:04:24 -05:00

143 lines
2.9 KiB
Go

package nigiri
import (
"fmt"
"os"
"path/filepath"
"regexp"
"sync"
)
type StoreManager interface {
LoadData(path string) error
SaveData(path string) error
Clear()
EntityExists(id int) bool
SetValidator(validator any)
}
type Collection struct {
baseDir string
stores map[string]StoreManager
migrator *Migrator
mu sync.RWMutex
}
func NewCollection(baseDir string) *Collection {
return &Collection{
baseDir: baseDir,
stores: make(map[string]StoreManager),
migrator: nil, // Lazy initialized
}
}
// Add registers store and auto-loads if file exists
func (c *Collection) Add(name string, store StoreManager) error {
c.mu.Lock()
defer c.mu.Unlock()
c.stores[name] = store
store.SetValidator(c)
// Auto-load if file exists
path := filepath.Join(c.baseDir, name+".json")
if _, err := os.Stat(path); err == nil {
return store.LoadData(path)
}
return nil
}
// Get returns typed store
func Get[T any](c *Collection, name string) *BaseStore[T] {
c.mu.RLock()
defer c.mu.RUnlock()
if store, exists := c.stores[name]; exists {
if typed, ok := store.(*BaseStore[T]); ok {
return typed
}
}
return nil
}
// Load loads all stores
func (c *Collection) Load() error {
c.mu.RLock()
defer c.mu.RUnlock()
os.MkdirAll(c.baseDir, 0755)
for name, store := range c.stores {
path := filepath.Join(c.baseDir, name+".json")
if err := store.LoadData(path); err != nil {
return fmt.Errorf("load %s: %w", name, err)
}
}
return nil
}
// Save saves all stores
func (c *Collection) Save() error {
c.mu.RLock()
defer c.mu.RUnlock()
os.MkdirAll(c.baseDir, 0755)
for name, store := range c.stores {
path := filepath.Join(c.baseDir, name+".json")
if err := store.SaveData(path); err != nil {
return fmt.Errorf("save %s: %w", name, err)
}
}
return nil
}
// Clear clears all stores
func (c *Collection) Clear() {
c.mu.RLock()
defer c.mu.RUnlock()
for _, store := range c.stores {
store.Clear()
}
}
// EntityExists implements relationship validation
func (c *Collection) EntityExists(entityName string, id int) bool {
c.mu.RLock()
defer c.mu.RUnlock()
if store, exists := c.stores[entityName]; exists {
return store.EntityExists(id)
}
return false
}
// Migration methods
func (c *Collection) GetMigrator() *Migrator {
if c.migrator == nil {
c.migrator = NewMigrator()
}
return c.migrator
}
func (c *Collection) RegisterMigrationCommand(name string, pattern *regexp.Regexp, handler MigrationHandler) {
c.GetMigrator().RegisterCommand(name, pattern, handler)
}
func (c *Collection) MigrateStore(storeName, command string) error {
c.mu.Lock()
defer c.mu.Unlock()
path := filepath.Join(c.baseDir, storeName+".json")
return c.GetMigrator().MigrateFile(path, command)
}
func (c *Collection) RunMigrationScript(scriptFile string) error {
return c.GetMigrator().RunScript(c.baseDir, scriptFile)
}
func (c *Collection) CreateMigrationCLI() *MigrationCLI {
return NewMigrationCLI(c)
}