<commit_before>(function($) {

  $.declare('fileUploader', {
    defaults: {
      formId: 'fileUploaderForm',
      action: window.location.href,
      method: 'POST',
      postKey: 'file',
      progressTemplate: '
Uploading...
',
      completeTemplateImage: '',
      completeTemplateOther: '
The file has been uploaded ✔
',
      images: ['jpg', 'png', 'bmp', 'gif', 'jpeg'],
      allow: [],
      processData: null,
      zIndex: 2,
      dropZone: 'this',
      iframeValidation: null,
      updateProgress: function(event) {},
      onUploadError: function() {
        alert('Error');
      },
      onInvalidFileType: function() {
        alert('Please select a file with a ' + this.allow.join(', ') + ' extension');
      },
      showProgress: function() {
        this.el.html(this.progressTemplate);
      },
      showComplete: function(data) {
        var extension = this.getExtension(data);
        var file = (this.processData) ? this.processData(data) : data;
        var isImage = $.inArray(extension, this.images) > -1;

        if (file) {
          if (isImage) {
            this.el
              .html(this.completeTemplateImage)
              .find('img')
              .attr('src', file);
          }
          else {
            this.el.html(this.completeTemplateOther);
          }
        }
      }
    },

    init: function() {
      this.supportsFileApi = (typeof window.FileReader !== 'undefined');

      this.el.css('cursor', 'pointer');

      this.setupFramejax();

      if (this.supportsFileApi) {
        this.setupFileApi();
      }
    },

    setupFramejax: function() {
      var self = this;

      $('#' + this.formId).remove();
      this.el.off('mousemove');

      var form = $('<form/>')
        .attr({
          action: this.action,
          method: this.method,
          enctype: 'multipart/form-data',
          id: this.formId
        })
        .appendTo('body');

      var input = $('<input/>')
        .attr({
          name: this.postKey,
          type: 'file'
        })
        .css({
          opacity: '0',
          cursor: 'pointer',
          position: 'absolute',
          zIndex: this.zIndex
        })
        .on('change', function(e) {
          var filename = e.target.value;

          if (!self.checkType(filename)) {
            self.onInvalidFileType.apply(self);
            return;
          }

          self.el.trigger('fileSelect');
          self.showProgress.apply(self);
          form.submit();
        })
        .appendTo(form);

      this.el.on('mousemove', function(e) {
        var h = input.height();
        var w = input.width();

        if (typeof e.pageY == 'undefined' && typeof e.clientX == 'number' && document.documentElement) {
          e.pageX = e.clientX + document.documentElement.scrollLeft;
          e.pageY = e.clientY + document.documentElement.scrollTop;
        }

        input.css({
          top: e.pageY - (h / 2),
          left: e.pageX - (w - 30)
        });
      });

      input.on('mouseenter', function() {
        clearTimeout(input.data('timer'));
        if (!input.data('hovering')) {
          self.el.trigger('fileUploaderMouseIn');
        }

        input.data('hovering', true);
      }).on('mouseleave', function() {
        var timer = setTimeout(function() {
          self.el.trigger('fileUploaderMouseOut');
          input.data('hovering', false);
        }, 500);
        input.data('timer', timer);
      });

      form
        .framejax({
          validate: self.iframeValidation
        })
        .on('complete', function(e, results) {
          self.showComplete.call(self, results);
          self.el.trigger('complete', results);
          self.setupFramejax();
        })
        .on('framejax.error', self.onUploadError.bind(self));
    },

    checkType: function(file) {
      return !this.allow.length || $.inArray(this.getExtension(file), this.allow) !== -1;
    },

    setupFileApi: function() {
      var self = this;

      if (self.dropZone === 'this') {
        self.dropZone = self.el;
      } else {
        self.dropZone = $(self.dropZone);
      }

      self.dropZone.bind('dragenter, dragover', function(event){
        event.stopPropagation();
        event.preventDefault();
        event.originalEvent.dataTransfer.dropEffect = 'copy';
        self.emit('over');
      });

      self.dropZone.bind('dragleave', function() {
        self.emit('out');
      });

      self.dropZone.bind('drop', function(event) {
        event.stopPropagation();
        event.preventDefault();

        var file = event.originalEvent.dataTransfer.files[0];

        if (!self.checkType(file.name)) {
          self.onInvalidFileType.apply(self);
          return;
        }

        self.upload(file);
      });
    },

    getExtension: function(file) {
      return file.split('.').pop().toLowerCase();
    },

    upload: function(file) {
      var formData = new FormData();
      var self = this;
      var xhr = new XMLHttpRequest();

      formData.append(this.postKey, file);

      self.showProgress.apply(self);

      xhr.open('POST', self.action, true);
      xhr.upload.onprogress = self.updateProgress;
      xhr.onload = function(event) {
        self.showComplete.call(self, this.responseText, this, event);
        self.el.trigger('complete', this.responseText);

        if (event.currentTarget.status !== 200) {
          self.onUploadError.apply(self, arguments);
        }
      };

      xhr.send(formData);
    }
  });
})(window.jQuery);
<commit_msg>Removing call to reset form since it breaks iframe validation.<commit_after>(function($) {

  $.declare('fileUploader', {
    defaults: {
      formId: 'fileUploaderForm',
      action: window.location.href,
      method: 'POST',
      postKey: 'file',
      progressTemplate: '
Uploading...
',
      completeTemplateImage: '',
      completeTemplateOther: '
The file has been uploaded ✔
',
      images: ['jpg', 'png', 'bmp', 'gif', 'jpeg'],
      allow: [],
      processData: null,
      zIndex: 2,
      dropZone: 'this',
      iframeValidation: null,
      updateProgress: function(event) {},
      onUploadError: function() {
        alert('Error');
      },
      onInvalidFileType: function() {
        alert('Please select a file with a ' + this.allow.join(', ') + ' extension');
      },
      showProgress: function() {
        this.el.html(this.progressTemplate);
      },
      showComplete: function(data) {
        var extension = this.getExtension(data);
        var file = (this.processData) ? this.processData(data) : data;
        var isImage = $.inArray(extension, this.images) > -1;

        if (file) {
          if (isImage) {
            this.el
              .html(this.completeTemplateImage)
              .find('img')
              .attr('src', file);
          }
          else {
            this.el.html(this.completeTemplateOther);
          }
        }
      }
    },

    init: function() {
      this.supportsFileApi = (typeof window.FileReader !== 'undefined');

      this.el.css('cursor', 'pointer');

      this.setupFramejax();

      if (this.supportsFileApi) {
        this.setupFileApi();
      }
    },

    setupFramejax: function() {
      var self = this;

      $('#' + this.formId).remove();
      this.el.off('mousemove');

      var form = $('<form/>')
        .attr({
          action: this.action,
          method: this.method,
          enctype: 'multipart/form-data',
          id: this.formId
        })
        .appendTo('body');

      var input = $('<input/>')
        .attr({
          name: this.postKey,
          type: 'file'
        })
        .css({
          opacity: '0',
          cursor: 'pointer',
          position: 'absolute',
          zIndex: this.zIndex
        })
        .on('change', function(e) {
          var filename = e.target.value;

          if (!self.checkType(filename)) {
            self.onInvalidFileType.apply(self);
            return;
          }

          self.el.trigger('fileSelect');
          self.showProgress.apply(self);
          form.submit();
        })
        .appendTo(form);

      this.el.on('mousemove', function(e) {
        var h = input.height();
        var w = input.width();

        if (typeof e.pageY == 'undefined' && typeof e.clientX == 'number' && document.documentElement) {
          e.pageX = e.clientX + document.documentElement.scrollLeft;
          e.pageY = e.clientY + document.documentElement.scrollTop;
        }

        input.css({
          top: e.pageY - (h / 2),
          left: e.pageX - (w - 30)
        });
      });

      input.on('mouseenter', function() {
        clearTimeout(input.data('timer'));
        if (!input.data('hovering')) {
          self.el.trigger('fileUploaderMouseIn');
        }

        input.data('hovering', true);
      }).on('mouseleave', function() {
        var timer = setTimeout(function() {
          self.el.trigger('fileUploaderMouseOut');
          input.data('hovering', false);
        }, 500);
        input.data('timer', timer);
      });

      form
        .framejax({
          validate: self.iframeValidation
        })
        .on('complete', function(e, results) {
          self.showComplete.call(self, results);
          self.el.trigger('complete', results);
        })
        .on('framejax.error', self.onUploadError.bind(self));
    },

    checkType: function(file) {
      return !this.allow.length || $.inArray(this.getExtension(file), this.allow) !== -1;
    },

    setupFileApi: function() {
      var self = this;

      if (self.dropZone === 'this') {
        self.dropZone = self.el;
      } else {
        self.dropZone = $(self.dropZone);
      }

      self.dropZone.bind('dragenter, dragover', function(event){
        event.stopPropagation();
        event.preventDefault();
        event.originalEvent.dataTransfer.dropEffect = 'copy';
        self.emit('over');
      });

      self.dropZone.bind('dragleave', function() {
        self.emit('out');
      });

      self.dropZone.bind('drop', function(event) {
        event.stopPropagation();
        event.preventDefault();

        var file = event.originalEvent.dataTransfer.files[0];

        if (!self.checkType(file.name)) {
          self.onInvalidFileType.apply(self);
          return;
        }

        self.upload(file);
      });
    },

    getExtension: function(file) {
      return file.split('.').pop().toLowerCase();
    },

    upload: function(file) {
      var formData = new FormData();
      var self = this;
      var xhr = new XMLHttpRequest();

      formData.append(this.postKey, file);

      self.showProgress.apply(self);

      xhr.open('POST', self.action, true);
      xhr.upload.onprogress = self.updateProgress;
      xhr.onload = function(event) {
        self.showComplete.call(self, this.responseText, this, event);
        self.el.trigger('complete', this.responseText);

        if (event.currentTarget.status !== 200) {
          self.onUploadError.apply(self, arguments);
        }
      };

      xhr.send(formData);
    }
  });
})(window.jQuery);
<|endoftext|>


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

/**
 * Module dependencies.
 */

var Compiler = require('../visitor/compiler')
  , events = require('../renderer').events
  , nodes = require('../nodes')
  , parse = require('url').parse
  , extname = require('path').extname
  , utils = require('../utils')
  , fs = require('fs');

/**
 * Mime table.
 */

var defaultMimes = {
    '.gif': 'image/gif'
  , '.png': 'image/png'
  , '.jpg': 'image/jpeg'
  , '.jpeg': 'image/jpeg'
  , '.svg': 'image/svg+xml'
  , '.ttf': 'application/x-font-ttf'
  , '.eot': 'application/vnd.ms-fontobject'
  , '.woff': 'application/font-woff'
};

/**
 * Return a url() function with the given `options`.
 *
 * Options:
 *
 *    - `limit` bytesize limit defaulting to 30Kb
 *    - `paths` image resolution path(s), merged with general lookup paths
 *
 * Examples:
 *
 *    stylus(str)
 *      .set('filename', __dirname + '/css/test.styl')
 *      .define('url', stylus.url({ paths: [__dirname + '/public'] }))
 *      .render(function(err, css){ ... })
 *
 * @param {Object} options
 * @return {Function}
 * @api public
 */

module.exports = function(options) {
  options = options || {};

  var _paths = options.paths || [];
  var sizeLimit = null != options.limit ? options.limit : 30000;
  var mimes = options.mimes || defaultMimes;

  function fn(url){
    // Compile the url
    var compiler = new Compiler(url);
    compiler.isURL = true;
    url = url.nodes.map(function(node){
      return compiler.visit(node);
    }).join('');

    // Parse literal
    url = parse(url);
    var ext = extname(url.pathname)
      , mime = mimes[ext]
      , hash = url.hash || ''
      , literal = new nodes.Literal('url("' + url.href + '")')
      , paths = _paths.concat(this.paths)
      , buf;

    // Not supported
    if (!mime) return literal;

    // Absolute
    if (url.protocol) return literal;

    // Lookup
    var found = utils.lookup(url.pathname, paths);

    // Failed to lookup
    if (!found) {
      events.emit(
          'file not found'
        , 'File ' + literal + ' could not be found, literal url retained!'
      );

      return literal;
    }

    // Read data
    buf = fs.readFileSync(found);

    // To large
    if (false !== sizeLimit && buf.length > sizeLimit) return literal;

    // Encode
    return new nodes.Literal('url("data:' + mime + ';base64,' + buf.toString('base64') + hash + '")');
  };

  fn.raw = true;
  return fn;
};

// Exporting default mimes so we could easily access them
module.exports.mimes = defaultMimes;

<commit_msg>Fix typo in url.js<commit_after>
/*!
 * Stylus - plugin - url
 * Copyright(c) 2010 LearnBoost <dev@learnboost.com>
 * MIT Licensed
 */

/**
 * Module dependencies.
 */

var Compiler = require('../visitor/compiler')
  , events = require('../renderer').events
  , nodes = require('../nodes')
  , parse = require('url').parse
  , extname = require('path').extname
  , utils = require('../utils')
  , fs = require('fs');

/**
 * Mime table.
 */

var defaultMimes = {
    '.gif': 'image/gif'
  , '.png': 'image/png'
  , '.jpg': 'image/jpeg'
  , '.jpeg': 'image/jpeg'
  , '.svg': 'image/svg+xml'
  , '.ttf': 'application/x-font-ttf'
  , '.eot': 'application/vnd.ms-fontobject'
  , '.woff': 'application/font-woff'
};

/**
 * Return a url() function with the given `options`.
 *
 * Options:
 *
 *    - `limit` bytesize limit defaulting to 30Kb
 *    - `paths` image resolution path(s), merged with general lookup paths
 *
 * Examples:
 *
 *    stylus(str)
 *      .set('filename', __dirname + '/css/test.styl')
 *      .define('url', stylus.url({ paths: [__dirname + '/public'] }))
 *      .render(function(err, css){ ... })
 *
 * @param {Object} options
 * @return {Function}
 * @api public
 */

module.exports = function(options) {
  options = options || {};

  var _paths = options.paths || [];
  var sizeLimit = null != options.limit ? options.limit : 30000;
  var mimes = options.mimes || defaultMimes;

  function fn(url){
    // Compile the url
    var compiler = new Compiler(url);
    compiler.isURL = true;
    url = url.nodes.map(function(node){
      return compiler.visit(node);
    }).join('');

    // Parse literal
    url = parse(url);
    var ext = extname(url.pathname)
      , mime = mimes[ext]
      , hash = url.hash || ''
      , literal = new nodes.Literal('url("' + url.href + '")')
      , paths = _paths.concat(this.paths)
      , buf;

    // Not supported
    if (!mime) return literal;

    // Absolute
    if (url.protocol) return literal;

    // Lookup
    var found = utils.lookup(url.pathname, paths);

    // Failed to lookup
    if (!found) {
      events.emit(
          'file not found'
        , 'File ' + literal + ' could not be found, literal url retained!'
      );

      return literal;
    }

    // Read data
    buf = fs.readFileSync(found);

    // Too large
    if (false !== sizeLimit && buf.length > sizeLimit) return literal;

    // Encode
    return new nodes.Literal('url("data:' + mime + ';base64,' + buf.toString('base64') + hash + '")');
  };

  fn.raw = true;
  return fn;
};

// Exporting default mimes so we could easily access them
module.exports.mimes = defaultMimes;

<|endoftext|>


<commit_before>(function(define){

define(['gen'], function(gen) {
"use strict";

var noop = function(){ return function(){}; };

/* Exported Objects
 ******************************************************************************/
/**
 * Factory for generator that attempts to yield elements from a source generator
 * while a condition holds true. Breaks once the condition is no longer true.
 *
 * @param {gen} source Source generator to yield elements from.
 * @param {function(value): boolean} pred Predicate function that determines when
 *     to step taking elements.
 * @param thisObj 'this' object used for predicate function.
 *
 * @returns {function(yield, break)} Generator that yields elements until the
 *     predicate is no longer true, then breaks.
 */
var takeWhile = function(source, pred, thisObj) {
    var condition = true;
    var innerB = function() {
        condition = false;
        return function() { };
    };
    return gen(function(y, b) {
        if (!condition) return b();
        var value = source(undefined, innerB);
        condition = condition && pred.call(thisObj, value);
        if (!condition) return b();
        return y(value);
    });
};

/**
 * Factory for generator that attempts to yield at most 'count' elements from
 * source generator.
 *
 * May yield fewer elements if generator breaks. Otherwise, behaves like normal
 * generator.
 *
 * @param {gen} source Source generator to yield elements from.
 * @param {number} count Number of elements to take. Must be greater than or
 *     equal to zero. Defaults to 'Infinity'.
 *
 * @returns {function(yield, break)} Generator that yields at most count elements
 *    from source.
 */
 var take = function(source, count) {
    count = (count >= 0 ? count : Infinity);
    if (count === Infinity)
        return source;
    var i = 0;
    return takeWhile(source, function(v) { return (i++ < count); });
};

/**
 * Factory for generator that skips 'count' elements before yielding anything.
 *
 * May break during the skip stage if the source generator has less than 'count'
 * elements.
 *
 * @param {gen} source Source generator to yield elements from.
 * @param {number} count Number of elements to skip. Must be greater than or
 *     equal to zero. Defaults to zero.
 *
 * @returns {function(yield, break)} Generator that skips skips 'count' elements
 *    before yielding anything.
 */
var skip = function(source, count) {
    count = (count >= 0 ? count : 0);
    var i = 0;
    return source.filter(function(v) {
        return (i++ >= count);
    });
};

/**
 *
 */
var count = function(source) {
    return source.reduce(function(p, c) { return p + 1; }, 0);
};

/* Export
 ******************************************************************************/
return {
    'take': take,
    'takeWhile': takeWhile,
    'skip': skip
};

});

}(
    typeof define !== 'undefined' ? define : function(factory) { genBatteries = factory(); }
));<commit_msg>Cleaned up existing battery funcs. Added documentation. Added count. Added placeholders for any and every.<commit_after>(function(define){

define(['gen'], function(gen) {
"use strict";

/* Exported Objects
 ******************************************************************************/
/**
 * Factory for generator that attempts to yield elements from a source generator
 * while a condition holds true. Breaks once the condition is no longer true.
 *
 * @param {gen} source Source generator to yield elements from.
 * @param {function(value): boolean} pred Predicate function that determines when
 *     to step taking elements.
 * @param thisObj 'this' object used for predicate function.
 *
 * @returns {function(yield, break)} Generator that yields elements until the
 *     predicate is no longer true, then breaks.
 */
var takeWhile = function(source, pred, thisObj) {
    var condition = true;
    var i = 0;
    var innerY = function(v) {
        condition = pred.call(thisObj, v, i);
        return function() { return v; };
    };
    var innerB = function() {
        condition = false;
        return function() { };
    };

    return gen(function(y, b) {
        if (!condition) return b();
        var value = source(innerY, innerB);
        if (!condition) return b();
        ++i;
        return y(value);
    });
};

/**
 * Factory for generator that attempts to yield at most 'count' elements from
 * source generator.
 *
 * May yield fewer elements if generator breaks. Otherwise, behaves like normal
 * generator.
 *
 * @param {gen} source Source generator to yield elements from.
 * @param {number} count Number of elements to take. Must be greater than or
 *     equal to zero. Defaults to 'Infinity'.
 *
 * @returns {function(yield, break)} Generator that yields at most count elements
 *    from source.
 */
 var take = function(source, count) {
    count = (count >= 0 ? count : Infinity);
    return (count === Infinity ? source :
        takeWhile(source, function(v, i) { return (i < count); }));
};

/**
 * Factory for generator that skips 'count' elements before yielding anything.
 *
 * May break during the skip stage if the source generator has less than 'count'
 * elements.
 *
 * @param {gen} source Source generator to yield elements from.
 * @param {number} count Number of elements to skip. Must be greater than or
 *     equal to zero. Defaults to zero.
 *
 * @returns {function(yield, break)} Generator that skips skips 'count' elements
 *    before yielding anything.
 */
var skipWhile = function(source, pred, thisObj) {
    var condition = true;
    var i = 0;
    return source.filter(function(v) {
        return !condition || !(condition = pred.call(thisObj, v, i++));
    });
};

/**
 * Factory for generator that skips 'count' elements before yielding anything.
 *
 * May break during the skip stage if the source generator has less than 'count'
 * elements.
 *
 * @param {gen} source Source generator to yield elements from.
 * @param {number} count Number of elements to skip. Must be greater than or
 *     equal to zero. Defaults to zero.
 *
 * @returns {function(yield, break)} Generator that skips skips 'count' elements
 *    before yielding anything.
 */
var skip = function(source, count) {
    count = (count >= 0 ? count : 0);
    return (count === 0 ? source :
        skipWhile(source, function(v, i) { return (i < count); }));
};

/**
 * Factory for generator that attempts to count the number of elements in the
 * source generator.
 *
 * Generator yields a single number value, the number of elements in the source
 * generator.
 *
 * @param {gen} source Source generator to count elements from.
 *
 * @returns {function(yield, break)} Generator that counts source generator
 *     elements and yields the result.
 */
var count = (function(){
    function inc(p) { return p + 1; }

    return function(source) {
        return source.reduce(inc, 0);
    };
}());

/**
 *
 */
var any = function(source, predicate, thisObj) {

};

/**
 *
 */
var every = function(source, predicate, thisObj) {

};

/* Export
 ******************************************************************************/
return {
    'take': take,
    'takeWhile': takeWhile,
    'skip': skip,
    'skipWhile': skipWhile,
    'count': count,
    'any': any,
    'ever': every
};

});

}(
    typeof define !== 'undefined' ? define : function(factory) { genBatteries = factory(); }
));<|endoftext|>


<commit_before>const { existsSync } = require('fs');
const { resolve, extname } = require('path');

const GroupHelper = require('../utils/group-helper');

class ConfigGroup extends GroupHelper {
    constructor(options) {
        super(options);
        this.extensions = ['.mjs', '.js', '.json', '.babel.js', '.ts'];
        this.defaultConfigFiles = this.getDefaultConfigFiles();
        this.configFiles = null;
        this.configOptions = [];
    }
    getDefaultConfigFiles() {
        const { mode } = this.args;
        let DEFAULT_FILES = ['.webpack/webpack.config', '.webpack/webpack.config.dev', '.webpack/webpack.config.prod', '.webpack/webpackfile', 'webpack.config'];

        return DEFAULT_FILES.map(filename =>
            this.extensions.map(ext => ({
                path: resolve(filename + ext),
                ext: ext,
            })),
        ).reduce((a, i) => a.concat(i), []);
    }

    getConfigExtension(configPath) {
        for (let i = this.extensions.length - 1; i >= 0; i--) {
            const tmpExt = this.extensions[i];
            if (configPath.indexOf(tmpExt, configPath.length - tmpExt.length) > -1) {
                return tmpExt;
            }
        }
        return extname(configPath);
    }
    mapConfigArg(config) {
        const { path } = config;
        const ext = this.getConfigExtension(path);
        return {
            path,
            ext,
        };
    }

    requireConfig(configPath) {
        const { register } = this.args;

        this.configOptions = (() => {
            if (register && register.length) {
                module.paths.unshift(resolve(process.cwd(), 'node_modules'));
                register.forEach(dep => {
                    const isRelative = ["./", "../", ".\\", "..\\"].some(start => dep.startsWith(start));
                    if (isRelative) {
                        require(resolve(process.cwd(), dep));
                    } else {
                        require(dep);
                    }
                });
            }
            return require(configPath);
        })();
    }

    resolveConfigFiles(envMode) {
        const { config, mode } = this.args;
        const path = require('path');

        if (config) {
            //TODO: check for existence, give user feedback otherwise
            const configPath = path.resolve(process.cwd(), config);
            const ext = this.getConfigExtension(configPath);
            this.configFiles = {
                path: configPath,
                ext,
            };
        }
        if (!this.configFiles) {
            const tmpConfigFiles = this.defaultConfigFiles
                .filter(defaultFile => {
                    return existsSync(defaultFile.path);
                })
                .map(this.mapConfigArg.bind(this));
            if (tmpConfigFiles.length) {
                if (!config) {
                    const defaultConfig = tmpConfigFiles.find(p => ~p.path.indexOf(mode));
                    this.configFiles = defaultConfig || tmpConfigFiles[0];
                }
            }
        }
        if (this.configFiles) {
            // TODO: support mjs etc..
            this.configOptions.push(this.requireConfig(this.configFiles.path));
        } else {
            // TODO: Array config or no config
        }

        if (this.configOptions.length >= 1) {
            // merge configs together
        } else if (this.configOptions.length == 0) {
            // NO found
        } else {
            // set defaults based on nothing
            this.opts['options'] = this.configOptions;
            //return processConfiguredOptions(this.configOptions);
        }

        // TODO: fill in defaults here
    }

    resolveConfigMerging() {
        const { merge } = this.args;
        if (merge) {
            const newConfigPath = this.resolveFilePath(merge, 'webpack.base');
            const newConfig = newConfigPath ? require(newConfigPath) : null;
            this.opts['options'] = require('webpack-merge')(this.opts['options'], newConfig);
        }
    }

    run(envMode) {
        this.resolveConfigFiles(envMode);
        this.resolveConfigMerging();
        return this.opts;
    }
}

module.exports = ConfigGroup;
<commit_msg>feat: Support `export default` from configuration files.<commit_after>const { existsSync } = require('fs');
const { resolve, extname } = require('path');

const GroupHelper = require('../utils/group-helper');

class ConfigGroup extends GroupHelper {
    constructor(options) {
        super(options);
        this.extensions = ['.mjs', '.js', '.json', '.babel.js', '.ts'];
        this.defaultConfigFiles = this.getDefaultConfigFiles();
        this.configFiles = null;
        this.configOptions = [];
    }
    getDefaultConfigFiles() {
        const { mode } = this.args;
        let DEFAULT_FILES = ['.webpack/webpack.config', '.webpack/webpack.config.dev', '.webpack/webpack.config.prod', '.webpack/webpackfile', 'webpack.config'];

        return DEFAULT_FILES.map(filename =>
            this.extensions.map(ext => ({
                path: resolve(filename + ext),
                ext: ext,
            })),
        ).reduce((a, i) => a.concat(i), []);
    }

    getConfigExtension(configPath) {
        for (let i = this.extensions.length - 1; i >= 0; i--) {
            const tmpExt = this.extensions[i];
            if (configPath.indexOf(tmpExt, configPath.length - tmpExt.length) > -1) {
                return tmpExt;
            }
        }
        return extname(configPath);
    }
    mapConfigArg(config) {
        const { path } = config;
        const ext = this.getConfigExtension(path);
        return {
            path,
            ext,
        };
    }

    require(path) {
        const result = require(path);
        if (result && result.__esModule && result.default) {
            return result.default;
        }
        return result;
    }

    requireConfig(configPath) {
        const { register } = this.args;

        this.configOptions = (() => {
            if (register && register.length) {
                module.paths.unshift(resolve(process.cwd(), 'node_modules'));
                register.forEach(dep => {
                    const isRelative = ['./', '../', '.\\', '..\\'].some(start => dep.startsWith(start));
                    if (isRelative) {
                        require(resolve(process.cwd(), dep));
                    } else {
                        require(dep);
                    }
                });
            }
            return this.require(configPath);
        })();
    }

    resolveConfigFiles(envMode) {
        const { config, mode } = this.args;
        const path = require('path');

        if (config) {
            //TODO: check for existence, give user feedback otherwise
            const configPath = path.resolve(process.cwd(), config);
            const ext = this.getConfigExtension(configPath);
            this.configFiles = {
                path: configPath,
                ext,
            };
        }
        if (!this.configFiles) {
            const tmpConfigFiles = this.defaultConfigFiles
                .filter(defaultFile => {
                    return existsSync(defaultFile.path);
                })
                .map(this.mapConfigArg.bind(this));
            if (tmpConfigFiles.length) {
                if (!config) {
                    const defaultConfig = tmpConfigFiles.find(p => ~p.path.indexOf(mode));
                    this.configFiles = defaultConfig || tmpConfigFiles[0];
                }
            }
        }
        if (this.configFiles) {
            // TODO: support mjs etc..
            this.configOptions.push(this.requireConfig(this.configFiles.path));
        } else {
            // TODO: Array config or no config
        }

        if (this.configOptions.length >= 1) {
            // merge configs together
        } else if (this.configOptions.length == 0) {
            // NO found
        } else {
            // set defaults based on nothing
            this.opts['options'] = this.configOptions;
            //return processConfiguredOptions(this.configOptions);
        }

        // TODO: fill in defaults here
    }

    resolveConfigMerging() {
        const { merge } = this.args;
        if (merge) {
            const newConfigPath = this.resolveFilePath(merge, 'webpack.base');
            const newConfig = newConfigPath ? this.require(newConfigPath) : null;
            this.opts['options'] = require('webpack-merge')(this.opts['options'], newConfig);
        }
    }

    run(envMode) {
        this.resolveConfigFiles(envMode);
        this.resolveConfigMerging();
        return this.opts;
    }
}

module.exports = ConfigGroup;
<|endoftext|>


<commit_before>/* jshint esversion: 6 */

const nThen = require('nthen');
const Crypto = require('crypto');
const WriteQueue = require("./write-queue");
const BatchRead = require("./batch-read");
const RPC = require("./rpc");
const HK = require("./hk-util.js");
const Core = require("./commands/core");

const Store = require("./storage/file");
const BlobStore = require("./storage/blob");

module.exports.create = function (config, cb) {
    const Log = config.log;
    var WARN = function (e, output) {
        if (e && output) {
            Log.warn(e, {
                output: output,
                message: String(e),
                stack: new Error(e).stack,
            });
        }
    };

    Log.silly('HK_LOADING', 'LOADING HISTORY_KEEPER MODULE');

    // TODO populate Env with everything that you use from config
    // so that you can stop passing around your raw config
    // and more easily share state between historyKeeper and rpc
    const Env = {
        Log: Log,
        // tasks
        // store
        id: Crypto.randomBytes(8).toString('hex'),

        metadata_cache: {},
        channel_cache: {},
        queueStorage: WriteQueue(),

        batchIndexReads: BatchRead("HK_GET_INDEX"),
        batchMetadata: BatchRead('GET_METADATA'),
        batchRegisteredUsers: BatchRead("GET_REGISTERED_USERS"),
        batchDiskUsage: BatchRead('GET_DISK_USAGE'),

        //historyKeeper: config.historyKeeper,
        intervals: config.intervals || {},
        maxUploadSize: config.maxUploadSize || (20 * 1024 * 1024),
        premiumUploadSize: false, // overridden below...
        Sessions: {},
        paths: {},
        //msgStore: config.store,

        netfluxUsers: {},

        pinStore: undefined,
        pinnedPads: {},
        pinsLoaded: false,
        pendingPinInquiries: {},
        pendingUnpins: {},
        pinWorkers: 5,

        limits: {},
        admins: [],
        WARN: WARN,
        flushCache: config.flushCache,
        adminEmail: config.adminEmail,
        allowSubscriptions: config.allowSubscriptions,
        myDomain: config.myDomain,
        mySubdomain: config.mySubdomain,
        customLimits: config.customLimits,
        // FIXME this attribute isn't in the default conf
        // but it is referenced in Quota
        domain: config.domain
    };

    (function () {
        var pes = config.premiumUploadSize;
        if (!isNaN(pes) && pes >= Env.maxUploadSize) {
            Env.premiumUploadSize = pes;
        }
    }());

    var paths = Env.paths;

    var keyOrDefaultString = function (key, def) {
        return typeof(config[key]) === 'string'? config[key]: def;
    };

    var pinPath = paths.pin = keyOrDefaultString('pinPath', './pins');
    paths.block = keyOrDefaultString('blockPath', './block');
    paths.data = keyOrDefaultString('filePath', './datastore');
    paths.staging = keyOrDefaultString('blobStagingPath', './blobstage');
    paths.blob = keyOrDefaultString('blobPath', './blob');

    Env.defaultStorageLimit = typeof(config.defaultStorageLimit) === 'number' && config.defaultStorageLimit > 0?
        config.defaultStorageLimit:
        Core.DEFAULT_LIMIT;

    try {
        Env.admins = (config.adminKeys || []).map(function (k) {
            k = k.replace(/\/+$/, '');
            var s = k.split('/');
            return s[s.length-1];
        });
    } catch (e) {
        console.error("Can't parse admin keys. Please update or fix your config.js file!");
    }

    config.historyKeeper = Env.historyKeeper = {
        metadata_cache: Env.metadata_cache,
        channel_cache: Env.channel_cache,

        id: Env.id,

        channelMessage: function (Server, channel, msgStruct) {
            // netflux-server emits 'channelMessage' events whenever someone broadcasts to a channel
            // historyKeeper stores these messages if the channel id indicates that they are
            // a channel type with permanent history
            HK.onChannelMessage(Env, Server, channel, msgStruct);
        },
        channelClose: function (channelName) {
            // netflux-server emits 'channelClose' events whenever everyone leaves a channel
            // we drop cached metadata and indexes at the same time
            HK.dropChannel(Env, channelName);
        },
        channelOpen: function (Server, channelName, userId, wait) {
            Env.channel_cache[channelName] = Env.channel_cache[channelName] || {};

            var sendHKJoinMessage = function () {
                Server.send(userId, [
                    0,
                    Env.id,
                    'JOIN',
                    channelName
                ]);
            };

            // a little backwards compatibility in case you don't have the latest server
            // allow lists won't work unless you update, though
            if (typeof(wait) !== 'function') { return void sendHKJoinMessage(); }

            var next = wait();
            var cb = function (err, info) {
                next(err, info, sendHKJoinMessage);
            };

            // only conventional channels can be restricted
            if ((channelName || "").length !== HK.STANDARD_CHANNEL_LENGTH) {
                return void cb();
            }

            // gets and caches the metadata...
            HK.getMetadata(Env, channelName, function (err, metadata) {
                if (err) {
                    Log.error('HK_METADATA_ERR', {
                        channel: channelName,
                        error: err,
                    });
                }
                if (!metadata || (metadata && !metadata.restricted)) {
                    // the channel doesn't have metadata, or it does and it's not restricted
                    // either way, let them join.
                    return void cb();
                }

                // this channel is restricted. verify that the user in question is in the allow list

                // construct a definitive list (owners + allowed)
                var allowed = HK.listAllowedUsers(metadata);
                // and get the list of keys for which this user has already authenticated
                var session = HK.getNetfluxSession(Env, userId);

                if (HK.isUserSessionAllowed(allowed, session)) {
                    return void cb();
                }

                // otherwise they're not allowed.
                // respond with a special error that includes the list of keys
                // which would be allowed...
                // FIXME RESTRICT bonus points if you hash the keys to limit data exposure
                cb("ERESTRICTED", allowed);
            });
        },
        sessionClose: function (userId, reason) {
            HK.closeNetfluxSession(Env, userId);
            if (['BAD_MESSAGE', 'SOCKET_ERROR', 'SEND_MESSAGE_FAIL_2'].indexOf(reason) !== -1) {
                if (reason && reason.code === 'ECONNRESET') { return; }
                return void Log.error('SESSION_CLOSE_WITH_ERROR', {
                    userId: userId,
                    reason: reason,
                });
            }

            if (['SOCKET_CLOSED', 'SOCKET_ERROR'].indexOf(reason)) { return; }
            Log.verbose('SESSION_CLOSE_ROUTINE', {
                userId: userId,
                reason: reason,
            });
        },
        directMessage: function (Server, seq, userId, json) {
            // netflux-server allows you to register an id with a handler
            // this handler is invoked every time someone sends a message to that id
            HK.onDirectMessage(Env, Server, seq, userId, json);
        },
    };

    Log.verbose('HK_ID', 'History keeper ID: ' + Env.id);

    nThen(function (w) {
        // create a pin store
        Store.create({
            filePath: pinPath,
        }, w(function (s) {
            Env.pinStore = s;
        }));

        // create a channel store
        Store.create(config, w(function (_store) {
            config.store = _store;
            Env.msgStore = _store; // API used by rpc
            Env.store = _store; // API used by historyKeeper
        }));

        // create a blob store
        BlobStore.create({
            blobPath: config.blobPath,
            blobStagingPath: config.blobStagingPath,
            archivePath: config.archivePath,
            getSession: function (safeKey) {
                return Core.getSession(Env.Sessions, safeKey);
            },
        }, w(function (err, blob) {
            if (err) { throw new Error(err); }
            Env.blobStore = blob;
        }));
    }).nThen(function (w) {
        // create a task store
        require("./storage/tasks").create(config, w(function (e, tasks) {
            if (e) {
                throw e;
            }
            Env.tasks = tasks;
            config.tasks = tasks;
            if (config.disableIntegratedTasks) { return; }

            config.intervals = config.intervals || {};
            config.intervals.taskExpiration = setInterval(function () {
                tasks.runAll(function (err) {
                    if (err) {
                        // either TASK_CONCURRENCY or an error with tasks.list
                        // in either case it is already logged.
                    }
                });
            }, 1000 * 60 * 5); // run every five minutes
        }));
    }).nThen(function () {
        RPC.create(Env, function (err, _rpc) {
            if (err) { throw err; }

            Env.rpc = _rpc;
            cb(void 0, config.historyKeeper);
        });
    });
};
<commit_msg>provide a consistent type for 'customLimits'<commit_after>/* jshint esversion: 6 */

const nThen = require('nthen');
const Crypto = require('crypto');
const WriteQueue = require("./write-queue");
const BatchRead = require("./batch-read");
const RPC = require("./rpc");
const HK = require("./hk-util.js");
const Core = require("./commands/core");

const Store = require("./storage/file");
const BlobStore = require("./storage/blob");

module.exports.create = function (config, cb) {
    const Log = config.log;
    var WARN = function (e, output) {
        if (e && output) {
            Log.warn(e, {
                output: output,
                message: String(e),
                stack: new Error(e).stack,
            });
        }
    };

    Log.silly('HK_LOADING', 'LOADING HISTORY_KEEPER MODULE');

    // TODO populate Env with everything that you use from config
    // so that you can stop passing around your raw config
    // and more easily share state between historyKeeper and rpc
    const Env = {
        Log: Log,
        // tasks
        // store
        id: Crypto.randomBytes(8).toString('hex'),

        metadata_cache: {},
        channel_cache: {},
        queueStorage: WriteQueue(),

        batchIndexReads: BatchRead("HK_GET_INDEX"),
        batchMetadata: BatchRead('GET_METADATA'),
        batchRegisteredUsers: BatchRead("GET_REGISTERED_USERS"),
        batchDiskUsage: BatchRead('GET_DISK_USAGE'),

        //historyKeeper: config.historyKeeper,
        intervals: config.intervals || {},
        maxUploadSize: config.maxUploadSize || (20 * 1024 * 1024),
        premiumUploadSize: false, // overridden below...
        Sessions: {},
        paths: {},
        //msgStore: config.store,

        netfluxUsers: {},

        pinStore: undefined,
        pinnedPads: {},
        pinsLoaded: false,
        pendingPinInquiries: {},
        pendingUnpins: {},
        pinWorkers: 5,

        limits: {},
        admins: [],
        WARN: WARN,
        flushCache: config.flushCache,
        adminEmail: config.adminEmail,
        allowSubscriptions: config.allowSubscriptions,
        myDomain: config.myDomain,
        mySubdomain: config.mySubdomain,
        customLimits: config.customLimits || {},
        // FIXME this attribute isn't in the default conf
        // but it is referenced in Quota
        domain: config.domain
    };

    (function () {
        var pes = config.premiumUploadSize;
        if (!isNaN(pes) && pes >= Env.maxUploadSize) {
            Env.premiumUploadSize = pes;
        }
    }());

    var paths = Env.paths;

    var keyOrDefaultString = function (key, def) {
        return typeof(config[key]) === 'string'? config[key]: def;
    };

    var pinPath = paths.pin = keyOrDefaultString('pinPath', './pins');
    paths.block = keyOrDefaultString('blockPath', './block');
    paths.data = keyOrDefaultString('filePath', './datastore');
    paths.staging = keyOrDefaultString('blobStagingPath', './blobstage');
    paths.blob = keyOrDefaultString('blobPath', './blob');

    Env.defaultStorageLimit = typeof(config.defaultStorageLimit) === 'number' && config.defaultStorageLimit > 0?
        config.defaultStorageLimit:
        Core.DEFAULT_LIMIT;

    try {
        Env.admins = (config.adminKeys || []).map(function (k) {
            k = k.replace(/\/+$/, '');
            var s = k.split('/');
            return s[s.length-1];
        });
    } catch (e) {
        console.error("Can't parse admin keys. Please update or fix your config.js file!");
    }

    config.historyKeeper = Env.historyKeeper = {
        metadata_cache: Env.metadata_cache,
        channel_cache: Env.channel_cache,

        id: Env.id,

        channelMessage: function (Server, channel, msgStruct) {
            // netflux-server emits 'channelMessage' events whenever someone broadcasts to a channel
            // historyKeeper stores these messages if the channel id indicates that they are
            // a channel type with permanent history
            HK.onChannelMessage(Env, Server, channel, msgStruct);
        },
        channelClose: function (channelName) {
            // netflux-server emits 'channelClose' events whenever everyone leaves a channel
            // we drop cached metadata and indexes at the same time
            HK.dropChannel(Env, channelName);
        },
        channelOpen: function (Server, channelName, userId, wait) {
            Env.channel_cache[channelName] = Env.channel_cache[channelName] || {};

            var sendHKJoinMessage = function () {
                Server.send(userId, [
                    0,
                    Env.id,
                    'JOIN',
                    channelName
                ]);
            };

            // a little backwards compatibility in case you don't have the latest server
            // allow lists won't work unless you update, though
            if (typeof(wait) !== 'function') { return void sendHKJoinMessage(); }

            var next = wait();
            var cb = function (err, info) {
                next(err, info, sendHKJoinMessage);
            };

            // only conventional channels can be restricted
            if ((channelName || "").length !== HK.STANDARD_CHANNEL_LENGTH) {
                return void cb();
            }

            // gets and caches the metadata...
            HK.getMetadata(Env, channelName, function (err, metadata) {
                if (err) {
                    Log.error('HK_METADATA_ERR', {
                        channel: channelName,
                        error: err,
                    });
                }
                if (!metadata || (metadata && !metadata.restricted)) {
                    // the channel doesn't have metadata, or it does and it's not restricted
                    // either way, let them join.
                    return void cb();
                }

                // this channel is restricted. verify that the user in question is in the allow list

                // construct a definitive list (owners + allowed)
                var allowed = HK.listAllowedUsers(metadata);
                // and get the list of keys for which this user has already authenticated
                var session = HK.getNetfluxSession(Env, userId);

                if (HK.isUserSessionAllowed(allowed, session)) {
                    return void cb();
                }

                // otherwise they're not allowed.
                // respond with a special error that includes the list of keys
                // which would be allowed...
                // FIXME RESTRICT bonus points if you hash the keys to limit data exposure
                cb("ERESTRICTED", allowed);
            });
        },
        sessionClose: function (userId, reason) {
            HK.closeNetfluxSession(Env, userId);
            if (['BAD_MESSAGE', 'SOCKET_ERROR', 'SEND_MESSAGE_FAIL_2'].indexOf(reason) !== -1) {
                if (reason && reason.code === 'ECONNRESET') { return; }
                return void Log.error('SESSION_CLOSE_WITH_ERROR', {
                    userId: userId,
                    reason: reason,
                });
            }

            if (['SOCKET_CLOSED', 'SOCKET_ERROR'].indexOf(reason)) { return; }
            Log.verbose('SESSION_CLOSE_ROUTINE', {
                userId: userId,
                reason: reason,
            });
        },
        directMessage: function (Server, seq, userId, json) {
            // netflux-server allows you to register an id with a handler
            // this handler is invoked every time someone sends a message to that id
            HK.onDirectMessage(Env, Server, seq, userId, json);
        },
    };

    Log.verbose('HK_ID', 'History keeper ID: ' + Env.id);

    nThen(function (w) {
        // create a pin store
        Store.create({
            filePath: pinPath,
        }, w(function (s) {
            Env.pinStore = s;
        }));

        // create a channel store
        Store.create(config, w(function (_store) {
            config.store = _store;
            Env.msgStore = _store; // API used by rpc
            Env.store = _store; // API used by historyKeeper
        }));

        // create a blob store
        BlobStore.create({
            blobPath: config.blobPath,
            blobStagingPath: config.blobStagingPath,
            archivePath: config.archivePath,
            getSession: function (safeKey) {
                return Core.getSession(Env.Sessions, safeKey);
            },
        }, w(function (err, blob) {
            if (err) { throw new Error(err); }
            Env.blobStore = blob;
        }));
    }).nThen(function (w) {
        // create a task store
        require("./storage/tasks").create(config, w(function (e, tasks) {
            if (e) {
                throw e;
            }
            Env.tasks = tasks;
            config.tasks = tasks;
            if (config.disableIntegratedTasks) { return; }

            config.intervals = config.intervals || {};
            config.intervals.taskExpiration = setInterval(function () {
                tasks.runAll(function (err) {
                    if (err) {
                        // either TASK_CONCURRENCY or an error with tasks.list
                        // in either case it is already logged.
                    }
                });
            }, 1000 * 60 * 5); // run every five minutes
        }));
    }).nThen(function () {
        RPC.create(Env, function (err, _rpc) {
            if (err) { throw err; }

            Env.rpc = _rpc;
            cb(void 0, config.historyKeeper);
        });
    });
};
<|endoftext|>


<commit_before>var Kuery = require('kuery');
var Observe = require('./observe');
var reconcile = require('./reconcile');
var _ = require('lodash');
var TimeTracker = require('./timeTracker');

var LoggerFactory = require('slf').LoggerFactory;
var LOG = LoggerFactory.getLogger('lx:viewdb-persistence-store-remote');
/**
 *
 * @param {*} query Mongodb query, for example: { 'identifiers.identifier': 'abc' }
 * @param {*} local Local cursor
 * @param {*} remote Remote cursor
 * @param {*} findOptions Not in use?
 * @param {*} options Options supplied from collection.
 */
var HybridCursor = function (query, local, remote, findOptions, options) {
  this._query = query;
  this._sort = null;
  this._limit = null;
  this._skip = 0;
  this._local = local;
  this._remote = remote;
  this._findOptions = findOptions;
  this._options = options;
  this._onCacheUpdateCallback = options.onCacheUpdateCallback;
  this._getCachedData = options.getCachedData;
};

HybridCursor.prototype._toArray = function (callback) {
  //reconcile strategy
  var self = this;
  var localData = null;
  var remoteData = null;
  var localErr = null;
  var remoteErr = null;
  var kuery = new Kuery(this._query);
  var sort = this._sort;
  var limit = this._limit;
  var skip = this._skip;
  var project = this._project;

  if (sort) {
    kuery.sort(sort);
  }
  if (limit) {
    kuery.limit(limit);
  }
  if (skip) {
    kuery.skip(skip);
  }

  function serverResult(err, result) {
    if (err) {
      remoteErr = err;
      result = result || [];
      if (self._options.throwRemoteErr) {
        return callback(err);
      }
    }
    remoteData = result;
    if (localData) {
      var combinedResult = kuery.find(reconcile(localData, remoteData));
      callback(null, combinedResult);
      if (_.isFunction(self._onCacheUpdateCallback)) {
        self._onCacheUpdateCallback(self._query, skip, limit, sort, project, combinedResult);
      }
    }
  }

  function localResult(err, result) {
    if (err) {
      localErr = err;
      return callback(err, result);
    }

    localData = result;
    if (remoteData || remoteErr) {
      if (!(remoteErr && self._options.throwRemoteErr)) {
        var combinedResult = kuery.find(reconcile(localData, remoteData || []));
        callback(null, combinedResult);
        if (_.isFunction(self._onCacheUpdateCallback)) {
          self._onCacheUpdateCallback(self._query, skip, limit, sort, project, combinedResult);
        }
      }
    } else {
      if (self._options.localFirst) {
        callback(err, localData);
      }
    }
  }

  if (sort) {
    this._local.sort(sort);
    this._remote.sort(sort);
  }
  if (limit) {
    this._local.limit(limit);
    this._remote.limit(limit);
  }
  if (skip) {
    this._local.skip(skip);
    this._remote.skip(skip);
  }
  if (project && _.isFunction(this._remote.project)) {
    this._remote.project(project);
  }

  this._local.toArray(localResult);
  this._remote.toArray(serverResult);
};

HybridCursor.prototype.toArray = function (callback) {
  var self = this;
  var timeTracker = new TimeTracker();
  var wrappedCallback = callback;

  if (this._options.loggingEnabled) {
    wrappedCallback = function () {
      timeTracker.stop();
      var queryTime = timeTracker.getExecutionTime();
      if (queryTime > self._options.queryMaxTime) {
        LOG.warn('Query %j, took longer than allowed max time of %s seconds.', self._query, self._options.queryMaxTime);
      }

      return callback.apply(self, arguments);
    };
  }
  timeTracker.start();
  if (this._getCachedData) {
    this._getCachedData(this._query, this._skip, this._limit, this._sort, this._project, function (err, data) {
      if (data) {
        wrappedCallback(null, data);
        return;
      }

      self._toArray(wrappedCallback);
    });
  } else {
    this._toArray(wrappedCallback);
  }
};

HybridCursor.prototype._refresh = function () {
  this._remote._refresh();
  this._local._refresh();
};

HybridCursor.prototype.sort = function (sort) {
  this._sort = sort;
  return this;
};

HybridCursor.prototype.limit = function (limit) {
  this._limit = limit;
  return this;
};

HybridCursor.prototype.skip = function (skip) {
  this._skip = skip;
  return this;
};

HybridCursor.prototype.updateQuery = function (query) {
  this._local._query.query = query;
  this._remote._query.query = query;
  this._query = query;
  this._refresh();
};

HybridCursor.prototype._onObserverCacheUpdate = function (result) {
  if (_.isFunction(this._onCacheUpdateCallback)) {
    this._onCacheUpdateCallback(this._query, this._skip, this._limit, this._sort, this._project, result);
  }
};

HybridCursor.prototype._getObserverData = function (callback) {
  this._getCachedData(this._query, this._skip, this._limit, this._sort, this._project, callback);
};

HybridCursor.prototype._count = function (options, callback) {
  var self = this;
  var localCount = null;
  var remoteCount = null;

  var timeTracker = new TimeTracker();
  var wrappedCallback = callback;

  if (this._options.loggingEnabled) {
    wrappedCallback = function () {
      timeTracker.stop();
      var queryTime = timeTracker.getExecutionTime();
      if (queryTime > self._options.queryMaxTime) {
        LOG.warn('Count query %j, took longer than allowed max time of %s seconds.', self._query, self._options.queryMaxTime);
      }

      return callback.apply(self, arguments);
    };
  }

  timeTracker.start();

  function serverResult(err, count) {
    if (err) {
      return wrappedCallback(err);
    }
    remoteCount = count;
    return wrappedCallback(null, count);
  }

  function localResult(err, count) {
    if (err) {
      return wrappedCallback(err, count);
    }

    localCount = count;
    if (remoteCount) {
      wrappedCallback(null, remoteCount);
    } else {
      if (self._options.localFirst) {
        wrappedCallback(err, localCount);
      }
    }
  }

  this._local.count(options, localResult);
  this._remote.count(options, serverResult);
};

HybridCursor.prototype.count = function (options, callback) {
  var self = this;
  if (_.isFunction(options)) {
    callback = options;
    options = undefined;
  }

  if (this._getCachedData) {
    this._getCachedData(this._query, this._skip, this._limit, this._sort, this._project, function (err, data) {
      if (data) {
        callback(null, data.length);
        return;
      }

      self._count(options, callback);
    });
  } else {
    this._count(options, callback);
  }
};

HybridCursor.prototype.observe = function (options) {
  var sort = this._sort;
  var limit = this._limit;
  var skip = this._skip;

  if (sort) {
    this._local.sort(sort);
    this._remote.sort(sort);
  }
  if (limit) {
    this._local.limit(limit);
    this._remote.limit(limit);
  }
  if (skip) {
    this._local.skip(skip);
    this._remote.skip(skip);
  }
  if (this._project && _.isFunction(this._remote.project)) {
    this._remote.project(this._project);
  }

  return new Observe(this._local, this._remote, this._options, options, this._onObserverCacheUpdate.bind(this), this._getObserverData.bind(this));
};

HybridCursor.prototype.project = function (project) {
  this._project = project;
  return this;
};

module.exports = HybridCursor;
<commit_msg>Changed to only use callback for getting data from cache if cache is enabled<commit_after>var Kuery = require('kuery');
var Observe = require('./observe');
var reconcile = require('./reconcile');
var _ = require('lodash');
var TimeTracker = require('./timeTracker');

var LoggerFactory = require('slf').LoggerFactory;
var LOG = LoggerFactory.getLogger('lx:viewdb-persistence-store-remote');
/**
 *
 * @param {*} query Mongodb query, for example: { 'identifiers.identifier': 'abc' }
 * @param {*} local Local cursor
 * @param {*} remote Remote cursor
 * @param {*} findOptions Not in use?
 * @param {*} options Options supplied from collection.
 */
var HybridCursor = function (query, local, remote, findOptions, options) {
  this._query = query;
  this._sort = null;
  this._limit = null;
  this._skip = 0;
  this._local = local;
  this._remote = remote;
  this._findOptions = findOptions;
  this._options = options;
  this._onCacheUpdateCallback = options.onCacheUpdateCallback;
  this._getCachedData = options.getCachedData;
};

HybridCursor.prototype._toArray = function (callback) {
  //reconcile strategy
  var self = this;
  var localData = null;
  var remoteData = null;
  var localErr = null;
  var remoteErr = null;
  var kuery = new Kuery(this._query);
  var sort = this._sort;
  var limit = this._limit;
  var skip = this._skip;
  var project = this._project;

  if (sort) {
    kuery.sort(sort);
  }
  if (limit) {
    kuery.limit(limit);
  }
  if (skip) {
    kuery.skip(skip);
  }

  function serverResult(err, result) {
    if (err) {
      remoteErr = err;
      result = result || [];
      if (self._options.throwRemoteErr) {
        return callback(err);
      }
    }
    remoteData = result;
    if (localData) {
      var combinedResult = kuery.find(reconcile(localData, remoteData));
      callback(null, combinedResult);
      if (_.isFunction(self._onCacheUpdateCallback)) {
        self._onCacheUpdateCallback(self._query, skip, limit, sort, project, combinedResult);
      }
    }
  }

  function localResult(err, result) {
    if (err) {
      localErr = err;
      return callback(err, result);
    }

    localData = result;
    if (remoteData || remoteErr) {
      if (!(remoteErr && self._options.throwRemoteErr)) {
        var combinedResult = kuery.find(reconcile(localData, remoteData || []));
        callback(null, combinedResult);
        if (_.isFunction(self._onCacheUpdateCallback)) {
          self._onCacheUpdateCallback(self._query, skip, limit, sort, project, combinedResult);
        }
      }
    } else {
      if (self._options.localFirst) {
        callback(err, localData);
      }
    }
  }

  if (sort) {
    this._local.sort(sort);
    this._remote.sort(sort);
  }
  if (limit) {
    this._local.limit(limit);
    this._remote.limit(limit);
  }
  if (skip) {
    this._local.skip(skip);
    this._remote.skip(skip);
  }
  if (project && _.isFunction(this._remote.project)) {
    this._remote.project(project);
  }

  this._local.toArray(localResult);
  this._remote.toArray(serverResult);
};

HybridCursor.prototype.toArray = function (callback) {
  var self = this;
  var timeTracker = new TimeTracker();
  var wrappedCallback = callback;

  if (this._options.loggingEnabled) {
    wrappedCallback = function () {
      timeTracker.stop();
      var queryTime = timeTracker.getExecutionTime();
      if (queryTime > self._options.queryMaxTime) {
        LOG.warn('Query %j, took longer than allowed max time of %s seconds.', self._query, self._options.queryMaxTime);
      }

      return callback.apply(self, arguments);
    };
  }
  timeTracker.start();
  if (this._options.cacheQueries && this._getCachedData) {
    this._getCachedData(this._query, this._skip, this._limit, this._sort, this._project, function (err, data) {
      if (data) {
        wrappedCallback(null, data);
        return;
      }

      self._toArray(wrappedCallback);
    });
  } else {
    this._toArray(wrappedCallback);
  }
};

HybridCursor.prototype._refresh = function () {
  this._remote._refresh();
  this._local._refresh();
};

HybridCursor.prototype.sort = function (sort) {
  this._sort = sort;
  return this;
};

HybridCursor.prototype.limit = function (limit) {
  this._limit = limit;
  return this;
};

HybridCursor.prototype.skip = function (skip) {
  this._skip = skip;
  return this;
};

HybridCursor.prototype.updateQuery = function (query) {
  this._local._query.query = query;
  this._remote._query.query = query;
  this._query = query;
  this._refresh();
};

HybridCursor.prototype._onObserverCacheUpdate = function (result) {
  if (_.isFunction(this._onCacheUpdateCallback)) {
    this._onCacheUpdateCallback(this._query, this._skip, this._limit, this._sort, this._project, result);
  }
};

HybridCursor.prototype._getObserverData = function (callback) {
  this._getCachedData(this._query, this._skip, this._limit, this._sort, this._project, callback);
};

HybridCursor.prototype._count = function (options, callback) {
  var self = this;
  var localCount = null;
  var remoteCount = null;

  var timeTracker = new TimeTracker();
  var wrappedCallback = callback;

  if (this._options.loggingEnabled) {
    wrappedCallback = function () {
      timeTracker.stop();
      var queryTime = timeTracker.getExecutionTime();
      if (queryTime > self._options.queryMaxTime) {
        LOG.warn('Count query %j, took longer than allowed max time of %s seconds.', self._query, self._options.queryMaxTime);
      }

      return callback.apply(self, arguments);
    };
  }

  timeTracker.start();

  function serverResult(err, count) {
    if (err) {
      return wrappedCallback(err);
    }
    remoteCount = count;
    return wrappedCallback(null, count);
  }

  function localResult(err, count) {
    if (err) {
      return wrappedCallback(err, count);
    }

    localCount = count;
    if (remoteCount) {
      wrappedCallback(null, remoteCount);
    } else {
      if (self._options.localFirst) {
        wrappedCallback(err, localCount);
      }
    }
  }

  this._local.count(options, localResult);
  this._remote.count(options, serverResult);
};

HybridCursor.prototype.count = function (options, callback) {
  var self = this;
  if (_.isFunction(options)) {
    callback = options;
    options = undefined;
  }

  if (this._getCachedData) {
    this._getCachedData(this._query, this._skip, this._limit, this._sort, this._project, function (err, data) {
      if (data) {
        callback(null, data.length);
        return;
      }

      self._count(options, callback);
    });
  } else {
    this._count(options, callback);
  }
};

HybridCursor.prototype.observe = function (options) {
  var sort = this._sort;
  var limit = this._limit;
  var skip = this._skip;

  if (sort) {
    this._local.sort(sort);
    this._remote.sort(sort);
  }
  if (limit) {
    this._local.limit(limit);
    this._remote.limit(limit);
  }
  if (skip) {
    this._local.skip(skip);
    this._remote.skip(skip);
  }
  if (this._project && _.isFunction(this._remote.project)) {
    this._remote.project(this._project);
  }

  var modifiedOptions = options;
  if (this._options.cacheQueries) {
    modifiedOptions = Object.assign({}, options, { cacheCallback: this._onObserverCacheUpdate.bind(this), getCache: this._getObserverData.bind(this) });
  }

  return new Observe(this._local, this._remote, this._options, modifiedOptions);
};

HybridCursor.prototype.project = function (project) {
  this._project = project;
  return this;
};

module.exports = HybridCursor;
<|endoftext|>


<commit_before>'use strict';

var extractCss = require('extract-css'),
    inlineCss = require('./inline-css');

module.exports = function inlineContent(src, options) {
    return new Promise(function (resolve, reject) {
        var content;

        if (!options.url) {
            reject('options.url is required');
        }

        extractCss(src, options, function (err, html, css) {
            var extraCss;

            if (err) {
                return reject(err);
            }

            extraCss = css + '\n' + options.extraCss;
            content = inlineCss(html, extraCss, options);
            resolve(content);
        });
    });

};
<commit_msg>Fix error in node v0.10 missing Promises.<commit_after>'use strict';

var Promise = require('bluebird'),
    extractCss = require('extract-css'),
    inlineCss = require('./inline-css');

module.exports = function inlineContent(src, options) {
    return new Promise(function (resolve, reject) {
        var content;

        if (!options.url) {
            reject('options.url is required');
        }

        extractCss(src, options, function (err, html, css) {
            var extraCss;

            if (err) {
                return reject(err);
            }

            extraCss = css + '\n' + options.extraCss;
            content = inlineCss(html, extraCss, options);
            resolve(content);
        });
    });

};
<|endoftext|>


<commit_before>// Copyright 2014, Renasar Technologies Inc.
/* jshint: node:true */

'use strict';

var di = require('di'),
    events = require('events');

module.exports = baseJobFactory;
di.annotate(baseJobFactory, new di.Provide('Job.Base'));
    di.annotate(baseJobFactory,
    new di.Inject(
        'Protocol.Events',
        'Protocol.Task',
        'Assert',
        'Util',
        'Q',
        '_'
    )
);
function baseJobFactory(eventsProtocol, taskProtocol, assert, util, Q, _) {

    function BaseJob(logger, options, context, taskId) {
        assert.func(this._run);

        assert.object(logger);
        assert.uuid(taskId);
        assert.object(options);
        assert.object(context);

        this.subscriptions = [];
        this.subscriptionPromises = [];

        this.logger = logger;
        this.options = options;
        this.context = context;
        this.taskId = taskId;
    }
    util.inherits(BaseJob, events.EventEmitter);

    BaseJob.prototype.run = function run() {
        this._run();
        return this;
    };

    BaseJob.prototype.cancel = function cancel() {
        this.logger.info("Canceling job.", {
            taskId: this.taskId,
            name: this.constructor.name
        });
        this._done();
    };

    BaseJob.prototype._done = function _done(error) {
        var self = this;

        // Handle resolution of created subscriptions in the case we cancel
        // while still initializing
        Q.all(self.subscriptionPromises)
        .then(function() {
            return Q.all(_.map(self.subscriptions, function(subscription) {
                return subscription.dispose();
            }));
        })
        .then(function() {
            if (error) {
                self.emit('done', error);
            } else {
                self.emit('done');
            }
            self.removeAllListeners();
        })
        .catch(function(e) {
            self.logger.error("Error canceling Job.", {
                error: e,
                taskId: self.taskId
            });
            self.emit('done', e);
            self.removeAllListeners();
        });
    };

    // enables JSON.stringify(this)
    BaseJob.prototype.toJSON = function toJSON() {
        return this.serialize();
    };

    BaseJob.prototype.serialize = function serialize() {
        var json = _.cloneDeep(_(this).value());
        delete json.logger;
        delete json.subscriptions;
        delete json.subscriptionPromises;
        return json;
    };

    BaseJob.prototype._subscribeRequestProfile = function _subscribeRequestProfile(callback) {
        var self = this;
        assert.isMongoId(self.nodeId);
        var deferred = taskProtocol.subscribeRequestProfile(self.nodeId, callback.bind(self));
        self.subscriptionPromises.push(deferred);
        deferred.then(function(subscription) {
            self.subscriptions.push(subscription);
        });
    };

    BaseJob.prototype._subscribeRequestProperties = function _subscribeRequestProperties(callback) {
        var self = this;
        assert.isMongoId(self.nodeId);
        var deferred = taskProtocol.subscribeRequestProperties(self.nodeId, callback.bind(self));
        self.subscriptionPromises.push(deferred);
        deferred.then(function(subscription) {
            self.subscriptions.push(subscription);
        });
    };

    BaseJob.prototype._subscribeRespondCommands = function _subscribeRespondCommands(callback) {
        var self = this;
        assert.isMongoId(self.nodeId);
        var deferred = taskProtocol.subscribeRespondCommands(self.nodeId, callback.bind(self));
        self.subscriptionPromises.push(deferred);
        deferred.then(function(subscription) {
            self.subscriptions.push(subscription);
        });
    };

    BaseJob.prototype._subscribeRequestCommands = function _subscribeRequestCommands(callback) {
        var self = this;
        assert.isMongoId(self.nodeId);
        var deferred = taskProtocol.subscribeRequestCommands(self.nodeId, callback.bind(self));
        self.subscriptionPromises.push(deferred);
        deferred.then(function(subscription) {
            self.subscriptions.push(subscription);
        });
    };

    BaseJob.prototype._subscribeHttpResponse = function _subscribeHttpResponse(callback) {
        var self = this;
        assert.isMongoId(self.nodeId);
        var deferred = eventsProtocol.subscribeHttpResponse(self.nodeId, callback.bind(self));
        self.subscriptionPromises.push(deferred);
        deferred.then(function(subscription) {
            self.subscriptions.push(subscription);
        });
    };

    BaseJob.prototype._subscribeGraphFinished = function _subscribeGraphFinished(callback) {
        var self = this;
        assert.func(callback);
        assert.uuid(self.graphId);
        var deferred = eventsProtocol.subscribeGraphFinished(self.graphId, callback.bind(self));
        self.subscriptionPromises.push(deferred);
        deferred.then(function(subscription) {
            self.subscriptions.push(subscription);
        });
    };

    BaseJob.prototype._publishSnmpCommandResult =
        function _publishSnmpCommandResult(uuid, data) {

        taskProtocol.publishSnmpCommandResult(uuid, data);
    };

    BaseJob.prototype._subscribeSnmpCommandResult =
        function _subscribeSnmpCommandResult(uuid, callback) {

        var self = this;

        var deferred = taskProtocol.subscribeSnmpCommandResult(uuid, callback.bind(self));
        self.subscriptionPromises.push(deferred);
        deferred.then(function(subscription) {
            self.subscriptions.push(subscription);
        });
    };

    BaseJob.prototype._subscribeRunSnmpCommand = function _subscribeRunSnmpCommand(uuid, callback) {
        var self = this;

        var deferred = taskProtocol.subscribeRunSnmpCommand(uuid, callback.bind(self));
        self.subscriptionPromises.push(deferred);
        deferred.then(function(subscription) {
            self.subscriptions.push(subscription);
        });
    };

    BaseJob.prototype._publishRunSnmpCommand = function _publishRunSnmpCommand(uuid, hostData) {
        taskProtocol.publishRunSnmpCommand(uuid, hostData);
    };

    BaseJob.prototype._publishIpmiCommandResult =
        function _publishIpmiCommandResult(uuid, command, data) {

        taskProtocol.publishIpmiCommandResult(uuid, command, data);
    };

    BaseJob.prototype._subscribeIpmiCommandResult =
        function _subscribeIpmiCommandResult(uuid, command, callback) {

        var self = this;

        var deferred = taskProtocol.subscribeIpmiCommandResult(uuid, command,
                callback.bind(self));
        self.subscriptionPromises.push(deferred);
        deferred.then(function(subscription) {
            self.subscriptions.push(subscription);
        });
    };

    BaseJob.prototype._subscribeRunIpmiCommand =
        function _subscribeRunIpmiCommand(uuid, command, callback) {

        var self = this;

        var deferred = taskProtocol.subscribeRunIpmiCommand(uuid, command,
                callback.bind(self));
        self.subscriptionPromises.push(deferred);
        deferred.then(function(subscription) {
            self.subscriptions.push(subscription);
        });
    };

    BaseJob.prototype._publishRunIpmiCommand =
        function _publishRunIpmiCommand(uuid, command, machine) {

        taskProtocol.publishRunIpmiCommand(uuid, command, machine);
    };

    BaseJob.prototype._publishPollerAlert = function _publishPollerAlert(id, data) {
        taskProtocol.publishPollerAlert(id, data);
    };

    BaseJob.prototype._subscribeRequestPollerCache =
        function _subscribeRequestPollerCache(callback) {

        var self = this;

        var deferred = taskProtocol.subscribeRequestPollerCache(callback.bind(self));
        self.subscriptionPromises.push(deferred);
        deferred.then(function(subscription) {
            self.subscriptions.push(subscription);
        });
    };

    return BaseJob;
}
<commit_msg>properly returning promises from base job subscription methods<commit_after>// Copyright 2014, Renasar Technologies Inc.
/* jshint: node:true */

'use strict';

var di = require('di'),
    events = require('events');

module.exports = baseJobFactory;
di.annotate(baseJobFactory, new di.Provide('Job.Base'));
    di.annotate(baseJobFactory,
    new di.Inject(
        'Protocol.Events',
        'Protocol.Task',
        'Assert',
        'Util',
        'Q',
        '_'
    )
);
function baseJobFactory(eventsProtocol, taskProtocol, assert, util, Q, _) {

    function BaseJob(logger, options, context, taskId) {
        assert.func(this._run);

        assert.object(logger);
        assert.uuid(taskId);
        assert.object(options);
        assert.object(context);

        this.subscriptions = [];
        this.subscriptionPromises = [];

        this.logger = logger;
        this.options = options;
        this.context = context;
        this.taskId = taskId;
    }
    util.inherits(BaseJob, events.EventEmitter);

    BaseJob.prototype.run = function run() {
        this._run();
        return this;
    };

    BaseJob.prototype.cancel = function cancel() {
        this.logger.info("Canceling job.", {
            taskId: this.taskId,
            name: this.constructor.name
        });
        this._done();
    };

    BaseJob.prototype._done = function _done(error) {
        var self = this;

        // Handle resolution of created subscriptions in the case we cancel
        // while still initializing
        Q.all(self.subscriptionPromises)
        .then(function() {
            return Q.all(_.map(self.subscriptions, function(subscription) {
                return subscription.dispose();
            }));
        })
        .then(function() {
            if (error) {
                self.emit('done', error);
            } else {
                self.emit('done');
            }
            self.removeAllListeners();
        })
        .catch(function(e) {
            self.logger.error("Error canceling Job.", {
                error: e,
                taskId: self.taskId
            });
            self.emit('done', e);
            self.removeAllListeners();
        });
    };

    // enables JSON.stringify(this)
    BaseJob.prototype.toJSON = function toJSON() {
        return this.serialize();
    };

    BaseJob.prototype.serialize = function serialize() {
        var json = _.cloneDeep(_(this).value());
        delete json.logger;
        delete json.subscriptions;
        delete json.subscriptionPromises;
        return json;
    };

    BaseJob.prototype._subscribeRequestProfile = function _subscribeRequestProfile(callback) {
        var self = this;
        assert.isMongoId(self.nodeId);
        var deferred = taskProtocol.subscribeRequestProfile(self.nodeId, callback.bind(self));
        self.subscriptionPromises.push(deferred);
        return deferred.then(function(subscription) {
            self.subscriptions.push(subscription);
        });
    };

    BaseJob.prototype._subscribeRequestProperties = function _subscribeRequestProperties(callback) {
        var self = this;
        assert.isMongoId(self.nodeId);
        var deferred = taskProtocol.subscribeRequestProperties(self.nodeId, callback.bind(self));
        self.subscriptionPromises.push(deferred);
        return deferred.then(function(subscription) {
            self.subscriptions.push(subscription);
        });
    };

    BaseJob.prototype._subscribeRespondCommands = function _subscribeRespondCommands(callback) {
        var self = this;
        assert.isMongoId(self.nodeId);
        var deferred = taskProtocol.subscribeRespondCommands(self.nodeId, callback.bind(self));
        self.subscriptionPromises.push(deferred);
        return deferred.then(function(subscription) {
            self.subscriptions.push(subscription);
        });
    };

    BaseJob.prototype._subscribeRequestCommands = function _subscribeRequestCommands(callback) {
        var self = this;
        assert.isMongoId(self.nodeId);
        var deferred = taskProtocol.subscribeRequestCommands(self.nodeId, callback.bind(self));
        self.subscriptionPromises.push(deferred);
        deferred.then(function(subscription) {
            self.subscriptions.push(subscription);
        });
    };

    BaseJob.prototype._subscribeHttpResponse = function _subscribeHttpResponse(callback) {
        var self = this;
        assert.isMongoId(self.nodeId);
        var deferred = eventsProtocol.subscribeHttpResponse(self.nodeId, callback.bind(self));
        self.subscriptionPromises.push(deferred);
        return deferred.then(function(subscription) {
            self.subscriptions.push(subscription);
        });
    };

    BaseJob.prototype._subscribeGraphFinished = function _subscribeGraphFinished(callback) {
        var self = this;
        assert.func(callback);
        assert.uuid(self.graphId);
        var deferred = eventsProtocol.subscribeGraphFinished(self.graphId, callback.bind(self));
        self.subscriptionPromises.push(deferred);
        return deferred.then(function(subscription) {
            self.subscriptions.push(subscription);
        });
    };

    BaseJob.prototype._publishSnmpCommandResult =
        function _publishSnmpCommandResult(uuid, data) {

        return taskProtocol.publishSnmpCommandResult(uuid, data);
    };

    BaseJob.prototype._subscribeSnmpCommandResult =
        function _subscribeSnmpCommandResult(uuid, callback) {

        var self = this;

        var deferred = taskProtocol.subscribeSnmpCommandResult(uuid, callback.bind(self));
        self.subscriptionPromises.push(deferred);
        return deferred.then(function(subscription) {
            self.subscriptions.push(subscription);
        });
    };

    BaseJob.prototype._subscribeRunSnmpCommand = function _subscribeRunSnmpCommand(uuid, callback) {
        var self = this;

        var deferred = taskProtocol.subscribeRunSnmpCommand(uuid, callback.bind(self));
        self.subscriptionPromises.push(deferred);
        return deferred.then(function(subscription) {
            self.subscriptions.push(subscription);
        });
    };

    BaseJob.prototype._publishRunSnmpCommand = function _publishRunSnmpCommand(uuid, hostData) {
        return taskProtocol.publishRunSnmpCommand(uuid, hostData);
    };

    BaseJob.prototype._publishIpmiCommandResult =
        function _publishIpmiCommandResult(uuid, command, data) {

        return taskProtocol.publishIpmiCommandResult(uuid, command, data);
    };

    BaseJob.prototype._subscribeIpmiCommandResult =
        function _subscribeIpmiCommandResult(uuid, command, callback) {

        var self = this;

        var deferred = taskProtocol.subscribeIpmiCommandResult(uuid, command,
                callback.bind(self));
        self.subscriptionPromises.push(deferred);
        return deferred.then(function(subscription) {
            self.subscriptions.push(subscription);
        });
    };

    BaseJob.prototype._subscribeRunIpmiCommand =
        function _subscribeRunIpmiCommand(uuid, command, callback) {

        var self = this;

        var deferred = taskProtocol.subscribeRunIpmiCommand(uuid, command,
                callback.bind(self));
        self.subscriptionPromises.push(deferred);
        return deferred.then(function(subscription) {
            self.subscriptions.push(subscription);
        });
    };

    BaseJob.prototype._publishRunIpmiCommand =
        function _publishRunIpmiCommand(uuid, command, machine) {

        taskProtocol.publishRunIpmiCommand(uuid, command, machine);
    };

    BaseJob.prototype._publishPollerAlert = function _publishPollerAlert(id, data) {
        taskProtocol.publishPollerAlert(id, data);
    };

    BaseJob.prototype._subscribeRequestPollerCache =
        function _subscribeRequestPollerCache(callback) {

        var self = this;

        var deferred = taskProtocol.subscribeRequestPollerCache(callback.bind(self));
        self.subscriptionPromises.push(deferred);
        deferred.then(function(subscription) {
            self.subscriptions.push(subscription);
        });
    };

    return BaseJob;
}
<|endoftext|>