# `ArchTest.Layers`
[🔗](https://github.com/yoavgeva/arch_test/blob/v0.2.0/lib/arch_test/layers.ex#L1)

Layered architecture enforcement.

Define layers top-to-bottom; `enforce_direction/1` ensures each layer
only depends on layers below it (never upward).

## Example

    define_layers(
      web:     "MyApp.Web.**",
      context: "MyApp.**",
      repo:    "MyApp.Repo.**"
    )
    |> enforce_direction()

## Onion / Hexagonal Architecture

    define_onion(
      domain:      "MyApp.Domain.**",
      application: "MyApp.Application.**",
      adapters:    "MyApp.Adapters.**"
    )
    |> enforce_onion_rules()

# `layer_name`

```elixir
@type layer_name() :: atom()
```

# `t`

```elixir
@type t() :: %ArchTest.Layers{
  app: atom() | nil,
  custom_rules: [
    {layer_name(), :may_only_depend_on | :may_not_depend_on, [layer_name()]}
  ],
  layers: [{layer_name(), String.t()}]
}
```

# `define_layers`

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

Defines an ordered list of architecture layers (top to bottom).

Accepts a keyword list of `layer_name: "Pattern"` pairs.
Order matters: earlier entries are "higher" layers.

# `define_onion`

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

Defines an onion/hexagonal architecture with ordered rings (innermost first).

Equivalent to `define_layers/1` but with onion semantics applied in
`enforce_onion_rules/1`.

# `enforce_direction`

```elixir
@spec enforce_direction(t()) :: :ok
```

Enforces that each layer only depends on layers below it in the ordered list.

Violations are raised as ExUnit assertion failures.

# `enforce_onion_rules`

```elixir
@spec enforce_onion_rules(t()) :: :ok
```

Enforces onion/hexagonal architecture rules:
- Inner rings (listed first) must not depend on outer rings
- Outer rings may depend on inner rings

In other words: dependencies can only point inward.

# `for_app`

```elixir
@spec for_app(t(), atom()) :: t()
```

Sets the OTP application to introspect (default: `:all`).

# `layer_may_not_depend_on`

```elixir
@spec layer_may_not_depend_on(t(), layer_name(), [layer_name()]) :: t()
```

Adds a custom rule: the given layer may not depend on listed layers.

# `layer_may_only_depend_on`

```elixir
@spec layer_may_only_depend_on(t(), layer_name(), [layer_name()]) :: t()
```

Adds a custom rule: the given layer may only depend on listed layers.

---

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