defmodule ApiBrasil.Client do @moduledoc """ Cliente já resolvido — o valor que todas as funções de serviço recebem como primeiro argumento. Crie com `ApiBrasil.new/1` (ou `ApiBrasil.from_env/0`) em vez de montar a struct à mão: `new/1` resolve o ambiente, aplica os padrões e normaliza os headers. client = ApiBrasil.new(bearer_token: "jwt", device_token: "device") {:ok, envelope} = ApiBrasil.Messaging.WhatsApp.send_text(client, %{ "number" => "5511999999999", "text" => "Olá! 👋" }) Por ser um valor imutável, trocar credenciais devolve um **novo** cliente: outro = ApiBrasil.put_device_token(client, "outro_device") """ alias ApiBrasil.Core.{Hooks, Retry, Transport} @type t :: %__MODULE__{ bearer_token: String.t() | nil, device_token: String.t() | nil, secret_key: String.t() | nil, base_url: String.t(), timeout: non_neg_integer(), headers: %{String.t() => String.t()}, transport: Transport.t(), retry: Retry.t(), hooks: Hooks.t(), options: keyword() } defstruct bearer_token: nil, device_token: nil, secret_key: nil, base_url: "", timeout: 30_000, headers: %{}, transport: nil, retry: %Retry{}, hooks: nil, options: [] defimpl Inspect do import Inspect.Algebra def inspect(client, opts) do fields = [ base_url: client.base_url, timeout: client.timeout, authenticated: client.bearer_token != nil, device: client.device_token != nil, transport: client.transport, retry: client.retry ] concat(["#ApiBrasil.Client<", to_doc(fields, opts), ">"]) end end end