-
Notifications
You must be signed in to change notification settings - Fork 21
feat: Add module pureconfig with tests and basic documentation #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
36c80a3
feat: Add module pureconfig with tests and basic documentation
avast-scala-builder 6dcbfb4
refactor: Rename makeOrThrow to makeOrRaise to convey it's wrapped in F
avast-scala-builder a707602
docs: Add Scala Steward badge
avast-scala-builder d121d3a
build: Refactor all dependency definitions into separate file
avast-scala-builder 459b8f2
Merge branch 'master' into feat/pureconfig
avast-scala-builder b2a3f44
docs: Add rationale of PureConfigModule
avast-scala-builder File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -7,19 +7,47 @@ ThisBuild / scmInfo := Some( | |
ScmInfo(url("https://github.com/avast/scala-server-toolkit"), "scm:git:[email protected]:avast/scala-server-toolkit.git") | ||
) | ||
|
||
ThisBuild / scalaVersion := "2.13.1" | ||
ThisBuild / scalaVersion := "2.13.0" | ||
ThisBuild / scalacOptions := ScalacOptions.default | ||
|
||
ThisBuild / turbo := true | ||
|
||
lazy val commonSettings = Seq( | ||
libraryDependencies ++= Seq( | ||
compilerPlugin("org.typelevel" %% "kind-projector" % "0.10.3") | ||
compilerPlugin(Dependencies.kindProjector), | ||
Dependencies.catsEffect, | ||
Dependencies.scalaTest | ||
), | ||
Test / publishArtifact := false | ||
) | ||
|
||
lazy val root = (project in file(".")) | ||
.aggregate(example, pureconfig) | ||
.settings( | ||
commonSettings, | ||
name := "scala-server-toolkit", | ||
publish / skip := true | ||
) | ||
|
||
lazy val example = project | ||
.dependsOn(pureconfig) | ||
.enablePlugins(MdocPlugin) | ||
.settings( | ||
commonSettings, | ||
name := "scala-server-toolkit-example", | ||
publish / skip := true, | ||
run / fork := true, | ||
Global / cancelable := true, | ||
mdocIn := baseDirectory.value / "src" / "main" / "mdoc", | ||
mdocOut := baseDirectory.value / ".." / "docs", | ||
libraryDependencies ++= Seq( | ||
Dependencies.zio, | ||
Dependencies.zioInteropCats | ||
) | ||
) | ||
|
||
lazy val pureconfig = project | ||
.settings( | ||
commonSettings, | ||
name := "scala-server-toolkit-pureconfig", | ||
libraryDependencies += Dependencies.pureConfig | ||
) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
# Scala Server Toolkit Documentation | ||
|
||
* [Getting Started](#getting-started) | ||
* [Module PureConfig](pureconfig.md) | ||
|
||
## Getting Started | ||
|
||
Creating a simple HTTP server is as easy as this: | ||
|
||
#### build.sbt | ||
|
||
 | ||
|
||
`libraryDependencies += "com.avast.server.toolkit" %% "scala-server-toolkit-pureconfig" % "<VERSION>"` |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
# Module PureConfig | ||
|
||
 | ||
|
||
`libraryDependencies += "com.avast.server.toolkit" %% "scala-server-toolkit-pureconfig" % "<VERSION>"` | ||
|
||
This module allows you to load your application's configuration file according to a case class provided to it. It uses | ||
[PureConfig](https://pureconfig.github.io) library to do so which uses [Lightbend Config](https://github.com/lightbend/config) which means | ||
that your application's configuration will be in [HOCON](https://github.com/lightbend/config/blob/master/HOCON.md) format. | ||
|
||
jakubjanecek marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
```scala | ||
import com.avast.server.toolkit.pureconfig._ | ||
import pureconfig.ConfigReader | ||
import pureconfig.generic.semiauto.deriveReader | ||
import zio.interop.catz._ | ||
import zio.Task | ||
|
||
final case class ServerConfiguration(listenAddress: String, listenPort: Int) | ||
|
||
implicit val serverConfigurationReader: ConfigReader[ServerConfiguration] = deriveReader | ||
// serverConfigurationReader: ConfigReader[ServerConfiguration] = pureconfig.generic.DerivedConfigReader1$$anon$3@662e5590 | ||
|
||
val maybeConfiguration = PureConfigModule.make[Task, ServerConfiguration] | ||
// maybeConfiguration: Task[Either[cats.data.NonEmptyList[String], ServerConfiguration]] = zio.ZIO$EffectPartial@606f0f70 | ||
``` | ||
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
# Scala Server Toolkit Documentation | ||
|
||
* [Getting Started](#getting-started) | ||
* [Module PureConfig](pureconfig.md) | ||
|
||
## Getting Started | ||
|
||
Creating a simple HTTP server is as easy as this: | ||
|
||
#### build.sbt | ||
|
||
 | ||
|
||
`libraryDependencies += "com.avast.server.toolkit" %% "scala-server-toolkit-pureconfig" % "<VERSION>"` |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
# Module PureConfig | ||
|
||
 | ||
|
||
`libraryDependencies += "com.avast.server.toolkit" %% "scala-server-toolkit-pureconfig" % "<VERSION>"` | ||
|
||
This module allows you to load your application's configuration file according to a case class provided to it. It uses | ||
[PureConfig](https://pureconfig.github.io) library to do so which uses [Lightbend Config](https://github.com/lightbend/config) which means | ||
that your application's configuration will be in [HOCON](https://github.com/lightbend/config/blob/master/HOCON.md) format. | ||
|
||
Loading of configuration is side-effectful so it is wrapped in `F` which is `Sync`. This module also tweaks the error messages a little. | ||
|
||
```scala mdoc | ||
import com.avast.server.toolkit.pureconfig._ | ||
import pureconfig.ConfigReader | ||
import pureconfig.generic.semiauto.deriveReader | ||
import zio.interop.catz._ | ||
import zio.Task | ||
|
||
final case class ServerConfiguration(listenAddress: String, listenPort: Int) | ||
|
||
implicit val serverConfigurationReader: ConfigReader[ServerConfiguration] = deriveReader | ||
|
||
val maybeConfiguration = PureConfigModule.make[Task, ServerConfiguration] | ||
``` |
Empty file.
26 changes: 26 additions & 0 deletions
26
example/src/main/scala/com/avast/server/toolkit/example/Main.scala
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
package com.avast.server.toolkit.example | ||
|
||
import cats.effect.Resource | ||
import com.avast.server.toolkit.example.config.Configuration | ||
import com.avast.server.toolkit.pureconfig.PureConfigModule | ||
import zio.interop.catz._ | ||
import zio.{Task, ZIO} | ||
|
||
object Main extends CatsApp { | ||
|
||
def program: Resource[Task, Unit] = { | ||
for { | ||
configuration <- Resource.liftF(PureConfigModule.makeOrRaise[Task, Configuration]) | ||
} yield () | ||
} | ||
|
||
override def run(args: List[String]): ZIO[Environment, Nothing, Int] = { | ||
program | ||
.use(_ => Task.never) | ||
.fold( | ||
_ => 1, | ||
_ => 0 | ||
) | ||
} | ||
|
||
} |
12 changes: 12 additions & 0 deletions
12
example/src/main/scala/com/avast/server/toolkit/example/config/Configuration.scala
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
package com.avast.server.toolkit.example.config | ||
|
||
import pureconfig.ConfigReader | ||
import pureconfig.generic.semiauto._ | ||
|
||
final case class Configuration() | ||
|
||
object Configuration { | ||
|
||
implicit val reader: ConfigReader[Configuration] = deriveReader | ||
|
||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import sbt._ | ||
|
||
object Dependencies { | ||
|
||
val catsEffect = "org.typelevel" %% "cats-effect" % "2.0.0" | ||
val kindProjector = "org.typelevel" %% "kind-projector" % "0.10.3" | ||
val pureConfig = "com.github.pureconfig" %% "pureconfig" % "0.12.0" | ||
val scalaTest = "org.scalatest" %% "scalatest" % "3.0.8" % Test | ||
val zio = "dev.zio" %% "zio" % "1.0.0-RC12-1" | ||
val zioInteropCats = "dev.zio" %% "zio-interop-cats" % "2.0.0.0-RC3" | ||
|
||
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,3 @@ | ||
addSbtPlugin("org.scalameta" % "sbt-scalafmt" % "2.0.5") | ||
addSbtPlugin("org.scalameta" % "sbt-mdoc" % "1.3.2") | ||
addSbtPlugin("com.github.cb372" % "sbt-explicit-dependencies" % "0.2.10") | ||
addSbtPlugin("com.geirsson" % "sbt-ci-release" % "1.3.2") |
42 changes: 42 additions & 0 deletions
42
pureconfig/src/main/scala/com/avast/server/toolkit/pureconfig/PureConfigModule.scala
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
package com.avast.server.toolkit.pureconfig | ||
|
||
import cats.data.NonEmptyList | ||
import cats.effect.Sync | ||
import cats.syntax.either._ | ||
import pureconfig.error.{ConfigReaderFailure, ConfigReaderFailures, ConvertFailure} | ||
import pureconfig.{ConfigReader, ConfigSource} | ||
|
||
import scala.language.higherKinds | ||
import scala.reflect.ClassTag | ||
|
||
/** Provides loading of configuration into case class via PureConfig. */ | ||
object PureConfigModule { | ||
|
||
/** Loads the case class `A` using Lightbend Config's standard behavior. */ | ||
def make[F[_]: Sync, A: ConfigReader]: F[Either[NonEmptyList[String], A]] = make(ConfigSource.default) | ||
|
||
/** Loads the case class `A` using provided [[pureconfig.ConfigSource]]. */ | ||
def make[F[_]: Sync, A: ConfigReader](source: ConfigSource): F[Either[NonEmptyList[String], A]] = { | ||
Sync[F].delay(source.load[A].leftMap(convertFailures)) | ||
} | ||
|
||
/** Loads the case class `A` using Lightbend Config's standard behavior or raises an exception. */ | ||
def makeOrRaise[F[_]: Sync, A: ConfigReader: ClassTag]: F[A] = makeOrRaise(ConfigSource.default) | ||
|
||
/** Loads the case class `A` using provided [[pureconfig.ConfigSource]] or raises an exception. */ | ||
def makeOrRaise[F[_]: Sync, A: ConfigReader: ClassTag](source: ConfigSource): F[A] = Sync[F].delay(source.loadOrThrow[A]) | ||
|
||
private def convertFailures(failures: ConfigReaderFailures): NonEmptyList[String] = { | ||
NonEmptyList(failures.head, failures.tail).map(formatFailure) | ||
} | ||
|
||
private def formatFailure(configReaderFailure: ConfigReaderFailure): String = { | ||
configReaderFailure match { | ||
case convertFailure: ConvertFailure => | ||
s"Invalid configuration ${convertFailure.path}: ${convertFailure.description}" | ||
case configFailure => | ||
s"Invalid configuration : ${configFailure.description}" | ||
} | ||
} | ||
|
||
} |
35 changes: 35 additions & 0 deletions
35
pureconfig/src/test/scala/com/avast/server/toolkit/pureconfig/PureConfigModuleTest.scala
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package com.avast.server.toolkit.pureconfig | ||
|
||
import cats.data.NonEmptyList | ||
import cats.effect.SyncIO | ||
import org.scalatest.FunSuite | ||
import pureconfig.error.ConfigReaderException | ||
import pureconfig.generic.semiauto.deriveReader | ||
import pureconfig.{ConfigReader, ConfigSource} | ||
|
||
class PureConfigModuleTest extends FunSuite { | ||
|
||
private val source = ConfigSource.string("""|number = 123 | ||
|string = "test"""".stripMargin) | ||
|
||
private case class TestConfig(number: Int, string: String) | ||
|
||
implicit private val configReader: ConfigReader[TestConfig] = deriveReader | ||
|
||
test("Simple configuration loading") { | ||
assert(PureConfigModule.make[SyncIO, TestConfig](source).unsafeRunSync() === Right(TestConfig(123, "test"))) | ||
assert( | ||
PureConfigModule.make[SyncIO, TestConfig](ConfigSource.empty).unsafeRunSync() === Left( | ||
NonEmptyList("Invalid configuration : Key not found: 'number'.", List("Invalid configuration : Key not found: 'string'.")) | ||
) | ||
) | ||
} | ||
|
||
test("Configuration loading with exceptions") { | ||
assert(PureConfigModule.makeOrRaise[SyncIO, TestConfig](source).unsafeRunSync() === TestConfig(123, "test")) | ||
assertThrows[ConfigReaderException[TestConfig]] { | ||
PureConfigModule.makeOrRaise[SyncIO, TestConfig](ConfigSource.empty).unsafeRunSync() | ||
} | ||
} | ||
|
||
} |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.