Repository: softwaremill/sttp-openai (scala)

Issue:
Delete file
Given uri:
`https://api.openai.com/v1/files/{file_id}`

Create sttp DELETE endpoint + tests

Docs reference
https://platform.openai.com/docs/api-reference/files/delete

Pull request:
Closes #14

Patch:
diff --git a/core/src/main/scala/sttp/openai/OpenAi.scala b/core/src/main/scala/sttp/openai/OpenAi.scala
index 73f07d63..2ed940fc 100644
--- a/core/src/main/scala/sttp/openai/OpenAi.scala
+++ b/core/src/main/scala/sttp/openai/OpenAi.scala
@@ -48,6 +48,16 @@ class OpenAi(authToken: String) {
       .get(OpenAIEndpoints.FilesEndpoint)
       .response(asJsonSnake[FilesResponse])
 
+  /** @param fileId
+    *   The ID of the file to use for this request.
+    * @return
+    *   Information about deleted file.
+    */
+  def deleteFile(fileId: String): Request[Either[ResponseException[String, Exception], DeletedFileData]] =
+    openApiAuthRequest
+      .delete(OpenAIEndpoints.deleteFileEndpoint(fileId))
+      .response(asJsonSnake[DeletedFileData])
+
   /** @param editRequestBody
     *   Edit request body
     *
@@ -90,7 +100,7 @@ private object OpenAIEndpoints {
   val EditEndpoint: Uri = uri"https://api.openai.com/v1/edits"
   val FilesEndpoint: Uri = uri"https://api.openai.com/v1/files"
   val ModelEndpoint: Uri = uri"https://api.openai.com/v1/models"
-
+  def deleteFileEndpoint(fileId: String): Uri = FilesEndpoint.addPath(fileId)
   def retrieveFileEndpoint(fileId: String): Uri = FilesEndpoint.addPath(fileId)
   def retrieveModelEndpoint(modelId: String): Uri = ModelEndpoint.addPath(modelId)
 }
diff --git a/core/src/main/scala/sttp/openai/requests/files/FilesResponseData.scala b/core/src/main/scala/sttp/openai/requests/files/FilesResponseData.scala
index 2cf54c3e..a90cd241 100644
--- a/core/src/main/scala/sttp/openai/requests/files/FilesResponseData.scala
+++ b/core/src/main/scala/sttp/openai/requests/files/FilesResponseData.scala
@@ -26,4 +26,14 @@ object FilesResponseData {
   object FilesResponse {
     implicit val filesResponseReadWriter: SnakePickle.ReadWriter[FilesResponse] = SnakePickle.macroRW[FilesResponse]
   }
+
+  case class DeletedFileData(
+      `object`: String,
+      id: String,
+      deleted: Boolean
+  )
+
+  object DeletedFileData {
+    implicit val deleteFileResponseReadWriter: SnakePickle.ReadWriter[DeletedFileData] = SnakePickle.macroRW[DeletedFileData]
+  }
 }


Test patch:
diff --git a/core/src/test/scala/sttp/openai/fixtures/FilesResponse.scala b/core/src/test/scala/sttp/openai/fixtures/FilesResponse.scala
index d66a745e..0d88b958 100644
--- a/core/src/test/scala/sttp/openai/fixtures/FilesResponse.scala
+++ b/core/src/test/scala/sttp/openai/fixtures/FilesResponse.scala
@@ -17,6 +17,12 @@ object FilesResponse {
                                 |  ]
                                 |}""".stripMargin
 
+  val deleteFileJsonResponse: String = """{
+                                         |  "object": "file",
+                                         |  "id": "file-tralala",
+                                         |  "deleted": true
+                                         |}""".stripMargin
+
   val retrieveFileJsonResponse: String = """{
                                            |  "object": "file",
                                            |  "id": "file-tralala",
diff --git a/core/src/test/scala/sttp/openai/requests/files/FilesResponseDataSpec.scala b/core/src/test/scala/sttp/openai/requests/files/FilesResponseDataSpec.scala
index 3021d450..d1a582fa 100644
--- a/core/src/test/scala/sttp/openai/requests/files/FilesResponseDataSpec.scala
+++ b/core/src/test/scala/sttp/openai/requests/files/FilesResponseDataSpec.scala
@@ -5,7 +5,7 @@ import org.scalatest.flatspec.AnyFlatSpec
 import org.scalatest.matchers.should.Matchers
 import sttp.openai.fixtures
 import sttp.openai.json.SttpUpickleApiExtension
-import sttp.openai.requests.files.FilesResponseData.{FileData, FilesResponse}
+import sttp.openai.requests.files.FilesResponseData.{DeletedFileData, FileData, FilesResponse}
 import sttp.openai.requests.files.FilesResponseData.FilesResponse._
 
 class FilesResponseDataSpec extends AnyFlatSpec with Matchers with EitherValues {
@@ -35,6 +35,23 @@ class FilesResponseDataSpec extends AnyFlatSpec with Matchers with EitherValues
     givenResponse.value shouldBe expectedResponse
   }
 
+  "Given delete file response as Json" should "be properly deserialized to case class" in {
+    // given
+    val listFilesResponse = fixtures.FilesResponse.deleteFileJsonResponse
+    val expectedResponse = DeletedFileData(
+      `object` = "file",
+      id = "file-tralala",
+      deleted = true
+    )
+
+    // when
+    val givenResponse: Either[Exception, DeletedFileData] =
+      SttpUpickleApiExtension.deserializeJsonSnake[DeletedFileData].apply(listFilesResponse)
+
+    // then
+    givenResponse.value shouldBe expectedResponse
+  }
+
   "Given retrieve file response as Json" should "be properly deserialized to case class" in {
     // given
     val retrieveFileJsonResponse = fixtures.FilesResponse.retrieveFileJsonResponse