<commit_before>/*
 * JSX tokanizer
 */

var Class = require("./Class");
eval(Class.$import("./token"));
eval(Class.$import("./util"));

"use strict";

var Lexer = exports.Lexer = Class.extend({

	$makeAlt: function (patterns) {
		return "(?: \n" + patterns.join("\n | \n") + "\n)\n";
	},

	$quoteMeta: function (pattern) {
		return pattern.replace(/([^0-9A-Za-z_])/g, '\\$1');
	},

	$asHash: function (array) {
		var hash = {};
		for (var i = 0; i < array.length; ++i)
			hash[array[i]] = 1;
		return hash;
	},

	/// compile a regular expression
	$rx: function (pat, flags) {
		return RegExp(pat.replace(/[ \t\r\n]/g, ""), flags);
	},

	// static variables
	$initialize: function () {
		var ident         = " [a-zA-Z_] [a-zA-Z0-9_]* ";
		var doubleQuoted  = ' "  [^"\\\\]* (?: \\\\. [^"\\\\]* )* " ';
		var singleQuoted  = " '  [^'\\\\]* (?: \\\\. [^'\\\\]* )* ' ";
		var stringLiteral = this.makeAlt([singleQuoted, doubleQuoted]);
		var regexpLiteral = doubleQuoted.replace(/"/g, "/");

		// ECMA 262 compatible,
		// see also ECMA 262 5th (7.8.3) Numeric Literals
		var decimalIntegerLiteral = "(?: 0 | [1-9][0-9]* )";
		var exponentPart = "(?: [eE] [+-]? [0-9]+ )";
		var numberLiteral = this.makeAlt([
				"(?: " + decimalIntegerLiteral + " \\. " +
					    "[0-9]* " + exponentPart + "? )",
				"(?: \\. [0-9]+ " + exponentPart + "? )",
				"(?: " + decimalIntegerLiteral + exponentPart + " )"
			]) + "\\";
		var integerLiteral = this.makeAlt([
				"(?: 0 [xX] [0-9a-fA-F]+ )", // hex
				decimalIntegerLiteral
			]) + "(?![\\.0-9eE])";

		var multiLineComment  = "(?: /\\* (?: [^*] | (?: \\*+ [^*\\/]) )* \\*+/)";
		var singleLineComment = "(?: // [^\\r\\n]* )";
		var comment           = this.makeAlt([multiLineComment, singleLineComment]);
		var whiteSpace        = "[\\x20\\t\\r\\n]+";

		this.keyword = this.asHash([
			// literals shared with ECMA 262
			"null",     "true",     "false",
			// keywords shared with ECMA 262
			"break",    "do",       "instanceof", "typeof",
			"case",     "else",     "new",        "var",
			"catch",    "finally",  "return",     "void",
			"continue", "for",      "switch",     "while",
			"function", "this",
			"default",  "if",       "throw",
			"delete",   "in",       "try",
			// keywords of JSX
			"class",	 "extends", "super",
			"import",    "implements",
			"interface", "static",
			"assert",    "log",
			"__FILE__",  "__LINE__"
		]);
		this.reserved = this.asHash([
			// literals of ECMA 262 but not used by JSX
			"debugger", "with",
			// future reserved words of ECMA 262
			"const", "export",
			// future reserved words within strict mode of ECMA 262
			"let",   "private",   "public", "yield",
			"protected",

			// JSX specific reserved words
			"extern", "native",
			"trait", "using",
			"as", "is",
			"operator", "package"
		]);

		// some operators are not used, but recognized
		// in order to make error massages helpful.
		// e.g. "operator -> is not defined. Do you mean this.foo()?"
		var ops = [
			"{",  "}",  "(",  ")",  "[",  "]",
			".",  ";",  ",",  ":",  "?",  "@",
			"->", "\\", "::", "..", "...",

			"<",  ">",  "<=",  ">=",
			"==", "!=", "<=>", "=~", "~!",

			"=",
			"+",  "-",  "*",  "/",  "%",
			"+=", "-=", "*=", "/=", "%=",
			"&",  "|",  "^",
			"&=", "|=", "^=",
			"~",  "!",
			"++", "--",
			"||", "&&"
		];
		for (var i = 0; i < ops.length; i++)
			ops[i] = this.quoteMeta(ops[i]);

		var operator = this.makeAlt(ops.sort().reverse());

		// regular expressions
		this.rxOperator       = this.rx("^" + operator);
		this.rxIdent          = this.rx("^" + ident);
		this.rxStringLiteral  = this.rx("^" + stringLiteral);
		this.rxNumberLiteral  = this.rx("^" + numberLiteral);
		this.rxIntegerLiteral = this.rx("^" + integerLiteral);
		this.rxRegExpLiteral  = this.rx("^" + regexpLiteral);
		this.rxSpace          = this.rx("^" + this.makeAlt([comment, whiteSpace]));
	},

	initialize: function (filename, input, errors) {
		this._filename = filename;
		this._input = input;
		this._pos = 0;
		this._errors = errors;
	},

	tokenize: function() {

		var tokens = [];

		while (this._pos < this._input.length) {

			var start = this._input.substring(this._pos);
			var matched;
			if (matched = start.match(Lexer.rxSpace)) {
				// skip tokens.push(new SpaceToken(this._filename, this._pos));
			}
			else if (matched = start.match(Lexer.rxStringLiteral)) {
				tokens.push(new StringToken(matched[0], this._filename, this._pos));
			}
			else if (matched = start.match(Lexer.rxIntegerLiteral)) {
				tokens.push(IntegerToken.create(matched[0], null, this._filename, this._pos));
			}
			else if (matched = start.match(Lexer.rxNumberLiteral)) {
				tokens.push(new NumberToken(matched[0], null, this._filename, this._pos));
			}
			else if (matched = start.match(Lexer.rxRegExpLiteral)) {
				tokens.push(new RegExpToken(matched[0], this._filename, this._pos));
			}
			else if (matched = start.match(Lexer.rxOperator)) {
				tokens.push(new KeywordToken(matched[0], this._filename, this._pos));
			}
			else if (matched = start.match(Lexer.rxIdent)) {
				if (Lexer.keyword.hasOwnProperty(matched[0])) {
					tokens.push(new KeywordToken(matched[0], this._filename, this._pos));
				} else if (Lexer.reserved.hasOwnProperty(matched[0])) {
					this._newError("keyword " + matched[0] + " is not supported under current version of JSX");
				} else {
					tokens.push(new IdentifierToken(matched[0], this._filename, this._pos));
				}
			}
			else {
				this._newError("unexpected character " + JSON.stringify(start[0]));
				// skip to the end of line
				matched = start.match(/^.*(?:\r\n?|\n|$)/);
			}

			this._pos += matched[0].length;
		}

		return tokens;
	},

	_newError: function (message) {
		var e = new CompileError(this._filename, this._pos, message);
		this._errors.push(e);
	}

});

if (typeof(process) !== 'undefined' && process.argv[1] === __filename) {
	// testing in node.js
	process.argv.slice(2).map(function(file) {
		console.log(file);
		var fs   = require("fs");
		var content = fs.readFileSync(file).toString();
		var errors = [];

		var lexer = new Lexer(file, content, errors);

		var t0 = Date.now();

		var tokens = lexer.tokenize();
		console.log("*** Errors ***");
		for (var i = 0; i < errors.length; ++i) {
			console.log(errors[i].toString());
		}
		console.log("*** Tokens ***");
		for (var i = 0; i < tokens.length; ++i) {
			console.log(JSON.stringify(tokens[i].serialize()));
		}
		console.log("elapsed %s ms.", Date.now() - t0);
	});
}
// vim: set noexpandtab:
<commit_msg>Fix compile error<commit_after>/*
 * JSX tokanizer
 */

var Class = require("./Class");
eval(Class.$import("./token"));
eval(Class.$import("./util"));

"use strict";

var Lexer = exports.Lexer = Class.extend({

	$makeAlt: function (patterns) {
		return "(?: \n" + patterns.join("\n | \n") + "\n)\n";
	},

	$quoteMeta: function (pattern) {
		return pattern.replace(/([^0-9A-Za-z_])/g, '\\$1');
	},

	$asHash: function (array) {
		var hash = {};
		for (var i = 0; i < array.length; ++i)
			hash[array[i]] = 1;
		return hash;
	},

	/// compile a regular expression
	$rx: function (pat, flags) {
		return RegExp(pat.replace(/[ \t\r\n]/g, ""), flags);
	},

	// static variables
	$initialize: function () {
		var ident         = " [a-zA-Z_] [a-zA-Z0-9_]* ";
		var doubleQuoted  = ' "  [^"\\\\]* (?: \\\\. [^"\\\\]* )* " ';
		var singleQuoted  = " '  [^'\\\\]* (?: \\\\. [^'\\\\]* )* ' ";
		var stringLiteral = this.makeAlt([singleQuoted, doubleQuoted]);
		var regexpLiteral = doubleQuoted.replace(/"/g, "/");

		// ECMA 262 compatible,
		// see also ECMA 262 5th (7.8.3) Numeric Literals
		var decimalIntegerLiteral = "(?: 0 | [1-9][0-9]* )";
		var exponentPart = "(?: [eE] [+-]? [0-9]+ )";
		var numberLiteral = this.makeAlt([
				"(?: " + decimalIntegerLiteral + " \\. " +
				        "[0-9]* " + exponentPart + "? )",
				"(?: \\. [0-9]+ " + exponentPart + "? )",
				"(?: " + decimalIntegerLiteral + exponentPart + " )"
			]);
		var integerLiteral = this.makeAlt([
				"(?: 0 [xX] [0-9a-fA-F]+ )", // hex
				decimalIntegerLiteral
			]) + "(?![\\.0-9eE])";

		var multiLineComment  = "(?: /\\* (?: [^*] | (?: \\*+ [^*\\/]) )* \\*+/)";
		var singleLineComment = "(?: // [^\\r\\n]* )";
		var comment           = this.makeAlt([multiLineComment, singleLineComment]);
		var whiteSpace        = "[\\x20\\t\\r\\n]+";

		this.keyword = this.asHash([
			// literals shared with ECMA 262
			"null",     "true",     "false",
			// keywords shared with ECMA 262
			"break",    "do",       "instanceof", "typeof",
			"case",     "else",     "new",        "var",
			"catch",    "finally",  "return",     "void",
			"continue", "for",      "switch",     "while",
			"function", "this",
			"default",  "if",       "throw",
			"delete",   "in",       "try",
			// keywords of JSX
			"class",	 "extends", "super",
			"import",    "implements",
			"interface", "static",
			"assert",    "log",
			"__FILE__",  "__LINE__"
		]);
		this.reserved = this.asHash([
			// literals of ECMA 262 but not used by JSX
			"debugger", "with",
			// future reserved words of ECMA 262
			"const", "export",
			// future reserved words within strict mode of ECMA 262
			"let",   "private",   "public", "yield",
			"protected",

			// JSX specific reserved words
			"extern", "native",
			"trait", "using",
			"as", "is",
			"operator", "package"
		]);

		// some operators are not used, but recognized
		// in order to make error massages helpful.
		// e.g. "operator -> is not defined. Do you mean this.foo()?"
		var ops = [
			"{",  "}",  "(",  ")",  "[",  "]",
			".",  ";",  ",",  ":",  "?",  "@",
			"->", "\\", "::", "..", "...",

			"<",  ">",  "<=",  ">=",
			"==", "!=", "<=>", "=~", "~!",

			"=",
			"+",  "-",  "*",  "/",  "%",
			"+=", "-=", "*=", "/=", "%=",
			"&",  "|",  "^",
			"&=", "|=", "^=",
			"~",  "!",
			"++", "--",
			"||", "&&"
		];
		for (var i = 0; i < ops.length; i++)
			ops[i] = this.quoteMeta(ops[i]);

		var operator = this.makeAlt(ops.sort().reverse());

		// regular expressions
		this.rxOperator       = this.rx("^" + operator);
		this.rxIdent          = this.rx("^" + ident);
		this.rxStringLiteral  = this.rx("^" + stringLiteral);
		this.rxNumberLiteral  = this.rx("^" + numberLiteral);
		this.rxIntegerLiteral = this.rx("^" + integerLiteral);
		this.rxRegExpLiteral  = this.rx("^" + regexpLiteral);
		this.rxSpace          = this.rx("^" + this.makeAlt([comment, whiteSpace]));
	},

	initialize: function (filename, input, errors) {
		this._filename = filename;
		this._input = input;
		this._pos = 0;
		this._errors = errors;
	},

	tokenize: function() {

		var tokens = [];

		while (this._pos < this._input.length) {

			var start = this._input.substring(this._pos);
			var matched;
			if (matched = start.match(Lexer.rxSpace)) {
				// skip tokens.push(new SpaceToken(this._filename, this._pos));
			}
			else if (matched = start.match(Lexer.rxStringLiteral)) {
				tokens.push(new StringToken(matched[0], this._filename, this._pos));
			}
			else if (matched = start.match(Lexer.rxIntegerLiteral)) {
				tokens.push(IntegerToken.create(matched[0], null, this._filename, this._pos));
			}
			else if (matched = start.match(Lexer.rxNumberLiteral)) {
				tokens.push(new NumberToken(matched[0], null, this._filename, this._pos));
			}
			else if (matched = start.match(Lexer.rxRegExpLiteral)) {
				tokens.push(new RegExpToken(matched[0], this._filename, this._pos));
			}
			else if (matched = start.match(Lexer.rxOperator)) {
				tokens.push(new KeywordToken(matched[0], this._filename, this._pos));
			}
			else if (matched = start.match(Lexer.rxIdent)) {
				if (Lexer.keyword.hasOwnProperty(matched[0])) {
					tokens.push(new KeywordToken(matched[0], this._filename, this._pos));
				} else if (Lexer.reserved.hasOwnProperty(matched[0])) {
					this._newError("keyword " + matched[0] + " is not supported under current version of JSX");
				} else {
					tokens.push(new IdentifierToken(matched[0], this._filename, this._pos));
				}
			}
			else {
				this._newError("unexpected character " + JSON.stringify(start[0]));
				// skip to the end of line
				matched = start.match(/^.*(?:\r\n?|\n|$)/);
			}

			this._pos += matched[0].length;
		}

		return tokens;
	},

	_newError: function (message) {
		var e = new CompileError(this._filename, this._pos, message);
		this._errors.push(e);
	}

});

if (typeof(process) !== 'undefined' && process.argv[1] === __filename) {
	// testing in node.js
	process.argv.slice(2).map(function(file) {
		console.log(file);
		var fs   = require("fs");
		var content = fs.readFileSync(file).toString();
		var errors = [];

		var lexer = new Lexer(file, content, errors);

		var t0 = Date.now();

		var tokens = lexer.tokenize();
		console.log("*** Errors ***");
		for (var i = 0; i < errors.length; ++i) {
			console.log(errors[i].toString());
		}
		console.log("*** Tokens ***");
		for (var i = 0; i < tokens.length; ++i) {
			console.log(JSON.stringify(tokens[i].serialize()));
		}
		console.log("elapsed %s ms.", Date.now() - t0);
	});
}
// vim: set noexpandtab:
<|endoftext|>


<commit_before>
/*!
 * CSS - Lexer
 * Copyright(c) 2010 LearnBoost <dev@learnboost.com>
 * MIT Licensed
 */

/**
 * Module dependencies.
 */

var Token = require('./token')
  , nodes = require('./nodes');

/**
 * Initialize a new `Lexer` with the given `str` and `options`.
 *
 * @param {String} str
 * @param {Object} options
 * @api private
 */

var Lexer = module.exports = function Lexer(str, options) {
  options = options || {};
  this.str = str;
  this.filename = options.filename || 'css';
  this.stash = [];
  this.prevIndents = 0;
};

/**
 * Lexer prototype.
 */

Lexer.prototype = {
  get next() {
    return this.stashed
      || this.newline
      || this.color
      || this.id
      || this.eos;
  },

  get peek() {
    if (this.stash.length) {
      return this.stash[0];
    } else {
      var tok;
      this.stash.push(tok = this.next);
      return tok;
    }
  },

  get stashed() {
    return this.stash.shift();
  },

  get isProperty() {
    return 1 == this.prevIndents % 2;
  },

  get eos() {
    if (this.str.length) return;
    return this.prevIndents-- > 0
      ? new Token('outdent')
      : new Token('eos');
  },

  get newline() {
    var captures;
    if (captures = /^\n( *)/.exec(this.str)) {
      this.str = this.str.substr(captures[0].length);
      var tok
        , spaces = captures[1].length
        , indents = spaces / 2;

      // To few spaces
      if (0 != spaces % 2) {
        throw new Error('Invalid indentation, got ' + spaces + ' space(s), expected multiple of 2');
      // To many spaces
      } else if (indents > this.prevIndents + 1) {
        var expected = 2 * this.prevIndents || 2;
        throw new Error('Invalid indentation, got ' + spaces + ' space(s), expected ' + expected);
      // Outdent
      } else if (indents < this.prevIndents) {
        var n = this.prevIndents - indents;
        while (--n) this.stash.push(new Token('outdent'));
        this.prevIndents = indents;
        tok = new Token('outdent');
      // Indent
      } else {
        this.prevIndents = indents;
        tok = new Token('indent');
      }

      return tok;
    }
  },

  get color() {
    return this.hexColor;
  },

  get hexColor() {
    return this.hex6Color
      || this.hex3Color
      || this.rgba
      || this.rgb;
  },

  get rgb() {
    var captures;
    if (captures = /^rgb\( *(\d+) *, *(\d+) *, *(\d+) *\)/.exec(this.str)) {
      this.str = this.str.substr(captures[0].length);
      var r = parseInt(captures[1], 10)
        , g = parseInt(captures[2], 10)
        , b = parseInt(captures[3], 10);
      return new Token('color', new nodes.Color(r, g, b, 1));
    }
  },

  get rgba() {
    var captures;
    if (captures = /^rgba\( *(\d+) *, *(\d+) *, *(\d+) *, *(\d+(?:\.\d+)?) *\)/.exec(this.str)) {
      this.str = this.str.substr(captures[0].length);
      var r = parseInt(captures[1], 10)
        , g = parseInt(captures[2], 10)
        , b = parseInt(captures[3], 10)
        , a = parseFloat(captures[4]);
      return new Token('color', new nodes.Color(r, g, b, a));
    }
  },

  get hex3Color() {
    var captures;
    if (captures = /^#([a-f-A-F0-9]{3})/.exec(this.str)) {
      this.str = this.str.substr(4);
      var rgb = captures[1]
        , r = parseInt(rgb[0] + rgb[0], 16)
        , g = parseInt(rgb[1] + rgb[1], 16)
        , b = parseInt(rgb[2] + rgb[2], 16);
      return new Token('color', new nodes.Color(r, g, b, 1));
    }
  },

  get hex6Color() {
    var captures;
    if (captures = /^#([a-f-A-F0-9]{6})/.exec(this.str)) {
      this.str = this.str.substr(7);
      var rgb = captures[1]
        , r = parseInt(rgb.substr(0, 2), 16)
        , g = parseInt(rgb.substr(2, 2), 16)
        , b = parseInt(rgb.substr(4, 2), 16);
      return new Token('color', new nodes.Color(r, g, b, 1));
    }
  },

  get id() {
    var captures;
    if (captures = /^([^\n]+)/.exec(this.str)) {
      var id = captures[0];
      this.str = this.str.substr(id.length);
      return this.isProperty
        ? new Token('property', id)
        : new Token('selector', id);
    }
  }
};
<commit_msg>Scanning properties correctly<commit_after>
/*!
 * CSS - Lexer
 * Copyright(c) 2010 LearnBoost <dev@learnboost.com>
 * MIT Licensed
 */

/**
 * Module dependencies.
 */

var Token = require('./token')
  , nodes = require('./nodes');

/**
 * Initialize a new `Lexer` with the given `str` and `options`.
 *
 * @param {String} str
 * @param {Object} options
 * @api private
 */

var Lexer = module.exports = function Lexer(str, options) {
  options = options || {};
  this.str = str;
  this.filename = options.filename || 'css';
  this.stash = [];
  this.prevIndents = 0;
};

/**
 * Lexer prototype.
 */

Lexer.prototype = {
  get next() {
    return this.stashed
      || this.newline
      || this.color
      || this.id
      || this.eos;
  },

  get peek() {
    if (this.stash.length) {
      return this.stash[0];
    } else {
      var tok;
      this.stash.push(tok = this.next);
      return tok;
    }
  },

  get stashed() {
    return this.stash.shift();
  },

  get isProperty() {
    return 1 == this.prevIndents % 2;
  },

  get eos() {
    if (this.str.length) return;
    return this.prevIndents-- > 0
      ? new Token('outdent')
      : new Token('eos');
  },

  get newline() {
    var captures;
    if (captures = /^\n( *)/.exec(this.str)) {
      this.str = this.str.substr(captures[0].length);
      var tok
        , spaces = captures[1].length
        , indents = spaces / 2;

      // To few spaces
      if (0 != spaces % 2) {
        throw new Error('Invalid indentation, got ' + spaces + ' space(s), expected multiple of 2');
      // To many spaces
      } else if (indents > this.prevIndents + 1) {
        var expected = 2 * this.prevIndents || 2;
        throw new Error('Invalid indentation, got ' + spaces + ' space(s), expected ' + expected);
      // Outdent
      } else if (indents < this.prevIndents) {
        var n = this.prevIndents - indents;
        while (--n) this.stash.push(new Token('outdent'));
        this.prevIndents = indents;
        tok = new Token('outdent');
      // Indent
      } else {
        this.prevIndents = indents;
        tok = new Token('indent');
      }

      return tok;
    }
  },

  get color() {
    return this.hexColor;
  },

  get hexColor() {
    return this.hex6Color
      || this.hex3Color
      || this.rgba
      || this.rgb;
  },

  get rgb() {
    var captures;
    if (captures = /^rgb\( *(\d+) *, *(\d+) *, *(\d+) *\)/.exec(this.str)) {
      this.str = this.str.substr(captures[0].length);
      var r = parseInt(captures[1], 10)
        , g = parseInt(captures[2], 10)
        , b = parseInt(captures[3], 10);
      return new Token('color', new nodes.Color(r, g, b, 1));
    }
  },

  get rgba() {
    var captures;
    if (captures = /^rgba\( *(\d+) *, *(\d+) *, *(\d+) *, *(\d+(?:\.\d+)?) *\)/.exec(this.str)) {
      this.str = this.str.substr(captures[0].length);
      var r = parseInt(captures[1], 10)
        , g = parseInt(captures[2], 10)
        , b = parseInt(captures[3], 10)
        , a = parseFloat(captures[4]);
      return new Token('color', new nodes.Color(r, g, b, a));
    }
  },

  get hex3Color() {
    var captures;
    if (captures = /^#([a-f-A-F0-9]{3})/.exec(this.str)) {
      this.str = this.str.substr(4);
      var rgb = captures[1]
        , r = parseInt(rgb[0] + rgb[0], 16)
        , g = parseInt(rgb[1] + rgb[1], 16)
        , b = parseInt(rgb[2] + rgb[2], 16);
      return new Token('color', new nodes.Color(r, g, b, 1));
    }
  },

  get hex6Color() {
    var captures;
    if (captures = /^#([a-f-A-F0-9]{6})/.exec(this.str)) {
      this.str = this.str.substr(7);
      var rgb = captures[1]
        , r = parseInt(rgb.substr(0, 2), 16)
        , g = parseInt(rgb.substr(2, 2), 16)
        , b = parseInt(rgb.substr(4, 2), 16);
      return new Token('color', new nodes.Color(r, g, b, 1));
    }
  },

  get id() {
    var captures;
    if (this.isProperty) {
      if (captures = /^[-a-z][-a-z0-9]* */.exec(this.str)) {
        var prop = captures[0];
        this.str = this.str.substr(prop.length);
        return new Token('property', prop);
      }
    } else if (captures = /^[^\n]+/.exec(this.str)) {
      var selector = captures[0];
      this.str = this.str.substr(selector.length);
      return new Token('selector', selector);
    }
  }
};
<|endoftext|>


<commit_before>var RoomClass = require('./room.js');

var Lobby = function(io) {
  this.io = io;
  this.rooms = {};
};

Lobby.prototype.createRoom = function(roomUrl) {
  roomUrl = roomUrl === undefined ? this.createUniqueURL() : roomUrl + this.createUniqueURL();
  if (roomUrl in this.rooms) {
    this.createRoom(roomUrl);
  }
  this.rooms[roomUrl] = new RoomClass.Room(this.io, roomUrl);
  return roomUrl;
};

Lobby.prototype.createUniqueURL = function() {
  var text = ""
    , possible = "abcdefghijklmnopqrstuvwxyz0123456789"
    , digits = "0123456789"
    , i
    ;
  text = digits.charAt(Math.floor(Math.random() * digits.length));
  for ( i = 0; i < 3; i++ ) {
    text += possible.charAt(Math.floor(Math.random() * possible.length));
    }
  return text;
};

Lobby.prototype.joinRoom = function(socket, data) {
  if(data.roomUrl && data.roomUrl in this.rooms) {
    var room = this.getRoom(data.roomUrl);
    if (socket != null && data && data.sessionId != null) {
      room.enter(socket, data);
      socket.join(data.roomUrl);
      socket.broadcast.to(data.roomUrl).emit('room joined');
    }
    return room;
  } else {
    return { error: 'room ' + data.roomUrl + ' does not exist'};
  }
};

Lobby.prototype.getRoom = function(roomUrl) {
  var room = this.rooms[roomUrl];
  if (room) {
    return room;
  } else {
    return { error: 'room ' + roomUrl + ' does not exist'};
  }
};

Lobby.prototype.broadcastDisconnect = function(socket) {
  var clientRooms = this.io.sockets.manager.roomClients[socket.id]
    , socketRoom, room
    ;
  console.log("broadcast Disconnect");
  for (socketRoom in clientRooms) {
    if (socketRoom.length) {
      roomUrl = socketRoom.substr(1);
      room = this.getRoom(roomUrl);
      room.leave(socket);
      this.io.sockets.in(roomUrl).emit('room left');
    }
  }
};

exports.Lobby = Lobby;<commit_msg>Remove empty rooms when we create new rooms.<commit_after>var _ = require('underscore')._;

var RoomClass = require('./room.js');

var Lobby = function(io) {
  this.io = io;
  this.rooms = {};
};

Lobby.prototype.createRoom = function(roomUrl) {
  roomUrl = roomUrl === undefined ? this.createUniqueURL() : roomUrl + this.createUniqueURL();
  if (this.rooms[roomUrl]) {
    this.createRoom(roomUrl);
  }

  // remove any existing empty rooms first
  var thatRooms = this.rooms;
  _.each(this.rooms, function(room, key, rooms) {
    if (room.getClientCount() == 0) {
      delete thatRooms[key];
      console.log("removed room " + key);
    }
  });

  this.rooms[roomUrl] = new RoomClass.Room(this.io, roomUrl);
  return roomUrl;
};

Lobby.prototype.createUniqueURL = function() {
  var text = ""
    , possible = "abcdefghijklmnopqrstuvwxyz0123456789"
    , digits = "0123456789"
    , i
    ;
  text = digits.charAt(Math.floor(Math.random() * digits.length));
  for ( i = 0; i < 3; i++ ) {
    text += possible.charAt(Math.floor(Math.random() * possible.length));
    }
  return text;
};

Lobby.prototype.joinRoom = function(socket, data) {
  if(data.roomUrl && data.roomUrl in this.rooms) {
    var room = this.getRoom(data.roomUrl);
    if (socket != null && data && data.sessionId != null) {
      room.enter(socket, data);
      socket.join(data.roomUrl);
      socket.broadcast.to(data.roomUrl).emit('room joined');
    }
    return room;
  } else {
    return { error: 'room ' + data.roomUrl + ' does not exist'};
  }
};

Lobby.prototype.getRoom = function(roomUrl) {
  var room = this.rooms[roomUrl];
  if (room) {
    return room;
  } else {
    return { error: 'room ' + roomUrl + ' does not exist'};
  }
};

Lobby.prototype.broadcastDisconnect = function(socket) {
  var clientRooms = this.io.sockets.manager.roomClients[socket.id]
    , socketRoom, room
    ;
  console.log("broadcast Disconnect");
  for (socketRoom in clientRooms) {
    if (socketRoom.length) {
      roomUrl = socketRoom.substr(1);
      var room = this.getRoom(roomUrl);
      if (room) {
        room.leave(socket);
      }
      this.io.sockets.in(roomUrl).emit('room left');
    }
  }
};

exports.Lobby = Lobby;<|endoftext|>


<commit_before>var c = require('better-console')

var Mango = module.exports = function(folder, config) {
	this.config = config || {}
	this.config.dir = folder
	this.config.devmode = false
}

Mango.prototype.init = function(forkTemplate, callback) {
	if((/^[a-z0-9_-]+\/[a-z0-9_-]+$/i).test(forkTemplate)) {
		forkTemplate = "git@github.com:" + forkTemplate + ".git"
	}
	this._forkRepository(this.config.dir, forkTemplate, function(err) {
		c.info('init done')
		if(callback instanceof Function) callback(err)
	})
}

Mango.prototype._forkRepository = function(destination, remote, callback) {
	c.log('Forking', remote, 'to', destination)

	var git = require('gift')

	git.clone(remote, destination, function(err, repo) {
		if(err) {
			c.error('Failed to clone', err)
			if(callback instanceof Function) callback(err)
			return
		}

		repo.remote_remove('origin', function(err) {
			if(err) c.error('Failed to remove origin', err)
			c.info('Repository forked')
			if(callback instanceof Function) callback(err, repo)
		})
	})
}

Mango.prototype._initRepo = function(folder, callback) {
	c.log('Initializing empty git repo in', folder)

	var fs = require('fs')
	var git = require('gift')

	if(!fs.existsSync(folder)) {
		fs.mkdirSync(folder)
	}

	git.init(folder, function(err, repo) {
		if(err) {
			c.error('Failed git repo initialization', err)
		}
		c.info('Repository initialized')
		if(callback instanceof Function) callback(err, repo)
	})
}

Mango.prototype.install = function(callback) {
	c.log('Installing NPM packages')

	var npm = require('npm')

	npm.load(function(err){
		if(err) {
			c.error('Failed loading NPM package.json', err)
			if(callback instanceof Function) callback(err)
			return
		}

		npm.on('log', console.log)

		npm.commands.install(this.config.dir, this.config.dependencies, function(err, data) {
			if(err) c.error('Failed installing packages', err)
			if(callback instanceof Function) callback(err)
		})
	}.bind(this))
}

Mango.prototype._cleanup = function() {
	if(this.config.dist_folder){
		c.log('Cleaning dist folder')
		var del = require('del')
		var path = require('path')
		var dir = path.resolve(this.config.dir, this.config.dist_folder)
		return del.sync(dir)
	}
	return false
}

Mango.prototype.build = function(tasks, callback) {
	c.info('Building project assets for production')
	var gulp = require('gulp')

	this._registerGulpTasks(gulp)

	if(!tasks || !tasks.length){
		tasks = ['styles', 'scripts', 'templates', 'images', 'static']
		this._cleanup()
	}

	gulp.start(tasks, callback)
}

Mango.prototype.dev = function(http_proxy, callback) {
	c.info('Starting development mode and watching for assets change')
	var gulp = require('gulp')
	var runSequence = require('run-sequence')

	this.config.devmode = true

	if(typeof http_proxy !== 'undefined') {
		this.config.proxy = http_proxy
	}

	this._registerGulpTasks(gulp)
	this._cleanup()

	runSequence('compile', [ 'watch:sources', 'watch:reload' ], callback)
}

Mango.prototype._registerGulpTasks = function(gulp) {
	gulp.task('styles', require('./tasks/styles')(gulp, this.config))
	gulp.task('scripts', require('./tasks/scripts')(gulp, this.config))
	gulp.task('images', require('./tasks/images')(gulp, this.config))
	gulp.task('templates', require('./tasks/templates')(gulp, this.config))
	gulp.task('static', require('./tasks/static')(gulp, this.config))

	gulp.task('watch:sources', require('./tasks/watch_sources')(gulp, this.config))
	gulp.task('watch:reload', require('./tasks/watch_reload')(gulp, this.config))

	gulp.task('compile', ['styles', 'scripts', 'templates', 'images', 'static'])
}
<commit_msg>Default tasks specified as Mango.defaultTasks<commit_after>var c = require('better-console')

var Mango = module.exports = function(folder, config) {
	this.config = config || {}
	this.config.dir = folder
	this.config.devmode = false
	this.defaultTasks = ['styles', 'scripts', 'templates', 'images', 'static']
}

Mango.prototype.init = function(forkTemplate, callback) {
	if((/^[a-z0-9_-]+\/[a-z0-9_-]+$/i).test(forkTemplate)) {
		forkTemplate = "git@github.com:" + forkTemplate + ".git"
	}
	this._forkRepository(this.config.dir, forkTemplate, function(err) {
		c.info('init done')
		if(callback instanceof Function) callback(err)
	})
}

Mango.prototype._forkRepository = function(destination, remote, callback) {
	c.log('Forking', remote, 'to', destination)

	var git = require('gift')

	git.clone(remote, destination, function(err, repo) {
		if(err) {
			c.error('Failed to clone', err)
			if(callback instanceof Function) callback(err)
			return
		}

		repo.remote_remove('origin', function(err) {
			if(err) c.error('Failed to remove origin', err)
			c.info('Repository forked')
			if(callback instanceof Function) callback(err, repo)
		})
	})
}

Mango.prototype._initRepo = function(folder, callback) {
	c.log('Initializing empty git repo in', folder)

	var fs = require('fs')
	var git = require('gift')

	if(!fs.existsSync(folder)) {
		fs.mkdirSync(folder)
	}

	git.init(folder, function(err, repo) {
		if(err) {
			c.error('Failed git repo initialization', err)
		}
		c.info('Repository initialized')
		if(callback instanceof Function) callback(err, repo)
	})
}

Mango.prototype.install = function(callback) {
	c.log('Installing NPM packages')

	var npm = require('npm')

	npm.load(function(err){
		if(err) {
			c.error('Failed loading NPM package.json', err)
			if(callback instanceof Function) callback(err)
			return
		}

		npm.on('log', console.log)

		npm.commands.install(this.config.dir, this.config.dependencies, function(err, data) {
			if(err) c.error('Failed installing packages', err)
			if(callback instanceof Function) callback(err)
		})
	}.bind(this))
}

Mango.prototype._cleanup = function() {
	if(this.config.dist_folder){
		c.log('Cleaning dist folder')
		var del = require('del')
		var path = require('path')
		var dir = path.resolve(this.config.dir, this.config.dist_folder)
		return del.sync(dir)
	}
	return false
}

Mango.prototype.build = function(tasks, callback) {
	c.info('Building project assets for production')
	var gulp = require('gulp')

	this._registerGulpTasks(gulp)

	if(!tasks || !tasks.length){
		tasks = this.defaultTasks
		this._cleanup()
	}

	gulp.start(tasks, callback)
}

Mango.prototype.dev = function(http_proxy, callback) {
	c.info('Starting development mode and watching for assets change')
	var gulp = require('gulp')
	var runSequence = require('run-sequence')

	this.config.devmode = true

	if(typeof http_proxy !== 'undefined') {
		this.config.proxy = http_proxy
	}

	this._registerGulpTasks(gulp)
	this._cleanup()

	runSequence('compile', [ 'watch:sources', 'watch:reload' ], callback)
}

Mango.prototype._registerGulpTasks = function(gulp) {
	gulp.task('styles', require('./tasks/styles')(gulp, this.config))
	gulp.task('scripts', require('./tasks/scripts')(gulp, this.config))
	gulp.task('images', require('./tasks/images')(gulp, this.config))
	gulp.task('templates', require('./tasks/templates')(gulp, this.config))
	gulp.task('static', require('./tasks/static')(gulp, this.config))

	gulp.task('watch:sources', require('./tasks/watch_sources')(gulp, this.config))
	gulp.task('watch:reload', require('./tasks/watch_reload')(gulp, this.config))

	gulp.task('compile', this.defaultTasks)
}
<|endoftext|>


<commit_before>(function(Ember) {
 /**
  * Handles detecting and responding to media queries.
  *
  * Generally speaking, you won't ever need to create an instance of this class
  * yourself, since `Ember.Responsive` takes care of creating and configuring it
  * for you. However, it is important to document how to interact with this
  * class—which can become important during test time in particular. With that
  * said, let's take a look at how to work with it.
  *
  * **Adding media query matchers**
  *
  * The first step to using the class is to add media queries that you
  * want it to listen to. Each media query has a name that you can
  * use to reference it by.
  *
  * ```javascript
  * media = Ember.Responsive.Media.create();
  * media.match('mobile', '(max-width: 768px)');
  * media.match('desktop', '(min-width: 769px)');
  * ```
  *
  * **Testing the media query matchers**
  *
  * Now that you've added a few matchers, you can access those media queries as
  * if they were properties on your object. The nice thing is that whenever the
  * media queries change, this class will automatically update the relevant
  * properties (and so will the rest of your application, thanks to the power
  * of two-way data-binding).
  *
  * ```javascript
  * media = Ember.Responsive.Media.create();
  * media.match('mobile', '(max-width: 768px)');
  * media.match('desktop', '(min-width: 769px)');
  *
  * // There are convenient "isser" properties defined...
  * if (media.get('isMobile')) {
  *   console.log('mobile!');
  * }
  *
  * // As well as access to the matchMedia API...
  * if (media.get('desktop.matches')) {
  *   console.log('desktop!');
  * }
  * ```
  *
  * **Retrieving a list of matching media queries**
  *
  * It's also nice to be able to see which media queries are matching, since
  * some applications might have many matches at the same time.
  *
  * ```javascript
  * media = Ember.Responsive.Media.create();
  * media.match('desktop', 'all');
  * media.match('mobile', 'all');
  *
  * console.log(media.get('matches'));
  * // => Ember.Set(['desktop', 'mobile']);
  * ```
  *
  * This class can also return that list as a string of dasherized class names,
  * which is useful for placing on your app's rootElement. By default, these
  * class names are prefixed with `media-`, so as not to clash with any other
  * classes your app might use.
  *
  * ```javascript
  * App.ApplicationView = Ember.View.extend({
  *   classNameBindings: ['media.classNames']
  * });
  * ```
  *
  * @module    ember-responsive
  * @namespace Ember.Responsive
  * @class     Media
  * @extends   Ember.Object
  */
  Ember.Responsive.Media = Ember.Object.extend({
   /**
    * A set of matching matchers.
    *
    * @property  matches
    * @type      Ember.Set
    * @default   Ember.Set
    */
    matches: function() {
      return new Ember.Set();
    }.property(),

   /**
    * The matcher to use for testing media queries.
    *
    * @property  matcher
    * @type      matchMedia
    * @default   window.matchMedia
    * @private
    */
    mql: window.matchMedia,

   /**
    * A string composed of all the matching matchers' names, turned into
    * friendly, dasherized class-names that are prefixed with `media-`.
    *
    * @property  classNames
    * @type      string
    */
    classNames: function() {
      return this.get('matches').map(function(name) {
        return 'media-' + name.dasherize();
      }).join(' ');
    }.property('matches.[]'),

   /**
    * Adds a new matcher to the list.
    *
    * After this method is called, you will be able to access the result
    * of the matcher as a property on this object.
    *
    * **Adding a new matcher**
    *
    * ```javascript
    * media = Ember.Responsive.Media.create();
    * media.match('all', 'all');
    * media.get('all');
    *   // => instanceof window.matchMedia
    * media.get('all.matches');
    *   // => true
    * ```
    *
    * @param   string  name   The name of the matcher
    * @param   string  query  The media query to match against
    * @method  match
    */
    match: function(name, query) {
      var matcher = this.get('mql')(query),
          isser = 'is' + name.classify(),
          _this = this;

      var listener = function(matcher) {
        _this.set(name, matcher);

        if (matcher.matches) {
          _this.get('matches').add(name);
        } else {
          _this.get('matches').remove(name);
        }
      };

      matcher.addListener(listener);
      listener(matcher);

      // Define a corresponding "isser" which is prettier to look at and type
      Ember.defineProperty(this, isser, Ember.computed(function() {
        return this.get(name).matches;
      }).property(name));
    }
  });
})(window.Ember);
<commit_msg>Set the `isser` in the mediaquery listener<commit_after>(function(Ember) {
 /**
  * Handles detecting and responding to media queries.
  *
  * Generally speaking, you won't ever need to create an instance of this class
  * yourself, since `Ember.Responsive` takes care of creating and configuring it
  * for you. However, it is important to document how to interact with this
  * class—which can become important during test time in particular. With that
  * said, let's take a look at how to work with it.
  *
  * **Adding media query matchers**
  *
  * The first step to using the class is to add media queries that you
  * want it to listen to. Each media query has a name that you can
  * use to reference it by.
  *
  * ```javascript
  * media = Ember.Responsive.Media.create();
  * media.match('mobile', '(max-width: 768px)');
  * media.match('desktop', '(min-width: 769px)');
  * ```
  *
  * **Testing the media query matchers**
  *
  * Now that you've added a few matchers, you can access those media queries as
  * if they were properties on your object. The nice thing is that whenever the
  * media queries change, this class will automatically update the relevant
  * properties (and so will the rest of your application, thanks to the power
  * of two-way data-binding).
  *
  * ```javascript
  * media = Ember.Responsive.Media.create();
  * media.match('mobile', '(max-width: 768px)');
  * media.match('desktop', '(min-width: 769px)');
  *
  * // There are convenient "isser" properties defined...
  * if (media.get('isMobile')) {
  *   console.log('mobile!');
  * }
  *
  * // As well as access to the matchMedia API...
  * if (media.get('desktop.matches')) {
  *   console.log('desktop!');
  * }
  * ```
  *
  * **Retrieving a list of matching media queries**
  *
  * It's also nice to be able to see which media queries are matching, since
  * some applications might have many matches at the same time.
  *
  * ```javascript
  * media = Ember.Responsive.Media.create();
  * media.match('desktop', 'all');
  * media.match('mobile', 'all');
  *
  * console.log(media.get('matches'));
  * // => Ember.Set(['desktop', 'mobile']);
  * ```
  *
  * This class can also return that list as a string of dasherized class names,
  * which is useful for placing on your app's rootElement. By default, these
  * class names are prefixed with `media-`, so as not to clash with any other
  * classes your app might use.
  *
  * ```javascript
  * App.ApplicationView = Ember.View.extend({
  *   classNameBindings: ['media.classNames']
  * });
  * ```
  *
  * @module    ember-responsive
  * @namespace Ember.Responsive
  * @class     Media
  * @extends   Ember.Object
  */
  Ember.Responsive.Media = Ember.Object.extend({
   /**
    * A set of matching matchers.
    *
    * @property  matches
    * @type      Ember.Set
    * @default   Ember.Set
    */
    matches: function() {
      return new Ember.Set();
    }.property(),

   /**
    * The matcher to use for testing media queries.
    *
    * @property  matcher
    * @type      matchMedia
    * @default   window.matchMedia
    * @private
    */
    mql: window.matchMedia,

   /**
    * A string composed of all the matching matchers' names, turned into
    * friendly, dasherized class-names that are prefixed with `media-`.
    *
    * @property  classNames
    * @type      string
    */
    classNames: function() {
      return this.get('matches').map(function(name) {
        return 'media-' + name.dasherize();
      }).join(' ');
    }.property('matches.[]'),

   /**
    * Adds a new matcher to the list.
    *
    * After this method is called, you will be able to access the result
    * of the matcher as a property on this object.
    *
    * **Adding a new matcher**
    *
    * ```javascript
    * media = Ember.Responsive.Media.create();
    * media.match('all', 'all');
    * media.get('all');
    *   // => instanceof window.matchMedia
    * media.get('all.matches');
    *   // => true
    * ```
    *
    * @param   string  name   The name of the matcher
    * @param   string  query  The media query to match against
    * @method  match
    */
    match: function(name, query) {
      var matcher = this.get('mql')(query),
          isser = 'is' + name.classify(),
          _this = this;

      var listener = function(matcher) {
        _this.set(name, matcher);
        _this.set(isser, matcher.matches);

        if (matcher.matches) {
          _this.get('matches').add(name);
        } else {
          _this.get('matches').remove(name);
        }
      };

      matcher.addListener(listener);
      listener(matcher);
    }
  });
})(window.Ember);
<|endoftext|>


<commit_before>var _ = require('lodash');
var Promise = require('bluebird');

var search = require('./search');
var query = require('./query');

var modelOptions = {};

function Model(connection, defaults, opt, schema) {
    this.index = opt.index || defaults.index;
    this.type = opt.type || defaults.type;
    this.connection = connection;
    this.schema = schema;
    // TODO after the props have been set it should check to see if the index exists
    // if the index does not exists then it should create the index mapping
    // based off of the schema mappings
    // There should also be strict mapping vs non strict

    var mapping = this.schema.getIndexMapping();
    var opts = this.schema.getIndexOpts();
    var index = this.index;
    var type = this.type;
    // todo compare mappings.
    connection.indices.exists({index: this.index}, function (err, indexTest) {
        if (!indexTest) {
            console.log('creating index %s',index);
            connection.indices.create({index: index},function(err,idx){
                console.log('created index %s Error: %s',index,err);
                connection.indices.putMapping({index: index, type: type, body: mapping})
            });
        }else {
            connection.indices.getSettings({index: index, name: "index.mapper.dynamic"}, function (err, settings) {
            });
            if (opts && !opts.dynamic) {
                //  connection.indices.putSettings({index:this.index, body:{"index.mapper.dynamic":opts.dynamic}});
            }
            console.log('Putting mapping Index: %s, Type: %s, Body: %s',index, type, JSON.stringify(mapping));
            connection.indices.putMapping({index: index, type: type, body: mapping},function(err,mapData){
                console.log('Put Mapping Error: %s',err)
            });
        }
    })
}

/**
 * # Model
 */

/**
 * Creates an elasticsearch document
 *
 * To create the documents with your own id set the *opt.id* property to the id you want for that document.
 * @param  {Object}   doc the body of the elasticsearch document
 * @param  {Object}   opt Optional options objectg
 * @param  {Function} cb  Optional callback
 * @return {Promise}       If there is no callback it will return a promise
 */
Model.prototype.create = function (doc, opt, cb) {
    if (!opt) opt = {};
    var err = this.schema.validateDoc(doc);
    if (err.length > 0) {
        if (cb)
            cb({msg: err.join('\m')}, undefined);
        else
            throw new Error(err.join('\n'));
    } else {
        var body = {
            body: this.schema.applySchema(doc)
        };
        return this
            .connection
            .create(_.merge(
                {
                    index: this.index,
                    type: this.type,
                    id: opt.id
                }, body),
                cb
            );
    }
}

/**
 * Update document by id
 * @param  {String|Number|ElasticsearchId}   id  document id
 * @param  {Object}   doc body
 * @param  {Object}   opt Optional options object
 * @param  {Function} cb  Optional callback
 * @return {Promise}       If there is no callback it will return a promise
 */
Model.prototype.update = function (id, doc, opt, cb) {
    if (!opt) opt = {};

    return this
        .connection
        .update(_.merge(
            {
                index: this.index,
                type: this.type,
                id: id,
                body: {
                    doc: doc
                }
            }, opt),
            cb
        );
}

/**
 * Deletes a document based of the supllied id
 * @param  {String|Number|ElasicsearchId}   id  document id
 * @param  {Object}   opt Optional options object
 * @param  {Function} cb  Optional callback
 * @return {Promise}       If there is no callback it will return a promise
 */
Model.prototype.delete = function (id, opt, cb) {
    if (!opt) opt = {};

    return this
        .connection
        .delete(_.merge(
            {
                index: this.index,
                type: this.type,
                id: id
            }, opt),
            cb
        );
}

/**
 * Delete document by a query
 * @param  {Object}   body Query body
 * @param  {Object}   opt Optional options object
 * @param  {Function} cb  Optional callback
 * @return {Promise}       If there is no callback it will return a promise
 */
Model.prototype.deleteByQuery = function (body, opt, cb) {
    if (!opt) opt = {};

    return this
        .connection
        .deleteByQuery(_.merge(
            {
                index: this.index,
                type: this.type,
                body: body
            }, opt),
            cb
        );
}

Model.prototype = _.merge(Model.prototype, query);

Model.prototype = _.merge(Model.prototype, search);

module.exports = Model;

/**
 * ## Query API
 *
 * Click [here](https://github.com/LucioFranco/Rebound-ODM/blob/master/API.md#query) for the Query API
 *
 * ## Search API
 *
 * Click [here](https://github.com/LucioFranco/Rebound-ODM/blob/master/API.md#search) for the Search API
 */
<commit_msg>adding create index if does not exists<commit_after>var _ = require('lodash');
var Promise = require('bluebird');

var search = require('./search');
var query = require('./query');

var modelOptions = {};

function Model(connection, defaults, opt, schema) {
    this.index = opt.index || defaults.index;
    this.type = opt.type || defaults.type;
    this.connection = connection;
    this.schema = schema;
    // TODO after the props have been set it should check to see if the index exists
    // if the index does not exists then it should create the index mapping
    // based off of the schema mappings
    // There should also be strict mapping vs non strict

    var mapping = this.schema.getIndexMapping();
    var opts = this.schema.getIndexOpts();
    var index = this.index;
    var type = this.type;
    // todo compare mappings.
    connection.indices.exists({index: this.index}, function (err, indexTest) {
        if (!indexTest) {
            console.log('creating index %s',index);
            connection.indices.create({index: index},function(err,idx){
                console.log('created index %s Error: %s',index,err);
                connection.indices.putMapping({index: index, type: type, body: mapping},function(err,mapData){
                    console.log('Put Mapping Error: %s',err)
                });
            });
        }else {
            connection.indices.getSettings({index: index, name: "index.mapper.dynamic"}, function (err, settings) {
            });
            if (opts && !opts.dynamic) {
                //  connection.indices.putSettings({index:this.index, body:{"index.mapper.dynamic":opts.dynamic}});
            }
            console.log('Putting mapping Index: %s, Type: %s, Body: %s',index, type, JSON.stringify(mapping));
            connection.indices.putMapping({index: index, type: type, body: mapping},function(err,mapData){
                console.log('Put Mapping Error: %s',err)
            });
        }
    })
}

/**
 * # Model
 */

/**
 * Creates an elasticsearch document
 *
 * To create the documents with your own id set the *opt.id* property to the id you want for that document.
 * @param  {Object}   doc the body of the elasticsearch document
 * @param  {Object}   opt Optional options objectg
 * @param  {Function} cb  Optional callback
 * @return {Promise}       If there is no callback it will return a promise
 */
Model.prototype.create = function (doc, opt, cb) {
    if (!opt) opt = {};
    var err = this.schema.validateDoc(doc);
    if (err.length > 0) {
        if (cb)
            cb({msg: err.join('\m')}, undefined);
        else
            throw new Error(err.join('\n'));
    } else {
        var body = {
            body: this.schema.applySchema(doc)
        };
        return this
            .connection
            .create(_.merge(
                {
                    index: this.index,
                    type: this.type,
                    id: opt.id
                }, body),
                cb
            );
    }
}

/**
 * Update document by id
 * @param  {String|Number|ElasticsearchId}   id  document id
 * @param  {Object}   doc body
 * @param  {Object}   opt Optional options object
 * @param  {Function} cb  Optional callback
 * @return {Promise}       If there is no callback it will return a promise
 */
Model.prototype.update = function (id, doc, opt, cb) {
    if (!opt) opt = {};

    return this
        .connection
        .update(_.merge(
            {
                index: this.index,
                type: this.type,
                id: id,
                body: {
                    doc: doc
                }
            }, opt),
            cb
        );
}

/**
 * Deletes a document based of the supllied id
 * @param  {String|Number|ElasicsearchId}   id  document id
 * @param  {Object}   opt Optional options object
 * @param  {Function} cb  Optional callback
 * @return {Promise}       If there is no callback it will return a promise
 */
Model.prototype.delete = function (id, opt, cb) {
    if (!opt) opt = {};

    return this
        .connection
        .delete(_.merge(
            {
                index: this.index,
                type: this.type,
                id: id
            }, opt),
            cb
        );
}

/**
 * Delete document by a query
 * @param  {Object}   body Query body
 * @param  {Object}   opt Optional options object
 * @param  {Function} cb  Optional callback
 * @return {Promise}       If there is no callback it will return a promise
 */
Model.prototype.deleteByQuery = function (body, opt, cb) {
    if (!opt) opt = {};

    return this
        .connection
        .deleteByQuery(_.merge(
            {
                index: this.index,
                type: this.type,
                body: body
            }, opt),
            cb
        );
}

Model.prototype = _.merge(Model.prototype, query);

Model.prototype = _.merge(Model.prototype, search);

module.exports = Model;

/**
 * ## Query API
 *
 * Click [here](https://github.com/LucioFranco/Rebound-ODM/blob/master/API.md#query) for the Query API
 *
 * ## Search API
 *
 * Click [here](https://github.com/LucioFranco/Rebound-ODM/blob/master/API.md#search) for the Search API
 */
<|endoftext|>


<commit_before>var Utils          = require("./utils")
  , Mixin          = require("./associations/mixin")
  , Validator      = require("validator")
  , QueryInterface = require("./query-interface")

module.exports = (function() {
  var Model = function(values, options) {
    var self = this

    this.__definition = null // will be set in Model.build
    this.attributes = []
    this.validators = {} // holds validation settings for each attribute
    this.__options = Utils._.extend({
      underscored: false,
      hasPrimaryKeys: false,
      timestamps: true,
      paranoid: false
    }, options || {})

    initAttributes.call(this, values)
  }
  Utils._.extend(Model.prototype, Mixin.prototype)

  Model.Events = {
    insert: 'InsertQuery',
    update: 'UpdateQuery',
    destroy: 'DestroyQuery'
  }

  Object.defineProperty(Model.prototype, 'sequelize', {
    get: function(){ return this.__definition.modelManager.sequelize }
  })

  Object.defineProperty(Model.prototype, 'QueryInterface', {
    get: function(){ return this.sequelize.getQueryInterface() }
  })

  Object.defineProperty(Model.prototype, 'QueryGenerator', {
    get: function(){ return this.QueryInterface.QueryGenerator }
  })

  Model.prototype.save = function() {
    var updatedAtAttr = this.__options.underscored ? 'updated_at' : 'updatedAt'

    if(this.hasOwnProperty(updatedAtAttr))
      this[updatedAtAttr] = new Date()

    if(this.isNewRecord) {
      return this.QueryInterface.insert(this, this.__definition.tableName, this.values)
    } else {
      var identifier = this.__options.hasPrimaryKeys ? this.primaryKeyValues : this.id
        , query = this.QueryInterface.update(this, this.__definition.tableName, this.values, identifier)

      return query
    }
  }

  /*
   * Validate this model's attribute values according to validation rules set in the model definition.
   *
   * @return null if and only if validation successful; otherwise an object containing { field name : [error msgs] } entries.
   */
  Model.prototype.validate = function() {
    var self = this
    var failures = {}

    // for each field and value
    Utils._.each(self.values, function(value, field) {

      // if field has validators
      if (self.validators.hasOwnProperty(field)) {
        // for each validator
        Utils._.each(self.validators[field], function(details, validatorType) {

          var is_custom_fn = false  // if true then it's a custom validation method
          var fn_method = null      // the validation function to call
          var fn_args = []          // extra arguments to pass to validation function
          var fn_msg = ""           // the error message to return if validation fails

          // is it a custom validator function?
          if (Utils._.isFunction(details)) {
            is_custom_fn = true
            fn_method = Utils._.bind(details, self, value)
          }
          // is it a validator module function?
          else {
            // extra args
            fn_args = details.hasOwnProperty("args") ? details.args : []
            if (!Utils._.isArray(fn_args))
              fn_args = [fn_args]
            // error msg
            fn_msg = details.hasOwnProperty("msg") ? details.msg : false
            // check method exists
            var v = Validator.check(value, fn_msg)
            if (!Utils._.isFunction(v[validatorType]))
              throw new Error("Invalid validator function: " + validatorType)
            // bind to validator obj
            fn_method = Utils._.bind(v[validatorType], v)
          }

          try {
            fn_method.apply(null, fn_args)
          } catch (err) {
            err = err.message
            // if we didn't provide a custom error message then augment the default one returned by the validator
            if (!fn_msg && !is_custom_fn)
              err += ": " + field
            // each field can have multiple validation failures stored against it
            if (failures.hasOwnProperty(field)) {
              failures[field].push(err)
            } else {
              failures[field] = [err]
            }
          }

        }) // for each validator for this field
      } // if field has validator set
    }) // for each field

    return (Utils._.isEmpty(failures) ? null : failures)
  }

  Model.prototype.updateAttributes = function(updates) {
    var self = this

    var readOnlyAttributes = Utils._.keys(this.__definition.primaryKeys)
    readOnlyAttributes.push('id')
    readOnlyAttributes.push('createdAt')
    readOnlyAttributes.push('updatedAt')
    readOnlyAttributes.push('deletedAt')

    Utils._.each(updates, function(value, attr) {
      var updateAllowed = (
        (readOnlyAttributes.indexOf(attr) == -1) &&
        (readOnlyAttributes.indexOf(Utils._.underscored(attr)) == -1) &&
        (self.attributes.indexOf(attr) > -1)
      )
      updateAllowed && (self[attr] = value)
    })
    return this.save()
  }

  Model.prototype.destroy = function() {
    if(this.__options.timestamps && this.__options.paranoid) {
      var attr = this.__options.underscored ? 'deleted_at' : 'deletedAt'
      this[attr] = new Date()
      return this.save()
    } else {
      var identifier = this.__options.hasPrimaryKeys ? this.primaryKeyValues : this.id
      return this.QueryInterface.delete(this, this.__definition.tableName, identifier)
    }
  }

  Model.prototype.__defineGetter__("identifiers", function() {
    var primaryKeys = Utils._.keys(this.__definition.primaryKeys)
      , result      = {}
      , self        = this

    if(!this.__definition.hasPrimaryKeys)
      primaryKeys = ['id']

    primaryKeys.forEach(function(identifier) {
      result[identifier] = self[identifier]
    })

    return result
  })

  Model.prototype.__defineGetter__('isDeleted', function() {
    var result = this.__options.timestamps && this.__options.paranoid
    result = result && this[this.__options.underscored ? 'deleted_at' : 'deletedAt'] != null

    return result
  })

  Model.prototype.__defineGetter__('values', function() {
    var result = {}
      , self   = this

    this.attributes.forEach(function(attr) {
      result[attr] = self[attr]
    })

    return result
  })

  Model.prototype.__defineGetter__('primaryKeyValues', function() {
    var result = {}
      , self   = this

    Utils._.each(this.__definition.primaryKeys, function(_, attr) {
      result[attr] = self[attr]
    })

    return result
  })

  Model.prototype.equals = function(other) {
    var result = true
      , self   = this

    Utils._.each(this.values, function(value, key) {
      result = result && (value == other[key])
    })

    return result
  }

  Model.prototype.equalsOneOf = function(others) {
    var result = false
      , self   = this

    others.forEach(function(other) { result = result || self.equals(other) })

    return result
  }

  Model.prototype.addAttribute = function(attribute, value) {
    this[attribute] = value
    this.attributes.push(attribute)
  }

  Model.prototype.setValidators = function(attribute, validators) {
    this.validators[attribute] = validators
  }

  // private

  var initAttributes = function(values) {
    var self = this

    // add all passed values to the model and store the attribute names in this.attributes
    Utils._.map(values, function(value, key) { self.addAttribute(key, value) })

    // set id to null if not passed as value
    // a newly created model has no id
    var defaults = this.__options.hasPrimaryKeys ? {} : { id: null }

    if(this.__options.timestamps) {
      defaults[this.__options.underscored ? 'created_at' : 'createdAt'] = new Date()
      defaults[this.__options.underscored ? 'updated_at' : 'updatedAt'] = new Date()

      if(this.__options.paranoid)
        defaults[this.__options.underscored ? 'deleted_at' : 'deletedAt'] = null
    }

    Utils._.map(defaults, function(value, attr) {
      if(!self.hasOwnProperty(attr))
        self.addAttribute(attr, value)
    })
  }

  var query = function() {
    var args = Utils._.map(arguments, function(arg, _) { return arg })
      , s    = this.__definition.modelManager.sequelize

    args.push(this)
    return s.query.apply(s, args)
  }

  /* Add the instance methods to Model */
  Utils._.extend(Model.prototype, Mixin.prototype)

  return Model
})()
<commit_msg>minor refactoring<commit_after>var Utils          = require("./utils")
  , Mixin          = require("./associations/mixin")
  , Validator      = require("validator")
  , QueryInterface = require("./query-interface")

module.exports = (function() {
  var Model = function(values, options) {
    var self = this

    this.__definition = null // will be set in Model.build
    this.attributes = []
    this.validators = {} // holds validation settings for each attribute
    this.__options = Utils._.extend({
      underscored: false,
      hasPrimaryKeys: false,
      timestamps: true,
      paranoid: false
    }, options || {})

    initAttributes.call(this, values)
  }
  Utils._.extend(Model.prototype, Mixin.prototype)

  Model.Events = {
    insert: 'InsertQuery',
    update: 'UpdateQuery',
    destroy: 'DestroyQuery'
  }

  Object.defineProperty(Model.prototype, 'sequelize', {
    get: function(){ return this.__definition.modelManager.sequelize }
  })

  Object.defineProperty(Model.prototype, 'QueryInterface', {
    get: function(){ return this.sequelize.getQueryInterface() }
  })

  Object.defineProperty(Model.prototype, 'QueryGenerator', {
    get: function(){ return this.QueryInterface.QueryGenerator }
  })

  Model.prototype.save = function() {
    var updatedAtAttr = this.__options.underscored ? 'updated_at' : 'updatedAt'

    if(this.hasOwnProperty(updatedAtAttr))
      this[updatedAtAttr] = new Date()

    if(this.isNewRecord) {
      return this.QueryInterface.insert(this, this.__definition.tableName, this.values)
    } else {
      var identifier = this.__options.hasPrimaryKeys ? this.primaryKeyValues : this.id
        , tableName  = this.__definition.tableName
        , query      = this.QueryInterface.update(this, tableName, this.values, identifier)

      return query
    }
  }

  /*
   * Validate this model's attribute values according to validation rules set in the model definition.
   *
   * @return null if and only if validation successful; otherwise an object containing { field name : [error msgs] } entries.
   */
  Model.prototype.validate = function() {
    var self = this
    var failures = {}

    // for each field and value
    Utils._.each(self.values, function(value, field) {

      // if field has validators
      if (self.validators.hasOwnProperty(field)) {
        // for each validator
        Utils._.each(self.validators[field], function(details, validatorType) {

          var is_custom_fn = false  // if true then it's a custom validation method
          var fn_method = null      // the validation function to call
          var fn_args = []          // extra arguments to pass to validation function
          var fn_msg = ""           // the error message to return if validation fails

          // is it a custom validator function?
          if (Utils._.isFunction(details)) {
            is_custom_fn = true
            fn_method = Utils._.bind(details, self, value)
          }
          // is it a validator module function?
          else {
            // extra args
            fn_args = details.hasOwnProperty("args") ? details.args : []
            if (!Utils._.isArray(fn_args))
              fn_args = [fn_args]
            // error msg
            fn_msg = details.hasOwnProperty("msg") ? details.msg : false
            // check method exists
            var v = Validator.check(value, fn_msg)
            if (!Utils._.isFunction(v[validatorType]))
              throw new Error("Invalid validator function: " + validatorType)
            // bind to validator obj
            fn_method = Utils._.bind(v[validatorType], v)
          }

          try {
            fn_method.apply(null, fn_args)
          } catch (err) {
            err = err.message
            // if we didn't provide a custom error message then augment the default one returned by the validator
            if (!fn_msg && !is_custom_fn)
              err += ": " + field
            // each field can have multiple validation failures stored against it
            if (failures.hasOwnProperty(field)) {
              failures[field].push(err)
            } else {
              failures[field] = [err]
            }
          }

        }) // for each validator for this field
      } // if field has validator set
    }) // for each field

    return (Utils._.isEmpty(failures) ? null : failures)
  }

  Model.prototype.updateAttributes = function(updates) {
    var self = this

    var readOnlyAttributes = Utils._.keys(this.__definition.primaryKeys)
    readOnlyAttributes.push('id')
    readOnlyAttributes.push('createdAt')
    readOnlyAttributes.push('updatedAt')
    readOnlyAttributes.push('deletedAt')

    Utils._.each(updates, function(value, attr) {
      var updateAllowed = (
        (readOnlyAttributes.indexOf(attr) == -1) &&
        (readOnlyAttributes.indexOf(Utils._.underscored(attr)) == -1) &&
        (self.attributes.indexOf(attr) > -1)
      )
      updateAllowed && (self[attr] = value)
    })
    return this.save()
  }

  Model.prototype.destroy = function() {
    if(this.__options.timestamps && this.__options.paranoid) {
      var attr = this.__options.underscored ? 'deleted_at' : 'deletedAt'
      this[attr] = new Date()
      return this.save()
    } else {
      var identifier = this.__options.hasPrimaryKeys ? this.primaryKeyValues : this.id
      return this.QueryInterface.delete(this, this.__definition.tableName, identifier)
    }
  }

  Model.prototype.__defineGetter__("identifiers", function() {
    var primaryKeys = Utils._.keys(this.__definition.primaryKeys)
      , result      = {}
      , self        = this

    if(!this.__definition.hasPrimaryKeys)
      primaryKeys = ['id']

    primaryKeys.forEach(function(identifier) {
      result[identifier] = self[identifier]
    })

    return result
  })

  Model.prototype.__defineGetter__('isDeleted', function() {
    var result = this.__options.timestamps && this.__options.paranoid
    result = result && this[this.__options.underscored ? 'deleted_at' : 'deletedAt'] != null

    return result
  })

  Model.prototype.__defineGetter__('values', function() {
    var result = {}
      , self   = this

    this.attributes.forEach(function(attr) {
      result[attr] = self[attr]
    })

    return result
  })

  Model.prototype.__defineGetter__('primaryKeyValues', function() {
    var result = {}
      , self   = this

    Utils._.each(this.__definition.primaryKeys, function(_, attr) {
      result[attr] = self[attr]
    })

    return result
  })

  Model.prototype.equals = function(other) {
    var result = true
      , self   = this

    Utils._.each(this.values, function(value, key) {
      result = result && (value == other[key])
    })

    return result
  }

  Model.prototype.equalsOneOf = function(others) {
    var result = false
      , self   = this

    others.forEach(function(other) { result = result || self.equals(other) })

    return result
  }

  Model.prototype.addAttribute = function(attribute, value) {
    this[attribute] = value
    this.attributes.push(attribute)
  }

  Model.prototype.setValidators = function(attribute, validators) {
    this.validators[attribute] = validators
  }

  // private

  var initAttributes = function(values) {
    var self = this

    // add all passed values to the model and store the attribute names in this.attributes
    Utils._.map(values, function(value, key) { self.addAttribute(key, value) })

    // set id to null if not passed as value
    // a newly created model has no id
    var defaults = this.__options.hasPrimaryKeys ? {} : { id: null }

    if(this.__options.timestamps) {
      defaults[this.__options.underscored ? 'created_at' : 'createdAt'] = new Date()
      defaults[this.__options.underscored ? 'updated_at' : 'updatedAt'] = new Date()

      if(this.__options.paranoid)
        defaults[this.__options.underscored ? 'deleted_at' : 'deletedAt'] = null
    }

    Utils._.map(defaults, function(value, attr) {
      if(!self.hasOwnProperty(attr))
        self.addAttribute(attr, value)
    })
  }

  var query = function() {
    var args = Utils._.map(arguments, function(arg, _) { return arg })
      , s    = this.__definition.modelManager.sequelize

    args.push(this)
    return s.query.apply(s, args)
  }

  /* Add the instance methods to Model */
  Utils._.extend(Model.prototype, Mixin.prototype)

  return Model
})()
<|endoftext|>