Adding substantial functionality and documentation.
This commit is contained in:
		
							parent
							
								
									f8928d24af
								
							
						
					
					
						commit
						67f5adc2a9
					
				
					 10 changed files with 360 additions and 29 deletions
				
			
		|  | @ -1,11 +1,11 @@ | ||||||
| --- | --- | ||||||
| repos: | repos: | ||||||
|   - repo: https://github.com/pre-commit/pre-commit-hooks |   - repo: https://github.com/pre-commit/pre-commit-hooks | ||||||
|     rev: v4.4.0 |     rev: v4.5.0 | ||||||
|     hooks: |     hooks: | ||||||
|       - id: end-of-file-fixer |       - id: end-of-file-fixer | ||||||
|       - id: trailing-whitespace |       - id: trailing-whitespace | ||||||
|   - repo: https://git.garrity.co/garrity-software/gs-pre-commit-scala |   - repo: https://git.garrity.co/garrity-software/gs-pre-commit-scala | ||||||
|     rev: v0.1.0 |     rev: v0.1.3 | ||||||
|     hooks: |     hooks: | ||||||
|       - id: scalafmt |       - id: scalafmt | ||||||
|  |  | ||||||
							
								
								
									
										56
									
								
								build.sbt
									
										
									
									
									
								
							
							
						
						
									
										56
									
								
								build.sbt
									
										
									
									
									
								
							|  | @ -13,12 +13,14 @@ externalResolvers := Seq( | ||||||
| val ProjectName: String = "gs-config" | val ProjectName: String = "gs-config" | ||||||
| val Description: String = "Garrity Software Configuration Library" | val Description: String = "Garrity Software Configuration Library" | ||||||
| 
 | 
 | ||||||
| /** | /** Helper to extract the value from `-Dproperty=value`. | ||||||
|   * Helper to extract the value from `-Dproperty=value`. |  | ||||||
|   * |   * | ||||||
|   * @param name The property name. |   * @param name | ||||||
|   * @param conv The conversion function to the output type. |   *   The property name. | ||||||
|   * @return The converted value, or `None` if no value exists. |   * @param conv | ||||||
|  |   *   The conversion function to the output type. | ||||||
|  |   * @return | ||||||
|  |   *   The converted value, or `None` if no value exists. | ||||||
|   */ |   */ | ||||||
| def getProperty[A]( | def getProperty[A]( | ||||||
|   name: String, |   name: String, | ||||||
|  | @ -26,53 +28,50 @@ def getProperty[A]( | ||||||
| ): Option[A] = | ): Option[A] = | ||||||
|   Option(System.getProperty(name)).map(conv) |   Option(System.getProperty(name)).map(conv) | ||||||
| 
 | 
 | ||||||
| /** | /** Use `sbt -Dversion=<version>` to provide the version, minus the SNAPSHOT | ||||||
|   * Use `sbt -Dversion=<version>` to provide the version, minus the SNAPSHOT |  | ||||||
|   * modifier. This is the typical approach for producing releases. |   * modifier. This is the typical approach for producing releases. | ||||||
|   */ |   */ | ||||||
| val VersionProperty: String = "version" | val VersionProperty: String = "version" | ||||||
| 
 | 
 | ||||||
| /** | /** Use `sbt -Drelease=true` to trigger a release build. | ||||||
|   * Use `sbt -Drelease=true` to trigger a release build. |  | ||||||
|   */ |   */ | ||||||
| val ReleaseProperty: String = "release" | val ReleaseProperty: String = "release" | ||||||
| 
 | 
 | ||||||
| /** | /** The value of `-Dversion=<value>`. | ||||||
|   * The value of `-Dversion=<value>`. |  | ||||||
|   * |   * | ||||||
|   * @return The version passed as input to SBT. |   * @return | ||||||
|  |   *   The version passed as input to SBT. | ||||||
|   */ |   */ | ||||||
| lazy val InputVersion: Option[String] = | lazy val InputVersion: Option[String] = | ||||||
|   getProperty(VersionProperty, identity) |   getProperty(VersionProperty, identity) | ||||||
| 
 | 
 | ||||||
| /** | /** @return | ||||||
|   * @return "-SNAPSHOT" if this is NOT a release, empty string otherwise. |   *   "-SNAPSHOT" if this is NOT a release, empty string otherwise. | ||||||
|   */ |   */ | ||||||
| lazy val Modifier: String = | lazy val Modifier: String = | ||||||
|   if (getProperty(ReleaseProperty, _.toBoolean).getOrElse(false)) "" |   if (getProperty(ReleaseProperty, _.toBoolean).getOrElse(false)) "" | ||||||
|   else "-SNAPSHOT" |   else "-SNAPSHOT" | ||||||
| 
 | 
 | ||||||
| /** | /** Version used if no version is passed as input. This helps with default/local | ||||||
|   * Version used if no version is passed as input. This helps with default/local |  | ||||||
|   * builds. |   * builds. | ||||||
|   */ |   */ | ||||||
| val DefaultVersion: String = "0.1.0-SNAPSHOT" | val DefaultVersion: String = "0.1.0-SNAPSHOT" | ||||||
| 
 | 
 | ||||||
| /** | /** This is the output version of the published artifact. If this build is not a | ||||||
|   * This is the output version of the published artifact. If this build is not |   * release, the suffix "-SNAPSHOT" will be appended. | ||||||
|   * a release, the suffix "-SNAPSHOT" will be appended. |  | ||||||
|   * |   * | ||||||
|   * @return The project version. |   * @return | ||||||
|  |   *   The project version. | ||||||
|   */ |   */ | ||||||
| lazy val SelectedVersion: String = | lazy val SelectedVersion: String = | ||||||
|   InputVersion |   InputVersion | ||||||
|     .map(v => s"$v$Modifier") |     .map(v => s"$v$Modifier") | ||||||
|     .getOrElse(DefaultVersion) |     .getOrElse(DefaultVersion) | ||||||
| 
 | 
 | ||||||
| /** | /** The major version (first segment) value. Used to label releases. | ||||||
|   * The major version (first segment) value. Used to label releases. |  | ||||||
|   * |   * | ||||||
|   * @return The major version of the project. |   * @return | ||||||
|  |   *   The major version of the project. | ||||||
|   */ |   */ | ||||||
| lazy val MajorVersion: String = | lazy val MajorVersion: String = | ||||||
|   SelectedVersion.split('.').apply(0) |   SelectedVersion.split('.').apply(0) | ||||||
|  | @ -96,10 +95,13 @@ lazy val publishSettings = Seq( | ||||||
|   licenses := List( |   licenses := List( | ||||||
|     "Apache 2.0" -> url("https://www.apache.org/licenses/LICENSE-2.0.html") |     "Apache 2.0" -> url("https://www.apache.org/licenses/LICENSE-2.0.html") | ||||||
|   ), |   ), | ||||||
|   homepage := Some(url(s"https://git.garrity.co/garrity-software/$ProjectName")), |   homepage := Some( | ||||||
|  |     url(s"https://git.garrity.co/garrity-software/$ProjectName") | ||||||
|  |   ), | ||||||
|   publishTo := { |   publishTo := { | ||||||
|     val repo = "https://maven.garrity.co/" |     val repo = "https://maven.garrity.co/" | ||||||
|     if (SelectedVersion.endsWith("SNAPSHOT")) Some("snapshots" at repo + "snapshots") |     if (SelectedVersion.endsWith("SNAPSHOT")) | ||||||
|  |       Some("snapshots" at repo + "snapshots") | ||||||
|     else Some("releases" at repo + "releases") |     else Some("releases" at repo + "releases") | ||||||
|   } |   } | ||||||
| ) | ) | ||||||
|  | @ -110,13 +112,15 @@ lazy val testSettings = Seq( | ||||||
|   ) |   ) | ||||||
| ) | ) | ||||||
| 
 | 
 | ||||||
| lazy val `gs-config` = (project.in(file("."))) | lazy val `gs-config` = project | ||||||
|  |   .in(file(".")) | ||||||
|   .settings(sharedSettings) |   .settings(sharedSettings) | ||||||
|   .settings(publishSettings) |   .settings(publishSettings) | ||||||
|   .settings(testSettings) |   .settings(testSettings) | ||||||
|   .settings(name := s"$ProjectName-v$MajorVersion") |   .settings(name := s"$ProjectName-v$MajorVersion") | ||||||
|   .settings( |   .settings( | ||||||
|     libraryDependencies ++= Seq( |     libraryDependencies ++= Seq( | ||||||
|  |       "org.typelevel" %% "cats-effect" % "3.5.2" | ||||||
|     ) |     ) | ||||||
|   ) |   ) | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										35
									
								
								src/main/scala/gs/config/ConfigError.scala
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								src/main/scala/gs/config/ConfigError.scala
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,35 @@ | ||||||
|  | package gs.config | ||||||
|  | 
 | ||||||
|  | import gs.config.audit.ConfigSource | ||||||
|  | 
 | ||||||
|  | /** Error hierarchy for the `gs-config` library. Indicates that something went | ||||||
|  |   * wrong while attempting to load configuration values. | ||||||
|  |   */ | ||||||
|  | sealed trait ConfigError | ||||||
|  | 
 | ||||||
|  | object ConfigError: | ||||||
|  |   /** Attempted to retreive the value for some [[ConfigKey]], but no value could | ||||||
|  |     * be found. | ||||||
|  |     * | ||||||
|  |     * @param name | ||||||
|  |     *   The name of the configuration value which was not found. | ||||||
|  |     */ | ||||||
|  |   case class MissingValue(name: ConfigName) extends ConfigError | ||||||
|  | 
 | ||||||
|  |   /** Found a value for some [[ConfigKey]], but that value could not be parsed | ||||||
|  |     * as the appropriate type. | ||||||
|  |     * | ||||||
|  |     * @param name | ||||||
|  |     *   The name of the configuration value which could not be parsed. | ||||||
|  |     * @param candidate | ||||||
|  |     *   The raw value that could not be parsed. | ||||||
|  |     * @param source | ||||||
|  |     *   The [[ConfigSource]] which provided the candidate value. | ||||||
|  |     */ | ||||||
|  |   case class CannotParseValue( | ||||||
|  |     name: ConfigName, | ||||||
|  |     candidate: String, | ||||||
|  |     source: ConfigSource | ||||||
|  |   ) extends ConfigError | ||||||
|  | 
 | ||||||
|  | end ConfigError | ||||||
							
								
								
									
										41
									
								
								src/main/scala/gs/config/ConfigKey.scala
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								src/main/scala/gs/config/ConfigKey.scala
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,41 @@ | ||||||
|  | package gs.config | ||||||
|  | 
 | ||||||
|  | /** Defines some piece of configuration. | ||||||
|  |   * | ||||||
|  |   * See: | ||||||
|  |   * | ||||||
|  |   *   - [[ConfigKey.Required]] | ||||||
|  |   *   - [[ConfigKey.WithDefaultValue]] | ||||||
|  |   * | ||||||
|  |   * @tparam A | ||||||
|  |   *   The type of data referenced by this key. This type must be | ||||||
|  |   *   [[Configurable]]. | ||||||
|  |   */ | ||||||
|  | sealed trait ConfigKey[A: Configurable]: | ||||||
|  |   def name: ConfigName | ||||||
|  | 
 | ||||||
|  | object ConfigKey: | ||||||
|  | 
 | ||||||
|  |   /** Defines a piece of configuration that is required and does not have any | ||||||
|  |     * default value. If the value referenced by the name cannot be found, an | ||||||
|  |     * [[ConfigError.MissingValue]] is returned. | ||||||
|  |     * | ||||||
|  |     * @param name | ||||||
|  |     *   The name of this configuration. | ||||||
|  |     */ | ||||||
|  |   case class Required[A: Configurable]( | ||||||
|  |     name: ConfigName | ||||||
|  |   ) extends ConfigKey[A] | ||||||
|  | 
 | ||||||
|  |   /** Defines a piece of configuration that has a default value. If the value | ||||||
|  |     * referenced by the name cannot be found, the default is used. | ||||||
|  |     * | ||||||
|  |     * @param name | ||||||
|  |     *   The name of this piece of configuration. | ||||||
|  |     * @param defaultValue | ||||||
|  |     *   The default value for this configuration. | ||||||
|  |     */ | ||||||
|  |   case class WithDefaultValue[A: Configurable]( | ||||||
|  |     name: ConfigName, | ||||||
|  |     defaultValue: A | ||||||
|  |   ) extends ConfigKey[A] | ||||||
							
								
								
									
										66
									
								
								src/main/scala/gs/config/ConfigName.scala
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								src/main/scala/gs/config/ConfigName.scala
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,66 @@ | ||||||
|  | package gs.config | ||||||
|  | 
 | ||||||
|  | /** Uniquely names some piece of configuration. This structure does _not_ | ||||||
|  |   * attempt to support every possible use case, but supports some common cases | ||||||
|  |   * for users that follow some basic rules. Please review conversion functions | ||||||
|  |   * to review the rules for each supported conversion. | ||||||
|  |   * | ||||||
|  |   * ## Recommended Naming Convention | ||||||
|  |   * | ||||||
|  |   * Use either property form (`foo.bar.baz-qwop`) or environment variable form | ||||||
|  |   * (`FOO_BAR_BAZ_QWOP`). Do not use dashes (`-`) in properties if you need to | ||||||
|  |   * convert bidirectionally. | ||||||
|  |   * | ||||||
|  |   * ## Supported Conversions | ||||||
|  |   * | ||||||
|  |   *   - `toRawString` | ||||||
|  |   *   - `toEnvironmentVariable` | ||||||
|  |   *   - `toProperty` | ||||||
|  |   */ | ||||||
|  | opaque type ConfigName = String | ||||||
|  | 
 | ||||||
|  | object ConfigName: | ||||||
|  | 
 | ||||||
|  |   /** Instantiate a new `ConfigName`. This function trims all leading and | ||||||
|  |     * trailing whitespace. | ||||||
|  |     * | ||||||
|  |     * @param name | ||||||
|  |     *   The raw string value of the name. | ||||||
|  |     * @return | ||||||
|  |     *   New `ConfigName`. | ||||||
|  |     */ | ||||||
|  |   def apply(name: String): ConfigName = name.trim() | ||||||
|  | 
 | ||||||
|  |   given CanEqual[ConfigName, ConfigName] = CanEqual.derived | ||||||
|  | 
 | ||||||
|  |   extension (name: ConfigName) | ||||||
|  |     /** Extract the unmodified string that backs this name. | ||||||
|  |       * | ||||||
|  |       * @return | ||||||
|  |       *   The underlying string representation of the name. | ||||||
|  |       */ | ||||||
|  |     def toRawString(): String = name | ||||||
|  | 
 | ||||||
|  |     /** Express this name as an environment variable. | ||||||
|  |       * | ||||||
|  |       *   - Replaces all alphanumeric characters with `_`. | ||||||
|  |       *   - Converts all characters to upper case. | ||||||
|  |       * | ||||||
|  |       * @return | ||||||
|  |       *   The environment variable form of this name. | ||||||
|  |       */ | ||||||
|  |     def toEnvironmentVariable(): String = | ||||||
|  |       name.replaceAll("[^0-9a-zA-Z_]", "_").toUpperCase() | ||||||
|  | 
 | ||||||
|  |     /** Express this name as a property. | ||||||
|  |       * | ||||||
|  |       *   - Replaces all underscore characters with `.`. | ||||||
|  |       *   - Converts all characters to lower case. | ||||||
|  |       * | ||||||
|  |       * @return | ||||||
|  |       *   The property form of this name. | ||||||
|  |       */ | ||||||
|  |     def toProperty(): String = | ||||||
|  |       name.replaceAll("_", ".").toLowerCase() | ||||||
|  | 
 | ||||||
|  | end ConfigName | ||||||
							
								
								
									
										46
									
								
								src/main/scala/gs/config/Configurable.scala
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								src/main/scala/gs/config/Configurable.scala
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,46 @@ | ||||||
|  | package gs.config | ||||||
|  | 
 | ||||||
|  | import java.time.Instant | ||||||
|  | import java.time.LocalDate | ||||||
|  | import scala.util.Try | ||||||
|  | 
 | ||||||
|  | /** Type class for types that can be parsed from raw string configuration. | ||||||
|  |   */ | ||||||
|  | trait Configurable[A]: | ||||||
|  |   /** Parse some raw string value as the desired type. | ||||||
|  |     * | ||||||
|  |     * @param raw | ||||||
|  |     *   The raw value to parse. | ||||||
|  |     * @return | ||||||
|  |     *   The parsed value, or `None` if parsing failed. | ||||||
|  |     */ | ||||||
|  |   def parse(raw: String): Option[A] | ||||||
|  | 
 | ||||||
|  | object Configurable: | ||||||
|  | 
 | ||||||
|  |   def apply[A]( | ||||||
|  |     using | ||||||
|  |     C: Configurable[A] | ||||||
|  |   ): Configurable[A] = C | ||||||
|  | 
 | ||||||
|  |   given Configurable[String] with | ||||||
|  |     def parse(raw: String): Option[String] = Some(raw) | ||||||
|  | 
 | ||||||
|  |   given Configurable[Int] with | ||||||
|  |     def parse(raw: String): Option[Int] = Try(raw.toInt).toOption | ||||||
|  | 
 | ||||||
|  |   given Configurable[Long] with | ||||||
|  |     def parse(raw: String): Option[Long] = Try(raw.toLong).toOption | ||||||
|  | 
 | ||||||
|  |   given Configurable[Boolean] with | ||||||
|  |     def parse(raw: String): Option[Boolean] = Try(raw.toBoolean).toOption | ||||||
|  | 
 | ||||||
|  |   given Configurable[LocalDate] with | ||||||
|  | 
 | ||||||
|  |     def parse(raw: String): Option[LocalDate] = | ||||||
|  |       Try(LocalDate.parse(raw)).toOption | ||||||
|  | 
 | ||||||
|  |   given Configurable[Instant] with | ||||||
|  | 
 | ||||||
|  |     def parse(raw: String): Option[Instant] = | ||||||
|  |       Try(Instant.parse(raw)).toOption | ||||||
|  | @ -1,3 +1,24 @@ | ||||||
| package gs.config | package gs.config | ||||||
| 
 | 
 | ||||||
| trait Configuration | import gs.config.audit.ConfigSource | ||||||
|  | 
 | ||||||
|  | /** Interface for loading configuration values. | ||||||
|  |   * | ||||||
|  |   * This interface is **not** intended to be used with sensitive information. Do | ||||||
|  |   * not use this interface for loading passwords, encryption keys, or any other | ||||||
|  |   * sensitive information. | ||||||
|  |   */ | ||||||
|  | trait Configuration[F[_]]: | ||||||
|  |   /** Retrieve the value for the specified key. | ||||||
|  |     * | ||||||
|  |     * @param key | ||||||
|  |     *   The key which defines the piece of configuration. | ||||||
|  |     * @return | ||||||
|  |     *   The value, or an error if no value can be retrieved. | ||||||
|  |     */ | ||||||
|  |   def getValue[A: Configurable](key: ConfigKey[A]): F[Either[ConfigError, A]] | ||||||
|  | 
 | ||||||
|  |   /** @return | ||||||
|  |     *   The backing source for this configuration. | ||||||
|  |     */ | ||||||
|  |   def source: ConfigSource | ||||||
|  |  | ||||||
							
								
								
									
										55
									
								
								src/main/scala/gs/config/audit/ConfigManifest.scala
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								src/main/scala/gs/config/audit/ConfigManifest.scala
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,55 @@ | ||||||
|  | package gs.config.audit | ||||||
|  | 
 | ||||||
|  | import cats.effect.Ref | ||||||
|  | import cats.effect.Sync | ||||||
|  | import gs.config.ConfigName | ||||||
|  | 
 | ||||||
|  | trait ConfigManifest[F[_]]: | ||||||
|  |   /** Retrieve a snapshot of the current state of this configuration manifest. | ||||||
|  |     * This state tracks all configuration names that the caller attempted to | ||||||
|  |     * access, along with a record of whether each attempt succeeded or failed. | ||||||
|  |     * | ||||||
|  |     * @return | ||||||
|  |     *   The current state of this manifest. | ||||||
|  |     */ | ||||||
|  |   def snapshot(): F[Map[ConfigName, List[ConfigQuery]]] | ||||||
|  | 
 | ||||||
|  |   /** Record a query for some [[ConfigName]] in this manifest. | ||||||
|  |     * | ||||||
|  |     * @param name | ||||||
|  |     *   The [[ConfigName]] that was queried. | ||||||
|  |     * @param query | ||||||
|  |     *   The [[ConfigQuery]] describing the result. | ||||||
|  |     * @return | ||||||
|  |     *   Side-effect indicating that the query was recorded. | ||||||
|  |     */ | ||||||
|  |   def record( | ||||||
|  |     name: ConfigName, | ||||||
|  |     query: ConfigQuery | ||||||
|  |   ): F[Unit] | ||||||
|  | 
 | ||||||
|  | object ConfigManifest: | ||||||
|  | 
 | ||||||
|  |   final class Standard[F[_]: Sync] private ( | ||||||
|  |     private val manifest: Ref[F, Map[ConfigName, List[ConfigQuery]]] | ||||||
|  |   ) extends ConfigManifest[F]: | ||||||
|  | 
 | ||||||
|  |     override def snapshot(): F[Map[ConfigName, List[ConfigQuery]]] = | ||||||
|  |       manifest.get | ||||||
|  | 
 | ||||||
|  |     override def record( | ||||||
|  |       name: ConfigName, | ||||||
|  |       query: ConfigQuery | ||||||
|  |     ): F[Unit] = | ||||||
|  |       manifest.update(addQueryToName(name, query, _)) | ||||||
|  | 
 | ||||||
|  |     private def addQueryToName( | ||||||
|  |       name: ConfigName, | ||||||
|  |       query: ConfigQuery, | ||||||
|  |       state: Map[ConfigName, List[ConfigQuery]] | ||||||
|  |     ): Map[ConfigName, List[ConfigQuery]] = | ||||||
|  |       state.get(name) match | ||||||
|  |         case Some(queries) => state.updated(name, queries ++ List(query)) | ||||||
|  |         case None          => state + (name -> List(query)) | ||||||
|  | 
 | ||||||
|  | end ConfigManifest | ||||||
							
								
								
									
										37
									
								
								src/main/scala/gs/config/audit/ConfigQuery.scala
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								src/main/scala/gs/config/audit/ConfigQuery.scala
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,37 @@ | ||||||
|  | package gs.config.audit | ||||||
|  | 
 | ||||||
|  | import gs.config.ConfigError | ||||||
|  | 
 | ||||||
|  | /** Describes queries used to find configuration. Used for auditing purposes and | ||||||
|  |   * is captured by [[ConfigManifest]]. | ||||||
|  |   */ | ||||||
|  | sealed trait ConfigQuery | ||||||
|  | 
 | ||||||
|  | object ConfigQuery: | ||||||
|  | 
 | ||||||
|  |   /** Represents a query for some configuration that completed successfully. | ||||||
|  |     * | ||||||
|  |     * @param source | ||||||
|  |     *   The source which provided the value. | ||||||
|  |     * @param rawValue | ||||||
|  |     *   The raw value that the source returned. | ||||||
|  |     */ | ||||||
|  |   case class SuccessfulQuery( | ||||||
|  |     source: ConfigSource, | ||||||
|  |     rawValue: String | ||||||
|  |   ) extends ConfigQuery | ||||||
|  | 
 | ||||||
|  |   /** Represents a query for some configuration that failed. | ||||||
|  |     * | ||||||
|  |     * @param sources | ||||||
|  |     *   List of all sources, in order, that were consulted to attempt to get | ||||||
|  |     *   this value. | ||||||
|  |     * @param error | ||||||
|  |     *   The reason why this query failed. | ||||||
|  |     */ | ||||||
|  |   case class FailedQuery( | ||||||
|  |     sources: List[ConfigSource], | ||||||
|  |     error: ConfigError | ||||||
|  |   ) | ||||||
|  | 
 | ||||||
|  | end ConfigQuery | ||||||
							
								
								
									
										26
									
								
								src/main/scala/gs/config/audit/ConfigSource.scala
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								src/main/scala/gs/config/audit/ConfigSource.scala
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,26 @@ | ||||||
|  | package gs.config.audit | ||||||
|  | 
 | ||||||
|  | /** Represents some _source_ of configuration data. This might be the system | ||||||
|  |   * environment, a properties file, application runtime properties, or some | ||||||
|  |   * other source. | ||||||
|  |   * | ||||||
|  |   * This type is used for auditing purposes. Each [[gs.config.Configuration]] | ||||||
|  |   * has a source, and the source which retrieves (or fails to retrieve) some | ||||||
|  |   * value is recorded in the [[ConfigManifest]]. | ||||||
|  |   */ | ||||||
|  | opaque type ConfigSource = String | ||||||
|  | 
 | ||||||
|  | object ConfigSource: | ||||||
|  | 
 | ||||||
|  |   /** Instantiate a new `ConfigSource`. | ||||||
|  |     * | ||||||
|  |     * @param source | ||||||
|  |     *   The name of the source. | ||||||
|  |     * @return | ||||||
|  |     *   The new instance. | ||||||
|  |     */ | ||||||
|  |   def apply(source: String): ConfigSource = source | ||||||
|  | 
 | ||||||
|  |   given CanEqual[ConfigSource, ConfigSource] = CanEqual.derived | ||||||
|  | 
 | ||||||
|  | end ConfigSource | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue