package collection import ( "encoding/json" "fmt" "strings" "codeberg.org/mapleopentech/monorepo/native/desktop/maplefile/pkg/storage" "codeberg.org/mapleopentech/monorepo/native/desktop/maplefile/internal/domain/collection" ) const ( collectionKeyPrefix = "collection:" parentCollIndex = "parent_collection_index:" rootCollIndex = "root_collection_index:" ) type repository struct { storage storage.Storage } // ProvideRepository creates a new collection repository for Wire func ProvideRepository(storage storage.Storage) collection.Repository { return &repository{storage: storage} } func (r *repository) Create(c *collection.Collection) error { return r.save(c) } func (r *repository) Get(id string) (*collection.Collection, error) { key := collectionKeyPrefix + id data, err := r.storage.Get(key) if err != nil { return nil, fmt.Errorf("failed to get collection: %w", err) } if data == nil { return nil, nil } var c collection.Collection if err := json.Unmarshal(data, &c); err != nil { return nil, fmt.Errorf("failed to unmarshal collection: %w", err) } return &c, nil } func (r *repository) Update(c *collection.Collection) error { // Get existing collection to clean up old indexes if parent changed existing, err := r.Get(c.ID) if err != nil { return fmt.Errorf("failed to get existing collection: %w", err) } if existing != nil && existing.ParentID != c.ParentID { // Clean up old parent index if existing.ParentID == "" { oldRootKey := rootCollIndex + existing.ID _ = r.storage.Delete(oldRootKey) } else { oldParentKey := parentCollIndex + existing.ParentID + ":" + existing.ID _ = r.storage.Delete(oldParentKey) } } return r.save(c) } func (r *repository) Delete(id string) error { // Get collection first to remove indexes c, err := r.Get(id) if err != nil { return err } if c == nil { return nil // Nothing to delete } // Delete parent index or root index if c.ParentID == "" { rootKey := rootCollIndex + id if err := r.storage.Delete(rootKey); err != nil { return fmt.Errorf("failed to delete root index: %w", err) } } else { parentKey := parentCollIndex + c.ParentID + ":" + id if err := r.storage.Delete(parentKey); err != nil { return fmt.Errorf("failed to delete parent index: %w", err) } } // Delete collection collKey := collectionKeyPrefix + id if err := r.storage.Delete(collKey); err != nil { return fmt.Errorf("failed to delete collection: %w", err) } return nil } func (r *repository) List() ([]*collection.Collection, error) { var collections []*collection.Collection err := r.storage.Iterate(func(key, value []byte) error { keyStr := string(key) if strings.HasPrefix(keyStr, collectionKeyPrefix) { var c collection.Collection if err := json.Unmarshal(value, &c); err != nil { return fmt.Errorf("failed to unmarshal collection: %w", err) } collections = append(collections, &c) } return nil }) if err != nil { return nil, fmt.Errorf("failed to list collections: %w", err) } return collections, nil } func (r *repository) ListByParent(parentID string) ([]*collection.Collection, error) { var collections []*collection.Collection prefix := parentCollIndex + parentID + ":" err := r.storage.Iterate(func(key, value []byte) error { keyStr := string(key) if strings.HasPrefix(keyStr, prefix) { // Extract collection ID from index key collID := strings.TrimPrefix(keyStr, prefix) c, err := r.Get(collID) if err != nil { return err } if c != nil { collections = append(collections, c) } } return nil }) if err != nil { return nil, fmt.Errorf("failed to list collections by parent: %w", err) } return collections, nil } func (r *repository) ListRoot() ([]*collection.Collection, error) { var collections []*collection.Collection err := r.storage.Iterate(func(key, value []byte) error { keyStr := string(key) if strings.HasPrefix(keyStr, rootCollIndex) { // Extract collection ID from index key collID := strings.TrimPrefix(keyStr, rootCollIndex) c, err := r.Get(collID) if err != nil { return err } if c != nil { collections = append(collections, c) } } return nil }) if err != nil { return nil, fmt.Errorf("failed to list root collections: %w", err) } return collections, nil } func (r *repository) Exists(id string) (bool, error) { key := collectionKeyPrefix + id data, err := r.storage.Get(key) if err != nil { return false, fmt.Errorf("failed to check collection existence: %w", err) } return data != nil, nil } // save persists the collection and maintains indexes func (r *repository) save(c *collection.Collection) error { data, err := json.Marshal(c) if err != nil { return fmt.Errorf("failed to marshal collection: %w", err) } // Save collection by ID collKey := collectionKeyPrefix + c.ID if err := r.storage.Set(collKey, data); err != nil { return fmt.Errorf("failed to save collection: %w", err) } // Create parent index (for ListByParent) or root index (for ListRoot) if c.ParentID == "" { rootKey := rootCollIndex + c.ID if err := r.storage.Set(rootKey, []byte(c.ID)); err != nil { return fmt.Errorf("failed to create root index: %w", err) } } else { parentKey := parentCollIndex + c.ParentID + ":" + c.ID if err := r.storage.Set(parentKey, []byte(c.ID)); err != nil { return fmt.Errorf("failed to create parent index: %w", err) } } return nil }