Last active
July 19, 2022 21:11
-
-
Save RobinDaugherty/085fe11e956f9819b396ea64a9e1e0bb to your computer and use it in GitHub Desktop.
Apollo client setup with ActionCable using TypeScript
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import ActionCable from 'actioncable'; | |
import { ActionCableLink } from 'graphql-ruby-client'; | |
import { ApolloClient } from "apollo-client"; | |
import { ApolloLink, Operation } from "apollo-link"; | |
import { DefinitionNode, OperationDefinitionNode } from 'graphql'; | |
import { RetryLink } from "apollo-link-retry"; | |
import { createHttpLink } from "apollo-link-http"; | |
import { InMemoryCache } from "apollo-cache-inmemory"; | |
import { onError } from "apollo-link-error"; | |
const errorLink = onError((error) => { | |
console.log(error); | |
}); | |
const createApolloClient = (authTokenForApollo: string | null) => { | |
const cache = new InMemoryCache({}); | |
const retryLink = new RetryLink(); | |
const authLink = setContext((_, { headers }) => { | |
let authHeaders: {[key: string]: string} = {}; | |
if (authTokenForApollo) { | |
authHeaders["Authorization"] = `Bearer ${authTokenForApollo}`; | |
} | |
return { | |
headers: { | |
...headers, | |
...authHeaders, | |
}, | |
}; | |
}); | |
const httpLink = createHttpLink({ | |
uri: getFinchApiUrl(), | |
}); | |
const authenticatedHttpLink = ApolloLink.from([authLink, httpLink]); | |
let link: ApolloLink; | |
if (authTokenForApollo) { | |
const actionCableConsumer = ActionCable.createConsumer( | |
`${getFinchActionCableUrl()}?token=${encodeURIComponent(authTokenForApollo)}`); | |
const actionCableLink = new ActionCableLink({ cable: actionCableConsumer }); | |
const hasSubscriptionOperation = (operation: Operation) => { | |
const { query: { definitions } } = operation; | |
return definitions.some( | |
(value: DefinitionNode) => { | |
const { kind, operation } = value as OperationDefinitionNode; | |
return kind === 'OperationDefinition' && operation === 'subscription'; | |
} | |
) | |
}; | |
const splitTransportLink = ApolloLink.split( | |
hasSubscriptionOperation, | |
actionCableLink, | |
authenticatedHttpLink, | |
); | |
link = ApolloLink.from([authLink, retryLink, errorLink, splitTransportLink]); | |
} else { | |
link = ApolloLink.from([authLink, retryLink, errorLink, authenticatedHttpLink]); | |
} | |
const apolloClientOptions = { | |
cache: cache, | |
link: link, | |
name: "your-app-name", | |
version: "1.0.0", | |
}; | |
return new ApolloClient(apolloClientOptions); | |
} | |
const ApolloClientProvider: React.FC = ({ children }) => { | |
const authToken = useAuthenticationState()?.authToken || null; | |
const apolloClient = React.useMemo(() => { | |
return createApolloClient(authToken); | |
}, [authToken]); | |
return ( | |
<ApolloProvider client={apolloClient}> | |
{children} | |
</ApolloProvider> | |
); | |
}; | |
export default ApolloClientProvider; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment