From d6c73eca00b1e6b7e071969a2565cbce8cbe27f7 Mon Sep 17 00:00:00 2001 From: mikkelam Date: Tue, 19 May 2026 18:38:12 +0200 Subject: [PATCH] fix(cli-go): respect explicit --db-url in gen types without requiring local stack --- apps/cli-go/cmd/gen.go | 5 +-- apps/cli-go/internal/gen/types/types.go | 4 +-- apps/cli-go/internal/gen/types/types_test.go | 35 +++++++++++++++----- 3 files changed, 32 insertions(+), 12 deletions(-) diff --git a/apps/cli-go/cmd/gen.go b/apps/cli-go/cmd/gen.go index c9d2510f5e..5b3a3efa33 100644 --- a/apps/cli-go/cmd/gen.go +++ b/apps/cli-go/cmd/gen.go @@ -88,7 +88,8 @@ var ( }, RunE: func(cmd *cobra.Command, args []string) error { ctx := cmd.Context() - if flags.DbConfig.Host == "" { + dbURLChanged := cmd.Flags().Changed("db-url") + if flags.DbConfig.Host == "" && !dbURLChanged { // If no flag is specified, prompt for project id. if err := flags.ParseProjectRef(ctx, afero.NewMemMapFs()); errors.Is(err, utils.ErrNotLinked) { return errors.New("Must specify one of --local, --linked, --project-id, or --db-url") @@ -96,7 +97,7 @@ var ( return err } } - return types.Run(ctx, flags.ProjectRef, flags.DbConfig, lang.Value, schema, postgrestV9Compat, swiftAccessControl.Value, queryTimeout, afero.NewOsFs()) + return types.Run(ctx, flags.ProjectRef, flags.DbConfig, lang.Value, schema, postgrestV9Compat, swiftAccessControl.Value, queryTimeout, dbURLChanged, afero.NewOsFs()) }, Example: ` supabase gen types --local supabase gen types --linked --lang=go diff --git a/apps/cli-go/internal/gen/types/types.go b/apps/cli-go/internal/gen/types/types.go index c12a7b58eb..28f8533719 100644 --- a/apps/cli-go/internal/gen/types/types.go +++ b/apps/cli-go/internal/gen/types/types.go @@ -33,7 +33,7 @@ const ( SwiftInternalAccessControl = "internal" ) -func Run(ctx context.Context, projectId string, dbConfig pgconn.Config, lang string, schemas []string, postgrestV9Compat bool, swiftAccessControl string, queryTimeout time.Duration, fsys afero.Fs, options ...func(*pgx.ConnConfig)) error { +func Run(ctx context.Context, projectId string, dbConfig pgconn.Config, lang string, schemas []string, postgrestV9Compat bool, swiftAccessControl string, queryTimeout time.Duration, directDbURL bool, fsys afero.Fs, options ...func(*pgx.ConnConfig)) error { originalURL := utils.ToPostgresURL(dbConfig) // Add default schemas if --schema flag is not specified if len(schemas) == 0 { @@ -61,7 +61,7 @@ func Run(ctx context.Context, projectId string, dbConfig pgconn.Config, lang str } hostConfig := container.HostConfig{} - if utils.IsLocalDatabase(dbConfig) { + if utils.IsLocalDatabase(dbConfig) && !directDbURL { if err := utils.AssertSupabaseDbIsRunning(); err != nil { return err } diff --git a/apps/cli-go/internal/gen/types/types_test.go b/apps/cli-go/internal/gen/types/types_test.go index e7134b1820..a473c24d56 100644 --- a/apps/cli-go/internal/gen/types/types_test.go +++ b/apps/cli-go/internal/gen/types/types_test.go @@ -49,7 +49,7 @@ func TestGenLocalCommand(t *testing.T) { conn := pgtest.NewConn() defer conn.Close(t) // Run test - assert.NoError(t, Run(context.Background(), "", dbConfig, LangTypescript, []string{}, true, "", time.Second, fsys, conn.Intercept)) + assert.NoError(t, Run(context.Background(), "", dbConfig, LangTypescript, []string{}, true, "", time.Second, false, fsys, conn.Intercept)) // Validate api assert.Empty(t, apitest.ListUnmatchedRequests()) }) @@ -64,7 +64,7 @@ func TestGenLocalCommand(t *testing.T) { Get("/v" + utils.Docker.ClientVersion() + "/containers/" + utils.DbId). Reply(http.StatusServiceUnavailable) // Run test - assert.Error(t, Run(context.Background(), "", dbConfig, LangTypescript, []string{}, true, "", time.Second, fsys)) + assert.Error(t, Run(context.Background(), "", dbConfig, LangTypescript, []string{}, true, "", time.Second, false, fsys)) // Validate api assert.Empty(t, apitest.ListUnmatchedRequests()) }) @@ -84,7 +84,7 @@ func TestGenLocalCommand(t *testing.T) { Get("/v" + utils.Docker.ClientVersion() + "/images"). Reply(http.StatusServiceUnavailable) // Run test - assert.Error(t, Run(context.Background(), "", dbConfig, LangTypescript, []string{}, true, "", time.Second, fsys)) + assert.Error(t, Run(context.Background(), "", dbConfig, LangTypescript, []string{}, true, "", time.Second, false, fsys)) // Validate api assert.Empty(t, apitest.ListUnmatchedRequests()) }) @@ -107,7 +107,26 @@ func TestGenLocalCommand(t *testing.T) { conn := pgtest.NewConn() defer conn.Close(t) // Run test - assert.NoError(t, Run(context.Background(), "", dbConfig, LangSwift, []string{}, true, SwiftInternalAccessControl, time.Second, fsys, conn.Intercept)) + assert.NoError(t, Run(context.Background(), "", dbConfig, LangSwift, []string{}, true, SwiftInternalAccessControl, time.Second, false, fsys, conn.Intercept)) + // Validate api + assert.Empty(t, apitest.ListUnmatchedRequests()) + }) + + t.Run("skips local stack check for explicit db-url on localhost", func(t *testing.T) { + const containerId = "test-pgmeta" + imageUrl := utils.GetRegistryImageUrl(utils.Config.Studio.PgmetaImage) + // Setup in-memory fs + fsys := afero.NewMemMapFs() + // Setup mock docker + require.NoError(t, apitest.MockDocker(utils.Docker)) + defer gock.OffAll() + apitest.MockDockerStart(utils.Docker, imageUrl, containerId) + require.NoError(t, apitest.MockDockerLogs(utils.Docker, containerId, "hello world\n")) + // Setup mock postgres + conn := pgtest.NewConn() + defer conn.Close(t) + // Run test + assert.NoError(t, Run(context.Background(), "", dbConfig, LangTypescript, []string{}, true, "", time.Second, true, fsys, conn.Intercept)) // Validate api assert.Empty(t, apitest.ListUnmatchedRequests()) }) @@ -130,7 +149,7 @@ func TestGenLinkedCommand(t *testing.T) { Reply(200). JSON(api.TypescriptResponse{Types: ""}) // Run test - assert.NoError(t, Run(context.Background(), projectId, pgconn.Config{}, LangTypescript, []string{}, true, "", time.Second, fsys)) + assert.NoError(t, Run(context.Background(), projectId, pgconn.Config{}, LangTypescript, []string{}, true, "", time.Second, false, fsys)) // Validate api assert.Empty(t, apitest.ListUnmatchedRequests()) }) @@ -145,7 +164,7 @@ func TestGenLinkedCommand(t *testing.T) { Get("/v1/projects/" + projectId + "/types/typescript"). ReplyError(errNetwork) // Run test - err := Run(context.Background(), projectId, pgconn.Config{}, LangTypescript, []string{}, true, "", time.Second, fsys) + err := Run(context.Background(), projectId, pgconn.Config{}, LangTypescript, []string{}, true, "", time.Second, false, fsys) // Validate api assert.ErrorIs(t, err, errNetwork) assert.Empty(t, apitest.ListUnmatchedRequests()) @@ -160,7 +179,7 @@ func TestGenLinkedCommand(t *testing.T) { Get("/v1/projects/" + projectId + "/types/typescript"). Reply(http.StatusServiceUnavailable) // Run test - assert.Error(t, Run(context.Background(), projectId, pgconn.Config{}, LangTypescript, []string{}, true, "", time.Second, fsys)) + assert.Error(t, Run(context.Background(), projectId, pgconn.Config{}, LangTypescript, []string{}, true, "", time.Second, false, fsys)) }) } @@ -185,7 +204,7 @@ func TestGenRemoteCommand(t *testing.T) { conn := pgtest.NewConn() defer conn.Close(t) // Run test - assert.NoError(t, Run(context.Background(), "", dbConfig, LangTypescript, []string{"public"}, true, "", time.Second, afero.NewMemMapFs(), conn.Intercept)) + assert.NoError(t, Run(context.Background(), "", dbConfig, LangTypescript, []string{"public"}, true, "", time.Second, false, afero.NewMemMapFs(), conn.Intercept)) // Validate api assert.Empty(t, apitest.ListUnmatchedRequests()) })