# `Chronicle.Events.Constraints`
[🔗](https://github.com/Cratis/Chronicle.Elixir/blob/main/lib/chronicle/events/constraints.ex#L4)

Registers event constraints with a Chronicle event store.

Constraints enforce invariants on the event log. The most common constraint
is a **unique constraint** — ensuring that no two events of the same type
share the same property value within the same event store.

## Registering a unique constraint

    alias Chronicle.Events.Constraints

    {:ok, channel} = Chronicle.Connections.Connection.channel(:my_conn)
    Constraints.register(channel, "my-store", [
      %{
        name: "unique-email",
        type: :unique,
        event_type_id: "user-registered-v1",
        on: ["Email"],
        message: "Email is already taken"
      }
    ])

Constraints are typically registered as part of event type registration
during client startup via `Chronicle.Client`.

# `from_constraint_modules`

```elixir
@spec from_constraint_modules([module()]) :: [map()]
```

Builds constraint definitions from standalone constraint modules (each
`use Chronicle.Events.Constraint`).

Unlike `from_event_types/1`, constraint names are not merged across modules: a module's
own duplicate-name and mode-conflict checks run at compile time (see
`Chronicle.Events.Constraint`), and a conflict between two different modules is left for
the kernel to reject at registration, mirroring the C# client's per-builder scoping.

# `from_event_types`

```elixir
@spec from_event_types([module()]) :: [map()]
```

Builds constraint definitions from model-bound event type attributes.

Event types can declare:

  * `@unique` / `unique(...)`
  * `@unique_event_type` / `unique_event_type(...)`
  * `@remove_constraint` / `remove_constraint(...)`

# `register`

```elixir
@spec register(term(), String.t(), [map()]) :: :ok | {:error, term()}
```

Registers a list of constraint definitions with Chronicle.

Each constraint map supports:

  * `:name` — **(required)** a unique constraint name
  * `:type` — **(required)** `:unique` or `:unique_event_type`
  * `:event_type_id` — the event type ID string this constraint applies to
  * `:on` — list of property path strings to check for uniqueness
  * `:message` — optional human-readable message to use when the constraint
    is violated. This is a **client-side-only** concern, matching every
    other Cratis client (C#, TypeScript, Kotlin): the Chronicle kernel's
    wire `Constraint` message has no field for it, so it is never sent as
    part of registration. Appends resolve it locally against the `Message`
    on a returned `ConstraintViolation` using the client's configured event
    types. Declare it with `unique/2` or `unique_event_type/1`; standalone
    registration does not retain messages for a client.

Returns `:ok` or `{:error, reason}`.

---

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