Skip to content

innFactory/smithy4play

Repository files navigation

GitHub last commit Scala Build and Test CI

Smithy4Play

smithy4play is a routing gernator for the play2 framework based on smithy4s. Just write your smithy API definition and the plugin will generate everything you need for play2 framework usage.


QuickStart

Add smithy4play to your project

plugins.sbt

addSbtPlugin("com.typesafe.play" % "sbt-plugin" % "2.*.*")
addSbtPlugin("com.codecommit" % "sbt-github-packages" % "0.*.*")
addSbtPlugin(
  "com.disneystreaming.smithy4s" % "smithy4s-sbt-codegen" % "0.*.*"
)

build.sbt

.enablePlugins(Smithy4sCodegenPlugin, PlayScala)
  .settings(
    githubSettings,
    Compile / smithy4sInputDir := (ThisBuild / baseDirectory).value / "smithy-in",
    Compile / smithy4sOutputDir := (ThisBuild / baseDirectory).value / "smithy-out",
    libraryDependencies += "de.innfactory" %% "smithy4play" % "latestVersion")

Usage

  • define your controllers in smithy files
  • use smithy4s codegen (sbt compile)

Server

  • create controller scala class
  • extend your Controller with the generated Scala Type and smithy4play Type ContextRoute
@Singleton
class PreviewController @Inject(
)(implicit
  cc: ControllerComponents,
  ec: ExecutionContext
 ) extends PreviewControllerService[ContextRoute] {

  override def preview(bye: PreviewBody): ContextRoute[PreviewResponse] =
    Kleisli { rc =>
      EitherT.rightT[Future, ContextRouteError](PreviewResponse(Some("Hello")))
    }
}

Client

  • import the EnhancedGenericAPIClient
import de.innfactory.smithy4play.client.GenericAPIClient.EnhancedGenericAPIClient
val previewControllerClient = PreviewControllerServiceGen.withClient(FakeRequestClient)
previewControllerClient.preview()

For a further examples take a look at the smithy4playTest project.

Routing

You can choose between autorouting or selfbinding.

Autorouting

  • Annotate your controller with @AutoRouting
  • add scalacOptions += "-Ymacro-annotations" to your build.sbt settings to enable macro annotations
  • bind the smithy4play AutoRouter in the play routes file
-> / de.innfactory.smithy4play.AutoRouter
  • add package name to configuration
smithy4play.autoRoutePackage = "your.package.name"

Selfbinding

  • Create a ApiRouter class and inject your controller
@Singleton
class ApiRouter @Inject()(
  homeController: HomeController,
  pizzaController: PizzaController
)(implicit
  cc: ControllerComponents,
  ec: ExecutionContext
) extends BaseRouter {

  override val controllers: Seq[Routes] =
    Seq(homeController, pizzaController)
}
  • bind the ApiRouter in the play routes file
-> / api.ApiRouter

Middlewares

If you want Middlewares that run before the endpoint logic follow these steps:

  • Implement Middlewares
@Singleton
class ExampleMiddleware @Inject() (implicit
  executionContext: ExecutionContext
) extends MiddlewareBase {

  override protected def skipMiddleware(r: RoutingContext): Boolean = false

  override def logic(
    r: RoutingContext,
    next: RoutingContext => RouteResult[EndpointResult]
  ): RouteResult[EndpointResult] =
    next(r)
}
  • Implement a MiddlewareRegistry and register your middlewares
class MiddlewareRegistry @Inject() (
  disableAbleMiddleware: DisableAbleMiddleware,
  testMiddlewareImpl: TestMiddlewareImpl,
  validateAuthMiddleware: ValidateAuthMiddleware
) extends MiddlewareRegistryBase {
  override val middlewares: Seq[MiddlewareBase] = Seq(ExampleMiddleware)
}

Credits:

innFactory ❤️ Open Source