ソースを参照

Add global settings.

Thomas Flucke 5 年 前
コミット
350f1e45cd
1 ファイル変更80 行追加0 行削除
  1. 80 0
      src/name/tflucke/webroutes/WebRoutes.scala

+ 80 - 0
src/name/tflucke/webroutes/WebRoutes.scala

@@ -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")
+      }
+    }
+  }
+}