Packages

Multi-surface application runtime for Elixir. One TEA module renders to terminal, browser (LiveView), SSH, and MCP (agents). 30+ widgets, flexbox + CSS grid, AI agent runtime, distributed swarm with CRDTs, time-travel debugging, session recording, sandboxed REPL, and agentic commerce.

Current section

Files

Jump to
raxol lib raxol terminal plugin dependency_resolver.ex
Raw

lib/raxol/terminal/plugin/dependency_resolver.ex

defmodule Raxol.Terminal.Plugin.DependencyResolver do
@moduledoc """
Handles plugin dependency resolution for the terminal emulator.
This module extracts the plugin dependency resolution logic from the main emulator.
"""
@doc """
Resolves plugin dependencies and returns the load order.
"""
@spec resolve_plugin_dependencies(map()) :: [String.t()]
def resolve_plugin_dependencies(plugin_manager) do
# Extract plugin dependencies
plugins = Map.get(plugin_manager, :plugins, [])
dependencies = extract_plugin_dependencies(plugins)
# Perform topological sort
case topological_sort(dependencies) do
{:ok, sorted_plugins} ->
sorted_plugins
{:error, _reason} ->
# If there are circular dependencies, return plugins in original order
Enum.map(plugins, & &1.name)
end
end
@doc """
Extracts dependencies from a list of plugins.
"""
@spec extract_plugin_dependencies([map()]) :: map()
def extract_plugin_dependencies(plugins) do
Enum.map(plugins, fn plugin ->
{plugin.name, Map.get(plugin, :dependencies, [])}
end)
|> Map.new()
end
@doc """
Performs topological sorting on plugin dependencies.
"""
@spec topological_sort(map()) :: {:ok, [String.t()]} | {:error, atom()}
def topological_sort(dependencies) do
# Kahn's algorithm for topological sorting
nodes = Map.keys(dependencies)
in_degree = calculate_in_degree(dependencies, nodes)
# Find nodes with no incoming edges
queue = Enum.filter(nodes, fn node -> Map.get(in_degree, node, 0) == 0 end)
case topological_sort_helper(dependencies, in_degree, queue, []) do
sorted when length(sorted) == length(nodes) -> {:ok, sorted}
_ -> {:error, :circular_dependency}
end
end
@doc """
Calculates the in-degree for each node in the dependency graph.
"""
@spec calculate_in_degree(map(), [String.t()]) :: map()
def calculate_in_degree(dependencies, nodes) do
Enum.reduce(nodes, %{}, fn node, acc ->
in_degree =
Enum.count(dependencies, fn {_name, deps} ->
Enum.member?(deps, node)
end)
Map.put(acc, node, in_degree)
end)
end
@doc """
Helper function for topological sorting using Kahn's algorithm.
"""
@spec topological_sort_helper(map(), map(), [String.t()], [String.t()]) :: [
String.t()
]
def topological_sort_helper(_dependencies, _in_degree, [], result) do
result
end
def topological_sort_helper(dependencies, in_degree, [node | queue], result) do
# Remove node and its outgoing edges
new_in_degree =
Enum.reduce(dependencies[node] || [], in_degree, fn dep, acc ->
Map.update(acc, dep, 0, &(&1 - 1))
end)
# Add nodes with no incoming edges to queue
new_queue =
queue ++
Enum.filter(dependencies[node] || [], fn dep ->
Map.get(new_in_degree, dep, 0) == 0
end)
topological_sort_helper(dependencies, new_in_degree, new_queue, [
node | result
])
end
end