From db6764234f0854c99ad7b2b7390bbf6fd8fd447c Mon Sep 17 00:00:00 2001 From: Claudio Caletti Date: Thu, 27 Feb 2020 16:41:35 +0100 Subject: [PATCH 01/20] Add tapir dependency for documentation --- build.sbt | 2 +- project/Dependencies.scala | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index 5e7db57f..90b21c3b 100644 --- a/build.sbt +++ b/build.sbt @@ -174,7 +174,7 @@ lazy val docs = project .settings( skip.in(publish) := true, moduleName := "retro-docs", - libraryDependencies ++= docsDependencies, + libraryDependencies ++= docsDependencies :+ tapir, mdocVariables := Map( "TOCTOC_SNAPSHOT_VERSION" -> version.in(toctocCore).value, "TOCTOC_STABLE_VERSION" -> version.in(toctocCore).value.replaceFirst("\\+.*", ""), diff --git a/project/Dependencies.scala b/project/Dependencies.scala index b3317934..9ad6801e 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -37,6 +37,7 @@ object Dependencies { val plantuml = "8059" val pprint = "0.5.9" val sbtLogging = "1.3.3" + val tapir = "0.12.19" } val circeCore = "io.circe" %% "circe-core" % V.circe @@ -80,6 +81,7 @@ object Dependencies { val plantuml = "net.sourceforge.plantuml" % "plantuml" % V.plantuml val pprint = "com.lihaoyi" %% "pprint" % V.pprint val sbtLogging = "org.scala-sbt" %% "util-logging" % V.sbtLogging + val tapir = "com.softwaremill.sttp.tapir" %% "tapir-core" % V.tapir val enumeroDependencies = List( scalatest, From 748459796c20c6965bae30a57733cbf1d8a15d2c Mon Sep 17 00:00:00 2001 From: Claudio Caletti Date: Thu, 27 Feb 2020 16:42:38 +0100 Subject: [PATCH 02/20] Add tapiro to website --- website/i18n/en.json | 1 + website/sidebars.json | 8 ++++++++ website/siteConfig.js | 1 + 3 files changed, 10 insertions(+) diff --git a/website/i18n/en.json b/website/i18n/en.json index 9f83a0ee..c4f7d25d 100644 --- a/website/i18n/en.json +++ b/website/i18n/en.json @@ -49,6 +49,7 @@ "toctoc": "toctoc", "enumero": "enumero", "sbt-buildo": "sbt-buildo", + "tapiro": "tapiro", "GitHub": "GitHub" }, "categories": { diff --git a/website/sidebars.json b/website/sidebars.json index 09a028e4..4a677b17 100644 --- a/website/sidebars.json +++ b/website/sidebars.json @@ -14,6 +14,14 @@ "enumero": { "Getting started": ["enumero/introduction", "enumero/installation"] }, + "tapiro": { + "Setup": ["tapiro/installation"], + "Getting started": [ + "tapiro/introduction", + "tapiro/rpc", + "tapiro/migrate" + ] + }, "sbt-buildo": { "Getting started": ["sbt-buildo/introduction"] }, diff --git a/website/siteConfig.js b/website/siteConfig.js index f95c1ddc..fd1f3191 100644 --- a/website/siteConfig.js +++ b/website/siteConfig.js @@ -29,6 +29,7 @@ const siteConfig = { { doc: "toctoc/installation", label: "toctoc" }, { doc: "enumero/introduction", label: "enumero" }, { doc: "sbt-buildo/introduction", label: "sbt-buildo" }, + { doc: "tapiro/introduction", label: "tapiro" }, { search: true }, { href: "https://github.com/buildo/retro", label: "GitHub", external: true } ], From 6189df6afe2e41a60555ad0947568bd0f85b0520 Mon Sep 17 00:00:00 2001 From: Claudio Caletti Date: Thu, 27 Feb 2020 16:42:50 +0100 Subject: [PATCH 03/20] Add tapiro docs --- docs/tapiro/installation.md | 100 ++++++++++++++++++++++++++++++++++++ docs/tapiro/introduction.md | 85 ++++++++++++++++++++++++++++++ docs/tapiro/migrate.md | 42 +++++++++++++++ docs/tapiro/rpc.md | 6 +++ 4 files changed, 233 insertions(+) create mode 100644 docs/tapiro/installation.md create mode 100644 docs/tapiro/introduction.md create mode 100644 docs/tapiro/migrate.md create mode 100644 docs/tapiro/rpc.md diff --git a/docs/tapiro/installation.md b/docs/tapiro/installation.md new file mode 100644 index 00000000..2e00e6fd --- /dev/null +++ b/docs/tapiro/installation.md @@ -0,0 +1,100 @@ +--- +id: installation +title: Installation +--- + +`tapiro` can be installed as an sbt-plugin. + +`sbt-tapiro` is an Sbt plugin that uses `tapiro` to generate http/json routes parsing scala traits definitions. + +## Installation + +To start using `sbt-tapiro` simply add this line in `project/plugins.sbt` + +```scala +addSbtPlugin("io.buildo" %% "sbt-tapiro" % "@SBT_BUILDO_STABLE_VERSION@") +``` + +### Snapshot releases + +We publish a snapshot version on every merge on master. + +The latest snapshot version is `@SBT_BUILDO_SNAPSHOT_VERSION@` and you can use +it to try the latest unreleased features. For example: + +```scala +addSbtPlugin("io.buildo" %% "sbt-tapiro" % "@SBT_BUILDO_SNAPSHOT_VERSION@") +resolvers += Resolver.sonatypeRepo("snapshots") +``` + +## Plugin + +To use the code generator, you need to add this to your `build.sbt`. + +```scala +lazy val application = project + .settings( + libraryDependencies ++= applicationDependencies ++ tapiroDependencies, + tapiro / tapiroRoutesPaths := List("[path to routes]"), + tapiro / tapiroModelsPaths := List("[path to models]"), + tapiro / tapiroOutputPath := "[path to endpoints]", + tapiro / tapiroEndpointsPackages := List("[package]", "[subpackage]"), + tapiro / tapiroServer := Server.AkkaHttp, //or Server.Http4s + ) + .enablePlugins(SbtTapiro) +``` + +You can now run it with `sbt application/tapiro`. + +In order to use `tapiro` you also need to add the macro paradise plugin (for +Scala 2.12) or to enable the `-Ymacro-annotations` compiler flag (for Scala +2.13). + +> 💡**PROTIP**: This is done automatically for you if you use `sbt-buildo` + +```scala +// Scala 2.12 +addCompilerPlugin("org.scalamacros" % "paradise" % "2.1.1" cross CrossVersion.full) + +// Scala 2.13 +scalacOptions += "-Ymacro-annotations" +``` + +## Dependencies + +The generated code comes with library dependencies. + +In case akka-http version is used: +```scala +val V = new { + val circe = "0.9.1" + val tapir = "0.12.19" + val akkaHttp = "10.1.11" +} + +val tapiroDependencies = Seq( + "com.softwaremill.sttp.tapir" %% "tapir-json-circe" % V.tapir, + "com.softwaremill.sttp.tapir" %% "tapir-core" % V.tapir, + "com.softwaremill.sttp.tapir" %% "tapir-akka-http-server" % V.tapir, + "com.typesafe.akka" %% "akka-http" % V.akkaHttp, + "io.circe" %% "circe-core" % V.circe, +) +``` + +In case http4s is used: + +```scala +val V = new { + val circe = "0.9.1" + val tapir = "0.12.19" +} + +val tapiroDependencies = Seq( + "com.softwaremill.sttp.tapir" %% "tapir-json-circe" % V.tapir, + "com.softwaremill.sttp.tapir" %% "tapir-core" % V.tapir, + "com.softwaremill.sttp.tapir" %% "tapir-http4s-server" % V.tapir, + "io.circe" %% "circe-core" % V.circe, +) +``` + +These dependencies usually go under `project/Dependencies.scala` \ No newline at end of file diff --git a/docs/tapiro/introduction.md b/docs/tapiro/introduction.md new file mode 100644 index 00000000..50f1c357 --- /dev/null +++ b/docs/tapiro/introduction.md @@ -0,0 +1,85 @@ +--- +id: introduction +title: Introduction +--- + +Tapiro parses your Scala controllers to generate HTTP endpoints. + +A Scala controller is a trait defined as follows: + +```scala mdoc +import scala.annotation.StaticAnnotation + +class query extends StaticAnnotation +class command extends StaticAnnotation + +case class Cat(name: String) +case class Error(msg: String) + +trait Cats[F[_], AuthToken] { + @query //translate this to a GET + def findCutestCat(): F[Either[Error, Cat]] + + @command //translate this to a POST + def doSomethingWithTheCat(catId: Int, token: AuthToken): F[Either[Error, Unit]] +} +``` + +For each controller tapiro generates two files: +- `CatsEndpoints.scala` containing the HTTP api description using https://tapir-scala.readthedocs.io/ +- `CatsHttp4sEndpoints.scala` or `CatsAkkaHttpEndpoints.scala` depeneding on the HTTP server the user is using. + +The resulting routes can be simply used like this (http4s example): +```scala +val routes = CatsHttp4sEndpoints.routes(catsImplementation) + +override def run(args: List[String]): IO[ExitCode] = + BlazeServerBuilder[IO] + .bindHttp(port, host) + .withHttpApp(routes.orNotFound) + .serve + .compile + .drain + .as(ExitCode.Success) +``` + +The resulting server can be queried as follows: +``` +/GET /Cats/findCutestCat +/POST /Cats/doSomethingWithTheCat -d '{ "catId": 1 }' +``` + +## Authentication + +An `AuthToken` type argument is expected in each controller and is added as authorization header. + +`trait Cats[F[_], AuthToken]` + +The acutal implementation of the `AuthToken` is left to the user. All tapiro requires is a proper tapir `PlainCodec` such as: + +```scala mdoc +import sttp.tapir._ +import sttp.tapir.Codec._ + +case class CustomAuth(token: String) + +def decodeAuth(s: String): DecodeResult[CustomAuth] = { + val TokenPattern = "Token token=(.+)".r + s match { + case TokenPattern(token) => DecodeResult.Value(CustomAuth(token)) + case _ => DecodeResult.Error(s, new Exception("token not found")) + } +} + +def encodeAuth(auth: CustomAuth): String = auth.token + +implicit val authCodec: PlainCodec[CustomAuth] = Codec.stringPlainCodecUtf8 + .mapDecode(decodeAuth)(encodeAuth) +``` + +The user will find the decoded token as the last argument of the method in the trait. + +```scala +@command //translate this to a POST +def doSomethingWithTheCat(catId: Int, token: AuthToken): F[Either[Error, Unit]] +``` \ No newline at end of file diff --git a/docs/tapiro/migrate.md b/docs/tapiro/migrate.md new file mode 100644 index 00000000..ea6b2774 --- /dev/null +++ b/docs/tapiro/migrate.md @@ -0,0 +1,42 @@ +--- +id: migrate +title: Migration from Wiro +--- + +Tapiro is meant to deprecated [wiro](https://github.com/buildo/wiro). + +Tapiro is based on the same concepts of wiro, the migration is pretty straightforward. + +Here is a checklist of what you need to do: +1. Install the plugin (as described in the [guide](installation.md)) +2. Configure your `build.sbt` (as described in the [guide](installation.md)) +3. Add `AuthToken` type parameter to controllers + `trait AccountController` -> `trait AccountController[AuthToken]` +4. Modify controllers so that wiro `Auth` is replaced with AuthToken and move as last argument + `def read(token: Auth, arg: Int)` -> `def read(arg: Int, token: AuthToken)` +5. Add `.gitattributes` file containing `**/*Endpoints.scala linguist-generated` +6. Add required codecs +This is a valid codec for wiro.Auth: + +```scala mdoc +import sttp.tapir._ +import sttp.tapir.Codec._ + +case class Auth(token: String) //should be imported as wiro.Auth instead + +implicit val authCodec: PlainCodec[Auth] = Codec.stringPlainCodecUtf8 + .mapDecode(decodeAuth)(encodeAuth) + +def decodeAuth(s: String): DecodeResult[Auth] = { + val TokenPattern = "Token token=(.+)".r + s match { + case TokenPattern(token) => DecodeResult.Value(Auth(token)) + case _ => DecodeResult.Error(s, new Exception("token not found")) + } +} + +def encodeAuth(auth: Auth): String = auth.token +``` +7. Run `sbt tapiro` + +Using `Server.AkkaHttp` the resulting routes can be added to wiro as custom routes. \ No newline at end of file diff --git a/docs/tapiro/rpc.md b/docs/tapiro/rpc.md new file mode 100644 index 00000000..cc735a43 --- /dev/null +++ b/docs/tapiro/rpc.md @@ -0,0 +1,6 @@ +--- +id: rpc +title: Why? +--- + +> 📖 **NOTE**: Long time ago we wrote a [blogpost](https://blog.buildo.io/http-routes-at-buildo-1424250c41d3) about this. The blogpost is about [another library](https://github.com/buildo/wiro) but the underlying concepts are the same. \ No newline at end of file From c646a2828118a614e97d8b97e55a09096c388b43 Mon Sep 17 00:00:00 2001 From: Claudio Caletti Date: Thu, 27 Feb 2020 17:00:02 +0100 Subject: [PATCH 04/20] Use tapiro versions instead of sbt-buildo --- build.sbt | 2 ++ docs/tapiro/installation.md | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/build.sbt b/build.sbt index 90b21c3b..d28203f9 100644 --- a/build.sbt +++ b/build.sbt @@ -182,6 +182,8 @@ lazy val docs = project "ENUMERO_STABLE_VERSION" -> version.in(enumeroCore).value.replaceFirst("\\+.*", ""), "SBT_BUILDO_SNAPSHOT_VERSION" -> version.in(`sbt-buildo`).value, "SBT_BUILDO_STABLE_VERSION" -> version.in(`sbt-buildo`).value.replaceFirst("\\+.*", ""), + "SBT_TAPIRO_SNAPSHOT_VERSION" -> version.in(`sbt-tapiro`).value, + "SBT_TAPIRO_STABLE_VERSION" -> version.in(`sbt-tapiro`).value.replaceFirst("\\+.*", ""), ), ) .dependsOn(toctocCore, enumeroCore, toctocSlickPostgreSql) diff --git a/docs/tapiro/installation.md b/docs/tapiro/installation.md index 2e00e6fd..1615388a 100644 --- a/docs/tapiro/installation.md +++ b/docs/tapiro/installation.md @@ -12,7 +12,7 @@ title: Installation To start using `sbt-tapiro` simply add this line in `project/plugins.sbt` ```scala -addSbtPlugin("io.buildo" %% "sbt-tapiro" % "@SBT_BUILDO_STABLE_VERSION@") +addSbtPlugin("io.buildo" %% "sbt-tapiro" % "@SBT_TAPIRO_STABLE_VERSION@") ``` ### Snapshot releases @@ -23,7 +23,7 @@ The latest snapshot version is `@SBT_BUILDO_SNAPSHOT_VERSION@` and you can use it to try the latest unreleased features. For example: ```scala -addSbtPlugin("io.buildo" %% "sbt-tapiro" % "@SBT_BUILDO_SNAPSHOT_VERSION@") +addSbtPlugin("io.buildo" %% "sbt-tapiro" % "@SBT_TAPIRO_SNAPSHOT_VERSION@") resolvers += Resolver.sonatypeRepo("snapshots") ``` From 695d8065fc031d79bb678f9fead16bf57f548f52 Mon Sep 17 00:00:00 2001 From: Claudio Caletti Date: Fri, 28 Feb 2020 15:28:12 +0100 Subject: [PATCH 05/20] Add tapir to docs dependencies --- build.sbt | 2 +- project/Dependencies.scala | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/build.sbt b/build.sbt index d28203f9..03e48bfd 100644 --- a/build.sbt +++ b/build.sbt @@ -174,7 +174,7 @@ lazy val docs = project .settings( skip.in(publish) := true, moduleName := "retro-docs", - libraryDependencies ++= docsDependencies :+ tapir, + libraryDependencies ++= docsDependencies, mdocVariables := Map( "TOCTOC_SNAPSHOT_VERSION" -> version.in(toctocCore).value, "TOCTOC_STABLE_VERSION" -> version.in(toctocCore).value.replaceFirst("\\+.*", ""), diff --git a/project/Dependencies.scala b/project/Dependencies.scala index 9ad6801e..a690a7db 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -193,6 +193,7 @@ object Dependencies { val docsDependencies = List( plantuml, + tapir ) } From a01f2b2b504f2667f96b6ecaf53575b9c3738863 Mon Sep 17 00:00:00 2001 From: Claudio Caletti Date: Fri, 28 Feb 2020 15:29:01 +0100 Subject: [PATCH 06/20] sbt-plugin/Sbt plugin --- docs/tapiro/installation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tapiro/installation.md b/docs/tapiro/installation.md index 1615388a..33d74409 100644 --- a/docs/tapiro/installation.md +++ b/docs/tapiro/installation.md @@ -3,7 +3,7 @@ id: installation title: Installation --- -`tapiro` can be installed as an sbt-plugin. +`tapiro` can be installed as an Sbt plugin. `sbt-tapiro` is an Sbt plugin that uses `tapiro` to generate http/json routes parsing scala traits definitions. From ae6cf8e7b84746220875c8d128f1d237ecb8a968 Mon Sep 17 00:00:00 2001 From: Claudio Caletti Date: Fri, 28 Feb 2020 15:29:29 +0100 Subject: [PATCH 07/20] Remove macro annotations doc --- docs/tapiro/installation.md | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/docs/tapiro/installation.md b/docs/tapiro/installation.md index 33d74409..ed392e5f 100644 --- a/docs/tapiro/installation.md +++ b/docs/tapiro/installation.md @@ -46,20 +46,7 @@ lazy val application = project You can now run it with `sbt application/tapiro`. -In order to use `tapiro` you also need to add the macro paradise plugin (for -Scala 2.12) or to enable the `-Ymacro-annotations` compiler flag (for Scala -2.13). - -> 💡**PROTIP**: This is done automatically for you if you use `sbt-buildo` - ```scala -// Scala 2.12 -addCompilerPlugin("org.scalamacros" % "paradise" % "2.1.1" cross CrossVersion.full) - -// Scala 2.13 -scalacOptions += "-Ymacro-annotations" -``` - ## Dependencies The generated code comes with library dependencies. From 252e6f477c30b7fe7eafb1e8222de41a56c36a00 Mon Sep 17 00:00:00 2001 From: Claudio Caletti Date: Fri, 28 Feb 2020 15:29:43 +0100 Subject: [PATCH 08/20] Acutal/actual --- docs/tapiro/introduction.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tapiro/introduction.md b/docs/tapiro/introduction.md index 50f1c357..1bb15376 100644 --- a/docs/tapiro/introduction.md +++ b/docs/tapiro/introduction.md @@ -55,7 +55,7 @@ An `AuthToken` type argument is expected in each controller and is added as auth `trait Cats[F[_], AuthToken]` -The acutal implementation of the `AuthToken` is left to the user. All tapiro requires is a proper tapir `PlainCodec` such as: +The actual implementation of the `AuthToken` is left to the user. All tapiro requires is a proper tapir `PlainCodec` such as: ```scala mdoc import sttp.tapir._ From 453b21a6b037921608dcd01bc097a297b86b7a89 Mon Sep 17 00:00:00 2001 From: Claudio Caletti Date: Fri, 28 Feb 2020 15:36:27 +0100 Subject: [PATCH 09/20] Add linguistic-generated explaination --- docs/tapiro/migrate.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tapiro/migrate.md b/docs/tapiro/migrate.md index ea6b2774..31257e38 100644 --- a/docs/tapiro/migrate.md +++ b/docs/tapiro/migrate.md @@ -14,7 +14,7 @@ Here is a checklist of what you need to do: `trait AccountController` -> `trait AccountController[AuthToken]` 4. Modify controllers so that wiro `Auth` is replaced with AuthToken and move as last argument `def read(token: Auth, arg: Int)` -> `def read(arg: Int, token: AuthToken)` -5. Add `.gitattributes` file containing `**/*Endpoints.scala linguist-generated` +5. Add `.gitattributes` file containing `**/*Endpoints.scala linguist-generated` so that autogenerated code is hidden by default in git diffs 6. Add required codecs This is a valid codec for wiro.Auth: From bc03dcdbcc07acd8d932b25dcada7b40fc3af30c Mon Sep 17 00:00:00 2001 From: Claudio Caletti Date: Tue, 3 Mar 2020 11:55:23 +0100 Subject: [PATCH 10/20] Rephrase explaination about .gitattributes --- docs/tapiro/installation.md | 2 +- docs/tapiro/migrate.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/tapiro/installation.md b/docs/tapiro/installation.md index ed392e5f..2ca73665 100644 --- a/docs/tapiro/installation.md +++ b/docs/tapiro/installation.md @@ -19,7 +19,7 @@ addSbtPlugin("io.buildo" %% "sbt-tapiro" % "@SBT_TAPIRO_STABLE_VERSION@") We publish a snapshot version on every merge on master. -The latest snapshot version is `@SBT_BUILDO_SNAPSHOT_VERSION@` and you can use +The latest snapshot version is `@SBT_TAPIRO_SNAPSHOT_VERSION@` and you can use it to try the latest unreleased features. For example: ```scala diff --git a/docs/tapiro/migrate.md b/docs/tapiro/migrate.md index 31257e38..45bb1e80 100644 --- a/docs/tapiro/migrate.md +++ b/docs/tapiro/migrate.md @@ -3,7 +3,7 @@ id: migrate title: Migration from Wiro --- -Tapiro is meant to deprecated [wiro](https://github.com/buildo/wiro). +Tapiro is meant to deprecate [wiro](https://github.com/buildo/wiro). Tapiro is based on the same concepts of wiro, the migration is pretty straightforward. @@ -14,7 +14,7 @@ Here is a checklist of what you need to do: `trait AccountController` -> `trait AccountController[AuthToken]` 4. Modify controllers so that wiro `Auth` is replaced with AuthToken and move as last argument `def read(token: Auth, arg: Int)` -> `def read(arg: Int, token: AuthToken)` -5. Add `.gitattributes` file containing `**/*Endpoints.scala linguist-generated` so that autogenerated code is hidden by default in git diffs +5. Add **/*Endpoints.scala linguist-generated to repository's .gitattributes to hide tapiro generated code from github diff's 6. Add required codecs This is a valid codec for wiro.Auth: From 1edc199f6866319fdd4d01486c317dcb04de8b17 Mon Sep 17 00:00:00 2001 From: Claudio Caletti Date: Tue, 3 Mar 2020 11:57:11 +0100 Subject: [PATCH 11/20] Add documentation about how to import tapiro Server object --- docs/tapiro/installation.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/tapiro/installation.md b/docs/tapiro/installation.md index 2ca73665..640d14f8 100644 --- a/docs/tapiro/installation.md +++ b/docs/tapiro/installation.md @@ -32,6 +32,8 @@ resolvers += Resolver.sonatypeRepo("snapshots") To use the code generator, you need to add this to your `build.sbt`. ```scala +import _root_.io.buildo.tapiro.Server + lazy val application = project .settings( libraryDependencies ++= applicationDependencies ++ tapiroDependencies, From 73b0dd8b77ef87fc801ce03f20b058bf19470d0e Mon Sep 17 00:00:00 2001 From: Claudio Caletti Date: Tue, 3 Mar 2020 11:59:43 +0100 Subject: [PATCH 12/20] Use codeblocks where needed in linguist-generated explaination --- docs/tapiro/migrate.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tapiro/migrate.md b/docs/tapiro/migrate.md index 45bb1e80..81043617 100644 --- a/docs/tapiro/migrate.md +++ b/docs/tapiro/migrate.md @@ -14,7 +14,7 @@ Here is a checklist of what you need to do: `trait AccountController` -> `trait AccountController[AuthToken]` 4. Modify controllers so that wiro `Auth` is replaced with AuthToken and move as last argument `def read(token: Auth, arg: Int)` -> `def read(arg: Int, token: AuthToken)` -5. Add **/*Endpoints.scala linguist-generated to repository's .gitattributes to hide tapiro generated code from github diff's +5. Add `**/*Endpoints.scala linguist-generated` to repository's `.gitattributes` to hide tapiro generated code from github diff's 6. Add required codecs This is a valid codec for wiro.Auth: From f318e127b912b14885a7a1c628390a9626838cc3 Mon Sep 17 00:00:00 2001 From: Claudio Caletti Date: Tue, 3 Mar 2020 16:09:02 +0100 Subject: [PATCH 13/20] Update docs/tapiro/migrate.md Co-Authored-By: Gabriele Petronella --- docs/tapiro/migrate.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/tapiro/migrate.md b/docs/tapiro/migrate.md index 81043617..ca30b193 100644 --- a/docs/tapiro/migrate.md +++ b/docs/tapiro/migrate.md @@ -14,7 +14,7 @@ Here is a checklist of what you need to do: `trait AccountController` -> `trait AccountController[AuthToken]` 4. Modify controllers so that wiro `Auth` is replaced with AuthToken and move as last argument `def read(token: Auth, arg: Int)` -> `def read(arg: Int, token: AuthToken)` -5. Add `**/*Endpoints.scala linguist-generated` to repository's `.gitattributes` to hide tapiro generated code from github diff's +5. Add `**/*Endpoints.scala linguist-generated` to repository's `.gitattributes` to automatically collapse tapiro generated code in GitHub diffs 6. Add required codecs This is a valid codec for wiro.Auth: @@ -39,4 +39,4 @@ def encodeAuth(auth: Auth): String = auth.token ``` 7. Run `sbt tapiro` -Using `Server.AkkaHttp` the resulting routes can be added to wiro as custom routes. \ No newline at end of file +Using `Server.AkkaHttp` the resulting routes can be added to wiro as custom routes. From c1def6c9d4a610768ab275d64e686e3a88c5ed21 Mon Sep 17 00:00:00 2001 From: Claudio Caletti Date: Tue, 3 Mar 2020 17:43:49 +0100 Subject: [PATCH 14/20] Add complete example --- docs/tapiro/introduction.md | 59 +++++++++++++++++++++++++++++-------- project/Dependencies.scala | 8 ++++- 2 files changed, 54 insertions(+), 13 deletions(-) diff --git a/docs/tapiro/introduction.md b/docs/tapiro/introduction.md index 1bb15376..284b1bc3 100644 --- a/docs/tapiro/introduction.md +++ b/docs/tapiro/introduction.md @@ -29,18 +29,53 @@ For each controller tapiro generates two files: - `CatsEndpoints.scala` containing the HTTP api description using https://tapir-scala.readthedocs.io/ - `CatsHttp4sEndpoints.scala` or `CatsAkkaHttpEndpoints.scala` depeneding on the HTTP server the user is using. -The resulting routes can be simply used like this (http4s example): -```scala -val routes = CatsHttp4sEndpoints.routes(catsImplementation) - -override def run(args: List[String]): IO[ExitCode] = - BlazeServerBuilder[IO] - .bindHttp(port, host) - .withHttpApp(routes.orNotFound) - .serve - .compile - .drain - .as(ExitCode.Success) +## Complete Example + +Here you have an example implementation of the `Cats` controller definied in the previous section: + +```scala mdoc +import cats.effect._ + +class CatsImpl[F[_]](implicit F: Sync[F]) extends Cats[F, String] { + override def findCutestCat(): F[Either[Error, Cat]] = F.delay(Right(Cat("Cheshire"))) + override def doSomethingWithTheCat(catId: Int, token: String): F[Either[Error, Unit]] = F.delay(Right(())) +} + + +``` + +Here you have the autogenerated magic fromo tapiro (This is the content of `CatsHttp4sEndpoints.scala` it will be autogenerated). + +```scala mdoc +import org.http4s.HttpRoutes + +// ---- begins autogenerated code +object CatsHttp4sEndpoints { + def routes(controller: Cats[IO, String]): HttpRoutes[IO] = ??? +} +// ---- ends autogenerated code +``` + +Here is how to run the server: + +```scala mdoc +import org.http4s.server.blaze._ +import org.http4s.implicits._ +import cats.implicits._ + +object Main extends IOApp { + val catsImpl = new CatsImpl[IO]() + val routes = CatsHttp4sEndpoints.routes(catsImpl) + + override def run(args: List[String]): IO[ExitCode] = + BlazeServerBuilder[IO] + .bindHttp(8080, "localhost") + .withHttpApp(routes.orNotFound) + .serve + .compile + .drain + .as(ExitCode.Success) +} ``` The resulting server can be queried as follows: diff --git a/project/Dependencies.scala b/project/Dependencies.scala index a690a7db..4c04340d 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -82,6 +82,9 @@ object Dependencies { val pprint = "com.lihaoyi" %% "pprint" % V.pprint val sbtLogging = "org.scala-sbt" %% "util-logging" % V.sbtLogging val tapir = "com.softwaremill.sttp.tapir" %% "tapir-core" % V.tapir + val tapirJsonCirce = "com.softwaremill.sttp.tapir" %% "tapir-json-circe" % V.tapir + val tapirCore = "com.softwaremill.sttp.tapir" %% "tapir-core" % V.tapir + val tapirHttp4s = "com.softwaremill.sttp.tapir" %% "tapir-http4s-server" % V.tapir val enumeroDependencies = List( scalatest, @@ -193,7 +196,10 @@ object Dependencies { val docsDependencies = List( plantuml, - tapir + tapir, + tapirJsonCirce, + tapirCore, + tapirHttp4s ) } From 70dc3c275079616488bf4f8e1e0004828aff560c Mon Sep 17 00:00:00 2001 From: Claudio Caletti Date: Tue, 3 Mar 2020 17:51:42 +0100 Subject: [PATCH 15/20] Remove whitespace --- docs/tapiro/introduction.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tapiro/introduction.md b/docs/tapiro/introduction.md index 284b1bc3..845f004d 100644 --- a/docs/tapiro/introduction.md +++ b/docs/tapiro/introduction.md @@ -50,7 +50,7 @@ Here you have the autogenerated magic fromo tapiro (This is the content of `Cats import org.http4s.HttpRoutes // ---- begins autogenerated code -object CatsHttp4sEndpoints { +object CatsHttp4sEndpoints { def routes(controller: Cats[IO, String]): HttpRoutes[IO] = ??? } // ---- ends autogenerated code From aebdf11dd3cd7accb11c8e83ea0010d3de9b41d8 Mon Sep 17 00:00:00 2001 From: Claudio Caletti Date: Tue, 3 Mar 2020 18:00:17 +0100 Subject: [PATCH 16/20] Add second type parameter to example --- docs/tapiro/migrate.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tapiro/migrate.md b/docs/tapiro/migrate.md index ca30b193..6b20a38b 100644 --- a/docs/tapiro/migrate.md +++ b/docs/tapiro/migrate.md @@ -11,7 +11,7 @@ Here is a checklist of what you need to do: 1. Install the plugin (as described in the [guide](installation.md)) 2. Configure your `build.sbt` (as described in the [guide](installation.md)) 3. Add `AuthToken` type parameter to controllers - `trait AccountController` -> `trait AccountController[AuthToken]` + `trait AccountController[F]` -> `trait AccountController[F[_], AuthToken]` 4. Modify controllers so that wiro `Auth` is replaced with AuthToken and move as last argument `def read(token: Auth, arg: Int)` -> `def read(arg: Int, token: AuthToken)` 5. Add `**/*Endpoints.scala linguist-generated` to repository's `.gitattributes` to automatically collapse tapiro generated code in GitHub diffs From 6da7938b977fe5149db448aee0acd7665565fd8e Mon Sep 17 00:00:00 2001 From: Claudio Caletti Date: Thu, 5 Mar 2020 12:15:42 +0100 Subject: [PATCH 17/20] Inject dependencies versions --- build.sbt | 3 +++ docs/tapiro/installation.md | 10 +++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/build.sbt b/build.sbt index 03e48bfd..9c897caa 100644 --- a/build.sbt +++ b/build.sbt @@ -176,6 +176,9 @@ lazy val docs = project moduleName := "retro-docs", libraryDependencies ++= docsDependencies, mdocVariables := Map( + "CIRCE_VERSION" -> V.circe, + "AKKA_HTTP_VERSION" -> V.akkaHttp, + "TAPIR_VERSION" -> V.tapir, "TOCTOC_SNAPSHOT_VERSION" -> version.in(toctocCore).value, "TOCTOC_STABLE_VERSION" -> version.in(toctocCore).value.replaceFirst("\\+.*", ""), "ENUMERO_SNAPSHOT_VERSION" -> version.in(enumeroCore).value, diff --git a/docs/tapiro/installation.md b/docs/tapiro/installation.md index 640d14f8..ee9507a5 100644 --- a/docs/tapiro/installation.md +++ b/docs/tapiro/installation.md @@ -56,9 +56,9 @@ The generated code comes with library dependencies. In case akka-http version is used: ```scala val V = new { - val circe = "0.9.1" - val tapir = "0.12.19" - val akkaHttp = "10.1.11" + val circe = "@CIRCE_VERSION@" + val tapir = "@TAPIR_VERSION@" + val akkaHttp = "@AKKA_HTTP_VERSION@" } val tapiroDependencies = Seq( @@ -74,8 +74,8 @@ In case http4s is used: ```scala val V = new { - val circe = "0.9.1" - val tapir = "0.12.19" + val circe = "@CIRCE_VERSION@" + val tapir = "@TAPIR_VERSION@" } val tapiroDependencies = Seq( From a0bb44bbfcb111690562f85b519d6306dbc4b953 Mon Sep 17 00:00:00 2001 From: Claudio Caletti Date: Thu, 5 Mar 2020 12:50:12 +0100 Subject: [PATCH 18/20] Update docs/tapiro/introduction.md Co-Authored-By: Gabriele Petronella --- docs/tapiro/introduction.md | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/docs/tapiro/introduction.md b/docs/tapiro/introduction.md index 845f004d..eb27a452 100644 --- a/docs/tapiro/introduction.md +++ b/docs/tapiro/introduction.md @@ -36,9 +36,13 @@ Here you have an example implementation of the `Cats` controller definied in the ```scala mdoc import cats.effect._ -class CatsImpl[F[_]](implicit F: Sync[F]) extends Cats[F, String] { - override def findCutestCat(): F[Either[Error, Cat]] = F.delay(Right(Cat("Cheshire"))) - override def doSomethingWithTheCat(catId: Int, token: String): F[Either[Error, Unit]] = F.delay(Right(())) +object Cats { + def create[F[_]](implicit F: Sync[F]) = new Cats[F, String] { + override def findCutestCat(): F[Either[Error, Cat]] = + F.delay(Right(Cat("Cheshire"))) + override def doSomethingWithTheCat(catId: Int, token: String): F[Either[Error, Unit]] = + F.delay(Right(())) + } } @@ -117,4 +121,4 @@ The user will find the decoded token as the last argument of the method in the t ```scala @command //translate this to a POST def doSomethingWithTheCat(catId: Int, token: AuthToken): F[Either[Error, Unit]] -``` \ No newline at end of file +``` From 2c4aad51215f5e680ef90c983e675fbee8e98852 Mon Sep 17 00:00:00 2001 From: Claudio Caletti Date: Thu, 5 Mar 2020 12:50:21 +0100 Subject: [PATCH 19/20] Update docs/tapiro/introduction.md Co-Authored-By: Gabriele Petronella --- docs/tapiro/introduction.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tapiro/introduction.md b/docs/tapiro/introduction.md index eb27a452..e0bbc5fa 100644 --- a/docs/tapiro/introduction.md +++ b/docs/tapiro/introduction.md @@ -68,7 +68,7 @@ import org.http4s.implicits._ import cats.implicits._ object Main extends IOApp { - val catsImpl = new CatsImpl[IO]() + val catsImpl = CatsImpl.create[IO] val routes = CatsHttp4sEndpoints.routes(catsImpl) override def run(args: List[String]): IO[ExitCode] = From a22e84f3efdf6ccfc1e6f3324f94ea9d9c7512c4 Mon Sep 17 00:00:00 2001 From: Claudio Caletti Date: Thu, 5 Mar 2020 12:54:49 +0100 Subject: [PATCH 20/20] Update docs/tapiro/introduction.md Co-Authored-By: Gabriele Petronella --- docs/tapiro/introduction.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/tapiro/introduction.md b/docs/tapiro/introduction.md index e0bbc5fa..9c60f350 100644 --- a/docs/tapiro/introduction.md +++ b/docs/tapiro/introduction.md @@ -68,7 +68,7 @@ import org.http4s.implicits._ import cats.implicits._ object Main extends IOApp { - val catsImpl = CatsImpl.create[IO] + val catsImpl = Cats.create[IO] val routes = CatsHttp4sEndpoints.routes(catsImpl) override def run(args: List[String]): IO[ExitCode] =