I am currently loading the GraphQL schema using a separate .graphql
file, but it is encapsulated within strings:
schema.graphql
const schema = `
type CourseType {
_id: String!
name: String!
}
type Query {
courseType(_id: String): CourseType
courseTypes: [CourseType]!
}
`
module.exports = schema
Then using it for the apollo-server
:
index.js
const { ApolloServer, makeExecutableSchema } = require('apollo-server')
const typeDefs = require('./schema.graphql')
const resolvers = { ... }
const schema = makeExecutableSchema({
typeDefs: typeDefs,
resolvers
})
const server = new ApolloServer({
schema: schema
})
server.listen().then(({ url }) => {
console.log(`Server ready at ${url}.`)
})
Is there any way to simply load a .graphql that looks as such?
schema.graphql
type CourseType {
_id: String!
name: String!
}
type Query {
courseType(_id: String): CourseType
courseTypes: [CourseType]!
}
Then it would be parsed in the index.js
? I noticed that graphql-yoga
supports this, but was wondering if apollo-server
does. I cannot find it anywhere in the docs. I can’t get fs.readFile
to work either.
1
6 Answers
If you define your type definitions inside a .graphql
file, you can read it in one of several ways:
1.) Read the file yourself:
const { readFileSync } = require('fs')
// we must convert the file Buffer to a UTF-8 string
const typeDefs = readFileSync(require.resolve('./type-defs.graphql')).toString('utf-8')
2.) Utilize a library like graphql-tools
to do it for you:
const { loadDocuments } = require('@graphql-tools/load');
const { GraphQLFileLoader } = require('@graphql-tools/graphql-file-loader');
// this can also be a glob pattern to match multiple files!
const typeDefs = await loadDocuments('./type-defs.graphql', {
file,
loaders: [
new GraphQLFileLoader()
]
})
3.) Use a babel plugin or a webpack loader
import typeDefs from './type-defs.graphql'
8
-
1
This is amazing! No way there's an equivalent
GraphQLFileLoader
method fromapollo-server
?– Sam SverkoJun 9, 2020 at 21:38
-
1
Maybe in a future version.
– Daniel ReardenJun 9, 2020 at 22:15
-
It should be noted that
readFileSync
only returns a string if you specify an encoding, eg:const typeDefs = readFileSync('./schema.graphql', 'utf-8')
. If you do not include an encoding, it returns as a Buffer which ApolloServer's constructor does not understand.– SoviutDec 20, 2020 at 5:24
-
thank you for noting about
'utf-8'
inreadFileSync
, I would have missed that– Paul MikulskisNov 9, 2021 at 22:19
-
@DanielRearden I am getting this error when loading a subgraph schema in a federated graph
ts Unknown directive "@key". Cannot extend type "Membership" because it is not defined. Unknown directive "@key". Unknown directive "@external". Unknown type "Query".
– Hazem AlabiadJan 11, 2022 at 12:32
Back in the day I wrote a teeny-tiny .graphql
loader myself. It is very small, very simple, and the only thing you have to do is import it before you try to import any .graphql
files. I have used it ever since even though I am sure that there are some 3rd party loaders available. Here’s the code:
// graphql-loader.js
const oldJSHook = require.extensions[".js"];
const loader = (module, filename) => {
const oldJSCompile = module._compile;
module._compile = function (code, file) {
code = `module.exports = `r${code}`;`;
module._compile = oldJSCompile;
module._compile(code, file);
};
oldJSHook(module, filename);
};
require.extensions[".graphql"] = loader;
require.extensions[".gql"] = loader;
And then in your app:
// index.js
import "./graphql-loader"; // (or require("./graphql-loader") if you prefer)
That’s it, you can then import typeDefs from "./type-defs.graphql"
wherever you want.
The loader works by wrapping the text in your .graphql
file inside a template string and compiling it as a simple JS module:
module.exports = ` ...your gql schema... `;
This worked for me:
const { gql } = require('apollo-server');
const fs = require('fs');
const path = require('path');
//function that imports .graphql files
const importGraphQL = (file) =>{
return fs.readFileSync(path.join(__dirname, file),"utf-8");
}
const gqlWrapper = (...files)=>{
return gql`${files}`;
}
const enums = importGraphQL('./enums.graphql');
const schema = importGraphQL('./schema.graphql');
module.exports = gqlWrapper(enums,schema);
0
Figured it out using fs
(thanks to Tal Z):
index.js
const fs = require('fs')
const mongoUtil = require('./mongoUtil')
const { ApolloServer, makeExecutableSchema } = require('apollo-server')
function readContent (file, callback) {
fs.readFile(file, 'utf8', (err, content) => {
if (err) return callback(err)
callback(null, content)
})
}
mongoUtil.connectToServer((error) => {
if (error) {
console.error('Error connecting to MongoDB.', error.stack)
process.exit(1)
}
console.log('Connected to database.')
const Query = require('./resolvers/Query')
const resolvers = {
Query
}
readContent('./schema.graphql', (error, content) => {
if (error) throw error
const schema = makeExecutableSchema({
typeDefs: content,
resolvers
})
const server = new ApolloServer({
schema: schema
})
server.listen().then(({ url }) => {
console.log(`Server ready at ${url}.`)
})
})
})
schema.graphql
type CourseType {
_id: String!
name: String!
}
type Query {
courseType(_id: String): CourseType
courseTypes: [CourseType]!
}
0
I use this helper:
import { readFileSync } from "fs";
const requireGQL = (file) =>
gql`${readFileSync(require.resolve(file)).toString("utf-8")}`;
Throw that at the top of your file and you can just:
const client = new ApolloClient({ uri: 'https://myendpoint.com/graphql' });
const { data } = await client.query({ query: requireGQL("./myquery.gql") });
For anyone who is looking for the Apollo documentation for this question here it is: https://www.apollographql.com/docs/apollo-server/workflow/generate-types
It describes using readFileSync
like many answers here, but I was having trouble finding where they actually describe this method. Here’s the snippet as well:
// ...other imports
import { readFileSync } from 'fs';
// Note: this uses a path relative to the project's
// root directory, which is the current working directory
// if the server is executed using `npm run`.
const typeDefs = readFileSync('./schema.graphql', { encoding: 'utf-8' });
const server = new ApolloServer<MyContext>({
typeDefs,
resolvers,
});
// ... start our server
github.com/apollographql/graphql-tag#importing-graphql-files
Jun 9, 2020 at 21:11