Hi @KrasniqiR Absolutely!
As @danny noted, the logic to assemble the links (and terminating link) isn’t a flexible as it could be – and would be great to get some ideas to make it easier to add a link like that for the upload client.
You can see the code starting here: redwood/packages/web/src/apollo/index.tsx at 2d134a8a54f32684f58fa195727cfaf52f761019 · redwoodjs/redwood · GitHub
// A terminating link. Apollo Client uses this to send GraphQL operations to a server over HTTP.
// See https://www.apollographql.com/docs/react/api/link/introduction/#the-terminating-link.
let httpLink = new HttpLink({ uri, ...httpLinkConfig })
if (globalThis.RWJS_EXP_STREAMING_SSR) {
httpLink = new HttpLink({ uri, fetch: crossFetch, ...httpLinkConfig })
}
// Our terminating link needs to be smart enough to handle subscriptions, and if the GraphQL query
// is subscription it needs to use the SSELink (server sent events link).
const httpOrSSELink =
typeof SSELink !== 'undefined'
? apolloClient.split(
({ query }) => {
const definition = getMainDefinition(query)
return (
definition.kind === 'OperationDefinition' &&
definition.operation === 'subscription'
)
},
new SSELink({
url: uri,
auth: { authProviderType, tokenFn: getToken },
httpLinkConfig,
headers,
}),
httpLink,
)
: httpLink
/**
* Use Trusted Documents aka Persisted Operations aka Queries
*
* When detecting a meta hash, Apollo Client will send the hash from the document and not the query itself.
*
* You must configure your GraphQL server to support this feature with the useTrustedDocuments option.
*
* See https://www.apollographql.com/docs/react/api/link/persisted-queries/
*/
interface DocumentNodeWithMeta extends apolloClient.DocumentNode {
__meta__?: {
hash: string
}
}
// Check if the query made includes the hash, and if so then make the request with the persisted query link
const terminatingLink = apolloClient.split(
({ query }) => {
const documentQuery = query as DocumentNodeWithMeta
return documentQuery?.['__meta__']?.['hash'] !== undefined
},
createPersistedQueryLink({
generateHash: (document: any) => document['__meta__']['hash'],
}).concat(httpOrSSELink),
httpOrSSELink,
)
// The order here is important. The last link *must* be a terminating link like HttpLink, SSELink, or the PersistedQueryLink.
const redwoodApolloLinks: RedwoodApolloLinks = [
{ name: 'withToken', link: withToken },
{ name: 'authMiddleware', link: authMiddleware },
{ name: 'updateDataApolloLink', link: updateDataApolloLink },
{ name: 'httpLink', link: terminatingLink },
]
let link = redwoodApolloLink
link ??= ApolloLink.from(redwoodApolloLinks.map((l) => l.link))
if (typeof link === 'function') {
link = link(redwoodApolloLinks)
}
const client = new ApolloClient({
// Default options for every Cell. Better to specify them here than in `beforeQuery` where it's too easy to overwrite them.
// See https://www.apollographql.com/docs/react/api/core/ApolloClient/#example-defaultoptions-object.
defaultOptions: {
watchQuery: {
// The `fetchPolicy` we expect:
//
// > Apollo Client executes the full query against both the cache and your GraphQL server.
// > The query automatically updates if the result of the server-side query modifies cached fields.
//
// See https://www.apollographql.com/docs/react/data/queries/#cache-and-network.
fetchPolicy: 'cache-and-network',
// So that Cells rerender when refetching.
// See https://www.apollographql.com/docs/react/data/queries/#inspecting-loading-states.
notifyOnNetworkStatusChange: true,
},
},
link,
...rest,
})
There are like two approaches:
- Make the configuration “more flexible” to add other links
- Add the upload link to the framework (like SSELink is).
If the latter, then there is some other consideration needed:
- Make it optional, ie, if “upload” is enabled, the link is added
This requires some vite config as don’t always want to include:
!realtimeEnabled &&
removeFromBundle([
{
id: /@redwoodjs\/web\/dist\/apollo\/sseLink/,
},
]),
And some documentation on how to use with Yoga: File Uploads (Yoga)
If you want to add a GitHub issue RFC, we can bring in the team to discuss an approach.