package commands import ( "encoding/json" "os" "path/filepath" "sync" ) type UserConfig struct { InstanceURL string `json:"instance_url"` APIKey string `json:"api_key"` } var ( storePath = filepath.Join("users.json") mu sync.Mutex ) func ensureDir() error { dir := filepath.Dir(storePath) return os.MkdirAll(dir, 0o755) } func GetUserConfig(userID string) (UserConfig, bool, error) { m, err := loadAll() if err != nil { return UserConfig{}, false, err } cfg, ok := m[userID] return cfg, ok, nil } func SaveUserConfig(userID string, cfg UserConfig) error { m, err := loadAll() if err != nil { // if load fails, maybe just start fresh? m = make(map[string]UserConfig) } m[userID] = cfg return saveAll(m) } func DeleteUserConfig(userID string) error { m, err := loadAll() if err != nil { return err } delete(m, userID) return saveAll(m) } func loadAll() (map[string]UserConfig, error) { mu.Lock() defer mu.Unlock() if err := ensureDir(); err != nil { return nil, err } if _, err := os.Stat(storePath); os.IsNotExist(err) { return map[string]UserConfig{}, nil } b, err := os.ReadFile(storePath) if err != nil { return nil, err } var m map[string]UserConfig if err := json.Unmarshal(b, &m); err != nil { return map[string]UserConfig{}, nil // return empty on corrupt } return m, nil } func saveAll(m map[string]UserConfig) error { mu.Lock() defer mu.Unlock() if err := ensureDir(); err != nil { return err } b, err := json.MarshalIndent(m, "", " ") if err != nil { return err } return os.WriteFile(storePath, b, 0o644) }