Interface or Union for this type”. That’s when the trouble starts.
I was receiving this warning in my web development console. Warning! heristic fragment matching going on!
. I thought it was something I could solve in my GQL schema definitions and query files. Nope. You actually need to feed Apollo client some more information.
What’s more, a query I was using started returning { data: undefined}
even though I could see the network response showing the data come back just fine.
First you need to generate a JSON file that holds these possibleTypes
. This node file we’ll call generate-possible-types.js
and run with node node ./generate-possible-types
. Note, you will need node-fetch
installed to do this (e.g npm i node-fetch
)
const fetch = require('node-fetch');
const fs = require('fs');
fetch(`${YOUR_API_HOST}/graphql`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
variables: {},
query: `
{
__schema {
types {
kind
name
possibleTypes {
name
}
}
}
}
`,
}),
})
.then(result => result.json())
.then(result => {
// here we're filtering out any type information unrelated to unions or interfaces
const filteredData = result.data.__schema.types.filter(
type => type.possibleTypes !== null,
);
result.data.__schema.types = filteredData;
fs.writeFile('./fragment-types.json', JSON.stringify(result.data), err => {
if (err) {
console.error('Error writing fragmentTypes file', err);
} else {
console.log('Fragment types successfully extracted!');
}
});
});
The above script generates a file called fragment-types.json
looking something like
{"__schema":{"types":[{"kind":"INTERFACE","name":"Payment","possibleTypes":[{"name":"PropertyOrderPayment"},{"name":"PersonPayment"}]}]}}
Now you need to include this file in your frontend somewhere.
In the code that you setup apollo-client, you’ll need to add these lines
import introspectionQueryResultData from './fragment-types.json'
import { InMemoryCache, IntrospectionFragmentMatcher } from 'apollo-cache-inmemory'
const fragmentMatcher = new IntrospectionFragmentMatcher({
introspectionQueryResultData,
})
const cache = new InMemoryCache({ fragmentMatcher })
...include the cache in your regular apollo-client middleware
Someday I’ll move away from Apollo GraphQL and just use GraphQL Tools which is much more straight forward. Until that glorious day, I’ll remain in the fight with Apollo.
Image by Robin Higgins