GraphQL Scanner
Define your GraphQL types in separate files
Introduction
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
Quickstart
Install the dependency
$ npm install graphql-scanner --save
Create a types directory
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
Define your types
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:
types/Query.js
moduleexports = typeDef: ` type Query { currentUser: User } ` resolver: { const apikey = ctx; return firstName: "John" lastName: "Do" apikey ; } ;
types/User.js
moduleexports = typeDef: ` type User { firstName: String! lastName: String apikey: String todoLists: [TodoList] } ` resolver: { return Promise; } ;
types/TodoList.js
moduleexports = typeDef: ` type TodoList { subject: String! tasks: [String] } ` resolver: { return Promise; } ;
Use the GraphQL Scanner
You need to pass the path to your directory that contain your types.
For example:
app.js:
const path = ;const graphqlScanner = ; // ... const dir = path;const typeDefs resolvers = ;const server = 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.
How does it work?
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 }