diff --git a/src/main/scala/gs/config/AuditedConfiguration.scala b/src/main/scala/gs/config/AuditedConfiguration.scala index 138e639..8204fa2 100644 --- a/src/main/scala/gs/config/AuditedConfiguration.scala +++ b/src/main/scala/gs/config/AuditedConfiguration.scala @@ -5,6 +5,8 @@ import cats.syntax.all.* import gs.config.audit.ConfigManifest import gs.config.audit.ConfigQueryResult import gs.config.source.ConfigSource +import gs.config.source.EnvironmentConfigSource +import gs.config.source.MemoryConfigSource final class AuditedConfiguration[F[_]: Sync]( val sources: List[ConfigSource[F]], @@ -68,6 +70,47 @@ final class AuditedConfiguration[F[_]: Sync]( object AuditedConfiguration: + def forSources[F[_]: Sync](sources: List[ConfigSource[F]]) + : F[Configuration[F]] = + ConfigManifest + .standard[F] + .map(manifest => + new AuditedConfiguration[F]( + sources = sources, + manifest = manifest + ) + ) + + def builder[F[_]: Sync]: Builder[F] = Builder[F](Vector.empty) + + case class Builder[F[_]: Sync](sources: Vector[ConfigSource[F]]): + + def withEnvironmentSource(): Builder[F] = + copy(sources = this.sources.appended(new EnvironmentConfigSource[F])) + + def withMemorySource(configs: Map[String, String]): Builder[F] = + copy(sources = this.sources.appended(new MemoryConfigSource[F](configs))) + + def withSource(source: ConfigSource[F]): Builder[F] = + copy(sources = this.sources.appended(source)) + + def build(): F[Configuration[F]] = + ConfigManifest + .standard[F] + .map(manifest => + new AuditedConfiguration[F]( + sources = sources.toList, + manifest = manifest + ) + ) + + /** Internal class for accumulating a result across sources. + * + * @param sources + * The seen sources. + * @param result + * The result, or `None` if no result has been found. + */ private case class Acc( sources: Vector[String], result: Option[String] diff --git a/src/main/scala/gs/config/Configuration.scala b/src/main/scala/gs/config/Configuration.scala index e9561e9..cb35aef 100644 --- a/src/main/scala/gs/config/Configuration.scala +++ b/src/main/scala/gs/config/Configuration.scala @@ -1,4 +1,28 @@ package gs.config +import cats.effect.Sync + +/** Interface for loading configuration. + */ trait Configuration[F[_]]: def getValue[A: Configurable](key: ConfigKey[A]): F[Either[ConfigError, A]] + +object Configuration: + + /** Start building a new [[AuditedConfiguration]]. + * + * @return + * Fluent builder for the [[AuditedConfiguration]] class. + */ + def audited[F[_]: Sync]: AuditedConfiguration.Builder[F] = + AuditedConfiguration.builder[F] + + /** Create a new [[AuditedConfiguration]] that reads from the environment. + * + * @return + * The new [[Configuration]]. + */ + def auditedEnvironmentOnly[F[_]: Sync]: F[Configuration[F]] = + audited[F].withEnvironmentSource().build() + +end Configuration