defmodule Hafnium do @external_resource readme = Path.join([__DIR__, "../README.md"]) @moduledoc readme |> File.read!() |> String.split("") |> Enum.fetch!(1) @moduledoc since: "0.1.0" @typedoc """ * `:ok` — success * `:error` — error * `:ignored` — like `ok` but won't trace * `:fatal` — error and break """ @type state :: :ignored | :error | :ok | :fatal @type result :: {state(), any()} @type input :: %{required(atom()) => any()} @type pipe_result :: t() | pipe_atom_result() | pipe_tuple_result() @typep pipe_atom_result :: :ignored | :ok @typep pipe_result_code :: :ok | :error | :fatal @typep pipe_tuple_result :: {code :: pipe_result_code(), result_or_reason :: any()} @version Mix.Project.config()[:version] @doc false def version, do: @version @typedoc "Base struct" @type t :: %__MODULE__{ context: context :: keyword(), result: result :: result(), pipelines: pipelines :: [Hafnium.Pipeline.t()], traces: traces :: [Hafnium.Trace.t()], time: now :: integer(), input: input(), option: temp_input :: any(), __module__: current_module :: module() } @enforce_keys [:__module__, :pipelines] defstruct context: [], result: {:ok, nil}, pipelines: [], traces: [], time: nil, input: %{}, option: nil, __module__: nil @callback before_invoke(o :: t()) :: pipe_result() @callback after_invoke(o :: t()) :: pipe_result() @optional_callbacks before_invoke: 1, after_invoke: 1 defmacro __using__(_opts) do quote do @behaviour unquote(__MODULE__) Module.register_attribute(__MODULE__, :pipelines, accumulate: true) @before_compile unquote(__MODULE__) end end defmacro __before_compile__(_env) do quote location: :keep, generated: true do @meta struct(unquote(__MODULE__), %{__module__: __MODULE__, pipelines: @pipelines}) @spec __meta__() :: unquote(__MODULE__).t() def __meta__, do: @meta end end defmacro pipeline(_opt) do quote do end end end