<commit_before>/**
 * Module dependencies.
 */
var express    = require('express');
var Check      = require('../../models/check');
var CheckEvent = require('../../models/checkEvent');

var app = module.exports = express.createServer();

// middleware

app.configure(function(){
  app.use(app.router);
  app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});

// up count
var upCount;
var refreshUpCount = function(callback) {
  var count = { up: 0, down: 0, paused: 0, total: 0 };
  Check.find({}).only(['isUp', 'isPaused']).each(function(err, check) {
    if (check) {
      count.total++;
      if (check.isPaused) {
        count.paused++;
      } else if (check.isUp) {
        count.up++;
      } else {
        count.down++;
      }
    } else {
      upCount = count;
      callback();
    }
  });
}

Check.on('postInsert', function() { upCount = undefined; });
Check.on('postRemove', function() { upCount = undefined; });
CheckEvent.on('postInsert', function() { upCount = undefined; });

app.get('/check/count', function(req, res) {
  if (upCount) {
    res.json(upCount);
  } else {
    refreshUpCount(function() {
      res.json(upCount);
    });
  }
});

// Routes

require('./routes/check')(app);
require('./routes/tag')(app);
require('./routes/ping')(app);

if (!module.parent) {
  app.listen(3000);
  console.log('Express started on port 3000');
}<commit_msg>Add api route list on root path ('/api/')<commit_after>/**
 * Module dependencies.
 */
var express    = require('express');
var Check      = require('../../models/check');
var CheckEvent = require('../../models/checkEvent');

var app = module.exports = express.createServer();

// middleware

app.configure(function(){
  app.use(app.router);
  app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});

// up count
var upCount;
var refreshUpCount = function(callback) {
  var count = { up: 0, down: 0, paused: 0, total: 0 };
  Check.find({}).only(['isUp', 'isPaused']).each(function(err, check) {
    if (check) {
      count.total++;
      if (check.isPaused) {
        count.paused++;
      } else if (check.isUp) {
        count.up++;
      } else {
        count.down++;
      }
    } else {
      upCount = count;
      callback();
    }
  });
}

Check.on('postInsert', function() { upCount = undefined; });
Check.on('postRemove', function() { upCount = undefined; });
CheckEvent.on('postInsert', function() { upCount = undefined; });

app.get('/check/count', function(req, res) {
  if (upCount) {
    res.json(upCount);
  } else {
    refreshUpCount(function() {
      res.json(upCount);
    });
  }
});

// Routes

require('./routes/check')(app);
require('./routes/tag')(app);
require('./routes/ping')(app);

// route list
app.get('/', function(req, res) {
  var routes = [];
  app.routes.all().forEach(function(route) {
    routes.push({method: route.method.toUpperCase() , path: app.route + route.path});
  });
  res.json(routes);
});

if (!module.parent) {
  app.listen(3000);
  console.log('Express started on port 3000');
}<|endoftext|>


<commit_before>/*
  Template Haskell communication

  reads messages from stdin, sends over stderr
  (Haskell stderr stream is redirected to stdout)

  messages are prefixed with the following data:
    - UInt32BE: message length
    - UInt32BE: message target:
                  0: control message from compiler to TH server
                  n: response to request n
*/

var h$THfs = require('fs');

require('jsdom-global')();

if(typeof __dirname == 'undefined') {
  // TODO work out the best shim to use here
  var __dirname = '/GHCJS_thrunner_dirname/';
}

// set this to true to record each message and the received JS code to a file
// you can then replay the TH session later with 'node thrunner.js replay'
var h$THRecord = // true ||
      !!process.env['GHCJS_RECORD_TH'];

var h$THReplay = process.argv.length > 0 && process.argv[process.argv.length-1] === 'replay';

var h$TH = { nWaiters: 0
           , waiters: {}
           , data: []
           , dataLen: 0
           , requestId: 1
           , loadedSymbol: null
           , sendRequest: h$sendRequest
           , awaitMessage: h$awaitMessage
           , sendMessage: h$sendMessage
           , loadCode: h$loadCode
           , loadCodeStr: h$loadCodeStr
           , bufSize: h$bufSize
           , getMemoryUsage: h$getMemoryUsage
           };

global.h$TH = h$TH;
global.require = require;
global.module = module;

// start listening
function h$initTH() {
    process.stdin.setEncoding('utf8');
    process.stderr.setEncoding('binary');
    process.on('uncaughtException', function(err) { console.log(err); });
    h$awaitMessageRaw(0, h$loadInitialCode);
    var leftover = null;
    process.stdin.on('readable', function() {
        while(true) {
            var str = process.stdin.read();
            if(str) {
                // save incomplete hex pair if needed
                str = str.toString();
                if(leftover) str = leftover + str;
                str = str.replace(/\s/gm, '');
                if(str.length % 2) {
                  leftover = str.slice(str.length-1);
                  str = str.slice(0,str.length-1);
                } else {
                  leftover = null;
                }
                var buf = Buffer.from(str, 'hex');

                // make sure the first 8 bytes into data[0]
                // otherwise delay copying the buffers until a complete message
                // has been received
                if(h$TH.data.length < 1 || h$TH.data[0].length >= 8) {
                  h$TH.data.push(buf);
                } else {
                  h$TH.data[0] = Buffer.concat([h$TH.data[0], buf]);
                }
                h$TH.dataLen += buf.length;
                h$processQueue();
            } else {
                return;
            }
        }
    });
    process.stdin.on('close', function() { process.exit(0); });
}

function h$getMemoryUsage() {
  var m = process.memoryUsage();
  // return m.rss;
  return (m.heapTotal + m.external)|0;
}

var h$THMessageN = 0;
function h$processQueue() {
    while(h$TH.nWaiters > 0 && h$TH.data && h$TH.dataLen >= 8) {
        // if we have at least 8 bytes, they are all in data[0]
        var msgLength = h$TH.data[0].readUInt32BE(0);
        var msgTarget = h$TH.data[0].readUInt32BE(4);
        var msgBytes  = msgLength + 8;
        if(h$TH.dataLen >= msgBytes && h$TH.waiters[msgTarget]) {
            var bb         = Buffer.concat(h$TH.data);
            var w          = h$TH.waiters[msgTarget]
            var msgPayload = bb.slice(8, msgBytes);

            h$TH.data = [bb.slice(msgBytes)];
            h$TH.dataLen -= msgBytes;
            delete h$TH.waiters[msgTarget];
            h$TH.nWaiters--;
            if(h$THRecord && !h$THReplay)
                h$THfs.writeFileSync("thmessage." + (++h$THMessageN) + ".dat", msgPayload);
            w(msgPayload);
        } else {
            return;
        }
    }
}

function h$sendRequest(bs, offset, len, c) {
    var req = h$TH.requestId++;
    h$sendMessage(bs, offset, len, req, function() {});
    h$awaitMessage(req, c);
}

function h$sendMessage(bs, offset, len, req, c) {
    var msg = len === -1 ? Buffer.from(bs.u8.subarray(offset))
                         : Buffer.from(bs.u8.subarray(offset, len));
    var hdr = Buffer.alloc(8);
    hdr.writeUInt32BE(msg.length, 0);
    hdr.writeUInt32BE(req, 4);
    process.stderr.write(Buffer.concat([hdr, msg]), 'binary', function() { c(); });
}

function h$awaitMessage(req, c) {
    h$awaitMessageRaw(req, function(buf) {
        c(h$THWrapBuffer(h$BufferToArrayBuffer(buf),false),0);
    });
}

var h$THReplayMessageN = 0;
function h$awaitMessageRaw(req, c) {
    if(h$TH.waiters[req]) throw ("h$awaitMessage: already waiting for " + req);
    if(h$THReplay) {
        try {
            c(h$THfs.readFileSync('thmessage.' + (++h$THReplayMessageN) + '.dat'));
            return;
        } catch(e) { }
    }
    h$TH.nWaiters++;
    h$TH.waiters[req] = c;
    h$processQueue();
}

function h$bufSize(buf, buf_offset) {
    if(buf === null) return 0;
    return buf.len;
}

// load the RTS and start the server
function h$loadInitialCode(buf) {
    var code = buf.toString('utf8');
    h$loadCodeStr(code, true);
    // don't allow Haskell to read from stdin
    h$base_stdin_fd.read = function(fd, fdo, buf, buf_offset, n, c) { c(0); }
    // redirect Haskell's stderr to stdout since we use stderr to communicate
    h$base_stderr_fd.write = h$base_stdout_fd.write;
    h$main(h$ghcjszmthZCGHCJSziPrimziTHziEvalzirunTHServer);

}

var h$THCodeN = 0;
function h$loadCodeStr(str, isFirst) {
    if(h$THReplay) {
        try {
            str = h$THfs.readFileSync("thcode." + (++h$THCodeN) + ".js").toString('utf8');
        } catch(e) { }
    } else if(h$THRecord) {
        h$THfs.writeFileSync("thcode." + (++h$THCodeN) + ".js", str);
    }
    eval.call(null, str);
}

// load additional code and run the initializers for it, the code should
// assign the h$TH.loadedSymbol variable
function h$loadCode(buf, off, len) {
    h$TH.loadedSymbol = null;
    var str = Buffer.from(buf.u8).toString('utf8',off, off+len);
    h$TH.loadCodeStr(str, false);
    // h$runInitStatic();
    if(h$TH.loadedSymbol === null) throw "h$loadCode: error loading code"
    return h$TH.loadedSymbol;
}

function h$BufferToArrayBuffer(buf) {
    if(buf.toArrayBuffer) return buf.toArrayBuffer();
    return new Uint8Array(buf).buffer;
}

// copied from src/mem.js
function h$THWrapBuffer(buf, unalignedOk, offset, length) {
    if(!unalignedOk && offset && offset % 8 !== 0) {
        throw ("h$THWrapBuffer: offset not aligned:" + offset);
    }
    if(!buf || !(buf instanceof ArrayBuffer))
        throw "h$THWrapBuffer: not an ArrayBuffer"
    if(!offset) { offset = 0; }
    if(!length || length < 0) { length = buf.byteLength - offset; }
    // console.log("wrapping buf: " + length + " " + offset);
    return { buf: buf
             , len: length
             , i3: (offset%4) ? null : new Int32Array(buf, offset, length >> 2)
             , u8: new Uint8Array(buf, offset, length)
             , u1: (offset%2) ? null : new Uint16Array(buf, offset, length >> 1)
             , f3: (offset%4) ? null : new Float32Array(buf, offset, length >> 2)
             , f6: (offset%8) ? null : new Float64Array(buf, offset, length >> 3)
             , dv: new DataView(buf, offset, length)
           };
}
h$initTH();
<commit_msg>Fix __dirname shim<commit_after>/*
  Template Haskell communication

  reads messages from stdin, sends over stderr
  (Haskell stderr stream is redirected to stdout)

  messages are prefixed with the following data:
    - UInt32BE: message length
    - UInt32BE: message target:
                  0: control message from compiler to TH server
                  n: response to request n
*/

var h$THfs = require('fs');

require('jsdom-global')();

if(typeof __dirname == 'undefined') {
  // TODO work out the best shim to use here
  var __dirname = '/GHCJS_thrunner_dirname/';
}

// set this to true to record each message and the received JS code to a file
// you can then replay the TH session later with 'node thrunner.js replay'
var h$THRecord = // true ||
      !!process.env['GHCJS_RECORD_TH'];

var h$THReplay = process.argv.length > 0 && process.argv[process.argv.length-1] === 'replay';

var h$TH = { nWaiters: 0
           , waiters: {}
           , data: []
           , dataLen: 0
           , requestId: 1
           , loadedSymbol: null
           , sendRequest: h$sendRequest
           , awaitMessage: h$awaitMessage
           , sendMessage: h$sendMessage
           , loadCode: h$loadCode
           , loadCodeStr: h$loadCodeStr
           , bufSize: h$bufSize
           , getMemoryUsage: h$getMemoryUsage
           };

global.h$TH = h$TH;
global.require = require;
global.module = module;
global.__dirname = __dirname;

// start listening
function h$initTH() {
    process.stdin.setEncoding('utf8');
    process.stderr.setEncoding('binary');
    process.on('uncaughtException', function(err) { console.log(err); });
    h$awaitMessageRaw(0, h$loadInitialCode);
    var leftover = null;
    process.stdin.on('readable', function() {
        while(true) {
            var str = process.stdin.read();
            if(str) {
                // save incomplete hex pair if needed
                str = str.toString();
                if(leftover) str = leftover + str;
                str = str.replace(/\s/gm, '');
                if(str.length % 2) {
                  leftover = str.slice(str.length-1);
                  str = str.slice(0,str.length-1);
                } else {
                  leftover = null;
                }
                var buf = Buffer.from(str, 'hex');

                // make sure the first 8 bytes into data[0]
                // otherwise delay copying the buffers until a complete message
                // has been received
                if(h$TH.data.length < 1 || h$TH.data[0].length >= 8) {
                  h$TH.data.push(buf);
                } else {
                  h$TH.data[0] = Buffer.concat([h$TH.data[0], buf]);
                }
                h$TH.dataLen += buf.length;
                h$processQueue();
            } else {
                return;
            }
        }
    });
    process.stdin.on('close', function() { process.exit(0); });
}

function h$getMemoryUsage() {
  var m = process.memoryUsage();
  // return m.rss;
  return (m.heapTotal + m.external)|0;
}

var h$THMessageN = 0;
function h$processQueue() {
    while(h$TH.nWaiters > 0 && h$TH.data && h$TH.dataLen >= 8) {
        // if we have at least 8 bytes, they are all in data[0]
        var msgLength = h$TH.data[0].readUInt32BE(0);
        var msgTarget = h$TH.data[0].readUInt32BE(4);
        var msgBytes  = msgLength + 8;
        if(h$TH.dataLen >= msgBytes && h$TH.waiters[msgTarget]) {
            var bb         = Buffer.concat(h$TH.data);
            var w          = h$TH.waiters[msgTarget]
            var msgPayload = bb.slice(8, msgBytes);

            h$TH.data = [bb.slice(msgBytes)];
            h$TH.dataLen -= msgBytes;
            delete h$TH.waiters[msgTarget];
            h$TH.nWaiters--;
            if(h$THRecord && !h$THReplay)
                h$THfs.writeFileSync("thmessage." + (++h$THMessageN) + ".dat", msgPayload);
            w(msgPayload);
        } else {
            return;
        }
    }
}

function h$sendRequest(bs, offset, len, c) {
    var req = h$TH.requestId++;
    h$sendMessage(bs, offset, len, req, function() {});
    h$awaitMessage(req, c);
}

function h$sendMessage(bs, offset, len, req, c) {
    var msg = len === -1 ? Buffer.from(bs.u8.subarray(offset))
                         : Buffer.from(bs.u8.subarray(offset, len));
    var hdr = Buffer.alloc(8);
    hdr.writeUInt32BE(msg.length, 0);
    hdr.writeUInt32BE(req, 4);
    process.stderr.write(Buffer.concat([hdr, msg]), 'binary', function() { c(); });
}

function h$awaitMessage(req, c) {
    h$awaitMessageRaw(req, function(buf) {
        c(h$THWrapBuffer(h$BufferToArrayBuffer(buf),false),0);
    });
}

var h$THReplayMessageN = 0;
function h$awaitMessageRaw(req, c) {
    if(h$TH.waiters[req]) throw ("h$awaitMessage: already waiting for " + req);
    if(h$THReplay) {
        try {
            c(h$THfs.readFileSync('thmessage.' + (++h$THReplayMessageN) + '.dat'));
            return;
        } catch(e) { }
    }
    h$TH.nWaiters++;
    h$TH.waiters[req] = c;
    h$processQueue();
}

function h$bufSize(buf, buf_offset) {
    if(buf === null) return 0;
    return buf.len;
}

// load the RTS and start the server
function h$loadInitialCode(buf) {
    var code = buf.toString('utf8');
    h$loadCodeStr(code, true);
    // don't allow Haskell to read from stdin
    h$base_stdin_fd.read = function(fd, fdo, buf, buf_offset, n, c) { c(0); }
    // redirect Haskell's stderr to stdout since we use stderr to communicate
    h$base_stderr_fd.write = h$base_stdout_fd.write;
    h$main(h$ghcjszmthZCGHCJSziPrimziTHziEvalzirunTHServer);

}

var h$THCodeN = 0;
function h$loadCodeStr(str, isFirst) {
    if(h$THReplay) {
        try {
            str = h$THfs.readFileSync("thcode." + (++h$THCodeN) + ".js").toString('utf8');
        } catch(e) { }
    } else if(h$THRecord) {
        h$THfs.writeFileSync("thcode." + (++h$THCodeN) + ".js", str);
    }
    eval.call(null, str);
}

// load additional code and run the initializers for it, the code should
// assign the h$TH.loadedSymbol variable
function h$loadCode(buf, off, len) {
    h$TH.loadedSymbol = null;
    var str = Buffer.from(buf.u8).toString('utf8',off, off+len);
    h$TH.loadCodeStr(str, false);
    // h$runInitStatic();
    if(h$TH.loadedSymbol === null) throw "h$loadCode: error loading code"
    return h$TH.loadedSymbol;
}

function h$BufferToArrayBuffer(buf) {
    if(buf.toArrayBuffer) return buf.toArrayBuffer();
    return new Uint8Array(buf).buffer;
}

// copied from src/mem.js
function h$THWrapBuffer(buf, unalignedOk, offset, length) {
    if(!unalignedOk && offset && offset % 8 !== 0) {
        throw ("h$THWrapBuffer: offset not aligned:" + offset);
    }
    if(!buf || !(buf instanceof ArrayBuffer))
        throw "h$THWrapBuffer: not an ArrayBuffer"
    if(!offset) { offset = 0; }
    if(!length || length < 0) { length = buf.byteLength - offset; }
    // console.log("wrapping buf: " + length + " " + offset);
    return { buf: buf
             , len: length
             , i3: (offset%4) ? null : new Int32Array(buf, offset, length >> 2)
             , u8: new Uint8Array(buf, offset, length)
             , u1: (offset%2) ? null : new Uint16Array(buf, offset, length >> 1)
             , f3: (offset%4) ? null : new Float32Array(buf, offset, length >> 2)
             , f6: (offset%8) ? null : new Float64Array(buf, offset, length >> 3)
             , dv: new DataView(buf, offset, length)
           };
}
h$initTH();
<|endoftext|>


<commit_before>"use strict";

/**
 * Load required modules
 */
var	express = require('express'),
	bodyParser = require('body-parser'),
	cookieParser = require('cookie-parser'),
	expressSession = require('express-session'),
	path = require('path'),
	moment = require('moment'),
	events = require('events'),
	passport = require('passport'),
	LocalStrategy = require('passport-local').Strategy,
	bunyan = require('bunyan');

/**
 * Linz constructor
 */
function Linz () {

	// internal properties
	this.settings = {};
	this.loggers = {};

}

/**
 * Expose Linz
 */
var linz = module.exports = exports = new Linz;

/**
 * Define local variables used by the Linz class
 */
var	routesManager = require('./lib/router'),
	passportHelpers = require('./lib/helpers-passport'),
	helpersModels = require('./lib/helpers-models'),
	debugModels = require('debug')('linz:models'),
	debugGeneral = require('debug')('linz:general'),
	debugSet = require('debug')('linz:set'),
	error = require('./lib/errors');

/**
 * Expose linz modules
 */
linz.formtools = require('./lib/formtools');
linz.middleware = require('./middleware-public')

/**
 * Linz inherits from EventEmitter for Linz.prototype.on('event') handling
 *
 */
 Linz.prototype.__proto__ = events.EventEmitter.prototype;

/**
 * Initialize linz with the express app
 * signature: app, mongoose, options
 *
 */
Linz.prototype.init = function () {

	var _app,
		_mongoose,
		_options;

	// loop through the arguments, and determine what is what
	for (var i = 0; i < arguments.length; i++) {

		var arg = arguments[i];

		if (arg.constructor.name === 'Mongoose') {
			_mongoose = arg;
		} else if (arg.constructor.name === 'Function' && typeof arg === 'function') {
			_app = arg;
		} else  if (arg.constructor.name === 'Object' && typeof arg === 'object') {
			_options = arg;
		}

	}

	// use anything that is passed in
	_app = _app || express();
	_mongoose = _mongoose || require('mongoose');
	_options = _options || {};

	// reference required properties
	this.app = _app;
	this.mongoose = _mongoose;

	// apply default linz options
	this.options(require('./lib/defaults'));

	// overlay runtime options, these will override linz defaults
	this.options(_options);

	this.on('admin path', function () {

		this.app.locals['linzNavigation'] = [
			{
				name: 'Models',
				href: this.get('admin path') + '/models/list'
			},
			{
				name: 'Logs',
				href: this.get('admin path') + '/logs/request/list'
			},
			{
				name: 'Logout',
				href: this.get('admin path') + '/logout'
			}
		];

	});

	this.configure();

	return this;

};

/**
* Initialize the application
*
* @api private
*/

Linz.prototype.configure = function() {

	this.defaultConfiguration();
	this.bootstrapExpress();
	this.mountAdmin();
	this.loadModels();
	this.bootstrapExpressLocals();
	this.checkSetup();

	// expose app
	this.set('app', this.app);

	// check for either a connect(ed|ing) mongoose object, or mongoose URI
	if ([1,2].indexOf(this.mongoose.connection.readyState) < 0) {

		if (!this.get('mongo')) {
			throw new Error('You must either supply a connected mongoose object, or a mongo URI');
		}

		this.mongoose.connect(this.get('mongo'));

	}

};

/**
* Search and look for the models folder, then go ahead and load them
*
* @return void
*/
Linz.prototype.loadModels = function () {

	// set the default models path
	this.set('models path', path.resolve(this.get('cwd'), 'models'), false);

	var modelsPath = this.get('models path');

	try {
		this.set('models', helpersModels.loadModels(modelsPath));
		debugModels('Loaded models from directory, %s', modelsPath);
	} catch (e) {
		debugModels('Error when loading models from directory, %s (%s)', modelsPath, e.toString());
	}

};

/**
* Setup the default configuration for Linz
*
* @return void
*/
Linz.prototype.defaultConfiguration = function () {

	var _this = this;

	debugGeneral('Setting up the default configuration');

	// setup the default admin path, unless already defined
	this.set('admin path', '/admin', false);

	this.set('admin title', 'Linz', false);

	// setup the router
	this.router = routesManager.getRouter();

	// assign the admin routes
	routesManager.setupAdminRoutes();

	// assign the model CRUD routes
	routesManager.setupModelRoutes(this.models);

	// assign the logging routes
	if (this.get('request logging') === true) routesManager.setupLoggingRoutes();

	// store the cwd
	this.set('cwd', process.cwd());

	// place holder for the models, which get loaded in next
	this.set('models', []);

};

Linz.prototype.mountAdmin = function () {

	debugGeneral('Mounting Linz on ' + this.get('admin path'));
	this.app.use(this.get('admin path'), this.router);
};

/**
* We need to setup the host express app with a few bits and pieces
*
* @api private
*/
Linz.prototype.bootstrapExpress = function () {

	// only run once
	if (this.bBootstrapExpress) return;
	if (!this.bBootstrapExpress) this.bBootstrapExpress = true;

	debugGeneral('Bootstrapping express');

	this.app.engine('jade', require('jade').__express);
	this.app.set('view engine', 'jade');

	// setup body-parser, and cookie-parser
	this.app.use(bodyParser());
	this.app.use(cookieParser());

	// need to hook session in here as it must be before passport.initialize
	if (typeof this.get('session') === 'function') {
		this.app.use(this.get('session'));
	} else {
		this.app.use(expressSession({ secret: 'linzcookiesecret' }));
	}

	// initialize passport
	this.app.use(this.get('admin path'), passport.initialize());
	this.app.use(this.get('admin path'), passport.session());

	// setup stylus for admin css
	this.app.use(this.get('admin path') + '/public/', require('stylus').middleware(path.resolve(__dirname, 'public')));

	// setup admin static routes
	this.app.use(this.get('admin path') + '/public/', express.static(path.resolve(__dirname, 'public')));

	// setup passport for authentication
	passport.use('linz-local', passportHelpers.login);

	// add serialize and deserialize functionality
	passportHelpers.setupPassport(passport);

};

/**
* Setup express locals for admin template generation
*
* @api private
*/
Linz.prototype.bootstrapExpressLocals = function () {

	// expose our settings to the rendering engine
	this.app.locals['linz'] = this;

	// expose the linz admin navigation
	this.app.locals['linzNavigation'] = this.buildNavigation();

	this.app.locals['adminPath'] = this.get('admin path');

	this.app.locals['adminTitle'] = this.get('admin title');

};

Linz.prototype.options = function (opts) {

	var _this = this,
		opts = opts || {};

	for (var opt in opts) {
		_this.set(opt, opts[opt]);
	}

};

/**
* Set a value or setting on Linz
*
* @return Linz for chaining
*/

Linz.prototype.set = function (setting, val, override) {

	if (arguments.length === 1) {
		return this.settings[setting];
	}

	// can only set the following values once
	var onceOnly = ['admin path', 'models path', 'admin title'];

	if (onceOnly.indexOf(setting) >= 0 && this.settings[setting] !== undefined) {
		return debugSet('You can only set \'' + setting + '\' once. Ignoring set this time.');
	}

	// defaults to true
	override = !(override === false);

	// override unless previously set
	if (override || override === false && this.settings[setting] === undefined) {
		debugSet('Setting ' + setting + ' to ' + val);
		this.settings[setting] = val;
		this.emit(setting, val);
	}

	return this;

};

/**
* Get a value or setting on Linz
*
* @return setting value
*/

Linz.prototype.get = function (setting) {
	return this.settings[setting];
};

/*
* Set a settings value to true
* synonym for admin.set('setting', true);
* @return Linz for chaining
*/

Linz.prototype.enable = function (setting) {
	this.set(setting, true);
	return this;
};

/*
* Set a settings value to false
* synonym for admin.set('setting', false);
* @return Linz for chaining
*/
Linz.prototype.disable = function (setting) {
	this.set(setting, false);
	return this;
};

/*
* Return the linz navigation structure
*
* @api private
*/
Linz.prototype.buildNavigation = function () {

	var nav = [],
		_this = this,
		linzModels = this.get('models');

	// add a reference for all of the models
	var models = {
		name: 'Models',
		href: this.get('admin path') + '/models/list',
		children: [
			{
				'name': 'All',
				href: this.get('admin path') + '/models/list'
			}
		]
	};

	// add each model to the navigation tree
	Object.keys(linzModels).forEach(function (model) {

		models.children.push({
			name: linzModels[model].label,
			href: _this.get('admin path') + '/model/' + model + '/list'
		});

	});
	nav.push(models);

	// add a reference for the logs
	var logs = {
		name: 'Logs',
		href: this.get('admin path') + '/logs/request/list'
	};
	nav.push(logs);

	return nav;

}

/**
 * Check the setup of linz and make sure we've got everything we require
 * @return {[type]} [description]
 */
Linz.prototype.checkSetup = function() {

	if (this.get('user model') === undefined) {
		error.log('You must define a user model');
	}

};

/**
* Create a logger which you can use in your applications.
* Linz uses bunyan internally and exposes this method to easily create logs within your application.
*
* @param {String|Object} options
* @return an instance of the logger
* @api public
*/
Linz.prototype.logger = function (options) {

	// user can pass either a String or an Object
	if (typeof options === 'string') options = {name: options};

	// The name parameter must exist
	if (!options.name) throw new Error('You must pass the name parameter when creating a logger.');

	// If we haven't already created a logger, create one now, transparently passing the options
	if (!this.loggers[options.name]) {
		this.loggers[options.name] = bunyan.createLogger(options);
	}

	return this.loggers[options.name];

};
<commit_msg>Added some extra debug output, and now using 'session middleware' as a key, rather than 'session'.<commit_after>"use strict";

/**
 * Load required modules
 */
var	express = require('express'),
	bodyParser = require('body-parser'),
	cookieParser = require('cookie-parser'),
	expressSession = require('express-session'),
	path = require('path'),
	moment = require('moment'),
	events = require('events'),
	passport = require('passport'),
	LocalStrategy = require('passport-local').Strategy,
	bunyan = require('bunyan');

/**
 * Linz constructor
 */
function Linz () {

	// internal properties
	this.settings = {};
	this.loggers = {};

}

/**
 * Expose Linz
 */
var linz = module.exports = exports = new Linz;

/**
 * Define local variables used by the Linz class
 */
var	routesManager = require('./lib/router'),
	passportHelpers = require('./lib/helpers-passport'),
	helpersModels = require('./lib/helpers-models'),
	debugModels = require('debug')('linz:models'),
	debugGeneral = require('debug')('linz:general'),
	debugSet = require('debug')('linz:set'),
	error = require('./lib/errors');

/**
 * Expose linz modules
 */
linz.formtools = require('./lib/formtools');
linz.middleware = require('./middleware-public')

/**
 * Linz inherits from EventEmitter for Linz.prototype.on('event') handling
 *
 */
 Linz.prototype.__proto__ = events.EventEmitter.prototype;

/**
 * Initialize linz with the express app
 * signature: app, mongoose, options
 *
 */
Linz.prototype.init = function () {

	var _app,
		_mongoose,
		_options;

	// loop through the arguments, and determine what is what
	for (var i = 0; i < arguments.length; i++) {

		var arg = arguments[i];

		if (arg.constructor.name === 'Mongoose') {
            debugGeneral('Using passed in mongoose object');
			_mongoose = arg;
		} else if (arg.constructor.name === 'Function' && typeof arg === 'function') {
            debugGeneral('Using passed in express app');
			_app = arg;
		} else  if (arg.constructor.name === 'Object' && typeof arg === 'object') {
            debugGeneral('Found options configuration object');
			_options = arg;
		}

	}

	// use anything that is passed in
	_app = _app || express();
	_mongoose = _mongoose || require('mongoose');
	_options = _options || {};

	// reference required properties
	this.app = _app;
	this.mongoose = _mongoose;

	// apply default linz options
	this.options(require('./lib/defaults'));

	// overlay runtime options, these will override linz defaults
	this.options(_options);

	this.on('admin path', function () {

		this.app.locals['linzNavigation'] = [
			{
				name: 'Models',
				href: this.get('admin path') + '/models/list'
			},
			{
				name: 'Logs',
				href: this.get('admin path') + '/logs/request/list'
			},
			{
				name: 'Logout',
				href: this.get('admin path') + '/logout'
			}
		];

	});

	this.configure();

	return this;

};

/**
* Initialize the application
*
* @api private
*/

Linz.prototype.configure = function() {

	this.defaultConfiguration();
	this.bootstrapExpress();
	this.mountAdmin();
	this.loadModels();
	this.bootstrapExpressLocals();
	this.checkSetup();

	// expose app
	this.set('app', this.app);

	// check for either a connect(ed|ing) mongoose object, or mongoose URI
	if ([1,2].indexOf(this.mongoose.connection.readyState) < 0) {

		if (!this.get('mongo')) {
			throw new Error('You must either supply a connected mongoose object, or a mongo URI');
		}

		this.mongoose.connect(this.get('mongo'));

	}

};

/**
* Search and look for the models folder, then go ahead and load them
*
* @return void
*/
Linz.prototype.loadModels = function () {

	// set the default models path
	this.set('models path', path.resolve(this.get('cwd'), 'models'), false);

	var modelsPath = this.get('models path');

	try {
		this.set('models', helpersModels.loadModels(modelsPath));
		debugModels('Loaded models from directory, %s', modelsPath);
	} catch (e) {
		debugModels('Error when loading models from directory, %s (%s)', modelsPath, e.toString());
	}

};

/**
* Setup the default configuration for Linz
*
* @return void
*/
Linz.prototype.defaultConfiguration = function () {

	var _this = this;

	debugGeneral('Setting up the default configuration');

	// setup the default admin path, unless already defined
	this.set('admin path', '/admin', false);

	this.set('admin title', 'Linz', false);

	// setup the router
	this.router = routesManager.getRouter();

	// assign the admin routes
	routesManager.setupAdminRoutes();

	// assign the model CRUD routes
	routesManager.setupModelRoutes(this.models);

	// assign the logging routes
	if (this.get('request logging') === true) routesManager.setupLoggingRoutes();

	// store the cwd
	this.set('cwd', process.cwd());

	// place holder for the models, which get loaded in next
	this.set('models', []);

};

Linz.prototype.mountAdmin = function () {

	debugGeneral('Mounting Linz on ' + this.get('admin path'));
	this.app.use(this.get('admin path'), this.router);
};

/**
* We need to setup the host express app with a few bits and pieces
*
* @api private
*/
Linz.prototype.bootstrapExpress = function () {

	// only run once
	if (this.bBootstrapExpress) return;
	if (!this.bBootstrapExpress) this.bBootstrapExpress = true;

	debugGeneral('Bootstrapping express');

	this.app.engine('jade', require('jade').__express);
	this.app.set('view engine', 'jade');

	// setup body-parser, and cookie-parser
	this.app.use(bodyParser());
	this.app.use(cookieParser());

	// need to hook session in here as it must be before passport.initialize
	if (typeof this.get('session middleware') === 'function') {
		this.app.use(this.get('session middleware'));
	} else {
		this.app.use(expressSession({ secret: 'linzcookiesecret' }));
	}

	// initialize passport
	this.app.use(this.get('admin path'), passport.initialize());
	this.app.use(this.get('admin path'), passport.session());

	// setup stylus for admin css
	this.app.use(this.get('admin path') + '/public/', require('stylus').middleware(path.resolve(__dirname, 'public')));

	// setup admin static routes
	this.app.use(this.get('admin path') + '/public/', express.static(path.resolve(__dirname, 'public')));

	// setup passport for authentication
	passport.use('linz-local', passportHelpers.login);

	// add serialize and deserialize functionality
	passportHelpers.setupPassport(passport);

};

/**
* Setup express locals for admin template generation
*
* @api private
*/
Linz.prototype.bootstrapExpressLocals = function () {

	// expose our settings to the rendering engine
	this.app.locals['linz'] = this;

	// expose the linz admin navigation
	this.app.locals['linzNavigation'] = this.buildNavigation();

	this.app.locals['adminPath'] = this.get('admin path');

	this.app.locals['adminTitle'] = this.get('admin title');

};

Linz.prototype.options = function (opts) {

	var _this = this,
		opts = opts || {};

	for (var opt in opts) {
		_this.set(opt, opts[opt]);
	}

};

/**
* Set a value or setting on Linz
*
* @return Linz for chaining
*/

Linz.prototype.set = function (setting, val, override) {

	if (arguments.length === 1) {
		return this.settings[setting];
	}

	// can only set the following values once
	var onceOnly = ['admin path', 'models path', 'admin title'];

	if (onceOnly.indexOf(setting) >= 0 && this.settings[setting] !== undefined) {
		return debugSet('You can only set \'' + setting + '\' once. Ignoring set this time.');
	}

	// defaults to true
	override = !(override === false);

	// override unless previously set
	if (override || override === false && this.settings[setting] === undefined) {
		debugSet('Setting ' + setting + ' to ' + val);
		this.settings[setting] = val;
		this.emit(setting, val);
	}

	return this;

};

/**
* Get a value or setting on Linz
*
* @return setting value
*/

Linz.prototype.get = function (setting) {
	return this.settings[setting];
};

/*
* Set a settings value to true
* synonym for admin.set('setting', true);
* @return Linz for chaining
*/

Linz.prototype.enable = function (setting) {
	this.set(setting, true);
	return this;
};

/*
* Set a settings value to false
* synonym for admin.set('setting', false);
* @return Linz for chaining
*/
Linz.prototype.disable = function (setting) {
	this.set(setting, false);
	return this;
};

/*
* Return the linz navigation structure
*
* @api private
*/
Linz.prototype.buildNavigation = function () {

	var nav = [],
		_this = this,
		linzModels = this.get('models');

	// add a reference for all of the models
	var models = {
		name: 'Models',
		href: this.get('admin path') + '/models/list',
		children: [
			{
				'name': 'All',
				href: this.get('admin path') + '/models/list'
			}
		]
	};

	// add each model to the navigation tree
	Object.keys(linzModels).forEach(function (model) {

		models.children.push({
			name: linzModels[model].label,
			href: _this.get('admin path') + '/model/' + model + '/list'
		});

	});
	nav.push(models);

	// add a reference for the logs
	var logs = {
		name: 'Logs',
		href: this.get('admin path') + '/logs/request/list'
	};
	nav.push(logs);

	return nav;

}

/**
 * Check the setup of linz and make sure we've got everything we require
 * @return {[type]} [description]
 */
Linz.prototype.checkSetup = function() {

	if (this.get('user model') === undefined) {
		error.log('You must define a user model');
	}

};

/**
* Create a logger which you can use in your applications.
* Linz uses bunyan internally and exposes this method to easily create logs within your application.
*
* @param {String|Object} options
* @return an instance of the logger
* @api public
*/
Linz.prototype.logger = function (options) {

	// user can pass either a String or an Object
	if (typeof options === 'string') options = {name: options};

	// The name parameter must exist
	if (!options.name) throw new Error('You must pass the name parameter when creating a logger.');

	// If we haven't already created a logger, create one now, transparently passing the options
	if (!this.loggers[options.name]) {
		this.loggers[options.name] = bunyan.createLogger(options);
	}

	return this.loggers[options.name];

};
<|endoftext|>


<commit_before>const net = require('net');
const port = process.env.PORT ? (process.env.PORT - 100) : 3000;

process.env.ELECTRON_START_URL = `http://localhost:${port}`;

const client = new net.Socket();

let startedElectron = false;
const tryConnection = () => client.connect({port: port}, () => {
        client.end();
        if(!startedElectron) {
            console.log('starting electron');
            startedElectron = true;
            const exec = require('child_process').exec;
            exec('npm run electron');
        }
    }
);

tryConnection();

client.on('error', (error) => {
    setTimeout(tryConnection, 1000);
});

<commit_msg>display child process logs in main console<commit_after>const net = require('net');
const port = process.env.PORT ? (process.env.PORT - 100) : 3000;

process.env.ELECTRON_START_URL = `http://localhost:${port}`;

const client = new net.Socket();

let startedElectron = false;
const tryConnection = () => client.connect({port: port}, () => {
        client.end();
        if(!startedElectron) {
            console.log('starting electron');
            startedElectron = true;
            const exec = require('child_process').exec;
            const electron = exec('npm run electron');
            electron.stdout.on("data", function(data) {
                console.log("stdout: " + data.toString());
            });
        }
    }
);

tryConnection();

client.on('error', (error) => {
    setTimeout(tryConnection, 1000);
});

<|endoftext|>


<commit_before>/**
 * Created by yangm11 on 7/20/2017.
 */
'use strict';

const fs = require('fs');
const readline = require('readline');
const splitLine = require('../string/splitLine');

function csv2json(path, cb, n) {
  let start = Date.now();

  let p = new Promise((resolve, reject) => {
    let types = {};
    let headers = '';
    let rl = readline.createInterface({
      input: fs.createReadStream(path, 'utf8')
    });

    let tmp = [];
    let count = 0;

    let num = n ? n : 51;

    let json = fs.createWriteStream(path + '.json', {
      flag: 'w+',
      defaultEncoding: 'utf8'
    });
    json.write('[\n');

    rl.on('line', function (line) {
      if (line.length && line[0] !== '#') {
        if (!headers) {
          headers = splitLine(line);
          headers = map(headers, d => {
            return d.replace(/ /g, '_'); // this is to make the name can be used in solr functions like "unique(name_a)"
          });
          // console.log(headers);

          for (let i = 0; i < headers.length; i++) {
            types[headers[i]] = [];
          }

        } else {
          let cur = splitLine(line);

          if (cur.length === headers.length) {
            let obj = {};
            for (let i = 0; i < headers.length; i++) {
              if (cur[i]) {
                obj[headers[i]] = cur[i];
                let type = guessType(cur[i]);
                if (type && types[headers[i]].indexOf(type) === -1) {
                  types[headers[i]].push(type);
                }
              }
            }
            tmp.push(obj);

          } else {
            console.log('Possibly wrong @ line: ', cur[i]);
          }

          if (tmp.length === num) {
            let to_write = tmp.slice(0, -1);
            json.write(JSON.stringify(to_write).slice(1, -1) + ',\n');

            count += 50;

            tmp = tmp.slice(-1);
            // this is to make sure that an nonempty array is always pass to the callback function on 'close' event, which will remove the comma following the last object
          }

        }
      }
    }).on('close', function () {
      json.write(JSON.stringify(tmp).slice(1, -1));

      count += tmp.length;

      json.end('\n]', 'utf8', () => {
        console.log('File is created successfully');
        let timeUsed = (Date.now() - start) / 1000;
        console.log('Time used: ' + timeUsed);

        for (let i = 0; i < headers.length; i++) {
          let t = types[headers[i]];
          if (t.length === 1) {
            types[headers[i]] = t[0];
          }
          if (t.length === 2) {
            if (t.includes('int') && t.includes('float')) {
              types[headers[i]] = 'float';
            }
            if (t.includes('string')) {
              types[headers[i]] = 'string';
            }
          }
          if (t.length > 2) {
            types[headers[i]] = 'string';
          }
        }
        console.log('Number of lines: ' + count);
        console.log('Types: ');
        console.dir(types, {
          depth: null,
          colors: true
        });

        resolve(types);
      });
    });
  });
  if (cb && typeof cb === 'function') {
    return p.then(types => {
      cb(types);
    })
  }
  return p;
}

let noType = ['null', 'Null', 'NULL', 'N/A', ''];
let boolType = ['true', 'True', 'TRUE', 'false', 'False', 'FALSE'];
let dateRe = new RegExp(/^(\d{4}\-\d\d\-\d\d([tT][\d:\.]*)?)([zZ]|([+\-])(\d\d):?(\d\d))?$/);

function guessType(str) {
  if (noType.includes(str)) {
    return '';
  }
  if (!isNaN(Number(str))) {
    let num = +str;
    if (num % 1 === 0) {
      return 'int';
    } else {
      return 'float';
    }
  }
  if (boolType.includes(str)) {
    return 'boolean';
  }
  if (dateRe.test(str)) {
    return 'date';
  }
  return 'string';
}

function map(arr, f) {
  let res = new Array(arr.length);
  for (let i = 0; i < res.length; i++) {
    res[i] = f(arr[i], i);
  }
  return res;
}

function filter(arr, f) {
  let res = [];
  for (let i = 0; i < arr.length; i++) {
    if (f(arr[i], i)) {
      res.push(arr[i]);
    }
  }
  return res;
}

function _csv2json(path, cb) {
  let start = Date.now();
  let p = new Promise((resolve, reject) => {
    let input = fs.createReadStream(path, 'utf8');
    let output = fs.createWriteStream(path + '.json', {
      flag: 'w',
      defaultEncoding: 'utf8'
    });
    output.write('[\n');

    let headers = '';
    let rems = '';
    let types = {};

    input.on('data', (str) => {
      str = rems + str;

      // let i = str.length - 1;
      // let n = 0;
      // for (i; i > 0; i--) {
      //   if (str[i] === '\n') {
      //     n += 1;
      //   }
      //   if (n === 2) {
      //     break;
      //   }
      // }
      // let s = str.slice(0, i);
      // rems = str.slice(i + 1);
      // let arr = s.split('\n');

      let arr = str.split('\n');
      rems = arr[arr.length - 1];
      arr = arr.slice(0, -1);

      arr = filter(arr, d => d.length && d[0] !== '#');
      arr = map(arr, d => d.trim());

      if (!headers) {

        headers = splitLine(arr[0]);
        headers = map(headers, d => d.replace(/ /g, '_'));

        for (let i = 0; i < headers.length; i++) {
          types[headers[i]] = [];
        }

        parseLines(arr.slice(1), headers, output, types, ',\n');

      } else {
        parseLines(arr, headers, output, types, ',\n');
      }
    }).on('end', () => {
      rems = rems.split('\n').filter(d => d.length);
      rems = map(rems, d => d.trim());
      parseLines(rems, headers, output, types, '\n');

      output.end(']', 'utf8', () => {
        console.log('File is created successfully');
        let timeUsed = (Date.now() - start) / 1000;
        console.log('Time used: ' + timeUsed);

        for (let i = 0; i < headers.length; i++) {
          let t = types[headers[i]];
          if (t.length === 1) {
            types[headers[i]] = t[0];
          }
          if (t.length === 2) {
            if (t.includes('int') && t.includes('float')) {
              types[headers[i]] = 'float';
            }
            if (t.includes('string')) {
              types[headers[i]] = 'string';
            }
          }
          if (t.length > 2) {
            types[headers[i]] = 'string';
          }
        }

        console.log('Types: ');
        console.dir(types, {
          depth: null,
          colors: true
        });

        resolve(types);
      });

    });

  });

  if (cb && typeof cb === 'function') {
    return p.then(types => {
      cb(types);
    })
  }
  return p;

}

function parseLines(arr, colNames, writeStream, typesObject, suffix) {
  // console.log('Processing: ' + arr.length);
  for (let i = 0; i < arr.length; i++) {

    let line = splitLine(arr[i]);

    if (line.length === colNames.length) {
      let obj = {};
      for (let i = 0; i < colNames.length; i++) {
        if (line[i]) {
          obj[colNames[i]] = line[i];
          let type = guessType(line[i]);
          if (type && typesObject[colNames[i]].indexOf(type) === -1) {
            typesObject[colNames[i]].push(type);
          }
        }
      }

      writeStream.write(JSON.stringify(obj) + suffix, 'utf8');

    } else {
      console.error('Error found @ line: ' + arr[i]);
      console.log('Length of headers: ' + colNames.length);
      console.log('Length of current line: ' + line.length);
    }
  }
}

if (typeof module !== 'undefined' && module.parent) {
  module.exports = csv2json;
} else {
  let csv = process.argv[2];
  let n = process.argv[3];
  if (csv) {
    if (csv.slice(-4) !== '.csv') {
      console.log('The input file is not ended with ".csv" !');
    } else {
      csv2json(csv, false, +n);
      // _csv2json(csv, false);
    }
  }

  // console.log(guessType('FALSE'));
  // console.log(guessType('2000'));
  // console.log(guessType('CANTIL 100'));
  // console.log(guessType('5% DEXTROS'));
  // console.log(guessType('10% ALCOHO'));
  // console.log(guessType('09 ALBUTER'));

  // console.log(splitLine('a, b, c,'));
  // console.log('a, b, c,'.split(','));

}
<commit_msg>csv2json4solr bugfix<commit_after>/**
 * Created by yangm11 on 7/20/2017.
 */
'use strict';

const fs = require('fs');
const readline = require('readline');
const splitLine = require('../string/splitLine');

function csv2json(path, cb, n) {
  let start = Date.now();

  let p = new Promise((resolve, reject) => {
    let types = {};
    let headers = '';
    let rl = readline.createInterface({
      input: fs.createReadStream(path, 'utf8')
    });

    let tmp = [];
    let count = 0;

    let num = n ? n : 51;

    let json = fs.createWriteStream(path + '.json', {
      flag: 'w+',
      defaultEncoding: 'utf8'
    });
    json.write('[\n');

    rl.on('line', function (line) {
      if (line.length && line[0] !== '#') {
        if (!headers) {
          headers = splitLine(line);
          headers = map(headers, d => {
            return d.replace(/ /g, '_'); // this is to make the name can be used in solr functions like "unique(name_a)"
          });
          // console.log(headers);

          for (let i = 0; i < headers.length; i++) {
            types[headers[i]] = [];
          }

        } else {
          let cur = splitLine(line);

          if (cur.length === headers.length) {
            let obj = {};
            for (let i = 0; i < headers.length; i++) {
              if (cur[i]) {
                obj[headers[i]] = cur[i];
                let type = guessType(cur[i]);
                if (type && types[headers[i]].indexOf(type) === -1) {
                  types[headers[i]].push(type);
                }
              }
            }
            tmp.push(obj);

          } else {
            console.log('Possibly wrong @ line: ', cur[i]);
          }

          if (tmp.length === num) {
            let to_write = tmp.slice(0, -1);
            json.write(JSON.stringify(to_write).slice(1, -1) + ',\n');

            count += 50;

            tmp = tmp.slice(-1);
            // this is to make sure that an nonempty array is always pass to the callback function on 'close' event, which will remove the comma following the last object
          }

        }
      }
    }).on('close', function () {
      json.write(JSON.stringify(tmp).slice(1, -1));

      count += tmp.length;

      json.end('\n]', 'utf8', () => {
        console.log('File is created successfully');
        let timeUsed = (Date.now() - start) / 1000;
        console.log('Time used: ' + timeUsed);

        for (let i = 0; i < headers.length; i++) {
          let t = types[headers[i]];
          if (t.length === 1) {
            types[headers[i]] = t[0];
          }
          if (t.length === 2) {
            if (t.includes('int') && t.includes('float')) {
              types[headers[i]] = 'float';
            }
            if (t.includes('string')) {
              types[headers[i]] = 'string';
            }
          }
          if (t.length > 2) {
            types[headers[i]] = 'string';
          }
        }
        console.log('Number of lines: ' + count);
        console.log('Types: ');
        console.dir(types, {
          depth: null,
          colors: true
        });

        resolve(types);
      });
    });
  });
  if (cb && typeof cb === 'function') {
    return p.then(types => {
      cb(types);
    })
  }
  return p;
}

let noType = ['null', 'Null', 'NULL', 'N/A', ''];
let boolType = ['true', 'True', 'TRUE', 'false', 'False', 'FALSE'];
let dateRe = new RegExp(/^(\d{4}\-\d\d\-\d\d([tT][\d:\.]*)?)([zZ]|([+\-])(\d\d):?(\d\d))?$/);

function guessType(str) {
  if (noType.includes(str)) {
    return '';
  }
  if (!isNaN(Number(str))) {
    let num = +str;
    if (num % 1 === 0) {
      return 'int';
    } else {
      return 'float';
    }
  }
  if (boolType.includes(str)) {
    return 'boolean';
  }
  if (dateRe.test(str)) {
    return 'date';
  }
  return 'string';
}

function map(arr, f) {
  let res = new Array(arr.length);
  for (let i = 0; i < res.length; i++) {
    res[i] = f(arr[i], i);
  }
  return res;
}

function filter(arr, f) {
  let res = [];
  for (let i = 0; i < arr.length; i++) {
    if (f(arr[i], i)) {
      res.push(arr[i]);
    }
  }
  return res;
}

function _csv2json(path, cb) {
  let start = Date.now();
  let p = new Promise((resolve, reject) => {
    let input = fs.createReadStream(path, 'utf8');
    let output = fs.createWriteStream(path + '.json', {
      flag: 'w',
      defaultEncoding: 'utf8'
    });
    output.write('[\n');

    let headers = '';
    let rems = '';
    let types = {};

    input.on('data', (str) => {
      str = rems + str;

      let i = str.length - 1;
      let n = 0;
      for (i; i > 0; i--) {
        if (str[i] === '\n') {
          n += 1;
        }
        if (n === 2) {
          break;
        }
      }
      let s = str.slice(0, i);
      rems = str.slice(i + 1);
      let arr = s.split('\n');

      // let arr = str.split('\n');
      // rems = arr[arr.length - 1];
      // arr = arr.slice(0, -1);

      arr = filter(arr, d => d.length && d[0] !== '#');
      arr = map(arr, d => d.trim());

      if (!headers) {

        headers = splitLine(arr[0]);
        headers = map(headers, d => d.replace(/ /g, '_'));

        for (let i = 0; i < headers.length; i++) {
          types[headers[i]] = [];
        }

        parseLines(arr.slice(1), headers, output, types, ',\n');

      } else {
        parseLines(arr, headers, output, types, ',\n');
      }
    }).on('end', () => {
      rems = rems.split('\n').filter(d => d.length);
      rems = map(rems, d => d.trim());
      parseLines(rems, headers, output, types, '\n');

      output.end(']', 'utf8', () => {
        console.log('File is created successfully');
        let timeUsed = (Date.now() - start) / 1000;
        console.log('Time used: ' + timeUsed);

        for (let i = 0; i < headers.length; i++) {
          let t = types[headers[i]];
          if (t.length === 1) {
            types[headers[i]] = t[0];
          }
          if (t.length === 2) {
            if (t.includes('int') && t.includes('float')) {
              types[headers[i]] = 'float';
            }
            if (t.includes('string')) {
              types[headers[i]] = 'string';
            }
          }
          if (t.length > 2) {
            types[headers[i]] = 'string';
          }
        }

        console.log('Types: ');
        console.dir(types, {
          depth: null,
          colors: true
        });

        resolve(types);
      });

    });

  });

  if (cb && typeof cb === 'function') {
    return p.then(types => {
      cb(types);
    })
  }
  return p;

}

function parseLines(arr, colNames, writeStream, typesObject, suffix) {
  // console.log('Processing: ' + arr.length);
  for (let i = 0; i < arr.length; i++) {

    let line = splitLine(arr[i]);

    if (line.length === colNames.length) {
      let obj = {};
      for (let i = 0; i < colNames.length; i++) {
        if (line[i]) {
          obj[colNames[i]] = line[i];
          let type = guessType(line[i]);
          if (type && typesObject[colNames[i]].indexOf(type) === -1) {
            typesObject[colNames[i]].push(type);
          }
        }
      }

      writeStream.write(JSON.stringify(obj) + suffix, 'utf8');

    } else {
      console.error('Error found @ line: ' + arr[i]);
      console.log('Length of headers: ' + colNames.length);
      console.log('Length of current line: ' + line.length);
    }
  }
}

if (typeof module !== 'undefined' && module.parent) {
  module.exports = csv2json;
} else {
  let csv = process.argv[2];
  let n = process.argv[3];
  if (csv) {
    if (csv.slice(-4) !== '.csv') {
      console.log('The input file is not ended with ".csv" !');
    } else {
      // csv2json(csv, false, +n);
      _csv2json(csv, false);
    }
  }

  // console.log(guessType('FALSE'));
  // console.log(guessType('2000'));
  // console.log(guessType('CANTIL 100'));
  // console.log(guessType('5% DEXTROS'));
  // console.log(guessType('10% ALCOHO'));
  // console.log(guessType('09 ALBUTER'));

  // console.log(splitLine('a, b, c,'));
  // console.log('a, b, c,'.split(','));

}
<|endoftext|>


<commit_before>(function()
{
    'use strict';

    angular
        .module('lumx.dropdown')
        .directive('lxDropdown', lxDropdown)
        .directive('lxDropdownToggle', lxDropdownToggle)
        .directive('lxDropdownMenu', lxDropdownMenu)
        .directive('lxDropdownFilter', lxDropdownFilter);

    lxDropdown.$inject = ['$document'];

    function lxDropdown($document)
    {
        return {
            restrict: 'E',
            templateUrl: 'dropdown.html',
            scope:
            {
                escapeClose: '=?lxEscapeClose',
                overToggle: '=?lxOverToggle',
                position: '@?lxPosition',
                width: '@?lxWidth'
            },
            link: link,
            controller: LxDropdownController,
            controllerAs: 'lxDropdown',
            bindToController: true,
            transclude: true
        };

        function link(scope, element, attrs, ctrl)
        {
            var backwardOneWay = ['position', 'width'];
            var backwardTwoWay = ['escapeClose', 'overToggle'];

            angular.forEach(backwardOneWay, function(attribute)
            {
                if (angular.isDefined(attrs[attribute]))
                {
                    attrs.$observe(attribute, function(newValue)
                    {
                        scope.lxDropdown[attribute] = newValue;
                    });
                }
            });

            angular.forEach(backwardTwoWay, function(attribute)
            {
                if (angular.isDefined(attrs[attribute]))
                {
                    scope.$watch(function()
                    {
                        return scope.$parent.$eval(attrs[attribute]);
                    }, function(newValue)
                    {
                        scope.lxDropdown[attribute] = newValue;
                    });
                }
            });

            $document.bind('click', closeDropdownMenu);

            scope.$on('$destroy', function()
            {
                ctrl.closeDropdownMenu();
                $document.unbind('click', closeDropdownMenu);
            });

            function closeDropdownMenu()
            {
                scope.$apply(function()
                {
                    ctrl.closeDropdownMenu();
                });
            }
        }
    }

    LxDropdownController.$inject = ['$element', '$scope', '$timeout', '$window', 'LxDepthService', 'LxEventSchedulerService'];

    function LxDropdownController($element, $scope, $timeout, $window, LxDepthService, LxEventSchedulerService)
    {
        var lxDropdown = this;
        var dropdownMenu;
        var dropdownToggle;
        var idEventScheduler;

        lxDropdown.closeDropdownMenu = closeDropdownMenu;
        lxDropdown.registerDropdownMenu = registerDropdownMenu;
        lxDropdown.registerDropdownToggle = registerDropdownToggle;
        lxDropdown.toggle = toggle;

        lxDropdown.escapeClose = angular.isDefined(lxDropdown.escapeClose) ? lxDropdown.escapeClose : true;
        lxDropdown.isOpen = false;
        lxDropdown.overToggle = angular.isDefined(lxDropdown.overToggle) ? lxDropdown.overToggle : false;
        lxDropdown.position = angular.isDefined(lxDropdown.position) ? lxDropdown.position : 'left';

        ////////////

        function closeDropdownMenu()
        {
            dropdownMenu.velocity(
            {
                width: 0,
                height: 0,
            },
            {
                duration: 200,
                easing: 'easeOutQuint',
                complete: function()
                {
                    $element.find('.dropdown').removeClass('dropdown--is-open');

                    dropdownMenu
                        .removeAttr('style')
                        .removeClass('dropdown-menu--is-open')
                        .appendTo($element.find('.dropdown'));

                    $scope.$apply(function()
                    {
                        lxDropdown.isOpen = false;

                        if (lxDropdown.escapeClose)
                        {
                            LxEventSchedulerService.unregister(idEventScheduler);
                            idEventScheduler = undefined;
                        }
                    });
                }
            });
        }

        function openDropdownMenu()
        {
            LxDepthService.register();

            lxDropdown.isOpen = true;

            $element.find('.dropdown').addClass('dropdown--is-open');

            dropdownMenu
                .addClass('dropdown-menu--is-open')
                .css('z-index', LxDepthService.getDepth())
                .appendTo('body');

            if (lxDropdown.escapeClose)
            {
                idEventScheduler = LxEventSchedulerService.register('keyup', onKeyUp);
            }

            $timeout(function()
            {
                var enoughtHeight = true;
                var availableHeight = setDropdownMenuCss();
                var width = dropdownMenu.outerWidth();
                var height = dropdownMenu.outerHeight();

                if (availableHeight < height)
                {
                    enoughtHeight = false;
                    height = availableHeight;
                }

                dropdownMenu.css(
                {
                    width: 0,
                    height: 0,
                    opacity: 1
                });

                dropdownMenu.find('.dropdown-menu__content').css(
                {
                    width: width,
                    height: height
                });

                dropdownMenu.velocity(
                {
                    width: width
                },
                {
                    duration: 200,
                    easing: 'easeOutQuint',
                    queue: false
                });

                dropdownMenu.velocity(
                {
                    height: height
                },
                {
                    duration: 500,
                    easing: 'easeOutQuint',
                    queue: false,
                    complete: function()
                    {
                        if (enoughtHeight)
                        {
                            dropdownMenu.css(
                            {
                                height: 'auto'
                            });
                        }

                        if (angular.isUndefined(lxDropdown.width))
                        {
                            dropdownMenu.css(
                            {
                                width: 'auto'
                            });
                        }

                        dropdownMenu.find('.dropdown-menu__content').removeAttr('style');
                    }
                });
            });
        }

        function onKeyUp(_event)
        {
            if (_event.keyCode == 27)
            {
                closeDropdownMenu();
            }

            _event.stopPropagation();
        }

        function registerDropdownMenu(_dropdownMenu)
        {
            dropdownMenu = _dropdownMenu;
        }

        function registerDropdownToggle(_dropdownToggle)
        {
            dropdownToggle = _dropdownToggle;
        }

        function setDropdownMenuCss()
        {
            var windowWidth = $window.innerWidth;
            var windowHeight = $window.innerHeight;
            var dropdownToggleWidth = dropdownToggle.outerWidth();
            var dropdownToggleHeight = dropdownToggle.outerHeight();
            var dropdownToggleTop = dropdownToggle.offset().top - angular.element($window).scrollTop();
            var dropdownMenuTopAvailable;
            var dropdownMenuBottomAvailable;
            var dropdownMenuWidth;

            if (lxDropdown.overToggle)
            {
                dropdownMenuTopAvailable = dropdownToggleTop + dropdownToggleHeight;
                dropdownMenuBottomAvailable = windowHeight - dropdownToggleTop;
            }
            else
            {
                dropdownMenuTopAvailable = dropdownToggleTop;
                dropdownMenuBottomAvailable = windowHeight - (dropdownToggleTop + dropdownToggleHeight);
            }

            if (angular.isDefined(lxDropdown.width))
            {
                if (lxDropdown.width.indexOf('%') > -1)
                {
                    dropdownMenuWidth = dropdownToggleWidth * (lxDropdown.width.slice(0, -1) / 100);
                }
                else
                {
                    dropdownMenuWidth = lxDropdown.width;
                }
            }
            else
            {
                dropdownMenuWidth = 'auto';
            }

            dropdownMenu.css(
            {
                right: lxDropdown.position === 'right' ? (windowWidth - dropdownToggle.offset().left - dropdownToggleWidth) : 'auto',
                left: lxDropdown.position === 'right' ? 'auto' : dropdownToggle.offset().left,
                width: dropdownMenuWidth
            });

            if (dropdownMenuTopAvailable > dropdownMenuBottomAvailable)
            {
                dropdownMenu.css(
                {
                    bottom: lxDropdown.overToggle ? (windowHeight - dropdownToggle.offset().top - dropdownToggleHeight) : (windowHeight - dropdownToggle.offset().top)
                });

                return dropdownMenuTopAvailable;
            }
            else
            {
                dropdownMenu.css(
                {
                    top: lxDropdown.overToggle ? dropdownToggle.offset().top : (dropdownToggle.offset().top + dropdownToggleHeight)
                });

                return dropdownMenuBottomAvailable;
            }
        }

        function toggle()
        {
            if (!lxDropdown.isOpen)
            {
                openDropdownMenu();
            }
            else
            {
                closeDropdownMenu();
            }
        }
    }

    function lxDropdownToggle()
    {
        return {
            restrict: 'AE',
            templateUrl: 'dropdown-toggle.html',
            require: '^lxDropdown',
            scope: true,
            link: link,
            replace: true,
            transclude: true
        };

        function link(scope, element, attrs, ctrl)
        {
            ctrl.registerDropdownToggle(element);

            element.bind('click', function(_event)
            {
                _event.stopPropagation();

                angular.element('.dropdown').each(function(index, dropdownElem)
                {
                    if (angular.isDefined(angular.element(dropdownElem).scope().lxDropdown) && angular.element(dropdownElem).scope().lxDropdown.isOpen)
                    {
                        angular.element(dropdownElem).scope().lxDropdown.closeDropdownMenu();
                    }
                });

                scope.$apply(function()
                {
                    ctrl.toggle();
                });
            });
        }
    }

    function lxDropdownMenu()
    {
        return {
            restrict: 'E',
            templateUrl: 'dropdown-menu.html',
            require: ['lxDropdownMenu', '^lxDropdown'],
            scope: true,
            link: link,
            controller: LxDropdownMenuController,
            controllerAs: 'lxDropdownMenu',
            bindToController: true,
            replace: true,
            transclude: true
        };

        function link(scope, element, attrs, ctrls)
        {
            ctrls[1].registerDropdownMenu(element);
            ctrls[0].setParentController(ctrls[1]);
        }
    }

    function LxDropdownMenuController()
    {
        var lxDropdownMenu = this;

        lxDropdownMenu.setParentController = setParentController;

        ////////////

        function setParentController(_parentCtrl)
        {
            lxDropdownMenu.parentCtrl = _parentCtrl;
        }
    }

    lxDropdownFilter.$inject = ['$timeout'];

    function lxDropdownFilter($timeout)
    {
        return {
            restrict: 'A',
            link: link
        };

        function link(scope, element)
        {
            element.bind('click', function(_event)
            {
                _event.stopPropagation();
            });

            $timeout(function()
            {
                element.find('input').focus();
            }, 200);
        }
    }
})();<commit_msg>feat dropdown: check dropdown position with interval<commit_after>(function()
{
    'use strict';

    angular
        .module('lumx.dropdown')
        .directive('lxDropdown', lxDropdown)
        .directive('lxDropdownToggle', lxDropdownToggle)
        .directive('lxDropdownMenu', lxDropdownMenu)
        .directive('lxDropdownFilter', lxDropdownFilter);

    lxDropdown.$inject = ['$document'];

    function lxDropdown($document)
    {
        return {
            restrict: 'E',
            templateUrl: 'dropdown.html',
            scope:
            {
                escapeClose: '=?lxEscapeClose',
                overToggle: '=?lxOverToggle',
                position: '@?lxPosition',
                width: '@?lxWidth'
            },
            link: link,
            controller: LxDropdownController,
            controllerAs: 'lxDropdown',
            bindToController: true,
            transclude: true
        };

        function link(scope, element, attrs, ctrl)
        {
            var backwardOneWay = ['position', 'width'];
            var backwardTwoWay = ['escapeClose', 'overToggle'];

            angular.forEach(backwardOneWay, function(attribute)
            {
                if (angular.isDefined(attrs[attribute]))
                {
                    attrs.$observe(attribute, function(newValue)
                    {
                        scope.lxDropdown[attribute] = newValue;
                    });
                }
            });

            angular.forEach(backwardTwoWay, function(attribute)
            {
                if (angular.isDefined(attrs[attribute]))
                {
                    scope.$watch(function()
                    {
                        return scope.$parent.$eval(attrs[attribute]);
                    }, function(newValue)
                    {
                        scope.lxDropdown[attribute] = newValue;
                    });
                }
            });

            $document.bind('click', closeDropdownMenu);

            scope.$on('$destroy', function()
            {
                ctrl.closeDropdownMenu();
                $document.unbind('click', closeDropdownMenu);
            });

            function closeDropdownMenu()
            {
                scope.$apply(function()
                {
                    ctrl.closeDropdownMenu();
                });
            }
        }
    }

    LxDropdownController.$inject = ['$element', '$interval', '$scope', '$timeout', '$window', 'LxDepthService', 'LxEventSchedulerService'];

    function LxDropdownController($element, $interval, $scope, $timeout, $window, LxDepthService, LxEventSchedulerService)
    {
        var lxDropdown = this;
        var dropdownInterval;
        var dropdownMenu;
        var dropdownToggle;
        var idEventScheduler;

        lxDropdown.closeDropdownMenu = closeDropdownMenu;
        lxDropdown.registerDropdownMenu = registerDropdownMenu;
        lxDropdown.registerDropdownToggle = registerDropdownToggle;
        lxDropdown.toggle = toggle;

        lxDropdown.escapeClose = angular.isDefined(lxDropdown.escapeClose) ? lxDropdown.escapeClose : true;
        lxDropdown.isOpen = false;
        lxDropdown.overToggle = angular.isDefined(lxDropdown.overToggle) ? lxDropdown.overToggle : false;
        lxDropdown.position = angular.isDefined(lxDropdown.position) ? lxDropdown.position : 'left';

        ////////////

        function closeDropdownMenu()
        {
            $interval.cancel(dropdownInterval);

            dropdownMenu.velocity(
            {
                width: 0,
                height: 0,
            },
            {
                duration: 200,
                easing: 'easeOutQuint',
                complete: function()
                {
                    $element.find('.dropdown').removeClass('dropdown--is-open');

                    dropdownMenu
                        .removeAttr('style')
                        .removeClass('dropdown-menu--is-open')
                        .appendTo($element.find('.dropdown'));

                    $scope.$apply(function()
                    {
                        lxDropdown.isOpen = false;

                        if (lxDropdown.escapeClose)
                        {
                            LxEventSchedulerService.unregister(idEventScheduler);
                            idEventScheduler = undefined;
                        }
                    });
                }
            });
        }

        function openDropdownMenu()
        {
            LxDepthService.register();

            lxDropdown.isOpen = true;

            $element.find('.dropdown').addClass('dropdown--is-open');

            dropdownMenu
                .addClass('dropdown-menu--is-open')
                .css('z-index', LxDepthService.getDepth())
                .appendTo('body');

            if (lxDropdown.escapeClose)
            {
                idEventScheduler = LxEventSchedulerService.register('keyup', onKeyUp);
            }

            $timeout(function()
            {
                var enoughtHeight = true;
                var availableHeight = setDropdownMenuCss();
                var width = dropdownMenu.outerWidth();
                var height = dropdownMenu.outerHeight();

                if (availableHeight < height)
                {
                    enoughtHeight = false;
                    height = availableHeight;
                }

                dropdownMenu.css(
                {
                    width: 0,
                    height: 0,
                    opacity: 1
                });

                dropdownMenu.find('.dropdown-menu__content').css(
                {
                    width: width,
                    height: height
                });

                dropdownMenu.velocity(
                {
                    width: width
                },
                {
                    duration: 200,
                    easing: 'easeOutQuint',
                    queue: false
                });

                dropdownMenu.velocity(
                {
                    height: height
                },
                {
                    duration: 500,
                    easing: 'easeOutQuint',
                    queue: false,
                    complete: function()
                    {
                        if (enoughtHeight)
                        {
                            dropdownMenu.css(
                            {
                                height: 'auto'
                            });
                        }

                        if (angular.isUndefined(lxDropdown.width))
                        {
                            dropdownMenu.css(
                            {
                                width: 'auto'
                            });
                        }

                        dropdownMenu.find('.dropdown-menu__content').removeAttr('style');

                        dropdownInterval = $interval(function()
                        {
                            setDropdownMenuCss();
                        }, 500);
                    }
                });
            });
        }

        function onKeyUp(_event)
        {
            if (_event.keyCode == 27)
            {
                closeDropdownMenu();
            }

            _event.stopPropagation();
        }

        function registerDropdownMenu(_dropdownMenu)
        {
            dropdownMenu = _dropdownMenu;
        }

        function registerDropdownToggle(_dropdownToggle)
        {
            dropdownToggle = _dropdownToggle;
        }

        function setDropdownMenuCss()
        {
            var windowWidth = $window.innerWidth;
            var windowHeight = $window.innerHeight;
            var dropdownToggleWidth = dropdownToggle.outerWidth();
            var dropdownToggleHeight = dropdownToggle.outerHeight();
            var dropdownToggleTop = dropdownToggle.offset().top - angular.element($window).scrollTop();
            var dropdownMenuTopAvailable;
            var dropdownMenuBottomAvailable;
            var dropdownMenuWidth;

            if (lxDropdown.overToggle)
            {
                dropdownMenuTopAvailable = dropdownToggleTop + dropdownToggleHeight;
                dropdownMenuBottomAvailable = windowHeight - dropdownToggleTop;
            }
            else
            {
                dropdownMenuTopAvailable = dropdownToggleTop;
                dropdownMenuBottomAvailable = windowHeight - (dropdownToggleTop + dropdownToggleHeight);
            }

            if (angular.isDefined(lxDropdown.width))
            {
                if (lxDropdown.width.indexOf('%') > -1)
                {
                    dropdownMenuWidth = dropdownToggleWidth * (lxDropdown.width.slice(0, -1) / 100);
                }
                else
                {
                    dropdownMenuWidth = lxDropdown.width;
                }
            }
            else
            {
                dropdownMenuWidth = 'auto';
            }

            dropdownMenu.css(
            {
                right: lxDropdown.position === 'right' ? (windowWidth - dropdownToggle.offset().left - dropdownToggleWidth) : 'auto',
                left: lxDropdown.position === 'right' ? 'auto' : dropdownToggle.offset().left,
                width: dropdownMenuWidth
            });

            if (dropdownMenuTopAvailable > dropdownMenuBottomAvailable)
            {
                dropdownMenu.css(
                {
                    bottom: lxDropdown.overToggle ? (windowHeight - dropdownToggle.offset().top - dropdownToggleHeight) : (windowHeight - dropdownToggle.offset().top)
                });

                return dropdownMenuTopAvailable;
            }
            else
            {
                dropdownMenu.css(
                {
                    top: lxDropdown.overToggle ? dropdownToggle.offset().top : (dropdownToggle.offset().top + dropdownToggleHeight)
                });

                return dropdownMenuBottomAvailable;
            }
        }

        function toggle()
        {
            if (!lxDropdown.isOpen)
            {
                openDropdownMenu();
            }
            else
            {
                closeDropdownMenu();
            }
        }
    }

    function lxDropdownToggle()
    {
        return {
            restrict: 'AE',
            templateUrl: 'dropdown-toggle.html',
            require: '^lxDropdown',
            scope: true,
            link: link,
            replace: true,
            transclude: true
        };

        function link(scope, element, attrs, ctrl)
        {
            ctrl.registerDropdownToggle(element);

            element.bind('click', function(_event)
            {
                _event.stopPropagation();

                angular.element('.dropdown').each(function(index, dropdownElem)
                {
                    if (angular.isDefined(angular.element(dropdownElem).scope().lxDropdown) && angular.element(dropdownElem).scope().lxDropdown.isOpen)
                    {
                        angular.element(dropdownElem).scope().lxDropdown.closeDropdownMenu();
                    }
                });

                scope.$apply(function()
                {
                    ctrl.toggle();
                });
            });
        }
    }

    function lxDropdownMenu()
    {
        return {
            restrict: 'E',
            templateUrl: 'dropdown-menu.html',
            require: ['lxDropdownMenu', '^lxDropdown'],
            scope: true,
            link: link,
            controller: LxDropdownMenuController,
            controllerAs: 'lxDropdownMenu',
            bindToController: true,
            replace: true,
            transclude: true
        };

        function link(scope, element, attrs, ctrls)
        {
            ctrls[1].registerDropdownMenu(element);
            ctrls[0].setParentController(ctrls[1]);
        }
    }

    function LxDropdownMenuController()
    {
        var lxDropdownMenu = this;

        lxDropdownMenu.setParentController = setParentController;

        ////////////

        function setParentController(_parentCtrl)
        {
            lxDropdownMenu.parentCtrl = _parentCtrl;
        }
    }

    lxDropdownFilter.$inject = ['$timeout'];

    function lxDropdownFilter($timeout)
    {
        return {
            restrict: 'A',
            link: link
        };

        function link(scope, element)
        {
            element.bind('click', function(_event)
            {
                _event.stopPropagation();
            });

            $timeout(function()
            {
                element.find('input').focus();
            }, 200);
        }
    }
})();<|endoftext|>