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

supabase / cli / 19494768794

19 Nov 2025 08:27AM UTC coverage: 55.051% (-0.03%) from 55.076%
19494768794

Pull #4448

github

web-flow
Merge 8fcb18af5 into 10cdd70c7
Pull Request #4448: chore: sync API types from infrastructure

4 of 10 new or added lines in 4 files covered. (40.0%)

5 existing lines in 1 file now uncovered.

6507 of 11820 relevant lines covered (55.05%)

6.28 hits per line

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

43.0
/internal/projects/create/create.go
1
package create
2

3
import (
4
        "context"
5
        "fmt"
6
        "os"
7
        "strings"
8

9
        "github.com/go-errors/errors"
10
        "github.com/spf13/afero"
11
        "github.com/spf13/viper"
12
        "github.com/supabase/cli/internal/utils"
13
        "github.com/supabase/cli/internal/utils/flags"
14
        "github.com/supabase/cli/pkg/api"
15
)
16

17
func Run(ctx context.Context, params api.V1CreateProjectBody, fsys afero.Fs) error {
5✔
18
        if err := promptMissingParams(ctx, &params); err != nil {
5✔
19
                return err
×
20
        }
×
21

22
        resp, err := utils.GetSupabase().V1CreateAProjectWithResponse(ctx, params)
5✔
23
        if err != nil {
7✔
24
                return errors.Errorf("failed to create project: %w", err)
2✔
25
        }
2✔
26
        if resp.JSON201 == nil {
5✔
27
                return errors.New("Unexpected error creating project: " + string(resp.Body))
2✔
28
        }
2✔
29

30
        flags.ProjectRef = resp.JSON201.Id
1✔
31
        viper.Set("DB_PASSWORD", params.DbPass)
1✔
32

1✔
33
        projectUrl := fmt.Sprintf("%s/project/%s", utils.GetSupabaseDashboardURL(), resp.JSON201.Id)
1✔
34
        fmt.Fprintf(os.Stderr, "Created a new project at %s\n", utils.Bold(projectUrl))
1✔
35
        if utils.OutputFormat.Value == utils.OutputPretty {
2✔
36
                table := `|ORG ID|REFERENCE ID|NAME|REGION|CREATED AT (UTC)|
1✔
37
|-|-|-|-|-|
1✔
38
`
1✔
39
                table += fmt.Sprintf(
1✔
40
                        "|`%s`|`%s`|`%s`|`%s`|`%s`|\n",
1✔
41
                        resp.JSON201.OrganizationSlug,
1✔
42
                        resp.JSON201.Id,
1✔
43
                        strings.ReplaceAll(resp.JSON201.Name, "|", "\\|"),
1✔
44
                        utils.FormatRegion(resp.JSON201.Region),
1✔
45
                        utils.FormatTimestamp(resp.JSON201.CreatedAt),
1✔
46
                )
1✔
47
                return utils.RenderTable(table)
1✔
48
        }
1✔
49
        return utils.EncodeOutput(utils.OutputFormat.Value, os.Stdout, resp.JSON201)
×
50
}
51

52
func printKeyValue(key, value string) string {
5✔
53
        indent := 20 - len(key)
5✔
54
        spaces := strings.Repeat(" ", indent)
5✔
55
        return key + ":" + spaces + value
5✔
56
}
5✔
57

58
func promptMissingParams(ctx context.Context, body *api.V1CreateProjectBody) error {
5✔
59
        var err error
5✔
60
        if len(body.Name) == 0 {
5✔
61
                if body.Name, err = promptProjectName(ctx); err != nil {
×
62
                        return err
×
63
                }
×
64
        } else {
5✔
65
                fmt.Fprintln(os.Stderr, printKeyValue("Creating project", body.Name))
5✔
66
        }
5✔
67
        if len(body.OrganizationSlug) == 0 {
5✔
NEW
68
                if body.OrganizationSlug, err = promptOrgId(ctx); err != nil {
×
69
                        return err
×
70
                }
×
NEW
71
                fmt.Fprintln(os.Stderr, printKeyValue("Selected org-id", body.OrganizationSlug))
×
72
        }
73
        if body.Region == nil || len(*body.Region) == 0 {
5✔
74
                region, err := promptProjectRegion(ctx)
×
75
                if err != nil {
×
76
                        return err
×
77
                }
×
78
                body.Region = &region
×
79
                fmt.Fprintln(os.Stderr, printKeyValue("Selected region", string(region)))
×
80
        }
81
        if len(body.DbPass) == 0 {
5✔
82
                body.DbPass = flags.PromptPassword(os.Stdin)
×
83
        }
×
84
        return nil
5✔
85
}
86

87
func promptProjectName(ctx context.Context) (string, error) {
×
88
        title := "Enter your project name: "
×
89
        if name, err := utils.NewConsole().PromptText(ctx, title); err != nil {
×
90
                return "", err
×
91
        } else if len(name) > 0 {
×
92
                return name, nil
×
93
        }
×
94
        return "", errors.New("project name cannot be empty")
×
95
}
96

97
func promptOrgId(ctx context.Context) (string, error) {
×
98
        title := "Which organisation do you want to create the project for?"
×
99
        resp, err := utils.GetSupabase().V1ListAllOrganizationsWithResponse(ctx)
×
100
        if err != nil {
×
101
                return "", err
×
102
        }
×
103
        if resp.JSON200 == nil {
×
104
                return "", errors.New("Unexpected error retrieving organizations: " + string(resp.Body))
×
105
        }
×
106
        items := make([]utils.PromptItem, len(*resp.JSON200))
×
107
        for i, org := range *resp.JSON200 {
×
108
                items[i] = utils.PromptItem{Summary: org.Name, Details: org.Id}
×
109
        }
×
110
        choice, err := utils.PromptChoice(ctx, title, items)
×
111
        if err != nil {
×
112
                return "", err
×
113
        }
×
114
        return choice.Details, nil
×
115
}
116

117
func promptProjectRegion(ctx context.Context) (api.V1CreateProjectBodyRegion, error) {
×
118
        title := "Which region do you want to host the project in?"
×
119
        items := make([]utils.PromptItem, len(utils.RegionMap))
×
120
        i := 0
×
121
        for k, v := range utils.RegionMap {
×
122
                items[i] = utils.PromptItem{Summary: k, Details: v}
×
123
                i++
×
124
        }
×
125
        choice, err := utils.PromptChoice(ctx, title, items)
×
126
        if err != nil {
×
127
                return "", err
×
128
        }
×
129
        return api.V1CreateProjectBodyRegion(choice.Summary), nil
×
130
}
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