package nigiri import ( "fmt" "os" "path/filepath" "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 mu sync.RWMutex } func NewCollection(baseDir string) *Collection { return &Collection{ baseDir: baseDir, stores: make(map[string]StoreManager), } } // 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 }