Skip to content

Commit

Permalink
feat: support adding static files to Edge Functions (#3045)
Browse files Browse the repository at this point in the history
  • Loading branch information
laktek authored Jan 15, 2025
1 parent 678f978 commit fb0cd15
Show file tree
Hide file tree
Showing 12 changed files with 32 additions and 12 deletions.
6 changes: 5 additions & 1 deletion internal/functions/deploy/bundle.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ func NewDockerBundler(fsys afero.Fs) function.EszipBundler {
return &dockerBundler{fsys: fsys}
}

func (b *dockerBundler) Bundle(ctx context.Context, entrypoint string, importMap string, output io.Writer) error {
func (b *dockerBundler) Bundle(ctx context.Context, entrypoint string, importMap string, staticFiles []string, output io.Writer) error {
// Create temp directory to store generated eszip
slug := filepath.Base(filepath.Dir(entrypoint))
fmt.Fprintln(os.Stderr, "Bundling Function:", utils.Bold(slug))
Expand Down Expand Up @@ -54,9 +54,13 @@ func (b *dockerBundler) Bundle(ctx context.Context, entrypoint string, importMap
if len(importMap) > 0 {
cmd = append(cmd, "--import-map", utils.ToDockerPath(importMap))
}
for _, staticFile := range staticFiles {
cmd = append(cmd, "--static", utils.ToDockerPath(staticFile))
}
if viper.GetBool("DEBUG") {
cmd = append(cmd, "--verbose")
}

env := []string{}
if custom_registry := os.Getenv("NPM_CONFIG_REGISTRY"); custom_registry != "" {
env = append(env, "NPM_CONFIG_REGISTRY="+custom_registry)
Expand Down
2 changes: 1 addition & 1 deletion internal/functions/deploy/bundle_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ func TestDockerBundle(t *testing.T) {
apitest.MockDockerStart(utils.Docker, imageUrl, containerId)
require.NoError(t, apitest.MockDockerLogsExitCode(utils.Docker, containerId, 1))
// Run test
err = NewDockerBundler(fsys).Bundle(context.Background(), "", "", &body)
err = NewDockerBundler(fsys).Bundle(context.Background(), "", "", []string{}, &body)
// Check error
assert.ErrorContains(t, err, "error running container: exit 1")
assert.Empty(t, apitest.ListUnmatchedRequests())
Expand Down
3 changes: 3 additions & 0 deletions internal/functions/serve/serve.go
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,9 @@ func populatePerFunctionConfigs(cwd, importMapPath string, noVerifyJWT *bool, fs
fc.ImportMap = utils.ToDockerPath(fc.ImportMap)
fc.Entrypoint = utils.ToDockerPath(fc.Entrypoint)
functionsConfig[slug] = fc
for i, val := range fc.StaticFiles {
fc.StaticFiles[i] = utils.ToDockerPath(val)
}
}
functionsConfigBytes, err := json.Marshal(functionsConfig)
if err != nil {
Expand Down
3 changes: 3 additions & 0 deletions internal/functions/serve/templates/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,8 @@ Deno.serve({
const absEntrypoint = posix.join(Deno.cwd(), functionsConfig[functionName].entrypointPath);
const maybeEntrypoint = posix.toFileUrl(absEntrypoint).href;

const staticPatterns = functionsConfig[functionName].staticFiles;

try {
const worker = await EdgeRuntime.userWorkers.create({
servicePath,
Expand All @@ -195,6 +197,7 @@ Deno.serve({
context: {
useReadSyncFileAPI: true,
},
staticPatterns,
});

return await worker.fetch(req);
Expand Down
12 changes: 8 additions & 4 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,10 +178,11 @@ type (
FunctionConfig map[string]function

function struct {
Enabled *bool `toml:"enabled" json:"-"`
VerifyJWT *bool `toml:"verify_jwt" json:"verifyJWT"`
ImportMap string `toml:"import_map" json:"importMapPath,omitempty"`
Entrypoint string `toml:"entrypoint" json:"entrypointPath,omitempty"`
Enabled *bool `toml:"enabled" json:"-"`
VerifyJWT *bool `toml:"verify_jwt" json:"verifyJWT"`
ImportMap string `toml:"import_map" json:"importMapPath,omitempty"`
Entrypoint string `toml:"entrypoint" json:"entrypointPath,omitempty"`
StaticFiles []string `toml:"static_files" json:"staticFiles,omitempty"`
}

analytics struct {
Expand Down Expand Up @@ -592,6 +593,9 @@ func (c *baseConfig) resolve(builder pathBuilder, fsys fs.FS) error {
} else if !filepath.IsAbs(function.ImportMap) {
function.ImportMap = filepath.Join(builder.SupabaseDirPath, function.ImportMap)
}
for i, val := range function.StaticFiles {
function.StaticFiles[i] = filepath.Join(builder.SupabaseDirPath, val)
}
c.Functions[slug] = function
}
return c.Db.Seed.loadSeedPaths(builder.SupabaseDirPath, fsys)
Expand Down
2 changes: 1 addition & 1 deletion pkg/config/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ const (
pgmetaImage = "supabase/postgres-meta:v0.84.2"
studioImage = "supabase/studio:20250113-83c9420"
imageProxyImage = "darthsim/imgproxy:v3.8.0"
edgeRuntimeImage = "supabase/edge-runtime:v1.66.4"
edgeRuntimeImage = "supabase/edge-runtime:v1.66.5"
vectorImage = "timberio/vector:0.28.1-alpine"
supavisorImage = "supabase/supavisor:1.1.56"
gotrueImage = "supabase/gotrue:v2.167.0"
Expand Down
3 changes: 3 additions & 0 deletions pkg/config/templates/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,9 @@ inspector_port = 8083
# Uncomment to specify a custom file path to the entrypoint.
# Supported file extensions are: .ts, .js, .mjs, .jsx, .tsx
# entrypoint = "./functions/MY_FUNCTION_NAME/index.ts"
# Specifies static files to be bundled with the function. Supports glob patterns.
# For example, if you want to serve static HTML pages in your function:
# static_files = [ "./functions/MY_FUNCTION_NAME/*.html" ]

[analytics]
enabled = true
Expand Down
2 changes: 1 addition & 1 deletion pkg/function/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ type EdgeRuntimeAPI struct {
}

type EszipBundler interface {
Bundle(ctx context.Context, entrypoint string, importMap string, output io.Writer) error
Bundle(ctx context.Context, entrypoint string, importMap string, staticFiles []string, output io.Writer) error
}

func NewEdgeRuntimeAPI(project string, client api.ClientWithResponses, bundler EszipBundler) EdgeRuntimeAPI {
Expand Down
2 changes: 1 addition & 1 deletion pkg/function/batch.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@ func (s *EdgeRuntimeAPI) UpsertFunctions(ctx context.Context, functionConfig con
}
}
var body bytes.Buffer
if err := s.eszip.Bundle(ctx, function.Entrypoint, function.ImportMap, &body); err != nil {
if err := s.eszip.Bundle(ctx, function.Entrypoint, function.ImportMap, function.StaticFiles, &body); err != nil {
return err
}
// Update if function already exists
Expand Down
2 changes: 1 addition & 1 deletion pkg/function/batch_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import (
type MockBundler struct {
}

func (b *MockBundler) Bundle(ctx context.Context, entrypoint string, importMap string, output io.Writer) error {
func (b *MockBundler) Bundle(ctx context.Context, entrypoint string, importMap string, staticFiles []string, output io.Writer) error {
return nil
}

Expand Down
5 changes: 4 additions & 1 deletion pkg/function/bundle.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,17 @@ func NewNativeBundler(tempDir string, fsys fs.FS) EszipBundler {
// 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, output io.Writer) error {
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
Expand Down
2 changes: 1 addition & 1 deletion pkg/function/bundle_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func TestBundleFunction(t *testing.T) {
// Setup mock bundler
bundler := nativeBundler{fsys: fsys}
// Run test
err := bundler.Bundle(context.Background(), "hello/index.ts", "", &body)
err := bundler.Bundle(context.Background(), "hello/index.ts", "", nil, &body)
// Check error
assert.NoError(t, err)
assert.Equal(t, compressedEszipMagicID+";", body.String())
Expand Down

0 comments on commit fb0cd15

Please sign in to comment.