47degrees / case-classy Goto Github PK
View Code? Open in Web Editor NEWconfiguration with less hassle
Home Page: http://47deg.github.io/case-classy/
License: Apache License 2.0
configuration with less hassle
Home Page: http://47deg.github.io/case-classy/
License: Apache License 2.0
I've got a simple example project and test that may highlight the problem I'm having in my application code.
Here is the test from a simple example:
package classy
import classy.Fruits.{Apple, FruityConfig}
import org.scalatest.{FlatSpec, Matchers}
import com.typesafe.config.ConfigFactory
import classy.config._
import classy.generic.auto._
import classy.core.DecodeError
class FruitsSpec extends FlatSpec with Matchers {
"A properly decoded config" should "contain two fruits" in {
val rawConfig = ConfigFactory load
val decoder = ConfigDecoder[FruityConfig]
val result0: Either[DecodeError, FruityConfig] = decoder.decode(rawConfig)
result0.isRight shouldBe true
result0.right.get.fruits should have size 2
val apple = result0.right.get.fruits.head.asInstanceOf[Apple]
apple.location.city shouldBe "cadiz"
}
}
This executes correctly, but ensime detects a missing implicit value ev: ConfigDecoder.
In my application code I have nearly the opposite problem- my ide does not detect a problem, but there is a compiler error indicating a missing implicit value ev: MkDecoder.
Can someone explain how I the MkDecoder is intended to be imported? I've tried a number of different imports but am still getting a compiler error.
My assumption from the examples is that import classy.generic._
should import an implicit MkDecoder.
However, previously there was an example that used import classy.generic.auto._
which is what I used in my example above.
Add an .atPath
method that transforms a decoder into one that decodes at a given path deeper.
Actual version: 0.9.3
Patch: 0.9.4
Minor: -
Major: -
with following dependencies,
name := "upd-frontend"
enablePlugins(ScalaJSPlugin)
version := "0.1"
scalaVersion := "2.12.6"
scalaJSUseMainModuleInitializer := true
libraryDependencies += "org.scala-js" %%% "scalajs-dom" % "0.9.5"
libraryDependencies += "org.querki" %%% "jquery-facade" % "1.2"
// required
libraryDependencies += "com.47deg" %% "classy-core" % "0.4.0"
// at least one required
libraryDependencies += "com.47deg" %% "classy-config-typesafe" % "0.4.0"
libraryDependencies += "com.47deg" %% "classy-config-shocon" % "0.4.0"
libraryDependencies += "com.47deg" %% "classy-generic" % "0.4.0"
libraryDependencies ++= Seq("com.chuusai" %% "shapeless" % "2.3.3")
I could not compile to JS
import classy.generic._
import classy.config._
case class Env(uri: String, heartbeatResource: String, handoffResource: String)
case class ApplicationConfig(dev: Env)
import com.typesafe.config.Config
val decoder1 = deriveDecoder[Config, ApplicationConfig]
val config: Either[DecodeError, ApplicationConfig] = decoder1.fromString("""{
| dev {
| uri = "uri"
| heartbeatResource = hb""
| handoffResource = "hr"
| }
|}
|""")
The stack-trace is
[error] Referring to non-existent method classy.generic.derive.MkRead$.mkReadNested(classy.Read,shapeless.Lazy)classy.generic.derive.MkRead
[error] called from UpdFrontend$anon$mkDecoderGeneric$macro$22$1.inst$macro$7$lzycompute()classy.generic.derive.MkRead
[error] called from UpdFrontend$anon$mkDecoderGeneric$macro$22$1.inst$macro$7()classy.generic.derive.MkRead
[error] called from UpdFrontend$anon$mkDecoderGeneric$macro$22$1.$$anonfun$inst$macro$5$1()classy.generic.derive.MkRead
[error] called from UpdFrontend$anon$mkDecoderGeneric$macro$22$1.inst$macro$5$lzycompute()classy.generic.derive.MkDecoder
[error] called from UpdFrontend$anon$mkDecoderGeneric$macro$22$1.inst$macro$5()classy.generic.derive.MkDecoder
[error] called from UpdFrontend$.main([java.lang.String)scala.Unit
[error] called from core module module initializers
[error] involving instantiated classes:
[error] UpdFrontend$anon$mkDecoderGeneric$macro$22$1
[error] UpdFrontend$
[error] Referring to non-existent method classy.generic.package$.deriveDecoder(classy.generic.derive.MkDecoder)classy.Decoder
[error] called from UpdFrontend$.main([java.lang.String)scala.Unit
[error] called from core module module initializers
[error] involving instantiated classes:
[error] UpdFrontend$
[error] org.scalajs.core.tools.linker.LinkingException: There were linking errors
[error] at org.scalajs.core.tools.linker.frontend.BaseLinker.linkInternal(BaseLinker.scala:160)
[error] at org.scalajs.core.tools.linker.frontend.BaseLinker.linkInternal(BaseLinker.scala:108)
[error] at org.scalajs.core.tools.linker.frontend.LinkerFrontend.$anonfun$link$3(LinkerFrontend.scala:63)
[error] at org.scalajs.core.tools.logging.Logger.time(Logger.scala:28)
[error] at org.scalajs.core.tools.logging.Logger.time$(Logger.scala:26)
[error] at org.scalajs.sbtplugin.Loggers$SbtLoggerWrapper.time(Loggers.scala:7)
[error] at org.scalajs.core.tools.linker.frontend.LinkerFrontend.link(LinkerFrontend.scala:62)
[error] at org.scalajs.core.tools.linker.Linker.$anonfun$link$1(Linker.scala:52)
[error] at scala.runtime.java8.JFunction0$mcV$sp.apply(JFunction0$mcV$sp.java:12)
[error] at org.scalajs.core.tools.linker.Linker.guard(Linker.scala:69)
[error] at org.scalajs.core.tools.linker.Linker.link(Linker.scala:50)
[error] at org.scalajs.core.tools.linker.ClearableLinker.$anonfun$link$1(ClearableLinker.scala:52)
[error] at org.scalajs.core.tools.linker.ClearableLinker.$anonfun$link$1$adapted(ClearableLinker.scala:52)
[error] at org.scalajs.core.tools.linker.ClearableLinker.linkerOp(ClearableLinker.scala:63)
[error] at org.scalajs.core.tools.linker.ClearableLinker.link(ClearableLinker.scala:52)
[error] at org.scalajs.sbtplugin.ScalaJSPluginInternal$.$anonfun$scalaJSStageSettings$11(ScalaJSPluginInternal.scala:315)
[error] at sbt.util.FileFunction$.$anonfun$cached$1(FileFunction.scala:73)
[error] at sbt.util.FileFunction$.$anonfun$cached$4(FileFunction.scala:147)
[error] at sbt.util.Difference.apply(Tracked.scala:313)
[error] at sbt.util.Difference.apply(Tracked.scala:293)
[error] at sbt.util.FileFunction$.$anonfun$cached$3(FileFunction.scala:143)
[error] at sbt.util.Difference.apply(Tracked.scala:313)
[error] at sbt.util.Difference.apply(Tracked.scala:288)
[error] at sbt.util.FileFunction$.$anonfun$cached$2(FileFunction.scala:142)
[error] at org.scalajs.sbtplugin.ScalaJSPluginInternal$.$anonfun$scalaJSStageSettings$10(ScalaJSPluginInternal.scala:320)
[error] at sbt.std.Transform$$anon$3.$anonfun$apply$2(System.scala:44)
[error] at sbt.std.Transform$$anon$4.work(System.scala:64)
[error] at sbt.Execute.$anonfun$submit$2(Execute.scala:257)
[error] at sbt.internal.util.ErrorHandling$.wideConvert(ErrorHandling.scala:16)
[error] at sbt.Execute.work(Execute.scala:266)
[error] at sbt.Execute.$anonfun$submit$1(Execute.scala:257)
[error] at sbt.ConcurrentRestrictions$$anon$4.$anonfun$submitValid$1(ConcurrentRestrictions.scala:167)
[error] at sbt.CompletionService$$anon$2.call(CompletionService.scala:32)
[error] at java.util.concurrent.FutureTask.run(FutureTask.java:266)
[error] at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
[error] at java.util.concurrent.FutureTask.run(FutureTask.java:266)
[error] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
[error] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
[error] at java.lang.Thread.run(Thread.java:748)
[error] (compile:fastOptJS) org.scalajs.core.tools.linker.LinkingException: There were linking errors
[error] Total time: 22 s, completed Jul 13, 2018 12:04:19 PM
Support decoding FiniteDuration for Typesafe/Shocon
Add a blurb such as
People are expected to follow the Typelevel Code of Conduct when ...
to the README file.
This functionality exists, but it's currently only in the code for the ScalaDays slides. I'll be pulling it out and turning it into a full blown implementation so that the core module has basic decoding of Map[String, String]
.
It would be useful to be able to create decoders directly from A => Try[B]
. The error can be directly turned into the underlying error wrapper.
For example, for monix-kafka
:
implicit val decodeKafkaProducerConfig: ConfigDecoder[KafkaProducerConfig] =
Decoder.instance(c => Try(KafkaProducerConfig(c)).toEither.leftMap(DecodeError.Underlying(_)))
this ideally could just be written as:
implicit val decodeKafkaProducerConfig: ConfigDecoder[KafkaProducerConfig] =
Decoder.instance(c => Try(KafkaProducerConfig(c)))
@jorgegalindocruces
I'm gearing up for an official release with PR #11. It would be really great to get a logo soon, since I writing some tutorials/documentation this weekend and I'd like to spin up a microsite.
Add a tupling syntax/helper set for dealing with this kind of cruft
The following should be added to the Read
companion object:
def apply[A, B](implicit ev: Read[A, B]): Read[A, B] = ev
def apply[A, B](path: String)(implicit ev: Read[A, B]): Decoder[A, B] = ev(path)
This is twofold:
ValidationFailed
(or similar) DecodeError
type and corresponding helper methods to add "validation" steps to a decoder.ValidationFailed
functionality.This may be impossible with the current approach to automatically deriving decoders, but I have a situation like this:
import classy._
import clasy.config._
import classy.generic._
import com.typesafe.config._
object Models{
sealed trait TopLevel
case class A(b: TopLevel) extends TopLevel
case class B(c: String) extends TopLevel
val topLevelDecoder = deriveDecoder[Config, TopLevel]
}
This doesn't compile... near as I can tell due to Stack Overflow during the macro (?) expansion... In the REPL you get something like:
java.lang.StackOverflowError
at classy.generic.derive.MkReadInstances0$$anonfun$mkReadNested$1.apply(MkDecoder.scala:162)
at classy.generic.derive.MkRead.apply(MkDecoder.scala:151)
at classy.generic.derive.MkDecoderInstances0$$anonfun$mkDecoderHListDerived$1.apply(MkDecoder.scala:129)
at classy.generic.derive.MkDecoderInstances0$$anonfun$mkDecoderHListDerived$1.apply(MkDecoder.scala:128)
at classy.generic.derive.MkDecoder.decoder(MkDecoder.scala:30)
at classy.generic.derive.MkDecoderInstances2$$anonfun$mkDecoderGeneric$1.apply(MkDecoder.scala:80)
at classy.generic.derive.MkDecoderInstances2$$anonfun$mkDecoderGeneric$1.apply(MkDecoder.scala:80)
at classy.generic.derive.MkDecoder.decoder(MkDecoder.scala:30)
at classy.generic.derive.MkDecoderInstances0$$anonfun$mkDecoderCoproductDerived$1.apply(MkDecoder.scala:144)
at classy.generic.derive.MkDecoderInstances0$$anonfun$mkDecoderCoproductDerived$1.apply(MkDecoder.scala:143)
at classy.generic.derive.MkDecoder.decoder(MkDecoder.scala:30)
...
For expressing complex domain models and being able to readily marshal them to and from config it would be really nice to have support for this. I'm not entirely sure how libraries like Play JSON achieve recursive structure support, but it would be really great if Case Classy could also support it as well.
I'm not terribly experienced with Scala metaprogramming, but if someone can point me in the right direction I'm happy to help try to find a solution for this... just not quite sure where to start...
P.S.: Thank you for Case Classy - it's generally quite awesome :-)
I have the following hierarchy:
sealed trait SomeType
case object Type1 extends SomeType
case object Type2 extends SomeType
case class MyConfig(t: SomeType)
and the following config:
t: type1
I know it's possible with a manual decoder but I wonder if wouldn't be possible with automatically derived decoders?
I'm pretty sure it's time to dump the funky flat layout and move to a standard src/main/scala
layout.
Hoping to get a review of the documentation, in particular everything included on the microsite. Feedback on language and technical content welcomed.
We need to integrate sbt-org-policies.
Page: https://47deg.github.io/case-classy/quick-start.html
Link to tiny configured application
https://47deg.github.io/examples.html#configured-app routes to unknown page
We need to migrate new releases to the group id com.47deg
Issue created at typelevel/general#63
We need all assets for microsite design.
Improve toString
of RootDecodeError
and friends so that errors logged to stdout are more readable. For example:
Oh no!: Left(classy.package$RootDecodeError)
is not particularly useful.
If we go back to the example in the readme, I'd like to be able to do:
import classy.generic._
import classy.config._
sealed trait Shape
case class Circle(radius: Double) extends Shape
case class Rectangle(length: Double, width: Double) extends Shape
case class MyConfig(
someString: String,
shape: Option[Shape])
import com.typesafe.config.Config
val decoder1 = deriveDecoder[Config, MyConfig]
decoder1.fromString("""someString = hello""")
It would be nice to be able to use deriveDecoder
without having to import anything from com.typesafe.config
.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.