Structure of SailsJS+GraphQL application

If you're having troubles with organizing API for the [Node.js](https://kolosek.com/learn-about-node) app, using the [Sails.js](https://sailsjs.com/) framework with the [GraphQL](http://graphql.org/graphql-js/), know that you're not the only one - we've been there too.

Since this is not an every-day combination of technologies, it was challenging to define the anatomy of such app and its tests, but we did it!

Are you asking yourself questions like these: 
- How will I organize all the **queries** and **mutations**?
- Where will the **schema** be defined? 
- What should I do with the authorization and other utilities? 

*If the answer is yes, this article has answers to all of your questions!*

##Let's Start!

First, we'll generate our sails app (I assume you have [installed **NodeJS**](https://kolosek.com/install-nodejs-on-ubuntu/) and **Sails**, if not here's a little help how to [get started](https://sailsjs.com/get-started)):

     $ sails new graphql-app
     

If generated successfully, you should get a small app with a structure like this: 

![Sails project structure](https://storage.kraken.io/kk8yWPxzXVfBD3654oMN/a18c934d165196bc4696d5677987b0fa/sails-structure.png)

First, we will go through ***api/*** folder, what it and its subfolders contain:

![Sails API folder](https://storage.kraken.io/kk8yWPxzXVfBD3654oMN/3ecfbdb32b0c3ff03f2792b7e9c123a1/sails-api.png)


## Controllers
As the name says, this folder will contain our controllers, or, may I say, **a controller** since we are using GraphQL.
*This sentence really needs a [text-decoration:underline](https://kolosek.com/css-text-underlined/) - GraphQL needs **only one** controller to handle all the requests sent to the API.

The purpose of the controller is to redirect requests to the right **query** or the **mutation** field and return the resolved value back to the client.

## Graphql

This folder won't be created by default, so we'll need to create it ourselves.

Here, we will store all of our GraphQL related files: queries, mutations, types, schema, etc. We created a folder for each entity in our app's model and stored the queries and mutations for it, and also defined type and utils regarding the entity in that folder. 

So, the user model will have it's own folder with *UserQueries.js*, *UserMutations.js*, *UserType* and *UserUtils.js* (if necessary), profile model we'll have its own related files and so on...

Here's a visual representation:

![Sails GraphQL folder](https://storage.kraken.io/kk8yWPxzXVfBD3654oMN/8596fc2aba90eb1990587f0ac4f5e33f/sails-graphql.png)

The root folder will contain the ***schema.js*** file, in which we'll combine all the queries and mutations into one big **GraphQL schema**.

*We initially chose SailsJS due to how similar it was to [Rails](https://kolosek.com/install-ruby-on-rails-on-ubuntu/).*

## Model
Once again, this is a self-explanatory directory which will contain all of our app ***models***.

A model represents a collection of structured data, usually corresponding to a single table or collection in a database. We will hold basic models in the root of the ***model/*** folder, and all the models related to our basic models in a separate folder.

For example, basic information about a user will be held in ***User.js*** model, but his details will be stored in ***Profile.js*** model, which will be contained in subfolder ***models/user/*** :

![Sails models](https://storage.kraken.io/kk8yWPxzXVfBD3654oMN/601eba447c5fc37503e67015adfccb0b/sails-models.png).

## Policies

Policies in SailsJS are versatile tools for authorization and access control. The policy file is defined for a specific route and since we will have only one controller accessed through **POST /graphql**, we will have only one policy file.

Through the policy, we will allow or deny clients' access to our GraphQL controller (our client is an universal [ReactJS](https://kolosek.com/react-jsx-loops/) app!).

## Responses
Sails comes with a handful of the most common response types by default and they can be found in ***api/responses*** directory. You are free to edit them, add new ones or remove them if you think they are unnecessary.

Since all the traffic is going through one specific controller, we will keep only 2 of those responses and create a new one. We will keep ***ok.js*** and ***badRequest.js***, since those are the only 2 responses our GraphQL controller can provide us, and we will create ***unauthorized.js*** which we will send if the request hasn't passed our policy mentioned above.

![Sails responses](https://storage.kraken.io/kk8yWPxzXVfBD3654oMN/2ad3114d4f90888edf961cd150b050f6/sails-responses.png)


## Services

Services are stateless libraries of functions (**helpers**) you can use from anywhere in your Sails app. For example, you might have an ***EmailService.js*** which tidily wraps up one or more helper functions so you can use them in more than one place within your application.

Services and their helpers are the best and simplest way to build reusable code in a Sails app. The greatest thing about them is that they are globalized, which means you can use them without having to **require()** or **import** them.

We use ***api/services/*** for reusable tools like S3Upload.js, Honeybadger.js, PusherService.js etc.

![Sails services folder](https://storage.kraken.io/kk8yWPxzXVfBD3654oMN/28376d794a613cceb91c83421eaa109f/sails-services.png)


With the text above, we covered the structure for ***api/*** and it's subfolders. I won't go through ***assets/*** , ***config/*** and ***tasks/*** since they are [the best organized as they initially are](https://sailsjs.com/documentation/anatomy).

Let's now take a look how the tests should look like.

## Test

Sails does not automatically create ***test/*** folder for us, so we'll go ahead and create one ourselves. The test folder should mimic the structure of our api folder which will lead to better *DX*, easier debugging of the code and resolving issues (everything [a good programmer wants](https://kolosek.com/differences-between-good-and-bad-programmers/)).

To create some quality tests, we will need an ***assets/*** folder for holding the files we need in tests, we will need ***factories/*** for a clean way to create our test data objects, ***graphql/*** where we will put the tests dedicated to testing queries and mutations and ***models/*** for unit testing.

![Sails test folder](https://storage.kraken.io/kk8yWPxzXVfBD3654oMN/85ad0b7b32381780133b4f8ba11b9f3c/sails-test.png)

As said before, the anatomy of ***test/*** folder is identical to ***api/*** folder structure, except we have additional folders for factories and assets.

This covers all the details regarding how we organize our code. We hope that this article will inspire you to write some great, well-structured Sails apps!

This post is originally published on [Kolosek Blog]().