package store import ( "encoding/json" "fmt" "os" "path/filepath" "superwork-tui/internal/config" ) // ProfileRow is one row in the profiles grid: a key and its per-profile values. type ProfileRow struct { Key string `json:"key"` Values map[string]string `json:"values"` } // ProfilesData is the workspace-level profiles grid persisted to profiles.json. type ProfilesData struct { Profiles []string `json:"profiles"` Rows []ProfileRow `json:"rows"` } func profilesFile(workspaceRoot string) string { return filepath.Join(config.SpxDir(workspaceRoot), "profiles.json") } // ReadProfiles reads the workspace profiles grid. // A missing or malformed file returns default data without error. func ReadProfiles(workspaceRoot string) (ProfilesData, error) { raw, err := os.ReadFile(profilesFile(workspaceRoot)) if err != nil { return ProfilesData{ Profiles: []string{"dev", "prod"}, Rows: []ProfileRow{}, }, nil } var data ProfilesData if err := json.Unmarshal(raw, &data); err != nil { return ProfilesData{ Profiles: []string{"dev", "prod"}, Rows: []ProfileRow{}, }, nil } if len(data.Profiles) == 0 { data.Profiles = []string{"dev", "prod"} } if data.Rows == nil { data.Rows = []ProfileRow{} } return data, nil } // WriteProfiles persists the profiles grid. Creates .spx if needed. func WriteProfiles(workspaceRoot string, data ProfilesData) error { if err := os.MkdirAll(config.SpxDir(workspaceRoot), 0o755); err != nil { return fmt.Errorf("create .spx dir: %w", err) } b, err := json.MarshalIndent(data, "", " ") if err != nil { return fmt.Errorf("marshal profiles: %w", err) } if err := os.WriteFile(profilesFile(workspaceRoot), append(b, '\n'), 0o644); err != nil { return fmt.Errorf("write profiles: %w", err) } return nil }