github.com/supabase/cli@v1.168.1/internal/projects/create/create.go (about) 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/credentials" 14 "github.com/supabase/cli/internal/utils/flags" 15 "github.com/supabase/cli/pkg/api" 16 ) 17 18 func Run(ctx context.Context, params api.V1CreateProjectBody, fsys afero.Fs) error { 19 if err := promptMissingParams(ctx, ¶ms); err != nil { 20 return err 21 } 22 23 resp, err := utils.GetSupabase().CreateProjectWithResponse(ctx, params) 24 if err != nil { 25 return errors.Errorf("failed to create project: %w", err) 26 } 27 if resp.JSON201 == nil { 28 return errors.New("Unexpected error creating project: " + string(resp.Body)) 29 } 30 31 flags.ProjectRef = resp.JSON201.Id 32 viper.Set("DB_PASSWORD", params.DbPass) 33 if err := credentials.Set(flags.ProjectRef, params.DbPass); err != nil { 34 fmt.Fprintln(os.Stderr, "Failed to save database password:", err) 35 } 36 37 projectUrl := fmt.Sprintf("%s/project/%s", utils.GetSupabaseDashboardURL(), resp.JSON201.Id) 38 fmt.Printf("Created a new project %s at %s\n", utils.Aqua(resp.JSON201.Name), utils.Bold(projectUrl)) 39 return nil 40 } 41 42 func printKeyValue(key, value string) string { 43 indent := 20 - len(key) 44 spaces := strings.Repeat(" ", indent) 45 return key + ":" + spaces + value 46 } 47 48 func promptMissingParams(ctx context.Context, body *api.V1CreateProjectBody) error { 49 var err error 50 if len(body.Name) == 0 { 51 if body.Name, err = promptProjectName(); err != nil { 52 return err 53 } 54 } else { 55 fmt.Fprintln(os.Stderr, printKeyValue("Creating project", body.Name)) 56 } 57 if len(body.OrganizationId) == 0 { 58 if body.OrganizationId, err = promptOrgId(ctx); err != nil { 59 return err 60 } 61 fmt.Fprintln(os.Stderr, printKeyValue("Selected org-id", body.OrganizationId)) 62 } 63 if len(body.Region) == 0 { 64 if body.Region, err = promptProjectRegion(ctx); err != nil { 65 return err 66 } 67 fmt.Fprintln(os.Stderr, printKeyValue("Selected region", string(body.Region))) 68 } 69 if len(body.DbPass) == 0 { 70 body.DbPass = flags.PromptPassword(os.Stdin) 71 } 72 return nil 73 } 74 75 func promptProjectName() (string, error) { 76 title := "Enter your project name: " 77 if name := utils.NewConsole().PromptText(title); len(name) > 0 { 78 return name, nil 79 } 80 return "", errors.New("project name cannot be empty") 81 } 82 83 func promptOrgId(ctx context.Context) (string, error) { 84 title := "Which organisation do you want to create the project for?" 85 resp, err := utils.GetSupabase().GetOrganizationsWithResponse(ctx) 86 if err != nil { 87 return "", err 88 } 89 if resp.JSON200 == nil { 90 return "", errors.New("Unexpected error retrieving organizations: " + string(resp.Body)) 91 } 92 items := make([]utils.PromptItem, len(*resp.JSON200)) 93 for i, org := range *resp.JSON200 { 94 items[i] = utils.PromptItem{Summary: org.Name, Details: org.Id} 95 } 96 choice, err := utils.PromptChoice(ctx, title, items) 97 if err != nil { 98 return "", err 99 } 100 return choice.Details, nil 101 } 102 103 func promptProjectRegion(ctx context.Context) (api.V1CreateProjectBodyRegion, error) { 104 title := "Which region do you want to host the project in?" 105 items := make([]utils.PromptItem, len(utils.RegionMap)) 106 i := 0 107 for k, v := range utils.RegionMap { 108 items[i] = utils.PromptItem{Summary: k, Details: v} 109 i++ 110 } 111 choice, err := utils.PromptChoice(ctx, title, items) 112 if err != nil { 113 return "", err 114 } 115 return api.V1CreateProjectBodyRegion(choice.Summary), nil 116 }