|
| 1 | +# NodeJS Slender |
| 2 | +This is a barebone boilerplate for creating a nodejs api. It comes with the following features: |
| 3 | +- 🗂 [MongoDB](https://www.mongodb.com) intergation |
| 4 | +- 🔐 [JWT](https://jwt.io) Authentication |
| 5 | +- 📨 Templated emails using [MJML](https://mjml.io) and [Mustache](https://mustache.github.io) 🧔🏽 |
| 6 | +- ✅ Request body validation using [Joi](https://hapi.dev/module/joi/) |
| 7 | + |
| 8 | +--- |
| 9 | +- [NodeJS Slender](#nodejs-slender) |
| 10 | + - [Creating a new project](#creating-a-new-project) |
| 11 | + - [Authentication](#authentication) |
| 12 | + - [Middleware](#middleware) |
| 13 | + - [Routes](#routes) |
| 14 | + - [Send emails from your app](#send-emails-from-your-app) |
| 15 | + - [Templated emails](#templated-emails) |
| 16 | + - [Simple emails](#simple-emails) |
| 17 | + - [Validation](#validation) |
| 18 | + |
| 19 | +--- |
| 20 | + |
| 21 | +## Creating a new project |
| 22 | +For creating a new project you can just clone this repo and change the origin. |
| 23 | +```bash |
| 24 | +git clone [email protected]:txbivs/nodejs-slender.git <projectname > && cd <projectname > |
| 25 | +git remote set-url origin <your-repo> |
| 26 | +``` |
| 27 | + |
| 28 | +After that you need to setup the environment. Start by typing the following command in your terminal of choice: |
| 29 | +```bash |
| 30 | +cp .env.sample .env |
| 31 | +``` |
| 32 | +That copies the sample `.env` file. Now you need to populate that with your own data. |
| 33 | + |
| 34 | +Next you need to install the dependencies using your package manager of choice, I use `yarn`. |
| 35 | +``` |
| 36 | +yarn install |
| 37 | +``` |
| 38 | + |
| 39 | +To start the app you need to type in one of the following commands depending on your current situation. |
| 40 | +```bash |
| 41 | +# Start app in development mode, with hot reloading enabled |
| 42 | +yarn dev |
| 43 | + |
| 44 | +# Start app in production mode |
| 45 | +yarn start |
| 46 | +``` |
| 47 | + |
| 48 | +--- |
| 49 | + |
| 50 | +## Authentication |
| 51 | +The authentication is done using JWT. The generated token must be send with every following request in the `Authorization` header. |
| 52 | + |
| 53 | +### Middleware |
| 54 | +To protect a route from unauthenticated users, you can add the `auth` middleware to it. To do that, you attach it to the `controller`'s export `array`. The last element of this `array` is the actual function. The elements before are used as middleware. |
| 55 | + |
| 56 | +### Routes |
| 57 | +For the authentication the following routes are predefined and used: |
| 58 | + |
| 59 | +- #### `POST /register` |
| 60 | + Creates a new user based on the incoming request body. |
| 61 | + |
| 62 | + **Request**: |
| 63 | + - ##### `firstName`: `string`, `required` *The first name of the new user* |
| 64 | + - ##### `lastName`: `string`, `required` *The last name of the new user* |
| 65 | + - ##### `email`: `string`, `email`, `unique`, `required` *The users email. An email can only be registered once.* |
| 66 | + - ##### `password`: `string`, `min(6)`, `required` *The plaintext password. Will be hashed using bcrypt.* |
| 67 | + |
| 68 | + **Response**: Responds with the created user. If failed -> returns errors. |
| 69 | + |
| 70 | + ##### Sample: |
| 71 | + ```json |
| 72 | + body: { |
| 73 | + "firstName": "John", |
| 74 | + "lastName": "Doe", |
| 75 | + |
| 76 | + "password:": "!secret$" |
| 77 | + } |
| 78 | + ``` |
| 79 | + |
| 80 | +- #### `POST /login` |
| 81 | + Attempts a login with the given credentials. |
| 82 | + |
| 83 | + **Request**: |
| 84 | + - ##### `email`: `string`, `email`, `required` *The users email.* |
| 85 | + - ##### `password`: `string`, `required` *The plaintext password.* |
| 86 | + |
| 87 | + **Response**: If valid -> returns the generated jwt token, if failed -> returns a `401 |
| 88 | + Unauthorized` with a reason. |
| 89 | + |
| 90 | + ##### Sample: |
| 91 | + ```json |
| 92 | + body: { |
| 93 | + "firstName": "John", |
| 94 | + "lastName": "Doe", |
| 95 | + |
| 96 | + "password:": "!secret$" |
| 97 | + } |
| 98 | + ``` |
| 99 | + |
| 100 | +- #### `POST /verify` |
| 101 | + Attempts the confirmation of an account using the `confirmKey`. |
| 102 | + |
| 103 | + **Request**: |
| 104 | + - ##### `confirmKey`: `string`, `length(16)`, `required` *The given 16 digit confirmation key* |
| 105 | + |
| 106 | + **Response**: If valid -> returns the generated jwt token, if failed -> returns a `401 |
| 107 | + Unauthorized` with a reason. |
| 108 | + |
| 109 | + ##### Sample: |
| 110 | + ```json |
| 111 | + body: { |
| 112 | + "confirmKey": "ld84jflsow39lc0e" |
| 113 | + } |
| 114 | + ``` |
| 115 | + |
| 116 | +--- |
| 117 | + |
| 118 | +## Send emails from your app |
| 119 | +There are two possible ways of sending an email. You can use mjml and mustache to generate beautiful, responsive emails with variables in a few lines of code, or just ship generic html or plaintext emails. |
| 120 | + |
| 121 | +### Templated emails |
| 122 | +To use the built-in email functionality you have to add your templates first. Add your template as `<name>.mjml` to the `mail/template` folder. |
| 123 | +You can create subfolders in the `mail/template` folder for organization, but keep in mind that you need to append that subfolder name to the path |
| 124 | +to the template when attempting to render it! |
| 125 | + |
| 126 | +Let's assume you created a new template under `mail/template/monitoring/ping.mjml`. For sending an email the only |
| 127 | +code you need is the following: |
| 128 | +```javascript |
| 129 | +const Mail = require('path/to/mail/Mail'); |
| 130 | + |
| 131 | +// Create a new Mail instance by giving it the receipient and a subject. |
| 132 | +let mail = new Mail('[email protected]', 'Monitoring Alert'); |
| 133 | + |
| 134 | +// Render the variables by specifying the template and an object with the variable data. |
| 135 | +// The sample assumes you have used the variables {{ url }} and {{ downtime }} in your mjml-template. |
| 136 | +mail.render('monitoring/ping', { |
| 137 | + host: '127.0.0.1', |
| 138 | + downtime: '20m' |
| 139 | +}); |
| 140 | + |
| 141 | +mail.send(); |
| 142 | +``` |
| 143 | + |
| 144 | +The `send()` function will return a `Promise`. So if you want to do something with failed emails, like logging or resending them after 1 day, or wait for the email to be sent, you can use the following code: |
| 145 | + |
| 146 | +```javascript |
| 147 | +mail.send().then(() => { |
| 148 | + // Do something on success. |
| 149 | +}).catch((err) => { |
| 150 | + console.error(err); |
| 151 | + // Do something with the failed email. |
| 152 | +}); |
| 153 | +``` |
| 154 | + |
| 155 | +### Simple emails |
| 156 | +If you just want to send a basic email without templating and mjml, you can use the `mail/mailer` module. Import |
| 157 | +it and use the send function. |
| 158 | +```javascript |
| 159 | +const mailer = require('path/to/mail/mailer'); |
| 160 | + |
| 161 | +mailer.send(_to, _subject, _htmlOrText, _from); |
| 162 | +``` |
| 163 | +This function is returing a `Promise` too. |
| 164 | + |
| 165 | +--- |
| 166 | + |
| 167 | +## Validation |
| 168 | +Validation is super easy with this boilerplate. All the validation rules are stored in the `validation/rules` module. |
| 169 | +You can create your own files, but make sure you require them in where you need them. These rules are basicly just objects consumed by Joi. To enable validation for a new route, add the route segments to the `validation/rules` module and add the `validator` middleware to your desired route. |
| 170 | + |
| 171 | +For example you want to enable validation for the route `POST /posts` you would create an object under `posts.create` with your desired validation rules. After that, go into your `PostController` and add the following import: |
| 172 | +```javascript |
| 173 | +const { posts } = require('path/to/validation/rules'); |
| 174 | +``` |
| 175 | +and add the middleware to your method: |
| 176 | +```javascript |
| 177 | +exports.create = [ |
| 178 | + auth, |
| 179 | + validator(posts.create), |
| 180 | + (req, res) => { |
| 181 | + // Your controller logic |
| 182 | + } |
| 183 | +]; |
| 184 | +``` |
0 commit comments