Idiomatic JavaScript Backend. Part 2
Tags: javascript, node, backend
Published: 2018-09-01 11:19:13

---
title: Idiomatic JavaScript Backend. Part 2
published: true
description: Curated step by step tutorial about writing nodeJS app using ritley
tags: javascript, node, backend
---

Hi everyone! This part of series __Idiomatic JavaScript Backend__.

[Part 1/3](https://dev.to/k1r0s/idiomatic-javascript-backend-part-1-4g0b)
[Part 3/3](https://dev.to/k1r0s/idiomatic-javascript-backend-part-3-1eii)

### Important Information

For best experience please clone this repo: [https://github.com/k1r0s/ritley-tutorial](https://github.com/k1r0s/ritley-tutorial). It contains __git tags__ that you can use to travel through different commits to properly follow this tutorial :)

```
$ git tag

1.preparing-the-env
2.connecting-a-persistance-layer
3.improving-project-structure
4.creating-entity-models
5.handling-errors
6.creating-and-managing-sessions
7.separation-of-concerns
8.everybody-concern-scalability
```

Go to specific tag

```
$ git checkout 1.preparing-the-env
```

Go to latest commit

```
$ git checkout master
```


See differences between tags on folder `src`

```
$ git diff 1.preparing-the-env 2.connecting-a-persistance-layer src
```
___
# 4. Creating entity models

Ritley doesn't tell you exactly how to build entity models, that's not our concern so I'll try to be brief.

Models encapsulate all logic related with the domain. For instance creating users, encrypting passwords, validate fields, etc. While Resources translate this logic into the HTTP layer.

Our first model will be located into `src/models/user.model.js`:

```js
import DataService from "../services/database.service";
import EncryptService from "../services/encrypt.service";
import { Provider, Dependency } from "@ritley/decorators";


@Provider.factory
@Dependency("database", DataService)
@Dependency("encrypt", EncryptService)
export default class UserModel {

  static userPublicPredicate = collection => collection.map(({ pass, ...user }) => ({
    ...user
  }))

  validate(payload) {
    const requiredProps = ["name", "pass", "mail"];
    const props = Object.keys(payload);
    if(requiredProps.every(prop => props.includes(prop))) {
      return Promise.resolve();
    } else {
      return Promise.reject();
    }
  }

  create(payload) {
    const pass = this.encrypt.encode(payload.pass);
    return this.database.create("users", { ...payload, pass });
  }

  isUnique({ mail }) {
    return new Promise((resolve, reject) =>
      this.database.exists("users", { mail }).then(reject, resolve));
  }

  searchBy(predicate) {
    return this.readUsers(predicate).then(UserModel.userPublicPredicate);
  }

  readUsers(predicate) {
    if(predicate) {
      return this.database.filter("users", predicate);
    } else {
      return this.database.read("users");
    }
  }

  update(uid, { mail, name }) {
    return this.database.update("users", { uid }, { mail, name });
  }
}
```

We've just implemented many methods that will be used later on, for now we're going to use `validate`, `isUnique` and `create` to fit [requirements](https://github.com/k1r0s/ritley-tutorial/blob/master/REQUIREMENTS.md) on user creation.

Note we've included a new package for [password encryption](https://www.npmjs.com/package/cpass).

Again all non topic packages as such are just placeholders, you can use any other you like :)

we run: `$ npm install cpass`

Now lets take a look over `src/resources/user.resource.js`:

```diff
 import { AbstractResource } from "@ritley/core";
-import DataService from "../services/database.service";
+import UserModel from "../models/user.model";
 
-import { Dependency, ReqTransformBodySync } from "@ritley/decorators";
+import { Dependency, ReqTransformBodyAsync } from "@ritley/decorators";
 
-@Dependency("database", DataService)
+@Dependency("userModel", UserModel)
 export default class UserResource extends AbstractResource {
   constructor() {
     super("/users");
   }
 
-  @ReqTransformBodySync
-  post(req, res) {
-    const payload = req.body.toJSON();
-    this.database.create("users", payload).then(user => {
-      res.statusCode = 200;
-      res.end(JSON.stringify(user));
-    });
+  @ReqTransformBodyAsync
+  async post(req, res) {
+    const body = await req.body;
+    const payload = body.toJSON();
+    await this.userModel.validate(payload);
+    await this.userModel.isUnique(payload);
+    const user = await this.userModel.create(payload);
+    res.statusCode = 200;
+    res.end(JSON.stringify(user));
   }
 }
```

As I said before, using async/await feature transforms our `post` method into a promise, so we're going to use __@ReqTransformBodyAsync__ instead of previous one @ReqTransformBodySync. First one is _promise based_, so it makes sense to use it with async/await code such as previous snippet.

Of course we've removed `this.database` calls and DataService from resources. You don't want to mess with persistence layer on your http layer ;)

Our service now fulfills the requirements for user creation but we're missing exception handling here. If JSON isn't well formed, payload doesn't contain required fields, provided email is taken or something we'll held an unhanded rejection or maybe an exception will terminate our app 😰

let's see what's next!

___
# 5. Handling exceptions

So, how to file proper responses anytime when an errors pops by?

Well, first of all we need to look at there:

```js
const body = await req.body;
const payload = body.toJSON();
await this.userModel.validate(payload);
await this.userModel.isUnique(payload);
const user = await this.userModel.create(payload);
res.statusCode = 200;
res.end(JSON.stringify(user));
```

All errors originate from there or subsequent calls and should be handled here (around here) because it involves sending back feedback to the client.

But that is quite difficult and involves a lot of intrusion you may think.

To better understand what means to deal with nested promise rejections in nodejs I recommend [this article about promise rejections](http://thecodebarbarian.com/unhandled-promise-rejections-in-node.js.html), or at least keep on the desktop.

Wrapping every specific case with `try ... catch` can be a nightmare. Lets start by separate every task into new methods that will handle single operations, for instance payload parsing:

```js
parseBody(req, res) {
  try {
    return req.body.toJSON();
  } catch (e) {
    res.statusCode = 400; // Bad Request
    res.end("payload isn't well formed");
  }
}
```

And of course this works! Lets see how it looks:

```js
import { AbstractResource } from "@ritley/core";
import UserModel from "../models/user.model";

import { Dependency, ReqTransformBodyAsync } from "@ritley/decorators";

@Dependency("userModel", UserModel)
export default class UserResource extends AbstractResource {
  constructor(_database) {
    super("/users");
  }

  @ReqTransformBodyAsync
  async post(req, res) {
    const body = await req.body;
    const payload = this.parseBody(body, res);
    await this.validate(payload, res);
    await this.isUnique(payload, res);
    const user = await this.create(payload, res);
    res.statusCode = 200;
    res.end(JSON.stringify(user));
  }

  parseBody(body, res) {
    try {
      return body.toJSON();
    } catch (e) {
      res.statusCode = 400;
      res.end("payload isn't well formed");
    }
  }

  validate(payload, res) {
    return this.userModel.validate(payload).catch(() => {
      res.statusCode = 400;
      res.end("missing fields, required: [name, mail, pass]");
    })
  }

  isUnique(payload, res) {
    return this.userModel.isUnique(payload).catch(() => {
      res.statusCode = 409;
      res.end("mail is already taken, try another one");
    })
  }

  create(payload, res) {
    return this.userModel.create(payload).catch(() => {
      res.statusCode = 500;
      res.end("there was an error creating your user, try again");
    })
  }
}
```

mmh! that's huge, does it make sense to expand our code that much only to properly catch exceptions? well...

Even though we're handling errors on every single task that may involve rejections or exceptions we're going to run into `UnhandledPromiseRejectionWarning` because async generators wraps the whole method into a promise, but we cannot handle `post` it self, because it gets called by the library and it should not do this by ourselves.

To avoid this we can create a __new async method__ that get's called by post so we can handle async call from outside, kind of a workaround:

```js
post(req, res) {
  this.handledPost(req, res).catch(() => console.log('rejection from inside'));
}

async handledPost() {
  ...lots of awaits that may be rejected but locally handled
}
```

Another may elegant solution is to use more abstractions since we're repeating the same pattern many times.`@ritley/decorators` provides some in order to make our life easier, for example:

```diff
 import {
+  Default,
+  Catch,
   InternalServerError,
   BadRequest,
   Conflict,
   Created
 } from "@ritley/decorators";
```

And probably there's not too much to explain:

```js
import { AbstractResource } from "@ritley/core";
import DataService from "../services/database.service";
import UserModel from "../models/user.model";

import {
  Dependency,
  ReqTransformBodyAsync,
  Default,
  Catch,
  InternalServerError,
  BadRequest,
  Conflict,
  Created
} from "@ritley/decorators";

@Dependency("userModel", UserModel)
export default class UserResource extends AbstractResource {
  constructor(_database) {
    super("/users");
  }

  @Default(Created)
  @ReqTransformBodyAsync
  async post(req, res) {
    const payload = await this.parseBody(req, res);
    await this.validate(payload, res);
    await this.isUnique(payload, res);
    return await this.create(payload, res);
  }

  @Catch(BadRequest, "payload isn't well formed")
  parseBody(req) {
    return req.body.then(body => body.toJSON());
  }

  @Catch(BadRequest, "missing fields, required: [name, mail, pass]")
  validate(payload) {
    return this.userModel.validate(payload);
  }

  @Catch(Conflict, "mail is already taken, try another one")
  isUnique(payload) {
    return this.userModel.isUnique(payload);
  }

  @Catch(InternalServerError, "there was an error creating your user, try again")
  create(payload) {
    return this.userModel.create(payload);
  }
}
```

As you can see these abstractions reduce a bit our code base and improve readability.

As you may wonder `@Catch(responseFn, content)` looks for __synchronous exceptions__ on the method but checks as well if returned value was a promise, if so, adds a `catch()` callback to it. Either a synchronous error or promise rejection will be handled and `responseFn` will be invoked with our `res <Response>` object.

So: `BadRequest, Conflict, InternalServerError, Created`... are just functions exported by `@ritley/decorators` that receive a `res <Response>` object and resolve the proper message to the client. So by calling `BadRequest(res, "wrong!")` client will receive a HTTP 400 with "wrong!" as a response body.

In the other hand `@Default(responseFn)` do quite the same but checking for promise resolution using `then()`. It also attaches a `catch()` to prevent possible unhandled rejections, but it will be resolved with __HTTP 500__ such a case, because that error was not properly handled indeed.

In other words __Default__ tells whats going to happen if everything goes well, and __Catch__ wraps sensible calls with an error message, like checkpoints.

But there is even more:

```diff
 import { AbstractResource } from "@ritley/core";
-import UserModel from "../models/user.model";
+import UserModel, { UserValidationError, UserMailInUseError } from "../models/user.model";
 
-import { Dependency, ReqTransformBodyAsync } from "@ritley/decorators";
+import {
+  Dependency,
+  ReqTransformBodyAsync,
+  Default,
+  Throws,
+  InternalServerError,
+  BadRequest,
+  Conflict,
+  Created
+} from "@ritley/decorators";
 
 @Dependency("userModel", UserModel)
 export default class UserResource extends AbstractResource {
@@ -9,14 +18,16 @@ export default class UserResource extends AbstractResource {
     super("/users");
   }
 
+  @Throws(SyntaxError, BadRequest)
+  @Throws(UserValidationError, BadRequest)
+  @Throws(UserMailInUseError, Conflict)
+  @Default(Created)
   @ReqTransformBodyAsync
   async post(req, res) {
     const body = await req.body;
     const payload = body.toJSON();
     await this.userModel.validate(payload);
     await this.userModel.isUnique(payload);
-    const user = await this.userModel.create(payload);
-    res.statusCode = 200;
-    res.end(JSON.stringify(user));
+    return this.userModel.create(payload);
   }
 }

```

You can use `@Throws` decorator to explicitly tell which type of exception we've to expect in order to trigger specific responses to the client. Mind blowing, right?

See how we're exporting custom errors from our model layer `src/models/user.model.js`:

```diff
     if(requiredProps.every(prop => props.includes(prop))) {
       return Promise.resolve();
     } else {
-      return Promise.reject();
+      throw new UserValidationError
     }
   }
 
@@ -29,7 +28,7 @@ export default class UserModel {
 
   isUnique({ mail }) {
     return new Promise((resolve, reject) =>
-      this.database.exists("users", { mail }).then(reject, resolve));
+      this.database.exists("users", { mail }).then(() => reject(new UserMailInUseError), resolve));
   }
 
   searchBy(predicate) {
@@ -48,3 +47,15 @@ export default class UserModel {
     return this.database.update("users", { uid }, { mail, name });
   }
 }
+
+export class UserValidationError extends Error {
+  constructor() {
+    super("missing fields, required: [name, mail, pass]")
+  }
+}
+
+export class UserMailInUseError extends Error {
+  constructor() {
+    super("mail is already taken, try another one")
+  }
+}
```

So `@Throws(errorType, responseFn)` just goes beyond. While `@Catch` will handle any exception regardless of error type, `@Throws` just provides more concrete way to handle out http layer.

This is the final look for now on `src/resources/user.resource.js`:

```js
import { AbstractResource } from "@ritley/core";
import UserModel, { UserValidationError, UserMailInUseError } from "../models/user.model";

import {
  Dependency,
  ReqTransformBodyAsync,
  Default,
  Throws,
  InternalServerError,
  BadRequest,
  Conflict,
  Created
} from "@ritley/decorators";

@Dependency("userModel", UserModel)
export default class UserResource extends AbstractResource {
  constructor() {
    super("/users");
  }

  @Throws(SyntaxError, BadRequest)
  @Throws(UserValidationError, BadRequest)
  @Throws(UserMailInUseError, Conflict)
  @Default(Created)
  @ReqTransformBodyAsync
  async post(req, res) {
    const body = await req.body;
    const payload = body.toJSON();
    await this.userModel.validate(payload);
    await this.userModel.isUnique(payload);
    return this.userModel.create(payload);
  }
}
```

Just to recap. Whether to use `@Throws` or `@Catch` is up to you although `@Catch` can be considered as a `@Throws(Error, fn)` alias because it will be executed on any exception. But `@Throws` is more deterministic because you can tie your HTTP responses to specific kind of errors or success.

Basically all the _framework logic_ is on http layer. Models are completely independent despite providers. 

[ritley](https://github.com/k1r0s/ritley) defines http triggers that will invoke specific operations on the model that, either success or fail, will be handled back using a declarative set of expressions on top of the same trigger. This basically allows for non-intrusive and declarative development on the backend.
 

That's all for now folks! Following chapter on series will be about handling sessions, separation of  concerns and to keep things scalable with ritley. Cya!

![ritley from metroid](https://thepracticaldev.s3.amazonaws.com/i/7q8l002pngb479ra00l3.jpeg)