Skip to content

Commit 224ee8b

Browse files
authored
use db-api v3 for certain operations (#1032)
Use regional db-api endpoints if `--v3-api` flag is set for db-related operations (create/show/list/etc)
2 parents e37d2b5 + 513e9ac commit 224ee8b

19 files changed

Lines changed: 697 additions & 77 deletions

internal/cmd/auth.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import (
1818
"github.com/tursodatabase/turso-cli/internal"
1919
"github.com/tursodatabase/turso-cli/internal/flags"
2020
"github.com/tursodatabase/turso-cli/internal/settings"
21-
"github.com/tursodatabase/turso-cli/internal/turso"
2221
)
2322

2423
//go:embed login.html
@@ -277,8 +276,8 @@ func signupHint(config *settings.Settings) {
277276
return
278277
}
279278

280-
r, err := client.Databases.List(turso.DatabaseListOptions{})
281-
if err != nil || len(r.Databases) != 0 {
279+
databases, err := listDatabases(client)
280+
if err != nil || len(databases) != 0 {
282281
return
283282
}
284283

internal/cmd/db.go

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66

77
"github.com/spf13/cobra"
88
"github.com/tursodatabase/turso-cli/internal"
9+
"github.com/tursodatabase/turso-cli/internal/flags"
910
"github.com/tursodatabase/turso-cli/internal/settings"
1011
"github.com/tursodatabase/turso-cli/internal/turso"
1112
)
@@ -38,6 +39,21 @@ func extractDatabaseNames(databases []turso.Database) []string {
3839
return names
3940
}
4041

42+
func getDatabaseConfig(client *turso.Client, name string) (turso.DatabaseConfig, error) {
43+
if !flags.V3Api() {
44+
return client.Databases.GetConfig(name)
45+
}
46+
orgID, err := tryResolveOrgID(client)
47+
if err != nil {
48+
return turso.DatabaseConfig{}, err
49+
}
50+
dbID, err := tryResolveDbID(client, name)
51+
if err != nil {
52+
return turso.DatabaseConfig{}, err
53+
}
54+
return client.DatabasesV3.GetConfig(orgID, dbID)
55+
}
56+
4157
func getDatabase(client *turso.Client, name string, fresh ...bool) (turso.Database, error) {
4258
databases, err := getDatabases(client, fresh...)
4359
if err != nil {
@@ -53,17 +69,40 @@ func getDatabase(client *turso.Client, name string, fresh ...bool) (turso.Databa
5369
return turso.Database{}, fmt.Errorf("database %s not found. List known databases using %s", internal.Emph(name), internal.Emph("turso db list"))
5470
}
5571

72+
func listDatabases(client *turso.Client) ([]turso.Database, error) {
73+
if !flags.V3Api() {
74+
return listDatabasesV2(client)
75+
}
76+
orgID, err := tryResolveOrgID(client)
77+
if err != nil {
78+
return nil, err
79+
}
80+
if orgID == "" {
81+
return listDatabasesV2(client)
82+
}
83+
databases, _, err := client.DatabasesV3.List(orgID, turso.DatabaseV3ListOptions{})
84+
return databases, err
85+
}
86+
87+
func listDatabasesV2(client *turso.Client) ([]turso.Database, error) {
88+
response, err := client.Databases.List(turso.DatabaseListOptions{})
89+
if err != nil {
90+
return nil, err
91+
}
92+
return response.Databases, err
93+
}
94+
5695
func getDatabases(client *turso.Client, fresh ...bool) ([]turso.Database, error) {
5796
skipCache := len(fresh) > 0 && fresh[0]
5897
if cachedNames := getDatabasesCache(); !skipCache && cachedNames != nil {
5998
return cachedNames, nil
6099
}
61-
r, err := client.Databases.List(turso.DatabaseListOptions{})
100+
databases, err := listDatabases(client)
62101
if err != nil {
63102
return nil, err
64103
}
65-
setDatabasesCache(r.Databases)
66-
return r.Databases, nil
104+
setDatabasesCache(databases)
105+
return databases, nil
67106
}
68107

69108
func getDatabasesMap(client *turso.Client, fresh bool) (map[string]turso.Database, error) {

internal/cmd/db_create.go

Lines changed: 74 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ func CreateDatabase(name string) error {
9292
return err
9393
}
9494

95-
groups, err := client.Groups.List()
95+
groups, err := listGroups(client)
9696
if err != nil {
9797
return err
9898
}
@@ -127,7 +127,7 @@ func CreateDatabase(name string) error {
127127
spinner := prompt.Spinner(fmt.Sprintf("Creating database %s in group %s...", internal.Emph(name), internal.Emph(groupName)))
128128
defer spinner.Stop()
129129

130-
if _, err = client.Databases.Create(name, location, "", "", groupName, schemaFlag, typeFlag == "schema", seed, sizeLimitFlag, remoteEncryptionCipherFlag, remoteEncryptionKeyFlag(), tursoDBFlag, spinner); err != nil {
130+
if err := createDatabase(client, name, location, groupName, seed, spinner); err != nil {
131131
return fmt.Errorf("could not create database %s: %w", name, err)
132132
}
133133

@@ -145,6 +145,78 @@ func CreateDatabase(name string) error {
145145
return nil
146146
}
147147

148+
func createDatabase(client *turso.Client, name, location, groupName string, seed *turso.DBSeed, spinner *prompt.SpinnerT) error {
149+
if !flags.V3Api() {
150+
return createDatabaseV2(client, name, location, groupName, seed, spinner)
151+
}
152+
if schemaFlag != "" || typeFlag == "schema" {
153+
return createDatabaseV2(client, name, location, groupName, seed, spinner)
154+
}
155+
if sizeLimitFlag != "" {
156+
return createDatabaseV2(client, name, location, groupName, seed, spinner)
157+
}
158+
if seed != nil && seed.Type != "database" && seed.Type != "upload" {
159+
return createDatabaseV2(client, name, location, groupName, seed, spinner)
160+
}
161+
orgID, err := tryResolveOrgID(client)
162+
if err != nil {
163+
return err
164+
}
165+
if orgID == "" {
166+
return createDatabaseV2(client, name, location, groupName, seed, spinner)
167+
}
168+
body := CreateDatabaseV3BodyFromFlags(name, seed)
169+
if seed == nil || seed.Type != "database" {
170+
groupID, err := tryResolveGroupID(client, groupName)
171+
if err != nil {
172+
return err
173+
}
174+
if groupID == "" {
175+
return createDatabaseV2(client, name, location, groupName, seed, spinner)
176+
}
177+
body.GroupID = groupID
178+
} else if seed.Type == "database" {
179+
_, err := client.DatabasesV3.Create(orgID, body)
180+
return err
181+
}
182+
_, err = client.DatabasesV3.Create(orgID, body)
183+
return err
184+
}
185+
186+
func createDatabaseV2(client *turso.Client, name, location, groupName string, seed *turso.DBSeed, spinner *prompt.SpinnerT) error {
187+
_, err := client.Databases.Create(name, location, "", "", groupName, schemaFlag, typeFlag == "schema", seed, sizeLimitFlag, remoteEncryptionCipherFlag, remoteEncryptionKeyFlag(), tursoDBFlag, spinner)
188+
return err
189+
}
190+
191+
func CreateDatabaseV3BodyFromFlags(name string, seed *turso.DBSeed) turso.CreateDatabaseV3Body {
192+
body := turso.CreateDatabaseV3Body{
193+
Name: name,
194+
CreationMode: "empty",
195+
}
196+
if tursoDBFlag {
197+
body.DatabaseType = "tursodb"
198+
} else {
199+
body.DatabaseType = "libsql"
200+
}
201+
if seed != nil && seed.Type == "database" {
202+
body.CreationMode = "fork"
203+
body.ParentDBName = seed.Name
204+
if seed.Timestamp != nil {
205+
body.Timestamp = seed.Timestamp
206+
}
207+
}
208+
if seed != nil && seed.Type == "upload" {
209+
body.CreationMode = "upload"
210+
}
211+
if remoteEncryptionKeyFlag() != "" {
212+
body.RemoteEncryption = &turso.RemoteEncryption{
213+
EncryptionKey: remoteEncryptionKeyFlag(),
214+
EncryptionCipher: remoteEncryptionCipherFlag,
215+
}
216+
}
217+
return body
218+
}
219+
148220
func ensureGroup(client *turso.Client, group string, groups []turso.Group, location, version string) error {
149221
if !shouldAutoCreateGroup(group, groups) {
150222
return nil

internal/cmd/db_generatetoken.go

Lines changed: 31 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ var dbGenerateTokenCmd = &cobra.Command{
6262
}
6363
token, err := getToken(client, database, expiration, flags.ReadOnly(), groupTokenFlag, claim, permissions)
6464
if err != nil {
65-
return errors.New("your database does not support token generation")
65+
return fmt.Errorf("failed to generate database token: %v", err)
6666
}
6767
fmt.Println(token)
6868
return nil
@@ -77,11 +77,36 @@ func getToken(
7777
claim *turso.PermissionsClaim,
7878
fineGrainedPermissions []flags.FineGrainedPermissions,
7979
) (string, error) {
80-
if !group {
81-
return client.Databases.Token(database.Name, expiration, readOnly, claim, fineGrainedPermissions)
80+
if group {
81+
if database.Group == "" {
82+
return "", errors.New("--group flag can only be set with group databases")
83+
}
84+
return client.Groups.Token(database.Group, expiration, readOnly, claim, fineGrainedPermissions)
85+
}
86+
if !flags.V3Api() {
87+
return getTokenV2(client, database, expiration, readOnly, claim, fineGrainedPermissions)
88+
}
89+
if claim != nil {
90+
return getTokenV2(client, database, expiration, readOnly, claim, fineGrainedPermissions)
8291
}
83-
if group && database.Group == "" {
84-
return "", errors.New("--group flag can only be set with group databases")
92+
orgID, err := tryResolveOrgID(client)
93+
if err != nil {
94+
return "", err
8595
}
86-
return client.Groups.Token(database.Group, expiration, readOnly, claim, fineGrainedPermissions)
96+
dbID := database.ID
97+
if orgID == "" || dbID == "" {
98+
return getTokenV2(client, database, expiration, readOnly, claim, fineGrainedPermissions)
99+
}
100+
return client.DatabasesV3.Token(orgID, dbID, expiration, readOnly, fineGrainedPermissions)
101+
}
102+
103+
func getTokenV2(
104+
client *turso.Client,
105+
database turso.Database,
106+
expiration string,
107+
readOnly bool,
108+
claim *turso.PermissionsClaim,
109+
fineGrainedPermissions []flags.FineGrainedPermissions,
110+
) (string, error) {
111+
return client.Databases.Token(database.Name, expiration, readOnly, claim, fineGrainedPermissions)
87112
}

internal/cmd/db_inspect.go

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import (
77
"github.com/dustin/go-humanize"
88
"github.com/rodaine/table"
99
"github.com/spf13/cobra"
10-
"github.com/tursodatabase/turso-cli/internal"
1110
"github.com/tursodatabase/turso-cli/internal/turso"
1211
)
1312

@@ -57,11 +56,6 @@ var dbInspectCmd = &cobra.Command{
5756
fmt.Printf("Embedded syncs: %s\n", humanize.Bytes(dbUsage.Usage.BytesSynced))
5857
}
5958

60-
if len(instances) == 0 {
61-
fmt.Printf("\n🛠 Run %s to finish your database creation!\n", internal.Emph("turso db replicate "+db.Name))
62-
return nil
63-
}
64-
6559
if !verboseFlag {
6660
return nil
6761
}

internal/cmd/db_list.go

Lines changed: 77 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package cmd
22

33
import (
44
"github.com/spf13/cobra"
5+
"github.com/tursodatabase/turso-cli/internal/flags"
56
"github.com/tursodatabase/turso-cli/internal/turso"
67
)
78

@@ -15,10 +16,68 @@ func init() {
1516
}
1617

1718
type DatabaseFetcher struct {
18-
client *turso.Client
19+
client *turso.Client
20+
SchemaFilter string
21+
GroupFilter string
22+
ParentDbId string
23+
LoadFullInfo bool
1924
}
2025

2126
func (df *DatabaseFetcher) FetchPage(pageSize int, cursor *string) (turso.ListResponse, error) {
27+
if !flags.V3Api() {
28+
return df.fetchPageV2(pageSize, cursor)
29+
}
30+
if df.SchemaFilter != "" {
31+
return df.fetchPageV2(pageSize, cursor)
32+
}
33+
orgID, err := tryResolveOrgID(df.client)
34+
if err != nil {
35+
return turso.ListResponse{}, err
36+
}
37+
if orgID == "" {
38+
return df.fetchPageV2(pageSize, cursor)
39+
}
40+
groupID := ""
41+
if df.GroupFilter != "" {
42+
id, err := tryResolveGroupID(df.client, df.GroupFilter)
43+
if err != nil {
44+
return turso.ListResponse{}, err
45+
}
46+
if id == "" {
47+
return df.fetchPageV2(pageSize, cursor)
48+
}
49+
groupID = id
50+
}
51+
cursorStr := ""
52+
if cursor != nil {
53+
cursorStr = *cursor
54+
}
55+
options := turso.DatabaseV3ListOptions{
56+
GroupId: groupID,
57+
Limit: pageSize,
58+
Cursor: cursorStr,
59+
ParentDbId: df.ParentDbId,
60+
}
61+
dbs, next, err := df.client.DatabasesV3.List(orgID, options)
62+
if err != nil {
63+
return turso.ListResponse{}, err
64+
}
65+
response := turso.ListResponse{Databases: dbs}
66+
if next != "" {
67+
response.Pagination = &turso.Pagination{Next: &next}
68+
}
69+
if df.LoadFullInfo {
70+
for i := range response.Databases {
71+
response.Databases[i], err = df.client.DatabasesV3.Get(orgID, response.Databases[i].ID)
72+
if err != nil {
73+
return turso.ListResponse{}, err
74+
}
75+
}
76+
}
77+
return response, nil
78+
}
79+
80+
func (df *DatabaseFetcher) fetchPageV2(pageSize int, cursor *string) (turso.ListResponse, error) {
2281
cursorStr := ""
2382
if cursor != nil {
2483
cursorStr = *cursor
@@ -29,9 +88,22 @@ func (df *DatabaseFetcher) FetchPage(pageSize int, cursor *string) (turso.ListRe
2988
Schema: schemaFilter,
3089
Limit: pageSize,
3190
Cursor: cursorStr,
91+
Parent: df.ParentDbId,
3292
}
3393

34-
return df.client.Databases.List(options)
94+
response, err := df.client.Databases.List(options)
95+
if err != nil {
96+
return turso.ListResponse{}, err
97+
}
98+
if df.LoadFullInfo {
99+
for i := range response.Databases {
100+
response.Databases[i], err = df.client.Databases.Get(response.Databases[i].Name)
101+
if err != nil {
102+
return turso.ListResponse{}, err
103+
}
104+
}
105+
}
106+
return response, nil
35107
}
36108

37109
var listCmd = &cobra.Command{
@@ -47,7 +119,9 @@ var listCmd = &cobra.Command{
47119
}
48120

49121
fetcher := &DatabaseFetcher{
50-
client: client,
122+
client: client,
123+
SchemaFilter: schemaFilter,
124+
GroupFilter: groupFilter,
51125
}
52126
return printDatabaseList(fetcher)
53127
},

0 commit comments

Comments
 (0)