# `CMDC.Plugin.Registry`
[🔗](https://github.com/tupleyun/cmdc/blob/v0.5.3/lib/cmdc/plugin/registry.ex#L1)

Plugin 注册表。

管理已注册的 Plugin 集合，按 `priority/0` 自动排序（数值小的先执行），
同一模块只保留一份（去重）。

## 使用示例

    registry = CMDC.Plugin.Registry.new()
    {:ok, registry} = CMDC.Plugin.Registry.register(registry, {MyPlugin, []})
    {:ok, registry} = CMDC.Plugin.Registry.register(registry, {SecurityPlugin, max_paths: 10})

    plugins = CMDC.Plugin.Registry.entries(registry)

# `entry`

```elixir
@type entry() :: {module(), CMDC.Plugin.plugin_state()}
```

# `plugin_spec`

```elixir
@type plugin_spec() :: module() | {module(), keyword()}
```

# `t`

```elixir
@type t() :: %CMDC.Plugin.Registry{entries: [entry()]}
```

# `count`

```elixir
@spec count(t()) :: non_neg_integer()
```

返回已注册 plugin 的数量。

# `entries`

```elixir
@spec entries(t()) :: [entry()]
```

返回已排序的 `[{module, plugin_state}]` 列表，供 Pipeline.run/3 使用。

# `from_specs`

```elixir
@spec from_specs([plugin_spec()]) :: t()
```

从 plugin 规格列表构建 Registry，完成初始化、去重、排序。

`specs` 支持两种格式：
- `{ModuleName, keyword_opts}` — 带自定义选项
- `ModuleName` — 使用空 opts 初始化

初始化失败的 plugin 会被跳过并记录警告日志。

# `modules`

```elixir
@spec modules(t()) :: [module()]
```

返回已注册的 plugin 模块列表。

# `new`

```elixir
@spec new() :: t()
```

创建空的 Registry。

# `register`

```elixir
@spec register(
  t(),
  {module(), keyword()}
) :: {:ok, t()} | {:error, term()}
```

注册一个 Plugin。

调用 `module.init(opts)` 初始化状态，若同一模块已注册则覆盖旧状态，
注册后自动重新排序。

# `registered?`

```elixir
@spec registered?(t(), module()) :: boolean()
```

检查模块是否已注册。

# `unregister`

```elixir
@spec unregister(t(), module()) :: t()
```

注销一个 Plugin（按模块名移除）。

---

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