Files
base/plugins/extruntime/manifest.go
zeekay 33793e3b16 feat(base): extension runtime interface + native impl
Foundation for pluggable extension runtimes. One Runtime interface
that wazero, v8go, goja, and native-Go all satisfy. Extensions
declare their preferred runtime in extension.json; the loader
dispatches.

This sits alongside plugins/jsvm — goja-via-the-existing-jsvm-path
remains the default for .base.js hooks. The new path is for users
who want hard-sandboxed WASM extensions or full V8 perf.

Files:
- plugins/extruntime/extruntime.go — Runtime + Module interfaces, Manifest
- plugins/extruntime/manifest.go — JSON manifest loader (stdlib only)
- plugins/extruntime/native.go — reference impl, registers Go funcs

Concrete runtimes land in sibling commits:
- plugins/wasmvm — wazero (pure Go, hard sandbox)
- plugins/v8vm — v8go (cgo, -tags v8vm)
- plugins/gojavm — goja adapter (no new deps)
- plugins/extbench — fixtures + benchmarks across all 5
2026-05-18 17:40:50 -07:00

36 lines
940 B
Go

package extruntime
import (
"encoding/json"
"fmt"
"os"
"path/filepath"
)
// LoadManifest reads extension.json from dir and returns the parsed manifest.
// JSON over TOML — base has zero TOML deps and the manifest is small enough
// that the JSON ergonomics tax is irrelevant.
func LoadManifest(dir string) (*Manifest, error) {
p := filepath.Join(dir, "extension.json")
data, err := os.ReadFile(p)
if err != nil {
if os.IsNotExist(err) {
return nil, fmt.Errorf("%w: %s", ErrNoManifest, p)
}
return nil, fmt.Errorf("read manifest %s: %w", p, err)
}
var m Manifest
if err := json.Unmarshal(data, &m); err != nil {
return nil, fmt.Errorf("%w: %s: %v", ErrBadManifest, p, err)
}
if m.Name == "" {
return nil, fmt.Errorf("%w: %s: name is required", ErrBadManifest, p)
}
if m.Runtime == "" {
return nil, fmt.Errorf("%w: %s: runtime is required (native|goja|wazero|v8go)", ErrBadManifest, p)
}
return &m, nil
}