Documentation
¶
Overview ¶
Package plugin 提供插件系统:插件包加载、生命周期与设置声明。
v1 的插件是**纯声明式**的:包内只有清单、设置声明与展示图,没有可执行的代码。 这一期的目标是先把插件契约立起来——包的格式、安装与启停的语义、设置如何生效。 缺的从来不是加载器;契约定不下来,加载器做出来也无处可挂(§14.2)。
后端代码的执行(wazero + host function 白名单)排在后面几期, 届时 plugin.yaml 会多一个 runtime 字段,包内会多出 .wasm, 而本包的结构不必推倒重来。
Index ¶
- Constants
- Variables
- func AllowedExtensions() []string
- func ListInstalled(root string) ([]string, error)
- func Remove(root, name string) error
- type Author
- type Handler
- type Loaded
- type Manifest
- type Meta
- type Module
- func (m *Module) Migrations() fs.FS
- func (m *Module) Name() string
- func (m *Module) Navigation() app.Navigation
- func (m *Module) Permissions() []app.Permission
- func (m *Module) Register(a *app.App) error
- func (m *Module) Registry() *Registry
- func (m *Module) Routes(r app.Router)
- func (m *Module) Start(ctx context.Context) error
- type Record
- type Registry
- func (r *Registry) Broken() map[string]string
- func (r *Registry) Enabled() []*Loaded
- func (r *Registry) Get(name string) (*Loaded, bool)
- func (r *Registry) Install(ctx context.Context, reader io.ReaderAt, size int64) (*Manifest, error)
- func (r *Registry) List() []*Loaded
- func (r *Registry) Load(ctx context.Context) error
- func (r *Registry) Root() string
- func (r *Registry) SetEnabled(ctx context.Context, name string, enabled bool) error
- func (r *Registry) Uninstall(ctx context.Context, name string) error
- type RegistryOptions
- type SettingsGroup
- type Spec
- type Store
- func (s *Store) Delete(ctx context.Context, name string) error
- func (s *Store) Get(ctx context.Context, name string) (*Record, error)
- func (s *Store) List(ctx context.Context) ([]Record, error)
- func (s *Store) LoadSettings(ctx context.Context, name string) (map[string]map[string]any, error)
- func (s *Store) Put(ctx context.Context, manifest *Manifest, raw []byte) error
- func (s *Store) SaveSettings(ctx context.Context, name, group string, values map[string]any) error
- func (s *Store) SetEnabled(ctx context.Context, name string, enabled bool) error
Constants ¶
const ( // FileManifest 是插件元信息,必需。 FileManifest = "plugin.yaml" // FileSettings 是插件设置项声明,可缺省;格式与主题设置完全一致。 FileSettings = "settings.yaml" // FileLogo 是后台展示用的图标,可缺省。 FileLogo = "logo.png" )
插件包内的固定文件名。
const ( APIVersion = "plugin.lumo.run/v1alpha1" Kind = "Plugin" )
APIVersion 与 Kind 是 plugin.yaml 里的固定写法。
与 Extension 平面同一套形态:插件清单本身就是一份 GVK 资源, 将来要把它放进 extensions 表或经 API 暴露,都不必改格式。
const Name = "plugin"
Name 是模块名,也是迁移版本表的后缀(goose_db_version_plugin)。
const PathPlugins = "/plugins"
PathPlugins 是插件管理页在 Console 中的路径。
与接口的 /plugins 恰好同名,但两者是不同的东西:这一条是前端路由。 写成一个常量是为了让「它们恰好一样」这件事是显式的,而不是靠人记得两边一起改。
Variables ¶
var ErrAlreadyExists = errors.New("插件已安装")
ErrAlreadyExists 表示同名插件已安装。
var ErrInvalidPackage = errors.New("插件包不合法")
ErrInvalidPackage 表示插件包不合法。
var ErrNotFound = errors.New("插件不存在")
ErrNotFound 表示插件不存在。
Functions ¶
func ListInstalled ¶
ListInstalled 列出 root 下已安装的插件目录名。
目录不存在时返回空列表而不是报错:首次启动、或用不到插件的部署里, 这个目录压根不会被创建。
Types ¶
type Author ¶
type Author struct {
Name string `yaml:"name" json:"name"`
Website string `yaml:"website" json:"website"`
}
Author 是作者信息。
type Handler ¶
type Handler struct {
// contains filtered or unexported fields
}
Handler 提供插件的 Console 接口。
全部操作都要求 plugins:manage:插件能往后台加页面、改设置,门槛与主题同级。
type Loaded ¶
type Loaded struct {
Manifest *Manifest
// Dir 是插件目录的绝对路径。
Dir string
// FS 是插件包的根文件系统。
FS fs.FS
// Groups 是插件声明的设置分组。
Groups []SettingsGroup
// Enabled 是当前的启用状态。
Enabled bool
}
Loaded 是一个已安装的插件。
func (*Loaded) SettingGroup ¶
func (l *Loaded) SettingGroup(name string) (*SettingsGroup, bool)
SettingGroup 按名字取设置分组。
type Manifest ¶
type Manifest struct {
APIVersion string `yaml:"apiVersion" json:"apiVersion"`
Kind string `yaml:"kind" json:"kind"`
Metadata Meta `yaml:"metadata" json:"metadata"`
Spec Spec `yaml:"spec" json:"spec"`
}
Manifest 是 plugin.yaml 的内容。
type Meta ¶
type Meta struct {
// Name 是插件标识(DNS-1123),同时是安装目录名,必须与目录名一致。
Name string `yaml:"name" json:"name"`
}
Meta 是清单的元信息。
type Module ¶
type Module struct {
// contains filtered or unexported fields
}
Module 是插件模块。
func (*Module) Navigation ¶
func (m *Module) Navigation() app.Navigation
Navigation 实现 app.NavigationProvider。
插件能改后台的页面与设置,门槛与主题同级,故整项按 plugins:manage 收起。
func (*Module) Permissions ¶
func (m *Module) Permissions() []app.Permission
Permissions 实现 app.PermissionProvider。
type Record ¶
type Record struct {
bun.BaseModel `bun:"table:plugins,alias:p"`
Name string `bun:"name,pk"`
Version string `bun:"version,notnull"`
DisplayName string `bun:"display_name,notnull"`
Description string `bun:"description,notnull"`
Author string `bun:"author,notnull"`
Enabled bool `bun:"enabled,notnull"`
Manifest []byte `bun:"manifest,type:jsonb,notnull"`
InstalledAt time.Time `bun:"installed_at,nullzero,notnull,default:now()"`
UpdatedAt time.Time `bun:"updated_at,nullzero,notnull,default:now()"`
}
Record 是 plugins 表的一行。
type Registry ¶
type Registry struct {
// contains filtered or unexported fields
}
Registry 持有全部已安装插件与它们的启用状态。
它是插件系统的唯一运行时状态:设置分组、菜单项与列表接口都经它取数据。 读远多于写,故用 RWMutex。
func NewRegistry ¶
func NewRegistry(opts *RegistryOptions) *Registry
NewRegistry 构造 Registry。此时不读盘也不读库——那是 Load 的事。
func (*Registry) Install ¶
Install 从 zip 包安装或升级一个插件,登记为未启用。
已存在的插件走覆盖安装(升级):升级后仍然是「已安装」状态, 但**保持原来的启用状态**——升级一个正在用的插件不该把它停掉。
func (*Registry) Load ¶
Load 扫描已安装的插件目录并与库里的状态对齐。
这是模块第一次被允许访问数据库的时机。
两边不一致时的处置:
- 目录在、库里没有 —— 手工拷进来的插件。照收,登记为「已安装但未启用」, 与主题的做法一致;不这样,用户把目录拷进去后会找不到它。
- 库里有、目录不在 —— 文件被手工删了。标记为损坏并在列表里标出来, 而不是静默丢掉那一行:用户需要知道发生了什么。
func (*Registry) SetEnabled ¶
SetEnabled 启用或停用一个插件。
type RegistryOptions ¶
type RegistryOptions struct {
// Root 是插件安装目录,通常是 data/plugins。
Root string
Store *Store
Logger *slog.Logger
}
RegistryOptions 是构造 Registry 的参数。
type SettingsGroup ¶
type SettingsGroup struct {
Name string
Label string
Description string
Order int
Icon string
Form *form.Form
// contains filtered or unexported fields
}
SettingsGroup 是一个插件的设置分组。
形态与 app.SettingGroup 同构,但**不注册进全局设置服务**: 插件的设置随插件走,停用时要能连同它一起收起,而全局设置分组的生命周期 钉在进程启动那一刻。主题设置也是同样的处置(见 internal/theme/settings.go)。
func (*SettingsGroup) Validator ¶
func (g *SettingsGroup) Validator() *settings.Validator
Validator 返回分组的校验器。
type Spec ¶
type Spec struct {
// DisplayName 是显示名。
DisplayName string `yaml:"displayName" json:"displayName"`
// Version 是插件版本。
Version string `yaml:"version" json:"version"`
// Description 是一句话说明。
Description string `yaml:"description" json:"description"`
// Author 是作者信息。
Author Author `yaml:"author" json:"author"`
// Homepage 是插件主页。
Homepage string `yaml:"homepage" json:"homepage"`
// Repo 是源码仓库地址。
Repo string `yaml:"repo" json:"repo"`
// License 是许可证标识。
License string `yaml:"license" json:"license"`
// Requires 声明所需的 Lumo 版本范围;留空表示不限制。
//
// v1 只做语法校验,不做范围求解与拒绝安装——「不满足就装不上」需要一套
// 完整的版本比较,而那要等插件间依赖一起做(§14.2 期 3)。届时这里会被真正用上。
Requires string `yaml:"requires" json:"requires"`
}
Spec 是清单的规格。
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store 持久化插件状态与设置值。
func (*Store) LoadSettings ¶
LoadSettings 读取某个插件全部分组的已保存值。
func (*Store) SaveSettings ¶
SaveSettings 覆盖式写入某个插件某个分组的值。