Skip to content

Commit

Permalink
feat: add support for multiple output formats (#2674)
Browse files Browse the repository at this point in the history
  • Loading branch information
djhi authored Sep 13, 2024
1 parent e55fef9 commit 54fa898
Show file tree
Hide file tree
Showing 7 changed files with 76 additions and 39 deletions.
1 change: 1 addition & 0 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,7 @@ func init() {
flags.String("workdir", "", "path to a Supabase project directory")
flags.Bool("experimental", false, "enable experimental features")
flags.String("network-id", "", "use the specified docker network instead of a generated one")
flags.Var(&utils.OutputFormat, "output", "output format of status variables")
flags.Var(&utils.DNSResolver, "dns-resolver", "lookup domain names using the specified resolver")
flags.BoolVar(&createTicket, "create-ticket", false, "create a support ticket for any CLI error")
cobra.CheckErr(viper.BindPFlags(flags))
Expand Down
17 changes: 6 additions & 11 deletions cmd/sso.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,6 @@ var (
ssoDomains []string
ssoAddDomains []string
ssoRemoveDomains []string
ssoOutput = utils.EnumFlag{
Allowed: utils.OutputDefaultAllowed,
Value: utils.OutputPretty,
}

ssoAddCmd = &cobra.Command{
Use: "add",
Expand All @@ -47,7 +43,7 @@ var (
return create.Run(cmd.Context(), create.RunParams{
ProjectRef: flags.ProjectRef,
Type: ssoProviderType.String(),
Format: ssoOutput.Value,
Format: utils.OutputFormat.Value,
MetadataFile: ssoMetadataFile,
MetadataURL: ssoMetadataURL,
SkipURLValidation: ssoSkipURLValidation,
Expand All @@ -68,7 +64,7 @@ var (
return errors.Errorf("identity provider ID %q is not a UUID", args[0])
}

return remove.Run(cmd.Context(), flags.ProjectRef, args[0], ssoOutput.Value)
return remove.Run(cmd.Context(), flags.ProjectRef, args[0], utils.OutputFormat.Value)
},
}

Expand All @@ -86,7 +82,7 @@ var (
return update.Run(cmd.Context(), update.RunParams{
ProjectRef: flags.ProjectRef,
ProviderID: args[0],
Format: ssoOutput.Value,
Format: utils.OutputFormat.Value,

MetadataFile: ssoMetadataFile,
MetadataURL: ssoMetadataURL,
Expand All @@ -110,7 +106,7 @@ var (
return errors.Errorf("identity provider ID %q is not a UUID", args[0])
}

format := ssoOutput.Value
format := utils.OutputFormat.Value
if ssoMetadata {
format = utils.OutputMetadata
}
Expand All @@ -125,7 +121,7 @@ var (
Long: "List all connections to a SSO identity provider to your Supabase project.",
Example: ` supabase sso list --project-ref mwjylndxudmiehsxhmmz`,
RunE: func(cmd *cobra.Command, args []string) error {
return list.Run(cmd.Context(), flags.ProjectRef, ssoOutput.Value)
return list.Run(cmd.Context(), flags.ProjectRef, utils.OutputFormat.Value)
},
}

Expand All @@ -135,15 +131,14 @@ var (
Long: "Returns all of the important SSO information necessary for your project to be registered with a SAML 2.0 compatible identity provider.",
Example: ` supabase sso info --project-ref mwjylndxudmiehsxhmmz`,
RunE: func(cmd *cobra.Command, args []string) error {
return info.Run(cmd.Context(), flags.ProjectRef, ssoOutput.Value)
return info.Run(cmd.Context(), flags.ProjectRef, utils.OutputFormat.Value)
},
}
)

func init() {
persistentFlags := ssoCmd.PersistentFlags()
persistentFlags.StringVar(&flags.ProjectRef, "project-ref", "", "Project ref of the Supabase project.")
persistentFlags.VarP(&ssoOutput, "output", "o", "Output format")
ssoAddFlags := ssoAddCmd.Flags()
ssoAddFlags.VarP(&ssoProviderType, "type", "t", "Type of identity provider (according to supported protocol).")
ssoAddFlags.StringSliceVar(&ssoDomains, "domains", nil, "Comma separated list of email domains to associate with the added identity provider.")
Expand Down
1 change: 1 addition & 0 deletions cmd/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ var (
Allowed: append([]string{utils.OutputEnv}, utils.OutputDefaultAllowed...),
Value: utils.OutputPretty,
}

statusCmd = &cobra.Command{
GroupID: groupLocalDev,
Use: "status",
Expand Down
13 changes: 9 additions & 4 deletions internal/projects/apiKeys/api_keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package apiKeys
import (
"context"
"fmt"
"os"
"strings"

"github.com/go-errors/errors"
Expand All @@ -18,14 +19,18 @@ func Run(ctx context.Context, projectRef string, fsys afero.Fs) error {
return err
}

table := `|NAME|KEY VALUE|
if utils.OutputFormat.Value == utils.OutputPretty {
table := `|NAME|KEY VALUE|
|-|-|
`
for _, entry := range keys {
table += fmt.Sprintf("|`%s`|`%s`|\n", strings.ReplaceAll(entry.Name, "|", "\\|"), entry.ApiKey)
for _, entry := range keys {
table += fmt.Sprintf("|`%s`|`%s`|\n", strings.ReplaceAll(entry.Name, "|", "\\|"), entry.ApiKey)
}

return list.RenderTable(table)
}

return list.RenderTable(table)
return utils.EncodeOutput(utils.OutputFormat.Value, os.Stdout, keys)
}

func RunGetApiKeys(ctx context.Context, projectRef string) ([]api.ApiKeyResponse, error) {
Expand Down
8 changes: 6 additions & 2 deletions internal/projects/create/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,12 @@ func Run(ctx context.Context, params api.V1CreateProjectBody, fsys afero.Fs) err
}

projectUrl := fmt.Sprintf("%s/project/%s", utils.GetSupabaseDashboardURL(), resp.JSON201.Id)
fmt.Printf("Created a new project %s at %s\n", utils.Aqua(resp.JSON201.Name), utils.Bold(projectUrl))
return nil
fmt.Fprintf(os.Stderr, "Created a new project %s at %s\n", utils.Aqua(resp.JSON201.Name), utils.Bold(projectUrl))
if utils.OutputFormat.Value == utils.OutputPretty {
return nil
}

return utils.EncodeOutput(utils.OutputFormat.Value, os.Stdout, resp.JSON201)
}

func printKeyValue(key, value string) string {
Expand Down
70 changes: 48 additions & 22 deletions internal/projects/list/list.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,20 @@ import (
"fmt"
"os"
"strings"
"time"

"github.com/go-errors/errors"
"github.com/spf13/afero"
"github.com/supabase/cli/internal/migration/list"
"github.com/supabase/cli/internal/utils"
"github.com/supabase/cli/internal/utils/flags"
"github.com/supabase/cli/pkg/api"
)

type linkedProject struct {
api.V1ProjectResponse `yaml:",inline"`
Linked bool `json:"linked"`
}

func Run(ctx context.Context, fsys afero.Fs) error {
resp, err := utils.GetSupabase().V1ListAllProjectsWithResponse(ctx)
if err != nil {
Expand All @@ -29,30 +34,51 @@ func Run(ctx context.Context, fsys afero.Fs) error {
fmt.Fprintln(os.Stderr, err)
}

table := `LINKED|ORG ID|REFERENCE ID|NAME|REGION|CREATED AT (UTC)
var projects []linkedProject
for _, project := range *resp.JSON200 {
projects = append(projects, linkedProject{
V1ProjectResponse: project,
Linked: project.Id == projectRef,
})
}

if utils.OutputFormat.Value == utils.OutputPretty {
table := `LINKED|ORG ID|REFERENCE ID|NAME|REGION|CREATED AT (UTC)
|-|-|-|-|-|-|
`
for _, project := range *resp.JSON200 {
if t, err := time.Parse(time.RFC3339, project.CreatedAt); err == nil {
project.CreatedAt = t.UTC().Format("2006-01-02 15:04:05")
}
if region, ok := utils.RegionMap[project.Region]; ok {
project.Region = region
for _, project := range projects {
table += fmt.Sprintf(
"|`%s`|`%s`|`%s`|`%s`|`%s`|`%s`|\n",
formatBullet(project.Linked),
project.OrganizationId,
project.Id,
strings.ReplaceAll(project.Name, "|", "\\|"),
formatRegion(project.Region),
utils.FormatTimestamp(project.CreatedAt),
)
}
linked := " "
if project.Id == projectRef {
linked = " ●"
}
table += fmt.Sprintf(
"|`%s`|`%s`|`%s`|`%s`|`%s`|`%s`|\n",
linked,
project.OrganizationId,
project.Id,
strings.ReplaceAll(project.Name, "|", "\\|"),
project.Region,
utils.FormatTimestamp(project.CreatedAt),
)
return list.RenderTable(table)
} else if utils.OutputFormat.Value == utils.OutputToml {
return utils.EncodeOutput(utils.OutputFormat.Value, os.Stdout, struct {
Projects []linkedProject `toml:"projects"`
}{
Projects: projects,
})
}

return list.RenderTable(table)
return utils.EncodeOutput(utils.OutputFormat.Value, os.Stdout, projects)
}

func formatBullet(value bool) string {
if value {
return " ●"
}
return " "
}

func formatRegion(region string) string {
if readable, ok := utils.RegionMap[region]; ok {
return readable
}
return region
}
5 changes: 5 additions & 0 deletions internal/utils/output.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,11 @@ var (
OutputToml,
OutputYaml,
}

OutputFormat = EnumFlag{
Allowed: OutputDefaultAllowed,
Value: OutputPretty,
}
)

func EncodeOutput(format string, w io.Writer, value any) error {
Expand Down

0 comments on commit 54fa898

Please sign in to comment.