94 lines
1.7 KiB
Go

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
}