# `Bylaw.Ecto.Query`
[🔗](https://github.com/ryanzidago/bylaw/blob/v0.1.0-alpha.1/lib/bylaw/ecto/query.ex#L1)

Runs Ecto query checks from an explicit list of check specs.

`Bylaw.Ecto.Query.validate/3` is the public entry point for end-user query
validation. Use it from `c:Ecto.Repo.prepare_query/3` when you want repo-wide
enforcement while keeping check selection explicit:

    @query_checks [
      Bylaw.Ecto.Query.Checks.RequiredOrder,
      {Bylaw.Ecto.Query.Checks.MandatoryWhereKeys, keys: [:organization_id]}
    ]

    def prepare_query(operation, query, opts) do
      case Bylaw.Ecto.Query.validate(operation, query, @query_checks) do
        :ok -> {query, opts}
        {:error, issues} -> raise Bylaw.Ecto.Query.Issue.format_many(issues)
      end
    end

A check spec is either a check module or `{check_module, opts}`. Each check
module may appear at most once.

## Examples

    iex> import Ecto.Query
    iex> query = from("posts", as: :post, limit: 1)
    iex> {:error, [issue]} =
    ...>   Bylaw.Ecto.Query.validate(:all, query, [
    ...>     Bylaw.Ecto.Query.Checks.RequiredOrder
    ...>   ])
    iex> issue.check
    Bylaw.Ecto.Query.Checks.RequiredOrder

    iex> Bylaw.Ecto.Query.validate(:all, :query, [])
    :ok

# `check_spec`

```elixir
@type check_spec() :: module() | {module(), Bylaw.Ecto.Query.Check.opts()}
```

# `checks`

```elixir
@type checks() :: [check_spec()]
```

# `validate`

```elixir
@spec validate(
  Bylaw.Ecto.Query.Check.operation(),
  Bylaw.Ecto.Query.Check.query(),
  checks()
) ::
  :ok | {:error, [Bylaw.Ecto.Query.Issue.t(), ...]}
```

Runs the given query checks against a prepared Ecto query.

Returns `:ok` when every enabled check passes. Returns `{:error, issues}`
when one or more checks fail.

`checks` accepts modules and `{module, opts}` tuples. Duplicate check modules
raise `ArgumentError`. Bylaw does not read check lists from application
config; callers pass checks explicitly.

---

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