diff --git a/Makefile b/Makefile index 43fd1c4..6dba5f1 100644 --- a/Makefile +++ b/Makefile @@ -12,12 +12,16 @@ smoke-test: test: @echo "Running unit tests" - @go test -count=1 -cover -race ./... + @go test -count=1 -cover -race ./xata integration-test: @echo "Running integration test" - @go test -v --tags=integration -count=1 -cover -race ./internal/integration-tests + @go test -count=1 -cover -race ./internal/integration-tests download-openapi-specs: @echo "Downloading openapi specs" - @cd internal/docs && go run . && cd ../.. \ No newline at end of file + @cd internal/docs && go run . && cd ../.. + +clean-workspaces: + @echo "Cleaning integration test workspaces" + CLEAN_UP_INTEGRATION_WORKSPACES=true go test -v -run Test_cleanupIntegrationWorkspaces ./... \ No newline at end of file diff --git a/internal/integration-tests/files_client_test.go b/internal/integration-tests/files_client_test.go index 820799d..cff12c4 100644 --- a/internal/integration-tests/files_client_test.go +++ b/internal/integration-tests/files_client_test.go @@ -29,7 +29,8 @@ func Test_filesClient(t *testing.T) { } }) - filesCli, err := xata.NewFilesClient(xata.WithAPIKey(cfg.apiKey), + recordsCli, err := xata.NewRecordsClient( + xata.WithAPIKey(cfg.apiKey), xata.WithBaseURL(fmt.Sprintf( "https://%s.%s.xata.sh", cfg.wsID, @@ -38,11 +39,12 @@ func Test_filesClient(t *testing.T) { xata.WithHTTPClient(retryablehttp.NewClient().StandardClient()), ) if err != nil { - t.Fatalf("unable to construct files cli: %v", err) + t.Fatal(err) } - recordsCli, err := xata.NewRecordsClient( - xata.WithAPIKey(cfg.apiKey), + insertRecordRequest := generateInsertRecordRequest(cfg.databaseName, cfg.tableName) + + filesCli, err := xata.NewFilesClient(xata.WithAPIKey(cfg.apiKey), xata.WithBaseURL(fmt.Sprintf( "https://%s.%s.xata.sh", cfg.wsID, @@ -51,18 +53,58 @@ func Test_filesClient(t *testing.T) { xata.WithHTTPClient(retryablehttp.NewClient().StandardClient()), ) if err != nil { - t.Fatal(err) + t.Fatalf("unable to construct files cli: %v", err) } - insertRecordRequest := generateInsertRecordRequest(cfg.databaseName, cfg.tableName) + t.Run("get a file", func(t *testing.T) { + record, err := recordsCli.Insert(ctx, insertRecordRequest) + if err != nil { + t.Fatal(err) + } + assert.NotNil(t, record) - record, err := recordsCli.Insert(ctx, insertRecordRequest) - if err != nil { - t.Fatal(err) - } - assert.NotNil(t, record) + getFileRes, err := filesCli.Get(ctx, xata.GetFileRequest{ + BranchRequestOptional: xata.BranchRequestOptional{ + DatabaseName: xata.String(cfg.databaseName), + }, + TableName: cfg.tableName, + RecordId: record.Id, + ColumnName: fileColumn, + }) + assert.NoError(t, err) + assert.Equal(t, fileContent, string(getFileRes.Content)) + }) + + t.Run("put a file", func(t *testing.T) { + record, err := recordsCli.Insert(ctx, insertRecordRequest) + if err != nil { + t.Fatal(err) + } + assert.NotNil(t, record) + + fileRes, err := filesCli.Put(ctx, xata.PutFileRequest{ + BranchRequestOptional: xata.BranchRequestOptional{ + DatabaseName: xata.String(cfg.databaseName), + }, + TableName: cfg.tableName, + RecordId: record.Id, + ColumnName: fileColumn, + ContentType: xata.String(""application/octet-stream""), + Data: []byte(`new content`), + }) + assert.NoError(t, err) + assert.NotNil(t, fileRes.Attributes) + assert.Equal(t, "", fileRes.Name) + assert.Nil(t, fileRes.Id) + }) t.Run("delete a file", func(t *testing.T) { + record, err := recordsCli.Insert(ctx, insertRecordRequest) + if err != nil { + t.Fatal(err) + } + assert.NotNil(t, record) + delRes, err := filesCli.Delete(ctx, xata.DeleteFileRequest{ BranchRequestOptional: xata.BranchRequestOptional{ DatabaseName: xata.String(cfg.databaseName), @@ -74,4 +116,68 @@ func Test_filesClient(t *testing.T) { assert.NoError(t, err) assert.Equal(t, testFileName, delRes.Name) }) + + t.Run("get file item", func(t *testing.T) { + record, err := recordsCli.Insert(ctx, insertRecordRequest) + if err != nil { + t.Fatal(err) + } + assert.NotNil(t, record) + + getItemRes, err := filesCli.GetItem(ctx, xata.GetFileItemRequest{ + BranchRequestOptional: xata.BranchRequestOptional{ + DatabaseName: xata.String(cfg.databaseName), + }, + TableName: cfg.tableName, + RecordId: record.Id, + ColumnName: fileArrayColumn, + FileID: record.Data[fileArrayColumn].([]interface{})[0].(map[string]any)["id"].(string), + }) + assert.NoError(t, err) + assert.Equal(t, fileContent, string(getItemRes.Content)) + }) + + t.Run("put a file item", func(t *testing.T) { + record, err := recordsCli.Insert(ctx, insertRecordRequest) + if err != nil { + t.Fatal(err) + } + assert.NotNil(t, record) + + fileRes, err := filesCli.PutItem(ctx, xata.PutFileItemRequest{ + BranchRequestOptional: xata.BranchRequestOptional{ + DatabaseName: xata.String(cfg.databaseName), + }, + TableName: cfg.tableName, + RecordId: record.Id, + ColumnName: fileArrayColumn, + FileID: record.Data[fileArrayColumn].([]interface{})[0].(map[string]any)["id"].(string), + ContentType: xata.String("text/plain"), + Data: []byte(`new content`), + }) + assert.NoError(t, err) + assert.NotNil(t, fileRes.Attributes) + assert.Equal(t, "", fileRes.Name) + assert.NotNil(t, fileRes.Id) + }) + + t.Run("delete a file item", func(t *testing.T) { + record, err := recordsCli.Insert(ctx, insertRecordRequest) + if err != nil { + t.Fatal(err) + } + assert.NotNil(t, record) + + delRes, err := filesCli.DeleteItem(ctx, xata.DeleteFileItemRequest{ + BranchRequestOptional: xata.BranchRequestOptional{ + DatabaseName: xata.String(cfg.databaseName), + }, + TableName: cfg.tableName, + RecordId: record.Id, + ColumnName: fileArrayColumn, + FileID: record.Data[fileArrayColumn].([]interface{})[0].(map[string]any)["id"].(string), + }) + assert.NoError(t, err) + assert.Equal(t, testFileName, delRes.Name) + }) } diff --git a/internal/integration-tests/records_client_test.go b/internal/integration-tests/records_client_test.go index 62e47d4..63659a8 100644 --- a/internal/integration-tests/records_client_test.go +++ b/internal/integration-tests/records_client_test.go @@ -2,6 +2,7 @@ package integrationtests import ( "context" + "encoding/base64" "fmt" "testing" "time" @@ -13,18 +14,20 @@ import ( ) const ( - stringColumn = "user-name" - boolColumn = "active" - textColumn = "text-column" - emailColumn = "email" - dateTimeColumn = "date-of-birth" - integerColumn = "integer-column" - floatColumn = "float-column" - fileColumn = "file-column" - jsonColumn = "json-column" - vectorColumn = "vector-column" // it is important to set a vector dimension on the UI: 2 - multipleColumn = "multiple-column" - testFileName = "file-name.txt" + stringColumn = "user-name" + boolColumn = "active" + textColumn = "text-column" + emailColumn = "email" + dateTimeColumn = "date-of-birth" + integerColumn = "integer-column" + floatColumn = "float-column" + fileColumn = "file-column" + fileArrayColumn = "fileArrayColumn" + fileContent = "file content" + jsonColumn = "json-column" + vectorColumn = "vector-column" // it is important to set a vector dimension on the UI: 2 + multipleColumn = "multiple-column" + testFileName = "file-name.txt" ) func Test_recordsClient_Insert_Get(t *testing.T) { @@ -73,7 +76,8 @@ func Test_recordsClient_Insert_Get(t *testing.T) { assert.Equal(t, insertRecordRequest.Body[textColumn].String, record.Data[textColumn]) assert.Equal(t, insertRecordRequest.Body[integerColumn].Double, record.Data[integerColumn]) assert.Equal(t, insertRecordRequest.Body[floatColumn].Double, record.Data[floatColumn]) - assert.Equal(t, insertRecordRequest.Body[fileColumn].InputFile.Name, record.Data[fileColumn].(map[string]interface{})["name"]) + assert.Equal(t, insertRecordRequest.Body[fileColumn].InputFile.Name, record.Data[fileColumn].(map[string]any)["name"]) + assert.Equal(t, *(insertRecordRequest.Body[fileArrayColumn].InputFileArray[0]).Name, record.Data[fileArrayColumn].([]interface{})[0].(map[string]any)["name"]) assert.ElementsMatch(t, insertRecordRequest.Body[vectorColumn].DoubleList, record.Data[vectorColumn]) assert.ElementsMatch(t, insertRecordRequest.Body[multipleColumn].StringList, record.Data[multipleColumn]) assert.Equal(t, insertRecordRequest.Body[jsonColumn].String, record.Data[jsonColumn]) @@ -102,6 +106,8 @@ func Test_recordsClient_Insert_Get(t *testing.T) { // 400: {"errors":[{ //"status":400,"message":"column [file-column]: file upload not permitted in transaction"}, delete(insertRecordRequest.Body, fileColumn) + //"status":400,"message":"column [fileArrayColumn]: file entry [0]: file upload not permitted in transaction"} + delete(insertRecordRequest.Body, fileArrayColumn) records, err := recordsCli.BulkInsert(ctx, xata.BulkInsertRecordRequest{ RecordRequest: insertRecordRequest.RecordRequest, @@ -443,6 +449,7 @@ func generateInsertRecordRequest(databaseName, tableName string) xata.InsertReco integerColumn, floatColumn, fileColumn, + fileArrayColumn, jsonColumn, vectorColumn, multipleColumn, @@ -457,7 +464,13 @@ func generateInsertRecordRequest(databaseName, tableName string) xata.InsertReco floatColumn: xata.ValueFromDouble(10.3), fileColumn: xata.ValueFromInputFile(xata.InputFile{ Name: testFileName, - Base64Content: xata.String("ZmlsZSBjb250ZW50"), // file content + Base64Content: xata.String(base64.StdEncoding.EncodeToString([]byte(fileContent))), + }), + fileArrayColumn: xata.ValueFromInputFileArray(xata.InputFileArray{ + { + Name: xata.String(testFileName), + Base64Content: xata.String(base64.StdEncoding.EncodeToString([]byte(fileContent))), + }, }), vectorColumn: xata.ValueFromDoubleList([]float64{10.3, 20.2}), multipleColumn: xata.ValueFromStringList([]string{"hello", "world"}), diff --git a/internal/integration-tests/setup_test.go b/internal/integration-tests/setup_test.go index 95021f1..9b24971 100644 --- a/internal/integration-tests/setup_test.go +++ b/internal/integration-tests/setup_test.go @@ -249,6 +249,25 @@ func setupTableWithColumns(ctx context.Context, cfg *config) error { return err } + _, err = tableCli.AddColumn(ctx, xata.AddColumnRequest{ + TableRequest: xata.TableRequest{ + TableName: cfg.tableName, + DatabaseName: xata.String(cfg.databaseName), + }, + Column: &xata.Column{ + Name: fileArrayColumn, + Type: xata.ColumnTypeFileMap, + File: &xata.ColumnFile{ + DefaultPublicAccess: xata.Bool(true), + }, + NotNull: xata.Bool(false), + Unique: xata.Bool(false), + }, + }) + if err != nil { + return err + } + _, err = tableCli.AddColumn(ctx, xata.AddColumnRequest{ TableRequest: xata.TableRequest{ TableName: cfg.tableName, diff --git a/internal/integration-tests/setup_test_test.go b/internal/integration-tests/setup_test_test.go index 551d037..f551ab2 100644 --- a/internal/integration-tests/setup_test_test.go +++ b/internal/integration-tests/setup_test_test.go @@ -2,6 +2,7 @@ package integrationtests import ( "context" + "os" "testing" "github.com/stretchr/testify/assert" @@ -30,6 +31,9 @@ func Test_setup_cleanup(t *testing.T) { } func Test_cleanupIntegrationWorkspaces(t *testing.T) { + if _, found := os.LookupEnv("CLEAN_UP_INTEGRATION_WORKSPACES"); !found { + t.Skip("skipping integration workspaces cleanup") + } err := cleanAllWorkspaces() if err != nil { t.Fatal(err) diff --git a/xata/files_cilent.go b/xata/files_cilent.go index b693eda..f2b64cc 100644 --- a/xata/files_cilent.go +++ b/xata/files_cilent.go @@ -9,11 +9,11 @@ import ( ) type FilesClient interface { - // GetFileItem(ctx context.Context, dbBranchName DbBranchName, tableName TableName, recordId RecordId, columnName ColumnName, fileId FileItemId) error - // PutFileItem(ctx context.Context, dbBranchName DbBranchName, tableName TableName, recordId RecordId, columnName ColumnName, fileId FileItemId) (*FileResponse, error) - // DeleteFileItem(ctx context.Context, dbBranchName DbBranchName, tableName TableName, recordId RecordId, columnName ColumnName, fileId FileItemId) (*FileResponse, error) - // GetFile(ctx context.Context, dbBranchName DbBranchName, tableName TableName, recordId RecordId, columnName ColumnName) error - // PutFile(ctx context.Context, dbBranchName DbBranchName, tableName TableName, recordId RecordId, columnName ColumnName) (*FileResponse, error) + GetItem(ctx context.Context, request GetFileItemRequest) (*xatagenworkspace.GetFileResponse, error) + PutItem(ctx context.Context, request PutFileItemRequest) (*xatagenworkspace.FileResponse, error) + DeleteItem(ctx context.Context, request DeleteFileItemRequest) (*xatagenworkspace.FileResponse, error) + Get(ctx context.Context, request GetFileRequest) (*xatagenworkspace.GetFileResponse, error) + Put(ctx context.Context, request PutFileRequest) (*xatagenworkspace.FileResponse, error) Delete(ctx context.Context, request DeleteFileRequest) (*xatagenworkspace.FileResponse, error) } @@ -57,6 +57,107 @@ func (f filesClient) Delete(ctx context.Context, request DeleteFileRequest) (*xa return f.generated.DeleteFile(ctx, dbBranchName, request.TableName, request.RecordId, request.ColumnName) } +type PutFileRequest struct { + BranchRequestOptional + ContentType *string + TableName string + RecordId string + ColumnName string + Data []byte +} + +func (f filesClient) Put(ctx context.Context, request PutFileRequest) (*xatagenworkspace.FileResponse, error) { + dbBranchName, err := f.dbBranchName(request.BranchRequestOptional) + if err != nil { + return nil, err + } + + contentType := "application/octet-stream" + if request.ContentType != nil && *request.ContentType != "" { + contentType = *request.ContentType + } + + f.generated.SetContentTypeHeader(contentType) + + return f.generated.PutFile(ctx, dbBranchName, request.TableName, request.RecordId, request.ColumnName, request.Data) +} + +type GetFileRequest struct { + BranchRequestOptional + TableName string + RecordId string + ColumnName string +} + +func (f filesClient) Get(ctx context.Context, request GetFileRequest) (*xatagenworkspace.GetFileResponse, error) { + dbBranchName, err := f.dbBranchName(request.BranchRequestOptional) + if err != nil { + return nil, err + } + + return f.generated.GetFile(ctx, dbBranchName, request.TableName, request.RecordId, request.ColumnName) +} + +type GetFileItemRequest struct { + BranchRequestOptional + TableName string + RecordId string + ColumnName string + FileID string +} + +func (f filesClient) GetItem(ctx context.Context, request GetFileItemRequest) (*xatagenworkspace.GetFileResponse, error) { + dbBranchName, err := f.dbBranchName(request.BranchRequestOptional) + if err != nil { + return nil, err + } + + return f.generated.GetFileItem(ctx, dbBranchName, request.TableName, request.RecordId, request.ColumnName, request.FileID) +} + +type PutFileItemRequest struct { + BranchRequestOptional + ContentType *string + TableName string + RecordId string + ColumnName string + FileID string + Data []byte +} + +func (f filesClient) PutItem(ctx context.Context, request PutFileItemRequest) (*xatagenworkspace.FileResponse, error) { + dbBranchName, err := f.dbBranchName(request.BranchRequestOptional) + if err != nil { + return nil, err + } + + contentType := "application/octet-stream" + if request.ContentType != nil && *request.ContentType != "" { + contentType = *request.ContentType + } + + f.generated.SetContentTypeHeader(contentType) + + return f.generated.PutFileItem(ctx, dbBranchName, request.TableName, request.RecordId, request.ColumnName, request.FileID, request.Data) +} + +type DeleteFileItemRequest struct { + BranchRequestOptional + TableName string + RecordId string + ColumnName string + FileID string +} + +func (f filesClient) DeleteItem(ctx context.Context, request DeleteFileItemRequest) (*xatagenworkspace.FileResponse, error) { + dbBranchName, err := f.dbBranchName(request.BranchRequestOptional) + if err != nil { + return nil, err + } + + return f.generated.DeleteFileItem(ctx, dbBranchName, request.TableName, request.RecordId, request.ColumnName, request.FileID) +} + func NewFilesClient(opts ...ClientOption) (FilesClient, error) { cliOpts, dbCfg, err := consolidateClientOptionsForWorkspace(opts...) if err != nil { diff --git a/xata/files_cilent_test.go b/xata/files_cilent_test.go index 6a7d80a..0456cf9 100644 --- a/xata/files_cilent_test.go +++ b/xata/files_cilent_test.go @@ -83,3 +83,305 @@ func Test_filesClient_Delete(t *testing.T) { }) } } + +func Test_filesClient_Put(t *testing.T) { + assert := assert.New(t) + + type tc struct { + name string + want *xatagenworkspace.FileResponse + statusCode int + apiErr *xatagencore.APIError + } + + tests := []tc{ + { + name: "should put a file successfully", + want: &xatagenworkspace.FileResponse{ + MediaType: "text/plain", + }, + statusCode: http.StatusOK, + }, + } + + for _, eTC := range errTestCasesWorkspace { + tests = append(tests, tc{ + name: eTC.name, + statusCode: eTC.statusCode, + apiErr: eTC.apiErr, + }) + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + testSrv := testService(t, http.MethodPut, "/db", tt.statusCode, tt.apiErr != nil, tt.want) + + cli, err := xata.NewFilesClient(xata.WithBaseURL(testSrv.URL), xata.WithAPIKey("test-key")) + assert.NoError(err) + assert.NotNil(cli) + + got, err := cli.Put(context.TODO(), xata.PutFileRequest{ + BranchRequestOptional: xata.BranchRequestOptional{ + DatabaseName: xata.String("my-db"), + }, + TableName: "my-table", + RecordId: "my-id", + ColumnName: "file-column", + Data: []byte(`hola`), + }) + + if tt.apiErr != nil { + errAPI := tt.apiErr.Unwrap() + if errAPI == nil { + t.Fatal("expected error but got nil") + } + assert.ErrorAs(err, &errAPI) + assert.Equal(err.Error(), tt.apiErr.Error()) + assert.Nil(got) + } else { + assert.Equal(tt.want.MediaType, got.MediaType) + assert.NoError(err) + } + }) + } +} + +func Test_filesClient_Get(t *testing.T) { + assert := assert.New(t) + + type tc struct { + name string + statusCode int + apiErr *xatagencore.APIError + } + + tests := []tc{ + { + name: "should get a file successfully", + statusCode: http.StatusOK, + }, + } + + for _, eTC := range errTestCasesWorkspace { + tests = append(tests, tc{ + name: eTC.name, + statusCode: eTC.statusCode, + apiErr: eTC.apiErr, + }) + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + testSrv := testService(t, http.MethodGet, "/db", tt.statusCode, tt.apiErr != nil, nil) + + cli, err := xata.NewFilesClient(xata.WithBaseURL(testSrv.URL), xata.WithAPIKey("test-key")) + assert.NoError(err) + assert.NotNil(cli) + + got, err := cli.Get(context.TODO(), xata.GetFileRequest{ + BranchRequestOptional: xata.BranchRequestOptional{ + DatabaseName: xata.String("my-db"), + }, + TableName: "my-table", + RecordId: "my-id", + ColumnName: "file-column", + }) + + if tt.apiErr != nil { + errAPI := tt.apiErr.Unwrap() + if errAPI == nil { + t.Fatal("expected error but got nil") + } + assert.ErrorAs(err, &errAPI) + assert.Equal(err.Error(), tt.apiErr.Error()) + assert.Nil(got) + } else { + assert.NotNil(got) + assert.NoError(err) + } + }) + } +} + +func Test_filesClient_GetItem(t *testing.T) { + assert := assert.New(t) + + type tc struct { + name string + statusCode int + apiErr *xatagencore.APIError + } + + tests := []tc{ + { + name: "should get a file item successfully", + statusCode: http.StatusOK, + }, + } + + for _, eTC := range errTestCasesWorkspace { + tests = append(tests, tc{ + name: eTC.name, + statusCode: eTC.statusCode, + apiErr: eTC.apiErr, + }) + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + testSrv := testService(t, http.MethodGet, "/db", tt.statusCode, tt.apiErr != nil, nil) + + cli, err := xata.NewFilesClient(xata.WithBaseURL(testSrv.URL), xata.WithAPIKey("test-key")) + assert.NoError(err) + assert.NotNil(cli) + + got, err := cli.GetItem(context.TODO(), xata.GetFileItemRequest{ + BranchRequestOptional: xata.BranchRequestOptional{ + DatabaseName: xata.String("my-db"), + }, + TableName: "my-table", + RecordId: "my-id", + ColumnName: "file-column", + FileID: "some-id", + }) + + if tt.apiErr != nil { + errAPI := tt.apiErr.Unwrap() + if errAPI == nil { + t.Fatal("expected error but got nil") + } + assert.ErrorAs(err, &errAPI) + assert.Equal(err.Error(), tt.apiErr.Error()) + assert.Nil(got) + } else { + assert.NotNil(got) + assert.NoError(err) + } + }) + } +} + +func Test_filesClient_PutItem(t *testing.T) { + assert := assert.New(t) + + type tc struct { + name string + want *xatagenworkspace.FileResponse + statusCode int + apiErr *xatagencore.APIError + } + + tests := []tc{ + { + name: "should put a file item successfully", + want: &xatagenworkspace.FileResponse{ + MediaType: "text/plain", + }, + statusCode: http.StatusOK, + }, + } + + for _, eTC := range errTestCasesWorkspace { + tests = append(tests, tc{ + name: eTC.name, + statusCode: eTC.statusCode, + apiErr: eTC.apiErr, + }) + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + testSrv := testService(t, http.MethodPut, "/db", tt.statusCode, tt.apiErr != nil, tt.want) + + cli, err := xata.NewFilesClient(xata.WithBaseURL(testSrv.URL), xata.WithAPIKey("test-key")) + assert.NoError(err) + assert.NotNil(cli) + + got, err := cli.PutItem(context.TODO(), xata.PutFileItemRequest{ + BranchRequestOptional: xata.BranchRequestOptional{ + DatabaseName: xata.String("my-db"), + }, + TableName: "my-table", + RecordId: "my-id", + ColumnName: "file-column", + FileID: "some-id", + Data: []byte(`hola`), + }) + + if tt.apiErr != nil { + errAPI := tt.apiErr.Unwrap() + if errAPI == nil { + t.Fatal("expected error but got nil") + } + assert.ErrorAs(err, &errAPI) + assert.Equal(err.Error(), tt.apiErr.Error()) + assert.Nil(got) + } else { + assert.Equal(tt.want.MediaType, got.MediaType) + assert.NoError(err) + } + }) + } +} + +func Test_filesClient_DeleteItem(t *testing.T) { + assert := assert.New(t) + + type tc struct { + name string + want *xatagenworkspace.FileResponse + statusCode int + apiErr *xatagencore.APIError + } + + tests := []tc{ + { + name: "should delete a file item successfully", + want: &xatagenworkspace.FileResponse{ + Name: "test-file.txt", + }, + statusCode: http.StatusOK, + }, + } + + for _, eTC := range errTestCasesWorkspace { + tests = append(tests, tc{ + name: eTC.name, + statusCode: eTC.statusCode, + apiErr: eTC.apiErr, + }) + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + testSrv := testService(t, http.MethodDelete, "/db", tt.statusCode, tt.apiErr != nil, tt.want) + + cli, err := xata.NewFilesClient(xata.WithBaseURL(testSrv.URL), xata.WithAPIKey("test-key")) + assert.NoError(err) + assert.NotNil(cli) + + got, err := cli.DeleteItem(context.TODO(), xata.DeleteFileItemRequest{ + BranchRequestOptional: xata.BranchRequestOptional{ + DatabaseName: xata.String("my-db"), + }, + TableName: "my-table", + RecordId: "my-id", + ColumnName: "file-column", + FileID: "some-id", + }) + + if tt.apiErr != nil { + errAPI := tt.apiErr.Unwrap() + if errAPI == nil { + t.Fatal("expected error but got nil") + } + assert.ErrorAs(err, &errAPI) + assert.Equal(err.Error(), tt.apiErr.Error()) + assert.Nil(got) + } else { + assert.Equal(tt.want.Name, got.Name) + assert.NoError(err) + } + }) + } +} diff --git a/xata/internal/fern-workspace/generated/go/column_type.go b/xata/internal/fern-workspace/generated/go/column_type.go index 86e4dec..5e55c64 100644 --- a/xata/internal/fern-workspace/generated/go/column_type.go +++ b/xata/internal/fern-workspace/generated/go/column_type.go @@ -56,7 +56,7 @@ func (c ColumnType) String() string { case ColumnTypeFile: return "file" case ColumnTypeFileMap: - return "fileMap" + return "file[]" case ColumnTypeJson: return "json" } diff --git a/xata/internal/fern-workspace/generated/go/files_client.go b/xata/internal/fern-workspace/generated/go/files_client.go index 84de0df..d0a9f10 100644 --- a/xata/internal/fern-workspace/generated/go/files_client.go +++ b/xata/internal/fern-workspace/generated/go/files_client.go @@ -14,12 +14,13 @@ import ( ) type FilesClient interface { - GetFileItem(ctx context.Context, dbBranchName DbBranchName, tableName TableName, recordId RecordId, columnName ColumnName, fileId FileItemId) error - PutFileItem(ctx context.Context, dbBranchName DbBranchName, tableName TableName, recordId RecordId, columnName ColumnName, fileId FileItemId) (*FileResponse, error) + GetFileItem(ctx context.Context, dbBranchName DbBranchName, tableName TableName, recordId RecordId, columnName ColumnName, fileId FileItemId) (*GetFileResponse, error) + PutFileItem(ctx context.Context, dbBranchName DbBranchName, tableName TableName, recordId RecordId, columnName ColumnName, fileId FileItemId, data []byte) (*FileResponse, error) DeleteFileItem(ctx context.Context, dbBranchName DbBranchName, tableName TableName, recordId RecordId, columnName ColumnName, fileId FileItemId) (*FileResponse, error) - GetFile(ctx context.Context, dbBranchName DbBranchName, tableName TableName, recordId RecordId, columnName ColumnName) error - PutFile(ctx context.Context, dbBranchName DbBranchName, tableName TableName, recordId RecordId, columnName ColumnName) (*FileResponse, error) + GetFile(ctx context.Context, dbBranchName DbBranchName, tableName TableName, recordId RecordId, columnName ColumnName) (*GetFileResponse, error) + PutFile(ctx context.Context, dbBranchName DbBranchName, tableName TableName, recordId RecordId, columnName ColumnName, data []byte) (*FileResponse, error) DeleteFile(ctx context.Context, dbBranchName DbBranchName, tableName TableName, recordId RecordId, columnName ColumnName) (*FileResponse, error) + SetContentTypeHeader(value string) } func NewFilesClient(opts ...core.ClientOption) FilesClient { @@ -34,6 +35,10 @@ func NewFilesClient(opts ...core.ClientOption) FilesClient { } } +func (f *filesClient) SetContentTypeHeader(value string) { + f.header.Set("content-type", value) +} + type filesClient struct { baseURL string httpClient core.HTTPClient @@ -48,7 +53,7 @@ type filesClient struct { // The Record name // The Column name // The File Identifier -func (f *filesClient) GetFileItem(ctx context.Context, dbBranchName DbBranchName, tableName TableName, recordId RecordId, columnName ColumnName, fileId FileItemId) error { +func (f *filesClient) GetFileItem(ctx context.Context, dbBranchName DbBranchName, tableName TableName, recordId RecordId, columnName ColumnName, fileId FileItemId) (*GetFileResponse, error) { baseURL := "/" if f.baseURL != "" { baseURL = f.baseURL @@ -88,20 +93,21 @@ func (f *filesClient) GetFileItem(ctx context.Context, dbBranchName DbBranchName return apiError } + response := &GetFileResponse{} if err := core.DoRequest( ctx, f.httpClient, endpointURL, http.MethodGet, nil, - nil, + response, false, f.header, errorDecoder, ); err != nil { - return err + return nil, err } - return nil + return response, nil } // Uploads the file content to an array given the file ID @@ -112,7 +118,7 @@ func (f *filesClient) GetFileItem(ctx context.Context, dbBranchName DbBranchName // The Record name // The Column name // The File Identifier -func (f *filesClient) PutFileItem(ctx context.Context, dbBranchName DbBranchName, tableName TableName, recordId RecordId, columnName ColumnName, fileId FileItemId) (*FileResponse, error) { +func (f *filesClient) PutFileItem(ctx context.Context, dbBranchName DbBranchName, tableName TableName, recordId RecordId, columnName ColumnName, fileId FileItemId, data []byte) (*FileResponse, error) { baseURL := "/" if f.baseURL != "" { baseURL = f.baseURL @@ -165,7 +171,7 @@ func (f *filesClient) PutFileItem(ctx context.Context, dbBranchName DbBranchName f.httpClient, endpointURL, http.MethodPut, - nil, + data, &response, false, f.header, @@ -248,7 +254,7 @@ func (f *filesClient) DeleteFileItem(ctx context.Context, dbBranchName DbBranchN // The Table name // The Record name // The Column name -func (f *filesClient) GetFile(ctx context.Context, dbBranchName DbBranchName, tableName TableName, recordId RecordId, columnName ColumnName) error { +func (f *filesClient) GetFile(ctx context.Context, dbBranchName DbBranchName, tableName TableName, recordId RecordId, columnName ColumnName) (*GetFileResponse, error) { baseURL := "/" if f.baseURL != "" { baseURL = f.baseURL @@ -288,20 +294,21 @@ func (f *filesClient) GetFile(ctx context.Context, dbBranchName DbBranchName, ta return apiError } + response := &GetFileResponse{} if err := core.DoRequest( ctx, f.httpClient, endpointURL, http.MethodGet, nil, - nil, + response, false, f.header, errorDecoder, ); err != nil { - return err + return nil, err } - return nil + return response, nil } // Uploads the file content to the given file column @@ -311,7 +318,7 @@ func (f *filesClient) GetFile(ctx context.Context, dbBranchName DbBranchName, ta // The Table name // The Record name // The Column name -func (f *filesClient) PutFile(ctx context.Context, dbBranchName DbBranchName, tableName TableName, recordId RecordId, columnName ColumnName) (*FileResponse, error) { +func (f *filesClient) PutFile(ctx context.Context, dbBranchName DbBranchName, tableName TableName, recordId RecordId, columnName ColumnName, data []byte) (*FileResponse, error) { baseURL := "/" if f.baseURL != "" { baseURL = f.baseURL @@ -364,7 +371,7 @@ func (f *filesClient) PutFile(ctx context.Context, dbBranchName DbBranchName, ta f.httpClient, endpointURL, http.MethodPut, - nil, + data, &response, false, f.header, diff --git a/xata/internal/fern-workspace/generated/go/get_file_response.go b/xata/internal/fern-workspace/generated/go/get_file_response.go new file mode 100644 index 0000000..91aa169 --- /dev/null +++ b/xata/internal/fern-workspace/generated/go/get_file_response.go @@ -0,0 +1,11 @@ +package api + +type GetFileResponse struct { + Content []byte +} + +func (r *GetFileResponse) Write(p []byte) (n int, err error) { + r.Content = append(r.Content, p...) + + return len(p), nil +}