Documentation
¶
Overview ¶
Package plugin 是插件宿主:编译、加载、按钩子调用本地 JavaScript 插件,并提供 校验与回放工具。
插件是单文件同步 ECMAScript 模块,导出 meta 与若干钩子函数。契约见 plugin-api/v1/v1.d.ts 与 docs/plugin.md。
安全边界:宿主不提供网络、文件系统、require、import 与动态代码执行;插件的执行 时长、并发数、源码大小与单次输入大小都有限额。加载插件等同于管理员级信任决定。
Index ¶
- Constants
- Variables
- func ValidateFixture(fixture Fixture) error
- type CaseResult
- type Entry
- type Failure
- type Fixture
- type FixtureCase
- type Hook
- type Instance
- func (i *Instance) Call(ctx context.Context, hook Hook, input []byte, session Session) ([]byte, bool, error)
- func (i *Instance) Config() map[string]any
- func (i *Instance) Has(hook Hook) bool
- func (i *Instance) Key() string
- func (i *Instance) Manifest() Manifest
- func (i *Instance) Path() string
- func (i *Instance) Replay(fixture Fixture, logger *slog.Logger) []CaseResult
- type Issue
- type Limits
- type Loaded
- type Manifest
- type Merger
- type Outcome
- type Session
- type Store
- func (s *Store) Apply(ctx context.Context, hook Hook, input []byte, merger Merger, keys []string, ...) Outcome
- func (s *Store) Entries() []Entry
- func (s *Store) Get(key string) (*Instance, bool)
- func (s *Store) HasAny(hook Hook) bool
- func (s *Store) Keys() []string
- func (s *Store) Len() int
- func (s *Store) Missing(keys []string) []string
Constants ¶
const ( // SeverityError 表示插件不可用。 SeverityError = "error" // SeverityWarning 表示插件可用但值得注意。 SeverityWarning = "warning" )
检查结论的级别。
const ( DefaultSourceBytes = 1 << 20 DefaultPayloadBytes = 8 << 20 DefaultTimeout = 50 * time.Millisecond DefaultConcurrency = 8 )
默认限额。
const APIVersion = "v1"
APIVersion 是当前支持的插件契约版本。
const (
PluginFile = "plugin.js"
)
插件文件名。目录形式为 <key>/plugin.js,也接受平铺的 <key>.js。
Variables ¶
var ( // ErrPayloadTooLarge 表示单次输入或输出超过限额。 ErrPayloadTooLarge = errors.New("plugin: 负载超过限额") // ErrAsyncHook 表示钩子返回了 Promise。钩子必须是同步函数。 ErrAsyncHook = errors.New("plugin: 钩子必须是同步函数,不能返回 Promise") // ErrMissingMeta 表示插件没有导出 meta。 ErrMissingMeta = errors.New("plugin: 缺少 meta 导出") // ErrHookMissing 表示插件没有导出调用方要求的钩子。 ErrHookMissing = errors.New("plugin: 插件未导出该钩子") )
错误集合。
Functions ¶
Types ¶
type CaseResult ¶
type CaseResult struct {
Name string `json:"name"`
Passed bool `json:"passed"`
Message string `json:"message,omitempty"`
}
CaseResult 是一条用例的结果。
type Entry ¶
type Entry struct {
// Instance 是绑定配置后的插件。
Instance *Instance
// Enabled 是启用状态,取自配置。
Enabled bool
// Order 是执行顺序,越小越先执行。
Order int
// Position 是加载顺序,Order 相同时按它排序。
Position int
}
Entry 是插件集合里的一项。
type Fixture ¶
type Fixture struct {
// UnixNow 固定插件内 host.now() 的取值,让签名与时间戳类钩子可复现。
// 为 0 时用当前时间。
UnixNow int64 `json:"unixNow"`
// Cases 是用例列表。
Cases []FixtureCase `json:"cases"`
}
Fixture 是一组插件回放用例。形状与 new-api 的任务插件 fixture 一致,便于互相 搬运用例。
type FixtureCase ¶
type FixtureCase struct {
// Name 是用例名。
Name string `json:"name"`
// Hook 是要调用的钩子。
Hook Hook `json:"hook"`
// Member 指定只比较返回值的某个成员,与 Path 互斥。
Member string `json:"member,omitempty"`
// Path 是按点分路径定位返回值的比较目标,与 Member 互斥。数字段表示数组下标。
Path string `json:"path,omitempty"`
// Args 是钩子的参数列表,第一个参数即钩子的输入负载。
Args []json.RawMessage `json:"args"`
// Expected 是期望值,与 ExpectedError 互斥。
Expected json.RawMessage `json:"expected,omitempty"`
// ExpectedError 是期望的错误信息子串,与 Expected 互斥。
ExpectedError string `json:"expectedError,omitempty"`
}
FixtureCase 是一条回放用例。
type Instance ¶
type Instance struct {
// contains filtered or unexported fields
}
Instance 是绑定配置后的插件。可以并发调用。
type Issue ¶
type Issue struct {
// Path 是插件文件路径。
Path string `json:"path"`
// Severity 取 error 或 warning。
Severity string `json:"severity"`
// Message 是结论说明。
Message string `json:"message"`
}
Issue 是一条检查结论。
func LintSource ¶
LintSource 检查插件源码,返回全部结论。
type Limits ¶
type Limits struct {
// SourceBytes 是单个插件源码的字节上限。
SourceBytes int
// PayloadBytes 是单次钩子调用输入与输出的字节上限。
PayloadBytes int
// Timeout 是单次钩子调用的上限。
Timeout time.Duration
// Concurrency 是同一插件同时执行的钩子上限。
Concurrency int
}
Limits 是插件执行的限额。零值不可用,请用 DefaultLimits。
func DefaultLimits ¶
func DefaultLimits() Limits
DefaultLimits 返回默认限额。默认超时取 50 毫秒:本地改写的正常耗时在微秒级, 超过这个量级的插件应当在转发路径之外完成。
type Loaded ¶
type Loaded struct {
// contains filtered or unexported fields
}
Loaded 是编译好的插件。编译一次,可被任意多个 Instance 复用,可并发使用。
func LoadDir ¶
LoadDir 扫描插件目录,按文件名排序返回全部插件。
目录里每一项要么是子目录,要么是 .js 文件;两种形式都要求名字与 meta.key 一致。 其它文件与目录会被忽略,因此插件目录里可以放图标与说明。
type Manifest ¶
type Manifest struct {
// Key 是插件标识,须与目录名一致。
Key string `json:"key"`
// Name 是展示名。
Name string `json:"name"`
// Version 是插件自己的版本号。
Version string `json:"version"`
// APIVersion 是插件声明的契约版本,目前只支持 v1。
APIVersion string `json:"apiVersion"`
// Description 是可选说明。
Description string `json:"description,omitempty"`
// Hooks 是实际导出的钩子,由宿主在编译后填入,插件不必自己写。
Hooks []Hook `json:"hooks,omitempty"`
}
Manifest 是插件的自述信息,取自模块导出的 meta 对象。
type Outcome ¶
type Outcome struct {
// Data 是链路走完后的负载。
Data []byte
// Applied 是实际改写了负载的插件 key,按执行顺序。
Applied []string
// Failures 是执行失败的插件。
Failures []Failure
}
Outcome 是一次钩子链调用的结果。
type Session ¶
type Session struct {
// Now 是插件内 host.now() 看到的时间。
Now time.Time
// Logger 接收插件通过 host.log 写出的日志,为 nil 时丢弃。
Logger *slog.Logger
}
Session 是一次调用携带的宿主环境。
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store 是插件集合。可以并发使用。
func (*Store) Apply ¶
func (s *Store) Apply(ctx context.Context, hook Hook, input []byte, merger Merger, keys []string, session Session) Outcome
Apply 按顺序对启用插件调用一个钩子,每个插件看到的是上一个插件改写之后的完整 负载,而不是只看到上一个插件的返回值。
keys 为空表示全部启用插件参与;非空时只有列出的 key 参与。 merger 为 nil 时,插件返回的新值直接成为下一次调用的负载。
单个插件失败不影响链路:该插件被跳过,前一个成功的改写结果继续传给后面的插件。