granate
Granate container for annotated GraphQL
Introduction
GraphQL is an amazing technology that allows to build application APIs in a much better way than by implementing REST services. On top of this, GraphQL can be defined using a textual representation (schema language) which offers a lot of really useful possibilities. Granate leverages these possibilities.
Usage
To understand better how to use granate, please have a look at the examples in granate-showcase
Installation
In order to use granate from the CLI, install granate-cli with the following command:
> npm i -g granate-cli
If you prefer to use granate as an API, install granate and graphql (peer dependency of granate) in your application with the following command:
> npm i granate graphql --save
Where does granate come from? (TL;DR)
Imagine that you want to implement a Todo application and you have drafted a GraphQL schema which looks as follows:
# Domain entity which represents a Todo object
type Todo {
id: ID!
title: String!
completed: Boolean!
}
# Query model for Todos
type Query {
# Returns the collection of Todos filtered by completed status (optional)
todos(completed: Boolean): [Todo]
}
# Mutations for Todos
type Mutation {
# Adds an uncompleted Todo with the given description
addTodo(title: String!): Todo!
# Removes a Todo by id
removeTodo(id: ID!): Todo!
# Toggles the completed state of a Todo by id
toggleTodo(id: ID!): Todo!
}
As of graphql-js@0.7.0, by
using the buildSchema()
and graphql()
functions together with an object like the one below as
rootValue
, it is then possible to execute GraphQL queries and mutations against the object as if it were a
full-fledged GraphQL endpoint.
{ thisnextId = Date; thistodos = ; } { return thistodos; { return completed === undefined ? todo : todocompleted === completed; } } { const todo = id: StringthisnextId++ title completed: false ; thistodos; return todo; } { const todo = thistodos0; todos; return todo; } { const todo = thistodos0; todocompleted = !todocompleted; return todo; }
Then you can use this as:
;; const schemaText = `# Domain entity which represents a Todo objecttype Todo {... content skipped`;const query = ` { todos { title completed } }`;const todos = ; ; // prints the query result
And if you want to make this API available through HTTP:
;;;; const PORT = 4000;const schemaText = `# Domain entity which represents a Todo objecttype Todo {... content skipped`;const todos = ;const graphqlHTTPConfig = ; ; { return schema rootValue graphiql: true ;}
Wouldn't it be cool if we could avoid defining the rootValue
implementation and use instead mock data like the one
generated by casual or faker.js?
This would allow to mock an API just by using a GraphQL schema text file.
Well, we easily can if we use the package graphql-tools
as explained in Mocking your server with just one line of code.
- But, wouldn't it be better if we could start with a schema file and default mock data and incrementally
refine the mock data or even the implementation to use as
rootValue
? - And what if we could use mock data where the root value provides no implementation?
- Couldn't we eventually use a legacy REST API to implement part of the schema?
- And if we could reuse not only existing REST APIs but also GraphQL endpoints?
- Even better, what if I could just install a library and do all this from the CLI without writing any code?