<commit_before>$(function() {
$('.mask').css({
  'position':'relative',
  'display':'inline-block',
  'flex-grow':'1',
  'overflow':'hidden'
});

$('.mask').children().css({
  '-webkit-transform':'translate(150%, 150%)',
  '-moz-transform':'translate(150%, 150%)',
  '-o-transform':'translate(150%, 150%)',
  '-ms-transform':'translate(150%, 150%)',
  'transform':'translate(150%, 150%)'
});
});

function maskIt() {
  var $mask = $('.mask'),
      $masked = $mask.children();

  $mask.each(function() {
  var maskTransition = $(this).data('mask-transition');
  switch(maskTransition) {
    case 'fromLeft':
      $(this).children().css({
        '-webkit-transform': 'translate(-150%, 0)',
        '-moz-transform': 'translate(-150%, 0)',
        '-o-transform': 'translate(-150%, 0)',
        '-ms-transform': 'translate(-150%, 0)',
        'transform': 'translate(-150%, 0)'
      });
      break;
    case 'fromRight':
      $(this).children().css({
        '-webkit-transform': 'translate(150%, 0)',
        '-moz-transform': 'translate(150%, 0)',
        '-o-transform': 'translate(150%, 0)',
        '-ms-transform': 'translate(150%, 0)',
        'transform': 'translate(150%, 0)'
      });
      break;
    case 'fromTop':
      $(this).children().css({
        '-webkit-transform': 'translate(0, -150%)',
        '-moz-transform': 'translate(0, -150%)',
        '-o-transform': 'translate(0, -150%)',
        '-ms-transform': 'translate(0, -150%)',
        'transform': 'translate(0, -150%)'
      });
      break;
    case 'fromBottom':
      $(this).children().css({
        '-webkit-transform': 'translate(0, 150%)',
        '-moz-transform': 'translate(0, 150%)',
        '-o-transform': 'translate(0, 150%)',
        '-ms-transform': 'translate(0, 150%)',
        'transform': 'translate(0, 150%)'
      });
      break;
  }
    });

  $.each($mask, function(h) {
    $(this).children().delay(h * 150).queue(function() {
      $(this).css({
        '-webkit-transition': '.5s ease',
        '-moz-transition': '.5s ease',
        '-o-transition': '.5s ease',
        'transition': '.5s ease',
        '-webkit-transform': 'translate(0,0)',
        '-moz-transform': 'translate(0,0)',
        '-o-transform': 'translate(0,0)',
        '-ms-transform': 'translate(0,0)',
        'transform': 'translate(0,0)'
      });
    });
  });

}

$(window).load(function() {
    maskIt();
});<commit_msg>Delete masked.js<commit_after><|endoftext|>


<commit_before>'use strict';

/**
 * A database API for plain JavaScript objects that is compatible to
 * [persistence-mongodb](https://github.com/n-fuse/persistence-memory) and thus
 * can be used as a database abstraction layer for
 * [persistence](https://github.com/n-fuse/persistence).
 *
 * @module persistence-memory
 */

var filtr = require('filtr');
var uuid = require('node-uuid');

var stores = {};

/**
 * Connects to the in-memory database.
 *
 * @param {Object}
 *            [options] ignored (only for compatibility with other
 *            implementations)
 * @param {Function(err,
 *            db)} callback is called when an error occurs or when the database
 *            connection has been established.
 * @param {Error*}
 *            callback.err the error, if an error occurred or `null`
 * @param {DB}
 *            callback.db the `DB` instance
 */
exports.connect = function(options, callback) {
  if (arguments.length == 1) {
    callback = options;
    options = {};
  }

  callback(null, new DB(options));
};

/**
 * @classdesc Dummy wrapper around an array of objects.
 * @constructor
 *
 * @property {String} protocol Database protocol
 */
function DB(options) {
  var counter = 0;
  options = options || {};

  this.increment = function() {
    return ++counter;
  };

  // create empty document store
  this._store = {};
};

DB.prototype.protocol = 'memory';

/**
 * Creates/gets a collection.
 *
 * @param {String}
 *            name collection's name
 * @param {Array}
 *            indexes ignored
 * @param {Function(err,
 *            collection)} callback is called when an error occurs or when the
 *            collection is returned.
 * @param {Error*}
 *            callback.err the error, if an error occurred or `null`
 * @param {Collection}
 *            callback.collection the `Collection` instance
 */
DB.prototype.getCollection = function(name, indexes, callback) {
  if (arguments.length == 2) {
    callback = indexes;
  }

  if (typeof this._store[name] == 'undefined')
    this._store[name] = {};
  var collection = this._store[name];

  process.nextTick(function() {
    callback(null, new Collection(collection));
  });
};

/**
 * Closes the connection to the database.
 *
 * @param {Boolean}
 *            [force] force to close the connect so that it cannot be reused.
 * @param {Function(err,
 *            results)} callback is called when the db has been closed or an
 *            error occurred
 * @param {Error*}
 *            callback.err the error, if an error occurred or `null`
 * @param {Object}
 *            callback.results
 */
DB.prototype.close = function(force, callback) {
  process.nextTick(function () {
    callback(null);
  });
}

/**
 * @classdesc Dummy wrapper around a collection object.
 * @constructor
 *
 * @param {Object}
 *            collection collection object
 */
function Collection(coll) {
  this._coll = coll;
}

/**
 * Check if the record matches the query.
 *
 * @param {Object}
 *            query query object
 * @param {Object}
 *            record record
 *
 * @returns {Boolean}
 */
function matches(query, record) {
  var keys = Object.keys(query);
  var len = keys.length;

  var matches = true;
  for ( var i = 0; i < len; i++) {
    var key = keys[i];
    if (record[key] !== query[key]) {
      matches = false;
      break;
    }
  }

  return matches;
}

/**
 * Filters fields of an object.
 *
 * @param {Object}
 *            record
 * @param {String[]}
 *            fields String array that specifies all requested keys
 * @returns {Object} filtered object
 */
function filterFields(record, fields) {
  // walk through the array and only inherit the properties in fields
  var len = fields.length;
  if (len > 0) {
    var resultRec = {};
    for ( var i = 0; i < len; i++) {
      var key = fields[j];
      resultRec[key] = record[key];
    }
    return resultRec;
  } else {
    // if fields is empty, return the record as is.
    return record;
  }
}

/**
 * Finds all records that match a given query.
 *
 * @param {Object|String}
 *            query resulting objects must match this query.
 * @param {String[]}
 *            [fields] specifies the fields of the resulting objects
 * @param {Object}
 *            [options] ignored
 * @param {Function(err,
 *            res)} callback is called when an error occurs or when the
 *            record(s) return
 * @param {Error*}
 *            callback.err the error, if an error occurred or `null`
 * @param {Object|Int}
 *            callback.saved the record, if it has been inserted and `1` if the
 *            record has been updated
 */
Collection.prototype.find = function(query, fields, options, callback) {
  // TODO handle options

  // optional arguments
  if (arguments.length == 2) {
    callback = fields;
    fields = [];
    options = {};
  } else if (arguments.length == 3) {
    callback = options;
    options = fields;
    fields = [];
  }

  var results = [];
  var Q = filtr(query);

  // find records
  if (typeof query._id != 'undefined') {
    // check if the record with query._id matches the query
    if (typeof this._coll[query._id] != 'undefined') {
      var rec = this._coll[query._id];
      if (Q.test(rec, {
        type : 'single'
      }))
        results.push(filterFields(rec, fields));
    }
  } else {
    // match against all records
    var keys = Object.keys(this._coll);
    var len = keys.length;
    for ( var i = 0; i < len; i++) {
      var rec = this._coll[keys[i]];
      if (Q.test(rec, {
        type : 'single'
      }))
        results.push(filterFields(rec, fields));
    }
  }

  process.nextTick(function() {
    callback(null, results);
  });
};

/**
 * Finds the first record that matches a given query. Use this method, if you
 * know that there will be only one resulting document. (E.g. when you want to
 * find a result by its `_id`.)
 *
 * @param {Object|String}
 *            query resulting objects must match this query.
 * @param {String[]}
 *            [fields] specifies the fields of the resulting objects
 * @param {Object}
 *            [options] ignored
 * @param {Function(err,
 *            res)} callback is called when an error occurs or when the
 *            record(s) return
 */
Collection.prototype.findOne = function(query, fields, options, callback) {
  // optional arguments
  if (arguments.length == 2) {
    callback = fields;
    fields = [];
    options = {};
  } else if (arguments.length == 3) {
    callback = options;
    options = fields;
    fields = [];
  }

  var result = null;
  var Q = filtr(query);

  // find records
  if (typeof query._id != 'undefined') {
    // check if the record with query._id matches the query
    if (typeof this._coll[query._id] != 'undefined') {
      var rec = this._coll[query._id];
      if (Q.test(rec, {
        type : 'single'
      }))
        result = filterFields(rec, fields);
    }
  } else {
    // match against all records
    var keys = Object.keys(this._coll);
    var len = keys.length;
    for ( var i = 0; i < len; i++) {
      var rec = this._coll[keys[i]];
      if (Q.test(rec, {
        type : 'single'
      })) {
        result = filterFields(rec, fields);
        break;
      }
    }
  }

  // callback results
  process.nextTick(function() {
    callback(null, result);
  });
};

/**
 * Saves a record. If an object with the same `_id` exists already, this will
 * overwrite it completely.
 *
 * @param {Object}
 *            record record that shall be saved. This parameter can be an
 *            arbitrary _non-circular_ JS object that contains only primitive
 *            values or arrays and objects, no functions.
 * @param {String|Int|ObjectId}
 *            [record._id] ID that is used by MongoDB. If no ID is specified,
 *            the a default MongoDB ID will be generated.
 * @param {Object}
 *            [options] ignored
 * @param {Function(err,
 *            saved)} callback is called when an error occurs or when the record
 *            has been saved
 * @param {Error*}
 *            callback.err the error, if an error occurred or `null`
 * @param {Object|Int}
 *            callback.saved the record, if it has been inserted and `1` if the
 *            record has been updated
 */
Collection.prototype.save = function(record, options, callback) {
  // optional arguments
  if (arguments.length == 2) {
    callback = options;
    options = {};
  }

  var _id, result;
  if (typeof record._id == 'undefined') {
    _id = uuid.v1();
    record._id = _id;
    result = record;
  } else {
    _id = record._id;
    result = 1;
  }

  this._coll[_id] = record;

  process.nextTick(function() {
    callback(null, result);
  });
};

/**
 * Removes all records that match the given query object from the collection.
 *
 * @param {Object|String}
 *            query records that match this query will be deleted
 * @param {Object}
 *            [options] ignored
 * @param {Function(err,
 *            deleted)} callback is called when an error occurs or when the
 *            record(s) have been deleted
 * @param {Error*}
 *            callback.err the error, if an error occurred or `null`
 * @param {Object|Int}
 *            callback.deleted the number of records that have been deleted
 */
Collection.prototype.delete = function(query, options, callback) {
  // optional arguments
  if (arguments.length == 2) {
    callback = options;
    options = {};
  }

  var Q = filtr(query);
  var numRemoved = 0;

  // find records
  if (typeof query._id != 'undefined') {
    // check if the record with query._id matches the query
    if (typeof this._coll[query._id] != 'undefined') {
      var rec = this._coll[query._id];
      if (Q.test(rec, {
        type : 'single'
      })) {
        numRemoved++;
        delete this._coll[query._id];
      }
    }
  } else {
    // match against all records
    var keys = Object.keys(this._coll);
    var len = keys.length;
    for ( var i = 0; i < len; i++) {
      var rec = this._coll[keys[i]];
      if (Q.test(rec, {
        type : 'single'
      })) {
        numRemoved++;
        delete this._coll[rec._id];
      }
    }
  }

  // callback results
  process.nextTick(function() {
    callback(null, numRemoved);
  });
};
<commit_msg>Documentation<commit_after>'use strict';

/**
 * A database API for plain JavaScript objects that is compatible to
 * [persistence-mongodb](https://github.com/n-fuse/persistence-memory) and thus
 * can be used as a database abstraction layer for
 * [persistence](https://github.com/n-fuse/persistence).
 *
 * @module persistence-memory
 */

var filtr = require('filtr');
var uuid = require('node-uuid');

var stores = {};

/**
 * Connects to the in-memory database.
 *
 * @param {Object}
 *            [options] ignored (only for compatibility with other
 *            implementations)
 * @param {Function(err,
 *            db)} callback is called when an error occurs or when the database
 *            connection has been established.
 * @param {Error*}
 *            callback.err the error, if an error occurred or `null`
 * @param {DB}
 *            callback.db the `DB` instance
 */
exports.connect = function(options, callback) {
  if (arguments.length == 1) {
    callback = options;
    options = {};
  }

  callback(null, new DB(options));
};

/**
 * @classdesc Dummy wrapper around an array of objects.
 * @constructor
 *
 * @property {String} protocol Database protocol
 */
function DB(options) {
  var counter = 0;
  options = options || {};

  this.increment = function() {
    return ++counter;
  };

  // create empty document store
  this._store = {};
};

DB.prototype.protocol = 'memory';

/**
 * Creates/gets a collection.
 *
 * @param {String}
 *            name collection's name
 * @param {Array}
 *            indexes ignored
 * @param {Function(err,
 *            collection)} callback is called when an error occurs or when the
 *            collection is returned.
 * @param {Error*}
 *            callback.err the error, if an error occurred or `null`
 * @param {Collection}
 *            callback.collection the `Collection` instance
 */
DB.prototype.getCollection = function(name, indexes, callback) {
  if (arguments.length == 2) {
    callback = indexes;
  }

  if (typeof this._store[name] == 'undefined')
    this._store[name] = {};
  var collection = this._store[name];

  process.nextTick(function() {
    callback(null, new Collection(collection));
  });
};

/**
 * Closes the connection to the database.
 *
 * @param {Boolean}
 *            [force] force to close the connect so that it cannot be reused.
 * @param {Function(err,
 *            results)} callback is called when the db has been closed or an
 *            error occurred
 * @param {Error*}
 *            callback.err the error, if an error occurred or `null`
 * @param {Object}
 *            callback.results
 */
DB.prototype.close = function(force, callback) {
  process.nextTick(function () {
    callback(null);
  });
}

/**
 * @classdesc Dummy wrapper around an object.
 * @constructor
 *
 * @param {Object}
 *            collection collection object
 */
function Collection(coll) {
  this._coll = coll;
}

/**
 * Check if the record matches the query.
 *
 * @param {Object}
 *            query query object
 * @param {Object}
 *            record record
 *
 * @returns {Boolean}
 */
function matches(query, record) {
  var keys = Object.keys(query);
  var len = keys.length;

  var matches = true;
  for ( var i = 0; i < len; i++) {
    var key = keys[i];
    if (record[key] !== query[key]) {
      matches = false;
      break;
    }
  }

  return matches;
}

/**
 * Filters fields of an object.
 *
 * @param {Object}
 *            record
 * @param {String[]}
 *            fields String array that specifies all requested keys
 * @returns {Object} filtered object
 */
function filterFields(record, fields) {
  // walk through the array and only inherit the properties in fields
  var len = fields.length;
  if (len > 0) {
    var resultRec = {};
    for ( var i = 0; i < len; i++) {
      var key = fields[j];
      resultRec[key] = record[key];
    }
    return resultRec;
  } else {
    // if fields is empty, return the record as is.
    return record;
  }
}

/**
 * Finds all records that match a given query.
 *
 * @param {Object|String}
 *            query resulting objects must match this query.
 * @param {String[]}
 *            [fields] specifies the fields of the resulting objects
 * @param {Object}
 *            [options] ignored
 * @param {Function(err,
 *            res)} callback is called when an error occurs or when the
 *            record(s) return
 * @param {Error*}
 *            callback.err the error, if an error occurred or `null`
 * @param {Object|Int}
 *            callback.saved the record, if it has been inserted and `1` if the
 *            record has been updated
 */
Collection.prototype.find = function(query, fields, options, callback) {
  // TODO handle options

  // optional arguments
  if (arguments.length == 2) {
    callback = fields;
    fields = [];
    options = {};
  } else if (arguments.length == 3) {
    callback = options;
    options = fields;
    fields = [];
  }

  var results = [];
  var Q = filtr(query);

  // find records
  if (typeof query._id != 'undefined') {
    // check if the record with query._id matches the query
    if (typeof this._coll[query._id] != 'undefined') {
      var rec = this._coll[query._id];
      if (Q.test(rec, {
        type : 'single'
      }))
        results.push(filterFields(rec, fields));
    }
  } else {
    // match against all records
    var keys = Object.keys(this._coll);
    var len = keys.length;
    for ( var i = 0; i < len; i++) {
      var rec = this._coll[keys[i]];
      if (Q.test(rec, {
        type : 'single'
      }))
        results.push(filterFields(rec, fields));
    }
  }

  process.nextTick(function() {
    callback(null, results);
  });
};

/**
 * Finds the first record that matches a given query. Use this method, if you
 * know that there will be only one resulting document. (E.g. when you want to
 * find a result by its `_id`.)
 *
 * @param {Object|String}
 *            query resulting objects must match this query.
 * @param {String[]}
 *            [fields] specifies the fields of the resulting objects
 * @param {Object}
 *            [options] ignored
 * @param {Function(err,
 *            res)} callback is called when an error occurs or when the
 *            record(s) return
 */
Collection.prototype.findOne = function(query, fields, options, callback) {
  // optional arguments
  if (arguments.length == 2) {
    callback = fields;
    fields = [];
    options = {};
  } else if (arguments.length == 3) {
    callback = options;
    options = fields;
    fields = [];
  }

  var result = null;
  var Q = filtr(query);

  // find records
  if (typeof query._id != 'undefined') {
    // check if the record with query._id matches the query
    if (typeof this._coll[query._id] != 'undefined') {
      var rec = this._coll[query._id];
      if (Q.test(rec, {
        type : 'single'
      }))
        result = filterFields(rec, fields);
    }
  } else {
    // match against all records
    var keys = Object.keys(this._coll);
    var len = keys.length;
    for ( var i = 0; i < len; i++) {
      var rec = this._coll[keys[i]];
      if (Q.test(rec, {
        type : 'single'
      })) {
        result = filterFields(rec, fields);
        break;
      }
    }
  }

  // callback results
  process.nextTick(function() {
    callback(null, result);
  });
};

/**
 * Saves a record. If an object with the same `_id` exists already, this will
 * overwrite it completely.
 *
 * @param {Object}
 *            record record that shall be saved. This parameter can be an
 *            arbitrary _non-circular_ JS object that contains only primitive
 *            values or arrays and objects, no functions.
 * @param {String|Int|ObjectId}
 *            [record._id] ID that is used by MongoDB. If no ID is specified,
 *            the a default MongoDB ID will be generated.
 * @param {Object}
 *            [options] ignored
 * @param {Function(err,
 *            saved)} callback is called when an error occurs or when the record
 *            has been saved
 * @param {Error*}
 *            callback.err the error, if an error occurred or `null`
 * @param {Object|Int}
 *            callback.saved the record, if it has been inserted and `1` if the
 *            record has been updated
 */
Collection.prototype.save = function(record, options, callback) {
  // optional arguments
  if (arguments.length == 2) {
    callback = options;
    options = {};
  }

  var _id, result;
  if (typeof record._id == 'undefined') {
    _id = uuid.v1();
    record._id = _id;
    result = record;
  } else {
    _id = record._id;
    result = 1;
  }

  this._coll[_id] = record;

  process.nextTick(function() {
    callback(null, result);
  });
};

/**
 * Removes all records that match the given query object from the collection.
 *
 * @param {Object|String}
 *            query records that match this query will be deleted
 * @param {Object}
 *            [options] ignored
 * @param {Function(err,
 *            deleted)} callback is called when an error occurs or when the
 *            record(s) have been deleted
 * @param {Error*}
 *            callback.err the error, if an error occurred or `null`
 * @param {Object|Int}
 *            callback.deleted the number of records that have been deleted
 */
Collection.prototype.delete = function(query, options, callback) {
  // optional arguments
  if (arguments.length == 2) {
    callback = options;
    options = {};
  }

  var Q = filtr(query);
  var numRemoved = 0;

  // find records
  if (typeof query._id != 'undefined') {
    // check if the record with query._id matches the query
    if (typeof this._coll[query._id] != 'undefined') {
      var rec = this._coll[query._id];
      if (Q.test(rec, {
        type : 'single'
      })) {
        numRemoved++;
        delete this._coll[query._id];
      }
    }
  } else {
    // match against all records
    var keys = Object.keys(this._coll);
    var len = keys.length;
    for ( var i = 0; i < len; i++) {
      var rec = this._coll[keys[i]];
      if (Q.test(rec, {
        type : 'single'
      })) {
        numRemoved++;
        delete this._coll[rec._id];
      }
    }
  }

  // callback results
  process.nextTick(function() {
    callback(null, numRemoved);
  });
};
<|endoftext|>


<commit_before>/**
 * Jquery Multilevel Menu from JSON String
 * @autor David Ticona Saravia
 * @version 1.0
 * @abstract Create Multilevel Menu from JSON String.
 * Formats availables: Unordered list and Select (Combobox)
 *
 */
(function ($) {
    function str_repeat(input, multiplier) {
        var y = '';
        while (true) {
            if (multiplier & 1) {
                y += input;
            }
            multiplier >>= 1;
            if (multiplier) {
                input += input;
            } else {
                break;
            }
        }
        return y;
    }
    $.fn.menuSelect = function (options) {
        var settings = $.extend({
            data: null,
            active: window.location.href,
            title: '',
            group: false,
            bullet: '- '
        }, options);
        var arrJson = settings.data;
        if (typeof settings.data === 'string') {
            try {
                arrJson = JSON.parse(settings.data);
            } catch (e) {
                return null;
            }
        }
        if (this.prop('tagName') === 'SELECT') {
            if (settings.title !== '') {
                let $opt = $('<option>').append(settings.title).val("");
                this.append($opt);
            }
            fillSelect(this, arrJson, settings.active);
            return this;
        } else {
            return null;
        }

        function fillSelect(jqContainer, arrayItem, active, level) {
            var $element = jqContainer;
            level = (typeof (level) === 'undefined') ? 0 : level;
            $.each(arrayItem, function (k, v) {
                var isParent = ((typeof (v.children) !== "undefined") && ($.isArray(v.children)));
                var $opt = $('<option>');
                if (active === v.value) {
                    $opt.addClass('active').prop('selected', true);
                }
                var bullet = (level === 0) ? '' : settings.bullet;
                if ((!settings.group) || ((level === 0) && (!isParent))) {
                    console.log(k + '::: isParent:' + isParent + ', Level:' + level + ', group:' + settings.group);
                    $opt.val(v.value).append(str_repeat(' ', level)).append(bullet + v.text);
                    $element.append($opt);
                }
                if (isParent) {
                    if ((settings.group)) {
                        createGroup($element, v.text, v.children);
                    } else {
                        fillSelect(jqContainer, v.children, active, level + 2);
                    }
                }
            });
        }
        function createGroup(jqContainer, title, items) {
            var $group = $('<optgroup>').attr('label', title);
            $.each(items, function (k, v) {
                var $opt = $('<option>');
                $opt.val(v.value).append(settings.bullet + v.text);
                $group.append($opt);
            });
            jqContainer.append($group);
        }
    };

    $.fn.menuList = function (options) {
        var settings = $.extend({
            data: null,
            active: window.location.href,
            ulParentClass: '',
            aParentClass: '',
            dropdownIcon: null
        }, options);
        var arrJson = settings.data;
        if (typeof settings.data === 'string') {
            try {
                arrJson = JSON.parse(settings.data);
            } catch (e) {
                return null;
            }
        }

        if (this.prop('tagName') === 'UL') {
            renderMenu(this, arrJson, settings.active);
            return this;
        } else {
            return null;
        }

        function renderMenu(jqContainer, arrayItem, active, depth) {
            var level = (typeof (depth) === 'undefined') ? 0 : depth;
            var $elem;
            if (level === 0) {
                $elem = jqContainer;
            } else {
                $elem = $('<ul>').addClass(settings.ulParentClass);
            }
            $.each(arrayItem, function (k, v) {
                var isParent = (typeof (v.children) !== "undefined") && ($.isArray(v.children));
                var $li = $('<li>');
                $li.attr('id', v.text);
                if (v.href === '#') {
                    v.href = 'javascript:void(0)';
                }
                var $a = $('<a>').attr('href', v.href);
                if (active === v.href) {
                    $li.addClass('active');
                }
                let $i = $('<i>').addClass(v.icon);
                $a.append($i).append(" ").append(v.text);
                if ((isParent) && (settings.dropdownIcon !== null)) {
                    $a.append(' ').append(settings.dropdownIcon);
                }
                if ((isParent) && (settings.aParentClass !== '')) {
                    $a.addClass(settings.aParentClass);
                }
                $li.append($a);
                if (isParent) {
                    $li.append(renderMenu(jqContainer, v.children, active, level + 1));
                }
                $elem.append($li);
            });
            return $elem;
        }
    };
}(jQuery));
<commit_msg>Add option propertyValue to menuSelect plugin<commit_after>/**
 * Jquery Multilevel Menu from JSON String
 * @autor David Ticona Saravia
 * @version 1.0
 * @abstract Create Multilevel Menu from JSON String.
 * Formats availables: Unordered list and Select (Combobox)
 *
 */
(function ($) {
    function str_repeat(input, multiplier) {
        var y = '';
        while (true) {
            if (multiplier & 1) {
                y += input;
            }
            multiplier >>= 1;
            if (multiplier) {
                input += input;
            } else {
                break;
            }
        }
        return y;
    }

    $.fn.menuSelect = function (options) {
        var settings = $.extend({
            data: null,
            active: window.location.href,
            title: '',
            group: false,
            bullet: '- ',
            propertyValue: 'value'
        }, options);
        var arrJson = settings.data;
        if (typeof settings.data === 'string') {
            try {
                arrJson = JSON.parse(settings.data);
            } catch (e) {
                return null;
            }
        }
        if (this.prop('tagName') === 'SELECT') {
            if (settings.title !== '') {
                let $opt = $('<option>').append(settings.title).val("");
                this.append($opt);
            }
            fillSelect(this, arrJson, settings.active);
            return this;
        } else {
            return null;
        }

        function fillSelect(jqContainer, arrayItem, active, level) {
            var $element = jqContainer;
            level = (typeof (level) === 'undefined') ? 0 : level;
            $.each(arrayItem, function (k, v) {
                var isParent = ((typeof (v.children) !== "undefined") && ($.isArray(v.children)));
                var $opt = $('<option>');
                var value = v[settings.propValue];
                if (active === value) {
                    $opt.addClass('active').prop('selected', true);
                }
                var bullet = (level === 0) ? '' : settings.bullet;
                if ((!settings.group) || ((level === 0) && (!isParent))) {
                    $opt.val(value).append(str_repeat(' ', level)).append(bullet + v.text);
                    $element.append($opt);
                }
                if (isParent) {
                    if ((settings.group)) {
                        createGroup($element, v.text, v.children);
                    } else {
                        fillSelect(jqContainer, v.children, active, level + 2);
                    }
                }
            });
        }
        function createGroup(jqContainer, title, items) {
            var $group = $('<optgroup>').attr('label', title);
            $.each(items, function (k, v) {
                let $opt = $('<option>');
                $opt.val(v.value).append(settings.bullet + v.text);
                $group.append($opt);
            });
            jqContainer.append($group);
        }
    };

    $.fn.menuList = function (options) {
        var settings = $.extend({
            data: null,
            active: window.location.href,
            ulParentClass: '',
            aParentClass: '',
            dropdownIcon: null
        }, options);
        var arrJson = settings.data;
        if (typeof settings.data === 'string') {
            try {
                arrJson = JSON.parse(settings.data);
            } catch (e) {
                return null;
            }
        }

        if (this.prop('tagName') === 'UL') {
            renderMenu(this, arrJson, settings.active);
            return this;
        } else {
            return null;
        }

        function renderMenu(jqContainer, arrayItem, active, depth) {
            var level = (typeof (depth) === 'undefined') ? 0 : depth;
            var $elem;
            if (level === 0) {
                $elem = jqContainer;
            } else {
                $elem = $('<ul>').addClass(settings.ulParentClass);
            }
            $.each(arrayItem, function (k, v) {
                var isParent = (typeof (v.children) !== "undefined") && ($.isArray(v.children));
                var $li = $('<li>');
                $li.attr('id', v.text);
                if (v.href === '#') {
                    v.href = 'javascript:void(0)';
                }
                var $a = $('<a>').attr('href', v.href);
                if (active === v.href) {
                    $li.addClass('active');
                }
                let $i = $('<i>').addClass(v.icon);
                $a.append($i).append(" ").append(v.text);
                if ((isParent) && (settings.dropdownIcon !== null)) {
                    $a.append(' ').append(settings.dropdownIcon);
                }
                if ((isParent) && (settings.aParentClass !== '')) {
                    $a.addClass(settings.aParentClass);
                }
                $li.append($a);
                if (isParent) {
                    $li.append(renderMenu(jqContainer, v.children, active, level + 1));
                }
                $elem.append($li);
            });
            return $elem;
        }
    };
}(jQuery));
<|endoftext|>


<commit_before>var express = require("express");
var fs = require("fs");
var jade = require("jade");
var mkdirp = require("mkdirp");
var path = require("path");
var walk = require("walk");
var url = require("url");

// Not found
function NotFoundError(file) {
    this.name = "NotFoundError";
    this.message = file + " not found";
    this.stack = (new Error(this.message)).stack;
}
NotFoundError.prototype = new Error();

// Not an output file
function NoExtendsError(file) {
    this.name = "NoExtendsError";
    this.message = file + " does not use a template";
    this.stack = (new Error(this.message)).stack;
}
NoExtendsError.prototype = new Error();

function RenderPipe(dir) {
    this.dir = dir || __dirname;
    this.renderRequest = this.renderRequest.bind(this);
    this.readAsset = this.readAsset.bind(this);
    this.readJsonAsset = this.readJsonAsset.bind(this);

    this.assets = {};
    this.jsonAssets = {};
}

RenderPipe.prototype.listen = function (port) {
    if (this.app) {
        return;
    }

    this.app = express();
    this.app.get(/.*/, this.renderRequest);
    this.app.listen(port || 3000);
};

RenderPipe.prototype.renderRequest = function (req, res, next) {
    var reqpath = url.parse(req.url).pathname;
    var file = path.join(this.dir, reqpath).replace(/\.html$/, ".jade");

    this.renderFile(file, function (err, html) {
        if (err) {
            if (err instanceof NotFoundError) {
                return next();
            } else {
                return next(err);
            }
        }

        res.end(html);
    });
};

RenderPipe.prototype.renderFile = function (file, cb) {
    var self = this;

    fs.exists(file, function (exists) {
        if (!exists) {
            return cb(new NotFoundError(file));
        }

        if (!file.match(/\.jade/)) {
            return cb(new Error(file + " does not look like a Jade file"));
        }

        fs.readFile(file, "utf8", function (err, src) {
            if (err) {
                return cb(err);
            }

            if (!src.match(/^extends/)) {
                return cb(new NoExtendsError(file));
            }

            try {
                var render = jade.compileFile(file, {});
                cb(null, render({
                    read: self.readAsset,
                    readJson: self.readJsonAsset,
                    filename: path.basename(file),
                }));
            } catch (e) {
                cb(e);
            }
        });
    });
};

RenderPipe.prototype.renderStatic = function (out, cb) {
    var self = this;

    var walker = walk.walk(this.dir);
    walker.on("file", function (root, stats, next) {
        if (!stats.name.match(/\.jade$/)) {
            return next();
        }

        var srcPath = path.join(root, stats.name);
        var outDir = path.join(out, root.replace(self.dir, ""));
        var outName = stats.name.replace(/\.jade$/, ".html");

        mkdirp(outDir, function (err) {
            if (err) {
                return cb(err);
            }

            self.renderFile(srcPath, function (err, html) {
                if (err) {
                    if (err instanceof NoExtendsError) {
                        return next(); // Skip it
                    } else {
                        return cb(err);
                    }
                }

                fs.writeFile(path.join(outDir, outName), html, function (err) {
                    if (err) {
                        cb(err);
                    } else {
                        next();
                    }
                });
            });
        });
    });
    walker.on("end", cb);
};

RenderPipe.prototype.readAsset = function (filename) {
    if (!this.assets[filename]) {
        this.assets[filename] = fs.readFileSync(path.join(this.dir, filename), "utf8");
    }
    return this.assets[filename];
};

RenderPipe.prototype.readJsonAsset = function (filename) {
    if (!this.jsonAssets[filename]) {
        this.jsonAssets[filename] = JSON.parse(this.readAsset(filename));
    }
    return this.jsonAssets[filename];
};

module.exports = RenderPipe;
<commit_msg>Fix extends detection.<commit_after>var express = require("express");
var fs = require("fs");
var jade = require("jade");
var mkdirp = require("mkdirp");
var path = require("path");
var walk = require("walk");
var url = require("url");

// Not found
function NotFoundError(file) {
    this.name = "NotFoundError";
    this.message = file + " not found";
    this.stack = (new Error(this.message)).stack;
}
NotFoundError.prototype = new Error();

// Not an output file
function NoExtendsError(file) {
    this.name = "NoExtendsError";
    this.message = file + " does not use a template";
    this.stack = (new Error(this.message)).stack;
}
NoExtendsError.prototype = new Error();

function RenderPipe(dir) {
    this.dir = dir || __dirname;
    this.renderRequest = this.renderRequest.bind(this);
    this.readAsset = this.readAsset.bind(this);
    this.readJsonAsset = this.readJsonAsset.bind(this);

    this.assets = {};
    this.jsonAssets = {};
}

RenderPipe.prototype.listen = function (port) {
    if (this.app) {
        return;
    }

    this.app = express();
    this.app.get(/.*/, this.renderRequest);
    this.app.listen(port || 3000);
};

RenderPipe.prototype.renderRequest = function (req, res, next) {
    var reqpath = url.parse(req.url).pathname;
    var file = path.join(this.dir, reqpath).replace(/\.html$/, ".jade");

    this.renderFile(file, function (err, html) {
        if (err) {
            if (err instanceof NotFoundError) {
                return next();
            } else {
                return next(err);
            }
        }

        res.end(html);
    });
};

RenderPipe.prototype.renderFile = function (file, cb) {
    var self = this;

    fs.exists(file, function (exists) {
        if (!exists) {
            return cb(new NotFoundError(file));
        }

        if (!file.match(/\.jade/)) {
            return cb(new Error(file + " does not look like a Jade file"));
        }

        fs.readFile(file, "utf8", function (err, src) {
            if (err) {
                return cb(err);
            }

            if (!src.match(/(^|\n)extends/)) {
                return cb(new NoExtendsError(file));
            }

            try {
                var render = jade.compileFile(file, {});
                cb(null, render({
                    read: self.readAsset,
                    readJson: self.readJsonAsset,
                    filename: path.basename(file),
                }));
            } catch (e) {
                cb(e);
            }
        });
    });
};

RenderPipe.prototype.renderStatic = function (out, cb) {
    var self = this;

    var walker = walk.walk(this.dir);
    walker.on("file", function (root, stats, next) {
        if (!stats.name.match(/\.jade$/)) {
            return next();
        }

        var srcPath = path.join(root, stats.name);
        var outDir = path.join(out, root.replace(self.dir, ""));
        var outName = stats.name.replace(/\.jade$/, ".html");

        mkdirp(outDir, function (err) {
            if (err) {
                return cb(err);
            }

            self.renderFile(srcPath, function (err, html) {
                if (err) {
                    if (err instanceof NoExtendsError) {
                        return next(); // Skip it
                    } else {
                        return cb(err);
                    }
                }

                fs.writeFile(path.join(outDir, outName), html, function (err) {
                    if (err) {
                        cb(err);
                    } else {
                        next();
                    }
                });
            });
        });
    });
    walker.on("end", cb);
};

RenderPipe.prototype.readAsset = function (filename) {
    if (!this.assets[filename]) {
        this.assets[filename] = fs.readFileSync(path.join(this.dir, filename), "utf8");
    }
    return this.assets[filename];
};

RenderPipe.prototype.readJsonAsset = function (filename) {
    if (!this.jsonAssets[filename]) {
        this.jsonAssets[filename] = JSON.parse(this.readAsset(filename));
    }
    return this.jsonAssets[filename];
};

module.exports = RenderPipe;
<|endoftext|>


<commit_before>'use strict';

const Attribute = require('./Attribute');
const errors = require('./errors');
const VirtualType = require('./VirtualType');
//const util = require('util');

const debug = require('debug')('dynamoose:schema');

function Schema(obj, options) {
  debug('Creating Schema', obj);

  this.tree = {};
  this.methods = {};
  this.statics = {};
  this.virtuals = {};
  this.options = options || {};

  if(this.options.throughput) {
    let throughput = this.options.throughput;
    if(typeof throughput === 'number') {
      throughput = {read: throughput, write: throughput};
    }
    this.throughput = throughput;
  } else {
    this.throughput = {read: 1, write: 1};
  }

  if((!this.throughput.read || !this.throughput.write) &&
  this.throughput.read >= 1 && this.throughput.write >= 1) {
    throw new errors.SchemaError('Invalid throughput: '+ this.throughput);
  }

  /*
  * Added support for timestamps attribute
  */
  if (this.options.timestamps) {
    let createdAt = null;
    let updatedAt = null;

    if (this.options.timestamps === true) {
      createdAt = 'createdAt';
      updatedAt = 'updatedAt';
    } else if (typeof this.options.timestamps === 'object') {
      if (this.options.timestamps.createdAt && this.options.timestamps.updatedAt) {
        createdAt = this.options.timestamps.createdAt;
        updatedAt = this.options.timestamps.updatedAt;
      } else {
        throw new errors.SchemaError('Missing createdAt and updatedAt timestamps attribute. Maybe set timestamps: true?');
      }
    } else {
      throw new errors.SchemaError('Invalid syntax for timestamp: ' + this.options.timestamps);
    }

    obj[createdAt] = obj[createdAt] || {};
    obj[createdAt].type = Date;
    obj[createdAt].default = Date.now;

    obj[updatedAt] = obj[updatedAt] || {};
    obj[updatedAt].type = Date;
    obj[updatedAt].default = Date.now;
    obj[updatedAt].set = function() { return Date.now(); };
    this.timestamps = { createdAt: createdAt, updatedAt: updatedAt };
  }

  /*
  * Added support for expires attribute
  */
  if (this.options.expires !== null && this.options.expires !== undefined ) {
    let expires = {
      attribute: 'expires',
      returnExpiredItems: true
    };

    if (typeof this.options.expires === 'number') {
      expires.ttl = this.options.expires;
    } else if (typeof this.options.expires === 'object') {
      if (typeof this.options.expires.ttl === 'number') {
        expires.ttl = this.options.expires.ttl;
      } else {
        throw new errors.SchemaError('Missing or invalided ttl for expires attribute.');
      }
      if(typeof this.options.expires.attribute === 'string') {
        expires.attribute = this.options.expires.attribute;
      }

      if (typeof this.options.expires.returnExpiredItems === "boolean") {
        expires.returnExpiredItems = this.options.expires.returnExpiredItems;
      }

      if (typeof this.options.expires.defaultExpires === "function") {
        expires.defaultExpires = this.options.expires.defaultExpires;
      }
    } else {
      throw new errors.SchemaError('Invalid syntax for expires: ' + this.options.expires);
    }

    let defaultExpires = function () {
      return new Date(Date.now() + (expires.ttl * 1000));
    };

    obj[expires.attribute] = {
      type: Number,
      default: expires.defaultExpires || defaultExpires,
      set: function(v) {
        return Math.floor(v.getTime() / 1000);
      },
      get: function (v) {
        return new Date(v * 1000);
      }
    };
    this.expires = expires;
  }
  this.useDocumentTypes = this.options.useDocumentTypes === undefined ? true : this.options.useDocumentTypes;
  this.useNativeBooleans = this.options.useNativeBooleans === undefined ? true : this.options.useNativeBooleans;
  this.attributeFromDynamo = this.options.attributeFromDynamo;
  this.attributeToDynamo = this.options.attributeToDynamo;

  this.attributes = {};
  this.indexes = {local: {}, global: {}};

  for(const n in obj) {

    if(this.attributes[n]) {
      throw new errors.SchemaError('Duplicate attribute: ' + n);
    }

    debug('Adding Attribute to Schema (%s)', n, obj);
    this.attributes[n] = Attribute.create(this, n, obj[n]);
  }
}

/*Schema.prototype.attribute = function(name, obj) {
debug('Adding Attribute to Schema (%s)', name, obj);

this Attribute.create(name, obj);

};*/

Schema.prototype.toDynamo = async function(model, options) {

  let dynamoObj = {};
  let name, attr;

  for(name in model) {
    if(!model.hasOwnProperty(name)){
      continue;
    }
    if (model[name] === undefined || model[name] === null || Number.isNaN(model[name])) {
      debug('toDynamo: skipping attribute: %s because its definition or value is null, undefined, or NaN', name);
      continue;
    }
    attr = this.attributes[name];
    if((!attr && this.options.saveUnknown === true) || (Array.isArray(this.options.saveUnknown) && this.options.saveUnknown.indexOf(name) >= 0)) {
      attr = Attribute.create(this, name, model[name]);
      this.attributes[name] = attr;
    }
  }

  for(name in this.attributes) {
    attr = this.attributes[name];

    await attr.setDefault(model);
    let dynamoAttr;
    if (this.attributeToDynamo) {
      dynamoAttr = await this.attributeToDynamo(name, model[name], model, attr.toDynamo.bind(attr), options);
    } else {
      dynamoAttr = await attr.toDynamo(model[name], undefined, model, options);
    }
    if(dynamoAttr) {
      dynamoObj[attr.name] = dynamoAttr;
    }
  }

  debug('toDynamo: %s', dynamoObj );
  return dynamoObj;
};

Schema.prototype.parseDynamo = async function(model, dynamoObj) {

  debug('MADE IT')
  for(const name in dynamoObj) {
    let attr = this.attributes[name];

    if (!attr && this.options.errorUnknown) throw new errors.ParseError(`unknown top-level attribute ${name} on model ${model.$__.name}: ${JSON.stringify(dynamoObj[name])}`)
    if((!attr && this.options.saveUnknown === true) || (Array.isArray(this.options.saveUnknown) && this.options.saveUnknown.indexOf(name) >= 0)) {
      attr = Attribute.createUnknownAttributeFromDynamo(this, name, dynamoObj[name]);
      this.attributes[name] = attr;
    }

    if(attr) {
      let attrVal;
      if (this.attributeFromDynamo) {
        attrVal = await this.attributeFromDynamo(name, dynamoObj[name], attr.parseDynamo.bind(attr), model);
      } else {
        attrVal = await attr.parseDynamo(dynamoObj[name]);
      }
      if (attrVal !== undefined && attrVal !== null) {
        model[name] = attrVal;
      }
    } else {
      debug('parseDynamo: received an attribute name (%s) that is not defined in the schema', name);
    }
  }

  if (model.$__) {
    model.$__.originalItem = JSON.parse(JSON.stringify(model));
  }

  debug('parseDynamo: %s', model);

  return dynamoObj;

};

/**
* Adds an instance method to documents constructed from Models compiled from this schema.
*
* ####Example
*
*     let schema = kittySchema = new Schema(..);
*
*     schema.method('meow', function () {
*       console.log('meeeeeoooooooooooow');
*     })
*
*     let Kitty = mongoose.model('Kitty', schema);
*
*     let fizz = new Kitty;
*     fizz.meow(); // meeeeeooooooooooooow
*
* If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as methods.
*
*     schema.method({
*         purr: function () {}
*       , scratch: function () {}
*     });
*
*     // later
*     fizz.purr();
*     fizz.scratch();
*
* @param {String|Object} method name
* @param {Function} [fn]
* @api public
*/

Schema.prototype.method = function (name, fn) {
  if (typeof name !== 'string' ){
    for (const i in name){
      this.methods[i] = name[i];
    }
  } else {
    this.methods[name] = fn;
  }
  return this;
};

/**
* Adds static "class" methods to Models compiled from this schema.
*
* ####Example
*
*     let schema = new Schema(..);
*     schema.static('findByName', function (name, callback) {
*       return this.find({ name: name }, callback);
*     });
*
*     let Drink = mongoose.model('Drink', schema);
*     Drink.findByName('sanpellegrino', function (err, drinks) {
*       //
*     });
*
* If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as statics.
*
* @param {String} name
* @param {Function} fn
* @api public
*/

Schema.prototype.static = function(name, fn) {
  if (typeof name !== 'string' ){
    for (const i in name){
      this.statics[i] = name[i];
    }
  } else {
    this.statics[name] = fn;
  }
  return this;
};

/**
* Creates a virtual type with the given name.
*
* @param {String} name
* @param {Object} [options]
* @return {VirtualType}
*/

Schema.prototype.virtual = function (name, options) {
  //let virtuals = this.virtuals;
  const parts = name.split('.');

  return this.virtuals[name] = parts.reduce(function (mem, part, i) {
    mem[part] || (mem[part] = (i === parts.length-1) ? new VirtualType(options, name) : {});
    return mem[part];
  }, this.tree);
};

/**
* Returns the virtual type with the given `name`.
*
* @param {String} name
* @return {VirtualType}
*/

Schema.prototype.virtualpath = function (name) {
  return this.virtuals[name];
};

module.exports = Schema;
<commit_msg>Update lib/Schema.js<commit_after>'use strict';

const Attribute = require('./Attribute');
const errors = require('./errors');
const VirtualType = require('./VirtualType');
//const util = require('util');

const debug = require('debug')('dynamoose:schema');

function Schema(obj, options) {
  debug('Creating Schema', obj);

  this.tree = {};
  this.methods = {};
  this.statics = {};
  this.virtuals = {};
  this.options = options || {};

  if(this.options.throughput) {
    let throughput = this.options.throughput;
    if(typeof throughput === 'number') {
      throughput = {read: throughput, write: throughput};
    }
    this.throughput = throughput;
  } else {
    this.throughput = {read: 1, write: 1};
  }

  if((!this.throughput.read || !this.throughput.write) &&
  this.throughput.read >= 1 && this.throughput.write >= 1) {
    throw new errors.SchemaError('Invalid throughput: '+ this.throughput);
  }

  /*
  * Added support for timestamps attribute
  */
  if (this.options.timestamps) {
    let createdAt = null;
    let updatedAt = null;

    if (this.options.timestamps === true) {
      createdAt = 'createdAt';
      updatedAt = 'updatedAt';
    } else if (typeof this.options.timestamps === 'object') {
      if (this.options.timestamps.createdAt && this.options.timestamps.updatedAt) {
        createdAt = this.options.timestamps.createdAt;
        updatedAt = this.options.timestamps.updatedAt;
      } else {
        throw new errors.SchemaError('Missing createdAt and updatedAt timestamps attribute. Maybe set timestamps: true?');
      }
    } else {
      throw new errors.SchemaError('Invalid syntax for timestamp: ' + this.options.timestamps);
    }

    obj[createdAt] = obj[createdAt] || {};
    obj[createdAt].type = Date;
    obj[createdAt].default = Date.now;

    obj[updatedAt] = obj[updatedAt] || {};
    obj[updatedAt].type = Date;
    obj[updatedAt].default = Date.now;
    obj[updatedAt].set = function() { return Date.now(); };
    this.timestamps = { createdAt: createdAt, updatedAt: updatedAt };
  }

  /*
  * Added support for expires attribute
  */
  if (this.options.expires !== null && this.options.expires !== undefined ) {
    let expires = {
      attribute: 'expires',
      returnExpiredItems: true
    };

    if (typeof this.options.expires === 'number') {
      expires.ttl = this.options.expires;
    } else if (typeof this.options.expires === 'object') {
      if (typeof this.options.expires.ttl === 'number') {
        expires.ttl = this.options.expires.ttl;
      } else {
        throw new errors.SchemaError('Missing or invalided ttl for expires attribute.');
      }
      if(typeof this.options.expires.attribute === 'string') {
        expires.attribute = this.options.expires.attribute;
      }

      if (typeof this.options.expires.returnExpiredItems === "boolean") {
        expires.returnExpiredItems = this.options.expires.returnExpiredItems;
      }

      if (typeof this.options.expires.defaultExpires === "function") {
        expires.defaultExpires = this.options.expires.defaultExpires;
      }
    } else {
      throw new errors.SchemaError('Invalid syntax for expires: ' + this.options.expires);
    }

    let defaultExpires = function () {
      return new Date(Date.now() + (expires.ttl * 1000));
    };

    obj[expires.attribute] = {
      type: Number,
      default: expires.defaultExpires || defaultExpires,
      set: function(v) {
        return Math.floor(v.getTime() / 1000);
      },
      get: function (v) {
        return new Date(v * 1000);
      }
    };
    this.expires = expires;
  }
  this.useDocumentTypes = this.options.useDocumentTypes === undefined ? true : this.options.useDocumentTypes;
  this.useNativeBooleans = this.options.useNativeBooleans === undefined ? true : this.options.useNativeBooleans;
  this.attributeFromDynamo = this.options.attributeFromDynamo;
  this.attributeToDynamo = this.options.attributeToDynamo;

  this.attributes = {};
  this.indexes = {local: {}, global: {}};

  for(const n in obj) {

    if(this.attributes[n]) {
      throw new errors.SchemaError('Duplicate attribute: ' + n);
    }

    debug('Adding Attribute to Schema (%s)', n, obj);
    this.attributes[n] = Attribute.create(this, n, obj[n]);
  }
}

/*Schema.prototype.attribute = function(name, obj) {
debug('Adding Attribute to Schema (%s)', name, obj);

this Attribute.create(name, obj);

};*/

Schema.prototype.toDynamo = async function(model, options) {

  let dynamoObj = {};
  let name, attr;

  for(name in model) {
    if(!model.hasOwnProperty(name)){
      continue;
    }
    if (model[name] === undefined || model[name] === null || Number.isNaN(model[name])) {
      debug('toDynamo: skipping attribute: %s because its definition or value is null, undefined, or NaN', name);
      continue;
    }
    attr = this.attributes[name];
    if((!attr && this.options.saveUnknown === true) || (Array.isArray(this.options.saveUnknown) && this.options.saveUnknown.indexOf(name) >= 0)) {
      attr = Attribute.create(this, name, model[name]);
      this.attributes[name] = attr;
    }
  }

  for(name in this.attributes) {
    attr = this.attributes[name];

    await attr.setDefault(model);
    let dynamoAttr;
    if (this.attributeToDynamo) {
      dynamoAttr = await this.attributeToDynamo(name, model[name], model, attr.toDynamo.bind(attr), options);
    } else {
      dynamoAttr = await attr.toDynamo(model[name], undefined, model, options);
    }
    if(dynamoAttr) {
      dynamoObj[attr.name] = dynamoAttr;
    }
  }

  debug('toDynamo: %s', dynamoObj );
  return dynamoObj;
};

Schema.prototype.parseDynamo = async function(model, dynamoObj) {

  debug('MADE IT')
  for(const name in dynamoObj) {
    let attr = this.attributes[name];

    if (!attr && this.options.errorUnknown) {
      throw new errors.ParseError(`Unknown top-level attribute ${name} on model ${model.$__.name}: ${JSON.stringify(dynamoObj[name])}`)
    }
    if((!attr && this.options.saveUnknown === true) || (Array.isArray(this.options.saveUnknown) && this.options.saveUnknown.indexOf(name) >= 0)) {
      attr = Attribute.createUnknownAttributeFromDynamo(this, name, dynamoObj[name]);
      this.attributes[name] = attr;
    }

    if(attr) {
      let attrVal;
      if (this.attributeFromDynamo) {
        attrVal = await this.attributeFromDynamo(name, dynamoObj[name], attr.parseDynamo.bind(attr), model);
      } else {
        attrVal = await attr.parseDynamo(dynamoObj[name]);
      }
      if (attrVal !== undefined && attrVal !== null) {
        model[name] = attrVal;
      }
    } else {
      debug('parseDynamo: received an attribute name (%s) that is not defined in the schema', name);
    }
  }

  if (model.$__) {
    model.$__.originalItem = JSON.parse(JSON.stringify(model));
  }

  debug('parseDynamo: %s', model);

  return dynamoObj;

};

/**
* Adds an instance method to documents constructed from Models compiled from this schema.
*
* ####Example
*
*     let schema = kittySchema = new Schema(..);
*
*     schema.method('meow', function () {
*       console.log('meeeeeoooooooooooow');
*     })
*
*     let Kitty = mongoose.model('Kitty', schema);
*
*     let fizz = new Kitty;
*     fizz.meow(); // meeeeeooooooooooooow
*
* If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as methods.
*
*     schema.method({
*         purr: function () {}
*       , scratch: function () {}
*     });
*
*     // later
*     fizz.purr();
*     fizz.scratch();
*
* @param {String|Object} method name
* @param {Function} [fn]
* @api public
*/

Schema.prototype.method = function (name, fn) {
  if (typeof name !== 'string' ){
    for (const i in name){
      this.methods[i] = name[i];
    }
  } else {
    this.methods[name] = fn;
  }
  return this;
};

/**
* Adds static "class" methods to Models compiled from this schema.
*
* ####Example
*
*     let schema = new Schema(..);
*     schema.static('findByName', function (name, callback) {
*       return this.find({ name: name }, callback);
*     });
*
*     let Drink = mongoose.model('Drink', schema);
*     Drink.findByName('sanpellegrino', function (err, drinks) {
*       //
*     });
*
* If a hash of name/fn pairs is passed as the only argument, each name/fn pair will be added as statics.
*
* @param {String} name
* @param {Function} fn
* @api public
*/

Schema.prototype.static = function(name, fn) {
  if (typeof name !== 'string' ){
    for (const i in name){
      this.statics[i] = name[i];
    }
  } else {
    this.statics[name] = fn;
  }
  return this;
};

/**
* Creates a virtual type with the given name.
*
* @param {String} name
* @param {Object} [options]
* @return {VirtualType}
*/

Schema.prototype.virtual = function (name, options) {
  //let virtuals = this.virtuals;
  const parts = name.split('.');

  return this.virtuals[name] = parts.reduce(function (mem, part, i) {
    mem[part] || (mem[part] = (i === parts.length-1) ? new VirtualType(options, name) : {});
    return mem[part];
  }, this.tree);
};

/**
* Returns the virtual type with the given `name`.
*
* @param {String} name
* @return {VirtualType}
*/

Schema.prototype.virtualpath = function (name) {
  return this.virtuals[name];
};

module.exports = Schema;
<|endoftext|>


<commit_before>/**
 * ignis.js
 *
 * @author  Denis Luchkin-Zhou <denis@ricepo.com>
 * @license MIT
 */

import Express     from 'express';
import Bluebird    from 'bluebird';
import Monologue   from 'monologue.js';

/**
 * IgnisApp
 *
 * @description Ignis application class.
 */
export class Ignis extends Monologue {

  constructor(name) {
    super();
    this.name       = name || 'ignis-app';

    /* Ignis application middleware management */
    this.factories  = [ ];

    /* Promises to wait on */
    this.startup    = Bluebird.resolve();
    this.extensions = new Set();

    /* Root express router */
    this.root       = Express();
  }

  /**
   * wait(1)
   *
   * @access         public
   * @description                Makes Ignis wait for the promise before starting.
   * @param          {action}    Function to call and wait for.
   * @returns        {Ignis}     Ignis instance for further chaining.
   */
  wait(action) {
    if (typeof action === 'function') {
      this.startup = this.startup.then(i => action.call(this, this.root));
    } else {
      throw new Error('Cannot wait on non-function objects.');
    }
    return this;
  }

  /**
   * listen(1)
   *
   * @description                Creates an Express.js application, mounts the
   *                             root router and listens for connections on the
   *                             specified port.
   * @param          {port}      [Optional] Port to listen on (default: PORT)
   * @returns        {promise}   Rejects when an error occurs.
   */
  listen(port) {
    if (typeof port !== 'number') { port = Number(process.env.PORT); }
    return Bluebird.fromNode((done) => {
      this.root.listen(port, done);
    });
  }

  /**
   * use(1)
   *
   * @access         public
   * @description                Make Ignis use the extension.
   * @param          {fn}        Function exported by the extension module.
   * @returns        {Ignis}     Ignis class for further chaining.
   */
  use(fn) {
    if (typeof fn === 'object' && typeof fn.default === 'function') {
      fn = fn.default;
    }
    if (!this.extensions.has(fn)) {
      this.extensions.add(fn);
      fn(this);
    }
    return this;
  }

}

/*!
 * Ignis root namespace object.
 */
const instance = new Ignis();
export default instance;
<commit_msg>Make Ignis.listen() wait for startup queue to clear<commit_after>/**
 * ignis.js
 *
 * @author  Denis Luchkin-Zhou <denis@ricepo.com>
 * @license MIT
 */

import Express     from 'express';
import Bluebird    from 'bluebird';
import Monologue   from 'monologue.js';

/**
 * IgnisApp
 *
 * @description Ignis application class.
 */
export class Ignis extends Monologue {

  constructor(name) {
    super();
    this.name       = name || 'ignis-app';

    /* Ignis application middleware management */
    this.factories  = [ ];

    /* Promises to wait on */
    this.startup    = Bluebird.resolve();
    this.extensions = new Set();

    /* Root express router */
    this.root       = Express();
  }

  /**
   * wait(1)
   *
   * @access         public
   * @description                Makes Ignis wait for the promise before starting.
   * @param          {action}    Function to call and wait for.
   * @returns        {Ignis}     Ignis instance for further chaining.
   */
  wait(action) {
    if (typeof action === 'function') {
      this.startup = this.startup.then(i => action.call(this, this.root));
    } else {
      throw new Error('Cannot wait on non-function objects.');
    }
    return this;
  }

  /**
   * listen(1)
   *
   * @description                Creates an Express.js application, mounts the
   *                             root router and listens for connections on the
   *                             specified port.
   * @param          {port}      [Optional] Port to listen on (default: PORT)
   * @returns        {promise}   Rejects when an error occurs.
   */
  listen(port) {
    if (typeof port !== 'number') { port = Number(process.env.PORT); }
    this.wait(i =>
      Bluebird.fromNode((done) => {
        this.root.listen(port, done);
      })
    );
    return this.startup;
  }

  /**
   * use(1)
   *
   * @access         public
   * @description                Make Ignis use the extension.
   * @param          {fn}        Function exported by the extension module.
   * @returns        {Ignis}     Ignis class for further chaining.
   */
  use(fn) {
    if (typeof fn === 'object' && typeof fn.default === 'function') {
      fn = fn.default;
    }
    if (!this.extensions.has(fn)) {
      this.extensions.add(fn);
      fn(this);
    }
    return this;
  }

}

/*!
 * Ignis root namespace object.
 */
const instance = new Ignis();
export default instance;
<|endoftext|>


<commit_before>/* Implement TCP Server(s) per protocol */

var EventEmitter = require('events').EventEmitter;
var net = require('net');
var Tracker = require('./Tracker');

var Server = new EventEmitter;

/**
 * Constructor
 * @param {options} options
 */
Server = function (opts) {
  this.config = {
    timeout: 120    // in s
  };

  if( typeof opts === 'object' && Object.keys(opts) .length >= 1 ) {
    for (var key in opts) {
        this.config[key] = opts[key];
    }
  }

  this.trackers = [];

  var server = this;
  this.tcpServers = [];

  /* Start servers for protocols */

  /* Incutex TK104 */
  this.tcpServers[Tracker.TK104.protocol] = net.CreateServer( function(connection) {
    var tracker = new Tracker(Tracker.TK104.protocol, connection, {timeout: server.config.timeout});

    tracker.on('connect', function(imei) { server.emit('connect', imei, tracker); });

    tracker.on('message', function(message) { server.emit('message', message, tracker); });
    tracker.on('position', function(pos) { server.emit('position', pos, tracker); });

    tracker.on('packet.in', function(packet){ server.emit('packet.in', packet, tracker); });
    tracker.on('packet.out', function(packet){ server.emit('packet.out', packet, tracker); });

    tracker.on('error', function(err, data){ server.emit('error', err, data); });
    tracker.on('disconnect', function() {
        for (var i in server.trackers) {
            if (server.trackers[i] == tracker) {
                server.emit('disconnect', tracker);
                delete server.trackers[i];
              }
          }
    });

    server.trackers.push(tracker);

  }).listen(Tracker.TK104.port, function() {  server.emit('listen', Tracker.TK104.protocol, Tracker.TK104.port); });

  /* Konga KT90 */
  this.tcpServers[Tracker.KT90.protocol] = net.CreateServer( function(connection) {
    var tracker = new Tracker(Tracker.KT90.protocol, connection, {timeout: server.config.timeout});

    tracker.on('connect', function(imei) { server.emit('connect', imei, tracker); });

    tracker.on('message', function(message){ server.emit('message', message, tracker); });
    tracker.on('position', function(pos) { server.emit('position', pos, tracker); });

    tracker.on('packet.in', function(packet){ server.emit('packet.in', packet, tracker); });
    tracker.on('packet.out', function(packet){ server.emit('packet.out', packet, tracker); });

    tracker.on('error', function(err, data){ server.emit('error', err, data); });
    tracker.on('disconnect', function() {
        for (var i in server.trackers) {
            if (server.trackers[i] == tracker) {
                server.emit('disconnect', tracker);
                delete server.trackers[i];
              }
          }
    });

    server.trackers.push(tracker);

  }).listen(Tracker.KT90.port, function() {  server.emit('listen', Tracker.KT90.protocol, Tracker.KT90.port); });

  return this;
}

module.exports = Server;
<commit_msg>Update Server.js<commit_after>/* Implement TCP Server(s) per protocol */

var EventEmitter = require('events').EventEmitter;
var net = require('net');
var Tracker = require('./Tracker');

var Server = new EventEmitter;

/**
 * Constructor
 * @param {options} options
 */
Server = function (opts) {
  this.config = {
    timeout: 120    // in s
  };

  if( typeof opts === 'object') {
    for (var key in opts) {
      if (typeof this.config[key] !== 'undefined') {
        this.config[key] = opts[key];
      }
    }
  }

  this.trackers = [];

  var server = this;
  this.tcpServers = [];

  /* Start servers for protocols */

  /* Incutex TK104 */
  this.tcpServers[Tracker.TK104.protocol] = net.CreateServer( function(connection) {
    var tracker = new Tracker(Tracker.TK104.protocol, connection, {timeout: server.config.timeout});

    tracker.on('connect', function(imei) { server.emit('connect', imei, tracker); });

    tracker.on('message', function(message) { server.emit('message', message, tracker); });
    tracker.on('position', function(pos) { server.emit('position', pos, tracker); });

    tracker.on('packet.in', function(packet){ server.emit('packet.in', packet, tracker); });
    tracker.on('packet.out', function(packet){ server.emit('packet.out', packet, tracker); });

    tracker.on('error', function(err, data){ server.emit('error', err, data); });
    tracker.on('disconnect', function() {
        for (var i in server.trackers) {
            if (server.trackers[i] == tracker) {
                server.emit('disconnect', tracker);
                delete server.trackers[i];
              }
          }
    });

    server.trackers.push(tracker);

  }).listen(Tracker.TK104.port, function() {  server.emit('listen', Tracker.TK104.protocol, Tracker.TK104.port); });

  /* Konga KT90 */
  this.tcpServers[Tracker.KT90.protocol] = net.CreateServer( function(connection) {
    var tracker = new Tracker(Tracker.KT90.protocol, connection, {timeout: server.config.timeout});

    tracker.on('connect', function(imei) { server.emit('connect', imei, tracker); });

    tracker.on('message', function(message){ server.emit('message', message, tracker); });
    tracker.on('position', function(pos) { server.emit('position', pos, tracker); });

    tracker.on('packet.in', function(packet){ server.emit('packet.in', packet, tracker); });
    tracker.on('packet.out', function(packet){ server.emit('packet.out', packet, tracker); });

    tracker.on('error', function(err, data){ server.emit('error', err, data); });
    tracker.on('disconnect', function() {
        for (var i in server.trackers) {
            if (server.trackers[i] == tracker) {
                server.emit('disconnect', tracker);
                delete server.trackers[i];
              }
          }
    });

    server.trackers.push(tracker);

  }).listen(Tracker.KT90.port, function() {  server.emit('listen', Tracker.KT90.protocol, Tracker.KT90.port); });

  return this;
}

module.exports = Server;
<|endoftext|>


<commit_before>"use strict"

const EventEmitter = require("events");
const PassThrough = require("stream").PassThrough;
const Sequence = require("./Sequence");
const cache_ns = "s:";

module.exports = (scope, sequence_id, options = {}) => {

    let role = (options.session ? options.session.role : null) || scope.env.role;
    let stream = scope.cache.get(cache_ns + sequence_id);
    if (!stream) {
        stream = Stream(scope, sequence_id, options.objectMode);
        scope.cache.set(cache_ns + sequence_id, stream);
        Sequence(scope, sequence_id, role, stream);
    }

    return stream;
};

function Stream (scope, sequence_id, objectMode = true) {

    const stream = new EventEmitter();
    stream.readable = true;
    stream.writable = true;
    stream.objectMode = objectMode;
    stream.id = sequence_id;

    // create input stream
    stream._i = new PassThrough({objectMode: objectMode});
    stream._i.cork();

    // create output stream
    stream._o = new PassThrough({objectMode: objectMode});
    stream._o.on("unpipe", () => stream.end());
    stream._o.on('data', (chunk) => stream.emit('data', chunk));
	stream._o.once('end', () => stream.emit('end'));

    stream.write = chunk => {
        stream._chunk = chunk;
        !stream.ended && stream._i.write(chunk);
    };

    stream.end = chunk => {
		scope.cache.del(cache_ns + sequence_id);
        stream.ready ? stream._i.end(chunk) : stream.once("ready", () => {
            stream._i.end(chunk);
        });
        stream.ended = true;
        stream.readable = false;
        stream.writable = false;
	};

    // input
    stream.cork = () => stream._i.cork();
    stream.uncork = () => stream._i.uncork();

    // output
    stream.unpipe = dest => stream._o.unpipe(dest);
    stream.pipe = dest => {return stream._o.pipe(dest)};

    return stream;
}
<commit_msg>dont cache streams<commit_after>"use strict"

const EventEmitter = require("events");
const PassThrough = require("stream").PassThrough;
const Sequence = require("./Sequence");

module.exports = (scope, sequence_id, options = {}) => {

    let role = (options.session ? options.session.role : scope.env.role) || scope.env.role;
    let stream = Stream(scope, sequence_id, options.objectMode);
    Sequence(scope, sequence_id, role, stream);

    return stream;
};

function Stream (scope, sequence_id, objectMode = true) {

    const stream = new EventEmitter();
    stream.readable = true;
    stream.writable = true;
    stream.objectMode = objectMode;
    stream.id = sequence_id;

    // create input stream
    stream._i = new PassThrough({objectMode: objectMode});
    stream._i.cork();

    // create output stream
    stream._o = new PassThrough({objectMode: objectMode});
    stream._o.on("unpipe", () => stream.end());
    stream._o.on('data', (chunk) => stream.emit('data', chunk));
	stream._o.once('end', () => stream.emit('end'));

    stream.write = chunk => {
        stream._chunk = chunk;
        !stream.ended && stream._i.write(chunk);
    };

    stream.end = chunk => {
        stream.ready ? stream._i.end(chunk) : stream.once("ready", () => {
            stream._i.end(chunk);
        });
        stream.ended = true;
        stream.readable = false;
        stream.writable = false;
	};

    // input
    stream.cork = () => stream._i.cork();
    stream.uncork = () => stream._i.uncork();

    // output
    stream.unpipe = dest => stream._o.unpipe(dest);
    stream.pipe = dest => {return stream._o.pipe(dest)};

    return stream;
}
<|endoftext|>


<commit_before>require("babel-polyfill");

import fs from "fs";
import gm from "gm";
import config from "config";
import log from "./log";
import uuid from "uuid/v4";

const gmOptions = {};
if (config.has('timeout.conversion')) {
  const timeout = Number(config.get('timeout.conversion'));
  if (isNaN(timeout)) {
    log('warn', 'The configuration value of timeout.conversion resolved to a NaN value. Ignoring it!');
  } else if (timeout < 0) {
    log('warn', 'The configuration value of timeout.conversion did not resolve to a nonnegative value. Ignoring it!');
  } else if (timeout === 0) {
    log('info', 'Not setting any image timeout');
  } else {
    gmOptions.timeout = timeout;
  }
}

log('info', `Booting gm with the following options: ${JSON.stringify(gmOptions)}`);

const im = gm.subClass({imageMagick: true});

// 10 seconds
const clearTempfilesTimeout = 10000;

// Wrap these calls in promises so we can use async/await
const write = (client, file) => {
  return new Promise((resolve, reject) => client.write(file, err => err ? reject(err) : resolve()));
};
const size = (client) => {
  return new Promise((resolve, reject) => client.size({bufferStream: true}, (err, data) => err ? reject(err) : resolve(data)));
};

// Interlacing for png isn't efficient (both in filesize as render performance), so we only do it for jpg
const interlace = async(client, params) => {
  if (params.mime === 'image/jpeg') {
    return client.interlace('Line');
  }
  return client;
};

// When cropping, we size the image first to fix completely within the bounding box
// Then we crop the requested size, and center to the center of the image
const crop = async(client, params) => {
  // Resize the image to fit within the bounding box
  // The ^ ensures the images is resized while maintaining the ratio
  // However the sizes are treated as minimum values instead of maximum values
  client = client.resize(params.width, params.height, '^');
  const tmpFile = `/tmp/${uuid()}`;
  try {
    await write(client, tmpFile);
    client = im(tmpFile).options(gmOptions);
    const imgSize = await size(client);
    setTimeout(() => fs.unlink(tmpFile), clearTempfilesTimeout);
    return client
      .repage(imgSize.width, imgSize.height, 0, 0)
      .gravity('Center')
      // Crop the image to the exact size (the ! indicates a force)
      // This is ok since we first resized appropriately
      .crop(params.width, params.height, '!');
  } catch (e) {
    log('error', 'could not write tempfile');
    log('error', e.stack);
    throw e;
  }
};

// The sizes in the params given define the bounding box. The image is sized
// proportionally such that it fits in the bounding box without cropping
const clip = async(client, params) => {
  return client.resize(params.width, params.height);
};

const cover = async(client, params) => {
  return client.resize(params.width, params.height, '^');
};

// Same as clipping, however the remainder of the bounding box is filled with
// white.
const canvas = async(client, params) => {
  client = await clip(client, params);
  return client.gravity('Center').extent(params.width, params.height);
};

// Fill a transparent background with white
const background = async(client, params) => {
	if (params.mime === 'image/jpeg') {
		return client.background('white').flatten();
	}
	return client;
};

// Fit the image appropriately.
const fit = async(client, params) => {
  //For original format
  if (!params.width || !params.height) {
    return client;
  }
  if (params.fit === 'crop') {
    return crop(client, params);
  } else if (params.fit === 'canvas') {
    return canvas(client, params);
  } else if (params.fit === 'clip') {
    return clip(client, params);
  } else if (params.fit === 'cover') {
    return cover(client, params);
  }
  throw new Error(`Format '${params.fit}' was accepted but could not be handled`);
};

const setQuality = async(client, params) => {
  if (params.quality === -1) {
    return client;
  }

  // The imagemagick 'quality' parameter has a very different meaning for
  // different image types, so it's not a good idea to just blindly pass it
  // through. For now, we only support jpg compression, which is the most intuitive.
  switch (params.mime) {
    case 'image/jpeg':
      return client.quality(Math.min(100, Math.max(0, params.quality)));
    default:
      //No compression supported for other types
      return client;
  }
};

// Blur the image if requested in the params
const blur = async(client, params) => {
  if (params.blur === null) {
    return client;
  }
  return client.blur(params.blur.radius, params.blur.sigma);
};

export default {
  magic: async function (file, params) {
    let client = im(file).options(gmOptions);
    client = await fit(client, params);
    client = await background(client, params);
    client = await blur(client, params);
    client = await setQuality(client, params);
    client = await interlace(client, params);
    return client;
  },
  writeOriented: async function (source, destination, cropParameters) {
    // if possible, crop first (since the UA had that orientation), then orient
    if (cropParameters) {
      const cropped = im(source).options(gmOptions)
          .crop(cropParameters.width, cropParameters.height, cropParameters.xOffset, cropParameters.yOffset);
      try {
        await write(cropped, source);
      } catch (e) {
        log('error', e.stack);
        throw e;
      }
    }

    const oriented = im(source).options(gmOptions).autoOrient();

    try {
      await write(oriented, destination);
    } catch (e) {
      log('error', e.stack);
      throw e;
    }

    try {
      const imgSize = await size(im(destination).options(gmOptions));
      return {
        originalHeight: imgSize.height || null,
        originalWidth: imgSize.width || null
      };
    } catch (e) {
      log('error', e.stack);
      return {
        originalHeight: null,
        originalWidth: null
      };
    }
  },
  imageSize: async function (path) {
    return size(im(path));
  },
  imageArea: async function (path) {
    try {
      const imgSize = await size(im(path).options(gmOptions));
      return imgSize.width * imgSize.height;
    } catch (e) {
      log('error', e);
      return Number.MAX_SAFE_INTEGER;
    }
  }
};
<commit_msg>Apply the timeouts consistently<commit_after>require("babel-polyfill");

import fs from "fs";
import gm from "gm";
import config from "config";
import log from "./log";
import uuid from "uuid/v4";

const gmOptions = {};
if (config.has('timeout.conversion')) {
  const timeout = Number(config.get('timeout.conversion'));
  if (isNaN(timeout)) {
    log('warn', 'The configuration value of timeout.conversion resolved to a NaN value. Ignoring it!');
  } else if (timeout < 0) {
    log('warn', 'The configuration value of timeout.conversion did not resolve to a nonnegative value. Ignoring it!');
  } else if (timeout === 0) {
    log('info', 'Not setting any image timeout');
  } else {
    gmOptions.timeout = timeout;
  }
}

const options = Object.assign({}, {imageMagick: true}, gmOptions);
log('info', `Booting gm with the following options: ${JSON.stringify(options)}`);

const im = gm.subClass(options);

// 10 seconds
const clearTempfilesTimeout = 10000;

// Wrap these calls in promises so we can use async/await
const write = (client, file) => {
  return new Promise((resolve, reject) => client.write(file, err => err ? reject(err) : resolve()));
};
const size = (client) => {
  return new Promise((resolve, reject) => client.size({bufferStream: true}, (err, data) => err ? reject(err) : resolve(data)));
};

// Interlacing for png isn't efficient (both in filesize as render performance), so we only do it for jpg
const interlace = async(client, params) => {
  if (params.mime === 'image/jpeg') {
    return client.interlace('Line');
  }
  return client;
};

// When cropping, we size the image first to fix completely within the bounding box
// Then we crop the requested size, and center to the center of the image
const crop = async(client, params) => {
  // Resize the image to fit within the bounding box
  // The ^ ensures the images is resized while maintaining the ratio
  // However the sizes are treated as minimum values instead of maximum values
  client = client.resize(params.width, params.height, '^');
  const tmpFile = `/tmp/${uuid()}`;
  try {
    await write(client, tmpFile);
    client = im(tmpFile).options(gmOptions);
    const imgSize = await size(client);
    setTimeout(() => fs.unlink(tmpFile), clearTempfilesTimeout);
    return client
      .repage(imgSize.width, imgSize.height, 0, 0)
      .gravity('Center')
      // Crop the image to the exact size (the ! indicates a force)
      // This is ok since we first resized appropriately
      .crop(params.width, params.height, '!');
  } catch (e) {
    log('error', 'could not write tempfile');
    log('error', e.stack);
    throw e;
  }
};

// The sizes in the params given define the bounding box. The image is sized
// proportionally such that it fits in the bounding box without cropping
const clip = async(client, params) => {
  return client.resize(params.width, params.height);
};

const cover = async(client, params) => {
  return client.resize(params.width, params.height, '^');
};

// Same as clipping, however the remainder of the bounding box is filled with
// white.
const canvas = async(client, params) => {
  client = await clip(client, params);
  return client.gravity('Center').extent(params.width, params.height);
};

// Fill a transparent background with white
const background = async(client, params) => {
	if (params.mime === 'image/jpeg') {
		return client.background('white').flatten();
	}
	return client;
};

// Fit the image appropriately.
const fit = async(client, params) => {
  //For original format
  if (!params.width || !params.height) {
    return client;
  }
  if (params.fit === 'crop') {
    return crop(client, params);
  } else if (params.fit === 'canvas') {
    return canvas(client, params);
  } else if (params.fit === 'clip') {
    return clip(client, params);
  } else if (params.fit === 'cover') {
    return cover(client, params);
  }
  throw new Error(`Format '${params.fit}' was accepted but could not be handled`);
};

const setQuality = async(client, params) => {
  if (params.quality === -1) {
    return client;
  }

  // The imagemagick 'quality' parameter has a very different meaning for
  // different image types, so it's not a good idea to just blindly pass it
  // through. For now, we only support jpg compression, which is the most intuitive.
  switch (params.mime) {
    case 'image/jpeg':
      return client.quality(Math.min(100, Math.max(0, params.quality)));
    default:
      //No compression supported for other types
      return client;
  }
};

// Blur the image if requested in the params
const blur = async(client, params) => {
  if (params.blur === null) {
    return client;
  }
  return client.blur(params.blur.radius, params.blur.sigma);
};

export default {
  magic: async function (file, params) {
    let client = im(file).options(gmOptions);
    client = await fit(client, params);
    client = await background(client, params);
    client = await blur(client, params);
    client = await setQuality(client, params);
    client = await interlace(client, params);
    return client;
  },
  writeOriented: async function (source, destination, cropParameters) {
    // if possible, crop first (since the UA had that orientation), then orient
    if (cropParameters) {
      const cropped = im(source).options(gmOptions)
          .crop(cropParameters.width, cropParameters.height, cropParameters.xOffset, cropParameters.yOffset);
      try {
        await write(cropped, source);
      } catch (e) {
        log('error', e.stack);
        throw e;
      }
    }

    const oriented = im(source).options(gmOptions).autoOrient();

    try {
      await write(oriented, destination);
    } catch (e) {
      log('error', e.stack);
      throw e;
    }

    try {
      const imgSize = await size(im(destination).options(gmOptions));
      return {
        originalHeight: imgSize.height || null,
        originalWidth: imgSize.width || null
      };
    } catch (e) {
      log('error', e.stack);
      return {
        originalHeight: null,
        originalWidth: null
      };
    }
  },
  imageSize: async function (path) {
    return size(im(path).options(gmOptions));
  },
  imageArea: async function (path) {
    try {
      const imgSize = await size(im(path).options(gmOptions));
      return imgSize.width * imgSize.height;
    } catch (e) {
      log('error', e);
      return Number.MAX_SAFE_INTEGER;
    }
  }
};
<|endoftext|>


<commit_before>/*
Copyright (c) 2015 Simon Cullen, http://github.com/cullens

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/
'use strict';

/**
 * @class Tasker
 * @mixes $thing.Base
 * @memberOf $thing
 */
$thing.Tasker = new ($thing.Base.inherit({

    doAction: function(container, selector, iteration) {
        var self = this;

        container.isTaskerQueued = true;

        if (iteration > selector.length) {
            selector.select();
            iteration = 0;
        }

        if (selector.length === 0) {
            selector.release();
            container.isTaskerQueued = false;
        }
        else {

            selector.schedule();

            selector.dispatch(
                {   filters: $thing.Filter.FIRST,
                    method: 'action',
                    args: []
                },
                function(cbNext) {
                    cbNext();
                },
                function() {

                    $thing.async.setImmediate(function() {
                        self.doAction(container, selector, ++iteration);
                    });

                }
            );

        }

    },

    thread: function(threadId) {
        if (threadId === undefined)
            threadId = $thing.getThreadId(1);

        var container = $thing.getContainer(threadId);

        if (!container.isTaskerQueued) {

            var selector = new $thing.Selector(threadId, [['Behaviour']], false);

            selector.select();

            this.doAction(
                container,
                selector,
                0
            );

        }

    }

}))();<commit_msg>Wake improvements for HRRN<commit_after>/*
Copyright (c) 2015 Simon Cullen, http://github.com/cullens

Permission is hereby granted, free of charge, to any person
obtaining a copy of this software and associated documentation
files (the "Software"), to deal in the Software without
restriction, including without limitation the rights to use,
copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the
Software is furnished to do so, subject to the following
conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
*/
'use strict';

/**
 * @class Tasker
 * @mixes $thing.Base
 * @memberOf $thing
 */
$thing.Tasker = new ($thing.Base.inherit({

    doWake: function(container, selector) {

        selector.schedule();

        selector.dispatch(
            {   filters: $thing.Filter.ALL,
                method: 'action',
                args: []
            },
            function(cbNext) {
                cbNext();
            },
            function() {

                selector.release();

            }
        );

    },

    doAction: function(container, selector, iteration) {
        var self = this;

        container.isTaskerQueued = true;

        if (iteration > selector.length) {
            selector.select();
            iteration = 0;
        }

        if (selector.length === 0) {
            selector.release();
            container.isTaskerQueued = false;
        }
        else {

            selector.schedule();

            selector.dispatch(
                {   filters: $thing.Filter.FIRST,
                    method: 'action',
                    args: []
                },
                function(cbNext) {
                    cbNext();
                },
                function() {

                    $thing.async.setImmediate(function() {
                        self.doAction(container, selector, ++iteration);
                    });

                }
            );

        }

    },

    thread: function(threadId) {

        if (threadId === undefined)
            threadId = $thing.getThreadId(1);

        var selector,
            now = $thing.getMicroTime(),
            container = $thing.getContainer(threadId)
            ;

        if (!container.nextWakeTime || now >= container.nextWakeTime) {

            container.nextWakeTime =
                now + $thing.WAKE_MIN_PERIOD - (now % $thing.WAKE_MIN_PERIOD);

            selector = new $thing.Selector(threadId, [['Behaviour', 'and', 'Waker']], false);

            selector.select();

            this.doWake(container, selector);

        }

        if (!container.isTaskerQueued) {

            selector = new $thing.Selector(threadId, [['Behaviour', 'not', 'Waker']], false);

            selector.select();

            this.doAction(container, selector, 0);

        }

    }

}))();<|endoftext|>