skuld_port

Port > | Umbrella →

Port/adapter boundaries for Skuld — typed contracts, pluggable backends, and bridges between effectful and plain Elixir code. This is the hexagonal architecture layer: define interfaces, swap implementations.

What's included

The four directions

CallerImplementationMechanism
Plain ElixirPlain ElixirDoubleDown.ContractFacade
Plain ElixirEffectfulSkuld.Adapter
EffectfulPlain ElixirPort.with_handler + :direct
EffectfulEffectfulPort.with_handler + effectful module (auto-detected)

Installation

def deps do
[
{:skuld_port, "~> 0.32"}
]
end

Example: single-module effectful boundary

# Contract + Facade in one module
defmodule MyApp.Payments do
use Skuld.Effects.Port.EffectfulFacade
defcallback charge(amount :: integer()) :: {:ok, receipt()} | {:error, term()}
end
# Implementation — one-liner with compile-time behaviour
defmodule MyApp.Payments.Stripe do
use Skuld.Syntax
use MyApp.Payments
@impl MyApp.Payments
defcomp charge(amount) do
{:ok, _} <- StripeAPI.create_charge(amount)
charge_id <- Fresh.uuid4()
{:ok, %{charge_id: charge_id}}
end
end
# Wire at runtime — auto-detected as effectful
MyApp.Payments.charge(99)
|> Port.with_handler(%{MyApp.Payments => MyApp.Payments.Stripe})
|> Throw.with_handler()
|> Comp.run!()

Further reading

See the architecture guide for how this fits into the Skuld ecosystem.


Port > | Umbrella →