Define your GraphQL types in separate files
A GraphQL server generally needs two things: a typeDefs
string and a resolvers
object.
- The
typeDefs
string contains the schema definitions, resolvers
object describes how to resolve certain attributes of a type.
The problem is, both the typeDefs
and resolvers
can get huge and/or impractical to use.
Enter GraphQL Scanner! A tiny util that allows you to define each type (and their matching resolver) in a separate file.
Tested with Apollo Server, but should also work with GraphQL.js and express-graphql
$ npm install graphql-scanner --save
Create a 'types' directory in your project, and use it to store your GraphQL types.
For example:
├── types
| ├── Query.js
| └── TodoList.js
| └── User.js
├── app.js
Each type MUST expose an object containing two attributes:
typeDef
(String, required): the GraphQL schema definition of your typeresolver
(Object, optional): an object to resolve certain attributes of the type you've defined
For example:
module.exports = {
typeDef: `
type Query {
currentUser: User
}
`,
resolver: {
currentUser(_, args, ctx) {
const { apikey } = ctx;
return {
firstName: "John",
lastName: "Do",
apikey
};
}
}
};
module.exports = {
typeDef: `
type User {
firstName: String!
lastName: String
apikey: String
todoLists: [TodoList]
}
`,
resolver: {
todoLists(user, args, ctx) {
return Promise.resolve([
{
subject: 'Holidays',
}
]);
}
}
};
module.exports = {
typeDef: `
type TodoList {
subject: String!
tasks: [String]
}
`,
resolver: {
tasks(todoList, arg, ctx) {
return Promise.resolve(['Fix a cab', 'Book a flight']);
}
}
};
You need to pass the path to your directory that contain your types.
For example:
const path = require('path');
const graphqlScanner = require('graphql-scanner');
// ...
const dir = path.join(__dirname, './types');
const { typeDefs, resolvers } = graphqlScanner(dir);
const server = new GraphQLServer({ typeDefs, resolvers });
The graphqlScanner(dir)
expression scans your types and returns an object containing typeDefs
and resolvers
.
You can then pass these typeDefs
and resolvers
to your favourite GraphQL server library.
Check the code, it's less than 20 lines!
It uses require-all to load all modules in the dir
you've passed as an argument
Then, it will iterate over all loaded modules and
- append each individual
typeDef
string to atypeDefs
variable. - add each individual
resolver
to aresolvers
object as an attribute. The key of each attribute is the file name (minus extension) of the type
Finally, it will return an object: { typeDefs, resolvers }