Files
Konrad NeitzelandCursor 9068d8ba8e Extract Files seam, WebDAV, and Visit from CheckDNS.
Publish go-nc-files v1 with local/WebDAV Root, DefaultPathStore, and
neutral Working Folder language; depends on go-nc-exapp v0.1.0.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-26 19:16:53 +02:00

94 lines
2.5 KiB
Go

package goncfiles
import (
"fmt"
"strings"
)
// Visit is one ExApp opening: Working Folder for this request plus the Saved Default.
type Visit struct {
SavedDefault string
WorkingRel string
VisitRelative string
FS Folder
defaults DefaultPathStore
root Root
}
// Open resolves the Working Folder for this visit.
// initialFolderName is used when no Saved Default is stored yet (app-icon first launch).
// visitRelative empty means app-icon launch (Saved Default, creating the initial folder empty if missing).
// A Files-view folder is used only for this visit and does not change the Saved Default.
// Missing or forbidden visit paths fail closed (no create, no fallback).
func Open(root Root, defaults DefaultPathStore, initialFolderName, visitRelative string) (*Visit, error) {
saved, err := defaults.GetDefault()
if err != nil {
return nil, err
}
if saved == "" {
saved = initialFolderName
}
if CleanRel(saved) == "" {
return nil, fmt.Errorf("invalid saved Working Folder path")
}
raw := strings.Trim(strings.ReplaceAll(visitRelative, "\\", "/"), "/")
v := &Visit{
SavedDefault: saved,
defaults: defaults,
root: root,
}
if raw == "" {
fs, err := root.EnsureFolder(saved)
if err != nil {
return nil, err
}
v.WorkingRel = saved
v.FS = fs
return v, nil
}
rel := CleanRel(raw)
if rel == "" {
return nil, fmt.Errorf("invalid Working Folder path")
}
v.VisitRelative = rel
fs, err := root.OpenFolder(rel)
if err != nil {
return nil, fmt.Errorf("Working Folder %q: %w", rel, err)
}
v.WorkingRel = rel
v.FS = fs
return v, nil
}
// OpenLocal is the local-adapter convenience: files root + settings JSON.
func OpenLocal(filesRoot, settingsPath, initialFolderName, visitRelative string) (*Visit, error) {
return Open(Local{RootDir: filesRoot}, FileStore{Path: settingsPath}, initialFolderName, visitRelative)
}
// SetDefault persists a new Saved Default and ensures the folder exists.
func (v *Visit) SetDefault(relative string) error {
rel := CleanRel(relative)
if rel == "" {
return fmt.Errorf("invalid Saved Default path")
}
if _, err := v.root.EnsureFolder(rel); err != nil {
return err
}
if err := v.defaults.SetDefault(rel); err != nil {
return err
}
v.SavedDefault = rel
return nil
}
// WorkingDir returns a local absolute path when using the local adapter; otherwise WorkingRel.
func (v *Visit) WorkingDir() string {
if p, ok := LocalPath(v.FS); ok {
return p
}
return v.WorkingRel
}