{"id":13808767,"url":"https://github.com/emadalam/mahaul","last_synced_at":"2025-07-24T00:38:14.855Z","repository":{"id":65747416,"uuid":"598782197","full_name":"emadalam/mahaul","owner":"emadalam","description":"Supercharge your environment variables in Elixir. Parse and validate with compile time access guarantees, defaults, fallbacks and app pre-boot validations.","archived":false,"fork":false,"pushed_at":"2023-12-18T15:08:00.000Z","size":425,"stargazers_count":22,"open_issues_count":5,"forks_count":2,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-07-12T16:05:33.582Z","etag":null,"topics":["elixir","elixir-library","environment-variables"],"latest_commit_sha":null,"homepage":"https://hex.pm/packages/mahaul","language":"Elixir","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/emadalam.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null}},"created_at":"2023-02-07T19:53:28.000Z","updated_at":"2024-10-30T01:48:56.000Z","dependencies_parsed_at":"2024-01-05T21:54:18.689Z","dependency_job_id":"af5e1d43-c74a-479c-b6b3-2d204579225b","html_url":"https://github.com/emadalam/mahaul","commit_stats":{"total_commits":21,"total_committers":1,"mean_commits":21.0,"dds":0.0,"last_synced_commit":"d3920d7017562e981533aee92d4802cf9d601654"},"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/emadalam/mahaul","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emadalam%2Fmahaul","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emadalam%2Fmahaul/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emadalam%2Fmahaul/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emadalam%2Fmahaul/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/emadalam","download_url":"https://codeload.github.com/emadalam/mahaul/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/emadalam%2Fmahaul/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266774802,"owners_count":23982247,"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","status":"online","status_checked_at":"2025-07-23T02:00:09.312Z","response_time":66,"last_error":null,"robots_txt_status":null,"robots_txt_updated_at":null,"robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["elixir","elixir-library","environment-variables"],"created_at":"2024-08-04T01:01:51.396Z","updated_at":"2025-07-24T00:38:14.831Z","avatar_url":"https://github.com/emadalam.png","language":"Elixir","funding_links":[],"categories":["Configuration"],"sub_categories":[],"readme":"# Mahaul\n\n[![hex.pm](https://img.shields.io/hexpm/v/mahaul.svg)](https://hex.pm/packages/mahaul)\n[![hex.pm](https://img.shields.io/hexpm/l/mahaul.svg)](https://hex.pm/packages/mahaul)\n[![Coverage Status](https://coveralls.io/repos/github/emadalam/mahaul/badge.svg?branch=main)](https://coveralls.io/github/emadalam/mahaul?branch=main)\n\n\nParse and validate your environment variables easily in Elixir with the following benefits.\n\n* Compile time access guarantees\n* Parsed values with accurate elixir data types\n* Validation of required values before app boot\n* `mix` environment specific defaults and fallbacks\n* Code autocompletion (if using elixir language server)\n\n![Screenshot](assets/images/autocomplete.png)\n\n[Read more](#why-this-package) for understanding why to use this package and its benefits. The complete documentation for `mahaul` is [available online at HexDocs](https://hexdocs.pm/mahaul).\n\n## Requirements\n\nElixir 1.13+\n\n## Installation\n\n- Add `mahaul` to your list of dependencies in `mix.exs`:\n\n```elixir\ndef deps do\n  [\n    {:mahaul, \"~\u003e 0.6.0\"}\n  ]\nend\n```\n\n- Run `mix deps.get`\n\n- Add config in your `config/config.exs` file\n\n```elixir\nconfig :mahaul, mix_env: Mix.env()\n```\n\n## Getting started\n\n#### Define the environment variables needed in your app\n\n```elixir\ndefmodule MyApp.Env do\n  use Mahaul,\n    DEPLOYMENT_ENV: [\n      type: :enum,\n      defaults: [dev: \"dev\", test: \"dev\"],\n      choices: [:dev, :staging, :live]\n    ],\n    PORT: [type: :port, defaults: [dev: \"4000\"]],\n    DATABASE_URL: [type: :uri, defaults: [dev: \"postgresql://user:pass@localhost:5432/app_dev\"]],\n    ANOTHER_ENV: [type: :host, default: \"//localhost\"]\nend\n```\n\n#### Use in `config/runtime.exs`\n\n```elixir\nimport Config\n\nif config_env() == :dev do\n  MyApp.Env.validate()\n\n  config :my_app, MyApp.Endpoint,\n    http: [port: MyApp.Env.port()]\nend\n\nif config_env() == :prod do\n  MyApp.Env.validate!()\n\n  config :my_app, MyApp.Repo,\n    url: MyApp.Env.database_url()\n\n  config :my_app, :something,\n    another: MyApp.Env.another_env()\n\n  if MyApp.Env.deployment_env() == :staging do\n    # configure something more\n  end\nend\n```\n\n#### Use anywhere in the code\n\n```elixir\ndefmodule MyApp.Magic\n  def do_magic(env \\\\ MyApp.Env.deployment_env())\n  def do_magic(:live), do: \"Magic on live\"\n  def do_magic(:staging), do: \"Magic on staging\"\n  def do_magic(:dev), do: \"Magic on dev\"\nend\n```\n\n## Supported types\n\nThe following type configurations are supported.\n\n| Type    | Elixir Type | Valid Environment variables value                               |\n| :------ | :---------- | :-------------------------------------------------------------- |\n| `:str`  | String      | Any string                                                      |\n| `:enum` | Atom        | Any string                                                      |\n| `:num`  | Float       | Any string that can be parsed as float                          |\n| `:int`  | Integer     | Any string that can be parsed as integer                        |\n| `:bool` | Boolean     | \"true\" and \"1\" as `true`; \"false\" and \"0\" as `false`            |\n| `:port` | Integer     | Any valid port value between \"1\" to \"65535\" (casted as integer) |\n| `:host` | String      | Any valid host name                                             |\n| `:uri`  | String      | Any valid uris                                                  |\n\n\n## Setting Defaults\n\nAny defaults and fallback values can be set globally using the `default` or for any mix environment using the `defaults` configuration options. Make sure to **use the string values** same as we set in the actual system environment, as it will be parsed depending upon the provided `type` configuration.\n\n#### Globally\n\n```elixir\ndefmodule MyApp.Env do\n  use Mahaul,\n    MY_ENV: [type: :str, default: \"Hello World\"]\nend\n```\n\n```\niex -S mix\niex\u003e MyApp.Env.my_env()\nHello World\n\nMY_ENV=\"Hello Universe\" iex -S mix\niex\u003e MyApp.Env.my_env()\nHello Universe\n```\n\n#### For any mix environment\n\n```elixir\ndefmodule MyApp.Env do\n  use Mahaul,\n    MY_ENV: [\n      type: :str,\n      defaults: [prod: \"Hello Prod\", dev: \"Hello Dev\", test: \"Hello Test\", custom: \"Hello Custom\"]\n    ]\nend\n```\n\n```\nMIX_ENV=prod iex -S mix\niex\u003e MyApp.Env.my_env()\nHello Prod\n\nMIX_ENV=dev iex -S mix\niex\u003e MyApp.Env.my_env()\nHello Dev\n\nMIX_ENV=test iex -S mix\niex\u003e MyApp.Env.my_env()\nHello Test\n\nMIX_ENV=custom iex -S mix\niex\u003e MyApp.Env.my_env()\nHello Custom\n\nMIX_ENV=prod MY_ENV=\"Hello World\" iex -S mix\niex\u003e MyApp.Env.my_env()\nHello World\n```\n\n#### For any mix environment with fallback\n\n```elixir\ndefmodule MyApp.Env do\n  use Mahaul,\n    MY_ENV: [\n      type: :str,\n      default: \"Hello World\",\n      defaults: [prod: \"Hello Prod\", dev: \"Hello Dev\", test: \"Hello Test\"]\n    ]\nend\n```\n\n```\nMIX_ENV=prod iex -S mix\niex\u003e MyApp.Env.my_env()\nHello Prod\n\nMIX_ENV=dev iex -S mix\niex\u003e MyApp.Env.my_env()\nHello Dev\n\nMIX_ENV=test iex -S mix\niex\u003e MyApp.Env.my_env()\nHello Test\n\nMIX_ENV=custom iex -S mix\niex\u003e MyApp.Env.my_env()\nHello World\n\nMIX_ENV=custom MY_ENV=\"Hello Universe\" iex -S mix\niex\u003e MyApp.Env.my_env()\nHello Universe\n```\n\n## Setting choices list\n\nYou can further restrict the parsed values to a predefined list by setting the `choices` option with list of allowed values. Note that the values are parsed first and then matched against the provided list.\n\n```elixir\ndefmodule MyApp.Env do\n  use Mahaul,\n    DEPLOYMENT_ENV: [type: :enum, choices: [:dev, :staging, :live]],\n    DAY_OF_WEEK: [type: :int, choices: [1, 2, 3, 4, 5, 6, 7]]\nend\n```\n\n## Setting documentation\n\nThere is a default documentation added for each of the compile time generated function equivalents for the environment variables. However you may use the `doc` option to add a custom documentation with more details and explanations as per your needs.\n\n#### Default\n\n```elixir\ndefmodule MyApp.Env do\n  use Mahaul,\n    PORT: [type: :port, defaults: [dev: \"4000\"]]\nend\n```\n![Documentation-default](assets/images/doc-default.png)\n\n#### Custom\n\n```elixir\ndefmodule MyApp.Env do\n  use Mahaul,\n    PORT: [\n      type: :port,\n      defaults: [dev: \"4000\"],\n      doc: ~s\"\"\"\n      This is an example documentation for the environment variable.\n      We can use all the features from the elixir `@doc` tag that will\n      appear as the function documentation during its usage.\n\n      ## Usage\n\n          Env.port()\n\n      ## Notes\n      These are some notes to keep in mind.\n      \"\"\"\n    ]\nend\n```\n![Documentation-custom](assets/images/doc-custom.png)\n\n## Why this package\n\n`mahaul` accomplishes the following functionalities for streamlining the environment variables requirements for an elixir app.\n\n#### Compile time access guarantees\n\nUsing the meta programming capabilities of Elixir, `mahaul` creates compile time methods for accessing the environment variables. This guarantees that there are no accidental typos during the access of the environment variables from the code. Also as an added bonus, if you are using the [Elixir Language Server](https://github.com/elixir-lsp/elixir-ls) for your development environment, you'd get code autocompletion.\n\n#### Parsed values with accurate data types\n\nDepending upon the configuration, the access to the predefined environment variables string values are parsed and the correct elixir data types are returned. `mahaul` supports [a wide range](#supported-types) of commonly set environment variable types. It also supports the `choices` options to limit the allowed values for an environment variable.\n\n#### Validation of required values before app boot\n\nOften times we release new versions of the app accessing new environment variables, but we forget to set those for one of our app deployments. This creates nasty bugs that are only discovered when certain parts of the app behaves erratically or fails. With `mahaul`, you can pre-validate the existence of the required environment variables with correct values before booting the app (ideally in `config/runtime.exs`). This ensures that your application will fail to boot unless you have set those environment variables with correct values. This works really well with any cloud deployments that makes new version of your app active and available only after ensuring the new deployment had a successful boot.\n\n#### Defaults and fallbacks\n\nYou can [set default values](#setting-defaults) for the production or development environment of your app while configuring `mahaul`. This comes handy when you want some defaults for dev/test environment to let other contributors of your app quickly start the dev environment of your app without worrying to set some needed environment variables. Or have some sensible defaults for production version of your app with flexibility to change the values by setting an environment variable.\n\n## Contributing\n\nContributions are welcome. Please follow the commit guidelines from https://www.conventionalcommits.org.\n\n### Setup\n\nClone the repo and fetch its dependencies:\n\n```sh\ngit clone https://github.com/emadalam/mahaul.git\ncd mahaul\nmix setup\n```\n\n### Running tests\n\n```sh\nmix test\n\n# or with coverage threshold\n# mix coveralls\n```\n\n### Building docs\n\n```sh\nMIX_ENV=docs mix docs\n\n# or view the docs\n# MIX_ENV=docs mix docs --open\n```\n\n## LICENSE\n\nSee [LICENSE](https://github.com/emadalam/mahaul/blob/main/LICENSE.txt)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Femadalam%2Fmahaul","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Femadalam%2Fmahaul","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Femadalam%2Fmahaul/lists"}