From 961c2e44d1b8d1e877b8bd3724e6bfabc0be550a Mon Sep 17 00:00:00 2001 From: "Jenny G. L." <5222542+JennyLeahy@users.noreply.github.com> Date: Fri, 8 Nov 2024 04:15:32 -0500 Subject: [PATCH] [scala][client]: scala-http4s: minor improvement (enum companion method, remove implicit, error handling) (#19901) * [scala][http4s][client]: add enum method; remove implicit * improve error handling * more enum enhancement * remove unused * update samle * avoid breaking change --------- Co-authored-by: Jenny Leahy --- .../main/resources/scala-http4s/api.mustache | 2 +- .../scala-http4s/baseClient.mustache | 2 +- .../scala-http4s/errorResponsePart.mustache | 2 +- .../scala-http4s/failedRequest.mustache | 18 +++++----- .../scala-http4s/jsonSupports.mustache | 4 +-- .../scala-http4s/methodParameters.mustache | 2 +- .../resources/scala-http4s/model.mustache | 13 +++---- .../scala-http4s/modelsPackage.mustache | 36 ++++++++++--------- .../scala-http4s/responseState.mustache | 2 +- .../openapitools/client/apis/BaseClient.scala | 2 +- .../client/apis/JsonSupports.scala | 4 +-- .../org/openapitools/client/apis/PetApi.scala | 4 +-- .../openapitools/client/apis/StoreApi.scala | 4 +-- .../openapitools/client/apis/UserApi.scala | 24 ++++++------- ...FindPetsByStatusStatusParameterInner.scala | 13 +++---- .../client/models/OrderStatus.scala | 13 +++---- .../client/models/PetStatus.scala | 13 +++---- .../client/models/_FailedRequest.scala | 18 +++++----- .../openapitools/client/models/package.scala | 36 ++++++++++--------- 19 files changed, 112 insertions(+), 100 deletions(-) diff --git a/modules/openapi-generator/src/main/resources/scala-http4s/api.mustache b/modules/openapi-generator/src/main/resources/scala-http4s/api.mustache index 339ecc9bd37f..a0bf72123d07 100644 --- a/modules/openapi-generator/src/main/resources/scala-http4s/api.mustache +++ b/modules/openapi-generator/src/main/resources/scala-http4s/api.mustache @@ -48,7 +48,7 @@ class {{classname}}EndpointsImpl[F[*]: Concurrent]( formParameters = {{^hasFormParams}}None,{{/hasFormParams}}{{#hasFormParams}}formParameters,{{/hasFormParams}} queryParameters = {{^hasQueryParams}}Nil,{{/hasQueryParams}}{{#hasQueryParams}}queryParameters,{{/hasQueryParams}} requestHeaders = requestHeaders, - auth = {{#authMethods}}Some(auth){{/authMethods}}{{^authMethods}}None{{/authMethods}}) { + auth = {{#authMethods.0}}Some(auth){{/authMethods.0}}{{^authMethods}}None{{/authMethods}}) { {{>responseState}} } } diff --git a/modules/openapi-generator/src/main/resources/scala-http4s/baseClient.mustache b/modules/openapi-generator/src/main/resources/scala-http4s/baseClient.mustache index aa325edc0a6e..b10d24f790d4 100644 --- a/modules/openapi-generator/src/main/resources/scala-http4s/baseClient.mustache +++ b/modules/openapi-generator/src/main/resources/scala-http4s/baseClient.mustache @@ -33,7 +33,7 @@ abstract class BaseClient[F[*]: Concurrent]( queryParameters: Seq[(String, Any)] = Nil, requestHeaders: Seq[(String, String)] = Nil, auth: Option[_Authorization] = None - )(handler: Response[F] => F[U])(implicit encoder: Encoder[T]): F[U] = { + )(handler: Response[F] => F[U])(using Encoder[T]): F[U] = { val m = Method.fromString(method) match { case Right(m) => m diff --git a/modules/openapi-generator/src/main/resources/scala-http4s/errorResponsePart.mustache b/modules/openapi-generator/src/main/resources/scala-http4s/errorResponsePart.mustache index b879b7607f69..2955e8ce765c 100644 --- a/modules/openapi-generator/src/main/resources/scala-http4s/errorResponsePart.mustache +++ b/modules/openapi-generator/src/main/resources/scala-http4s/errorResponsePart.mustache @@ -1 +1 @@ -{{#dataType}}case r if r.status.code == {{code}} => parseJson[F, {{dataType}}]("{{dataType}}", r).flatMap(res => Concurrent[F].raiseError(_FailedRequest(r.status.code, res.asJson.noSpaces))){{/dataType}}{{^dataType}}case r if r.status.code == {{code}} => Concurrent[F].raiseError(_FailedRequest(r.status.code, r.status.reason)){{/dataType}} \ No newline at end of file +{{#dataType}}case r if r.status.code == {{code}} => parseJson[F, {{dataType}}]("{{dataType}}", r).flatMap(res => Concurrent[F].raiseError(_FailedRequest(r.status.code, r.status.reason, Some(res.asJson)))){{/dataType}}{{^dataType}}case r if r.status.code == {{code}} => Concurrent[F].raiseError(_FailedRequest(r.status.code, r.status.reason)){{/dataType}} \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/scala-http4s/failedRequest.mustache b/modules/openapi-generator/src/main/resources/scala-http4s/failedRequest.mustache index a2845b037741..40f8aeb1cfd2 100644 --- a/modules/openapi-generator/src/main/resources/scala-http4s/failedRequest.mustache +++ b/modules/openapi-generator/src/main/resources/scala-http4s/failedRequest.mustache @@ -1,21 +1,21 @@ {{>licenseInfo}} package {{modelPackage}} -import io.circe.* -import io.circe.Decoder.* -import io.circe.Encoder.* +import io.circe.{Decoder, Encoder, Json} import io.circe.syntax.* -case class _FailedRequest(code: Int, message: String) extends Exception(s"Server return status code: $code; message: $message") +case class _FailedRequest(code: Int, message: String, body: Option[Json] = None) + extends Exception(s"Server returned status $code; message: $message; body: ${body.map(_.noSpaces).getOrElse("")}") object _FailedRequest { given encoderFailedRequest: Encoder[_FailedRequest] = Encoder.instance { t => Json.fromFields{ Seq( - "code" -> t.code.asJson, - "message" -> t.message.asJson - ) + Some("code" -> t.code.asJson), + Some("message" -> t.message.asJson), + t.body.map(x => "body" -> x) + ).flatten } } @@ -23,9 +23,11 @@ object _FailedRequest { for { code <- c.downField("code").as[Int] message <- c.downField("message").as[String] + body <- c.downField("body").as[Option[Json]] } yield _FailedRequest( code = code, - message = message + message = message, + body = body ) } diff --git a/modules/openapi-generator/src/main/resources/scala-http4s/jsonSupports.mustache b/modules/openapi-generator/src/main/resources/scala-http4s/jsonSupports.mustache index 6b6ae135e041..bc7ef4243813 100644 --- a/modules/openapi-generator/src/main/resources/scala-http4s/jsonSupports.mustache +++ b/modules/openapi-generator/src/main/resources/scala-http4s/jsonSupports.mustache @@ -10,9 +10,9 @@ import {{modelPackage}}.* object JsonSupports { - implicit def circeJsonEncoder[F[*]: Concurrent, A](implicit encoder: Encoder[A]): EntityEncoder[F, A] = + implicit def circeJsonEncoder[F[*]: Concurrent, A](using Encoder[A]): EntityEncoder[F, A] = http4sCirce.jsonEncoderOf[F, A] - implicit def circeJsonDecoder[F[*]: Concurrent, A](implicit decoder: Decoder[A]): EntityDecoder[F, A] = + implicit def circeJsonDecoder[F[*]: Concurrent, A](using Decoder[A]): EntityDecoder[F, A] = http4sCirce.jsonOf[F, A] def parseJson[F[*]: Concurrent, T]( diff --git a/modules/openapi-generator/src/main/resources/scala-http4s/methodParameters.mustache b/modules/openapi-generator/src/main/resources/scala-http4s/methodParameters.mustache index c80db9ee5675..d36f95ac243e 100644 --- a/modules/openapi-generator/src/main/resources/scala-http4s/methodParameters.mustache +++ b/modules/openapi-generator/src/main/resources/scala-http4s/methodParameters.mustache @@ -1 +1 @@ -{{#allParams}}{{paramName}}: {{#required}}{{dataType}}{{/required}}{{^required}}Option[{{dataType}}]{{/required}}{{^defaultValue}}{{^required}} = None{{/required}}{{/defaultValue}}{{^-last}}, {{/-last}}{{/allParams}}{{#authMethods.0}}{{#isApiKey}})(implicit auth: _Authorization.ApiKey{{/isApiKey}}{{#isBasic}}{{#isBasicBasic}})(implicit auth: _Authorization.Basic{{/isBasicBasic}}{{#isBasicBearer}})(implicit auth: _Authorization.Bearer{{/isBasicBearer}}{{/isBasic}}{{/authMethods.0}} \ No newline at end of file +{{#allParams}}{{paramName}}: {{#required}}{{dataType}}{{/required}}{{^required}}Option[{{dataType}}]{{/required}}{{^defaultValue}}{{^required}} = None{{/required}}{{/defaultValue}}{{^-last}}, {{/-last}}{{/allParams}}{{#authMethods.0}}{{#isApiKey}})(using auth: _Authorization.ApiKey{{/isApiKey}}{{#isBasic}}{{#isBasicBasic}})(using auth: _Authorization.Basic{{/isBasicBasic}}{{#isBasicBearer}})(using auth: _Authorization.Bearer{{/isBasicBearer}}{{/isBasic}}{{/authMethods.0}} \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/scala-http4s/model.mustache b/modules/openapi-generator/src/main/resources/scala-http4s/model.mustache index 912925158182..118fdb0fabd0 100644 --- a/modules/openapi-generator/src/main/resources/scala-http4s/model.mustache +++ b/modules/openapi-generator/src/main/resources/scala-http4s/model.mustache @@ -26,13 +26,14 @@ enum {{classname}}(val value: String) { } object {{classname}} { - given decoder{{classname}}: Decoder[{{classname}}] = - Decoder.decodeString.map(str => {{classname}}.values.find(_.value == str) - .getOrElse(throw java.lang.IllegalArgumentException(s"{{classname}} enum case not found: $str")) - ) - given encoder{{classname}}: Encoder[{{classname}}] = - Encoder.encodeString.contramap[{{classname}}](_.value) + def withValueOpt(value: String): Option[{{classname}}] = {{classname}}.values.find(_.value == value) + def withValue(value: String): {{classname}} = + withValueOpt(value).getOrElse(throw java.lang.IllegalArgumentException(s"{{classname}} enum case not found: $value")) + + given decoder{{classname}}: Decoder[{{classname}}] = Decoder.decodeString.map(withValue) + given encoder{{classname}}: Encoder[{{classname}}] = Encoder.encodeString.contramap[{{classname}}](_.value) + } {{/isEnum}} {{^isEnum}} diff --git a/modules/openapi-generator/src/main/resources/scala-http4s/modelsPackage.mustache b/modules/openapi-generator/src/main/resources/scala-http4s/modelsPackage.mustache index 5211e1dd5cc7..3c99460f4b8a 100644 --- a/modules/openapi-generator/src/main/resources/scala-http4s/modelsPackage.mustache +++ b/modules/openapi-generator/src/main/resources/scala-http4s/modelsPackage.mustache @@ -1,32 +1,34 @@ {{>licenseInfo}} package {{packageName}} -import io.circe.{Decoder, Encoder} +import io.circe.{Decoder, Encoder, Json} +import java.time.{Instant, LocalDate, OffsetDateTime} +import java.util.UUID package object models { - given decodeUUID: Decoder[_root_.java.util.UUID] = - Decoder.decodeString.map(str => _root_.java.util.UUID.fromString(str)) + given decodeUUID: Decoder[UUID] = + Decoder.decodeString.map(str => UUID.fromString(str)) - given encodeUUID: Encoder[_root_.java.util.UUID] = - Encoder.encodeString.contramap[_root_.java.util.UUID](uuid => uuid.toString) + given encodeUUID: Encoder[UUID] = + Encoder.encodeString.contramap[UUID](uuid => uuid.toString) - given decodeInstant: Decoder[_root_.java.time.Instant] = - Decoder.decodeString.map(str => _root_.java.time.OffsetDateTime.parse(str).toInstant) + given decodeInstant: Decoder[Instant] = + Decoder.decodeString.map(str => OffsetDateTime.parse(str).toInstant) - given encodeInstant: Encoder[_root_.java.time.Instant] = - Encoder.encodeString.contramap[_root_.java.time.Instant](_.toString) + given encodeInstant: Encoder[Instant] = + Encoder.encodeString.contramap[Instant](_.toString) - given decodeLocalDate: Decoder[_root_.java.time.LocalDate] = - Decoder.decodeString.map(str => _root_.java.time.LocalDate.parse(str)) + given decodeLocalDate: Decoder[LocalDate] = + Decoder.decodeString.map(str => LocalDate.parse(str)) - given encodeLocalDate: Encoder[_root_.java.time.LocalDate] = - Encoder.encodeString.contramap[_root_.java.time.LocalDate](_.toString) + given encodeLocalDate: Encoder[LocalDate] = + Encoder.encodeString.contramap[LocalDate](_.toString) - given decodeJson: Decoder[io.circe.Json] = - Decoder.decodeString.map(str => io.circe.Json.fromString(str)) + given decodeJson: Decoder[Json] = + Decoder.decodeString.map(str => Json.fromString(str)) - given encodeJson: Encoder[io.circe.Json] = - Encoder.encodeString.contramap[io.circe.Json](_.toString) + given encodeJson: Encoder[Json] = + Encoder.encodeString.contramap[Json](_.toString) } \ No newline at end of file diff --git a/modules/openapi-generator/src/main/resources/scala-http4s/responseState.mustache b/modules/openapi-generator/src/main/resources/scala-http4s/responseState.mustache index b8aa1645d66f..b2372c5691da 100644 --- a/modules/openapi-generator/src/main/resources/scala-http4s/responseState.mustache +++ b/modules/openapi-generator/src/main/resources/scala-http4s/responseState.mustache @@ -2,4 +2,4 @@ {{>successResponsePart}}{{/is2xx}}{{^is2xx}}{{#is3xx}} {{>successResponsePart}}{{/is3xx}}{{^is3xx}}{{^isDefault}} {{>errorResponsePart}}{{/isDefault}}{{#isDefault}} - {{#dataType}}case r => parseJson[F, {{dataType}}]("{{dataType}}", r).flatMap(res => Concurrent[F].raiseError(_FailedRequest(r.status.code, res.asJson.noSpaces))){{/dataType}}{{^dataType}}case r => Concurrent[F].raiseError(_FailedRequest(r.status.code, r.status.reason)){{/dataType}}{{/isDefault}}{{/is3xx}}{{/is2xx}}{{/responses}}{{/hasOnlyDefaultResponse}} \ No newline at end of file + {{#dataType}}case r => parseJson[F, {{dataType}}]("{{dataType}}", r).flatMap(res => Concurrent[F].raiseError(_FailedRequest(r.status.code, r.status.reason, Some(res.asJson)))){{/dataType}}{{^dataType}}case r => Concurrent[F].raiseError(_FailedRequest(r.status.code, r.status.reason)){{/dataType}}{{/isDefault}}{{/is3xx}}{{/is2xx}}{{/responses}}{{/hasOnlyDefaultResponse}} \ No newline at end of file diff --git a/samples/client/petstore/scala-http4s/src/main/scala/org/openapitools/client/apis/BaseClient.scala b/samples/client/petstore/scala-http4s/src/main/scala/org/openapitools/client/apis/BaseClient.scala index aafc08df2b37..8a8b663010e8 100644 --- a/samples/client/petstore/scala-http4s/src/main/scala/org/openapitools/client/apis/BaseClient.scala +++ b/samples/client/petstore/scala-http4s/src/main/scala/org/openapitools/client/apis/BaseClient.scala @@ -42,7 +42,7 @@ abstract class BaseClient[F[*]: Concurrent]( queryParameters: Seq[(String, Any)] = Nil, requestHeaders: Seq[(String, String)] = Nil, auth: Option[_Authorization] = None - )(handler: Response[F] => F[U])(implicit encoder: Encoder[T]): F[U] = { + )(handler: Response[F] => F[U])(using Encoder[T]): F[U] = { val m = Method.fromString(method) match { case Right(m) => m diff --git a/samples/client/petstore/scala-http4s/src/main/scala/org/openapitools/client/apis/JsonSupports.scala b/samples/client/petstore/scala-http4s/src/main/scala/org/openapitools/client/apis/JsonSupports.scala index 70dd487ea314..c2bfa09bd6c3 100644 --- a/samples/client/petstore/scala-http4s/src/main/scala/org/openapitools/client/apis/JsonSupports.scala +++ b/samples/client/petstore/scala-http4s/src/main/scala/org/openapitools/client/apis/JsonSupports.scala @@ -19,9 +19,9 @@ import org.openapitools.client.models.* object JsonSupports { - implicit def circeJsonEncoder[F[*]: Concurrent, A](implicit encoder: Encoder[A]): EntityEncoder[F, A] = + implicit def circeJsonEncoder[F[*]: Concurrent, A](using Encoder[A]): EntityEncoder[F, A] = http4sCirce.jsonEncoderOf[F, A] - implicit def circeJsonDecoder[F[*]: Concurrent, A](implicit decoder: Decoder[A]): EntityDecoder[F, A] = + implicit def circeJsonDecoder[F[*]: Concurrent, A](using Decoder[A]): EntityDecoder[F, A] = http4sCirce.jsonOf[F, A] def parseJson[F[*]: Concurrent, T]( diff --git a/samples/client/petstore/scala-http4s/src/main/scala/org/openapitools/client/apis/PetApi.scala b/samples/client/petstore/scala-http4s/src/main/scala/org/openapitools/client/apis/PetApi.scala index e562c0edfb3c..8d609c269140 100644 --- a/samples/client/petstore/scala-http4s/src/main/scala/org/openapitools/client/apis/PetApi.scala +++ b/samples/client/petstore/scala-http4s/src/main/scala/org/openapitools/client/apis/PetApi.scala @@ -27,7 +27,7 @@ trait PetApiEndpoints[F[*]] { def deletePet(petId: Long, apiKey: Option[String] = None): F[Unit] def findPetsByStatus(status: Seq[FindPetsByStatusStatusParameterInner]): F[Seq[Pet]] def findPetsByTags(tags: Seq[String]): F[Seq[Pet]] - def getPetById(petId: Long)(implicit auth: _Authorization.ApiKey): F[Pet] + def getPetById(petId: Long)(using auth: _Authorization.ApiKey): F[Pet] def updatePet(pet: Pet): F[Pet] def updatePetWithForm(petId: Long, name: Option[String] = None, status: Option[String] = None): F[Unit] def uploadFile(petId: Long, additionalMetadata: Option[String] = None, file: Option[File] = None): F[ApiResponse] @@ -126,7 +126,7 @@ class PetApiEndpointsImpl[F[*]: Concurrent]( } } - override def getPetById(petId: Long)(implicit auth: _Authorization.ApiKey): F[Pet] = { + override def getPetById(petId: Long)(using auth: _Authorization.ApiKey): F[Pet] = { val requestHeaders = Seq( Some("Content-Type" -> "application/json") ).flatten diff --git a/samples/client/petstore/scala-http4s/src/main/scala/org/openapitools/client/apis/StoreApi.scala b/samples/client/petstore/scala-http4s/src/main/scala/org/openapitools/client/apis/StoreApi.scala index a0c33365cc0a..7a59c8537442 100644 --- a/samples/client/petstore/scala-http4s/src/main/scala/org/openapitools/client/apis/StoreApi.scala +++ b/samples/client/petstore/scala-http4s/src/main/scala/org/openapitools/client/apis/StoreApi.scala @@ -20,7 +20,7 @@ import org.openapitools.client.models.* trait StoreApiEndpoints[F[*]] { def deleteOrder(orderId: String): F[Unit] - def getInventory()(implicit auth: _Authorization.ApiKey): F[Map[String, Int]] + def getInventory()(using auth: _Authorization.ApiKey): F[Map[String, Int]] def getOrderById(orderId: Long): F[Order] def placeOrder(order: Order): F[Order] @@ -55,7 +55,7 @@ class StoreApiEndpointsImpl[F[*]: Concurrent]( } } - override def getInventory()(implicit auth: _Authorization.ApiKey): F[Map[String, Int]] = { + override def getInventory()(using auth: _Authorization.ApiKey): F[Map[String, Int]] = { val requestHeaders = Seq( Some("Content-Type" -> "application/json") ).flatten diff --git a/samples/client/petstore/scala-http4s/src/main/scala/org/openapitools/client/apis/UserApi.scala b/samples/client/petstore/scala-http4s/src/main/scala/org/openapitools/client/apis/UserApi.scala index 749cb93d4b80..c9e34f8278c8 100644 --- a/samples/client/petstore/scala-http4s/src/main/scala/org/openapitools/client/apis/UserApi.scala +++ b/samples/client/petstore/scala-http4s/src/main/scala/org/openapitools/client/apis/UserApi.scala @@ -21,14 +21,14 @@ import org.openapitools.client.models.* trait UserApiEndpoints[F[*]] { - def createUser(user: User)(implicit auth: _Authorization.ApiKey): F[Unit] - def createUsersWithArrayInput(user: Seq[User])(implicit auth: _Authorization.ApiKey): F[Unit] - def createUsersWithListInput(user: Seq[User])(implicit auth: _Authorization.ApiKey): F[Unit] - def deleteUser(username: String)(implicit auth: _Authorization.ApiKey): F[Unit] + def createUser(user: User)(using auth: _Authorization.ApiKey): F[Unit] + def createUsersWithArrayInput(user: Seq[User])(using auth: _Authorization.ApiKey): F[Unit] + def createUsersWithListInput(user: Seq[User])(using auth: _Authorization.ApiKey): F[Unit] + def deleteUser(username: String)(using auth: _Authorization.ApiKey): F[Unit] def getUserByName(username: String): F[User] def loginUser(username: String, password: String): F[String] - def logoutUser()(implicit auth: _Authorization.ApiKey): F[Unit] - def updateUser(username: String, user: User)(implicit auth: _Authorization.ApiKey): F[Unit] + def logoutUser()(using auth: _Authorization.ApiKey): F[Unit] + def updateUser(username: String, user: User)(using auth: _Authorization.ApiKey): F[Unit] } @@ -42,7 +42,7 @@ class UserApiEndpointsImpl[F[*]: Concurrent]( import io.circe.syntax.EncoderOps import cats.implicits.toFlatMapOps - override def createUser(user: User)(implicit auth: _Authorization.ApiKey): F[Unit] = { + override def createUser(user: User)(using auth: _Authorization.ApiKey): F[Unit] = { val requestHeaders = Seq( Some("Content-Type" -> "application/json") ).flatten @@ -59,7 +59,7 @@ class UserApiEndpointsImpl[F[*]: Concurrent]( } } - override def createUsersWithArrayInput(user: Seq[User])(implicit auth: _Authorization.ApiKey): F[Unit] = { + override def createUsersWithArrayInput(user: Seq[User])(using auth: _Authorization.ApiKey): F[Unit] = { val requestHeaders = Seq( Some("Content-Type" -> "application/json") ).flatten @@ -76,7 +76,7 @@ class UserApiEndpointsImpl[F[*]: Concurrent]( } } - override def createUsersWithListInput(user: Seq[User])(implicit auth: _Authorization.ApiKey): F[Unit] = { + override def createUsersWithListInput(user: Seq[User])(using auth: _Authorization.ApiKey): F[Unit] = { val requestHeaders = Seq( Some("Content-Type" -> "application/json") ).flatten @@ -93,7 +93,7 @@ class UserApiEndpointsImpl[F[*]: Concurrent]( } } - override def deleteUser(username: String)(implicit auth: _Authorization.ApiKey): F[Unit] = { + override def deleteUser(username: String)(using auth: _Authorization.ApiKey): F[Unit] = { val requestHeaders = Seq( Some("Content-Type" -> "application/json") ).flatten @@ -155,7 +155,7 @@ class UserApiEndpointsImpl[F[*]: Concurrent]( } } - override def logoutUser()(implicit auth: _Authorization.ApiKey): F[Unit] = { + override def logoutUser()(using auth: _Authorization.ApiKey): F[Unit] = { val requestHeaders = Seq( Some("Content-Type" -> "application/json") ).flatten @@ -172,7 +172,7 @@ class UserApiEndpointsImpl[F[*]: Concurrent]( } } - override def updateUser(username: String, user: User)(implicit auth: _Authorization.ApiKey): F[Unit] = { + override def updateUser(username: String, user: User)(using auth: _Authorization.ApiKey): F[Unit] = { val requestHeaders = Seq( Some("Content-Type" -> "application/json") ).flatten diff --git a/samples/client/petstore/scala-http4s/src/main/scala/org/openapitools/client/models/FindPetsByStatusStatusParameterInner.scala b/samples/client/petstore/scala-http4s/src/main/scala/org/openapitools/client/models/FindPetsByStatusStatusParameterInner.scala index e2534970a07e..0a5f572417c4 100644 --- a/samples/client/petstore/scala-http4s/src/main/scala/org/openapitools/client/models/FindPetsByStatusStatusParameterInner.scala +++ b/samples/client/petstore/scala-http4s/src/main/scala/org/openapitools/client/models/FindPetsByStatusStatusParameterInner.scala @@ -24,12 +24,13 @@ enum FindPetsByStatusStatusParameterInner(val value: String) { } object FindPetsByStatusStatusParameterInner { - given decoderFindPetsByStatusStatusParameterInner: Decoder[FindPetsByStatusStatusParameterInner] = - Decoder.decodeString.map(str => FindPetsByStatusStatusParameterInner.values.find(_.value == str) - .getOrElse(throw java.lang.IllegalArgumentException(s"FindPetsByStatusStatusParameterInner enum case not found: $str")) - ) - given encoderFindPetsByStatusStatusParameterInner: Encoder[FindPetsByStatusStatusParameterInner] = - Encoder.encodeString.contramap[FindPetsByStatusStatusParameterInner](_.value) + def withValueOpt(value: String): Option[FindPetsByStatusStatusParameterInner] = FindPetsByStatusStatusParameterInner.values.find(_.value == value) + def withValue(value: String): FindPetsByStatusStatusParameterInner = + withValueOpt(value).getOrElse(throw java.lang.IllegalArgumentException(s"FindPetsByStatusStatusParameterInner enum case not found: $value")) + + given decoderFindPetsByStatusStatusParameterInner: Decoder[FindPetsByStatusStatusParameterInner] = Decoder.decodeString.map(withValue) + given encoderFindPetsByStatusStatusParameterInner: Encoder[FindPetsByStatusStatusParameterInner] = Encoder.encodeString.contramap[FindPetsByStatusStatusParameterInner](_.value) + } diff --git a/samples/client/petstore/scala-http4s/src/main/scala/org/openapitools/client/models/OrderStatus.scala b/samples/client/petstore/scala-http4s/src/main/scala/org/openapitools/client/models/OrderStatus.scala index 96a360806ea3..38922d97a0d1 100644 --- a/samples/client/petstore/scala-http4s/src/main/scala/org/openapitools/client/models/OrderStatus.scala +++ b/samples/client/petstore/scala-http4s/src/main/scala/org/openapitools/client/models/OrderStatus.scala @@ -24,12 +24,13 @@ enum OrderStatus(val value: String) { } object OrderStatus { - given decoderOrderStatus: Decoder[OrderStatus] = - Decoder.decodeString.map(str => OrderStatus.values.find(_.value == str) - .getOrElse(throw java.lang.IllegalArgumentException(s"OrderStatus enum case not found: $str")) - ) - given encoderOrderStatus: Encoder[OrderStatus] = - Encoder.encodeString.contramap[OrderStatus](_.value) + def withValueOpt(value: String): Option[OrderStatus] = OrderStatus.values.find(_.value == value) + def withValue(value: String): OrderStatus = + withValueOpt(value).getOrElse(throw java.lang.IllegalArgumentException(s"OrderStatus enum case not found: $value")) + + given decoderOrderStatus: Decoder[OrderStatus] = Decoder.decodeString.map(withValue) + given encoderOrderStatus: Encoder[OrderStatus] = Encoder.encodeString.contramap[OrderStatus](_.value) + } diff --git a/samples/client/petstore/scala-http4s/src/main/scala/org/openapitools/client/models/PetStatus.scala b/samples/client/petstore/scala-http4s/src/main/scala/org/openapitools/client/models/PetStatus.scala index 5300aff9dc6d..2e28131df660 100644 --- a/samples/client/petstore/scala-http4s/src/main/scala/org/openapitools/client/models/PetStatus.scala +++ b/samples/client/petstore/scala-http4s/src/main/scala/org/openapitools/client/models/PetStatus.scala @@ -24,12 +24,13 @@ enum PetStatus(val value: String) { } object PetStatus { - given decoderPetStatus: Decoder[PetStatus] = - Decoder.decodeString.map(str => PetStatus.values.find(_.value == str) - .getOrElse(throw java.lang.IllegalArgumentException(s"PetStatus enum case not found: $str")) - ) - given encoderPetStatus: Encoder[PetStatus] = - Encoder.encodeString.contramap[PetStatus](_.value) + def withValueOpt(value: String): Option[PetStatus] = PetStatus.values.find(_.value == value) + def withValue(value: String): PetStatus = + withValueOpt(value).getOrElse(throw java.lang.IllegalArgumentException(s"PetStatus enum case not found: $value")) + + given decoderPetStatus: Decoder[PetStatus] = Decoder.decodeString.map(withValue) + given encoderPetStatus: Encoder[PetStatus] = Encoder.encodeString.contramap[PetStatus](_.value) + } diff --git a/samples/client/petstore/scala-http4s/src/main/scala/org/openapitools/client/models/_FailedRequest.scala b/samples/client/petstore/scala-http4s/src/main/scala/org/openapitools/client/models/_FailedRequest.scala index e883a521dc2f..3c3964aa29c9 100644 --- a/samples/client/petstore/scala-http4s/src/main/scala/org/openapitools/client/models/_FailedRequest.scala +++ b/samples/client/petstore/scala-http4s/src/main/scala/org/openapitools/client/models/_FailedRequest.scala @@ -10,21 +10,21 @@ */ package org.openapitools.client.models -import io.circe.* -import io.circe.Decoder.* -import io.circe.Encoder.* +import io.circe.{Decoder, Encoder, Json} import io.circe.syntax.* -case class _FailedRequest(code: Int, message: String) extends Exception(s"Server return status code: $code; message: $message") +case class _FailedRequest(code: Int, message: String, body: Option[Json] = None) + extends Exception(s"Server returned status $code; message: $message; body: ${body.map(_.noSpaces).getOrElse("")}") object _FailedRequest { given encoderFailedRequest: Encoder[_FailedRequest] = Encoder.instance { t => Json.fromFields{ Seq( - "code" -> t.code.asJson, - "message" -> t.message.asJson - ) + Some("code" -> t.code.asJson), + Some("message" -> t.message.asJson), + t.body.map(x => "body" -> x) + ).flatten } } @@ -32,9 +32,11 @@ object _FailedRequest { for { code <- c.downField("code").as[Int] message <- c.downField("message").as[String] + body <- c.downField("body").as[Option[Json]] } yield _FailedRequest( code = code, - message = message + message = message, + body = body ) } diff --git a/samples/client/petstore/scala-http4s/src/main/scala/org/openapitools/client/models/package.scala b/samples/client/petstore/scala-http4s/src/main/scala/org/openapitools/client/models/package.scala index b3a8d920c308..17fb2a647027 100644 --- a/samples/client/petstore/scala-http4s/src/main/scala/org/openapitools/client/models/package.scala +++ b/samples/client/petstore/scala-http4s/src/main/scala/org/openapitools/client/models/package.scala @@ -10,32 +10,34 @@ */ package org.openapitools.client -import io.circe.{Decoder, Encoder} +import io.circe.{Decoder, Encoder, Json} +import java.time.{Instant, LocalDate, OffsetDateTime} +import java.util.UUID package object models { - given decodeUUID: Decoder[_root_.java.util.UUID] = - Decoder.decodeString.map(str => _root_.java.util.UUID.fromString(str)) + given decodeUUID: Decoder[UUID] = + Decoder.decodeString.map(str => UUID.fromString(str)) - given encodeUUID: Encoder[_root_.java.util.UUID] = - Encoder.encodeString.contramap[_root_.java.util.UUID](uuid => uuid.toString) + given encodeUUID: Encoder[UUID] = + Encoder.encodeString.contramap[UUID](uuid => uuid.toString) - given decodeInstant: Decoder[_root_.java.time.Instant] = - Decoder.decodeString.map(str => _root_.java.time.OffsetDateTime.parse(str).toInstant) + given decodeInstant: Decoder[Instant] = + Decoder.decodeString.map(str => OffsetDateTime.parse(str).toInstant) - given encodeInstant: Encoder[_root_.java.time.Instant] = - Encoder.encodeString.contramap[_root_.java.time.Instant](_.toString) + given encodeInstant: Encoder[Instant] = + Encoder.encodeString.contramap[Instant](_.toString) - given decodeLocalDate: Decoder[_root_.java.time.LocalDate] = - Decoder.decodeString.map(str => _root_.java.time.LocalDate.parse(str)) + given decodeLocalDate: Decoder[LocalDate] = + Decoder.decodeString.map(str => LocalDate.parse(str)) - given encodeLocalDate: Encoder[_root_.java.time.LocalDate] = - Encoder.encodeString.contramap[_root_.java.time.LocalDate](_.toString) + given encodeLocalDate: Encoder[LocalDate] = + Encoder.encodeString.contramap[LocalDate](_.toString) - given decodeJson: Decoder[io.circe.Json] = - Decoder.decodeString.map(str => io.circe.Json.fromString(str)) + given decodeJson: Decoder[Json] = + Decoder.decodeString.map(str => Json.fromString(str)) - given encodeJson: Encoder[io.circe.Json] = - Encoder.encodeString.contramap[io.circe.Json](_.toString) + given encodeJson: Encoder[Json] = + Encoder.encodeString.contramap[Json](_.toString) } \ No newline at end of file