Documentation
¶
Index ¶
- func AutoWorkerCount() int
- func CheckNodeAvailable() error
- func CheckSandbox(runtime interface{}) error
- func EncodeMessage(msg *Message) ([]byte, error)
- func ResolveWorkerCount(configured interface{}) int
- func ValidateScope(event HookName, scope HookScope) error
- type BatchHookFunc
- type BatchProgressFunc
- type BridgeState
- type EvalWarner
- type FileChangedResult
- type HookAssetPayload
- type HookBuildCompletePayload
- type HookCascadePayload
- type HookDetailer
- type HookFormatRenderedPayload
- type HookFunc
- type HookName
- type HookPagePayload
- type HookPagesReadyPayload
- type HookRegistration
- type HookRegistry
- func (r *HookRegistry) HasHooks(event HookName) bool
- func (r *HookRegistry) Register(event HookName, fn HookFunc)
- func (r *HookRegistry) RegisterBatchWithOptions(event HookName, singleFn HookFunc, batchFn BatchHookFunc, scope HookScope, ...)
- func (r *HookRegistry) RegisterBatchWithPriority(event HookName, fn HookFunc, batchFn BatchHookFunc, priority int)
- func (r *HookRegistry) RegisterWithOptions(event HookName, fn HookFunc, scope HookScope, priority int)
- func (r *HookRegistry) RegisterWithPriority(event HookName, fn HookFunc, priority int)
- func (r *HookRegistry) Run(event HookName, payload interface{}) (interface{}, error)
- func (r *HookRegistry) RunBatchWithProgress(event HookName, payloads []interface{}, onProgress BatchProgressFunc) ([]interface{}, error)
- func (r *HookRegistry) RunBatchWithTimeout(event HookName, payloads []interface{}) ([]interface{}, error)
- func (r *HookRegistry) RunEachWithTimeout(event HookName, payloadFn func(i int, scope *HookScope) interface{}, ...) error
- func (r *HookRegistry) RunWithTimeout(event HookName, payload interface{}) (interface{}, error)
- func (r *HookRegistry) ScopeFor(event HookName) []*HookScope
- func (r *HookRegistry) SetTimeout(ms int)
- func (r *HookRegistry) Timeout() int
- func (r *HookRegistry) Warnings() []string
- type HookRenderedPayload
- type HookScope
- type HookTransformPayload
- type Message
- type NodeBridge
- type NodeRuntime
- func (r *NodeRuntime) BatchCallHook(name string, payloads []interface{}, onProgress func(int)) ([]interface{}, error)
- func (r *NodeRuntime) CallFilter(name string, input interface{}, args ...interface{}) (interface{}, error)
- func (r *NodeRuntime) CallHook(name string, payload interface{}) (interface{}, error)
- func (r *NodeRuntime) CallShortcode(name string, args []string, innerContent string) (string, error)
- func (r *NodeRuntime) CallSource(name string, config map[string]interface{}) (interface{}, error)
- func (r *NodeRuntime) Close()
- func (r *NodeRuntime) CloseWorkers()
- func (r *NodeRuntime) EvalFile(path string) error
- func (r *NodeRuntime) EvalWarnings() []string
- func (r *NodeRuntime) PrepareWorkerPool(n int) error
- func (r *NodeRuntime) ProjectRoot() string
- func (r *NodeRuntime) RegisteredFilters() []string
- func (r *NodeRuntime) RegisteredHookDetails() []HookRegistration
- func (r *NodeRuntime) RegisteredHooks() []string
- func (r *NodeRuntime) RegisteredShortcodes() []string
- func (r *NodeRuntime) RegisteredSources() []string
- func (r *NodeRuntime) Restart() error
- func (r *NodeRuntime) SetProjectRoot(root string)
- func (r *NodeRuntime) SetSiteData(data map[string]interface{}) error
- func (r *NodeRuntime) SetSourceTimeout(d time.Duration)
- type PagesScope
- type PagesScopeMode
- type PluginFilterRuntime
- type PluginInfo
- type PluginRuntime
- type PluginTier
- type QuickJSRuntime
- func (r *QuickJSRuntime) BatchCallHook(name string, payloads []interface{}, onProgress func(int)) ([]interface{}, error)
- func (r *QuickJSRuntime) CallFilter(name string, input interface{}, args ...interface{}) (interface{}, error)
- func (r *QuickJSRuntime) CallHook(name string, payload interface{}) (interface{}, error)
- func (r *QuickJSRuntime) CallShortcode(name string, args []string, innerContent string) (string, error)
- func (r *QuickJSRuntime) Close()
- func (r *QuickJSRuntime) EvalFile(path string) error
- func (r *QuickJSRuntime) EvalWarnings() []string
- func (r *QuickJSRuntime) Init() error
- func (r *QuickJSRuntime) IsInitialized() bool
- func (r *QuickJSRuntime) RegisteredFilters() []string
- func (r *QuickJSRuntime) RegisteredHookDetails() []HookRegistration
- func (r *QuickJSRuntime) RegisteredHooks() []string
- func (r *QuickJSRuntime) RegisteredShortcodes() []string
- func (r *QuickJSRuntime) SetSiteData(data map[string]interface{}) error
- type Registry
- func (r *Registry) Close()
- func (r *Registry) ConflictWarnings() []string
- func (r *Registry) DiscoverPlugins() error
- func (r *Registry) HasFilter(name string) bool
- func (r *Registry) InitRuntimes() ([]PluginFilterRuntime, []string)
- func (r *Registry) LoadPlugins(hooks *HookRegistry) []string
- func (r *Registry) Plugins() []PluginInfo
- func (r *Registry) RegisterFilter(name, source string)
- func (r *Registry) RestartNodeRuntimes() error
- func (r *Registry) Runtimes() []PluginFilterRuntime
- func (r *Registry) SetPluginsDirRel(rel string)
- func (r *Registry) SetProjectRoot(root string)
- func (r *Registry) SetWASMCacheDir(dir string)
- type SSRInstance
- type SandboxViolationError
- type WASMRuntime
- func (r *WASMRuntime) CallExport(name string, args ...interface{}) (interface{}, error)
- func (r *WASMRuntime) CallExportRaw(name string, ptr, length uint32) (string, error)
- func (r *WASMRuntime) CallFilter(name string, input interface{}, args ...interface{}) (interface{}, error)
- func (r *WASMRuntime) CallHook(name string, payload interface{}) (interface{}, error)
- func (r *WASMRuntime) CallShortcode(name string, args []string, innerContent string) (string, error)
- func (r *WASMRuntime) Close()
- func (r *WASMRuntime) HasExport(name string) bool
- func (r *WASMRuntime) LoadModule(path string) error
- func (r *WASMRuntime) RegisteredFilters() []string
- func (r *WASMRuntime) RegisteredHookDetails() []HookRegistration
- func (r *WASMRuntime) RegisteredHooks() []string
- func (r *WASMRuntime) RegisteredShortcodes() []string
- func (r *WASMRuntime) SetCacheDir(dir string)
- func (r *WASMRuntime) SetCompilationCache(cache wazero.CompilationCache)
- func (r *WASMRuntime) SetSiteData(data map[string]interface{}) error
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func AutoWorkerCount ¶
func AutoWorkerCount() int
AutoWorkerCount returns the auto-scaled worker count: min(NumCPU/2, 8) with floor 2.
func CheckNodeAvailable ¶
func CheckNodeAvailable() error
CheckNodeAvailable verifies that the `node` binary is available in PATH.
func CheckSandbox ¶
func CheckSandbox(runtime interface{}) error
CheckSandbox validates that the Tier 2 runtime has no filesystem or network access. Both QuickJS and WASM runtimes are sandboxed by design — no host imports for filesystem or network are provided.
func EncodeMessage ¶
EncodeMessage serializes a Message into an LSP-style framed byte sequence. For hook messages with large HTML/content fields, uses split-body framing: Content-Length: <N>\r\nX-Body-Length: <M>\r\nX-Body-Field: <field>\r\n\r\n<JSON><raw bytes> For all other messages, uses standard single-header framing: Content-Length: <N>\r\n\r\n<JSON body>
func ResolveWorkerCount ¶
func ResolveWorkerCount(configured interface{}) int
ResolveWorkerCount resolves a configured worker count to a concrete integer. Positive integers are returned as-is (no floor applied). All other values (including "auto", 0, negative, or unrecognized types) fall back to AutoWorkerCount.
func ValidateScope ¶
ValidateScope checks that a scope is valid for the given hook event.
Types ¶
type BatchHookFunc ¶
type BatchHookFunc func(ctx context.Context, payloads []interface{}, onProgress BatchProgressFunc) ([]interface{}, error)
BatchHookFunc processes multiple payloads in a single call, returning one result per input. Used by subprocess plugins to distribute work across multiple worker processes. The onProgress callback, when non-nil, is called after each item completes.
type BatchProgressFunc ¶
type BatchProgressFunc func(completed, total int)
BatchProgressFunc is called after each item is dispatched during batch hook execution (including timed-out items), reporting the running count and total.
type BridgeState ¶
type BridgeState int
BridgeState represents the lifecycle state of the Node subprocess bridge.
const ( // BridgeNotStarted is the initial state before Start() is called. BridgeNotStarted BridgeState = iota + 1 // BridgeRunning means the Node subprocess is active and accepting messages. BridgeRunning // BridgeStopped means the Node subprocess has been shut down. BridgeStopped )
type EvalWarner ¶
type EvalWarner interface {
EvalWarnings() []string
}
EvalWarner is implemented by runtimes that collect warnings during plugin evaluation.
type FileChangedResult ¶ added in v0.6.0
FileChangedResult holds the structured return value from an onFileChanged hook. Nil when the plugin returns nil, non-map, or a map with no recognized keys (backward-compatible no-op).
func ParseFileChangedResult ¶ added in v0.6.0
func ParseFileChangedResult(result interface{}) *FileChangedResult
ParseFileChangedResult extracts the structured return value from an onFileChanged hook result. Returns nil for nil, non-map, or maps without recognized keys (issue #1100).
type HookAssetPayload ¶
HookAssetPayload is the outbound payload for per-asset onAssetProcess dispatch. Sent once per asset file with the relative path and file content as a string. Return value's "content" key replaces the asset content written to the output directory.
type HookBuildCompletePayload ¶ added in v0.6.0
type HookBuildCompletePayload struct {
PageCount int `json:"pageCount"`
Duration string `json:"duration"`
Errors []string `json:"errors"`
OutputDir string `json:"outputDir"`
}
HookBuildCompletePayload is the trimmed onBuildComplete payload sent to plugins. Only includes stats + outputDir — no rendered HTML, cache, or site data (issue #1098).
type HookCascadePayload ¶
type HookCascadePayload struct {
Path string `json:"path"`
Data map[string]interface{} `json:"data"`
}
HookCascadePayload is one entry in the onDataCascadeReady batch payload.
type HookDetailer ¶
type HookDetailer interface {
RegisteredHookDetails() []HookRegistration
}
HookDetailer is implemented by runtimes that can report hook priorities. Runtimes without priority support fall back to RegisteredHooks() with default priority 50.
type HookFormatRenderedPayload ¶ added in v0.6.0
type HookFormatRenderedPayload struct {
Format string `json:"format"`
Content string `json:"content"`
URL string `json:"url"`
Path string `json:"path"`
FrontMatter map[string]interface{} `json:"frontMatter"`
}
HookFormatRenderedPayload is the outbound payload for onFormatRendered (per-format body). Only the returned content field is applied back; format, frontMatter, url, and path are read-only context for conditional processing (issue #1102).
type HookFunc ¶
HookFunc processes a hook payload and returns a (potentially modified) result. The context carries the per-hook timeout deadline for cooperative cancellation.
type HookName ¶
type HookName string
HookName identifies a lifecycle event.
const ( OnConfig HookName = "onConfig" OnBeforeValidation HookName = "onBeforeValidation" OnAfterValidation HookName = "onAfterValidation" OnDataFetched HookName = "onDataFetched" OnDataCascadeReady HookName = "onDataCascadeReady" OnPagesReady HookName = "onPagesReady" OnContentLoaded HookName = "onContentLoaded" OnContentTransformed HookName = "onContentTransformed" OnPageRendered HookName = "onPageRendered" OnFormatRendered HookName = "onFormatRendered" OnAssetProcess HookName = "onAssetProcess" OnBuildComplete HookName = "onBuildComplete" OnDevServerStart HookName = "onDevServerStart" OnFileChanged HookName = "onFileChanged" )
type HookPagePayload ¶
type HookPagePayload struct {
Path string `json:"path"`
URL string `json:"url"`
FrontMatter map[string]interface{} `json:"frontMatter"`
Content string `json:"content,omitempty"`
HTML string `json:"html,omitempty"`
}
HookPagePayload is the outbound representation of a page sent to plugins. Separate from the template data path (which uses map[string]interface{} for liquidgo).
type HookPagesReadyPayload ¶
type HookPagesReadyPayload struct {
Pages []HookPagePayload `json:"pages"`
SiteData map[string]interface{} `json:"siteData"`
}
HookPagesReadyPayload is the outbound payload for onPagesReady (per-batch).
type HookRegistration ¶
HookRegistration pairs a hook name with its priority and optional scope.
type HookRegistry ¶
type HookRegistry struct {
// contains filtered or unexported fields
}
HookRegistry manages lifecycle hook registrations and execution.
func NewHookRegistry ¶
func NewHookRegistry() *HookRegistry
NewHookRegistry creates an empty hook registry with a default timeout of 5000ms.
func (*HookRegistry) HasHooks ¶
func (r *HookRegistry) HasHooks(event HookName) bool
HasHooks returns true if any hooks are registered for the given event.
func (*HookRegistry) Register ¶
func (r *HookRegistry) Register(event HookName, fn HookFunc)
Register adds a hook function for the given event with default priority (50).
func (*HookRegistry) RegisterBatchWithOptions ¶
func (r *HookRegistry) RegisterBatchWithOptions(event HookName, singleFn HookFunc, batchFn BatchHookFunc, scope HookScope, priority int)
RegisterBatchWithOptions adds a batch-capable hook with scope and explicit priority.
func (*HookRegistry) RegisterBatchWithPriority ¶
func (r *HookRegistry) RegisterBatchWithPriority(event HookName, fn HookFunc, batchFn BatchHookFunc, priority int)
RegisterBatchWithPriority adds a hook with both single and batch dispatch functions. The batch function is used by RunBatchWithTimeout to distribute work across workers.
func (*HookRegistry) RegisterWithOptions ¶
func (r *HookRegistry) RegisterWithOptions(event HookName, fn HookFunc, scope HookScope, priority int)
RegisterWithOptions adds a hook with scope and explicit priority.
func (*HookRegistry) RegisterWithPriority ¶
func (r *HookRegistry) RegisterWithPriority(event HookName, fn HookFunc, priority int)
RegisterWithPriority adds a hook function for the given event with explicit priority. Lower priority runs first. Hooks with the same priority preserve registration order.
func (*HookRegistry) Run ¶
func (r *HookRegistry) Run(event HookName, payload interface{}) (interface{}, error)
Run executes all hooks for an event in priority order, chaining results. Context fields from the original payload are merged for chain carry-forward (issue #1216).
func (*HookRegistry) RunBatchWithProgress ¶
func (r *HookRegistry) RunBatchWithProgress(event HookName, payloads []interface{}, onProgress BatchProgressFunc) ([]interface{}, error)
RunBatchWithProgress is like RunBatchWithTimeout but accepts a progress callback that fires after each item completes during batch hook execution. Context fields (url, path, frontMatter) from the original payloads are merged into hook results for chain carry-forward (issue #1216).
func (*HookRegistry) RunBatchWithTimeout ¶
func (r *HookRegistry) RunBatchWithTimeout(event HookName, payloads []interface{}) ([]interface{}, error)
RunBatchWithTimeout dispatches multiple payloads through all hooks for an event. Hooks with a batchFn use batch dispatch (distributing across workers). Hooks without batchFn fall back to per-item dispatch with timeout enforcement. Batch timeout scales linearly with payload count (timeout × itemCount).
func (*HookRegistry) RunEachWithTimeout ¶ added in v0.5.0
func (r *HookRegistry) RunEachWithTimeout(event HookName, payloadFn func(i int, scope *HookScope) interface{}, resultFn func(i int, scope *HookScope, result interface{}) error, ) error
RunEachWithTimeout runs each hook for an event individually with timeout enforcement. Before each hook, payloadFn builds the per-hook payload (receiving the hook index and scope). After each hook, resultFn processes the result. If resultFn returns an error, execution stops. Timed-out hooks are skipped with a warning (resultFn is not called).
func (*HookRegistry) RunWithTimeout ¶
func (r *HookRegistry) RunWithTimeout(event HookName, payload interface{}) (interface{}, error)
RunWithTimeout executes all hooks for an event with timeout enforcement. If a hook exceeds the timeout, its modifications are discarded (the pre-hook payload is kept), a warning is logged, and the build continues. Each hook receives a context with the timeout deadline for cooperative cancellation. Context fields (url, path, frontMatter) from the original payload are merged into hook results for chain carry-forward (issue #1216).
func (*HookRegistry) ScopeFor ¶
func (r *HookRegistry) ScopeFor(event HookName) []*HookScope
ScopeFor returns the scope for each hook registered on the event, in priority order. Returns nil when no hooks are registered. Entries are nil for unscoped hooks.
func (*HookRegistry) SetTimeout ¶
func (r *HookRegistry) SetTimeout(ms int)
SetTimeout configures the per-hook execution timeout in milliseconds.
func (*HookRegistry) Timeout ¶
func (r *HookRegistry) Timeout() int
Timeout returns the current per-hook timeout in milliseconds.
func (*HookRegistry) Warnings ¶
func (r *HookRegistry) Warnings() []string
Warnings returns warnings from hook execution (e.g., timeouts) and plugin loading (e.g., duplicate registrations).
type HookRenderedPayload ¶ added in v0.6.0
type HookRenderedPayload struct {
HTML string `json:"html"`
FrontMatter map[string]interface{} `json:"frontMatter"`
URL string `json:"url"`
Path string `json:"path"`
}
HookRenderedPayload is the outbound payload for onPageRendered (per-page). Only the returned html field is applied back; frontMatter, url, and path are read-only context for conditional processing (issue #1095).
type HookScope ¶
type HookScope struct {
Data []string `json:"data"` // siteData keys; nil = omit, ["*"] = all
Pages PagesScope // page filtering mode
PageFields []string `json:"pageFields"` // per-page fields; nil = all
}
HookScope declares what data subset a plugin hook needs.
func (*HookScope) WantsAllData ¶
WantsAllData returns true if Data contains "*".
func (*HookScope) WantsField ¶
WantsField returns true if name is in PageFields, or PageFields is nil or contains "*".
type HookTransformPayload ¶
type HookTransformPayload struct {
Path string `json:"path"`
URL string `json:"url"`
FrontMatter map[string]interface{} `json:"frontMatter"`
HTML string `json:"html"`
TOC []content.TOCEntry `json:"toc,omitempty"`
}
HookTransformPayload is the outbound payload for onContentTransformed (per-page).
type Message ¶
type Message struct {
ID int `json:"id"`
Type string `json:"type,omitempty"` // "hook", "ssr", "filter"
Name string `json:"name,omitempty"` // hook/filter name
Payload interface{} `json:"payload,omitempty"` // hook/filter payload
Result interface{} `json:"result,omitempty"` // response result
Error string `json:"error,omitempty"` // error message from bridge
Instances []SSRInstance `json:"instances,omitempty"` // SSR render instances
}
Message represents a JSON-RPC message exchanged between Alloy (Go) and the Node bridge subprocess. Framed with LSP-style Content-Length headers over stdin/stdout.
func DecodeMessage ¶
DecodeMessage parses an LSP-style framed byte sequence back into a Message. Supports both single-header and split-body (multi-header) frames. Returns an error if the Content-Length header is missing or malformed.
type NodeBridge ¶
type NodeBridge struct {
// contains filtered or unexported fields
}
NodeBridge manages the lifecycle of the Node subprocess used for Tier 3 plugins. Communication uses length-prefixed JSON-RPC over stdin/stdout.
func NewNodeBridge ¶
func NewNodeBridge(projectRoot string) *NodeBridge
NewNodeBridge creates a Node bridge for the given project root.
func (*NodeBridge) PID ¶
func (b *NodeBridge) PID() int
PID returns the process ID of the Node subprocess, or 0 if not running.
func (*NodeBridge) Send ¶
func (b *NodeBridge) Send(msg *Message) (*Message, error)
Send sends a JSON-RPC message and reads the response. Supports both single-header and multi-header (split-body) responses.
func (*NodeBridge) Start ¶
func (b *NodeBridge) Start() error
Start spawns the Node subprocess with the embedded bridge script. When a project root is available, the bridge script is written under .alloy/ so Node's module resolution can find node_modules/ via normal ancestor directory traversal.
func (*NodeBridge) State ¶
func (b *NodeBridge) State() BridgeState
State returns the current lifecycle state of the bridge.
func (*NodeBridge) Stop ¶
func (b *NodeBridge) Stop() error
Stop gracefully shuts down the Node subprocess and its process group.
func (*NodeBridge) WorkingDir ¶
func (b *NodeBridge) WorkingDir() string
WorkingDir returns the working directory of the Node subprocess.
type NodeRuntime ¶
type NodeRuntime struct {
// contains filtered or unexported fields
}
NodeRuntime runs Tier 3 Node plugins via a persistent subprocess. Communicates via JSON-RPC over stdin/stdout using the embedded bridge.js.
func NewNodeRuntime ¶
func NewNodeRuntime() *NodeRuntime
NewNodeRuntime creates a new Node.js plugin runtime with its own bridge. Defaults to the current working directory as the project root for module resolution.
func (*NodeRuntime) BatchCallHook ¶
func (r *NodeRuntime) BatchCallHook(name string, payloads []interface{}, onProgress func(int)) ([]interface{}, error)
BatchCallHook distributes payloads across the worker pool for parallel processing. Uses per-page IPC dispatch which outperforms large batch JSON serialization.
func (*NodeRuntime) CallFilter ¶
func (r *NodeRuntime) CallFilter(name string, input interface{}, args ...interface{}) (interface{}, error)
CallFilter routes a filter call through the Node subprocess.
func (*NodeRuntime) CallHook ¶
func (r *NodeRuntime) CallHook(name string, payload interface{}) (interface{}, error)
CallHook routes a hook call through the Node subprocess.
func (*NodeRuntime) CallShortcode ¶
func (r *NodeRuntime) CallShortcode(name string, args []string, innerContent string) (string, error)
CallShortcode routes a shortcode call through the Node subprocess.
func (*NodeRuntime) CallSource ¶ added in v0.5.0
func (r *NodeRuntime) CallSource(name string, config map[string]interface{}) (interface{}, error)
CallSource invokes a registered data source handler in the Node subprocess. Applies sourceTimeout (default 5s) to prevent slow handlers from hanging the build.
func (*NodeRuntime) Close ¶
func (r *NodeRuntime) Close()
Close shuts down the worker pool and primary Node subprocess.
func (*NodeRuntime) CloseWorkers ¶
func (r *NodeRuntime) CloseWorkers()
CloseWorkers shuts down all worker pool bridges.
func (*NodeRuntime) EvalFile ¶
func (r *NodeRuntime) EvalFile(path string) error
EvalFile loads a JS plugin file in the Node subprocess via ESM import(). The absolute file path is sent to the bridge, which uses dynamic import() to load the plugin as a native ES module.
func (*NodeRuntime) EvalWarnings ¶
func (r *NodeRuntime) EvalWarnings() []string
EvalWarnings returns warnings collected during EvalFile calls.
func (*NodeRuntime) PrepareWorkerPool ¶
func (r *NodeRuntime) PrepareWorkerPool(n int) error
PrepareWorkerPool starts n-1 additional Node bridges for parallel hook dispatch. Each worker loads the same plugin files as the primary bridge. Skipped when the runtime has no hooks (only filters/shortcodes).
func (*NodeRuntime) ProjectRoot ¶
func (r *NodeRuntime) ProjectRoot() string
ProjectRoot returns the project root used for Node module resolution.
func (*NodeRuntime) RegisteredFilters ¶
func (r *NodeRuntime) RegisteredFilters() []string
RegisteredFilters returns the names of filters registered by the Node plugin.
func (*NodeRuntime) RegisteredHookDetails ¶
func (r *NodeRuntime) RegisteredHookDetails() []HookRegistration
RegisteredHookDetails returns hook registrations with priority and scope.
func (*NodeRuntime) RegisteredHooks ¶
func (r *NodeRuntime) RegisteredHooks() []string
RegisteredHooks returns the deduplicated names of hooks registered by the Node plugin.
func (*NodeRuntime) RegisteredShortcodes ¶
func (r *NodeRuntime) RegisteredShortcodes() []string
RegisteredShortcodes returns the names of shortcodes registered by the Node plugin.
func (*NodeRuntime) RegisteredSources ¶ added in v0.5.0
func (r *NodeRuntime) RegisteredSources() []string
RegisteredSources returns the names of data sources registered by the Node plugin.
func (*NodeRuntime) Restart ¶ added in v0.6.0
func (r *NodeRuntime) Restart() error
Restart stops the Node bridge subprocess and worker pool, then starts a fresh bridge and re-evaluates all previously loaded plugin files. Used when onFileChanged returns restart: true — Node's ESM module cache holds stale references, so a fresh process is needed to re-import changed component definitions (issue #1100).
Restart re-sends eval messages but does not parse the responses to refresh filter/hook/shortcode registrations. This is safe because restart is for clearing ESM caches when imported dependencies change, not when the plugin's own registrations change. If plugin registrations change, a full rebuild (which creates fresh runtimes) is required.
Worker pools are not recreated — the dev server registry never has worker pools (PrepareWorkerPool is only called inside pipeline.Build on a separate registry). If future refactoring moves worker pool setup to the dev registry, this method would need updating.
func (*NodeRuntime) SetProjectRoot ¶
func (r *NodeRuntime) SetProjectRoot(root string)
SetProjectRoot sets the project root used for Node module resolution.
func (*NodeRuntime) SetSiteData ¶
func (r *NodeRuntime) SetSiteData(data map[string]interface{}) error
SetSiteData is a stub for the Node runtime. Site data injection over the Node bridge is not yet implemented — returns nil (no-op) since Node plugins receive data through hook payloads rather than a persistent alloy.data binding.
func (*NodeRuntime) SetSourceTimeout ¶ added in v0.5.0
func (r *NodeRuntime) SetSourceTimeout(d time.Duration)
SetSourceTimeout configures the timeout for source handler calls.
type PagesScope ¶
type PagesScope struct {
Mode PagesScopeMode
Glob string // path pattern when Mode == PagesScopeGlob
Taxonomies map[string][]string // taxonomy → terms when Mode == PagesScopeTaxonomy
Explicit bool // true when the plugin explicitly set a pages value
}
PagesScope controls which pages a hook receives.
type PagesScopeMode ¶
type PagesScopeMode int
PagesScopeMode determines how pages are filtered for a hook.
const ( PagesScopeNone PagesScopeMode = iota // skip pages entirely PagesScopeAll // send all pages PagesScopeGlob // filter by path glob PagesScopeTaxonomy // filter by taxonomy terms )
type PluginFilterRuntime ¶
type PluginFilterRuntime interface {
RegisteredFilters() []string
CallFilter(name string, input interface{}, args ...interface{}) (interface{}, error)
RegisteredShortcodes() []string
CallShortcode(name string, args []string, innerContent string) (string, error)
RegisteredHooks() []string
// SetSiteData injects site data so plugins can access it (e.g. alloy.data in JS).
// Implementations must treat nil as an empty map. Data values must be JSON-serializable.
SetSiteData(data map[string]interface{}) error
}
PluginFilterRuntime is the interface for plugin runtimes that can provide filters, shortcodes, and hooks to the template engine and hook registry. QuickJSRuntime, WASMRuntime, and NodeRuntime all implement this interface.
type PluginInfo ¶
type PluginInfo struct {
Path string // File path relative to plugins dir
Name string // Plugin name (filename without extension)
Tier PluginTier // Execution tier
Runtime PluginRuntime // Specific runtime within the tier
}
PluginInfo describes a discovered plugin file.
func ClassifyPlugin ¶
func ClassifyPlugin(path string) (*PluginInfo, error)
ClassifyPlugin determines the tier and runtime for a plugin file based on its extension and (for .js/.ts files) whether it exports runtime: "node".
type PluginRuntime ¶
type PluginRuntime string
PluginRuntime distinguishes sub-types within a tier.
const ( RuntimeGoBuiltIn PluginRuntime = "go" RuntimeQuickJS PluginRuntime = "quickjs" RuntimeWASM PluginRuntime = "wasm" RuntimeNode PluginRuntime = "node" )
type PluginTier ¶
type PluginTier int
PluginTier represents the execution tier of a plugin.
const ( // TierBuiltIn is Tier 1: Go built-in filters compiled into the binary. TierBuiltIn PluginTier = iota + 1 // TierInProcess is Tier 2: In-process plugins via wazero (QuickJS or WASM). TierInProcess // TierNode is Tier 3: Node subprocess plugins via IPC bridge. TierNode )
type QuickJSRuntime ¶
type QuickJSRuntime struct {
// contains filtered or unexported fields
}
QuickJSRuntime wraps a QuickJS instance for Tier 2 in-process JS plugins. JavaScript is executed via QuickJS compiled to WASM, running on wazero (pure Go, zero CGo). See PLAN.md §5.
func NewQuickJSRuntime ¶
func NewQuickJSRuntime() *QuickJSRuntime
NewQuickJSRuntime creates a new QuickJS runtime instance. Startup cost is ~10-50ms (one-time).
func (*QuickJSRuntime) BatchCallHook ¶ added in v0.6.0
func (r *QuickJSRuntime) BatchCallHook(name string, payloads []interface{}, onProgress func(int)) ([]interface{}, error)
BatchCallHook loops synchronously through payloads calling callHookLocked for each one (issue #1185). No per-item goroutine/channel/context overhead. onProgress is called with 1-based indices after each item completes.
func (*QuickJSRuntime) CallFilter ¶
func (r *QuickJSRuntime) CallFilter(name string, input interface{}, args ...interface{}) (interface{}, error)
CallFilter calls a registered filter function by name with an input value. The filter function is invoked in the QuickJS VM and the result is converted back to a Go value.
func (*QuickJSRuntime) CallHook ¶
func (r *QuickJSRuntime) CallHook(name string, payload interface{}) (interface{}, error)
CallHook invokes a registered hook function by name with a payload. The hook function is invoked in the QuickJS VM and the result is converted back to a Go value.
func (*QuickJSRuntime) CallShortcode ¶
func (r *QuickJSRuntime) CallShortcode(name string, args []string, innerContent string) (string, error)
CallShortcode calls a registered shortcode function by name with args and inner content. The shortcode function is invoked in the QuickJS VM with an array of string arguments.
func (*QuickJSRuntime) Close ¶
func (r *QuickJSRuntime) Close()
Close releases resources held by the QuickJS runtime. Acquires the mutex to wait for any in-flight WASM operations (e.g., from timed-out RunWithTimeout goroutines) to finish before freeing the runtime.
func (*QuickJSRuntime) EvalFile ¶
func (r *QuickJSRuntime) EvalFile(path string) error
EvalFile evaluates a JavaScript file in the QuickJS context. Plugin files using "export default function(alloy) { ... }" module syntax are transformed to an IIFE that receives the global alloy object.
func (*QuickJSRuntime) EvalWarnings ¶
func (r *QuickJSRuntime) EvalWarnings() []string
EvalWarnings returns warnings collected during plugin evaluation.
func (*QuickJSRuntime) Init ¶
func (r *QuickJSRuntime) Init() error
Init initializes the QuickJS instance via wazero.
func (*QuickJSRuntime) IsInitialized ¶
func (r *QuickJSRuntime) IsInitialized() bool
IsInitialized returns whether the runtime has been initialized.
func (*QuickJSRuntime) RegisteredFilters ¶
func (r *QuickJSRuntime) RegisteredFilters() []string
RegisteredFilters returns the names of all filters registered in the QuickJS context.
func (*QuickJSRuntime) RegisteredHookDetails ¶
func (r *QuickJSRuntime) RegisteredHookDetails() []HookRegistration
RegisteredHookDetails returns hook registrations with priority and scope info.
func (*QuickJSRuntime) RegisteredHooks ¶
func (r *QuickJSRuntime) RegisteredHooks() []string
RegisteredHooks returns the names of all hooks registered in the QuickJS context.
func (*QuickJSRuntime) RegisteredShortcodes ¶
func (r *QuickJSRuntime) RegisteredShortcodes() []string
RegisteredShortcodes returns the names of all shortcodes registered in the QuickJS context.
func (*QuickJSRuntime) SetSiteData ¶
func (r *QuickJSRuntime) SetSiteData(data map[string]interface{}) error
SetSiteData makes site data available as alloy.data in the JS context. Data is JSON-serialized from Go and parsed in JS. The resulting object is frozen to prevent cross-plugin mutation.
type Registry ¶
type Registry struct {
// contains filtered or unexported fields
}
Registry manages plugin discovery and loading.
func NewRegistry ¶
NewRegistry creates a plugin registry for the given plugins directory.
func (*Registry) Close ¶
func (r *Registry) Close()
Close releases resources held by all loaded runtimes and any pre-initialized runtimes that were never consumed by LoadPlugins. Also clears global plugin source handlers to prevent stale closures from referencing stopped NodeBridge instances during dev server rebuilds.
func (*Registry) ConflictWarnings ¶
ConflictWarnings returns any name conflict warnings produced during plugin loading.
func (*Registry) DiscoverPlugins ¶
DiscoverPlugins scans the plugins directory and loads plugins by file extension.
func (*Registry) HasFilter ¶
HasFilter reports whether a filter with the given name has been registered.
func (*Registry) InitRuntimes ¶
func (r *Registry) InitRuntimes() ([]PluginFilterRuntime, []string)
InitRuntimes concurrently initializes runtimes for all discovered plugins (Phase A). Runtimes are created and compiled but not evaluated — no filters or hooks are registered. Call LoadPlugins after to complete Phase B.
QuickJS and WASM plugins run in goroutines (CPU-bound compilation). Node plugins are initialized sequentially on the calling goroutine because subprocess spawn is I/O-bound with side effects.
func (*Registry) LoadPlugins ¶
func (r *Registry) LoadPlugins(hooks *HookRegistry) []string
LoadPlugins loads all discovered plugins into the given HookRegistry. If InitRuntimes was called first, uses pre-initialized runtimes (Phase B only). Otherwise initializes and evaluates sequentially (both phases). Returns warnings for plugins that fail to load (non-fatal).
func (*Registry) Plugins ¶
func (r *Registry) Plugins() []PluginInfo
Plugins returns the list of discovered plugins after DiscoverPlugins is called.
func (*Registry) RegisterFilter ¶
RegisterFilter records a filter registration and tracks name conflicts.
func (*Registry) RestartNodeRuntimes ¶ added in v0.6.0
RestartNodeRuntimes stops and restarts all Node bridge subprocesses so that ESM module caches are cleared. Called when onFileChanged returns restart: true — the plugin's import()ed dependencies have changed on disk and the Node process must re-import them (issue #1100).
func (*Registry) Runtimes ¶
func (r *Registry) Runtimes() []PluginFilterRuntime
Runtimes returns all loaded plugin runtimes for filter/shortcode bridging.
func (*Registry) SetPluginsDirRel ¶ added in v0.3.1
SetPluginsDirRel sets the config-relative plugins directory path used for filter source attribution (e.g. "plugins" or "tools/plugins").
func (*Registry) SetProjectRoot ¶ added in v0.3.1
SetProjectRoot sets the project root directory for plugin runtimes.
func (*Registry) SetWASMCacheDir ¶
SetWASMCacheDir configures a persistent compilation cache directory for WASM modules. When set, compiled native code is reused across builds. Creates the cache eagerly so it can be shared across all WASM runtimes.
type SSRInstance ¶
SSRInstance represents a single component instance for SSR rendering.
type SandboxViolationError ¶
type SandboxViolationError struct {
Resource string // "filesystem", "network", etc.
Detail string
}
SandboxViolationError represents an attempt to access a forbidden resource.
func (*SandboxViolationError) Error ¶
func (e *SandboxViolationError) Error() string
type WASMRuntime ¶
type WASMRuntime struct {
// contains filtered or unexported fields
}
WASMRuntime wraps a wazero WASM module for Tier 2 compiled plugins.
func NewWASMRuntime ¶
func NewWASMRuntime() *WASMRuntime
NewWASMRuntime creates a new WASM runtime via wazero.
func (*WASMRuntime) CallExport ¶
func (r *WASMRuntime) CallExport(name string, args ...interface{}) (interface{}, error)
CallExport calls an exported WASM function by name. At least one argument is required. For string arguments, the input is written to the module's memory and the function is called with (ptr, len). The result is read back from a packed i64 return.
func (*WASMRuntime) CallExportRaw ¶
func (r *WASMRuntime) CallExportRaw(name string, ptr, length uint32) (string, error)
CallExportRaw invokes a WASM function with raw i32 arguments and reads the result from memory. The function must return a packed i64: result = (ptr << 32) | len. Returns error if the unpacked result is (0, 0) per the ABI error convention.
func (*WASMRuntime) CallFilter ¶
func (r *WASMRuntime) CallFilter(name string, input interface{}, args ...interface{}) (interface{}, error)
CallFilter calls a WASM-exported filter function by name.
func (*WASMRuntime) CallHook ¶
func (r *WASMRuntime) CallHook(name string, payload interface{}) (interface{}, error)
CallHook marshals a JSON envelope and dispatches to the hook(ptr, len) export. The envelope is {event: name, payload: data}. When the WASM module returns an envelope-shaped response (has "payload" key), the payload is extracted so callers receive the hook result directly, not the transport envelope.
func (*WASMRuntime) CallShortcode ¶
func (r *WASMRuntime) CallShortcode(name string, args []string, innerContent string) (string, error)
CallShortcode is a no-op for WASM modules.
func (*WASMRuntime) HasExport ¶
func (r *WASMRuntime) HasExport(name string) bool
HasExport checks if the WASM module exports a function with the given name.
func (*WASMRuntime) LoadModule ¶
func (r *WASMRuntime) LoadModule(path string) error
LoadModule loads a WASM module from the given file path. Validates the binary, compiles it, and discovers exported functions.
func (*WASMRuntime) RegisteredFilters ¶
func (r *WASMRuntime) RegisteredFilters() []string
RegisteredFilters returns the names of exported functions that can be used as filters. Excludes well-known WASM runtime exports (memory, _start, etc.).
func (*WASMRuntime) RegisteredHookDetails ¶
func (r *WASMRuntime) RegisteredHookDetails() []HookRegistration
RegisteredHookDetails returns hook registrations with per-hook priority and scope.
func (*WASMRuntime) RegisteredHooks ¶
func (r *WASMRuntime) RegisteredHooks() []string
RegisteredHooks returns hook names discovered from the hooks() export.
func (*WASMRuntime) RegisteredShortcodes ¶
func (r *WASMRuntime) RegisteredShortcodes() []string
RegisteredShortcodes returns an empty list — WASM modules don't register shortcodes.
func (*WASMRuntime) SetCacheDir ¶
func (r *WASMRuntime) SetCacheDir(dir string)
SetCacheDir configures a persistent compilation cache directory. When set, wazero persists compiled native code to disk so subsequent builds skip WASM recompilation. Must be called before LoadModule.
func (*WASMRuntime) SetCompilationCache ¶
func (r *WASMRuntime) SetCompilationCache(cache wazero.CompilationCache)
SetCompilationCache sets a shared compilation cache owned by the caller. The cache is NOT closed by WASMRuntime — the caller manages its lifecycle.
func (*WASMRuntime) SetSiteData ¶
func (r *WASMRuntime) SetSiteData(data map[string]interface{}) error
SetSiteData is a no-op for WASM modules — they don't have a JS context to inject site data into.