HexPort.Contract (hex_port v0.17.0)

Copy Markdown View Source

Macro for defining typed port contracts with defport declarations.

use HexPort.Contract imports the defport macro and registers a @before_compile hook that generates:

  • @callback declarations on the contract module itself — the contract module is the behaviour
  • __port_operations__/0 — introspection metadata

Contracts are purely static interface definitions. They do not generate a dispatch facade (.Port module) — that is the concern of HexPort.Facade, which the consuming application uses separately to bind a contract to an OTP application's config.

Usage

defmodule MyApp.Todos do
  use HexPort.Contract

  defport get_todo(tenant_id :: String.t(), id :: String.t()) ::
    {:ok, Todo.t()} | {:error, term()}

  defport list_todos(tenant_id :: String.t()) :: [Todo.t()]
end

This generates @callback declarations on MyApp.Todos and MyApp.Todos.__port_operations__/0.

Implementations use @behaviour MyApp.Todos directly:

defmodule MyApp.Todos.Ecto do
  @behaviour MyApp.Todos
  # ...
end

Compatible with Mox.defmock(Mock, for: MyApp.Todos).

To generate a dispatch facade, use HexPort.Facade in a separate module:

defmodule MyApp.Todos do
  use HexPort.Facade, contract: MyApp.Todos.Contract, otp_app: :my_app
end

See HexPort.Facade for dispatch configuration and HexPort for an overview.

Summary

Functions

Define a typed port operation.

Functions

defport(spec, opts \\ [])

(macro)

Define a typed port operation.

Syntax

defport function_name(param :: type(), ...) :: return_type()
defport function_name(param :: type(), ...) :: return_type(), bang: option

Bang Options

  • omitted — auto-detect: generate bang only if return type contains {:ok, T}
  • true — force standard {:ok, v} / {:error, r} unwrapping
  • false — suppress bang generation
  • unwrap_fn — generate bang using custom unwrap function

Pre-dispatch Transform

  • :pre_dispatch — a function (args, facade_module) -> args that transforms the argument list before dispatch. The function receives the args as a list and the facade module atom, and must return the (possibly modified) args list. This is useful for injecting facade-specific context into arguments at the dispatch boundary.