diff --git a/openapi-codegen/core/src/main/scala/sttp/tapir/codegen/EndpointGenerator.scala b/openapi-codegen/core/src/main/scala/sttp/tapir/codegen/EndpointGenerator.scala index 3504ab127a..b2e48ad531 100644 --- a/openapi-codegen/core/src/main/scala/sttp/tapir/codegen/EndpointGenerator.scala +++ b/openapi-codegen/core/src/main/scala/sttp/tapir/codegen/EndpointGenerator.scala @@ -127,21 +127,34 @@ class EndpointGenerator { openapiTags.map(_.distinct.mkString(".tags(List(\"", "\", \"", "\"))")).mkString } + // treats redirects as ok + private val okStatus = """([23]\d\d)""".r + private val errorStatus = """([45]\d\d)""".r private def outs(responses: Seq[OpenapiResponse]) = { // .errorOut(stringBody) // .out(jsonBody[List[Book]]) responses .map { resp => + val d = s""".description("${resp.description}")""" resp.content match { - case Nil => "" + case Nil => + resp.code match { + case "200" | "default" => "" + case okStatus(s) => s".out(statusCode(sttp.model.StatusCode($s))$d)" + case errorStatus(s) => s".errorOut(statusCode(sttp.model.StatusCode($s))$d)" + } case content +: Nil => resp.code match { case "200" => - s".out(${contentTypeMapper(content.contentType, content.schema)})" + s".out(${contentTypeMapper(content.contentType, content.schema)}$d)" + case okStatus(s) => + s".out(${contentTypeMapper(content.contentType, content.schema)}$d.and(statusCode(sttp.model.StatusCode($s))))" case "default" => - s".errorOut(${contentTypeMapper(content.contentType, content.schema)})" - case _ => - throw new NotImplementedError("Statuscode mapping is incomplete!") + s".errorOut(${contentTypeMapper(content.contentType, content.schema)}$d)" + case errorStatus(s) => + s".errorOut(${contentTypeMapper(content.contentType, content.schema)}$d.and(statusCode(sttp.model.StatusCode($s))))" + case x => + throw new NotImplementedError(s"Statuscode mapping is incomplete! Cannot handle $x") } case _ => throw new NotImplementedError("We can handle only one return content!") } diff --git a/openapi-codegen/core/src/test/scala/sttp/tapir/codegen/EndpointGeneratorSpec.scala b/openapi-codegen/core/src/test/scala/sttp/tapir/codegen/EndpointGeneratorSpec.scala index 2b49655f6c..897f68c238 100644 --- a/openapi-codegen/core/src/test/scala/sttp/tapir/codegen/EndpointGeneratorSpec.scala +++ b/openapi-codegen/core/src/test/scala/sttp/tapir/codegen/EndpointGeneratorSpec.scala @@ -123,4 +123,52 @@ class EndpointGeneratorSpec extends CompileCheckTestBase { BasicGenerator.imports ++ new EndpointGenerator().endpointDefs(doc) shouldCompile() } + + it should "handle status codes" in { + val doc = OpenapiDocument( + "", + null, + Seq( + OpenapiPath( + "find/{id}", + Seq( + OpenapiPathMethod( + methodType = "get", + parameters = Seq(Resolved(OpenapiParameter("id", "path", true, None, OpenapiSchemaString(true)))), + responses = Seq( + OpenapiResponse("202", "Processing", Seq(OpenapiResponseContent("text/plain", OpenapiSchemaString(false)))), + OpenapiResponse("404", "couldn't find thing", Seq(OpenapiResponseContent("text/plain", OpenapiSchemaString(false)))) + ), + requestBody = None, + summary = None, + tags = Some(Seq("Tag 1", "Tag 2", "Tag 1")) + ) + ) + ), + OpenapiPath( + "find_v2/{id}", + Seq( + OpenapiPathMethod( + methodType = "get", + parameters = Seq(Resolved(OpenapiParameter("id", "path", true, None, OpenapiSchemaString(true)))), + responses = Seq( + OpenapiResponse("204", "No body", Nil), + OpenapiResponse("403", "Not authorised", Nil) + ), + requestBody = None, + summary = None, + tags = Some(Seq("Tag 1", "Tag 2", "Tag 1")) + ) + ) + ) + ), + null + ) + val generatedCode = BasicGenerator.imports ++ new EndpointGenerator().endpointDefs(doc) + generatedCode should include(""".out(stringBody.description("Processing").and(statusCode(sttp.model.StatusCode(202))))""") // status code with body + generatedCode should include(""".errorOut(stringBody.description("couldn't find thing").and(statusCode(sttp.model.StatusCode(404))))""") // error status code with body + generatedCode should include(""".errorOut(statusCode(sttp.model.StatusCode(403)).description("Not authorised"))""") // error status code, no body + generatedCode should include(""".out(statusCode(sttp.model.StatusCode(204)).description("No body"))""") // status code, no body + generatedCode shouldCompile() + } } diff --git a/openapi-codegen/sbt-plugin/src/main/scala/sttp/tapir/sbt/OpenapiCodegenTask.scala b/openapi-codegen/sbt-plugin/src/main/scala/sttp/tapir/sbt/OpenapiCodegenTask.scala index a12109309a..c620d3d442 100644 --- a/openapi-codegen/sbt-plugin/src/main/scala/sttp/tapir/sbt/OpenapiCodegenTask.scala +++ b/openapi-codegen/sbt-plugin/src/main/scala/sttp/tapir/sbt/OpenapiCodegenTask.scala @@ -36,6 +36,7 @@ case class OpenapiCodegenTask( def makeFile(file: File): Task[File] = { task { val parsed = YamlParser.parseFile(IO.readLines(inputYaml).mkString("\n")) + .left.map(d => new RuntimeException(_root_.io.circe.Error.showError.show(d))) val lines = BasicGenerator.generateObjects(parsed.toTry.get, packageName, objectName, targetScala3).linesIterator.toSeq IO.writeLines(file, lines, IO.utf8) file