<commit_before>const crypto = require('crypto');
const fs = require('fs');

function errCode (fn) {
  return (...args) => {
    try {
      let ret = fn(...args);
      if (ret == null) { ret = {}; }
      return Object.assign(ret, {err_code: 0});
    } catch (err) {
      let err_code = (err.err_code == null ? -1 : err.err_code); // eslint-disable-line camelcase
      let err_msg = (err.err_msg == null ? err : err.err_msg) + ''; // eslint-disable-line camelcase
      return { err_code, err_msg };
    }
  };
}

function readJson (path, cb) {
  return new Promise((resolve, reject) => {
    fs.readFile(path, (err, data) => {
      if (err) {
        reject(err);
      } else {
        resolve(JSON.parse(data));
      }
    });
  });
}

function randomMac (prefix, delim = ':') {
  var mac = prefix || ['50', 'c7', 'bf'].join(delim);

  for (var i = 0; i < 6; i++) {
    if (i % 2 === 0) mac += delim;
    mac += Math.floor(Math.random() * 16).toString(16);
  }

  return mac;
}

function generateId (len) {
  return crypto.randomBytes(len / 2).toString('hex').toUpperCase();
}

function randomInt (min, max) {
  // The maximum is inclusive and the minimum is inclusive
  min = Math.ceil(min);
  max = Math.floor(max);
  return Math.floor(Math.random() * (max - min + 1)) + min;
}

function randomFloat (min, max) {
  return Math.random() * (max - min) + min;
}

function randomLatitude ({fixed = 4, min = -90, max = 90} = {}) {
  return randomFloat(min, max).toFixed(fixed);
}

function randomLongitude ({fixed = 4, min = -180, max = 180} = {}) {
  return randomFloat(min, max).toFixed(fixed);
}

function getDaysInMonth (year, month) {
  var date = new Date(year, month - 1, 1);
  var result = [];
  while (date.getMonth() === month - 1) {
    result.push(date.getDate());
    date.setDate(date.getDate() + 1);
  }
  return result;
}

function getDayList (year, month, key, dayListData = [], defaultValue) {
  let dayList = [];
  if (year != null && month != null) {
    let now = new Date();
    let lastDay;
    if (now.getFullYear() === year && now.getMonth() + 1 === month) {
      lastDay = now.getDate();
    }
    getDaysInMonth(year, month).forEach((day) => {
      if (day > lastDay) return; // Don't return data for future dates
      let entry = dayListData.find((dl) => (dl.year === year && dl.month === month && dl.day === day));
      if (entry == null) {
        let def = (typeof defaultValue === 'function' ? defaultValue(year, month, day) : defaultValue);
        entry = { year, month, day, [key]: def };
        dayListData.push(entry);
      }
      dayList.push(entry);
    });
  }
  return dayList;
}

function getMonthList (year, key, dayListData = [], defaultValue) {
  let monthList = [];
  if (year != null) {
    for (var month = 1; month <= 12; month++) {
      let monthSum = getDayList(year, month, key, dayListData, defaultValue).reduce((acc, val) => (acc + val[key]), 0);
      monthList.push({ year, month, [key]: monthSum });
    }
  }
  return monthList;
}

function editRule (rules, rule) {
  if (rule.id == null) {
    throw { err_code: -3, err_msg: 'invalid argument' }; // eslint-disable-line no-throw-literal
  }
  let existingRule = rules.find((r, i, a) => {
    if (r.id === rule.id) {
      a[i] = rule;
    }
  });
  if (existingRule == null) {
    throw { err_code: -14, err_msg: 'entry not exist' }; // eslint-disable-line no-throw-literal
  }
}

function deleteRule (rules, id) {
  let rule = rules.find((r, i, a) => {
    if (r.id === id) {
      a.splice(i, 1); // remove rule
      return true;
    }
  });
  if (rule == null) {
    throw { err_code: -14, err_msg: 'entry not exist' }; // eslint-disable-line no-throw-literal
  }
}

module.exports = {
  errCode,
  randomMac,
  generateId,
  randomInt,
  randomFloat,
  randomLatitude,
  randomLongitude,
  getDayList,
  getMonthList,
  editRule,
  deleteRule,
  readJson
};
<commit_msg>use strict<commit_after>'use strict';

const crypto = require('crypto');
const fs = require('fs');

function errCode (fn) {
  return (...args) => {
    try {
      let ret = fn(...args);
      if (ret == null) { ret = {}; }
      return Object.assign(ret, {err_code: 0});
    } catch (err) {
      let err_code = (err.err_code == null ? -1 : err.err_code); // eslint-disable-line camelcase
      let err_msg = (err.err_msg == null ? err : err.err_msg) + ''; // eslint-disable-line camelcase
      return { err_code, err_msg };
    }
  };
}

function readJson (path, cb) {
  return new Promise((resolve, reject) => {
    fs.readFile(path, (err, data) => {
      if (err) {
        reject(err);
      } else {
        resolve(JSON.parse(data));
      }
    });
  });
}

function randomMac (prefix, delim = ':') {
  var mac = prefix || ['50', 'c7', 'bf'].join(delim);

  for (var i = 0; i < 6; i++) {
    if (i % 2 === 0) mac += delim;
    mac += Math.floor(Math.random() * 16).toString(16);
  }

  return mac;
}

function generateId (len) {
  return crypto.randomBytes(len / 2).toString('hex').toUpperCase();
}

function randomInt (min, max) {
  // The maximum is inclusive and the minimum is inclusive
  min = Math.ceil(min);
  max = Math.floor(max);
  return Math.floor(Math.random() * (max - min + 1)) + min;
}

function randomFloat (min, max) {
  return Math.random() * (max - min) + min;
}

function randomLatitude ({fixed = 4, min = -90, max = 90} = {}) {
  return randomFloat(min, max).toFixed(fixed);
}

function randomLongitude ({fixed = 4, min = -180, max = 180} = {}) {
  return randomFloat(min, max).toFixed(fixed);
}

function getDaysInMonth (year, month) {
  var date = new Date(year, month - 1, 1);
  var result = [];
  while (date.getMonth() === month - 1) {
    result.push(date.getDate());
    date.setDate(date.getDate() + 1);
  }
  return result;
}

function getDayList (year, month, key, dayListData = [], defaultValue) {
  let dayList = [];
  if (year != null && month != null) {
    let now = new Date();
    let lastDay;
    if (now.getFullYear() === year && now.getMonth() + 1 === month) {
      lastDay = now.getDate();
    }
    getDaysInMonth(year, month).forEach((day) => {
      if (day > lastDay) return; // Don't return data for future dates
      let entry = dayListData.find((dl) => (dl.year === year && dl.month === month && dl.day === day));
      if (entry == null) {
        let def = (typeof defaultValue === 'function' ? defaultValue(year, month, day) : defaultValue);
        entry = { year, month, day, [key]: def };
        dayListData.push(entry);
      }
      dayList.push(entry);
    });
  }
  return dayList;
}

function getMonthList (year, key, dayListData = [], defaultValue) {
  let monthList = [];
  if (year != null) {
    for (var month = 1; month <= 12; month++) {
      let monthSum = getDayList(year, month, key, dayListData, defaultValue).reduce((acc, val) => (acc + val[key]), 0);
      monthList.push({ year, month, [key]: monthSum });
    }
  }
  return monthList;
}

function editRule (rules, rule) {
  if (rule.id == null) {
    throw { err_code: -3, err_msg: 'invalid argument' }; // eslint-disable-line no-throw-literal
  }
  let existingRule = rules.find((r, i, a) => {
    if (r.id === rule.id) {
      a[i] = rule;
    }
  });
  if (existingRule == null) {
    throw { err_code: -14, err_msg: 'entry not exist' }; // eslint-disable-line no-throw-literal
  }
}

function deleteRule (rules, id) {
  let rule = rules.find((r, i, a) => {
    if (r.id === id) {
      a.splice(i, 1); // remove rule
      return true;
    }
  });
  if (rule == null) {
    throw { err_code: -14, err_msg: 'entry not exist' }; // eslint-disable-line no-throw-literal
  }
}

module.exports = {
  errCode,
  randomMac,
  generateId,
  randomInt,
  randomFloat,
  randomLatitude,
  randomLongitude,
  getDayList,
  getMonthList,
  editRule,
  deleteRule,
  readJson
};
<|endoftext|>


<commit_before>
var BYTE = 1,
    KB = 1024 * BYTE,
    MB = 1024 * KB,
    GB = 1024 * MB,
    TB = 1024 * GB,
    PB = 1024 * TB;

var MILLISECOND = 1,
    SECOND = 1000 * MILLISECOND,
    MINUTE = 60 * SECOND,
    HOUR = 60 * MINUTE,
    DAY = 24 * HOUR,
    WEEK = 7 * DAY,
    MONTH = 30 * DAY,
    YEAR = 365 * DAY;

//
// "This one will strictly match latitude and longitude values that fall within the correct range:"
// ...
// Matches
//
// +90.0, -127.554334 45, 180
// -90, -180
// -90.000, -180.0000
// +90, +180
// 47.1231231, 179.99999999
// Doesn't Match
//
// -90., -180.
// +90.1, -100.111
// -91, 123.456
// 045, 180
//
// @see: http://stackoverflow.com/a/18690202/1690165
//
var GPSRegExp = new RegExp(/^[-+]?([1-8]?\d(\.\d+)?|90(\.0+)?),\s*[-+]?(180(\.0+)?|((1[0-7]\d)|([1-9]?\d))(\.\d+)?)$/)

// @see - http://killdream.github.io/blog/2011/10/understanding-javascript-oop/index.html

// Aliases for the rather verbose methods on ES5
var descriptor  = Object.getOwnPropertyDescriptor,
    properties  = Object.getOwnPropertyNames,
    define_prop = Object.defineProperty;

function clone(parent) {
    var cloned = {};
    properties(parent).forEach(function(key) {
        define_prop(cloned, key, descriptor(parent, key))
    });

    return cloned;
};

function extend(original, extensions) {

    original = original || {};
    extensions = extensions || {};

    properties(extensions).forEach(function(key) {
        define_prop(original, key, descriptor(extensions, key))
    });

    return original;
};

function getType (obj) {
  return (Number.isNaN(obj)) ? 'NaN' : ({}).toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase()
};

// returns that to which an XOR expression would evaluate
function XOR (a,b) {
  return ( a || b ) && !( a && b );
};

module.exports = {

    clone: clone,

    // emitter: function () {
    //     var cloned
    // }
    extend: extend,
    getType: getType,
    XOR: XOR,
    GPSRegExp: GPSRegExp,

    BYTE: BYTE,
    KB: KB,
    MB: MB,
    GB: GB,
    TB: TB,
    PB: PB,

    MILLISECOND: MILLISECOND,
    SECOND: SECOND,
    MINUTE: MINUTE,
    HOUR: HOUR,
    DAY: DAY,
    WEEK: WEEK,
    MONTH: MONTH,
    YEAR: YEAR
};
<commit_msg>added LatRegExp and LngRegExp<commit_after>
var BYTE = 1,
    KB = 1024 * BYTE,
    MB = 1024 * KB,
    GB = 1024 * MB,
    TB = 1024 * GB,
    PB = 1024 * TB;

var MILLISECOND = 1,
    SECOND = 1000 * MILLISECOND,
    MINUTE = 60 * SECOND,
    HOUR = 60 * MINUTE,
    DAY = 24 * HOUR,
    WEEK = 7 * DAY,
    MONTH = 30 * DAY,
    YEAR = 365 * DAY;

//
// "This one will strictly match latitude and longitude values that fall within the correct range:"
// ...
// Matches
//
// +90.0, -127.554334 45, 180
// -90, -180
// -90.000, -180.0000
// +90, +180
// 47.1231231, 179.99999999
// Doesn't Match
//
// -90., -180.
// +90.1, -100.111
// -91, 123.456
// 045, 180
//
// @see: http://stackoverflow.com/a/18690202/1690165
//
var GPSRegExp = new RegExp(/^[-+]?([1-8]?\d(\.\d+)?|90(\.0+)?),\s*[-+]?(180(\.0+)?|((1[0-7]\d)|([1-9]?\d))(\.\d+)?)$/)

// matches valid latitude strings
var LatRegExp = new RegExp(/^[-+]?([1-8]?\d(\.\d+)?|90(\.0+)?)$/);

// matches valid longitude strings
var LngRegExp = new RegExp(/^[-+]?(180(\.0+)?|((1[0-7]\d)|([1-9]?\d))(\.\d+)?)$/);

// @see - http://killdream.github.io/blog/2011/10/understanding-javascript-oop/index.html

// Aliases for the rather verbose methods on ES5
var descriptor  = Object.getOwnPropertyDescriptor,
    properties  = Object.getOwnPropertyNames,
    define_prop = Object.defineProperty;

function clone(parent) {
    var cloned = {};
    properties(parent).forEach(function(key) {
        define_prop(cloned, key, descriptor(parent, key))
    });

    return cloned;
};

function extend(original, extensions) {

    original = original || {};
    extensions = extensions || {};

    properties(extensions).forEach(function(key) {
        define_prop(original, key, descriptor(extensions, key))
    });

    return original;
};

function getType (obj) {
  return (Number.isNaN(obj)) ? 'NaN' : ({}).toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase()
};

// returns that to which an XOR expression would evaluate
function XOR (a,b) {
  return ( a || b ) && !( a && b );
};

module.exports = {

    clone: clone,

    // emitter: function () {
    //     var cloned
    // }
    extend: extend,
    getType: getType,
    XOR: XOR,
    GPSRegExp: GPSRegExp,

    BYTE: BYTE,
    KB: KB,
    MB: MB,
    GB: GB,
    TB: TB,
    PB: PB,

    MILLISECOND: MILLISECOND,
    SECOND: SECOND,
    MINUTE: MINUTE,
    HOUR: HOUR,
    DAY: DAY,
    WEEK: WEEK,
    MONTH: MONTH,
    YEAR: YEAR
};
<|endoftext|>


<commit_before>'use strict';

var DataTypes = require('./data-types')
  , SqlString = require('./sql-string')
  , lodash = require('lodash')
  , ParameterValidator = require('./utils/parameter-validator')
  , inflection = require('inflection')
  , dottie = require('dottie')
  , uuid = require('node-uuid')
  , deprecate = require('depd')('Utils');

var Utils = module.exports = {
  inflection: inflection,
  _: (function() {
    var _ = lodash;

    _.mixin({
      includes: function(str, needle){
        if (needle === '') return true;
        if (str === null) return false;
        return String(str).indexOf(needle) !== -1;
      },
      camelizeIf: function(string, condition) {
        var result = string;

        if (condition) {
          result = Utils.camelize(string);
        }

        return result;
      },
      underscoredIf: function(string, condition) {
        var result = string;

        if (condition) {
          result = inflection.underscore(string);
        }

        return result;
      },
      /*
       * Returns an array with some falsy values removed. The values null, "", undefined and NaN are considered falsey.
       */
      compactLite: function(array) {
        var index = -1,
          length = array ? array.length : 0,
          result = [];

        while (++index < length) {
          var value = array[index];
          if (typeof value === 'boolean' || value === 0 || value) {
            result.push(value);
          }
        }
        return result;
      },
      matchesDots: function (dots, value) {
        return function (item) {
          return dottie.get(item, dots) === value;
        };
      }
    });

    return _;
  })(),
  // Same concept as _.merge, but don't overwrite properties that have already been assigned
  mergeDefaults: function (a, b) {
    return this._.merge(a, b, function (objectValue, sourceValue) {
      // If it's an object, let _ handle it this time, we will be called again for each property
      if (!this._.isPlainObject(objectValue) && objectValue !== undefined) {
        return objectValue;
      }
    }, this);
  },
  lowercaseFirst: function (s) {
    return s[0].toLowerCase() + s.slice(1);
  },
  uppercaseFirst: function (s) {
    return s[0].toUpperCase() + s.slice(1);
  },
  spliceStr: function (str, index, count, add) {
    return str.slice(0, index) + add + str.slice(index + count);
  },
  camelize: function(str){
    return str.trim().replace(/[-_\s]+(.)?/g, function(match, c){ return c.toUpperCase(); });
  },
  format: function(arr, dialect) {
    var timeZone = null;
    // Make a clone of the array beacuse format modifies the passed args
    return SqlString.format(arr[0], arr.slice(1), timeZone, dialect);
  },
  formatNamedParameters: function(sql, parameters, dialect) {
    var timeZone = null;
    return SqlString.formatNamedParameters(sql, parameters, timeZone, dialect);
  },
  cloneDeep: function(obj, fn) {
    return lodash.cloneDeep(obj, function (elem) {
      // Unfortunately, lodash.cloneDeep doesn't preserve Buffer.isBuffer, which we have to rely on for binary data
      if (Buffer.isBuffer(elem)) { return elem; }

      return fn ? fn(elem) : undefined;
    });
  },

  /* Used to map field names in attributes and where conditions */
  mapOptionFieldNames: function(options, Model) {
    if (options.attributes) {
      options.attributes = options.attributes.map(function(attr) {
        // Object lookups will force any variable to strings, we don't want that for special objects etc
        if (typeof attr !== 'string') return attr;
        // Map attributes to aliased syntax attributes
        if (Model.rawAttributes[attr] && attr !== Model.rawAttributes[attr].field) {
          return [Model.rawAttributes[attr].field, attr];
        }
        return attr;
      });
    }

    if (options.where) {
      var attributes = options.where
        , attribute
        , rawAttribute;

      if (options.where instanceof Utils.and || options.where instanceof Utils.or) {
        attributes = undefined;
        options.where.args = options.where.args.map(function (where) {
          return Utils.mapOptionFieldNames({
            where: where
          }, Model).where;
        });
      }

      if (attributes) {
        for (attribute in attributes) {
          rawAttribute = Model.rawAttributes[attribute];
          if (rawAttribute && rawAttribute.field !== rawAttribute.fieldName) {
            attributes[rawAttribute.field] = attributes[attribute];
            delete attributes[attribute];
          }

          if (lodash.isPlainObject(attributes[attribute])) {
            attributes[attribute] = Utils.mapOptionFieldNames({
              where: attributes[attribute]
            }, Model).where;
          }

          if (Array.isArray(attributes[attribute])) {
            attributes[attribute] = attributes[attribute].map(function (where) {
              return Utils.mapOptionFieldNames({
                where: where
              }, Model).where;
            });
          }
        }
      }
    }
    return options;
  },

  /* Used to map field names in values */
  mapValueFieldNames: function (dataValues, fields, Model) {
    var values = {};

    fields.forEach(function(attr) {
      if (dataValues[attr] !== undefined && !Model._isVirtualAttribute(attr)) {
        // Field name mapping
        if (Model.rawAttributes[attr] && Model.rawAttributes[attr].field && Model.rawAttributes[attr].field !== attr) {
          values[Model.rawAttributes[attr].field] = dataValues[attr];
        } else {
          values[attr] = dataValues[attr];
        }
      }
    });

    return values;
  },
  argsArePrimaryKeys: function(args, primaryKeys) {
    var result = (args.length === Object.keys(primaryKeys).length);
    if (result) {
      Utils._.each(args, function(arg) {
        if (result) {
          if (['number', 'string'].indexOf(typeof arg) !== -1) {
            result = true;
          } else {
            result = (arg instanceof Date) || Buffer.isBuffer(arg);
          }
        }
      });
    }
    return result;
  },
  canTreatArrayAsAnd: function(arr) {
    return arr.reduce(function(treatAsAnd, arg) {
      if (treatAsAnd) {
        return treatAsAnd;
      } else {
        return !(arg instanceof Date) && ((arg instanceof Utils.and) || (arg instanceof Utils.or) || Utils._.isPlainObject(arg));
      }
    }, false);
  },

  combineTableNames: function(tableName1, tableName2) {
    return (tableName1.toLowerCase() < tableName2.toLowerCase()) ? (tableName1 + tableName2) : (tableName2 + tableName1);
  },

  singularize: function(s) {
    return inflection.singularize(s);
  },

  pluralize: function(s) {
    return inflection.pluralize(s);
  },

  removeCommentsFromFunctionString: function(s) {
    s = s.replace(/\s*(\/\/.*)/g, '');
    s = s.replace(/(\/\*[\n\r\s\S]*?\*\/)/mg, '');

    return s;
  },

  toDefaultValue: function(value) {
    if (typeof value === 'function') {
      var tmp = value();
      if (tmp instanceof DataTypes.ABSTRACT) {
        return tmp.toSql();
      } else {
        return tmp;
      }
    } else if (value instanceof DataTypes.UUIDV1) {
      return uuid.v1();
    } else if (value instanceof DataTypes.UUIDV4) {
      return uuid.v4();
    } else if (value instanceof DataTypes.NOW) {
      return Utils.now();
    } else {
      return value;
    }
  },

  /**
   * Determine if the default value provided exists and can be described
   * in a db schema using the DEFAULT directive.
   *
   * @param  {*} value Any default value.
   * @return {boolean} yes / no.
   */
  defaultValueSchemable: function(value) {
    if (typeof value === 'undefined') { return false; }

    // TODO this will be schemable when all supported db
    // have been normalized for this case
    if (value instanceof DataTypes.NOW) { return false; }

    if (value instanceof DataTypes.UUIDV1 || value instanceof DataTypes.UUIDV4) { return false; }

    if (lodash.isFunction(value)) {
      return false;
    }

    return true;
  },

  removeNullValuesFromHash: function(hash, omitNull, options) {
    var result = hash;

    options = options || {};
    options.allowNull = options.allowNull || [];

    if (omitNull) {
      var _hash = {};

      Utils._.forIn(hash, function(val, key) {
        if (options.allowNull.indexOf(key) > -1 || key.match(/Id$/) || ((val !== null) && (val !== undefined))) {
          _hash[key] = val;
        }
      });

      result = _hash;
    }

    return result;
  },

  inherit: function(SubClass, SuperClass) {
    if (SuperClass.constructor === Function) {
      // Normal Inheritance
      SubClass.prototype = new SuperClass();
      SubClass.prototype.constructor = SubClass;
      SubClass.prototype.parent = SuperClass.prototype;
    } else {
      // Pure Virtual Inheritance
      SubClass.prototype = SuperClass;
      SubClass.prototype.constructor = SubClass;
      SubClass.prototype.parent = SuperClass;
    }

    return SubClass;
  },

  stack: function _stackGrabber() {
    var orig = Error.prepareStackTrace;
    Error.prepareStackTrace = function(_, stack) { return stack; };
    var err = new Error();
    Error.captureStackTrace(err, _stackGrabber);
    var errStack = err.stack;
    Error.prepareStackTrace = orig;
    return errStack;
  },

  sliceArgs: function (args, begin) {
    begin = begin || 0;
    var tmp = new Array(args.length - begin);
    for (var i = begin; i < args.length; ++i) {
        tmp[i - begin] = args[i];
    }
    return tmp;
  },

  now: function(dialect) {
    var now = new Date();
    if (dialect !== 'postgres') now.setMilliseconds(0);
    return now;
  },

  tick: function(func) {
    var tick = (global.hasOwnProperty('setImmediate') ? global.setImmediate : process.nextTick);
    tick(func);
  },

  // Note: Use the `quoteIdentifier()` and `escape()` methods on the
  // `QueryInterface` instead for more portable code.

  TICK_CHAR: '`',
  addTicks: function(s, tickChar) {
    tickChar = tickChar || Utils.TICK_CHAR;
    return tickChar + Utils.removeTicks(s, tickChar) + tickChar;
  },
  removeTicks: function(s, tickChar) {
    tickChar = tickChar || Utils.TICK_CHAR;
    return s.replace(new RegExp(tickChar, 'g'), '');
  },

  /*
   * Utility functions for representing SQL functions, and columns that should be escaped.
   * Please do not use these functions directly, use Sequelize.fn and Sequelize.col instead.
   */
  fn: function(fn, args) {
    this.fn = fn;
    this.args = args;
  },

  col: function(col) {
    if (arguments.length > 1) {
      col = this.sliceArgs(arguments);
    }
    this.col = col;
  },

  cast: function(val, type) {
    this.val = val;
    this.type = (type || '').trim();
  },

  literal: function(val) {
    this.val = val;
  },

  and: function(args) {
    this.args = args;
  },

  or: function(args) {
    this.args = args;
  },

  json: function(conditionsOrPath, value) {
    if (Utils._.isObject(conditionsOrPath)) {
      this.conditions = conditionsOrPath;
    } else {
      this.path = conditionsOrPath;
      if (value) {
        this.value = value;
      }
    }
  },

  where: function(attribute, comparator, logic) {
    if (logic === undefined) {
      logic = comparator;
      comparator = '=';
    }

    this.attribute = attribute;
    this.comparator = comparator;
    this.logic = logic;
  },

  validateParameter: function(value, expectation, options) {
    return ParameterValidator.check(value, expectation, options);
  },

  formatReferences: function (obj) {
    if (!lodash.isPlainObject(obj.references)) {
      deprecate('Non-object references property found. Support for that will be removed in version 4. Expected { references: { model: "value", key: "key" } } instead of { references: "value", referencesKey: "key" }.');
      obj.references = { model: obj.references, key: obj.referencesKey, deferrable: obj.referencesDeferrable };
      obj.referencesKey = undefined;
      obj.referencesDeferrable = undefined;
    }

    return obj;
  }
};

Utils.and.prototype._isSequelizeMethod =
Utils.or.prototype._isSequelizeMethod =
Utils.where.prototype._isSequelizeMethod =
Utils.literal.prototype._isSequelizeMethod =
Utils.cast.prototype._isSequelizeMethod =
Utils.fn.prototype._isSequelizeMethod =
Utils.col.prototype._isSequelizeMethod =
Utils.json.prototype._isSequelizeMethod = true;

Utils.Promise = require('./promise');
<commit_msg>:bug: Add millisecond precision for sqlite. Closes #3793<commit_after>'use strict';

var DataTypes = require('./data-types')
  , SqlString = require('./sql-string')
  , lodash = require('lodash')
  , ParameterValidator = require('./utils/parameter-validator')
  , inflection = require('inflection')
  , dottie = require('dottie')
  , uuid = require('node-uuid')
  , deprecate = require('depd')('Utils');

var Utils = module.exports = {
  inflection: inflection,
  _: (function() {
    var _ = lodash;

    _.mixin({
      includes: function(str, needle){
        if (needle === '') return true;
        if (str === null) return false;
        return String(str).indexOf(needle) !== -1;
      },
      camelizeIf: function(string, condition) {
        var result = string;

        if (condition) {
          result = Utils.camelize(string);
        }

        return result;
      },
      underscoredIf: function(string, condition) {
        var result = string;

        if (condition) {
          result = inflection.underscore(string);
        }

        return result;
      },
      /*
       * Returns an array with some falsy values removed. The values null, "", undefined and NaN are considered falsey.
       */
      compactLite: function(array) {
        var index = -1,
          length = array ? array.length : 0,
          result = [];

        while (++index < length) {
          var value = array[index];
          if (typeof value === 'boolean' || value === 0 || value) {
            result.push(value);
          }
        }
        return result;
      },
      matchesDots: function (dots, value) {
        return function (item) {
          return dottie.get(item, dots) === value;
        };
      }
    });

    return _;
  })(),
  // Same concept as _.merge, but don't overwrite properties that have already been assigned
  mergeDefaults: function (a, b) {
    return this._.merge(a, b, function (objectValue, sourceValue) {
      // If it's an object, let _ handle it this time, we will be called again for each property
      if (!this._.isPlainObject(objectValue) && objectValue !== undefined) {
        return objectValue;
      }
    }, this);
  },
  lowercaseFirst: function (s) {
    return s[0].toLowerCase() + s.slice(1);
  },
  uppercaseFirst: function (s) {
    return s[0].toUpperCase() + s.slice(1);
  },
  spliceStr: function (str, index, count, add) {
    return str.slice(0, index) + add + str.slice(index + count);
  },
  camelize: function(str){
    return str.trim().replace(/[-_\s]+(.)?/g, function(match, c){ return c.toUpperCase(); });
  },
  format: function(arr, dialect) {
    var timeZone = null;
    // Make a clone of the array beacuse format modifies the passed args
    return SqlString.format(arr[0], arr.slice(1), timeZone, dialect);
  },
  formatNamedParameters: function(sql, parameters, dialect) {
    var timeZone = null;
    return SqlString.formatNamedParameters(sql, parameters, timeZone, dialect);
  },
  cloneDeep: function(obj, fn) {
    return lodash.cloneDeep(obj, function (elem) {
      // Unfortunately, lodash.cloneDeep doesn't preserve Buffer.isBuffer, which we have to rely on for binary data
      if (Buffer.isBuffer(elem)) { return elem; }

      return fn ? fn(elem) : undefined;
    });
  },

  /* Used to map field names in attributes and where conditions */
  mapOptionFieldNames: function(options, Model) {
    if (options.attributes) {
      options.attributes = options.attributes.map(function(attr) {
        // Object lookups will force any variable to strings, we don't want that for special objects etc
        if (typeof attr !== 'string') return attr;
        // Map attributes to aliased syntax attributes
        if (Model.rawAttributes[attr] && attr !== Model.rawAttributes[attr].field) {
          return [Model.rawAttributes[attr].field, attr];
        }
        return attr;
      });
    }

    if (options.where) {
      var attributes = options.where
        , attribute
        , rawAttribute;

      if (options.where instanceof Utils.and || options.where instanceof Utils.or) {
        attributes = undefined;
        options.where.args = options.where.args.map(function (where) {
          return Utils.mapOptionFieldNames({
            where: where
          }, Model).where;
        });
      }

      if (attributes) {
        for (attribute in attributes) {
          rawAttribute = Model.rawAttributes[attribute];
          if (rawAttribute && rawAttribute.field !== rawAttribute.fieldName) {
            attributes[rawAttribute.field] = attributes[attribute];
            delete attributes[attribute];
          }

          if (lodash.isPlainObject(attributes[attribute])) {
            attributes[attribute] = Utils.mapOptionFieldNames({
              where: attributes[attribute]
            }, Model).where;
          }

          if (Array.isArray(attributes[attribute])) {
            attributes[attribute] = attributes[attribute].map(function (where) {
              return Utils.mapOptionFieldNames({
                where: where
              }, Model).where;
            });
          }
        }
      }
    }
    return options;
  },

  /* Used to map field names in values */
  mapValueFieldNames: function (dataValues, fields, Model) {
    var values = {};

    fields.forEach(function(attr) {
      if (dataValues[attr] !== undefined && !Model._isVirtualAttribute(attr)) {
        // Field name mapping
        if (Model.rawAttributes[attr] && Model.rawAttributes[attr].field && Model.rawAttributes[attr].field !== attr) {
          values[Model.rawAttributes[attr].field] = dataValues[attr];
        } else {
          values[attr] = dataValues[attr];
        }
      }
    });

    return values;
  },
  argsArePrimaryKeys: function(args, primaryKeys) {
    var result = (args.length === Object.keys(primaryKeys).length);
    if (result) {
      Utils._.each(args, function(arg) {
        if (result) {
          if (['number', 'string'].indexOf(typeof arg) !== -1) {
            result = true;
          } else {
            result = (arg instanceof Date) || Buffer.isBuffer(arg);
          }
        }
      });
    }
    return result;
  },
  canTreatArrayAsAnd: function(arr) {
    return arr.reduce(function(treatAsAnd, arg) {
      if (treatAsAnd) {
        return treatAsAnd;
      } else {
        return !(arg instanceof Date) && ((arg instanceof Utils.and) || (arg instanceof Utils.or) || Utils._.isPlainObject(arg));
      }
    }, false);
  },

  combineTableNames: function(tableName1, tableName2) {
    return (tableName1.toLowerCase() < tableName2.toLowerCase()) ? (tableName1 + tableName2) : (tableName2 + tableName1);
  },

  singularize: function(s) {
    return inflection.singularize(s);
  },

  pluralize: function(s) {
    return inflection.pluralize(s);
  },

  removeCommentsFromFunctionString: function(s) {
    s = s.replace(/\s*(\/\/.*)/g, '');
    s = s.replace(/(\/\*[\n\r\s\S]*?\*\/)/mg, '');

    return s;
  },

  toDefaultValue: function(value) {
    if (typeof value === 'function') {
      var tmp = value();
      if (tmp instanceof DataTypes.ABSTRACT) {
        return tmp.toSql();
      } else {
        return tmp;
      }
    } else if (value instanceof DataTypes.UUIDV1) {
      return uuid.v1();
    } else if (value instanceof DataTypes.UUIDV4) {
      return uuid.v4();
    } else if (value instanceof DataTypes.NOW) {
      return Utils.now();
    } else {
      return value;
    }
  },

  /**
   * Determine if the default value provided exists and can be described
   * in a db schema using the DEFAULT directive.
   *
   * @param  {*} value Any default value.
   * @return {boolean} yes / no.
   */
  defaultValueSchemable: function(value) {
    if (typeof value === 'undefined') { return false; }

    // TODO this will be schemable when all supported db
    // have been normalized for this case
    if (value instanceof DataTypes.NOW) { return false; }

    if (value instanceof DataTypes.UUIDV1 || value instanceof DataTypes.UUIDV4) { return false; }

    if (lodash.isFunction(value)) {
      return false;
    }

    return true;
  },

  removeNullValuesFromHash: function(hash, omitNull, options) {
    var result = hash;

    options = options || {};
    options.allowNull = options.allowNull || [];

    if (omitNull) {
      var _hash = {};

      Utils._.forIn(hash, function(val, key) {
        if (options.allowNull.indexOf(key) > -1 || key.match(/Id$/) || ((val !== null) && (val !== undefined))) {
          _hash[key] = val;
        }
      });

      result = _hash;
    }

    return result;
  },

  inherit: function(SubClass, SuperClass) {
    if (SuperClass.constructor === Function) {
      // Normal Inheritance
      SubClass.prototype = new SuperClass();
      SubClass.prototype.constructor = SubClass;
      SubClass.prototype.parent = SuperClass.prototype;
    } else {
      // Pure Virtual Inheritance
      SubClass.prototype = SuperClass;
      SubClass.prototype.constructor = SubClass;
      SubClass.prototype.parent = SuperClass;
    }

    return SubClass;
  },

  stack: function _stackGrabber() {
    var orig = Error.prepareStackTrace;
    Error.prepareStackTrace = function(_, stack) { return stack; };
    var err = new Error();
    Error.captureStackTrace(err, _stackGrabber);
    var errStack = err.stack;
    Error.prepareStackTrace = orig;
    return errStack;
  },

  sliceArgs: function (args, begin) {
    begin = begin || 0;
    var tmp = new Array(args.length - begin);
    for (var i = begin; i < args.length; ++i) {
        tmp[i - begin] = args[i];
    }
    return tmp;
  },

  now: function(dialect) {
    var now = new Date();
    if (['postgres', 'sqlite'].indexOf(dialect) === -1) {
      now.setMilliseconds(0);
    }
    return now;
  },

  tick: function(func) {
    var tick = (global.hasOwnProperty('setImmediate') ? global.setImmediate : process.nextTick);
    tick(func);
  },

  // Note: Use the `quoteIdentifier()` and `escape()` methods on the
  // `QueryInterface` instead for more portable code.

  TICK_CHAR: '`',
  addTicks: function(s, tickChar) {
    tickChar = tickChar || Utils.TICK_CHAR;
    return tickChar + Utils.removeTicks(s, tickChar) + tickChar;
  },
  removeTicks: function(s, tickChar) {
    tickChar = tickChar || Utils.TICK_CHAR;
    return s.replace(new RegExp(tickChar, 'g'), '');
  },

  /*
   * Utility functions for representing SQL functions, and columns that should be escaped.
   * Please do not use these functions directly, use Sequelize.fn and Sequelize.col instead.
   */
  fn: function(fn, args) {
    this.fn = fn;
    this.args = args;
  },

  col: function(col) {
    if (arguments.length > 1) {
      col = this.sliceArgs(arguments);
    }
    this.col = col;
  },

  cast: function(val, type) {
    this.val = val;
    this.type = (type || '').trim();
  },

  literal: function(val) {
    this.val = val;
  },

  and: function(args) {
    this.args = args;
  },

  or: function(args) {
    this.args = args;
  },

  json: function(conditionsOrPath, value) {
    if (Utils._.isObject(conditionsOrPath)) {
      this.conditions = conditionsOrPath;
    } else {
      this.path = conditionsOrPath;
      if (value) {
        this.value = value;
      }
    }
  },

  where: function(attribute, comparator, logic) {
    if (logic === undefined) {
      logic = comparator;
      comparator = '=';
    }

    this.attribute = attribute;
    this.comparator = comparator;
    this.logic = logic;
  },

  validateParameter: function(value, expectation, options) {
    return ParameterValidator.check(value, expectation, options);
  },

  formatReferences: function (obj) {
    if (!lodash.isPlainObject(obj.references)) {
      deprecate('Non-object references property found. Support for that will be removed in version 4. Expected { references: { model: "value", key: "key" } } instead of { references: "value", referencesKey: "key" }.');
      obj.references = { model: obj.references, key: obj.referencesKey, deferrable: obj.referencesDeferrable };
      obj.referencesKey = undefined;
      obj.referencesDeferrable = undefined;
    }

    return obj;
  }
};

Utils.and.prototype._isSequelizeMethod =
Utils.or.prototype._isSequelizeMethod =
Utils.where.prototype._isSequelizeMethod =
Utils.literal.prototype._isSequelizeMethod =
Utils.cast.prototype._isSequelizeMethod =
Utils.fn.prototype._isSequelizeMethod =
Utils.col.prototype._isSequelizeMethod =
Utils.json.prototype._isSequelizeMethod = true;

Utils.Promise = require('./promise');
<|endoftext|>


<commit_before>'use strict';

/**
 * @exports CamSDK.utils
 */
var utils = module.exports = {"typeUtils" : require('./forms/type-util')};

utils.solveHALEmbedded = function(results) {

  function isId(str) {
    if (str.slice(-2) !== 'Id') { return false; }

    var prop = str.slice(0, -2);
    var embedded = results._embedded;
    return !!(embedded[prop] && !!embedded[prop].length);
  }

  function keys(obj) {
    var arr = Object.keys(obj);

    for (var a in arr) {
      if (arr[a][0] === '_' || !isId(arr[a])) {
        arr.splice(a, 1);
      }
    }

    return arr;
  }

  var _embeddedRessources = Object.keys(results._embedded);
  for (var r in _embeddedRessources) {
    var name = _embeddedRessources[r];

    for (var i in results._embedded[name]) {
      results._embedded[name][i]._embedded = results._embedded[name][i]._embedded || {};

      var properties = keys(results._embedded[name][i]);

      for (var p in properties) {
        var prop = properties[p];
        if (results._embedded[name][i][prop]) {
          var embedded = results._embedded[prop.slice(0, -2)];
          for (var e in embedded) {
            if (embedded[e].id === results._embedded[name][i][prop]) {
              results._embedded[name][i]._embedded[prop.slice(0, -2)] = [embedded[e]];
            }
          }
        }
      }
    }
  }

  return results;
};

// the 2 folowing functions were borrowed from async.js
// https://github.com/caolan/async/blob/master/lib/async.js

function _eachSeries(arr, iterator, callback) {
  callback = callback || function () {};
  if (!arr.length) {
    return callback();
  }
  var completed = 0;
  var iterate = function () {
    iterator(arr[completed], function (err) {
      if (err) {
        callback(err);
        callback = function () {};
      }
      else {
        completed += 1;
        if (completed >= arr.length) {
          callback();
        }
        else {
          iterate();
        }
      }
    });
  };
  iterate();
}

/**
 * Executes functions in serie
 *
 * @param  {(Object.<String, Function>|Array.<Function>)} tasks object or array of functions
 *                                                              taking a callback
 *
 * @param  {Function} callback                                  executed at the end, first argument
 *                                                              will be an error (if error occured),
 *                                                              the second depends on "tasks" type
 *
 * @example
 * CamSDK.utils.series({
 *   a: function(cb) { setTimeout(function() { cb(null, 1); }, 1); },
 *   b: function(cb) { setTimeout(function() { cb(new Error('Bang!')); }, 1); },
 *   c: function(cb) { setTimeout(function() { cb(null, 3); }, 1); }
 * }, function(err, result) {
 *   // err will be passed
 *   // result will be { a: 1, b: undefined }
 * });
 */
utils.series = function(tasks, callback) {
  callback = callback || function () {};

  var results = {};
  _eachSeries(Object.keys(tasks), function (k, callback) {
    tasks[k](function (err) {
      var args = Array.prototype.slice.call(arguments, 1);
      if (args.length <= 1) {
        args = args[0];
      }
      results[k] = args;
      callback(err);
    });
  }, function (err) {
    callback(err, results);
  });
};
<commit_msg>fix(Object/keys): fix type error<commit_after>'use strict';

/**
 * @exports CamSDK.utils
 */
var utils = module.exports = {"typeUtils" : require('./forms/type-util')};

utils.solveHALEmbedded = function(results) {

  function isId(str) {
    if (str.slice(-2) !== 'Id') { return false; }

    var prop = str.slice(0, -2);
    var embedded = results._embedded;
    return !!(embedded[prop] && !!embedded[prop].length);
  }

  function keys(obj) {
    var arr = Object.keys(obj);

    for (var a in arr) {
      if (arr[a][0] === '_' || !isId(arr[a])) {
        arr.splice(a, 1);
      }
    }

    return arr;
  }

  var _embeddedRessources = Object.keys(results._embedded || {});
  for (var r in _embeddedRessources) {
    var name = _embeddedRessources[r];

    for (var i in results._embedded[name]) {
      results._embedded[name][i]._embedded = results._embedded[name][i]._embedded || {};

      var properties = keys(results._embedded[name][i]);

      for (var p in properties) {
        var prop = properties[p];
        if (results._embedded[name][i][prop]) {
          var embedded = results._embedded[prop.slice(0, -2)];
          for (var e in embedded) {
            if (embedded[e].id === results._embedded[name][i][prop]) {
              results._embedded[name][i]._embedded[prop.slice(0, -2)] = [embedded[e]];
            }
          }
        }
      }
    }
  }

  return results;
};

// the 2 folowing functions were borrowed from async.js
// https://github.com/caolan/async/blob/master/lib/async.js

function _eachSeries(arr, iterator, callback) {
  callback = callback || function () {};
  if (!arr.length) {
    return callback();
  }
  var completed = 0;
  var iterate = function () {
    iterator(arr[completed], function (err) {
      if (err) {
        callback(err);
        callback = function () {};
      }
      else {
        completed += 1;
        if (completed >= arr.length) {
          callback();
        }
        else {
          iterate();
        }
      }
    });
  };
  iterate();
}

/**
 * Executes functions in serie
 *
 * @param  {(Object.<String, Function>|Array.<Function>)} tasks object or array of functions
 *                                                              taking a callback
 *
 * @param  {Function} callback                                  executed at the end, first argument
 *                                                              will be an error (if error occured),
 *                                                              the second depends on "tasks" type
 *
 * @example
 * CamSDK.utils.series({
 *   a: function(cb) { setTimeout(function() { cb(null, 1); }, 1); },
 *   b: function(cb) { setTimeout(function() { cb(new Error('Bang!')); }, 1); },
 *   c: function(cb) { setTimeout(function() { cb(null, 3); }, 1); }
 * }, function(err, result) {
 *   // err will be passed
 *   // result will be { a: 1, b: undefined }
 * });
 */
utils.series = function(tasks, callback) {
  callback = callback || function () {};

  var results = {};
  _eachSeries(Object.keys(tasks), function (k, callback) {
    tasks[k](function (err) {
      var args = Array.prototype.slice.call(arguments, 1);
      if (args.length <= 1) {
        args = args[0];
      }
      results[k] = args;
      callback(err);
    });
  }, function (err) {
    callback(err, results);
  });
};
<|endoftext|>


<commit_before>'use strict';

var path = require('path');

/**
 * Lazily required module dependencies
 */

var lazy = require('lazy-cache')(require);

// object/array/type utils
lazy('clone');
lazy('is-buffer');
lazy('define-property', 'define');
lazy('mixin-deep', 'merge');
lazy('extend-shallow', 'extend');
lazy('object.reduce', 'reduce');

// routing
lazy('en-route', 'router');

// engines, templates and helpers
lazy('engine-base', 'engine');
lazy('engine-cache', 'Engines');
lazy('helper-cache', 'Helpers');
lazy('template-error', 'rethrow');
lazy('inflection', 'inflect');
lazy('layouts');

// glob/matching utils
lazy('globby');
lazy('micromatch', 'mm');
lazy('is-valid-glob');
lazy('has-glob');

/**
 * Utils
 */

var utils = lazy;

/**
 * Default router methods used in all Template instances
 */

utils.methods = [
  'onLoad',
  'preCompile',
  'preLayout',
  'onLayout',
  'postLayout',
  'onMerge',
  'postCompile',
  'preRender',
  'postRender'
];

/**
 * FILE / GLOB UTILS
 * --------------------------------
 */

/**
 * Resolve the absolute file paths for a glob of files.
 */

utils.resolveGlob = function resolveGlob(patterns, options) {
  var opts = utils.extend({cwd: process.cwd()}, options);
  return utils.globby.sync(patterns, opts).map(function (fp) {
    return path.resolve(opts.cwd, fp);
  });
};

/**
 * Require a glob of files
 */

utils.requireGlob = function requireGlob(patterns, options) {
  return utils.resolveGlob(patterns, options).reduce(function (acc, fp) {
    if (/\.(js(?:on)?)/.test(fp)) {
      acc[utils.rename(fp, options)] = utils.tryRequire(fp);
    }
    return acc;
  }, {});
};

/**
 * Attempt to require a file. Fail silently.
 */

utils.tryRequire = function tryRequire(fp) {
  try {
    return require(path.resolve(fp));
  } catch(err) {}
  return null;
};

/**
 * CLASS UTILS
 * ------------------------
 */

utils.copyDescriptor = function copyDescriptor(receiver, provider, key) {
  var val = utils.getDescriptor(provider, key);
  if (val) utils.define(receiver, key, val);
};

utils.getDescriptor = function getDescriptor(provider, key) {
  return Object.getOwnPropertyDescriptor(provider, key);
};

/**
 * OBJECT / ARRAY / TYPE UTILS
 * --------------------------------
 */

/**
 * Format an error object.
 */

utils.error = function error(msg, val) {
  return new Error(msg + JSON.stringify(val));
};

/**
 * Do nothing.
 */

utils.noop = function noop() {};

/**
 * Return the given value as-is.
 */

utils.identity = function identity(val) {
  return val;
};

/**
 * Arrayify the given value by casting it to an array.
 */

utils.arrayify = function arrayify(val) {
  return val ? (Array.isArray(val) ? val : [val]) : [];
};

/**
 * Return true if the given value is an object.
 */

utils.isObject = function isObject(val) {
  return val && (typeof val === 'function' || typeof val === 'object')
    && !Array.isArray(val);
};

/**
 * Bind a `thisArg` to all the functions on the target
 *
 * @param  {Object|Array} `target` Object or Array with functions as values that will be bound.
 * @param  {Object} `thisArg` Object to bind to the functions
 * @return {Object|Array} Object or Array with bound functions.
 */

utils.bindAll = function bindAll(target, thisArg) {
  return utils.reduce(target, function (acc, fn, key) {
    if (typeof fn === 'object') {
      acc[key] = utils.bindAll(fn, thisArg);
    } else if (typeof fn === 'function') {
      acc[key] = fn.bind(thisArg);
      // get `async` flag or any other helper options on `fn`
      for (var k in fn) acc[key][k] = fn[k];
    }
    return acc;
  }, {});
};

/**
 * VIEW UTILS
 * --------------------------------
 */

/**
 * Rename a file
 */

utils.rename = function rename(fp, options) {
  var opts = utils.extend({renameFn: name}, options);
  return opts.renameFn(fp);
};

/**
 * Singularize the given `name`
 */

utils.single = function single(name) {
  return utils.inflect.singularize(name);
};

/**
 * Pluralize the given `name`
 */

utils.plural = function plural(name) {
  return utils.inflect.pluralize(name);
};

/**
 * Return true if the given value is a view.
 */

utils.isView = function isView(val) {
  return val && val.hasOwnProperty('content')
    || val.hasOwnProperty('contents')
    || val.hasOwnProperty('path');
};

/**
 * Return true if the given value is a view.
 */

utils.hasView = function hasView(val) {
  var keys = Object.keys(val);
  if (keys.length > 1) return false;
  return utils.isView(val[keys[0]]);
};

/**
 * Return the first object with a key that matches
 * the given glob pattern.
 *
 * @param {Object} `object`
 * @param {String|Array} `patterns`
 * @param {Object} `options`
 * @return {Object}
 */

utils.matchKey = function matchKey(obj, patterns, options) {
  if (!utils.isObject(obj)) return null;
  var keys = utils.mm(Object.keys(obj), patterns, options);
  return obj[keys[0]];
};

/**
 * Return all objects with keys that match
 * the given glob pattern.
 *
 * @param {Object} `object`
 * @param {String|Array} `patterns`
 * @param {Object} `options`
 * @return {Object}
 */

utils.matchKeys = function matchKeys(obj, patterns, options) {
  var keys = utils.mm(Object.keys(obj), patterns, options).sort();
  var len = keys.length, i = 0;
  var res = {};

  while (len--) {
    var key = keys[i++];
    res[key] = obj[key];
  }
  return res;
};

/**
 * Return true if the given value is a view.
 */

utils.renameKey = function(app) {
  utils.define(app, 'renameKey', function renameKey(key, fn) {
    if (typeof key === 'function') {
      fn = key;
      key = null;
    }

    if (typeof fn !== 'function') {
      fn = this.option('renameKey');
    }
    if (typeof fn !== 'function') {
      fn = utils.identity;
    }

    this.options.renameKey = fn;
    if (typeof key === 'string') {
      return fn(key);
    }
    return fn;
  }.bind(app));
};

/**
 * Set or get an option value. This is a factory for
 * adding an `option` method to a class
 */

utils.option = function(app) {
  utils.define(app, 'option', function(key, value) {
    if (typeof key === 'string') {
      if (arguments.length === 1) {
        return this.get('options.' + key);
      }
      this.set('options.' + key, value);
      this.emit('option', key, value);
      return this;
    }
    if (typeof key !== 'object') {
      throw new TypeError('expected a string or object.');
    }
    this.visit('option', key);
    return this;
  }.bind(app));
};

/**
 * Ensure file extensions are formatted properly for lookups.
 *
 * ```js
 * utils.formatExt('hbs');
 * //=> '.hbs'
 *
 * utils.formatExt('.hbs');
 * //=> '.hbs'
 * ```
 *
 * @param {String} `ext` File extension
 * @return {String}
 * @api public
 */

utils.formatExt = function formatExt(ext) {
  if (typeof ext !== 'string') {
    throw new Error('utils.formatExt() expects `ext` to be a string.');
  }
  if (ext.charAt(0) !== '.') {
    return '.' + ext;
  }
  return ext;
};

/**
 * Strip the dot from a file extension
 *
 * ```js
 * utils.stripDot('.hbs');
 * //=> 'hbs'
 * ```
 *
 * @param {String} `ext` extension
 * @return {String}
 * @api public
 */

utils.stripDot = function stripDot(ext) {
  if (typeof ext !== 'string') {
    throw new Error('utils.stripDot() expects `ext` to be a string.');
  }
  if (ext.charAt(0) === '.') {
    return ext.slice(1);
  }
  return ext;
};

/**
 * Get locals from helper arguments.
 *
 * @param  {Object} `locals`
 * @param  {Object} `options`
 */

utils.getLocals = function getLocals(locals, options) {
  options = options || {};
  locals = locals || {};
  var ctx = {};

  if (options.hasOwnProperty('hash')) {
    utils.extend(ctx, locals);
    utils.extend(ctx, options.hash);

  } else if (locals.hasOwnProperty('hash')) {
    utils.extend(ctx, locals.hash);

  } else if (!locals.hasOwnProperty('hash') && !options.hasOwnProperty('hash')) {
    utils.extend(ctx, options);
    utils.extend(ctx, locals);
  }
  return ctx;
};

/**
 * Get the basename from a filepath, excluding extension.
 */

function name(fp) {
  return path.basename(fp, path.extname(fp));
}

/**
 * Expose utils
 */

module.exports = lazy;

<commit_msg>isStream util from @doowb<commit_after>'use strict';

var path = require('path');

/**
 * Lazily required module dependencies
 */

var lazy = require('lazy-cache')(require);

// object/array/type utils
lazy('clone');
lazy('is-buffer');
lazy('define-property', 'define');
lazy('mixin-deep', 'merge');
lazy('extend-shallow', 'extend');
lazy('object.reduce', 'reduce');

// routing
lazy('en-route', 'router');

// engines, templates and helpers
lazy('engine-base', 'engine');
lazy('engine-cache', 'Engines');
lazy('helper-cache', 'Helpers');
lazy('template-error', 'rethrow');
lazy('inflection', 'inflect');
lazy('layouts');

// glob/matching utils
lazy('globby');
lazy('micromatch', 'mm');
lazy('is-valid-glob');
lazy('has-glob');

/**
 * Utils
 */

var utils = lazy;

/**
 * Default router methods used in all Template instances
 */

utils.methods = [
  'onLoad',
  'preCompile',
  'preLayout',
  'onLayout',
  'postLayout',
  'onMerge',
  'postCompile',
  'preRender',
  'postRender'
];

/**
 * FILE / GLOB UTILS
 * --------------------------------
 */

/**
 * Resolve the absolute file paths for a glob of files.
 */

utils.resolveGlob = function resolveGlob(patterns, options) {
  var opts = utils.extend({cwd: process.cwd()}, options);
  return utils.globby.sync(patterns, opts).map(function (fp) {
    return path.resolve(opts.cwd, fp);
  });
};

/**
 * Require a glob of files
 */

utils.requireGlob = function requireGlob(patterns, options) {
  return utils.resolveGlob(patterns, options).reduce(function (acc, fp) {
    if (/\.(js(?:on)?)/.test(fp)) {
      acc[utils.rename(fp, options)] = utils.tryRequire(fp);
    }
    return acc;
  }, {});
};

/**
 * Attempt to require a file. Fail silently.
 */

utils.tryRequire = function tryRequire(fp) {
  try {
    return require(path.resolve(fp));
  } catch(err) {}
  return null;
};

/**
 * CLASS UTILS
 * ------------------------
 */

utils.copyDescriptor = function copyDescriptor(receiver, provider, key) {
  var val = utils.getDescriptor(provider, key);
  if (val) utils.define(receiver, key, val);
};

utils.getDescriptor = function getDescriptor(provider, key) {
  return Object.getOwnPropertyDescriptor(provider, key);
};

/**
 * OBJECT / ARRAY / TYPE UTILS
 * --------------------------------
 */

/**
 * Format an error object.
 */

utils.error = function error(msg, val) {
  return new Error(msg + JSON.stringify(val));
};

/**
 * Do nothing.
 */

utils.noop = function noop() {};

/**
 * Return the given value as-is.
 */

utils.identity = function identity(val) {
  return val;
};

/**
 * Arrayify the given value by casting it to an array.
 */

utils.arrayify = function arrayify(val) {
  return val ? (Array.isArray(val) ? val : [val]) : [];
};

/**
 * Return true if the given value is an object.
 */

utils.isObject = function isObject(val) {
  return val && (typeof val === 'function' || typeof val === 'object')
    && !Array.isArray(val);
};
/**
 * Return true if the given value is a stream.
 */

utils.isStream = function isStream(val) {
  return val && (typeof val === 'function' || typeof val === 'object')
    && !Array.isArray(val)
    && (typeof val.pipe === 'function')
    && (typeof val.on === 'function');
};

/**
 * Bind a `thisArg` to all the functions on the target
 *
 * @param  {Object|Array} `target` Object or Array with functions as values that will be bound.
 * @param  {Object} `thisArg` Object to bind to the functions
 * @return {Object|Array} Object or Array with bound functions.
 */

utils.bindAll = function bindAll(target, thisArg) {
  return utils.reduce(target, function (acc, fn, key) {
    if (typeof fn === 'object') {
      acc[key] = utils.bindAll(fn, thisArg);
    } else if (typeof fn === 'function') {
      acc[key] = fn.bind(thisArg);
      // get `async` flag or any other helper options on `fn`
      for (var k in fn) acc[key][k] = fn[k];
    }
    return acc;
  }, {});
};

/**
 * VIEW UTILS
 * --------------------------------
 */

/**
 * Rename a file
 */

utils.rename = function rename(fp, options) {
  var opts = utils.extend({renameFn: name}, options);
  return opts.renameFn(fp);
};

/**
 * Singularize the given `name`
 */

utils.single = function single(name) {
  return utils.inflect.singularize(name);
};

/**
 * Pluralize the given `name`
 */

utils.plural = function plural(name) {
  return utils.inflect.pluralize(name);
};

/**
 * Return true if the given value is a view.
 */

utils.isView = function isView(val) {
  return val && val.hasOwnProperty('content')
    || val.hasOwnProperty('contents')
    || val.hasOwnProperty('path');
};

/**
 * Return true if the given value is a view.
 */

utils.hasView = function hasView(val) {
  var keys = Object.keys(val);
  if (keys.length > 1) return false;
  return utils.isView(val[keys[0]]);
};

/**
 * Return the first object with a key that matches
 * the given glob pattern.
 *
 * @param {Object} `object`
 * @param {String|Array} `patterns`
 * @param {Object} `options`
 * @return {Object}
 */

utils.matchKey = function matchKey(obj, patterns, options) {
  if (!utils.isObject(obj)) return null;
  var keys = utils.mm(Object.keys(obj), patterns, options);
  return obj[keys[0]];
};

/**
 * Return all objects with keys that match
 * the given glob pattern.
 *
 * @param {Object} `object`
 * @param {String|Array} `patterns`
 * @param {Object} `options`
 * @return {Object}
 */

utils.matchKeys = function matchKeys(obj, patterns, options) {
  var keys = utils.mm(Object.keys(obj), patterns, options).sort();
  var len = keys.length, i = 0;
  var res = {};

  while (len--) {
    var key = keys[i++];
    res[key] = obj[key];
  }
  return res;
};

/**
 * Sync the _content and _contents properties on a view to ensure
 * both are set when setting one.
 *
 * @param {Object} `view` instance of a `View`
 * @param {String|Buffer|Stream|null} `contents` contents to set on both properties
 */

utils.syncContents = function syncContents(view, contents) {
  if (contents === null) {
    view._contents = null;
    view._content = null;
  }
  if (typeof contents === 'string') {
    view._contents = new Buffer(contents);
    view._content = contents;
  }
  if (utils.isBuffer(contents)) {
    view._contents = contents;
    view._content = contents.toString();
  }
  if (utils.isStream(contents)) {
    view._contents = contents;
    // what should be done here?
    view._content = contents;
  }
};

/**
 * Return true if the given value is a view.
 */

utils.renameKey = function(app) {
  utils.define(app, 'renameKey', function renameKey(key, fn) {
    if (typeof key === 'function') {
      fn = key;
      key = null;
    }

    if (typeof fn !== 'function') {
      fn = this.option('renameKey');
    }
    if (typeof fn !== 'function') {
      fn = utils.identity;
    }

    this.options.renameKey = fn;
    if (typeof key === 'string') {
      return fn(key);
    }
    return fn;
  }.bind(app));
};

/**
 * Set or get an option value. This is a factory for
 * adding an `option` method to a class
 */

utils.option = function(app) {
  utils.define(app, 'option', function(key, value) {
    if (typeof key === 'string') {
      if (arguments.length === 1) {
        return this.get('options.' + key);
      }
      this.set('options.' + key, value);
      this.emit('option', key, value);
      return this;
    }
    if (typeof key !== 'object') {
      throw new TypeError('expected a string or object.');
    }
    this.visit('option', key);
    return this;
  }.bind(app));
};

/**
 * Ensure file extensions are formatted properly for lookups.
 *
 * ```js
 * utils.formatExt('hbs');
 * //=> '.hbs'
 *
 * utils.formatExt('.hbs');
 * //=> '.hbs'
 * ```
 *
 * @param {String} `ext` File extension
 * @return {String}
 * @api public
 */

utils.formatExt = function formatExt(ext) {
  if (typeof ext !== 'string') {
    throw new Error('utils.formatExt() expects `ext` to be a string.');
  }
  if (ext.charAt(0) !== '.') {
    return '.' + ext;
  }
  return ext;
};

/**
 * Strip the dot from a file extension
 *
 * ```js
 * utils.stripDot('.hbs');
 * //=> 'hbs'
 * ```
 *
 * @param {String} `ext` extension
 * @return {String}
 * @api public
 */

utils.stripDot = function stripDot(ext) {
  if (typeof ext !== 'string') {
    throw new Error('utils.stripDot() expects `ext` to be a string.');
  }
  if (ext.charAt(0) === '.') {
    return ext.slice(1);
  }
  return ext;
};

/**
 * Get locals from helper arguments.
 *
 * @param  {Object} `locals`
 * @param  {Object} `options`
 */

utils.getLocals = function getLocals(locals, options) {
  options = options || {};
  locals = locals || {};
  var ctx = {};

  if (options.hasOwnProperty('hash')) {
    utils.extend(ctx, locals);
    utils.extend(ctx, options.hash);

  } else if (locals.hasOwnProperty('hash')) {
    utils.extend(ctx, locals.hash);

  } else if (!locals.hasOwnProperty('hash') && !options.hasOwnProperty('hash')) {
    utils.extend(ctx, options);
    utils.extend(ctx, locals);
  }
  return ctx;
};

/**
 * Get the basename from a filepath, excluding extension.
 */

function name(fp) {
  return path.basename(fp, path.extname(fp));
}

/**
 * Expose utils
 */

module.exports = lazy;

<|endoftext|>


<commit_before>const YOUTUBE_REGEX = /http(?:s?):\/\/(?:www\.)?(?:music\.)?youtu(?:be\.com\/watch\?v=|\.be\/)([\w\-\_]*)(&(amp;)?[\w\?=]*)?/
const URI_REGEX = /\w+:(\/?\/?)[^\s]+/
const PATH_REGEX = /(\\\\?([^\\/]*[\\/])*)([^\\/]+)/

/**
* Utils
**/
class Utils {
  static getYoutubeId (obj) {
    if (!obj || typeof obj !== 'string') return null

    const youtubeMatch = obj.match(YOUTUBE_REGEX)
    const uriMatch = obj.match(URI_REGEX)
    const pathMatch = obj.match(PATH_REGEX)

    if (youtubeMatch && youtubeMatch.length > 1) {
      // Extract the video id
      return youtubeMatch[1]
    } else if ((uriMatch && uriMatch.length > 1) || (pathMatch && pathMatch.length > 1)) {
      // URI or path to file
      return null
    } else {
       // Looks like a possible video id (lets try)
      return obj
    }
  }
}

module.exports = Utils
<commit_msg>make http\s optional and minify youtube regex<commit_after>const YOUTUBE_REGEX = /(?:http(?:s?):\/\/)?(?:www\.)?(?:music\.)?youtu(?:be\.com\/watch\?v=|\.be\/)([\w\-\_]*)/
const URI_REGEX = /\w+:(\/?\/?)[^\s]+/
const PATH_REGEX = /(\\\\?([^\\/]*[\\/])*)([^\\/]+)/

/**
* Utils
**/
class Utils {
  static getYoutubeId (obj) {
    if (!obj || typeof obj !== 'string') return null

    const youtubeMatch = obj.match(YOUTUBE_REGEX)
    const uriMatch = obj.match(URI_REGEX)
    const pathMatch = obj.match(PATH_REGEX)

    if (youtubeMatch && youtubeMatch.length > 1) {
      // Extract the video id
      return youtubeMatch[1]
    } else if ((uriMatch && uriMatch.length > 1) || (pathMatch && pathMatch.length > 1)) {
      // URI or path to file
      return null
    } else {
       // Looks like a possible video id (lets try)
      return obj
    }
  }
}

module.exports = Utils
<|endoftext|>


<commit_before>const fs = require('fs'),

    strip = require('strip-json-comments'),

    UTF8 = 'utf-8',

    /**
     * Check if string ends with the specified suffix.
     *
     * @param {String} str - Input string
     * @param {String} suffix - suffix to be checked
     * @returns {Boolean}
     */
    endsWith = (str, suffix) => {
        return str.indexOf(suffix, str.length - suffix.length) !== -1; // eslint-disable-line lodash/prefer-includes
    },

    /**
     * Check if string starts with the specified prefix.
     *
     * @param {String} str - Input string
     * @param {String} prefix - prefix to be checked
     * @returns {Boolean}
     */
    startsWith = (str, prefix) => {
        return str.slice(0, prefix.length) === prefix;
    },

    /**
     * Strip comments from JSON and Parse.
     *
     * @param {String} path - Path to JSON file
     * @returns {Object}
     */
    removeCommentsAndLoadJSON = (path) => {
        return JSON.parse(strip(fs.readFileSync(path, UTF8)));
    },

    /**
     * Recursively get all the schemas.
     *
     * @param {String} path - Path to schema file or directory
     * @param {Object} schemas - Resultant schema
     * @returns {Object}
     */
    _getAllSchemasRecurse = (path, schemas) => {
        const stats = fs.lstatSync(path);
        let file;

        if (stats.isDirectory()) {
            fs.readdirSync(path).map((child) => {
                return _getAllSchemasRecurse(path + '/' + child, schemas);
            });

            return schemas;
        }

        if (endsWith(path, '.json')) {
            file = removeCommentsAndLoadJSON(path);
            schemas[file.id] = file;
            if (!file.id) {
                console.warn('WARNING: File: ', path + ' has no id');
            }
        }

        return schemas;
    },

    /**
     * Load all schemas from the give path.
     *
     * @param {String} path - Path to schema file or directory
     * @returns {Object}
     */
    getAllSchemas = function (path) {
        return _getAllSchemasRecurse(path, {});
    };

module.exports = {
    endsWith,
    startsWith,
    getAllSchemas,
    removeCommentsAndLoadJSON
};
<commit_msg>Updated utils to account for draft versions<commit_after>const fs = require('fs'),

    strip = require('strip-json-comments'),

    UTF8 = 'utf-8',

    /**
     * Check if string ends with the specified suffix.
     *
     * @param {String} str - Input string
     * @param {String} suffix - suffix to be checked
     * @returns {Boolean}
     */
    endsWith = (str, suffix) => {
        return str.indexOf(suffix, str.length - suffix.length) !== -1; // eslint-disable-line lodash/prefer-includes
    },

    /**
     * Check if string starts with the specified prefix.
     *
     * @param {String} str - Input string
     * @param {String} prefix - prefix to be checked
     * @returns {Boolean}
     */
    startsWith = (str, prefix) => {
        return str.slice(0, prefix.length) === prefix;
    },

    /**
     * Strip comments from JSON and Parse.
     *
     * @param {String} path - Path to JSON file
     * @returns {Object}
     */
    removeCommentsAndLoadJSON = (path) => {
        return JSON.parse(strip(fs.readFileSync(path, UTF8)));
    },

    /**
     * Recursively get all the schemas.
     *
     * @param {String} path - Path to schema file or directory
     * @param {String} schemaId - The unique identified for each sub-schema file
     * @param {Object} schemas - Resultant schema
     * @returns {Object}
     */
    _getAllSchemasRecurse = (path, schemaId, schemas) => {
        const stats = fs.lstatSync(path);
        let file;

        if (stats.isDirectory()) {
            fs.readdirSync(path).map((child) => {
                return _getAllSchemasRecurse(path + '/' + child, schemaId, schemas);
            });

            return schemas;
        }

        if (endsWith(path, '.json')) {
            file = removeCommentsAndLoadJSON(path);
            schemas[file[schemaId]] = file;
            if (!file[schemaId]) {
                console.warn(`WARNING: File: ${path} has no ${schemaId}`);
            }
        }

        return schemas;
    },

    /**
     * Load all schemas from the give path.
     *
     * @param {String} path - Path to schema file or directory
     * @param {String} schemaId - The primary key .
     * @returns {Object}
     */
    getAllSchemas = function (path, schemaId) {
        return _getAllSchemasRecurse(path, schemaId, {});
    };

module.exports = {
    endsWith,
    startsWith,
    getAllSchemas,
    removeCommentsAndLoadJSON
};
<|endoftext|>


<commit_before>/**
 * @license Copyright 2013 Logentries.
 * Please view license at https://raw.github.com/logentries/le_js/master/LICENSE
 */

/** @param {Object} window */
var LE = (function(window) {
    "use strict";

    /**
     * A single log event stream.
     * @constructor
     * @param {Object} options
     */
    function LogStream(options) {
        /**
         * @const
         * @type {string} */
        var _traceCode = (Math.random() + Math.PI).toString(36).substring(2, 10);
        /** @type {boolean} */
        var _doTrace = options.trace;
        /** @type {string} */
        var _pageInfo = options.page_info;
        /** @type {string} */
        var _token = options.token;
        /** @type {boolean} */
        var _print = options.print;
        /**
         * @const
         * @type {string} */
        var _endpoint = "localhost:8080/v1";

        /**
         * Flag to prevent further invocations on network err
         ** @type {boolean} */
        var _shouldCall = true;
        /** @type {boolean} */
        var _SSL = options.ssl;
        /** @type {Array.<string>} */
        var _backlog = [];
        /** @type {boolean} */
        var _active = false;
        /** @type {boolean} */
        var _sentPageInfo = false;

        if (options.catchall) {
            var oldHandler = window.onerror;
            var newHandler = function(msg, url, line) {
                _rawLog({error: msg, line: line, location: url}).level('ERROR').send();
                if (oldHandler)
                    return oldHandler(msg, url, line);
                return true;
            };
            window.onerror = newHandler;
        }

        var _agentInfo = function() {
            var navigator = window.navigator || {};
            var screen = window.screen || {};
            var location = window.location || {};
            return {
                name: navigator.userAgent,
                screenWidth: screen.width,
                screenHeight: screen.height,
                windowWidth: window.innerWidth,
                windowHeight: window.innerHeight,
                url: location.pathname
            }
        };

        var _isComplex = function(obj) {
            return (typeof obj === "object" || Array.isArray(obj)) && obj !== null;
        };

        var _prettyPrint = function(obj) {
            if (typeof obj === "undefined") {
                return "undefined";
            } else if (obj === null) {
                return "null";
            } else {
                return obj;
            }
        };

        // Traverses a log object,
        // turning nullish values into
        // string literals
        var _serialize = function(obj) {
            if (_isComplex(obj)) {
                for (var o in obj) {
                    obj[o] = _serialize(obj[o]);
                }
                return obj;
            } else {
                return _prettyPrint(obj);
            }
        };

        var _getEvent = function() {
            var raw = null;
            var args = Array.prototype.slice.call(arguments);
            if (args.length === 0) {
                throw new Error("No arguments!");
            } else if (args.length === 1) {
                raw = args[0];
            } else {
                // Handle a variadic overload,
                // e.g. _rawLog("some text ", x, " ...", 1);
                for (var i in args) {
                    args[i] = JSON.stringify(_serialize(args[i]));
                }
                raw = args.join(" ");
            }
            return raw;
        };

        // Single arg stops the compiler arity warning
        var _rawLog = function(msg) {
            var event = _getEvent.apply(this, arguments);

            var data = {event: event};

            // Add agent info if required
            if (_pageInfo !== 'never') {
                if (!_sentPageInfo) {
//                    data.agent = _agentInfo();
                    _sentPageInfo = true;
                  _rawLog(_agentInfo()).level('LOG').send();
                }
            }

            // Add trace code if required
            if (_doTrace) {
                data.trace = _traceCode;
            }

            return {level: function(l) {
                    if (_print && typeof console !== "undefined") {
                        console[l.toLowerCase()].call(console, data);
                    }
                    data.level = l;

                    return {send: function() {
                            var serialized = JSON.stringify(_serialize(data));

                            if (_active) {
                                _backlog.push(serialized);
                            } else {
                                _apiCall(_token, serialized);
                            }
                        }};
                }};
        };

        /** @expose */
        this.log = _rawLog;

        var _apiCall = function(token, data) {
            _active = true;

            // Obtain a browser-specific XHR object
            var _getAjaxObject = function() {
                if (window.ActiveXObject) {
                    window.XMLHttpRequest = function() {
                        // IE6 compat
                        return new ActiveXObject('Microsoft.XMLHTTP');
                    };
                }
                return new XMLHttpRequest();
            };

            var request = _getAjaxObject();

            if (_shouldCall) {
                request.onreadystatechange = function() {
                    if (request.readyState === 4) {
                        // Handle any errors
                        if (request.status >= 400) {
                            console.error("Couldn't submit events.");
                            if (request.status === 410) {
                                // This API version has been phased out
                                console.warn("This version of le_js is no longer supported!");
                            }
                        } else {
                            if (request.status === 301) {
                                // Server issued a deprecation warning
                                console.warn("This version of le_js is deprecated! Consider upgrading.");
                            }
                            if (_backlog.length > 0) {
                                // Submit the next event in the backlog
                                _apiCall(token, _backlog.shift());
                            } else {
                                _active = false;
                            }
                        }
                    }

                };
                var uri = (_SSL ? "https://" : "http://") + _endpoint + "/logs/" + _token;
                request.open("POST", uri, true);
                request.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
                request.setRequestHeader('Content-type', 'text/json');
                request.send(data);
            }
        };

    }

    var logger;

    var _init = function(options) {
        // Default values
        var dict = {
            ssl: true,
            catchall: false,
            trace: true,
            page_info: 'never',
            print: false
        };

        if (typeof options === "object")
            for (var k in options)
                dict[k] = options[k];
        else if (typeof options === "string")
            dict.token = options;
        else
            throw new Error("Invalid parameters for init()");

        if (dict.token === undefined) {
            throw new Error("Token not present.");
        } else {
            logger = new LogStream(dict);
        }

        return true;
    };

    var _log = function() {
        if (logger) {
            return logger.log.apply(this, arguments);
        } else
            throw new Error("You must call LE.init(...) first.");
    };

    // The public interface
    return {
        init: _init,
        log: function() {
            _log.apply(this, arguments).level('LOG').send();
        },
        warn: function() {
            _log.apply(this, arguments).level('WARN').send();
        },
        error: function() {
            _log.apply(this, arguments).level('ERROR').send();
        },
        info: function() {
            _log.apply(this, arguments).level('INFO').send();
        }
    };
}(this));
<commit_msg>clean up getEvent fn<commit_after>/**
 * @license Copyright 2013 Logentries.
 * Please view license at https://raw.github.com/logentries/le_js/master/LICENSE
 */

/** @param {Object} window */
var LE = (function(window) {
    "use strict";

    /**
     * A single log event stream.
     * @constructor
     * @param {Object} options
     */
    function LogStream(options) {
        /**
         * @const
         * @type {string} */
        var _traceCode = (Math.random() + Math.PI).toString(36).substring(2, 10);
        /** @type {boolean} */
        var _doTrace = options.trace;
        /** @type {string} */
        var _pageInfo = options.page_info;
        /** @type {string} */
        var _token = options.token;
        /** @type {boolean} */
        var _print = options.print;
        /**
         * @const
         * @type {string} */
        var _endpoint = "localhost:8080/v1";

        /**
         * Flag to prevent further invocations on network err
         ** @type {boolean} */
        var _shouldCall = true;
        /** @type {boolean} */
        var _SSL = options.ssl;
        /** @type {Array.<string>} */
        var _backlog = [];
        /** @type {boolean} */
        var _active = false;
        /** @type {boolean} */
        var _sentPageInfo = false;

        if (options.catchall) {
            var oldHandler = window.onerror;
            var newHandler = function(msg, url, line) {
                _rawLog({error: msg, line: line, location: url}).level('ERROR').send();
                if (oldHandler)
                    return oldHandler(msg, url, line);
                return true;
            };
            window.onerror = newHandler;
        }

        var _agentInfo = function() {
            var navigator = window.navigator || {};
            var screen = window.screen || {};
            var location = window.location || {};
            return {
                name: navigator.userAgent,
                screenWidth: screen.width,
                screenHeight: screen.height,
                windowWidth: window.innerWidth,
                windowHeight: window.innerHeight,
                url: location.pathname
            }
        };

        var _isComplex = function(obj) {
            return (typeof obj === "object" || Array.isArray(obj)) && obj !== null;
        };

        var _prettyPrint = function(obj) {
            if (typeof obj === "undefined") {
                return "undefined";
            } else if (obj === null) {
                return "null";
            } else {
                return obj;
            }
        };

        // Traverses a log object,
        // turning nullish values into
        // string literals
        var _serialize = function(obj) {
            if (_isComplex(obj)) {
                for (var o in obj) {
                    obj[o] = _serialize(obj[o]);
                }
                return obj;
            } else {
                return _prettyPrint(obj);
            }
        };

        var _getEvent = function() {
            var raw = null;
            var args = Array.prototype.slice.call(arguments);
            if (args.length === 0) {
                throw new Error("No arguments!");
            } else if (args.length === 1) {
                raw = args[0];
            } else {
                // Handle a variadic overload,
                // e.g. _rawLog("some text ", x, " ...", 1);
                for (var i in args) {
                    args[i] = _serialize(args[i]);
                }
                raw = args.join(" ");
            }
            return raw;
        };

        // Single arg stops the compiler arity warning
        var _rawLog = function(msg) {
            var event = _getEvent.apply(this, arguments);

            var data = {event: event};

            // Add agent info if required
            if (_pageInfo !== 'never') {
                if (!_sentPageInfo) {
                    _sentPageInfo = true;
                  _rawLog(_agentInfo()).level('LOG').send();
                }
            }

            // Add trace code if required
            if (_doTrace) {
                data.trace = _traceCode;
            }

            return {level: function(l) {
                    if (_print && typeof console !== "undefined") {
                        console[l.toLowerCase()].call(console, data);
                    }
                    data.level = l;

                    return {send: function() {
                            var serialized = JSON.stringify(_serialize(data));

                            if (_active) {
                                _backlog.push(serialized);
                            } else {
                                _apiCall(_token, serialized);
                            }
                        }};
                }};
        };

        /** @expose */
        this.log = _rawLog;

        var _apiCall = function(token, data) {
            _active = true;

            // Obtain a browser-specific XHR object
            var _getAjaxObject = function() {
                if (window.ActiveXObject) {
                    window.XMLHttpRequest = function() {
                        // IE6 compat
                        return new ActiveXObject('Microsoft.XMLHTTP');
                    };
                }
                return new XMLHttpRequest();
            };

            var request = _getAjaxObject();

            if (_shouldCall) {
                request.onreadystatechange = function() {
                    if (request.readyState === 4) {
                        // Handle any errors
                        if (request.status >= 400) {
                            console.error("Couldn't submit events.");
                            if (request.status === 410) {
                                // This API version has been phased out
                                console.warn("This version of le_js is no longer supported!");
                            }
                        } else {
                            if (request.status === 301) {
                                // Server issued a deprecation warning
                                console.warn("This version of le_js is deprecated! Consider upgrading.");
                            }
                            if (_backlog.length > 0) {
                                // Submit the next event in the backlog
                                _apiCall(token, _backlog.shift());
                            } else {
                                _active = false;
                            }
                        }
                    }

                };
                var uri = (_SSL ? "https://" : "http://") + _endpoint + "/logs/" + _token;
                request.open("POST", uri, true);
                request.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
                request.setRequestHeader('Content-type', 'text/json');
                request.send(data);
            }
        };

    }

    var logger;

    var _init = function(options) {
        // Default values
        var dict = {
            ssl: true,
            catchall: false,
            trace: true,
            page_info: 'never',
            print: false
        };

        if (typeof options === "object")
            for (var k in options)
                dict[k] = options[k];
        else if (typeof options === "string")
            dict.token = options;
        else
            throw new Error("Invalid parameters for init()");

        if (dict.token === undefined) {
            throw new Error("Token not present.");
        } else {
            logger = new LogStream(dict);
        }

        return true;
    };

    var _log = function() {
        if (logger) {
            return logger.log.apply(this, arguments);
        } else
            throw new Error("You must call LE.init(...) first.");
    };

    // The public interface
    return {
        init: _init,
        log: function() {
            _log.apply(this, arguments).level('LOG').send();
        },
        warn: function() {
            _log.apply(this, arguments).level('WARN').send();
        },
        error: function() {
            _log.apply(this, arguments).level('ERROR').send();
        },
        info: function() {
            _log.apply(this, arguments).level('INFO').send();
        }
    };
}(this));
<|endoftext|>