Shared request/response plumbing for all Xero API resource modules.
This used to live inline inside Xero.API.Base's quote do ... end block
and get re-injected (re-compiled, re-inferred) into every single resource
module via use Xero.API.Base. That meant ~30 duplicate private copies of
the same logic, each independently type-inferred by Dialyzer, and any
diagnostic pointing into one of those copies collapsed onto the use call
site instead of a real line (macro-injected code has no line metadata
unless the quote uses location: :keep).
Pulling the logic out into a normal, single, fully-specced module fixes
both problems: Dialyzer infers/checks this exactly once, and every
diagnostic points at a real line in this file. Xero.API.Base now just
injects trivial one-line delegates that close over the :api atom.
Summary
Functions
Decodes a JSON body on success; passes non-JSON bodies through raw (e.g. PDF).
Passes the body through raw and undecoded — for XML-returning endpoints.
Functions
@spec delete(atom(), Xero.Auth.Token.t(), String.t() | nil, String.t()) :: Xero.HTTP.Client.result()
@spec get(atom(), Xero.Auth.Token.t(), String.t() | nil, String.t(), map()) :: Xero.HTTP.Client.result()
@spec get_modified( atom(), Xero.Auth.Token.t(), String.t() | nil, String.t(), DateTime.t() | String.t(), map() ) :: Xero.HTTP.Client.result()
@spec ok_body(Xero.HTTP.Client.result()) :: {:ok, term()} | {:error, Xero.Error.t()}
Decodes a JSON body on success; passes non-JSON bodies through raw (e.g. PDF).
@spec ok_xml(Xero.HTTP.Client.result()) :: {:ok, term()} | {:error, Xero.Error.t()}
Passes the body through raw and undecoded — for XML-returning endpoints.
@spec post(atom(), Xero.Auth.Token.t(), String.t() | nil, String.t(), term()) :: Xero.HTTP.Client.result()
@spec put(atom(), Xero.Auth.Token.t(), String.t() | nil, String.t(), term()) :: Xero.HTTP.Client.result()