<commit_before>/* Copyright (c) 2012-2015 The Tagspaces Authors. All rights reserved.
 * Use of this source code is governed by a AGPL3 license that
 * can be found in the LICENSE file. */
/* jshint moz: true, strict: false */
/* global exports */
// the value of this var is replaced to "true" by the build script
var PRODUCTION = "@@PRODUCTION";
var VERSION = "@@VERSION";
// Disabling all output to console in production mode
if (PRODUCTION == "true") {
  console = console || {}; // jshint ignore:line
  console.log = function() {};
  console.error = function() {};
}
// Import the needed APIs
var data = require('sdk/self').data; // self
var ioutils = require("ioutils");
var settings = require("settings");
var request = require("sdk/request"); // request
var tabs = require("sdk/tabs");
var unload = require('sdk/system/unload');
var Panel = require('sdk/panel').Panel;
var selection = require("sdk/selection");
var capture = require("capture");
//var userstyles = require("userstyles");
var {
  Cc, Ci, Cu
} = require('chrome');
var utils = require('sdk/window/utils');
//var os = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime).OS;
var workers = [];
var toolbarButton;
if (require("sdk/system").staticArgs.disableStrict) {
  require("sdk/preferences/service").set("javascript.options.strict", false);
}
exports.main = function(options, callbacks) {
  console.log("Load reason: " + options.loadReason);
  var mainUIMod = require("sdk/page-mod"); // page-mod
  mainUIMod.PageMod({
    include: data.url("index.html"),
    contentScript: '' +
      'self.on("message", function(message) {' +
      //            'console.log("Message received in content script from addon: "+JSON.stringify(message));'+
      'var event = document.createEvent("CustomEvent");' +
      'var cloned = cloneInto(message, document.defaultView);' +
      'event.initCustomEvent("tsMessage", true, true, cloned);' +
      'document.documentElement.dispatchEvent(event);' +
      '}); ' +
      'document.documentElement.addEventListener("addon-message", function(event) {' +
      //            'console.log("Message received from page script in content script "+JSON.stringify(event.detail));'+
      'self.postMessage(event.detail);' +
      '}, false);' +
      '',
    contentScriptWhen: 'end',
    onAttach: function onAttach(worker) {
      console.log("Attaching worker on tab with title: " + worker.tab.title);
      workers.push(worker);
      worker.on('message', function(data) {
        handleMessage(data, this);
      });
      worker.on('detach', function() {
        detachWorker(this);
      });
    }
  });
  // Adding menuitem to the tools menu
  var menuitem = require("menuitems").Menuitem({
    id: "TagSpacesMenuItem",
    menuid: "menu_ToolsPopup",
    label: "TagSpaces",
    // image: data.url("assets/icon16.png"),
    onCommand: openTagSpacesInNewTab,
    insertbefore: "menu_pageInfo"
  });
  // Adding toolbar button
  initToobarButton();
  if (options.loadReason == "install" || options.loadReason == "enable") {
    installToolbarButton();
  }
};

function installToolbarButton() {
//  if (typeof(toolbarButton.moveTo) === 'function') {
    toolbarButton.moveTo({
      toolbarID: "nav-bar",
      insertbefore: "home-button",
      forceMove: false
    });
//  }
}

function openTagSpacesInNewTab() {
  tabs.open({
    url: data.url("index.html"),
    //isPinned: true,
    isPrivate: true
  });
}

function initToobarButton() {
  // Toolbar icon with badge
  /*toolbarButton = require('toolbarbutton').ToolbarButton({
      id: "tagspaces",
      label: "TagSpaces",
      tooltiptext: "TagSpaces",
      onClick: openTagSpacesInNewTab
  });
  toolbarButton.badge = "1.8.6";

  // Loading style for the toolbar icon with badge
  userstyles.load(data.url("mozilla/overlay.css"));
  if (os == "Linux") {
      userstyles.load(data.url("mozilla/overlay-linux.css"));
  }
  else if (os == "Darwin") {
      userstyles.load(data.url("mozilla/overlay-darwin.css"));
  }*/
  var tagspacesPanel = new Panel({
    width: 530,
    height: 410,
    contentURL: data.url('mozilla/popup.html'),
    contentScriptFile: [
      data.url('libs/jquery/dist/jquery.min.js'),
      data.url('libs/select2/select2.min.js'),
      data.url('libs/dompurify/dist/purify.min.js'),
      data.url('mozilla/popup.js')
    ],
    onShow: function() {
      var contextExt = capture.getFileExt(tabs.activeTab.url.toString());
      tagspacesPanel.port.emit("show", selection.html,
          tabs.activeTab.title.toString(), contextExt);
    },
    onHide: function() {
      tagspacesPanel.port.emit("hide");
    }
  });

  tagspacesPanel.port.on('openNewTab', function(content) {
    tagspacesPanel.hide();
    openTagSpacesInNewTab();
  });

  tagspacesPanel.port.on('saveSelectionAsHtml', function(name, content) {
    tagspacesPanel.hide();
    capture.saveContentToFile(name, content);
  });

  tagspacesPanel.port.on('saveAsMHTML', function(name) {
    tagspacesPanel.hide();
    capture.saveURLToFile(name, tabs.activeTab.url.toString());
  });

  tagspacesPanel.port.on('saveScreenshot', function(name) {
    tagspacesPanel.hide();
    var screenCastData = capture.captureTab();
    var content = capture.dataURItoBlob(screenCastData);
    capture.saveContentToBinaryFile(name, content);
  });

  var handleChange = function (elem) {
    tagspacesPanel.show({
      position: toolbarButton
    });
  };

  var buttons = require('sdk/ui/button/action');
  toolbarButton = buttons.ActionButton({
    id: "TSToolbarButton",
    label: "TagSpaces",
    icon: {
      "32": data.url("assets/icon32.png"),
      "64": data.url("assets/icon64.png")
    },
    onClick: handleChange
  });
}

unload.when(function(reason) {
  // since FF24 reason is never 'uninstall' see https://bugzilla.mozilla.org/show_bug.cgi?id=571049
  if (reason === 'uninstall' || reason === 'disable') {
    // action by uninstall or disable
    let prompts = Cc["@mozilla.org/embedcomp/prompt-service;1"].getService(Ci.nsIPromptService);
    if (prompts.confirm(utils.getMostRecentBrowserWindow(), "Fill the uninstall survey", "Please fill the uninstall survey and tell us why are you removing TagSpaces. Your feedback could be very valuable for us! Would you like to fill it out?")) {
      tabs.open({
        url: "http://www.tagspaces.com/uninstallsurvey"
      });
    }
  }
});

exports.onUnload = function(reason) {
  console.log(reason);
};

function detachWorker(worker) {
  console.log("Detaching worker...");
  var index = workers.indexOf(worker);
  workers.splice(index, 1);
}

var checkForNewVersion = request.Request({
  url: "http://tagspaces.org/releases/version.json?fVer=" + VERSION,
  onComplete: function(response) {
    //    console.log("Result: " + response.text + " " + response.status);
    return response.text;
  }
});

function checkNewVersion(worker) {
  try {
    var content;
    var versionReq = request.Request({
      url: "http://tagspaces.org/releases/version.json?fVer=" + VERSION,
      onComplete: function(response) {
        console.log("Result: " + response.text + " " + response.status);
        response.text;
        worker.postMessage({
          "command": "checkNewVersion",
          "content": response.text,
          "success": true
        });
        console.log("Loading settings successful!");
      }
    }).get();
  } catch (ex) {
    worker.postMessage({
      "command": "checkNewVersion",
      "success": false
    });
    console.error("Checking new version failed " + ex);
  }
}

function handleMessage(msg, worker) {
  //console.log("Message in main.js: " + JSON.stringify(msg) + " from tab " + worker.tab.title);
  //console.log("Thumbnail: "+worker.tab.getThumbnail());
  switch (msg.detail.command) {
    case "loadSettings":
      settings.loadSettings(worker);
      break;
    case "checkNewVersion":
      checkNewVersion(worker);
      break;
    case "saveSettings":
      settings.saveSettings(msg.detail.content, worker);
      break;
    case "rename":
      ioutils.rename(msg.detail.path, msg.detail.newPath, worker);
      break;
    case "copy":
      ioutils.copy(msg.detail.path, msg.detail.newPath, worker);
      break;
    case "saveTextFile":
      ioutils.saveTextFile(msg.detail.path, msg.detail.content, worker,
          msg.detail.overwrite, msg.detail.silent);
      break;
    case "saveBinaryFile":
      ioutils.saveBinaryFile(msg.detail.path, msg.detail.content, worker,
          msg.detail.overwrite, msg.detail.silent);
      break;
    case "createDirectory":
      ioutils.createDirectory(msg.detail.path, worker, msg.detail.silent);
      break;
    case "loadTextFile":
      ioutils.loadTextFile(msg.detail.path, worker);
      break;
    case "listDirectory":
      ioutils.listDirectory(msg.detail.path, worker);
      break;
    case "delete":
      ioutils.deleteElement(msg.detail.path, worker);
      break;
    case "selectFile":
      ioutils.promptFileOpenPicker(worker);
      break;
    case "selectDirectory":
      ioutils.promptDirectorySelector(worker);
      break;
    case "openDirectory":
      ioutils.openDirectory(msg.detail.path, worker);
      break;
    case "createDirectoryIndex":
      ioutils.createDirectoryIndex(msg.detail.path, worker);
      break;
    case "createDirectoryTree":
      ioutils.createDirectoryTree(msg.detail.path, worker);
      break;
    case "getFileProperties":
      ioutils.getFileProperties(msg.detail.path, worker);
      break;
    case "getFileContent":
      ioutils.getFileContent(msg.detail.path, worker);
      break;
    default:
      break;
  }
}
<commit_msg>removing unneeded function<commit_after>/* Copyright (c) 2012-2015 The Tagspaces Authors. All rights reserved.
 * Use of this source code is governed by a AGPL3 license that
 * can be found in the LICENSE file. */
/* jshint moz: true, strict: false */
/* global exports */
// the value of this var is replaced to "true" by the build script
var PRODUCTION = "@@PRODUCTION";
var VERSION = "@@VERSION";
// Disabling all output to console in production mode
if (PRODUCTION == "true") {
  console = console || {}; // jshint ignore:line
  console.log = function() {};
  console.error = function() {};
}
// Import the needed APIs
var data = require('sdk/self').data; // self
var ioutils = require("ioutils");
var settings = require("settings");
var request = require("sdk/request"); // request
var tabs = require("sdk/tabs");
var unload = require('sdk/system/unload');
var Panel = require('sdk/panel').Panel;
var selection = require("sdk/selection");
var capture = require("capture");
//var userstyles = require("userstyles");
var {
  Cc, Ci, Cu
} = require('chrome');
var utils = require('sdk/window/utils');
//var os = Cc["@mozilla.org/xre/app-info;1"].getService(Ci.nsIXULRuntime).OS;
var workers = [];
var toolbarButton;
if (require("sdk/system").staticArgs.disableStrict) {
  require("sdk/preferences/service").set("javascript.options.strict", false);
}
exports.main = function(options, callbacks) {
  console.log("Load reason: " + options.loadReason);
  var mainUIMod = require("sdk/page-mod"); // page-mod
  mainUIMod.PageMod({
    include: data.url("index.html"),
    contentScript: '' +
      'self.on("message", function(message) {' +
      //            'console.log("Message received in content script from addon: "+JSON.stringify(message));'+
      'var event = document.createEvent("CustomEvent");' +
      'var cloned = cloneInto(message, document.defaultView);' +
      'event.initCustomEvent("tsMessage", true, true, cloned);' +
      'document.documentElement.dispatchEvent(event);' +
      '}); ' +
      'document.documentElement.addEventListener("addon-message", function(event) {' +
      //            'console.log("Message received from page script in content script "+JSON.stringify(event.detail));'+
      'self.postMessage(event.detail);' +
      '}, false);' +
      '',
    contentScriptWhen: 'end',
    onAttach: function onAttach(worker) {
      console.log("Attaching worker on tab with title: " + worker.tab.title);
      workers.push(worker);
      worker.on('message', function(data) {
        handleMessage(data, this);
      });
      worker.on('detach', function() {
        detachWorker(this);
      });
    }
  });
  // Adding menuitem to the tools menu
  var menuitem = require("menuitems").Menuitem({
    id: "TagSpacesMenuItem",
    menuid: "menu_ToolsPopup",
    label: "TagSpaces",
    // image: data.url("assets/icon16.png"),
    onCommand: openTagSpacesInNewTab,
    insertbefore: "menu_pageInfo"
  });
  // Adding toolbar button
  initToobarButton();
  if (options.loadReason == "install" || options.loadReason == "enable") {
    installToolbarButton();
  }
};

function installToolbarButton() {
//  if (typeof(toolbarButton.moveTo) === 'function') {
    toolbarButton.moveTo({
      toolbarID: "nav-bar",
      insertbefore: "home-button",
      forceMove: false
    });
//  }
}

function openTagSpacesInNewTab() {
  tabs.open({
    url: data.url("index.html"),
    //isPinned: true,
    isPrivate: true
  });
}

function initToobarButton() {
  // Toolbar icon with badge
  /*toolbarButton = require('toolbarbutton').ToolbarButton({
      id: "tagspaces",
      label: "TagSpaces",
      tooltiptext: "TagSpaces",
      onClick: openTagSpacesInNewTab
  });
  toolbarButton.badge = "1.8.6";

  // Loading style for the toolbar icon with badge
  userstyles.load(data.url("mozilla/overlay.css"));
  if (os == "Linux") {
      userstyles.load(data.url("mozilla/overlay-linux.css"));
  }
  else if (os == "Darwin") {
      userstyles.load(data.url("mozilla/overlay-darwin.css"));
  }*/
  var tagspacesPanel = new Panel({
    width: 530,
    height: 410,
    contentURL: data.url('mozilla/popup.html'),
    contentScriptFile: [
      data.url('libs/jquery/dist/jquery.min.js'),
      data.url('libs/select2/select2.min.js'),
      data.url('libs/dompurify/dist/purify.min.js'),
      data.url('mozilla/popup.js')
    ],
    onShow: function() {
      var contextExt = capture.getFileExt(tabs.activeTab.url.toString());
      tagspacesPanel.port.emit("show", selection.html,
          tabs.activeTab.title.toString(), contextExt);
    },
    onHide: function() {
      tagspacesPanel.port.emit("hide");
    }
  });

  tagspacesPanel.port.on('openNewTab', function(content) {
    tagspacesPanel.hide();
    openTagSpacesInNewTab();
  });

  tagspacesPanel.port.on('saveSelectionAsHtml', function(name, content) {
    tagspacesPanel.hide();
    capture.saveContentToFile(name, content);
  });

  tagspacesPanel.port.on('saveAsMHTML', function(name) {
    tagspacesPanel.hide();
    capture.saveURLToFile(name, tabs.activeTab.url.toString());
  });

  tagspacesPanel.port.on('saveScreenshot', function(name) {
    tagspacesPanel.hide();
    var screenCastData = capture.captureTab();
    var content = capture.dataURItoBlob(screenCastData);
    capture.saveContentToBinaryFile(name, content);
  });

  var handleChange = function (elem) {
    tagspacesPanel.show({
      position: toolbarButton
    });
  };

  var buttons = require('sdk/ui/button/action');
  toolbarButton = buttons.ActionButton({
    id: "TSToolbarButton",
    label: "TagSpaces",
    icon: {
      "32": data.url("assets/icon32.png"),
      "64": data.url("assets/icon64.png")
    },
    onClick: handleChange
  });
}

unload.when(function(reason) {
  // since FF24 reason is never 'uninstall' see https://bugzilla.mozilla.org/show_bug.cgi?id=571049
  if (reason === 'uninstall' || reason === 'disable') {
    // action by uninstall or disable
    let prompts = Cc["@mozilla.org/embedcomp/prompt-service;1"].getService(Ci.nsIPromptService);
    if (prompts.confirm(utils.getMostRecentBrowserWindow(), "Fill the uninstall survey", "Please fill the uninstall survey and tell us why are you removing TagSpaces. Your feedback could be very valuable for us! Would you like to fill it out?")) {
      tabs.open({
        url: "http://www.tagspaces.com/uninstallsurvey"
      });
    }
  }
});

exports.onUnload = function(reason) {
  console.log(reason);
};

function detachWorker(worker) {
  console.log("Detaching worker...");
  var index = workers.indexOf(worker);
  workers.splice(index, 1);
}

function checkNewVersion(worker) {
  try {
    var content;
    var versionReq = request.Request({
      url: "http://tagspaces.org/releases/version.json?fVer=" + VERSION,
      onComplete: function(response) {
        console.log("Result: " + response.text + " " + response.status);
        response.text;
        worker.postMessage({
          "command": "checkNewVersion",
          "content": response.text,
          "success": true
        });
        console.log("Loading settings successful!");
      }
    }).get();
  } catch (ex) {
    worker.postMessage({
      "command": "checkNewVersion",
      "success": false
    });
    console.error("Checking new version failed " + ex);
  }
}

function handleMessage(msg, worker) {
  //console.log("Message in main.js: " + JSON.stringify(msg) + " from tab " + worker.tab.title);
  //console.log("Thumbnail: "+worker.tab.getThumbnail());
  switch (msg.detail.command) {
    case "loadSettings":
      settings.loadSettings(worker);
      break;
    case "checkNewVersion":
      checkNewVersion(worker);
      break;
    case "saveSettings":
      settings.saveSettings(msg.detail.content, worker);
      break;
    case "rename":
      ioutils.rename(msg.detail.path, msg.detail.newPath, worker);
      break;
    case "copy":
      ioutils.copy(msg.detail.path, msg.detail.newPath, worker);
      break;
    case "saveTextFile":
      ioutils.saveTextFile(msg.detail.path, msg.detail.content, worker,
          msg.detail.overwrite, msg.detail.silent);
      break;
    case "saveBinaryFile":
      ioutils.saveBinaryFile(msg.detail.path, msg.detail.content, worker,
          msg.detail.overwrite, msg.detail.silent);
      break;
    case "createDirectory":
      ioutils.createDirectory(msg.detail.path, worker, msg.detail.silent);
      break;
    case "loadTextFile":
      ioutils.loadTextFile(msg.detail.path, worker);
      break;
    case "listDirectory":
      ioutils.listDirectory(msg.detail.path, worker);
      break;
    case "delete":
      ioutils.deleteElement(msg.detail.path, worker);
      break;
    case "selectFile":
      ioutils.promptFileOpenPicker(worker);
      break;
    case "selectDirectory":
      ioutils.promptDirectorySelector(worker);
      break;
    case "openDirectory":
      ioutils.openDirectory(msg.detail.path, worker);
      break;
    case "createDirectoryIndex":
      ioutils.createDirectoryIndex(msg.detail.path, worker);
      break;
    case "createDirectoryTree":
      ioutils.createDirectoryTree(msg.detail.path, worker);
      break;
    case "getFileProperties":
      ioutils.getFileProperties(msg.detail.path, worker);
      break;
    case "getFileContent":
      ioutils.getFileContent(msg.detail.path, worker);
      break;
    default:
      break;
  }
}
<|endoftext|>


<commit_before>require('proof')(3, require('cadence')(prove))

function prove (async, assert) {
    var UserAgent = require('../..')
    var Transport = require('../../mock')
    var responses = [
        function (request, response, next) {
            response.writeHead(200, 'ignore', { key: 'value' })
            response.end('foo')
            assert(response.getHeader('key'), 'value', 'get header')
            next()
        },
        function (request, response, next) {
            response.writeHead(200)
            response.end('foo')
            next()
        }
    ]
    var transport = new Transport(function (request, response, next) {
        responses.shift()(request, response, next)
    })
    var ua = new UserAgent({ transport: transport })
    async(function () {
        ua.fetch({ url: '/' }, async())
    }, function (body, response, buffer) {
        assert(response.headers, { key: 'value' }, 'headers')
        ua.fetch({ url: '/' }, async())
    }, function (body, response, buffer) {
        assert(response.headers, {}, 'no headers')
    })
}
<commit_msg>Fix `mock.t.js`.<commit_after>require('proof')(3, require('cadence')(prove))

function prove (async, assert) {
    var UserAgent = require('../..')
    var Transport = require('../../mock')
    var responses = [
        function (request, response, next) {
            response.writeHead(200, 'ignore', { key: 'value' })
            response.end('foo')
            assert(response.getHeader('key'), 'value', 'get header')
        },
        function (request, response, next) {
            response.writeHead(200)
            response.end('foo')
        }
    ]
    var transport = new Transport(function (request, response, next) {
        responses.shift()(request, response, next)
    })
    var ua = new UserAgent({ transport: transport })
    async(function () {
        ua.fetch({ url: '/' }, async())
    }, function (body, response, buffer) {
        assert(response.headers, { key: 'value' }, 'headers')
        ua.fetch({ url: '/' }, async())
    }, function (body, response, buffer) {
        assert(response.headers, {}, 'no headers')
    })
}
<|endoftext|>


<commit_before>import {Items} from './collections';
import {_} from 'meteor/underscore';
import {waitForHandleToBeReady, callWithPromise} from '../lib/sync_utils';
import { Random } from 'meteor/random';

describe('Optimistic UI', () => {
    it('Should not cause a flicker with method calls', async function (done) {
        const context = Random.id();

        const itemId = await callWithPromise('optimistic_ui.items.insert', {
            context,
            liked: ['YYY']
        });

        const handle = Meteor.subscribe('optimistic_ui.items', {_id: itemId});
        await waitForHandleToBeReady(handle);

        const cursor = Items.find({ _id: itemId });

        let alreadyIn = 0;
        const observer = cursor.observeChanges({
            changed(docId, doc) {
                alreadyIn++;
                if (alreadyIn > 1) {
                    done('A flicker was caused.');
                }

                assert.lengthOf(doc.liked, 2);
                assert.isTrue(_.contains(doc.liked, 'XXX'));

                setTimeout(() => {
                    handle.stop();
                    observer.stop();
                    done();
                }, 200);
            }
        });

        const item = _.first(cursor.fetch());
        assert.isObject(item);

        await callWithPromise('optimistic_ui.items.update', item._id, {
            $addToSet: {
                liked: 'XXX'
            }
        });
    });

    it('Should not cause a flicker with isomorphic calls', async function (done) {
        const context = Random.id();

        const itemId = Items.insert({
            context,
            liked: ['YYY']
        });

        const handle = Meteor.subscribe('optimistic_ui.items', {_id: itemId});
        await waitForHandleToBeReady(handle);

        const cursor = Items.find({_id: itemId});

        let alreadyIn = 0;
        const observer = cursor.observeChanges({
            changed(docId, doc) {
                console.log(docId, doc);

                alreadyIn++;
                if (alreadyIn > 1) {
                    done('A flicker was caused.');
                }

                assert.lengthOf(doc.liked, 2);
                assert.isTrue(_.contains(doc.liked, 'XXX'));

                setTimeout(() => {
                    handle.stop();
                    observer.stop();
                    done();
                }, 200);
            }
        });

        const item = _.first(cursor.fetch());
        assert.isObject(item);

        Items.update(item._id, {
            $addToSet: {
                liked: 'XXX'
            }
        });
    })
});<commit_msg>test cleanup<commit_after>import {Items} from './collections';
import {_} from 'meteor/underscore';
import {waitForHandleToBeReady, callWithPromise} from '../lib/sync_utils';
import { Random } from 'meteor/random';

describe('Optimistic UI', () => {
    it('Should not cause a flicker with method calls', async function (done) {
        const context = Random.id();

        const itemId = await callWithPromise('optimistic_ui.items.insert', {
            context,
            liked: ['YYY']
        });

        const handle = Meteor.subscribe('optimistic_ui.items', {_id: itemId});
        await waitForHandleToBeReady(handle);

        const cursor = Items.find({ _id: itemId });

        let alreadyIn = 0;
        const observer = cursor.observeChanges({
            changed(docId, doc) {
                alreadyIn++;
                if (alreadyIn > 1) {
                    done('A flicker was caused.');
                }

                assert.lengthOf(doc.liked, 2);
                assert.isTrue(_.contains(doc.liked, 'XXX'));

                setTimeout(() => {
                    handle.stop();
                    observer.stop();
                    done();
                }, 200);
            }
        });

        const item = _.first(cursor.fetch());
        assert.isObject(item);

        await callWithPromise('optimistic_ui.items.update', item._id, {
            $addToSet: {
                liked: 'XXX'
            }
        });
    });

    it('Should not cause a flicker with isomorphic calls', async function (done) {
        const context = Random.id();

        const itemId = Items.insert({
            context,
            liked: ['YYY']
        });

        const handle = Meteor.subscribe('optimistic_ui.items', {_id: itemId});
        await waitForHandleToBeReady(handle);

        const cursor = Items.find({_id: itemId});

        let alreadyIn = 0;
        const observer = cursor.observeChanges({
            changed(docId, doc) {
                alreadyIn++;
                if (alreadyIn > 1) {
                    done('A flicker was caused.');
                }

                assert.lengthOf(doc.liked, 2);
                assert.isTrue(_.contains(doc.liked, 'XXX'));

                setTimeout(() => {
                    handle.stop();
                    observer.stop();
                    done();
                }, 200);
            }
        });

        const item = _.first(cursor.fetch());
        assert.isObject(item);

        Items.update(item._id, {
            $addToSet: {
                liked: 'XXX'
            }
        });
    })
});<|endoftext|>


<commit_before><commit_msg>fixed possible erasing of inherited options.callbacks function-type properties on execution of options verification<commit_after><|endoftext|>


<commit_before>//
const execSync = require('child_process').execSync
const spawnSync = require('child_process').spawnSync
const chalk = require('chalk')
const ansiEscapes = require('ansi-escapes')
const debounce = require('lodash.debounce')
const gitFiles = require('git-files')
const keypress = require('terminal-keypress')
const jumper = require('terminal-jumper')

class Interactive {
	constructor() {
		this.fileIndex = 0
		this.showingIndicator = false
		this.showingDiff = false

		this.instructions = `${chalk.gray('Arrow keys to navigate')}\n${chalk.gray('Tab to show diff of selected file(s)')}`
		this.gitAddPrompt = `${chalk.green('Enter a file glob: ')}`

		this.onType = debounce(this.onType.bind(this), 200)
		this.onTab = this.onTab.bind(this)
		this.onArrow = this.onArrow.bind(this)
		this.exitBeforeAdd = this.exitBeforeAdd.bind(this)
		this.exitAfterAdd = this.exitAfterAdd.bind(this)

		keypress.init()
		keypress.on('exit', () => this.showCursor())
		keypress.on('exit', this.exitBeforeAdd)
	}

	run() {
		let stagedFiles = gitFiles.staged()

		if (stagedFiles.length > 0) {
			this.showAlreadyAddedFilesWarning(stagedFiles)
		} else {
			this.showGlobPrompt()
		}
	}

	showAlreadyAddedFilesWarning(stagedFiles) {
		jumper.block('There are file(s) already staged for commit.')
		for (let file of stagedFiles) {
			jumper.block(chalk.red(file))
		}
		jumper.break()
		jumper.block(chalk.bold('These file(s) will be committed. Continue? (y/n) '), 'warning')

		jumper.render()
		jumper.jumpTo('warning', -1)
		keypress.beginInput()

		keypress.once('return', () => {
			let answer = keypress.input()
			jumper.erase()

			if (['y', 'yes', 'Y', 'Yes'].includes(answer)) {
				jumper.reset()
				this.showGlobPrompt()
			} else if (['n', 'no', 'N', 'No'].includes(answer)) {
				keypress.exit()
			}
		})
	}

	showGlobPrompt() {
		// configure keypress
		keypress.color(letter => chalk.red(letter))
		keypress.disableBehavior('tab right left')

		// show prompt and available files
		jumper.block(this.instructions, 'instructions')
		jumper.break()
		jumper.block(this.gitAddPrompt, 'enter')
		jumper.break()
		jumper.block(chalk.green('Files found:'), 'found')
		this.renderFoundGitFiles()

		jumper.jumpTo('enter', -1)
		keypress.beginInput()

		keypress.on('keypress', this.onType)
		keypress.on('tab', this.onTab)
		keypress.on('arrow', this.onArrow)

		keypress.once('return', () => {
			this.showCursor()
			keypress.removeListener('keypress', this.onType)
			keypress.removeListener('tab', this.onTab)
			this.renderAddSuccess()
			this.startCommit()
		})
	}

	onType(char, key) {
		if (['left', 'right', 'up', 'down', 'tab', 'return'].includes(key.name)) {
			return
		}

		if (this.showingIndicator) {
			this.showCursor()
			this.fileIndex = 0
			this.showingIndicator = false
		}

		let glob = keypress.input()
		let coloredInput = keypress.input(true)
		jumper.find('enter').content(this.gitAddPrompt + coloredInput)

		this.renderFoundGitFiles(glob)
		jumper.jumpTo('enter', -1)
	}

	onTab() {
		if (this.showingDiff) {
			this.showOriginalScreen()
		} else {
			this.showAlternateScreen()
		}

		this.showingDiff = !this.showingDiff
	}

	onArrow(dir) {
		if (['left', 'right'].includes(dir)) {
			return
		}
		if (!this.showingIndicator && dir === 'up') {
			return
		}

		let numFiles = this.getGitFilesMatching(keypress.input()).length

		if (numFiles < 2) {
			return
		}

		// go to the correct file based on input direction
		if (!this.showingIndicator) {
			this.fileIndex = 0
			this.hideCursor()
		} else if (dir === 'up') {
			this.fileIndex -= 1
		} else if (dir === 'down') {
			this.fileIndex += 1
		}

		// return if the index is lower than 0 or greater than the number of files
		if (this.fileIndex < 0) {
			this.fileIndex = 0
			jumper.render()
			jumper.jumpTo('enter', -1)
			this.showCursor()
			this.showingIndicator = false
			return
		}
		if (this.fileIndex > numFiles - 1) {
			this.fileIndex = numFiles - 1
			return
		}

		// erase any previously printed indicators
		jumper.render()

		// write a file indicator on the current file line
		jumper.jumpTo(`gitFile${this.fileIndex}`, -1)
		process.stdout.write(ansiEscapes.cursorForward(2))
		process.stdout.write(chalk.blue('⇦'))

		this.showingIndicator = true
	}

	showCursor() {
		process.stdout.write(ansiEscapes.cursorShow)
	}

	hideCursor() {
		process.stdout.write(ansiEscapes.cursorHide)
	}

	getIndicatedFile() {
		let currentLine = jumper.find(`gitFile${this.fileIndex}`).escapedText
		return currentLine.trim().split(' ')[1]
	}

	showOriginalScreen() {
		// remove scrollback so that scrolling up on the original screen doesn't show the diff
		process.stdout.write(execSync("clear && printf \'\\e[3J\'", { encoding: 'utf8' }))
		// switch to original screen
		spawnSync('tput', ['rmcup'], { stdio: 'inherit' })

		jumper.jumpTo('enter', -1)
		keypress.enable()
	}

	showAlternateScreen() {
		// prevent rendering on each keypress
		keypress.disable()

		// if the indicator is showing, grab the diff for the chosen file.
		// otherwise, grab the diff for the current glob entry
		let diff
		if (this.showingIndicator) {
			let file = this.getIndicatedFile()
			diff = execSync(`git -c color.ui=always diff ${file}`).toString('utf8')
		} else {
			let files = this.getGitFilesMatching(keypress.input())

			// grab the diff of each file that matches the input glob
			diff = ''
			for (let file of files) {
				diff += execSync(`git -c color.ui=always diff ${file}`).toString('utf8')
			}
		}

		// show diff on alternate screen
		spawnSync('tput', ['smcup'], { stdio: 'inherit' })
		jumper.cursorTo(0, 0)
		console.log(diff)

		// make sure to enable a second tab after disabling all events
		keypress.once('tab', this.onTab)
	}

	renderAddSuccess() {
		// if the indicator is showing, only add that specific file.
		// otherwise, add all files matching the given glob
		if (this.showingIndicator) {
			this.addFiles = [this.getIndicatedFile()]
		} else {
			let glob = keypress.input()
			this.addFiles = this.getGitFilesMatching(glob)
		}

		jumper.reset()

		jumper.block(chalk.green('Added files:'), 'found')
		for (let i = 0; i < this.addFiles.length; i++) {
			let file = this.addFiles[i]
			let id = `addedFile${i}`
			jumper.block(`${chalk.red(file)}  ${chalk.green('✓')}`, id)
		}
		jumper.break()
		jumper.block('---------------------------------------------')
		jumper.break()
		jumper.block(chalk.green('Enter commit message: "'), 'commit')
		jumper.render()

		jumper.jumpTo('commit', -1)
		process.stdout.write(chalk.green('"'))
		jumper.jumpTo('commit', -1)
	}

	startCommit() {
		keypress.color(letter => chalk.green(letter))
		keypress.beginInput()

		let onKeypress = () => {
			process.stdout.write(`${chalk.green('"')}`)
			process.stdout.write(ansiEscapes.cursorBackward(1))
		}
		keypress.on('keypress', onKeypress)

		keypress.once('return', () => {
			keypress.removeListener('keypress', onKeypress)
			this.commitMessage = keypress.input()

			let content = jumper.find('commit').text
			content = `${content}${keypress.input(true)}${chalk.green('"')}`
			jumper.find('commit').content(content)
			this.commit()
			this.complete()
		})

		keypress.removeListener('exit', this.exitBeforeAdd)
		keypress.on('exit', this.exitAfterAdd)
	}

	commit() {
		for (let file of this.addFiles) {
			execSync(`git add ${file}`)
		}
		execSync(`git commit -m "${this.commitMessage}"`)

		keypress.removeListener('exit', this.exitAfterAdd)
	}

	complete() {
		jumper.break()
		jumper.block('---------------------------------------------')
		jumper.break()
		jumper.block('Files committed successfully.')
		jumper.render()

		keypress.exit()
	}

	renderFoundGitFiles(glob = '') {
		// remove previous search
		jumper.removeAllMatching(/gitFile\d+/)

		let allMatches = {
			untracked: gitFiles.untracked('relative').filter(file => new RegExp(glob, 'i').test(file)),
			modified: gitFiles.modified('relative').filter(file => new RegExp(glob, 'i').test(file)),
			deleted: gitFiles.deleted('relative').filter(file => new RegExp(glob, 'i').test(file))
		}

		let counter = 0

		for (let group of Object.keys(allMatches)) {
			for (let file of allMatches[group]) {
				let text = `  ${chalk.bold.gray(`(${group})`)} ${chalk.red(file)}`
				jumper.block(text, `gitFile${counter}`)
				counter += 1
			}
		}
		jumper.render()
	}

	getGitFilesMatching(glob) {
		let files = gitFiles.all('relative').sort()
		let regex = new RegExp(glob, 'i')
		return files.filter(file => regex.test(file))
	}

	exitBeforeAdd() {
		jumper.erase()
	}

	exitAfterAdd() {
		process.stdout.write(ansiEscapes.cursorSavePosition)

		for (let i = 0; i < this.addFiles.length; i++) {
			let id = `addedFile${i}`
			jumper.jumpTo(id, -2)
			process.stdout.write(chalk.red('✗'))
		}

		process.stdout.write(ansiEscapes.cursorRestorePosition)
		console.log()
		console.log()
		console.log('Aborting -- no files added.')
	}
}

module.exports = Interactive
<commit_msg>Remove extra line<commit_after>const execSync = require('child_process').execSync
const spawnSync = require('child_process').spawnSync
const chalk = require('chalk')
const ansiEscapes = require('ansi-escapes')
const debounce = require('lodash.debounce')
const gitFiles = require('git-files')
const keypress = require('terminal-keypress')
const jumper = require('terminal-jumper')

class Interactive {
	constructor() {
		this.fileIndex = 0
		this.showingIndicator = false
		this.showingDiff = false

		this.instructions = `${chalk.gray('Arrow keys to navigate')}\n${chalk.gray('Tab to show diff of selected file(s)')}`
		this.gitAddPrompt = `${chalk.green('Enter a file glob: ')}`

		this.onType = debounce(this.onType.bind(this), 200)
		this.onTab = this.onTab.bind(this)
		this.onArrow = this.onArrow.bind(this)
		this.exitBeforeAdd = this.exitBeforeAdd.bind(this)
		this.exitAfterAdd = this.exitAfterAdd.bind(this)

		keypress.init()
		keypress.on('exit', () => this.showCursor())
		keypress.on('exit', this.exitBeforeAdd)
	}

	run() {
		let stagedFiles = gitFiles.staged()

		if (stagedFiles.length > 0) {
			this.showAlreadyAddedFilesWarning(stagedFiles)
		} else {
			this.showGlobPrompt()
		}
	}

	showAlreadyAddedFilesWarning(stagedFiles) {
		jumper.block('There are file(s) already staged for commit.')
		for (let file of stagedFiles) {
			jumper.block(chalk.red(file))
		}
		jumper.break()
		jumper.block(chalk.bold('These file(s) will be committed. Continue? (y/n) '), 'warning')

		jumper.render()
		jumper.jumpTo('warning', -1)
		keypress.beginInput()

		keypress.once('return', () => {
			let answer = keypress.input()
			jumper.erase()

			if (['y', 'yes', 'Y', 'Yes'].includes(answer)) {
				jumper.reset()
				this.showGlobPrompt()
			} else if (['n', 'no', 'N', 'No'].includes(answer)) {
				keypress.exit()
			}
		})
	}

	showGlobPrompt() {
		// configure keypress
		keypress.color(letter => chalk.red(letter))
		keypress.disableBehavior('tab right left')

		// show prompt and available files
		jumper.block(this.instructions, 'instructions')
		jumper.break()
		jumper.block(this.gitAddPrompt, 'enter')
		jumper.break()
		jumper.block(chalk.green('Files found:'), 'found')
		this.renderFoundGitFiles()

		jumper.jumpTo('enter', -1)
		keypress.beginInput()

		keypress.on('keypress', this.onType)
		keypress.on('tab', this.onTab)
		keypress.on('arrow', this.onArrow)

		keypress.once('return', () => {
			this.showCursor()
			keypress.removeListener('keypress', this.onType)
			keypress.removeListener('tab', this.onTab)
			this.renderAddSuccess()
			this.startCommit()
		})
	}

	onType(char, key) {
		if (['left', 'right', 'up', 'down', 'tab', 'return'].includes(key.name)) {
			return
		}

		if (this.showingIndicator) {
			this.showCursor()
			this.fileIndex = 0
			this.showingIndicator = false
		}

		let glob = keypress.input()
		let coloredInput = keypress.input(true)
		jumper.find('enter').content(this.gitAddPrompt + coloredInput)

		this.renderFoundGitFiles(glob)
		jumper.jumpTo('enter', -1)
	}

	onTab() {
		if (this.showingDiff) {
			this.showOriginalScreen()
		} else {
			this.showAlternateScreen()
		}

		this.showingDiff = !this.showingDiff
	}

	onArrow(dir) {
		if (['left', 'right'].includes(dir)) {
			return
		}
		if (!this.showingIndicator && dir === 'up') {
			return
		}

		let numFiles = this.getGitFilesMatching(keypress.input()).length

		if (numFiles < 2) {
			return
		}

		// go to the correct file based on input direction
		if (!this.showingIndicator) {
			this.fileIndex = 0
			this.hideCursor()
		} else if (dir === 'up') {
			this.fileIndex -= 1
		} else if (dir === 'down') {
			this.fileIndex += 1
		}

		// return if the index is lower than 0 or greater than the number of files
		if (this.fileIndex < 0) {
			this.fileIndex = 0
			jumper.render()
			jumper.jumpTo('enter', -1)
			this.showCursor()
			this.showingIndicator = false
			return
		}
		if (this.fileIndex > numFiles - 1) {
			this.fileIndex = numFiles - 1
			return
		}

		// erase any previously printed indicators
		jumper.render()

		// write a file indicator on the current file line
		jumper.jumpTo(`gitFile${this.fileIndex}`, -1)
		process.stdout.write(ansiEscapes.cursorForward(2))
		process.stdout.write(chalk.blue('⇦'))

		this.showingIndicator = true
	}

	showCursor() {
		process.stdout.write(ansiEscapes.cursorShow)
	}

	hideCursor() {
		process.stdout.write(ansiEscapes.cursorHide)
	}

	getIndicatedFile() {
		let currentLine = jumper.find(`gitFile${this.fileIndex}`).escapedText
		return currentLine.trim().split(' ')[1]
	}

	showOriginalScreen() {
		// remove scrollback so that scrolling up on the original screen doesn't show the diff
		process.stdout.write(execSync("clear && printf \'\\e[3J\'", { encoding: 'utf8' }))
		// switch to original screen
		spawnSync('tput', ['rmcup'], { stdio: 'inherit' })

		jumper.jumpTo('enter', -1)
		keypress.enable()
	}

	showAlternateScreen() {
		// prevent rendering on each keypress
		keypress.disable()

		// if the indicator is showing, grab the diff for the chosen file.
		// otherwise, grab the diff for the current glob entry
		let diff
		if (this.showingIndicator) {
			let file = this.getIndicatedFile()
			diff = execSync(`git -c color.ui=always diff ${file}`).toString('utf8')
		} else {
			let files = this.getGitFilesMatching(keypress.input())

			// grab the diff of each file that matches the input glob
			diff = ''
			for (let file of files) {
				diff += execSync(`git -c color.ui=always diff ${file}`).toString('utf8')
			}
		}

		// show diff on alternate screen
		spawnSync('tput', ['smcup'], { stdio: 'inherit' })
		jumper.cursorTo(0, 0)
		console.log(diff)

		// make sure to enable a second tab after disabling all events
		keypress.once('tab', this.onTab)
	}

	renderAddSuccess() {
		// if the indicator is showing, only add that specific file.
		// otherwise, add all files matching the given glob
		if (this.showingIndicator) {
			this.addFiles = [this.getIndicatedFile()]
		} else {
			let glob = keypress.input()
			this.addFiles = this.getGitFilesMatching(glob)
		}

		jumper.reset()

		jumper.block(chalk.green('Added files:'), 'found')
		for (let i = 0; i < this.addFiles.length; i++) {
			let file = this.addFiles[i]
			let id = `addedFile${i}`
			jumper.block(`${chalk.red(file)}  ${chalk.green('✓')}`, id)
		}
		jumper.break()
		jumper.block('---------------------------------------------')
		jumper.break()
		jumper.block(chalk.green('Enter commit message: "'), 'commit')
		jumper.render()

		jumper.jumpTo('commit', -1)
		process.stdout.write(chalk.green('"'))
		jumper.jumpTo('commit', -1)
	}

	startCommit() {
		keypress.color(letter => chalk.green(letter))
		keypress.beginInput()

		let onKeypress = () => {
			process.stdout.write(`${chalk.green('"')}`)
			process.stdout.write(ansiEscapes.cursorBackward(1))
		}
		keypress.on('keypress', onKeypress)

		keypress.once('return', () => {
			keypress.removeListener('keypress', onKeypress)
			this.commitMessage = keypress.input()

			let content = jumper.find('commit').text
			content = `${content}${keypress.input(true)}${chalk.green('"')}`
			jumper.find('commit').content(content)
			this.commit()
			this.complete()
		})

		keypress.removeListener('exit', this.exitBeforeAdd)
		keypress.on('exit', this.exitAfterAdd)
	}

	commit() {
		for (let file of this.addFiles) {
			execSync(`git add ${file}`)
		}
		execSync(`git commit -m "${this.commitMessage}"`)

		keypress.removeListener('exit', this.exitAfterAdd)
	}

	complete() {
		jumper.break()
		jumper.block('---------------------------------------------')
		jumper.break()
		jumper.block('Files committed successfully.')
		jumper.render()

		keypress.exit()
	}

	renderFoundGitFiles(glob = '') {
		// remove previous search
		jumper.removeAllMatching(/gitFile\d+/)

		let allMatches = {
			untracked: gitFiles.untracked('relative').filter(file => new RegExp(glob, 'i').test(file)),
			modified: gitFiles.modified('relative').filter(file => new RegExp(glob, 'i').test(file)),
			deleted: gitFiles.deleted('relative').filter(file => new RegExp(glob, 'i').test(file))
		}

		let counter = 0

		for (let group of Object.keys(allMatches)) {
			for (let file of allMatches[group]) {
				let text = `  ${chalk.bold.gray(`(${group})`)} ${chalk.red(file)}`
				jumper.block(text, `gitFile${counter}`)
				counter += 1
			}
		}
		jumper.render()
	}

	getGitFilesMatching(glob) {
		let files = gitFiles.all('relative').sort()
		let regex = new RegExp(glob, 'i')
		return files.filter(file => regex.test(file))
	}

	exitBeforeAdd() {
		jumper.erase()
	}

	exitAfterAdd() {
		process.stdout.write(ansiEscapes.cursorSavePosition)

		for (let i = 0; i < this.addFiles.length; i++) {
			let id = `addedFile${i}`
			jumper.jumpTo(id, -2)
			process.stdout.write(chalk.red('✗'))
		}

		process.stdout.write(ansiEscapes.cursorRestorePosition)
		console.log()
		console.log()
		console.log('Aborting -- no files added.')
	}
}

module.exports = Interactive
<|endoftext|>


<commit_before>var tiers = [];
var defaultDatasource = "_default";

var ruleTypes = [
  "loadByInterval",
  "loadByPeriod",
  "dropByInterval",
  "dropByPeriod",
  "loadForever",
  "dropForever",
  "JSON"
];

function makeRuleDiv(rule) {
  var retVal = "
";

  if (rule === null || typeof rule === "undefined") {
    retVal += makeRuleComponents("") + makeRuleBody();
  } else {
    retVal += makeRuleComponents(rule.type) + makeRuleBody(rule);
  }

  retVal += "
";
  return retVal;
}

function makeRuleComponents(type) {
  var components = "<button type='button' class='delete_rule'>X</button>";
  components +=
  "" +
    "type" +
      "<select class='rule_dropdown_types'>" +
        "<option></option>";

  $.each(ruleTypes, function(index, ruleType) {
    if (ruleType === type) {
      components += "<option selected='selected' value='" + ruleType + "'>" + ruleType + "</option>";
    } else {
      components += "<option value='" + ruleType + "'>" + ruleType + "</option>";
    }
  });

  components +=
    "</select>" +
  "";

  return components;
}

function makeRuleBody(rule) {
  var retVal = "";
  if (rule !== null && typeof rule !== "undefined") {
    switch (rule.type) {
      case "loadByInterval":
        retVal += makeLoadByInterval(rule);
        break;
      case "loadByPeriod":
        retVal += makeLoadByPeriod(rule);
        break;
      case "loadForever":
        retVal += makeLoadForever(rule);
        break;
      case "dropByInterval":
        retVal += makeDropByInterval(rule);
        break;
      case "dropByPeriod":
        retVal += makeDropByPeriod(rule);
        break;
      case "dropForever":
        retVal += "";
        break;
      case "JSON":
        retVal += makeJSON();
        break;
      default:
        break;
    }
  }
  retVal += ""
  return retVal;
}

function makeLoadByInterval(rule) {
  var retVal = "";
  retVal += "interval<input type='text' class='long_text' name='interval' " + "value='" + rule.interval + "'/>";
  retVal += "<button type='button' class='add_tier'>Add Another Tier</button>";
  if (rule.tieredReplicants === undefined) {
    retVal += makeTierLoad(null, 0);
  }
  for (var tier in rule.tieredReplicants) {
    retVal += makeTierLoad(tier, rule.tieredReplicants[tier]);
  }
  return retVal;
}

function makeLoadByPeriod(rule) {
  var retVal = "";
  retVal += "period<input type='text' name='period' " + "value='" + rule.period + "'/>";
  retVal += "<button type='button' class='add_tier'>Add Another Tier</button>";
  if (rule.tieredReplicants === undefined) {
    retVal += makeTierLoad(null, 0);
  }
  for (var tier in rule.tieredReplicants) {
    retVal += makeTierLoad(tier, rule.tieredReplicants[tier]);
  }
  return retVal;
}

function makeLoadForever(rule) {
  var retVal = "";
  retVal += "<button type='button' class='add_tier'>Add Another Tier</button>";
  if (rule.tieredReplicants === undefined) {
    retVal += makeTierLoad(null, 0);
  }
  for (var tier in rule.tieredReplicants) {
    retVal += makeTierLoad(tier, rule.tieredReplicants[tier]);
  }
  return retVal;
}

function makeTierLoad(tier, val) {
  return "
" +
         "replicants<input type='text' class='short_text' name='replicants' " + "value='" + val + "'/>" +
                      makeTiersDropdown(tier) +
         "
";
}

function makeDropByInterval(rule) {
  return "interval<input type='text' name='interval' " + "value='" + rule.interval + "'/>";
}

function makeDropByPeriod(rule) {
  return "period<input type='text' name='period' " + "value='" + rule.period + "'/>";
}

function makeJSON() {
  return "JSON<input type='text' class='very_long_text' name='JSON'/>";
}

function makeTiersDropdown(selTier) {
  var retVal = "tier<select class='tiers' name='tier'>"

  $.each(tiers, function(index, tier) {
    if (selTier === tier) {
      retVal += "<option selected='selected' value='" + tier + "'>" + tier + "</option>";
    } else {
      retVal += "<option value='" + tier + "'>" + tier + "</option>";
    }
  });

  retVal += "</select>";
  return retVal;
}

function getRules() {
  var selected = $('#datasources option:selected').text();
  if (selected !== "") {
    $.getJSON("/druid/coordinator/v1/rules/" + selected, function(data) {
      $('#rules_list').empty();
      if (!$.isEmptyObject(data)) {
        $.each(data, function(index, rule) {
          $('#rules_list').append(makeRuleDiv(rule));
        });
      }
    });
  }
}

function domToRule(domRule) {
  var ruleType = $($(domRule).find(".rule_dropdown_types:first")).val();
  var inputs = $($(domRule).find(".rule_body:first")).children("input");

  // Special case for free form JSON
  if (ruleType === "JSON") {
    return $.parseJSON($(inputs.children("input:first")).val());
  }

  var rule = {};
  rule.type = ruleType;
  $.each(inputs, function(index, input) {
    var name = $(input).attr("name");
    rule[name] = $(input).val();
  });

  var theTiers = $($(domRule).find(".rule_body:first")).children(".rule_tier");

  var tieredReplicants = {};
  $.each(theTiers, function(index, theTier) {
    var tierName = $(theTier).find("select").val();
    var replicants = $(theTier).find("[name=replicants]").val();
    tieredReplicants[tierName] = replicants;
  });
  rule.tieredReplicants = tieredReplicants;

  return rule;
}

$(document).ready(function() {
  $("button").button();

  $("#rules_list").sortable();

  $("#error_dialog").dialog({
      autoOpen: false,
      modal:true,
      resizeable: false,
      buttons: {
        Ok : function() {
          $(this).dialog("close");
        }
      }
  });

  $("#cancel_dialog").dialog({
      autoOpen: false,
      modal:true,
      resizeable: false,
      buttons: {
        Yes : function() {
          getRules();
          $(this).dialog("close");
        },
        No: function() {
          $(this).dialog("close");
        }
      }
  });

  $("#update_dialog").dialog({
    autoOpen: false,
    modal:true,
    resizeable: false,
    buttons: {
      Yes : function() {
        var rules = [];
        $.each($("#rules_list").children(), function(index, domRule) {
          rules.push(domToRule(domRule));
        });

        var selected = $('#datasources option:selected').text();
        $.ajax({
          type: 'POST',
          url:'/druid/coordinator/v1/rules/' + selected,
          data: JSON.stringify(rules),
          contentType:"application/json; charset=utf-8",
          dataType:"text",
          error: function(xhr, status, error) {
            $("#update_dialog").dialog("close");
            $("#error_dialog").html(xhr.responseText);
            $("#error_dialog").dialog("open");
          },
          success: function(data, status, xhr) {
            $("#update_dialog").dialog("close");
          }
        });
      },
      Cancel: function() {
        $(this).dialog("close");
      }
    }
  });

  $.getJSON("/druid/coordinator/v1/tiers", function(theTiers) {
      tiers = theTiers;
  });

  $.getJSON("/druid/coordinator/v1/db/datasources", function(data) {
    $.each(data, function(index, datasource) {
      $('#datasources').append($('<option></option>').val(datasource).text(datasource));
    });
    $('#datasources').append($('<option></option>').val(defaultDatasource).text(defaultDatasource));
  });

  $("#datasources").change(function(event) {
    getRules();
    $("#rules").show();
  });

  $(document).on("change", '.rule_dropdown_types', null, function(event) {
    var newRule = {
      "type" : $(event.target).val()
    };
    var ruleBody = $(event.target).parent('.rule_dropdown').next('.rule_body');
    ruleBody.replaceWith(makeRuleBody(newRule));
  });

  $(document).on("click", '.delete_rule', null, function(event) {
    $(event.target).parent(".rule").remove();
  });

  $(document).on("click", '.add_tier', null, function(event) {
    $(event.target).parent().append(makeTierLoad(null, 0));
  });

  $("#create_new_rule").click(function (event) {
    $('#rules_list').prepend(makeRuleDiv());
  });

  $("#cancel").click(function() {
    $("#cancel_dialog").dialog("open");
  });

  $('#update').click(function (){
    $("#update_dialog").dialog("open")
  });
});<commit_msg>minor javascript problem<commit_after>var tiers = [];
var defaultDatasource = "_default";

var ruleTypes = [
  "loadByInterval",
  "loadByPeriod",
  "dropByInterval",
  "dropByPeriod",
  "loadForever",
  "dropForever",
  "JSON"
];

function makeRuleDiv(rule) {
  var retVal = "
";

  if (rule === null || typeof rule === "undefined") {
    retVal += makeRuleComponents("") + makeRuleBody();
  } else {
    retVal += makeRuleComponents(rule.type) + makeRuleBody(rule);
  }

  retVal += "
";
  return retVal;
}

function makeRuleComponents(type) {
  var components = "<button type='button' class='delete_rule'>X</button>";
  components +=
  "" +
    "type" +
      "<select class='rule_dropdown_types'>" +
        "<option></option>";

  $.each(ruleTypes, function(index, ruleType) {
    if (ruleType === type) {
      components += "<option selected='selected' value='" + ruleType + "'>" + ruleType + "</option>";
    } else {
      components += "<option value='" + ruleType + "'>" + ruleType + "</option>";
    }
  });

  components +=
    "</select>" +
  "";

  return components;
}

function makeRuleBody(rule) {
  var retVal = "";
  if (rule !== null && typeof rule !== "undefined") {
    switch (rule.type) {
      case "loadByInterval":
        retVal += makeLoadByInterval(rule);
        break;
      case "loadByPeriod":
        retVal += makeLoadByPeriod(rule);
        break;
      case "loadForever":
        retVal += makeLoadForever(rule);
        break;
      case "dropByInterval":
        retVal += makeDropByInterval(rule);
        break;
      case "dropByPeriod":
        retVal += makeDropByPeriod(rule);
        break;
      case "dropForever":
        retVal += "";
        break;
      case "JSON":
        retVal += makeJSON();
        break;
      default:
        break;
    }
  }
  retVal += ""
  return retVal;
}

function makeLoadByInterval(rule) {
  var retVal = "";
  retVal += "interval<input type='text' class='long_text' name='interval' " + "value='" + rule.interval + "'/>";
  retVal += "<button type='button' class='add_tier'>Add Another Tier</button>";
  if (rule.tieredReplicants === undefined) {
    retVal += makeTierLoad(null, 0);
  }
  for (var tier in rule.tieredReplicants) {
    retVal += makeTierLoad(tier, rule.tieredReplicants[tier]);
  }
  return retVal;
}

function makeLoadByPeriod(rule) {
  var retVal = "";
  retVal += "period<input type='text' name='period' " + "value='" + rule.period + "'/>";
  retVal += "<button type='button' class='add_tier'>Add Another Tier</button>";
  if (rule.tieredReplicants === undefined) {
    retVal += makeTierLoad(null, 0);
  }
  for (var tier in rule.tieredReplicants) {
    retVal += makeTierLoad(tier, rule.tieredReplicants[tier]);
  }
  return retVal;
}

function makeLoadForever(rule) {
  var retVal = "";
  retVal += "<button type='button' class='add_tier'>Add Another Tier</button>";
  if (rule.tieredReplicants === undefined) {
    retVal += makeTierLoad(null, 0);
  }
  for (var tier in rule.tieredReplicants) {
    retVal += makeTierLoad(tier, rule.tieredReplicants[tier]);
  }
  return retVal;
}

function makeTierLoad(tier, val) {
  return "
" +
         "replicants<input type='text' class='short_text' name='replicants' " + "value='" + val + "'/>" +
                      makeTiersDropdown(tier) +
         "
";
}

function makeDropByInterval(rule) {
  return "interval<input type='text' name='interval' " + "value='" + rule.interval + "'/>";
}

function makeDropByPeriod(rule) {
  return "period<input type='text' name='period' " + "value='" + rule.period + "'/>";
}

function makeJSON() {
  return "JSON<input type='text' class='very_long_text' name='JSON'/>";
}

function makeTiersDropdown(selTier) {
  var retVal = "tier<select class='tiers' name='tier'>"

  if ($.inArray(selTier, tiers) == -1) {
    tiers.push(selTier);
  }

  $.each(tiers, function(index, tier) {
    if (selTier === tier) {
      retVal += "<option selected='selected' value='" + tier + "'>" + tier + "</option>";
    } else {
      retVal += "<option value='" + tier + "'>" + tier + "</option>";
    }
  });

  retVal += "</select>";
  return retVal;
}

function getRules() {
  var selected = $('#datasources option:selected').text();
  if (selected !== "") {
    $.getJSON("/druid/coordinator/v1/rules/" + selected, function(data) {
      $('#rules_list').empty();
      if (!$.isEmptyObject(data)) {
        $.each(data, function(index, rule) {
          $('#rules_list').append(makeRuleDiv(rule));
        });
      }
    });
  }
}

function domToRule(domRule) {
  var ruleType = $($(domRule).find(".rule_dropdown_types:first")).val();
  var inputs = $($(domRule).find(".rule_body:first")).children("input");

  // Special case for free form JSON
  if (ruleType === "JSON") {
    return $.parseJSON($(inputs.children("input:first")).val());
  }

  var rule = {};
  rule.type = ruleType;
  $.each(inputs, function(index, input) {
    var name = $(input).attr("name");
    rule[name] = $(input).val();
  });

  var theTiers = $($(domRule).find(".rule_body:first")).children(".rule_tier");

  var tieredReplicants = {};
  $.each(theTiers, function(index, theTier) {
    var tierName = $(theTier).find("select").val();
    var replicants = $(theTier).find("[name=replicants]").val();
    tieredReplicants[tierName] = replicants;
  });
  rule.tieredReplicants = tieredReplicants;

  return rule;
}

$(document).ready(function() {
  $("button").button();

  $("#rules_list").sortable();

  $("#error_dialog").dialog({
      autoOpen: false,
      modal:true,
      resizeable: false,
      buttons: {
        Ok : function() {
          $(this).dialog("close");
        }
      }
  });

  $("#cancel_dialog").dialog({
      autoOpen: false,
      modal:true,
      resizeable: false,
      buttons: {
        Yes : function() {
          getRules();
          $(this).dialog("close");
        },
        No: function() {
          $(this).dialog("close");
        }
      }
  });

  $("#update_dialog").dialog({
    autoOpen: false,
    modal:true,
    resizeable: false,
    buttons: {
      Yes : function() {
        var rules = [];
        $.each($("#rules_list").children(), function(index, domRule) {
          rules.push(domToRule(domRule));
        });

        var selected = $('#datasources option:selected').text();
        $.ajax({
          type: 'POST',
          url:'/druid/coordinator/v1/rules/' + selected,
          data: JSON.stringify(rules),
          contentType:"application/json; charset=utf-8",
          dataType:"text",
          error: function(xhr, status, error) {
            $("#update_dialog").dialog("close");
            $("#error_dialog").html(xhr.responseText);
            $("#error_dialog").dialog("open");
          },
          success: function(data, status, xhr) {
            $("#update_dialog").dialog("close");
          }
        });
      },
      Cancel: function() {
        $(this).dialog("close");
      }
    }
  });

  $.getJSON("/druid/coordinator/v1/tiers", function(theTiers) {
      tiers = theTiers;
  });

  $.getJSON("/druid/coordinator/v1/db/datasources", function(data) {
    $.each(data, function(index, datasource) {
      $('#datasources').append($('<option></option>').val(datasource).text(datasource));
    });
    $('#datasources').append($('<option></option>').val(defaultDatasource).text(defaultDatasource));
  });

  $("#datasources").change(function(event) {
    getRules();
    $("#rules").show();
  });

  $(document).on("change", '.rule_dropdown_types', null, function(event) {
    var newRule = {
      "type" : $(event.target).val()
    };
    var ruleBody = $(event.target).parent('.rule_dropdown').next('.rule_body');
    ruleBody.replaceWith(makeRuleBody(newRule));
  });

  $(document).on("click", '.delete_rule', null, function(event) {
    $(event.target).parent(".rule").remove();
  });

  $(document).on("click", '.add_tier', null, function(event) {
    $(event.target).parent().append(makeTierLoad(null, 0));
  });

  $("#create_new_rule").click(function (event) {
    $('#rules_list').prepend(makeRuleDiv());
  });

  $("#cancel").click(function() {
    $("#cancel_dialog").dialog("open");
  });

  $('#update').click(function (){
    $("#update_dialog").dialog("open")
  });
});<|endoftext|>


<commit_before>let aDefault = {
    'ho-oh': 'hooh',
    'bounty': 'porygonz-shiny',
    'tech': 'vileplume',
    'lectro': 'noivern',
    'ngb': 'ampharos',
    'amph': 'ampharos-mega',
    'fable': 'flygon-shiny',
    'thane': 'absol',
    'semper': 'flygon',
    'monk': 'weavile',
    'baru': 'arcanine',
    'ace': 'suicune',
    'quote': 'sableye',
    'stall': 'sableye-mega',
    'surv': 'zorua-shiny',
    'josh': 'staraptor',
    'luc': 'lucario',
    'flare': 'flareon',
    'fluffy': 'leafeon',
    'fug': 'rayquaza',
    'sol': 'solrock',
    'cell': 'gengar',
    'dom': 'charizard',
    'hiccup': 'spinda',
    'runtime': 'lapras',
    'curtis': 'reuniclus',
    'type: null': 'typenull',
    'type null': 'typenull',
    'mr. mime': 'mrmime',
    'mr mime': 'mrmime',
    'mime jr.': 'mimejr',
    'mime jr': 'mimejr',
    'tapu koko': 'tapukoko',
    'tapu lele': 'tapulele',
    'tapu bulu': 'tapubulu',
    'tapu fini': 'tapufini'
}

let custom = {
    'matt': 'meowstic',
    'erebus': 'meowstic',
    'blue': 'popplio',
    'emily': 'luxio',
    'hound': 'houndoom',
    'zytom': 'lurantis',
    'jenn': 'bellossom',
    'skul': 'totodile',
    'orn': 'decidueye-shiny',
    'jordan': 'dewott',
    'mene': 'cosmog',
    'minty': 'archeops',
    'sapph': 'glaceon',
    'swed': 'vaporeon',
    'pally': 'lilligant',
    'thirst': 'lilligant'
}

exports.aliases = (id) => {
    let toReturn = aDefault;
    if (id != 111504456838819840) toReturn = Object.assign(aDefault, custom);
    console.log(`111504456838819840\n${id}`);
    return toReturn;
}<commit_msg>please please please<commit_after>let aDefault = {
    'ho-oh': 'hooh',
    'bounty': 'porygonz-shiny',
    'tech': 'vileplume',
    'lectro': 'noivern',
    'ngb': 'ampharos',
    'amph': 'ampharos-mega',
    'fable': 'flygon-shiny',
    'thane': 'absol',
    'semper': 'flygon',
    'monk': 'weavile',
    'baru': 'arcanine',
    'ace': 'suicune',
    'quote': 'sableye',
    'stall': 'sableye-mega',
    'surv': 'zorua-shiny',
    'josh': 'staraptor',
    'luc': 'lucario',
    'flare': 'flareon',
    'fluffy': 'leafeon',
    'fug': 'rayquaza',
    'sol': 'solrock',
    'cell': 'gengar',
    'dom': 'charizard',
    'hiccup': 'spinda',
    'runtime': 'lapras',
    'curtis': 'reuniclus',
    'type: null': 'typenull',
    'type null': 'typenull',
    'mr. mime': 'mrmime',
    'mr mime': 'mrmime',
    'mime jr.': 'mimejr',
    'mime jr': 'mimejr',
    'tapu koko': 'tapukoko',
    'tapu lele': 'tapulele',
    'tapu bulu': 'tapubulu',
    'tapu fini': 'tapufini'
}

let custom = {
    'matt': 'meowstic',
    'erebus': 'meowstic',
    'blue': 'popplio',
    'emily': 'luxio',
    'hound': 'houndoom',
    'zytom': 'lurantis',
    'jenn': 'bellossom',
    'skul': 'totodile',
    'orn': 'decidueye-shiny',
    'jordan': 'dewott',
    'mene': 'cosmog',
    'minty': 'archeops',
    'sapph': 'glaceon',
    'swed': 'vaporeon',
    'pally': 'lilligant',
    'thirst': 'lilligant'
}

exports.aliases = (id) => {
    if (id == 111504456838819840) {
        return toReturn;
    } else {
        return Object.assign(aDefault, custom);
    }
}<|endoftext|>


<commit_before>/*
 *  awa-storages -- Storages and folders
 *  Copyright (C) 2012, 2016, 2018 Stephane Carrez
 *  Written by Stephane Carrez (Stephane.Carrez@gmail.com)
 *
 *  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.
 */
(function($, undefined) {

    $.widget("ui.folder", $.ui.list, {
        options: {
            actionId: null,
            itemPrefix: 'folder-',
        },

        _create: function() {
            var self = this;
            var upload = $(self.options.uploadButton);

            $.ui.list.prototype._create.apply(this, arguments);
            $(upload).bind('click', function(event) {
                var id = self.getSelectedId(self.currentNode);
                if (id != null) {
                    self.uploadDialog(id);
                }
                return false;
            });
        },
        selectAction: function(node, event) {
            var id = this.getSelectedId(node);
            this.currentNode = node;
            return ASF.Update(this, this.options.selectUrl + '?folderId=' + id, '#document-list-editor');
        },
        value: function() {
            return this.currentItem;
        },
        uploadDialog: function(folderId) {
            var self = this;
            var div = document.createElement("div");
            div.id = 'upload-dialog';
            div = $(div);

            var d = $(document.body);
            if (d.length == 0) {
                return false;
            }

            $(d).append($(div));

            /* Perform the HTTP GET */
            jQuery.ajax({
                url: this.options.uploadUrl + "?folderId=" + folderId,
                context: document.body,
                success: function(data, status, jqXHDR) {
                    var contentType = jqXHDR.getResponseHeader('Content-type');
                    if (contentType == null) {
                        contentType = "text/html";
                    }
                    if (contentType.match(/^text\/(html|xml)(;.*)?$/i)) {
                        $(div).dialog({
                            autoOpen: false,
                            show: "blind",
                            hide: "explode",
                            minWidth: 600,
                            close: function() {
                                $(div).dialog('destroy');
                                $(div).remove();
                            }
                        });

                        $(div).html(jqXHDR.responseText);

                        /**
                        * Extract a title from the inner form to setup the dialog box.
                        */
                        var dTitle, dBox = $(div).children('div');
                        if (dBox.length == 0) {
                            dTitle = $(div).children('h2');
                        } else {
                            dTitle = $(dBox).children('h2');
                        }
                        if (dTitle.length > 0) {
                            $(div).dialog("option", "title", dTitle.html());
                            dTitle.remove();
                        } else {
                            dTitle = $(div).children('div').attr('title');
                            if (dTitle != null) {
                                $(div).dialog("option", "title", dTitle );
                                /* $(div).attr('title', title); */
                            }
                        }
                        $(div).dialog('open');
                        $("#uploadForm").dropzone({
                            url: self.options.uploadUrl,
                            dictDefaultMessage: self.options.dictDefaultMessage,
                            maxFiles: 1,
                            paramName: "upload-file",
                            params: function(files, xhr, chunk) {
                                return { "upload-button": "1", "uploadForm": "1" }
                            },
                            success: function(file, response) {
                                ASF.Execute(self.currentNode, response);
                                $(div).dialog('close');
                            }
                        });

                    } else if (contentType.match(/^application\/json(;.*)?$/i)) {
                        ASF.Execute(self.currentNode, data);
                    }
                },
                error: function(jqXHDR, status, error) {
                    ASF.AjaxError(jqXHDR, status, error, d);
                }
            });
        }
    });

})( jQuery );
<commit_msg>Fix folder selection<commit_after>/*
 *  awa-storages -- Storages and folders
 *  Copyright (C) 2012, 2016, 2018 Stephane Carrez
 *  Written by Stephane Carrez (Stephane.Carrez@gmail.com)
 *
 *  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.
 */
(function($, undefined) {

    $.widget("ui.folder", $.ui.list, {
        options: {
            actionId: null,
            itemPrefix: 'folder-'
        },
        selectedItem: null,

        _create: function() {
            var self = this;
            var upload = $(self.options.uploadButton);

            $.ui.list.prototype._create.apply(this, arguments);
            $(upload).bind('click', function(event) {
                var id = self.getSelectedId(self.currentNode);
                if (id != null) {
                    self.uploadDialog(id);
                }
                return false;
            });
            self.options.selectAction = self.selectAction;
        },
        selectAction: function(node, event) {
            var id = this.getSelectedId(node);
            if (this.selectedItem) {
                $(this.selectedItem).removeClass(this.options.selectClass);
            }
            this.currentNode = node;
            this.selectedItem = node;
            $(this.selectedItem).addClass(this.options.selectClass);
            return ASF.Update(this, this.options.selectUrl + '?folderId=' + id, '#document-list-editor');
        },
        uploadDialog: function(folderId) {
            var self = this;
            var div = document.createElement("div");
            div.id = 'upload-dialog';
            div = $(div);

            var d = $(document.body);
            if (d.length == 0) {
                return false;
            }

            $(d).append($(div));

            /* Perform the HTTP GET */
            jQuery.ajax({
                url: this.options.uploadUrl + "?folderId=" + folderId,
                context: document.body,
                success: function(data, status, jqXHDR) {
                    var contentType = jqXHDR.getResponseHeader('Content-type');
                    if (contentType == null) {
                        contentType = "text/html";
                    }
                    if (contentType.match(/^text\/(html|xml)(;.*)?$/i)) {
                        $(div).dialog({
                            autoOpen: false,
                            show: "blind",
                            hide: "explode",
                            minWidth: 600,
                            close: function() {
                                $(div).dialog('destroy');
                                $(div).remove();
                            }
                        });

                        $(div).html(jqXHDR.responseText);

                        /**
                        * Extract a title from the inner form to setup the dialog box.
                        */
                        var dTitle, dBox = $(div).children('div');
                        if (dBox.length == 0) {
                            dTitle = $(div).children('h2');
                        } else {
                            dTitle = $(dBox).children('h2');
                        }
                        if (dTitle.length > 0) {
                            $(div).dialog("option", "title", dTitle.html());
                            dTitle.remove();
                        } else {
                            dTitle = $(div).children('div').attr('title');
                            if (dTitle != null) {
                                $(div).dialog("option", "title", dTitle );
                                /* $(div).attr('title', title); */
                            }
                        }
                        $(div).dialog('open');
                        $("#uploadForm").dropzone({
                            url: self.options.uploadUrl,
                            dictDefaultMessage: self.options.dictDefaultMessage,
                            maxFiles: 1,
                            paramName: "upload-file",
                            params: function(files, xhr, chunk) {
                                return { "upload-button": "1", "uploadForm": "1" }
                            },
                            success: function(file, response) {
                                ASF.Execute(self.currentNode, response);
                                $(div).dialog('close');
                            }
                        });

                    } else if (contentType.match(/^application\/json(;.*)?$/i)) {
                        ASF.Execute(self.currentNode, data);
                    }
                },
                error: function(jqXHDR, status, error) {
                    ASF.AjaxError(jqXHDR, status, error, d);
                }
            });
        }
    });

})( jQuery );
<|endoftext|>


<commit_before>// Compare the alternative routes to the actual route.
const db = require('./db.js');

class Compare {

}

db.prepare()
  .then(() => {

  })
  .then(() => process.exit())
  .catch((e) => {
    console.error(e);
    process.exit();
  });
<commit_msg>Removed empty compare script.<commit_after><|endoftext|>


<commit_before>/**
 * Package dependencies
 */
const crypto = require('crypto')
const RSA = require('node-rsa')

/**
 * Local dependencies
 */
const Algorithm = require('../Algorithm')
const BigInteger = require('../BigInteger')
const CryptoKeyPair = require('../CryptoKeyPair')
const HashAlgorithmIdentifier = require('../HashAlgorithmIdentifier')
const KeyAlgorithm = require('../KeyAlgorithm')

/**
 * RsaKeyGenParams
 */
class RsaKeyGenParams extends Algorithm {
  constructor (modulusLength, publicExponent) {
    // validate and set modulusLength
    if (typeof modulusLength !== 'number') { throw new Error() }
    if (modulusLength < 1024) { throw new Error() }
    this.modulusLength = modulusLength

    // validate and set publicExponent
    if (!(publicExponent instanceof BigInteger)) { throw new Error() }
    this.publicExponent = publicExponent
  }
}

/**
 * RsaHashedKeyGenParams
 */
class RsaHashedKeyGenParams extends RsaKeyGenParams {
  constructor (modulusLength, publicExponent, hash) {
    super(modulusLength, publicExponent)

    // validate and set hash
    if (!(hash instanceof HashAlgorithmIdentifier)) { throw new Error() }
    this.hash = hash
  }
}

/**
 * RsaKeyAlgorithm
 */
class RsaKeyAlgorithm extends KeyAlgorithm {
  constructor (modulusLength, publicExponent) {
    // validate and set modulusLength
    if (typeof modulusLength !== 'number') { throw new Error() }
    if (modulusLength < 1024) { throw new Error() }
    this.modulusLength = modulusLength

    // validate and set publicExponent
    if (!(publicExponent instanceof BigInteger)) { throw new Error() }
    this.publicExponent = publicExponent
  }
}

/**
 * RsaHashedKeyAlgorithm
 */
class RsaHashedKeyAlgorithm extends RsaKeyAlgorithm {
  constructor (modulusLength, publicExponent, hash) {
    super(modulusLength, publicExponent)

    // validate and set hash
    if (!(hash instanceof KeyAlgorithm)) { throw new Error() }
    this.hash = hash
  }
}

/**
 * RsaHashedImportParams
 */
class RsaHashedImportParams {
  constructor (hash) {
    // validate and set hash
    if (!(hash instanceof HashAlgorithmIdentifier)) { throw new Error() }
    this.hash = hash
  }
}

/**
 * RSASSA-PKCS1-v1_5
 */
class RSASSA-PKCS1-v1_5 {

  /**
   * Constuctor
   */
  constructor (key, data, bitlength) {
    // TODO should name be an argument to constructor?
    this.name = 'RSASSA-PKCS1-v1_5'
    this.key = key
    this.data = data
    this.bitlength = bitlength
  }

  /**
   * exportKey
   */
  exportKey () {}

  /**
   * generateKey
   */
  generateKey () {
    let key = new RSA()

    // ...

    return new CryptoKeyPair()
  }

  /**
   * importKey
   */
  importKey () {}

  /**
   * signKey
   */
  sign (key, data) {

  }

  /**
   * verifyKey
   */
  verify () {}
}

/**
 * Export
 */
module.exports = RSASSA-PKCS1-v1_5
<commit_msg>feat(RSASSA-PKCS1-v1_5): draft generateKey method<commit_after>/**
 * Package dependencies
 */
const crypto = require('crypto')
const RSA = require('node-rsa')

/**
 * Local dependencies
 */
const Algorithm = require('./Algorithm')
const BigInteger = require('../BigInteger')
const CryptoKey = require('../CryptoKey')
const CryptoKeyPair = require('../CryptoKeyPair')
const KeyAlgorithm = require('./KeyAlgorithm')
const RsaKeyGenParams = require('./RsaKeyGenParams')
const RsaHashedKeyGenParams = require('./RsaHashedKeyGenParams')
const RsaKeyAlgorithm = require('./RsaKeyAlgorithm')
const RsaHashedKeyAlgorithm = require('./RsaHashedKeyAlgorithm')
const RsaHashedImportParams = require('./RsaHashedImportParams')

/**
 * RSASSA-PKCS1-v1_5
 */
class RSASSA_PKCS1_v1_5 {

  /**
   * Constructor
   *
   * @param {RsaKeyAlgorithm} algorithm
   * @param {Boolean} extractable
   * @param {Array} usages
   */
  constructor (algorithm, extractable, usages) {
    this.algorithm = algorithm
    this.extractable = extractable
    this.usages = usages
  }

  /**
   * exportKey
   */
  exportKey () {}

  /**
   * generateKey
   *
   * @param {RsaHashedKeyGenParams} params
   * @returns {CryptoKeyPair}
   */
  generateKey (params) {
    // validate usages
    this.usages.forEach(usage => {
      if (usage !== 'sign' && usage !== 'verify') {
        throw new SyntaxError()
      }
    })

    // Generate and RSA keypair
    try {
      // TODO
      // what is this bit option, where do we get the value from in this
      // api?
      let key = new RSA({b:512})
      let {modulusLength,publicExponent} = this.algorithm
      let keypair = key.generateKeyPair(modulusLength, publicExponent)
      console.log('KEYPAIR', keypair)
    } catch (e) {
      throw new OperationError()
    }

    // cast params to algorithm
    let algorithm = new RsaHashedKeyAlgorithm(params)

    // instantiate publicKey
    let publicKey = new CryptoKey({
      type: 'public',
      algorithm,
      extractable: true,
      usages: ['verify']
    })

    // instantiate privateKey
    let privateKey = new CryptoKey({
      type: 'private',
      algorithm,
      // TODO is there a typo in the spec?
      // it says "extractable" instead of "false"
      extractable: false,
      usages: ['sign']
    })

    // return a new keypair
    return new CryptoKeyPair({publicKey,privateKey})
  }

  /**
   * importKey
   */
  importKey () {}

  /**
   * signKey
   */
  sign (key, data) {

  }

  /**
   * verifyKey
   */
  verify () {}
}

/**
 * Export
 */
module.exports = RSASSA_PKCS1_v1_5
<|endoftext|>