diff --git a/README.md b/README.md index 067a5ff901..4876f1c2dc 100644 --- a/README.md +++ b/README.md @@ -128,7 +128,7 @@ tapir documentation is available at [tapir.softwaremill.com](http://tapir.softwa Add the following dependency: ```sbt -"com.softwaremill.sttp.tapir" %% "tapir-core" % "1.1.4" +"com.softwaremill.sttp.tapir" %% "tapir-core" % "1.2.0" ``` Then, import: diff --git a/generated-doc/out/adopters/kensu.png b/generated-doc/out/adopters/kensu.png new file mode 100644 index 0000000000..fc4a924363 Binary files /dev/null and b/generated-doc/out/adopters/kensu.png differ diff --git a/generated-doc/out/adopters/swisscom.svg b/generated-doc/out/adopters/swisscom.svg new file mode 100644 index 0000000000..d1dff03c99 --- /dev/null +++ b/generated-doc/out/adopters/swisscom.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/generated-doc/out/client/http4s.md b/generated-doc/out/client/http4s.md index ec215910f3..52a335f979 100644 --- a/generated-doc/out/client/http4s.md +++ b/generated-doc/out/client/http4s.md @@ -3,7 +3,7 @@ Add the dependency: ```scala -"com.softwaremill.sttp.tapir" %% "tapir-http4s-client" % "1.1.4" +"com.softwaremill.sttp.tapir" %% "tapir-http4s-client" % "1.2.0" ``` To interpret an endpoint definition as an `org.http4s.Request[F]`, import: diff --git a/generated-doc/out/client/play.md b/generated-doc/out/client/play.md index bb886c7593..1d183ddaca 100644 --- a/generated-doc/out/client/play.md +++ b/generated-doc/out/client/play.md @@ -3,7 +3,7 @@ Add the dependency: ```scala -"com.softwaremill.sttp.tapir" %% "tapir-play-client" % "1.1.4" +"com.softwaremill.sttp.tapir" %% "tapir-play-client" % "1.2.0" ``` To make requests using an endpoint definition using the [play client](https://github.com/playframework/play-ws), import: diff --git a/generated-doc/out/client/sttp.md b/generated-doc/out/client/sttp.md index a29874cef1..8b87bdde03 100644 --- a/generated-doc/out/client/sttp.md +++ b/generated-doc/out/client/sttp.md @@ -3,7 +3,7 @@ Add the dependency: ```scala -"com.softwaremill.sttp.tapir" %% "tapir-sttp-client" % "1.1.4" +"com.softwaremill.sttp.tapir" %% "tapir-sttp-client" % "1.2.0" ``` To make requests using an endpoint definition using the [sttp client](https://github.com/softwaremill/sttp), import: @@ -102,7 +102,7 @@ In this case add the following dependencies (note the [`%%%`](https://www.scala- instead of the usual `%%`): ```scala -"com.softwaremill.sttp.tapir" %%% "tapir-sttp-client" % "1.1.4" +"com.softwaremill.sttp.tapir" %%% "tapir-sttp-client" % "1.2.0" "io.github.cquiroz" %%% "scala-java-time" % "2.2.0" // implementations of java.time classes for Scala.JS ``` diff --git a/generated-doc/out/docs/asyncapi.md b/generated-doc/out/docs/asyncapi.md index ab54e0d7e5..ae14defa16 100644 --- a/generated-doc/out/docs/asyncapi.md +++ b/generated-doc/out/docs/asyncapi.md @@ -3,7 +3,7 @@ To use, add the following dependencies: ```scala -"com.softwaremill.sttp.tapir" %% "tapir-asyncapi-docs" % "1.1.4" +"com.softwaremill.sttp.tapir" %% "tapir-asyncapi-docs" % "1.2.0" "com.softwaremill.sttp.apispec" %% "asyncapi-circe-yaml" % "..." // see https://github.com/softwaremill/sttp-apispec ``` diff --git a/generated-doc/out/docs/openapi.md b/generated-doc/out/docs/openapi.md index 5030b8953f..dc00c8c6c7 100644 --- a/generated-doc/out/docs/openapi.md +++ b/generated-doc/out/docs/openapi.md @@ -13,7 +13,7 @@ these steps can be done separately, giving you complete control over the process To generate OpenAPI documentation and expose it using the Swagger UI in a single step, first add the dependency: ```scala -"com.softwaremill.sttp.tapir" %% "tapir-swagger-ui-bundle" % "1.1.4" +"com.softwaremill.sttp.tapir" %% "tapir-swagger-ui-bundle" % "1.2.0" ``` Then, you can interpret a list of endpoints using `SwaggerInterpreter`. The result will be a list of file-serving @@ -55,7 +55,7 @@ for details. Similarly as above, you'll need the following dependency: ```scala -"com.softwaremill.sttp.tapir" %% "tapir-redoc-bundle" % "1.1.4" +"com.softwaremill.sttp.tapir" %% "tapir-redoc-bundle" % "1.2.0" ``` And the server endpoints can be generated using the `sttp.tapir.redoc.bundle.RedocInterpreter` class. @@ -65,7 +65,7 @@ And the server endpoints can be generated using the `sttp.tapir.redoc.bundle.Red To generate the docs in the OpenAPI yaml format, add the following dependencies: ```scala -"com.softwaremill.sttp.tapir" %% "tapir-openapi-docs" % "1.1.4" +"com.softwaremill.sttp.tapir" %% "tapir-openapi-docs" % "1.2.0" "com.softwaremill.sttp.apispec" %% "openapi-circe-yaml" % "..." // see https://github.com/softwaremill/sttp-apispec ``` @@ -133,7 +133,7 @@ For example, generating the OpenAPI 3.1.0 YAML string can be achieved by perform Firstly add dependencies: ```scala -"com.softwaremill.sttp.tapir" %% "tapir-openapi-docs" % "1.1.4" +"com.softwaremill.sttp.tapir" %% "tapir-openapi-docs" % "1.2.0" "com.softwaremill.sttp.apispec" %% "openapi-circe-yaml" % "..." // see https://github.com/softwaremill/sttp-apispec ``` @@ -164,12 +164,12 @@ The modules `tapir-swagger-ui` and `tapir-redoc` contain server endpoint definit yaml format, will expose it using the given context path. To use, add as a dependency either `tapir-swagger-ui`: ```scala -"com.softwaremill.sttp.tapir" %% "tapir-swagger-ui" % "1.1.4" +"com.softwaremill.sttp.tapir" %% "tapir-swagger-ui" % "1.2.0" ``` or `tapir-redoc`: ```scala -"com.softwaremill.sttp.tapir" %% "tapir-redoc" % "1.1.4" +"com.softwaremill.sttp.tapir" %% "tapir-redoc" % "1.2.0" ``` Then, you'll need to pass the server endpoints to your server interpreter. For example, using akka-http: diff --git a/generated-doc/out/endpoint/basics.md b/generated-doc/out/endpoint/basics.md index 856ba00023..b48fe41fe1 100644 --- a/generated-doc/out/endpoint/basics.md +++ b/generated-doc/out/endpoint/basics.md @@ -30,7 +30,7 @@ import sttp.tapir._ type PublicEndpoint[I, E, O, -R] = Endpoint[Unit, I, E, O, R] ``` -A public endpoint has two inputs of types `UUID` and `Int`, upon error returns a `String`, and on normal +A public endpoint that has two inputs of types `UUID` and `Int`, upon error returns a `String`, and on normal completion returns a `User`, would have the type: @@ -40,7 +40,7 @@ import sttp.tapir._ val userEndpoint: PublicEndpoint[(UUID, Int), String, User, Any] = ??? ``` -You can think of an endpoint as a function, which takes input parameters of type `A` and `I` and returns a result of type +You can think of an endpoint as a function which takes input parameters of type `A` and `I` and returns a result of type `Either[E, O]`. ### Infallible endpoints @@ -49,7 +49,7 @@ Note that the empty `endpoint` description maps no values to either error and su are still represented and allowed to occur. In case of the error output, the single member of the unit type, `(): Unit`, maps to an empty-body `400 Bad Request`. -If you prefer to use an endpoint description, where errors cannot happen, use +If you prefer to use an endpoint description where errors cannot happen use `infallibleEndpoint: PublicEndpoint[Unit, Nothing, Unit, Any]`. This might be useful when interpreting endpoints [as a client](../client/sttp.md). diff --git a/generated-doc/out/endpoint/codecs.md b/generated-doc/out/endpoint/codecs.md index b4a9cd303a..5337dc3998 100644 --- a/generated-doc/out/endpoint/codecs.md +++ b/generated-doc/out/endpoint/codecs.md @@ -29,8 +29,8 @@ integer. If any of this fails, a decode failure will be reported. However, in some cases codecs aren't looked up as implicit values, instead being created from simpler components, which themselves are looked up as implicits. This is the case e.g. for json bodies specified using `jsonBody`. The rationale -behind such a design is that this provides better error reporting, in case the implicit components, used to create the -codec, are missing. Consult the signature of the specific input/output to learn what are its implicit requirements. +behind such a design is that this provides better error reporting, in case the implicit components used to create the +codec are missing. Consult the signature of the specific input/output to learn what are its implicit requirements. ## Decode failures diff --git a/generated-doc/out/endpoint/customtypes.md b/generated-doc/out/endpoint/customtypes.md index 4aef3f7a31..3a4ae194e5 100644 --- a/generated-doc/out/endpoint/customtypes.md +++ b/generated-doc/out/endpoint/customtypes.md @@ -36,7 +36,7 @@ information: * schema (for documentation and validation) * codec format (`text/plain`, `application/json` etc.) -This might be quite a lot of work, that's why it's usually easier to map over an existing codec. To do that, you'll +This might be quite a lot of work; that's why it's usually easier to map over an existing codec. To do that, you'll need to provide two mappings: * a `decode` method which decodes the lower-level type into the custom type, optionally reporting decode failures @@ -88,7 +88,7 @@ implicit val myIdCodec: PlainCodec[MyId] = Codec.string.mapDecode(decode)(encode usually better to define a codec for that type. ``` -Then, you can use the new codec e.g. to obtain an id from a query parameter, or a path segment: +Then, you can use the new codec; e.g. to obtain an id from a query parameter, or a path segment: ```scala endpoint.in(query[MyId]("myId")) @@ -96,11 +96,6 @@ endpoint.in(query[MyId]("myId")) endpoint.in(path[MyId]) ``` -### Codecs for enumerations - -In some cases, codecs for enumerations can be derived, but need to be defined as an implicit value by hand, because -you'll need to provide some parameters. See the section on [enumerations validators](validation.md) for more details. - ## Next Read on about [deriving schemas](schemas.md). diff --git a/generated-doc/out/endpoint/enumerations.md b/generated-doc/out/endpoint/enumerations.md new file mode 100644 index 0000000000..f783adfcdc --- /dev/null +++ b/generated-doc/out/endpoint/enumerations.md @@ -0,0 +1,265 @@ +# Enumerations + +tapir supports both `scala.Enumeration`-based enumerations, as well as enumerations created as a `sealed` family of +`object`s (in Scala 2) or Scala 3 `enum`s where all cases are parameterless. Other enumeration implementations are +also supported by integrating with [third-party libraries](integrations.md). + +Depending on the context, in which an enumeration is used, you'll need to create either a [`Schema`](schemas.md), or +a [`Codec`](codecs.md) (which includes a schema). + +## Using enumerations as values of query parameters, headers, path components + +When using an enumeration in such a context, a `Codec` has to be defined for the enumeration. + +tapir needs to know how to decode a low-level value into the enumeration, and how to encode an enumeration value into +the low-level representation. This is handled by the codec's `decode` and `encode` functions. + +Moreover, each codec is associated with a schema (which describes the low-level representation for documentation). +A schema, in turn, can have associated validators. In case of enumerations, a `Validator.Enumeration` should be added. +The validator contains a list of all possible values (which are used when generating the docs). + +The enumeration validator doesn't provide any important run-time behavior, as if a value can be represented as an +enumeration in the first place (by the process of decoding), it is valid. However, the codec's `decode` should return a +`DecodeResult.InvalidValue` with a reference to the validator, if validation fails. This way, the +[server](../server/errors.md) can provide appropriate user-friendly messages. + +### scala.Enumeration support + +A default codec for any subtype of `scala.Enumeration#Value` is provided as an implicit/given value. Such a codec +assumes that the low-level representation of the enumeration is a string. Encoding is done using `.toString`, while +decoding performs a case-insensitive search through the enumeration's values. For example: + +```scala +import sttp.tapir._ + +object Features extends Enumeration { + type Feature = Value + + val A: Feature = Value("a") + val B: Feature = Value("b") + val C: Feature = Value("c") +} + +query[Features.Feature]("feature") +``` + +This can be customised (e.g. if the encoding/decoding should behave differently, or if the low-level representation +should be a number), by defining an implicit codec: + +```scala +import sttp.tapir.Codec.PlainCodec + +implicit val customFeatureCodec: PlainCodec[Features.Feature] = + Codec.derivedEnumerationValueCustomise[Int, Features.Feature]( + { + case 0 => Some(Features.A) + case 1 => Some(Features.B) + case 2 => Some(Features.C) + case _ => None + }, + { + case Features.A => 0 + case Features.B => 1 + case Features.C => 2 + case _ => -1 + }, + None + ) +``` + +### Sealed families / enum support + +When the enumeration is defined as a sealed family containing only objects, or a Scala 3 `enum` with all cases +parameterless, a codec has to be provided as an implicit value by hand. + +There is no implicit/given codec provided by default, as there's no way to constrain the type for which such an implicit +would be considered by the compiler. + +For example: + +```scala +import sttp.tapir._ +import sttp.tapir.Codec.PlainCodec + +sealed trait Feature +object Feature { + case object A extends Feature + case object B extends Feature + case object C extends Feature +} + +implicit val featureCodec: PlainCodec[Feature] = + Codec.derivedEnumeration[String, Feature].defaultStringBased + +query[Feature]("feature") +``` + +The `.defaultStringBased` method creates a default codec with decoding and encoding rules as described for the +default `Enumeration` codec (using `.toString`). Such a codec can be similarly customised, by providing the `encode` +and `decode` functions as parameters to the value returned to `derivedEnumeration`: + +```scala +import sttp.tapir._ +import sttp.tapir.Codec.PlainCodec + +sealed trait Color +case object Blue extends Color +case object Red extends Color + +implicit val colorCodec: PlainCodec[Color] = { + Codec.derivedEnumeration[String, Color]( + (_: String) match { + case "red" => Some(Red) + case "blue" => Some(Blue) + case _ => None + }, + _.toString.toLowerCase + ) +} +``` + +### Creating an enum codec by hand + +Creating an enumeration [codec](codecs.md) by hand is exactly the same as for any other type. The only difference +is that an enumeration [validator](validation.md) has to be added to the codec's schema. Note that when decoding a +value fails, it's best to return a `DecodeResult.InvalidValue`, with a reference to the enumeration validator. + +### Lists of enumeration values + +If an input/output contains multiple enumeration values, delimited e.g. using a comma, you can look up a codec for +`CommaSeparated[T]` or `Delimited[DELIMITER, T]` (where `D` is a type literal). The `Delimited` +type is a simple wrapper for a list of `T`-values. For example, if the query parameter is required: + +```scala +import sttp.tapir._ +import sttp.tapir.model.CommaSeparated + +object Features extends Enumeration { + type Feature = Value + + val A: Feature = Value("a") + val B: Feature = Value("b") + val C: Feature = Value("c") +} + +query[CommaSeparated[Features.Feature]]("features") +``` + +Additionally, the schema for such an input/output will have the `explode` parameter set to `false`, so that it is +properly represented in [OpenAPI](../docs/openapi.md) documentation. + +## Using enumerations as part of bodies + +When an enumeration is used as part of a body, on the tapir side you'll have to provide a [schema](schemas.md) for +that type, so that the documentation is properly generated. + +Note, however, that the enumeration will also need to be properly supported by whatever means that body is parsed. +If we have an [JSON](json.md) body, parsed with circe, you'll also need to provide circe's `Encoder` and `Decoder` +implicits for the enumerations type, for the parsing to work properly. + +### scala.Enumeration support + +A default schema for any subtype of `scala.Enumeration#Value` is provided as an implicit/given value. Such a schema +assumes that the low-level representation of the enumeration is a string. Encoding is done using `.toString` (to +represent the enumeration's values in the documentation). For example, to use an enum as part of a `jsonBody`, using +the circe library for JSON parsing/serialisation, and automatic schema derivation for case classes: + +```scala +import io.circe._ +import io.circe.generic.auto._ +import sttp.tapir._ +import sttp.tapir.json.circe._ +import sttp.tapir.generic.auto._ + +object Features extends Enumeration { + type Feature = Value + + val A: Feature = Value("a") + val B: Feature = Value("b") + val C: Feature = Value("c") +} + +case class Body(someField: String, feature: Features.Feature) + +// these need to be provided so that circe knows how to encode/decode enumerations +implicit val enumDecoder: Decoder[Features.Feature] = Decoder.decodeEnumeration(Features) +implicit val enumEncoder: Encoder[Features.Feature] = Encoder.encodeEnumeration(Features) + +// the schema for the body is automatically-derived, using the default schema for +// enumerations (Schema.derivedEnumerationValue) +jsonBody[Body] +``` + +A custom schema can be created by providing an alternate schema type (e.g. if the low-level representation of the +enumeration is an integer), using `Schema.derivedEnumerationValueCustomise.apply(...)`. In this case, you'll need +to provide the schema an implicit/given value: + +```scala +import sttp.tapir._ + +object Features extends Enumeration { + type Feature = Value + + val A: Feature = Value("a") + val B: Feature = Value("b") + val C: Feature = Value("c") +} + +implicit val customFeatureSchema: Schema[Features.Feature] = + Schema.derivedEnumerationValueCustomise[Features.Feature]( + encode = Some { + case Features.A => 0 + case Features.B => 1 + case Features.C => 2 + case _ => -1 + }, + schemaType = SchemaType.SInteger() + ) +``` + +### Sealed families / Scala3 enum support + +When the enumeration is defined as a sealed family containing only objects, or a Scala 3 `enum` with all cases +parameterless, a schema has to be provided as an implicit/given value. + +There is no implicit/given schema provided by default, as there's no way to constrain the type for which such an +implicit would be considered by the compiler. Moreover, when automatic [schema](schemas.md) derivation is used, +the current implementation has no possibility to create the list of possible enumeration values (which is needed +to create the enumeration validator). This might be changed in the future, but currently schemas for enumerations +need to be created using `.derivedEnumeration`, instead of the more general `.derived`. + +For example: + +```scala +import sttp.tapir._ + +sealed trait Feature +object Feature { + case object A extends Feature + case object B extends Feature + case object C extends Feature +} + +implicit val featureSchema: Schema[Feature] = + Schema.derivedEnumeration[Feature].defaultStringBased +``` + +Similarly, using Scala 3's enums: + +```scala +enum ColorEnum { + case Green extends ColorEnum + case Pink extends ColorEnum +} + +given Schema[ColorEnum] = Schema.derivedEnumeration.defaultStringBased +``` + +### Creating an enum schema by hand + +Creating an enumeration [schema](schema.md) by hand is exactly the same as for any other type. The only difference +is that an enumeration [validator](validation.md) has to be added to the schema. + +## Next + +Read on about [validation](validation.md). \ No newline at end of file diff --git a/generated-doc/out/endpoint/integrations.md b/generated-doc/out/endpoint/integrations.md index 3fef9e3aa1..c36455c93e 100644 --- a/generated-doc/out/endpoint/integrations.md +++ b/generated-doc/out/endpoint/integrations.md @@ -14,7 +14,7 @@ The `tapir-cats` module contains additional instances for some [cats](https://ty datatypes as well as additional syntax: ```scala -"com.softwaremill.sttp.tapir" %% "tapir-cats" % "1.1.4" +"com.softwaremill.sttp.tapir" %% "tapir-cats" % "1.2.0" ``` - `import sttp.tapir.integ.cats.codec._` - brings schema, validator and codec instances @@ -26,7 +26,7 @@ If you use [refined](https://github.com/fthomas/refined), the `tapir-refined` mo validators for `T Refined P` as long as a codec for `T` already exists: ```scala -"com.softwaremill.sttp.tapir" %% "tapir-refined" % "1.1.4" +"com.softwaremill.sttp.tapir" %% "tapir-refined" % "1.2.0" ``` You'll need to extend the `sttp.tapir.codec.refined.TapirCodecRefined` @@ -47,47 +47,20 @@ The `tapir-enumeratum` module provides schemas, validators and codecs for [Enume enumerations. To use, add the following dependency: ```scala -"com.softwaremill.sttp.tapir" %% "tapir-enumeratum" % "1.1.4" +"com.softwaremill.sttp.tapir" %% "tapir-enumeratum" % "1.2.0" ``` Then, `import sttp.tapir.codec.enumeratum._`, or extends the `sttp.tapir.codec.enumeratum.TapirCodecEnumeratum` trait. This will bring into scope implicit values for values extending `*EnumEntry`. -## Enumeration integration - -There is no library for the use of the build in scala `Enumeration`, but it can be implemented by hand. - -The example code below will generate [enums](https://swagger.io/docs/specification/data-models/enums/) to the open-api documentation. - -```scala -import sttp.tapir._ - -trait EnumHelper { e: Enumeration => - import io.circe._ - - implicit val enumDecoder: Decoder[e.Value] = Decoder.decodeEnumeration(e) - implicit val enumEncoder: Encoder[e.Value] = Encoder.encodeEnumeration(e) - - // needs to be a def or lazy val so that the enumeration values are available! - implicit def schemaForEnum: Schema[e.Value] = Schema.string.validate(Validator.enumeration(e.values.toList, v => Option(v))) -} -object Color extends Enumeration with EnumHelper { - type Color = Value - val Blue = Value("blue") - val Red = Value("red") -} -``` - -Tapir `Schema` for any `Enumeration.Value` can also be auto or semi-auto derived using `import sttp.tapir.generic.auto._` or `Schema.derivedEnumerationValue`. - ## NewType integration If you use [scala-newtype](https://github.com/estatico/scala-newtype), the `tapir-newtype` module will provide implicit codecs and schemas for types with a `@newtype` and `@newsubtype` annotations as long as a codec and schema for its underlying value already exists: ```scala -"com.softwaremill.sttp.tapir" %% "tapir-newtype" % "1.1.4" +"com.softwaremill.sttp.tapir" %% "tapir-newtype" % "1.2.0" ``` Then, `import sttp.tapir.codec.newtype._`, or extend the `sttp.tapir.codec.newtype.TapirCodecNewType` trait to bring the implicit values into scope. @@ -98,7 +71,7 @@ If you use [monix newtypes](https://github.com/monix/newtypes), the `tapir-monix schemas for types which extend `NewtypeWrapped` and `NewsubtypeWrapped` annotations as long as a codec and schema for its underlying value already exists: ```scala -"com.softwaremill.sttp.tapir" %% "tapir-monix-newtype" % "1.1.4" +"com.softwaremill.sttp.tapir" %% "tapir-monix-newtype" % "1.2.0" ``` Then, `import sttp.tapir.codec.monix.newtype._`, or extend the `sttp.tapir.codec.monix.newtype.TapirCodecMonixNewType` trait to bring the implicit values into scope. @@ -109,7 +82,7 @@ If you use [ZIO Prelude Newtypes](https://zio.github.io/zio-prelude/docs/newtype schemas for types defined using `Newtype` and `Subtype` as long as a codec and a schema for the underlying type already exists: ```scala -"com.softwaremill.sttp.tapir" %% "tapir-zio-prelude" % "1.1.4" +"com.softwaremill.sttp.tapir" %% "tapir-zio-prelude" % "1.2.0" ``` Then, mix in `sttp.tapir.codec.zio.prelude.newtype.TapirNewtypeSupport` into your newtype to bring the implicit values into scope: @@ -148,7 +121,7 @@ For details refer to [derevo documentation](https://github.com/tofu-tf/derevo#in To use, add the following dependency: ```scala -"com.softwaremill.sttp.tapir" %% "tapir-derevo" % "1.1.4" +"com.softwaremill.sttp.tapir" %% "tapir-derevo" % "1.2.0" ``` Then you can derive schema for your ADT along with other typeclasses besides ADT declaration itself: diff --git a/generated-doc/out/endpoint/ios.md b/generated-doc/out/endpoint/ios.md index 4815442c05..02b0a2e9e4 100644 --- a/generated-doc/out/endpoint/ios.md +++ b/generated-doc/out/endpoint/ios.md @@ -47,7 +47,7 @@ For outputs: Endpoint inputs/outputs can be combined in two ways. However they are combined, the values they represent always accumulate into tuples of values. -First, inputs/outputs can be combined using the `.and` method. Such a combination results in an input/output, which maps +First, inputs/outputs can be combined using the `.and` method. Such a combination results in an input/output which maps to a tuple of the given types. This combination can be assigned to a value and re-used in multiple endpoints. As all other values in tapir, endpoint input/output descriptions are immutable. For example, an input specifying two query parameters, `start` (mandatory) and `limit` (optional) can be written down as: diff --git a/generated-doc/out/endpoint/json.md b/generated-doc/out/endpoint/json.md index ebbf99e4ba..a5ea14af67 100644 --- a/generated-doc/out/endpoint/json.md +++ b/generated-doc/out/endpoint/json.md @@ -45,7 +45,7 @@ stringJsonBody.schema(implicitly[Schema[MyBody]].as[String]) To use [Circe](https://github.com/circe/circe), add the following dependency to your project: ```scala -"com.softwaremill.sttp.tapir" %% "tapir-json-circe" % "1.1.4" +"com.softwaremill.sttp.tapir" %% "tapir-json-circe" % "1.2.0" ``` Next, import the package (or extend the `TapirJsonCirce` trait, see [MyTapir](../mytapir.md)): @@ -118,7 +118,7 @@ Now the above JSON object will render as To use [µPickle](http://www.lihaoyi.com/upickle/) add the following dependency to your project: ```scala -"com.softwaremill.sttp.tapir" %% "tapir-json-upickle" % "1.1.4" +"com.softwaremill.sttp.tapir" %% "tapir-json-upickle" % "1.2.0" ``` Next, import the package (or extend the `TapirJsonuPickle` trait, see [MyTapir](../mytapir.md) and add `TapirJsonuPickle` not `TapirCirceJson`): @@ -153,7 +153,7 @@ For more examples, including making a custom encoder/decoder, see [TapirJsonuPic To use [Play JSON](https://github.com/playframework/play-json) add the following dependency to your project: ```scala -"com.softwaremill.sttp.tapir" %% "tapir-json-play" % "1.1.4" +"com.softwaremill.sttp.tapir" %% "tapir-json-play" % "1.2.0" ``` Next, import the package (or extend the `TapirJsonPlay` trait, see [MyTapir](../mytapir.md) and add `TapirJsonPlay` not `TapirCirceJson`): @@ -169,7 +169,7 @@ Play JSON requires `Reads` and `Writes` implicit values in scope for each type y To use [Spray JSON](https://github.com/spray/spray-json) add the following dependency to your project: ```scala -"com.softwaremill.sttp.tapir" %% "tapir-json-spray" % "1.1.4" +"com.softwaremill.sttp.tapir" %% "tapir-json-spray" % "1.2.0" ``` Next, import the package (or extend the `TapirJsonSpray` trait, see [MyTapir](../mytapir.md) and add `TapirJsonSpray` not `TapirCirceJson`): @@ -185,7 +185,7 @@ Spray JSON requires a `JsonFormat` implicit value in scope for each type you wan To use [Tethys JSON](https://github.com/tethys-json/tethys) add the following dependency to your project: ```scala -"com.softwaremill.sttp.tapir" %% "tapir-json-tethys" % "1.1.4" +"com.softwaremill.sttp.tapir" %% "tapir-json-tethys" % "1.2.0" ``` Next, import the package (or extend the `TapirJsonTethys` trait, see [MyTapir](../mytapir.md) and add `TapirJsonTethys` not `TapirCirceJson`): @@ -201,7 +201,7 @@ Tethys JSON requires `JsonReader` and `JsonWriter` implicit values in scope for To use [Jsoniter-scala](https://github.com/plokhotnyuk/jsoniter-scala) add the following dependency to your project: ```scala -"com.softwaremill.sttp.tapir" %% "tapir-jsoniter-scala" % "1.1.4" +"com.softwaremill.sttp.tapir" %% "tapir-jsoniter-scala" % "1.2.0" ``` Next, import the package (or extend the `TapirJsonJsoniter` trait, see [MyTapir](../mytapir.md) and add `TapirJsonJsoniter` not `TapirCirceJson`): @@ -217,7 +217,7 @@ Jsoniter Scala requires `JsonValueCodec` implicit value in scope for each type y To use [json4s](https://github.com/json4s/json4s) add the following dependencies to your project: ```scala -"com.softwaremill.sttp.tapir" %% "tapir-json-json4s" % "1.1.4" +"com.softwaremill.sttp.tapir" %% "tapir-json-json4s" % "1.2.0" ``` And one of the implementations: @@ -248,7 +248,7 @@ implicit val formats: Formats = org.json4s.jackson.Serialization.formats(NoTypeH To use [zio-json](https://github.com/zio/zio-json), add the following dependency to your project: ```scala -"com.softwaremill.sttp.tapir" %% "tapir-json-zio" % "1.1.4" +"com.softwaremill.sttp.tapir" %% "tapir-json-zio" % "1.2.0" ``` Next, import the package (or extend the `TapirJsonZio` trait, see [MyTapir](../mytapir.md) and add `TapirJsonZio` instead of `TapirCirceJson`): diff --git a/generated-doc/out/endpoint/oneof.md b/generated-doc/out/endpoint/oneof.md index 8b6f05d260..6d43bcbb97 100644 --- a/generated-doc/out/endpoint/oneof.md +++ b/generated-doc/out/endpoint/oneof.md @@ -11,7 +11,7 @@ Outputs with multiple variants can be specified using the `oneOf` output. Each v variant. All possible outputs must have a common supertype. Typically, the supertype is a sealed trait, and the variants are implementing case classes. -Each one-of variant needs an `appliesTo` function to determine at run-time, if the variant should be used for a given +Each one-of variant needs an `appliesTo` function to determine at run-time if the variant should be used for a given value. This function is inferred at compile time when using `oneOfVariant`, but can also be provided by hand, or if the compile-time inference fails, using one of the other factory methods (see below). A catch-all variant can be defined using `oneOfDefaultVariant`, and should be placed as the last variant in the list of possible variants. @@ -205,7 +205,7 @@ However, this makes it impossible to use streaming bodies in `oneOf` (via `oneOf require normal input/outputs as parameters. To bypass this limitation, a `.toEndpointIO` method is available on streaming bodies, which "lifts" them to an `EndpointIO` type, forgetting the streaming requirement. This decreases type safety, as a run-time error might occur if an incompatible interpreter is used, however allows describing -endpoints, which require including streaming bodies in output variants. +endpoints which require including streaming bodies in output variants. ```eval_rst .. note:: diff --git a/generated-doc/out/endpoint/schemas.md b/generated-doc/out/endpoint/schemas.md index 30aed4178a..9375de5feb 100644 --- a/generated-doc/out/endpoint/schemas.md +++ b/generated-doc/out/endpoint/schemas.md @@ -300,12 +300,6 @@ val e: PublicEndpoint[FruitAmount, Unit, Unit, Nothing] = endpoint.in(jsonBody[FruitAmount]) ``` -## Enumerations - -Currently only schemas for Scala2's `Enumeration#Value` enumerations are automatically derived. For Scala3 `enum`s, -an implicit schema value has to be provided by hand. See the enumeration docs in [validation](validation.md) for -details. - ## Next -Read on about [validation](validation.md). +Read on about [enumerations](enumerations.md). diff --git a/generated-doc/out/endpoint/validation.md b/generated-doc/out/endpoint/validation.md index b40f91679d..674379c2cc 100644 --- a/generated-doc/out/endpoint/validation.md +++ b/generated-doc/out/endpoint/validation.md @@ -62,8 +62,8 @@ implicit val myIdCodec: Codec[String, MyId, TextPlain] = Codec.string The validators are run when a value is being decoded from its low-level representation. This is done using the `Codec.decode` method, which returns a `DecodeResult`. Such a result can be successful, or a decoding failure. -Keep in mind, that the validator mechanism described here is meant for input/output values which are in an incorrect -low-level format. Validators and more generally decoding failures should be reported only for format failures. +Keep in mind that the validator mechanism described here is meant for input/output values which are in an incorrect +low-level format. Validation and more generally decoding failures should be reported only for format failures. Business validation errors, which are often contextual, should use the error output instead. To customise error messages that are returned upon validation/decode failures by the server, see @@ -74,14 +74,17 @@ To customise error messages that are returned upon validation/decode failures by Validators for enumerations can be created using: * for arbitrary types, using `Validator.enumeration`, which takes the list of possible values -* for `sealed` hierarchies, where all implementations are objects, using `Validator.derivedEnumeration[T]`. +* for `sealed` hierarchies, where all implementations are objects, using `Validator.derivedEnumeration[T]`. This method is a macro which determines the possible values. * for Scala3 `enum`s, where all implementation don't have parameters, using `Validator.derivedEnumeration[T]` as above * for Scala2 `Enumeration#Value`, automatically derived `Schema`s have the validator added (see `Schema.derivedEnumerationValue`) +The enumeration schemas and codecs that are created by tapir-provided methods already have the enumeration validator +added. See the section on [enumerations](enumerations.md) for more information. + ### Enumeration values in documentation -To properly represent possible values in documentation, the enum validator additionally needs an `encode` method, which +To properly represent possible values in documentation, the enum validator additionally needs an `encode` method, which converts the enum value to a raw type (typically a string). This can be specified by: * explicitly providing it using the overloaded `enumeration` method with an `encode` parameter @@ -89,57 +92,26 @@ converts the enum value to a raw type (typically a string). This can be specifie * when the values possible values are of a basic type (numbers, strings), the encode function is inferred if not present * by adding the validator directly to a codec using `.validate` (the encode function is then taken from the codec) -### Enumerations in schemas/codecs - -To simplify creation of schemas and codec, with a derived enum validator, `Schema.derivedEnumeration` and `Codec.derivedEnumeration` -helper methods are available. For example: +For example: ```scala import sttp.tapir._ -import sttp.tapir.Codec.PlainCodec sealed trait Color case object Blue extends Color case object Red extends Color -implicit def plainCodecForColor: PlainCodec[Color] = { - Codec.derivedEnumeration[String, Color]( - (_: String) match { - case "red" => Some(Red) - case "blue" => Some(Blue) - case _ => None - }, - _.toString.toLowerCase - ) -} -``` - -If the enum values aren't of a "basic" type (numbers, strings), regardless of whether the codec for that object is -defined by hand or derived, we need to specify the encode function by hand: - -```scala // providing the enum values by hand implicit def colorSchema: Schema[Color] = Schema.string.validate( Validator.enumeration(List(Blue, Red), (c: Color) => Some(c.toString.toLowerCase))) - -// or deriving the enum values and using the helper function -implicit def colorSchema2: Schema[Color] = Schema.derivedEnumeration[Color](encode = Some(_.toString.toLowerCase)) ``` -### Scala3 enums - -Due to technical limitations, automatically derived schemas for `enum`s where all cases are parameterless don't have -the enumeration validator added. Until this limitation is lifted, you'll have to define `implicit` (or equivalently, -`given`) schemas in such cases by hand. These values will be used when deriving schemas containing your enumeration: +## Validation of unrepresentable values -```scala -enum ColorEnum { - case Green extends ColorEnum - case Pink extends ColorEnum -} - -given Schema[ColorEnum] = Schema.derivedEnumeration(encode = Some(v => v)) -``` +Note that validation is run on a fully decoded values. That is, during decoding, first all the provided decoding +functions are run, followed by validations. If you'd like to validate before decoding, e.g. because the value +isn't representable unless validator conditions are met due to preconditions, you can use ``.mapValidate``. However, +this will cause the validator function to be run twice if there are no validation error. ## Next diff --git a/generated-doc/out/generator/sbt-openapi-codegen.md b/generated-doc/out/generator/sbt-openapi-codegen.md index eb4a7caa63..1e5b65d775 100644 --- a/generated-doc/out/generator/sbt-openapi-codegen.md +++ b/generated-doc/out/generator/sbt-openapi-codegen.md @@ -11,7 +11,7 @@ Add the sbt plugin to the `project/plugins.sbt`: ```scala -addSbtPlugin("com.softwaremill.sttp.tapir" % "sbt-openapi-codegen" % "1.1.4") +addSbtPlugin("com.softwaremill.sttp.tapir" % "sbt-openapi-codegen" % "1.2.0") ``` Enable the plugin for your project in the `build.sbt`: diff --git a/generated-doc/out/index.md b/generated-doc/out/index.md index d012fae469..9529e77276 100644 --- a/generated-doc/out/index.md +++ b/generated-doc/out/index.md @@ -75,7 +75,7 @@ Thank you!
Adobe -Colisweb +Swisscom Swissborg
@@ -94,9 +94,9 @@ Thank you! Wegtam
-
Broad -
+Kensu +Colisweb
## Code teaser @@ -198,6 +198,7 @@ Development and maintenance of sttp tapir is sponsored by [SoftwareMill](https:/ endpoint/codecs endpoint/customtypes endpoint/schemas + endpoint/enumerations endpoint/validation endpoint/contenttype endpoint/json diff --git a/generated-doc/out/quickstart.md b/generated-doc/out/quickstart.md index 5e178a9582..278d4ddddf 100644 --- a/generated-doc/out/quickstart.md +++ b/generated-doc/out/quickstart.md @@ -3,7 +3,7 @@ To use tapir, add the following dependency to your project: ```scala -"com.softwaremill.sttp.tapir" %% "tapir-core" % "1.1.4" +"com.softwaremill.sttp.tapir" %% "tapir-core" % "1.2.0" ``` This will import only the core classes needed to create endpoint descriptions. To generate a server or a client, you diff --git a/generated-doc/out/server/akkahttp.md b/generated-doc/out/server/akkahttp.md index acfaa464ad..60c52cca84 100644 --- a/generated-doc/out/server/akkahttp.md +++ b/generated-doc/out/server/akkahttp.md @@ -4,14 +4,14 @@ To expose an endpoint as an [akka-http](https://doc.akka.io/docs/akka-http/curre dependency: ```scala -"com.softwaremill.sttp.tapir" %% "tapir-akka-http-server" % "1.1.4" +"com.softwaremill.sttp.tapir" %% "tapir-akka-http-server" % "1.2.0" ``` This will transitively pull some Akka modules in version 2.6. If you want to force your own Akka version (for example 2.5), use sbt exclusion. Mind the Scala version in artifact name: ```scala -"com.softwaremill.sttp.tapir" %% "tapir-akka-http-server" % "1.1.4" exclude("com.typesafe.akka", "akka-stream_2.12") +"com.softwaremill.sttp.tapir" %% "tapir-akka-http-server" % "1.2.0" exclude("com.typesafe.akka", "akka-stream_2.12") ``` Now import the object: diff --git a/generated-doc/out/server/armeria.md b/generated-doc/out/server/armeria.md index 01974a2695..96dab069d3 100644 --- a/generated-doc/out/server/armeria.md +++ b/generated-doc/out/server/armeria.md @@ -8,7 +8,7 @@ Armeria interpreter can be used with different effect systems (cats-effect, ZIO) Add the following dependency ```scala -"com.softwaremill.sttp.tapir" %% "tapir-armeria-server" % "1.1.4" +"com.softwaremill.sttp.tapir" %% "tapir-armeria-server" % "1.2.0" ``` and import the object: @@ -75,7 +75,7 @@ Note that Armeria automatically injects an `ExecutionContext` on top of Armeria' Add the following dependency ```scala -"com.softwaremill.sttp.tapir" %% "tapir-armeria-server-cats" % "1.1.4" +"com.softwaremill.sttp.tapir" %% "tapir-armeria-server-cats" % "1.2.0" ``` to use this interpreter with Cats Effect typeclasses. @@ -155,9 +155,9 @@ Add the following dependency ```scala // for zio 2: -"com.softwaremill.sttp.tapir" %% "tapir-armeria-server-zio" % "1.1.4" +"com.softwaremill.sttp.tapir" %% "tapir-armeria-server-zio" % "1.2.0" // for zio 1: -"com.softwaremill.sttp.tapir" %% "tapir-armeria-server-zio1" % "1.1.4" +"com.softwaremill.sttp.tapir" %% "tapir-armeria-server-zio1" % "1.2.0" ``` to use this interpreter with ZIO. diff --git a/generated-doc/out/server/aws.md b/generated-doc/out/server/aws.md index 797dd4ad6d..3057b126ff 100644 --- a/generated-doc/out/server/aws.md +++ b/generated-doc/out/server/aws.md @@ -13,7 +13,7 @@ To implement the Lambda function, a server interpreter is available, which takes Currently, only an interpreter integrating with cats-effect is available (`AwsCatsEffectServerInterpreter`). To use, add the following dependency: ```scala -"com.softwaremill.sttp.tapir" %% "tapir-aws-lambda" % "1.1.4" +"com.softwaremill.sttp.tapir" %% "tapir-aws-lambda" % "1.2.0" ``` To configure API Gateway and the Lambda function, you can use: @@ -24,8 +24,8 @@ To configure API Gateway and the Lambda function, you can use: Add one of the following dependencies: ```scala -"com.softwaremill.sttp.tapir" %% "tapir-aws-sam" % "1.1.4" -"com.softwaremill.sttp.tapir" %% "tapir-aws-terraform" % "1.1.4" +"com.softwaremill.sttp.tapir" %% "tapir-aws-sam" % "1.2.0" +"com.softwaremill.sttp.tapir" %% "tapir-aws-terraform" % "1.2.0" ``` ## Examples diff --git a/generated-doc/out/server/finatra.md b/generated-doc/out/server/finatra.md index b2ddb7aa74..1e1aab1e16 100644 --- a/generated-doc/out/server/finatra.md +++ b/generated-doc/out/server/finatra.md @@ -4,7 +4,7 @@ To expose an endpoint as an [finatra](https://twitter.github.io/finatra/) server dependency: ```scala -"com.softwaremill.sttp.tapir" %% "tapir-finatra-server" % "1.1.4" +"com.softwaremill.sttp.tapir" %% "tapir-finatra-server" % "1.2.0" ``` and import the object: @@ -17,7 +17,7 @@ This interpreter supports the twitter `Future`. Or, if you would like to use cats-effect project, you can add the following dependency: ```scala -"com.softwaremill.sttp.tapir" %% "tapir-finatra-server-cats" % "1.1.4" +"com.softwaremill.sttp.tapir" %% "tapir-finatra-server-cats" % "1.2.0" ``` and import the object: diff --git a/generated-doc/out/server/http4s.md b/generated-doc/out/server/http4s.md index 4650130c4e..eca0874498 100644 --- a/generated-doc/out/server/http4s.md +++ b/generated-doc/out/server/http4s.md @@ -4,7 +4,7 @@ To expose an endpoint as an [http4s](https://http4s.org) server, first add the f dependency: ```scala -"com.softwaremill.sttp.tapir" %% "tapir-http4s-server" % "1.1.4" +"com.softwaremill.sttp.tapir" %% "tapir-http4s-server" % "1.2.0" ``` and import the object: diff --git a/generated-doc/out/server/netty.md b/generated-doc/out/server/netty.md index 0bafc50c18..7962d9cfa2 100644 --- a/generated-doc/out/server/netty.md +++ b/generated-doc/out/server/netty.md @@ -4,10 +4,10 @@ To expose an endpoint using a [Netty](https://netty.io)-based server, first add ```scala // if you are using Future or just exploring -"com.softwaremill.sttp.tapir" %% "tapir-netty-server" % "1.1.4" +"com.softwaremill.sttp.tapir" %% "tapir-netty-server" % "1.2.0" // if you are using cats-effect: -"com.softwaremill.sttp.tapir" %% "tapir-netty-server-cats" % "1.1.4" +"com.softwaremill.sttp.tapir" %% "tapir-netty-server-cats" % "1.2.0" ``` Then, use: diff --git a/generated-doc/out/server/observability.md b/generated-doc/out/server/observability.md index e0af54907c..4297fa8bed 100644 --- a/generated-doc/out/server/observability.md +++ b/generated-doc/out/server/observability.md @@ -49,7 +49,7 @@ val labels = MetricLabels( Add the following dependency: ```scala -"com.softwaremill.sttp.tapir" %% "tapir-prometheus-metrics" % "1.1.4" +"com.softwaremill.sttp.tapir" %% "tapir-prometheus-metrics" % "1.2.0" ``` `PrometheusMetrics` encapsulates `CollectorReqistry` and `Metric` instances. It provides several ready to use metrics as @@ -130,7 +130,7 @@ val prometheusMetrics = PrometheusMetrics[Future]("tapir", CollectorRegistry.def Add the following dependency: ```scala -"com.softwaremill.sttp.tapir" %% "tapir-opentelemetry-metrics" % "1.1.4" +"com.softwaremill.sttp.tapir" %% "tapir-opentelemetry-metrics" % "1.2.0" ``` OpenTelemetry metrics are vendor-agnostic and can be exported using one @@ -157,7 +157,7 @@ val metricsInterceptor = metrics.metricsInterceptor() // add to your server opti Add the following dependency: ```scala -"com.softwaremill.sttp.tapir" %% "tapir-datadog-metrics" % "1.1.4" +"com.softwaremill.sttp.tapir" %% "tapir-datadog-metrics" % "1.2.0" ``` Datadog metrics are sent as Datadog custom metrics through diff --git a/generated-doc/out/server/play.md b/generated-doc/out/server/play.md index d709d8eba1..83fea15e3a 100644 --- a/generated-doc/out/server/play.md +++ b/generated-doc/out/server/play.md @@ -3,7 +3,7 @@ To expose endpoint as a [play-server](https://www.playframework.com/) first add the following dependencies: ```scala -"com.softwaremill.sttp.tapir" %% "tapir-play-server" % "1.1.4" +"com.softwaremill.sttp.tapir" %% "tapir-play-server" % "1.2.0" ``` and (if you don't already depend on Play) diff --git a/generated-doc/out/server/vertx.md b/generated-doc/out/server/vertx.md index 477e4e076f..c569b24aef 100644 --- a/generated-doc/out/server/vertx.md +++ b/generated-doc/out/server/vertx.md @@ -8,7 +8,7 @@ Vert.x interpreter can be used with different effect systems (cats-effect, ZIO) Add the following dependency ```scala -"com.softwaremill.sttp.tapir" %% "tapir-vertx-server" % "1.1.4" +"com.softwaremill.sttp.tapir" %% "tapir-vertx-server" % "1.2.0" ``` to use this interpreter with `Future`. @@ -63,7 +63,7 @@ It's also possible to define an endpoint together with the server logic in a sin Add the following dependency ```scala -"com.softwaremill.sttp.tapir" %% "tapir-vertx-server-cats" % "1.1.4" +"com.softwaremill.sttp.tapir" %% "tapir-vertx-server-cats" % "1.2.0" ``` to use this interpreter with Cats Effect typeclasses. @@ -146,9 +146,9 @@ Add the following dependency ```scala // for zio2: -"com.softwaremill.sttp.tapir" %% "tapir-vertx-server-zio" % "1.1.4" +"com.softwaremill.sttp.tapir" %% "tapir-vertx-server-zio" % "1.2.0" // for zio1: -"com.softwaremill.sttp.tapir" %% "tapir-vertx-server-zio1" % "1.1.4" +"com.softwaremill.sttp.tapir" %% "tapir-vertx-server-zio1" % "1.2.0" ``` to use this interpreter with ZIO. diff --git a/generated-doc/out/server/zio-http4s.md b/generated-doc/out/server/zio-http4s.md index 865d1b1524..ad958a64dd 100644 --- a/generated-doc/out/server/zio-http4s.md +++ b/generated-doc/out/server/zio-http4s.md @@ -9,16 +9,16 @@ The `*-zio` modules depend on ZIO 2.x. For ZIO 1.x support, use modules with the You'll need the following dependency for the `ZServerEndpoint` type alias and helper classes: ```scala -"com.softwaremill.sttp.tapir" %% "tapir-zio" % "1.1.4" +"com.softwaremill.sttp.tapir" %% "tapir-zio" % "1.2.0" ``` or just add the zio-http4s integration which already depends on `tapir-zio`: ```scala // for zio 2: -"com.softwaremill.sttp.tapir" %% "tapir-http4s-server-zio" % "1.1.4" +"com.softwaremill.sttp.tapir" %% "tapir-http4s-server-zio" % "1.2.0" // for zio 1: -"com.softwaremill.sttp.tapir" %% "tapir-http4s-server-zio1" % "1.1.4" +"com.softwaremill.sttp.tapir" %% "tapir-http4s-server-zio1" % "1.2.0" ``` Next, instead of the usual `import sttp.tapir._`, you should import (or extend the `ZTapir` trait, see [MyTapir](../mytapir.md)): diff --git a/generated-doc/out/server/ziohttp.md b/generated-doc/out/server/ziohttp.md index a7b4fbb4d8..1cec38c0c4 100644 --- a/generated-doc/out/server/ziohttp.md +++ b/generated-doc/out/server/ziohttp.md @@ -9,13 +9,13 @@ The `*-zio` modules depend on ZIO 2.x. For ZIO 1.x support, use modules with the You'll need the following dependency for the `ZServerEndpoint` type alias and helper classes: ```scala -"com.softwaremill.sttp.tapir" %% "tapir-zio" % "1.1.4" +"com.softwaremill.sttp.tapir" %% "tapir-zio" % "1.2.0" ``` or just add the zio-http integration which already depends on `tapir-zio`: ```scala -"com.softwaremill.sttp.tapir" %% "tapir-zio-http-server" % "1.1.4" +"com.softwaremill.sttp.tapir" %% "tapir-zio-http-server" % "1.2.0" ``` Next, instead of the usual `import sttp.tapir._`, you should import (or extend the `ZTapir` trait, see [MyTapir](../mytapir.md)): diff --git a/generated-doc/out/testing.md b/generated-doc/out/testing.md index 88803b4a54..61811b0b94 100644 --- a/generated-doc/out/testing.md +++ b/generated-doc/out/testing.md @@ -23,7 +23,7 @@ Tapir builds upon the `SttpBackendStub` to enable stubbing using `Endpoint`s or dependency: ```scala -"com.softwaremill.sttp.tapir" %% "tapir-sttp-stub-server" % "1.1.4" +"com.softwaremill.sttp.tapir" %% "tapir-sttp-stub-server" % "1.2.0" ``` Let's assume you are using the [akka http](server/akkahttp.md) interpreter. Given the following server endpoint: @@ -140,7 +140,7 @@ requests matching an endpoint, you can use the tapir `SttpBackendStub` extension Similarly as when testing server interpreters, add the dependency: ```scala -"com.softwaremill.sttp.tapir" %% "tapir-sttp-stub-server" % "1.1.4" +"com.softwaremill.sttp.tapir" %% "tapir-sttp-stub-server" % "1.2.0" ``` And the following imports: @@ -195,7 +195,7 @@ with [mock-server](https://www.mock-server.com/) Add the following dependency: ```scala -"com.softwaremill.sttp.tapir" %% "tapir-sttp-mock-server" % "1.1.4" +"com.softwaremill.sttp.tapir" %% "tapir-sttp-mock-server" % "1.2.0" ``` Imports: @@ -266,7 +266,7 @@ result == out To use, add the following dependency: ```scala -"com.softwaremill.sttp.tapir" %% "tapir-testing" % "1.1.4" +"com.softwaremill.sttp.tapir" %% "tapir-testing" % "1.2.0" ``` ### Shadowed endpoints @@ -292,7 +292,7 @@ Results in: ```scala res.toString -// res2: String = "Set(GET /x, is shadowed by: GET /x/*, GET /x/y/x, is shadowed by: GET /x/*)" +// res2: String = "Set(GET /x/y/x, is shadowed by: GET /x/*, GET /x, is shadowed by: GET /x/*)" ``` Example 2: