fs.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126
  1. package decoder
  2. import (
  3. "errors"
  4. "io"
  5. "io/fs"
  6. "os"
  7. "path/filepath"
  8. "strings"
  9. "github.com/langgenius/dify-plugin-daemon/internal/types/entities/plugin_entities"
  10. "github.com/langgenius/dify-plugin-daemon/internal/utils/parser"
  11. )
  12. var (
  13. ErrNotDir = errors.New("not a directory")
  14. )
  15. type FSPluginDecoder struct {
  16. PluginDecoder
  17. // root directory of the plugin
  18. root string
  19. fs fs.FS
  20. pluginDeclaration *plugin_entities.PluginDeclaration
  21. }
  22. func NewFSPluginDecoder(root string) (*FSPluginDecoder, error) {
  23. decoder := &FSPluginDecoder{
  24. root: root,
  25. }
  26. err := decoder.Open()
  27. if err != nil {
  28. return nil, err
  29. }
  30. // read the manifest file
  31. if _, err := decoder.Manifest(); err != nil {
  32. return nil, err
  33. }
  34. return decoder, nil
  35. }
  36. func (d *FSPluginDecoder) Open() error {
  37. d.fs = os.DirFS(d.root)
  38. // try to stat the root directory
  39. s, err := os.Stat(d.root)
  40. if err != nil {
  41. return err
  42. }
  43. if !s.IsDir() {
  44. return ErrNotDir
  45. }
  46. return nil
  47. }
  48. func (d *FSPluginDecoder) Walk(fn func(filename string, dir string) error) error {
  49. return filepath.Walk(d.root, func(path string, info fs.FileInfo, err error) error {
  50. // trim the first directory path
  51. path = strings.TrimPrefix(path, d.root)
  52. // trim / from the beginning
  53. path = strings.TrimPrefix(path, "/")
  54. if path == "" {
  55. return nil
  56. }
  57. if err != nil {
  58. return err
  59. }
  60. return fn(info.Name(), filepath.Dir(path))
  61. })
  62. }
  63. func (d *FSPluginDecoder) Close() error {
  64. return nil
  65. }
  66. func (d *FSPluginDecoder) Stat(filename string) (fs.FileInfo, error) {
  67. return os.Stat(filepath.Join(d.root, filename))
  68. }
  69. func (d *FSPluginDecoder) ReadFile(filename string) ([]byte, error) {
  70. return os.ReadFile(filepath.Join(d.root, filename))
  71. }
  72. func (d *FSPluginDecoder) FileReader(filename string) (io.ReadCloser, error) {
  73. return os.Open(filepath.Join(d.root, filename))
  74. }
  75. func (d *FSPluginDecoder) Signature() (string, error) {
  76. return "", nil
  77. }
  78. func (d *FSPluginDecoder) CreateTime() (int64, error) {
  79. return 0, nil
  80. }
  81. func (d *FSPluginDecoder) Manifest() (plugin_entities.PluginDeclaration, error) {
  82. if d.pluginDeclaration != nil {
  83. return *d.pluginDeclaration, nil
  84. }
  85. // read the manifest file
  86. manifest, err := d.ReadFile("manifest.yaml")
  87. if err != nil {
  88. return plugin_entities.PluginDeclaration{}, err
  89. }
  90. dec, err := parser.UnmarshalYamlBytes[plugin_entities.PluginDeclaration](manifest)
  91. if err != nil {
  92. return plugin_entities.PluginDeclaration{}, err
  93. }
  94. d.pluginDeclaration = &dec
  95. return dec, nil
  96. }