Skip to content

Commit

Permalink
feat: add remote utils for api config
Browse files Browse the repository at this point in the history
  • Loading branch information
avallete committed Oct 11, 2024
1 parent 54c9d20 commit 15ff758
Show file tree
Hide file tree
Showing 5 changed files with 422 additions and 31 deletions.
16 changes: 2 additions & 14 deletions internal/link/link.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
package link

import (
"bytes"
"context"
"fmt"
"os"
"strconv"
"strings"
"sync"

"github.com/BurntSushi/toml"
"github.com/go-errors/errors"
"github.com/jackc/pgconn"
"github.com/jackc/pgx/v4"
Expand All @@ -25,7 +23,7 @@ import (
)

func Run(ctx context.Context, projectRef string, fsys afero.Fs, options ...func(*pgx.ConnConfig)) error {
original := toTomlBytes(map[string]interface{}{
original := cliConfig.ToTomlBytes(map[string]interface{}{
"api": utils.Config.Api,
"db": utils.Config.Db,
})
Expand Down Expand Up @@ -60,7 +58,7 @@ func Run(ctx context.Context, projectRef string, fsys afero.Fs, options ...func(
fmt.Fprintln(os.Stdout, "Finished "+utils.Aqua("supabase link")+".")

// 4. Suggest config update
updated := toTomlBytes(map[string]interface{}{
updated := cliConfig.ToTomlBytes(map[string]interface{}{
"api": utils.Config.Api,
"db": utils.Config.Db,
})
Expand All @@ -72,16 +70,6 @@ func Run(ctx context.Context, projectRef string, fsys afero.Fs, options ...func(
return nil
}

func toTomlBytes(config any) []byte {
var buf bytes.Buffer
enc := toml.NewEncoder(&buf)
enc.Indent = ""
if err := enc.Encode(config); err != nil {
fmt.Fprintln(utils.GetDebugLogger(), "failed to marshal toml config:", err)
}
return buf.Bytes()
}

func LinkServices(ctx context.Context, projectRef, anonKey string, fsys afero.Fs) {
// Ignore non-fatal errors linking services
var wg sync.WaitGroup
Expand Down
72 changes: 72 additions & 0 deletions pkg/config/api.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package config

import (
"strings"

v1API "github.com/supabase/cli/pkg/api"
)

type (
api struct {
Enabled bool `toml:"enabled"`
Image string `toml:"-"`
KongImage string `toml:"-"`
Port uint16 `toml:"port"`
Schemas []string `toml:"schemas"`
ExtraSearchPath []string `toml:"extra_search_path"`
MaxRows uint `toml:"max_rows"`
Tls tlsKong `toml:"tls"`
// TODO: replace [auth|studio].api_url
ExternalUrl string `toml:"external_url"`
}

tlsKong struct {
Enabled bool `toml:"enabled"`
}
)

func (a *api) ToUpdatePostgrestConfigBody() v1API.UpdatePostgrestConfigBody {
body := v1API.UpdatePostgrestConfigBody{}

// Convert Schemas to a comma-separated string
if len(a.Schemas) > 0 {
schemas := strings.Join(a.Schemas, ",")
body.DbSchema = &schemas
}

// Convert ExtraSearchPath to a comma-separated string
if len(a.ExtraSearchPath) > 0 {
extraSearchPath := strings.Join(a.ExtraSearchPath, ",")
body.DbExtraSearchPath = &extraSearchPath
}

// Convert MaxRows to int pointer
if a.MaxRows > 0 {
maxRows := int(a.MaxRows)
body.MaxRows = &maxRows
}

// Note: DbPool is not present in the Api struct, so it's not set here
return body
}

func (a *api) FromRemoteApiConfig(remoteConfig v1API.PostgrestConfigWithJWTSecretResponse) api {
result := *a
// Update Schemas if present in remoteConfig
result.Schemas = strings.Split(remoteConfig.DbSchema, ",")

// Update ExtraSearchPath if present in remoteConfig
result.ExtraSearchPath = strings.Split(remoteConfig.DbExtraSearchPath, ",")

// Update MaxRows if present in remoteConfig
result.MaxRows = uint(remoteConfig.MaxRows)

return result
}

func (a *api) DiffWithRemote(remoteConfig v1API.PostgrestConfigWithJWTSecretResponse) []byte {
// Convert the config values into easily comparable remoteConfig values
currentValue := ToTomlBytes(a)
remoteCompare := ToTomlBytes(a.FromRemoteApiConfig(remoteConfig))
return Diff("remote[api]", remoteCompare, "local[api]", currentValue)
}
77 changes: 77 additions & 0 deletions pkg/config/api_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package config

import (
"testing"

"github.com/stretchr/testify/assert"
v1API "github.com/supabase/cli/pkg/api"
)

func TestApiToUpdatePostgrestConfigBody(t *testing.T) {
t.Run("converts all fields correctly", func(t *testing.T) {
api := &api{
Schemas: []string{"public", "private"},
ExtraSearchPath: []string{"extensions", "public"},
MaxRows: 1000,
}

body := api.ToUpdatePostgrestConfigBody()

assert.Equal(t, "public,private", *body.DbSchema)
assert.Equal(t, "extensions,public", *body.DbExtraSearchPath)
assert.Equal(t, 1000, *body.MaxRows)
})

t.Run("handles empty fields", func(t *testing.T) {
api := &api{}

body := api.ToUpdatePostgrestConfigBody()

assert.Nil(t, body.DbSchema)
assert.Nil(t, body.DbExtraSearchPath)
assert.Nil(t, body.MaxRows)
})
}

func TestApiDiffWithRemote(t *testing.T) {
t.Run("detects differences", func(t *testing.T) {
api := &api{
Schemas: []string{"public", "private"},
ExtraSearchPath: []string{"extensions", "public"},
MaxRows: 1000,
}

remoteConfig := v1API.PostgrestConfigWithJWTSecretResponse{
DbSchema: "public",
DbExtraSearchPath: "public",
MaxRows: 500,
}

diff := api.DiffWithRemote(remoteConfig)

assert.Contains(t, string(diff), "-schemas = [\"public\"]")
assert.Contains(t, string(diff), "+schemas = [\"public\", \"private\"]")
assert.Contains(t, string(diff), "-extra_search_path = [\"public\"]")
assert.Contains(t, string(diff), "+extra_search_path = [\"extensions\", \"public\"]")
assert.Contains(t, string(diff), "-max_rows = 500")
assert.Contains(t, string(diff), "+max_rows = 1000")
})

t.Run("handles no differences", func(t *testing.T) {
api := &api{
Schemas: []string{"public"},
ExtraSearchPath: []string{"public"},
MaxRows: 500,
}

remoteConfig := v1API.PostgrestConfigWithJWTSecretResponse{
DbSchema: "public",
DbExtraSearchPath: "public",
MaxRows: 500,
}

diff := api.DiffWithRemote(remoteConfig)

assert.Empty(t, diff)
})
}
27 changes: 10 additions & 17 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -145,23 +145,6 @@ type (
Remotes map[string]baseConfig `toml:"-"`
}

api struct {
Enabled bool `toml:"enabled"`
Image string `toml:"-"`
KongImage string `toml:"-"`
Port uint16 `toml:"port"`
Schemas []string `toml:"schemas"`
ExtraSearchPath []string `toml:"extra_search_path"`
MaxRows uint `toml:"max_rows"`
Tls tlsKong `toml:"tls"`
// TODO: replace [auth|studio].api_url
ExternalUrl string `toml:"external_url"`
}

tlsKong struct {
Enabled bool `toml:"enabled"`
}

db struct {
Image string `toml:"-"`
Port uint16 `toml:"port"`
Expand Down Expand Up @@ -1322,3 +1305,13 @@ func (a *auth) ResolveJWKS(ctx context.Context) (string, error) {

return string(jwksEncoded), nil
}

func ToTomlBytes(config any) []byte {
var buf bytes.Buffer
enc := toml.NewEncoder(&buf)
enc.Indent = ""
if err := enc.Encode(config); err != nil {
fmt.Fprintln(os.Stderr, "failed to marshal toml config:", err)
}
return buf.Bytes()
}
Loading

0 comments on commit 15ff758

Please sign in to comment.