Skip to content

anyTV/anytv-node-boilerplate

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Node REST API Boilerplate

Build Status Coverage Status Dependencies bitHound Dependencies bitHound Code

Table of contents

Introduction

A boilerplate for REST APIs. Can also be used for server-side rendered web pages. This project strictly uses the company's JS conventions.

Running the application

  1. Download Zip
  2. Extract to your project's folder
  3. Import database/schema.sql and database/seed.sql
mysql -uroot < database/schema.sql
mysql -uroot < database/seed.sql
  1. Run these commands:
npm install -g grunt-cli
npm install
grunt #or npm run dev-server
  1. check http://localhost:<config.app.PORT>
  2. Update package.json details
  3. Update config/config.js
  4. Don't forget to pull

Creating a controller

Controllers are the heart of your application, as they determine how HTTP requests should be handled. They are located at the controllers folder. They are not automatically routed. You must explicitly route them in config/router.js. Using sub-folders for file organization is allowed.

Here's a typical controller:

// user.js

require('app-module-path/register');

const util   = require('../helpers/util');
const mysql  = require('anytv-node-mysql');
const squel  = require('squel');
const moment = require('moment');



exports.update_user = (req, res, next) => {

    const data = util.get_data(
        {
            user_id: '',
            _first_name: '',
            _last_name: ''
        },
        req.body
    );


    function start () {
        let id;

        if (data instanceof Error) {
            return res.warn(400, {message: data.message});
        }

        id = data.user_id;
        delete data.user_id;

        const query = squel.update()
            .table('users')
            .setFields(data)
            .where('user_id = ?', id)
            .limit(1);
        
        mysql.use('my_db')
            .squel(query, send_response)
            .end();
    }


    function send_response (err, result) {
        if (err) {
            return next(err);
        }

        res.send({ message: 'User successfully updated' });
    }

    start();
};



exports.delete_user = (req, res, next) => {
...

Detailed explanation:

require('app-module-path/register');

const util   = require('../helpers/util');
const mysql  = require('anytv-node-mysql');
const squel  = require('squel');
const moment = require('moment');
  • The first part of the controller contains the helpers, and libraries to be used by the controller's functions
  • The app-module-path/register module prevents the usage of __dirname in requiring local modules
  • Notice the order of imported files, local files first followed by 3rd-party libraries
  • This block should always be followed by at least one new line to separate them visually easily
exports.update_user = (req, res, next) => {
  • snake_case on exported function names
  • req is an object from express, it contains user's request
  • res also an object from express, use this object to respond to the request
  • next a function from express, use this to pass to the next middleware which is the error handler
    const data = util.get_data(
        {
            user_id: '',
            _first_name: '',
            _last_name: ''
        },
        req.body
    ),
  • it is common to use data as the variable to store the parameters given by the user
  • util.get_data helps on filtering the request payload
  • putting an underscore as first character makes it optional
  • non-function variables are also declared first
  • new line after non-function variables to make it more readable
    function start () {

        let id;

        if (data instanceof Error) {
            return res.warn(400, {message: data.message});
        }

        id = data.id;
        delete data.id;

        const query = squel.update()
            .table('users')
            .setFields(data)
            .where('user_id = ?', id)
            .limit(1);
        
        mysql.use('my_db')
            .squel(query, send_response)
            .end();
    }
  • start function is required for uniformity
  • the idea is to have the code be readable like a book, from top-to-bottom
  • since variables are declared first and functions are assigned to variables, we thought of having start function to denote the start of the process
  • as much as possible, there should be no more named functions inside this level except for forEach, map, filter, and reduce. If lodash is available, use it.
    function send_response (err, result) {

        if (err) {
            return next(err);
        }

        res.send({ message: 'User successfully updated' });
    }

    start();
  • send_response is common to be the last function to be executed
  • use next for passing server fault errors
  • after all variable and function declarations, call start

Notes:

  • use res.warn(status, obj) or res.warn(obj) instead of next(error) if the error is caused by the API caller

Setting environment configs

The default configuration uses development. Any changes on the files inside that folder will be ignored. If you want your config to be added on the repo permanently, add it on config.js. Just make sure that it's not confidential.

production is a dedicated config folder for the production environment. Use it via setting $NODE_ENV to production

export NODE_ENV=production

Contributing

Install the tools needed:

npm install istanbul -g
npm install apidoc -g
npm install mocha -g
npm install --only=dev

Production Config

git submodule add -b <branch> <https repository> config/env/production
  • Whenever there are changes in production, you should update the submodule too.
git submodule init
git submodule foreach git pull

Running test

npm test
# or
grunt test

Test Driven Development (TDD)

  • Use npm scripts or grunt tasks that watches the tests.
npm run dev-tests
# or
grunt dev-tests

Code coverage

npm run coverage

Then open coverage/lcov-report/index.html.

API documentation

npm run docs

Then open apidoc/index.html.

License

MIT

Author

Freedom! Labs, any.TV Limited DBA Freedom!

About

anyTV boilerplate for creating backend API on node.js

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published