Current section
Files
Jump to
Current section
Files
lib/nombaone/events.ex
defmodule Nombaone.Events do
@moduledoc """
Events — the append-only log behind every webhook. Webhook delivery is
at-least-once; this log is your reconciliation backstop when a delivery was
missed or you need to backfill.
"""
use Nombaone.Resource
alias Nombaone.{DomainEvent, EventCatalogEntry}
@doc """
List events, newest first. Optional filters: `:type` (a catalog type, e.g.
`"invoice.paid"`), `:limit`, `:cursor`.
## Example
for event <- Nombaone.Events.list!(client, %{type: "invoice.paid"}) do
IO.inspect({event.id, event.payload})
end
"""
@spec list(Nombaone.Client.t(), map(), keyword()) ::
{:ok, Nombaone.Page.t()} | {:error, Nombaone.Error.t()}
def list(client, params \\ %{}, opts \\ []) do
API.list(client, %{method: :get, path: "/events", query: params, options: opts}, DomainEvent)
end
@doc "Raising variant of `list/3`."
@spec list!(Nombaone.Client.t(), map(), keyword()) :: Nombaone.Page.t()
def list!(client, params \\ %{}, opts \\ []), do: unwrap!(list(client, params, opts))
@doc "Retrieve one event by id (`nbo…evt`)."
@spec retrieve(Nombaone.Client.t(), String.t(), keyword()) ::
{:ok, DomainEvent.t()} | {:error, Nombaone.Error.t()}
def retrieve(client, id, opts \\ []) do
API.request(
client,
%{method: :get, path: "/events/#{encode_segment(id)}", options: opts},
DomainEvent
)
end
@doc "Raising variant of `retrieve/3`."
@spec retrieve!(Nombaone.Client.t(), String.t(), keyword()) :: DomainEvent.t()
def retrieve!(client, id, opts \\ []), do: unwrap!(retrieve(client, id, opts))
@doc """
The machine-readable event catalog — every event type the platform can emit,
keyed by type, each an `Nombaone.EventCatalogEntry`. Useful for subscription
pickers or codegen.
## Example
{:ok, catalog} = Nombaone.Events.catalog(client)
catalog["invoice.paid"].payload # => ["reference", ...]
"""
@spec catalog(Nombaone.Client.t(), keyword()) ::
{:ok, %{optional(String.t()) => EventCatalogEntry.t()}} | {:error, Nombaone.Error.t()}
def catalog(client, opts \\ []) do
API.request(client, %{method: :get, path: "/events/catalog", options: opts}, &cast_catalog/1)
end
@doc "Raising variant of `catalog/2`."
@spec catalog!(Nombaone.Client.t(), keyword()) :: %{
optional(String.t()) => EventCatalogEntry.t()
}
def catalog!(client, opts \\ []), do: unwrap!(catalog(client, opts))
# The catalog `data` is a map of event-type string → entry. Keep the type
# keys verbatim (they are data, not fields); cast each value to a struct.
defp cast_catalog(data) when is_map(data),
do: Map.new(data, fn {type, entry} -> {type, EventCatalogEntry.cast(entry)} end)
defp cast_catalog(data), do: data
end