Skip to content

Instantly share code, notes, and snippets.

@wellitongervickas
Created November 25, 2023 19:25
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save wellitongervickas/087fb0d0550c429aae4500e4e4e9f624 to your computer and use it in GitHub Desktop.
Save wellitongervickas/087fb0d0550c429aae4500e4e4e9f624 to your computer and use it in GitHub Desktop.
graphql-ws payload data fix
import { ApolloClient, InMemoryCache, ApolloLink } from '@apollo/client'
import { RetryLink } from '@apollo/client/link/retry'
import { split, HttpLink } from '@apollo/client'
import { getMainDefinition } from '@apollo/client/utilities'
import { SubscriptionClient } from 'subscriptions-transport-ws'
import { WebSocketLink } from '@apollo/client/link/ws'
const API_URL = process.env.NEXT_PUBLIC_AWS_GRAPHQL_ENDPOINT!
const API_KEY = process.env.NEXT_PUBLIC_AWS_GRAPHQL_X_API_KEY!
const WSS_URL = API_URL.replace('https', 'wss').replace(
'appsync-api',
'appsync-realtime-api'
)
const HOST = API_URL.replace('https://', '').replace('/graphql', '')
const api_header = {
host: HOST,
'x-api-key': API_KEY
}
function getWebsocketUrl() {
const header = btoa(JSON.stringify(api_header))
const payload = btoa(JSON.stringify({}))
const url = `${WSS_URL}?header=${header}&payload=${payload}`
return url
}
const httpLink = new HttpLink({
uri: API_URL
})
const wsLink = new WebSocketLink(
new SubscriptionClient(getWebsocketUrl(), {
reconnect: true,
connectionCallback(error, result) {
console.log('WS-CONNECTION-CALLBACK', error, result)
},
connectionParams: {
authorization: api_header
}
})
)
const sptliLink = split(
({ query }) => {
const definition = getMainDefinition(query)
return (
definition.kind === 'OperationDefinition' &&
definition.operation === 'subscription'
)
},
wsLink,
httpLink
)
const retryLink = new RetryLink({
delay: {
initial: 1000,
max: Infinity,
jitter: true
},
attempts: {
max: 20,
retryIf: (error, op) => {
console.log('WS-RETRY-ERROR', error, op)
return !!error
}
}
})
const middlewareLink = new ApolloLink((operation, forward) => {
// auth mode
operation.extensions = {
...operation.extensions,
authorization: api_header
}
// fix data payload (HERES THE HOPE)
Object.assign(operation, {
data: JSON.stringify({
query: operation.query.loc?.source.body,
variables: operation.variables
})
})
// http request
operation.setContext({
headers: {
...api_header
}
})
return forward(operation)
})
const link = ApolloLink.from([middlewareLink, retryLink, sptliLink])
const cache = new InMemoryCache()
const client = new ApolloClient({
link,
cache
})
type Client = typeof client
export type { Client }
export default client
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment