Files
zeekayandHanzo Dev 3e5f509c69 One plugin runtime, four languages, one interface
The contract was written down twice — zip declares Module and Loader, and the
loader beside base's runners declared its own copy. Structural typing was the
only thing keeping them equal, which is a property nobody can see and a compiler
will not check.

This implements zip's. The loader, the manifest and the runners live here so
cloud can stop carrying a second goja runtime of its own — a shim, a bundler and
a third registry that answered the same question this one does.

native, goja, wazero and pyvm. wazero is the reason this is not a list of four
languages: anything compiled to WebAssembly ahead of time arrives without a new
runner, and Rust walks through that door rather than getting one built for it.
pyvm is real CPython through cgo with PEP 684 sub-interpreters, behind a build
tag, because embedding the language beats reimplementing a subset of it.

Its one dependency on base was a single call for an unguessable string, which
crypto/rand says directly.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-16 12:33:40 -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
}