Skip to content

[gen] endpoints with inline response body are missing zio.schema._ import #4198

Description

@jirihausner

Describe the bug
When generating endpoints from OpenAPI specification using EndpointGen, zio.schema._ import is missing when using inline response bodies, which breaks the compilation of generated Scala file.

Note: this does not happen for (inline) request bodies.

To Reproduce

//> using scala 3.3.8
//> using dep dev.zio::zio-http-gen:3.11.3

import zio.http.endpoint.openapi.OpenAPI
import zio.http.gen.openapi.{Config, EndpointGen}
import zio.http.gen.scala.CodeGen

object InlineResponseBodyMissingImport extends App {

  val spec: String =
    """|{
       |  "openapi": "3.0.3",
       |  "info": { "title": "Users API", "version": "1.0.0" },
       |  "paths": {
       |    "/user/{id}": {
       |      "get": {
       |        "parameters": [
       |          {
       |            "name": "id",
       |            "in": "path",
       |            "required": true,
       |            "schema": { "type": "string", "format": "uuid" }
       |          }
       |        ],
       |        "responses": {
       |          "200": {
       |            "description": "OK",
       |            "content": {
       |              "application/json": {
       |                "schema": {
       |                  "type": "object",
       |                  "properties": {
       |                    "id":   { "type": "integer" },
       |                    "name": { "type": "string" }
       |                  }
       |                }
       |              }
       |            }
       |          }
       |        }
       |      }
       |    }
       |  }
       |}
       |""".stripMargin
  
  println(spec)

  val openApi: OpenAPI =
    OpenAPI.fromJson(spec).fold(err => sys.error(s"Failed to parse OpenAPI spec: $err"), identity)

  val rendered: Map[String, String] =
    CodeGen.renderedFiles(
      EndpointGen.fromOpenAPI(openApi, Config.default),
      basePackage = "example",
    )

  rendered.foreach { case (path, content) =>
    println(s"=== generated: $path ===")
    println(content)
    println()
  }
}

Got

object Id {

  import zio.http._
  import zio.http.endpoint._
  import zio.http.codec._

  val get = Endpoint(Method.GET / "user" / uuid("id"))
    .in[Unit]
    .out[GET.ResponseBody](status = Status.Ok)

  object GET {

    case class ResponseBody(
      id: Option[Long],
      name: Option[String]
    )
    object ResponseBody {
      implicit val codec: Schema[ResponseBody] = DeriveSchema.gen[ResponseBody]
    }
  }
}

where compilation fails with Not found: type Schema - did you mean Scheme? or perhaps Scheme.type? on implicit val codec: Schema[ResponseBody] = ... line.

Expected behaviour

object Id {

  import zio.http._
  import zio.http.endpoint._
  import zio.http.codec._
  import zio.schema._ // <- this is missing when using inline response bodies

  val get = Endpoint(Method.GET / "user" / uuid("id"))
    .in[Unit]
    .out[GET.ResponseBody](status = Status.Ok)

  object GET {

    case class ResponseBody(
      id: Option[Long],
      name: Option[String]
    )
    object ResponseBody {
      implicit val codec: Schema[ResponseBody] = DeriveSchema.gen[ResponseBody]
    }
  }
}

Root cause

  • in zio.http.gen.openapi.EndpointGen, the function private def endpoint(...) which is used to generate endpoint code with imports is ignoring response body imports by returning Nil -> s"$method.${Inline.ResponseBodyType}" unlike request body which includes code.imports

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions