package plugins
import (
"archive/zip"
"errors"
"fmt"
"io"
)
const (
PackageExtension = ".ndp"
manifestFileName = "manifest.json"
wasmFileName = "plugin.wasm"
)
type ndpPackage struct {
Manifest *Manifest
WasmBytes []byte
}
func openPackage(ndpPath string) (*ndpPackage, error) {
zr, err := zip.OpenReader(ndpPath)
if err != nil {
return nil, fmt.Errorf("opening package: %w", err)
}
defer zr.Close()
var manifestBytes []byte
var wasmBytes []byte
for _, f := range zr.File {
switch f.Name {
case manifestFileName:
manifestBytes, err = readZipFile(f)
if err != nil {
return nil, fmt.Errorf("reading manifest: %w", err)
}
case wasmFileName:
wasmBytes, err = readZipFile(f)
if err != nil {
return nil, fmt.Errorf("reading wasm: %w", err)
}
}
}
if manifestBytes == nil {
return nil, errors.New("package missing manifest.json")
}
if wasmBytes == nil {
return nil, errors.New("package missing plugin.wasm")
}
manifest, err := ParseManifest(manifestBytes)
if err != nil {
return nil, fmt.Errorf("parsing manifest: %w", err)
}
return &ndpPackage{
Manifest: manifest,
WasmBytes: wasmBytes,
}, nil
}
func readManifest(ndpPath string) (*Manifest, error) {
zr, err := zip.OpenReader(ndpPath)
if err != nil {
return nil, fmt.Errorf("opening package: %w", err)
}
defer zr.Close()
for _, f := range zr.File {
if f.Name == manifestFileName {
manifestBytes, err := readZipFile(f)
if err != nil {
return nil, fmt.Errorf("reading manifest: %w", err)
}
manifest, err := ParseManifest(manifestBytes)
if err != nil {
return nil, fmt.Errorf("parsing manifest: %w", err)
}
return manifest, nil
}
}
return nil, errors.New("package missing manifest.json")
}
func readZipFile(f *zip.File) ([]byte, error) {
rc, err := f.Open()
if err != nil {
return nil, err
}
defer rc.Close()
return io.ReadAll(rc)
}