# `Selecto.Config.Overlay`

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

- **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
- **Source relationships** (`source_relationships`): Deep merge - overlay can add
  or override relationship entries
- **Choice sources** (`choice_sources`): Deep merge - overlay can add or override
  choice-source entries
- **Writes** (`writes`): Deep merge - overlay can add or override write
  operations, fields, relationships, validations, constraints, and transitions
- **Actions** (`actions`): Deep merge - overlay can add or override domain
  actions without replacing sibling actions
- **Capabilities** (`capabilities`): Deep merge - overlay can add or override
  capability entries without replacing sibling capabilities
- **Redact fields**: Union - unique list of all redacted fields
- **Other fields**: Shallow merge - overlay takes precedence

## Examples

### 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

    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)

    # 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

# `merge`

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

  - `base` - The base domain configuration map
  - `overlay` - The overlay configuration map to merge in

## 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: []}}

---

*Consult [api-reference.md](api-reference.md) for complete listing*
