Some minor changes and additional documentation.

This commit is contained in:
Pat Garrity 2024-01-04 22:34:10 -06:00
parent 642d8dfc73
commit 1fdde0d7fb
Signed by: pfm
GPG key ID: 5CA5D21BAB7F3A76
2 changed files with 50 additions and 13 deletions

View file

@ -1,5 +1,6 @@
package gs.config
import cats.data.NonEmptyList
import cats.effect.Sync
import cats.syntax.all.*
import gs.config.audit.ConfigManifest
@ -8,8 +9,16 @@ import gs.config.source.ConfigSource
import gs.config.source.EnvironmentConfigSource
import gs.config.source.MemoryConfigSource
/** Implementation of [[gs.config.Configuration]] that tracks every call to
* `getValue` and reports on whether the query succeeded or failed.
*
* @param sources
* List of sources to use, in order, when resolving keys.
* @param manifest
* The manifest used to audit configuration loaded by this class.
*/
final class AuditedConfiguration[F[_]: Sync](
val sources: List[ConfigSource[F]],
val sources: NonEmptyList[ConfigSource[F]],
val manifest: ConfigManifest[F]
) extends BaseConfiguration[F]:
import AuditedConfiguration.Acc
@ -70,8 +79,17 @@ final class AuditedConfiguration[F[_]: Sync](
object AuditedConfiguration:
def forSources[F[_]: Sync](sources: List[ConfigSource[F]])
: F[Configuration[F]] =
/** Instantiate a new [[AuditedConfiguration]] based on the given list of
* sources.
*
* @param sources
* The list of [[ConfigSource]] backing this configuration.
* @return
* The new [[Configuration]] instance.
*/
def forSources[F[_]: Sync](
sources: NonEmptyList[ConfigSource[F]]
): F[Configuration[F]] =
ConfigManifest
.standard[F]
.map(manifest =>
@ -81,25 +99,32 @@ object AuditedConfiguration:
)
)
def builder[F[_]: Sync]: Builder[F] = Builder[F](Vector.empty)
def forSource[F[_]: Sync](source: ConfigSource[F]): Builder[F] =
Builder[F](NonEmptyList.of(source))
case class Builder[F[_]: Sync](sources: Vector[ConfigSource[F]]):
def forEnvironmentSource[F[_]: Sync]: Builder[F] =
Builder[F](NonEmptyList.of(new EnvironmentConfigSource[F]))
def forMemorySource[F[_]: Sync](configs: Map[String, String]): Builder[F] =
Builder[F](NonEmptyList.of(new MemoryConfigSource[F](configs)))
case class Builder[F[_]: Sync](sources: NonEmptyList[ConfigSource[F]]):
def withEnvironmentSource(): Builder[F] =
copy(sources = this.sources.appended(new EnvironmentConfigSource[F]))
copy(sources = this.sources.append(new EnvironmentConfigSource[F]))
def withMemorySource(configs: Map[String, String]): Builder[F] =
copy(sources = this.sources.appended(new MemoryConfigSource[F](configs)))
copy(sources = this.sources.append(new MemoryConfigSource[F](configs)))
def withSource(source: ConfigSource[F]): Builder[F] =
copy(sources = this.sources.appended(source))
copy(sources = this.sources.append(source))
def build(): F[Configuration[F]] =
ConfigManifest
.standard[F]
.map(manifest =>
new AuditedConfiguration[F](
sources = sources.toList,
sources = sources,
manifest = manifest
)
)

View file

@ -1,21 +1,33 @@
package gs.config
import cats.effect.Sync
import gs.config.source.ConfigSource
/** Interface for loading configuration.
/** Interface for loading configuration. This type should not be used for any
* sensitive configuration such as secrets or private keys.
*/
trait Configuration[F[_]]:
/** Retrieve a value based on some key.
*
* @param key
* The key that identifies the piece of configuration to retrieve.
* @return
* The value, or an error if no value is present.
*/
def getValue[A: Configurable](key: ConfigKey[A]): F[Either[ConfigError, A]]
object Configuration:
/** Start building a new [[AuditedConfiguration]].
*
* @param source
* The first source relevant to the configuration.
* @return
* Fluent builder for the [[AuditedConfiguration]] class.
*/
def audited[F[_]: Sync]: AuditedConfiguration.Builder[F] =
AuditedConfiguration.builder[F]
def audited[F[_]: Sync](source: ConfigSource[F])
: AuditedConfiguration.Builder[F] =
AuditedConfiguration.forSource[F](source)
/** Create a new [[AuditedConfiguration]] that reads from the environment.
*
@ -23,6 +35,6 @@ object Configuration:
* The new [[Configuration]].
*/
def auditedEnvironmentOnly[F[_]: Sync]: F[Configuration[F]] =
audited[F].withEnvironmentSource().build()
AuditedConfiguration.forEnvironmentSource[F].build()
end Configuration