Skip to content

Instantly share code, notes, and snippets.

@kdrakon
Created November 7, 2019 23:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kdrakon/1630cbf97f7d117ce6fb857c3c94e233 to your computer and use it in GitHub Desktop.
Save kdrakon/1630cbf97f7d117ce6fb857c3c94e233 to your computer and use it in GitHub Desktop.
A helper to write the JSON OpenAPI spec from tapir (https://github.com/softwaremill/tapir)
package io.policarp
import java.io.{BufferedWriter, FileWriter}
import java.nio.file.Paths
import cats.implicits._
import cats.kernel.Semigroup
import io.circe.Printer
import io.circe.syntax._
import tapir.docs.openapi._
import tapir.openapi.circe._
import tapir.openapi.{Components, OpenAPI, PathItem}
import scala.annotation.tailrec
import scala.collection.immutable.ListMap
/**
* A helper to generate an OpenAPI JSON spec from tapir endpoints
*/
object GenerateSwaggerJson {
implicit val openAPISemigroup: Semigroup[OpenAPI] = Semigroup.instance((a, b) => {
@tailrec
def mergePaths(a: OpenAPI, paths: ListMap[String, PathItem]): OpenAPI = {
paths.toList match {
case Nil => a
case (path, pathItem) :: Nil => a.addPathItem(path, pathItem)
case (path, pathItem) :: tail => mergePaths(a.addPathItem(path, pathItem), tail.toListMap)
}
}
def mergeComponents(a: OpenAPI, optComponents: Option[Components]): OpenAPI = {
val optionalMerge =
for {
bComponents <- optComponents
aComponents <- a.components
} yield {
val schemas = (bComponents.schemas.toSet union aComponents.schemas.toSet).toListMap
val securitySchemas = (bComponents.securitySchemes.toSet union aComponents.securitySchemes.toSet).toListMap
Components(schemas, securitySchemas)
}
a.copy(components = optionalMerge.orElse(a.components))
}
mergeComponents(mergePaths(a, b.paths), b.components)
})
def main(args: Array[String]): Unit = {
val endpointA = ???
val endpointB = ???
// endpoints to include
val openAPI = endpointA |+| endpointB
val swaggerFile = Paths.get("src/main/resources/static/doc/swagger.json").toFile // or wherever you want to write it
val writer = new BufferedWriter(new FileWriter(swaggerFile))
writer.write(Printer.spaces2.copy(dropNullValues = true).print(openAPI.asJson))
writer.close()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment