Skip to content

Commit

Permalink
fix: append config.toml when creating new function (#3212)
Browse files Browse the repository at this point in the history
* fix: append config.toml when creating new function

* chore: update unit tests

* chore: remove unnecessary comments from config template
  • Loading branch information
sweatybridge authored Feb 26, 2025
1 parent 6ccc4fd commit a1aab11
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 48 deletions.
89 changes: 53 additions & 36 deletions internal/functions/new/new.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,11 @@ var (
denoEmbed string
//go:embed templates/.npmrc
npmrcEmbed string
//go:embed templates/config.toml
configEmbed string

indexTemplate = template.Must(template.New("index").Parse(indexEmbed))
indexTemplate = template.Must(template.New("index").Parse(indexEmbed))
configTemplate = template.Must(template.New("config").Parse(configEmbed))
)

type indexConfig struct {
Expand All @@ -32,49 +35,63 @@ type indexConfig struct {

func Run(ctx context.Context, slug string, fsys afero.Fs) error {
// 1. Sanity checks.
funcDir := filepath.Join(utils.FunctionsDir, slug)
{
if err := utils.ValidateFunctionSlug(slug); err != nil {
return err
}
if err := utils.ValidateFunctionSlug(slug); err != nil {
return err
}

// 2. Create new function.
{
if err := utils.MkdirIfNotExistFS(fsys, funcDir); err != nil {
return err
}

// Load config if available
if err := flags.LoadConfig(fsys); err != nil {
utils.CmdSuggestion = ""
}

if err := createTemplateFile(fsys, filepath.Join(funcDir, "index.ts"), indexTemplate, indexConfig{
URL: utils.GetApiUrl("/functions/v1/" + slug),
Token: utils.Config.Auth.AnonKey,
}); err != nil {
return errors.Errorf("failed to create function entrypoint: %w", err)
}

if err := afero.WriteFile(fsys, filepath.Join(funcDir, "deno.json"), []byte(denoEmbed), 0644); err != nil {
return errors.Errorf("failed to create deno.json config: %w", err)
}

if err := afero.WriteFile(fsys, filepath.Join(funcDir, ".npmrc"), []byte(npmrcEmbed), 0644); err != nil {
return errors.Errorf("failed to create .npmrc config: %w", err)
}
funcDir := filepath.Join(utils.FunctionsDir, slug)
if err := utils.MkdirIfNotExistFS(fsys, funcDir); err != nil {
return err
}
// Load config if available
if err := flags.LoadConfig(fsys); err != nil {
utils.CmdSuggestion = ""
}
if err := createEntrypointFile(slug, fsys); err != nil {
return err
}
if err := appendConfigFile(slug, fsys); err != nil {
return err
}
// 3. Create optional files
if err := afero.WriteFile(fsys, filepath.Join(funcDir, "deno.json"), []byte(denoEmbed), 0644); err != nil {
return errors.Errorf("failed to create deno.json config: %w", err)
}
if err := afero.WriteFile(fsys, filepath.Join(funcDir, ".npmrc"), []byte(npmrcEmbed), 0644); err != nil {
return errors.Errorf("failed to create .npmrc config: %w", err)
}

fmt.Println("Created new Function at " + utils.Bold(funcDir))
return nil
}

func createTemplateFile(fsys afero.Fs, path string, tmpl *template.Template, data interface{}) error {
f, err := fsys.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0644)
func createEntrypointFile(slug string, fsys afero.Fs) error {
entrypointPath := filepath.Join(utils.FunctionsDir, slug, "index.ts")
f, err := fsys.OpenFile(entrypointPath, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0644)
if err != nil {
return err
return errors.Errorf("failed to create entrypoint: %w", err)
}
defer f.Close()
if err := indexTemplate.Option("missingkey=error").Execute(f, indexConfig{
URL: utils.GetApiUrl("/functions/v1/" + slug),
Token: utils.Config.Auth.AnonKey,
}); err != nil {
return errors.Errorf("failed to write entrypoint: %w", err)
}
return nil
}

func appendConfigFile(slug string, fsys afero.Fs) error {
if _, exists := utils.Config.Functions[slug]; exists {
fmt.Fprintf(os.Stderr, "[functions.%s] is already declared in %s\n", slug, utils.Bold(utils.ConfigPath))
return nil
}
f, err := fsys.OpenFile(utils.ConfigPath, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)
if err != nil {
return errors.Errorf("failed to append config: %w", err)
}
defer f.Close()
return tmpl.Option("missingkey=error").Execute(f, data)
if err := configTemplate.Option("missingkey=error").Execute(f, slug); err != nil {
return errors.Errorf("failed to append template: %w", err)
}
return nil
}
4 changes: 4 additions & 0 deletions internal/functions/new/new_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ func TestNewCommand(t *testing.T) {
"curl -i --location --request POST 'http://127.0.0.1:54321/functions/v1/test-func'",
)

// Verify config.toml is updated
_, err = afero.ReadFile(fsys, utils.ConfigPath)
assert.NoError(t, err, "config.toml should be created")

// Verify deno.json exists
denoPath := filepath.Join(utils.FunctionsDir, "test-func", "deno.json")
_, err = afero.ReadFile(fsys, denoPath)
Expand Down
11 changes: 11 additions & 0 deletions internal/functions/new/templates/config.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@

[functions.{{ . }}]
enabled = true
verify_jwt = true
import_map = "./functions/{{ . }}/deno.json"
# Uncomment to specify a custom file path to the entrypoint.
# Supported file extensions are: .ts, .js, .mjs, .jsx, .tsx
entrypoint = "./functions/{{ . }}/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/{{ . }}/*.html" ]
12 changes: 0 additions & 12 deletions pkg/config/templates/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -263,18 +263,6 @@ policy = "oneshot"
# Port to attach the Chrome inspector for debugging edge functions.
inspector_port = 8083

# Use these configurations to customize your Edge Function.
# [functions.MY_FUNCTION_NAME]
# enabled = true
# verify_jwt = true
# import_map = "./functions/MY_FUNCTION_NAME/deno.json"
# 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
port = 54327
Expand Down

0 comments on commit a1aab11

Please sign in to comment.