diff options
author | Li Haoyi <haoyi@dropbox.com> | 2014-09-03 23:06:31 -0700 |
---|---|---|
committer | Li Haoyi <haoyi@dropbox.com> | 2014-09-03 23:06:31 -0700 |
commit | 2f96da023d9172deb646de9bd1cf0a05c4201df7 (patch) | |
tree | 8636cf8853fe0a8621587e4a9870230545f89f9c | |
parent | 424cc28d19f7e23cab6af9795a6c6a5c4adf5e3c (diff) | |
download | workbench-2f96da023d9172deb646de9bd1cf0a05c4201df7.tar.gz workbench-2f96da023d9172deb646de9bd1cf0a05c4201df7.tar.bz2 workbench-2f96da023d9172deb646de9bd1cf0a05c4201df7.zip |
lols
-rw-r--r-- | build.sbt | 20 | ||||
-rw-r--r-- | client/src/main/scala/workbench/Main.scala | 76 | ||||
-rw-r--r-- | example/project/build.sbt | 6 | ||||
-rw-r--r-- | shared/main/scala/workbench/Shared.scala | 8 | ||||
-rw-r--r-- | shared/src/main/scala/workbench/Shared.scala | 1 | ||||
-rw-r--r-- | src/main/scala/workbench/Plugin.scala (renamed from plugin/src/main/scala/workbench/Plugin.scala) | 29 | ||||
-rw-r--r-- | src/main/scala/workbench/Server.scala (renamed from plugin/src/main/scala/workbench/Server.scala) | 37 |
7 files changed, 128 insertions, 49 deletions
@@ -1,14 +1,17 @@ import sbt.Keys._ +import scala.scalajs.sbtplugin.ScalaJSPlugin._ +import ScalaJSKeys._ val defaultSettings = Seq( unmanagedSourceDirectories in Compile <+= baseDirectory(_ / "shared" / "main" / "scala"), unmanagedSourceDirectories in Test <+= baseDirectory(_ / "shared" / "test" / "scala") ) -lazy val plugin = project.in(file("plugin")).settings(defaultSettings:_*).settings( +lazy val root = project.in(file(".")).settings(defaultSettings:_*).settings( name := "workbench", - version := "0.1.5", + version := "0.1.6-SNAPSHOT", organization := "com.lihaoyi", + scalaVersion := "2.10.4", sbtPlugin := true, publishArtifact in Test := false, publishTo := Some("releases" at "https://oss.sonatype.org/service/local/staging/deploy/maven2"), @@ -32,12 +35,16 @@ lazy val plugin = project.in(file("plugin")).settings(defaultSettings:_*).settin </developer> </developers> ), - (resources in Compile) := {(resources in Compile).value ++ (baseDirectory.value * "*.js").get}, + (resources in Compile) += { + (fullOptJS in (client, Compile)).value + (artifactPath in (client, Compile, fullOptJS)).value + }, libraryDependencies ++= Seq( "io.spray" % "spray-can" % "1.3.1", "io.spray" % "spray-routing" % "1.3.1", "com.typesafe.akka" %% "akka-actor" % "2.3.0", - "com.lihaoyi" %% "upickle" % "0.2.1" + "com.lihaoyi" %% "autowire" % "0.2.3-SNAPSHOT", + "com.lihaoyi" %% "upickle" % "0.2.3-SNAPSHOT" ) ) @@ -47,6 +54,7 @@ lazy val client = project.in(file("client")) libraryDependencies ++= Seq( "org.scala-lang.modules.scalajs" %%% "scalajs-dom" % "0.6", "org.scala-lang.modules" %% "scala-async" % "0.9.2", - "com.lihaoyi" %%% "upickle" % "0.2.1" + "com.lihaoyi" %%% "autowire" % "0.2.3-SNAPSHOT", + "com.lihaoyi" %%% "upickle" % "0.2.3-SNAPSHOT" ) -)
\ No newline at end of file +) diff --git a/client/src/main/scala/workbench/Main.scala b/client/src/main/scala/workbench/Main.scala index 0b0cea7..7f63da6 100644 --- a/client/src/main/scala/workbench/Main.scala +++ b/client/src/main/scala/workbench/Main.scala @@ -1,10 +1,74 @@ -package workbench +package com.lihaoyi.workbench +import upickle._ +import org.scalajs.dom import org.scalajs.dom.extensions._ -import async.Async._ -object Main{ - def main(bootSnippet: String, host: String, port: Int): Unit = async{ - while(true){ - val data = await(Ajax.get(s"http://$host:$port/notifications")) +import upickle.{Reader, Writer, Js} + +import scala.scalajs.js +import scala.scalajs.js.annotation.JSExport +import scalajs.concurrent.JSExecutionContext.Implicits.runNow +object WireServer extends autowire.Server[Js.Value, upickle.Reader, upickle.Writer]{ + + def write[Result: Writer](r: Result) = upickle.writeJs(r) + def read[Result: Reader](p: Js.Value) = upickle.readJs[Result](p) + def wire(parsed: Js.Arr): Unit = { + WireServer.route[Api](Main).apply( + autowire.Core.Request( + parsed(0).asInstanceOf[Js.Arr].value.collect{case Js.Str(s) => s}, + parsed(1).value.asInstanceOf[Map[String, Js.Value]] + ) + ) + } +} +@JSExport +object Main extends Api{ + def main(bootSnippet: String, host: String, port: Int): Unit = { + def rec(): Unit = { + val f = Ajax.get(s"http://$host:$port/notifications") + + f.onSuccess { case data => + val parsed = json.read(data.responseText).asInstanceOf[Js.Arr] + WireServer.wire(parsed) + rec() + } (runNow) + () + } + rec() + } + + + override def clear(): Unit = ??? + + override def reload(): Unit = { + dom.console.log("Reloading page...") + dom.location.reload() + } + + override def run(path: String, bootSnippet: Option[String]): Unit = { + val tag = dom.document.createElement("script") + var loaded = false + + tag.setAttribute("src", path) + + bootSnippet.foreach{ bootSnippet => + tag.onreadystatechange = (e: dom.Event) => { + dom.console.log("Post-run reboot") + if (!loaded) { + dom.console.log("Post-run reboot go!") + js.eval(bootSnippet) + } + loaded = true + } + } + dom.document.head.appendChild(tag) + } + + override def print(level: String, msg: String): Unit = { + level match { + case "error" => dom.console.error(msg) + case "warn" => dom.console.warn(msg) + case "info" => dom.console.info(msg) + case "log" => dom.console.log(msg) } } }
\ No newline at end of file diff --git a/example/project/build.sbt b/example/project/build.sbt index 24009f8..4871695 100644 --- a/example/project/build.sbt +++ b/example/project/build.sbt @@ -1,6 +1,4 @@ -addSbtPlugin("org.scala-lang.modules.scalajs" % "scalajs-sbt-plugin" % "0.5.3") +addSbtPlugin("org.scala-lang.modules.scalajs" % "scalajs-sbt-plugin" % "0.5.4") -lazy val root = project.in( file(".") ).dependsOn( - file("../..") -)
\ No newline at end of file +lazy val root = project.in(file(".")).dependsOn(file("../.."))
\ No newline at end of file diff --git a/shared/main/scala/workbench/Shared.scala b/shared/main/scala/workbench/Shared.scala new file mode 100644 index 0000000..da202b4 --- /dev/null +++ b/shared/main/scala/workbench/Shared.scala @@ -0,0 +1,8 @@ +package com.lihaoyi.workbench + +trait Api{ + def clear(): Unit + def reload(): Unit + def print(level: String, msg: String): Unit + def run(path: String, bootSnippet: Option[String]): Unit +}
\ No newline at end of file diff --git a/shared/src/main/scala/workbench/Shared.scala b/shared/src/main/scala/workbench/Shared.scala deleted file mode 100644 index be0ee43..0000000 --- a/shared/src/main/scala/workbench/Shared.scala +++ /dev/null @@ -1 +0,0 @@ -package workbench diff --git a/plugin/src/main/scala/workbench/Plugin.scala b/src/main/scala/workbench/Plugin.scala index 3a434e8..8e122fe 100644 --- a/plugin/src/main/scala/workbench/Plugin.scala +++ b/src/main/scala/workbench/Plugin.scala @@ -1,3 +1,9 @@ +package com.lihaoyi.workbench +import sbt._ +import sbt.Keys._ +import autowire._ +import upickle.Js +import scala.concurrent.ExecutionContext.Implicits.global object Plugin extends sbt.Plugin { val refreshBrowsers = taskKey[Unit]("Sends a message to all connected web pages asking them to refresh the page") @@ -9,8 +15,6 @@ object Plugin extends sbt.Plugin { val bootSnippet = settingKey[String]("piece of javascript to make things happen") val updatedJS = taskKey[List[String]]("Provides the addresses of the JS files that have changed") - - val workbenchSettings = Seq( localUrl := ("localhost", 12345), updatedJS := { @@ -36,9 +40,9 @@ object Plugin extends sbt.Plugin { val clientLogger = FullLogger{ new Logger { def log(level: Level.Value, message: => String) = - if(level >= Level.Info) server.value msg Seq("print", level.toString, message) - def success(message: => String) = server.value msg Seq("print", "info", message) - def trace(t: => Throwable) = server.value msg Seq("print", "error", t.toString) + if(level >= Level.Info) server.value.Wire[Api].print(level.toString, message).call() + def success(message: => String) = server.value.Wire[Api].print("info", message).call() + def trace(t: => Throwable) = server.value.Wire[Api].print("error", t.toString).call() } } clientLogger.setSuccessEnabled(true) @@ -47,22 +51,17 @@ object Plugin extends sbt.Plugin { }, refreshBrowsers := { streams.value.log.info("workbench: Reloading Pages...") - server.value msg Seq("reload") + server.value.Wire[Api].reload().call() }, updateBrowsers := { val changed = updatedJS.value // There is no point in clearing the browser if no js files have changed. if (changed.length > 0) { - server.value msg Seq("clear") + server.value.Wire[Api].clear().call() - changed.foreach { - path => - streams.value.log.info("workbench: Refreshing " + path) - server.value msg Seq( - "run", - path, - bootSnippet.value - ) + changed.foreach { path => + streams.value.log.info("workbench: Refreshing " + path) + server.value.Wire[Api].run(path, Some(bootSnippet.value)).call() } } }, diff --git a/plugin/src/main/scala/workbench/Server.scala b/src/main/scala/workbench/Server.scala index b9773a7..96ac736 100644 --- a/plugin/src/main/scala/workbench/Server.scala +++ b/src/main/scala/workbench/Server.scala @@ -5,19 +5,28 @@ import com.typesafe.config.ConfigFactory import sbt.IO import spray.routing.SimpleRoutingApp import akka.actor.ActorDSL._ -import scala.Some -import upickle.{Writer, Json, Js} + +import upickle.{Reader, Writer, Js} import spray.http.{AllOrigins, HttpResponse} import spray.http.HttpHeaders.`Access-Control-Allow-Origin` import concurrent.duration._ +import scala.concurrent.Future + class Server(url: String, port: Int, bootSnippet: String) extends SimpleRoutingApp{ implicit val system = ActorSystem( "SystemLol", config = ConfigFactory.load(ActorSystem.getClass.getClassLoader), classLoader = ActorSystem.getClass.getClassLoader ) - - val pubSub = actor(new Actor{ + object Wire extends autowire.Client[Js.Value, upickle.Reader, upickle.Writer]{ + def doCall(req: Request): Future[Js.Value] = { + pubSub ! Js.Arr(Js.Str(req.path.mkString(".")), Js.Obj(req.args.toSeq:_*)) + Future.successful(Js.Null) + } + def write[Result: Writer](r: Result) = upickle.writeJs(r) + def read[Result: Reader](p: Js.Value) = upickle.readJs[Result](p) + } + private val pubSub = actor(new Actor{ var waitingActor: Option[ActorRef] = None var queuedMessages = List[Js.Value]() case object Clear @@ -37,15 +46,15 @@ class Server(url: String, port: Int, bootSnippet: String) extends SimpleRoutingA waitingActor = Some(a) case (a: ActorRef, None, msgs) => - respond(a, Json.write(Js.Array(msgs))) + respond(a, upickle.json.write(Js.Arr(msgs:_*))) queuedMessages = Nil - case (msg: Js.Array, None, msgs) => + case (msg: Js.Arr, None, msgs) => queuedMessages = msg :: msgs - case (msg: Js.Array, Some(a), Nil) => - respond(a, Json.write(Js.Array(Seq(msg)))) + case (msg: Js.Arr, Some(a), Nil) => + respond(a, upickle.json.write(Js.Arr(msg))) waitingActor = None case (Clear, Some(a), Nil) => - respond(a, Json.write(Js.Array(Nil))) + respond(a, upickle.json.write(Js.Arr())) waitingActor = None } }) @@ -56,10 +65,8 @@ class Server(url: String, port: Int, bootSnippet: String) extends SimpleRoutingA complete { IO.readStream( getClass.getClassLoader - .getResourceAsStream("workbench_template.js") - ).replace("<host>", url) - .replace("<port>", port.toString) - .replace("<bootSnippet>", bootSnippet) + .getResourceAsStream("client-opt.js") + ) + s"\nMain.main(${upickle.write(bootSnippet)}, ${upickle.write(url)}, ${upickle.write(port)})" } } ~ getFromDirectory(".") @@ -70,10 +77,6 @@ class Server(url: String, port: Int, bootSnippet: String) extends SimpleRoutingA } } } - - def msg[T: Writer](t: T) = { - pubSub ! upickle.writeJs(t) - } def kill() = { system.shutdown() } |