{"id":20664507,"url":"https://github.com/outr/profig","last_synced_at":"2025-04-19T16:24:57.200Z","repository":{"id":22431547,"uuid":"96230729","full_name":"outr/profig","owner":"outr","description":"Powerful configuration management for Scala (JSON, properties, command-line arguments, and environment variables)","archived":false,"fork":false,"pushed_at":"2024-09-06T19:23:04.000Z","size":427,"stargazers_count":28,"open_issues_count":1,"forks_count":2,"subscribers_count":3,"default_branch":"master","last_synced_at":"2024-09-07T22:03:08.961Z","etag":null,"topics":["command-line","config","configuration","json","properties","scala","scalajs"],"latest_commit_sha":null,"homepage":null,"language":"Scala","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/outr.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-07-04T15:15:08.000Z","updated_at":"2024-09-06T19:23:07.000Z","dependencies_parsed_at":"2024-05-05T02:23:32.092Z","dependency_job_id":"f14c36c2-794d-41d4-ab37-624238d14201","html_url":"https://github.com/outr/profig","commit_stats":null,"previous_names":[],"tags_count":60,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/outr%2Fprofig","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/outr%2Fprofig/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/outr%2Fprofig/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/outr%2Fprofig/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/outr","download_url":"https://codeload.github.com/outr/profig/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":224959990,"owners_count":17398790,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["command-line","config","configuration","json","properties","scala","scalajs"],"created_at":"2024-11-16T19:24:42.479Z","updated_at":"2025-04-19T16:24:57.193Z","avatar_url":"https://github.com/outr.png","language":"Scala","funding_links":[],"categories":[],"sub_categories":[],"readme":"# profig\n\n[![CI](https://github.com/outr/profig/actions/workflows/ci.yml/badge.svg)](https://github.com/outr/profig/actions/workflows/ci.yml)\n[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/outr/profig)\n[![Maven Central](https://maven-badges.herokuapp.com/maven-central/com.outr/profig_2.13/badge.svg)](https://maven-badges.herokuapp.com/maven-central/com.outr/profig_2.12)\n[![Latest version](https://index.scala-lang.org/outr/profig/profig/latest.svg)](https://index.scala-lang.org/outr/profig)\n\nPowerful configuration management for Scala (JSON, properties, command-line arguments, and environment variables)\n\n# Latest version\n3.4.18\n\n# Justification\n\nIn any case where there are existing libraries that accomplish a task it is worthwhile to document the justification for\ncreating yet another library. This is beneficial both for users to understand how it is differentiated and for the\ndevelopers to clarify if there is valid purpose in the endeavor.\n\nIn the Scala configuration arena the most popular offering is that of Typesafe Config (https://github.com/typesafehub/config).\nWhile this is a powerful and useful library it is more complicated to work with and less flexible than we'd like. One of\nthe very specific problems with it is the lack of support for Scala.js, but the larger issue is the distinction that\narises from considering configuration coming from files vs environment variables vs command-line arguments vs any other\norigin of configuration that any modern application may want to utilize.\n\n# Features\n\nOur goal is primarily simplicity. A configuration library should do the necessary work and get out of the way of the\ndeveloper and let them get their job done. To this end we support a unified configuration merging command-line arguments,\nenvironment variables, system properties, and configuration files to provide maximum flexibility of defining, defaulting,\nand overriding configuration in your application.\n\n# File Formats\n\n* JSON\n* Properties\n* YAML\n* HOCON\n* XML\n\n# Setup\n\n## SBT Configuration\n\nProfig is published to Sonatype OSS and synchronized to Maven Central supporting JVM and Scala.js on 2.11, 2.12, 2.13, and Scala 3.x:\n\n```\nlibraryDependencies += \"com.outr\" %% \"profig\" % \"3.4.18\"   // Scala\nlibraryDependencies += \"com.outr\" %%% \"profig\" % \"3.4.18\"  // Scala.js / Cross-Build\n```\n\n## Getting Started\n\nWhether you are using this in JVM or JS you need one import to access everything:\n\n```scala\nimport profig._\n```\n\nThis brings some implicits on specific platforms (for example, loading URLs, Files, Sources, etc. in the JVM) but the\nonly class you really need be concerned with is `Profig`.\n\n### Initializing\n\nAs of version 3.0, you now need to initialize Profig in order to fully utilize it:\n\n```scala\nProfig.init()\n```\n\n### Simple Usage\n\nWhile Profig has a lot of very powerful features, the most useful feature is its ability to provide multiple levels of\nconfiguration. Instead of locking yourself to only file configuration, environment variables, or command-line arguments,\nProfig allows you hierarchical overrides to be able to specify configuration at any level.\n\nConfiguration is loaded level-by-level with configuration at the lower-level overriding that at a higher level:\n- File Configuration\n- Environment Variables\n- Command-Line arguments\n\nFor example:\nIf the application is executed with a `config.json` of:\n```json\n{\n  \"server\": {\n    \"port\": 8888\n  }\n}\n```\n```scala\nProfig(\"server.port\").as[Int]\n// res2: Int = 8888\n```\nHowever, if there were an environment variable `SERVER_PORT=8889`:\n```scala\nProfig(\"server.port\").as[Int]\n// res4: Int = 8889\n```\nFinally, if a command-line property were set, for example:\n```\nrunCommand -server.port 8890\n```\n```scala\nProfig(\"server.port\").as[Int]\n// res6: Int = 8890\n```\nSo, to summarize, command-line arguments take the highest priority, followed by environment variables, and finally\nconfiguration files.\n\nThe easiest way (explained in greater detail below) to properly initialize Profig:\n```scala\nProfig.initConfiguration()  // Loads everything except the command-line arguments\nProfig.merge(args)          // This can be a `List[String]` or `Array[String]` depending on your application\n```\n\n### Loading Command-Line arguments\n\nWhen your application starts it is reasonable to want to allow execution of the application to override existing\nconfiguration via the command-line. In order to effectively do this we can simply invoke `Profig.merge(args)` within our\nmain method. This will merge all command-line arguments into Profig.\n\nNote that the signature of `merge` is `def merge(json: Json, ``type``: MergeType = MergeType.Overwrite): Unit`. If you\nset the type to `MergeType.Add`, existing configuration will not be overwritten. This is useful for default configuration\nloading.\n\n### Loading Files\n\nProfig supports many configuration formats and can look in the classpath as well as the filesystem to find configuration\nto load. Of course, this is only supported on the JVM, but to load a file simply call:\n\n```scala\nProfig.loadFile(new java.io.File(\"config.json\"))\n```\n\nThis will look for `config.json` on the filesystem, load it as JSON, and merge it into the configuration. The signature\nof `loadFile` is: `Profig.loadFile(file: File, mergeType: MergeType = MergeType.Overwrite, errorHandler: Option[Throwable =\u003e Unit] = None)`\n\nHowever, if your application doesn't need very explicit files to be loaded you can load defaults instead:\n\n```scala\nProfig.loadConfiguration()\n```\n\nThis will look for any standardized configuration file in the classpath and filesystem and load it into the system.\n\nYou can also use `Profig.initConfiguration()` to initialize and load configuration in a single call.\n\nFinally, you can use `Profig.initConfigurationBlocking()` if you want initialization and loading to block before continuing with your application.\n\n### Accessing values\n\nAs stated above, system properties and environment variables are automatically loaded into the configuration. So if we\nwanted to access the system property \"java.version\" we can easily do so:\n\n```scala\nval javaVersion = Profig(\"java.version\").as[String]\n// javaVersion: String = \"23.0.1\"\n```\n\nYou can also load from a higher level as a case class to get more information. For example:\n\n```scala\nimport fabric.rw._\n\ncase class JVMInfo(version: String, specification: Specification)\n\nobject JVMInfo {\n  implicit val rw: RW[JVMInfo] = RW.gen\n}\n\ncase class Specification(vendor: String, name: String, version: String)\n\nobject Specification {\n  implicit val rw: RW[Specification] = RW.gen\n}\n\nval info = Profig(\"java\").as[JVMInfo]\n// info: JVMInfo = JVMInfo(\n//   version = \"23.0.1\",\n//   specification = Specification(\n//     vendor = \"Oracle Corporation\",\n//     name = \"Java Platform API Specification\",\n//     version = \"23\"\n//   )\n// )\n```\n\nConfiguration files will automatically be loaded from config.json, config.conf, configuration.json, configuration.conf,\napplication.conf, and application.json if found in the application path or in the classpath.\n\nIf default values or `Option` values are defined in the case class they will be used if the value is not available in\nthe config. However, if any required parameters are missing an exception will be thrown when attempting to read.\n\n### Storing values\n\nAdding values at runtime is almost exactly the same as reading values. For example, if we want to store a basic\nconfiguration:\n\n```scala\nimport fabric._\n\ncase class MyConfig(path: String = \"/my/application\",\n                    timeout: Long = 1000L,\n                    username: String = \"root\",\n                    password: String = \"password\")\n                    \nobject MyConfig {\n  implicit val rw: RW[MyConfig] = RW.gen\n}\n\nval json: Json = MyConfig(path = \"/another/path\").json\n// json: Json = {\"path\": \"/another/path\", \"timeout\": 1000, \"username\": \"root\", \"password\": \"password\"}\nProfig.merge(json)\n```\n\nIf you prefer to merge in an object without overwriting existing values you can use `defaults` instead of `merge`:\n\n```scala\nval myConfig: Json = MyConfig(path = \"/another/path\").json\n// myConfig: Json = {\"path\": \"/another/path\", \"timeout\": 1000, \"username\": \"root\", \"password\": \"password\"}\nProfig.merge(json, MergeType.Add)\n```\n\n### Next steps\n\nThis only scratches the surface of the features and functionality Profig provides. For additional information read the\nScalaDocs and the specs: https://github.com/outr/profig/blob/master/core/shared/src/test/scala/spec/ProfigSpec.scala","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foutr%2Fprofig","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Foutr%2Fprofig","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Foutr%2Fprofig/lists"}