From b71acec3565767c21d53eb211cdbf846339dea89 Mon Sep 17 00:00:00 2001 From: Bobbie Soedirgo Date: Tue, 28 Jun 2022 23:49:05 +0800 Subject: [PATCH 1/3] chore: bump pg-meta --- internal/utils/misc.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/utils/misc.go b/internal/utils/misc.go index 54c1d1cd6f..23634b1ddd 100644 --- a/internal/utils/misc.go +++ b/internal/utils/misc.go @@ -33,7 +33,7 @@ const ( InbucketImage = "inbucket/inbucket:stable" PostgrestImage = "postgrest/postgrest:v9.0.0.20220211" DifferImage = "supabase/pgadmin-schema-diff:cli-0.0.4" - PgmetaImage = "supabase/postgres-meta:v0.33.2" + PgmetaImage = "supabase/postgres-meta:v0.40.0" // TODO: Hardcode version once provided upstream. StudioImage = "supabase/studio:latest" DenoRelayImage = "supabase/deno-relay:v1.2.0" From 69693bb72dd1e41ba8096420fac260c1af0c8547 Mon Sep 17 00:00:00 2001 From: Bobbie Soedirgo Date: Wed, 29 Jun 2022 00:11:57 +0800 Subject: [PATCH 2/3] chore: go fmt --- cmd/projects.go | 6 +++--- internal/projects/create/create.go | 6 ++++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/cmd/projects.go b/cmd/projects.go index d8bed4f61d..8c04147611 100644 --- a/cmd/projects.go +++ b/cmd/projects.go @@ -13,9 +13,9 @@ var ( } projectsCreateCmd = &cobra.Command{ - Use: "create", - Short: "Create a new project.", - Args: cobra.ExactArgs(1), + Use: "create", + Short: "Create a new project.", + Args: cobra.ExactArgs(1), Example: `supabase projects create my-project --org-id 12345 --db-password ******** --region us-east-1`, RunE: func(cmd *cobra.Command, args []string) error { name := args[0] diff --git a/internal/projects/create/create.go b/internal/projects/create/create.go index d325f5b60f..7ea0425767 100644 --- a/internal/projects/create/create.go +++ b/internal/projects/create/create.go @@ -18,7 +18,8 @@ func Run(name string, orgId uint, dbPassword string, region string, plan string) } // TODO: Prompt missing args. - {} + { + } // POST request, check errors var project struct { @@ -71,7 +72,8 @@ func Run(name string, orgId uint, dbPassword string, region string, plan string) } // TODO: Poll until PostgREST is reachable. - {} + { + } fmt.Printf(`Created a new project %s at %s\n`, utils.Aqua(project.Name), utils.Aqua("https://app.supabase.com/project/"+project.Ref)) return nil From a0b78a7333fafbdd9ee2a24998ad104f1e3411c9 Mon Sep 17 00:00:00 2001 From: Bobbie Soedirgo Date: Wed, 29 Jun 2022 00:12:46 +0800 Subject: [PATCH 3/3] feat(gen/types/typescript): add command --- cmd/gen.go | 41 +++++ internal/gen/types/typescript/typescript.go | 193 ++++++++++++++++++++ 2 files changed, 234 insertions(+) create mode 100644 cmd/gen.go create mode 100644 internal/gen/types/typescript/typescript.go diff --git a/cmd/gen.go b/cmd/gen.go new file mode 100644 index 0000000000..f2354a14cc --- /dev/null +++ b/cmd/gen.go @@ -0,0 +1,41 @@ +package cmd + +import ( + "github.com/spf13/cobra" + "github.com/supabase/cli/internal/gen/types/typescript" +) + +var ( + genCmd = &cobra.Command{ + Use: "gen", + } + + genTypesCmd = &cobra.Command{ + Use: "types", + } + + genTypesTypescriptCmd = &cobra.Command{ + Use: "typescript", + Short: "Generate types for TypeScript. Must either specify --local, or --db-url, or be in a linked project (with supabase link)", + RunE: func(cmd *cobra.Command, args []string) error { + isLocal, err := cmd.Flags().GetBool("local") + if err != nil { + return err + } + dbUrl, err := cmd.Flags().GetString("db-url") + if err != nil { + return err + } + + return typescript.Run(isLocal, dbUrl) + }, + } +) + +func init() { + genTypesTypescriptCmd.Flags().Bool("local", false, "Generate types from the local dev database") + genTypesTypescriptCmd.Flags().String("db-url", "", "Generate types from a database url") + genTypesCmd.AddCommand(genTypesTypescriptCmd) + genCmd.AddCommand(genTypesCmd) + rootCmd.AddCommand(genCmd) +} diff --git a/internal/gen/types/typescript/typescript.go b/internal/gen/types/typescript/typescript.go new file mode 100644 index 0000000000..9858120c65 --- /dev/null +++ b/internal/gen/types/typescript/typescript.go @@ -0,0 +1,193 @@ +package typescript + +import ( + "bytes" + "context" + "encoding/json" + "errors" + "fmt" + "io" + "net/http" + "net/url" + "os" + + "github.com/docker/docker/api/types" + "github.com/docker/docker/api/types/container" + "github.com/docker/docker/pkg/stdcopy" + "github.com/supabase/cli/internal/utils" +) + +var ctx = context.Background() + +func Run(isLocal bool, dbUrl string) error { + if isLocal && dbUrl != "" { + return errors.New("Cannot specify both --local and --db-url") + } + + if isLocal { + if err := utils.AssertSupabaseStartIsRunning(); err != nil { + return err + } + + exec, err := utils.Docker.ContainerExecCreate( + ctx, + utils.PgmetaId, + types.ExecConfig{ + Env: []string{ + "PG_META_DB_HOST=" + utils.DbId, + }, + Cmd: []string{ + "node", "bin/src/server/app.js", "gen", "types", "typescript", "--exclude-schemas", "auth,extensions,graphql,graphql_public,realtime,storage,supabase_functions,supabase_migrations", + }, + AttachStderr: true, + AttachStdout: true, + }, + ) + if err != nil { + return err + } + + resp, err := utils.Docker.ContainerExecAttach(ctx, exec.ID, types.ExecStartCheck{}) + if err != nil { + return err + } + var genBuf, errBuf bytes.Buffer + if _, err := stdcopy.StdCopy(&genBuf, &errBuf, resp.Reader); err != nil { + return err + } + if errBuf.Len() > 0 { + return errors.New(errBuf.String()) + } + + fmt.Print(genBuf.String()) + return nil + } + + // determine db url if in a linked project + if dbUrl == "" { + var accessToken string + var projectRef string + { + if err := utils.AssertSupabaseCliIsSetUp(); err != nil { + return err + } + _accessToken, err := utils.LoadAccessToken() + if err != nil { + return err + } + if err := utils.AssertIsLinked(); err != nil { + return err + } + projectRefBytes, err := os.ReadFile("supabase/.temp/project-ref") + if err != nil { + return err + } + _projectRef := string(projectRefBytes) + + accessToken = _accessToken + projectRef = _projectRef + } + + req, err := http.NewRequest("GET", "https://api.supabase.io/v1/projects", nil) + if err != nil { + return err + } + req.Header.Add("Authorization", "Bearer "+string(accessToken)) + resp, err := http.DefaultClient.Do(req) + if err != nil { + return err + } + defer resp.Body.Close() + + if resp.StatusCode != http.StatusOK { + body, err := io.ReadAll(resp.Body) + if err != nil { + return fmt.Errorf("Unexpected error retrieving projects: %w", err) + } + + return errors.New("Unexpected error retrieving projects: " + string(body)) + } + + body, err := io.ReadAll(resp.Body) + if err != nil { + return err + } + + var projects []struct { + Ref string `json:"ref"` + DbPass string `json:"db_pass"` + } + if err := json.Unmarshal(body, &projects); err != nil { + return err + } + + var dbPass string + for _, project := range projects { + if project.Ref == projectRef { + dbPass = project.DbPass + } + } + if dbPass == "" { + return errors.New("Could not find the linked project for the logged-in user. Try running supabase link again") + } + + dbUrl = "postgresql://postgres:" + url.QueryEscape(dbPass) + "@db." + projectRef + ".supabase.co:5432/postgres" + } + + // run typegen on the dbUrl + { + if err := utils.AssertDockerIsRunning(); err != nil { + return err + } + + defer utils.DockerRemoveAll() + + if _, _, err := utils.Docker.ImageInspectWithRaw(ctx, "docker.io/"+utils.PgmetaImage); err != nil { + fmt.Fprintln(os.Stderr, "Downloading type generator...") + out, err := utils.Docker.ImagePull( + ctx, + "docker.io/"+utils.PgmetaImage, + types.ImagePullOptions{}, + ) + if err != nil { + return err + } + if _, err := io.ReadAll(out); err != nil { + return err + } + if err := out.Close(); err != nil { + return err + } + fmt.Fprintln(os.Stderr, "Done downloading type generator") + } + + out, err := utils.DockerRun( + ctx, + "supabase_gen_types_typescript", + &container.Config{ + Image: utils.PgmetaImage, + Env: []string{ + "PG_META_DB_URL=" + dbUrl, + }, + Cmd: []string{ + "node", "bin/src/server/app.js", "gen", "types", "typescript", "--exclude-schemas", "auth,extensions,graphql,graphql_public,realtime,storage,supabase_functions,supabase_migrations", + }, + }, + &container.HostConfig{}, + ) + if err != nil { + return err + } + var genBuf, errBuf bytes.Buffer + if _, err := stdcopy.StdCopy(&genBuf, &errBuf, out); err != nil { + return err + } + if errBuf.Len() > 0 { + return errors.New(errBuf.String()) + } + + fmt.Print(genBuf.String()) + } + + return nil +}