Selecto.Config.Overlay (Selecto v0.4.3)
Merges overlay configurations into base domain configurations.
Overlays provide a flexible way to customize domain configurations at compile-time or runtime without modifying the base configuration. This is particularly useful for:
- Separating generated code from user customizations
- Multi-tenant applications with per-tenant configurations
- Feature flags that change available filters or columns
- A/B testing different domain configurations
- Environment-specific domain customizations
merge-strategy
Merge Strategy
- Column configurations: Deep merge - overlay extends/overrides base column properties
- Filters: Additive merge - both base and overlay filters are available
- Functions: Deep merge - overlay can add or override named UDF specs
- Query members (
query_members.ctes/values/subqueries): Deep merge - overlay can add or override named query-member presets without replacing the full registry - Schemas (
schemas): Deep merge - overlay can add/override schema entries without replacing the full schemas map - Joins (
joins): Deep merge - overlay can add/override join entries without replacing the full joins map - Source associations (
source.associations): Deep merge - overlay can add or override root associations without replacing the full source map - Redact fields: Union - unique list of all redacted fields
- Other fields: Shallow merge - overlay takes precedence
examples
Examples
basic-overlay-merge
Basic Overlay Merge
base = %{
source: %{
columns: %{
price: %{type: :decimal}
},
redact_fields: []
},
filters: %{}
}
overlay = %{
columns: %{
price: %{
label: "Product Price",
format: :currency
}
},
redact_fields: [:internal_notes]
}
merged = Selecto.Config.Overlay.merge(base, overlay)
# => %{
# source: %{
# columns: %{
# price: %{type: :decimal, label: "Product Price", format: :currency}
# },
# redact_fields: [:internal_notes]
# },
# filters: %{}
# }
runtime-multi-tenant-configuration
Runtime Multi-Tenant Configuration
defmodule MyApp.ProductDomain do
def domain(tenant_id) do
base_domain()
|> Selecto.Config.Overlay.merge(tenant_overlay(tenant_id))
end
defp tenant_overlay("premium"), do: %{
columns: %{price: %{format: :currency_with_symbol}}
}
defp tenant_overlay(_), do: %{}
end
compile-time-customization-generated-domains
Compile-Time Customization (Generated Domains)
# Generated by selecto_mix
defmodule MyApp.SelectoDomains.ProductDomain do
def domain do
base_domain()
|> Selecto.Config.Overlay.merge(overlay())
end
# Generated base configuration
defp base_domain, do: %{...}
# User-defined overlay
defp overlay do
if Code.ensure_loaded?(MyApp.SelectoDomains.Overlays.ProductDomainOverlay) do
MyApp.SelectoDomains.Overlays.ProductDomainOverlay.overlay()
else
%{}
end
end
end
Link to this section Summary
Functions
Merges an overlay configuration into a base domain configuration.
Link to this section Functions
Link to this function
merge(base, overlay)
Merges an overlay configuration into a base domain configuration.
The overlay is intelligently merged based on the semantics of each configuration key:
- Columns are deep-merged to allow fine-grained property overrides
- Filters are combined additively
- Redact fields are unioned
- Other fields use overlay value if present
Returns the merged configuration map.
parameters
Parameters
base- The base domain configuration mapoverlay- The overlay configuration map to merge in
examples
Examples
iex> base = %{source: %{columns: %{id: %{type: :integer}}, redact_fields: []}}
iex> overlay = %{columns: %{id: %{label: "ID"}}}
iex> Selecto.Config.Overlay.merge(base, overlay)
%{source: %{columns: %{id: %{type: :integer, label: "ID"}}, redact_fields: []}}