Skip to content

Commit 65b93e2

Browse files
authored
Split lib from examples (#8)
* split lib from example * Removing the play dependency on core module * Remove playJdbc and anorm dependencies on core * Reformatting code * Fix missing jdbc dependency * Remove version per project in build.sbt * Change organization domain * Cleaning: delete utils package * Fully qualified package name with organization name * update package name + projects arborescence
1 parent 0bdb704 commit 65b93e2

File tree

10 files changed

+186
-135
lines changed

10 files changed

+186
-135
lines changed

app/database/package.scala

Lines changed: 0 additions & 23 deletions
This file was deleted.

app/utils/ReaderT.scala

Lines changed: 0 additions & 25 deletions
This file was deleted.

app/utils/package.scala

Lines changed: 0 additions & 31 deletions
This file was deleted.

build.sbt

Lines changed: 70 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,83 @@
1+
import Dependencies._
2+
13
name := """query-monad-code"""
24

35
version := "1.0-SNAPSHOT"
46

5-
lazy val root = (project in file(".")).enablePlugins(PlayScala)
6-
77
scalaVersion := "2.12.4"
88

9-
libraryDependencies ++= Seq(
10-
jdbc,
11-
"org.playframework.anorm" %% "anorm" % "2.6.0",
12-
"org.typelevel" %% "cats-core" % "1.0.1",
13-
"org.scalatestplus.play" %% "scalatestplus-play" % "3.1.1" % Test
9+
// Common values
10+
val commonSettings = Seq(
11+
organization := "com.zengularity",
12+
scalaVersion := "2.12.4",
13+
crossPaths := false,
14+
scalacOptions ++= Seq(
15+
"-deprecation", // Emit warning and location for usages of deprecated APIs.
16+
"-encoding",
17+
"utf-8", // Specify character encoding used by source files.
18+
"-explaintypes", // Explain type errors in more detail.
19+
"-feature", // Emit warning and location for usages of features that should be imported explicitly.
20+
"-unchecked", // Enable additional warnings where generated code depends on assumptions.
21+
"-Xcheckinit", // Wrap field accessors to throw an exception on uninitialized access.
22+
"-Xfatal-warnings", // Fail the compilation if there are any warnings.
23+
"-Xlint",
24+
"-Yno-adapted-args", // Do not adapt an argument list (either by inserting () or creating a tuple) to match the receiver.
25+
"-Ypartial-unification", // Enable partial unification in type constructor inference
26+
"-Ywarn-dead-code", // Warn when dead code is identified.
27+
"-Ywarn-extra-implicit", // Warn when more than one implicit parameter section is defined.
28+
"-Ywarn-inaccessible", // Warn about inaccessible types in method signatures.
29+
"-Ywarn-infer-any", // Warn when a type argument is inferred to be `Any`.
30+
"-Ywarn-nullary-override", // Warn when non-nullary `def f()' overrides nullary `def f'.
31+
"-Ywarn-nullary-unit", // Warn when nullary methods return Unit.
32+
"-Ywarn-numeric-widen", // Warn when numerics are widened.
33+
"-Ywarn-unused", // Warn if unused.
34+
"-Ywarn-value-discard" // Warn when non-Unit expression results are unused.
35+
),
36+
scalacOptions in (Compile, console) ~= (_.filterNot(
37+
Set(
38+
"-Ywarn-unused:imports",
39+
"-Xfatal-warnings"
40+
))),
41+
scalacOptions in (Test, compile) ~= (_.filterNot(
42+
Set(
43+
"-Ywarn-unused:imports",
44+
"-Xfatal-warnings"
45+
))),
46+
resolvers ++= Seq[Resolver](
47+
Resolver.sonatypeRepo("releases")
48+
)
1449
)
1550

16-
wartremoverErrors ++= Warts.unsafe
51+
scalafmtOnCompile := true
52+
scalafmtConfig := file("project/scalafmt.conf")
1753

18-
scalacOptions ++= Seq(
19-
"-deprecation", // Emit warning and location for usages of deprecated APIs.
20-
"-encoding",
21-
"utf-8", // Specify character encoding used by source files.
22-
"-explaintypes", // Explain type errors in more detail.
23-
"-feature", // Emit warning and location for usages of features that should be imported explicitly.
24-
"-unchecked", // Enable additional warnings where generated code depends on assumptions.
25-
"-Xcheckinit", // Wrap field accessors to throw an exception on uninitialized access.
26-
"-Xfatal-warnings", // Fail the compilation if there are any warnings.
27-
"-Xlint",
28-
"-Yno-adapted-args", // Do not adapt an argument list (either by inserting () or creating a tuple) to match the receiver.
29-
"-Ypartial-unification", // Enable partial unification in type constructor inference
30-
"-Ywarn-dead-code", // Warn when dead code is identified.
31-
"-Ywarn-extra-implicit", // Warn when more than one implicit parameter section is defined.
32-
"-Ywarn-inaccessible", // Warn about inaccessible types in method signatures.
33-
"-Ywarn-infer-any", // Warn when a type argument is inferred to be `Any`.
34-
"-Ywarn-nullary-override", // Warn when non-nullary `def f()' overrides nullary `def f'.
35-
"-Ywarn-nullary-unit", // Warn when nullary methods return Unit.
36-
"-Ywarn-numeric-widen", // Warn when numerics are widened.
37-
"-Ywarn-unused", // Warn if unused.
38-
"-Ywarn-value-discard" // Warn when non-Unit expression results are unused.
39-
)
54+
wartremoverErrors ++= Warts.unsafe
4055

41-
scalacOptions in (Compile, console) ~= (_.filterNot(
42-
Set(
43-
"-Ywarn-unused:imports",
44-
"-Xfatal-warnings"
45-
)))
56+
// Projects definitions
4657

47-
scalacOptions in (Test, compile) ~= (_.filterNot(
48-
Set(
49-
"-Ywarn-unused:imports",
50-
"-Xfatal-warnings"
51-
)))
58+
lazy val core = (project in file("core"))
59+
.settings(commonSettings)
60+
.settings(
61+
name := "query-core",
62+
libraryDependencies ++= Seq(
63+
Dependencies.cats
64+
)
65+
)
5266

53-
scalafmtOnCompile := true
54-
scalafmtConfig := file("project/scalafmt.conf")
67+
lazy val sampleAppExample = (project in file("examples/sample-app"))
68+
.enablePlugins(PlayScala)
69+
.settings(commonSettings)
70+
.settings(
71+
name := "sample-app-example",
72+
libraryDependencies ++= Seq(
73+
jdbc,
74+
Dependencies.anorm,
75+
Dependencies.h2,
76+
Dependencies.scalaTestPlusPlay
77+
)
78+
)
79+
.dependsOn(core)
5580

56-
wartremoverErrors in (Compile, compile) ++= Warts.unsafe
81+
lazy val root: Project = project
82+
.in(file("."))
83+
.aggregate(core, sampleAppExample)
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package com.zengularity.querymonad.core.database
2+
3+
import java.sql.Connection
4+
import javax.sql.DataSource
5+
6+
import scala.util.control.ControlThrowable
7+
8+
/**
9+
* This class is copy from Play DefaultDatabase class.
10+
* See https://github.com/playframework/playframework/blob/master/framework/src/play-jdbc/src/main/scala/play/api/db/Databases.scala#L94
11+
*
12+
* @dataSource managed dataSource used to obtain connection.
13+
*/
14+
class Database(dataSource: DataSource) {
15+
16+
def getConnection(autocommit: Boolean): Connection = {
17+
val connection = dataSource.getConnection
18+
connection.setAutoCommit(autocommit)
19+
connection
20+
}
21+
22+
def withConnection[A](block: Connection => A): A = {
23+
withConnection(autocommit = true)(block)
24+
}
25+
26+
def withConnection[A](autocommit: Boolean)(block: Connection => A): A = {
27+
val connection = getConnection(autocommit)
28+
try {
29+
block(connection)
30+
} finally {
31+
connection.close()
32+
}
33+
}
34+
35+
def withTransaction[A](block: Connection => A): A = {
36+
withConnection(autocommit = false) { connection =>
37+
try {
38+
val r = block(connection)
39+
connection.commit()
40+
r
41+
} catch {
42+
case e: ControlThrowable =>
43+
connection.commit()
44+
throw e
45+
case e: Throwable =>
46+
connection.rollback()
47+
throw e
48+
}
49+
}
50+
}
51+
52+
}
53+
54+
object Database {
55+
def apply(dataSource: DataSource): Database = new Database(dataSource)
56+
}
Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,29 @@
1-
package database
1+
package com.zengularity.querymonad.core.database
22

3-
import scala.concurrent.{ExecutionContext, Future}
3+
import javax.sql.DataSource
44

5-
import play.api.db.Database
5+
import scala.concurrent.{ExecutionContext, Future}
66

7-
class QueryRunner[DB <: Database](
7+
class QueryRunner(
88
db: Database,
99
ec: ExecutionContext
1010
) {
1111
def run[A](query: Query[A]): Future[A] =
1212
Future {
13-
db.withConnection(query.f)
13+
db.withConnection(query.run)
1414
}(ec)
1515

1616
// TODO: Remove with a transaction run at context level
1717
def commit[A](query: Query[A]): Future[A] =
1818
Future {
19-
db.withTransaction(query.f)
19+
db.withTransaction(query.run)
2020
}(ec)
2121
}
2222

2323
object QueryRunner {
24-
def apply[DB <: Database](db: Database, ec: ExecutionContext) =
24+
def apply(db: Database, ec: ExecutionContext) =
2525
new QueryRunner(db, ec)
26+
27+
def apply(ds: DataSource, ec: ExecutionContext) =
28+
new QueryRunner(Database(ds), ec)
2629
}
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
package com.zengularity.querymonad.core
2+
3+
import java.sql.Connection
4+
5+
import scala.language.higherKinds
6+
7+
import cats.{Applicative, Id}
8+
import cats.data.{Reader, ReaderT}
9+
10+
package object database {
11+
type Query[A] = Reader[Connection, A]
12+
13+
object Query {
14+
def pure[A](a: A) = ReaderT.pure[Id, Connection, A](a)
15+
16+
val ask = ReaderT.ask[Id, Connection]
17+
18+
def apply[A](f: Connection => A) = new Query(f)
19+
}
20+
21+
type QueryT[F[_], A] = ReaderT[F, Connection, A]
22+
23+
object QueryT {
24+
def pure[M[_]: Applicative, A](a: A) = ReaderT.pure[M, Connection, A](a)
25+
26+
def ask[M[_]: Applicative] = ReaderT.ask[M, Connection]
27+
28+
def liftF[M[_], A](ma: M[A]) = ReaderT.liftF[M, Connection, A](ma)
29+
}
30+
31+
type QueryO[A] = QueryT[Option, A]
32+
33+
type QueryE[A, Err] = QueryT[({ type Res[T] = Either[Err, T] })#Res, A]
34+
}

app/wiring/AppLoader.scala renamed to examples/sample-app/app/wiring/AppLoader.scala

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,16 @@
1-
package wiring
1+
package com.zengularity.querymonad.examples.wiring
22

33
import scala.concurrent.ExecutionContext
44

55
import anorm._
6-
76
import play.api.ApplicationLoader.Context
87
import play.api._
98
import play.api.db.{DBComponents, HikariCPComponents}
109
import play.api.mvc.Results._
1110
import play.api.routing.Router
1211
import play.api.routing.sird._
1312

14-
import database.{Query, QueryRunner}
13+
import com.zengularity.querymonad.core.database.{Query, QueryRunner}
1514

1615
class AppComponents(context: Context)
1716
extends BuiltInComponentsFromContext(context)
@@ -21,7 +20,7 @@ class AppComponents(context: Context)
2120

2221
val db = dbApi.database("default")
2322

24-
def queryRunner(implicit ec: ExecutionContext) = QueryRunner(db, ec)
23+
val queryRunner = QueryRunner(db.dataSource, implicitly[ExecutionContext])
2524

2625
val router: Router = Router.from {
2726

conf/application.conf renamed to examples/sample-app/conf/application.conf

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ play.i18n.langs = [ "en" ]
3131
# By convention, the default datasource is named `default`
3232

3333
db.default.driver=org.h2.Driver
34-
db.default.url="jdbc:h2:mem:play"
34+
db.default.url="jdbc:h2:mem:play;MODE=PostgreSQL"
3535
# db.default.username=sa
3636
# db.default.password=""
3737

@@ -43,4 +43,4 @@ db.default.url="jdbc:h2:mem:play"
4343
# You can disable evolutions for a specific datasource if necessary
4444
# play.evolutions.db.default.enabled=false
4545

46-
play.application.loader = wiring.AppLoader
46+
play.application.loader = com.zengularity.querymonad.examples.wiring.AppLoader

project/Dependencies.scala

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import sbt._
2+
3+
object Dependencies {
4+
lazy val anorm = "org.playframework.anorm" %% "anorm" % "2.6.0"
5+
6+
lazy val cats = "org.typelevel" %% "cats-core" % "1.0.1"
7+
8+
lazy val h2 = "com.h2database" % "h2" % "1.4.196"
9+
10+
lazy val scalaTestPlusPlay = "org.scalatestplus.play" %% "scalatestplus-play" % "3.1.1" % Test
11+
}

0 commit comments

Comments
 (0)