@dillonkearns/elm-graphql
Version:
<img src="https://cdn.jsdelivr.net/gh/martimatix/logo-graphqelm/logo.svg" alt="dillonearns/elm-graphql logo" width="40%" align="right">
93 lines (72 loc) • 2.63 kB
Flow
// @flow
import {Socket as PhoenixSocket} from "phoenix";
import type {Message} from "phoenix";
import joinChannel from "./joinChannel";
import notifierFind from "./notifier/find";
import notifierNotify from "./notifier/notify";
import notifierRemove from "./notifier/remove";
import updateNotifiers from "./updateNotifiers";
import type {AbsintheSocket, SubscriptionPayload} from "./types";
const createConnectionCloseError = () => new Error("connection: close");
const mutationOnConnectionClose = (absintheSocket, notifier) => {
updateNotifiers(absintheSocket, notifierRemove(notifier));
notifierNotify(notifier, "Abort", createConnectionCloseError());
};
const notifierOnConnectionClose = absintheSocket => notifier => {
if (notifier.operationType === "mutation") {
mutationOnConnectionClose(absintheSocket, notifier);
} else {
notifierNotify(notifier, "Error", createConnectionCloseError());
}
};
const onConnectionClose = absintheSocket => () =>
absintheSocket.notifiers.forEach(notifierOnConnectionClose(absintheSocket));
const onSubscriptionData = (
absintheSocket: AbsintheSocket,
{payload}: Message<SubscriptionPayload<any>>
) => {
const notifier = notifierFind(
absintheSocket.notifiers,
"subscriptionId",
payload.subscriptionId
);
if (notifier) {
notifierNotify(notifier, "Result", payload.result);
}
};
const onMessage = absintheSocket => (response: Message<>) => {
if (response.event === "subscription:data") {
onSubscriptionData(absintheSocket, response);
}
};
const shouldJoinChannel = absintheSocket =>
!absintheSocket.channelJoinCreated && absintheSocket.notifiers.length > 0;
const onConnectionOpen = absintheSocket => () => {
if (shouldJoinChannel(absintheSocket)) {
joinChannel(absintheSocket);
}
};
const absintheChannelName = "__absinthe__:control";
/**
* Creates an Absinthe Socket using the given Phoenix Socket instance
*
* @example
* import * as AbsintheSocket from "@absinthe/socket";
* import {Socket as PhoenixSocket} from "phoenix";
* const absintheSocket = AbsintheSocket.create(
* new PhoenixSocket("ws://localhost:4000/socket")
* );
*/
const create = (phoenixSocket: PhoenixSocket): AbsintheSocket => {
const absintheSocket: AbsintheSocket = {
phoenixSocket,
channel: phoenixSocket.channel(absintheChannelName),
channelJoinCreated: false,
notifiers: []
};
phoenixSocket.onOpen(onConnectionOpen(absintheSocket));
phoenixSocket.onMessage(onMessage(absintheSocket));
phoenixSocket.onClose(onConnectionClose(absintheSocket));
return absintheSocket;
};
export default create;