Skip to content

Instantly share code, notes, and snippets.

@jaydenseric
Created October 11, 2017 06:11
Show Gist options
  • Save jaydenseric/dccd8719ee41741df6d221815a0b0394 to your computer and use it in GitHub Desktop.
Save jaydenseric/dccd8719ee41741df6d221815a0b0394 to your computer and use it in GitHub Desktop.
Custom fragment matcher and schema fetching script for `apollo-cache-inmemory`.
GRAPHQL_URI=http://localhost:3001/graphql
{
"schemaPath": "schema.graphql",
"extensions": {
"endpoints": {
"development": "${env:GRAPHQL_URI}"
}
}
}
import InMemoryCache from 'apollo-cache-inmemory'
import createFragmentMatcher from './fragment-matcher'
import implementations from './schema-implementations.json'
const cache = new InMemoryCache({
fragmentMatcher: createFragmentMatcher(implementations)
})
export default implementations => ({
match: ({ id }, typename, { store }) => {
const cached = store[id]
if (!cached) return false
if (!cached.__typename)
throw new Error(
`Missing __typename to match fragment: ${JSON.stringify(cached)}`
)
return (
typename === cached.__typename ||
(implementations[typename] &&
implementations[typename].includes(cached.__typename))
)
}
})
{
"dependencies": {
"apollo-cache-inmemory": "^0.2.0-beta.5",
"dotenv-cli": "^1.4.0"
},
"devDependencies": {
"graphql-config": "^1.0.7"
},
"scripts": {
"update-schema": "dotenv node update-schema"
}
}
{
"Person": [
"Student",
"Teacher"
]
}
interface Person {
id: ID!
name: String!
}
type Student implements Person {
id: ID!
name: String!
}
type Teacher implements Person {
id: ID!
name: String!
}
const { getGraphQLProjectConfig, writeSchema } = require('graphql-config')
const { writeFile } = require('fs')
const { promisify } = require('util')
const writeFileAsync = promisify(writeFile)
const projectConfig = getGraphQLProjectConfig()
const endpoint = projectConfig.endpointsExtension.getEndpoint('development')
endpoint
.resolveSchema()
.then(schema => {
const updateSchema = writeSchema(projectConfig.schemaPath, schema)
const updateImplementations = writeFileAsync(
'schema-implementations.json',
`${JSON.stringify(schema._implementations, null, 2)}\n`
)
Promise.all([updateSchema, updateImplementations])
.then(() => console.log('Updated schema.'))
.catch(console.error)
})
.catch(console.error)
@jaydenseric
Copy link
Author

jaydenseric commented Oct 11, 2017

Following on from this discussion.

The update-schema script simultaneously generates schema-implementations.json for the custom fragment matcher, as well as schema.graphql for eslint-plugin-graphql and other tools that refer to .graphqlconfig from a remote GraphQL API.

.graphqlconfig can be configured for a .graphql or .json schema; I choose to use .graphql because it is about 7 thousand lines smaller for versioning and easier to read.

To my knowledge, schema._implementations works for both unions and interfaces but I could be wrong, since we don't use unions and I havn't tested it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment