Friday, 17 November, 2017 UTC


Summary

Graphcool, a popular GraphQL backend as a service solution recently moved away from the pure BaaS model and into an open source model instead with the Graphcool framework. Using the Graphcool framework, it’s easier than ever to spin-up and deploy GraphQL backends on either Graphcool’s shared infrastructure, locally in a Docker container, or on something like AWS. Graphcool framework backends are known as services.
In this quick intro we’ll cover how to get started with creating and deploying a basic GraphQL service to one of Graphcool’s shared clusters.
Note that this post assumes basic knowledge of GraphQL's schema definition language.
Installation
First, you’ll need the Graphcool CLI installed globally on your machine:
$ npm install graphcool -g # or, using Yarn: $ yarn global add graphcool
Then, you’ll also want to install GraphQL Playground on your machine for an easy IDE to interact with your GraphQL API.
Getting Started
Initialize a new Graphcool service using the init command. Here we’ll create a simple todo service:
$ graphcool init todo-service
The command creates a base service with the following starting file structure:
├─ types.graphql ├─ src │ ├─ hello.js │ └─ hello.graphql ├─ graphcool.yml └─ package.json
Here’s a quick breakdown of the different files:
  • types.graphql: This is for defining your GraphQL schema, using GraphQL’s schema definition language (SDL).
  • graphcool.yml: Configuration file for your service. This is where permission rules and functions are configured.
  • hello.js & hello.graphql: A sample Resolver function, which can be deleted. Three types of functions are possible using Graphcool: Resolver functions for extending your API, Hook functions for data transformation and validation and Subscription functions to perform tasks when certain events happen with the service (e.g.: a node is created, updated or deleted).
  • package.json: If your service defines functions that depend on any npm package, this is where the dependencies would be added.
Configuration & Setup
Now that you have a basic service in place, let’s slightly change the graphcool.yml and types.graphql files to accomodate our simple needs for a todo app.
First, our schema definition:
types.graphql
type User @model { id: ID! @isUnique createdAt: DateTime! updatedAt: DateTime! name: String todos: [Todo!]! @relation(name: "UserTodos") } type Todo @model { id: ID! @isUnique createdAt: DateTime! updatedAt: DateTime! title: String! description: String! completed: Boolean! @defaultValue(value: false) owner: User! @relation(name: "UserTodos") }
We only have two types for our service: User and Todo. We also added a one to many relation between a user and todo nodes called UserTodos. A user can have many todos, and todos have exactly one owner.
The id, createdAt and updatedAt fields are read-only and are managed by Graphcool. The createdAt and updatedAt fields are optional.

Then, our service definition:
graphcool.yml
types: ./types.graphql permissions: - operation: "User.create" - operation: "User.read" - operation: "Todo.create" authenticated: true - operation: UserTodos.connect authenticated: true - operation: "Todo.read" authenticated: true query: ./permissions/todo.graphql - operation: "Todo.update" authenticated: true query: ./permissions/todo.graphql - operation: "Todo.delete" authenticated: true query: ./permissions/todo.graphql
First our service definition references our schema definition, and then we set a few permission rules our Todo and User fields.
Notice how the permissions for Todo nodes also reference a query file. That file should be a GraphQL query that returns a boolean to indicate if the operation should be permitted or not. Here’s a sample of such query:
./permissions/todo.graphql
query ($node_id: ID!, $user_id: ID!) { SomeTodoExists( filter: { id: $node_id, owner: { id: $user_id } } ) }
The query gets the user id for the authenticated user as well as the node id for the node that’s trying to access the permission. We can query using a filter that the node in question exists and that its owner is the currently authenticated user.
Also, you’ll notice that we have to explicitly define a permission for our relation (UserTodos.connect). Without such permission, a todo wouldn’t be permitted to be associated with its owner.
Authentication
We’ve setup permissions for Todo nodes that require a user to be authenticated, but we haven’t added any form of authentication yet. This can be done easily using a pre-defined template provided by Graphcool. Here’s we’ll demonstrate how to setup the email-password auth template.
Using the Graphcool CLI, add the template to your service using the add-template command:
$ graphcool add-template graphcool/templates/auth/email-password
This will add a bunch of files in a src folder for 3 resolver functions: signup, authenticate and loggedInUser. It’ll also add new dependencies to the service’s package.json file. You don’t need to modify these files.
At this point, you can run npm install or yarn install to ensure that the dependencies are installed locally.
The add-template command also added the function definition to graphcool.yml and a User type in types.graphql, but these additions are commented, as to not interfere with your current definitions. You’ll need to uncomment the additions in graphcool.yml and merge the additions to the User type.
This is what our service definition file now looks like:
graphcool.yml
types: ./types.graphql functions: signup: type: resolver schema: src/email-password/signup.graphql handler: code: src/email-password/signup.ts authenticate: type: resolver schema: src/email-password/authenticate.graphql handler: code: src/email-password/authenticate.ts loggedInUser: type: resolver schema: src/email-password/loggedInUser.graphql handler: code: src/email-password/loggedInUser.ts permissions: # ...our permissions, same as before

And this is what our schema definition now looks like:
types.graphql
type User @model { id: ID! @isUnique createdAt: DateTime! updatedAt: DateTime! email: String! @isUnique password: String! name: String todos: [Todo!]! @relation(name: "UserTodos") } type Todo @model { id: ID! @isUnique createdAt: DateTime! updatedAt: DateTime! title: String! description: String! completed: Boolean! @defaultValue(value: false) owner: User! @relation(name: "UserTodos") }
The two additions to our schema are the email required and unique field and the password required field.
Deployment
With all of this in place, we’re ready to deploy our simple todo GraphQL service. We can deploy locally to a Docker container or deploy online to a shared cluster. Let’s do the latter here, but keep in mind that you’ll need a user account with Graphcool to deploy to a shared cluster.
Deploying is as simple as running the graphcool deploy command:
$ graphcool deploy
First you’ll be prompted to choose a location for the shared cluster, then a target name, which can be anything you’d like (here we’ll call it dev) and finally a name for your service. You’ll then be prompted to authenticate to your Graphcool account.
After the deployment is successful, you’ll get back the endpoint information for your GraphQL service. To get that information again in the future, you can simply run graphcool info.
A new file .graphcoolrc is also added locally to the project with content that looks like this for your deployment target information:
.graphcoolrc
targets: dev: shared-us-west-2/___SERVICE_ID_____ default: dev
Testing Out Using GraphQL Playground
Now that our service is live, we can test out some CRUD operations using the GraphQL Playground IDE. Simply add the URL for the simple API you got back when deploying as the endpoint URL.
Let’s create a new user in the playground using the following mutation:
mutation { createUser(email: "[email protected]", password: "DontSay", name: "Bob") { id } }
This will create and user and return its ID. To authenticate as that user and get an authorization token, we can run the authenticateUser mutation:
mutation authenticateUser { authenticateUser(email: "[email protected]", password: "DontSay") { token } }
In the GraphQL playground you’ll need to add an Authorization HTTP header with the value Bearer followed by a space and the token received back from the user authentication mutation. To test that the authorization header is working, you can run the following query, which should return the user id:
query isLoggedIn { loggedInUser { id } }

Now that you’ve created a user and authenticated, we can create todo items. Here for example we’re create 2 todo nodes:
mutation createTodo1 { createTodo( title: "Buy milk", description: "whole milk please", ownerId: "cja4dk2id82vy0155jhqlhowv" # the user id ) { completed description title } } mutation createTodo2 { createTodo( title: "Repair the shed", description: "arrg, I need to get my tools", ownerId: "cja4dk2id82vy0155jhqlhowv", completed: true ) { completed description title }
And finally, we can run the following query to get all the todo items:
query getTodos { allTodoes { description title } }
That’s it! You now have a working GraphQL backend. You can evolve and add to the schema and simply re-deploy to make changes to your service.
🏓 This introduction barely scratched the surface, so we'll dive peeper in future posts, especially as it relates to building a frontend to interface with our GraphQL service. You can also refer to the official Graphcool docs to learn more.