https://gist.github.com/tomdavies/b88c68110333c5754f81f785ec0f270d
I'm attempting to override the cache in my apollo config so as to be able to define a fragmentMatcher
The relevant bit of my nuxt,config.js looks like this:
module.exports = {
...
// Modules
modules: ['@nuxtjs/apollo'],
apollo: {
// tokenName: 'yourApolloTokenName', // optional, default: apollo-token
includeNodeModules: true, // optional, default: false (this includes graphql-tag for node_modules folder)
authenticationType: 'Bearer', // optional, default: 'Bearer'
// required
clientConfigs: {
default: {
httpEndpoint: GRAPHQL_ENDPOINT,
cache: new InMemoryCache({ fragmentMatcher }),
},
},
},
...
}
The Apollo cache is replaced with the InMemoryCache passed in the cache key of clientConfigs, with the fragmentMatcher applied
A TypeError is thrown:
cache.transformDocument is not a function
Looking in my generated .nuxt/apollo-module.js (included in Gist) it looks as if the cache option I pass is getting stringified somewhere (?)
The issue described here seems relevant and involves the same error message but doesn't describe a fix.
PS I'm something of a noob when it comes to Apollo so apologies if I've missed something stupid
might be duplicate of #119 I will look into this but will also encourage to provide a PR because currently I won't have much time to dig into it.
Hey @dohomi thanks for the quick reply.
I took a quick pass at fixing the general case of making custom cache fns work locally. However because of the way Nuxt plugins work AFAICS we're stuck with eval if we want to pass a function into the template. That's not so bad for something like getAuth as we only need to return a string, but things get ugly very quickly as soon as we need any dependencies in or fn as it gets eval'ed in the scope of the generated apollo-module.js, not nuxt-config.js.
What I have working therefore feels super hacky as it involves the user putting any require() calls for dependencies for the custom cache _inside_ the cache fn inside of clientConfigs, which is pretty vile even if it works.
For my use case for now I've added an optional introspectionFragmentMatcherData key on the client config and used that to pass in the introspectionQueryResultData required. See here. That feels much cleaner (as we're just passing actual data, not string to eval) but obviously does nothing for the general use case such as in @gbouteiller's issue in #119.
Generally this seems like a hard problem to solve when using Nuxt plugin templates - a quick 10-15 min perusal of other Nuxt modules on GH didn't turn up any that pass fns from their module options into a template.
I'm also looking towards using apollo-link-state so currently thinking I'll probably need to roll my own custom apollo integration instead in order to do that
I'd love to hear feedback from @pi0 or @Atinux if they have experience in passing functions for plugins. Probably if you rely on a fast solution skip this module and run your own plugin and just depend on vue-cli-plugin-apollo/graphql-client which is a fair trade I guess.
Please share the solution you end up using - I will post that inside of the README for other users.
I tried to properly convert an object to string and then convert it back. All works, before native functions... I think there is no properly way to handle it this way.
May be its better to not pass objects through the options, but through creating an extension?
My experiments link: http://jsbin.com/semuvuleyu/edit?js,console
It's better to use javascript-serialization from yahoo ofc, but it will be crash every time on native functions...
Actually one way is to let user define custom function inside their plugin (extend the module), we do this for https://axios.nuxtjs.org/extend.html
I published a new release https://github.com/nuxt-community/apollo-module/releases/tag/v4.0.0-beta.6 Now you should be able to provide a path to your config and return your config as shown in the example. Please report back if this fixes your current issue
Thanks for the releas @dohomi, back on the project that鈥檚 using this tomorrow so will update and test then
Sorry to resurrect this one @dohomi...on 4.0.0-rc0, I'm using the path option to import a custom cache with fragmentMatcher. The apollo-module.js file appears to contain the config as expected, but I'm still getting both client.cache.extract is not a function and cache.transformDocument is not a function whenever I try to load a page.
Here's the config object that gets generated:
defaultClientConfig = {
"httpEndpoint": GQL_SERVER_ENDPOINT,
"cache": {
"optimistic": [],
"watches": [],
"typenameDocumentCache": {},
"silenceBroadcast": false,
"config": {
"fragmentMatcher": {
"possibleTypesMap": {
"Entry": [
"Global",
"SectionContentSummary",
"NavMenu",
"Page",
"SectionImagesText"
],
"Sys": [
"EntrySys",
"AssetSys"
]
},
"isReady": true
},
"addTypename": true
},
"addTypename": true,
"data": {
"data": {}
}
}
}
@dohomi I was just able to upgrade a project which uses a custom cache object from ^3.0.6 to 4.0.0-beta.6 without any code changes 鈥撀爐hanks!
@dohomi circling back to say that 4.0.0-beta6 fixed my issue and the module is working great for me now - many thanks
good to hear! thanks for reporting it back
@dohomi Unfortunately I was mistaken, the custom cache keys weren't being set. I've just tried to follow the pattern @tomdavies used, but I'm getting that same cache.transformDocument is not a function error. Currently on 4.0.0-beta.8.
Here's what I'm passing in from nuxt.config.js:
default: {
httpEndpoint: ENDPOINT,
cache: new InMemoryCache({ cacheRedirects: {
Query: {
postBy: (_, { slug }, { getCacheKey } ) => getCacheKey({ __typename: 'Post', slug }),
post: (_, { slug }, { getCacheKey } ) => getCacheKey({ __typename: 'Post', slug })
}
}}),
},
This is from the generated apollo-module.js, assuming this is the issue:
const defaultCache = '[object Object]' || new InMemoryCache()
@timhanlon currently rc0 is already out with some bugfixes. Beside that, are you providing your config to the path of your config file? Because thats essential for your use case
@dohomi Thanks, rc0 has fixed the issue 鈥撀營'm back to using the same config I was with v3.
I am still having this error. Any progress?
@sahilranpuri I've been using it like this since at least rc2.0 and it's working as expected.
// nuxt.config.js
apollo: {
clientConfigs: {
default: '~/apollo/config.js'
}
},
// /apollo/config.js
import cache from './cache'
export default function(ctx) {
const token = process.env.token
return {
httpEndpoint: `https://endpoint.com`,
getAuth: () => `Bearer ${token}`,
cache
}
}
// /apollo/cache.js
import { InMemoryCache, IntrospectionFragmentMatcher } from 'apollo-cache-inmemory'
import introspectionQueryResultData from './fragmentTypes.json'
const fragmentMatcher = new IntrospectionFragmentMatcher({
introspectionQueryResultData
})
export default new InMemoryCache({ fragmentMatcher })
@papertokyo this is a permanent solution!! You saved 2 days of my life. Thank you !!!
During development of a project, i was in a case where my graphql schema changes so instead of create a file manually each time i used nuxt hooks to fetch my schema and write the result in my schema file.
If anyone is interested here is the code:
in your nuxt.config.js file add
hooks: {
build: {
before (builder) {
axios.post('MySuperGraphqlEndpoint', {
query: `
query schema{
__schema{
types{
kind
name
possibleTypes {
name
description
}
}
}
}`
}).then(({ data }) => {
fs.writeFile('apollo/client-configs/schema.json', JSON.stringify(data.data) + '\r\n', ((err) => {
if (err) {
/* eslint-disable-next-line */
console.log(err)
}
}))
})
}
}
},
Used @papertokyo method. Finally got rid of all errors and everything works as intended! Thanks!
Big question though... my fragmentTypes.json file is... empty!
I was trying to understand how to use it, as it wasn't clear to me how to write its content, when I noticed it didn't really matter.
At the moment this is it:
{
"__schema": {
"types": [
]
}
}
Why does it work? What should be inside and how would make a difference?
For those who want to generate introspection json automatically there is also graphql-codegen introspection plugin.
https://www.graphql-code-generator.com/docs/plugins/introspection
Most helpful comment
@sahilranpuri I've been using it like this since at least rc2.0 and it's working as expected.