jx/internal/config/fs.go

110 lines
2.3 KiB
Go
Raw Normal View History

// Copyright 2024 Matthew Rich <matthewrich.conf@gmail.com>. All rights reserved.
package config
import (
_ "context"
_ "encoding/json"
_ "fmt"
_ "gopkg.in/yaml.v3"
"net/url"
"path/filepath"
"decl/internal/codec"
"os"
"io"
"errors"
"io/fs"
"log/slog"
)
type ConfigFS struct {
Path string `yaml:"path" json:"path"`
subDirsStack []fs.FS `yaml:"-" json:"-"`
fsys fs.FS `yaml:"-" json:"-"`
}
func NewConfigFS(fsys fs.FS) *ConfigFS {
return &ConfigFS{
subDirsStack: make([]fs.FS, 0, 100),
fsys: fsys,
}
}
func init() {
ConfigSourceTypes.Register([]string{"fs"}, func(u *url.URL) ConfigSource {
t := NewConfigFS(nil)
t.Path,_ = filepath.Abs(filepath.Join(u.Hostname(), u.Path))
t.fsys = os.DirFS(t.Path)
return t
})
}
func (c *ConfigFS) Type() string { return "fs" }
func (c *ConfigFS) ExtractDirectory(fsys fs.FS) ([]*Document, error) {
documents := make([]*Document, 0, 100)
files, err := fs.ReadDir(fsys, ".")
if err != nil {
return nil, err
}
for _,file := range files {
slog.Info("ConfigFS.ExtractDirectory", "file", file)
if file.IsDir() {
dir, subErr := fs.Sub(fsys, file.Name())
if subErr != nil {
return nil, subErr
}
c.subDirsStack = append(c.subDirsStack, dir)
} else {
fileHandle, fileErr := fsys.Open(file.Name())
if fileErr != nil {
return nil, fileErr
}
decoder := codec.NewYAMLDecoder(fileHandle)
doc := NewDocument()
e := decoder.Decode(doc)
if errors.Is(e, io.EOF) {
break
}
if e != nil {
return documents, e
}
slog.Info("ConfigFS.ExtractDirectory", "doc", doc)
if validationErr := doc.Validate(); validationErr != nil {
return documents, validationErr
}
documents = append(documents, doc)
}
}
return documents, nil
}
func (c *ConfigFS) Extract(filter ConfigurationSelector) ([]*Document, error) {
documents := make([]*Document, 0, 100)
path := c.fsys
c.subDirsStack = append(c.subDirsStack, path)
for {
if len(c.subDirsStack) == 0 {
break
}
var dirPath fs.FS
dirPath, c.subDirsStack = c.subDirsStack[len(c.subDirsStack) - 1], c.subDirsStack[:len(c.subDirsStack) - 1]
docs, dirErr := c.ExtractDirectory(dirPath)
if dirErr != nil {
return documents, dirErr
}
documents = append(documents, docs...)
}
return documents, nil
}