diff --git a/internal/cmd/auth.go b/internal/cmd/auth.go index 0f176d2a..b21487c6 100644 --- a/internal/cmd/auth.go +++ b/internal/cmd/auth.go @@ -276,7 +276,7 @@ func signupHint(config *settings.Settings) { return } - r, err := client.Databases.List(turso.DatabaseListOptions{}) + r, err := client.Databases.List(turso.DatabaseListOptions{Limit: 1}) if err != nil || len(r.Databases) != 0 { return } diff --git a/internal/cmd/cache.go b/internal/cmd/cache.go index eecbbfb5..c4bd910a 100644 --- a/internal/cmd/cache.go +++ b/internal/cmd/cache.go @@ -12,6 +12,23 @@ const ( DB_CACHE_TTL_SECONDS = 30 * 60 ) +func updateDatabaseCache(dbsToUpdate map[string]turso.Database) { + cache := getDatabasesCache() + if cache == nil { + return + } + for i, cached := range cache { + if update, ok := dbsToUpdate[cached.Name]; ok { + cache[i] = update + delete(dbsToUpdate, cached.Name) + } + } + for _, update := range dbsToUpdate { + cache = append(cache, update) + } + setDatabasesCache(cache) +} + func setDatabasesCache(dbNames []turso.Database) { settings.SetCache(DB_CACHE_KEY, DB_CACHE_TTL_SECONDS, dbNames) } diff --git a/internal/cmd/cache_test.go b/internal/cmd/cache_test.go index 3b97a419..752e7456 100644 --- a/internal/cmd/cache_test.go +++ b/internal/cmd/cache_test.go @@ -33,6 +33,65 @@ func Test_setDatabasesCache(t *testing.T) { } } +func Test_updateDatabasesCache(t *testing.T) { + dbNames := []turso.Database{ + { + Name: "name", + ID: "id", + Regions: []string{"waw"}, + PrimaryRegion: "waw", + Hostname: "hostname", + }, + { + Name: "name2", + ID: "id2", + Regions: []string{"waw", "ams"}, + PrimaryRegion: "ams", + Hostname: "hostname2", + }, + } + setDatabasesCache(dbNames) + updateDatabaseCache(map[string]turso.Database{"name2": { + Name: "name2-upd", + ID: "id2-upd", + Regions: []string{"lhr"}, + PrimaryRegion: "ams", + Hostname: "hostname2-upd", + }, "name3": { + Name: "name3", + ID: "id3", + Regions: []string{"aws"}, + PrimaryRegion: "waw", + Hostname: "hostname3", + }}) + dbNamesUpdated := []turso.Database{ + { + Name: "name", + ID: "id", + Regions: []string{"waw"}, + PrimaryRegion: "waw", + Hostname: "hostname", + }, + { + Name: "name2-upd", + ID: "id2-upd", + Regions: []string{"lhr"}, + PrimaryRegion: "ams", + Hostname: "hostname2-upd", + }, + { + Name: "name3", + ID: "id3", + Regions: []string{"aws"}, + PrimaryRegion: "waw", + Hostname: "hostname3", + }, + } + if !reflect.DeepEqual(getDatabasesCache(), dbNamesUpdated) { + t.Errorf("setDatabasesCache() = %v, want %v", getDatabasesCache(), dbNamesUpdated) + } +} + func Test_closestLocationCache(t *testing.T) { loc := "waw" setClosestLocationCache(loc) diff --git a/internal/cmd/db.go b/internal/cmd/db.go index 2d296388..14931299 100644 --- a/internal/cmd/db.go +++ b/internal/cmd/db.go @@ -39,6 +39,15 @@ func extractDatabaseNames(databases []turso.Database) []string { } func getDatabase(client *turso.Client, name string, fresh ...bool) (turso.Database, error) { + if len(fresh) > 0 && fresh[0] { + database, err := client.Databases.Get(name) + if err != nil { + return turso.Database{}, err + } + updateDatabaseCache(map[string]turso.Database{database.Name: database}) + return database, nil + } + databases, err := getDatabases(client, fresh...) if err != nil { return turso.Database{}, err diff --git a/internal/cmd/list_databases.go b/internal/cmd/list_databases.go index c0406396..2806b531 100644 --- a/internal/cmd/list_databases.go +++ b/internal/cmd/list_databases.go @@ -188,6 +188,8 @@ func printDatabaseList(fetcher PageFetcher) error { databases: allDatabases, } + setDatabasesCache(allDatabases) + fmt.Print(model.View()) return nil } diff --git a/internal/turso/databases.go b/internal/turso/databases.go index 0fbc8a40..4b967ba4 100644 --- a/internal/turso/databases.go +++ b/internal/turso/databases.go @@ -547,6 +547,10 @@ type DatabaseConfig struct { DeleteProtection *bool `json:"delete_protection"` } +type DatabaseResponse struct { + Database Database `json:"database"` +} + func (d *DatabaseConfig) IsDeleteProtected() bool { if d.DeleteProtection == nil { return false @@ -582,6 +586,31 @@ func (d *DatabasesClient) GetConfig(database string) (DatabaseConfig, error) { return unmarshal[DatabaseConfig](r) } +func (d *DatabasesClient) Get(database string) (Database, error) { + url := d.URL(fmt.Sprintf("/%s", database)) + r, err := d.client.Get(url, nil) + if err != nil { + return Database{}, fmt.Errorf("failed to get database: %w", err) + } + defer r.Body.Close() + + org := d.client.Org + if isNotMemberErr(r.StatusCode, org) { + return Database{}, notMemberErr(org) + } + + if r.StatusCode != http.StatusOK { + err = parseResponseError(r) + return Database{}, fmt.Errorf("failed to get database: %d %s", r.StatusCode, err) + } + + response, err := unmarshal[DatabaseResponse](r) + if err != nil { + return Database{}, err + } + return response.Database, nil +} + func (d *DatabasesClient) UpdateConfig(database string, config DatabaseConfig) error { url := d.URL(fmt.Sprintf("/%s/configuration", database)) body, err := marshal(config)