package store import ( "encoding/json" "fmt" "os" "path/filepath" "sort" "time" ) func ensureDir(dir string) error { return os.MkdirAll(dir, 0o755) } func readJSON[T any](path string) (T, error) { var v T data, err := os.ReadFile(path) if err != nil { return v, err } if err := json.Unmarshal(data, &v); err != nil { return v, err } return v, nil } func writeJSON(path string, v any) error { data, err := json.MarshalIndent(v, "", " ") if err != nil { return err } return os.WriteFile(path, data, 0o644) } func removeFile(path, notFoundMsg string) error { if err := os.Remove(path); err != nil { if os.IsNotExist(err) { return fmt.Errorf("%s", notFoundMsg) } return err } return nil } func listFromDir[T any]( dir string, match func(name string) bool, readLabel string, createdAt func(T) time.Time, ) ([]T, error) { if err := ensureDir(dir); err != nil { return nil, err } entries, err := os.ReadDir(dir) if err != nil { return nil, fmt.Errorf("read %s: %w", readLabel, err) } var out []T for _, e := range entries { if e.IsDir() || !match(e.Name()) { continue } v, err := readJSON[T](filepath.Join(dir, e.Name())) if err != nil { return nil, err } out = append(out, v) } sort.Slice(out, func(i, j int) bool { return createdAt(out[i]).After(createdAt(out[j])) }) return out, nil } func findByID[T any](list []T, id string, idOf func(T) string) (T, error) { for _, v := range list { if idOf(v) == id { return v, nil } } var zero T return zero, fmt.Errorf("not found: %s", id) } func stampNew(createdAt *time.Time) time.Time { if createdAt.IsZero() { return time.Now().UTC() } return *createdAt }