 
   @type socket_opts :: [{:serializer, module}]
   @type callback_state :: any
-  @type transport :: %{transport: pid | nil, message_refs: :ets.tab, serializer: module}
+  @opaque transport :: %{
+    transport_mod: module,
+    transport: pid | nil,
+    message_refs: :ets.tab,
+    serializer: module
+  }
   @type topic :: String.t
   @type event :: String.t
   @type payload :: %{String.t => any}

  # -------------------------------------------------------------------

  @doc false
  def init({callback, transport, arg, socket_opts}) do
    case callback.init(arg) do
      {:ok, url, callback_state} ->
        {:ok, %{
          url: url,
          transport: transport,
          serializer: Keyword.get(socket_opts, :serializer, Phoenix.Channels.GenSocketClient.Serializer.Json),
          callback: callback,
          callback_state: callback_state,

        {:error, :already_joined}
      true ->
        frame = transport.serializer.encode_message(%{topic: topic, event: event, payload: payload, ref: ref})
        transport.transport_mod.push(transport.transport_pid, frame)
        {:ok, ref}
    end
  end
