diff --git a/doc/generator/sbt-openapi-codegen.md b/doc/generator/sbt-openapi-codegen.md index 39887ffd0a..8c6dab156c 100644 --- a/doc/generator/sbt-openapi-codegen.md +++ b/doc/generator/sbt-openapi-codegen.md @@ -43,6 +43,7 @@ openapiUseHeadTagForObjectName false If tr openapiJsonSerdeLib circe The json serde library to use. openapiValidateNonDiscriminatedOneOfs true Whether to fail if variants of a oneOf without a discriminator cannot be disambiguated. openapiMaxSchemasPerFile 400 Maximum number of schemas to generate in a single file (tweak if hitting javac class size limits). +openapiAdditionalPackages Nil Additional packageName/swaggerFile pairs for generating from multiple schemas ===================================== ==================================== ================================================================================================== ``` @@ -88,6 +89,16 @@ If `openapiUseHeadTagForObjectName = true`, then the `GET /foo` and `GET /bar` `Baz.scala` file, containing a single `object Baz` with those endpoint definitions; the `PUT /foo` endpoint, by dint of having no tags, would be output to the `TapirGeneratedEndpoints` file, along with any schema and parameter definitions. +Files can be generated from multiple openapi schemas if `openapiAdditionalPackages` is configured; for example +```sbt +openapiAdditionalPackages := List( + "sttp.tapir.generated.v1" -> baseDirectory.value / "src" / "main" / "resources" / "openapi_v1.yml") +``` +would generate files in the package `sttp.tapir.generated.v1` based on the `openapi_v1.yml` schema at the provided +location. This would be in addition to files generated in `openapiPackage` from the specs configured by +`openapiSwaggerFile` + + ### Json Support ```{eval-rst} 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 68e42db635..d1ad3ecd70 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 @@ -42,7 +42,8 @@ class EndpointGeneratorSpec extends CompileCheckTestBase { parameters = Seq( Resolved(OpenapiParameter("asd-id", "path", Some(true), None, OpenapiSchemaString(false))), Resolved(OpenapiParameter("fgh-id", "query", Some(false), None, OpenapiSchemaString(false))), - Resolved(OpenapiParameter("jkl-id", "header", Some(false), None, OpenapiSchemaString(false)))), + Resolved(OpenapiParameter("jkl-id", "header", Some(false), None, OpenapiSchemaString(false))) + ), responses = Seq( OpenapiResponse( "200", diff --git a/openapi-codegen/sbt-plugin/src/main/scala/sttp/tapir/sbt/OpenapiCodegenKeys.scala b/openapi-codegen/sbt-plugin/src/main/scala/sttp/tapir/sbt/OpenapiCodegenKeys.scala index 0299642f55..312a261207 100644 --- a/openapi-codegen/sbt-plugin/src/main/scala/sttp/tapir/sbt/OpenapiCodegenKeys.scala +++ b/openapi-codegen/sbt-plugin/src/main/scala/sttp/tapir/sbt/OpenapiCodegenKeys.scala @@ -13,6 +13,7 @@ trait OpenapiCodegenKeys { lazy val openapiValidateNonDiscriminatedOneOfs = settingKey[Boolean]("Whether to fail if variants of a oneOf without a discriminator cannot be disambiguated..") lazy val openapiMaxSchemasPerFile = settingKey[Int]("Maximum number of schemas to generate for a single file") + lazy val openapiAdditionalPackages = taskKey[List[(String, File)]]("Addition package -> spec mappings to generate.") lazy val generateTapirDefinitions = taskKey[Unit]("The task that generates tapir definitions based on the input swagger file.") } diff --git a/openapi-codegen/sbt-plugin/src/main/scala/sttp/tapir/sbt/OpenapiCodegenPlugin.scala b/openapi-codegen/sbt-plugin/src/main/scala/sttp/tapir/sbt/OpenapiCodegenPlugin.scala index 9c766a6f1b..dfab718af3 100644 --- a/openapi-codegen/sbt-plugin/src/main/scala/sttp/tapir/sbt/OpenapiCodegenPlugin.scala +++ b/openapi-codegen/sbt-plugin/src/main/scala/sttp/tapir/sbt/OpenapiCodegenPlugin.scala @@ -29,7 +29,8 @@ object OpenapiCodegenPlugin extends AutoPlugin { openapiUseHeadTagForObjectName := false, openapiJsonSerdeLib := "circe", openapiValidateNonDiscriminatedOneOfs := true, - openapiMaxSchemasPerFile := 400 + openapiMaxSchemasPerFile := 400, + openapiAdditionalPackages := Nil ) private def codegen = Def.task { @@ -43,6 +44,7 @@ object OpenapiCodegenPlugin extends AutoPlugin { openapiJsonSerdeLib, openapiValidateNonDiscriminatedOneOfs, openapiMaxSchemasPerFile, + openapiAdditionalPackages, sourceManaged, streams, scalaVersion @@ -55,22 +57,29 @@ object OpenapiCodegenPlugin extends AutoPlugin { jsonSerdeLib: String, validateNonDiscriminatedOneOfs: Boolean, maxSchemasPerFile: Int, + additionalPackages: List[(String, File)], srcDir: File, taskStreams: TaskStreams, sv: String ) => - OpenapiCodegenTask( - swaggerFile, - packageName, - objectName, - useHeadTagForObjectName, - jsonSerdeLib, - validateNonDiscriminatedOneOfs, - maxSchemasPerFile, - srcDir, - taskStreams.cacheDirectory, - sv.startsWith("3") - ).file + def genTask(swaggerFile: File, packageName: String, directoryName: Option[String] = None) = + OpenapiCodegenTask( + swaggerFile, + packageName, + objectName, + useHeadTagForObjectName, + jsonSerdeLib, + validateNonDiscriminatedOneOfs, + maxSchemasPerFile, + srcDir, + taskStreams.cacheDirectory, + sv.startsWith("3"), + directoryName + ) + (genTask(swaggerFile, packageName).file +: additionalPackages.map { case (pkg, defns) => + genTask(defns, pkg, Some(pkg.replace('.', '/'))).file + }) + .reduceLeft((l, r) => l.flatMap(_l => r.map(_l ++ _))) }) map (Seq(_))).value } } 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 c4d55c257f..546081e95d 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 @@ -15,11 +15,13 @@ case class OpenapiCodegenTask( maxSchemasPerFile: Int, dir: File, cacheDir: File, - targetScala3: Boolean + targetScala3: Boolean, + overrideDirectoryName: Option[String] ) { - val tempDirectory = cacheDir / "sbt-openapi-codegen" - val outDirectory = dir / "sbt-openapi-codegen" + private val directoryName: String = overrideDirectoryName.getOrElse("sbt-openapi-codegen") + val tempDirectory = cacheDir / directoryName + val outDirectory = dir / directoryName // 1. make the files under cache/sbt-tapircodegen. // 2. compare their SHA1 against cache/sbtbuildinfo-inputs