Current section
Files
Jump to
Current section
Files
src/dream_config@loader.erl
-module(dream_config@loader).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch, inline]).
-define(FILEPATH, "src/dream_config/loader.gleam").
-export([load_dotenv/0, load_dotenv_from/1, get_required/1, get/1, get_int/1, get_required_int/1, get_bool/1]).
-if(?OTP_RELEASE >= 27).
-define(MODULEDOC(Str), -moduledoc(Str)).
-define(DOC(Str), -doc(Str)).
-else.
-define(MODULEDOC(Str), -compile([])).
-define(DOC(Str), -compile([])).
-endif.
?MODULEDOC(
" Configuration loading from environment variables and .env files\n"
"\n"
" This module provides a clean interface for loading configuration from\n"
" environment variables and `.env` files. It handles common patterns like\n"
" required vs optional values, type conversion, and boolean parsing.\n"
"\n"
" ## Quick Start\n"
"\n"
" ```gleam\n"
" import dream_config/loader as config\n"
"\n"
" // Load .env file (if present)\n"
" config.load_dotenv()\n"
"\n"
" // Get configuration values\n"
" let assert Ok(db_url) = config.get_required(\"DATABASE_URL\")\n"
" let assert Ok(port) = config.get_required_int(\"PORT\")\n"
" let debug_mode = config.get_bool(\"DEBUG\")\n"
" ```\n"
"\n"
" ## Loading .env Files\n"
"\n"
" Call `load_dotenv()` at application startup to load variables from a `.env`\n"
" file in your project root. This is useful for local development.\n"
"\n"
" For production, set environment variables directly (via systemd, Docker, etc.)\n"
" and skip `.env` loading.\n"
"\n"
" ## Type Safety\n"
"\n"
" All functions return `Result` types, forcing you to handle missing or invalid\n"
" values. Use `get_required*` functions for values that must be present, and\n"
" `get*` functions for optional values.\n"
).
-file("src/dream_config/loader.gleam", 60).
?DOC(
" Load `.env` file from the default location\n"
"\n"
" Looks for a `.env` file in the current working directory and loads all\n"
" variables into the environment. This is typically called at application\n"
" startup.\n"
"\n"
" Returns `Ok(Nil)` if:\n"
" - The file doesn't exist (no error - environment variables may be set directly)\n"
" - The file exists and loads successfully\n"
"\n"
" Returns `Error(String)` only if the file exists but has an invalid format.\n"
"\n"
" ## Example\n"
"\n"
" ```gleam\n"
" import dream_config/loader as config\n"
"\n"
" // At application startup\n"
" config.load_dotenv()\n"
" ```\n"
).
-spec load_dotenv() -> {ok, nil} | {error, binary()}.
load_dotenv() ->
_ = dot_env:load_default(),
{ok, nil}.
-file("src/dream_config/loader.gleam", 86).
?DOC(
" Load `.env` file from a specific path\n"
"\n"
" Loads environment variables from a `.env` file at the specified path.\n"
" Useful when your `.env` file is in a non-standard location.\n"
"\n"
" ## Parameters\n"
"\n"
" - `path`: The file path to the `.env` file\n"
"\n"
" ## Returns\n"
"\n"
" - `Ok(Nil)`: File loaded successfully or doesn't exist\n"
" - `Error(String)`: File exists but has invalid format\n"
"\n"
" ## Example\n"
"\n"
" ```gleam\n"
" import dream_config/loader as config\n"
"\n"
" config.load_dotenv_from(\"/etc/myapp/.env\")\n"
" ```\n"
).
-spec load_dotenv_from(binary()) -> {ok, nil} | {error, binary()}.
load_dotenv_from(Path) ->
Opts = dot_env:new_with_path(Path),
_ = dot_env:load(Opts),
{ok, nil}.
-file("src/dream_config/loader.gleam", 117).
?DOC(
" Get a required environment variable\n"
"\n"
" Returns the value of the environment variable if it exists, or an error\n"
" if it's not set. Use this for configuration values that your application\n"
" cannot run without.\n"
"\n"
" ## Parameters\n"
"\n"
" - `name`: The name of the environment variable\n"
"\n"
" ## Returns\n"
"\n"
" - `Ok(String)`: The variable value\n"
" - `Error(String)`: The variable is not set (includes variable name in message)\n"
"\n"
" ## Example\n"
"\n"
" ```gleam\n"
" import dream_config/loader as config\n"
"\n"
" case config.get_required(\"DATABASE_URL\") {\n"
" Ok(url) -> start_database(url)\n"
" Error(msg) -> panic as msg\n"
" }\n"
" ```\n"
).
-spec get_required(binary()) -> {ok, binary()} | {error, binary()}.
get_required(Name) ->
case envoy_ffi:get(Name) of
{ok, Value} ->
{ok, Value};
{error, _} ->
{error,
<<"Required environment variable not set: "/utf8, Name/binary>>}
end.
-file("src/dream_config/loader.gleam", 150).
?DOC(
" Get an optional environment variable\n"
"\n"
" Returns the value if the variable is set, or `Error(Nil)` if it's not.\n"
" Use this for configuration values that have sensible defaults or are\n"
" truly optional.\n"
"\n"
" ## Parameters\n"
"\n"
" - `name`: The name of the environment variable\n"
"\n"
" ## Returns\n"
"\n"
" - `Ok(String)`: The variable value\n"
" - `Error(Nil)`: The variable is not set\n"
"\n"
" ## Example\n"
"\n"
" ```gleam\n"
" import dream_config/loader as config\n"
" import gleam/option\n"
"\n"
" let api_key = case config.get(\"API_KEY\") {\n"
" Ok(key) -> option.Some(key)\n"
" Error(_) -> option.None\n"
" }\n"
" ```\n"
).
-spec get(binary()) -> {ok, binary()} | {error, nil}.
get(Name) ->
envoy_ffi:get(Name).
-file("src/dream_config/loader.gleam", 178).
?DOC(
" Get an environment variable as an integer\n"
"\n"
" Attempts to parse the environment variable as an integer. Returns an error\n"
" if the variable is not set or cannot be parsed as an integer.\n"
"\n"
" ## Parameters\n"
"\n"
" - `name`: The name of the environment variable\n"
"\n"
" ## Returns\n"
"\n"
" - `Ok(Int)`: The parsed integer value\n"
" - `Error(Nil)`: Variable not set or not a valid integer\n"
"\n"
" ## Example\n"
"\n"
" ```gleam\n"
" import dream_config/loader as config\n"
"\n"
" case config.get_int(\"PORT\") {\n"
" Ok(port) -> start_server(port)\n"
" Error(_) -> start_server(3000) // Default port\n"
" }\n"
" ```\n"
).
-spec get_int(binary()) -> {ok, integer()} | {error, nil}.
get_int(Name) ->
case envoy_ffi:get(Name) of
{ok, Value} ->
_pipe = gleam_stdlib:parse_int(Value),
gleam@result:replace_error(_pipe, nil);
{error, _} ->
{error, nil}
end.
-file("src/dream_config/loader.gleam", 207).
?DOC(
" Get a required environment variable as an integer\n"
"\n"
" Returns the parsed integer value if the variable is set and valid, or an\n"
" error if it's missing or cannot be parsed. Use this for required numeric\n"
" configuration like port numbers or timeouts.\n"
"\n"
" ## Parameters\n"
"\n"
" - `name`: The name of the environment variable\n"
"\n"
" ## Returns\n"
"\n"
" - `Ok(Int)`: The parsed integer value\n"
" - `Error(String)`: Variable not set or not a valid integer (includes helpful message)\n"
"\n"
" ## Example\n"
"\n"
" ```gleam\n"
" import dream_config/loader as config\n"
"\n"
" let assert Ok(port) = config.get_required_int(\"PORT\")\n"
" ```\n"
).
-spec get_required_int(binary()) -> {ok, integer()} | {error, binary()}.
get_required_int(Name) ->
gleam@result:'try'(
get_required(Name),
fun(Value) -> _pipe = gleam_stdlib:parse_int(Value),
gleam@result:replace_error(
_pipe,
<<<<"Environment variable "/utf8, Name/binary>>/binary,
" must be an integer"/utf8>>
) end
).
-file("src/dream_config/loader.gleam", 245).
?DOC(
" Get an environment variable as a boolean\n"
"\n"
" Parses the environment variable as a boolean. The following values are\n"
" treated as `True` (case-insensitive):\n"
" - `\"true\"`\n"
" - `\"1\"`\n"
" - `\"yes\"`\n"
"\n"
" All other values (including unset variables) are treated as `False`.\n"
"\n"
" ## Parameters\n"
"\n"
" - `name`: The name of the environment variable\n"
"\n"
" ## Returns\n"
"\n"
" - `True`: Variable is set to a truthy value\n"
" - `False`: Variable is not set or set to a falsy value\n"
"\n"
" ## Example\n"
"\n"
" ```gleam\n"
" import dream_config/loader as config\n"
"\n"
" let debug_mode = config.get_bool(\"DEBUG\")\n"
" if debug_mode {\n"
" enable_debug_logging()\n"
" }\n"
" ```\n"
).
-spec get_bool(binary()) -> boolean().
get_bool(Name) ->
case envoy_ffi:get(Name) of
{ok, <<"true"/utf8>>} ->
true;
{ok, <<"1"/utf8>>} ->
true;
{ok, <<"yes"/utf8>>} ->
true;
{ok, <<"YES"/utf8>>} ->
true;
{ok, <<"True"/utf8>>} ->
true;
{ok, <<"TRUE"/utf8>>} ->
true;
_ ->
false
end.