import { ApolloClient, InMemoryCache, HttpLink, ApolloProvider, split } from '@apollo/client'; import { getMainDefinition } from '@apollo/client/utilities'; import nextWithApollo from 'next-with-apollo'; import { WebSocketLink } from '@apollo/client/link/ws'; import { nanoid } from 'nanoid'; import { SERVER_API_ENDPOINT, BROWSER_API_ENDPOINT, WEBSOCKET_API_URL, IS_SERVER } from 'config/env'; const withApollo = nextWithApollo( ({ initialState, headers, ...rest }) => { const httpLink = new HttpLink({ uri: IS_SERVER ? SERVER_API_ENDPOINT : BROWSER_API_ENDPOINT, headers: { ...headers }, credentials: 'include' }); return new ApolloClient({ ssrMode: IS_SERVER, link: httpLink, cache: new InMemoryCache().restore(initialState || {}), // A hack to get ctx oin the page's props on the initial render // @ts-ignore defaultOptions: { ...rest } }); }, { render: ({ Page, props }) => { return ( <ApolloProvider client={props.apollo}> <Page {...props} {...props.apollo.defaultOptions.ctx} /> </ApolloProvider> ); } } ); export const withApolloWithSubscriptions = nextWithApollo( ({ initialState, headers, ...rest }) => { const clientId = nanoid(); const wsLink = !IS_SERVER ? new WebSocketLink({ uri: WEBSOCKET_API_URL, options: { reconnect: true, connectionParams: { clientId } } }) : null; const httpLink = new HttpLink({ uri: IS_SERVER ? SERVER_API_ENDPOINT : BROWSER_API_ENDPOINT, headers: { ...headers }, credentials: 'include' }); /* * Only create a split link on the browser * The server can not use websockets and is therefore * always a http link */ const splitLink = !IS_SERVER ? split( ({ query }) => { const definition = getMainDefinition(query); return ( definition.kind === 'OperationDefinition' && definition.operation === 'subscription' ); }, wsLink, httpLink ) : httpLink; return new ApolloClient({ ssrMode: IS_SERVER, link: splitLink, cache: new InMemoryCache().restore(initialState || {}), // A hack to get ctx oin the page's props on the initial render // @ts-ignore defaultOptions: { ...rest, clientId } }); }, { render: ({ Page, props }) => { return ( <ApolloProvider client={props.apollo}> <Page {...props} {...props.apollo.defaultOptions.ctx} clientId={props.apollo.defaultOptions.clientId} /> </ApolloProvider> ); } } ); export default withApollo;