diff --git a/build.sbt b/build.sbt index 9cddbbb5..1c4680ee 100644 --- a/build.sbt +++ b/build.sbt @@ -1,38 +1,65 @@ +lazy val noPublishSettings = Seq( + publish := (), + publishLocal := (), + publishArtifact := false +) + lazy val root = (project in file(".")) .settings(mainClass in Universal := Some("org.scalaexercises.evaluator.EvaluatorServer")) .settings(stage <<= (stage in Universal in `evaluator-server`)) - .aggregate(`evaluator-server`, `evaluator-shared`, `evaluator-client`) + .settings(noPublishSettings: _*) + .aggregate(`evaluator-server`, `evaluator-shared-jvm`, `evaluator-shared-js`, `evaluator-client-jvm`, `evaluator-client-js`) -lazy val `evaluator-shared` = (project in file("shared")) +lazy val `evaluator-shared` = (crossProject in file("shared")) .enablePlugins(AutomateHeaderPlugin) .settings(name := "evaluator-shared") -lazy val `evaluator-client` = (project in file("client")) +lazy val `evaluator-shared-jvm` = `evaluator-shared`.jvm +lazy val `evaluator-shared-js` = `evaluator-shared`.js + +lazy val scalaJSSettings = Seq( + requiresDOM := false, + scalaJSUseRhino := false, + jsEnv := NodeJSEnv().value, + libraryDependencies ++= Seq( + "fr.hmil" %%% "roshttp" % v('roshttp), + "org.typelevel" %%% "cats-free" % v('cats), + "io.circe" %%% "circe-core" % v('circe), + "io.circe" %%% "circe-generic" % v('circe), + "io.circe" %%% "circe-parser" % v('circe) + ) +) + +lazy val `evaluator-client` = (crossProject in file("client")) .dependsOn(`evaluator-shared`) .enablePlugins(AutomateHeaderPlugin) .settings( name := "evaluator-client", - libraryDependencies <++= libraryVersions { v => Seq( + libraryDependencies ++= Seq( + "fr.hmil" %% "roshttp" % v('roshttp), "org.typelevel" %% "cats-free" % v('cats), - "io.circe" %% "circe-core" % v('circe), - "io.circe" %% "circe-generic" % v('circe), - "io.circe" %% "circe-parser" % v('circe), + "io.circe" %% "circe-core" % v('circe), + "io.circe" %% "circe-generic" % v('circe), + "io.circe" %% "circe-parser" % v('circe), "org.log4s" %% "log4s" % v('log4s), - "org.scalaj" %% "scalaj-http" % v('scalajhttp), "org.slf4j" % "slf4j-simple" % v('slf4j), // Testing libraries "org.scalatest" %% "scalatest" % v('scalaTest) % "test" ) - } - ) +) + .jsSettings(scalaJSSettings: _*) + +lazy val `evaluator-client-jvm` = `evaluator-client`.jvm +lazy val `evaluator-client-js` = `evaluator-client`.js lazy val `evaluator-server` = (project in file("server")) - .dependsOn(`evaluator-shared`) + .dependsOn(`evaluator-shared-jvm`) .enablePlugins(JavaAppPackaging) .enablePlugins(AutomateHeaderPlugin) + .settings(noPublishSettings: _*) .settings( name := "evaluator-server", - libraryDependencies <++= libraryVersions { v => Seq( + libraryDependencies ++= Seq( "io.monix" %% "monix" % v('monix), "org.http4s" %% "http4s-dsl" % v('http4s), "org.http4s" %% "http4s-blaze-server" % v('http4s), @@ -49,9 +76,8 @@ lazy val `evaluator-server` = (project in file("server")) "io.get-coursier" %% "coursier-cache" % v('coursier), "org.scalatest" %% "scalatest" % v('scalaTest) % "test" ) - } ) .settings(compilerDependencySettings: _*) onLoad in Global := (Command.process("project evaluator-server", _: State)) compose (onLoad in Global).value -addCommandAlias("publishSignedAll", ";evaluator-shared/publishSigned;evaluator-client/publishSigned") \ No newline at end of file +addCommandAlias("publishSignedAll", ";evaluator-sharedJS/publishSigned;evaluator-sharedJVM/publishSigned;evaluator-clientJS/publishSigned;evaluator-clientJVM/publishSigned") diff --git a/client/src/main/scala/org/scalaexercises/evaluator/Decoders.scala b/client/shared/src/main/scala/org/scalaexercises/evaluator/Decoders.scala similarity index 100% rename from client/src/main/scala/org/scalaexercises/evaluator/Decoders.scala rename to client/shared/src/main/scala/org/scalaexercises/evaluator/Decoders.scala diff --git a/client/shared/src/main/scala/org/scalaexercises/evaluator/EvaluatorAPI.scala b/client/shared/src/main/scala/org/scalaexercises/evaluator/EvaluatorAPI.scala new file mode 100644 index 00000000..7f9b92e2 --- /dev/null +++ b/client/shared/src/main/scala/org/scalaexercises/evaluator/EvaluatorAPI.scala @@ -0,0 +1,19 @@ +/* + * scala-exercises-evaluator-client + * Copyright (C) 2015-2016 47 Degrees, LLC. + */ + +package org.scalaexercises.evaluator + +import cats.free.Free +import org.scalaexercises.evaluator.EvaluatorResponses.EvaluationResponse +import org.scalaexercises.evaluator.free.algebra.EvaluatorOps + +class EvaluatorAPI[F[_]](url: String, authKey: String)( + implicit O: EvaluatorOps[F]) { + + def evaluates(resolvers: List[String] = Nil, + dependencies: List[Dependency] = Nil, + code: String): Free[F, EvaluationResponse[EvalResponse]] = + O.evaluates(url, authKey, resolvers, dependencies, code) +} diff --git a/client/shared/src/main/scala/org/scalaexercises/evaluator/EvaluatorClient.scala b/client/shared/src/main/scala/org/scalaexercises/evaluator/EvaluatorClient.scala new file mode 100644 index 00000000..6df3bef5 --- /dev/null +++ b/client/shared/src/main/scala/org/scalaexercises/evaluator/EvaluatorClient.scala @@ -0,0 +1,39 @@ +/* + * scala-exercises-evaluator-client + * Copyright (C) 2015-2016 47 Degrees, LLC. + */ + +package org.scalaexercises.evaluator + +import cats.data.XorT +import cats.~> +import cats._, cats.std.all._ +import org.scalaexercises.evaluator.EvaluatorResponses.{EvalIO, EvaluationException, EvaluationResponse, EvaluationResult} +import org.scalaexercises.evaluator.free.algebra.EvaluatorOp + +import scala.concurrent.Future +import scala.concurrent.ExecutionContext.Implicits.global + +class EvaluatorClient(url: String, authKey: String) { + + lazy val api: EvaluatorAPI[EvaluatorOp] = new EvaluatorAPI(url, authKey) + +} + +object EvaluatorClient { + + def apply(url: String, authKey: String) = + new EvaluatorClient(url, authKey) + + implicit class EvaluationIOSyntaxXOR[A]( + evalIO: EvalIO[EvaluationResponse[A]]) { + + def exec( + implicit I: (EvaluatorOp ~> Future)): Future[EvaluationResponse[A]] = + evalIO foldMap I + + def liftEvaluator: XorT[EvalIO, EvaluationException, EvaluationResult[A]] = + XorT[EvalIO, EvaluationException, EvaluationResult[A]](evalIO) + + } +} diff --git a/client/shared/src/main/scala/org/scalaexercises/evaluator/EvaluatorResponses.scala b/client/shared/src/main/scala/org/scalaexercises/evaluator/EvaluatorResponses.scala new file mode 100644 index 00000000..8a4ebfd3 --- /dev/null +++ b/client/shared/src/main/scala/org/scalaexercises/evaluator/EvaluatorResponses.scala @@ -0,0 +1,69 @@ +/* + * scala-exercises-evaluator-client + * Copyright (C) 2015-2016 47 Degrees, LLC. + */ + +package org.scalaexercises.evaluator + +import cats.data.Xor +import cats.free.Free +import cats.syntax.xor._ +import io.circe.Decoder +import io.circe.parser._ +import io.circe.generic.auto._ +import org.scalaexercises.evaluator.free.algebra.EvaluatorOp + +import scala.concurrent.Future +import scala.concurrent.ExecutionContext.Implicits.global + +import fr.hmil.roshttp.HttpResponse +import fr.hmil.roshttp.HeaderMap + +object EvaluatorResponses { + + type EvalIO[A] = Free[EvaluatorOp, A] + + type EvaluationResponse[A] = EvaluationException Xor EvaluationResult[A] + + case class EvaluationResult[A](result: A, + statusCode: Int, + headers: Map[String, String]) + + sealed abstract class EvaluationException(msg: String, + cause: Option[Throwable] = None) + extends Throwable(msg) { + cause foreach initCause + } + + case class JsonParsingException(msg: String, json: String) + extends EvaluationException(msg) + + case class UnexpectedException(msg: String) extends EvaluationException(msg) + + def toEntity[A](futureResponse: Future[HttpResponse])( + implicit D: Decoder[A]): Future[EvaluationResponse[A]] = + futureResponse map { + case r if isSuccess(r.statusCode) ⇒ + decode[A](r.body).fold( + e ⇒ + JsonParsingException(e.getMessage, r.body) + .left[EvaluationResult[A]], + result ⇒ + Xor.Right( + EvaluationResult(result, r.statusCode, r.headers.toLowerCase)) + ) + case r ⇒ + UnexpectedException( + s"Failed invoking get with status : ${r.statusCode}, body : \n ${r.body}") + .left[EvaluationResult[A]] + } + + private[this] def isSuccess(statusCode: Int) = + statusCode >= 200 && statusCode <= 299 + + implicit class HeadersLowerCase[A >: String](headers: HeaderMap[A]) { + + def toLowerCase: Map[String, A] = + headers.iterator.map(t => (t._1.toLowerCase, t._2)).toList.toMap + } +} diff --git a/client/src/main/scala/org/scalaexercises/evaluator/api/Evaluator.scala b/client/shared/src/main/scala/org/scalaexercises/evaluator/api/Evaluator.scala similarity index 77% rename from client/src/main/scala/org/scalaexercises/evaluator/api/Evaluator.scala rename to client/shared/src/main/scala/org/scalaexercises/evaluator/api/Evaluator.scala index 332fb92e..05db870a 100644 --- a/client/src/main/scala/org/scalaexercises/evaluator/api/Evaluator.scala +++ b/client/shared/src/main/scala/org/scalaexercises/evaluator/api/Evaluator.scala @@ -11,7 +11,7 @@ import org.scalaexercises.evaluator.http.HttpClient import io.circe.generic.auto._ import io.circe.syntax._ -import scala.concurrent.duration.Duration +import scala.concurrent.Future class Evaluator { @@ -21,16 +21,12 @@ class Evaluator { def eval(url: String, authKey: String, - connTimeout: Duration, - readTimeout: Duration, resolvers: List[String] = Nil, dependencies: List[Dependency] = Nil, - code: String): EvaluationResponse[EvalResponse] = + code: String): Future[EvaluationResponse[EvalResponse]] = httpClient.post[EvalResponse]( url = url, secretKey = authKey, - connTimeout = connTimeout, - readTimeout = readTimeout, data = EvalRequest(resolvers, dependencies, code).asJson.noSpaces) } diff --git a/client/src/main/scala/org/scalaexercises/evaluator/free/algebra/EvaluatorOps.scala b/client/shared/src/main/scala/org/scalaexercises/evaluator/free/algebra/EvaluatorOps.scala similarity index 74% rename from client/src/main/scala/org/scalaexercises/evaluator/free/algebra/EvaluatorOps.scala rename to client/shared/src/main/scala/org/scalaexercises/evaluator/free/algebra/EvaluatorOps.scala index a78ee978..11b3e555 100644 --- a/client/src/main/scala/org/scalaexercises/evaluator/free/algebra/EvaluatorOps.scala +++ b/client/shared/src/main/scala/org/scalaexercises/evaluator/free/algebra/EvaluatorOps.scala @@ -9,14 +9,9 @@ import cats.free.{Free, Inject} import org.scalaexercises.evaluator.{Dependency, EvalResponse} import org.scalaexercises.evaluator.EvaluatorResponses.EvaluationResponse -import scala.concurrent.duration._ -import scala.concurrent.duration.Duration - sealed trait EvaluatorOp[A] final case class Evaluates(url: String, authKey: String, - connTimeout: Duration, - readTimeout: Duration, resolvers: List[String] = Nil, dependencies: List[Dependency] = Nil, code: String) @@ -27,21 +22,12 @@ class EvaluatorOps[F[_]](implicit I: Inject[EvaluatorOp, F]) { def evaluates( url: String, authKey: String, - connTimeout: Duration, - readTimeout: Duration, resolvers: List[String] = Nil, dependencies: List[Dependency] = Nil, code: String ): Free[F, EvaluationResponse[EvalResponse]] = Free.inject[EvaluatorOp, F]( - Evaluates( - url, - authKey, - connTimeout, - readTimeout, - resolvers, - dependencies, - code)) + Evaluates(url, authKey, resolvers, dependencies, code)) } diff --git a/client/shared/src/main/scala/org/scalaexercises/evaluator/free/interpreters/Interpreter.scala b/client/shared/src/main/scala/org/scalaexercises/evaluator/free/interpreters/Interpreter.scala new file mode 100644 index 00000000..687bbceb --- /dev/null +++ b/client/shared/src/main/scala/org/scalaexercises/evaluator/free/interpreters/Interpreter.scala @@ -0,0 +1,30 @@ +/* + * scala-exercises-evaluator-client + * Copyright (C) 2015-2016 47 Degrees, LLC. + */ + +package org.scalaexercises.evaluator.free.interpreters + +import cats.~> +import org.scalaexercises.evaluator.api.Evaluator +import org.scalaexercises.evaluator.free.algebra.{Evaluates, EvaluatorOp} + +import scala.concurrent.Future + +trait Interpreter { + + /** + * Lifts Evaluator Ops to an effect capturing Monad such as Task via natural transformations + */ + implicit def evaluatorOpsInterpreter: EvaluatorOp ~> Future = + new (EvaluatorOp ~> Future) { + + val evaluator = new Evaluator() + + def apply[A](fa: EvaluatorOp[A]): Future[A] = fa match { + case Evaluates(url, authKey, resolvers, dependencies, code) ⇒ + evaluator.eval(url, authKey, resolvers, dependencies, code) + } + + } +} diff --git a/client/src/main/scala/org/scalaexercises/evaluator/http/HttpClient.scala b/client/shared/src/main/scala/org/scalaexercises/evaluator/http/HttpClient.scala similarity index 69% rename from client/src/main/scala/org/scalaexercises/evaluator/http/HttpClient.scala rename to client/shared/src/main/scala/org/scalaexercises/evaluator/http/HttpClient.scala index da58573e..aa9e0da5 100644 --- a/client/src/main/scala/org/scalaexercises/evaluator/http/HttpClient.scala +++ b/client/shared/src/main/scala/org/scalaexercises/evaluator/http/HttpClient.scala @@ -9,8 +9,7 @@ import io.circe.Decoder import org.scalaexercises.evaluator.EvaluatorResponses import org.scalaexercises.evaluator.EvaluatorResponses.EvaluationResponse -import scala.concurrent.duration._ -import scala.concurrent.duration.Duration +import scala.concurrent.Future object HttpClient { @@ -26,17 +25,11 @@ class HttpClient { url: String, secretKey: String, method: String = "post", - connTimeout: Duration, - readTimeout: Duration, headers: Headers = Map.empty, data: String - )(implicit D: Decoder[A]): EvaluationResponse[A] = + )(implicit D: Decoder[A]): Future[EvaluationResponse[A]] = EvaluatorResponses.toEntity( - HttpRequestBuilder( - url = url, - httpVerb = method, - connTimeout = connTimeout, - readTimeout = readTimeout) + HttpRequestBuilder(url = url, httpVerb = method) .withHeaders(headers + (authHeaderName -> secretKey)) .withBody(data) .run) diff --git a/client/shared/src/main/scala/org/scalaexercises/evaluator/http/HttpRequestBuilder.scala b/client/shared/src/main/scala/org/scalaexercises/evaluator/http/HttpRequestBuilder.scala new file mode 100644 index 00000000..bbbd4689 --- /dev/null +++ b/client/shared/src/main/scala/org/scalaexercises/evaluator/http/HttpRequestBuilder.scala @@ -0,0 +1,43 @@ +/* + * scala-exercises-evaluator-client + * Copyright (C) 2015-2016 47 Degrees, LLC. + */ + +package org.scalaexercises.evaluator.http + +import org.scalaexercises.evaluator.http.HttpClient._ + +import scala.concurrent.Future + +import fr.hmil.roshttp.{HttpRequest, Method, HttpResponse} +import fr.hmil.roshttp.body.BodyPart + +import java.nio.ByteBuffer + +case class HttpRequestBuilder( + url: String, + httpVerb: String, + headers: Headers = Map.empty[String, String], + body: String = "" +) { + + case class CirceJSONBody(value: String) extends BodyPart { + override def contentType: String = s"application/json; charset=utf-8" + + override def content: ByteBuffer = ByteBuffer.wrap(value.getBytes("utf-8")) + } + + def withHeaders(headers: Headers) = copy(headers = headers) + + def withBody(body: String) = copy(body = body) + + def run: Future[HttpResponse] = { + + val request = HttpRequest(url) + .withMethod(Method(httpVerb)) + .withHeader("content-type", "application/json") + .withHeaders(headers.toList: _*) + + request.send(CirceJSONBody(body)) + } +} diff --git a/client/shared/src/main/scala/org/scalaexercises/evaluator/implicits.scala b/client/shared/src/main/scala/org/scalaexercises/evaluator/implicits.scala new file mode 100644 index 00000000..c1fdd0f6 --- /dev/null +++ b/client/shared/src/main/scala/org/scalaexercises/evaluator/implicits.scala @@ -0,0 +1,10 @@ +/* + * scala-exercises-evaluator-client + * Copyright (C) 2015-2016 47 Degrees, LLC. + */ + +package org.scalaexercises.evaluator + +import org.scalaexercises.evaluator.free.interpreters.Interpreter + +object implicits extends Interpreter diff --git a/client/src/main/scala/org/scalaexercises/evaluator/EvaluatorAPI.scala b/client/src/main/scala/org/scalaexercises/evaluator/EvaluatorAPI.scala deleted file mode 100644 index c5e7dec1..00000000 --- a/client/src/main/scala/org/scalaexercises/evaluator/EvaluatorAPI.scala +++ /dev/null @@ -1,30 +0,0 @@ -/* - * scala-exercises-evaluator-client - * Copyright (C) 2015-2016 47 Degrees, LLC. - */ - -package org.scalaexercises.evaluator - -import cats.free.Free -import org.scalaexercises.evaluator.EvaluatorResponses.EvaluationResponse -import org.scalaexercises.evaluator.free.algebra.{EvaluatorOp, EvaluatorOps} - -import scala.concurrent.duration.Duration - -class EvaluatorAPI[F[_]](url: String, - authKey: String, - connTimeout: Duration, - readTimeout: Duration)(implicit O: EvaluatorOps[F]) { - - def evaluates(resolvers: List[String] = Nil, - dependencies: List[Dependency] = Nil, - code: String): Free[F, EvaluationResponse[EvalResponse]] = - O.evaluates( - url, - authKey, - connTimeout, - readTimeout, - resolvers, - dependencies, - code) -} diff --git a/client/src/main/scala/org/scalaexercises/evaluator/EvaluatorClient.scala b/client/src/main/scala/org/scalaexercises/evaluator/EvaluatorClient.scala deleted file mode 100644 index 1b60b50c..00000000 --- a/client/src/main/scala/org/scalaexercises/evaluator/EvaluatorClient.scala +++ /dev/null @@ -1,45 +0,0 @@ -/* - * scala-exercises-evaluator-client - * Copyright (C) 2015-2016 47 Degrees, LLC. - */ - -package org.scalaexercises.evaluator - -import cats.data.XorT -import cats.{MonadError, ~>} -import org.scalaexercises.evaluator.EvaluatorResponses.{EvalIO, EvaluationException, EvaluationResponse, EvaluationResult} -import org.scalaexercises.evaluator.free.algebra.EvaluatorOp - -import scala.concurrent.duration._ -import scala.concurrent.duration.Duration - -class EvaluatorClient(url: String, - authKey: String, - connTimeout: Duration = 1.second, - readTimeout: Duration = 10.seconds) { - - lazy val api: EvaluatorAPI[EvaluatorOp] = - new EvaluatorAPI(url, authKey, connTimeout, readTimeout) - -} - -object EvaluatorClient { - - def apply(url: String, - authKey: String, - connTimeout: Duration = 1.second, - readTimeout: Duration = 10.seconds) = - new EvaluatorClient(url, authKey, connTimeout, readTimeout) - - implicit class EvaluationIOSyntaxXOR[A]( - evalIO: EvalIO[EvaluationResponse[A]]) { - - def exec[M[_]](implicit I: (EvaluatorOp ~> M), - A: MonadError[M, Throwable]): M[EvaluationResponse[A]] = - evalIO foldMap I - - def liftEvaluator: XorT[EvalIO, EvaluationException, EvaluationResult[A]] = - XorT[EvalIO, EvaluationException, EvaluationResult[A]](evalIO) - - } -} diff --git a/client/src/main/scala/org/scalaexercises/evaluator/EvaluatorResponses.scala b/client/src/main/scala/org/scalaexercises/evaluator/EvaluatorResponses.scala deleted file mode 100644 index b305a942..00000000 --- a/client/src/main/scala/org/scalaexercises/evaluator/EvaluatorResponses.scala +++ /dev/null @@ -1,60 +0,0 @@ -/* - * scala-exercises-evaluator-client - * Copyright (C) 2015-2016 47 Degrees, LLC. - */ - -package org.scalaexercises.evaluator - -import cats.data.Xor -import cats.free.Free -import cats.syntax.xor._ -import io.circe.Decoder -import io.circe.parser._ -import io.circe.generic.auto._ -import org.scalaexercises.evaluator.free.algebra.EvaluatorOp - -import scala.language.higherKinds -import scalaj.http.HttpResponse - -object EvaluatorResponses { - - type EvalIO[A] = Free[EvaluatorOp, A] - - type EvaluationResponse[A] = EvaluationException Xor EvaluationResult[A] - - case class EvaluationResult[A](result: A, - statusCode: Int, - headers: Map[String, IndexedSeq[String]]) - - sealed abstract class EvaluationException(msg: String, - cause: Option[Throwable] = None) - extends Throwable(msg) { - cause foreach initCause - } - - case class JsonParsingException(msg: String, json: String) - extends EvaluationException(msg) - - case class UnexpectedException(msg: String) extends EvaluationException(msg) - - def toEntity[A](response: HttpResponse[String])( - implicit D: Decoder[A]): EvaluationResponse[A] = response match { - case r if r.isSuccess ⇒ - decode[A](r.body).fold( - e ⇒ - JsonParsingException(e.getMessage, r.body).left[EvaluationResult[A]], - result ⇒ - Xor.Right(EvaluationResult(result, r.code, r.headers.toLowerCase)) - ) - case r ⇒ - UnexpectedException( - s"Failed invoking get with status : ${r.code}, body : \n ${r.body}") - .left[EvaluationResult[A]] - } - - implicit class HeadersLowerCase[A](headers: Map[String, A]) { - - def toLowerCase: Map[String, A] = headers.map(e ⇒ (e._1.toLowerCase, e._2)) - - } -} diff --git a/client/src/main/scala/org/scalaexercises/evaluator/free/interpreters/Interpreter.scala b/client/src/main/scala/org/scalaexercises/evaluator/free/interpreters/Interpreter.scala deleted file mode 100644 index dd1d2130..00000000 --- a/client/src/main/scala/org/scalaexercises/evaluator/free/interpreters/Interpreter.scala +++ /dev/null @@ -1,51 +0,0 @@ -/* - * scala-exercises-evaluator-client - * Copyright (C) 2015-2016 47 Degrees, LLC. - */ - -package org.scalaexercises.evaluator.free.interpreters - -import cats.{ApplicativeError, Eval, MonadError, ~>} -import org.scalaexercises.evaluator.api.Evaluator -import org.scalaexercises.evaluator.free.algebra.{Evaluates, EvaluatorOp} - -import scala.language.higherKinds - -trait Interpreter { - - implicit def interpreter[M[_]]( - implicit A: MonadError[M, Throwable] - ): EvaluatorOp ~> M = evaluatorOpsInterpreter[M] - - /** - * Lifts Evaluator Ops to an effect capturing Monad such as Task via natural transformations - */ - def evaluatorOpsInterpreter[M[_]]( - implicit A: ApplicativeError[M, Throwable]): EvaluatorOp ~> M = - new (EvaluatorOp ~> M) { - - val evaluator = new Evaluator() - - def apply[A](fa: EvaluatorOp[A]): M[A] = fa match { - case Evaluates( - url, - authKey, - connTimeout, - readTimeout, - resolvers, - dependencies, - code) ⇒ - A.pureEval( - Eval.later( - evaluator.eval( - url, - authKey, - connTimeout, - readTimeout, - resolvers, - dependencies, - code))) - } - - } -} diff --git a/client/src/main/scala/org/scalaexercises/evaluator/http/HttpRequestBuilder.scala b/client/src/main/scala/org/scalaexercises/evaluator/http/HttpRequestBuilder.scala deleted file mode 100644 index 5485cbec..00000000 --- a/client/src/main/scala/org/scalaexercises/evaluator/http/HttpRequestBuilder.scala +++ /dev/null @@ -1,39 +0,0 @@ -/* - * scala-exercises-evaluator-client - * Copyright (C) 2015-2016 47 Degrees, LLC. - */ - -package org.scalaexercises.evaluator.http - -import org.scalaexercises.evaluator.http.HttpClient._ - -import scala.concurrent.duration.Duration -import scalaj.http.{Http, HttpOptions} - -case class HttpRequestBuilder( - url: String, - httpVerb: String, - connTimeout: Duration, - readTimeout: Duration, - followRedirects: Boolean = true, - headers: Headers = Map.empty[String, String], - body: Option[String] = None -) { - - def withHeaders(headers: Headers) = copy(headers = headers) - - def withBody(body: String) = copy(body = Option(body)) - - def run = { - val request = Http(url).method(httpVerb).headers(headers) - - body - .fold(request)( - request - .option(HttpOptions.connTimeout(connTimeout.toMillis.toInt)) - .option(HttpOptions.readTimeout(readTimeout.toMillis.toInt)) - .postData(_) - .header("content-type", "application/json")) - .asString - } -} diff --git a/client/src/main/scala/org/scalaexercises/evaluator/implicits.scala b/client/src/main/scala/org/scalaexercises/evaluator/implicits.scala deleted file mode 100644 index 84043653..00000000 --- a/client/src/main/scala/org/scalaexercises/evaluator/implicits.scala +++ /dev/null @@ -1,41 +0,0 @@ -/* - * scala-exercises-evaluator-client - * Copyright (C) 2015-2016 47 Degrees, LLC. - */ - -package org.scalaexercises.evaluator - -import cats.std.FutureInstances -import cats.std.future._ -import cats.{Eval, MonadError} -import org.scalaexercises.evaluator.free.interpreters.Interpreter - -object implicits extends Interpreter with EvalInstances with FutureInstances - -trait EvalInstances { - - implicit val evalMonadError: MonadError[Eval, Throwable] = - new MonadError[Eval, Throwable] { - - override def pure[A](x: A): Eval[A] = Eval.now(x) - - override def map[A, B](fa: Eval[A])(f: A ⇒ B): Eval[B] = fa.map(f) - - override def flatMap[A, B](fa: Eval[A])(ff: A ⇒ Eval[B]): Eval[B] = - fa.flatMap(ff) - - override def raiseError[A](e: Throwable): Eval[A] = - Eval.later({ throw e }) - - override def handleErrorWith[A](fa: Eval[A])( - f: Throwable ⇒ Eval[A]): Eval[A] = - Eval.later({ - try { - fa.value - } catch { - case e: Throwable ⇒ f(e).value - } - }) - } - -} diff --git a/project/EvaluatorBuild.scala b/project/EvaluatorBuild.scala index f8a6ad6b..bcd65353 100644 --- a/project/EvaluatorBuild.scala +++ b/project/EvaluatorBuild.scala @@ -14,7 +14,21 @@ object EvaluatorBuild extends AutoPlugin { object autoImport { - val libraryVersions = settingKey[Map[Symbol, String]]("Common versions to be used for dependencies") + val v = Map( + 'cats -> "0.6.1", + 'circe -> "0.5.0-M2", + 'config -> "1.3.0", + 'coursier -> "1.0.0-M12", + 'http4s -> "0.14.1", + 'jwtcore -> "0.8.0", + 'log4s -> "1.3.0", + 'monix -> "2.0-RC8", + 'roshttp -> "1.1.0", + 'scalacheck -> "1.12.5", + 'scalaTest -> "2.2.6", + 'slf4j -> "1.7.21" + ) + def compilerDependencySettings = Seq( libraryDependencies ++= Seq( @@ -31,13 +45,12 @@ object EvaluatorBuild extends AutoPlugin { override def projectSettings = baseSettings ++ reformatOnCompileSettings ++ - dependencySettings ++ publishSettings ++ miscSettings private[this] def baseSettings = Seq( - version := "0.0.3-SNAPSHOT", + version := "0.1.0-SNAPSHOT", organization := "org.scala-exercises", scalaVersion := "2.11.8", scalafmtConfig in ThisBuild := Some(file(".scalafmt")), @@ -55,23 +68,6 @@ object EvaluatorBuild extends AutoPlugin { javacOptions ++= Seq("-encoding", "UTF-8", "-Xlint:-options") ) - private[this] def dependencySettings = Seq( - libraryVersions := Map( - 'cats -> "0.6.1", - 'circe -> "0.5.0-M2", - 'config -> "1.3.0", - 'coursier -> "1.0.0-M12", - 'http4s -> "0.14.1", - 'jwtcore -> "0.8.0", - 'log4s -> "1.3.0", - 'monix -> "2.0-RC8", - 'scalajhttp -> "2.3.0", - 'scalacheck -> "1.12.5", - 'scalaTest -> "2.2.6", - 'slf4j -> "1.7.21" - ) - ) - private[this] def miscSettings = Seq( headers <<= (name, version) { (name, version) => Map( "scala" -> ( @@ -128,4 +124,4 @@ object EvaluatorBuild extends AutoPlugin { Some("Releases" at nexus + "service/local/staging/deploy/maven2") } ) -} \ No newline at end of file +} diff --git a/project/plugins.sbt b/project/plugins.sbt index 85e4cdec..a68ff8a3 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -2,3 +2,4 @@ addSbtPlugin("com.typesafe.sbt" % "sbt-native-packager" % "1.1.1") addSbtPlugin("com.geirsson" % "sbt-scalafmt" % "0.2.11") addSbtPlugin("de.heikoseeberger" % "sbt-header" % "1.6.0") addSbtPlugin("com.jsuereth" % "sbt-pgp" % "1.0.1") +addSbtPlugin("org.scala-js" % "sbt-scalajs" % "0.6.12") \ No newline at end of file diff --git a/server/src/main/scala/org/scalaexercises/evaluator/evaluation.scala b/server/src/main/scala/org/scalaexercises/evaluator/evaluation.scala index 0b307bc7..63bbe528 100644 --- a/server/src/main/scala/org/scalaexercises/evaluator/evaluation.scala +++ b/server/src/main/scala/org/scalaexercises/evaluator/evaluation.scala @@ -57,7 +57,8 @@ class Evaluator(timeout: FiniteDuration = 20.seconds)( def resolveArtifacts(remotes: Seq[Remote], dependencies: Seq[Dependency]): Task[Resolution] = { val resolution = Resolution(dependencies.map(dependencyToModule).toSet) - val repositories: Seq[Repository] = Cache.ivy2Local +: remotes.map(remoteToRepository) + val repositories: Seq[Repository] = Cache.ivy2Local +: remotes.map( + remoteToRepository) val fetch = Fetch.from(repositories, Cache.fetch()) resolution.process.run(fetch) } diff --git a/shared/src/main/scala/org/scalaexercises/evaluator/types.scala b/shared/shared/src/main/scala/org/scalaexercises/evaluator/types.scala similarity index 100% rename from shared/src/main/scala/org/scalaexercises/evaluator/types.scala rename to shared/shared/src/main/scala/org/scalaexercises/evaluator/types.scala