Packages

Helpers for building modular GraphQL API projects using Absinthe and Phoenix.

Current section

Files

Jump to
grapix lib graphql_ws_v1_json_serializer.ex
Raw

lib/graphql_ws_v1_json_serializer.ex

defmodule Grapix.GraphqlWS.V1.JSONSerializer do
@moduledoc false
@behaviour Phoenix.Socket.Serializer
alias Phoenix.Socket.{Broadcast, Message, Reply}
@impl true
def fastlane!(%Broadcast{} = msg) do
data = phoenix2gql(nil, "1", msg.topic, msg.event, msg.payload.result)
{:socket_push, :text, Phoenix.json_library().encode_to_iodata!(data)}
end
@impl true
def encode!(%Reply{payload: %{ subscriptionId: _subscription_id }} = reply) do
data = phoenix2gql(reply.join_ref, reply.ref, reply.topic, "subs_ack", reply.payload)
# client doesn't like empty or unexpectedly-shapen data, but fine with nought
#{:socket_push, :text, Phoenix.json_library().encode_to_iodata!(data)}
{nil, :text, Phoenix.json_library().encode_to_iodata!(data)}
end
def encode!(%Reply{payload: %{}} = reply) do
data =
case reply.status do
:error -> phoenix2gql(reply.join_ref, reply.ref, reply.topic, "phx_error", reply.payload)
:ok -> phoenix2gql(reply.join_ref, reply.ref, reply.topic, "phx_reply", nil)
end
{:socket_push, :text, Phoenix.json_library().encode_to_iodata!(data)}
end
def encode!(%Message{} = msg) do
data =
phoenix2gql(msg.join_ref, msg.ref, msg.topic, "phx_message", msg.payload)
{:socket_push, :text, Phoenix.json_library().encode_to_iodata!(data)}
end
defmodule(RandomId, do: use(Puid, bits: 64, charset: :alphanum_lower))
@impl true
def decode!(raw_message, _opts) do
incoming = raw_message
|> Phoenix.json_library().decode!
Map.merge(%{ "payload" => %{}, "id" => RandomId.generate()}, incoming)
|> gql2Phoenix
end
defp gql2Phoenix(%{ "type" => "connection_init", "payload" => payload, "id" => id }) do
%Phoenix.Socket.Message{
topic: "__absinthe__:control",
event: "phx_join",
payload: payload,
ref: id,
join_ref: nil
}
end
defp gql2Phoenix(%{ "type" => "start", "payload" => payload, "id" => id }) do
variables = Map.put(Map.get(payload, "variables", %{}), :__graphql_client_ref__, id)
%Phoenix.Socket.Message{
topic: "__absinthe__:control",
event: "doc",
payload: Map.put(payload, "variables", variables),
ref: id,
join_ref: nil
}
end
defp gql2Phoenix(%{ "type" => "stop", "payload" => payload, "id" => id }) do
%Phoenix.Socket.Message{
topic: "__absinthe__:control",
event: "phx_leave",
payload: payload,
ref: nil,
join_ref: id
}
end
#[msg.join_ref, msg.ref, msg.topic, msg.event, msg.payload]
defp phoenix2gql(_join_ref, ref, "__absinthe__:control", "subs_ack", %{subscriptionId: _subscription_id} = payload) do
%{ "type" => "data", "id" => ref, "payload" => %{data: payload}}
end
defp phoenix2gql(join_ref, _ref, "__absinthe__:control", "phx_reply", payload) do
%{ "type" => "connection_ack", "id" => join_ref, "payload" => payload }
end
defp phoenix2gql(_, ref, "__absinthe__:control", "phx_message", payload) do
%{ "type" => "data", "id" => ref, "payload" => payload }
end
defp phoenix2gql(_, ref, "__absinthe__:control", "phx_error", payload) do
%{ "type" => "error", "id" => ref, "payload" => payload }
end
defp phoenix2gql(_, ref, _msg_topic, "subscription:data", payload) do
%{ "type" => "data", "id" => ref, "payload" => payload }
end
end