Skuld.Effects.Port.Facade (skuld v0.23.0)

View Source

Generates an effectful dispatch facade for a port contract.

use Skuld.Effects.Port.Facade reads the contract's __port_operations__/0 metadata and generates effectful caller functions (returning computations), bang variants (unwrap or throw), and __key__ helpers for test stub matching.

Combined effectful contract + facade (simplest)

When :hex_port_contract is given (and :contract is omitted), the effectful contract is set up implicitly and the facade is generated on the same module:

defmodule MyApp.Todos.Contract do
  use HexPort.Contract

  defport get_todo(id :: String.t()) :: {:ok, Todo.t()} | {:error, term()}
  defport list_todos() :: [Todo.t()]
end

defmodule MyApp.Todos do
  use Skuld.Effects.Port.Facade,
    hex_port_contract: MyApp.Todos.Contract
end

MyApp.Todos is both the effectful contract (has effectful @callbacks, __port_operations__/0, __port_effectful__?/0) and the dispatch facade.

Separate effectful contract and facade

For cases where you want them in different modules:

defmodule MyApp.Todos.Effectful do
  use Skuld.Effects.Port.EffectfulContract,
    hex_port_contract: MyApp.Todos.Contract
end

defmodule MyApp.Todos do
  use Skuld.Effects.Port.Facade, contract: MyApp.Todos.Effectful
end

Handler Installation

comp do
  todo <- MyApp.Todos.get_todo!("42")
  todo
end
|> Port.with_handler(%{MyApp.Todos => MyApp.Todos.Ecto})
|> Throw.with_handler()
|> Comp.run!()

Options

  • :contract — the effectful contract module. Defaults to __MODULE__.
  • :hex_port_contract — the HexPort contract module. When given (and :contract is not), implicitly issues use Skuld.Effects.Port.EffectfulContract and sets :contract to __MODULE__. Cannot be combined with :contract.