# `ExQuality.Umbrella`
[🔗](https://github.com/riddler/ex_quality/blob/v0.15.0/lib/ex_quality/umbrella.ex#L1)

Umbrella awareness: which child apps exist, where they live, and what they
declare.

An umbrella root's `mix.exs` usually declares no dependencies of its own, so
anything that reads only the root project sees an empty list and concludes
that no quality tools are installed. Every function here folds the child apps
in, and answers `false`, `%{}` or `nil` for a single-app project, so callers
never branch on the project shape themselves.

## Example

    ExQuality.Umbrella.apps_paths()
    #=> %{web: "apps/web", core: "apps/core"}

    ExQuality.Umbrella.app_for_path("apps/web/lib/user.ex")
    #=> :web

# `app_deps`

```elixir
@spec app_deps() :: %{required(atom()) =&gt; [tuple()]}
```

Returns the dependency specs declared by each child app, keyed by app.

Use this over `child_deps/0` when *which* app declares a dependency matters,
as it does for a stage that only has something to say about the apps using a
given library.

Returns an empty map for a single-app project. Shares `child_deps/0`'s cache.

# `app_for_path`

```elixir
@spec app_for_path(String.t() | nil, %{required(atom()) =&gt; String.t()}) ::
  atom() | nil
```

Returns the umbrella app a path belongs to, or `nil` when it belongs to none.

Pass `apps` to avoid re-reading the project once per path, which is what
callers tagging a list of findings should do.

    iex> apps = %{web: "apps/web"}
    iex> ExQuality.Umbrella.app_for_path("apps/web/lib/user.ex", apps)
    :web

    iex> ExQuality.Umbrella.app_for_path("lib/user.ex", %{web: "apps/web"})
    nil

# `apps_paths`

```elixir
@spec apps_paths() :: %{required(atom()) =&gt; String.t()}
```

Returns the child apps as a map of app name to path, relative to the
umbrella root.

Returns an empty map for a single-app project.

# `child_deps`

```elixir
@spec child_deps() :: [tuple()]
```

Returns the dependency specs declared by every child app, in `mix.exs` form.

The result is cached for the lifetime of the VM, because reading it evaluates
each child's `mix.exs`. A child whose `mix.exs` cannot be evaluated
contributes nothing rather than failing the run: the compile stage reports
that problem with a far better message than tool detection could.

# `reset_cache`

```elixir
@spec reset_cache() :: :ok
```

Drops the cached child dependencies. Intended for tests.

# `umbrella?`

```elixir
@spec umbrella?() :: boolean()
```

Returns true when the current project is an umbrella.

Returns false when there is no project at all, so this is safe to call
outside a Mix project.

---

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