<commit_before>/**
 * @fileoverview Test for BubbleChart.
 * @author NHN Ent.
 *         FE Development Team <dl_javascript@nhnent.com>
 */

'use strict';

var BubbleChart = require('../../src/js/charts/bubbleChart'),
    axisDataMaker = require('../../src/js/helpers/axisDataMaker');

describe('Test for BubbleChart', function() {
    var bubbleChart, sereisDataModel;

    beforeEach(function() {
        bubbleChart = BubbleChart.prototype;
        bubbleChart.dataProcessor = jasmine.createSpyObj('dataProcessor',
            ['getCategories', 'hasCategories', 'getSeriesDataModel', 'getValues', 'addDataRatiosForCoordinateType']);
        sereisDataModel = jasmine.createSpyObj('seriesDataModel', ['isXCountGreaterThanYCount']);
    });

    describe('_makeAxisScaleMakerMap()', function() {
        it('_createAxisScaleMaker()의 반환값으로 scaleMakerMap의 xAxis와 yAxis에 설정합니다.', function() {
            bubbleChart.dataProcessor.hasCategories.and.returnValue(false);
            bubbleChart.dataProcessor.getSeriesDataModel.and.returnValue(sereisDataModel);
            spyOn(bubbleChart, '_createAxisScaleMaker').and.returnValue('instance of axisScaleMaker');
            bubbleChart.options = {
                xAxis: {
                    min: 0,
                    max: 80
                },
                yAxis: {
                    min: 20,
                    max: 90
                }
            };

            bubbleChart._makeAxisScaleMakerMap();

            expect(bubbleChart._createAxisScaleMaker).toHaveBeenCalledWith({
                min: 0,
                max: 80
            }, 'x');
            expect(bubbleChart._createAxisScaleMaker).toHaveBeenCalledWith({
                min: 20,
                max: 90
            }, 'y');
        });

        it('카테고리가 없다면 xAxis와 yAxis 모두에 설정하여 반환합니다.', function() {
            var actual, expected;

            bubbleChart.dataProcessor.hasCategories.and.returnValue(false);
            bubbleChart.dataProcessor.getSeriesDataModel.and.returnValue(sereisDataModel);
            spyOn(bubbleChart, '_createAxisScaleMaker').and.returnValue('instance of axisScaleMaker');
            bubbleChart.options = {
                xAxis: {
                    min: 0,
                    max: 80
                },
                yAxis: {
                    min: 20,
                    max: 90
                }
            };

            actual = bubbleChart._makeAxisScaleMakerMap();
            expected = {
                xAxis: 'instance of axisScaleMaker',
                yAxis: 'instance of axisScaleMaker'
            };

            expect(actual).toEqual(expected);
        });

        it('카테고리가 있고 x값의 개수가 y값의 개수보다 많다면 xAxis만 설정하여 반환합니다.', function() {
            var actual, expected;

            bubbleChart.dataProcessor.hasCategories.and.returnValue(true);
            sereisDataModel.isXCountGreaterThanYCount.and.returnValue(true);
            bubbleChart.dataProcessor.getSeriesDataModel.and.returnValue(sereisDataModel);
            spyOn(bubbleChart, '_createAxisScaleMaker').and.returnValue('instance of axisScaleMaker');
            bubbleChart.options = {
                xAxis: {
                    min: 0,
                    max: 80
                },
                yAxis: {
                    min: 20,
                    max: 90
                }
            };

            actual = bubbleChart._makeAxisScaleMakerMap();
            expected = {
                xAxis: 'instance of axisScaleMaker'
            };

            expect(actual).toEqual(expected);
        });

        it('카테고리가 있고 x값의 개수가 y값의 개수보다 작거나 같다면 yAxis만 설정하여 반환합니다.', function() {
            var actual, expected;

            bubbleChart.dataProcessor.hasCategories.and.returnValue(true);
            sereisDataModel.isXCountGreaterThanYCount.and.returnValue(false);
            bubbleChart.dataProcessor.getSeriesDataModel.and.returnValue(sereisDataModel);
            spyOn(bubbleChart, '_createAxisScaleMaker').and.returnValue('instance of axisScaleMaker');
            bubbleChart.options = {
                xAxis: {
                    min: 0,
                    max: 80
                },
                yAxis: {
                    min: 20,
                    max: 90
                }
            };

            actual = bubbleChart._makeAxisScaleMakerMap();
            expected = {
                yAxis: 'instance of axisScaleMaker'
            };

            expect(actual).toEqual(expected);
        });
    });

    describe('_makeAxesData()', function() {
        it('카테고리가 없고 axisScaleMap의 xAxis, yAxis모두 axisScaleMaker를 갖고 있다면 반환하는 xAxis와 yAxis의 axisData는 모두 값 타입 입니다.', function() {
            var actual, expected;

            bubbleChart.dataProcessor.getCategories.and.returnValue([]);
            spyOn(axisDataMaker, 'makeValueAxisData').and.returnValue('value type');
            spyOn(bubbleChart, '_getAxisScaleMakerMap').and.returnValue({
                xAxis: 'instance of axisScaleMaker',
                yAxis: 'instance of axisScaleMaker'
            })
            actual = bubbleChart._makeAxesData();
            expected = {
                xAxis: 'value type',
                yAxis: 'value type'
            };

            expect(actual).toEqual(expected);
        });

        it('카테고리가 있고 axisScaleMap의 xAxis만 axisScaleMaker를 갖고 있다면 반환하는 xAxis는 값 타입이고 yAxis는 라벨 타입 입니다.', function() {
            var actual, expected;

            bubbleChart.dataProcessor.getCategories.and.returnValue(['cate1', 'cate2', 'cate3']);
            spyOn(axisDataMaker, 'makeValueAxisData').and.returnValue('value type');
            spyOn(axisDataMaker, 'makeLabelAxisData').and.returnValue({
                isLabel: true
            });
            spyOn(bubbleChart, '_getAxisScaleMakerMap').and.returnValue({
                xAxis: 'instance of axisScaleMaker'
            });
            actual = bubbleChart._makeAxesData();
            expected = {
                xAxis: 'value type',
                yAxis: {
                    isLabel: true,
                    isVertical: true
                }
            };

            expect(actual).toEqual(expected);
        });

        it('카테고리가 있고 yAxis만 axisScaleMaker를 갖고 있다면 반환하는 xAxis는 라벨 타입이고 yAxis는 값 타입 입니다.', function() {
            var actual, expected;

            bubbleChart.dataProcessor.getCategories.and.returnValue(['cate1', 'cate2', 'cate3']);
            spyOn(axisDataMaker, 'makeValueAxisData').and.returnValue('value type');
            spyOn(axisDataMaker, 'makeLabelAxisData').and.returnValue('label type');
            spyOn(bubbleChart, '_getAxisScaleMakerMap').and.returnValue({
                yAxis: 'instance of axisScaleMaker'
            });
            actual = bubbleChart._makeAxesData();
            expected = {
                xAxis: 'label type',
                yAxis: 'value type'
            };

            expect(actual).toEqual(expected);
        });
    });

    describe('_addDataRatios()', function() {
        it('axisScaleMap의 xAxis가 axisScaleMaker를 갖고 있다면 limit을 구해 limitMap.x에 설정한뒤 dataProcessor.addDataRatiosForCoordinateType에 전달합니다', function() {
            var axisScaleMaker = jasmine.createSpyObj('axisScaleMaker', ['getLimit']);

            axisScaleMaker.getLimit.and.returnValue('calculated limit by x values');
            spyOn(bubbleChart, '_getAxisScaleMakerMap').and.returnValue({
                xAxis: axisScaleMaker
            });
            bubbleChart._addDataRatios();

            expect(bubbleChart.dataProcessor.addDataRatiosForCoordinateType).toHaveBeenCalledWith({
                x: 'calculated limit by x values'
            });
        });

        it('axisScaleMap의 yAxis가 axisScaleMaker를 갖고 있다면 limit을 구해 limitMap.y에 설정한뒤 dataProcessor.addDataRatiosForCoordinateType에 전달합니다', function() {
            var axisScaleMaker = jasmine.createSpyObj('axisScaleMaker', ['getLimit']);

            axisScaleMaker.getLimit.and.returnValue('calculated limit by y values');
            spyOn(bubbleChart, '_getAxisScaleMakerMap').and.returnValue({
                yAxis: axisScaleMaker
            });
            bubbleChart._addDataRatios();

            expect(bubbleChart.dataProcessor.addDataRatiosForCoordinateType).toHaveBeenCalledWith({
                y: 'calculated limit by y values'
            });
        });
    });
});
<commit_msg>test: Use dataProcessor instead bubbleChart.dataProcessor.<commit_after>/**
 * @fileoverview Test for BubbleChart.
 * @author NHN Ent.
 *         FE Development Team <dl_javascript@nhnent.com>
 */

'use strict';

var BubbleChart = require('../../src/js/charts/bubbleChart'),
    axisDataMaker = require('../../src/js/helpers/axisDataMaker');

describe('Test for BubbleChart', function() {
    var bubbleChart, dataProcessor, sereisDataModel;

    beforeEach(function() {
        bubbleChart = BubbleChart.prototype;
        dataProcessor = jasmine.createSpyObj('dataProcessor',
            ['getCategories', 'hasCategories', 'getCategories', 'getSeriesDataModel', 'getValues',
                'getFormattedMaxValue', 'addDataRatiosForCoordinateType']);
        sereisDataModel = jasmine.createSpyObj('seriesDataModel', ['isXCountGreaterThanYCount']);

        bubbleChart.dataProcessor = dataProcessor;
    });

    describe('_makeAxisScaleMakerMap()', function() {
        it('_createAxisScaleMaker()의 반환값으로 scaleMakerMap의 xAxis와 yAxis에 설정합니다.', function() {
            dataProcessor.hasCategories.and.returnValue(false);
            dataProcessor.getSeriesDataModel.and.returnValue(sereisDataModel);
            spyOn(bubbleChart, '_createAxisScaleMaker').and.returnValue('instance of axisScaleMaker');
            bubbleChart.options = {
                xAxis: {
                    min: 0,
                    max: 80
                },
                yAxis: {
                    min: 20,
                    max: 90
                }
            };

            bubbleChart._makeAxisScaleMakerMap();

            expect(bubbleChart._createAxisScaleMaker).toHaveBeenCalledWith({
                min: 0,
                max: 80
            }, 'x');
            expect(bubbleChart._createAxisScaleMaker).toHaveBeenCalledWith({
                min: 20,
                max: 90
            }, 'y');
        });

        it('카테고리가 없다면 xAxis와 yAxis 모두에 설정하여 반환합니다.', function() {
            var actual, expected;

            dataProcessor.hasCategories.and.returnValue(false);
            dataProcessor.getSeriesDataModel.and.returnValue(sereisDataModel);
            spyOn(bubbleChart, '_createAxisScaleMaker').and.returnValue('instance of axisScaleMaker');
            bubbleChart.options = {
                xAxis: {
                    min: 0,
                    max: 80
                },
                yAxis: {
                    min: 20,
                    max: 90
                }
            };

            actual = bubbleChart._makeAxisScaleMakerMap();
            expected = {
                xAxis: 'instance of axisScaleMaker',
                yAxis: 'instance of axisScaleMaker'
            };

            expect(actual).toEqual(expected);
        });

        it('카테고리가 있고 x값의 개수가 y값의 개수보다 많다면 xAxis만 설정하여 반환합니다.', function() {
            var actual, expected;

            dataProcessor.hasCategories.and.returnValue(true);
            sereisDataModel.isXCountGreaterThanYCount.and.returnValue(true);
            dataProcessor.getSeriesDataModel.and.returnValue(sereisDataModel);
            spyOn(bubbleChart, '_createAxisScaleMaker').and.returnValue('instance of axisScaleMaker');
            bubbleChart.options = {
                xAxis: {
                    min: 0,
                    max: 80
                },
                yAxis: {
                    min: 20,
                    max: 90
                }
            };

            actual = bubbleChart._makeAxisScaleMakerMap();
            expected = {
                xAxis: 'instance of axisScaleMaker'
            };

            expect(actual).toEqual(expected);
        });

        it('카테고리가 있고 x값의 개수가 y값의 개수보다 작거나 같다면 yAxis만 설정하여 반환합니다.', function() {
            var actual, expected;

            dataProcessor.hasCategories.and.returnValue(true);
            sereisDataModel.isXCountGreaterThanYCount.and.returnValue(false);
            dataProcessor.getSeriesDataModel.and.returnValue(sereisDataModel);
            spyOn(bubbleChart, '_createAxisScaleMaker').and.returnValue('instance of axisScaleMaker');
            bubbleChart.options = {
                xAxis: {
                    min: 0,
                    max: 80
                },
                yAxis: {
                    min: 20,
                    max: 90
                }
            };

            actual = bubbleChart._makeAxisScaleMakerMap();
            expected = {
                yAxis: 'instance of axisScaleMaker'
            };

            expect(actual).toEqual(expected);
        });
    });

    describe('_makeAxesData()', function() {
        it('카테고리가 없고 axisScaleMap의 xAxis, yAxis모두 axisScaleMaker를 갖고 있다면 반환하는 xAxis와 yAxis의 axisData는 모두 값 타입 입니다.', function() {
            var actual, expected;

            dataProcessor.getCategories.and.returnValue([]);
            spyOn(axisDataMaker, 'makeValueAxisData').and.returnValue('value type');
            spyOn(bubbleChart, '_getAxisScaleMakerMap').and.returnValue({
                xAxis: 'instance of axisScaleMaker',
                yAxis: 'instance of axisScaleMaker'
            })
            actual = bubbleChart._makeAxesData();
            expected = {
                xAxis: 'value type',
                yAxis: 'value type'
            };

            expect(actual).toEqual(expected);
        });

        it('카테고리가 있고 axisScaleMap의 xAxis만 axisScaleMaker를 갖고 있다면 반환하는 xAxis는 값 타입이고 yAxis는 라벨 타입 입니다.', function() {
            var actual, expected;

            dataProcessor.getCategories.and.returnValue(['cate1', 'cate2', 'cate3']);
            spyOn(axisDataMaker, 'makeValueAxisData').and.returnValue('value type');
            spyOn(axisDataMaker, 'makeLabelAxisData').and.returnValue({
                isLabel: true
            });
            spyOn(bubbleChart, '_getAxisScaleMakerMap').and.returnValue({
                xAxis: 'instance of axisScaleMaker'
            });
            actual = bubbleChart._makeAxesData();
            expected = {
                xAxis: 'value type',
                yAxis: {
                    isLabel: true,
                    isVertical: true
                }
            };

            expect(actual).toEqual(expected);
        });

        it('카테고리가 있고 yAxis만 axisScaleMaker를 갖고 있다면 반환하는 xAxis는 라벨 타입이고 yAxis는 값 타입 입니다.', function() {
            var actual, expected;

            dataProcessor.getCategories.and.returnValue(['cate1', 'cate2', 'cate3']);
            spyOn(axisDataMaker, 'makeValueAxisData').and.returnValue('value type');
            spyOn(axisDataMaker, 'makeLabelAxisData').and.returnValue('label type');
            spyOn(bubbleChart, '_getAxisScaleMakerMap').and.returnValue({
                yAxis: 'instance of axisScaleMaker'
            });
            actual = bubbleChart._makeAxesData();
            expected = {
                xAxis: 'label type',
                yAxis: 'value type'
            };

            expect(actual).toEqual(expected);
        });
    });

    describe('_addDataRatios()', function() {
        it('axisScaleMap의 xAxis가 axisScaleMaker를 갖고 있다면 limit을 구해 limitMap.x에 설정한뒤 dataProcessor.addDataRatiosForCoordinateType에 전달합니다', function() {
            var axisScaleMaker = jasmine.createSpyObj('axisScaleMaker', ['getLimit']);

            axisScaleMaker.getLimit.and.returnValue('calculated limit by x values');
            spyOn(bubbleChart, '_getAxisScaleMakerMap').and.returnValue({
                xAxis: axisScaleMaker
            });
            bubbleChart._addDataRatios();

            expect(dataProcessor.addDataRatiosForCoordinateType).toHaveBeenCalledWith({
                x: 'calculated limit by x values'
            });
        });

        it('axisScaleMap의 yAxis가 axisScaleMaker를 갖고 있다면 limit을 구해 limitMap.y에 설정한뒤 dataProcessor.addDataRatiosForCoordinateType에 전달합니다', function() {
            var axisScaleMaker = jasmine.createSpyObj('axisScaleMaker', ['getLimit']);

            axisScaleMaker.getLimit.and.returnValue('calculated limit by y values');
            spyOn(bubbleChart, '_getAxisScaleMakerMap').and.returnValue({
                yAxis: axisScaleMaker
            });
            bubbleChart._addDataRatios();

            expect(dataProcessor.addDataRatiosForCoordinateType).toHaveBeenCalledWith({
                y: 'calculated limit by y values'
            });
        });
    });
});
<|endoftext|>


<commit_before>var config = require('../config.json');
var _ = require('lodash');
//var jwt = require('jsonwebtoken');
//var bcrypt = require('bcryptjs');
var Q = require('q');
var mongo = require('mongoskin');
var db = mongo.db(config.connectionString, { native_parser: true });
db.bind('timesheets');
db.bind('users');
db.bind('projects');

var service = {};
service.getProjectInfoById = getProjectInfoById;
var rowCnt = 0;
var allProjects = [];
db.projects.find({}).toArray(function(err, projects) {
    allProjects = projects;
    db.timesheets.find({}).sort({createdOn: 1}).toArray(function(err, timesheets) {
        _.each(timesheets, function (timesheetObj) {
            db.users.findById(timesheetObj.userId, function(err, userObj) {
                if (err) console.log(err.name + ': ' + err.message);
                if(userObj === null){
                    console.log(timesheetObj);
                }
                if(userObj !== null && userObj.userResourceType){
                    timesheetObj.userResourceType = userObj.userResourceType;
                }else{
                    timesheetObj.userResourceType = "";
                }
                timesheetObj.createdOn = new Date(timesheetObj.weekDate);
                timesheetObj.updatedOn = new Date(timesheetObj.weekDate);
                _.each(timesheetObj.projects, function (projectObj) {
                    projectObj.sickLeaveHours = 0;
                    projectObj.timeoffHours = 0;
                    var billData = getProjectBillData(projectObj, timesheetObj.weekDate, userObj);
                    projectObj.resourceType = billData.resourceType;
                    projectObj.allocatedHours = billData.allocatedHours;
                    projectObj.billableMaxHours = billData.billableMaxHours;
                    if(projectObj.billableMaxHours > 0){
                        if(projectObj.projectHours > projectObj.billableMaxHours){
                            projectObj.billableHours = projectObj.billableMaxHours;
                        }else{
                            projectObj.billableHours = projectObj.projectHours;
                        }
                    }else{
                        projectObj.billableHours = projectObj.projectHours;
                    }
                });
                var timeoffObj = _.find(timesheetObj.projects, {projectName: 'Timeoff'});
                if(timeoffObj && timesheetObj.projects.length > 1){
                    timesheetObj.projects.splice(timesheetObj.projects.indexOf(timeoffObj), 1);
                    timesheetObj.projects[0].timeoffHours = timeoffObj.projectHours;
                    timesheetObj.projects[0].projectComment = timesheetObj.projects[0].projectComment + " Timeoff: " +timeoffObj.projectComment;
                }
                timesheetObj.timeoffHours = 0;
                timesheetObj.totalHours = 0;
                _.each(timesheetObj.projects, function (projectObj) {
                    projectObj.businessUnit = "";
                    var projectInfo = _.find(allProjects, {_id: projectObj.projectId});
                    if(projectInfo && projectInfo.businessUnit){
                        projectObj.businessUnit = projectInfo.businessUnit;
                    }
                    timesheetObj.totalHours += projectObj.projectHours;
                    timesheetObj.timeoffHours += projectObj.sickLeaveHours;
                    timesheetObj.timeoffHours += projectObj.timeoffHours;
                });
                db.timesheets.update({ _id: mongo.helper.toObjectID(timesheetObj._id) }, { $set: timesheetObj }, function(err, responseSheet) {
                    if (err) console.log(err.name + ': ' + err.message);
                    rowCnt++;
                    console.log(timesheetObj._id+" Updated "+rowCnt);
                });
            });
        });
    });
});

function getProjectBillData(projectObj, weekDateVal, sheetUserObj) {
    var BillData = {
        resourceType: "buffer",
        allocatedHours: 40,
        billableMaxHours: 0
    };
    if (sheetUserObj && sheetUserObj.projects) {
        var prjData = _.find(sheetUserObj.projects, {"projectId": projectObj.projectId+""});
        if (prjData && prjData.billDates) {
            var weekDate = new Date(weekDateVal);
            _.each(prjData.billDates, function (billDate) {
                if (billDate.start && billDate.start != "" && billDate.end && billDate.end != "") {
                    var startDate = new Date(billDate.start);
                    var endDate = new Date(billDate.end);
                    if (weekDate >= startDate && weekDate <= endDate) {
                        BillData.resourceType = billDate.resourceType;
                        BillData.allocatedHours = billDate.allocatedHours;
                        BillData.billableMaxHours = billDate.billableMaxHours;
                    }
                } else if (billDate.start && billDate.start != "") {
                    var startDate = new Date(billDate.start);
                    if (weekDate >= startDate) {
                        BillData.resourceType = billDate.resourceType;
                        BillData.allocatedHours = billDate.allocatedHours;
                        BillData.billableMaxHours = billDate.billableMaxHours;
                    }
                } else if (billDate.end && billDate.end != "") {
                    var endDate = new Date(billDate.end);
                    if (weekDate <= endDate) {
                        BillData.resourceType = billDate.resourceType;
                        BillData.allocatedHours = billDate.allocatedHours;
                        BillData.billableMaxHours = billDate.billableMaxHours;
                    }
                } else if (billDate.start == "" && billDate.end == "") {
                    BillData.resourceType = billDate.resourceType;
                    BillData.allocatedHours = billDate.allocatedHours;
                    BillData.billableMaxHours = billDate.billableMaxHours;
                }
            });
        }
    }
    if(!(BillData.allocatedHours >= 0)){
        BillData.allocatedHours = 40;
    }
    if(!(BillData.billableMaxHours >= 0)){
        BillData.billableMaxHours = 0;
    }
    return BillData;
}

function getProjectInfoById(projectId) {
    var deferred = Q.defer();
    db.projects.findById(projectId, function(err, projectInfo) {
        if (projectInfo) {
            deferred.resolve(projectInfo);
        } else {
            deferred.resolve([])
        }
    });
    return deferred.promise;
}
<commit_msg>timesheets update<commit_after>var config = require('../config.json');
var _ = require('lodash');
//var jwt = require('jsonwebtoken');
//var bcrypt = require('bcryptjs');
var Q = require('q');
var mongo = require('mongoskin');
var db = mongo.db(config.connectionString, { native_parser: true });
db.bind('timesheets');
db.bind('users');
db.bind('projects');

var service = {};

db.timesheets.find({}).sort({createdOn: -1}).toArray(function(err, timesheets) {
    _.each(timesheets, function (timesheetObj) {
        timesheetObj.overtimeHours = 0;
        _.each(timesheetObj.projects, function (projectObj) {
            projectObj.overtimeHours = 0;
            if(projectObj.billableMaxHours > 0 && projectObj.projectHours > projectObj.billableMaxHours){
                projectObj.overtimeHours = projectObj.projectHours - projectObj.billableMaxHours;
            }
            timesheetObj.overtimeHours += projectObj.overtimeHours;
        });
        db.timesheets.update({ _id: mongo.helper.toObjectID(timesheetObj._id) }, { '$set': timesheetObj }, function(err, response) {
            if (err) deferred.reject(err.name + ': ' + err.message);
            console.log(timesheetObj._id);
        });
    });
});

<|endoftext|>


<commit_before>var Blockchain = require('./blockchain.js');
var Compiler = require('./compiler.js');
var utils = require('ethereumjs-util');
var fs = require('fs');
var async = require('async');
var pkg = require('../package.json');

var optionalCallback = function (cb) {
    if (typeof(cb) == 'undefined') {
        return function (err, val) { return err ? err : val; }
    }
    return cb;
};

Manager = function () {
  this.blockchain = new Blockchain();
}

Manager.prototype.initialize = function(initialAccounts, callback) {
  var self = this;
  // Add accounts for testing purposes.
  if (typeof(initialAccounts) == 'function') {
    return initialAccounts();
  }

  async.times(initialAccounts, function(n, next) {
    self.blockchain.addAccount(next);
  }, callback);
};

Manager.prototype.mine = function() {
  this.blockchain.mine();
}

Manager.prototype.response = function(params, result) {
  return {"id":params.id,"jsonrpc":"2.0","result":result};
}

// Handle individual requests.

Manager.prototype.request = function(params, cb) {
  if (Object.prototype.toString.call(params) === '[object Array]') {
    var results = [];
    for (var i=0; i < params.length; i+=1) {
      results.push(this.request(params[i]));
    }
    return cb(null, results);
  }

  var fn = this[params.method];
  var args = params.params || [];

  if (cb) {
    var that = this;
    args.push(function (err, res) {
      cb(err, that.response(params, res));
    });
  }

  var result = fn.apply(this, args);

  return this.response(params, result);
};

Manager.prototype.eth_accounts = function(callback) {
  callback = optionalCallback(callback);
  return callback(null, this.blockchain.accountAddresses());
};

Manager.prototype.eth_blockNumber = function(callback) {
  callback = optionalCallback(callback);
  return callback(null, this.blockchain.toHex(this.blockchain.blockNumber()));
};

Manager.prototype.eth_coinbase = function(callback) {
  callback = optionalCallback(callback);
  return callback(null, this.blockchain.coinbase);
};

Manager.prototype.eth_mining = function(callback) {
  callback = optionalCallback(callback);
  return callback(null, false);
};

Manager.prototype.eth_hashrate = function(callback) {
  callback = optionalCallback(callback);
  return callback(null, '0x' + utils.intToHex(0));
};

Manager.prototype.eth_gasPrice = function(callback) {
  callback = optionalCallback(callback);
  return callback(null, '0x' + this.blockchain.gasPrice());
};

Manager.prototype.eth_getBalance = function(address, block_number, callback) {
  if (callback !== undefined) this.blockchain.getBalance(address, callback);
  return "please use an async call";
};

Manager.prototype.ethersim_setBalance = function(address, balance, callback) {
  this.blockchain.setBalance(address, balance, callback);
};

Manager.prototype.eth_getCode = function(address, block_number, callback) {
  callback = optionalCallback(callback);
  return callback(null, this.blockchain.getCode(address));
};

Manager.prototype.eth_getBlockByNumber = function(block_number, include_transactions, callback) {
  callback = optionalCallback(callback);
  return callback(null, this.blockchain.getBlockByNumber(block_number));
};

Manager.prototype.eth_getBlockByHash = function(tx_hash, include_transactions, callback) {
  callback = optionalCallback(callback);
  return callback(null, this.blockchain.getBlockByHash(tx_hash));
};

Manager.prototype.eth_getTransactionReceipt = function(tx_hash, callback) {
  callback = optionalCallback(callback);
  return callback(null, this.blockchain.getTransactionReceipt(tx_hash));
};

Manager.prototype.eth_getTransactionByHash = function(tx_hash, callback) {
  callback = optionalCallback(callback);
  return callback(null, this.blockchain.getTransactionByHash(tx_hash));
}

Manager.prototype.eth_getTransactionCount = function(address, block_number, callback) {
  callback = optionalCallback(callback);
  this.blockchain.getTransactionCount(address, callback);
}

Manager.prototype.eth_sendTransaction = function(tx_data, callback) {
  callback = optionalCallback(callback);
  this.blockchain.queueTransaction(tx_data, callback);
};

Manager.prototype.eth_sendRawTransaction = function(rawTx, callback) {
  callback = optionalCallback(callback);
  return callback(new Error("eth_sendRawTransaction not implemented yet, but it will be soon"));
};

Manager.prototype.eth_call = function(tx_data, block_number, callback) {
  callback = optionalCallback(callback);
  this.blockchain.queueCall(tx_data, callback);
};

Manager.prototype.eth_newBlockFilter = function(callback) {
  var filter_id = utils.addHexPrefix(utils.intToHex(this.blockchain.latest_filter_id));
  this.blockchain.latest_filter_id += 1;
  callback(null, filter_id);
};

Manager.prototype.eth_getFilterChanges = function(filter_id, callback) {
  var blockHash = this.blockchain.latestBlock().hash().toString("hex");
  // Mine a block after each request to getFilterChanges so block filters work.
  this.blockchain.mine();
  callback = optionalCallback(callback);
  return callback(null, [blockHash]);
};

Manager.prototype.eth_uninstallFilter = function(filter_id, callback) {
  callback(null, true);
};

Manager.prototype.eth_getCompilers = function(callback) {
  callback(null, ["solidity"]);
}

Manager.prototype.eth_compileSolidity = function(code, callback) {
  var compiler = new Compiler();
  fs.writeFileSync("/tmp/solCompiler.sol", code);
  compiled = compiler.compile_solidity("/tmp/solCompiler.sol");
  callback = optionalCallback(callback);
  return callback(null, compiled);
};

Manager.prototype.web3_clientVersion = function(callback) {
  callback = optionalCallback(callback);
  return callback(null, "EtherSim/v" + pkg.version + "/ethereum-js")
};

/* Functions for testing purposes only. */

Manager.prototype.evm_snapshot = function(callback) {
  callback = optionalCallback(callback);
  return callback(null, this.blockchain.snapshot());
};

Manager.prototype.evm_revert = function(snapshot_id, callback) {
  callback = optionalCallback(callback);
  return callback(null, this.blockchain.revert(snapshot_id));
};

module.exports = Manager;
<commit_msg>tx_hash => block_hash<commit_after>var Blockchain = require('./blockchain.js');
var Compiler = require('./compiler.js');
var utils = require('ethereumjs-util');
var fs = require('fs');
var async = require('async');
var pkg = require('../package.json');

var optionalCallback = function (cb) {
    if (typeof(cb) == 'undefined') {
        return function (err, val) { return err ? err : val; }
    }
    return cb;
};

Manager = function () {
  this.blockchain = new Blockchain();
}

Manager.prototype.initialize = function(initialAccounts, callback) {
  var self = this;
  // Add accounts for testing purposes.
  if (typeof(initialAccounts) == 'function') {
    return initialAccounts();
  }

  async.times(initialAccounts, function(n, next) {
    self.blockchain.addAccount(next);
  }, callback);
};

Manager.prototype.mine = function() {
  this.blockchain.mine();
}

Manager.prototype.response = function(params, result) {
  return {"id":params.id,"jsonrpc":"2.0","result":result};
}

// Handle individual requests.

Manager.prototype.request = function(params, cb) {
  if (Object.prototype.toString.call(params) === '[object Array]') {
    var results = [];
    for (var i=0; i < params.length; i+=1) {
      results.push(this.request(params[i]));
    }
    return cb(null, results);
  }

  var fn = this[params.method];
  var args = params.params || [];

  if (cb) {
    var that = this;
    args.push(function (err, res) {
      cb(err, that.response(params, res));
    });
  }

  var result = fn.apply(this, args);

  return this.response(params, result);
};

Manager.prototype.eth_accounts = function(callback) {
  callback = optionalCallback(callback);
  return callback(null, this.blockchain.accountAddresses());
};

Manager.prototype.eth_blockNumber = function(callback) {
  callback = optionalCallback(callback);
  return callback(null, this.blockchain.toHex(this.blockchain.blockNumber()));
};

Manager.prototype.eth_coinbase = function(callback) {
  callback = optionalCallback(callback);
  return callback(null, this.blockchain.coinbase);
};

Manager.prototype.eth_mining = function(callback) {
  callback = optionalCallback(callback);
  return callback(null, false);
};

Manager.prototype.eth_hashrate = function(callback) {
  callback = optionalCallback(callback);
  return callback(null, '0x' + utils.intToHex(0));
};

Manager.prototype.eth_gasPrice = function(callback) {
  callback = optionalCallback(callback);
  return callback(null, '0x' + this.blockchain.gasPrice());
};

Manager.prototype.eth_getBalance = function(address, block_number, callback) {
  if (callback !== undefined) this.blockchain.getBalance(address, callback);
  return "please use an async call";
};

Manager.prototype.ethersim_setBalance = function(address, balance, callback) {
  this.blockchain.setBalance(address, balance, callback);
};

Manager.prototype.eth_getCode = function(address, block_number, callback) {
  callback = optionalCallback(callback);
  return callback(null, this.blockchain.getCode(address));
};

Manager.prototype.eth_getBlockByNumber = function(block_number, include_transactions, callback) {
  callback = optionalCallback(callback);
  return callback(null, this.blockchain.getBlockByNumber(block_number));
};

Manager.prototype.eth_getBlockByHash = function(block_hash, include_transactions, callback) {
  callback = optionalCallback(callback);
  return callback(null, this.blockchain.getBlockByHash(block_hash));
};

Manager.prototype.eth_getTransactionReceipt = function(tx_hash, callback) {
  callback = optionalCallback(callback);
  return callback(null, this.blockchain.getTransactionReceipt(tx_hash));
};

Manager.prototype.eth_getTransactionByHash = function(tx_hash, callback) {
  callback = optionalCallback(callback);
  return callback(null, this.blockchain.getTransactionByHash(tx_hash));
}

Manager.prototype.eth_getTransactionCount = function(address, block_number, callback) {
  callback = optionalCallback(callback);
  this.blockchain.getTransactionCount(address, callback);
}

Manager.prototype.eth_sendTransaction = function(tx_data, callback) {
  callback = optionalCallback(callback);
  this.blockchain.queueTransaction(tx_data, callback);
};

Manager.prototype.eth_sendRawTransaction = function(rawTx, callback) {
  callback = optionalCallback(callback);
  return callback(new Error("eth_sendRawTransaction not implemented yet, but it will be soon"));
};

Manager.prototype.eth_call = function(tx_data, block_number, callback) {
  callback = optionalCallback(callback);
  this.blockchain.queueCall(tx_data, callback);
};

Manager.prototype.eth_newBlockFilter = function(callback) {
  var filter_id = utils.addHexPrefix(utils.intToHex(this.blockchain.latest_filter_id));
  this.blockchain.latest_filter_id += 1;
  callback(null, filter_id);
};

Manager.prototype.eth_getFilterChanges = function(filter_id, callback) {
  var blockHash = this.blockchain.latestBlock().hash().toString("hex");
  // Mine a block after each request to getFilterChanges so block filters work.
  this.blockchain.mine();
  callback = optionalCallback(callback);
  return callback(null, [blockHash]);
};

Manager.prototype.eth_uninstallFilter = function(filter_id, callback) {
  callback(null, true);
};

Manager.prototype.eth_getCompilers = function(callback) {
  callback(null, ["solidity"]);
}

Manager.prototype.eth_compileSolidity = function(code, callback) {
  var compiler = new Compiler();
  fs.writeFileSync("/tmp/solCompiler.sol", code);
  compiled = compiler.compile_solidity("/tmp/solCompiler.sol");
  callback = optionalCallback(callback);
  return callback(null, compiled);
};

Manager.prototype.web3_clientVersion = function(callback) {
  callback = optionalCallback(callback);
  return callback(null, "EtherSim/v" + pkg.version + "/ethereum-js")
};

/* Functions for testing purposes only. */

Manager.prototype.evm_snapshot = function(callback) {
  callback = optionalCallback(callback);
  return callback(null, this.blockchain.snapshot());
};

Manager.prototype.evm_revert = function(snapshot_id, callback) {
  callback = optionalCallback(callback);
  return callback(null, this.blockchain.revert(snapshot_id));
};

module.exports = Manager;
<|endoftext|>


<commit_before>module.exports = [
    { path : '.(.name | .booksCount)', res : ['books and authors', 5]},
    { path : '.books(.idx{. === 1} | .idx{. === 2})', res : [1, 2]},
    { path : '.books(.idx{. === 3} | (((.author[0].name)) | .author[0].name))', res : [3, 'Robert C. Martin', 'Robert C. Martin']},
    { path : '.name | .booksCount', res : ['books and authors', 5]},
    { path : '(.name)', res : ['books and authors']},
    { path : '(.name | .booksCount)', res : ['books and authors', 5]},
    { path : '.name | (.booksCount | .booksCount)', res : ['books and authors', 5, 5]},
    { path : '(.name | .booksCount)[0]', res : 'books and authors'},
    { path : '.name | .booksCount[0]', res : ['books and authors', 5]}
];<commit_msg>add test<commit_after>module.exports = [
    { path : '.(.name | .booksCount)', res : ['books and authors', 5]},
    { path : '.books(.idx{. === 1} | .idx{. === 2})', res : [1, 2]},
    { path : '.books(.idx{. === 3} | (((.author[0].name)) | .author[0].name))', res : [3, 'Robert C. Martin', 'Robert C. Martin']},
    { path : '.name | .booksCount', res : ['books and authors', 5]},
    { path : '(.name)', res : ['books and authors']},
    { path : '(.name)[0]', res : 'books and authors'},
    { path : '(.name | .booksCount)', res : ['books and authors', 5]},
    { path : '.name | (.booksCount | .booksCount)', res : ['books and authors', 5, 5]},
    { path : '(.name | .booksCount)[0]', res : 'books and authors'},
    { path : '.name | .booksCount[0]', res : ['books and authors', 5]}
];<|endoftext|>


<commit_before>'use strict';
// Load modules

const Fs = require('fs');
const Path = require('path');

const Boom = require('boom');
const Hoek = require('hoek');
const Joi = require('joi');
const Items = require('items');
// Additional helper modules required in constructor

// Declare internals

const internals = {};

internals.defaults = {
    // defaultExtension: '',
    // path: '',
    // relativeTo: '',
    compileOptions: {},
    runtimeOptions: {},
    layout: false,
    layoutKeyword: 'content',
    encoding: 'utf8',
    isCached: true,
    allowAbsolutePaths: false,
    allowInsecureAccess: false,
    // partialsPath: '',
    contentType: 'text/html',
    compileMode: 'sync',
    context: null
};

internals.schema = {};

internals.schema.viewOverride = Joi.object({
    path: [Joi.array().items(Joi.string()), Joi.string()],
    relativeTo: Joi.string(),
    compileOptions: Joi.object(),
    runtimeOptions: Joi.object(),
    layout: Joi.string().allow(false, true),
    layoutKeyword: Joi.string(),
    layoutPath: [Joi.array().items(Joi.string()), Joi.string()],
    encoding: Joi.string(),
    allowAbsolutePaths: Joi.boolean(),
    allowInsecureAccess: Joi.boolean(),
    contentType: Joi.string()
});

internals.schema.viewBase = internals.schema.viewOverride.keys({
    partialsPath: [Joi.array().items(Joi.string()), Joi.string()],
    helpersPath: [Joi.array().items(Joi.string()), Joi.string()],
    isCached: Joi.boolean(),
    compileMode: Joi.string().valid('sync', 'async'),
    defaultExtension: Joi.string()
});

internals.schema.manager = internals.schema.viewBase.keys({
    engines: Joi.object().required(),
    context: [Joi.object(), Joi.func()]
});

internals.schema.view = internals.schema.viewBase.keys({
    module: Joi.object({
        compile: Joi.func().required()
    })
        .options({ allowUnknown: true })
        .required()
});

exports = module.exports = internals.Manager = function (options) {

    Joi.assert(options, internals.schema.manager);

    // Save non-defaults values

    const engines = options.engines;
    const defaultExtension = options.defaultExtension;

    // Clone options

    const defaults = Hoek.applyToDefaultsWithShallow(internals.defaults, options, ['engines', 'context']);
    delete defaults.engines;
    delete defaults.defaultExtension;

    // Prepare manager state

    const extensions = Object.keys(engines);
    Hoek.assert(extensions.length, 'Views manager requires at least one registered extension handler');

    this._context = defaults.context;
    this._engines = {};
    this._defaultExtension = defaultExtension || (extensions.length === 1 ? extensions[0] : '');

    // Load engines

    extensions.forEach((extension) => {

        const config = engines[extension];
        const engine = {};

        if (config.compile &&
            typeof config.compile === 'function') {

            engine.module = config;
            engine.config = defaults;
        }
        else {
            Joi.assert(config, internals.schema.view);

            engine.module = config.module;
            engine.config = Hoek.applyToDefaultsWithShallow(defaults, config, ['module']);
        }

        engine.suffix = '.' + extension;
        engine.compileFunc = engine.module.compile;

        if (engine.config.compileMode === 'sync') {
            engine.compileFunc = function (str, opt, next) {

                let compiled = null;
                try {
                    compiled = engine.module.compile(str, opt);
                }
                catch (err) {
                    return next(err);
                }

                const renderer = function (context, runtimeOptions, renderNext) {

                    let rendered = null;
                    try {
                        rendered = compiled(context, runtimeOptions);
                    }
                    catch (err) {
                        return renderNext(err);
                    }

                    return renderNext(null, rendered);
                };

                return next(null, renderer);
            };
        }

        if (engine.config.isCached) {
            engine.cache = {};
        }

        // When a prepare function is provided, state needs to be initialized before trying to compile and render
        engine.ready = !(engine.module.prepare && typeof engine.module.prepare === 'function');

        // Load partials and helpers

        this._loadPartials(engine);
        this._loadHelpers(engine);

        // Set engine

        this._engines[extension] = engine;
    });
};

internals.Manager.prototype._loadPartials = function (engine) {

    if (!engine.config.partialsPath ||
        !engine.module.registerPartial ||
        typeof engine.module.registerPartial !== 'function') {

        return;
    }

    const load = function () {

        const partialsPaths = [].concat(engine.config.partialsPath);

        partialsPaths.forEach((partialsPath) => {

            const path = internals.path(engine.config.relativeTo, partialsPath);
            const files = traverse(path);
            files.forEach((file) => {

                const offset = path.slice(-1) === Path.sep ? 0 : 1;
                const name = file.slice(path.length + offset, -engine.suffix.length).replace(/\\/g, '/');
                const src = Fs.readFileSync(file).toString(engine.config.encoding);
                engine.module.registerPartial(name, src);
            });
        });
    };

    const traverse = function (path) {

        let files = [];

        Fs.readdirSync(path).forEach((file) => {

            file = Path.join(path, file);
            const stat = Fs.statSync(file);
            if (stat.isDirectory()) {
                files = files.concat(traverse(file));
                return;
            }

            if (Path.basename(file)[0] !== '.' &&
                Path.extname(file) === engine.suffix) {

                files.push(file);
            }
        });

        return files;
    };

    load();
};

internals.Manager.prototype._loadHelpers = function (engine) {

    if (!engine.config.helpersPath ||
        !engine.module.registerHelper ||
        typeof engine.module.registerHelper !== 'function') {

        return;
    }

    const helpersPaths = [].concat(engine.config.helpersPath);

    helpersPaths.forEach((helpersPath) => {

        let path = internals.path(engine.config.relativeTo, helpersPath);
        if (!Path.isAbsolute(path)) {
            path = Path.join(process.cwd(), path);
        }

        Fs.readdirSync(path).forEach((file) => {

            file = Path.join(path, file);
            const stat = Fs.statSync(file);
            if (stat.isDirectory() ||
                Path.basename(file).startsWith('.') ||
                !Object.keys(require.extensions).includes(Path.extname(file))) {
                return;
            }

            try {
                const helper = require(file);
                if (typeof helper === 'function') {
                    const offset = path.slice(-1) === Path.sep ? 0 : 1;
                    const name = file.slice(path.length + offset, -Path.extname(file).length);
                    console.log('name', name);
                    engine.module.registerHelper(name, helper);
                }
            }
            catch (err) {
                console.warn('WARNING: vision failed to load helper \'%s\': %s', file, err.message);
            }
        });
    });
};

internals.Manager.prototype.registerHelper = function (name, helper) {

    Object.keys(this._engines).forEach((extension) => {

        const engine = this._engines[extension];

        if (typeof engine.module.registerHelper === 'function') {
            engine.module.registerHelper(name, helper);
        }
    });
};

internals.Manager.prototype.render = function (filename, context, options, callback) {

    if (!callback) {
        return internals._wrapMethod(this, this.render, [filename, context, options]);
    }

    this._prepare(filename, options, (err, compiled) => {

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

        this._render(compiled, context, null, (err, rendered) => {

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

            return callback(null, rendered, compiled.settings);
        });
    });
};

internals.Manager.prototype._prepare = function (template, options, callback) {

    options = options || {};

    const fileExtension = Path.extname(template).slice(1);
    const extension = fileExtension || this._defaultExtension;
    if (!extension) {
        return callback(Boom.badImplementation('Unknown extension and no defaultExtension configured for view template: ' + template));
    }

    const engine = this._engines[extension];
    if (!engine) {
        return callback(Boom.badImplementation('No view engine found for file: ' + template));
    }

    template = template + (fileExtension ? '' : engine.suffix);

    // Engine is ready to render

    if (engine.ready) {
        return this._prepareTemplates(template, engine, options, callback);
    }

    // Engine needs initialization

    return this._prepareEngine(engine, (err) => {

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

        return this._prepareTemplates(template, engine, options, callback);
    });
};

internals.Manager.prototype._prepareEngine = function (engine, next) {

    // _prepareEngine can only be invoked when the prepare function is defined

    try {
        return engine.module.prepare(engine.config, (err) => {

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

            engine.ready = true;
            return next();
        });
    }
    catch (err) {
        return next(err);
    }
};

internals.Manager.prototype._prepareTemplates = function (template, engine, options, callback) {

    const compiled = {
        settings: Hoek.applyToDefaults(engine.config, options)
    };

    this._path(template, compiled.settings, false, (err, templatePath) => {

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

        this._compile(templatePath, engine, compiled.settings, (err, compiledTemplate) => {

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

            compiled.template = compiledTemplate;

            // No layout

            if (!compiled.settings.layout) {
                return callback(null, compiled);
            }

            // With layout

            this._path((compiled.settings.layout === true ? 'layout' : compiled.settings.layout) + engine.suffix, compiled.settings, true, (err, layoutPath) => {

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

                this._compile(layoutPath, engine, compiled.settings, (err, layout) => {

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

                    compiled.layout = layout;
                    return callback(null, compiled);
                });
            });
        });
    });
};

internals.Manager.prototype._path = function (template, settings, isLayout, next) {

    // Validate path

    const isAbsolutePath = Path.isAbsolute(template);
    const isInsecurePath = template.match(/\.\.\//g);

    if (!settings.allowAbsolutePaths &&
        isAbsolutePath) {

        return next(Boom.badImplementation('Absolute paths are not allowed in views'));
    }

    if (!settings.allowInsecureAccess &&
        isInsecurePath) {

        return next(Boom.badImplementation('View paths cannot lookup templates outside root path (path includes one or more \'../\')'));
    }

    // Resolve path and extension

    let paths;
    if (isAbsolutePath) {
        paths = [template];
    }
    else {
        paths = [].concat((isLayout && settings.layoutPath) || settings.path);

        for (let i = 0; i < paths.length; ++i) {
            paths[i] = internals.path(settings.relativeTo, paths[i], template);
        }
    }

    Items.serial(paths, (path, nextFile) => {

        Fs.stat(path, (err, stats) => {

            if (!err &&
                stats.isFile()) {

                return next(null, path);
            }

            return nextFile();
        });
    }, () => {

        return next(Boom.badImplementation('View file not found: `' + template + '`. Locations searched: [' + paths.join(',') + ']'));
    });
};

internals.Manager.prototype._render = function (compiled, context, request, callback) {

    if (this._context) {
        let base = typeof this._context === 'function' ? this._context(request) : this._context;
        if (context) {
            base = Hoek.shallow(base);
            const keys = Object.keys(context);
            for (let i = 0; i < keys.length; ++i) {
                const key = keys[i];
                base[key] = context[key];
            }
        }

        context = base;
    }

    context = context || {};

    if (compiled.layout &&
        context.hasOwnProperty(compiled.settings.layoutKeyword)) {

        return callback(Boom.badImplementation('settings.layoutKeyword conflict', { context, keyword: compiled.settings.layoutKeyword }));
    }

    compiled.template(context, compiled.settings.runtimeOptions, (err, renderedContent) => {

        if (err) {
            return callback(Boom.badImplementation(err.message, err));
        }

        // No layout

        if (!compiled.layout) {
            return callback(null, renderedContent);
        }

        // With layout

        context[compiled.settings.layoutKeyword] = renderedContent;
        compiled.layout(context, compiled.settings.runtimeOptions, (err, renderedWithLayout) => {

            delete context[compiled.settings.layoutKeyword];

            if (err) {
                return callback(Boom.badImplementation(err.message, err));
            }

            return callback(null, renderedWithLayout);
        });
    });
};

internals.path = function (base, path, file) {

    if (path &&
        Path.isAbsolute(path)) {

        return Path.join(path, file || '');
    }

    return Path.join(base || '', path || '', file || '');
};

internals.Manager.prototype._compile = function (template, engine, settings, callback) {

    if (engine.cache &&
        engine.cache[template]) {

        return callback(null, engine.cache[template]);
    }

    settings.compileOptions.filename = template;            // Pass the template to Jade via this copy of compileOptions

    // Read file

    Fs.readFile(template, { encoding: settings.encoding }, (err, data) => {

        if (err) {
            return callback(Boom.badImplementation('Failed to read view file: ' + template));
        }

        engine.compileFunc(data, settings.compileOptions, (err, compiled) => {

            if (err) {
                return callback(Boom.boomify(err));
            }

            if (engine.cache) {
                engine.cache[template] = compiled;
            }

            return callback(null, compiled);
        });
    });
};

internals.Manager.prototype._response = function (template, context, options, request) {

    Joi.assert(options, internals.schema.viewOverride);

    const source = { manager: this, template, context, options };
    return request.generateResponse(source, { variety: 'view', marshal: internals.marshal, prepare: internals.prepare });
};

internals.marshal = function (response) {

    const manager = response.source.manager;

    return new Promise((resolve, reject) => {

        manager._render(response.source.compiled, response.source.context, response.request, (err, rendered) => {

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

            const config = response.source.compiled.settings;

            if (!response.headers['content-type']) {
                response.type(config.contentType);
            }

            response.encoding(config.encoding);

            return resolve(rendered);
        });
    });
};

internals.prepare = function (response) {

    const manager = response.source.manager;

    return new Promise((resolve, reject) => {

        manager._prepare(response.source.template, response.source.options, (err, compiled) => {

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

            response.source.compiled = compiled;
            return resolve(response);
        });
    });
};

internals._wrapMethod = (bind, method, args) => {

    return new Promise((resolve, reject) => {

        const callback = function (err, result) {

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

            return resolve(result);
        };

        method.apply(bind, args.concat(callback));
    });
};
<commit_msg>Cleanup<commit_after>'use strict';
// Load modules

const Fs = require('fs');
const Path = require('path');

const Boom = require('boom');
const Hoek = require('hoek');
const Joi = require('joi');
const Items = require('items');
// Additional helper modules required in constructor

// Declare internals

const internals = {};

internals.defaults = {
    // defaultExtension: '',
    // path: '',
    // relativeTo: '',
    compileOptions: {},
    runtimeOptions: {},
    layout: false,
    layoutKeyword: 'content',
    encoding: 'utf8',
    isCached: true,
    allowAbsolutePaths: false,
    allowInsecureAccess: false,
    // partialsPath: '',
    contentType: 'text/html',
    compileMode: 'sync',
    context: null
};

internals.schema = {};

internals.schema.viewOverride = Joi.object({
    path: [Joi.array().items(Joi.string()), Joi.string()],
    relativeTo: Joi.string(),
    compileOptions: Joi.object(),
    runtimeOptions: Joi.object(),
    layout: Joi.string().allow(false, true),
    layoutKeyword: Joi.string(),
    layoutPath: [Joi.array().items(Joi.string()), Joi.string()],
    encoding: Joi.string(),
    allowAbsolutePaths: Joi.boolean(),
    allowInsecureAccess: Joi.boolean(),
    contentType: Joi.string()
});

internals.schema.viewBase = internals.schema.viewOverride.keys({
    partialsPath: [Joi.array().items(Joi.string()), Joi.string()],
    helpersPath: [Joi.array().items(Joi.string()), Joi.string()],
    isCached: Joi.boolean(),
    compileMode: Joi.string().valid('sync', 'async'),
    defaultExtension: Joi.string()
});

internals.schema.manager = internals.schema.viewBase.keys({
    engines: Joi.object().required(),
    context: [Joi.object(), Joi.func()]
});

internals.schema.view = internals.schema.viewBase.keys({
    module: Joi.object({
        compile: Joi.func().required()
    })
        .options({ allowUnknown: true })
        .required()
});

exports = module.exports = internals.Manager = function (options) {

    Joi.assert(options, internals.schema.manager);

    // Save non-defaults values

    const engines = options.engines;
    const defaultExtension = options.defaultExtension;

    // Clone options

    const defaults = Hoek.applyToDefaultsWithShallow(internals.defaults, options, ['engines', 'context']);
    delete defaults.engines;
    delete defaults.defaultExtension;

    // Prepare manager state

    const extensions = Object.keys(engines);
    Hoek.assert(extensions.length, 'Views manager requires at least one registered extension handler');

    this._context = defaults.context;
    this._engines = {};
    this._defaultExtension = defaultExtension || (extensions.length === 1 ? extensions[0] : '');

    // Load engines

    extensions.forEach((extension) => {

        const config = engines[extension];
        const engine = {};

        if (config.compile &&
            typeof config.compile === 'function') {

            engine.module = config;
            engine.config = defaults;
        }
        else {
            Joi.assert(config, internals.schema.view);

            engine.module = config.module;
            engine.config = Hoek.applyToDefaultsWithShallow(defaults, config, ['module']);
        }

        engine.suffix = '.' + extension;
        engine.compileFunc = engine.module.compile;

        if (engine.config.compileMode === 'sync') {
            engine.compileFunc = function (str, opt, next) {

                let compiled = null;
                try {
                    compiled = engine.module.compile(str, opt);
                }
                catch (err) {
                    return next(err);
                }

                const renderer = function (context, runtimeOptions, renderNext) {

                    let rendered = null;
                    try {
                        rendered = compiled(context, runtimeOptions);
                    }
                    catch (err) {
                        return renderNext(err);
                    }

                    return renderNext(null, rendered);
                };

                return next(null, renderer);
            };
        }

        if (engine.config.isCached) {
            engine.cache = {};
        }

        // When a prepare function is provided, state needs to be initialized before trying to compile and render
        engine.ready = !(engine.module.prepare && typeof engine.module.prepare === 'function');

        // Load partials and helpers

        this._loadPartials(engine);
        this._loadHelpers(engine);

        // Set engine

        this._engines[extension] = engine;
    });
};

internals.Manager.prototype._loadPartials = function (engine) {

    if (!engine.config.partialsPath ||
        !engine.module.registerPartial ||
        typeof engine.module.registerPartial !== 'function') {

        return;
    }

    const load = function () {

        const partialsPaths = [].concat(engine.config.partialsPath);

        partialsPaths.forEach((partialsPath) => {

            const path = internals.path(engine.config.relativeTo, partialsPath);
            const files = traverse(path);
            files.forEach((file) => {

                const offset = path.slice(-1) === Path.sep ? 0 : 1;
                const name = file.slice(path.length + offset, -engine.suffix.length).replace(/\\/g, '/');
                const src = Fs.readFileSync(file).toString(engine.config.encoding);
                engine.module.registerPartial(name, src);
            });
        });
    };

    const traverse = function (path) {

        let files = [];

        Fs.readdirSync(path).forEach((file) => {

            file = Path.join(path, file);
            const stat = Fs.statSync(file);
            if (stat.isDirectory()) {
                files = files.concat(traverse(file));
                return;
            }

            if (Path.basename(file)[0] !== '.' &&
                Path.extname(file) === engine.suffix) {

                files.push(file);
            }
        });

        return files;
    };

    load();
};

internals.Manager.prototype._loadHelpers = function (engine) {

    if (!engine.config.helpersPath ||
        !engine.module.registerHelper ||
        typeof engine.module.registerHelper !== 'function') {

        return;
    }

    const helpersPaths = [].concat(engine.config.helpersPath);

    helpersPaths.forEach((helpersPath) => {

        let path = internals.path(engine.config.relativeTo, helpersPath);
        if (!Path.isAbsolute(path)) {
            path = Path.join(process.cwd(), path);
        }

        Fs.readdirSync(path).forEach((file) => {

            file = Path.join(path, file);
            const stat = Fs.statSync(file);
            if (stat.isDirectory() ||
                Path.basename(file).startsWith('.') ||
                !Object.keys(require.extensions).includes(Path.extname(file))) {
                return;
            }

            try {
                const helper = require(file);
                if (typeof helper === 'function') {
                    const offset = path.slice(-1) === Path.sep ? 0 : 1;
                    const name = file.slice(path.length + offset, -Path.extname(file).length);
                    engine.module.registerHelper(name, helper);
                }
            }
            catch (err) {
                console.warn('WARNING: vision failed to load helper \'%s\': %s', file, err.message);
            }
        });
    });
};

internals.Manager.prototype.registerHelper = function (name, helper) {

    Object.keys(this._engines).forEach((extension) => {

        const engine = this._engines[extension];

        if (typeof engine.module.registerHelper === 'function') {
            engine.module.registerHelper(name, helper);
        }
    });
};

internals.Manager.prototype.render = function (filename, context, options, callback) {

    if (!callback) {
        return internals._wrapMethod(this, this.render, [filename, context, options]);
    }

    this._prepare(filename, options, (err, compiled) => {

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

        this._render(compiled, context, null, (err, rendered) => {

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

            return callback(null, rendered, compiled.settings);
        });
    });
};

internals.Manager.prototype._prepare = function (template, options, callback) {

    options = options || {};

    const fileExtension = Path.extname(template).slice(1);
    const extension = fileExtension || this._defaultExtension;
    if (!extension) {
        return callback(Boom.badImplementation('Unknown extension and no defaultExtension configured for view template: ' + template));
    }

    const engine = this._engines[extension];
    if (!engine) {
        return callback(Boom.badImplementation('No view engine found for file: ' + template));
    }

    template = template + (fileExtension ? '' : engine.suffix);

    // Engine is ready to render

    if (engine.ready) {
        return this._prepareTemplates(template, engine, options, callback);
    }

    // Engine needs initialization

    return this._prepareEngine(engine, (err) => {

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

        return this._prepareTemplates(template, engine, options, callback);
    });
};

internals.Manager.prototype._prepareEngine = function (engine, next) {

    // _prepareEngine can only be invoked when the prepare function is defined

    try {
        return engine.module.prepare(engine.config, (err) => {

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

            engine.ready = true;
            return next();
        });
    }
    catch (err) {
        return next(err);
    }
};

internals.Manager.prototype._prepareTemplates = function (template, engine, options, callback) {

    const compiled = {
        settings: Hoek.applyToDefaults(engine.config, options)
    };

    this._path(template, compiled.settings, false, (err, templatePath) => {

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

        this._compile(templatePath, engine, compiled.settings, (err, compiledTemplate) => {

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

            compiled.template = compiledTemplate;

            // No layout

            if (!compiled.settings.layout) {
                return callback(null, compiled);
            }

            // With layout

            this._path((compiled.settings.layout === true ? 'layout' : compiled.settings.layout) + engine.suffix, compiled.settings, true, (err, layoutPath) => {

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

                this._compile(layoutPath, engine, compiled.settings, (err, layout) => {

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

                    compiled.layout = layout;
                    return callback(null, compiled);
                });
            });
        });
    });
};

internals.Manager.prototype._path = function (template, settings, isLayout, next) {

    // Validate path

    const isAbsolutePath = Path.isAbsolute(template);
    const isInsecurePath = template.match(/\.\.\//g);

    if (!settings.allowAbsolutePaths &&
        isAbsolutePath) {

        return next(Boom.badImplementation('Absolute paths are not allowed in views'));
    }

    if (!settings.allowInsecureAccess &&
        isInsecurePath) {

        return next(Boom.badImplementation('View paths cannot lookup templates outside root path (path includes one or more \'../\')'));
    }

    // Resolve path and extension

    let paths;
    if (isAbsolutePath) {
        paths = [template];
    }
    else {
        paths = [].concat((isLayout && settings.layoutPath) || settings.path);

        for (let i = 0; i < paths.length; ++i) {
            paths[i] = internals.path(settings.relativeTo, paths[i], template);
        }
    }

    Items.serial(paths, (path, nextFile) => {

        Fs.stat(path, (err, stats) => {

            if (!err &&
                stats.isFile()) {

                return next(null, path);
            }

            return nextFile();
        });
    }, () => {

        return next(Boom.badImplementation('View file not found: `' + template + '`. Locations searched: [' + paths.join(',') + ']'));
    });
};

internals.Manager.prototype._render = function (compiled, context, request, callback) {

    if (this._context) {
        let base = typeof this._context === 'function' ? this._context(request) : this._context;
        if (context) {
            base = Hoek.shallow(base);
            const keys = Object.keys(context);
            for (let i = 0; i < keys.length; ++i) {
                const key = keys[i];
                base[key] = context[key];
            }
        }

        context = base;
    }

    context = context || {};

    if (compiled.layout &&
        context.hasOwnProperty(compiled.settings.layoutKeyword)) {

        return callback(Boom.badImplementation('settings.layoutKeyword conflict', { context, keyword: compiled.settings.layoutKeyword }));
    }

    compiled.template(context, compiled.settings.runtimeOptions, (err, renderedContent) => {

        if (err) {
            return callback(Boom.badImplementation(err.message, err));
        }

        // No layout

        if (!compiled.layout) {
            return callback(null, renderedContent);
        }

        // With layout

        context[compiled.settings.layoutKeyword] = renderedContent;
        compiled.layout(context, compiled.settings.runtimeOptions, (err, renderedWithLayout) => {

            delete context[compiled.settings.layoutKeyword];

            if (err) {
                return callback(Boom.badImplementation(err.message, err));
            }

            return callback(null, renderedWithLayout);
        });
    });
};

internals.path = function (base, path, file) {

    if (path &&
        Path.isAbsolute(path)) {

        return Path.join(path, file || '');
    }

    return Path.join(base || '', path || '', file || '');
};

internals.Manager.prototype._compile = function (template, engine, settings, callback) {

    if (engine.cache &&
        engine.cache[template]) {

        return callback(null, engine.cache[template]);
    }

    settings.compileOptions.filename = template;            // Pass the template to Jade via this copy of compileOptions

    // Read file

    Fs.readFile(template, { encoding: settings.encoding }, (err, data) => {

        if (err) {
            return callback(Boom.badImplementation('Failed to read view file: ' + template));
        }

        engine.compileFunc(data, settings.compileOptions, (err, compiled) => {

            if (err) {
                return callback(Boom.boomify(err));
            }

            if (engine.cache) {
                engine.cache[template] = compiled;
            }

            return callback(null, compiled);
        });
    });
};

internals.Manager.prototype._response = function (template, context, options, request) {

    Joi.assert(options, internals.schema.viewOverride);

    const source = { manager: this, template, context, options };
    return request.generateResponse(source, { variety: 'view', marshal: internals.marshal, prepare: internals.prepare });
};

internals.marshal = function (response) {

    const manager = response.source.manager;

    return new Promise((resolve, reject) => {

        manager._render(response.source.compiled, response.source.context, response.request, (err, rendered) => {

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

            const config = response.source.compiled.settings;

            if (!response.headers['content-type']) {
                response.type(config.contentType);
            }

            response.encoding(config.encoding);

            return resolve(rendered);
        });
    });
};

internals.prepare = function (response) {

    const manager = response.source.manager;

    return new Promise((resolve, reject) => {

        manager._prepare(response.source.template, response.source.options, (err, compiled) => {

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

            response.source.compiled = compiled;
            return resolve(response);
        });
    });
};

internals._wrapMethod = (bind, method, args) => {

    return new Promise((resolve, reject) => {

        const callback = function (err, result) {

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

            return resolve(result);
        };

        method.apply(bind, args.concat(callback));
    });
};
<|endoftext|>


<commit_before>var should = require('chai').should();
var expect = require('chai').expect;

var configure = require('../../lib/configurator');
var createConfig = configure.createConfigFromLoaders;
var Plugin = require('../../lib/plugin');
var defaultConfig = require('../../lib/config');

describe('configure()', function() {

  it('should use default config if no options presented', function() {
    configure().should.deep.equal(defaultConfig);
  });

  it('should properly set params and override defaults', function() {
    var params = {
      test: 'olala',
      qwe: 123
    };

    var config = configure(params);
    config.should.have.property('qwe').and.eql(123);
    config.should.have.property('test').and.eql('olala');
  });

});

describe('configure.createConfigFromLoaders', function() {

  it('should throw when loaders config is not an array', function() {
    expect(function() {
      createConfig({test: /\.png$/, loader: 'file'})
    }).to.throw();
  });

  it('should skip non-plugin loaders', function() {
    createConfig([ {test: /\.png$/, loader: 'file'} ])
      .should.be.a('array').and.be.empty;
  });

  it('should skip `loaders` property', function() {
    createConfig([ {test: /\.scss$/, loaders: ['style', 'css', 'sass']} ])
      .should.be.a('array').and.be.empty;
  });

  it('should copy test, include and exclude properties', function() {
    var loaderConfig = {
      test: /\.js$/,
      include: [],
      exclude: [],
      loader: Plugin.extract()
    };
    var result = createConfig([loaderConfig]);
    var config = result[0];

    result.should.be.a('array').and.have.lengthOf(1);
    config.should.have.property('test').and.eql(loaderConfig.test);
    config.should.have.property('include').and.eql(loaderConfig.include);
    config.should.have.property('exclude').and.eql(loaderConfig.exclude);
  });

});<commit_msg>Configurator refactoring<commit_after>var should = require('chai').should();
var expect = require('chai').expect;

var configure = require('../../lib/configurator');
var createConfig = configure.createConfigFromLoaders;
var Plugin = require('../../lib/plugin');
var defaultConfig = require('../../lib/config');

describe('configurator()', function() {

  it('should use default config if no options presented', function() {
    configure().should.deep.equal(defaultConfig);
  });

  it('should properly set params and override defaults', function() {
    var params = {
      test: 'olala',
      qwe: 123
    };

    var config = configure(params);
    config.should.have.property('qwe').and.eql(123);
    config.should.have.property('test').and.eql('olala');
  });

});

describe('createConfigFromLoaders()', function() {

  it('should throw when loaders config is not an array', function() {
    expect(function() {
      createConfig({test: /\.png$/, loader: 'file'})
    }).to.throw();
  });

  it('should skip non-plugin loaders', function() {
    createConfig([ {test: /\.png$/, loader: 'file'} ])
      .should.be.a('array').and.be.empty;
  });

  it('should skip `loaders` property', function() {
    createConfig([ {test: /\.scss$/, loaders: ['style', 'css', 'sass']} ])
      .should.be.a('array').and.be.empty;
  });

  it('should copy test, include and exclude properties', function() {
    var loaderConfig = {
      test: /\.js$/,
      include: [],
      exclude: [],
      loader: Plugin.extract()
    };
    var result = createConfig([loaderConfig]);
    var config = result[0];

    result.should.be.a('array').and.have.lengthOf(1);
    config.should.have.property('test').and.eql(loaderConfig.test);
    config.should.have.property('include').and.eql(loaderConfig.include);
    config.should.have.property('exclude').and.eql(loaderConfig.exclude);
  });

});<|endoftext|>


<commit_before>var fs = require('fs');
var path = require('path');
var util = require('util');
var glue = require('cli-interface');
var CommandInterface = glue.CommandInterface;
var cli = glue.cli, help = cli.help;

var print = require('./print');
var build = require('./build');

var ManualPage = function() {
  CommandInterface.apply(this, arguments);
}

util.inherits(ManualPage, CommandInterface);

ManualPage.prototype.configure = function() {
  var options = {
    commands: {
    },
    options: {
      output: cli.types.file('d')
    }
  }
  var file = path.join(__dirname, 'manpage.md');
  var conf = {
    load: {
      file: file, options: options
    },
    substitute: {enabled: true},
    manual: {
      dir: path.normalize(path.join(__dirname, '..', 'doc', 'man'))
    }
  }
  this
    .configure(conf)
    .usage();
}

ManualPage.prototype.use = function() {
  this
    .use(cli.middleware.color)
    .use(cli.middleware.manual)
    .use(cli.middleware.logger, null);
  this.converter(cli.types.file('efx'));
}

ManualPage.prototype.on = function() {
  this
    .once('load', function(req) {
      this.help().version();
    })
    .once('empty', function(req) {
      help.call(this);
    })
    .once('complete', function(req) {
      if(!this.output) {
        return print.call(this, req);
      }
      build.call(this, req);
    })
}

module.exports = function(pkg) {
  return new ManualPage(pkg);
}
<commit_msg>Allow dynamic man pages.<commit_after>var fs = require('fs');
var path = require('path');
var util = require('util');
var glue = require('cli-interface');
var CommandInterface = glue.CommandInterface;
var cli = glue.cli, help = cli.help;

var print = require('./print');
var build = require('./build');

var ManualPage = function() {
  CommandInterface.apply(this, arguments);
}

util.inherits(ManualPage, CommandInterface);

ManualPage.prototype.configure = function() {
  var options = {
    commands: {
    },
    options: {
      output: cli.types.file('d')
    }
  }
  var file = path.join(__dirname, 'manpage.md');
  var conf = {
    load: {
      file: file, options: options
    },
    substitute: {enabled: true},
    manual: {
      dir: path.normalize(path.join(__dirname, '..', 'doc', 'man')),
      dynamic: true
    }
  }
  this
    .configure(conf)
    .usage();
}

ManualPage.prototype.use = function() {
  this
    .use(cli.middleware.color)
    .use(cli.middleware.manual)
    .use(cli.middleware.logger, null);
  this.converter(cli.types.file('efx'));
}

ManualPage.prototype.on = function() {
  this
    .once('load', function(req) {
      this.help().version();
    })
    .once('empty', function(req) {
      help.call(this);
    })
    .once('complete', function(req) {
      if(!this.output) {
        return print.call(this, req);
      }
      build.call(this, req);
    })
}

module.exports = function(pkg) {
  return new ManualPage(pkg);
}
<|endoftext|>


<commit_before>import Transporter from './Transporter';

export default { Interface: Transporter, Transporter };
export { Transporter as Interface, Transporter };
<commit_msg>Delete index.js<commit_after><|endoftext|>