Confispex.Schema behaviour (confispex v1.2.0)
Defines the behavior and helpers for creating configuration schemas.
A schema describes all environment variables your application uses, their types, defaults, validation rules, and how they're organized into logical groups.
Basic Usage
defmodule MyApp.RuntimeConfigSchema do
import Confispex.Schema
@behaviour Confispex.Schema
alias Confispex.Type
defvariables(%{
"DATABASE_URL" => %{
cast: Type.URL,
groups: [:database],
required: [:database]
}
})
endVariable Specification
Each variable is defined with a map containing the following options:
Required Options
:cast- type specification for casting the value. Can be:- A module implementing
Confispex.Typebehavior (e.g.,Type.String) - A tuple with module and options (e.g.,
{Type.Integer, scope: :positive})
- A module implementing
:groups- list of group atoms this variable belongs to. Groups are used for:- Organizing variables in reports
- Checking if a feature is properly configured via
all_required_touched?/1 - Conditional configuration based on
any_required_touched?/1
Optional Options
:doc- human-readable description shown in generated.envrctemplate files:default- default value as a string. Used when variable is not present in the store. Cannot be used with:requiredor:default_lazy."PORT" => %{ cast: Type.Integer, default: "4000", groups: [:server] }:default_lazy- function(context -> String.t() | nil)for context-dependent defaults. Receives runtime context (e.g.,%{env: :prod, target: :host}) and returns default value ornilto skip default. Cannot be used with:default."LOG_LEVEL" => %{ cast: {Type.Enum, values: ["debug", "info", "warning", "error"]}, default_lazy: fn %{env: :prod} -> "warning" %{env: :dev} -> "debug" _ -> "info" end, groups: [:logging] }:required- marks variable as required in specific groups. Can be:- List of group atoms (e.g.,
[:database, :cache]) - Function
(context -> [atom()])for context-dependent requirements
When all required variables in a group are present and valid, the group is considered ready for use. Cannot be used with
:default."DATABASE_URL" => %{ cast: Type.URL, groups: [:database], required: [:database] # Required when using :database group }- List of group atoms (e.g.,
:context- keyword list specifying when this variable should be included in the schema. Variables outside their context are filtered out completely."DATABASE_URL" => %{ cast: Type.URL, context: [env: [:prod]], # Only in production groups: [:database] }:aliases- list of alternative names for this variable. Confispex will try each name in order until it finds a value in the store."DATABASE_URL" => %{ aliases: ["DB_URL", "DATABASE_CONNECTION"], cast: Type.URL, groups: [:database] }:template_value_generator- function(-> String.t())that generates a value for.envrctemplate. Useful for secrets that should be generated once."SECRET_KEY_BASE" => %{ cast: Type.String, template_value_generator: fn -> :crypto.strong_rand_bytes(64) |> Base.encode64() end, groups: [:security] }
Complete Example
defmodule MyApp.RuntimeConfigSchema do
import Confispex.Schema
@behaviour Confispex.Schema
alias Confispex.Type
defvariables(%{
# Simple required variable
"DATABASE_URL" => %{
aliases: ["DB_URL"],
doc: "PostgreSQL connection URL",
cast: Type.URL,
context: [env: [:prod]],
groups: [:database],
required: [:database]
},
# Variable with default
"DATABASE_POOL_SIZE" => %{
aliases: ["POOL_SIZE"],
cast: {Type.Integer, scope: :positive},
default: "10",
context: [env: [:prod]],
groups: [:database]
},
# Context-dependent default
"LOG_LEVEL" => %{
cast: {Type.Enum, values: ["debug", "info", "warning", "error"]},
default_lazy: fn
%{env: :test} -> "warning"
%{env: :dev} -> "debug"
%{env: :prod} -> "info"
end,
groups: [:logging]
},
# Generated secret
"SECRET_KEY_BASE" => %{
cast: Type.String,
template_value_generator: fn ->
:crypto.strong_rand_bytes(64) |> Base.encode64()
end,
groups: [:security],
required: [:security]
}
})
end
Summary
Functions
A helper which performs basic validations of the input schema and then defines variables_schema/0 function.
Types
@type variable_name() :: term()
Name of a configuration variable.
Typically a string representing an environment variable name (e.g., "DATABASE_URL"),
but can be any term.
@type variable_spec() :: %{ :cast => module() | {module(), opts :: keyword()}, :groups => [atom()], optional(:doc) => String.t(), optional(:default) => String.t(), optional(:default_lazy) => (Confispex.context() -> String.t() | nil), optional(:template_value_generator) => (-> String.t()), optional(:required) => [atom()] | (Confispex.context() -> [atom()]), optional(:context) => [{atom(), atom()}], optional(:aliases) => [variable_name()] }
Specification for a single configuration variable.
See the module documentation for detailed explanation of each option.
Callbacks
@callback variables_schema() :: %{required(variable_name()) => variable_spec()}