From 86a8e52d08d0244a2bfb1e03712031c32d347813 Mon Sep 17 00:00:00 2001 From: William Cheng Date: Wed, 9 Apr 2025 17:19:06 +0800 Subject: [PATCH] Add tests for scala sttp client (jsonLibrary: circe) (#21061) * add tests for scala sttp circe * use jdk 11 * test with jdk 17 * fix * test in circleci * remove finch --- .github/workflows/samples-scala-jdk8.yaml | 38 ++++ .github/workflows/samples-scala.yaml | 8 +- CI/circle_parallel.sh | 1 + bin/configs/scala-sttp-circe.yaml | 15 ++ .../.openapi-generator-ignore | 23 +++ .../scala-sttp-circe/.openapi-generator/FILES | 18 ++ .../.openapi-generator/VERSION | 1 + .../petstore/scala-sttp-circe/README.md | 120 ++++++++++++ .../petstore/scala-sttp-circe/build.sbt | 18 ++ .../client/petstore/scala-sttp-circe/pom.xml | 34 ++++ .../scala-sttp-circe/project/build.properties | 1 + .../org/openapitools/client/api/FakeApi.scala | 42 ++++ .../org/openapitools/client/api/PetApi.scala | 177 +++++++++++++++++ .../openapitools/client/api/StoreApi.scala | 92 +++++++++ .../org/openapitools/client/api/UserApi.scala | 183 ++++++++++++++++++ .../core/AdditionalTypeSerializers.scala | 21 ++ .../client/core/DateSerializers.scala | 13 ++ .../client/core/JsonSupport.scala | 29 +++ .../client/model/ApiResponse.scala | 24 +++ .../openapitools/client/model/Category.scala | 23 +++ .../openapitools/client/model/EnumTest.scala | 38 ++++ .../org/openapitools/client/model/Order.scala | 39 ++++ .../org/openapitools/client/model/Pet.scala | 38 ++++ .../client/model/PropertyNameMapping.scala | 21 ++ .../org/openapitools/client/model/Tag.scala | 23 +++ .../org/openapitools/client/model/User.scala | 30 +++ 26 files changed, 1066 insertions(+), 4 deletions(-) create mode 100644 .github/workflows/samples-scala-jdk8.yaml create mode 100644 bin/configs/scala-sttp-circe.yaml create mode 100644 samples/client/petstore/scala-sttp-circe/.openapi-generator-ignore create mode 100644 samples/client/petstore/scala-sttp-circe/.openapi-generator/FILES create mode 100644 samples/client/petstore/scala-sttp-circe/.openapi-generator/VERSION create mode 100644 samples/client/petstore/scala-sttp-circe/README.md create mode 100644 samples/client/petstore/scala-sttp-circe/build.sbt create mode 100644 samples/client/petstore/scala-sttp-circe/pom.xml create mode 100644 samples/client/petstore/scala-sttp-circe/project/build.properties create mode 100644 samples/client/petstore/scala-sttp-circe/src/main/scala/org/openapitools/client/api/FakeApi.scala create mode 100644 samples/client/petstore/scala-sttp-circe/src/main/scala/org/openapitools/client/api/PetApi.scala create mode 100644 samples/client/petstore/scala-sttp-circe/src/main/scala/org/openapitools/client/api/StoreApi.scala create mode 100644 samples/client/petstore/scala-sttp-circe/src/main/scala/org/openapitools/client/api/UserApi.scala create mode 100644 samples/client/petstore/scala-sttp-circe/src/main/scala/org/openapitools/client/core/AdditionalTypeSerializers.scala create mode 100644 samples/client/petstore/scala-sttp-circe/src/main/scala/org/openapitools/client/core/DateSerializers.scala create mode 100644 samples/client/petstore/scala-sttp-circe/src/main/scala/org/openapitools/client/core/JsonSupport.scala create mode 100644 samples/client/petstore/scala-sttp-circe/src/main/scala/org/openapitools/client/model/ApiResponse.scala create mode 100644 samples/client/petstore/scala-sttp-circe/src/main/scala/org/openapitools/client/model/Category.scala create mode 100644 samples/client/petstore/scala-sttp-circe/src/main/scala/org/openapitools/client/model/EnumTest.scala create mode 100644 samples/client/petstore/scala-sttp-circe/src/main/scala/org/openapitools/client/model/Order.scala create mode 100644 samples/client/petstore/scala-sttp-circe/src/main/scala/org/openapitools/client/model/Pet.scala create mode 100644 samples/client/petstore/scala-sttp-circe/src/main/scala/org/openapitools/client/model/PropertyNameMapping.scala create mode 100644 samples/client/petstore/scala-sttp-circe/src/main/scala/org/openapitools/client/model/Tag.scala create mode 100644 samples/client/petstore/scala-sttp-circe/src/main/scala/org/openapitools/client/model/User.scala diff --git a/.github/workflows/samples-scala-jdk8.yaml b/.github/workflows/samples-scala-jdk8.yaml new file mode 100644 index 00000000000..526ceaa0fe0 --- /dev/null +++ b/.github/workflows/samples-scala-jdk8.yaml @@ -0,0 +1,38 @@ +name: Samples Scala/sbt (JDK8) + +on: + push: + paths: + - 'samples/server/petstore/scala-finch/**' + pull_request: + paths: + - 'samples/server/petstore/scala-finch/**' +jobs: + build: + name: Build scala-finch servers + runs-on: ubuntu-latest + strategy: + fail-fast: false + matrix: + sample: + # servers + - samples/server/petstore/scala-finch # cannot be tested with jdk11 + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-java@v4 + with: + distribution: 'temurin' + java-version: 8 + - name: Setup sbt launcher + uses: sbt/setup-sbt@v1 + - name: Cache maven dependencies + uses: actions/cache@v4 + env: + cache-name: maven-repository + with: + path: | + ~/.ivy2 + key: ${{ runner.os }}-${{ github.job }}-${{ env.cache-name }}-${{ hashFiles('**/build.sbt') }} + - name: Build and test + working-directory: ${{ matrix.sample }} + run: sbt -v +test diff --git a/.github/workflows/samples-scala.yaml b/.github/workflows/samples-scala.yaml index 5c2cb8bc04f..fb05cb378f4 100644 --- a/.github/workflows/samples-scala.yaml +++ b/.github/workflows/samples-scala.yaml @@ -20,18 +20,18 @@ jobs: matrix: sample: # clients - - 'samples/client/petstore/java/okhttp-gson' + - samples/client/petstore/java/okhttp-gson - samples/client/petstore/scalaz - samples/client/petstore/scala-pekko - samples/client/petstore/scala-http4s - #- samples/client/petstore/scala-sttp # won't pass while the same tests in circleci pass + #- samples/client/petstore/scala-sttp + #- samples/client/petstore/scala-sttp-circe # servers - samples/server/petstore/scala-lagom-server - samples/server/petstore/scala-play-server - samples/server/petstore/scala-akka-http-server - samples/server/petstore/scala-pekko-http-server - samples/server/petstore/scalatra - - samples/server/petstore/scala-finch # cannot be tested with jdk11 - samples/server/petstore/scala-http4s-server - samples/server/petstore/scala-cask steps: @@ -39,7 +39,7 @@ jobs: - uses: actions/setup-java@v4 with: distribution: 'temurin' - java-version: 8 + java-version: 11 - name: Setup sbt launcher uses: sbt/setup-sbt@v1 - name: Cache maven dependencies diff --git a/CI/circle_parallel.sh b/CI/circle_parallel.sh index 0d02dce87a7..9c55aeea28c 100755 --- a/CI/circle_parallel.sh +++ b/CI/circle_parallel.sh @@ -122,6 +122,7 @@ else (cd samples/client/petstore/scala-akka && mvn integration-test) (cd samples/client/petstore/scala-sttp && mvn integration-test) + (cd samples/client/petstore/scala-sttp-circe && mvn integration-test) (cd samples/client/petstore/scala-sttp4 && mvn integration-test) (cd samples/client/petstore/clojure && mvn integration-test) (cd samples/client/petstore/java/jersey2-java8 && mvn integration-test) diff --git a/bin/configs/scala-sttp-circe.yaml b/bin/configs/scala-sttp-circe.yaml new file mode 100644 index 00000000000..37771342b0f --- /dev/null +++ b/bin/configs/scala-sttp-circe.yaml @@ -0,0 +1,15 @@ +generatorName: scala-sttp +outputDir: samples/client/petstore/scala-sttp-circe +inputSpec: modules/openapi-generator/src/test/resources/3_0/scala/petstore.yaml +templateDir: modules/openapi-generator/src/main/resources/scala-sttp +nameMappings: + _type: "`underscoreType`" + type_: "`typeWithUnderscore`" + http_debug_operation: "`httpDebugOperation`" +parameterNameMappings: + _type: underscoreType + type_: typeWithUnderscore + http_debug_operation: httpDebugOperation +additionalProperties: + artifactId: scala-sttp-petstore + jsonLibrary: circe diff --git a/samples/client/petstore/scala-sttp-circe/.openapi-generator-ignore b/samples/client/petstore/scala-sttp-circe/.openapi-generator-ignore new file mode 100644 index 00000000000..7484ee590a3 --- /dev/null +++ b/samples/client/petstore/scala-sttp-circe/.openapi-generator-ignore @@ -0,0 +1,23 @@ +# OpenAPI Generator Ignore +# Generated by openapi-generator https://github.com/openapitools/openapi-generator + +# Use this file to prevent files from being overwritten by the generator. +# The patterns follow closely to .gitignore or .dockerignore. + +# As an example, the C# client generator defines ApiClient.cs. +# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line: +#ApiClient.cs + +# You can match any string of characters against a directory, file or extension with a single asterisk (*): +#foo/*/qux +# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux + +# You can recursively match patterns against a directory, file or extension with a double asterisk (**): +#foo/**/qux +# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux + +# You can also negate patterns with an exclamation (!). +# For example, you can ignore all files in a docs folder with the file extension .md: +#docs/*.md +# Then explicitly reverse the ignore rule for a single file: +#!docs/README.md diff --git a/samples/client/petstore/scala-sttp-circe/.openapi-generator/FILES b/samples/client/petstore/scala-sttp-circe/.openapi-generator/FILES new file mode 100644 index 00000000000..80b204182f1 --- /dev/null +++ b/samples/client/petstore/scala-sttp-circe/.openapi-generator/FILES @@ -0,0 +1,18 @@ +README.md +build.sbt +project/build.properties +src/main/scala/org/openapitools/client/api/FakeApi.scala +src/main/scala/org/openapitools/client/api/PetApi.scala +src/main/scala/org/openapitools/client/api/StoreApi.scala +src/main/scala/org/openapitools/client/api/UserApi.scala +src/main/scala/org/openapitools/client/core/AdditionalTypeSerializers.scala +src/main/scala/org/openapitools/client/core/DateSerializers.scala +src/main/scala/org/openapitools/client/core/JsonSupport.scala +src/main/scala/org/openapitools/client/model/ApiResponse.scala +src/main/scala/org/openapitools/client/model/Category.scala +src/main/scala/org/openapitools/client/model/EnumTest.scala +src/main/scala/org/openapitools/client/model/Order.scala +src/main/scala/org/openapitools/client/model/Pet.scala +src/main/scala/org/openapitools/client/model/PropertyNameMapping.scala +src/main/scala/org/openapitools/client/model/Tag.scala +src/main/scala/org/openapitools/client/model/User.scala diff --git a/samples/client/petstore/scala-sttp-circe/.openapi-generator/VERSION b/samples/client/petstore/scala-sttp-circe/.openapi-generator/VERSION new file mode 100644 index 00000000000..96cfbb19ae2 --- /dev/null +++ b/samples/client/petstore/scala-sttp-circe/.openapi-generator/VERSION @@ -0,0 +1 @@ +7.13.0-SNAPSHOT diff --git a/samples/client/petstore/scala-sttp-circe/README.md b/samples/client/petstore/scala-sttp-circe/README.md new file mode 100644 index 00000000000..201ce196b7d --- /dev/null +++ b/samples/client/petstore/scala-sttp-circe/README.md @@ -0,0 +1,120 @@ +# scala-sttp-petstore + +OpenAPI Petstore +- API version: 1.0.0 + - Generator version: 7.13.0-SNAPSHOT + +This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. + + +*Automatically generated by the [OpenAPI Generator](https://openapi-generator.tech)* + +## Requirements + +Building the API client library requires: +1. Java 1.7+ +2. Maven/Gradle/SBT + +## Installation + +To install the API client library to your local Maven repository, simply execute: + +```shell +mvn clean install +``` + +To deploy it to a remote Maven repository instead, configure the settings of the repository and execute: + +```shell +mvn clean deploy +``` + +Refer to the [OSSRH Guide](http://central.sonatype.org/pages/ossrh-guide.html) for more information. + +### Maven users + +Add this dependency to your project's POM: + +```xml + + org.openapitools + scala-sttp-petstore + 1.0.0 + compile + +``` + +### Gradle users + +Add this dependency to your project's build file: + +```groovy +compile "org.openapitools:scala-sttp-petstore:1.0.0" +``` + +### SBT users + +```scala +libraryDependencies += "org.openapitools" % "scala-sttp-petstore" % "1.0.0" +``` + +## Getting Started + +## Documentation for API Endpoints + +All URIs are relative to *http://petstore.swagger.io/v2* + +Class | Method | HTTP request | Description +------------ | ------------- | ------------- | ------------- +*FakeApi* | **getParameterNameMapping** | **GET** /fake/parameter-name-mapping | parameter name mapping test +*PetApi* | **addPet** | **POST** /pet | Add a new pet to the store +*PetApi* | **deletePet** | **DELETE** /pet/${petId} | Deletes a pet +*PetApi* | **findPetsByStatus** | **GET** /pet/findByStatus | Finds Pets by status +*PetApi* | **findPetsByTags** | **GET** /pet/findByTags | Finds Pets by tags +*PetApi* | **getPetById** | **GET** /pet/${petId} | Find pet by ID +*PetApi* | **updatePet** | **PUT** /pet | Update an existing pet +*PetApi* | **updatePetWithForm** | **POST** /pet/${petId} | Updates a pet in the store with form data +*PetApi* | **uploadFile** | **POST** /pet/${petId}/uploadImage | uploads an image +*StoreApi* | **deleteOrder** | **DELETE** /store/order/${orderId} | Delete purchase order by ID +*StoreApi* | **getInventory** | **GET** /store/inventory | Returns pet inventories by status +*StoreApi* | **getOrderById** | **GET** /store/order/${orderId} | Find purchase order by ID +*StoreApi* | **placeOrder** | **POST** /store/order | Place an order for a pet +*UserApi* | **createUser** | **POST** /user | Create user +*UserApi* | **createUsersWithArrayInput** | **POST** /user/createWithArray | Creates list of users with given input array +*UserApi* | **createUsersWithListInput** | **POST** /user/createWithList | Creates list of users with given input array +*UserApi* | **deleteUser** | **DELETE** /user/${username} | Delete user +*UserApi* | **getUserByName** | **GET** /user/${username} | Get user by user name +*UserApi* | **loginUser** | **GET** /user/login | Logs user into the system +*UserApi* | **logoutUser** | **GET** /user/logout | Logs out current logged in user session +*UserApi* | **updateUser** | **PUT** /user/${username} | Updated user + + +## Documentation for Models + + - [ApiResponse](ApiResponse.md) + - [Category](Category.md) + - [EnumTest](EnumTest.md) + - [Order](Order.md) + - [Pet](Pet.md) + - [PropertyNameMapping](PropertyNameMapping.md) + - [Tag](Tag.md) + - [User](User.md) + + + +## Documentation for Authorization + + +Authentication schemes defined for the API: + +### api_key + +- **Type**: API key +- **API key parameter name**: api_key +- **Location**: HTTP header + + +## Author + + + diff --git a/samples/client/petstore/scala-sttp-circe/build.sbt b/samples/client/petstore/scala-sttp-circe/build.sbt new file mode 100644 index 00000000000..8c3f82eb343 --- /dev/null +++ b/samples/client/petstore/scala-sttp-circe/build.sbt @@ -0,0 +1,18 @@ +version := "1.0.0" +name := "scala-sttp-petstore" +organization := "org.openapitools" + +scalaVersion := "2.13.16" +crossScalaVersions := Seq(scalaVersion.value, "2.12.20") + +libraryDependencies ++= Seq( + "com.softwaremill.sttp.client3" %% "core" % "3.3.18", + "com.softwaremill.sttp.client3" %% "circe" % "3.3.18", + "io.circe" %% "circe-generic" % "0.14.1" +) + +scalacOptions := Seq( + "-unchecked", + "-deprecation", + "-feature" +) diff --git a/samples/client/petstore/scala-sttp-circe/pom.xml b/samples/client/petstore/scala-sttp-circe/pom.xml new file mode 100644 index 00000000000..3584f791ac0 --- /dev/null +++ b/samples/client/petstore/scala-sttp-circe/pom.xml @@ -0,0 +1,34 @@ + + 4.0.0 + org.openapitools + scala-sttp-circe-petstore + pom + 1.0-SNAPSHOT + scala-sttp-circe-petstore + + + + org.codehaus.mojo + exec-maven-plugin + 1.5.0 + + + sbt-test + integration-test + + exec + + + sbt + + -ivy + ${user.home}/.ivy2 + test + + + + + + + + diff --git a/samples/client/petstore/scala-sttp-circe/project/build.properties b/samples/client/petstore/scala-sttp-circe/project/build.properties new file mode 100644 index 00000000000..cc68b53f1a3 --- /dev/null +++ b/samples/client/petstore/scala-sttp-circe/project/build.properties @@ -0,0 +1 @@ +sbt.version=1.10.11 diff --git a/samples/client/petstore/scala-sttp-circe/src/main/scala/org/openapitools/client/api/FakeApi.scala b/samples/client/petstore/scala-sttp-circe/src/main/scala/org/openapitools/client/api/FakeApi.scala new file mode 100644 index 00000000000..84ce29a85bc --- /dev/null +++ b/samples/client/petstore/scala-sttp-circe/src/main/scala/org/openapitools/client/api/FakeApi.scala @@ -0,0 +1,42 @@ +/** + * OpenAPI Petstore + * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. + * + * The version of the OpenAPI document: 1.0.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ +package org.openapitools.client.api + +import org.openapitools.client.core.JsonSupport._ +import sttp.client3._ +import sttp.model.Method + +object FakeApi { + def apply(baseUrl: String = "http://petstore.swagger.io/v2") = new FakeApi(baseUrl) +} + +class FakeApi(baseUrl: String) { + + /** + * Expected answers: + * code 200 : (OK) + * + * @param underscoreType _type + * @param `type` type + * @param typeWithUnderscore type_ + * @param httpDebugOption http debug option (to test parameter naming option) + */ + def getParameterNameMapping(underscoreType: Long, `type`: String, typeWithUnderscore: String, httpDebugOption: String +): Request[Either[ResponseException[String, Exception], Unit], Any] = + basicRequest + .method(Method.GET, uri"$baseUrl/fake/parameter-name-mapping?type=${ `type` }&http_debug_option=${ httpDebugOption }") + .contentType("application/json") + .header("_type", underscoreType.toString) + .header("type_", typeWithUnderscore.toString) + .response(asString.mapWithMetadata(ResponseAs.deserializeRightWithError(_ => Right(())))) + +} diff --git a/samples/client/petstore/scala-sttp-circe/src/main/scala/org/openapitools/client/api/PetApi.scala b/samples/client/petstore/scala-sttp-circe/src/main/scala/org/openapitools/client/api/PetApi.scala new file mode 100644 index 00000000000..a412877580d --- /dev/null +++ b/samples/client/petstore/scala-sttp-circe/src/main/scala/org/openapitools/client/api/PetApi.scala @@ -0,0 +1,177 @@ +/** + * OpenAPI Petstore + * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. + * + * The version of the OpenAPI document: 1.0.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ +package org.openapitools.client.api + +import org.openapitools.client.model.ApiResponse +import java.io.File +import org.openapitools.client.model.Pet +import org.openapitools.client.core.JsonSupport._ +import sttp.client3._ +import sttp.model.Method + +object PetApi { + def apply(baseUrl: String = "http://petstore.swagger.io/v2") = new PetApi(baseUrl) +} + +class PetApi(baseUrl: String) { + + /** + * + * + * Expected answers: + * code 200 : Pet (successful operation) + * code 405 : (Invalid input) + * + * @param pet Pet object that needs to be added to the store + */ + def addPet(pet: Pet +): Request[Either[ResponseException[String, Exception], Pet], Any] = + basicRequest + .method(Method.POST, uri"$baseUrl/pet") + .contentType("application/json") + .body(pet) + .response(asJson[Pet]) + + /** + * + * + * Expected answers: + * code 400 : (Invalid pet value) + * + * @param petId Pet id to delete + * @param apiKey + */ + def deletePet(petId: Long, apiKey: Option[String] = None +): Request[Either[ResponseException[String, Exception], Unit], Any] = + basicRequest + .method(Method.DELETE, uri"$baseUrl/pet/${petId}") + .contentType("application/json") + .header("api_key", apiKey.toString) + .response(asString.mapWithMetadata(ResponseAs.deserializeRightWithError(_ => Right(())))) + + /** + * Multiple status values can be provided with comma separated strings + * + * Expected answers: + * code 200 : Seq[Pet] (successful operation) + * code 400 : (Invalid status value) + * + * @param status Status values that need to be considered for filter + */ + def findPetsByStatus(status: Seq[String] +): Request[Either[ResponseException[String, Exception], Seq[Pet]], Any] = + basicRequest + .method(Method.GET, uri"$baseUrl/pet/findByStatus?status=${ status }") + .contentType("application/json") + .response(asJson[Seq[Pet]]) + + /** + * Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing. + * + * Expected answers: + * code 200 : Seq[Pet] (successful operation) + * code 400 : (Invalid tag value) + * + * @param tags Tags to filter by + */ + def findPetsByTags(tags: Seq[String] +): Request[Either[ResponseException[String, Exception], Seq[Pet]], Any] = + basicRequest + .method(Method.GET, uri"$baseUrl/pet/findByTags?tags=${ tags }") + .contentType("application/json") + .response(asJson[Seq[Pet]]) + + /** + * Returns a single pet + * + * Expected answers: + * code 200 : Pet (successful operation) + * code 400 : (Invalid ID supplied) + * code 404 : (Pet not found) + * + * Available security schemes: + * api_key (apiKey) + * + * @param petId ID of pet to return + */ + def getPetById(apiKey: String)(petId: Long +): Request[Either[ResponseException[String, Exception], Pet], Any] = + basicRequest + .method(Method.GET, uri"$baseUrl/pet/${petId}") + .contentType("application/json") + .header("api_key", apiKey) + .response(asJson[Pet]) + + /** + * + * + * Expected answers: + * code 200 : Pet (successful operation) + * code 400 : (Invalid ID supplied) + * code 404 : (Pet not found) + * code 405 : (Validation exception) + * + * @param pet Pet object that needs to be added to the store + */ + def updatePet(pet: Pet +): Request[Either[ResponseException[String, Exception], Pet], Any] = + basicRequest + .method(Method.PUT, uri"$baseUrl/pet") + .contentType("application/json") + .body(pet) + .response(asJson[Pet]) + + /** + * + * + * Expected answers: + * code 405 : (Invalid input) + * + * @param petId ID of pet that needs to be updated + * @param name Updated name of the pet + * @param status Updated status of the pet + */ + def updatePetWithForm(petId: Long, name: Option[String] = None, status: Option[String] = None +): Request[Either[ResponseException[String, Exception], Unit], Any] = + basicRequest + .method(Method.POST, uri"$baseUrl/pet/${petId}") + .contentType("application/x-www-form-urlencoded") + .body(Map( + "name" -> name, + "status" -> status + )) + .response(asString.mapWithMetadata(ResponseAs.deserializeRightWithError(_ => Right(())))) + + /** + * + * + * Expected answers: + * code 200 : ApiResponse (successful operation) + * + * @param petId ID of pet to update + * @param additionalMetadata Additional data to pass to server + * @param file file to upload + */ + def uploadFile(petId: Long, additionalMetadata: Option[String] = None, file: Option[File] = None +): Request[Either[ResponseException[String, Exception], ApiResponse], Any] = + basicRequest + .method(Method.POST, uri"$baseUrl/pet/${petId}/uploadImage") + .contentType("multipart/form-data") + .multipartBody(Seq( + additionalMetadata.map(multipart("additionalMetadata", _)) +, + file.map(multipartFile("file", _)) + + ).flatten) + .response(asJson[ApiResponse]) + +} diff --git a/samples/client/petstore/scala-sttp-circe/src/main/scala/org/openapitools/client/api/StoreApi.scala b/samples/client/petstore/scala-sttp-circe/src/main/scala/org/openapitools/client/api/StoreApi.scala new file mode 100644 index 00000000000..1cecc3117fe --- /dev/null +++ b/samples/client/petstore/scala-sttp-circe/src/main/scala/org/openapitools/client/api/StoreApi.scala @@ -0,0 +1,92 @@ +/** + * OpenAPI Petstore + * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. + * + * The version of the OpenAPI document: 1.0.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ +package org.openapitools.client.api + +import org.openapitools.client.model.Order +import org.openapitools.client.core.JsonSupport._ +import sttp.client3._ +import sttp.model.Method + +object StoreApi { + def apply(baseUrl: String = "http://petstore.swagger.io/v2") = new StoreApi(baseUrl) +} + +class StoreApi(baseUrl: String) { + + /** + * For valid response try integer IDs with value < 1000. Anything above 1000 or nonintegers will generate API errors + * + * Expected answers: + * code 400 : (Invalid ID supplied) + * code 404 : (Order not found) + * + * @param orderId ID of the order that needs to be deleted + */ + def deleteOrder(orderId: String +): Request[Either[ResponseException[String, Exception], Unit], Any] = + basicRequest + .method(Method.DELETE, uri"$baseUrl/store/order/${orderId}") + .contentType("application/json") + .response(asString.mapWithMetadata(ResponseAs.deserializeRightWithError(_ => Right(())))) + + /** + * Returns a map of status codes to quantities + * + * Expected answers: + * code 200 : Map[String, Int] (successful operation) + * + * Available security schemes: + * api_key (apiKey) + */ + def getInventory(apiKey: String)( +): Request[Either[ResponseException[String, Exception], Map[String, Int]], Any] = + basicRequest + .method(Method.GET, uri"$baseUrl/store/inventory") + .contentType("application/json") + .header("api_key", apiKey) + .response(asJson[Map[String, Int]]) + + /** + * For valid response try integer IDs with value <= 5 or > 10. Other values will generate exceptions + * + * Expected answers: + * code 200 : Order (successful operation) + * code 400 : (Invalid ID supplied) + * code 404 : (Order not found) + * + * @param orderId ID of pet that needs to be fetched + */ + def getOrderById(orderId: Long +): Request[Either[ResponseException[String, Exception], Order], Any] = + basicRequest + .method(Method.GET, uri"$baseUrl/store/order/${orderId}") + .contentType("application/json") + .response(asJson[Order]) + + /** + * + * + * Expected answers: + * code 200 : Order (successful operation) + * code 400 : (Invalid Order) + * + * @param order order placed for purchasing the pet + */ + def placeOrder(order: Order +): Request[Either[ResponseException[String, Exception], Order], Any] = + basicRequest + .method(Method.POST, uri"$baseUrl/store/order") + .contentType("application/json") + .body(order) + .response(asJson[Order]) + +} diff --git a/samples/client/petstore/scala-sttp-circe/src/main/scala/org/openapitools/client/api/UserApi.scala b/samples/client/petstore/scala-sttp-circe/src/main/scala/org/openapitools/client/api/UserApi.scala new file mode 100644 index 00000000000..d8eb054688c --- /dev/null +++ b/samples/client/petstore/scala-sttp-circe/src/main/scala/org/openapitools/client/api/UserApi.scala @@ -0,0 +1,183 @@ +/** + * OpenAPI Petstore + * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. + * + * The version of the OpenAPI document: 1.0.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ +package org.openapitools.client.api + +import java.time.OffsetDateTime +import org.openapitools.client.model.User +import org.openapitools.client.core.JsonSupport._ +import sttp.client3._ +import sttp.model.Method + +object UserApi { + def apply(baseUrl: String = "http://petstore.swagger.io/v2") = new UserApi(baseUrl) +} + +class UserApi(baseUrl: String) { + + /** + * This can only be done by the logged in user. + * + * Expected answers: + * code 0 : (successful operation) + * + * Available security schemes: + * api_key (apiKey) + * + * @param user Created user object + */ + def createUser(apiKey: String)(user: User +): Request[Either[ResponseException[String, Exception], Unit], Any] = + basicRequest + .method(Method.POST, uri"$baseUrl/user") + .contentType("application/json") + .header("api_key", apiKey) + .body(user) + .response(asString.mapWithMetadata(ResponseAs.deserializeRightWithError(_ => Right(())))) + + /** + * + * + * Expected answers: + * code 0 : (successful operation) + * + * Available security schemes: + * api_key (apiKey) + * + * @param user List of user object + */ + def createUsersWithArrayInput(apiKey: String)(user: Seq[User] +): Request[Either[ResponseException[String, Exception], Unit], Any] = + basicRequest + .method(Method.POST, uri"$baseUrl/user/createWithArray") + .contentType("application/json") + .header("api_key", apiKey) + .body(user) + .response(asString.mapWithMetadata(ResponseAs.deserializeRightWithError(_ => Right(())))) + + /** + * + * + * Expected answers: + * code 0 : (successful operation) + * + * Available security schemes: + * api_key (apiKey) + * + * @param user List of user object + */ + def createUsersWithListInput(apiKey: String)(user: Seq[User] +): Request[Either[ResponseException[String, Exception], Unit], Any] = + basicRequest + .method(Method.POST, uri"$baseUrl/user/createWithList") + .contentType("application/json") + .header("api_key", apiKey) + .body(user) + .response(asString.mapWithMetadata(ResponseAs.deserializeRightWithError(_ => Right(())))) + + /** + * This can only be done by the logged in user. + * + * Expected answers: + * code 400 : (Invalid username supplied) + * code 404 : (User not found) + * + * Available security schemes: + * api_key (apiKey) + * + * @param username The name that needs to be deleted + */ + def deleteUser(apiKey: String)(username: String +): Request[Either[ResponseException[String, Exception], Unit], Any] = + basicRequest + .method(Method.DELETE, uri"$baseUrl/user/${username}") + .contentType("application/json") + .header("api_key", apiKey) + .response(asString.mapWithMetadata(ResponseAs.deserializeRightWithError(_ => Right(())))) + + /** + * + * + * Expected answers: + * code 200 : User (successful operation) + * code 400 : (Invalid username supplied) + * code 404 : (User not found) + * + * @param username The name that needs to be fetched. Use user1 for testing. + */ + def getUserByName(username: String +): Request[Either[ResponseException[String, Exception], User], Any] = + basicRequest + .method(Method.GET, uri"$baseUrl/user/${username}") + .contentType("application/json") + .response(asJson[User]) + + /** + * + * + * Expected answers: + * code 200 : String (successful operation) + * Headers : + * Set-Cookie - Cookie authentication key for use with the `api_key` apiKey authentication. + * X-Rate-Limit - calls per hour allowed by the user + * X-Expires-After - date in UTC when token expires + * code 400 : (Invalid username/password supplied) + * + * @param username The user name for login + * @param password The password for login in clear text + */ + def loginUser(username: String, password: String +): Request[Either[ResponseException[String, Exception], String], Any] = + basicRequest + .method(Method.GET, uri"$baseUrl/user/login?username=${ username }&password=${ password }") + .contentType("application/json") + .response(asJson[String]) + + /** + * + * + * Expected answers: + * code 0 : (successful operation) + * + * Available security schemes: + * api_key (apiKey) + */ + def logoutUser(apiKey: String)( +): Request[Either[ResponseException[String, Exception], Unit], Any] = + basicRequest + .method(Method.GET, uri"$baseUrl/user/logout") + .contentType("application/json") + .header("api_key", apiKey) + .response(asString.mapWithMetadata(ResponseAs.deserializeRightWithError(_ => Right(())))) + + /** + * This can only be done by the logged in user. + * + * Expected answers: + * code 400 : (Invalid user supplied) + * code 404 : (User not found) + * + * Available security schemes: + * api_key (apiKey) + * + * @param username name that need to be deleted + * @param user Updated user object + */ + def updateUser(apiKey: String)(username: String, user: User +): Request[Either[ResponseException[String, Exception], Unit], Any] = + basicRequest + .method(Method.PUT, uri"$baseUrl/user/${username}") + .contentType("application/json") + .header("api_key", apiKey) + .body(user) + .response(asString.mapWithMetadata(ResponseAs.deserializeRightWithError(_ => Right(())))) + +} diff --git a/samples/client/petstore/scala-sttp-circe/src/main/scala/org/openapitools/client/core/AdditionalTypeSerializers.scala b/samples/client/petstore/scala-sttp-circe/src/main/scala/org/openapitools/client/core/AdditionalTypeSerializers.scala new file mode 100644 index 00000000000..137dbc248fa --- /dev/null +++ b/samples/client/petstore/scala-sttp-circe/src/main/scala/org/openapitools/client/core/AdditionalTypeSerializers.scala @@ -0,0 +1,21 @@ +package org.openapitools.client.core + +import java.net.{ URI, URISyntaxException } + +trait AdditionalTypeSerializers { + import io.circe._ + + implicit final lazy val URIDecoder: Decoder[URI] = Decoder.decodeString.emap(string => + try Right(new URI(string)) + catch { + case _: URISyntaxException => + Left("String could not be parsed as a URI reference, it violates RFC 2396.") + case _: NullPointerException => + Left("String is null.") + } + ) + + implicit final lazy val URIEncoder: Encoder[URI] = new Encoder[URI] { + final def apply(a: URI): Json = Json.fromString(a.toString) + } +} diff --git a/samples/client/petstore/scala-sttp-circe/src/main/scala/org/openapitools/client/core/DateSerializers.scala b/samples/client/petstore/scala-sttp-circe/src/main/scala/org/openapitools/client/core/DateSerializers.scala new file mode 100644 index 00000000000..1bed2914651 --- /dev/null +++ b/samples/client/petstore/scala-sttp-circe/src/main/scala/org/openapitools/client/core/DateSerializers.scala @@ -0,0 +1,13 @@ +package org.openapitools.client.core + +import java.time.{LocalDate, OffsetDateTime} +import java.time.format.DateTimeFormatter + +trait DateSerializers { + import io.circe.{Decoder, Encoder} + implicit val isoOffsetDateTimeDecoder: Decoder[OffsetDateTime] = Decoder.decodeOffsetDateTimeWithFormatter(DateTimeFormatter.ISO_OFFSET_DATE_TIME) + implicit val isoOffsetDateTimeEncoder: Encoder[OffsetDateTime] = Encoder.encodeOffsetDateTimeWithFormatter(DateTimeFormatter.ISO_OFFSET_DATE_TIME) + + implicit val localDateDecoder: Decoder[LocalDate] = Decoder.decodeLocalDateWithFormatter(DateTimeFormatter.ISO_LOCAL_DATE) + implicit val localDateEncoder: Encoder[LocalDate] = Encoder.encodeLocalDateWithFormatter(DateTimeFormatter.ISO_LOCAL_DATE) +} diff --git a/samples/client/petstore/scala-sttp-circe/src/main/scala/org/openapitools/client/core/JsonSupport.scala b/samples/client/petstore/scala-sttp-circe/src/main/scala/org/openapitools/client/core/JsonSupport.scala new file mode 100644 index 00000000000..4d3dfa52752 --- /dev/null +++ b/samples/client/petstore/scala-sttp-circe/src/main/scala/org/openapitools/client/core/JsonSupport.scala @@ -0,0 +1,29 @@ +/** + * OpenAPI Petstore + * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. + * + * The version of the OpenAPI document: 1.0.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ +package org.openapitools.client.core + +import org.openapitools.client.model._ +import io.circe.{Decoder, Encoder} +import io.circe.generic.AutoDerivation +import sttp.client3.circe.SttpCirceApi + +object JsonSupport extends SttpCirceApi with AutoDerivation with DateSerializers with AdditionalTypeSerializers { + + implicit val EnumTestSearchDecoder: Decoder[EnumTestEnums.Search] = Decoder.decodeEnumeration(EnumTestEnums.Search) + implicit val EnumTestSearchEncoder: Encoder[EnumTestEnums.Search] = Encoder.encodeEnumeration(EnumTestEnums.Search) + implicit val EnumTestSortByDecoder: Decoder[EnumTestEnums.SortBy] = Decoder.decodeEnumeration(EnumTestEnums.SortBy) + implicit val EnumTestSortByEncoder: Encoder[EnumTestEnums.SortBy] = Encoder.encodeEnumeration(EnumTestEnums.SortBy) + implicit val OrderStatusDecoder: Decoder[OrderEnums.Status] = Decoder.decodeEnumeration(OrderEnums.Status) + implicit val OrderStatusEncoder: Encoder[OrderEnums.Status] = Encoder.encodeEnumeration(OrderEnums.Status) + implicit val PetStatusDecoder: Decoder[PetEnums.Status] = Decoder.decodeEnumeration(PetEnums.Status) + implicit val PetStatusEncoder: Encoder[PetEnums.Status] = Encoder.encodeEnumeration(PetEnums.Status) +} diff --git a/samples/client/petstore/scala-sttp-circe/src/main/scala/org/openapitools/client/model/ApiResponse.scala b/samples/client/petstore/scala-sttp-circe/src/main/scala/org/openapitools/client/model/ApiResponse.scala new file mode 100644 index 00000000000..b0abb512265 --- /dev/null +++ b/samples/client/petstore/scala-sttp-circe/src/main/scala/org/openapitools/client/model/ApiResponse.scala @@ -0,0 +1,24 @@ +/** + * OpenAPI Petstore + * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. + * + * The version of the OpenAPI document: 1.0.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ +package org.openapitools.client.model + + + /** + * An uploaded response + * Describes the result of uploading an image resource + */ +case class ApiResponse( + code: Option[Int] = None, + `type`: Option[String] = None, + message: Option[String] = None +) + diff --git a/samples/client/petstore/scala-sttp-circe/src/main/scala/org/openapitools/client/model/Category.scala b/samples/client/petstore/scala-sttp-circe/src/main/scala/org/openapitools/client/model/Category.scala new file mode 100644 index 00000000000..169acc49cef --- /dev/null +++ b/samples/client/petstore/scala-sttp-circe/src/main/scala/org/openapitools/client/model/Category.scala @@ -0,0 +1,23 @@ +/** + * OpenAPI Petstore + * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. + * + * The version of the OpenAPI document: 1.0.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ +package org.openapitools.client.model + + + /** + * Pet category + * A category for a pet + */ +case class Category( + id: Option[Long] = None, + name: Option[String] = None +) + diff --git a/samples/client/petstore/scala-sttp-circe/src/main/scala/org/openapitools/client/model/EnumTest.scala b/samples/client/petstore/scala-sttp-circe/src/main/scala/org/openapitools/client/model/EnumTest.scala new file mode 100644 index 00000000000..96fad75f85d --- /dev/null +++ b/samples/client/petstore/scala-sttp-circe/src/main/scala/org/openapitools/client/model/EnumTest.scala @@ -0,0 +1,38 @@ +/** + * OpenAPI Petstore + * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. + * + * The version of the OpenAPI document: 1.0.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ +package org.openapitools.client.model + + +case class EnumTest( + emails: Option[Seq[String]] = None, + search: Option[EnumTestEnums.Search] = None, + sortBy: Option[Seq[EnumTestEnums.SortBy]] = None +) + +object EnumTestEnums { + + type Search = Search.Value + type SortBy = SortBy.Value + object Search extends Enumeration { + val FirstName = Value("first_name") + val LastName = Value("last_name") + val Email = Value("email") + val FullName = Value("full_name") + } + + object SortBy extends Enumeration { + val FirstName = Value("first_name") + val LastName = Value("last_name") + val Email = Value("email") + } + +} diff --git a/samples/client/petstore/scala-sttp-circe/src/main/scala/org/openapitools/client/model/Order.scala b/samples/client/petstore/scala-sttp-circe/src/main/scala/org/openapitools/client/model/Order.scala new file mode 100644 index 00000000000..9e805e256b2 --- /dev/null +++ b/samples/client/petstore/scala-sttp-circe/src/main/scala/org/openapitools/client/model/Order.scala @@ -0,0 +1,39 @@ +/** + * OpenAPI Petstore + * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. + * + * The version of the OpenAPI document: 1.0.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ +package org.openapitools.client.model + +import java.time.OffsetDateTime + + /** + * Pet Order + * An order for a pets from the pet store + */ +case class Order( + id: Option[Long] = None, + petId: Option[Long] = None, + quantity: Option[Int] = None, + shipDate: Option[OffsetDateTime] = None, + /* Order Status */ + status: Option[OrderEnums.Status] = None, + complete: Option[Boolean] = None +) + +object OrderEnums { + + type Status = Status.Value + object Status extends Enumeration { + val Placed = Value("placed") + val Approved = Value("approved") + val Delivered = Value("delivered") + } + +} diff --git a/samples/client/petstore/scala-sttp-circe/src/main/scala/org/openapitools/client/model/Pet.scala b/samples/client/petstore/scala-sttp-circe/src/main/scala/org/openapitools/client/model/Pet.scala new file mode 100644 index 00000000000..3cbab605128 --- /dev/null +++ b/samples/client/petstore/scala-sttp-circe/src/main/scala/org/openapitools/client/model/Pet.scala @@ -0,0 +1,38 @@ +/** + * OpenAPI Petstore + * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. + * + * The version of the OpenAPI document: 1.0.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ +package org.openapitools.client.model + + + /** + * a Pet + * A pet for sale in the pet store + */ +case class Pet( + id: Option[Long] = None, + category: Option[Category] = None, + name: String, + photoUrls: Seq[String], + tags: Option[Seq[Tag]] = None, + /* pet status in the store */ + status: Option[PetEnums.Status] = None +) + +object PetEnums { + + type Status = Status.Value + object Status extends Enumeration { + val Available = Value("available") + val Pending = Value("pending") + val Sold = Value("sold") + } + +} diff --git a/samples/client/petstore/scala-sttp-circe/src/main/scala/org/openapitools/client/model/PropertyNameMapping.scala b/samples/client/petstore/scala-sttp-circe/src/main/scala/org/openapitools/client/model/PropertyNameMapping.scala new file mode 100644 index 00000000000..3782f4c12be --- /dev/null +++ b/samples/client/petstore/scala-sttp-circe/src/main/scala/org/openapitools/client/model/PropertyNameMapping.scala @@ -0,0 +1,21 @@ +/** + * OpenAPI Petstore + * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. + * + * The version of the OpenAPI document: 1.0.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ +package org.openapitools.client.model + + +case class PropertyNameMapping( + `httpDebugOperation`: Option[String] = None, + `underscoreType`: Option[String] = None, + `type`: Option[String] = None, + `typeWithUnderscore`: Option[String] = None +) + diff --git a/samples/client/petstore/scala-sttp-circe/src/main/scala/org/openapitools/client/model/Tag.scala b/samples/client/petstore/scala-sttp-circe/src/main/scala/org/openapitools/client/model/Tag.scala new file mode 100644 index 00000000000..c2020246658 --- /dev/null +++ b/samples/client/petstore/scala-sttp-circe/src/main/scala/org/openapitools/client/model/Tag.scala @@ -0,0 +1,23 @@ +/** + * OpenAPI Petstore + * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. + * + * The version of the OpenAPI document: 1.0.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ +package org.openapitools.client.model + + + /** + * Pet Tag + * A tag for a pet + */ +case class Tag( + id: Option[Long] = None, + name: Option[String] = None +) + diff --git a/samples/client/petstore/scala-sttp-circe/src/main/scala/org/openapitools/client/model/User.scala b/samples/client/petstore/scala-sttp-circe/src/main/scala/org/openapitools/client/model/User.scala new file mode 100644 index 00000000000..6977180bcce --- /dev/null +++ b/samples/client/petstore/scala-sttp-circe/src/main/scala/org/openapitools/client/model/User.scala @@ -0,0 +1,30 @@ +/** + * OpenAPI Petstore + * This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters. + * + * The version of the OpenAPI document: 1.0.0 + * + * + * NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + * https://openapi-generator.tech + * Do not edit the class manually. + */ +package org.openapitools.client.model + + + /** + * a User + * A User who is purchasing from the pet store + */ +case class User( + id: Option[Long] = None, + username: Option[String] = None, + firstName: Option[String] = None, + lastName: Option[String] = None, + email: Option[String] = None, + password: Option[String] = None, + phone: Option[String] = None, + /* User Status */ + userStatus: Option[Int] = None +) +