Source: gwisp.js

/**
- Exports constructor to create instance of Gwisp

@exports gwisp
@author kevin leptons <kevin.leptons@gmail.com>
@example
const gwisp = require('./lib/gwisp')

var app = gwisp({
  verbose: true,
  port: 9001,
  dbUrl: 'mongodb://localhost/gwisp',
  clientId: '327834646153-27e424bo1lpofea0lkfs8bvrf7sv5j2e.apps.googleusercontent.com',
  clientSecret: 'y7RCBAr4AT26oACJBJUSJIxv',
  redirectUrl: 'http://localhost:9001/v1/oauth/login',
  scopes: [
    'https://www.googleapis.com/auth/plus.me',
    'profile',
    'email'
  ]
})

app.start(function(err) {
  // do some thing here
})
*/
module.exports = function (config) {
  return new Gwisp(config)
}

const express = require('express')
const bodyParser = require('body-parser')
const cors = require('cors')
const async = require('async')

const flatlog = require('./flatlog')
const database = require('./database')

/**
- Configuration of Gwisp

For knowledgement for `clientId`, `clientSecret`, `redirectUrl`, `scopes`,
`accountUrl`, see
[google oauth 2]{@link https://developers.google.com/identity/protocols/OAuth2}

For creation an oauth 2 application, go to
[developers]{@link https://console.developers.google.com/apis/dashboard}

@memberof module:gwisp
@typedef {object} Config
@property {boolean} verbose - Decide log request incomming
@property {int} port - Which service listen on
@property {string} dbUrl - Url to mongodb server
@property {string} dbUser - Username of mongodb
@property {string} dbPass - Password to access to mongodb
@property {string} clientId - Client id of google oauth-2
@property {string} clientSecret - Secret key of google oauth-2
@property {string} redirectUrl - Which call by oauth-2 after successful
@property {array} scopes - Array of string which scope of oauth-2
@property {string} accountUrl - Url to retrieve oauth-2 account
@example
var config = {
  verbose: true,
  port: 9001,
  dbUrl: 'mongodb://localhost/gwisp',
  clientId: '327834646153-27e424bo1lpofea0lkfs8bvrf7sv5j2e.apps.googleusercontent.com',
  clientSecret: 'y7RCBAr4AT26oACJBJUSJIxv',
  redirectUrl: 'http://localhost:9001/v1/oauth/login',
  scopes: [
    'https://www.googleapis.com/auth/plus.me',
    'profile',
    'email'
  ]
}
*/

/**
- Create a new Gwisp from configuration

- It use to start http service which help people store and retrieve schedulers

@constructor
@memberof module:gwisp
@class Gwisp
@param {module:gwisp.Config} config - configuration of gwisp
@return {Gwisp} - The new gwisp object
@example
var app = new Gwisp({
  verbose: true,
  port: 9001,
  dbUrl: 'mongodb://localhost/gwisp',
  clientId: '327834646153-27e424bo1lpofea0lkfs8bvrf7sv5j2e.apps.googleusercontent.com',
  clientSecret: 'y7RCBAr4AT26oACJBJUSJIxv',
  redirectUrl: 'http://localhost:9001/v1/oauth/login',
  scopes: [
    'https://www.googleapis.com/auth/plus.me',
    'profile',
    'email'
  ]
})
*/
function Gwisp (config) {
  /**
  Apllication configuration. It is assign by config parameter

  @member {module:gwisp.Config}
  */
  this._config = config

  /**
  Use to make log message iniform

  @member {module:flatlog.FlatLog}
  */
  this._logger = flatlog({verbose: config.verbose, caller: 'gwisp'})

  /**
  Instance of mongo client. Use to do transaction with mongo server.
  It is initialize during start phase, not construt phase

  @member {module:database.Database}
  */
  this._db = database(this._config.dbUrl, this._config.dbUser,
    this._config.dbPass, this._logger)
}

// Shortcut to gwisp prototype
const prototype = Gwisp.prototype

/**
- Start service

@memberof module:gwisp.Gwisp
@param {StdCallback} callback - function will be call after start done
@example
// see constructor for detail
var app = gwisp(config)

app.start(function(err) {
  // do some thing here
})
*/
prototype.start = function (callback) {
  var self = this
  var calls = []

  self._logger.info('kick ass service')

  // handler for error when service is start
  process.on('uncaughtException', function (e) {
    self._logger.error(e.message)
    process.exit(1)
  })

  // connect mongoose database
  // save and reuse only connection
  // todo: configure username, passoword
  calls.push(function (callback) {
    self._db.connect(function (err, db) {
      if (err) {
        self._logger.error(err)
        return callback(err)
      }
      self._dbclient = db

      callback(err)
    })
  })

  calls.push(function (callback) {
    callback(self._serveHttp())
  })

  async.series(calls, function (err) {
    if (err) {
      self._logger.error('kick ass server')
      return callback(err)
    }

    self._logger.info('service is ready')
    callback(null)
  })
}

/**
- create an http server follow configure then listen on specify port

@memberof module:gwisp.Gwisp
@return {Number} - 0 on success, 1 on error
*/
prototype._serveHttp = function () {
  const self = this

  const rootController = require('./controller/root')
  const manController = require('./controller/man')
  // const oauthController = require('./controller/oauth')
  // const accountController = require('./controller/account')
  const regionController = require('./controller/region')
  // const schedulerController = require('./controller/scheduler')
  // const Auth = require('./service/auth')

  // create express erver
  var app = express()
  app.use(cors())
  app.use(bodyParser.urlencoded({extended: true}))
  app.use(bodyParser.json())

  // use router as controller
  // var oauth = self.config.oauth
  // const auth = new Auth(self.db, self.config.oauth.clientId,
  //   self.config.oauth.clientSecret,
  //   self.config.oauth.redirectUrl,
  //   self.config.oauth.scope)
  app.use('/', rootController(self._logger))
  app.use('/man', manController())
  // app.use('/oauth', oauthController(self.db, oauth, auth))
  // app.use('/account', accountController(self.db, oauth, auth))
  app.use('/region', regionController(self._dbclient))
  // app.use('/scheduler', schedulerController(self.db, oauth))

  // start listen request
  try {
    app.listen(self._config.port)
  } catch (e) {
    self._logger.error(e.message)
    return 1
  }

  return 0
}

/**
- Drop databse if it is early exists then install an sample data to database

@memberof module:gwisp.Gwisp
@param {module:database.AssetDir} assetDir - Path to asset directory,
contains static data file in json format
@param {StdCallback} callback Function will be call when setup done.
In this case, result parameter of callback will not specify
@example
// see constructor for detail
var app = new Gwisp(config)

app.setup('asset/sample-data', function(err, res) {
  if (err) {
    console.log('setup new database fails', err)
    process.exit(1)
  }

  console.log('setup new database successfully')
})
*/
prototype.setup = function (assetDir, callback) {
  this._db.setup(assetDir, callback)
}