{"id":14384717,"url":"https://github.com/aichbauer/express-graphql-boilerplate","last_synced_at":"2025-04-08T03:11:03.987Z","repository":{"id":21803573,"uuid":"94079542","full_name":"aichbauer/express-graphql-boilerplate","owner":"aichbauer","description":"Express GraphQL API with JWT Authentication and support for sqlite, mysql, and postgresql","archived":false,"fork":false,"pushed_at":"2023-01-03T18:23:16.000Z","size":2268,"stargazers_count":247,"open_issues_count":30,"forks_count":61,"subscribers_count":11,"default_branch":"master","last_synced_at":"2025-03-31T17:21:18.764Z","etag":null,"topics":["authentication","boilerplate","express","graphql","jest","jwt","mysql","nodejs","postgresql","sqlite"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/aichbauer.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-06-12T09:37:23.000Z","updated_at":"2024-11-11T20:47:18.000Z","dependencies_parsed_at":"2023-01-12T03:46:01.275Z","dependency_job_id":null,"html_url":"https://github.com/aichbauer/express-graphql-boilerplate","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aichbauer%2Fexpress-graphql-boilerplate","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aichbauer%2Fexpress-graphql-boilerplate/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aichbauer%2Fexpress-graphql-boilerplate/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aichbauer%2Fexpress-graphql-boilerplate/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/aichbauer","download_url":"https://codeload.github.com/aichbauer/express-graphql-boilerplate/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247767236,"owners_count":20992548,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["authentication","boilerplate","express","graphql","jest","jwt","mysql","nodejs","postgresql","sqlite"],"created_at":"2024-08-28T18:01:36.606Z","updated_at":"2025-04-08T03:11:03.962Z","avatar_url":"https://github.com/aichbauer.png","language":"JavaScript","funding_links":[],"categories":["JavaScript"],"sub_categories":[],"readme":"# express-graphql-boilerplate\n\n\u003e Express GraphQL API with JWT Authentication and support for sqlite, mysql, and postgresql\n\n- Authentication via [JWT](https://jwt.io/)\n- Support for [sqlite](https://www.sqlite.org/), [mysql](https://www.mysql.com/), and [postgresql](https://www.postgresql.org/)\n- Support for [graphiql](https://github.com/graphql/graphiql) an easy way exploring a GraphQL API\n- Environments for `development`, `testing`, and `production`\n- Linting via [eslint](https://github.com/eslint/eslint)\n- Integration tests running with [Jest](https://github.com/facebook/jest)\n- Built with [npm scripts](#npm-scripts)\n- Examples for User, Note, and nested GraphQL Queries\n\n## Quick Intro\n\nGraphQL is a Query Language where your REST API can co-exist directly beside your GraphQL API in **harmony**. To demonstrate this we have two REST endpoints for `register` and `login`.\n\n```sh\n# clone repository\n$ git clone https://github.com/aichbauer/express-graphql-boilerplate.git\n# cd into project root\n$ cd express-graphql-boilerplate\n# install dependencies\n$ npm i\n# start application\n$ npm start\n# create a User via the REST API\n$ curl -H \"Content-Type: application/json\" -X POST -d '{\"email\":\"test@mail.com\",\"password\":\"pw\",\"password2\":\"pw\"}' http://localhost:2017/rest/register\n# login a User via the REST API\n# you will get a JSON with a token and this is your token to get access to the GraphQL API\n$ curl -H \"Content-Type: application/json\" -X POST -d '{\"email\":\"test@mail.com\",\"password\":\"pw\"}' http://localhost:2017/rest/login\n# requesting a User via the GraphQL API\n$ curl -i -H \"Content-Type:application/json\" -H \"Authorization: Bearer \u003ctoken\u003e\" -X POST -d '{\"query\": \"{user{id, username}}\"}'  http://localhost:2017/graphql\n# creating a Note for a user via the GraphQL API\n$ curl -i -H \"Content-Type:application/json\" -H \"Authorization: Bearer \u003ctoken\u003e\" -X POST -d '{\"query\": \"mutation{createNote(userId:1,note:\\\"this is a note\\\"){id,userId,note}}\"}' http://localhost:2017/graphql\n# requesting a User with its Notes via the GraphQL API (nested Query)\n$ curl -i -H \"Content-Type:application/json\" -H \"Authorization: Bearer \u003ctoken\u003e\" -X POST -d '{\"query\": \"{user{id, username, notes{id, note}}}\"}'  http://localhost:2017/graphql\n```\n\n## Table of Contents\n\n- [Install \u0026 Use](#install-and-use)\n- [Folder Structure](#folder-structure)\n- [Controllers](#controllers)\n  - [Create a Controller](#create-a-controller)\n- [GraphQL](#graphql)\n  - [Create a Query](#create-a-query)\n  - [Create a Mutation](#create-a-mutation)\n  - [Create a Type](#create-a-type)\n  - [Create an InputType](#create-an-inputtype)\n  - [RootQuery and Schema](#rootquery-and-schema)\n- [Models](#models)\n  - [Create a Model](#create-a-model)\n- [Policies](#policies)\n  - [auth.policy](#authpolicy)\n- [Services](#services)\n- [Config](#config)\n  - [Connection and Database](#connection-and-database)\n  - [Routes](#routes)\n- [Test](#test)\n  - [Setup](#setup)\n- [npm scripts](#npm-scripts)\n- [Deploy](#deploy)\n  - [database](#database)\n  - [nginx](#nginx)\n\n## Install and Use\n\nStart by cloning this repository\n\n```sh\n# HTTPS\n$ git clone https://github.com/aichbauer/express-graphql-boilerplate.git\n```\n\nthen\n\n```sh\n# change directory to project root\n$ cd express-graphql-boilerplate\n# install dependencies\n$ npm i\n# to use mysql\n$ npm i mysql2 -S\n# to use postgresql\n$ npm i pg pg-hstore -S\n```\n\nor\n\n```sh\n# change directory to project root\n$ cd express-graphql-boilerplate\n# install dependencies\n$ yarn\n# to use mysql\n$ yarn add mysql2\n# to use postgresql\n$ yarn add pg pg-hstore\n```\n\nSQLite is supported out of the box as it is the default database.\n\n## Folder Structure\n\nThis boilerplate has four main directories:\n\n- api - for controllers, queries, mutations, models, types, services, etc.\n- config - for routes, database, etc.\n- db - this is only a directory for the sqlite database, the default for `NODE_ENV=development`\n- test - using [Jest](https://github.com/facebook/jest)\n\n## Controllers\n\nControllers in this boilerplate have a naming convention: `ModelnameController.js` and uses an object factory pattern. To use a model inside of your controller you have to require it. We use [Sequelize](http://docs.sequelizejs.com/) as ORM, if you want further information read the [Docs](http://docs.sequelizejs.com/).\n\n### Create a Controller\n\nFor an example with all CRUD operations visit the [express-rest-api-boilerplate](https://www.github.com/aichbauer/express-rest-api-boilerplate)\n\n## GraphQL\n\nThis directory holds all files that are related to GraphQL (mutations, queries, types, ...).\n\n### Create a Query\n\n\u003e Note: You need to have a [Type](#create-a-type), and an existing [Model](#create-a-model) to use queries in combination with a database!\n\nExample query for a User which lets you request all different fields which are defined in `args`.\n\n```js\n// import the required GraphQL Types\nconst {\n  GraphQLInt,\n  GraphQLString,\n  GraphQLList,\n} = require('graphql');\n\n// import the Model and the Type\nconst { UserType } = require('../types');\nconst { User } = require('../../models');\n\n// create the query\nconst userQuery = {\n  type: new GraphQLList(UserType), // the Type which it returns (an array of Users)\n  args: {\n    // arguments you are able to Query\n    // notice no password field\n    // so the password will not be send as respond\n    // neither can you Query for it\n    id: {\n      name: 'id',\n      type: GraphQLInt,\n    },\n    username: {\n      name: 'username',\n      type: GraphQLString,\n    },\n    email: {\n      name: 'email',\n      type: GraphQLString,\n    },\n    notes: {\n      name: 'notes',\n      type: GraphQLString,\n    },\n    createdAt: {\n      name: 'createdAt',\n      type: GraphQLString,\n    },\n    updatedAt: {\n      name: 'updatedAt',\n      type: GraphQLString,\n    },\n  },\n  // how to get the respond\n  // DB call\n  resolve: (user, args) =\u003e User.findAll({ where: args }),\n};\n\nmodule.exports = { userQuery };\n```\n\nDo not forget to `require` and `export`  the query in `./api/graphql/queries/index.js`.\n\n### Create a Mutation\n\n\u003e Note: You need to have a [Type](#create-a-type), and an existing [Model](#create-a-model) to use mutations in combination with a database!\n\n```js\n// import the rqeuired GraphQL Types\nconst {\n  GraphQLString,\n  GraphQLInt,\n  GraphQLNonNull,\n} = require('graphql');\nconst merge = require('lodash.merge');\n\n// import the Model and the Type\nconst { UserType } = require('../types');\nconst { User } = require('../../models');\n\n// create the mutation\nconst updateUser = {\n  // the Type which it returns (one user)\n  type: UserType,\n  description: 'The mutation that allows you to update an existing User by Id',\n  // arguments you can use\n  // have to be fields that are\n  // resolvable by the UserType\n  args: {\n    id: {\n      name: 'id',\n      type: new GraphQLNonNull(GraphQLInt),\n    },\n    username: {\n      name: 'username',\n      type: GraphQLString,\n    },\n    email: {\n      name: 'email',\n      type: GraphQLString,\n    },\n  },\n  // find the User in the DB\n  // update the fields for this user\n  resolve: async (user, { id, username, email }) =\u003e {\n    const foundUser = await User.findByPk(id);\n\n    if (!foundUser) {\n      throw new Error(`User with id: ${id} not found!`);\n    }\n\n    const updatedUser = merge(foundUser, {\n      username,\n      email,\n    });\n\n    return foundUser.update(updatedUser);\n  },\n};\n\n// the delete mutation\nconst deleteUser = {\n  // the Type which it returns (one user)\n  type: UserType,\n  description: 'The mutation that allows you to delete a existing User by Id',\n  // arguments you can use\n  args: {\n    id: {\n      name: 'id',\n      type: new GraphQLNonNull(GraphQLInt),\n    },\n  },\n  resolve: async (user, { id }) =\u003e {\n    const foundUser = await User.findByPk(id);\n\n    if (!foundUser) {\n      throw new Error(`User with id: ${id} not found!`);\n    }\n\n    await User.destroy({\n      where: {\n        id,\n      },\n    });\n\n    return foundUser;\n  },\n};\n\nmodule.exports = {\n  updateUser,\n  deleteUser,\n};\n```\n\nDo not forget to `require` and `export`  the mutation in `./api/graphql/mutations/index.js`.\n\n### Create a Type\n\nTypes are necessary to let GraphQL know, how to resolve the different fields you provide in your queries and mutations.\n\n```js\n// import the required GraphQL Types\nconst {\n  GraphQLObjectType,\n  GraphQLInt,\n  GraphQLString,\n  GraphQLList,\n} = require('graphql');\n\n// our UserType definition\nconst UserType = new GraphQLObjectType({\n  name: 'User',\n  description: 'This represents a User',\n  // all the fields a User can have\n  fields: () =\u003e ({\n    id: {\n      type: GraphQLInt,\n      resolve: (user) =\u003e user.id,\n    },\n    username: {\n      type: GraphQLString,\n      resolve: (user) =\u003e user.username,\n    },\n    email: {\n      type: GraphQLString,\n      resolve: (user) =\u003e user.email,\n    },\n    createdAt: {\n      type: GraphQLString,\n      resolve: (user) =\u003e user.createdAt,\n    },\n    updatedAt: {\n      type: GraphQLString,\n      resolve: (user) =\u003e user.updatedAt,\n    },\n  }),\n});\n\nmodule.exports = { UserType };\n```\n\nDo not forget to `require` and `export` the type in `./api/graphql/types/index.js`.\n\n### Create an InputType\n\nInputTypes are a way to simplify your arguments on a mutation or a query. You may not need to implement InputTypes, but it is common that some kind of mutations or queries accept the same input types, what makes them pretty handy.\n\nThe simpliest version would of a InputType could look like this:\n\n```js\n// import the GraphQL types\n// that you need for your\n// input type\nconst {\n  GraphQLInputObjectType,\n  GraphQLInt,\n  GraphQLNonNull,\n  GraphQLString,\n} = require('graphql');\n\n// create a InputType\nconst UserInputType = new GraphQLInputObjectType({\n  name: 'UserInputType',\n  description: 'This represents a UserInputType',\n  fields: {\n    id: {\n      type: new GraphQLNonNull(GraphQLInt),\n    },\n    username: {\n      type: GraphQLString,\n    },\n    email: {\n      type: GraphQLString,\n    },\n  },\n});\n\n\nmodule.exports = { UserInputType };\n```\n\nBut you can reuse the same implementation for multiple purposes of the same InputType, e.g. `update` and `delete`. To delete a user you only need to send the Id and nothing else, this could help front end developers.\n\n```js\n// import the GraphQL types\n// that you need for your\n// input type\nconst {\n  GraphQLInputObjectType,\n  GraphQLInt,\n  GraphQLNonNull,\n  GraphQLString,\n} = require('graphql');\n\n// the function that accepts a\n// string, specifying the type\n// e.g. 'create', 'update', or 'delete'\nconst UserInputType = (type) =\u003e {\n  let allGraphFields = {};\n  const standardGraphFields = {\n    id: {\n      type: new GraphQLNonNull(GraphQLInt),\n    },\n  };\n\n  // add args for different mutations\n  switch (type) {\n    case 'delete':\n      allGraphFields = {\n        ...standardGraphFields,\n      };\n      break;\n    case 'update':\n      allGraphFields = {\n        ...standardGraphFields,\n        username: {\n          type: GraphQLString,\n        },\n        email: {\n          type: GraphQLString,\n        },\n      };\n      break;\n    default:\n      allGraphFields = {\n        ...standardGraphFields,\n      };\n  }\n\n  // create a InputType\n  // keep in mind that\n  // one name can only\n  // exist once in a schema\n  const userInputType = new GraphQLInputObjectType({\n    name: `UserInputType${type[0].toUpperCase() + type.slice(1, type.length - 1)}`,\n    description: 'This represents a UserInputType',\n    fields: allGraphFields,\n  });\n\n  return userInputType;\n};\n\nmodule.exports = { UserInputType };\n```\n\nNow you can use this on a mutation or a query like:\n\n```js\nconst updateUser = {\n  type: UserType,\n  description: 'The mutation that allows you to update an existing User by Id',\n  args: {\n    user: {\n      name: 'user',\n      // use the InputType\n      type: UserInputType('update'),\n    },\n  },\n  resolve: async (_, { user }) =\u003e {\n    const foundUser = await User.findByPk(user.id);\n\n    if (!foundUser) {\n      throw new Error(`User with id: ${user.id} not found!`);\n    }\n\n    const updatedUser = merge(foundUser, {\n      username: user.username,\n      email: user.email,\n    });\n\n    return foundUser.update(updatedUser);\n  },\n};\n\nconst deleteUser = {\n  type: UserType,\n  description: 'The mutation that allows you to delete a existing User by Id',\n  args: {\n    user: {\n      name: 'user',\n      // use the InputType\n      type: UserInputType('delete'),\n    },\n  },\n  resolve: async (_, { user }) =\u003e {\n    const foundUser = await User.findByPk(user.id);\n\n    if (!foundUser) {\n      throw new Error(`User with id: ${user.id} not found!`);\n    }\n\n    await User.destroy({\n      where: {\n        id: user.id,\n      },\n    });\n\n    return foundUser;\n  },\n};\n```\n\n### RootQuery, RootMutation and Schema\n\nThe schema holds the `RootQuery` and the `RootMutation` which holds all the other Queries and Mutations, that is applied to one route which is your entrypoint for your GraphQL API. The schema has to be exported and used in the `./api/api.js` file.\n\n```js\n// import required GraphQL Types\nconst {\n  GraphQLSchema,\n  GraphQLObjectType,\n} = require('graphql');\n\n// import Query and Mutations\nconst { userQuery } = require('./queries');\nconst {\n  updateUser,\n  deleteUser,\n} = require('./mutations');\n\n// add Queries to RootQuery\nconst RootQuery = new GraphQLObjectType({\n  name: 'rootQuery',\n  description: 'This is the RootQuery which holds all possible READ entrypoints for the GraphQL API',\n  fields: () =\u003e ({\n    user: userQuery,\n  }),\n});\n\n// add Mutations to RootMutations\nconst RootMutation = new GraphQLObjectType({\n  name: 'rootMutation',\n  description: 'This is the root Mutation which holds all possible WRITE entrypoints for the GraphQL API',\n  fields: () =\u003e ({\n    updateUser,\n    deleteUser,\n  }),\n});\n\n// add RootQuery and RootMutation\n// to your Schema\nconst schema = new GraphQLSchema({\n  query: RootQuery,\n  mutation: RootMutation,\n});\n\nmodule.exports = { schema };\n```\n\nTo use the this schema for your API we need to add it to a route, as you can see we use our auth service\nto protect our GraphQL API to be used without authorization via a valid JSON Web Token.\nWe get a nice web interface for our GraphQL API via the `graphql-playground-middleware-express` package.\nYou can use it if you visit `http://localhost:2017/explore`. If you want to use it in production you should make sure only you have access to `/explore`.\n\n```js\napi.all('/graphql', (req, res, next) =\u003e auth(req, res, next));\napi.use('/graphql', bodyParser.json(), graphqlExpress({ schema }));\napi.get('/explore', expressPlayground({ endpoint: '/graphql' }));\n```\n\nThe entrypoint for our GraphQL API is `http://localhost:2017/graphql`\n\n## Models\n\nThis folder holds all models. Every model is `required` and `exported` in `index.js`.\n\n### Create a model\n\nModels in this boilerplate have a naming convention: `Model.js` and uses [Sequelize](http://docs.sequelizejs.com/) to define our Models, if you want further information, read the [Docs](http://docs.sequelizejs.com/).\n\nExample User Model:\n\n```js\n// as our ORM\nconst Sequelize = require('sequelize');\n// for encrypting our passwords\nconst bcryptSevice = require('../services/bcrypt.service');\n\n// the DB connection\nconst sequelize = require('../../config/database');\n\n// hooks are functions that can run before or after a specific event\nconst hooks = {\n  beforeCreate(user) {\n    user.password = bcryptSevice().password(user); // eslint-disable-line no-param-reassign\n  },\n};\n\n// naming the table in the DB\nconst tableName = 'users';\n\n// the actual Model\nconst User = sequelize.define('User', {\n  username: {\n    type: Sequelize.STRING,\n  },\n  password: {\n    type: Sequelize.STRING,\n  },\n  email: {\n    type: Sequelize.STRING,\n    unique: true,\n  },\n}, { hooks, tableName });\n\n// instanceMethods are functions that run on instances of our Model\n// toJSON runs before delivering it to our client\n// we delete the password, that the client has no sensitive data\nUser.prototype.toJSON = function () {\n  const values = Object.assign({}, this.get());\n\n  delete values.password;\n\n  return values;\n};\n\nmodule.exports = { User };\n```\n\nDo not forget to `require` the the model in `./api/models/index.js`.\n\n## Policies\n\nPolicies are middleware functions that can run before hitting a specific or more specified route(s).\n\nExample policy:\n\nOnly allow if the user is marked as admin.\n\n\u003e Note: this is not a secure example, only for presentation puposes\n\n```js\nmodule.exports = (req, res, next) =\u003e {\n  if(req.body.userrole === 'admin') {\n    // do some verification stuff\n    const verified = verifyAdmin(req.body.userid);\n\n    if(verified) {\n      return next();\n    }\n\n    return res.status(401).json({ msg: 'Unauthorized' });\n  }\n\n  return res.status(401).json({ msg: 'Unauthorized' });\n};\n```\n\nTo use this policy on all routes that only admins are allowed:\n\napi.js\n\n```js\nconst adminPolicy = require('./policies/admin.policy');\n\napp.all('/admin/*', (req, res, next) =\u003e adminPolicy(req, res, next));\n```\n\nOr for one specific route\n\napi.js\n\n```js\nconst adminPolicy = require('./policies/admin.policy');\n\napp.get('/admin/myroute',\n  (req, res, next) =\u003e adminPolicy(req, res, next),\n  (req, res) =\u003e {\n  //do some fancy stuff\n});\n```\n\n## auth.policy\n\nThe `auth.policy` checks wether a [JSON Web Token](https://jwt.io/) is send in the header of an request as `Authorization: Bearer [JSON Web Token]` or inside of the body of an request as `token: [JSON Web Token]`.\nThe policy runs default on all API routes that are are prefixed with `/graphql`. To map multiple routes read the [express-routes-mapper docs](https://github.com/aichbauer/express-routes-mapper/blob/master/README.md).\n\nTo use this policy on all routes of a specific prefix:\n\napp.js\n\n```js\napp.use('/prefix', yourRoutes);\napp.all('/prefix', (req, res, next) =\u003e auth(req, res, next));\n```\n\nor to use this policy on one specific route:\n\napp.js\n\n```js\napp.get('/specificRoute',\n  (req, res, next) =\u003e auth(req, res, next),\n  (req, res) =\u003e {\n  // do some fancy stuff\n});\n```\n\n## Services\n\nServices are little useful snippets, or calls to another API that are not the main focus of your API.\n\nExample service:\n\nGet comments from another API:\n\n```js\nmodule.exports = {\n  getComments: () =\u003e (\n    fetch('https://jsonplaceholder.typicode.com/comments', {\n      method: 'get'\n    }).then(function(res) {\n      // do some fancy stuff with the response\n    }).catch(function(err) {\n      // Error :(\n    })\n  );\n};\n```\n\n## Config\n\nHolds all the server configurations.\n\n### Connection and Database\n\n\u003e Note: If you use mysql make sure mysql server is running on the machine\n\n\u003e Note: If you use postgresql make sure postgresql server is running on the machine\n\nThese two files are the way to establish a connection to a database.\n\nYou only need to touch connection.js, default for `development` is sqlite, but it is easy as typing `mysql` or `postgres` to switch to another db.\n\n\u003e Note: To run a mysql db install these package with: `npm i mysql2 -S` or `yarn add mysql2`\n\n\u003e Note: To run a postgres db run these package with: `npm i -S pg pg-hstore` or `yarn add pg pg-hstore`\n\nNow simple configure the keys with your credentials.\n\n```js\n{\n  database: 'databasename',\n  username: 'username',\n  password: 'password',\n  host: 'localhost',\n  dialect: 'sqlite' || 'mysql' || 'postgres',\n}\n```\n\nTo not configure the production code.\n\nTo start the DB, add the credentials for production. Add `environment variables` by typing e.g. `export DB_USER=yourusername` before starting the API.\n\n### Routes\n\n\u003e For an example REST API with routes visit [express-rest-api-boilerplate](https://www.github.com/aichbauer/express-rest-api-boilerplate)\n\nHere you define all your routes for your API. It doesn't matter how you structure them. By default they are mapped on `privateRoutes` and `publicRoutes`. You can define as much routes files as you want e.g. for every Model or for specific use cases, e.g. normal user and admins.\n\n## Test\n\nAll test for this boilerplate uses [Jest](https://github.com/facebook/jest) and [supertest](https://github.com/visionmedia/superagent) for integration testing. So read their docs on further information.\n\n## npm scripts\n\nThere are no automation tools or task runners like [grunt](https://gruntjs.com/) or [gulp](http://gulpjs.com/) used for this boilerplate. This boilerplate only uses npm scripts for automatization.\n\n### npm start\n\nThis is the entry for a developer.\n\nBy default it uses a sqlite databse, if you want to migrate the sqlite database by each start, disable the `prestart` and `poststart` command. Also mind if you are using a sqlite database to delete the `drop-sqlite-db` in the prepush hook.\n\n- runs a **nodemon watch task** for the all files in the project root\n- sets the **environment variable** `NODE_ENV` to `development`\n- opens the db connection for `development`\n- starts the server on 127.0.0.1:2017\n\n### npm test\n\nThis command:\n\n- runs `npm run lint` ([eslint](http://eslint.org/)) with the [airbnb styleguide](https://github.com/airbnb/javascript) without arrow-parens rule for **better readability**\n- sets the **environment variable** `NODE_ENV` to `testing`\n- creates the `database.sqlite` for the test\n- runs `jest --coverage` for testing with [Jest](https://github.com/facebook/jest) and the coverage\n- drops the `database.sqlite` after the test\n\n### npm run production\n\nThis command:\n\n- sets the **environment variable** to `production`\n- opens the db connection for `production`\n- starts the server on 127.0.0.1:2017 or on 127.0.0.1:PORT_ENV\n\nBefore running on production you have to set the **environment vaiables**:\n\n- DB_NAME - database name for production\n- DB_USER - database username for production\n- DB_PASS - database password for production\n- DB_HOST - database host for production\n- JWT_SECRET - secret for json web token\n\nOptional:\n\n- PORT - the port your API on 127.0.0.1, default to 2017\n\n### other commands\n\n- `npm run project clean` - clean up `controllers`, `models`, `graphql`, `config/routes` to start developing your own api\n- `npm run dev` - simply starts the server without a watch task\n- `npm run creates-sqlite-db` - creates the sqlite database file\n- `npm run drop-sqlite-db` - deletes the sqlite database file\n- `npm run lint` - linting with [eslint](http://eslint.org/)\n- `npm run nodemon` - same as `npm start`\n- `npm run prepush` - a hook which runs before pushing to a repository, runs `npm test` and `npm run drop-sqlite-db`\n- `pretest` - runs linting before `npm test`\n- `test-ci` - only runs tests, nothing in pretest, nothing in posttest, for better use with ci tools\n\n## Deploy\n\nThis section gives an overview of how to deploy this project to a server. For this examples we use an ubuntu server.\n\n### Database\n\nThis section gives an overview of how to set up the database (for this example we will use a postgres database).\n\n```sh\n# update package database\n$ sudo apt-get update\n# install all postgres required resources\n$ sudo apt-get install python-psycopg2 libpq-dev postgresql postgresql-contrib\n# open postgres\n$ sudo -u postgres psql postgres\n# set passsword for postgres user\n$ \\password postgres\n# create a new DB\n$ CREATE DATABASE db_name;\n# list all dbs\n$ \\l\n# exit psql\n$ \\q\n```\n\nTo use postgres with this project you need to install two additional packages from npm. See next section.\n\n### nginx\n\nThis section gives an overview of how to use ngingx as a webserver for this project.\n\n```sh\n# update package database\n$ sudo apt-get update\n# install all required resources for this project and nginx\n$ sudo apt-get install nginx git-all\n$ curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -\n$ sudo apt-get install -y nodejs\n# install forever js\n$ npm i -g forever\n# now copy your project to the server\n$ git clone https://example.com/your/repository\n```\n\nTo use this project with `postgres` you need to install two additional packages from npm.\n\n```sh\n# cd into your project\n$ cd project\n# install dependencies\n$ npm i\n# install two new packages for postgres\n$ npm i pg pg-hstore -S\n# start project with forever\n$ NODE_ENV=production DB_NAME=DB_NAME DB_USER=DB_USER DB_PASS=DB_PASS DB_HOST=DB_HOST DB_PORT=DB_PORT JWT_SECRET=JWT_SECRET forever start -c node ./api/api.js\n```\n\nYou need to update the `config/connection.js` to use `postgres`, see [config](#config).\n\nNow we need our `nginx` configuration to be set up. Save the following in `/etc/nginx/sites-available/project_name`. Where `project_name` is the name of your project. You need to replace everything that is written in UPPERCASE with your details.\n\nIf you do not have a domain yet just fill `_` for `PUBLIC_SERVER_NAME`. `PUBLIC_IP` is the IP of your server and `PUBLIC_PORT` is most likely `80` for `http` and `443` for `https`.\n\n```nginx\nserver {\n    listen PUBLIC_IP:PUBLIC_PORT;\n\n    server_name PUBLIC_SERVER_NAME;\n\n    location / {\n        proxy_pass http://127.0.0.1:2017;\n    }\n}\n```\n\nNow configure `nginx` to use your config.\n\n```sh\n#stop nginx\n$ sudo systemctl stop nginx\n# delete symlink default config\n$ sudo rm /etc/nginx/sites-enabled/default\n# create new sysmlink to sites enabled\n$ ln -s /etc/nginx/sites-available/project_name /etc/nginx/sites-enabled/project_name\n# reload and start nginx with new configuration\n$ sudo systemctl start nginx\n```\n\nYour project is now live under `http://PUBLIC_SEVER_NAME` or `http://PUBLIC_IP`.\n\nIf you now visit `http://PUBLIC_SEVER_NAME/explore` or `http://PUBLIC_IP/explore` you need a valid HTTP header to access the server.\n\nFor example register a new user if you just used this blank boilerplate.\n\n```sh\n# you will get a JSON with a token and this is your token to get access to the GraphQL API\n$ curl -H \"Content-Type: application/json\" -X POST -d '{\"email\":\"test@mail.com\",\"password\":\"pw\"}' http://localhost:2017/rest/login\n```\n\nUse this token and add it under HTTP headers on the bottom left of the `graphql playground` you are now able to use the `graphql playground` on a server.\n\n```json\n{\n  \"Authorization\": \"Bearer \u003ctoken\u003e\"\n}\n```\n\n## LICENSE\n\nMIT © Lukas Aichbauer\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faichbauer%2Fexpress-graphql-boilerplate","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faichbauer%2Fexpress-graphql-boilerplate","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faichbauer%2Fexpress-graphql-boilerplate/lists"}