• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

supabase / cli / 20065213712

09 Dec 2025 01:30PM UTC coverage: 56.212% (+0.03%) from 56.185%
20065213712

Pull #4598

github

web-flow
Merge 783fdacae into e43638018
Pull Request #4598: refactor(cli): move Deno/IntelliJ prompts from init to functions new

35 of 45 new or added lines in 4 files covered. (77.78%)

6 existing lines in 2 files now uncovered.

6832 of 12154 relevant lines covered (56.21%)

6.31 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

69.77
/internal/functions/new/new.go
1
package new
2

3
import (
4
        "context"
5
        _ "embed"
6
        "fmt"
7
        "html/template"
8
        "os"
9
        "path/filepath"
10

11
        "github.com/go-errors/errors"
12
        "github.com/spf13/afero"
13
        _init "github.com/supabase/cli/internal/init"
14
        "github.com/supabase/cli/internal/utils"
15
        "github.com/supabase/cli/internal/utils/flags"
16
)
17

18
var (
19
        //go:embed templates/index.ts
20
        indexEmbed string
21
        //go:embed templates/deno.json
22
        denoEmbed string
23
        //go:embed templates/.npmrc
24
        npmrcEmbed string
25
        //go:embed templates/config.toml
26
        configEmbed string
27

28
        indexTemplate  = template.Must(template.New("index").Parse(indexEmbed))
29
        configTemplate = template.Must(template.New("config").Parse(configEmbed))
30
)
31

32
type indexConfig struct {
33
        URL   string
34
        Token string
35
}
36

37
func Run(ctx context.Context, slug string, fsys afero.Fs) error {
4✔
38
        // 1. Sanity checks.
4✔
39
        if err := utils.ValidateFunctionSlug(slug); err != nil {
5✔
40
                return err
1✔
41
        }
1✔
42
        isFirstFunction := isFirstFunctionCreation(fsys)
3✔
43

3✔
44
        // 2. Create new function.
3✔
45
        funcDir := filepath.Join(utils.FunctionsDir, slug)
3✔
46
        if err := utils.MkdirIfNotExistFS(fsys, funcDir); err != nil {
4✔
47
                return err
1✔
48
        }
1✔
49
        // Load config if available
50
        if err := flags.LoadConfig(fsys); err != nil {
2✔
51
                fmt.Fprintln(utils.GetDebugLogger(), err)
×
52
        }
×
53
        if err := createEntrypointFile(slug, fsys); err != nil {
3✔
54
                return err
1✔
55
        }
1✔
56
        if err := appendConfigFile(slug, fsys); err != nil {
1✔
57
                return err
×
58
        }
×
59
        // 3. Create optional files
60
        if err := afero.WriteFile(fsys, filepath.Join(funcDir, "deno.json"), []byte(denoEmbed), 0644); err != nil {
1✔
61
                return errors.Errorf("failed to create deno.json config: %w", err)
×
62
        }
×
63
        if err := afero.WriteFile(fsys, filepath.Join(funcDir, ".npmrc"), []byte(npmrcEmbed), 0644); err != nil {
1✔
64
                return errors.Errorf("failed to create .npmrc config: %w", err)
×
65
        }
×
66
        fmt.Println("Created new Function at " + utils.Bold(funcDir))
1✔
67

1✔
68
        if isFirstFunction {
2✔
69
                if err := promptForIDESettings(ctx, fsys); err != nil {
1✔
NEW
70
                        return err
×
NEW
71
                }
×
72
        }
73
        return nil
1✔
74
}
75

76
// Checks if this is the first function being created.
77
// Returns true if the functions directory doesn't exist or is empty.
78
func isFirstFunctionCreation(fsys afero.Fs) bool {
8✔
79
        entries, err := afero.ReadDir(fsys, utils.FunctionsDir)
8✔
80
        if err != nil {
11✔
81
                // Directory doesn't exist, this is the first function
3✔
82
                return true
3✔
83
        }
3✔
84
        // Check if there are any subdirectories (existing functions)
85
        for _, entry := range entries {
10✔
86
                if entry.IsDir() {
8✔
87
                        return false
3✔
88
                }
3✔
89
        }
90
        return true
2✔
91
}
92

93
func promptForIDESettings(ctx context.Context, fsys afero.Fs) error {
1✔
94
        console := utils.NewConsole()
1✔
95
        if isVscode, err := console.PromptYesNo(ctx, "Generate VS Code settings for Deno?", true); err != nil {
1✔
NEW
96
                return err
×
97
        } else if isVscode {
2✔
98
                return _init.WriteVscodeConfig(fsys)
1✔
99
        }
1✔
NEW
100
        if isIntelliJ, err := console.PromptYesNo(ctx, "Generate IntelliJ IDEA settings for Deno?", false); err != nil {
×
NEW
101
                return err
×
NEW
102
        } else if isIntelliJ {
×
NEW
103
                return _init.WriteIntelliJConfig(fsys)
×
NEW
104
        }
×
UNCOV
105
        return nil
×
106
}
107

108
func createEntrypointFile(slug string, fsys afero.Fs) error {
2✔
109
        entrypointPath := filepath.Join(utils.FunctionsDir, slug, "index.ts")
2✔
110
        f, err := fsys.OpenFile(entrypointPath, os.O_WRONLY|os.O_CREATE|os.O_EXCL, 0644)
2✔
111
        if err != nil {
3✔
112
                return errors.Errorf("failed to create entrypoint: %w", err)
1✔
113
        }
1✔
114
        defer f.Close()
1✔
115
        if err := indexTemplate.Option("missingkey=error").Execute(f, indexConfig{
1✔
116
                URL:   utils.GetApiUrl("/functions/v1/" + slug),
1✔
117
                Token: utils.Config.Auth.AnonKey.Value,
1✔
118
        }); err != nil {
1✔
119
                return errors.Errorf("failed to write entrypoint: %w", err)
×
120
        }
×
121
        return nil
1✔
122
}
123

124
func appendConfigFile(slug string, fsys afero.Fs) error {
1✔
125
        if _, exists := utils.Config.Functions[slug]; exists {
1✔
126
                fmt.Fprintf(os.Stderr, "[functions.%s] is already declared in %s\n", slug, utils.Bold(utils.ConfigPath))
×
127
                return nil
×
128
        }
×
129
        f, err := fsys.OpenFile(utils.ConfigPath, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644)
1✔
130
        if err != nil {
1✔
131
                return errors.Errorf("failed to append config: %w", err)
×
132
        }
×
133
        defer f.Close()
1✔
134
        if err := configTemplate.Option("missingkey=error").Execute(f, slug); err != nil {
1✔
135
                return errors.Errorf("failed to append template: %w", err)
×
136
        }
×
137
        return nil
1✔
138
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc