import { ApolloClient, ApolloProvider, InMemoryCache, NormalizedCacheObject, } from '@apollo/client'; import { WebSocketLink } from '@apollo/client/link/ws'; import { SubscriptionClient } from 'subscriptions-transport-ws'; import React, { useContext, useEffect } from 'react'; import { LoadingContext } from '/imports/ui/components/common/loading-screen/loading-screen-HOC/component'; import logger from '/imports/startup/client/logger'; interface ConnectionManagerProps { children: React.ReactNode; } interface Response { response: { returncode: string; version: string; apiVersion: string; bbbVersion: string; graphqlWebsocketUrl: string; } } const ConnectionManager: React.FC = ({ children }): React.ReactNode => { const [graphqlUrlApolloClient, setApolloClient] = React.useState | null>(null); const [graphqlUrl, setGraphqlUrl] = React.useState(''); const loadingContextInfo = useContext(LoadingContext); useEffect(() => { fetch(`https://${window.location.hostname}/bigbluebutton/api`, { headers: { 'Content-Type': 'application/json', }, }).then(async (response) => { const responseJson: Response = await response.json(); setGraphqlUrl(responseJson.response.graphqlWebsocketUrl); }).catch((error) => { loadingContextInfo.setLoading(false, ''); throw new Error('Error fetching GraphQL URL: '.concat(error.message || '')); }); logger.info('Fetching GraphQL URL'); loadingContextInfo.setLoading(true, '1/4'); }, []); useEffect(() => { logger.info('Connecting to GraphQL server'); loadingContextInfo.setLoading(true, '2/4'); if (graphqlUrl) { const urlParams = new URLSearchParams(window.location.search); const sessionToken = urlParams.get('sessionToken'); if (!sessionToken) { loadingContextInfo.setLoading(false, ''); throw new Error('Missing session token'); } sessionStorage.setItem('sessionToken', sessionToken); let wsLink; try { const subscription = new SubscriptionClient(graphqlUrl, { reconnect: true, timeout: 30000, minTimeout: 30000, connectionParams: { headers: { 'X-Session-Token': sessionToken, }, }, }); subscription.onError(() => { loadingContextInfo.setLoading(false, ''); throw new Error('Error: on subscription to server'); }); wsLink = new WebSocketLink( subscription, ); wsLink.setOnError((error) => { loadingContextInfo.setLoading(false, ''); throw new Error('Error: on apollo connection'.concat(JSON.stringify(error) || '')); }); } catch (error) { loadingContextInfo.setLoading(false, ''); throw new Error('Error creating WebSocketLink: '.concat(JSON.stringify(error) || '')); } let client; try { client = new ApolloClient({ link: wsLink, cache: new InMemoryCache(), connectToDevTools: true, }); setApolloClient(client); } catch (error) { loadingContextInfo.setLoading(false, ''); throw new Error('Error creating Apollo Client: '.concat(JSON.stringify(error) || '')); } } }, [graphqlUrl]); return ( graphqlUrlApolloClient ? ( {children} ) : null ); }; export default ConnectionManager;