package store import ( "embed" "encoding/json" "fmt" "sort" "sync" "git.dumerain.org/alban/calcul-astreintes/internal/models" ) /* On embarque internal/store/profiles.json dans le binaire. Ça simplifie énormément le "standalone": pas de fichier externe obligatoire. */ //go:embed profiles.json var embeddedFS embed.FS type ProfileRepo struct { mu sync.RWMutex profiles map[string]models.Profile } type embeddedData struct { Rules models.GlobalRules `json:"rules"` Profiles []models.Profile `json:"profiles"` } func NewEmbeddedRepo() (*ProfileRepo, *models.GlobalRules, error) { b, err := embeddedFS.ReadFile("profiles.json") if err != nil { return nil, nil, err } var data embeddedData if err := json.Unmarshal(b, &data); err != nil { return nil, nil, err } repo := &ProfileRepo{profiles: map[string]models.Profile{}} for _, p := range data.Profiles { repo.profiles[p.ID] = p } return repo, &data.Rules, nil } // List : profils triés par label (pour un dropdown stable). func (r *ProfileRepo) List() ([]models.ProfileListItem, error) { r.mu.RLock() defer r.mu.RUnlock() items := make([]models.ProfileListItem, 0, len(r.profiles)) for _, p := range r.profiles { items = append(items, models.ProfileListItem{ID: p.ID, Label: p.Label}) } sort.Slice(items, func(i, j int) bool { return items[i].Label < items[j].Label }) return items, nil } func (r *ProfileRepo) Get(id string) (models.Profile, error) { r.mu.RLock() defer r.mu.RUnlock() p, ok := r.profiles[id] if !ok { return models.Profile{}, fmt.Errorf("profil introuvable: %s", id) } return p, nil }