|
|
@@ -0,0 +1,80 @@
|
|
|
+package name.tflucke.webroutes
|
|
|
+
|
|
|
+import sbt._
|
|
|
+import Keys._
|
|
|
+
|
|
|
+object WebRoutes extends AutoPlugin {
|
|
|
+ val routePattern = ("\\s*#\\s*Shared\\s+Route\\s*\n" +
|
|
|
+ "((\\s*#\\s*\\w+\\s*:\\s*[^\\s]+\\s*\n)*)" +
|
|
|
+ "\\s*(GET|PUT|POST|DELETE)\\s+(/[^\\s]*)+\\s+@?([\\.\\w]+.controllers).([\\w]+).([\\w]+)\\s*(\\((\\w+\\s*:\\s*\\w+\\s*)?(,\\s*\\w+\\s*:\\s*\\w+)?\\))?").r
|
|
|
+
|
|
|
+ override def requires: Plugins = ScalaJSPlugin && JSDependenciesPlugin
|
|
|
+ override def trigger = noTrigger
|
|
|
+
|
|
|
+ object autoImport {
|
|
|
+ val generateJsRoutes = taskKey[Seq[File]]("Generate scala client routes objects")
|
|
|
+
|
|
|
+ lazy val baseWebRouteSettings: Seq[Def.Setting[_]] = Seq(
|
|
|
+ generateJsRoutes := {
|
|
|
+ println("Generating Scala Web route objects...")
|
|
|
+ generateRoutes(generateJsRoutes.inputFileChanges.modified, (Compile / resourceManaged).value)
|
|
|
+ }
|
|
|
+ )
|
|
|
+ }
|
|
|
+ import autoImport._
|
|
|
+
|
|
|
+ override lazy val globalSettings = baseWebRouteSettings
|
|
|
+
|
|
|
+ override lazy val projectSettings =
|
|
|
+ inConfig(Compile)(baseWebRouteSettings) ++
|
|
|
+ inConfig(Test)(baseWebRouteSettings)
|
|
|
+
|
|
|
+ def generateRoutes(routeFiles: Seq[java.nio.file.Path], outpath: File): Seq[File] {
|
|
|
+ routeFiles.flatMap((routesFile: java.nio.file.Path) => {
|
|
|
+ import scala.io.Source
|
|
|
+
|
|
|
+ val routeGroups = (for (route <- routePattern.findAllMatchIn(Source.fromFile(routesFile.toFile).mkString)) yield {
|
|
|
+ val propPattern = "\\s*#\\s*(\\w+)\\s*:\\s*([^\\s]+)\\s*\n".r
|
|
|
+ val props = propPattern.findAllMatchIn(route.group(1)).map(m => (m.group(1), m.group(2)))
|
|
|
+ def getProp(name: String): Option[String] = props.find(_._1.equalsIgnoreCase(name)).map(_._2)
|
|
|
+ val method = route.group(3)
|
|
|
+ val path = route.group(4)
|
|
|
+ val pack = route.group(5)
|
|
|
+ val obj = route.group(6)
|
|
|
+ val function = route.group(7)
|
|
|
+ val args = (Option(route.group(9)).getOrElse("") + Option(route.group(10)).getOrElse("")).split(",")
|
|
|
+ RouteDef(method, path, pack, obj, function, args,
|
|
|
+ getProp("type") getOrElse "Any",
|
|
|
+ "text")//getProp("mime") getOrElse "json"
|
|
|
+ }).toList.groupBy[(String, String)]((route) => (route.pack, route.controller))
|
|
|
+ val outFiles = routeGroups.map(tuple => {
|
|
|
+ val ((pack, controller), routes) = tuple
|
|
|
+ val content = s"""package ${pack}
|
|
|
+object ${controller} {
|
|
|
+${routes.mkString("\n")}
|
|
|
+}
|
|
|
+"""
|
|
|
+ val outFile = makeControllerFile(pack, controller, outpath.value)
|
|
|
+ IO.write(outFile, content)
|
|
|
+ outFile
|
|
|
+ }).toSeq
|
|
|
+ outFiles
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ def makeControllerFile(path: String, controller: String, baseDir: File): File = {
|
|
|
+ val pattern = "\\.?([^.]+)(.*)".r
|
|
|
+ path match {
|
|
|
+ case pattern(head, rest) => {
|
|
|
+ val nextDir = new File(baseDir, head)
|
|
|
+ if (!nextDir.exists) {
|
|
|
+ nextDir.mkdir()
|
|
|
+ }
|
|
|
+ makeControllerFile(rest, controller, nextDir)
|
|
|
+ }
|
|
|
+ case _ => {
|
|
|
+ new File(baseDir, s"${controller}.scala")
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|