Add initial url parsing and pattern matching
Credit to http4s everywhere.
This commit is contained in:
parent
29a7c572ba
commit
8ddf2bcdc1
142
.gitignore
vendored
Normal file
142
.gitignore
vendored
Normal file
@ -0,0 +1,142 @@
|
||||
|
||||
# Created by https://www.gitignore.io/api/sbt,scala,bloop,metals,intellij,sublimetext
|
||||
# Edit at https://www.gitignore.io/?templates=sbt,scala,bloop,metals,intellij,sublimetext
|
||||
|
||||
### Bloop ###
|
||||
.bloop/
|
||||
|
||||
### Intellij ###
|
||||
# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm
|
||||
# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
|
||||
|
||||
# User-specific stuff
|
||||
.idea/**/workspace.xml
|
||||
.idea/**/tasks.xml
|
||||
.idea/**/usage.statistics.xml
|
||||
.idea/**/dictionaries
|
||||
.idea/**/shelf
|
||||
|
||||
# Generated files
|
||||
.idea/**/contentModel.xml
|
||||
|
||||
# Sensitive or high-churn files
|
||||
.idea/**/dataSources/
|
||||
.idea/**/dataSources.ids
|
||||
.idea/**/dataSources.local.xml
|
||||
.idea/**/sqlDataSources.xml
|
||||
.idea/**/dynamic.xml
|
||||
.idea/**/uiDesigner.xml
|
||||
.idea/**/dbnavigator.xml
|
||||
|
||||
# Gradle
|
||||
.idea/**/gradle.xml
|
||||
.idea/**/libraries
|
||||
|
||||
# Gradle and Maven with auto-import
|
||||
# When using Gradle or Maven with auto-import, you should exclude module files,
|
||||
# since they will be recreated, and may cause churn. Uncomment if using
|
||||
# auto-import.
|
||||
# .idea/modules.xml
|
||||
# .idea/*.iml
|
||||
# .idea/modules
|
||||
|
||||
# CMake
|
||||
cmake-build-*/
|
||||
|
||||
# Mongo Explorer plugin
|
||||
.idea/**/mongoSettings.xml
|
||||
|
||||
# File-based project format
|
||||
*.iws
|
||||
|
||||
# IntelliJ
|
||||
out/
|
||||
|
||||
# mpeltonen/sbt-idea plugin
|
||||
.idea_modules/
|
||||
|
||||
# JIRA plugin
|
||||
atlassian-ide-plugin.xml
|
||||
|
||||
# Cursive Clojure plugin
|
||||
.idea/replstate.xml
|
||||
|
||||
# Crashlytics plugin (for Android Studio and IntelliJ)
|
||||
com_crashlytics_export_strings.xml
|
||||
crashlytics.properties
|
||||
crashlytics-build.properties
|
||||
fabric.properties
|
||||
|
||||
# Editor-based Rest Client
|
||||
.idea/httpRequests
|
||||
|
||||
# Android studio 3.1+ serialized cache file
|
||||
.idea/caches/build_file_checksums.ser
|
||||
|
||||
### Intellij Patch ###
|
||||
# Comment Reason: https://github.com/joeblau/gitignore.io/issues/186#issuecomment-215987721
|
||||
|
||||
# *.iml
|
||||
# modules.xml
|
||||
# .idea/misc.xml
|
||||
# *.ipr
|
||||
|
||||
# Sonarlint plugin
|
||||
.idea/sonarlint
|
||||
|
||||
### Metals ###
|
||||
.metals/
|
||||
|
||||
### SBT ###
|
||||
# Simple Build Tool
|
||||
# http://www.scala-sbt.org/release/docs/Getting-Started/Directories.html#configuring-version-control
|
||||
|
||||
dist/*
|
||||
target/
|
||||
lib_managed/
|
||||
src_managed/
|
||||
project/boot/
|
||||
project/plugins/project/
|
||||
.history
|
||||
.cache
|
||||
.lib/
|
||||
|
||||
### Scala ###
|
||||
*.class
|
||||
*.log
|
||||
|
||||
### SublimeText ###
|
||||
# Cache files for Sublime Text
|
||||
*.tmlanguage.cache
|
||||
*.tmPreferences.cache
|
||||
*.stTheme.cache
|
||||
|
||||
# Workspace files are user-specific
|
||||
*.sublime-workspace
|
||||
|
||||
# Project files should be checked into the repository, unless a significant
|
||||
# proportion of contributors will probably not be using Sublime Text
|
||||
# *.sublime-project
|
||||
|
||||
# SFTP configuration file
|
||||
sftp-config.json
|
||||
|
||||
# Package control specific files
|
||||
Package Control.last-run
|
||||
Package Control.ca-list
|
||||
Package Control.ca-bundle
|
||||
Package Control.system-ca-bundle
|
||||
Package Control.cache/
|
||||
Package Control.ca-certs/
|
||||
Package Control.merged-ca-bundle
|
||||
Package Control.user-ca-bundle
|
||||
oscrypto-ca-bundle.crt
|
||||
bh_unicode_properties.cache
|
||||
|
||||
# Sublime-github package stores a github token in this file
|
||||
# https://packagecontrol.io/packages/sublime-github
|
||||
GitHub.sublime-settings
|
||||
|
||||
# End of https://www.gitignore.io/api/sbt,scala,bloop,metals,intellij,sublimetext
|
||||
|
||||
/.idea/
|
23
.scalafmt.conf
Normal file
23
.scalafmt.conf
Normal file
@ -0,0 +1,23 @@
|
||||
style = default
|
||||
|
||||
maxColumn = 100
|
||||
|
||||
// Vertical alignment is pretty, but leads to bigger diffs
|
||||
align = none
|
||||
|
||||
// Insist on trailing commas for better difs in element construction
|
||||
trailingCommas = always
|
||||
danglingParentheses = true
|
||||
|
||||
rewrite.rules = [
|
||||
AvoidInfix
|
||||
RedundantBraces
|
||||
RedundantParens
|
||||
AsciiSortImports
|
||||
PreferCurlyFors
|
||||
]
|
||||
|
||||
project.excludeFilters = [
|
||||
"scalafix-inputs",
|
||||
"scalafix-outputs"
|
||||
]
|
33
.travis.yml
Normal file
33
.travis.yml
Normal file
@ -0,0 +1,33 @@
|
||||
language: scala
|
||||
|
||||
install:
|
||||
- rvm use 2.3.0 --install --fuzzy
|
||||
- gem update --system
|
||||
- gem install sass
|
||||
- gem install jekyll -v 3.2.1
|
||||
|
||||
scala:
|
||||
- 2.12.8
|
||||
|
||||
jobs:
|
||||
include:
|
||||
- stage: verify
|
||||
|
||||
script:
|
||||
- sbt ++$TRAVIS_SCALA_VERSION todomvc/fullOptJS::webpack
|
||||
- sbt docs/mdoc
|
||||
- sbt docs/makeMicrosite
|
||||
- mkdir -p router-docs/site/todomvc
|
||||
- cp -R router-docs/target/site/* ./router-docs/site/
|
||||
- cp ./router-docs/site/Readme.html ./router-docs/site/index.html
|
||||
|
||||
deploy:
|
||||
provider: pages
|
||||
skip-cleanup: true
|
||||
github-token: $GITHUB_TOKEN # Set in the settings page of your repository, as a secure variable
|
||||
keep-history: true
|
||||
local-dir: router-docs/site
|
||||
target-branch: gh-pages
|
||||
on:
|
||||
branch: master
|
||||
|
8
README.md
Normal file
8
README.md
Normal file
@ -0,0 +1,8 @@
|
||||
outwatch-router
|
||||
===
|
||||
|
||||
Easy routing for [outwatch](https://outwatch.github.io) on scala.js
|
||||
|
||||
Most of this code is adapted from [http4s](http4s.org)'s route parsing and path pattern matching.
|
||||
|
||||
See [documentation](https://clovellytech.github.io/outwatch-router/index.html)
|
77
build.sbt
Normal file
77
build.sbt
Normal file
@ -0,0 +1,77 @@
|
||||
import dependencies._
|
||||
|
||||
cancelable in Global := true
|
||||
|
||||
val commonSettings = Seq(
|
||||
organization := "com.clovellytech",
|
||||
version := Version.version,
|
||||
scalaVersion := Version.scalaVersion,
|
||||
resolvers ++= addResolvers,
|
||||
scalacOptions ++= options.scalac,
|
||||
scalacOptions in (Compile, console) := options.scalacConsole,
|
||||
updateOptions := updateOptions.value.withLatestSnapshots(false)
|
||||
) ++ compilerPlugins
|
||||
|
||||
val withTests : String = "compile->compile;test->test"
|
||||
val testOnly : String = "test->test"
|
||||
|
||||
lazy val docs = (project in file("./router-docs"))
|
||||
.settings(name := "outwatch-router-docs")
|
||||
.enablePlugins(MdocPlugin)
|
||||
.settings(commonSettings)
|
||||
.dependsOn(router)
|
||||
|
||||
lazy val copyFastOptJS = TaskKey[Unit]("copyFastOptJS", "Copy javascript files to target directory")
|
||||
|
||||
lazy val router = (project in file("./outwatch-router"))
|
||||
.settings(name := "outwatch-router")
|
||||
.enablePlugins(ScalaJSPlugin)
|
||||
.enablePlugins(ScalaJSBundlerPlugin)
|
||||
.settings(commonSettings)
|
||||
.settings(
|
||||
scalaJSModuleKind := ModuleKind.CommonJSModule,
|
||||
scalacOptions += "-P:scalajs:sjsDefinedByDefault",
|
||||
useYarn := true, // makes scalajs-bundler use yarn instead of npm
|
||||
jsEnv in Test := new org.scalajs.jsenv.jsdomnodejs.JSDOMNodeJSEnv,
|
||||
scalaJSUseMainModuleInitializer := true,
|
||||
scalaJSModuleKind := ModuleKind.CommonJSModule, // configure Scala.js to emit a JavaScript module instead of a top-level script
|
||||
version in webpack := "4.16.1",
|
||||
version in startWebpackDevServer := "3.1.4",
|
||||
webpackDevServerExtraArgs := Seq("--progress", "--color"),
|
||||
webpackConfigFile in fastOptJS := Some(baseDirectory.value / "webpack.config.dev.js"),
|
||||
// https://scalacenter.github.io/scalajs-bundler/cookbook.html#performance
|
||||
webpackBundlingMode in fastOptJS := BundlingMode.LibraryOnly(),
|
||||
resolvers += "jitpack" at "https://jitpack.io",
|
||||
libraryDependencies ++= Seq(
|
||||
"io.github.outwatch" % "outwatch" % "ea240c6d04",
|
||||
"org.http4s" %% "parboiled" % "1.0.0",
|
||||
"org.scalatest" %%% "scalatest" % "3.0.5" % Test
|
||||
),
|
||||
copyFastOptJS := {
|
||||
val inDir = (crossTarget in (Compile, fastOptJS)).value
|
||||
val outDir = (crossTarget in (Compile, fastOptJS)).value / "dev"
|
||||
val files = Seq("outwatch-router-fastopt-loader.js", "outwatch-router-frontend-fastopt.js", "outwatch-router-frontend-fastopt.js.map") map { p => (inDir / p, outDir / p) }
|
||||
IO.copy(files, overwrite = true, preserveLastModified = true, preserveExecutable = true)
|
||||
},
|
||||
// hot reloading configuration:
|
||||
// https://github.com/scalacenter/scalajs-bundler/issues/180
|
||||
addCommandAlias("dev", "; compile; fastOptJS::startWebpackDevServer; devwatch; fastOptJS::stopWebpackDevServer"),
|
||||
addCommandAlias("devwatch", "~; fastOptJS; copyFastOptJS")
|
||||
)
|
||||
|
||||
lazy val exampleApp = (project in file("router-example"))
|
||||
.settings(name := "outwatch-example")
|
||||
.settings(commonSettings)
|
||||
.dependsOn(router)
|
||||
|
||||
lazy val root = (project in file("."))
|
||||
.settings(name := "outwatch-router-root")
|
||||
.settings(commonSettings)
|
||||
.settings(
|
||||
skip in publish := true,
|
||||
aggregate in reStart := false,
|
||||
)
|
||||
.dependsOn(router)
|
||||
.aggregate(router)
|
||||
|
||||
|
43
docs/Intro.md
Normal file
43
docs/Intro.md
Normal file
@ -0,0 +1,43 @@
|
||||
Outwatch Router
|
||||
===
|
||||
|
||||
```scala mdoc
|
||||
import cats._
|
||||
import cats.implicits._
|
||||
import cats.Applicative
|
||||
import cats.data.Kleisli
|
||||
import outwatch.router._, Router._
|
||||
|
||||
sealed abstract class Page
|
||||
case class RootPage() extends Page
|
||||
case class Login() extends Page
|
||||
case class Register() extends Page
|
||||
case class Profile(userId: String) extends Page
|
||||
case class NotFound() extends Page
|
||||
|
||||
object Page{
|
||||
def root: Page = RootPage()
|
||||
def login: Page = Login()
|
||||
def register: Page = Register()
|
||||
def profile(userId: String): Page = Profile(userId)
|
||||
def notFound: Page = NotFound()
|
||||
}
|
||||
|
||||
def routes[F[_]: Applicative]: AppRouter[F, Page] = Kleisli[F, Path, Page] {
|
||||
case Root => Page.root.pure[F]
|
||||
case Root / "login" => Page.login.pure[F]
|
||||
case Root / "register" => Page.register.pure[F]
|
||||
case Root / "profile" / userId => Page.profile(userId).pure[F]
|
||||
case _ => Page.notFound.pure[F]
|
||||
}
|
||||
|
||||
val router = routes[Id]
|
||||
|
||||
router.run(Root)
|
||||
router.run(Root / "login")
|
||||
router.run(Root / "profile" / "saopa98f")
|
||||
|
||||
router.run(Path("/profile/asd"))
|
||||
router.run(Path("/apsinoasn"))
|
||||
```
|
||||
|
220
outwatch-router/src/main/scala/outwatch/router/Path.scala
Normal file
220
outwatch-router/src/main/scala/outwatch/router/Path.scala
Normal file
@ -0,0 +1,220 @@
|
||||
// Completely copied from org.http4s.dsl.impl
|
||||
|
||||
package outwatch.router
|
||||
|
||||
import cats.implicits._
|
||||
import java.nio.{ByteBuffer, CharBuffer}
|
||||
import java.nio.charset.Charset
|
||||
import java.nio.charset.StandardCharsets.UTF_8
|
||||
|
||||
/** Base class for path extractors. */
|
||||
trait Path {
|
||||
def /(child: String) = new /(this, child)
|
||||
def toList: List[String]
|
||||
def parent: Path
|
||||
def lastOption: Option[String]
|
||||
def startsWith(other: Path): Boolean
|
||||
}
|
||||
|
||||
object Path {
|
||||
|
||||
/** Constructs a path from a single string by splitting on the `'/'`
|
||||
* character.
|
||||
*
|
||||
* Leading slashes do not create an empty path segment. This is to
|
||||
* reflect that there is no distinction between a request to
|
||||
* `http://www.example.com` from `http://www.example.com/`.
|
||||
*
|
||||
* Trailing slashes result in a path with an empty final segment,
|
||||
* unless the path is `"/"`, which is `Root`.
|
||||
*
|
||||
* Segments are URL decoded.
|
||||
*
|
||||
* {{{
|
||||
* scala> Path("").toList
|
||||
* res0: List[String] = List()
|
||||
* scala> Path("/").toList
|
||||
* res1: List[String] = List()
|
||||
* scala> Path("a").toList
|
||||
* res2: List[String] = List(a)
|
||||
* scala> Path("/a").toList
|
||||
* res3: List[String] = List(a)
|
||||
* scala> Path("/a/").toList
|
||||
* res4: List[String] = List(a, "")
|
||||
* scala> Path("//a").toList
|
||||
* res5: List[String] = List("", a)
|
||||
* scala> Path("/%2F").toList
|
||||
* res0: List[String] = List(/)
|
||||
* }}}
|
||||
*/
|
||||
def apply(str: String): Path =
|
||||
if (str == "" || str == "/")
|
||||
Root
|
||||
else {
|
||||
val segments = str.split("/", -1)
|
||||
// .head is safe because split always returns non-empty array
|
||||
val segments0 = if (segments.head == "") segments.drop(1) else segments
|
||||
segments0.foldLeft(Root: Path)((path, seg) => path / UrlCodingUtils.urlDecode(seg))
|
||||
}
|
||||
|
||||
def apply(first: String, rest: String*): Path =
|
||||
rest.foldLeft(Root / first)(_ / _)
|
||||
|
||||
def apply(list: List[String]): Path =
|
||||
list.foldLeft(Root: Path)(_ / _)
|
||||
|
||||
def unapplySeq(path: Path): Some[List[String]] =
|
||||
Some(path.toList)
|
||||
//
|
||||
// def unapplySeq[F[_]](request: Request[F]): Some[List[String]] =
|
||||
// Some(Path(request.pathInfo).toList)
|
||||
}
|
||||
|
||||
|
||||
final case class /(parent: Path, child: String) extends Path {
|
||||
lazy val toList: List[String] = parent.toList ++ List(child)
|
||||
|
||||
def lastOption: Some[String] = Some(child)
|
||||
|
||||
lazy val asString: String = s"$parent/${UrlCodingUtils.pathEncode(child)}"
|
||||
override def toString: String = asString
|
||||
def startsWith(other: Path): Boolean = {
|
||||
val components = other.toList
|
||||
toList.take(components.length) === components
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Root extractor:
|
||||
* {{{
|
||||
* Path("/") match {
|
||||
* case Root => ...
|
||||
* }
|
||||
* }}}
|
||||
*/
|
||||
case object Root extends Path {
|
||||
def toList: List[String] = Nil
|
||||
def parent: Path = this
|
||||
def lastOption: None.type = None
|
||||
override def toString = ""
|
||||
def startsWith(other: Path): Boolean = other == Root
|
||||
}
|
||||
|
||||
|
||||
private[router] object UrlCodingUtils {
|
||||
|
||||
private val lower = ('a' to 'z').toSet
|
||||
private val upper = ('A' to 'Z').toSet
|
||||
private val num = ('0' to '9').toSet
|
||||
val Unreserved: Set[Char] = lower ++ upper ++ num ++ "-_.~"
|
||||
|
||||
private val toSkip : Set[Char] = Unreserved ++ "!$&'()*+,;=:/?@"
|
||||
|
||||
private val HexUpperCaseChars: Array[Char] = ('A' to 'F').toArray
|
||||
/**
|
||||
* Percent-encodes a string. Depending on the parameters, this method is
|
||||
* appropriate for URI or URL form encoding. Any resulting percent-encodings
|
||||
* are normalized to uppercase.
|
||||
*
|
||||
* @param toEncode the string to encode
|
||||
* @param charset the charset to use for characters that are percent encoded
|
||||
* @param spaceIsPlus if space is not skipped, determines whether it will be
|
||||
* rendreed as a `"+"` or a percent-encoding according to `charset`.
|
||||
* @param toSkip a predicate of characters exempt from encoding. In typical
|
||||
* use, this is composed of all Unreserved URI characters and sometimes a
|
||||
* subset of Reserved URI characters.
|
||||
*/
|
||||
def urlEncode(
|
||||
toEncode: String,
|
||||
charset: Charset = UTF_8,
|
||||
spaceIsPlus: Boolean = false,
|
||||
toSkip: Char => Boolean = toSkip): String = {
|
||||
val in = charset.encode(toEncode)
|
||||
val out = CharBuffer.allocate((in.remaining() * 3).toInt)
|
||||
while (in.hasRemaining) {
|
||||
val c = in.get().toChar
|
||||
if (toSkip(c)) {
|
||||
out.put(c)
|
||||
} else if (c == ' ' && spaceIsPlus) {
|
||||
out.put('+')
|
||||
} else {
|
||||
out.put('%')
|
||||
out.put(HexUpperCaseChars((c >> 4) & 0xF))
|
||||
out.put(HexUpperCaseChars(c & 0xF))
|
||||
}
|
||||
}
|
||||
out.flip()
|
||||
out.toString
|
||||
}
|
||||
|
||||
private val SkipEncodeInPath =
|
||||
Unreserved ++ ":@!$&'()*+,;="
|
||||
|
||||
def pathEncode(s: String, charset: Charset = UTF_8): String =
|
||||
UrlCodingUtils.urlEncode(s, charset, false, SkipEncodeInPath)
|
||||
|
||||
/**
|
||||
* Percent-decodes a string.
|
||||
*
|
||||
* @param toDecode the string to decode
|
||||
* @param charset the charset of percent-encoded characters
|
||||
* @param plusIsSpace true if `'+'` is to be interpreted as a `' '`
|
||||
* @param toSkip a predicate of characters whose percent-encoded form
|
||||
* is left percent-encoded. Almost certainly should be left empty.
|
||||
*/
|
||||
def urlDecode(
|
||||
toDecode: String,
|
||||
charset: Charset = UTF_8,
|
||||
plusIsSpace: Boolean = false,
|
||||
toSkip: Char => Boolean = Function.const(false)): String = {
|
||||
val in = CharBuffer.wrap(toDecode)
|
||||
// reserve enough space for 3-byte UTF-8 characters. 4-byte characters are represented
|
||||
// as surrogate pairs of characters, and will get a luxurious 6 bytes of space.
|
||||
val out = ByteBuffer.allocate(in.remaining() * 3)
|
||||
while (in.hasRemaining) {
|
||||
val mark = in.position()
|
||||
val c = in.get()
|
||||
if (c == '%') {
|
||||
if (in.remaining() >= 2) {
|
||||
val xc = in.get()
|
||||
val yc = in.get()
|
||||
// scalastyle:off magic.number
|
||||
val x = Character.digit(xc, 0x10)
|
||||
val y = Character.digit(yc, 0x10)
|
||||
// scalastyle:on magic.number
|
||||
if (x != -1 && y != -1) {
|
||||
val oo = (x << 4) + y
|
||||
if (!toSkip(oo.toChar)) {
|
||||
out.put(oo.toByte)
|
||||
} else {
|
||||
out.put('%'.toByte)
|
||||
out.put(xc.toByte)
|
||||
out.put(yc.toByte)
|
||||
}
|
||||
} else {
|
||||
out.put('%'.toByte)
|
||||
in.position(mark + 1)
|
||||
}
|
||||
} else {
|
||||
// This is an invalid encoding. Fail gracefully by treating the '%' as
|
||||
// a literal.
|
||||
out.put(c.toByte)
|
||||
while (in.hasRemaining) out.put(in.get().toByte)
|
||||
}
|
||||
} else if (c == '+' && plusIsSpace) {
|
||||
out.put(' '.toByte)
|
||||
} else {
|
||||
// normally `out.put(c.toByte)` would be enough since the url is %-encoded,
|
||||
// however there are cases where a string can be partially decoded
|
||||
// so we have to make sure the non us-ascii chars get preserved properly.
|
||||
if (this.toSkip(c)) {
|
||||
out.put(c.toByte)
|
||||
} else {
|
||||
out.put(charset.encode(String.valueOf(c)))
|
||||
}
|
||||
}
|
||||
}
|
||||
out.flip()
|
||||
charset.decode(out).toString
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
package outwatch.router
|
||||
|
||||
import cats.data.Kleisli
|
||||
|
||||
object Router {
|
||||
type AppRouter[F[_], A] = Kleisli[F, Path, A]
|
||||
val AppRouter = Kleisli
|
||||
|
||||
}
|
84
project/Dependencies.scala
Normal file
84
project/Dependencies.scala
Normal file
@ -0,0 +1,84 @@
|
||||
import sbt._
|
||||
import sbt.librarymanagement.DependencyBuilders
|
||||
import org.portablescala.sbtplatformdeps._
|
||||
|
||||
object dependencies {
|
||||
val addResolvers = Seq(
|
||||
"52north for postgis" at "http://52north.org/maven/repo/releases/",
|
||||
Resolver.sonatypeRepo("releases"),
|
||||
Resolver.sonatypeRepo("snapshots")
|
||||
)
|
||||
|
||||
val compilerPlugins = Seq(
|
||||
addCompilerPlugin("org.spire-math" %% "kind-projector" % "0.9.9"),
|
||||
addCompilerPlugin("org.scalamacros" % "paradise" % "2.1.1" cross CrossVersion.full)
|
||||
)
|
||||
|
||||
val bcrypt = "3.1"
|
||||
val cats = "1.4.0"
|
||||
val catsMtl = "0.4.0"
|
||||
val catsEffect = "1.2.0"
|
||||
val circe = "0.11.0"
|
||||
val circeConfig = "0.6.1"
|
||||
val doobie = "0.6.0"
|
||||
val flyway = "5.2.4"
|
||||
val fs2 = "1.0.2"
|
||||
val h4sm = "0.0.17"
|
||||
val http4s = "0.20.0-M5"
|
||||
val logback = "1.2.3"
|
||||
val monocle = "1.5.0"
|
||||
val postgis = "1.3.3"
|
||||
val postgres = "42.2.5"
|
||||
val scalaCheck = "1.14.0"
|
||||
val scalaTest = "3.0.5"
|
||||
val simulacrum = "0.14.0"
|
||||
|
||||
val httpDeps = Seq(
|
||||
"http4s-blaze-server",
|
||||
"http4s-blaze-client",
|
||||
"http4s-circe",
|
||||
"http4s-dsl"
|
||||
).map("org.http4s" %% _ % http4s) ++ Seq(
|
||||
"circe-core",
|
||||
"circe-generic",
|
||||
"circe-parser",
|
||||
"circe-java8"
|
||||
).map("io.circe" %% _ % circe)
|
||||
|
||||
val testDeps = Seq(
|
||||
"org.scalatest" %% "scalatest" % scalaTest,
|
||||
"org.tpolecat" %% "doobie-scalatest" % doobie,
|
||||
"org.scalacheck" %% "scalacheck" % scalaCheck,
|
||||
"com.clovellytech" %% "h4sm-dbtesting" % h4sm
|
||||
)
|
||||
|
||||
val testDepsInTestOnly = testDeps.map(_ % "test")
|
||||
|
||||
val dbDeps = Seq(
|
||||
"org.flywaydb" % "flyway-core" % flyway,
|
||||
"org.postgresql" % "postgresql" % postgres,
|
||||
"org.postgis" % "postgis-jdbc" % postgis
|
||||
) ++ Seq(
|
||||
"doobie-core",
|
||||
"doobie-postgres",
|
||||
"doobie-hikari"
|
||||
).map("org.tpolecat" %% _ % doobie)
|
||||
|
||||
val commonDeps = Seq(
|
||||
"io.circe" %% "circe-config" % circeConfig,
|
||||
"ch.qos.logback" % "logback-classic" % logback,
|
||||
"com.github.mpilquist" %% "simulacrum" % simulacrum
|
||||
) ++ Seq(
|
||||
"h4sm-auth",
|
||||
"h4sm-files",
|
||||
"h4sm-permissions"
|
||||
).map("com.clovellytech" %% _ % h4sm) ++ Seq(
|
||||
"monocle-core",
|
||||
"monocle-generic",
|
||||
"monocle-macro",
|
||||
"monocle-state",
|
||||
"monocle-refined"
|
||||
).map("com.github.julien-truffaut" %% _ % monocle)
|
||||
|
||||
val allDeps = httpDeps ++ dbDeps ++ commonDeps ++ testDepsInTestOnly
|
||||
}
|
58
project/Options.scala
Normal file
58
project/Options.scala
Normal file
@ -0,0 +1,58 @@
|
||||
|
||||
object options {
|
||||
|
||||
val scalac = Seq(
|
||||
// format: off
|
||||
"-deprecation", // Emit warning and location for usages of deprecated APIs.
|
||||
"-encoding", "utf-8", // Specify character encoding used by source files.
|
||||
"-explaintypes", // Explain type errors in more detail.
|
||||
"-feature", // Emit warning and location for usages of features that should be imported explicitly.
|
||||
"-language:existentials", // Existential types (besides wildcard types) can be written and inferred
|
||||
"-language:experimental.macros", // Allow macro definition (besides implementation and application)
|
||||
"-language:higherKinds", // Allow higher-kinded types
|
||||
"-language:implicitConversions", // Allow definition of implicit functions called views
|
||||
"-unchecked", // Enable additional warnings where generated code depends on assumptions.
|
||||
"-Xcheckinit", // Wrap field accessors to throw an exception on uninitialized access.
|
||||
"-Xfatal-warnings", // Fail the compilation if there are any warnings.
|
||||
"-Xfuture", // Turn on future language features.
|
||||
"-Xlint:adapted-args", // Warn if an argument list is modified to match the receiver.
|
||||
"-Xlint:by-name-right-associative", // By-name parameter of right associative operator.
|
||||
"-Xlint:constant", // Evaluation of a constant arithmetic expression results in an error.
|
||||
"-Xlint:delayedinit-select", // Selecting member of DelayedInit.
|
||||
"-Xlint:doc-detached", // A Scaladoc comment appears to be detached from its element.
|
||||
"-Xlint:inaccessible", // Warn about inaccessible types in method signatures.
|
||||
"-Xlint:infer-any", // Warn when a type argument is inferred to be `Any`.
|
||||
"-Xlint:missing-interpolator", // A string literal appears to be missing an interpolator id.
|
||||
"-Xlint:nullary-override", // Warn when non-nullary `def f()' overrides nullary `def f'.
|
||||
"-Xlint:nullary-unit", // Warn when nullary methods return Unit.
|
||||
"-Xlint:option-implicit", // Option.apply used implicit view.
|
||||
"-Xlint:package-object-classes", // Class or object defined in package object.
|
||||
"-Xlint:poly-implicit-overload", // Parameterized overloaded implicit methods are not visible as view bounds.
|
||||
"-Xlint:private-shadow", // A private field (or class parameter) shadows a superclass field.
|
||||
"-Xlint:stars-align", // Pattern sequence wildcard must align with sequence component.
|
||||
"-Xlint:type-parameter-shadow", // A local type parameter shadows a type already in scope.
|
||||
"-Xlint:unsound-match", // Pattern match may not be typesafe.
|
||||
"-Yno-adapted-args", // Do not adapt an argument list (either by inserting () or creating a tuple) to match the receiver.
|
||||
"-Ypartial-unification", // Enable partial unification in type constructor inference
|
||||
"-Ywarn-dead-code", // Warn when dead code is identified.
|
||||
"-Ywarn-extra-implicit", // Warn when more than one implicit parameter section is defined.
|
||||
"-Ywarn-inaccessible", // Warn about inaccessible types in method signatures.
|
||||
"-Ywarn-infer-any", // Warn when a type argument is inferred to be `Any`.
|
||||
"-Ywarn-nullary-unit", // Warn when nullary methods return Unit.
|
||||
"-Ywarn-nullary-override", // Warn when non-nullary `def f()' overrides nullary `def f'.
|
||||
"-Ywarn-numeric-widen", // Warn when numerics are widened.
|
||||
"-Ywarn-unused:implicits", // Warn if an implicit parameter is unused.
|
||||
"-Ywarn-unused:imports", // Warn if an import selector is not referenced.
|
||||
"-Ywarn-unused:locals", // Warn if a local definition is unused.
|
||||
"-Ywarn-unused:params", // Warn if a value parameter is unused.
|
||||
"-Ywarn-unused:patvars", // Warn if a variable bound in a pattern is unused.
|
||||
"-Ywarn-unused:privates", // Warn if a private member is unused.
|
||||
"-Ywarn-value-discard", // Warn when non-Unit expression results are unused.
|
||||
"-Yrangepos"
|
||||
// format: on
|
||||
)
|
||||
|
||||
val badScalacConsoleFlags = Seq("-Xfatal-warnings", "-Ywarn-unused:imports")
|
||||
|
||||
val scalacConsole = scalac.filterNot(badScalacConsoleFlags.contains(_))
|
||||
}
|
4
project/Version.scala
Normal file
4
project/Version.scala
Normal file
@ -0,0 +1,4 @@
|
||||
object Version{
|
||||
val version = "0.0.1"
|
||||
val scalaVersion = "2.12.8"
|
||||
}
|
1
project/build.properties
Normal file
1
project/build.properties
Normal file
@ -0,0 +1 @@
|
||||
sbt.version=1.2.3
|
4
project/plugins.sbt
Normal file
4
project/plugins.sbt
Normal file
@ -0,0 +1,4 @@
|
||||
addSbtPlugin("ch.epfl.scala" % "sbt-scalajs-bundler" % "0.13.1")
|
||||
addSbtPlugin("org.scala-js" % "sbt-scalajs" % "0.6.26")
|
||||
addSbtPlugin("org.scalameta" % "sbt-mdoc" % "1.2.8" )
|
||||
addSbtPlugin("com.47deg" % "sbt-microsites" % "0.8.0")
|
Loading…
Reference in New Issue
Block a user