provider.go

 1package configv2
 2
 3import (
 4	"encoding/json"
 5	"os"
 6	"path/filepath"
 7	"sync"
 8
 9	"github.com/charmbracelet/fur/pkg/client"
10	"github.com/charmbracelet/fur/pkg/provider"
11)
12
13var fur = client.New()
14
15var (
16	providerOnc  sync.Once // Ensures the initialization happens only once
17	providerList []provider.Provider
18)
19
20func providersPath() string {
21	return filepath.Join(baseDataPath(), "providers.json")
22}
23
24func saveProviders(providers []provider.Provider) error {
25	path := providersPath()
26	dir := filepath.Dir(path)
27	if err := os.MkdirAll(dir, 0o755); err != nil {
28		return err
29	}
30
31	data, err := json.MarshalIndent(providers, "", "  ")
32	if err != nil {
33		return err
34	}
35
36	return os.WriteFile(path, data, 0o644)
37}
38
39func loadProviders() ([]provider.Provider, error) {
40	path := providersPath()
41	data, err := os.ReadFile(path)
42	if err != nil {
43		return nil, err
44	}
45
46	var providers []provider.Provider
47	err = json.Unmarshal(data, &providers)
48	return providers, err
49}
50
51func Providers() []provider.Provider {
52	providerOnc.Do(func() {
53		// Try to get providers from upstream API
54		if providers, err := fur.GetProviders(); err == nil {
55			providerList = providers
56			// Save providers locally for future fallback
57			_ = saveProviders(providers)
58		} else {
59			// If upstream fails, try to load from local cache
60			if localProviders, localErr := loadProviders(); localErr == nil {
61				providerList = localProviders
62			} else {
63				// If both fail, return empty list
64				providerList = []provider.Provider{}
65			}
66		}
67	})
68	return providerList
69}