Skip to content

Commit cf4d803

Browse files
committed
fix: support main.ts as an entrypoint
1 parent 0b8c968 commit cf4d803

File tree

2 files changed

+115
-2
lines changed

2 files changed

+115
-2
lines changed

internal/functions/deploy/deploy.go

+10-2
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ func Run(ctx context.Context, slugs []string, useDocker bool, noVerifyJWT *bool,
5454
}
5555

5656
func GetFunctionSlugs(fsys afero.Fs) (slugs []string, err error) {
57-
pattern := filepath.Join(utils.FunctionsDir, "*", "index.ts")
57+
pattern := filepath.Join(utils.FunctionsDir, "*", "*.ts")
5858
paths, err := afero.Glob(fsys, pattern)
5959
if err != nil {
6060
return nil, errors.Errorf("failed to glob function slugs: %w", err)
@@ -97,7 +97,15 @@ func GetFunctionConfig(slugs []string, importMapPath string, noVerifyJWT *bool,
9797
// Precedence order: flag > config > fallback
9898
functionDir := filepath.Join(utils.FunctionsDir, name)
9999
if len(function.Entrypoint) == 0 {
100-
function.Entrypoint = filepath.Join(functionDir, "index.ts")
100+
indexEntrypoint := filepath.Join(functionDir, "index.ts")
101+
mainEntrypoint := filepath.Join(functionDir, "main.ts")
102+
if _, err := fsys.Stat(indexEntrypoint); err == nil {
103+
function.Entrypoint = indexEntrypoint
104+
} else if _, err := fsys.Stat(mainEntrypoint); err == nil {
105+
function.Entrypoint = mainEntrypoint
106+
} else {
107+
return nil, errors.Errorf("Cannot find a valid entrypoint file (index.ts or main.ts) for the function. Set the custom entrypoint path in config.toml")
108+
}
101109
}
102110
if len(importMapPath) > 0 {
103111
function.ImportMap = importMapPath

internal/functions/deploy/deploy_test.go

+105
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@ func TestDeployCommand(t *testing.T) {
3131
// Setup in-memory fs
3232
fsys := afero.NewMemMapFs()
3333
require.NoError(t, utils.WriteConfig(fsys, false))
34+
35+
require.NoError(t, afero.WriteFile(fsys, filepath.Join(utils.FunctionsDir, slug, "index.ts"), []byte{}, 0644))
36+
require.NoError(t, afero.WriteFile(fsys, filepath.Join(utils.FunctionsDir, slug+"-2", "index.ts"), []byte{}, 0644))
37+
3438
// Setup valid access token
3539
token := apitest.RandomAccessToken(t)
3640
t.Setenv("SUPABASE_ACCESS_TOKEN", string(token))
@@ -120,6 +124,47 @@ import_map = "./import_map.json"
120124
assert.Empty(t, apitest.ListUnmatchedRequests())
121125
})
122126

127+
t.Run("deploys functions with main.ts as entrypoint", func(t *testing.T) {
128+
t.Cleanup(func() { clear(utils.Config.Functions) })
129+
// Setup in-memory fs
130+
fsys := afero.NewMemMapFs()
131+
132+
// Setup function entrypoint
133+
entrypointPath := filepath.Join(utils.FunctionsDir, slug, "main.ts")
134+
require.NoError(t, afero.WriteFile(fsys, entrypointPath, []byte{}, 0644))
135+
136+
// Setup valid access token
137+
token := apitest.RandomAccessToken(t)
138+
t.Setenv("SUPABASE_ACCESS_TOKEN", string(token))
139+
// Setup valid deno path
140+
_, err := fsys.Create(utils.DenoPathOverride)
141+
require.NoError(t, err)
142+
// Setup mock api
143+
defer gock.OffAll()
144+
gock.New(utils.DefaultApiHost).
145+
Get("/v1/projects/" + flags.ProjectRef + "/functions").
146+
Reply(http.StatusOK).
147+
JSON([]api.FunctionResponse{})
148+
gock.New(utils.DefaultApiHost).
149+
Post("/v1/projects/"+flags.ProjectRef+"/functions").
150+
MatchParam("slug", slug).
151+
ParamPresent("import_map_path").
152+
Reply(http.StatusCreated).
153+
JSON(api.FunctionResponse{Id: "1"})
154+
// Setup mock docker
155+
require.NoError(t, apitest.MockDocker(utils.Docker))
156+
apitest.MockDockerStart(utils.Docker, imageUrl, containerId)
157+
require.NoError(t, apitest.MockDockerLogs(utils.Docker, containerId, "bundled"))
158+
// Setup output file
159+
outputDir := filepath.Join(utils.TempDir, fmt.Sprintf(".output_%s", slug))
160+
require.NoError(t, afero.WriteFile(fsys, filepath.Join(outputDir, "output.eszip"), []byte(""), 0644))
161+
// Run test
162+
err = Run(context.Background(), []string{slug}, true, nil, "", 1, fsys)
163+
// Check error
164+
assert.NoError(t, err)
165+
assert.Empty(t, apitest.ListUnmatchedRequests())
166+
})
167+
123168
t.Run("skip disabled functions from config", func(t *testing.T) {
124169
t.Cleanup(func() { clear(utils.Config.Functions) })
125170
// Setup in-memory fs
@@ -190,6 +235,47 @@ import_map = "./import_map.json"
190235
assert.ErrorContains(t, err, "No Functions specified or found in supabase/functions")
191236
})
192237

238+
t.Run("throws error on missing entrypoint", func(t *testing.T) {
239+
t.Cleanup(func() { clear(utils.Config.Functions) })
240+
// Setup in-memory fs
241+
fsys := afero.NewMemMapFs()
242+
require.NoError(t, utils.WriteConfig(fsys, false))
243+
244+
// Setup function entrypoint
245+
entrypointPath := filepath.Join(utils.FunctionsDir, slug, "not-entrypoint.ts")
246+
require.NoError(t, afero.WriteFile(fsys, entrypointPath, []byte{}, 0644))
247+
248+
// Setup valid access token
249+
token := apitest.RandomAccessToken(t)
250+
t.Setenv("SUPABASE_ACCESS_TOKEN", string(token))
251+
// Setup valid deno path
252+
_, err := fsys.Create(utils.DenoPathOverride)
253+
require.NoError(t, err)
254+
// Setup mock api
255+
defer gock.OffAll()
256+
gock.New(utils.DefaultApiHost).
257+
Get("/v1/projects/" + flags.ProjectRef + "/functions").
258+
Reply(http.StatusOK).
259+
JSON([]api.FunctionResponse{})
260+
gock.New(utils.DefaultApiHost).
261+
Post("/v1/projects/"+flags.ProjectRef+"/functions").
262+
MatchParam("slug", slug).
263+
ParamPresent("import_map_path").
264+
Reply(http.StatusCreated).
265+
JSON(api.FunctionResponse{Id: "1"})
266+
// Setup mock docker
267+
require.NoError(t, apitest.MockDocker(utils.Docker))
268+
apitest.MockDockerStart(utils.Docker, imageUrl, containerId)
269+
require.NoError(t, apitest.MockDockerLogs(utils.Docker, containerId, "bundled"))
270+
// Setup output file
271+
outputDir := filepath.Join(utils.TempDir, fmt.Sprintf(".output_%s", slug))
272+
require.NoError(t, afero.WriteFile(fsys, filepath.Join(outputDir, "output.eszip"), []byte(""), 0644))
273+
// Run test
274+
err = Run(context.Background(), []string{slug}, true, nil, "", 1, fsys)
275+
// Check error
276+
assert.ErrorContains(t, err, "Cannot find a valid entrypoint file")
277+
})
278+
193279
t.Run("verify_jwt param falls back to config", func(t *testing.T) {
194280
t.Cleanup(func() { clear(utils.Config.Functions) })
195281
// Setup in-memory fs
@@ -283,6 +369,10 @@ func TestImportMapPath(t *testing.T) {
283369
// Setup in-memory fs
284370
fsys := afero.NewMemMapFs()
285371
require.NoError(t, afero.WriteFile(fsys, utils.FallbackImportMapPath, []byte("{}"), 0644))
372+
373+
// Write function entrypoints
374+
require.NoError(t, afero.WriteFile(fsys, filepath.Join(utils.FunctionsDir, "test", "index.ts"), []byte{}, 0644))
375+
286376
// Run test
287377
fc, err := GetFunctionConfig([]string{"test"}, "", nil, fsys)
288378
// Check error
@@ -299,6 +389,10 @@ func TestImportMapPath(t *testing.T) {
299389
// Setup in-memory fs
300390
fsys := afero.NewMemMapFs()
301391
require.NoError(t, afero.WriteFile(fsys, utils.FallbackImportMapPath, []byte("{}"), 0644))
392+
393+
// Write function entrypoints
394+
require.NoError(t, afero.WriteFile(fsys, filepath.Join(utils.FunctionsDir, slug, "index.ts"), []byte{}, 0644))
395+
302396
// Run test
303397
fc, err := GetFunctionConfig([]string{slug}, "", nil, fsys)
304398
// Check error
@@ -319,6 +413,9 @@ func TestImportMapPath(t *testing.T) {
319413
require.NoError(t, afero.WriteFile(fsys, customImportMapPath, []byte("{}"), 0644))
320414
// Create fallback import map to test precedence order
321415
require.NoError(t, afero.WriteFile(fsys, utils.FallbackImportMapPath, []byte("{}"), 0644))
416+
// Write function entrypoints
417+
require.NoError(t, afero.WriteFile(fsys, filepath.Join(utils.FunctionsDir, slug, "index.ts"), []byte{}, 0644))
418+
322419
// Run test
323420
fc, err := GetFunctionConfig([]string{slug}, customImportMapPath, cast.Ptr(false), fsys)
324421
// Check error
@@ -329,6 +426,10 @@ func TestImportMapPath(t *testing.T) {
329426
t.Run("returns empty string if no fallback", func(t *testing.T) {
330427
// Setup in-memory fs
331428
fsys := afero.NewMemMapFs()
429+
430+
// Write function entrypoints
431+
require.NoError(t, afero.WriteFile(fsys, filepath.Join(utils.FunctionsDir, "test", "index.ts"), []byte{}, 0644))
432+
332433
// Run test
333434
fc, err := GetFunctionConfig([]string{"test"}, "", nil, fsys)
334435
// Check error
@@ -341,6 +442,10 @@ func TestImportMapPath(t *testing.T) {
341442
// Setup in-memory fs
342443
fsys := afero.NewMemMapFs()
343444
require.NoError(t, afero.WriteFile(fsys, utils.FallbackImportMapPath, []byte("{}"), 0644))
445+
446+
// Write function entrypoints
447+
require.NoError(t, afero.WriteFile(fsys, filepath.Join(utils.FunctionsDir, "test", "index.ts"), []byte{}, 0644))
448+
344449
// Run test
345450
fc, err := GetFunctionConfig([]string{"test"}, path, nil, fsys)
346451
// Check error

0 commit comments

Comments
 (0)