# `Clarity.Introspector`
[🔗](https://github.com/team-alembic/clarity/blob/v0.5.1/lib/clarity/introspector.ex#L1)

Defines the behaviour and orchestration logic for introspectors.

Clarity introspects `ash` applications using an underlying `:digraph` structure,
allowing visualization and exploration of resources, domains, actions, types,
and more.

This module defines the `Clarity.Introspector` behaviour and the default
pipeline for built-in and user-defined introspectors. Each introspector
processes vertices individually through the `c:introspect_vertex/2` callback.

## Custom Introspectors

Introspector configuration is managed by `Clarity.Config`. See the documentation
for `Clarity.Config` for detailed configuration options and examples.

## Example

Here's a simplified example of a custom introspector implementation:

```elixir
defmodule MyApp.MyCustomIntrospector do
  @behaviour Clarity.Introspector

  alias Clarity.Vertex

  @impl Clarity.Introspector
  def source_vertex_types, do: [Vertex.Module]

  @impl Clarity.Introspector
  def introspect_vertex(%Vertex.Module{module: module} = module_vertex, _graph) do
    # Create a custom vertex for the module
    custom_vertex = %Vertex.Custom{module: module}

    [
      {:vertex, custom_vertex},
      {:edge, module_vertex, custom_vertex, :custom}
    ]
  end

  def introspect_vertex(_vertex, _graph), do: []
end
```

# `entry`

```elixir
@type entry() ::
  {:vertex, Clarity.Vertex.t()}
  | {:edge, Clarity.Vertex.t(), Clarity.Vertex.t(), term()}
  | {:purge, Clarity.Vertex.t()}
```

An introspection entry returned by introspectors.

- `{:vertex, vertex}` - Adds a new vertex to the graph
- `{:edge, from_vertex, to_vertex, label}` - Adds an edge between vertices
- `{:purge, vertex}` - Removes a vertex and all vertices caused by it

> #### Warning - Internal API {: .warning}
>
> The `{:purge, vertex}` entry type is for internal use by Clarity's
> Application and Module introspectors only. Custom introspectors
> must not emit purge entries.

# `result`

```elixir
@type result() :: {:ok, [entry()]} | {:error, :unmet_dependencies | term()}
```

# `t`

```elixir
@type t() :: module()
```

A module implementing the Clarity.Introspector behaviour.

# `introspect_vertex`

```elixir
@callback introspect_vertex(vertex :: Clarity.Vertex.t(), graph :: Clarity.Graph.t()) ::
  result()
```

Performs introspection on a single vertex in the async system.

This callback is called by workers for each vertex that needs to be processed.
The introspector receives the vertex to process and a read-only view of the 
current graph state for context.

Returns `{:ok, results}` on success, where `results` is a list of
`{:vertex, vertex}` and `{:edge, from_vertex, to_vertex, label}` tuples to add
to the graph.

If the introspector cannot run due to missing dependencies in the graph
(such as an Ash resource referencing a domain that hasn't been introspected
yet), it should return `:missing_dependencies`. The worker will re-queue
the task to be retried later, allowing other introspectors to run first
and potentially satisfy the dependencies.

If an unexpected error occurs, return `{:error, reason}`. The worker will
log the error and acknowledge the task to prevent infinite retries.

# `source_vertex_types`

```elixir
@callback source_vertex_types() :: [module()]
```

Returns the list of vertex types this introspector can process.

This is used to filter which introspectors should be run for each vertex type,
improving performance by avoiding unnecessary task creation.

---

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