Skip to content

Commit

Permalink
chore: move apollo links into separate files
Browse files Browse the repository at this point in the history
  • Loading branch information
alexander.pomazan committed Feb 11, 2019
1 parent e9d041f commit c59f1e3
Show file tree
Hide file tree
Showing 7 changed files with 110 additions and 76 deletions.
3 changes: 2 additions & 1 deletion .eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@ module.exports = {
"module": true,
"process": true,
"console": true,
"window": true
"window": true,
"global": true
},
"extends": [
"plugin:import/errors", // See https://github.com/benmosher/eslint-plugin-import
Expand Down
33 changes: 33 additions & 0 deletions src/common/apollo-middleware/create-afterware-link.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import { ApolloLink } from 'apollo-link'

import { storeTokensInCookie } from '../manage-token'

export const createAfterwareLink = () =>
new ApolloLink((operation, forward) => {
return forward(operation).map((response) => {
const { headers, cache } = operation.getContext()

// check if tokens were refreshed
if (headers && headers['x-token'] && headers['x-refresh-token']) {
const token = headers['x-token']
const refreshToken = headers['x-refresh-token']

const data = {
authState: {
__typename: 'authState',
token,
refreshToken
}
}

cache.writeData({ data })
if (typeof window !== 'undefined') {
// make sure to only do this on client as this
// will try to access window.document
storeTokensInCookie(token, refreshToken)
}
}

return response
})
})
20 changes: 20 additions & 0 deletions src/common/apollo-middleware/create-auth-link.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { setContext } from 'apollo-link-context'

import { getTokens } from '../localState'

export const createAuthLink = () =>
setContext((_, { headers, cache }) => {
const {
authState: { token, refreshToken }
} = cache.readQuery({
query: getTokens
})

return {
headers: {
...headers,
['x-token']: token || '',
['x-refresh-token']: refreshToken || ''
}
}
})
16 changes: 16 additions & 0 deletions src/common/apollo-middleware/create-state-link.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { withClientState } from 'apollo-link-state'

import { localStateResolvers } from '../localState'

export const createStateLink = (cache, token, refreshToken) =>
withClientState({
cache,
defaults: {
authState: {
__typename: 'authState',
token,
refreshToken
}
},
resolvers: localStateResolvers
})
22 changes: 22 additions & 0 deletions src/common/apollo-middleware/create-ws-link.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import getConfig from 'next/config'
import { WebSocketLink } from 'apollo-link-ws'

import { extractTokens } from '../manage-token'

const {
publicRuntimeConfig: { WS_ENDPOINT }
} = getConfig()

export const createWsLink = () =>
process.browser
? new WebSocketLink({
uri: WS_ENDPOINT,
options: {
reconnect: true,
connectionParams: () => {
const { token, refreshToken } = extractTokens()
return { token, refreshToken }
}
}
})
: null
4 changes: 4 additions & 0 deletions src/common/apollo-middleware/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export { createAfterwareLink } from './create-afterware-link'
export { createAuthLink } from './create-auth-link'
export { createWsLink } from './create-ws-link'
export { createStateLink } from './create-state-link'
88 changes: 13 additions & 75 deletions src/common/init-apollo.js
Original file line number Diff line number Diff line change
@@ -1,19 +1,20 @@
import { ApolloClient } from 'apollo-client'
import { InMemoryCache } from 'apollo-cache-inmemory'
import { HttpLink } from 'apollo-link-http'
import { withClientState } from 'apollo-link-state'
import { ApolloLink, split } from 'apollo-link'
import { setContext } from 'apollo-link-context'
import { getMainDefinition } from 'apollo-utilities'
import fetch from 'isomorphic-unfetch'
import getConfig from 'next/config'
import { WebSocketLink } from 'apollo-link-ws'

import { storeTokensInCookie, extractTokens } from './manage-token'
import { localStateResolvers, getTokens } from './localState'
import {
createAfterwareLink,
createAuthLink,
createWsLink,
createStateLink
} from './apollo-middleware'

const {
publicRuntimeConfig: { GRAPHQL_ENDPOINT, WS_ENDPOINT, DEVELOPMENT_MODE }
publicRuntimeConfig: { GRAPHQL_ENDPOINT, DEVELOPMENT_MODE }
} = getConfig()

let apolloClient = null
Expand All @@ -25,77 +26,15 @@ if (!process.browser) {

function create(initialState, { token = '', refreshToken = '' }) {
const cache = new InMemoryCache().restore(initialState || {})
// this link will handle refreshing of out tokens
const afterwareLink = new ApolloLink((operation, forward) => {
return forward(operation).map((response) => {
const { headers, cache } = operation.getContext()

// check if tokens were refreshed
if (headers && headers['x-token'] && headers['x-refresh-token']) {
const token = headers['x-token']
const refreshToken = headers['x-refresh-token']

const data = {
authState: {
__typename: 'authState',
token,
refreshToken
}
}

cache.writeData({ data })
if (typeof window !== 'undefined') {
// make sure to only do this on client as this
// will try to access window.document
storeTokensInCookie(token, refreshToken)
}
}

return response
})
})
// this link will handle refreshing of our tokens
const afterwareLink = createAfterwareLink()

// this link will extract token from apollo-link-state and add it to request's headers
const authLink = setContext((_, { headers, cache }) => {
const {
authState: { token, refreshToken }
} = cache.readQuery({
query: getTokens
})

return {
headers: {
...headers,
['x-token']: token || '',
['x-refresh-token']: refreshToken || ''
}
}
})
const authLink = createAuthLink()

const wsLink = process.browser
? new WebSocketLink({
uri: WS_ENDPOINT,
options: {
reconnect: true,
connectionParams: () => {
const { token, refreshToken } = extractTokens()
return { token, refreshToken }
}
}
})
: null

const stateLink = withClientState({
cache,
defaults: {
authState: {
__typename: 'authState',
token,
refreshToken
}
},
resolvers: localStateResolvers
})
const wsLink = createWsLink()

const stateLink = createStateLink(cache, token, refreshToken)

const httpLink = new HttpLink({
uri: GRAPHQL_ENDPOINT
Expand All @@ -118,7 +57,6 @@ function create(initialState, { token = '', refreshToken = '' }) {
)
: httpLinkWithState

// Check out https://github.com/zeit/next.js/pull/4611 if you want to use the AWSAppSyncClient
return new ApolloClient({
connectToDevTools: process.browser && DEVELOPMENT_MODE,
ssrMode: !process.browser, // Disables forceFetch on the server (so queries are only run once)
Expand Down

0 comments on commit c59f1e3

Please sign in to comment.