Skip to content

Commit

Permalink
Merge pull request #504 from little-inferno/description
Browse files Browse the repository at this point in the history
Add typesafe swagger description module
  • Loading branch information
Boris authored Feb 10, 2021
2 parents 27e9f58 + 00ae964 commit 96f62f5
Show file tree
Hide file tree
Showing 5 changed files with 133 additions and 0 deletions.
14 changes: 14 additions & 0 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,8 @@ val collectionCompat = libraryDependencies += "org.scala-lang.modules" %% "scala

val enumeratumCirce = "com.beachape" %% "enumeratum-circe" % Version.enumeratumCirce

val typesafeConfig = "com.typesafe" % "config" % Version.typesafeConfig

def resourcesOnCompilerCp(config: Configuration): Setting[_] =
managedClasspath in config := {
val res = (resourceDirectory in config).value
Expand Down Expand Up @@ -312,6 +314,17 @@ lazy val swaggerUI =
buildInfoPackage := "ru.tinkoff.tschema.swagger"
)

lazy val swaggerTypesafe = project
.in(file("modules/swaggerTypesafe"))
.dependsOn(kernel, swagger)
.settings(
commonSettings,
simulacrumSettings,
paradise,
moduleName := "typed-schema-swagger-typesafe",
libraryDependencies += typesafeConfig,
)

lazy val docs = project
.in(file("modules/docs"))
.enablePlugins(ScalaUnidocPlugin)
Expand Down Expand Up @@ -340,6 +353,7 @@ lazy val typedschema =
main,
param,
swagger,
swaggerTypesafe,
akkaHttp,
finagle,
finagleZio,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package ru.tinkoff.tschema.swagger.typesafe

import cats.syntax.option._
import com.typesafe.config.Config
import ru.tinkoff.tschema.swagger.PathDescription.{MethodTarget, Target, TypeTarget}
import ru.tinkoff.tschema.swagger.{PathDescription, SwaggerDescription}

object TypesafeDescription {
def apply(cfg: Config): PathDescription.DescriptionMap = {
def readKey(name: String): Option[SwaggerDescription] =
if (cfg.hasPath(name)) cfg.getString(name).some else None

{
case Target.Tag(key) => readKey(s"$key.tag")
case Target.Method(key, sub) =>
sub match {
case MethodTarget.Path => readKey(s"$key.path")
case MethodTarget.Body => readKey(s"$key.body")
case MethodTarget.Summary => readKey(s"$key.summary")
case MethodTarget.Param(name) => readKey(s"$key.params.$name")
case MethodTarget.Status(status) => readKey(s"$key.status.$status")
}
case Target.Type(name, sub) =>
sub match {
case TypeTarget.Type => readKey(s"types.$name.info")
case TypeTarget.Title => readKey(s"types.$name.title")
case TypeTarget.Field(field) => readKey(s"types.$name.values.$field")
}
}
}
}
32 changes: 32 additions & 0 deletions modules/swaggerTypesafe/src/test/resources/swagger.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
test {
tag = "Good test"
check {
params {
mark = "Mark"
}

status {
200 = Good
400 = Bad
500 = Ugly
}
}
}

test2 {
tag = "Good test2"
check {
summary = "Check swagger description"
}
}

types {
ru.tinkoff.tschema.swagger.typesafe.TypesafeDescriptionSpec.TestResponse {
info = "Test response"
title = "Test title"
values {
title = "Title"
status = "Response status"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package ru.tinkoff.tschema.swagger.typesafe

import org.scalatest.flatspec.AnyFlatSpec
import ru.tinkoff.tschema.typeDSL.Complete
import ru.tinkoff.tschema.syntax._
import TypesafeDescriptionSpec.api
import com.typesafe.config.{ConfigFactory => TypesafeConfigFactory}
import derevo.derive
import ru.tinkoff.tschema.swagger.{MkSwagger, Swagger, SwaggerObject}
import ru.tinkoff.tschema.swagger.OpenApi.Method

class TypesafeDescriptionSpec extends AnyFlatSpec {
val swagger = MkSwagger(api).describe(TypesafeDescription(TypesafeConfigFactory.load("swagger.conf"))).make()

"description" should "read descriptions from typesafe config" in {
val path = swagger.paths("/test/check/{mark}")(Method.get)
assert(path.responses.codes(200).description.get == "Good")
assert(path.responses.codes(400).description.get == "Bad")
assert(path.responses.codes(500).description.get == "Ugly")
assert(path.parameters.head.description.get == "Mark")

val check = swagger.paths("/check")(Method.get)
assert(swagger.tags.head.description.get == "Good test")
assert(
swagger.components
.schemas("ru.tinkoff.tschema.swagger.typesafe.TypesafeDescriptionSpec.TestResponse")
.typ
.asInstanceOf[SwaggerObject]
.properties
.map(_.description.get) == Vector("Response status", "Title")
)
assert(check.summary.get == "Check swagger description")
}
}

object TypesafeDescriptionSpec {
@derive(Swagger)
case class TestResponse(status: String, title: String)

class GoodBadUgly[X]

def gbu[A]: Complete[GoodBadUgly[A]] = new Complete

implicit def gbuSwagger[X: Swagger]: MkSwagger[Complete[GoodBadUgly[X]]] =
MkSwagger
.summon[Complete[X]]
.addResponse(400)
.addResponse(500)
.as

val api =
(tagPrefix("test") |> operation("check") |> capture[String]("mark") |> get |> gbu[String]) <|>
(tag("test2") |> operation("check") |> get |> $$[TestResponse])
}
2 changes: 2 additions & 0 deletions project/Version.scala
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,6 @@ object Version {
val scalaTestScalaCheck = "3.2.3.0"

val scalazDeriving = "1.0.0"

val typesafeConfig = "1.4.1"
}

0 comments on commit 96f62f5

Please sign in to comment.