From 117a37558de915ff7e9784bd1969a38c503be27d Mon Sep 17 00:00:00 2001 From: Pepe Garcia Date: Tue, 5 Jun 2018 10:06:47 +0200 Subject: [PATCH 1/8] bump freestyle version to 0.8.1 --- project/ProjectPlugin.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/ProjectPlugin.scala b/project/ProjectPlugin.scala index 9aa2f3076..cf677d314 100644 --- a/project/ProjectPlugin.scala +++ b/project/ProjectPlugin.scala @@ -23,7 +23,7 @@ object ProjectPlugin extends AutoPlugin { val avrohugger: String = "1.0.0-RC10" val catsEffect: String = "0.10.1" val circe: String = "0.9.3" - val frees: String = "0.8.0" + val frees: String = "0.8.1" val fs2ReactiveStreams: String = "0.5.1" val grpc: String = "1.11.0" val log4s: String = "1.6.1" From c5c4c11c99f1739269106a634aca4ffc0859b544 Mon Sep 17 00:00:00 2001 From: Pepe Garcia Date: Tue, 5 Jun 2018 10:07:10 +0200 Subject: [PATCH 2/8] bump frees-todolist-lib to 0.8.1 --- project/ProjectPlugin.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/ProjectPlugin.scala b/project/ProjectPlugin.scala index cf677d314..c27106d59 100644 --- a/project/ProjectPlugin.scala +++ b/project/ProjectPlugin.scala @@ -164,7 +164,7 @@ object ProjectPlugin extends AutoPlugin { lazy val exampleTodolistCommonSettings: Seq[Def.Setting[_]] = Seq( libraryDependencies ++= Seq( - "io.frees" %% "frees-todolist-lib" % "0.8.1-SNAPSHOT", + "io.frees" %% "frees-todolist-lib" % V.frees, %%("log4s", V.log4s), %("logback-classic", V.logback) ) From 0b43c5ee3f0fa2b9f426cd9d674147ca0d5e4c1d Mon Sep 17 00:00:00 2001 From: Pepe Garcia Date: Tue, 5 Jun 2018 18:09:21 +0200 Subject: [PATCH 3/8] bump sbt-freestyle --- project/plugins.sbt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/plugins.sbt b/project/plugins.sbt index 55a53de3b..c9bace722 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,7 +1,7 @@ resolvers += Resolver.sonatypeRepo("releases") resolvers += Resolver.sonatypeRepo("snapshots") -addSbtPlugin("io.frees" % "sbt-freestyle" % "0.3.21") +addSbtPlugin("io.frees" % "sbt-freestyle" % "0.3.23") addSbtPlugin("com.eed3si9n" % "sbt-buildinfo" % "0.8.0") libraryDependencies += "org.scala-sbt" %% "scripted-plugin" % sbtVersion.value From ee3de5b1dc71183a3166a6a2c2df0db12d1e6e80 Mon Sep 17 00:00:00 2001 From: Pepe Garcia Date: Tue, 5 Jun 2018 18:10:29 +0200 Subject: [PATCH 4/8] don't depend on frees-config depend on pureconfig instead --- project/ProjectPlugin.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/ProjectPlugin.scala b/project/ProjectPlugin.scala index c27106d59..38739ed33 100644 --- a/project/ProjectPlugin.scala +++ b/project/ProjectPlugin.scala @@ -92,7 +92,7 @@ object ProjectPlugin extends AutoPlugin { lazy val configSettings = Seq( libraryDependencies ++= Seq( - %%("frees-config", V.frees) + %%("pureconfig") ) ) From ba3ffd9c1353cb14cb6382273bdd6f2fd12ac36a Mon Sep 17 00:00:00 2001 From: Pepe Garcia Date: Tue, 5 Jun 2018 18:14:45 +0200 Subject: [PATCH 5/8] don't depend on freestyle.tagless.ConfigM create our own ConfigM instead --- .../src/main/scala/client/ChannelConfig.scala | 49 +++++++++++------ modules/config/src/main/scala/config.scala | 33 ++++++++++++ .../src/main/scala/server/ServerConfig.scala | 52 +++++++++++++------ .../scala/client/ChannelConfigTests.scala | 13 ++--- .../test/scala/server/ServerConfigTests.scala | 3 +- 5 files changed, 108 insertions(+), 42 deletions(-) create mode 100644 modules/config/src/main/scala/config.scala diff --git a/modules/config/src/main/scala/client/ChannelConfig.scala b/modules/config/src/main/scala/client/ChannelConfig.scala index 749443ca2..3fa6421ba 100644 --- a/modules/config/src/main/scala/client/ChannelConfig.scala +++ b/modules/config/src/main/scala/client/ChannelConfig.scala @@ -18,27 +18,46 @@ package freestyle.rpc package client package config -import cats.Functor -import cats.syntax.either._ +import cats.effect.Sync import cats.syntax.functor._ -import freestyle.tagless._ -import freestyle.tagless.config.ConfigM +import cats.syntax.flatMap._ +import cats.syntax.either._ + +import freestyle.rpc.config.ConfigM + +import com.typesafe.config.ConfigException.Missing -@module -trait ChannelConfig { +trait ChannelConfig[F[_]] { - implicit val functor: Functor + implicit def sync: Sync[F] + implicit def configM: ConfigM[F] - val configM: ConfigM val defaultHost: String = "localhost" val defaultPort: Int = freestyle.rpc.server.defaultPort - def loadChannelAddress(hostPath: String, portPath: String): FS[ChannelForAddress] = - configM.load map (config => - ChannelForAddress( - config.string(hostPath).getOrElse(defaultHost), - config.int(portPath).getOrElse(defaultPort))) + def loadChannelAddress(hostPath: String, portPath: String): F[ChannelForAddress] = + for { + config <- configM.load + host <- sync.pure( + Either + .catchOnly[Missing](config.getString(hostPath))) + port <- sync.pure(Either.catchOnly[Missing](config.getInt(portPath))) + } yield ChannelForAddress(host.getOrElse(defaultHost), port.getOrElse(defaultPort)) + + def loadChannelTarget(targetPath: String): F[ChannelForTarget] = + for { + config <- configM.load + target <- sync.pure(Either.catchOnly[Missing](config.getString(targetPath))) + } yield ChannelForTarget(target.getOrElse("target")) + +} + +object ChannelConfig { + def apply[F[_]](implicit S: Sync[F], C: ConfigM[F]): ChannelConfig[F] = new ChannelConfig[F] { + def sync = S + def configM = C + } - def loadChannelTarget(targetPath: String): FS[ChannelForTarget] = - configM.load map (config => ChannelForTarget(config.string(targetPath).getOrElse("target"))) + implicit def defaultChannelConfig[F[_]](implicit S: Sync[F], C: ConfigM[F]): ChannelConfig[F] = + apply[F](S, C) } diff --git a/modules/config/src/main/scala/config.scala b/modules/config/src/main/scala/config.scala new file mode 100644 index 000000000..da27bb5f5 --- /dev/null +++ b/modules/config/src/main/scala/config.scala @@ -0,0 +1,33 @@ +/* + * Copyright 2017-2018 47 Degrees, LLC. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package freestyle.rpc + +import cats.effect.Sync +import pureconfig._ +import com.typesafe.config.{Config, ConfigFactory} + +object config { + + trait ConfigM[F[_]] { + def load: F[Config] + } + + implicit def syncConfigM[F[_]](implicit F: Sync[F]): ConfigM[F] = new ConfigM[F] { + def load: F[Config] = F.delay(loadConfigOrThrow[Config](ConfigFactory.load())) + } + +} diff --git a/modules/config/src/main/scala/server/ServerConfig.scala b/modules/config/src/main/scala/server/ServerConfig.scala index 3d1ab7b0c..efb8eaa59 100644 --- a/modules/config/src/main/scala/server/ServerConfig.scala +++ b/modules/config/src/main/scala/server/ServerConfig.scala @@ -18,26 +18,44 @@ package freestyle.rpc package server package config -import cats.Functor -import cats.syntax.either._ +import cats.effect.Sync +import cats.syntax.flatMap._ import cats.syntax.functor._ -import freestyle.tagless._ -import freestyle.tagless.config.ConfigM +import cats.syntax.either._ + +import freestyle.rpc.config.ConfigM + +import com.typesafe.config.ConfigException.Missing -@module -trait ServerConfig { +trait ServerConfig[F[_]] { + + implicit def sync: Sync[F] + implicit def configM: ConfigM[F] + + def buildServer(portPath: String, configList: List[GrpcConfig] = Nil): F[ServerW] = + for { + config <- configM.load + port <- sync.pure( + Either + .catchOnly[Missing](config.getInt(portPath))) + } yield ServerW.default(port.getOrElse(defaultPort), configList) + + def buildNettyServer(portPath: String, configList: List[GrpcConfig] = Nil): F[ServerW] = + for { + config <- configM.load + port <- sync.pure( + Either + .catchOnly[Missing](config.getInt(portPath))) + } yield ServerW.netty(ChannelForPort(port.getOrElse(defaultPort)), configList) +} - val configM: ConfigM - implicit val functor: Functor +object ServerConfig { + def apply[F[_]](implicit S: Sync[F], C: ConfigM[F]): ServerConfig[F] = new ServerConfig[F] { + def sync = S + def configM = C + } - def buildServer(portPath: String, configList: List[GrpcConfig] = Nil): FS[ServerW] = - configM.load.map { config => - val port = config.int(portPath).getOrElse(defaultPort) - ServerW.default(port, configList) - } + implicit def defaultServerConfig[F[_]](implicit S: Sync[F], C: ConfigM[F]): ServerConfig[F] = + apply[F](S, C) - def buildNettyServer(portPath: String, configList: List[GrpcConfig] = Nil): FS[ServerW] = - configM.load.map { config => - ServerW.netty(ChannelForPort(config.int(portPath).getOrElse(defaultPort)), configList) - } } diff --git a/modules/config/src/test/scala/client/ChannelConfigTests.scala b/modules/config/src/test/scala/client/ChannelConfigTests.scala index 832db3867..81a7a5a52 100644 --- a/modules/config/src/test/scala/client/ChannelConfigTests.scala +++ b/modules/config/src/test/scala/client/ChannelConfigTests.scala @@ -18,24 +18,21 @@ package freestyle.rpc package client package config -import cats.instances.try_._ -import freestyle.tagless.config.implicits._ -import freestyle.rpc.common.SC - -import scala.util.{Success, Try} +import freestyle.rpc.common.{ConcurrentMonad, SC} class ChannelConfigTests extends RpcClientTestSuite { "ChannelConfig" should { "for Address [host, port] work as expected" in { - - ConfigForAddress[Try](SC.host, SC.port.toString) shouldBe a[Success[_]] + ConfigForAddress[ConcurrentMonad](SC.host, SC.port.toString).unsafeRunSync shouldBe ChannelForAddress( + "localhost", + 50051) } "for Target work as expected" in { - ConfigForTarget[Try](SC.host) shouldBe a[Success[_]] + ConfigForTarget[ConcurrentMonad](SC.host).unsafeRunSync shouldBe ChannelForTarget("target") } } diff --git a/modules/config/src/test/scala/server/ServerConfigTests.scala b/modules/config/src/test/scala/server/ServerConfigTests.scala index d80399059..c5149d10c 100644 --- a/modules/config/src/test/scala/server/ServerConfigTests.scala +++ b/modules/config/src/test/scala/server/ServerConfigTests.scala @@ -18,7 +18,6 @@ package freestyle.rpc package server package config -import freestyle.tagless.config.implicits._ import freestyle.rpc.common.{ConcurrentMonad, SC} import scala.concurrent.ExecutionContext @@ -27,7 +26,7 @@ class ServerConfigTests extends RpcServerTestSuite { implicit val ec: ExecutionContext = ExecutionContext.Implicits.global - "ServerConfig.Op" should { + "ServerConfig" should { "load the port specified in the config file" in { From b40b26d57af25d1cafef4b33a77bac0a346d58dd Mon Sep 17 00:00:00 2001 From: Pepe Garcia Date: Tue, 5 Jun 2018 18:57:07 +0200 Subject: [PATCH 6/8] remove imports related to frees-config --- .../routeguide/client/src/main/scala/runtime/ClientConf.scala | 1 - .../examples/routeguide/server/src/main/scala/implicits.scala | 1 - modules/examples/todolist/client/src/main/scala/implicits.scala | 1 - modules/examples/todolist/server/src/main/scala/implicits.scala | 1 - 4 files changed, 4 deletions(-) diff --git a/modules/examples/routeguide/client/src/main/scala/runtime/ClientConf.scala b/modules/examples/routeguide/client/src/main/scala/runtime/ClientConf.scala index 095034872..cce8afad9 100644 --- a/modules/examples/routeguide/client/src/main/scala/runtime/ClientConf.scala +++ b/modules/examples/routeguide/client/src/main/scala/runtime/ClientConf.scala @@ -19,7 +19,6 @@ package example.routeguide.client.runtime import cats.effect.IO import freestyle.rpc.ChannelFor import freestyle.rpc.client.config.ConfigForAddress -import freestyle.tagless.config.implicits._ trait ClientConf { diff --git a/modules/examples/routeguide/server/src/main/scala/implicits.scala b/modules/examples/routeguide/server/src/main/scala/implicits.scala index df76e5fac..77a71c29d 100644 --- a/modules/examples/routeguide/server/src/main/scala/implicits.scala +++ b/modules/examples/routeguide/server/src/main/scala/implicits.scala @@ -20,7 +20,6 @@ import cats.effect.IO import freestyle.rpc.server._ import freestyle.rpc.server.config.BuildServerFromConfig import freestyle.rpc.server.{AddService, GrpcConfig, ServerW} -import freestyle.tagless.config.implicits._ import example.routeguide.server.handlers.RouteGuideServiceHandler import example.routeguide.protocol.Protocols.RouteGuideService import example.routeguide.runtime._ diff --git a/modules/examples/todolist/client/src/main/scala/implicits.scala b/modules/examples/todolist/client/src/main/scala/implicits.scala index 39a5b3550..7438768fe 100644 --- a/modules/examples/todolist/client/src/main/scala/implicits.scala +++ b/modules/examples/todolist/client/src/main/scala/implicits.scala @@ -20,7 +20,6 @@ import cats.effect.IO import examples.todolist.client.handlers._ import examples.todolist.protocol.Protocols._ import freestyle.tagless.loggingJVM.log4s.implicits._ -import freestyle.tagless.config.implicits._ import examples.todolist.runtime.CommonRuntime import freestyle.rpc.ChannelFor import freestyle.rpc.client.config.ConfigForAddress diff --git a/modules/examples/todolist/server/src/main/scala/implicits.scala b/modules/examples/todolist/server/src/main/scala/implicits.scala index 1022f5e10..59e31b1be 100644 --- a/modules/examples/todolist/server/src/main/scala/implicits.scala +++ b/modules/examples/todolist/server/src/main/scala/implicits.scala @@ -28,7 +28,6 @@ import examples.todolist.server.handlers._ import freestyle.rpc.server._ import freestyle.rpc.server.config.BuildServerFromConfig import freestyle.rpc.server.{AddService, GrpcConfig, ServerW} -import freestyle.tagless.config.implicits._ import freestyle.tagless.loggingJVM.log4s.implicits._ import java.util.Properties From 365ec974a20bd9fa7d543afd1ec565a83a99fec9 Mon Sep 17 00:00:00 2001 From: Pepe Garcia Date: Wed, 6 Jun 2018 10:02:06 +0200 Subject: [PATCH 7/8] fix docs We need to make the calls to `ConfigForAddress` with an F that has `Sync`, so we're making them with `IO` now. --- docs/src/main/tut/core-concepts.md | 10 +++------- docs/src/main/tut/metrics-reporting.md | 11 +++-------- docs/src/main/tut/patterns.md | 11 +++-------- 3 files changed, 9 insertions(+), 23 deletions(-) diff --git a/docs/src/main/tut/core-concepts.md b/docs/src/main/tut/core-concepts.md index 9bdc7e31d..17e5c3948 100644 --- a/docs/src/main/tut/core-concepts.md +++ b/docs/src/main/tut/core-concepts.md @@ -225,10 +225,11 @@ trait CommonRuntime { ``` ```tut:silent +import cats.effect.IO import cats.implicits._ -import freestyle.free.config.implicits._ import freestyle.async.catsEffect.implicits._ import freestyle.rpc._ +import freestyle.rpc.config._ import freestyle.rpc.client._ import freestyle.rpc.client.config._ import freestyle.rpc.client.implicits._ @@ -241,12 +242,7 @@ import scala.util.{Failure, Success, Try} trait Implicits extends CommonRuntime { val channelFor: ChannelFor = - ConfigForAddress[Try]("rpc.host", "rpc.port") match { - case Success(c) => c - case Failure(e) => - e.printStackTrace() - throw new RuntimeException("Unable to load the client configuration", e) - } + ConfigForAddress[IO]("rpc.host", "rpc.port").unsafeRunSync implicit val serviceClient: Greeter.Client[Task] = Greeter.client[Task](channelFor, options = CallOptions.DEFAULT.withCompression("gzip")) diff --git a/docs/src/main/tut/metrics-reporting.md b/docs/src/main/tut/metrics-reporting.md index b6ffda67b..39a138c2c 100644 --- a/docs/src/main/tut/metrics-reporting.md +++ b/docs/src/main/tut/metrics-reporting.md @@ -101,9 +101,9 @@ In this case, in order to intercept the client calls we need additional configur ```tut:silent import cats.implicits._ import cats.effect.IO -import freestyle.free.config.implicits._ import freestyle.async.catsEffect.implicits._ import freestyle.rpc._ +import freestyle.rpc.config._ import freestyle.rpc.client._ import freestyle.rpc.client.config._ import freestyle.rpc.client.implicits._ @@ -119,12 +119,7 @@ import freestyle.rpc.prometheus.client.MonitoringClientInterceptor object InterceptingClientCalls extends CommonRuntime { val channelFor: ChannelFor = - ConfigForAddress[Try]("rpc.host", "rpc.port") match { - case Success(c) => c - case Failure(e) => - e.printStackTrace() - throw new RuntimeException("Unable to load the client configuration", e) - } + ConfigForAddress[IO]("rpc.host", "rpc.port").unsafeRunSync implicit val serviceClient: Greeter.Client[Task] = Greeter.client[Task]( @@ -169,4 +164,4 @@ configuration.collectorRegistry.register(new DropwizardExports(metrics)) [Monix]: https://monix.io/ [cats-effect]: https://github.com/typelevel/cats-effect [Metrifier]: https://github.com/47deg/metrifier -[frees-config]: http://frees.io/docs/patterns/config/ \ No newline at end of file +[frees-config]: http://frees.io/docs/patterns/config/ diff --git a/docs/src/main/tut/patterns.md b/docs/src/main/tut/patterns.md index ce4efa1fe..8208ab1fc 100644 --- a/docs/src/main/tut/patterns.md +++ b/docs/src/main/tut/patterns.md @@ -280,9 +280,9 @@ So, taking into account all we have just said, how would our code look? ```tut:silent import cats.implicits._ import cats.effect.IO -import freestyle.free.config.implicits._ import freestyle.async.catsEffect.implicits._ import freestyle.rpc._ +import freestyle.rpc.config._ import freestyle.rpc.client._ import freestyle.rpc.client.config._ import freestyle.rpc.client.implicits._ @@ -297,12 +297,7 @@ object gclient { trait Implicits extends CommonRuntime { val channelFor: ChannelFor = - ConfigForAddress[Try]("rpc.host", "rpc.port") match { - case Success(c) => c - case Failure(e) => - e.printStackTrace() - throw new RuntimeException("Unable to load the client configuration", e) - } + ConfigForAddress[IO]("rpc.host", "rpc.port").unsafeRunSync implicit val serviceClient: Greeter.Client[Task] = Greeter.client[Task](channelFor) @@ -355,4 +350,4 @@ object RPCDemoApp { [Monix]: https://monix.io/ [cats-effect]: https://github.com/typelevel/cats-effect [Metrifier]: https://github.com/47deg/metrifier -[frees-config]: http://frees.io/docs/patterns/config/ \ No newline at end of file +[frees-config]: http://frees.io/docs/patterns/config/ From 1bb4bcf071353229deb3df08f8a1a32a8a1c093d Mon Sep 17 00:00:00 2001 From: Pepe Garcia Date: Wed, 6 Jun 2018 11:54:29 +0200 Subject: [PATCH 8/8] convert ChannelConfig and ServerConfig to classes --- .../src/main/scala/client/ChannelConfig.scala | 21 +++++++------------ .../src/main/scala/server/ServerConfig.scala | 19 ++++++----------- 2 files changed, 14 insertions(+), 26 deletions(-) diff --git a/modules/config/src/main/scala/client/ChannelConfig.scala b/modules/config/src/main/scala/client/ChannelConfig.scala index 3fa6421ba..a785706c9 100644 --- a/modules/config/src/main/scala/client/ChannelConfig.scala +++ b/modules/config/src/main/scala/client/ChannelConfig.scala @@ -27,36 +27,31 @@ import freestyle.rpc.config.ConfigM import com.typesafe.config.ConfigException.Missing -trait ChannelConfig[F[_]] { - - implicit def sync: Sync[F] - implicit def configM: ConfigM[F] +class ChannelConfig[F[_]](implicit S: Sync[F], C: ConfigM[F]) { val defaultHost: String = "localhost" val defaultPort: Int = freestyle.rpc.server.defaultPort def loadChannelAddress(hostPath: String, portPath: String): F[ChannelForAddress] = for { - config <- configM.load - host <- sync.pure( + config <- C.load + host <- S.pure( Either .catchOnly[Missing](config.getString(hostPath))) - port <- sync.pure(Either.catchOnly[Missing](config.getInt(portPath))) + port <- S.pure(Either.catchOnly[Missing](config.getInt(portPath))) } yield ChannelForAddress(host.getOrElse(defaultHost), port.getOrElse(defaultPort)) def loadChannelTarget(targetPath: String): F[ChannelForTarget] = for { - config <- configM.load - target <- sync.pure(Either.catchOnly[Missing](config.getString(targetPath))) + config <- C.load + target <- S.pure(Either.catchOnly[Missing](config.getString(targetPath))) } yield ChannelForTarget(target.getOrElse("target")) } object ChannelConfig { - def apply[F[_]](implicit S: Sync[F], C: ConfigM[F]): ChannelConfig[F] = new ChannelConfig[F] { - def sync = S - def configM = C - } + def apply[F[_]](implicit S: Sync[F], C: ConfigM[F]): ChannelConfig[F] = + new ChannelConfig[F] implicit def defaultChannelConfig[F[_]](implicit S: Sync[F], C: ConfigM[F]): ChannelConfig[F] = apply[F](S, C) diff --git a/modules/config/src/main/scala/server/ServerConfig.scala b/modules/config/src/main/scala/server/ServerConfig.scala index efb8eaa59..0bcb525be 100644 --- a/modules/config/src/main/scala/server/ServerConfig.scala +++ b/modules/config/src/main/scala/server/ServerConfig.scala @@ -27,35 +27,28 @@ import freestyle.rpc.config.ConfigM import com.typesafe.config.ConfigException.Missing -trait ServerConfig[F[_]] { - - implicit def sync: Sync[F] - implicit def configM: ConfigM[F] +class ServerConfig[F[_]](implicit S: Sync[F], C: ConfigM[F]) { def buildServer(portPath: String, configList: List[GrpcConfig] = Nil): F[ServerW] = for { - config <- configM.load - port <- sync.pure( + config <- C.load + port <- S.pure( Either .catchOnly[Missing](config.getInt(portPath))) } yield ServerW.default(port.getOrElse(defaultPort), configList) def buildNettyServer(portPath: String, configList: List[GrpcConfig] = Nil): F[ServerW] = for { - config <- configM.load - port <- sync.pure( + config <- C.load + port <- S.pure( Either .catchOnly[Missing](config.getInt(portPath))) } yield ServerW.netty(ChannelForPort(port.getOrElse(defaultPort)), configList) } object ServerConfig { - def apply[F[_]](implicit S: Sync[F], C: ConfigM[F]): ServerConfig[F] = new ServerConfig[F] { - def sync = S - def configM = C - } + def apply[F[_]](implicit S: Sync[F], C: ConfigM[F]): ServerConfig[F] = new ServerConfig[F] implicit def defaultServerConfig[F[_]](implicit S: Sync[F], C: ConfigM[F]): ServerConfig[F] = apply[F](S, C) - }