package projects import ( "errors" "sort" "sync" "gorm.io/gorm" ) // Store : persistance des projets. type Store interface { Create(p Project) (Project, error) Get(id string) (Project, bool) List() ([]Project, error) Update(p Project) (Project, error) } // GormStore : Store adossé à PostgreSQL via GORM. type GormStore struct{ db *gorm.DB } func NewGormStore(db *gorm.DB) *GormStore { return &GormStore{db: db} } func (s *GormStore) Create(p Project) (Project, error) { if err := s.db.Create(&p).Error; err != nil { return Project{}, err } return p, nil } func (s *GormStore) Get(id string) (Project, bool) { var p Project err := s.db.Where("id = ?", id).First(&p).Error if errors.Is(err, gorm.ErrRecordNotFound) || err != nil { return Project{}, false } return p, true } func (s *GormStore) List() ([]Project, error) { var out []Project if err := s.db.Order("created_at DESC").Find(&out).Error; err != nil { return nil, err } return out, nil } func (s *GormStore) Update(p Project) (Project, error) { if err := s.db.Save(&p).Error; err != nil { return Project{}, err } return p, nil } // MemStore : Store en mémoire (dev/tests). type MemStore struct { mu sync.RWMutex items map[string]Project } func NewMemStore() *MemStore { return &MemStore{items: make(map[string]Project)} } func (m *MemStore) Create(p Project) (Project, error) { m.mu.Lock() defer m.mu.Unlock() m.items[p.ID] = p return p, nil } func (m *MemStore) Get(id string) (Project, bool) { m.mu.RLock() defer m.mu.RUnlock() p, ok := m.items[id] return p, ok } func (m *MemStore) List() ([]Project, error) { m.mu.RLock() defer m.mu.RUnlock() out := make([]Project, 0, len(m.items)) for _, p := range m.items { out = append(out, p) } sort.Slice(out, func(i, j int) bool { return out[i].CreatedAt.After(out[j].CreatedAt) }) return out, nil } func (m *MemStore) Update(p Project) (Project, error) { m.mu.Lock() defer m.mu.Unlock() m.items[p.ID] = p return p, nil }