# `StatifierPersistence.Ecto.Config`
[🔗](https://github.com/riddler/statifier_persistence/blob/v0.18.0/lib/statifier_persistence/ecto/config.ex#L1)

The resolved configuration behind `use StatifierPersistence.Ecto`.

ADR-0002 decision 3 requires that the generated schemas and the
migrations helper take the same options and cannot disagree. This module
is the single definition site that makes that true: `__using__/1` builds
a `Config` at the host's compile time, and the migrations helper reads
the same struct (via `for: HostModule`) or funnels literal options
through the same `new/1`.

Options:

  * `:repo` - required, the host's `Ecto.Repo` module
  * `:key` - the surrogate-key scheme, `:uxid` (default), `:uuid`,
    `:bigserial`, or `{module, opts}` implementing
    `StatifierPersistence.Ecto.KeyGenerator`
  * `:table_prefix` - prefix for the generated table names, default
    `"statifier_"`
  * `:tables` - per-table override map with keys `:charts`,
    `:positions`, `:executions`, `:inputs`; an override replaces the whole
    name, prefix included
  * `:prefix` - the Postgres schema (Ecto's `@schema_prefix`), default
    `nil`
  * `:blob_type` - the Ecto type applied to the payload blob columns
    (`identity_blob`, `chart_blob`, `position_blob`, `outcome_blob`,
    and `input_blob` since ADR-0010 decision 4), default
    `:binary` (the built-in `bytea` behaviour, unchanged). Pass a
    module implementing `Ecto.Type` for `field(name, Mod)`, or a
    `{module, opts}` tuple for an `Ecto.ParameterizedType` for
    `field(name, Mod, opts)` - the shape Ecto itself uses to declare a
    parameterized field. Keys and lookup columns (`content_hash`,
    `session_id`, `execution_id`, `status`, `failure`, `seq`, `door`) are
    never affected; only the payload blob columns reach this option. Resolved and
    stored on the struct as `:binary` (bare) or `{module, opts}`
    (normalized, so a bare custom module becomes `{module, []}`) -
    one shape for downstream code to read.
  * `:leading_columns` - host-owned columns the migrations helper places
    immediately after `id` in every table V01 and V05 create (`charts`,
    `positions`, `executions`, `inputs`), in the order given, default
    `[]`. A keyword list of `name: {type, opts}`, where `type` and `opts`
    are what `Ecto.Migration.add/3` takes:
    `leading_columns: [tenant_id: {:text, null: true}]` puts a nullable
    `tenant_id` at ordinal position 2 on all four tables. The option
    only places the column: it reaches a table only as V01 or V05
    creates it, so a table that already exists - one V06 renamed on a
    database built before `0.12.0` included - keeps the columns it
    already had; the generated schemas do not declare it, so the
    package never reads or writes it; and a default or a `NOT NULL`
    belongs to a later migration of the host's own.
  * `:timestamps_position` - where the migrations helper places
    `inserted_at` and `updated_at` in every table V01 and V05 create,
    `:trailing` (default: last in the `CREATE TABLE`, the package's
    layout since V01) or `:leading` (immediately after `id` and the
    `:leading_columns`). Like `:leading_columns` it only places the two
    columns, on a fresh create: an existing table keeps its layout, and
    a column a later version adds (V02's `metadata`, V03's
    `outcome_blob`, V07's `retired_at` and `retired_by`) still lands
    at the end.
  * `:column_collations` - a collation per package column, applied
    where V01 or V05 declares that column in a `CREATE TABLE`, default
    `[]` (every column takes the database default). A keyword list of
    `name: collation`, the collation a string:
    `column_collations: [execution_id: "C"]` declares `execution_id`
    `COLLATE "C"` on the executions and inputs tables. The names are
    the text columns those two versions declare (`content_hash`,
    `session_id`, `execution_id`, `status`, `failure`, `door`); a
    host column takes its collation in its own `:leading_columns`
    opts instead. The collation is passed to `Ecto.Migration.add/3`
    as its `:collation` option, so it must be one the database knows.

Unknown options and unknown table keys raise `ArgumentError` - at the
host's compile time when reached through `use`.

# `t`

```elixir
@type t() :: %StatifierPersistence.Ecto.Config{
  blob_type: :binary | {module(), keyword()},
  column_collations: [{atom(), String.t()}],
  key: {module(), keyword()},
  leading_columns: [{atom(), {term(), keyword()}}],
  prefix: String.t() | nil,
  repo: module(),
  table_prefix: String.t(),
  tables: %{
    optional(StatifierPersistence.Ecto.KeyGenerator.table()) =&gt; String.t()
  },
  timestamps_position: :trailing | :leading
}
```

Resolved configuration for one host module.

# `blob_field_args`

```elixir
@spec blob_field_args(t(), atom()) :: [term(), ...]
```

The resolved `field/3` arguments for a blob column under this
configuration: `[name, :binary]` for the default, or
`[name, module, opts]` for a custom `:blob_type` (`opts` is `[]` for
a bare custom module, since `field/3` treats an empty-opts
parameterized call and a plain `Ecto.Type` call identically).

# `new`

```elixir
@spec new(keyword()) :: t()
```

Validates and resolves the options `use StatifierPersistence.Ecto`
accepts. Raises `ArgumentError` on anything malformed.

# `table`

```elixir
@spec table(t(), StatifierPersistence.Ecto.KeyGenerator.table()) :: String.t()
```

The table name (source) for `table` under this configuration: the
per-table override when one was given, otherwise the table prefix plus
the table's own name.

---

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