<commit_before>'use strict';

var DIRECTIONS = {
  NONE: 0
, DoubleUp: 1
, SingleUp: 2
, FortyFiveUp: 3
, Flat: 4
, FortyFiveDown: 5
, SingleDown: 6
, DoubleDown: 7
, 'NOT COMPUTABLE': 8
, 'RATE OUT OF RANGE': 9
};

var iob = require("./plugins/iob")();
var async = require('async');
var units = require('./units')();

function directionToTrend (direction) {
  var trend = 8;
  if (direction in DIRECTIONS) {
    trend = DIRECTIONS[direction];
  }
  return trend;
}

function pebble (req, res) {
  var ONE_DAY = 24 * 60 * 60 * 1000
      , uploaderBattery
      , treatmentResults
      , profileResult
      , sgvData = [ ]
      , calData = [ ];

  function scaleBg(bg) {
      if (req.mmol) {
          return units.mgdlToMMOL(bg);
      } else {
          return bg;
      }
  }

  function sendData () {
    var now = Date.now();

    //for compatibility we're keeping battery and iob here, but they would be better somewhere else
    if (sgvData.length > 0) {
        sgvData[0].battery = uploaderBattery ? "" + uploaderBattery : undefined;
        if (req.iob) {
            sgvData[0].iob = iob.calcTotal(treatmentResults.slice(0, 20), profileResult, new Date(now)).display;
        }
    }

    var result = { status: [ {now: now} ], bgs: sgvData.slice(0, req.count), cals: calData };
    res.setHeader('content-type', 'application/json');
    res.write(JSON.stringify(result));
    res.end( );
  }

    var earliest_data = Date.now() - ONE_DAY;

    async.parallel({
        devicestatus: function (callback) {
            req.ctx.devicestatus.last(function (err, value) {
                if (!err && value) {
                    uploaderBattery = value.uploaderBattery;
                } else {
                    console.error("req.devicestatus.tail", err);
                }
                callback();
            });
        }
        , treatments: function(callback) {
            loadTreatments(req, earliest_data, function (err, trs) {
                treatmentResults = trs;
                callback();
            });
        }
        , profile: function(callback) {
            loadProfile(req, function (err, profileResults) {
                if (!err && profileResults) {
                  profileResults.forEach(function (profile) {
                      if (profile) {
                          if (profile.dia) {
                              profileResult = profile;
                          }
                      }
                  });
                } else {
                  console.error("pebble profile error", arguments);
                }
                callback();
            });
        }
        , cal: function(callback) {
            if (req.rawbg) {
                var cq = { count: req.count, find: {type: 'cal'} };
                req.ctx.entries.list(cq, function (err, results) {
                  if (!err && results) {
                    results.forEach(function (element) {
                        if (element) {
                          calData.push({
                              slope: element.slope
                              , intercept: element.intercept
                              , scale: element.scale
                          });
                        }
                    });
                  } else {
                    console.error("pebble cal error", arguments);
                  }
                  callback();
                });
            } else {
                callback();
            }
        }
        , entries: function(callback) {
            var q = { count: req.count + 1, find: { "sgv": { $exists: true }} };

            req.ctx.entries.list(q, function(err, results) {
              if (!err && results) {
                results.forEach(function(element, index) {
                    if (element) {
                        var obj = {};
                        var next = null;
                        var sgvs = results.filter(function(d) {
                            return !!d.sgv;
                        });
                        if (index + 1 < sgvs.length) {
                            next = sgvs[index + 1];
                        }
                        obj.sgv = scaleBg(element.sgv).toString();
                        obj.bgdelta = (next ? (scaleBg(element.sgv) - scaleBg(next.sgv) ) : 0);
                        if (req.mmol) {
                            obj.bgdelta = obj.bgdelta.toFixed(1);
                        }
                        if ('direction' in element) {
                            obj.trend = directionToTrend(element.direction);
                            obj.direction = element.direction;
                        }
                        obj.datetime = element.date;
                        if (req.rawbg) {
                            obj.filtered = element.filtered;
                            obj.unfiltered = element.unfiltered;
                            obj.noise = element.noise;
                        }
                        sgvData.push(obj);
                    }
                });
              } else {
                console.error("pebble entries error", arguments);
              }
                callback();
            });
        }
    }, sendData);

}

function loadTreatments(req, earliest_data, fn) {
  if (req.iob) {
    var q = { find: {"created_at": {"$gte": new Date(earliest_data).toISOString()}} };
    req.ctx.treatments.list(q, fn);
  } else {
    fn(null, []);
  }
}

function loadProfile(req, fn) {
  if (req.iob) {
    req.ctx.profile.list(fn);
  } else {
    fn(null, []);
  }
}

function configure (env, ctx) {
  function middle (req, res, next) {
    req.ctx = ctx;
    req.rawbg = env.enable && env.enable.indexOf('rawbg') > -1;
    req.iob = env.enable && env.enable.indexOf('iob') > -1;
    req.mmol = (req.query.units || env.DISPLAY_UNITS) === 'mmol';
    req.count = parseInt(req.query.count) || 1;

    next( );
  }
  return [middle, pebble];
}

configure.pebble = pebble;
module.exports = configure;
<commit_msg>Fix Pebble API. This really needs to start using the sbx<commit_after>'use strict';

var DIRECTIONS = {
  NONE: 0
, DoubleUp: 1
, SingleUp: 2
, FortyFiveUp: 3
, Flat: 4
, FortyFiveDown: 5
, SingleDown: 6
, DoubleDown: 7
, 'NOT COMPUTABLE': 8
, 'RATE OUT OF RANGE': 9
};

var iob = require("./plugins/iob")();
var async = require('async');
var units = require('./units')();
var profileObject = require("./profilefunctions")();

function directionToTrend (direction) {
  var trend = 8;
  if (direction in DIRECTIONS) {
    trend = DIRECTIONS[direction];
  }
  return trend;
}

function pebble (req, res) {
  var ONE_DAY = 24 * 60 * 60 * 1000
      , uploaderBattery
      , treatmentResults
      , profileResult
      , sgvData = [ ]
      , calData = [ ];

  function scaleBg(bg) {
      if (req.mmol) {
          return units.mgdlToMMOL(bg);
      } else {
          return bg;
      }
  }

  function sendData () {
    var now = Date.now();

    //for compatibility we're keeping battery and iob here, but they would be better somewhere else
    if (sgvData.length > 0) {
        sgvData[0].battery = uploaderBattery ? "" + uploaderBattery : undefined;
        if (req.iob) {
            sgvData[0].iob = iob.calcTotal(treatmentResults.slice(0, 20), profileResult, new Date(now)).display;
        }
    }

    var result = { status: [ {now: now} ], bgs: sgvData.slice(0, req.count), cals: calData };
    res.setHeader('content-type', 'application/json');
    res.write(JSON.stringify(result));
    res.end( );
  }

    var earliest_data = Date.now() - ONE_DAY;

    async.parallel({
        devicestatus: function (callback) {
            req.ctx.devicestatus.last(function (err, value) {
                if (!err && value) {
                    uploaderBattery = value.uploaderBattery;
                } else {
                    console.error("req.devicestatus.tail", err);
                }
                callback();
            });
        }
        , treatments: function(callback) {
            loadTreatments(req, earliest_data, function (err, trs) {
                treatmentResults = trs;
                callback();
            });
        }
        , profile: function(callback) {
            loadProfile(req, function (err, profileResults) {
                if (!err && profileResults) {
                  profileResults.forEach(function (profile) {
                      if (profile) {
                          if (profile.dia) {
                              profileResult = profileObject.loadData([profile]);
                          }
                      }
                  });
                } else {
                  console.error("pebble profile error", arguments);
                }
                callback();
            });
        }
        , cal: function(callback) {
            if (req.rawbg) {
                var cq = { count: req.count, find: {type: 'cal'} };
                req.ctx.entries.list(cq, function (err, results) {
                  if (!err && results) {
                    results.forEach(function (element) {
                        if (element) {
                          calData.push({
                              slope: element.slope
                              , intercept: element.intercept
                              , scale: element.scale
                          });
                        }
                    });
                  } else {
                    console.error("pebble cal error", arguments);
                  }
                  callback();
                });
            } else {
                callback();
            }
        }
        , entries: function(callback) {
            var q = { count: req.count + 1, find: { "sgv": { $exists: true }} };

            req.ctx.entries.list(q, function(err, results) {
              if (!err && results) {
                results.forEach(function(element, index) {
                    if (element) {
                        var obj = {};
                        var next = null;
                        var sgvs = results.filter(function(d) {
                            return !!d.sgv;
                        });
                        if (index + 1 < sgvs.length) {
                            next = sgvs[index + 1];
                        }
                        obj.sgv = scaleBg(element.sgv).toString();
                        obj.bgdelta = (next ? (scaleBg(element.sgv) - scaleBg(next.sgv) ) : 0);
                        if (req.mmol) {
                            obj.bgdelta = obj.bgdelta.toFixed(1);
                        }
                        if ('direction' in element) {
                            obj.trend = directionToTrend(element.direction);
                            obj.direction = element.direction;
                        }
                        obj.datetime = element.date;
                        if (req.rawbg) {
                            obj.filtered = element.filtered;
                            obj.unfiltered = element.unfiltered;
                            obj.noise = element.noise;
                        }
                        sgvData.push(obj);
                    }
                });
              } else {
                console.error("pebble entries error", arguments);
              }
                callback();
            });
        }
    }, sendData);

}

function loadTreatments(req, earliest_data, fn) {
  if (req.iob) {
    var q = { find: {"created_at": {"$gte": new Date(earliest_data).toISOString()}} };
    req.ctx.treatments.list(q, fn);
  } else {
    fn(null, []);
  }
}

function loadProfile(req, fn) {
  if (req.iob) {
    req.ctx.profile.list(fn);
  } else {
    fn(null, []);
  }
}

function configure (env, ctx) {
  function middle (req, res, next) {
    req.ctx = ctx;
    req.rawbg = env.enable && env.enable.indexOf('rawbg') > -1;
    req.iob = env.enable && env.enable.indexOf('iob') > -1;
    req.mmol = (req.query.units || env.DISPLAY_UNITS) === 'mmol';
    req.count = parseInt(req.query.count) || 1;

    next( );
  }
  return [middle, pebble];
}

configure.pebble = pebble;
module.exports = configure;
<|endoftext|>


<commit_before>var PATH = '/Users/lukasz/sandbox/lupa41/src/**/*.js'
var vfs = require('vinyl-fs');
var fs = require('fs');
var through = require('through2');
var Path = require('path');

var lupa = require('lupa').lupa;
var createParser = require('lupa/parsers/parsers');
var File = require('vinyl');
var parseHtml = require('html-flavors').parseHtml;

var MAX_LISTENERS = 10000000;

var child_process = require('child_process');

function findVariables(file, enc, cb) {
    // this is example lupa plugin

    var body = file.ast.program.body;

    // analyze AST
    var variables = body.filter(function (node) {
        return node.type == 'VariableDeclaration'
    }).reduce(function (vars, node) {
        return vars.concat(node.declarations.map(function (decl) {
            return decl.id.name;
        }));
    }, []);

    var result = file.clone();
    result.metadata = [{name: 'variables', data: variables}]; // add metadata
    cb(null, result);
}

var fileInfo = require('lupa/src/plugins/FileInfo')();
lupa.plugin(function (file, enc, cb) {
    var result = file.clone();
    var contents = file.contents + '';
    var info = fileInfo(contents, file.path);
    result.metadata = [
        {name: 'lines', data: [info.lines] }
    ]
    cb(null, result);
}, function () { return true;});

lupa.plugin(function (file, enc, cb) {
    var result = file.clone();
    result.metadata = [
        {name: 'html-ast', data: file.ast}
    ]
    cb(null, result);
}, function (p, f) { return f.extname == '.html';});

lupa.plugin(findVariables);

lupa.plugin(require('lupa/plugins/React/components.js').getComponents);

//require('lupa/plugins/React/components')
process.on('message', function (msg) {
    console.log("plugin, got message", msg);
    module.exports.analyze(msg.path, function (state) {
        console.log("plugin, analyzed");
        process.send('message', state);
    });
})
module.exports = {
    lupa: lupa,

    analyze: function (path, onAnalyze) {

        if (lupa.getState().files.filter(function (f) {
            return f.path == path;
        }).length) {
            onAnalyze(lupa.getState())
            return;
        }

        var parser = createParser(path);
        if (parser) {

            var parse = require('ast-stream')(parser);

            var code = fs.readFileSync(path, 'utf8');
            var vinyl = new File({
                path: path,
                contents: new Buffer(code)
            })

            // get data from lupa
            lupa.output.pipe(through.obj( function (data, enc, cb) {
                cb(null, data)
                onAnalyze(lupa.getState());
            }));

            // hack to prevent break NodeJs stream
            parse.setMaxListeners(MAX_LISTENERS);

            // pipe parsed data tu lupa
            parse.pipe(through.obj(
                function (data, enc, cb) {
                    console.log("pipe data feeding XD");
                    //lupa.input.write(data);
                    console.log("creating worker");
                    var worker = child_process.fork(__dirname + '/worker');
                    console.log("worker created", worker);
                    worker.on('message', function(data) {
                        console.log('pl/ message from worker', data);
                    });
                    worker.send(data);

                    lupa.feed(data);
                }
            ));

            parse.write(vinyl)
        } else {
            console.log("unable to parse ", path);
        }
    }
}
<commit_msg>setInterval<commit_after>var PATH = '/Users/lukasz/sandbox/lupa41/src/**/*.js'
var vfs = require('vinyl-fs');
var fs = require('fs');
var through = require('through2');
var Path = require('path');

var lupa = require('lupa').lupa;
var createParser = require('lupa/parsers/parsers');
var File = require('vinyl');
var parseHtml = require('html-flavors').parseHtml;

var MAX_LISTENERS = 10000000;

var child_process = require('child_process');

function findVariables(file, enc, cb) {
    // this is example lupa plugin

    var body = file.ast.program.body;

    // analyze AST
    var variables = body.filter(function (node) {
        return node.type == 'VariableDeclaration'
    }).reduce(function (vars, node) {
        return vars.concat(node.declarations.map(function (decl) {
            return decl.id.name;
        }));
    }, []);

    var result = file.clone();
    result.metadata = [{name: 'variables', data: variables}]; // add metadata
    cb(null, result);
}

var fileInfo = require('lupa/src/plugins/FileInfo')();
lupa.plugin(function (file, enc, cb) {
    var result = file.clone();
    var contents = file.contents + '';
    var info = fileInfo(contents, file.path);
    result.metadata = [
        {name: 'lines', data: [info.lines] }
    ]
    cb(null, result);
}, function () { return true;});

lupa.plugin(function (file, enc, cb) {
    var result = file.clone();
    result.metadata = [
        {name: 'html-ast', data: file.ast}
    ]
    cb(null, result);
}, function (p, f) { return f.extname == '.html';});

lupa.plugin(findVariables);

lupa.plugin(require('lupa/plugins/React/components.js').getComponents);

//require('lupa/plugins/React/components')
process.on('message', function (msg) {
    console.log("plugin, got message", msg);
    module.exports.analyze(msg.path, function (state) {
        console.log("plugin, analyzed");
        process.send('message', state);
    });
})
module.exports = {
    lupa: lupa,

    analyze: function (path, onAnalyze) {

        if (lupa.getState().files.filter(function (f) {
            return f.path == path;
        }).length) {
            onAnalyze(lupa.getState())
            return;
        }

        var parser = createParser(path);
        if (parser) {

            var parse = require('ast-stream')(parser);

            var code = fs.readFileSync(path, 'utf8');
            var vinyl = new File({
                path: path,
                contents: new Buffer(code)
            })

            // get data from lupa
            lupa.output.pipe(through.obj( function (data, enc, cb) {
                cb(null, data)
                onAnalyze(lupa.getState());
            }));

            // hack to prevent break NodeJs stream
            parse.setMaxListeners(MAX_LISTENERS);

            // pipe parsed data tu lupa
            parse.pipe(through.obj(
                function (data, enc, cb) {
                    console.log("pipe data feeding XD");
                    //lupa.input.write(data);
                    console.log("creating worker");
                    var worker = child_process.fork(__dirname + '/worker');
                    console.log("worker created", worker);
                    worker.on('message', function(data) {
                        console.log('pl/ message from worker', data);
                    });
                    worker.send(data);

                    lupa.feed(data);
                }
            ));

            parse.write(vinyl)
        } else {
            console.log("unable to parse ", path);
        }
    }
}

console.log("Hello world from plugin: loaded");
setInterval(function () {
    console.log("Hello world from plugin");
}, 10 * 1000);
<|endoftext|>


<commit_before>var fs = require('fs');
var path = require('path');

function ManifestPlugin() {
  this.opts = {
    fileName: 'manifest.json'
  }
};

ManifestPlugin.prototype.apply = function(compiler) {
  var outputName = this.opts.fileName;

  compiler.plugin('done', function(stats){
    var outputPath = path.join(this.options.output.path, outputName);
    var assetsByChunkName = stats.toJson().assetsByChunkName;

    fs.writeFileSync(outputPath, JSON.stringify(assetsByChunkName, null, 2));
  });
};

module.exports = ManifestPlugin;
<commit_msg>some cleanup<commit_after>var fs = require('fs');
var path = require('path');

function ManifestPlugin() {
  this.opts = {
    fileName: 'manifest.json'
  }
};

ManifestPlugin.prototype.apply = function(compiler) {
  var outputName = this.opts.fileName;
  var outputPath = path.join(compiler.options.output.path, outputName);

  compiler.plugin('done', function(stats){
    var assetsByChunkName = stats.toJson().assetsByChunkName;

    fs.writeFileSync(outputPath, JSON.stringify(assetsByChunkName, null, 2));
  }.bind(this));
};

module.exports = ManifestPlugin;
<|endoftext|>


<commit_before>'use strict';

var debug = require('debug')('kiss.io:plugin');

var Router = require('./router');

/**
 * Plugin is the base class that each external plug-in
 * ..must inherit and implement to be plugged to the namespace.
 * An external plug-in that doesn't inherit from `Plugin` is ignored.
 *
 * @constructs Plugin
 * @access public
 *
 * @param {Object} [opts]: special options to pass to the plugin.
 * @returns {Plugin} self
 */
function Plugin(opts)
{
  if(!(this instanceof Plugin))
  {
    return new Plugin(opts);
  }

  this.opts = opts || {};
  this.exports =
  {
    nsp: {},
    socket: {},
    router: new Router(opts)
  };
}

/**
 *
 * @access public
 *
 */
{
};

/*!
 * Module exports.
 */
module.exports = Plugin;
<commit_msg>Added Plugin.wrap for wrapping custom plugins with the base `Plugin` skeleton<commit_after>'use strict';

var debug = require('debug')('kiss.io:plugin');
var util  = require('util');

var Router = require('./router');

/**
 * Plugin is the base class that each external plug-in
 * ..must inherit and implement to be plugged to the namespace.
 * An external plug-in that doesn't inherit from `Plugin` is ignored.
 *
 * @constructs Plugin
 * @access public
 *
 * @param {Object} [opts]: special options to pass to the plugin.
 * @returns {Plugin} self
 */
function Plugin(opts)
{
  if(!(this instanceof Plugin))
  {
    return new Plugin(opts);
  }

  this.opts = opts || {};
  this.exports =
  {
    nsp: {},
    socket: {},
    router: new Router(opts)
  };
}

/**
 * Wrap `Plugin` skeleton on a given plugin, essentially
 * ..extending its prototype.
 * TL;DR plugin inherits from `Plugin` class.
 *
 * @access public
 *
 * @param {Function} plugin: the plugin function (before initiated).
 */
Plugin.wrap = function(plugin)
{
  util.inherits(plugin, Plugin);
};

/*!
 * Module exports.
 */
module.exports = Plugin;
<|endoftext|>


<commit_before>var PATH = '/Users/lukasz/sandbox/lupa41/src/**/*.js'
var vfs = require('vinyl-fs');
var through = require('through2');

var lupa = require('lupa').lupa;
var File = require('vinyl');
var parse = require('ast-stream')(require('flow-parser'));

function findVariables(file, enc, cb) {
    // this is example lupa plugin

    var body = file.ast.program.body;

    // analyze AST
    var variables = body.filter(function (node) {
        return node.type == 'VariableDeclaration'
    }).reduce(function (vars, node) {
        return vars.concat(node.declarations.map(function (decl) {
            return decl.id.name;
        }));
    }, []);

    var result = file.clone();
    result.metadata = [{name: 'variables', data: variables}]; // add metadata
    cb(null, result);
}

var fileInfo = require('lupa/src/plugins/FileInfo')();
lupa.plugin(function (file, enc, cb) {
    var result = file.clone();
    var contents = file.contents + '';
    var info = fileInfo(contents, file.path);
    result.metadata = [
        {name: 'lines', data: [info.lines] }
    ]
    cb(null, result);
});

lupa.plugin(findVariables);

console.log("pluginek", require('lupa/plugins/React/components.js').getComponents);
lupa.plugin(require('lupa/plugins/React/components.js').getComponents);

//require('lupa/plugins/React/components')

module.exports = {
    lupa: lupa,
    analyze: function (path, onAnalyze) {
        // if (path.substr(-2) != 'js') {
        //     console.log("only JS files");
        // }
        if (lupa.getState().files.filter(function (f) {
            return f.path == path;
        }).length) {
            onAnalyze(lupa.getState())
            return;
        }
        console.log("TO JE PATH", lupa.input)
        // lupa.input._writableState.ended = false
        // lupa.input._writableState.ending = false
        // lupa.input._writableState.finished = false
        var parse = require('ast-stream')(require('flow-parser'));

        // lupa.input = through.obj(function (ch, enc, cb) {
        //     cb(null, ch);
        // });
        //
        // console.log("Buffer", parse.write);

        var fs = require('fs');
        var code = fs.readFileSync(path, 'utf8');
        var vinyl = new File({
            path: path,
            contents: new Buffer(code)
        })
        //vfs.src([path])
        var c = 0;
        lupa.output.pipe(through.obj( function (data, enc, cb) {
            cb(null, data)
            onAnalyze(lupa.getState());
        }));

        parse.pipe(lupa.input);

        parse.write(vinyl)
    }
}
<commit_msg>setMaxListeners<commit_after>var PATH = '/Users/lukasz/sandbox/lupa41/src/**/*.js'
var vfs = require('vinyl-fs');
var through = require('through2');

var lupa = require('lupa').lupa;
var File = require('vinyl');
var parse = require('ast-stream')(require('flow-parser'));
var MAX_LISTENERS = 10000000;

function findVariables(file, enc, cb) {
    // this is example lupa plugin

    var body = file.ast.program.body;

    // analyze AST
    var variables = body.filter(function (node) {
        return node.type == 'VariableDeclaration'
    }).reduce(function (vars, node) {
        return vars.concat(node.declarations.map(function (decl) {
            return decl.id.name;
        }));
    }, []);

    var result = file.clone();
    result.metadata = [{name: 'variables', data: variables}]; // add metadata
    cb(null, result);
}

var fileInfo = require('lupa/src/plugins/FileInfo')();
lupa.plugin(function (file, enc, cb) {
    var result = file.clone();
    var contents = file.contents + '';
    var info = fileInfo(contents, file.path);
    result.metadata = [
        {name: 'lines', data: [info.lines] }
    ]
    cb(null, result);
});

lupa.plugin(findVariables);

console.log("pluginek", require('lupa/plugins/React/components.js').getComponents);
lupa.plugin(require('lupa/plugins/React/components.js').getComponents);

//require('lupa/plugins/React/components')

module.exports = {
    lupa: lupa,
    analyze: function (path, onAnalyze) {
        // if (path.substr(-2) != 'js') {
        //     console.log("only JS files");
        // }
        if (lupa.getState().files.filter(function (f) {
            return f.path == path;
        }).length) {
            onAnalyze(lupa.getState())
            return;
        }
        console.log("TO JE PATH", lupa.input)
        // lupa.input._writableState.ended = false
        // lupa.input._writableState.ending = false
        // lupa.input._writableState.finished = false
        var parse = require('ast-stream')(require('flow-parser'));

        // lupa.input = through.obj(function (ch, enc, cb) {
        //     cb(null, ch);
        // });
        //
        // console.log("Buffer", parse.write);

        var fs = require('fs');
        var code = fs.readFileSync(path, 'utf8');
        var vinyl = new File({
            path: path,
            contents: new Buffer(code)
        })
        //vfs.src([path])
        var c = 0;
        lupa.output.pipe(through.obj( function (data, enc, cb) {
            cb(null, data)
            onAnalyze(lupa.getState());
        }));
        parse.setMaxListeners(MAX_LISTENERS);

        parse.pipe(lupa.input);

        parse.write(vinyl)
    }
}
<|endoftext|>


<commit_before>var http = require("http");
var Browser = require("zombie");

// Express `get` path
exports.path = "/presto/:cardNum";

// Express `get` callback
exports.func = function (req, res) {
  var cardNum = req.params.cardNum;

  // Assume card number is last 17 digits of url
  if (req.url.length <= 17) {
  		res.send({status: 400, message: "Error, card must have 17 digits"});
  		return;
  }

  // Get the request. HTML elements are taken from login page.
	browser = new Browser()
	browser.visit("https://www.prestocard.ca/en-US/Pages/TransactionalPages/AccountLogin.aspx", function () {
		browser.
	    fill("#ctl00_SPWebPartManager1_AccountLoginWebpartControl_ctl00_webpartAnonymousUserLogin_ctl00_textboxAnonymousLogin", "31240102581783007").
	    pressButton("#ctl00_SPWebPartManager1_AccountLoginWebpartControl_ctl00_webpartAnonymousUserLogin_ctl00_buttonSubmit", function() {
	      var balance = browser.html("#ctl00_SPWebPartManager1_AFMSCardSummaryWebpart_ctl00_wizardCardSummary_labelDisplayBalance");
	      var regex = /\$[0-9.]*/
	      var money = balance.match(regex)[0];

	      // Send the response
	      var html =
      	"<meta name='viewport' content='width=device-width, initial-scale=1.0, maximum-scale=1.0'/> \
	       <title>_money_</title> \
	        \

_money_
 \

_card_
 \
	       ";
	    	html = html.replace (/_money_/g, money);
	    	html = html.replace (/_card_/g, cardNum);
	    	res.send(html);

	      browser.visit("https://www.prestocard.ca/en-US/Pages/Logout.aspx");
	      browser.then(done, done);
	    });
	});
}
<commit_msg>remove testing number, better error handling<commit_after>var http = require("http");
var Browser = require("zombie");

// Express `get` path
exports.path = "/presto/:cardNum";

// Express `get` callback
exports.func = function (req, res) {
  var cardNum = String(req.params.cardNum);

  // Presto card numbers always have a length of 17
  if (cardNum.length != 17) {
  		res.send({status: 400, message: "Error, card must have 17 digits"});
  		return;
  }

	// Get the request. (HTML elements are taken from Presto login page.)
	browser = new Browser()
	browser.visit("https://www.prestocard.ca/en-US/Pages/TransactionalPages/AccountLogin.aspx", function () {
		browser.
	    fill("#ctl00_SPWebPartManager1_AccountLoginWebpartControl_ctl00_webpartAnonymousUserLogin_ctl00_textboxAnonymousLogin", cardNum).
	    pressButton("#ctl00_SPWebPartManager1_AccountLoginWebpartControl_ctl00_webpartAnonymousUserLogin_ctl00_buttonSubmit", function() {
	      // See if login was successful (in which case there would be a balance)
	      var balance = browser.html("#ctl00_SPWebPartManager1_AFMSCardSummaryWebpart_ctl00_wizardCardSummary_labelDisplayBalance");
	      if (!balance || typeof balance !== 'string') {
	      	res.send({status: 400, message: "Error, invalid card number"});
	      	browser.then(done, done);
	      	return;
	      }

	      var regex = /\$[0-9.]*/
	      var money = balance.match(regex)[0];

	      // Create and send the response
	      var html =
      	"<meta name='viewport' content='width=device-width, initial-scale=1.0, maximum-scale=1.0'/> \
	       <title>_money_</title> \
	        \

_money_
 \

_card_
 \
	       ";
	    	html = html.replace (/_money_/g, money);
	    	html = html.replace (/_card_/g, cardNum);
	    	res.send(html);

	      browser.visit("https://www.prestocard.ca/en-US/Pages/Logout.aspx");
	      browser.then(done, done);
	    });
	});
}
<|endoftext|>


<commit_before>/*
 * reader for nico
 *
 * @author: Hsiaoming Yang <lepture@me.com>
 */

var fs = require('fs');
var util = require('util');
var path = require('path');
var moment = require('moment');
var rs = require('robotskirt');
var Class = require('arale').Class;
var _ = require('underscore');
var highlight = require('highlight.js');
var utils = require('./utils');
var urilab = require('./utils/uri');
var pathlib = require('./utils/path');
var logging = utils.logging;

function Post(obj) {
  this.filepath = obj.filepath;
  this.relative_filepath = pathlib.relative(obj.root, this.filepath);
  this.parser = obj.parser || new MarkdownParser();

  var content = obj.content;
  if (!content) {
    logging.debug('reading content from %s', this.relative_filepath);
    content = fs.readFileSync(this.filepath, 'utf8');
  }
  var parsed = parseContent(content);
  this.header = parsed.header;
  this.body = parsed.body;
  this.title = obj.title || this.meta.title;

  if (!this.title) {
    logging.warn('no title of %s', this.relative_filepath);
  } else {
    logging.debug('find post: %s', this.title);
  }
}
Post.metadata = ['id'];

Object.defineProperty(Post.prototype, 'id', {
  configurable: true,
  get: function() {
    if (!this.directory) return this.filename;
    var bits = this.directory.split(path.sep);
    bits.push(this.filename);
    return bits.join('-');
  }
});

Object.defineProperty(Post.prototype, 'meta', {
  get: function() {
    if (this._meta) return this._meta;
    this._meta = this.parser.meta(this.header);
    return this._meta;
  }
});

Object.defineProperty(Post.prototype, 'pubdate', {
  configurable: true,
  set: function(date) {
    this._meta.pubdate = moment(date).clone();
  },
  get: function() {
    if (!this.meta.pubdate) return null;
    return moment(this.meta.pubdate).clone();
  }
});

Object.defineProperty(Post.prototype, 'updated', {
  configurable: true,
  get: function() {
    if (this.meta.updated) return moment(this.meta.updated).clone();
    return moment(fs.statSync(this.filepath).mtime).clone();
  }
});

Object.defineProperty(Post.prototype, 'status', {
  get: function() {
    if (!this.meta.status) return 'public';
    return this.meta.status;
  }
});

Object.defineProperty(Post.prototype, 'tags', {
  configurable: true,
  get: function() {
    if (!this.meta.tags) return [];
    var ret = [];
    var tags = this.meta.tags.split(',');
    tags.forEach(function(tag) {
      ret.push(tag.trim());
    });
    return ret;
  }
});

Object.defineProperty(Post.prototype, 'html', {
  configurable: true,
  get: function() {
    return this.parser.html(this.body, this.id);
  }
});

Object.defineProperty(Post.prototype, 'iframes', {
  configurable: true,
  get: function() {
    return this.parser.iframes(this.body, this.id);
  }
});

Object.defineProperty(Post.prototype, 'toc', {
  configurable: true,
  get: function() {
    return this.parser.toc(this.body);
  }
});

Object.defineProperty(Post.prototype, 'filename', {
  configurable: true,
  get: function() {
    if (this.meta.filename) return this.meta.filename;
    var basename = path.basename(this.relative_filepath);
    var extname = path.extname(this.relative_filepath);
    return basename.slice(0, -extname.length);
  }
});

Object.defineProperty(Post.prototype, 'directory', {
  configurable: true,
  get: function() {
    if (this.meta.directory) return this.meta.directory;
    var dirname = path.dirname(this.relative_filepath);
    if (dirname === '.') return '';
    return dirname;
  }
});

Object.defineProperty(Post.prototype, 'template', {
  configurable: true,
  get: function() {
    return this.meta.template || null;
  }
});

Object.defineProperty(Post.prototype, 'description', {
  configurable: true,
  get: function() {
    return this.meta.description || '';
  }
});

exports.Post = Post;

var MarkdownParser = Class.create({
  meta: function(content) {
    var parser = new rs.Markdown(new rs.HtmlRenderer());
    var html = parser.render(content);
    var m = html.match(/
(.*?)<\/h1>/);
    var meta = {};
    if (!m) {
      meta.title = null;
    } else {
      meta.title = m[1];
    }
    var items = [];
    var regex = /
(.*?)<\/li>/g;
    utils.match(regex, html, function(m) {
      items.push(m[1]);
    });
    if (items) {
      items.forEach(function(item) {
        var splits = item.split(':');
        var key = splits[0].trim();
        var value = splits.slice(1).join(':').trim();
        meta[key] = value;
      });
    }
    items = html.match(/
(.*?)<\/p>/g);
    if (items) {
      meta.description = items.join('\n');
    }
    return meta;
  },
  html: function(content, id) {
    content = content.replace(/^````(\w+)/gm, '````$1+');
    content = content.replace(/^`````(\w+)/gm, '`````$1-');
    return getHtml(content, id);
  },
  iframes: function(content, id) {
    return getIframes(content, id);
  },
  toc: function(content) {
    var toc = getToc(content);
    if (_.isEmpty(toc)) return '';
    var html = '
';
    var begin, last;
    toc.forEach(function(item) {
      if (!begin) {
        begin = item.level;
        last = item.level;
      }
      if (item.level < begin) return;
      if (Math.abs(item.level - last) > 1 ) return;
      // equal
      if (item.level === last) {
        html += util.format('
%s
', item.id, item.text);
      }
      // indent
      if (item.level > last) {
        html = html.slice(0, -5);
        html += util.format('

%s
', item.id, item.text);
      }
      // unident
      if (item.level < last) {
        html += util.format('

%s
', item.id, item.text);
      }
      last = item.level;
    });
    _(last - begin + 1).times(function() {
      html += '
';
    });
    return html;
  }
});

exports.MarkdownParser = MarkdownParser;

// helpers

function parseContent(content) {
  var lines = content.split(/\r\n|\r|\n/);
  var header = [];
  var body = [];
  var recording = true;
  lines.forEach(function(line) {
    if (recording && line.slice(0, 3) == '---') {
      recording = false;
    } else if (recording) {
      header.push(line);
    } else {
      body.push(line);
    }
  });
  return {header: header.join('\n'), body: body.join('\n')};
}

function getToc(content) {
  var renderer = new rs.HtmlRenderer();
  var toc = [];
  renderer.header = function(text, level) {
    var id = urilab.encode(text);
    toc.push({id: id, text: text, level: level});
    return util.format('<h%d id="%s">%s</h%d>', level, id, text, level);
  };
  var parser = new rs.Markdown(renderer);
  parser.render(content);
  return toc;
}

function getHtml(content, id) {
  var renderer = new rs.HtmlRenderer([rs.HTML_USE_XHTML]);
  var count = 0;

  renderer.blockcode = function(code, language) {
    if (!language || language === '+' || language === '-') {
      return '\n
' + rs.houdini.escapeHTML(code) + '
\n';
    }

    var indicate = language.slice(-1);
    var hide = indicate == '-';
    var inject = indicate == '-' || indicate == '+';
    if (inject) {
      language = language.slice(0, -1);
    }
    var shortcuts = {
      'js': 'javascript',
      'json': 'javascript',
      'py': 'python',
      'rb': 'ruby',
      'md': 'markdown',
      'mkd': 'markdown',
      'c++': 'cpp'
    };
    if (language in shortcuts) {
      language = shortcuts[language];
    }
    inject = inject && ['javascript', 'css', 'html'].indexOf(language) !== -1;
    var html = '';

    // iframe hack
    if (language.slice(0, 6) === 'iframe') {
      count = count + 1;
      var height = language.split(':')[1];
      if (height) {
        height = 'height="' + height + '"';
      }
      html = [
        '
',
        '
'
      ].join('\n');
      html = util.format(html, id, count, height);
      language = 'html';
    }

    if (inject) {
      if (language === 'javascript') {
        html = util.format('\n\n', code);
      } else if (language === 'css') {
        html = util.format('\n\n', code);
      } else {
        html = util.format('\n
%s
\n', code);
      }
    }
    if (hide && inject) {
      return html;
    }
    if (language === 'html') {
      language = 'xml';
    }
    code = highlight.highlight(language, code).value;
    html += util.format(
      '

%s

',
      language, code
    );
    return html;
  };

  renderer.header = function(text, level) {
    var id = urilab.encode(text);
    return util.format('<h%d id="%s">%s</h%d>', level, id, text, level);
  };

  var parser = new rs.Markdown(
    renderer,
    [
      rs.EXT_FENCED_CODE, rs.EXT_TABLES,
      rs.EXT_AUTOLINK, rs.EXT_NO_INTRA_EMPHASIS,
      rs.EXT_STRIKETHROUGH
    ]
  );
  return parser.render(content);
}

function getIframes(content, id) {
  var renderer = new rs.HtmlRenderer();
  var count = 0;
  var iframes = {};

  renderer.blockcode = function(code, language) {
    if (!language) return '';
    if (language.slice(0, 6) === 'iframe') {
      count += 1;
      iframes['iframe-' + id + '-' + count] = code;
    }
  };

  var parser = new rs.Markdown(renderer, [rs.EXT_FENCED_CODE]);
  parser.render(content);
  return iframes;
}
<commit_msg>moment transform date<commit_after>/*
 * reader for nico
 *
 * @author: Hsiaoming Yang <lepture@me.com>
 */

var fs = require('fs');
var util = require('util');
var path = require('path');
var moment = require('moment');
var rs = require('robotskirt');
var Class = require('arale').Class;
var _ = require('underscore');
var highlight = require('highlight.js');
var utils = require('./utils');
var urilab = require('./utils/uri');
var pathlib = require('./utils/path');
var logging = utils.logging;

function Post(obj) {
  this.filepath = obj.filepath;
  this.relative_filepath = pathlib.relative(obj.root, this.filepath);
  this.parser = obj.parser || new MarkdownParser();

  var content = obj.content;
  if (!content) {
    logging.debug('reading content from %s', this.relative_filepath);
    content = fs.readFileSync(this.filepath, 'utf8');
  }
  var parsed = parseContent(content);
  this.header = parsed.header;
  this.body = parsed.body;
  this.title = obj.title || this.meta.title;

  if (!this.title) {
    logging.warn('no title of %s', this.relative_filepath);
  } else {
    logging.debug('find post: %s', this.title);
  }
}
Post.metadata = ['id'];

Object.defineProperty(Post.prototype, 'id', {
  configurable: true,
  get: function() {
    if (!this.directory) return this.filename;
    var bits = this.directory.split(path.sep);
    bits.push(this.filename);
    return bits.join('-');
  }
});

Object.defineProperty(Post.prototype, 'meta', {
  get: function() {
    if (this._meta) return this._meta;
    this._meta = this.parser.meta(this.header);
    return this._meta;
  }
});

Object.defineProperty(Post.prototype, 'pubdate', {
  configurable: true,
  set: function(date) {
    this._meta.pubdate = new moment(date, 'YYYY-MM-DD HH:mm:ss');
  },
  get: function() {
    if (!this.meta.pubdate) return null;
    return new moment(this.meta.pubdate, 'YYYY-MM-DD HH:mm:ss');
  }
});

Object.defineProperty(Post.prototype, 'updated', {
  configurable: true,
  get: function() {
    if (this.meta.updated) {
      return new moment(this.meta.updated, 'YYYY-MM-DD HH:mm:ss');
    }
    return new moment(fs.statSync(this.filepath).mtime);
  }
});

Object.defineProperty(Post.prototype, 'status', {
  get: function() {
    if (!this.meta.status) return 'public';
    return this.meta.status;
  }
});

Object.defineProperty(Post.prototype, 'tags', {
  configurable: true,
  get: function() {
    if (!this.meta.tags) return [];
    var ret = [];
    var tags = this.meta.tags.split(',');
    tags.forEach(function(tag) {
      ret.push(tag.trim());
    });
    return ret;
  }
});

Object.defineProperty(Post.prototype, 'html', {
  configurable: true,
  get: function() {
    return this.parser.html(this.body, this.id);
  }
});

Object.defineProperty(Post.prototype, 'iframes', {
  configurable: true,
  get: function() {
    return this.parser.iframes(this.body, this.id);
  }
});

Object.defineProperty(Post.prototype, 'toc', {
  configurable: true,
  get: function() {
    return this.parser.toc(this.body);
  }
});

Object.defineProperty(Post.prototype, 'filename', {
  configurable: true,
  get: function() {
    if (this.meta.filename) return this.meta.filename;
    var basename = path.basename(this.relative_filepath);
    var extname = path.extname(this.relative_filepath);
    return basename.slice(0, -extname.length);
  }
});

Object.defineProperty(Post.prototype, 'directory', {
  configurable: true,
  get: function() {
    if (this.meta.directory) return this.meta.directory;
    var dirname = path.dirname(this.relative_filepath);
    if (dirname === '.') return '';
    return dirname;
  }
});

Object.defineProperty(Post.prototype, 'template', {
  configurable: true,
  get: function() {
    return this.meta.template || null;
  }
});

Object.defineProperty(Post.prototype, 'description', {
  configurable: true,
  get: function() {
    return this.meta.description || '';
  }
});

exports.Post = Post;

var MarkdownParser = Class.create({
  meta: function(content) {
    var parser = new rs.Markdown(new rs.HtmlRenderer());
    var html = parser.render(content);
    var m = html.match(/
(.*?)<\/h1>/);
    var meta = {};
    if (!m) {
      meta.title = null;
    } else {
      meta.title = m[1];
    }
    var items = [];
    var regex = /
(.*?)<\/li>/g;
    utils.match(regex, html, function(m) {
      items.push(m[1]);
    });
    if (items) {
      items.forEach(function(item) {
        var splits = item.split(':');
        var key = splits[0].trim();
        var value = splits.slice(1).join(':').trim();
        meta[key] = value;
      });
    }
    items = html.match(/
(.*?)<\/p>/g);
    if (items) {
      meta.description = items.join('\n');
    }
    return meta;
  },
  html: function(content, id) {
    content = content.replace(/^````(\w+)/gm, '````$1+');
    content = content.replace(/^`````(\w+)/gm, '`````$1-');
    return getHtml(content, id);
  },
  iframes: function(content, id) {
    return getIframes(content, id);
  },
  toc: function(content) {
    var toc = getToc(content);
    if (_.isEmpty(toc)) return '';
    var html = '
';
    var begin, last;
    toc.forEach(function(item) {
      if (!begin) {
        begin = item.level;
        last = item.level;
      }
      if (item.level < begin) return;
      if (Math.abs(item.level - last) > 1 ) return;
      // equal
      if (item.level === last) {
        html += util.format('
%s
', item.id, item.text);
      }
      // indent
      if (item.level > last) {
        html = html.slice(0, -5);
        html += util.format('

%s
', item.id, item.text);
      }
      // unident
      if (item.level < last) {
        html += util.format('

%s
', item.id, item.text);
      }
      last = item.level;
    });
    _(last - begin + 1).times(function() {
      html += '
';
    });
    return html;
  }
});

exports.MarkdownParser = MarkdownParser;

// helpers

function parseContent(content) {
  var lines = content.split(/\r\n|\r|\n/);
  var header = [];
  var body = [];
  var recording = true;
  lines.forEach(function(line) {
    if (recording && line.slice(0, 3) == '---') {
      recording = false;
    } else if (recording) {
      header.push(line);
    } else {
      body.push(line);
    }
  });
  return {header: header.join('\n'), body: body.join('\n')};
}

function getToc(content) {
  var renderer = new rs.HtmlRenderer();
  var toc = [];
  renderer.header = function(text, level) {
    var id = urilab.encode(text);
    toc.push({id: id, text: text, level: level});
    return util.format('<h%d id="%s">%s</h%d>', level, id, text, level);
  };
  var parser = new rs.Markdown(renderer);
  parser.render(content);
  return toc;
}

function getHtml(content, id) {
  var renderer = new rs.HtmlRenderer([rs.HTML_USE_XHTML]);
  var count = 0;

  renderer.blockcode = function(code, language) {
    if (!language || language === '+' || language === '-') {
      return '\n
' + rs.houdini.escapeHTML(code) + '
\n';
    }

    var indicate = language.slice(-1);
    var hide = indicate == '-';
    var inject = indicate == '-' || indicate == '+';
    if (inject) {
      language = language.slice(0, -1);
    }
    var shortcuts = {
      'js': 'javascript',
      'json': 'javascript',
      'py': 'python',
      'rb': 'ruby',
      'md': 'markdown',
      'mkd': 'markdown',
      'c++': 'cpp'
    };
    if (language in shortcuts) {
      language = shortcuts[language];
    }
    inject = inject && ['javascript', 'css', 'html'].indexOf(language) !== -1;
    var html = '';

    // iframe hack
    if (language.slice(0, 6) === 'iframe') {
      count = count + 1;
      var height = language.split(':')[1];
      if (height) {
        height = 'height="' + height + '"';
      }
      html = [
        '
',
        '
'
      ].join('\n');
      html = util.format(html, id, count, height);
      language = 'html';
    }

    if (inject) {
      if (language === 'javascript') {
        html = util.format('\n\n', code);
      } else if (language === 'css') {
        html = util.format('\n\n', code);
      } else {
        html = util.format('\n
%s
\n', code);
      }
    }
    if (hide && inject) {
      return html;
    }
    if (language === 'html') {
      language = 'xml';
    }
    code = highlight.highlight(language, code).value;
    html += util.format(
      '

%s

',
      language, code
    );
    return html;
  };

  renderer.header = function(text, level) {
    var id = urilab.encode(text);
    return util.format('<h%d id="%s">%s</h%d>', level, id, text, level);
  };

  var parser = new rs.Markdown(
    renderer,
    [
      rs.EXT_FENCED_CODE, rs.EXT_TABLES,
      rs.EXT_AUTOLINK, rs.EXT_NO_INTRA_EMPHASIS,
      rs.EXT_STRIKETHROUGH
    ]
  );
  return parser.render(content);
}

function getIframes(content, id) {
  var renderer = new rs.HtmlRenderer();
  var count = 0;
  var iframes = {};

  renderer.blockcode = function(code, language) {
    if (!language) return '';
    if (language.slice(0, 6) === 'iframe') {
      count += 1;
      iframes['iframe-' + id + '-' + count] = code;
    }
  };

  var parser = new rs.Markdown(renderer, [rs.EXT_FENCED_CODE]);
  parser.render(content);
  return iframes;
}
<|endoftext|>


<commit_before>const { EventEmitter } = require('events')

const debug = require('debug')

const RoundRobinList = require('./roundrobinlist')
const lookup = require('./lookupd')
const { NSQDConnection } = require('./nsqdconnection')
const { ReaderConfig } = require('./config')
const { ReaderRdy } = require('./readerrdy')

/**
 * Reader provides high-level functionality for building robust NSQ
 * consumers. Reader is built upon the EventEmitter and thus supports various
 * hooks when different events occur.
 * @type {Reader}
 */
class Reader extends EventEmitter {
  static get ERROR () {
    return 'error'
  }
  static get MESSAGE () {
    return 'message'
  }
  static get DISCARD () {
    return 'discard'
  }
  static get NSQD_CONNECTED () {
    return 'nsqd_connected'
  }
  static get NSQD_CLOSED () {
    return 'nsqd_closed'
  }

  /**
   * @constructor
   * @param  {String} topic
   * @param  {String} channel
   * @param  {Object} options
   */
  constructor (topic, channel, options, ...args) {
    super(topic, channel, options, ...args)
    this.topic = topic
    this.channel = channel
    this.debug = debug(`nsqjs:reader:${this.topic}/${this.channel}`)
    this.config = new ReaderConfig(options)
    this.config.validate()

    this.debug('Configuration')
    this.debug(this.config)

    this.roundrobinLookupd = new RoundRobinList(
      this.config.lookupdHTTPAddresses
    )

    this.readerRdy = new ReaderRdy(
      this.config.maxInFlight,
      this.config.maxBackoffDuration,
      `${this.topic}/${this.channel}`
    )

    this.lookupdIntervalId = null
    this.directIntervalId = null
    this.connectionIds = []
  }

  /**
   * Adds a connection to nsqd at the configured address.
   *
   * @return {undefined}
   */
  connect () {
    this._connectTCPAddresses()
    this._connectLookupd()
  }

  _connectInterval () {
    return this.config.lookupdPollInterval * 1000
  }

  _connectTCPAddresses () {
    const directConnect = () => {
      // Don't establish new connections while the Reader is paused.
      if (this.isPaused()) return

      if (this.connectionIds.length < this.config.nsqdTCPAddresses.length) {
        return this.config.nsqdTCPAddresses.forEach(addr => {
          const [address, port] = addr.split(':')
          this.connectToNSQD(address, Number(port))
        })
      }
    }

    this.lookupdIntervalId = setInterval(() => { directConnect() },
      this._connectInterval())

    // Connect immediately.
    directConnect()
  }

  _connectLookupd () {
    this.directIntervalId = setInterval(
      () => { this.queryLookupd() },
      this._connectInterval()
    )

    // Connect immediately.
    this.queryLookupd()
  }

  /**
   * Close all connections and prevent any periodic callbacks.
   * @return {Array} The closed connections.
   */
  close () {
    clearInterval(this.directIntervalId)
    clearInterval(this.lookupdIntervalId)
    return this.readerRdy.close()
  }

  /**
   * Pause all connections
   * @return {Array} The paused connections.
   */
  pause () {
    this.debug('pause')
    return this.readerRdy.pause()
  }

  /**
   * Unpause all connections
   * @return {Array} The unpaused connections.
   */
  unpause () {
    this.debug('unpause')
    return this.readerRdy.unpause()
  }

  /**
   * @return {Boolean}
   */
  isPaused () {
    return this.readerRdy.isPaused()
  }

  /**
   * Trigger a query of the configured nsq_lookupd_http_addresses.
   * @return {undefined}
   */
  queryLookupd () {
    // Don't establish new connections while the Reader is paused.
    if (this.isPaused()) return

    // Trigger a query of the configured `lookupdHTTPAddresses`.
    const endpoint = this.roundrobinLookupd.next()
    lookup(endpoint, this.topic, (err, nodes = []) =>
      nodes.map(n => {
        this.connectToNSQD(n.broadcast_address || n.hostname, n.tcp_port)
      })
    )
  }

  /**
   * Adds a connection to nsqd at the specified address.
   *
   * @param  {String} host
   * @param  {Number|String} port
   * @return {Object|undefined} The newly created nsqd connection.
   */
  connectToNSQD (host, port) {
    this.debug(`discovered ${host}:${port} for ${this.topic} topic`)
    const conn = new NSQDConnection(
      host,
      port,
      this.topic,
      this.channel,
      this.config
    )

    // Ensure a connection doesn't already exist to this nsqd instance.
    if (this.connectionIds.indexOf(conn.id()) !== -1) {
      return
    }

    this.debug(`connecting to ${host}:${port}`)
    this.connectionIds.push(conn.id())

    this.registerConnectionListeners(conn)
    this.readerRdy.addConnection(conn)

    return conn.connect()
  }

  /**
   * Registers event handlers for the nsqd connection.
   * @param  {Object} conn
   */
  registerConnectionListeners (conn) {
    conn.on(NSQDConnection.CONNECTED, () => {
      this.debug(Reader.NSQD_CONNECTED)
      this.emit(Reader.NSQD_CONNECTED, conn.nsqdHost, conn.nsqdPort)
    })

    conn.on(NSQDConnection.ERROR, err => {
      this.debug(Reader.ERROR)
      this.debug(err)
      this.emit(Reader.ERROR, err)
    })

    conn.on(NSQDConnection.CONNECTION_ERROR, err => {
      this.debug(Reader.ERROR)
      this.debug(err)
      this.emit(Reader.ERROR, err)
    })

    // On close, remove the connection id from this reader.
    conn.on(NSQDConnection.CLOSED, () => {
      this.debug(Reader.NSQD_CLOSED)

      const index = this.connectionIds.indexOf(conn.id())
      if (index === -1) {
        return
      }
      this.connectionIds.splice(index, 1)

      this.emit(Reader.NSQD_CLOSED, conn.nsqdHost, conn.nsqdPort)
    })

    /**
     * On message, send either a message or discard event depending on the
     * number of attempts.
     */
    conn.on(NSQDConnection.MESSAGE, message => {
      this.handleMessage(message)
    })
  }

  /**
   * Asynchronously handles an nsqd message.
   *
   * @param  {Object} message
   */
  handleMessage (message) {
    /**
     * Give the internal event listeners a chance at the events
     * before clients of the Reader.
     */
    process.nextTick(() => {
      const autoFinishMessage =
        this.config.maxAttempts > 0 &&
        this.config.maxAttempts < message.attempts
      const numDiscardListeners = this.listeners(Reader.DISCARD).length

      if (autoFinishMessage && numDiscardListeners > 0) {
        this.emit(Reader.DISCARD, message)
      } else {
        this.emit(Reader.MESSAGE, message)
      }

      if (autoFinishMessage) {
        message.finish()
      }
    })
  }
}

module.exports = Reader
<commit_msg>Fix memory leak. This fixes #211 (#212)<commit_after>const { EventEmitter } = require('events')

const debug = require('debug')

const RoundRobinList = require('./roundrobinlist')
const lookup = require('./lookupd')
const { NSQDConnection } = require('./nsqdconnection')
const { ReaderConfig } = require('./config')
const { ReaderRdy } = require('./readerrdy')

/**
 * Reader provides high-level functionality for building robust NSQ
 * consumers. Reader is built upon the EventEmitter and thus supports various
 * hooks when different events occur.
 * @type {Reader}
 */
class Reader extends EventEmitter {
  static get ERROR () {
    return 'error'
  }
  static get MESSAGE () {
    return 'message'
  }
  static get DISCARD () {
    return 'discard'
  }
  static get NSQD_CONNECTED () {
    return 'nsqd_connected'
  }
  static get NSQD_CLOSED () {
    return 'nsqd_closed'
  }

  /**
   * @constructor
   * @param  {String} topic
   * @param  {String} channel
   * @param  {Object} options
   */
  constructor (topic, channel, options, ...args) {
    super(topic, channel, options, ...args)
    this.topic = topic
    this.channel = channel
    this.debug = debug(`nsqjs:reader:${this.topic}/${this.channel}`)
    this.config = new ReaderConfig(options)
    this.config.validate()

    this.debug('Configuration')
    this.debug(this.config)

    this.roundrobinLookupd = new RoundRobinList(
      this.config.lookupdHTTPAddresses
    )

    this.readerRdy = new ReaderRdy(
      this.config.maxInFlight,
      this.config.maxBackoffDuration,
      `${this.topic}/${this.channel}`
    )

    this.lookupdIntervalId = null
    this.directIntervalId = null
    this.connectionIds = []
  }

  /**
   * Adds a connection to nsqd at the configured address.
   *
   * @return {undefined}
   */
  connect () {
    this._connectTCPAddresses()
    this._connectLookupd()
  }

  _connectInterval () {
    return this.config.lookupdPollInterval * 1000
  }

  _connectTCPAddresses () {
    const directConnect = () => {
      // Don't establish new connections while the Reader is paused.
      if (this.isPaused()) return

      if (this.connectionIds.length < this.config.nsqdTCPAddresses.length) {
        return this.config.nsqdTCPAddresses.forEach(addr => {
          const [address, port] = addr.split(':')
          this.connectToNSQD(address, Number(port))
        })
      }
    }

    this.lookupdIntervalId = setInterval(() => { directConnect() },
      this._connectInterval())

    // Connect immediately.
    directConnect()
  }

  _connectLookupd () {
    this.directIntervalId = setInterval(
      () => { this.queryLookupd() },
      this._connectInterval()
    )

    // Connect immediately.
    this.queryLookupd()
  }

  /**
   * Close all connections and prevent any periodic callbacks.
   * @return {Array} The closed connections.
   */
  close () {
    clearInterval(this.directIntervalId)
    clearInterval(this.lookupdIntervalId)
    return this.readerRdy.close()
  }

  /**
   * Pause all connections
   * @return {Array} The paused connections.
   */
  pause () {
    this.debug('pause')
    return this.readerRdy.pause()
  }

  /**
   * Unpause all connections
   * @return {Array} The unpaused connections.
   */
  unpause () {
    this.debug('unpause')
    return this.readerRdy.unpause()
  }

  /**
   * @return {Boolean}
   */
  isPaused () {
    return this.readerRdy.isPaused()
  }

  /**
   * Trigger a query of the configured nsq_lookupd_http_addresses.
   * @return {undefined}
   */
  queryLookupd () {
    // Don't establish new connections while the Reader is paused.
    if (this.isPaused()) return

    // Trigger a query of the configured `lookupdHTTPAddresses`.
    const endpoint = this.roundrobinLookupd.next()
    lookup(endpoint, this.topic, (err, nodes = []) =>
      nodes.map(n => {
        this.connectToNSQD(n.broadcast_address || n.hostname, n.tcp_port)
      })
    )
  }

  /**
   * Adds a connection to nsqd at the specified address.
   *
   * @param  {String} host
   * @param  {Number|String} port
   * @return {Object|undefined} The newly created nsqd connection.
   */
  connectToNSQD (host, port) {
    this.debug(`discovered ${host}:${port} for ${this.topic} topic`)
    const conn = new NSQDConnection(
      host,
      port,
      this.topic,
      this.channel,
      this.config
    )

    // Ensure a connection doesn't already exist to this nsqd instance.
    if (this.connectionIds.indexOf(conn.id()) !== -1) {
      conn.debug.destroy()
      return
    }

    this.debug(`connecting to ${host}:${port}`)
    this.connectionIds.push(conn.id())

    this.registerConnectionListeners(conn)
    this.readerRdy.addConnection(conn)

    return conn.connect()
  }

  /**
   * Registers event handlers for the nsqd connection.
   * @param  {Object} conn
   */
  registerConnectionListeners (conn) {
    conn.on(NSQDConnection.CONNECTED, () => {
      this.debug(Reader.NSQD_CONNECTED)
      this.emit(Reader.NSQD_CONNECTED, conn.nsqdHost, conn.nsqdPort)
    })

    conn.on(NSQDConnection.ERROR, err => {
      this.debug(Reader.ERROR)
      this.debug(err)
      this.emit(Reader.ERROR, err)
    })

    conn.on(NSQDConnection.CONNECTION_ERROR, err => {
      this.debug(Reader.ERROR)
      this.debug(err)
      this.emit(Reader.ERROR, err)
    })

    // On close, remove the connection id from this reader.
    conn.on(NSQDConnection.CLOSED, () => {
      this.debug(Reader.NSQD_CLOSED)

      const index = this.connectionIds.indexOf(conn.id())
      if (index === -1) {
        return
      }
      this.connectionIds.splice(index, 1)

      this.emit(Reader.NSQD_CLOSED, conn.nsqdHost, conn.nsqdPort)
    })

    /**
     * On message, send either a message or discard event depending on the
     * number of attempts.
     */
    conn.on(NSQDConnection.MESSAGE, message => {
      this.handleMessage(message)
    })
  }

  /**
   * Asynchronously handles an nsqd message.
   *
   * @param  {Object} message
   */
  handleMessage (message) {
    /**
     * Give the internal event listeners a chance at the events
     * before clients of the Reader.
     */
    process.nextTick(() => {
      const autoFinishMessage =
        this.config.maxAttempts > 0 &&
        this.config.maxAttempts < message.attempts
      const numDiscardListeners = this.listeners(Reader.DISCARD).length

      if (autoFinishMessage && numDiscardListeners > 0) {
        this.emit(Reader.DISCARD, message)
      } else {
        this.emit(Reader.MESSAGE, message)
      }

      if (autoFinishMessage) {
        message.finish()
      }
    })
  }
}

module.exports = Reader
<|endoftext|>


<commit_before>module.exports = remove;

function remove(element) {
  element.parentNode.removeChild(element);
  return element;
}<commit_msg>chore(remove): null-safe remove already detached<commit_after>module.exports = remove;

function remove(element) {
  var parent = element.parentNode;

  if (parent) {
    parent.removeChild(element);
  }

  return element;
}<|endoftext|>


<commit_before>/// <reference path="../typings/index.d.ts" />
/**
 * swig 模版类
 */
const swig = require("swig");
const path = require("path");

// let template = swig.compileFile(__dirname + "/templates/index.html");
// let output = template({
//     pagename: 'awesome people',
//     authors: ['Paul', 'Jim', 'Jane']
// });

let render_template = function (rootPath, config) {
    let _prefix = path.join(rootPath, config.templates);
    return function (templatePath, data) {
        let realyPath = path.join(_prefix, templatePath);
        let template = swig.compileFile(realyPath);
        return template(data);
    }
}

module.exports = render_template;<commit_msg>修复模板中静态文件的引入<commit_after>/// <reference path="../typings/index.d.ts" />
/**
 * swig 模版类
 */
const swig = require("swig");
const path = require("path");

swig.setFilter("static", function(input) {
    return "./" + input;
})

let render_template = function (rootPath, config) {
    let _prefix = path.join(rootPath, config.templates);
    return function (templatePath, data) {
        let realyPath = path.join(_prefix, templatePath);
        let template = swig.compileFile(realyPath);
        return template(data);
    }
};

module.exports = render_template;<|endoftext|>


<commit_before>'use strict';

/* render.js
 * Render CSS from a tree.
 */

const Rule = require('./rule'),
      Property = require('./property'),
      Value = require('./value'),
      loop = Array.prototype.forEach;

module.exports = exports = render;

function render(tree, opts){
  opts = (typeof opts === 'object') ? opts : [];

  if (tree instanceof Rule) return render.rule(tree, opts);
  if (tree instanceof Property) return render.property(tree, opts);
  if (tree instanceof Value) return render.value(tree, opts);

  if (!Array.isArray(tree))
   throw new TypeError('tree must be an array.');

  let doc = [];
  tree.forEach((x) => {
    if (!(x instanceof Rule) && !opts.weak)
      throw new Error('a tree\'s root may only contain Rule objects');

    doc.push(render.rule(x));
  });

  return doc.join(opts.indent ? '\n\n' : ' ');
}

render.value = function(value, opts){
  opts = opts || {};
  if (value.type === 'keyword') return value.keyword;
  else if (value.type === 'number') return value.val + value.unit;
  else if (value.type === 'function') {
    let args = '';
    value.args.forEach((arg, i) => {
      if (typeof arg === 'number') arg = new Value(arg);
      if (
        !opts.weak &&
        (!(arg instanceof Value) ||
        (arg.type !== 'number' &&
        arg.type !== 'keyword' &&
        arg.type === 'unknown'))
      ) throw new Error('function Values may only contain known non-function values as their arguments');

      args += arg.val + (value.args.length-1 !== i ? ', ' : '');
    });

    return value.name + '(' + args + ')';
  } else {
    if (!opts.weak)
      throw new Error('could not identify "'+value.val+'".');
    return value.val;
  }
};

render.property = function(property, opts){
  opts = opts || {};
  let values = [];
  loop.call(property.items, function(item){
    if (!(item instanceof Value) && !opts.weak)
      throw new Error('Property objects may only contain Value objects.');

    values.push(render.value(item, opts));
  });

  if (!(/^[a-z-]+$/.test(property.name)) && !opts.weak)
    throw new Error('property names may only be alpha and "-" characters.');

  return property.name + ': ' + values.join(' ');
};

render.rule = function(rule, opts){
  opts = opts || {};
  if (rule.type === 'selector') {
    let selector = rule.selectors.join(', ');

    let block = '{' + (opts.indent ? '\n' : '');
    loop.call(rule.items, (prop, i) => {
      if (!(prop instanceof Property) && !opts.weak)
        throw new Error('selector rules may only contain properties');

      block += render.property(prop, opts) + (i !== rule.items.length-1 ? ';' + (opts.indent ? '\n' : ' ') : '');
    });
    block += (opts.indent ? '\n' : '') + '}';

    return selector + ' ' + block;
  }

  else if (rule.type === 'at-rule expressive') {
    let expression = [];
    loop.call(rule.expression, (item) => {
      if (typeof item === 'string') item = new Value(item);
      if (item instanceof Property) {
        expression.push('('+render.property(item)+')');
      }
      else if (item instanceof Value && item.type === 'keyword') {
        expression.push(render.value(item, opts));
      }
      else
        if (!opts.weak)
          throw new Error('at-rule expressions may only contain keywords and properties');
    });

    let block = [];
    loop.call(rule.items, (item) => {
      if ((!(item instanceof Rule) || item.type !== 'selector') && !opts.weak)
        throw new Error('expressive at-rules may only contain selector rules');

      block.push(render.rule(item, opts));
    });

    return rule.name +
    ' ' + expression.join(' ') +
    ' {' +
      (opts.indent ? '\n' : '') +
      block.join((opts.indent ? '\n\n' : ' ')) +
      '\n' + (opts.indent ? '\n' : '') +
    '}';
  }
};
<commit_msg>Change specific render to loose render<commit_after>'use strict';

/* render.js
 * Render CSS from a tree.
 */

const Rule = require('./rule'),
      Property = require('./property'),
      Value = require('./value'),
      loop = Array.prototype.forEach;

module.exports = exports = render;

function render(tree, opts){
  opts = (typeof opts === 'object') ? opts : [];

  if (tree instanceof Rule) return render.rule(tree, opts);
  if (tree instanceof Property) return render.property(tree, opts);
  if (tree instanceof Value) return render.value(tree, opts);

  if (!Array.isArray(tree))
   throw new TypeError('tree must be an array.');

  let doc = [];
  tree.forEach((x) => {
    if (!(x instanceof Rule) && !opts.weak)
      throw new Error('a tree\'s root may only contain Rule objects');

    doc.push(render.rule(x));
  });

  return doc.join(opts.indent ? '\n\n' : ' ');
}

render.value = function(value, opts){
  opts = opts || {};
  if (value.type === 'keyword') return value.keyword;
  else if (value.type === 'number') return value.val + value.unit;
  else if (value.type === 'function') {
    let args = '';
    value.args.forEach((arg, i) => {
      if (typeof arg === 'number') arg = new Value(arg);
      if (
        !opts.weak &&
        (!(arg instanceof Value) ||
        (arg.type !== 'number' &&
        arg.type !== 'keyword' &&
        arg.type === 'unknown'))
      ) throw new Error('function Values may only contain known non-function values as their arguments');

      args += arg.val + (value.args.length-1 !== i ? ', ' : '');
    });

    return value.name + '(' + args + ')';
  } else {
    if (!opts.weak)
      throw new Error('could not identify "'+value.val+'".');
    return value.val;
  }
};

render.property = function(property, opts){
  opts = opts || {};
  let values = [];
  loop.call(property.items, function(item){
    if (!(item instanceof Value) && !opts.weak)
      throw new Error('Property objects may only contain Value objects.');

    values.push(render(item, opts));
  });

  if (!(/^[a-z-]+$/.test(property.name)) && !opts.weak)
    throw new Error('property names may only be alpha and "-" characters.');

  return property.name + ': ' + values.join(' ');
};

render.rule = function(rule, opts){
  opts = opts || {};
  if (rule.type === 'selector') {
    let selector = rule.selectors.join(', ');

    let block = '{' + (opts.indent ? '\n' : '');
    loop.call(rule.items, (prop, i) => {
      if (!(prop instanceof Property) && !opts.weak)
        throw new Error('selector rules may only contain properties');

      block += render(prop, opts) + (i !== rule.items.length-1 ? ';' + (opts.indent ? '\n' : ' ') : '');
    });
    block += (opts.indent ? '\n' : '') + '}';

    return selector + ' ' + block;
  }

  else if (rule.type === 'at-rule expressive') {
    let expression = [];
    loop.call(rule.expression, (item) => {
      if (typeof item === 'string') item = new Value(item);
      if (item instanceof Property) {
        expression.push('('+render(item)+')');
      }
      else if (item instanceof Value && item.type === 'keyword') {
        expression.push(render(item, opts));
      }
      else
        if (!opts.weak)
          throw new Error('at-rule expressions may only contain keywords and properties');
    });

    let block = [];
    loop.call(rule.items, (item) => {
      if ((!(item instanceof Rule) || item.type !== 'selector') && !opts.weak)
        throw new Error('expressive at-rules may only contain selector rules');

      block.push(render(item, opts));
    });

    return rule.name +
    ' ' + expression.join(' ') +
    ' {' +
      (opts.indent ? '\n' : '') +
      block.join((opts.indent ? '\n\n' : ' ')) +
      '\n' + (opts.indent ? '\n' : '') +
    '}';
  }
};
<|endoftext|>


<commit_before>'use strict';
const child_process = require('child_process'),
	Promisie = require('promisie'),
	map = Promisie.promisify(require('async').mapLimit),
	http = require('http'),
	express = require('express'),
	merge = require('util-extend'),
	path = require('path'),
	fs = Promisie.promisifyAll(require('fs')),
	sockets = require('socket.io'),
	Stream = require('stream'),
	REPL = require('repl');

require('shelljs/global');

var install = function (cmd) {
	return new Promise((resolve, reject) => {
		child_process.exec(cmd, {
			cwd: (this && typeof this === 'object' && this.cwd) ? this.cwd : path.join(__dirname, '../')
		}, (err, stdout, stderr) => {
			if (stdout) resolve(stdout);
			else reject(err || stderr);
		});
	});
};

var installModule = function (mod, cb) {
	try {
		if (typeof mod === 'object') {
			if (mod.type === 'internal') {
				let filePath = path.join(__dirname, mod.name);
				fs.statAsync(filePath)
					.then(() => {
						this.context[path.basename(filePath, '.js')] = require(filePath);
						cb(null, `${ mod.name } installed`);
					}, () => {
						cb(null, 'ERROR: FP-001');
					});
			}
			else if (mod.type === 'external') {
				if (mod.name === 'shelljs') {
					this.context.exec = exec;
					cb(null, 'shelljs installed');
				}
				else {
					let cleanedName = (/.+\..+/g.test(mod.name)) ? mod.name.substring(mod.name.indexOf('.')) : mod.name;
					try {
						let install = require(mod.name);
						this.context[cleanedName] = install;
						cb(null, `${ mod.name } installed`);
					}
					catch (e) {
						try {
							var installString = 'npm i ' + mod.name.toLowerCase();
							install(installString)
								.then(() => {
									let installed = require(mod.name);
									this.context[mod.name] = installed;
									cb(null, `${ mod.name } installed`);
								});
						}
						catch (err) {
							cb(null, 'ERROR: MOD-001');
						}
					}
				}
			}
			else {
				cb(null, 'ERROR: FMT-002');
			}
		}
		else {
			cb(null, 'ERROR: FMT-001');
		}
	}
	catch (e) {
		console.log('ERR', e);
		cb(e);
	}
};

var configureModules = function (socket) {
	return map(this.modules, 5, installModule.bind(this))
		.then(results => {
			console.log('results', results);
			if (!socket || this._getStream()) this._setREPL();
			else {
				this._setStream(socket);
				this._setREPL();
			}
			return this;
		}, e => {
			console.log('ERROR', e.stack);
			return e;
		});
};

var configureConnection = function (socket, cb) {
	console.log('configureConnection');
	socket.on('disconnect', () => {
		this.disconnect();
	});
	socket.on('end', () => {
		this.disconnect();
	});
	socket.on('close', () => {
		this.disconnect();
	});
	if (typeof this.replConnectionCallback === 'function') this.replConnectionCallback(socket);
	if (this.child_process || this.active) {
		this._setStream(socket);
		cb(null, this);
	}
	else {
		configureModules.call(this, socket)
			.then(_this => {
				if (_this instanceof Error) cb(_this);
				else cb(null, _this);
			});
	}
};

var REPLIE = class REPLIE {
	constructor (options) {
		let rp,
			stream = options.stream,
			app,
			connectedSocket;
		this.room = options.room;
		this.active = false;
		this.server = options.server;
		this.port = options.port || 5000;
		this.namespace = options.namespace;
		this.logger = options.logger || console.log;
		this.prompt = options.prompt;
		this.modules = options.modules || [];
		this.context = {};
		this.namespaces = {};
		this.sloppyMode = options.sloppyMode;
		this.errHandler = options.onError;
		this.child_process = options.child_process;
		this.connectionUrl = options.connectionUrl || '/';
		this.templatePath = options.templatePath || path.resolve(__dirname, '../views/example.html');
		this.connectionMessage = options.connectionMessage;
		this.replConnectionCallback = (typeof this.replConnectionCallback === 'function') ? this.replConnectionCallback : (socket) => {
			if (!this.room) {
				if (this.namespace) this.namespaces[this.namespace].emit('stdout', this.connectionMessage || 'Hello World');
				else this.io.emit('stdout', this.connectionMessage || 'Hello World');
			}
			else {
				if (this.namespace) this.namespaces[this.namespace].to(this.room).emit('stdout', this.connectionMessage || 'Hello World');
				else this.io.to(this.room).emit('stdout', this.connectionMessage || 'Hello World');
			}
		};
		this.serverConnectionCallback = (typeof options.serverConnectionCallback === 'function') ? options.serverConnectionCallback : (req, res) => {
			res.sendFile(this.templatePath);
		};
		if (!options.stream) {
			if (options.io_server) this.io = options.io_server;
			else if (this.server && !options.startServer) this.io = sockets(this.server);
			else {
				app = express();
				this.server = http.Server(app);
				this.io = sockets(this.server);
				this.server.listen(this.port);
				app.get(this.connectionUrl, this.serverConnectionCallback);
			}
		}
		this._getREPL = () => {
			if (rp) return rp;
		};
		this._getSocket = () => {
			if (connectedSocket) return connectedSocket;
		};
		this._setSocket = (socket) => {
			connectedSocket = socket;
		};
		this._setREPL = function () {
			if (stream) {
				rp = REPL.start({
					prompt: (this.prompt) ? this.prompt + '> ' : '> ',
					input: stream,
					output: stream,
					replMode: (this.sloppyMode) ? REPL.REPL_MODE_SLOPPY : REPL.REPL_MODE_STRICT
				});
				rp.context = merge(rp.context, this.context);
			}
			this.active = true;
		};
		this._setStream = function (socket) {
			stream = new Stream();
			stream.readable = true;
			stream.write = (data) => {
				if (this.room) {
					if (this.namespace) this.namespaces[this.namespace].to(this.room).emit('stdout', data);
					else this.io.to(this.room).emit('stdout', data);
				}
				else {
					if (this.namespace) this.namespaces[this.namespace].emit('stdout', data);
					else this.io.emit('stdout', data);
				}
			};
			stream.resume = function () {};
			stream.pause = function () {};
			stream.destroy = function () {};
			stream.end = function () {};
			socket.on('stdin', function (data) {
				stream.emit('data', `${ data }\r\n`);
			});
			this.active = true;
		};
		this._getStream = function () {
			return stream;
		};
		return this;
	}
	start () {
		return new Promise((resolve, reject) => {
			if (this._getStream() && !this.child_process) {
				configureModules.call(this, null)
					.then(_this => {
						if (_this instanceof Error) reject(_this);
						else resolve(_this);
					});
			}
			else {
				if (typeof this.namespace === 'string') {
					this.namespaces[this.namespace] = this.io.of(`/${ this.namespace }`);
					this.namespaces[this.namespace].on('connection', socket => {
						if (this.room) socket.join(this.room);
						this._setSocket(socket);
						configureConnection.call(this, this._getSocket(), function (err, rp) {
							if (err) reject(err);
							else resolve(rp);
						});
					});
					this.namespaces[this.namespace].on('error', err => {
						if (this.errHandler && typeof this.errHandler === 'function') this.errHandler(err);
						else this.logger('Error with io connection', err);
					});
				}
				else {
					this.io.on('connection', socket => {
						if (this.room) socket.join(this.room);
						this._setSocket(socket);
						configureConnection.call(this, this._getSocket(), function (err, rp) {
							if (err) reject(err);
							else resolve(rp);
						});
					});
					this.io.on('error', e => {
						if (e) console.log('ERROR', e.stack);
					});
				}
			}
		});
	}
	disconnect () {
		this.logger('User Disconnected');
		let rp = this._getREPL();
		if (rp) {
			this._getStream().emit('data', '.exit\r\n');
		}
		return this.start();
	}
	extend (mod, cb) {
		if (typeof cb === 'function') {
			installModule.call(this, mod, cb);
		}
		else return Promisie.promisify(installModule, this)(mod);
	}
	define (options) {
		let rp = this._getREPL();
		try {
			rp.defineCommand(`#${ options.command }`, {
				help: options.help || `type #${ options.command }`,
				action: options.action
			});
		}
		catch (e) {
			console.log('Command could not be defined', e);
		}
		return this;
	}
};

module.exports = REPLIE;<commit_msg>auto restart added<commit_after>'use strict';
const child_process = require('child_process'),
	Promisie = require('promisie'),
	map = Promisie.promisify(require('async').mapLimit),
	http = require('http'),
	express = require('express'),
	merge = require('util-extend'),
	path = require('path'),
	fs = Promisie.promisifyAll(require('fs')),
	sockets = require('socket.io'),
	Stream = require('stream'),
	REPL = require('repl');

require('shelljs/global');

var install = function (cmd) {
	return new Promise((resolve, reject) => {
		child_process.exec(cmd, {
			cwd: (this && typeof this === 'object' && this.cwd) ? this.cwd : path.join(__dirname, '../')
		}, (err, stdout, stderr) => {
			if (stdout) resolve(stdout);
			else reject(err || stderr);
		});
	});
};

var installModule = function (mod, cb) {
	try {
		if (typeof mod === 'object') {
			if (mod.type === 'internal') {
				let filePath = path.join(__dirname, mod.name);
				fs.statAsync(filePath)
					.then(() => {
						this.context[path.basename(filePath, '.js')] = require(filePath);
						cb(null, `${ mod.name } installed`);
					}, () => {
						cb(null, 'ERROR: FP-001');
					});
			}
			else if (mod.type === 'external') {
				if (mod.name === 'shelljs') {
					this.context.exec = exec;
					cb(null, 'shelljs installed');
				}
				else {
					let cleanedName = (/.+\..+/g.test(mod.name)) ? mod.name.substring(mod.name.indexOf('.')) : mod.name;
					try {
						let install = require(mod.name);
						this.context[cleanedName] = install;
						cb(null, `${ mod.name } installed`);
					}
					catch (e) {
						try {
							var installString = 'npm i ' + mod.name.toLowerCase();
							install(installString)
								.then(() => {
									let installed = require(mod.name);
									this.context[mod.name] = installed;
									cb(null, `${ mod.name } installed`);
								});
						}
						catch (err) {
							cb(null, 'ERROR: MOD-001');
						}
					}
				}
			}
			else {
				cb(null, 'ERROR: FMT-002');
			}
		}
		else {
			cb(null, 'ERROR: FMT-001');
		}
	}
	catch (e) {
		console.log('ERR', e);
		cb(e);
	}
};

var configureModules = function (socket) {
	return map(this.modules, 5, installModule.bind(this))
		.then(results => {
			console.log('results', results);
			if (!socket || this._getStream()) this._setREPL();
			else {
				this._setStream(socket);
				this._setREPL();
			}
			return this;
		}, e => {
			console.log('ERROR', e.stack);
			return e;
		});
};

var configureConnection = function (socket, cb) {
	console.log('configureConnection');
	socket.on('disconnect', () => {
		this.disconnect()
			.then(() => {
				console.log('restarted');
			});
	});
	socket.on('end', () => {
		this.disconnect()
			.then(() => {
				console.log('restarted');
			});
	});
	socket.on('close', () => {
		this.disconnect()
			.then(() => {
				console.log('restarted');
			});
	});
	if (typeof this.replConnectionCallback === 'function') this.replConnectionCallback(socket);
	if (this.child_process || this.active) {
		this._setStream(socket);
		cb(null, this);
	}
	else {
		configureModules.call(this, socket)
			.then(_this => {
				if (_this instanceof Error) cb(_this);
				else cb(null, _this);
			});
	}
};

var REPLIE = class REPLIE {
	constructor (options) {
		let rp,
			stream = options.stream,
			app,
			connectedSocket;
		this.room = options.room;
		this.active = false;
		this.server = options.server;
		this.port = options.port || 5000;
		this.namespace = options.namespace;
		this.logger = options.logger || console.log;
		this.prompt = options.prompt;
		this.modules = options.modules || [];
		this.context = {};
		this.namespaces = {};
		this.sloppyMode = options.sloppyMode;
		this.errHandler = options.onError;
		this.child_process = options.child_process;
		this.connectionUrl = options.connectionUrl || '/';
		this.templatePath = options.templatePath || path.resolve(__dirname, '../views/example.html');
		this.connectionMessage = options.connectionMessage;
		this.replConnectionCallback = (typeof this.replConnectionCallback === 'function') ? this.replConnectionCallback : (socket) => {
			if (!this.room) {
				if (this.namespace) this.namespaces[this.namespace].emit('stdout', this.connectionMessage || 'Hello World');
				else this.io.emit('stdout', this.connectionMessage || 'Hello World');
			}
			else {
				if (this.namespace) this.namespaces[this.namespace].to(this.room).emit('stdout', this.connectionMessage || 'Hello World');
				else this.io.to(this.room).emit('stdout', this.connectionMessage || 'Hello World');
			}
		};
		this.serverConnectionCallback = (typeof options.serverConnectionCallback === 'function') ? options.serverConnectionCallback : (req, res) => {
			res.sendFile(this.templatePath);
		};
		if (!options.stream) {
			if (options.io_server) this.io = options.io_server;
			else if (this.server && !options.startServer) this.io = sockets(this.server);
			else {
				app = express();
				this.server = http.Server(app);
				this.io = sockets(this.server);
				this.server.listen(this.port);
				app.get(this.connectionUrl, this.serverConnectionCallback);
			}
		}
		this._getREPL = () => {
			if (rp) return rp;
		};
		this._getSocket = () => {
			if (connectedSocket) return connectedSocket;
		};
		this._setSocket = (socket) => {
			connectedSocket = socket;
		};
		this._setREPL = function () {
			if (stream) {
				rp = REPL.start({
					prompt: (this.prompt) ? this.prompt + '> ' : '> ',
					input: stream,
					output: stream,
					replMode: (this.sloppyMode) ? REPL.REPL_MODE_SLOPPY : REPL.REPL_MODE_STRICT
				});
				rp.context = merge(rp.context, this.context);
			}
			this.active = true;
		};
		this._setStream = function (socket) {
			stream = new Stream();
			stream.readable = true;
			stream.write = (data) => {
				if (this.room) {
					if (this.namespace) this.namespaces[this.namespace].to(this.room).emit('stdout', data);
					else this.io.to(this.room).emit('stdout', data);
				}
				else {
					if (this.namespace) this.namespaces[this.namespace].emit('stdout', data);
					else this.io.emit('stdout', data);
				}
			};
			stream.resume = function () {};
			stream.pause = function () {};
			stream.destroy = function () {};
			stream.end = function () {};
			socket.on('stdin', function (data) {
				stream.emit('data', `${ data }\r\n`);
			});
			this.active = true;
		};
		this._getStream = function () {
			return stream;
		};
		return this;
	}
	start () {
		return new Promise((resolve, reject) => {
			if (this._getStream() && !this.child_process) {
				configureModules.call(this, null)
					.then(_this => {
						if (_this instanceof Error) reject(_this);
						else resolve(_this);
					});
			}
			else {
				if (typeof this.namespace === 'string') {
					this.namespaces[this.namespace] = this.io.of(`/${ this.namespace }`);
					this.namespaces[this.namespace].on('connection', socket => {
						if (this.room) socket.join(this.room);
						this._setSocket(socket);
						configureConnection.call(this, this._getSocket(), function (err, rp) {
							if (err) reject(err);
							else resolve(rp);
						});
					});
					this.namespaces[this.namespace].on('error', err => {
						if (this.errHandler && typeof this.errHandler === 'function') this.errHandler(err);
						else this.logger('Error with io connection', err);
					});
				}
				else {
					this.io.on('connection', socket => {
						if (this.room) socket.join(this.room);
						this._setSocket(socket);
						configureConnection.call(this, this._getSocket(), function (err, rp) {
							if (err) reject(err);
							else resolve(rp);
						});
					});
					this.io.on('error', e => {
						if (e) console.log('ERROR', e.stack);
					});
				}
			}
		});
	}
	disconnect () {
		this.logger('User Disconnected');
		let rp = this._getREPL();
		if (rp) {
			this._getStream().emit('data', '.clear\r\n');
		}
		return this.start();
	}
	extend (mod, cb) {
		if (typeof cb === 'function') {
			installModule.call(this, mod, cb);
		}
		else return Promisie.promisify(installModule, this)(mod);
	}
	define (options) {
		let rp = this._getREPL();
		try {
			rp.defineCommand(`#${ options.command }`, {
				help: options.help || `type #${ options.command }`,
				action: options.action
			});
		}
		catch (e) {
			console.log('Command could not be defined', e);
		}
		return this;
	}
};

module.exports = REPLIE;<|endoftext|>