Source: rest/ResponseJSON.js

/**
 * @version  1.0
 * @author Boris GBAHOUE
 * @file Response wrapper to structure the messages between our front and back
 * @module amiwo/rest
 * @class ResponseJSON
*/

// =======================================================================
// BASE SETUP
// =======================================================================
var GenericError        = require('./error/GenericError');

// =======================================================================
// METHODS
// =======================================================================
/**
 * Wrapper to build the ResponseJSON for non error replies
 * Every response generated as a result of a REST call is a JSON object.
 * 
 * @returns
 *      - JSON object
 *              - If ok:
 *                      - connection: ok, ko
 *                      - http_code (as per http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html)
 *                              . 200 (ok): the request has succeeded
 *                              . 201 (created): the request has been fulfilled and resulted in a new resource being created
 *                              . 204 (no content): the server has fulfilled the request but does not need to return an entity-body
 *                      - data: object
 *              - If failed:
 *                      - message: a message explaining the problem in plain English
 *                      - resource: the REST API called
 *                      - method: the HTTP method used
 *
 * @public
 * @memberOf ResponseJSON
 */
exports.responseJSON = function(http_code, obj) {
    var response            = {};
    response.connection     = "ok";
    response.http_code      = http_code;
    response.data           = obj;

    return response;
};

/**
 * Wrapper to build a ResponseJSON when an error occured
 * Every response generated as a result of a REST call is a JSON object.
 * In case of error, the data returned are more detailed and are useful
 * to understand why the request was rejected.
 * 
 * @returns
 *      - JSON object
 *              - connection: ko
 *              - http_code: error code (set to 'http_code' param when not null or 500 otherwise)
 *              - message: a message explaining the problem in plain English
 *              - resource: the REST API called
 *              - method: the HTTP method used
 *              - data: other data to describe the issue
 *
 * @public
 * @memberOf ResponseJSON
*/
exports.errorJSON = function(message, resource, method, obj, http_code) {
    var response            = {};
    response.connection     = "ko";
    response.message        = message;
    response.resource       = resource;
    response.method         = method;
    if (obj != null)
        response.data       = obj;

    if (http_code == null) {
        response.http_code = 500;
    } else {
        var code = Number(http_code);
        response.http_code = isNaN(code) ? 500 : code;
    }

    return response;
}

/**
 * Test if an Object is a proper ResponseJSON
 * 
 * @param {Object}
 * @return {Boolean}
 * 
 * @public
 * @memberOf ResponseJSON
 */
exports.isValid = function(json) {
    if (json == null) return false;
    
    if (json.connection == "ok") {
        return (!isNaN(json.http_code) && json.hasOwnProperty("data"));
    } else if (json.connection == "ko") {
        return (json.hasOwnProperty("message") && json.hasOwnProperty("resource") && json.hasOwnProperty("method") && !isNaN(json.http_code));
    } else {
        return false;
    }
}

/**
 * Process an error and returns a properly formatted JSON
 * 
 * @param {Object} msg
 * @param {Express.Request} req
 * 
 * @return {ErrorJSON}
 * 
 * @public
 * @memberOf ResponseJSON
 */
exports.processError = function(msg, req) {
    let tmp;
    let http_code = 500;

    if (msg instanceof GenericError) {
        tmp = msg.object;
        if (!this.isValid(tmp)) { // Check if tmp is a properly formatted errorJSON
            if (tmp && tmp.http_code) http_code = tmp.http_code;
            
            tmp = this.errorJSON(msg.message || "Unexpected Error", req.url, req.method, tmp, http_code);
        }

    } else if (msg instanceof Error) {
        let $err = msg; // for clarity
        let $message = $err.message ? $err.constructor.name+": "+$err.message : "Unexpected error "+$err.constructor.name;
        tmp = this.errorJSON($message, req.url, req.method, $err.object, http_code);

    } else if (typeof msg == 'string') {
        tmp = this.errorJSON(msg, req.url, req.method.toUpperCase(), null, http_code);

    } else {
        tmp = this.errorJSON("Unexpected error : '"+((msg instanceof Object) ? JSON.stringify(msg) : msg)+"'", req.url, req.method.toUpperCase(), msg, http_code);
    }

    return tmp;
}