fix swagger

This commit is contained in:
cheykrym 2025-08-05 07:52:14 +03:00
parent a058d89f3e
commit 2afe7e619d
7 changed files with 40 additions and 22 deletions

4
.idea/dataSources.xml generated
View File

@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="DataSourceManagerImpl" format="xml" multifile-model="true"> <component name="DataSourceManagerImpl" format="xml" multifile-model="true">
<data-source source="LOCAL" name="postgres@localhost" uuid="287c8ab2-ecce-4d79-8e73-e9b1e4cfecc4"> <data-source source="LOCAL" name="dev_yobble" uuid="287c8ab2-ecce-4d79-8e73-e9b1e4cfecc4">
<driver-ref>postgresql</driver-ref> <driver-ref>postgresql</driver-ref>
<synchronize>true</synchronize> <synchronize>true</synchronize>
<jdbc-driver>org.postgresql.Driver</jdbc-driver> <jdbc-driver>org.postgresql.Driver</jdbc-driver>
<jdbc-url>jdbc:postgresql://localhost:5432/postgres</jdbc-url> <jdbc-url>jdbc:postgresql://localhost:5101/yobble_db</jdbc-url>
<jdbc-additional-properties> <jdbc-additional-properties>
<property name="com.intellij.clouds.kubernetes.db.host.port" /> <property name="com.intellij.clouds.kubernetes.db.host.port" />
<property name="com.intellij.clouds.kubernetes.db.enabled" value="false" /> <property name="com.intellij.clouds.kubernetes.db.enabled" value="false" />

View File

@ -22,8 +22,12 @@ object Main extends IOApp {
.withHttpApp(httpAppWithMiddleware) .withHttpApp(httpAppWithMiddleware)
.build .build
.use { server => .use { server =>
IO.println(s"Server running at http://localhost:${server.address.getPort}") *> // Здесь вручную выводим "localhost" в лог, хотя слушаем "0.0.0.0"
IO.never for {
_ <- IO.println(s"Server running at http://localhost:$port")
_ <- IO.println(s"Swagger UI available at http://localhost:$port/docs")
_ <- IO.never
} yield ()
} }
.as(ExitCode.Success) .as(ExitCode.Success)
} }

View File

@ -27,5 +27,9 @@ object ErrorsEndpoint {
oneOfVariant(StatusCode.ServiceUnavailable, jsonBody[ErrorResponse].description("Service Unavailable").example(ErrorExamples.unavailable)) oneOfVariant(StatusCode.ServiceUnavailable, jsonBody[ErrorResponse].description("Service Unavailable").example(ErrorExamples.unavailable))
) )
) )
.out(jsonBody[BaseResponse]) .out(
jsonBody[BaseResponse]
.description("Successful Response")
.example(BaseResponse(message = "errors"))
)
} }

View File

@ -1,19 +1,27 @@
package org.yobble.scala_monolith.api.endpoint package org.yobble.scala_monolith.api.endpoint
import sttp.tapir._ import sttp.tapir.*
import sttp.tapir.json.circe.jsonBody import sttp.tapir.json.circe.jsonBody
import sttp.tapir.generic.auto._ import sttp.tapir.generic.auto.*
import org.yobble.scala_monolith.api.response.ErrorResponse import org.yobble.scala_monolith.api.response.{BaseResponse, ErrorResponse}
import io.circe.generic.auto._ import io.circe.generic.auto.*
import org.yobble.scala_monolith.api.util.ErrorExamples
import sttp.model.StatusCode
object PingEndpoint { object PingEndpoint {
case class Pong(status: String, message: String)
val pingEndpoint = endpoint val pingEndpoint = endpoint
.get .get
.in("ping") .in("ping")
.tags(List("Info")) .tags(List("Info"))
.out(jsonBody[Pong]) .errorOut(
.errorOut(jsonBody[ErrorResponse]) oneOf[ErrorResponse](
oneOfVariant(StatusCode.InternalServerError, jsonBody[ErrorResponse].description("Internal Server Error").example(ErrorExamples.internal))
)
)
.description("Check if the server is running") .description("Check if the server is running")
.out(
jsonBody[BaseResponse]
.description("Successful Response")
.example(BaseResponse(message = "pong"))
)
} }

View File

@ -1,3 +1,6 @@
package org.yobble.scala_monolith.api.response package org.yobble.scala_monolith.api.response
case class BaseResponse(status: String, message: String) case class BaseResponse(
status: String = "fine",
message: String
)

View File

@ -3,13 +3,12 @@ package org.yobble.scala_monolith.api.route
import cats.effect.IO import cats.effect.IO
import sttp.tapir.server.ServerEndpoint import sttp.tapir.server.ServerEndpoint
import org.yobble.scala_monolith.api.endpoint.PingEndpoint import org.yobble.scala_monolith.api.endpoint.PingEndpoint
import org.yobble.scala_monolith.api.endpoint.PingEndpoint.Pong
import org.yobble.scala_monolith.api.endpoint.ErrorsEndpoint import org.yobble.scala_monolith.api.endpoint.ErrorsEndpoint
import org.yobble.scala_monolith.api.response.BaseResponse import org.yobble.scala_monolith.api.response.BaseResponse
object AllServerEndpoints { object AllServerEndpoints {
val all: List[ServerEndpoint[Any, IO]] = List( val all: List[ServerEndpoint[Any, IO]] = List(
PingEndpoint.pingEndpoint.serverLogicSuccess(_ => IO.pure(Pong("ok", "pong"))), PingEndpoint.pingEndpoint.serverLogicSuccess(_ => IO.pure(BaseResponse(message = "pong"))),
ErrorsEndpoint.errorsEndpoint.serverLogicSuccess(_ => IO.pure(BaseResponse("fine", "errors"))) ErrorsEndpoint.errorsEndpoint.serverLogicSuccess(_ => IO.pure(BaseResponse(message = "errors")))
) )
} }

View File

@ -17,7 +17,7 @@ object ErrorUtils {
ErrorResponse(code = 404, errors = List(ErrorDetail("resource", message))) ErrorResponse(code = 404, errors = List(ErrorDetail("resource", message)))
def methodNotAllowed(message: String = "Method not allowed"): ErrorResponse = def methodNotAllowed(message: String = "Method not allowed"): ErrorResponse =
ErrorResponse(code = 405, errors = List(ErrorDetail("method", message))) ErrorResponse(code = 405, errors = List(ErrorDetail("request", message)))
def conflict(message: String = "Conflict"): ErrorResponse = def conflict(message: String = "Conflict"): ErrorResponse =
ErrorResponse(code = 409, errors = List(ErrorDetail("conflict", message))) ErrorResponse(code = 409, errors = List(ErrorDetail("conflict", message)))
@ -32,7 +32,7 @@ object ErrorUtils {
ErrorResponse(code = 500, errors = List(ErrorDetail("server", message))) ErrorResponse(code = 500, errors = List(ErrorDetail("server", message)))
def serviceUnavailableError(message: String = "Service unavailable"): ErrorResponse = def serviceUnavailableError(message: String = "Service unavailable"): ErrorResponse =
ErrorResponse(code = 503, errors = List(ErrorDetail("request", message))) ErrorResponse(code = 503, errors = List(ErrorDetail("proxy", message)))
} }
object ErrorExamples { object ErrorExamples {
@ -60,7 +60,7 @@ object ErrorExamples {
val notAllowed: ErrorResponse = ErrorResponse( val notAllowed: ErrorResponse = ErrorResponse(
code = 405, code = 405,
errors = List(ErrorDetail("resource", "Method not allowed on this endpoint")) errors = List(ErrorDetail("request", "Method not allowed on this endpoint"))
) )
val conflict: ErrorResponse = ErrorResponse( val conflict: ErrorResponse = ErrorResponse(
@ -75,7 +75,7 @@ object ErrorExamples {
val validation: ErrorResponse = ErrorResponse( val validation: ErrorResponse = ErrorResponse(
code = 422, code = 422,
errors = List(ErrorDetail("login", "Login must not contain whitespace characters")) errors = List(ErrorDetail("example login", "example Login must not contain whitespace characters"))
) )
val internal: ErrorResponse = ErrorResponse( val internal: ErrorResponse = ErrorResponse(
@ -85,7 +85,7 @@ object ErrorExamples {
val unavailable: ErrorResponse = ErrorResponse( val unavailable: ErrorResponse = ErrorResponse(
code = 503, code = 503,
errors = List(ErrorDetail("request", "Service unavailable.")) errors = List(ErrorDetail("proxy", "Service unavailable."))
) )
} }