DEV Community πŸ‘©β€πŸ’»πŸ‘¨β€πŸ’»

Remi Kristelijn
Remi Kristelijn

Posted on

my jsend implementation in node

JSend

This is my implementation of jsend. You can fork/clone the repo and give me your feedback. I tried to stick with:

  1. All responses return json (including errors)
  2. Limit HTTP.status to
    • 200 OK
    • 400 BAD REQUEST (client fault)
    • 500 INTERNAL SERVER ERROR (server fault)
  3. On top of 1 and 2, use jsend standard, but all 4 fields are always returned:
    • status - [OK,FAIL,ERROR],
    • data - the data or the stack
    • message - shortest message possible
    • code - [200,400,500]

The drivers for these 3 points is, that this REST API should serve a frontend with limited exotic situations where the server all of a sudden responds with HTML or different structure.

The code can be found here: https://github.com/rkristelijn/jsend.

I did not implement POST, PUT and DELETE (yet), so it is not a full REST service.

Install

With SSH:

git clone git@github.com:rkristelijn/jsend.git
cd jsend && npm i

With HTTP:

git clone https://github.com/rkristelijn/jsend.git
cd jsend && npm i

Usage

purpose command
start npm start -s
test npm test -s (after server is running)

Demo

Responses

GET /

{
  "status": "SUCCESS",
  "data": {
    "hello": "world",
    "api": "http://localhost:3000/api"
  },
  "message": "200: OK",
  "code": 200
}

GET /api

{
  "status": "FAIL",
  "message": "Route '/api' not found",
  "data": [
    "400: BAD REQUEST",
    "Route '/api' not found",
    {
      "available": [
        ["http://localhost:3000/api/users", "http://localhost:3000/api/fail"]
      ]
    }
  ],
  "code": 400
}

GET /api/users

{
  "status": "SUCCESS",
  "data": {
    "users": [
      {
        "name": "admin",
        "pass": "admin"
      },
      {
        "name": "system",
        "pass": "system"
      },
      {
        "name": "henk",
        "pass": "annie"
      }
    ]
  },
  "message": "200: OK",
  "code": 200
}

GET /api/users/henk

{
  "status": "SUCCESS",
  "data": {
    "user": {
      "name": "henk",
      "pass": "annie"
    }
  },
  "message": "200: OK",
  "code": 200
}

GET /api/fail

I purposely created an error, calling i_will_crash_on_purpose() that doesn't exist to see if a proper JSON is returned.

{
  "status": "ERROR",
  "message": "i_will_crash_on_purpose is not defined",
  "data": [
    "500: INTERNAL SERVER ERROR",
    "ReferenceError: i_will_crash_on_purpose is not defined",
    "at /home/gius/jsend/api/fail/fail-router.js:10:5"
  ],
  "code": 500
}

Key take-aways

npm WARN

Ignore the WARN per heavily discussed fsevent optional dependency for chokidar (via nodemon) in npm here on non-mac systems. There seems no way around it, like I did with the jQuery dependency here

console.log() vs debug()

Debug comes as a dependency of express. Debug can be tailored at the beginning of every file and filtered while starting the app.

you can use a .env file and dotenv or simply add the following to the start script in package.json:

"scripts": {
    "start": "PORT=3000 DEBUG=jsend* nodemon ./bin/www"

Custom validators in test

To keep the test clean, I've written 3 simple validators for jsend that can be reused and keep the test themselves short, manageable and reusable.

e2e test without bootstrapping the app

The test might as well skip setting up the app in before(). This removes redundant code, makes the test simpler and test the actual app.

Arrow-functions / lambdas in test

This is not best practice because of this scope is gone. Mocha strongly advices to avoid lambda's in test:

Passing arrow functions (aka "lambdas") to Mocha is discouraged. Lambdas lexically bind this and cannot access the Mocha context.

Sources

Top comments (0)

Hey 😍

Want to help the DEV Community feel more like a community?

Head over to the Welcome Thread and greet some new community members!

It only takes a minute of your time, and goes a long way!