Shared plumbing for the endpoint modules.
Every resource module under UnifiApi.Network.* and UnifiApi.Protect.*
needs the same three things: the path prefix for its API surface, id
validation before interpolation, and optional-query-param assembly. Before
v0.4.0 that was 37 copies of defp prefix, 20 copies of defp maybe_param,
and 115 inline Client.validate_id!/1 calls — so a missing validate_id!
in any one module was invisible, and moving the prefixes off global
Application env would have meant 37 near-identical edits.
Usage
defmodule UnifiApi.Network.Devices do
use UnifiApi.Resource, api: :network
def get(client, site_id, device_id) do
Client.get(client, "#{prefix(client)}/v1/sites/#{id!(site_id)}/devices/#{id!(device_id)}")
end
endapi: is one of UnifiApi.Client.api/0 — :network, :protect,
:network_v1, :protect_v1.
What it injects
alias UnifiApi.Clientprefix(client)— this module's path prefix, read from the client (not fromApplicationenv; seeUnifiApi.Client.prefix/2).id!(id)—UnifiApi.Client.validate_id!/1, shortened because it appears inline in interpolations where a long name hurts readability.maybe_param(params, key, value)— prepends{key, value}unlessvalueisnil.maybe_csv(params, key, values)— prepends a comma-joined{key, csv}unlessvaluesisnilor empty.
All four are private to the using module. The macro also defines
__resource__/1 for introspection: __resource__(:api) returns the API
surface and __resource__(:helpers) returns captures of the injected
helpers, which is also what keeps an unused one from tripping
--warnings-as-errors.