71 lines
1.8 KiB
Go
71 lines
1.8 KiB
Go
package function
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"io"
|
|
"io/fs"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
|
|
"github.com/andybalholm/brotli"
|
|
"github.com/go-errors/errors"
|
|
)
|
|
|
|
type nativeBundler struct {
|
|
tempDir string
|
|
fsys fs.FS
|
|
}
|
|
|
|
func NewNativeBundler(tempDir string, fsys fs.FS) EszipBundler {
|
|
return &nativeBundler{
|
|
tempDir: tempDir,
|
|
fsys: fsys,
|
|
}
|
|
}
|
|
|
|
// Use a package private variable to allow testing without gosec complaining about G204
|
|
var edgeRuntimeBin = "edge-runtime"
|
|
|
|
func (b *nativeBundler) Bundle(ctx context.Context, entrypoint string, importMap string, staticFiles []string, output io.Writer) error {
|
|
slug := filepath.Base(filepath.Dir(entrypoint))
|
|
outputPath := filepath.Join(b.tempDir, slug+".eszip")
|
|
// TODO: make edge runtime write to stdout
|
|
args := []string{"bundle", "--entrypoint", entrypoint, "--output", outputPath}
|
|
if len(importMap) > 0 {
|
|
args = append(args, "--import-map", importMap)
|
|
}
|
|
for _, staticFile := range staticFiles {
|
|
args = append(args, "--static", staticFile)
|
|
}
|
|
cmd := exec.CommandContext(ctx, edgeRuntimeBin, args...)
|
|
cmd.Stderr = os.Stderr
|
|
cmd.Stdout = os.Stdout
|
|
if err := cmd.Run(); err != nil {
|
|
return errors.Errorf("failed to bundle function: %w", err)
|
|
}
|
|
defer os.Remove(outputPath)
|
|
// Compress the output
|
|
eszipBytes, err := b.fsys.Open(outputPath)
|
|
if err != nil {
|
|
return errors.Errorf("failed to open eszip: %w", err)
|
|
}
|
|
defer eszipBytes.Close()
|
|
return Compress(eszipBytes, output)
|
|
}
|
|
|
|
const compressedEszipMagicID = "EZBR"
|
|
|
|
func Compress(r io.Reader, w io.Writer) error {
|
|
if _, err := fmt.Fprint(w, compressedEszipMagicID); err != nil {
|
|
return errors.Errorf("failed to append magic id: %w", err)
|
|
}
|
|
brw := brotli.NewWriter(w)
|
|
defer brw.Close()
|
|
if _, err := io.Copy(brw, r); err != nil {
|
|
return errors.Errorf("failed to compress eszip: %w", err)
|
|
}
|
|
return nil
|
|
}
|