plugin

package
v1.1.0-beta.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 23, 2026 License: MIT Imports: 43 Imported by: 0

Documentation

Overview

Package plugin manages Komari plugins: ZIP packages with a komari-plugin.json manifest, mirroring the theme package format. A plugin runs in its own jsruntime instance confined to its data/plugin/<short> directory, plus its long-term data directory data/plugin-data/<short> exposed as __storageDir__ (which survives plugin updates), declares runtime permissions in its manifest, and receives the host-injected "server" module (server.route / server.call / server.hook, whose ws kinds can intercept WebSocket connections and frames). Plugins run with admin authority inside the system.

Lifecycle: plugins are installed as directories under DataDir. The persisted state file (state.json) records which plugins are enabled, which permissions were approved, and the last load error. Enabled plugins are loaded at startup; a failed load auto-disables the plugin and keeps the error text visible through admin:listPlugins.

Index

Constants

This section is empty.

Variables

View Source
var DataDir = "./data/plugin"

DataDir is the on-disk root for installed plugins, mirroring the theme directory layout. It is a variable so tests can redirect it.

View Source
var ErrNotInstalled = errors.New("plugin is not installed")

ErrNotInstalled is returned when deleting a plugin that is not installed.

View Source
var ErrPermissionApprovalRequired = errors.New("plugin permissions require approval")

ErrPermissionApprovalRequired is returned when enabling a plugin whose declared permissions have not been approved, or changed since approval.

View Source
var StorageDir = "./data/plugin-data"

StorageDir is the on-disk root for long-term plugin data. Each plugin gets StorageDir/<short>. The directory is confined into the plugin runtime as __storageDir__ and survives plugin reinstalls: update removes only DataDir/<short> (the code from the ZIP) while StorageDir/<short> persists. Deleting a plugin removes both.

Functions

func AdminDeletePlugin

func AdminDeletePlugin(_ context.Context, req *rpc.JsonRpcRequest) (any, *rpc.JsonRpcError)

func AdminGetPluginConfiguration

func AdminGetPluginConfiguration(_ context.Context, req *rpc.JsonRpcRequest) (any, *rpc.JsonRpcError)

func AdminGetPluginLogs

func AdminGetPluginLogs(_ context.Context, req *rpc.JsonRpcRequest) (any, *rpc.JsonRpcError)

func AdminListPlugins

func AdminListPlugins(_ context.Context, _ *rpc.JsonRpcRequest) (any, *rpc.JsonRpcError)

func AdminSetPluginConfiguration

func AdminSetPluginConfiguration(_ context.Context, req *rpc.JsonRpcRequest) (any, *rpc.JsonRpcError)

func AdminSetPluginEnabled

func AdminSetPluginEnabled(_ context.Context, req *rpc.JsonRpcRequest) (any, *rpc.JsonRpcError)

AdminSetPluginEnabled is the single switch entry point. When a plugin's declared permissions differ from the approved hash, enabling it returns { requires_approval: true } instead of an error; the caller then shows a permission dialog and retries with approved=true.

func CheckKomariVersion

func CheckKomariVersion(constraint string) error

CheckKomariVersion is a backward-compatible alias for CheckSonarVersion.

func CheckSonarVersion

func CheckSonarVersion(constraint string) error

CheckSonarVersion validates a manifest version constraint against the running server version. Supported constraints: empty (any version), "x.y.z" (exact), and ">=x.y.z", ">x.y.z", "<=x.y.z", "<x.y.z". An optional leading "v" is accepted.

func CloseAll

func CloseAll() error

CloseAll unloads every loaded plugin. Used during server shutdown.

func CreatePluginMarketSource

func CreatePluginMarketSource(c *gin.Context)

func Delete

func Delete(short string) error

Delete removes an installed plugin and its persisted state.

func DeletePluginMarketSource

func DeletePluginMarketSource(c *gin.Context)

func GetConfiguration

func GetConfiguration(short string) (map[string]any, error)

GetConfiguration returns the saved configuration values of one plugin, merged with the manifest-declared defaults for keys that were never saved. This mirrors the theme configuration behavior so plugins and the admin UI always see a complete value set. Missing rows yield only defaults; a missing manifest yields only the saved values.

func GetLogs

func GetLogs(short string) string

GetLogs returns the bounded log buffer of one plugin.

func HTMLInjectHandler

func HTMLInjectHandler(next http.Handler) http.Handler

HTMLInjectHandler installs plugin HTML injection around the application handler. Every text/html response is buffered and gets the fragments registered through server.injectHTML inserted before </head> and </body>; all other responses (JSON, assets, streams, downloads...) pass through to the client unmodified.

func Init

func Init(engine *gin.Engine)

Init wires the manager to the HTTP engine and into every WebSocket wsconn. It must be called before any plugin is loaded.

func InstallPluginFromMarket

func InstallPluginFromMarket(c *gin.Context)

func InstallZip

func InstallZip(zipPath string) (models.Plugin, error)

InstallZip validates a plugin ZIP and extracts it into DataDir/<short>. The archive must contain komari-plugin.json at its root. Archive limits mirror the theme package format; path-traversal entries reject the whole package instead of being skipped. Reinstalling over a running plugin unloads it first and restores it to its persisted enabled state when the extraction succeeds.

func ListPluginMarketCatalog

func ListPluginMarketCatalog(c *gin.Context)

func ListPluginMarketSources

func ListPluginMarketSources(c *gin.Context)

func LoadAll

func LoadAll() error

LoadAll loads every installed plugin whose persisted state is enabled and approved. A failed load auto-disables the plugin, persists last_error and is returned joined so callers can log it without stopping startup.

func Manifest

func Manifest(short string) (models.Plugin, error)

Manifest returns the parsed manifest of an installed plugin.

func Reload

func Reload(short string) error

Reload unloads and loads an enabled plugin. The load hook completes before this function returns; a failed load is persisted as the plugin's last error and disables the plugin, matching the normal enable/startup path.

func ResolveFile

func ResolveFile(short, name string) (string, error)

ResolveFile returns the absolute path of a file inside an installed plugin directory, rejecting traversal. Used to serve injected plugin pages.

func ResolvePublicFile

func ResolvePublicFile(short, name string) (string, error)

ResolvePublicFile returns the absolute path of a file that belongs to a public iframe page of an installed plugin. Public pages are served without authentication: the plugin must be enabled and the requested file must live inside the directory of a page declared with visibility=public, so the page HTML and its relative assets are reachable without exposing the whole plugin directory.

func SaveConfiguration

func SaveConfiguration(short string, data map[string]any) error

SaveConfiguration upserts the configuration values of one plugin.

func ServeAdminPluginFile

func ServeAdminPluginFile(c *gin.Context)

ServeAdminPluginFile serves a static file from an installed plugin directory, used by injected plugin admin pages. 与 ServePublicPluginFile(无需鉴权的公开 iframe 页面)同名会冲突,故以 Admin/Public 区分。

func ServePublicPluginFile

func ServePublicPluginFile(c *gin.Context)

ServePublicPluginFile serves a public iframe page declared in a plugin manifest (visibility=public). It is reachable without authentication; the plugin must be enabled and the requested file must be listed as a public page. 与 ServeAdminPluginFile(管理页面静态文件)同名会冲突,故以 Admin/Public 区分。

func SetEnabled

func SetEnabled(short string, enabled, approved bool) error

SetEnabled is the single switch entry point. Enabling a plugin whose declared permissions differ from the approved hash requires approved=true.

func UpdatePluginMarketSource

func UpdatePluginMarketSource(c *gin.Context)

func WrapHandler

func WrapHandler(next http.Handler) http.Handler

WrapHandler installs the plugin HTTP hook chain around the application handler. Request hooks run before the handler and may modify the request; response hooks run after the handler and may modify status/headers/body.

Types

type Info

type Info struct {
	models.Plugin
	Enabled   bool   `json:"enabled"`
	Running   bool   `json:"running"`
	LastError string `json:"last_error"`
}

Info describes one installed plugin for the admin surface.

func List

func List() []Info

List returns the installed plugins with their enabled/running state.

type Instance

type Instance struct {
	// contains filtered or unexported fields
}

Instance is one loaded plugin runtime plus its host bindings.

type LogBuffer

type LogBuffer struct {
	// contains filtered or unexported fields
}

LogBuffer is a bounded ring buffer holding one plugin's console output and lifecycle markers. Old bytes are dropped from the front when the limit is reached.

func (*LogBuffer) Reset

func (b *LogBuffer) Reset()

func (*LogBuffer) String

func (b *LogBuffer) String() string

func (*LogBuffer) Write

func (b *LogBuffer) Write(p []byte) (int, error)

type Manager

type Manager struct {
	// contains filtered or unexported fields
}

Manager owns the installed plugin set: load/unload lifecycle, persisted state, per-plugin logs, and the host engine used by server.route.

func (*Manager) OnClose

func (m *Manager) OnClose(info *wsconn.ConnInfo)

OnClose implements wsconn.FrameInterceptor for connection teardown.

func (*Manager) OnConnect

func (m *Manager) OnConnect(info *wsconn.ConnInfo) (deny bool, reason string)

OnConnect implements wsconn.FrameInterceptor. It runs the wsConnect hooks registered for the connection path; the first denial rejects the wsconn.

func (*Manager) OnMessage

func (m *Manager) OnMessage(info *wsconn.ConnInfo, frameType int, data []byte) (int, []byte, bool)

OnMessage implements wsconn.FrameInterceptor for inbound frames.

func (*Manager) OnSend

func (m *Manager) OnSend(info *wsconn.ConnInfo, frameType int, data []byte) (int, []byte, bool)

OnSend implements wsconn.FrameInterceptor for outbound frames.

type PluginMarketPlugin

type PluginMarketPlugin struct {
	Name        any    `json:"name"`
	Short       string `json:"short"`
	Description any    `json:"description"`
	Version     string `json:"version"`
	Author      any    `json:"author"`
	URL         string `json:"url"`
	Download    string `json:"download"`
	SHA256      string `json:"sha256"`
	Sonar       string `json:"sonar"`
	Komari      string `json:"komari"`
	Installable bool   `json:"installable"`
	SourceID    string `json:"source_id,omitempty"`
	SourceName  string `json:"source_name,omitempty"`
}

type PluginMarketSource

type PluginMarketSource struct {
	ID      string `json:"id"`
	Name    string `json:"name"`
	URL     string `json:"url"`
	Enabled bool   `json:"enabled"`
}

type PluginState

type PluginState struct {
	Enabled                 bool      `json:"enabled"`
	ApprovedPermissionsHash string    `json:"approved_permissions_hash"`
	LastError               string    `json:"last_error"`
	UpdatedAt               time.Time `json:"updated_at"`
}

PluginState is the persisted state of one plugin.

type State

type State struct {
	// contains filtered or unexported fields
}

State persists the enabled flag, the approved permissions hash and the last error for each installed plugin in DataDir/state.json. Keeping it next to the plugin directories keeps plugin management self-contained.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL