package storage import ( "os" "path/filepath" "sort" "strings" "gopkg.in/yaml.v3" ) // EnvInfo describes a single environment file under .greq/. type EnvInfo struct { Name string // "default", "local", "staging", "prod", … Path string // absolute or relative path to the yaml file } // LoadEnvFromFile reads any env yaml file into a flat key/value map. func LoadEnvFromFile(path string) (map[string]string, error) { envs := make(map[string]string) data, err := os.ReadFile(path) if err != nil { if os.IsNotExist(err) { return envs, nil } return envs, err } return envs, yaml.Unmarshal(data, &envs) } // LoadEnvList scans .greq/ for files matching env*.yaml and returns them // sorted with "default" first, then alphabetically. func LoadEnvList() ([]EnvInfo, error) { matches, err := filepath.Glob(filepath.Join(RootDir, "env*.yaml")) if err != nil { return nil, err } var list []EnvInfo for _, p := range matches { base := filepath.Base(p) var name string if base == "env.yaml" { name = "default" } else { // env.NAME.yaml → NAME name = strings.TrimSuffix(strings.TrimPrefix(base, "env."), ".yaml") } list = append(list, EnvInfo{Name: name, Path: p}) } sort.Slice(list, func(i, j int) bool { if list[i].Name == "default" { return true } if list[j].Name == "default" { return false } return list[i].Name < list[j].Name }) return list, nil } const RootDir = ".greq" // LoadEnv reads .greq/env.yaml into a flat key/value map. // Missing file is not an error – an empty map is returned instead. func LoadEnv() (map[string]string, error) { return LoadEnvFromFile(filepath.Join(RootDir, "env.yaml")) } // LoadRequests walks .greq/requests/ and parses every .yaml/.yml file. // The first path segment below requests/ is used as the Folder name. func LoadRequests() ([]RequestItem, error) { var items []RequestItem root := filepath.Join(RootDir, "requests") _ = os.MkdirAll(root, 0o755) err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error { if err != nil { return err } if info.IsDir() { return nil } ext := strings.ToLower(filepath.Ext(path)) if ext != ".yaml" && ext != ".yml" { return nil } data, err := os.ReadFile(path) if err != nil { return nil // skip unreadable files silently } var rf RequestFile if err := yaml.Unmarshal(data, &rf); err != nil { return nil } if rf.Name == "" { rf.Name = strings.TrimSuffix(filepath.Base(path), filepath.Ext(path)) } if rf.Method == "" { rf.Method = "GET" } rel, _ := filepath.Rel(root, path) folder := "" if parts := strings.Split(rel, string(filepath.Separator)); len(parts) > 1 { folder = parts[0] } items = append(items, RequestItem{ Request: rf, Path: path, Folder: folder, }) return nil }) return items, err }