<commit_before>"use strict";

var p2r = require('path-to-regexp'),
    funcDeps = require('func-deps'),
    _ = require('lodash'),
    http = require('http'),
    util = require('util');

function Molded() {
    if (typeof this === 'undefined') {
        return new Molded();
    }
    this.providers = [];
    this.singletons = [];
    this.values = [];
    this.handlers = [];
}

function send(status, content) {
    var args = Array.prototype.slice.apply(arguments);
    if (typeof status === 'number') {
        this.statusCode = args.shift();
    } else {
        content = status;
    }
    if (typeof content === 'string') {
        if (!this.headersSent && undefined === this.getHeader('content-type')) {
            this.setHeader('Content-Type', 'text/html');
        }
        this.write(content);
        this.end();
    } else if (Buffer.isBuffer(content)) {
        this.write(content);
        this.end();
    } else if (undefined === content) {
        this.end('undefined');
    } else {
        if (!this.headersSent && undefined === this.getHeader('content-type')) {
            this.setHeader('Content-Type', 'application/json');
        }
        this.write(JSON.stringify(content));
        this.end();
    }
}

function initialDep(name, value) {
    return {
        method: 'ALL',
        route: /.*/,
        name: name,
        deps: [],
        resolve: function() { return value }
    }
};

function initialDeps(req, res, next) {
    if (next) {
        return [
            initialDep('req', req),
            initialDep('res', res),
            initialDep('next', next)
        ];
    } else {
        return [
            initialDep('req', req),
            initialDep('res', res)
        ];
    }
}

Molded.prototype.resolveDeps = function resolveDeps(req, initialDeps, depNames) {
    var self = this;
    var possibleDeps = initialDeps.concat(this.providers);
    var nextlessDeps = initialDeps.filter(function(dep) {
        return dep.name !== 'next';
    });
    var resolvedDeps = [];
    _.forEach(depNames, function(dep, index) {
        var found = _.find(possibleDeps, function(possibleDep) {
            if ('ALL' !== possibleDep.method && possibleDep.method !== req.method) {
                return false;
            }
            return possibleDep.name == dep
                && null !== possibleDep.route.exec(req.url);
        });
        if (found) {
            resolvedDeps.push(self.resolveAndCall(req, nextlessDeps, found));
        } else {
            console.log(dep);
            throw Error('Unresolved dependency: ' + dep);
        }
    });
    return resolvedDeps;
};

Molded.prototype.resolveAndCall = function resolveAndCall(req, initialDeps, callback) {
    var resolvedDeps = this.resolveDeps(req, initialDeps, callback.deps);
    return callback.resolve.apply(null, resolvedDeps);
};

Molded.prototype.handleRequest = function handleRequest(req, res) {
    var self = this;
    res.send = send.bind(res);
    var handlers = _.clone(this.handlers);
    function next() {
        if (handlers.length > 0) {
            var handler = handlers.shift();
            if ('ALL' !== handler.method && handler.method !== req.method) {
                return next();
            }
            var params = handler.route.exec(req.url);
            if (null === params) {
                return next();
            }
            var keys = _.pluck(handler.keys, 'name');
            var routeParams = handler.route.exec(req.url).slice(1);
            if (keys.length > 0) {
                req.params = _.zipObject(keys, routeParams);
            } else {
                req.params = routeParams;
            }
            self.resolveAndCall(req, initialDeps(req, res, next), handler);
        } else {
            res.statusCode = 404;
            res.write(util.format("Can't %s %s", req.method, req.url));
            res.end();
        }
    }
    next();
};

function addHandler(method, route, handler) {
    if (_.isFunction(route) || _.isArray(route)) {
        handler = route;
        route = /.*/;
    }
    var keys = [];
    var route = p2r(route, keys);
    var deps = funcDeps(handler);
    this.handlers.push({
        method: method,
        keys: keys,
        route: route,
        resolve: deps.func,
        deps: deps.deps
    });
}

Molded.prototype.provide = function provide(depName, provider) {
    var deps = funcDeps(provider);
    this.providers.push({
        method: 'ALL',
        route: /.*/,
        name: depName,
        deps: deps.deps,
        resolve: deps.func
    });
};

Molded.prototype.singleton = function singleton(depName, func) {
    this.singletons[depName] = func;
};

Molded.prototype.value = function value(depName, val) {
    if (val) {
        this.values[depName] = val;
    } else {
        return this.values[depName];
    }
};

Molded.prototype.use = function() {
    var args = ['ALL'].concat(Array.prototype.slice.apply(arguments));
    addHandler.apply(this, args);
};

var methods = ['get', 'post', 'put', 'patch', 'delete', 'copy',
               'head', 'options', 'link', 'unlink', 'purge', 'all'];

_.forEach(methods, function(method) {
    var methodUpper = method.toUpperCase();
    Molded.prototype[method] = function() {
        var args = [methodUpper].concat(Array.prototype.slice.apply(arguments));
        addHandler.apply(this, args);
    };
});

Molded.prototype.listen = function listen(port, cb) {
    http.createServer(this.handleRequest.bind(this)).listen(port);
};

module.exports = Molded;
<commit_msg>Remove extra console.log statement<commit_after>"use strict";

var p2r = require('path-to-regexp'),
    funcDeps = require('func-deps'),
    _ = require('lodash'),
    http = require('http'),
    util = require('util');

function Molded() {
    if (typeof this === 'undefined') {
        return new Molded();
    }
    this.providers = [];
    this.singletons = [];
    this.values = [];
    this.handlers = [];
}

function send(status, content) {
    var args = Array.prototype.slice.apply(arguments);
    if (typeof status === 'number') {
        this.statusCode = args.shift();
    } else {
        content = status;
    }
    if (typeof content === 'string') {
        if (!this.headersSent && undefined === this.getHeader('content-type')) {
            this.setHeader('Content-Type', 'text/html');
        }
        this.write(content);
        this.end();
    } else if (Buffer.isBuffer(content)) {
        this.write(content);
        this.end();
    } else if (undefined === content) {
        this.end('undefined');
    } else {
        if (!this.headersSent && undefined === this.getHeader('content-type')) {
            this.setHeader('Content-Type', 'application/json');
        }
        this.write(JSON.stringify(content));
        this.end();
    }
}

function initialDep(name, value) {
    return {
        method: 'ALL',
        route: /.*/,
        name: name,
        deps: [],
        resolve: function() { return value }
    }
};

function initialDeps(req, res, next) {
    if (next) {
        return [
            initialDep('req', req),
            initialDep('res', res),
            initialDep('next', next)
        ];
    } else {
        return [
            initialDep('req', req),
            initialDep('res', res)
        ];
    }
}

Molded.prototype.resolveDeps = function resolveDeps(req, initialDeps, depNames) {
    var self = this;
    var possibleDeps = initialDeps.concat(this.providers);
    var nextlessDeps = initialDeps.filter(function(dep) {
        return dep.name !== 'next';
    });
    var resolvedDeps = [];
    _.forEach(depNames, function(dep, index) {
        var found = _.find(possibleDeps, function(possibleDep) {
            if ('ALL' !== possibleDep.method && possibleDep.method !== req.method) {
                return false;
            }
            return possibleDep.name == dep
                && null !== possibleDep.route.exec(req.url);
        });
        if (found) {
            resolvedDeps.push(self.resolveAndCall(req, nextlessDeps, found));
        } else {
            throw Error('Unresolved dependency: ' + dep);
        }
    });
    return resolvedDeps;
};

Molded.prototype.resolveAndCall = function resolveAndCall(req, initialDeps, callback) {
    var resolvedDeps = this.resolveDeps(req, initialDeps, callback.deps);
    return callback.resolve.apply(null, resolvedDeps);
};

Molded.prototype.handleRequest = function handleRequest(req, res) {
    var self = this;
    res.send = send.bind(res);
    var handlers = _.clone(this.handlers);
    function next() {
        if (handlers.length > 0) {
            var handler = handlers.shift();
            if ('ALL' !== handler.method && handler.method !== req.method) {
                return next();
            }
            var params = handler.route.exec(req.url);
            if (null === params) {
                return next();
            }
            var keys = _.pluck(handler.keys, 'name');
            var routeParams = handler.route.exec(req.url).slice(1);
            if (keys.length > 0) {
                req.params = _.zipObject(keys, routeParams);
            } else {
                req.params = routeParams;
            }
            self.resolveAndCall(req, initialDeps(req, res, next), handler);
        } else {
            res.statusCode = 404;
            res.write(util.format("Can't %s %s", req.method, req.url));
            res.end();
        }
    }
    next();
};

function addHandler(method, route, handler) {
    if (_.isFunction(route) || _.isArray(route)) {
        handler = route;
        route = /.*/;
    }
    var keys = [];
    var route = p2r(route, keys);
    var deps = funcDeps(handler);
    this.handlers.push({
        method: method,
        keys: keys,
        route: route,
        resolve: deps.func,
        deps: deps.deps
    });
}

Molded.prototype.provide = function provide(depName, provider) {
    var deps = funcDeps(provider);
    this.providers.push({
        method: 'ALL',
        route: /.*/,
        name: depName,
        deps: deps.deps,
        resolve: deps.func
    });
};

Molded.prototype.singleton = function singleton(depName, func) {
    this.singletons[depName] = func;
};

Molded.prototype.value = function value(depName, val) {
    if (val) {
        this.values[depName] = val;
    } else {
        return this.values[depName];
    }
};

Molded.prototype.use = function() {
    var args = ['ALL'].concat(Array.prototype.slice.apply(arguments));
    addHandler.apply(this, args);
};

var methods = ['get', 'post', 'put', 'patch', 'delete', 'copy',
               'head', 'options', 'link', 'unlink', 'purge', 'all'];

_.forEach(methods, function(method) {
    var methodUpper = method.toUpperCase();
    Molded.prototype[method] = function() {
        var args = [methodUpper].concat(Array.prototype.slice.apply(arguments));
        addHandler.apply(this, args);
    };
});

Molded.prototype.listen = function listen(port, cb) {
    http.createServer(this.handleRequest.bind(this)).listen(port);
};

module.exports = Molded;
<|endoftext|>


<commit_before>var fs = require('fs'),
    events = require('events'),
    path = require('path'),
    analysis = require('./lib/analysis.js'),
    util = require('util')

exports.Freud = Freud
exports.createFreud = createFreud

function Freud(source, target, options) {
  if (!(this instanceof Freud)) return new Freud(source, target, options)

  this.source = path.normalize(source)
  this.target = path.normalize(target)
  this.processed = []
  this.rules = []
  this.options = options || {}
  this.listener = null
  this.version = require(path.join(__dirname, 'package.json')).version

  return this
}

util.inherits(Freud, events.EventEmitter)

Freud.prototype.doUnlink = function (filename) {
  var dummyFile = {
    name: filename,
    fullPath: path.join(this.source + filename),
    extension: filename.split('.').pop(),
    write: true,
    stats: undefined,
    data: ''
  }

  this.processFile(dummyFile, parseFile.bind(this))

  function parseFile(file) {
    analysis.unlink('file', this.target, file.name, checkUnlink.bind(this))

    function checkUnlink(err, didUnlink) {
      if (!err && didUnlink) return this.emit('unlinked', file.name);
      this.processDir(filename, checkDir.bind(this))

      function checkDir(dir) {
        analysis.unlink('dir', this.target, dir.name, checkDirUnlink.bind(this))

        function checkDirUnlink(err, didUnlink) {
          if (!err && didUnlink) this.emit('unlinked', dir.name);
        }
      }
    }
  }
}

Freud.prototype.recompile = function (filename) {
  var extension = filename.split('.').pop();
  if (this.rules[extension] || this.rules['*:before'] || this.rules['*:after']) {
    return this.compileFile(filename, recompileFile.bind(this))
  }
  fs.exists(path.join(this.target, filename), moveFile.bind(this))

  function moveFile(fileExists) {
    if (!fileExists) return this.copyFile(filename);
    fs.unlink(path.join(this.target, filename), function (err) {
      this.copyFile(filename);
    })
  }

  function recompileFile(filename, written) {
    this.emit('recompiled', filename);
    if (!written) this.emit('blocked', filename)
  }
}

Freud.prototype.listen = function (extension, callback) {
  if (!Array.isArray(extension)) extension = [extension]
  this.attachListeners(extension, callback)
}

Freud.prototype.checkStats = function (filename, callback) {
  analysis.getFile(this.source, filename, parseStats.bind(this))

  function parseStats(file) {
    if (file.stats === undefined) return callback(null, undefined);

    var theMTime = file.stats.mtime.getTime(),
        duplicate = this.processed[filename] && this.processed[filename] === theMTime
    this.processed[filename] = theMTime;
    callback(duplicate, file.stats);
  }
}

Freud.prototype.attachListeners = function (extensions, callback) {

  extensions.forEach(doAttach.bind(this))

  function doAttach(extension) {
    extension = extension === '*' ? '*:before' : extension
    extension = extension === '/*' ? '/*:before' : extension
    extension = this.options.ignoreCase ? extension.toLowerCase() : extension

    this.rules[extension] = this.rules[extension] || []
    this.rules[extension].push(callback)
    this.emit('extensionAdded', extension)
  }

}

Freud.prototype.go = function () {
  this.listener = fs.watch(this.source, { persistent: true }, this.eventResponse.bind(this))
  this.emit('started', this);
}

Freud.prototype.copyFile = function (filename) {
  this.emit('copying')
  fs.link(path.join(this.source, filename), path.join(this.target, filename), function () {
    this.emit('copied', filename)
  }.bind(this))
}
Freud.prototype.eventResponse = function (event, filename) {

  if (!filename) return this.emit('error', new Error('fs.watch error'))

  if ((!/^\./.test(filename) || this.options.monitorDot) && (!/~$/.test(filename) || this.options.monitorSquiggle)) {
    this.checkStats(filename, statResult.bind(this))
  }

  function statResult(isDuplicate, stats) {
    if (isDuplicate) return
    if (stats && stats.isDirectory()) {
      return this.compileDir(this, filename, fileCompiled.bind(this))
    }
    var extension = filename.split('.').pop()
    extension = this.options.ignoreCase ? extension.toLowerCase() : extension
    if (this.rules[extension] || this.rules['*:before'] || this.rules['*:after']) {
      return this.compileFile(filename, fileCompiled.bind(this))
    }
    fs.exists(path.join(this.source, filename), fileMove.bind(this))
  }

  function fileMove(linkFile) {
    this[linkFile ? 'copyFile' : 'doUnlink'](filename)
  }

  function fileCompiled(filename, written) {
    this.emit('compiled', filename)
    if (!written) this.emit('blocked', filename)
  }
}

Freud.prototype.processFile = function (file, callback) {
  var rules = [].concat(
      (this.rules['*:before'] || [])
      .concat(
      (this.rules[this.options.ignoreCase ? file.extension.toLowerCase() : file.extension] || [])
      .concat(
      (this.rules['*:after'] || []))
    ))
  if (!rules.length) return callback(file)
  analysis.executeRules(rules, file, callback)
}

Freud.prototype.processDir = function (dirname, callback) {

  var dir = { name: dirname, write: true },
      rules = [].concat(
          (this.rules['/*:before'] || [])
          .concat(
          (this.rules['/'] || [])
          .concat(
          (this.rules['/*:after'] ||[]))
        ))

  if (!rules.length) return callback(dir)
  analysis.executeRules(rules, dir, callback)
}

Freud.prototype.compileFile = function (filename, callback) {
  this.emit('compiling', filename)

  fs.exists(path.join(this.source, filename), checkFile.bind(this))

  function checkFile(inputFileExists) {
    if (!inputFileExists) return this.doUnlink(filename)
    analysis.getFile(this.source, filename, parseFile.bind(this))
    function parseFile(file) {
      this.processFile(file, putFile.bind(this))

      function putFile(file) {
        if (!file.write) return callback(file.name, false)

        analysis.putFile(this.target, file, function () {
          callback(file.name, true)
        }.bind(this))
      }
    }
  }
}

Freud.prototype.compileDir = function (filename, callback) {
  this.emit('compiling', filename)

  fs.exists(path.join(this.source, filename), checkDir.bind(this))
  function checkDir(inputDirExists) {
    if (inputDirExists) {
      return this.processDir(filename, onProcess.bind(this))
    }
    this.processDir(filename, processedDir.bind(this))
    function onProcess(dir) {
      if (!dir.write) return callback(dir.name, false);
      analysis.putDir(this.target, dir.name, function () {
        callback && callback(dir.name, true)
      }.bind(this))
    }
    function processedDir(dir) {

      analysis.unlink('dir', this.target, dir.name, unlinked.bind(this))

      function unlinked() {
        this.emit('unlinked', dir.name)
      }
    }
  }
}

Freud.prototype.stop = function (cb) {
  this.listener && this.listener.close()
  this.emit('stopped')

  cb && cb()
}

function createFreud(source, destination, options) {
  return new Freud(source, destination, options)
}

<commit_msg>whoops<commit_after>var fs = require('fs'),
    events = require('events'),
    path = require('path'),
    analysis = require('./lib/analysis.js'),
    util = require('util')

exports.Freud = Freud
exports.createFreud = createFreud

function Freud(source, target, options) {
  if (!(this instanceof Freud)) return new Freud(source, target, options)

  this.source = path.normalize(source)
  this.target = path.normalize(target)
  this.processed = []
  this.rules = []
  this.options = options || {}
  this.listener = null
  this.version = require(path.join(__dirname, 'package.json')).version

  return this
}

util.inherits(Freud, events.EventEmitter)

Freud.prototype.doUnlink = function (filename) {
  var dummyFile = {
    name: filename,
    fullPath: path.join(this.source + filename),
    extension: filename.split('.').pop(),
    write: true,
    stats: undefined,
    data: ''
  }

  this.processFile(dummyFile, parseFile.bind(this))

  function parseFile(file) {
    analysis.unlink('file', this.target, file.name, checkUnlink.bind(this))

    function checkUnlink(err, didUnlink) {
      if (!err && didUnlink) return this.emit('unlinked', file.name);
      this.processDir(filename, checkDir.bind(this))

      function checkDir(dir) {
        analysis.unlink('dir', this.target, dir.name, checkDirUnlink.bind(this))

        function checkDirUnlink(err, didUnlink) {
          if (!err && didUnlink) this.emit('unlinked', dir.name);
        }
      }
    }
  }
}

Freud.prototype.recompile = function (filename) {
  var extension = filename.split('.').pop();
  if (this.rules[extension] || this.rules['*:before'] || this.rules['*:after']) {
    return this.compileFile(filename, recompileFile.bind(this))
  }
  fs.exists(path.join(this.target, filename), moveFile.bind(this))

  function moveFile(fileExists) {
    if (!fileExists) return this.copyFile(filename);
    fs.unlink(path.join(this.target, filename), function (err) {
      this.copyFile(filename);
    })
  }

  function recompileFile(filename, written) {
    this.emit('recompiled', filename);
    if (!written) this.emit('blocked', filename)
  }
}

Freud.prototype.listen = function (extension, callback) {
  if (!Array.isArray(extension)) extension = [extension]
  this.attachListeners(extension, callback)
}

Freud.prototype.checkStats = function (filename, callback) {
  analysis.getFile(this.source, filename, parseStats.bind(this))

  function parseStats(file) {
    if (file.stats === undefined) return callback(null, undefined);

    var theMTime = file.stats.mtime.getTime(),
        duplicate = this.processed[filename] && this.processed[filename] === theMTime
    this.processed[filename] = theMTime;
    callback(duplicate, file.stats);
  }
}

Freud.prototype.attachListeners = function (extensions, callback) {

  extensions.forEach(doAttach.bind(this))

  function doAttach(extension) {
    extension = extension === '*' ? '*:before' : extension
    extension = extension === '/*' ? '/*:before' : extension
    extension = this.options.ignoreCase ? extension.toLowerCase() : extension

    this.rules[extension] = this.rules[extension] || []
    this.rules[extension].push(callback)
    this.emit('extensionAdded', extension)
  }

}

Freud.prototype.go = function () {
  this.listener = fs.watch(this.source, { persistent: true }, this.eventResponse.bind(this))
  this.emit('started', this);
}

Freud.prototype.copyFile = function (filename) {
  this.emit('copying')
  fs.link(path.join(this.source, filename), path.join(this.target, filename), function () {
    this.emit('copied', filename)
  }.bind(this))
}
Freud.prototype.eventResponse = function (event, filename) {

  if (!filename) return this.emit('error', new Error('fs.watch error'))

  if ((!/^\./.test(filename) || this.options.monitorDot) && (!/~$/.test(filename) || this.options.monitorSquiggle)) {
    this.checkStats(filename, statResult.bind(this))
  }

  function statResult(isDuplicate, stats) {
    if (isDuplicate) return
    if (stats && stats.isDirectory()) {
      return this.compileDir(filename, fileCompiled.bind(this))
    }
    var extension = filename.split('.').pop()
    extension = this.options.ignoreCase ? extension.toLowerCase() : extension
    if (this.rules[extension] || this.rules['*:before'] || this.rules['*:after']) {
      return this.compileFile(filename, fileCompiled.bind(this))
    }
    fs.exists(path.join(this.source, filename), fileMove.bind(this))
  }

  function fileMove(linkFile) {
    this[linkFile ? 'copyFile' : 'doUnlink'](filename)
  }

  function fileCompiled(filename, written) {
    this.emit('compiled', filename)
    if (!written) this.emit('blocked', filename)
  }
}

Freud.prototype.processFile = function (file, callback) {
  var rules = [].concat(
      (this.rules['*:before'] || [])
      .concat(
      (this.rules[this.options.ignoreCase ? file.extension.toLowerCase() : file.extension] || [])
      .concat(
      (this.rules['*:after'] || []))
    ))
  if (!rules.length) return callback(file)
  analysis.executeRules(rules, file, callback)
}

Freud.prototype.processDir = function (dirname, callback) {

  var dir = { name: dirname, write: true },
      rules = [].concat(
          (this.rules['/*:before'] || [])
          .concat(
          (this.rules['/'] || [])
          .concat(
          (this.rules['/*:after'] ||[]))
        ))

  if (!rules.length) return callback(dir)
  analysis.executeRules(rules, dir, callback)
}

Freud.prototype.compileFile = function (filename, callback) {
  this.emit('compiling', filename)

  fs.exists(path.join(this.source, filename), checkFile.bind(this))

  function checkFile(inputFileExists) {
    if (!inputFileExists) return this.doUnlink(filename)
    analysis.getFile(this.source, filename, parseFile.bind(this))
    function parseFile(file) {
      this.processFile(file, putFile.bind(this))

      function putFile(file) {
        if (!file.write) return callback(file.name, false)

        analysis.putFile(this.target, file, function () {
          callback(file.name, true)
        }.bind(this))
      }
    }
  }
}

Freud.prototype.compileDir = function (filename, callback) {
  this.emit('compiling', filename)

  fs.exists(path.join(this.source, filename), checkDir.bind(this))
  function checkDir(inputDirExists) {
    if (inputDirExists) {
      return this.processDir(filename, onProcess.bind(this))
    }
    this.processDir(filename, processedDir.bind(this))
    function onProcess(dir) {
      if (!dir.write) return callback(dir.name, false);
      analysis.putDir(this.target, dir.name, function () {
        callback && callback(dir.name, true)
      }.bind(this))
    }
    function processedDir(dir) {

      analysis.unlink('dir', this.target, dir.name, unlinked.bind(this))

      function unlinked() {
        this.emit('unlinked', dir.name)
      }
    }
  }
}

Freud.prototype.stop = function (cb) {
  this.listener && this.listener.close()
  this.emit('stopped')

  cb && cb()
}

function createFreud(source, destination, options) {
  return new Freud(source, destination, options)
}

<|endoftext|>


<commit_before>function loadBookmarks(cb) {
  // Mock bookmarks
  var bookmarks = [
    {
        "title": "fxn/tkn - Terminal keynote presentation",
        "dateAdded": 1349313664591754,
        "lastModified": 1349313676308463,
        "description": "tkn - Terminal Keynote - A hack for terminal-based talks",
        "uri": "https://github.com/fxn/tkn"
    },
    {
        "title": "pedalboard.js - Open-source JavaScript framework for developing audio effects",
        "dateAdded": 1349417966733927,
        "lastModified": 1349417969037920,
        "description": "pedalboard.js - Open-source JavaScript framework for developing audio e",
        "uri": "http://dashersw.github.com/pedalboard.js/demo/"
    }
  ];

  // // Load in our bookmarks
  // $.getJSON('bookmarks.min.json', function (bookmarks, success, res) {
  //   // If we were unsuccessful, callback with an error
  //   if (success !== "success") {
  //     cb(new Error('Could not load bookmarks.'));
  //   } else {
  //   // Otherwise, callback with our bookmarks
      cb(null, bookmarks);
  //   }
  // });
}
window.loadBookmarks = loadBookmarks;<commit_msg>Removed mock bookmarks<commit_after>function loadBookmarks(cb) {
  // // Mock bookmarks
  // var bookmarks = [
  //   {
  //       "title": "fxn/tkn - Terminal keynote presentation",
  //       "dateAdded": 1349313664591754,
  //       "lastModified": 1349313676308463,
  //       "description": "tkn - Terminal Keynote - A hack for terminal-based talks",
  //       "uri": "https://github.com/fxn/tkn"
  //   },
  //   {
  //       "title": "pedalboard.js - Open-source JavaScript framework for developing audio effects",
  //       "dateAdded": 1349417966733927,
  //       "lastModified": 1349417969037920,
  //       "description": "pedalboard.js - Open-source JavaScript framework for developing audio e",
  //       "uri": "http://dashersw.github.com/pedalboard.js/demo/"
  //   }
  // ];

  // Load in our bookmarks
  $.getJSON('bookmarks.min.json', function (bookmarks, success, res) {
    // If we were unsuccessful, callback with an error
    if (success !== "success") {
      cb(new Error('Could not load bookmarks.'));
    } else {
    // Otherwise, callback with our bookmarks
      cb(null, bookmarks);
    }
  });
}
window.loadBookmarks = loadBookmarks;<|endoftext|>


<commit_before>NailPolish.GlobalPublisherAdder = function (args) {
  this.args = args;
};

_.extend(NailPolish.GlobalPublisherAdder.prototype, {
  perform: function () {
    this.args.complete = this.wrapComplete(this.args.complete);
    return this.args;
  },

  wrapComplete: function (callback) {
    return function(xhr, status) {
      // call the original callback
      if (callback) {
        callback(xhr, status);
      }

      // extract the JSON data

      response = xhr.response || xhr.responseText || "{}"
      var data = JSON.parse(response);
      var publisher = NailPolish.Events;

      // publish each event received
      _.each(data.events, function (value, key) {
        publisher.publish(key, value);
      });
    };
  }
});
<commit_msg>I will not forget semicolons anymore; I will not forget...<commit_after>NailPolish.GlobalPublisherAdder = function (args) {
  this.args = args;
};

_.extend(NailPolish.GlobalPublisherAdder.prototype, {
  perform: function () {
    this.args.complete = this.wrapComplete(this.args.complete);
    return this.args;
  },

  wrapComplete: function (callback) {
    return function(xhr, status) {
      // call the original callback
      if (callback) {
        callback(xhr, status);
      }

      // extract the JSON data

      response = xhr.response || xhr.responseText || "{}";
      var data = JSON.parse(response);
      var publisher = NailPolish.Events;

      // publish each event received
      _.each(data.events, function (value, key) {
        publisher.publish(key, value);
      });
    };
  }
});
<|endoftext|>


<commit_before>"use strict";

var dummy
  , hotplate = require('hotplate')

  , e = require('allhttperrors')

  , Schema = require('simpleschema')
  , MongoSchemaMixin = require('simpleschema/MongoSchemaMixin.js')

  , Store = require('jsonreststores')
  , MongoDriverMixin = require('jsonreststores/MongoDriverMixin.js')

  , declare = require('simpledeclare')

  , hotCoreStoreConfig = require( 'hotCoreStoreConfig' )
  , hotCoreStoreRegistry = require( 'hotCoreStoreRegistry' )

;

// Define store and mongo drivers.

var TABLIFESPAN = 16000;
var CLEANUPINTERVAL = 2000;

hotplate.hotEvents.on( 'stores', 'hotCoreComet', hotplate.cachable( function( done ){

  var stores = {};

  // This module only uses JsonRestStores as a way to access the DB,
  // it doesn't mixin with hotJsonRestStores

  // Get the DB classes
  var PermStore = declare( [ Store, MongoDriverMixin ],   { db: hotplate.config.get('hotplate.db') } );
  var PermSchema = declare( [ Schema, MongoSchemaMixin ], { db: hotplate.config.get('hotplate.db') } );

  // ***********************************
  // *** OPEN TABS   *******************
  // ***********************************

  stores.Tabs = declare( PermStore, {

    schema: new PermSchema({
      tabId:         { type: 'id' },
      userId:        { type: 'id' },
      lastSync:      { type: 'date', required: true, default: function(){ return new Date() } },
    }),

    searchSchema: new PermSchema({
      tabId:         { type: 'id' },
      userId:        { type: 'id' },
      lastSync:      { type: 'date' },

      // Ordering filters
      fromLastSync:  { type: 'date', filterType: { type: 'range', direction: 'from', field: 'lastSync' } },
      toLastSync:    { type: 'date', filterType: { type: 'range', direction: 'to', field: 'lastSync' }  },
    }),

    handlePost: true,
    handleDelete: true,

    storeName:  'tabs',
    paramIds: [ 'tabId' ],

    publicURL: '/tabs/',

    // TODO: Maybe I need an extra hook, this is not quite about permissions...
    checkPermissionsPost: function( params, body, options, cb ){
      var self = this;

      // It's a local request: always work, set null to userId
      if( ! self.remote) {
        body.userId = null;
        cb( null, true );

      // It's a remote request: fail if not logged in
      } else {
        if( ! self._req.session.userId ){
          cb( null, false );
        } else {
          body.userId = self._req.session.userId;
          cb( null, true );
        }
      }
    },

    // Delete ALL entries in TabMessages when a tab gets deleted
    afterDelete: function( params, body, options, doc, fullDoc, cb ){
      stores.TabMessages.MassDelete( { filters: { tabId: body.tabId } }, function( err ) {
        // TODO: Log err
      }  );
      cb( null );
    },

  });

  stores.TabMessages = declare( PermStore, {

    // COMMON
    schema: new PermSchema({
      messageId:     { type: 'id' },
      tabId:         { type: 'id' },
      fromUserId:    { type: 'id' },
      message:       { type: 'serialize' },
      added:         { type: 'date', required: true, default: function() { return new Date() } },
    }),

    // COMMON
    searchSchema: new PermSchema({
      messageId:     { type: 'id' },
      tabId:         { type: 'id' },
      fromUserId:    { type: 'id' },
      message:       { type: 'serialize' },
      added:         { type: 'date' },

      fromAdded:     { type: 'date', filterType: { type: 'range', direction: 'from', field: 'added' }  },
      toAdded:       { type: 'date', filterType: { type: 'range', direction: 'to', field: 'added' }  },
    }),

    storeName:  'tabMessages',
    paramIds: [ 'tabId', 'messageId' ],
    killComet: true,
  });

  // PSEUDO-STORE, sends an object out with all of the messages
  // It will return an array of unserialised messages in TabMessages for
  // a specific tabId, and then it will DELETE those messages
  stores.TabMessageDispatcher = declare( Store, {

    // COMMON
    schema: new PermSchema({
      tabId:         { type: 'string' },
      messages:      { type: 'none' },
    }),

    handleGet: true,

    handlePut: false,
    handlePost: false,
    handleGetQuery: false,
    handleDelete: false,

    storeName:  'tabMessageDispatcher',

    paramIds: [ 'tabId' ],

    publicURL: '/tabs/dispatcher/',

    killComet: true,

    // Check that the remote user requesting the tab is indeed the tab's owner
    checkPermissionsGet: function( params, body, options, doc, fullDoc, done ){

      var self = this;

      // User needs to be logged in
      if( ! self._req.session.userId ) return done( null, false );

      // TODO: Optimise a little here. Since checkPermissionsGet is called before driverAllDbFetch,
      // try and cache this result
      stores.Tabs.GetQuery( { filters: { fromLastSync: new Date() - TABLIFESPAN, tabId: params.tabId } }, function( err, tab ){
        if( err ){
          done( err );
        } else {

          // This may seem strange, but always pass authentication if the tab is not
          // there, as the store will need to accept the get and return the "storeReset"
          // message after returning the new tab
          if( tab.length == 0 ){
             done( null, true );

          } else {
            tab = tab[0];
            done( null, tab.userId.toString() === self._req.session.userId );
          }
        }
      });

    },

    driverAllDbFetch: function( params, body, options, done ){

      var messages = [];
      var self = this;

      // If it's not a remote call, always return empty result
      if( ! self.remote ) return done( null, { messages: [] } );

      var headersWorkspaceId = self._req.headers[ 'x-hotplate-workspaceid' ];

      // Return all messages for that tab, REMOVING after fetching
      stores.Tabs.GetQuery( { filters: { tabId: params.tabId, fromLastSync: new Date() - TABLIFESPAN } }, function( err, tab ){
        if( err ){
          done( err );
        } else {
          if( tab.length != 1 && tab.length != 0 ){
            done( new self.NotFoundError() );

          } else if( tab.length == 0 ){

            // At this point, the tab wasn't found. If workspaceId was passed via headers,
            // the person will be returned the configuration for that workspace. We need to check
            // that the user actually has access to that workspaceId.

            hotCoreStoreRegistry.getAllStores( function( err, storesData ){
              if( err ){
                done( err );
              } else {
                storesData.stores.userWorkspaces.Store.GetQuery( { filters: { userId: self._req.session.userId, workspaceId: headersWorkspaceId } }, function( err, uwDocs){
                  if( err ){
                    done( err );
                  } else {
                    if( uwDocs.length == 0 ){
                      done( new self.NotFoundError() );
                    } else {

                      stores.Tabs.Post( { userId: self._req.session.userId }, {}, function( err, tab ){
                        if( err ){
                           done( err );
                        } else {

                          hotCoreStoreConfig.getConfigRecords( headersWorkspaceId, self._req.session.userId, function( err, storeRecords ){
                            if( err ){
                              done( err );
                            } else {
                              done( null, { messages: [ { fromUserId: self._req.session.userId, message: { type: 'resetStores', tabId: tab.tabId, storeRecords: storeRecords } } ] } );
                            };
                          });

                        }
                      }); // Tabs.Post()

                    }
                  }
                });//UserWorkspaces.GetQuer ()
              }
            });

          } else {

            // Write the new access time onto the tab's record;
            tab = tab[ 0 ];
            tab.lastSync = new Date();
            stores.Tabs.Put( tab.tabId, tab, function( err, tab ){
              if( err ){
                done( err );
              } else {

                // Return all messages for that tab, REMOVING after fetching
                stores.TabMessages.GetQuery( { filters: { tabId: params.tabId, fromAdded: new Date() - TABLIFESPAN }, remove: true }, function( err, tabMessages ){
                  if( err ){
                    done( err );
                  } else {

                    tabMessages.forEach( function( tabMessage ){
                      delete tabMessage._id;
                      delete tabMessage.messageId;
                      delete tabMessage.tabId;

                      messages.push( tabMessage);
                    });
                    done( null, { messages: messages } );
                  }
                });
              }

            });

           }
        };
      });

    },

  });

  // done( null, stores );
  done( null,  [ stores.Tabs, stores.TabMessages, stores.TabMessageDispatcher ] );

}))

hotplate.hotEvents.on( 'run', hotplate.cachable( function( done ){

  hotCoreStoreRegistry.getAllStores( function( err, storesData ){
    if( err ){
      done( err );
    } else {
      // Clean up Tabs collection every 30 seconds, so that
      // dead tabs are gotten rid of
      var cleaningUp = false;
      setInterval( function(){
        if( cleaningUp ) return;
        cleaningUp = true;

        storesData.stores.tabs.Store.MassDelete( { filters: { toLastSync: new Date() - TABLIFESPAN } }, function ( err ){
          //TODO: Log error
          storesData.stores.tabMessages.Store.MassDelete( { filters: { toAdded: new Date() - TABLIFESPAN } }, function ( err ){
            // TODO: Log error
            cleaningUp = false;
          });
        });

      }, CLEANUPINTERVAL );
    }
  });

  done( null );
}));

hotplate.hotEvents.on('cometBroadcast', 'hotCoreComet', function( userId, tabId, makeTabIdHash, message, done ){

  var self = this;

  hotCoreStoreRegistry.getAllStores( function( err, storesData ){
    if( err ){
      done( err );
    } else {

      // makeTabId function wasn't passed: just use the stock "send it to all tabs" function
      if( ! makeTabIdHash ) makeTabIdHash = allTabIdHash;

      // Get the list of tab ids
      makeTabIdHash( userId, tabId, message, function( err, tabIdHash ){

        // For each open tab, add the message to its queue
        for( tabId in tabIdHash ){
          storesData.stores.tabMessages.Store.Post( { tabId: tabId, fromUserId: userId, message: message }, function( err ) {
            if( err ){
              // TODO: log err
            }
          } );
        };

        done( null );
      })
    }

  });

});

function allTabIdHash( userId, tabId, message, done ){

  hotCoreStoreRegistry.getAllStores( function( err, storesData ){
    if( err ){
      done( err );
    } else {

      var tabIdHash = {};

      // Just return all active tabs

      storesData.stores.tabs.Store.GetQuery( { filters: { fromLastSync: new Date() - TABLIFESPAN  }  }, function( err, docs ){
        if( err ){
          done( err );
        } else {
          docs.forEach( function( i ){
            if( i.tabId != tabId ) tabIdHash[ i.tabId ] = true;
          });
          done( null, tabIdHash );
        }
      });
    }
  });

}

<commit_msg>Saner store variable names, much more verbose logging, and much stricter security checks<commit_after>"use strict";

var dummy
  , hotplate = require('hotplate')

  , e = require('allhttperrors')

  , JsonRestStore = require('jsonreststores')
  , SimpleSchema = require('simpleschema')

  , declare = require('simpledeclare')

  , hotCoreStoreConfig = require( 'hotCoreStoreConfig' )
  , hotCoreStoreRegistry = require( 'hotCoreStoreRegistry' )

;

// Define store and mongo drivers.

var TABLIFESPAN = 30000;
var CLEANUPINTERVAL = 2000;

hotplate.hotEvents.on( 'stores', 'hotCoreComet', hotplate.cachable( function( done ){

  var stores = {};

  // This module only uses JsonRestStores as a way to access the DB,
  // it doesn't mixin with hotJsonRestStores

  // Get the DB classes
  var BasicDbStore = declare( [ JsonRestStore, hotplate.config.get( 'hotplate.DriverMixin' ) ], { db: hotplate.config.get('hotplate.db') } );
  var BasicDbSchema = declare( [ SimpleSchema, hotplate.config.get( 'hotplate.SchemaMixin' ) ], { db: hotplate.config.get('hotplate.db') } );

  // ***********************************
  // *** OPEN TABS   *******************
  // ***********************************

  stores.Tabs = declare( BasicDbStore, {

    schema: new BasicDbSchema({
      tabId:         { type: 'id', required: true },
      userId:        { type: 'id', required: true },
      lastSync:      { type: 'date', required: true, default: function(){ return new Date() } },
    }),

    searchSchema: new BasicDbSchema({
      tabId:         { type: 'id' },
      userId:        { type: 'id' },
      lastSync:      { type: 'date' },

      // Ordering filters
      fromLastSync:  { type: 'date', filterType: { type: 'range', direction: 'from', field: 'lastSync' } },
      toLastSync:    { type: 'date', filterType: { type: 'range', direction: 'to', field: 'lastSync' }  },
    }),

    handlePost: true,
    handleDelete: true,

    storeName:  'tabs',
    paramIds: [ 'tabId' ],

    publicURL: '/tabs/',

    prepareBodyPost: function( body, cb ){
      var self = this;
      if( self.remote ) {
        if( self._req.session.userId ){
          body.userId = self._req.session.userId;
        }
      }
      cb( null, body );
    },

    checkPermissionsPost: function( params, body, options, cb ){
      var self = this;
      cb( null, true );
    },

    // Delete ALL entries in TabMessages when a tab gets deleted
    afterDelete: function( params, body, options, doc, fullDoc, cb ){
      stores.TabMessages.MassDelete( { filters: { tabId: body.tabId } }, function( err ) {
        // TODO: Log err
      }  );
      cb( null );
    },

  });

  stores.TabMessages = declare( BasicDbStore, {

    // COMMON
    schema: new BasicDbSchema({
      messageId:     { type: 'id' },
      tabId:         { type: 'id' },
      fromUserId:    { type: 'id' },
      message:       { type: 'serialize' },
      added:         { type: 'date', required: true, default: function() { return new Date() } },
    }),

    // COMMON
    searchSchema: new BasicDbSchema({
      messageId:     { type: 'id' },
      tabId:         { type: 'id' },
      fromUserId:    { type: 'id' },
      message:       { type: 'serialize' },
      added:         { type: 'date' },

      fromAdded:     { type: 'date', filterType: { type: 'range', direction: 'from', field: 'added' }  },
      toAdded:       { type: 'date', filterType: { type: 'range', direction: 'to', field: 'added' }  },
    }),

    storeName:  'tabMessages',
    paramIds: [ 'tabId', 'messageId' ],
    killComet: true,
  });

  // PSEUDO-STORE, sends an object out with all of the messages
  // It will return an array of unserialised messages in TabMessages for
  // a specific tabId, and then it will DELETE those messages
  stores.TabMessageDispatcher = declare( JsonRestStore, {

    // COMMON
    schema: new BasicDbSchema({
      tabId:         { type: 'string' },
      messages:      { type: 'none' },
    }),

    handleGet: true,

    handlePut: false,
    handlePost: false,
    handleGetQuery: false,
    handleDelete: false,

    storeName:  'tabMessageDispatcher',

    paramIds: [ 'tabId' ],

    publicURL: '/tabs/dispatcher/',

    killComet: true,

    // Check that the remote user requesting the tab is indeed the tab's owner
    checkPermissionsGet: function( params, body, options, doc, fullDoc, done ){

      var self = this;

      // User needs to be logged in
      if( ! self._req.session.userId ) return done( null, false );

      // TODO: Optimise a little here. Since checkPermissionsGet is called before driverAllDbFetch,
      // try and cache this result
      stores.Tabs.GetQuery( { filters: { fromLastSync: new Date() - TABLIFESPAN, tabId: params.tabId } }, function( err, tab ){
        if( err ){
          done( err );
        } else {

          // This may seem strange, but always pass authentication if the tab is not
          // there, as the store will need to accept the get and return the "storeReset"
          // message after returning the new tab
          if( tab.length == 0 ){
             done( null, true );

          } else {
            tab = tab[0];
            done( null, tab.userId.toString() === self._req.session.userId );
          }
        }
      });

    },

    driverAllDbFetch: function( params, body, options, done ){

      var messages = [];
      var self = this;

      // If it's not a remote call, always return empty result
      if( ! self.remote ) return done( null, { messages: [] } );

      var headersWorkspaceId = self._req.headers[ 'x-hotplate-workspaceid' ];

      hotplate.log("Looking for tab %s owned by user %s, x-workspaceId is %s", params.tabId, self._req.session.userId, headersWorkspaceId );

      // Return all messages for that tab, REMOVING after fetching
      stores.Tabs.GetQuery( { filters: { tabId: params.tabId, userId: self._req.session.userId, fromLastSync: new Date() - TABLIFESPAN } }, function( err, tab ){
        if( err ){
          done( err );
        } else {

          hotplate.log("Returned:");
          hotplate.log( tab );
          if( tab.length == 0 ){

            hotplate.log("Tab was NOT present. Trying to understand if I should create one");
            // At this point, the tab wasn't found. If workspaceId was passed via headers,
            // the person will be returned the configuration for that workspace. We need to check
            // that the user actually has access to that workspaceId.

            hotCoreStoreRegistry.getAllStores( function( err, storesData ){
              if( err ){
                done( err );
              } else {
                hotplate.log("Checking that user has access to the workspaceId she is trying to register for");
                storesData.stores.userWorkspaces.Store.GetQuery( { filters: { userId: self._req.session.userId, workspaceId: headersWorkspaceId } }, function( err, uwDocs){
                  if( err ){
                    done( err );
                  } else {
                    if( uwDocs.length == 0 ){
                      hotplate.log("No access -- user needs to (re?)login!");
                      done( new self.UnauthorizedError() );
                    } else {

                      hotplate.log("OK, access is cleared, creating the tab for the user...");
                      hotplate.log( self._req.session.userId );
                      stores.Tabs.Post( { userId: self._req.session.userId }, {}, function( err, tab ){
                        if( err ){
                           done( err );
                        } else {

                          hotplate.log("...and ALSO returning the workspace configuration for that userId");
                          hotCoreStoreConfig.getConfigRecords( headersWorkspaceId, self._req.session.userId, function( err, storeRecords ){
                            if( err ){
                              done( err );
                            } else {
                              done( null, { messages: [ { fromUserId: self._req.session.userId, message: { type: 'resetStores', tabId: tab.tabId, storeRecords: storeRecords } } ] } );
                            };
                          });

                        }
                      }); // Tabs.Post()

                    }
                  }
                });//UserWorkspaces.GetQuer ()
              }
            });

          } else {

            // Write the new access time onto the tab's record;
            tab = tab[ 0 ];
            tab.lastSync = new Date();
            stores.Tabs.Put( tab.tabId, tab, function( err, tab ){
              if( err ){
                done( err );
              } else {

                // Return all messages for that tab, REMOVING after fetching
                stores.TabMessages.GetQuery( { filters: { tabId: params.tabId, fromAdded: new Date() - TABLIFESPAN }, remove: true }, function( err, tabMessages ){
                  if( err ){
                    done( err );
                  } else {

                    tabMessages.forEach( function( tabMessage ){
                      delete tabMessage._id;
                      delete tabMessage.messageId;
                      delete tabMessage.tabId;

                      messages.push( tabMessage);
                    });
                    done( null, { messages: messages } );
                  }
                });
              }

            });

           }
        };
      });

    },

  });

  // done( null, stores );
  done( null,  [ stores.Tabs, stores.TabMessages, stores.TabMessageDispatcher ] );

}))

hotplate.hotEvents.on( 'run', hotplate.cachable( function( done ){

  hotCoreStoreRegistry.getAllStores( function( err, storesData ){
    if( err ){
      done( err );
    } else {
      // Clean up Tabs collection every 30 seconds, so that
      // dead tabs are gotten rid of
      var cleaningUp = false;
      setInterval( function(){
        if( cleaningUp ) return;
        cleaningUp = true;

        storesData.stores.tabs.Store.MassDelete( { filters: { toLastSync: new Date() - TABLIFESPAN } }, function ( err ){
          //TODO: Log error
          storesData.stores.tabMessages.Store.MassDelete( { filters: { toAdded: new Date() - TABLIFESPAN } }, function ( err ){
            // TODO: Log error
            cleaningUp = false;
          });
        });

      }, CLEANUPINTERVAL );
    }
  });

  done( null );
}));

hotplate.hotEvents.on('cometBroadcast', 'hotCoreComet', function( userId, tabId, makeTabIdHash, message, done ){

  var self = this;

  hotCoreStoreRegistry.getAllStores( function( err, storesData ){
    if( err ){
      done( err );
    } else {

      // makeTabId function wasn't passed: just use the stock "send it to all tabs" function
      if( ! makeTabIdHash ) makeTabIdHash = allTabIdHash;

      // Get the list of tab ids
      makeTabIdHash( userId, tabId, message, function( err, tabIdHash ){

        // For each open tab, add the message to its queue
        for( tabId in tabIdHash ){
          storesData.stores.tabMessages.Store.Post( { tabId: tabId, fromUserId: userId, message: message }, function( err ) {
            if( err ){
              // TODO: log err
            }
          } );
        };

        done( null );
      })
    }

  });

});

function allTabIdHash( userId, tabId, message, done ){

  hotCoreStoreRegistry.getAllStores( function( err, storesData ){
    if( err ){
      done( err );
    } else {

      var tabIdHash = {};

      // Just return all active tabs

      storesData.stores.tabs.Store.GetQuery( { filters: { fromLastSync: new Date() - TABLIFESPAN  }  }, function( err, docs ){
        if( err ){
          done( err );
        } else {
          docs.forEach( function( i ){
            if( i.tabId != tabId ) tabIdHash[ i.tabId ] = true;
          });
          done( null, tabIdHash );
        }
      });
    }
  });

}

<|endoftext|>


<commit_before>'use strict';

const
  Promise = require('bluebird'),
  PluginImplementationError = require('kuzzle-common-objects').errors.PluginImplementationError,
  Request = require('kuzzle-common-objects').Request,
  RequestContext = require('kuzzle-common-objects').models.RequestContext,
  RequestInput = require('kuzzle-common-objects').models.RequestInput,
  PluginRepository = require('../models/repositories/pluginRepository'),
  InternalEngine = require('../../../services/internalEngine/index'),
  PluginInternalEngineBootstrap = require('../../../services/internalEngine/pluginBootstrap');

/**
 * @class PluginContext
 * @property {object} accessors
 * @property {KuzzleConfiguration} config
 * @property {object} constructors
 * @property {object} errors
 */
class PluginContext {
  /**
   * @param {Kuzzle} kuzzle
   * @param {string} pluginName
   * @constructor
   */
  constructor(kuzzle, pluginName) {
    // we have a circular dependency between Kuzzle and the plugins.
    // We cannot get Kuzzle constructor from the global scope
    const Kuzzle = require('../../kuzzle');
    let pluginInternalEngine;

    this.accessors = {};
    this.config = kuzzle.config;
    this.constructors = {
      Dsl: require('../../dsl'),
      Request: instantiateRequest,
      RequestContext,
      RequestInput,
      BaseValidationType: require('../validation/baseType')
    };
    this.errors = require('kuzzle-common-objects').errors;

    if (kuzzle instanceof Kuzzle) {
      pluginInternalEngine = new InternalEngine(kuzzle, `%${pluginName}`);
      pluginInternalEngine.init(new PluginInternalEngineBootstrap(kuzzle, pluginInternalEngine));

      Object.defineProperty(this, 'log', {
        enumerable: true,
        get: () => {
          return {
            silly: msg => kuzzle.pluginsManager.trigger('log:silly', msg),
            verbose: msg => kuzzle.pluginsManager.trigger('log:verbose', msg),
            info: msg => kuzzle.pluginsManager.trigger('log:info', msg),
            debug: msg => kuzzle.pluginsManager.trigger('log:debug', msg),
            warn: msg => kuzzle.pluginsManager.trigger('log:warn', msg),
            error: msg => kuzzle.pluginsManager.trigger('log:error', msg)
          };
        }
      });

      Object.defineProperty(this.accessors, 'registerStrategy', {
        enumerable: true,
        get: () => registerStrategy.bind(kuzzle)
      });

      Object.defineProperty(this.accessors, 'execute', {
        enumerable: true,
        get: () => execute.bind(kuzzle)
      });

      /*
       Sharing only a handful user functions as wrappers for the repositories object
       */
      Object.defineProperty(this.accessors, 'users', {
        enumerable: true,
        get: () => {
          return {
            load: userId => kuzzle.repositories.user.load(userId)
          };
        }
      });

      Object.defineProperty(this.accessors, 'validation', {
        enumerable: true,
        get: () => {
          return {
            addType: kuzzle.validation.addType.bind(kuzzle.validation),
            validate: kuzzle.validation.validationPromise.bind(kuzzle.validation)
          };
        }
      });

      Object.defineProperty(this.accessors, 'storage', {
        enumerable: true,
        get: () => {
          return {
            bootstrap: pluginInternalEngine.bootstrap.all.bind(pluginInternalEngine.bootstrap),
            createCollection: pluginInternalEngine.bootstrap.createCollection.bind(pluginInternalEngine.bootstrap),
          };
        }
      });

      /**
       * @param {string} collection
       * @param {?function} ObjectConstructor
       */
      this.constructors.Repository = function PluginContextRepository (collection, ObjectConstructor = null) {
        let pluginRepository;

        if (!collection) {
          throw new PluginImplementationError('The collection must be specified.');
        }

        pluginRepository = new PluginRepository(kuzzle, pluginName, collection);
        pluginRepository.init({databaseEngine: pluginInternalEngine, cacheEngine: null, ObjectConstructor});

        return {
          search: pluginRepository.search.bind(pluginRepository),
          get: pluginRepository.load.bind(pluginRepository),
          mGet: pluginRepository.loadMultiFromDatabase.bind(pluginRepository),
          delete: pluginRepository.delete.bind(pluginRepository),
          create: pluginRepository.create.bind(pluginRepository),
          createOrReplace: pluginRepository.createOrReplace.bind(pluginRepository),
          replace: pluginRepository.replace.bind(pluginRepository),
          update: pluginRepository.update.bind(pluginRepository),
        };
      };
    }
  }
}

/**
 * @this {Kuzzle}
 * @param {Request} request
 * @param {function} callback
 */
function execute (request, callback) {
  const kuzzle = this;

  return kuzzle.funnel.processRequest(request)
    .then(response => {
      if (callback) {
        try {
          callback(null, response);
        }
        catch (e) {
          kuzzle.pluginsManager.trigger('log:error', new PluginImplementationError(`Uncatched error by a plugin callback: ${e}`));
        }

        return;
      }

      return Promise.resolve(response);
    })
    .catch(err => {
      request.setError(err);
      kuzzle.funnel.handleErrorDump(err);

      if (callback) {
        try {
          callback(err, request);
        }
        catch (e) {
          kuzzle.pluginsManager.trigger('log:error', new PluginImplementationError(`Uncatched error by a plugin callback: ${e}`));
          kuzzle.pluginsManager.trigger('log:error', `Previous error: ${err}`);
        }
        return;
      }

      return Promise.reject(err);
    });
}

/**
 * Instantiates a new Request object, using the provided one
 * to set the context informations
 *
 * @throws
 * @param {Request} request
 * @param {Object} data
 * @param {Object} [options]
 * @return {Request}
 */
function instantiateRequest(request, data, options) {
  let target;

  if (!request || !(request instanceof Request)) {
    throw new PluginImplementationError('A Request object must be provided');
  }

  options = options || {};
  Object.assign(options, request.context.toJSON());

  target = new Request(data, options);
  target.origin = target.previous = request;

  // forward informations from the provided request object
  ['_id', 'index', 'collection'].forEach(resource => {
    if (!target.input.resource[resource]) {
      target.input.resource[resource] = request.input.resource[resource];
    }
  });

  Object.keys(request.input.args).forEach(arg => {
    if (!target.input.args[arg]) {
      target.input.args[arg] = request.input.args[arg];
    }
  });

  if (!target.input.jwt) {
    target.input.jwt = request.input.jwt;
  }

  return target;
}

/**
 * Registers an authentication strategy
 *
 * @this kuzzle
 * @param {function} Strategy - strategy constructor
 * @param {string} name - strategy name
 * @param {object} context - plugin context, used to bind the verify callback
 * @param {function} verify - verification callback
 * @param {object} [options] - strategy optional parameters
 */
function registerStrategy(Strategy, name, context, verify, options = {}) {
  const opts = Object.assign(options, {passReqToCallback: true});

  try {
    this.passport.use(name, new Strategy(opts, verify.bind(context)));
  }
  catch (e) {
    // There might not be any logger active when an authentication plugin registers its strategy
    // eslint-disable-next-line no-console
    console.error(new PluginImplementationError(`Unable to register authentication strategy: ${e.message}`));
  }
}

module.exports = PluginContext;
<commit_msg>755 Removed users accessor from pluginContext<commit_after>'use strict';

const
  Promise = require('bluebird'),
  PluginImplementationError = require('kuzzle-common-objects').errors.PluginImplementationError,
  Request = require('kuzzle-common-objects').Request,
  RequestContext = require('kuzzle-common-objects').models.RequestContext,
  RequestInput = require('kuzzle-common-objects').models.RequestInput,
  PluginRepository = require('../models/repositories/pluginRepository'),
  InternalEngine = require('../../../services/internalEngine/index'),
  PluginInternalEngineBootstrap = require('../../../services/internalEngine/pluginBootstrap');

/**
 * @class PluginContext
 * @property {object} accessors
 * @property {KuzzleConfiguration} config
 * @property {object} constructors
 * @property {object} errors
 */
class PluginContext {
  /**
   * @param {Kuzzle} kuzzle
   * @param {string} pluginName
   * @constructor
   */
  constructor(kuzzle, pluginName) {
    // we have a circular dependency between Kuzzle and the plugins.
    // We cannot get Kuzzle constructor from the global scope
    const Kuzzle = require('../../kuzzle');
    let pluginInternalEngine;

    this.accessors = {};
    this.config = kuzzle.config;
    this.constructors = {
      Dsl: require('../../dsl'),
      Request: instantiateRequest,
      RequestContext,
      RequestInput,
      BaseValidationType: require('../validation/baseType')
    };
    this.errors = require('kuzzle-common-objects').errors;

    if (kuzzle instanceof Kuzzle) {
      pluginInternalEngine = new InternalEngine(kuzzle, `%${pluginName}`);
      pluginInternalEngine.init(new PluginInternalEngineBootstrap(kuzzle, pluginInternalEngine));

      Object.defineProperty(this, 'log', {
        enumerable: true,
        get: () => {
          return {
            silly: msg => kuzzle.pluginsManager.trigger('log:silly', msg),
            verbose: msg => kuzzle.pluginsManager.trigger('log:verbose', msg),
            info: msg => kuzzle.pluginsManager.trigger('log:info', msg),
            debug: msg => kuzzle.pluginsManager.trigger('log:debug', msg),
            warn: msg => kuzzle.pluginsManager.trigger('log:warn', msg),
            error: msg => kuzzle.pluginsManager.trigger('log:error', msg)
          };
        }
      });

      Object.defineProperty(this.accessors, 'registerStrategy', {
        enumerable: true,
        get: () => registerStrategy.bind(kuzzle)
      });

      Object.defineProperty(this.accessors, 'execute', {
        enumerable: true,
        get: () => execute.bind(kuzzle)
      });

      Object.defineProperty(this.accessors, 'validation', {
        enumerable: true,
        get: () => {
          return {
            addType: kuzzle.validation.addType.bind(kuzzle.validation),
            validate: kuzzle.validation.validationPromise.bind(kuzzle.validation)
          };
        }
      });

      Object.defineProperty(this.accessors, 'storage', {
        enumerable: true,
        get: () => {
          return {
            bootstrap: pluginInternalEngine.bootstrap.all.bind(pluginInternalEngine.bootstrap),
            createCollection: pluginInternalEngine.bootstrap.createCollection.bind(pluginInternalEngine.bootstrap),
          };
        }
      });

      /**
       * @param {string} collection
       * @param {?function} ObjectConstructor
       */
      this.constructors.Repository = function PluginContextRepository (collection, ObjectConstructor = null) {
        let pluginRepository;

        if (!collection) {
          throw new PluginImplementationError('The collection must be specified.');
        }

        pluginRepository = new PluginRepository(kuzzle, pluginName, collection);
        pluginRepository.init({databaseEngine: pluginInternalEngine, cacheEngine: null, ObjectConstructor});

        return {
          search: pluginRepository.search.bind(pluginRepository),
          get: pluginRepository.load.bind(pluginRepository),
          mGet: pluginRepository.loadMultiFromDatabase.bind(pluginRepository),
          delete: pluginRepository.delete.bind(pluginRepository),
          create: pluginRepository.create.bind(pluginRepository),
          createOrReplace: pluginRepository.createOrReplace.bind(pluginRepository),
          replace: pluginRepository.replace.bind(pluginRepository),
          update: pluginRepository.update.bind(pluginRepository),
        };
      };
    }
  }
}

/**
 * @this {Kuzzle}
 * @param {Request} request
 * @param {function} callback
 */
function execute (request, callback) {
  const kuzzle = this;

  return kuzzle.funnel.processRequest(request)
    .then(response => {
      if (callback) {
        try {
          callback(null, response);
        }
        catch (e) {
          kuzzle.pluginsManager.trigger('log:error', new PluginImplementationError(`Uncatched error by a plugin callback: ${e}`));
        }

        return;
      }

      return Promise.resolve(response);
    })
    .catch(err => {
      request.setError(err);
      kuzzle.funnel.handleErrorDump(err);

      if (callback) {
        try {
          callback(err, request);
        }
        catch (e) {
          kuzzle.pluginsManager.trigger('log:error', new PluginImplementationError(`Uncatched error by a plugin callback: ${e}`));
          kuzzle.pluginsManager.trigger('log:error', `Previous error: ${err}`);
        }
        return;
      }

      return Promise.reject(err);
    });
}

/**
 * Instantiates a new Request object, using the provided one
 * to set the context informations
 *
 * @throws
 * @param {Request} request
 * @param {Object} data
 * @param {Object} [options]
 * @return {Request}
 */
function instantiateRequest(request, data, options) {
  let target;

  if (!request || !(request instanceof Request)) {
    throw new PluginImplementationError('A Request object must be provided');
  }

  options = options || {};
  Object.assign(options, request.context.toJSON());

  target = new Request(data, options);
  target.origin = target.previous = request;

  // forward informations from the provided request object
  ['_id', 'index', 'collection'].forEach(resource => {
    if (!target.input.resource[resource]) {
      target.input.resource[resource] = request.input.resource[resource];
    }
  });

  Object.keys(request.input.args).forEach(arg => {
    if (!target.input.args[arg]) {
      target.input.args[arg] = request.input.args[arg];
    }
  });

  if (!target.input.jwt) {
    target.input.jwt = request.input.jwt;
  }

  return target;
}

/**
 * Registers an authentication strategy
 *
 * @this kuzzle
 * @param {function} Strategy - strategy constructor
 * @param {string} name - strategy name
 * @param {object} context - plugin context, used to bind the verify callback
 * @param {function} verify - verification callback
 * @param {object} [options] - strategy optional parameters
 */
function registerStrategy(Strategy, name, context, verify, options = {}) {
  const opts = Object.assign(options, {passReqToCallback: true});

  try {
    this.passport.use(name, new Strategy(opts, verify.bind(context)));
  }
  catch (e) {
    // There might not be any logger active when an authentication plugin registers its strategy
    // eslint-disable-next-line no-console
    console.error(new PluginImplementationError(`Unable to register authentication strategy: ${e.message}`));
  }
}

module.exports = PluginContext;
<|endoftext|>


<commit_before>/**
 * Created by Ryan on 05 Mar 2015.
 */

//Define mpa layer variables
var map,BaseMap;
var BoC, NazBeth, BethEgypt, Temple, Nazareth, Bapt, Wedding, SoM, WoW, Geth, Calvary, Rez;

//Define the default map projection
var projection = ol.proj.get('EPSG:3857');

/**********************************************************/
/*                Begin map creation section              */
/**********************************************************/

function CreateMap() {

    //Build the layer objects for each KML file
    CreateLayers();

    //Declare the map object itself.
    map = new ol.Map({
        target: 'map',

        //Set up the layers that will be loaded in the map
        layers: [BaseMap, BoC],

        //Establish the view area. Note the reprojection from lat long (EPSG:4326) to Web Mercator (EPSG:3857)
        view: new ol.View({
            center: ol.proj.transform([35.2167, 31.7833], 'EPSG:4326', projection),
            zoom: 8
        })
    });

    //Add some useful map controls
    map.addControl(new ol.control.ScaleLine());

    //Add Popup system
    var element = document.getElementById('popup');

    var popup = new ol.Overlay({
        element: element,
        positioning: 'bottom-center',
        stopEvent: false
    });
    map.addOverlay(popup);

    return map

}

/**********************************************************/
/*                End map creation section                */
/**********************************************************/

/**********************************************************/
/*             Begin location selection function          */
/**********************************************************/
function LocationSelector(location)
{
    var zoom_area = map.getView();

    switch (location)
    {
        case "BoC":
            TurnAllLayersOff(map);
            BoC.setVisible(true);
            zoom_area.setCenter(BoC);
            zoom_area.setZoom(13)

    }
}
/**********************************************************/
/*             End location selection function            */
/**********************************************************/

/**********************************************************/
/*             Begin layer definition function            */
/**********************************************************/
function CreateLayers() {
    BaseMap = new ol.layer.Tile({
        source: new ol.source.MapQuest({layer: 'osm'})
    });

    BoC = new ol.layer.Vector({
        source: new ol.source.KML({
            projection: projection,
            url: 'data/kml/birthofchrist.kml'
        })
    })

}
/**********************************************************/
/*             End layer definition function              */
/**********************************************************/

/**********************************************************/
/*              Begin popup bubble scripting              */
/**********************************************************/

function PopUp_Bubble(evt) {

    //Add Popup system
    var element = document.getElementById('popup');

    var popup = new ol.Overlay({
        element: element,
        positioning: 'bottom-center',
        stopEvent: false
    });
    map.addOverlay(popup);

    // display popup on click

    //try to destroy it before doing anything else
    $(element).popover('destroy');

    //Try to get a feature at the point of interest
    var feature = map.forEachFeatureAtPixel(evt.pixel,
        function (feature, layer) {
            return feature;
        });

    //if we found a feature then create and show the popup.
    if (feature) {
        var geometry = feature.getGeometry();
        var coord = geometry.getCoordinates();
        popup.setPosition(coord);
        var displaycontent = ('' + feature.get('name') + '' + '
'
        + '
' + feature.get('description')
        );
        $(element).popover({
            'placement': 'top',
            'html': true,
            'content': displaycontent
        });

        $(element).popover('show');

    } else {
        $(element).popover('destroy');
    }

}

/**********************************************************/
/*               End popup bubble scripting               */
/**********************************************************/

/**********************************************************/
/*              Begin disable layers script               */
/**********************************************************/

function TurnAllLayersOff(map) {
    //turn all the layers in the map off
    var layers = map.getLayers().a;
    for (var i=1; i <= 16; i++) {
        layers[i].setVisible(false);
    }
}

/**********************************************************/
/*               End disable layers script                */
/**********************************************************/<commit_msg>Add UI controls<commit_after>/**
 * Created by Ryan on 05 Mar 2015.
 */

//Define mpa layer variables
var map,BaseMap;
var BoC, NazBeth, BethEgypt, Temple, Nazareth, Bapt, Wedding, SoM, WoW, Geth, Calvary, Rez;

//Define the default map projection
var projection = ol.proj.get('EPSG:3857');

/**********************************************************/
/*                Begin map creation section              */
/**********************************************************/

function CreateMap() {

    //Build the layer objects for each KML file
    CreateLayers();

    //Declare the map object itself.
    map = new ol.Map({
        target: 'map',

        //Set up the layers that will be loaded in the map
        layers: [BaseMap, BoC],

        //Establish the view area. Note the reprojection from lat long (EPSG:4326) to Web Mercator (EPSG:3857)
        view: new ol.View({
            center: ol.proj.transform([35.2167, 31.7833], 'EPSG:4326', projection),
            zoom: 8
        })
    });

    //Add some useful map controls
    map.addControl(new ol.control.ScaleLine());

    //Add Popup system
    var element = document.getElementById('popup');

    var popup = new ol.Overlay({
        element: element,
        positioning: 'bottom-center',
        stopEvent: false
    });
    map.addOverlay(popup);

    return map

}

/**********************************************************/
/*                End map creation section                */
/**********************************************************/

/**********************************************************/
/*             Begin location selection function          */
/**********************************************************/
function LocationSelector(location)
{
    var zoom_area = map.getView();

    switch (location)
    {
        case "BoC":
            TurnAllLayersOff();
            BoC.setVisible(true);
            zoom_area.setCenter(BoC);
            zoom_area.setZoom(13)

    }
}
/**********************************************************/
/*             End location selection function            */
/**********************************************************/

/**********************************************************/
/*             Begin layer definition function            */
/**********************************************************/
function CreateLayers() {
    BaseMap = new ol.layer.Tile({
        source: new ol.source.MapQuest({layer: 'osm'})
    });

    BoC = new ol.layer.Vector({
        source: new ol.source.KML({
            projection: projection,
            url: 'data/kml/birthofchrist.kml'
        })
    })

}
/**********************************************************/
/*             End layer definition function              */
/**********************************************************/

/**********************************************************/
/*              Begin popup bubble scripting              */
/**********************************************************/

function PopUp_Bubble(evt) {

    //Add Popup system
    var element = document.getElementById('popup');

    var popup = new ol.Overlay({
        element: element,
        positioning: 'bottom-center',
        stopEvent: false
    });
    map.addOverlay(popup);

    // display popup on click

    //try to destroy it before doing anything else
    $(element).popover('destroy');

    //Try to get a feature at the point of interest
    var feature = map.forEachFeatureAtPixel(evt.pixel,
        function (feature, layer) {
            return feature;
        });

    //if we found a feature then create and show the popup.
    if (feature) {
        var geometry = feature.getGeometry();
        var coord = geometry.getCoordinates();
        popup.setPosition(coord);
        var displaycontent = ('' + feature.get('name') + '' + '
'
        + '
' + feature.get('description')
        );
        $(element).popover({
            'placement': 'top',
            'html': true,
            'content': displaycontent
        });

        $(element).popover('show');

    } else {
        $(element).popover('destroy');
    }

}

/**********************************************************/
/*               End popup bubble scripting               */
/**********************************************************/

/**********************************************************/
/*              Begin disable layers script               */
/**********************************************************/

function TurnAllLayersOff() {
    //turn all the layers in the map off
    var layers = map.getLayers().a;
    for (var i=1; i <= 16; i++) {
        layers[i].setVisible(false);
    }
}

/**********************************************************/
/*               End disable layers script                */
/**********************************************************/<|endoftext|>


<commit_before>  /**
    @class

Matches documents with fields that have terms within a certain range.

    @name ejs.RangeFilter

    @desc
    Filters documents with fields that have terms within a certain range.

    @param {String} field A valid field name.
    */
  ejs.RangeFilter = function (field) {

    /**
         The internal filter object. Use get()
         @member ejs.RangeFilter
         @property {Object} filter
         */
    var filter = {
      range: {}
    };

    filter.range[field] = {};

    return {

      /**
             The field to run the filter against.

             @member ejs.RangeFilter
             @param {String} f A single field name.
             @returns {Object} returns this so that calls can be chained.
             */
      field: function (f) {
        var oldValue = filter.range[field];

        if (f == null) {
          return field;
        }

        field = f;
        filter.range = {};
        filter.range[f] = oldValue;

        return this;
      },

      /**
            The lower bound. Defaults to start from the first.

            @member ejs.RangeFilter
            @param {Variable Type} f the lower bound value, type depends on field type
            @returns {Object} returns this so that calls can be chained.
            */
      from: function (f) {
        if (f == null) {
          return filter.range[field].from;
        }

        filter.range[field].from = f;
        return this;
      },

      /**
            The upper bound. Defaults to unbounded.

            @member ejs.RangeFilter
            @param {Variable Type} t the upper bound value, type depends on field type
            @returns {Object} returns this so that calls can be chained.
            */
      to: function (t) {
        if (t == null) {
          return filter.range[field].to;
        }

        filter.range[field].to = t;
        return this;
      },

      /**
            Should the first from (if set) be inclusive or not.
            Defaults to true

            @member ejs.RangeFilter
            @param {Boolean} trueFalse true to include, false to exclude
            @returns {Object} returns this so that calls can be chained.
            */
      includeLower: function (trueFalse) {
        if (trueFalse == null) {
          return filter.range[field].include_lower;
        }

        filter.range[field].include_lower = trueFalse;
        return this;
      },

      /**
            Should the last to (if set) be inclusive or not. Defaults to true.

            @member ejs.RangeFilter
            @param {Boolean} trueFalse true to include, false to exclude
            @returns {Object} returns this so that calls can be chained.
            */
      includeUpper: function (trueFalse) {
        if (trueFalse == null) {
          return filter.range[field].include_upper;
        }

        filter.range[field].include_upper = trueFalse;
        return this;
      },

      /**
            Greater than value.  Same as setting from to the value, and
            include_lower to false,

            @member ejs.RangeFilter
            @param {Variable Type} val the value, type depends on field type
            @returns {Object} returns this so that calls can be chained.
            */
      gt: function (val) {
        if (val == null) {
          return filter.range[field].gt;
        }

        filter.range[field].gt = val;
        return this;
      },

      /**
            Greater than or equal to value.  Same as setting from to the value,
            and include_lower to true.

            @member ejs.RangeFilter
            @param {Variable Type} val the value, type depends on field type
            @returns {Object} returns this so that calls can be chained.
            */
      gte: function (val) {
        if (val == null) {
          return filter.range[field].gte;
        }

        filter.range[field].gte = val;
        return this;
      },

      /**
            Less than value.  Same as setting to to the value, and include_upper
            to false.

            @member ejs.RangeFilter
            @param {Variable Type} val the value, type depends on field type
            @returns {Object} returns this so that calls can be chained.
            */
      lt: function (val) {
        if (val == null) {
          return filter.range[field].lt;
        }

        filter.range[field].lt = val;
        return this;
      },

      /**
            Less than or equal to value.  Same as setting to to the value,
            and include_upper to true.

            @member ejs.RangeFilter
            @param {Variable Type} val the value, type depends on field type
            @returns {Object} returns this so that calls can be chained.
            */
      lte: function (val) {
        if (val == null) {
          return filter.range[field].lte;
        }

        filter.range[field].lte = val;
        return this;
      },

      /**
            Sets the filter name.

            @member ejs.RangeFilter
            @param {String} name A name for the filter.
            @returns {Object} returns this so that calls can be chained.
            */
      name: function (name) {
        if (name == null) {
          return filter.range._name;
        }

        filter.range._name = name;
        return this;
      },

      /**
            Enable or disable caching of the filter

            @member ejs.RangeFilter
            @param {Boolean} trueFalse True to cache the filter, false otherwise.
            @returns {Object} returns this so that calls can be chained.
            */
      cache: function (trueFalse) {
        if (trueFalse == null) {
          return filter.range._cache;
        }

        filter.range._cache = trueFalse;
        return this;
      },

      /**
            Sets the cache key.

            @member ejs.RangeFilter
            @param {String} key the cache key as a string.
            @returns {Object} returns this so that calls can be chained.
            */
      cacheKey: function (key) {
        if (key == null) {
          return filter.range._cache_key;
        }

        filter.range._cache_key = key;
        return this;
      },

      /**
            Allows you to serialize this object into a JSON encoded string.

            @member ejs.RangeFilter
            @returns {String} returns this object as a serialized JSON string.
            */
      toString: function () {
        return JSON.stringify(filter);
      },

      /**
            Retrieves the internal filter object. This is typically used by
            internal API functions so use with caution.

            @member ejs.RangeFilter
            @returns {String} returns this object's internal filter property.
            */
      get: function () {
        return filter;
      }
    };
  };
<commit_msg>Small fix in RangeFilter field code<commit_after>  /**
    @class

Matches documents with fields that have terms within a certain range.

    @name ejs.RangeFilter

    @desc
    Filters documents with fields that have terms within a certain range.

    @param {String} field A valid field name.
    */
  ejs.RangeFilter = function (field) {

    /**
         The internal filter object. Use get()
         @member ejs.RangeFilter
         @property {Object} filter
         */
    var filter = {
      range: {}
    };

    filter.range[field] = {};

    return {

      /**
             The field to run the filter against.

             @member ejs.RangeFilter
             @param {String} f A single field name.
             @returns {Object} returns this so that calls can be chained.
             */
      field: function (f) {
        var oldValue = filter.range[field];

        if (f == null) {
          return field;
        }

        delete filter.range[field];
        field = f;
        filter.range[f] = oldValue;

        return this;
      },

      /**
            The lower bound. Defaults to start from the first.

            @member ejs.RangeFilter
            @param {Variable Type} f the lower bound value, type depends on field type
            @returns {Object} returns this so that calls can be chained.
            */
      from: function (f) {
        if (f == null) {
          return filter.range[field].from;
        }

        filter.range[field].from = f;
        return this;
      },

      /**
            The upper bound. Defaults to unbounded.

            @member ejs.RangeFilter
            @param {Variable Type} t the upper bound value, type depends on field type
            @returns {Object} returns this so that calls can be chained.
            */
      to: function (t) {
        if (t == null) {
          return filter.range[field].to;
        }

        filter.range[field].to = t;
        return this;
      },

      /**
            Should the first from (if set) be inclusive or not.
            Defaults to true

            @member ejs.RangeFilter
            @param {Boolean} trueFalse true to include, false to exclude
            @returns {Object} returns this so that calls can be chained.
            */
      includeLower: function (trueFalse) {
        if (trueFalse == null) {
          return filter.range[field].include_lower;
        }

        filter.range[field].include_lower = trueFalse;
        return this;
      },

      /**
            Should the last to (if set) be inclusive or not. Defaults to true.

            @member ejs.RangeFilter
            @param {Boolean} trueFalse true to include, false to exclude
            @returns {Object} returns this so that calls can be chained.
            */
      includeUpper: function (trueFalse) {
        if (trueFalse == null) {
          return filter.range[field].include_upper;
        }

        filter.range[field].include_upper = trueFalse;
        return this;
      },

      /**
            Greater than value.  Same as setting from to the value, and
            include_lower to false,

            @member ejs.RangeFilter
            @param {Variable Type} val the value, type depends on field type
            @returns {Object} returns this so that calls can be chained.
            */
      gt: function (val) {
        if (val == null) {
          return filter.range[field].gt;
        }

        filter.range[field].gt = val;
        return this;
      },

      /**
            Greater than or equal to value.  Same as setting from to the value,
            and include_lower to true.

            @member ejs.RangeFilter
            @param {Variable Type} val the value, type depends on field type
            @returns {Object} returns this so that calls can be chained.
            */
      gte: function (val) {
        if (val == null) {
          return filter.range[field].gte;
        }

        filter.range[field].gte = val;
        return this;
      },

      /**
            Less than value.  Same as setting to to the value, and include_upper
            to false.

            @member ejs.RangeFilter
            @param {Variable Type} val the value, type depends on field type
            @returns {Object} returns this so that calls can be chained.
            */
      lt: function (val) {
        if (val == null) {
          return filter.range[field].lt;
        }

        filter.range[field].lt = val;
        return this;
      },

      /**
            Less than or equal to value.  Same as setting to to the value,
            and include_upper to true.

            @member ejs.RangeFilter
            @param {Variable Type} val the value, type depends on field type
            @returns {Object} returns this so that calls can be chained.
            */
      lte: function (val) {
        if (val == null) {
          return filter.range[field].lte;
        }

        filter.range[field].lte = val;
        return this;
      },

      /**
            Sets the filter name.

            @member ejs.RangeFilter
            @param {String} name A name for the filter.
            @returns {Object} returns this so that calls can be chained.
            */
      name: function (name) {
        if (name == null) {
          return filter.range._name;
        }

        filter.range._name = name;
        return this;
      },

      /**
            Enable or disable caching of the filter

            @member ejs.RangeFilter
            @param {Boolean} trueFalse True to cache the filter, false otherwise.
            @returns {Object} returns this so that calls can be chained.
            */
      cache: function (trueFalse) {
        if (trueFalse == null) {
          return filter.range._cache;
        }

        filter.range._cache = trueFalse;
        return this;
      },

      /**
            Sets the cache key.

            @member ejs.RangeFilter
            @param {String} key the cache key as a string.
            @returns {Object} returns this so that calls can be chained.
            */
      cacheKey: function (key) {
        if (key == null) {
          return filter.range._cache_key;
        }

        filter.range._cache_key = key;
        return this;
      },

      /**
            Allows you to serialize this object into a JSON encoded string.

            @member ejs.RangeFilter
            @returns {String} returns this object as a serialized JSON string.
            */
      toString: function () {
        return JSON.stringify(filter);
      },

      /**
            Retrieves the internal filter object. This is typically used by
            internal API functions so use with caution.

            @member ejs.RangeFilter
            @returns {String} returns this object's internal filter property.
            */
      get: function () {
        return filter;
      }
    };
  };
<|endoftext|>


<commit_before>/*
  Copyright 2016 Google Inc. All Rights Reserved.

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
*/

'use strict';

/* eslint-env worker, serviceworker */

importScripts('/sw-toolbox.js');
importScripts('/test/data/skip-and-claim.js');

self.toolbox.router.get('/test/helper/redirect', self.toolbox.networkFirst);
<commit_msg>Trying network only for both paths<commit_after>/*
  Copyright 2016 Google Inc. All Rights Reserved.

  Licensed under the Apache License, Version 2.0 (the "License");
  you may not use this file except in compliance with the License.
  You may obtain a copy of the License at

      http://www.apache.org/licenses/LICENSE-2.0

  Unless required by applicable law or agreed to in writing, software
  distributed under the License is distributed on an "AS IS" BASIS,
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  See the License for the specific language governing permissions and
  limitations under the License.
*/

'use strict';

/* eslint-env worker, serviceworker */

importScripts('/sw-toolbox.js');
importScripts('/test/data/skip-and-claim.js');

self.toolbox.router.get('/test/helper/redirect', self.toolbox.networkFirst);

self.toolbox.router.get('/test/helper/redirect/bounce', self.toolbox.networkFirst);
<|endoftext|>


<commit_before>export default function arrayDeepEquals(arr1, arr2) {
    // if the other arr1 is a falsy value, return
    if (!arr1 || !arr2)
        return false;

    // compare lengths - can save a lot of time
    if (arr1.length !== arr2.length)
        return false;

    for (var i = 0, l=arr1.length; i < l; i++) {
        // Check if we have nested arrays
        if (arr1[i] instanceof Array && arr2[i] instanceof Array) {
            // recurse into the nested arrays
            if (!deepEquals(arr1[i], arr2[i]))
                return false;
        }
        else if (arr1[i] !== arr2[i]) {
            // Warning - two different object instances will never be equal: {x:20} != {x:20}
            return false;
        }
    }
    return true;
}<commit_msg>fix: Fixed arrayDeepEquals<commit_after>import objectDeepEquals from './objectDeepEquals.js';

export default function arrayDeepEquals(arr1, arr2) {
    // if the other arr1 is a falsy value, return
    if (!arr1 || !arr2)
        return false;

    // compare lengths - can save a lot of time
    if (arr1.length !== arr2.length)
        return false;

    for (var i = 0, l=arr1.length; i < l; i++) {
        // Check if we have nested arrays
        if (arr1[i] instanceof Array && arr2[i] instanceof Array) {
            // recurse into the nested arrays
            if (!arrayDeepEquals(arr1[i], arr2[i]))
                return false;
        }
        else if (arr1[i] instanceof Object && arr2[i] instanceof Object) {
            // recurse into another objects
            if (!objectDeepEquals(arr1[i], arr2[i]))
                return false;
        }
        else if (arr1[i] !== arr2[i]) {
            // Warning - two different object instances will never be equal: {x:20} != {x:20}
            return false;
        }
    }
    return true;
}<|endoftext|>


<commit_before>'use strict';
/* globals Connector, BaseConnector, Reactor */

/**
 * This script is injected to the page after the {@link BaseConnector} and a custom
 * connector are already in place and set up
 *
 * As custom connectors should be declarative only without any actions triggered
 * on pageload, this starter is needed for connectors to start running
 */
(function () {
	// intentionally global lock to avoid multiple execution of this function
	if (window.STARTER_LOADED !== undefined) {
		console.warn('starter already loaded');
		return;
	}
	window.STARTER_LOADED = true;

	/**
	 * Warnings to help developers with their custom connectors
	 */
	if (typeof(Connector) == 'undefined' || !(Connector instanceof BaseConnector)) {
		console.warn('Web Scrobbler: You have overwritten or unset the Connector object!');
		return;
	}

	// observes state and communicates with background script
	var reactor = new Reactor(Connector);

	/**
	 * Set up Mutation observing as a default state change detection
	 */
	if (Connector.playerSelector !== null) {
		console.log('Web Scrobbler: Setting up observer');

		var observer = new window.MutationObserver(function () {
			if (Connector.isStateChangeAllowed()) {
				Connector.onStateChanged();
			}
		});

		var observeTarget = document.querySelector(Connector.playerSelector);
		var config = {
			childList: true,
			subtree: true,
			attributes: true,
			characterData: true
		};
		observer.observe(observeTarget, config);
	}
	/**
	 * Player selector is not provided, current connector needs to detect state changes on its own
	 */
	else {
		console.info('Web Scrobbler: Connector.playerSelector is empty. The current connector is expected to manually detect state changes');
	}

	/**
	 * Automatically reset on window unload
	 */
	$(window).unload(function() {
		reactor.sendStateToBackground({});
		return true;
	});

})();
<commit_msg>prevent missing player from firing JS error; closes #657<commit_after>'use strict';
/* globals Connector, BaseConnector, Reactor */

/**
 * This script is injected to the page after the {@link BaseConnector} and a custom
 * connector are already in place and set up
 *
 * As custom connectors should be declarative only without any actions triggered
 * on pageload, this starter is needed for connectors to start running
 */
(function () {
	// intentionally global lock to avoid multiple execution of this function
	if (window.STARTER_LOADED !== undefined) {
		console.warn('Web Scrobbler: Starter already loaded');
		return;
	}
	window.STARTER_LOADED = true;

	/**
	 * Warnings to help developers with their custom connectors
	 */
	if (typeof(Connector) == 'undefined' || !(Connector instanceof BaseConnector)) {
		console.warn('Web Scrobbler: You have overwritten or unset the Connector object!');
		return;
	}

	// observes state and communicates with background script
	var reactor = new Reactor(Connector);

	/**
	 * Set up Mutation observing as a default state change detection
	 */
	if (Connector.playerSelector !== null) {
		console.log('Web Scrobbler: Setting up observer');

		var observeTarget = document.querySelector(Connector.playerSelector);

		if (observeTarget != null) {
			var observer = new window.MutationObserver(function () {
				if (Connector.isStateChangeAllowed()) {
					Connector.onStateChanged();
				}
			});

			var config = {
				childList: true,
				subtree: true,
				attributes: true,
				characterData: true
			};
			observer.observe(observeTarget, config);
		}
		// Some pages (looking at you Google Music!) may do some crazy navigation API tricks before loading the final page,
		// in which case we won't usually find the player. Instead of letting the observer to fire an error we just
		// log it and hope that the next navigation event will trigger a new injection. Unload event is still hooked though.
		else {
			console.warn('Web Scrobbler: Player element (' + Connector.playerSelector + ') was not found in the page.');
		}
	}
	/**
	 * Player selector is not provided, current connector needs to detect state changes on its own
	 */
	else {
		console.info('Web Scrobbler: Connector.playerSelector is empty. The current connector is expected to manually detect state changes');
	}

	/**
	 * Automatically reset on window unload
	 */
	$(window).unload(function() {
		reactor.sendStateToBackground({});
		return true;
	});

})();
<|endoftext|>