UNPKG

@codesandbox/api

Version:
78 lines 3.48 kB
import * as withAbsintheSocket from "@absinthe/socket"; import { Socket as PhoenixSocket } from "phoenix"; import { createClient } from "./generated_gql"; const SUBSCRIPTION_HEARTBEAT_INTERVAL = 10000; export class GQLApi { constructor(options) { const WEBSOCKET_URL = new URL(`${options.apiUrl}/socket`); const webSocketProtocol = WEBSOCKET_URL.protocol === "http:" ? "ws:" : "wss:"; WEBSOCKET_URL.protocol = webSocketProtocol; let socketPromise; const client = createClient({ onRequest: (query, variables, headers) => { return options .request({ method: "POST", data: { query, variables }, path: "/graphql", headers, }) .then(({ data }) => data); }, onSubscribe: (query, cb, variables) => { const currentSocketPromise = socketPromise; if (!currentSocketPromise) { // This is not really a possible scenario as we always create a socket // when starting the first subscription return () => { }; } const notifierPromise = currentSocketPromise.then((socket) => { const notifier = withAbsintheSocket.send(socket, { operation: query, variables: Object.assign({}, variables), }); withAbsintheSocket.observe(socket, notifier, { // eslint-disable-next-line onError: console.error, onResult: (result) => cb(result.data), }); return notifier; }); return () => { Promise.all([currentSocketPromise, notifierPromise]).then(([socket, notifier]) => { withAbsintheSocket.cancel(socket, notifier); }); }; }, includeTypeNames: false, cacheQueries: false, }); this.query = client.query.bind(client); // Not sure why TS is so angry at the parameters here // eslint-disable-next-line // @ts-ignore this.subscribe = (...args) => { // Creating the socket is ASYNC as we potentially need to call an endpoint to get the guardian token if (!socketPromise) { socketPromise = this.getSubscriptionSocket(WEBSOCKET_URL.toString(), options.session); } return client.subscribe(...args); }; } async getSubscriptionSocket(websocketUrl, session) { const getToken = async () => await (session.bearerToken || session.getGuardianToken()); let token = await getToken(); const phoenixSocketOpts = { params: () => ({ guardian_token: token }), heartbeatIntervalMs: SUBSCRIPTION_HEARTBEAT_INTERVAL, }; const phoenixSocket = new PhoenixSocket(websocketUrl, phoenixSocketOpts); // Whenever the socket errors it is most likely related to an expired token. We go and grab a new token // and update it phoenixSocket.onError(async () => { token = await getToken(); }); return withAbsintheSocket.create(phoenixSocket); } } //# sourceMappingURL=GQLApi.js.map