feat: add initial fs interfaces for webapp and dir

This commit is contained in:
Derrick Hammer 2024-03-01 22:49:47 -05:00
parent 3dbd791314
commit 8e2adba1eb
Signed by: pcfreak30
GPG Key ID: C997C339BE476FF2
2 changed files with 170 additions and 0 deletions

118
api/s5/fs_dir.go Normal file
View File

@ -0,0 +1,118 @@
package s5
import (
"errors"
"io/fs"
"strings"
"git.lumeweb.com/LumeWeb/libs5-go/encoding"
"git.lumeweb.com/LumeWeb/libs5-go/metadata"
)
var _ fs.FS = (*dirFs)(nil)
type dirFs struct {
root *encoding.CID
s5 *S5API
}
func (w *dirFs) Open(name string) (fs.File, error) {
file := w.s5.newFile(FileParams{
Hash: w.root.Hash.HashBytes(),
Type: w.root.Type,
})
manifest, err := file.Manifest()
if err != nil {
return nil, err
}
dir, ok := manifest.(*metadata.DirectoryMetadata)
if !ok {
return nil, errors.New("manifest is not a directory")
}
segments := strings.Split(name, "/")
if len(segments) == 1 {
return w.openDirectly(name, dir)
}
nextDirName := segments[0]
remainingPath := strings.Join(segments[1:], "/")
return w.openNestedDir(nextDirName, remainingPath, dir)
}
func (w *dirFs) openDirectly(name string, dir *metadata.DirectoryMetadata) (fs.File, error) {
file := dir.Files.Get(name)
subDir := dir.Directories.Get(name)
if file != nil {
return w.s5.newFile(FileParams{
Hash: file.File.CID().Hash.HashBytes(),
Type: file.File.CID().Type,
Name: file.Name,
}), nil
}
if subDir != nil {
cid, err := w.resolveDirCid(subDir)
if err != nil {
return nil, err
}
return w.s5.newFile(FileParams{
Hash: cid.Hash.HashBytes(),
Type: cid.Type,
Name: name,
}), nil
}
return nil, fs.ErrNotExist
}
func (w dirFs) openNestedDir(name string, remainingPath string, dir *metadata.DirectoryMetadata) (fs.File, error) {
subDir := dir.Directories.Get(name)
if subDir == nil {
return nil, fs.ErrNotExist
}
cid, err := w.resolveDirCid(subDir)
if err != nil {
return nil, err
}
nestedFs := newDirFs(cid, w.s5)
return nestedFs.Open(remainingPath)
}
func (w *dirFs) resolveDirCid(dir *metadata.DirectoryReference) (*encoding.CID, error) {
if len(dir.PublicKey) == 0 {
return nil, errors.New("missing public key")
}
entry, err := w.s5.getNode().Services().Registry().Get(dir.PublicKey)
if err != nil {
return nil, err
}
cid, err := encoding.CIDFromRegistry(entry.Data())
if err != nil {
return nil, err
}
return cid, nil
}
func newDirFs(root *encoding.CID, s5 *S5API) *dirFs {
return &dirFs{
root: root,
s5: s5,
}
}

52
api/s5/fs_webapp.go Normal file
View File

@ -0,0 +1,52 @@
package s5
import (
"errors"
"io/fs"
"git.lumeweb.com/LumeWeb/libs5-go/encoding"
"git.lumeweb.com/LumeWeb/libs5-go/metadata"
)
var _ fs.FS = (*webAppFs)(nil)
type webAppFs struct {
root *encoding.CID
s5 *S5API
}
func (w webAppFs) Open(name string) (fs.File, error) {
file := w.s5.newFile(FileParams{
Hash: w.root.Hash.HashBytes(),
Type: w.root.Type,
})
manifest, err := file.Manifest()
if err != nil {
return nil, err
}
webApp, ok := manifest.(*metadata.WebAppMetadata)
if !ok {
return nil, errors.New("manifest is not a web app")
}
item, ok := webApp.Paths[name]
if !ok {
return nil, fs.ErrNotExist
}
return w.s5.newFile(FileParams{
Hash: item.Cid.Hash.HashBytes(),
Type: item.Cid.Type,
Name: name,
}), nil
}
func newWebAppFs(root *encoding.CID, s5 *S5API) *webAppFs {
return &webAppFs{
root: root,
s5: s5,
}
}