- Panel Reglages dans l'UI (modal) - Folder picker natif Wails pour dossier local - ListS3Buckets via aws-cli (profile-aware) - TestS3Access pour verifier acces bucket - Config persistee user config dir (cross-OS): %APPDATA%/field-sync ou ~/.config/field-sync - Header affiche bucket + dest visibles - Auto-open modal si bucket vide au premier run Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
90 lines
1.9 KiB
Go
90 lines
1.9 KiB
Go
package config
|
|
|
|
import (
|
|
"encoding/json"
|
|
"os"
|
|
"path/filepath"
|
|
"strconv"
|
|
|
|
"github.com/joho/godotenv"
|
|
)
|
|
|
|
// Config holds runtime configuration
|
|
type Config struct {
|
|
S3Bucket string `json:"s3Bucket"`
|
|
LocalDest string `json:"localDest"`
|
|
AWSProfile string `json:"awsProfile"`
|
|
Concurrency int `json:"concurrency"`
|
|
}
|
|
|
|
// Path returns the cross-OS config file path
|
|
func Path() string {
|
|
dir, _ := os.UserConfigDir()
|
|
return filepath.Join(dir, "field-sync", "config.json")
|
|
}
|
|
|
|
// Save writes config to disk (atomic)
|
|
func Save(cfg Config) error {
|
|
p := Path()
|
|
if err := os.MkdirAll(filepath.Dir(p), 0755); err != nil {
|
|
return err
|
|
}
|
|
data, _ := json.MarshalIndent(cfg, "", " ")
|
|
tmp := p + ".tmp"
|
|
if err := os.WriteFile(tmp, data, 0644); err != nil {
|
|
return err
|
|
}
|
|
return os.Rename(tmp, p)
|
|
}
|
|
|
|
// LoadFromFile reads from JSON config file (no .env)
|
|
func LoadFromFile() Config {
|
|
data, err := os.ReadFile(Path())
|
|
if err != nil {
|
|
return Config{AWSProfile: "cosma", Concurrency: 4, LocalDest: defaultLocalDest()}
|
|
}
|
|
var c Config
|
|
json.Unmarshal(data, &c)
|
|
if c.Concurrency == 0 {
|
|
c.Concurrency = 4
|
|
}
|
|
if c.AWSProfile == "" {
|
|
c.AWSProfile = "cosma"
|
|
}
|
|
if c.LocalDest == "" {
|
|
c.LocalDest = defaultLocalDest()
|
|
}
|
|
return c
|
|
}
|
|
|
|
func defaultLocalDest() string {
|
|
home, _ := os.UserHomeDir()
|
|
return filepath.Join(home, "field-sync-data")
|
|
}
|
|
|
|
// Load reads config from ENV (with optional .env file) — kept for compat
|
|
func Load(envFile string) Config {
|
|
_ = godotenv.Load(envFile) // ignore if missing
|
|
|
|
concurrency := 4
|
|
if v := os.Getenv("FIELD_SYNC_CONCURRENCY"); v != "" {
|
|
if n, err := strconv.Atoi(v); err == nil && n > 0 {
|
|
concurrency = n
|
|
}
|
|
}
|
|
|
|
return Config{
|
|
S3Bucket: getenv("FIELD_SYNC_S3_BUCKET", ""),
|
|
LocalDest: getenv("FIELD_SYNC_LOCAL_DEST", os.TempDir()),
|
|
AWSProfile: getenv("AWS_PROFILE", "cosma"),
|
|
Concurrency: concurrency,
|
|
}
|
|
}
|
|
|
|
func getenv(key, fallback string) string {
|
|
if v := os.Getenv(key); v != "" {
|
|
return v
|
|
}
|
|
return fallback
|
|
}
|