Advertisement
Cool_Dalek

Simple cats/pureconfig Scala3 di modules

Dec 7th, 2022
1,256
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Scala 2.84 KB | None | 0 0
  1. import cats.*
  2. import cats.syntax.all.*
  3. import cats.effect.*
  4. import pureconfig.error.ConfigReaderException
  5. import pureconfig.{ConfigReader, ConfigSource}
  6.  
  7. import scala.annotation.targetName
  8. import scala.reflect.ClassTag
  9.  
  10. trait Module[F[_]: Concurrent, Config, Api, Deps]:
  11.  
  12.   def loadConfig: Resource[F, Config]
  13.  
  14.   def deferredApi(dependency: Deps): Resource[F, Deferred[F, Api]] =
  15.     Resource.eval(Deferred.apply)
  16.  
  17.   def initApi(
  18.                config: Config,
  19.                dependency: Deps,
  20.                uninitializedApi: Deferred[F, Api],
  21.              ): Resource[F, Unit] =
  22.     loadApi(config, dependency).evalMap { api =>
  23.       uninitializedApi.complete(api).void
  24.     }
  25.  
  26.   @targetName("loadInit")
  27.   final def initApi(
  28.                      dependency: Deps,
  29.                      uninitializedApi: Deferred[F, Api]
  30.                    ): Resource[F, Unit] =
  31.     loadConfig.flatMap(c => initApi(c, dependency, uninitializedApi))
  32.  
  33.   def loadApi(config: Config, dependency: Deps): Resource[F, Api]
  34.  
  35.   def loadModule(dependency: Deps): Resource[F, Api] =
  36.     loadConfig.flatMap(c => loadApi(c, dependency))
  37.  
  38.   protected final def configAt[T: ConfigReader : ClassTag](path: String)(using ApplicativeThrow[F]): Resource[F, T] =
  39.     Resource.eval {
  40.       ApplicativeThrow[F].fromEither {
  41.         ConfigSource.default
  42.           .at(path)
  43.           .load[T]
  44.           .left
  45.           .map(x => new ConfigReaderException[T](x))
  46.       }
  47.     }
  48.  
  49. object Module:
  50.  
  51.   trait Independent[F[_]: Concurrent, Config, Api] extends Module[F, Config, Api, Unit]:
  52.  
  53.     //Copy defaults just to avoid extra method invocations
  54.  
  55.     final override def deferredApi(dependency: Unit): Resource[F, Deferred[F, Api]] =
  56.       deferredApi
  57.  
  58.     final override def initApi(
  59.                                 config: Config,
  60.                                 dependency: Unit,
  61.                                 uninitializedApi: Deferred[F, Api],
  62.                               ): Resource[F, Unit] =
  63.       initApi(config, uninitializedApi)
  64.  
  65.     final override def loadApi(config: Config, dependency: Unit): Resource[F, Api] =
  66.       loadApi(config)
  67.  
  68.     final override def loadModule(dependency: Unit): Resource[F, Api] =
  69.       loadModule
  70.  
  71.     def initApi(
  72.                  config: Config,
  73.                  uninitializedApi: Deferred[F, Api],
  74.                ): Resource[F, Unit] =
  75.       loadApi(config).evalMap { api =>
  76.         uninitializedApi.complete(api).void
  77.       }
  78.  
  79.     final def initApi(uninitializedApi: Deferred[F, Api]): Resource[F, Unit] =
  80.       loadConfig.flatMap(c => initApi(c, uninitializedApi))
  81.  
  82.     def loadApi(config: Config): Resource[F, Api]
  83.    
  84.     def loadModule: Resource[F, Api] =
  85.       loadConfig.flatMap(loadApi)
  86.  
  87.     def deferredApi: Resource[F, Deferred[F, Api]] =
  88.       Resource.eval(Deferred.apply)
  89.  
  90.   end Independent
  91.  
  92. end Module
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement