# `Runic.Component`
[🔗](https://github.com/zblanco/runic/blob/main/lib/workflow/component.ex#L1)

Protocol defining how Runic components compose together and connect within workflows.

The `Component` protocol supports extension of modeling new component types that can be
added and connected with other components in Runic workflows. It provides introspection
capabilities for components (sub-components, inputs, outputs) and connection semantics
for workflow composition.

## Protocol Functions

| Function | Purpose |
|----------|---------|
| `connectable?/2` | Check if a component can be connected to another |
| `connect/3` | Connect this component to a parent in a workflow |
| `source/1` | Returns the source AST for building/serializing the component |
| `hash/1` | Returns the content-addressable hash of the component |
| `inputs/1` | Returns the nimble_options schema for component inputs |
| `outputs/1` | Returns the nimble_options schema for component outputs |

## Built-in Implementations

| Component Type | Description |
|----------------|-------------|
| `Runic.Workflow.Step` | Single transformation function |
| `Runic.Workflow.Rule` | Conditional logic with condition and reaction |
| `Runic.Workflow.Map` | Fan-out transformation over enumerables |
| `Runic.Workflow.Reduce` | Fan-in aggregation |
| `Runic.Workflow.Accumulator` | Stateful reducer across invocations |
| `Runic.Workflow.StateMachine` | Stateful reducer with reactive conditions |
| `Runic.Workflow` | Workflows themselves are components |
| `Tuple` | Pipeline syntax `{parent, [children]}` |

## Type Compatibility

The `Component` protocol includes type compatibility checking via an internal
`TypeCompatibility` helper module. This enables schema-based
validation when connecting components:

    # Type compatibility checks
    TypeCompatibility.types_compatible?(:any, :integer)  # => true
    TypeCompatibility.types_compatible?(:string, :integer)  # => false

    # Port compatibility for connecting components
    producer_outputs = [out: [type: {:list, :integer}]]
    consumer_inputs = [in: [type: {:list, :any}]]
    TypeCompatibility.ports_compatible?(producer_outputs, consumer_inputs)  # => {:ok, :inferred}

## Usage

    require Runic

    step = Runic.step(fn x -> x * 2 end, name: :double)
    rule = Runic.rule(fn x when x > 10 -> :large end, name: :classify)

    # Introspection
    Runic.Component.hash(step)  # => content-addressable hash
    Runic.Component.source(step)  # => AST representation

    # Compatibility checking
    Runic.Component.connectable?(step, rule)  # => true

    # Connection (typically done via Workflow.add/3)
    workflow = Runic.Workflow.new()
      |> Runic.Workflow.add(step)
      |> Runic.Workflow.add(rule, to: :double)

## Implementing Custom Component

    defmodule MyApp.CustomComponent do
      defstruct [:hash, :name, :config]
    end

    defimpl Runic.Component, for: MyApp.CustomComponent do
      alias Runic.Workflow

      def connectable?(_component, _other), do: true

      def connect(component, to, workflow) do
        workflow
        |> Workflow.add_step(to, some_internal_step(component))
        |> Workflow.register_component(component)
      end

      def source(component) do
        quote do
          MyApp.CustomComponent.new(name: unquote(component.name))
        end
      end

      def hash(component), do: component.hash

      def inputs(_component), do: [in: [type: :any, doc: "Input value"]]

      def outputs(_component), do: [out: [type: :any, doc: "Output value"]]
    end

See the [Protocols Guide](protocols.html) for more details and examples.

# `t`

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

All the types that implement this protocol.

# `connect`

# `connectable?`

Check if a component can be connected to another component.

# `hash`

# `inputs`

Returns port contract for component inputs.
Each entry is a named port with options like :type, :doc, :cardinality, :required.

# `outputs`

Returns port contract for component outputs.
Each entry is a named port with options like :type, :doc, :cardinality.

# `source`

Returns the source AST for building a component.

---

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