<commit_before>/*
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * ndf command protocol
 *
 * list systems
 * list container systemid
 *
 *
 */

'use strict';

var bcksrv = require('bcksrv');
var netOut = require('./networkOut');
var net = require('net');

module.exports = function(api, auth, logger) {

  var login = function(out, username, password, cb) {
    auth.login(username, password, function(err, result) {
      if (err) {
        return cb(err)
      }
      if (result.user) {
        out.connection.user = result.user;
      }
      out.response(result);
    });
  };

  var token = function(out, token, cb) {
    auth.userInfo(token, function(err, user) {
      if (err) { return cb(err); }
      out.connection.user = user;
      out.response(user);
      cb();
    });
  };

  var authorized = function(connection, out) {
    if (!connection.user) {
      out.response({ok:false, err:'Unauthorized'});
    }
    return connection.user;
  };

  var githubLogin = function(out, accessToken, cb) {
    auth.githubLogin(accessToken, function(err, result) {
      if (err) { return cb(err); }
      if (result.user) {
        out.connection.user = result.user;
      }
      out.response(result);
      cb();
    });
  };

  var listSystems = function(out, cb) {
    api.listSystems(function(err, systems) {
      if (err) { return cb(err); }

      logger.info('rsp: list systems');
      out.response(systems);
      cb();
    });
  };

  var createSystem = function(out, name, namespace, cb) {
    api.createSystem(out.connection.user, name, namespace, function(err, system) {
      if (err) {
        return cb(err);
      }
      logger.info('rsp: create system');
      out.response(system);
      cb();
    });
  };

  var getSystem = function(out, systemId, cb) {
    api.getHeadSystem(systemId, function(err, system) {
      logger.info('rsp: get system ' + systemId);
      if (err) {
        return cb(err);
      }
      out.response(system);
      cb();
    });
  };

  var getDeployed = function(out, systemId, cb) {
    api.getDeployedSystem(systemId, function(err, system) {
      if (err) {
        return cb(err);
      }
      logger.info('rsp: get deployed ' + systemId);
      out.response(system);
      cb();
    });
  };

  var putSystem = function(out, systemJson, cb) {
    api.putSystem(out.connection.user, systemJson, function(err) {
      logger.info('rsp: put system');
      if (err) {
        return cb(err);
      }
      out.response({result: 'ok'});
      cb();
    });
  };

  // disabled by @mcollina
  //var deleteSystem = function(out, user, systemId) {
  //  api.deleteSystem(user, systemId, function(err) {
  //    logger.info('rsp: delete system');
  //    if (err) { out.response({result: 'err', err: err}); }
  //    else { out.response({result: 'ok'}); }
  //  });
  //};

  var cloneSystem = function(out, url, cb) {
    api.cloneSystem(out.connection.user, url, function(err) {
      logger.info('rsp: clone system');
      if (err) {
        return cb(err);
      }
      out.response({result: 'ok'});
      cb();
    });
  };

  var syncSystem = function(out, systemId, cb) {
    api.syncSystem(out.connection.user, systemId, function(err) {
      logger.info('rsp: sync system');
      if (err) {
        return cb(err);
      }
      out.response({result: 'ok'});
      cb()
    });
  };

  var addRemote = function(out, systemId, url, cb) {
    api.addRemote(out.connection.user, systemId, url, function(err) {
      logger.info('rsp: add remote');
      if (err) {
        return cb(err);
      }
      out.response({result: 'ok'});
      cb();
    });
  };

  var listContainers = function(out, systemId, cb) {
    api.listContainers(systemId, function(err, containers) {
      logger.info('rsp: list containers ' + systemId);
      if (err) {
        return cb(err);
      }
      out.response(containers);
      cb();
    });
  };

  //var addContainer = function(out, user, containerJson, systemId) {
  //  api.addContainer(user, systemId, containerJson, function(err) {
  //    logger.info('rsp: add container');
  //    if (err) { out.response({result: 'err', err: err}); }
  //    else { out.response({result: 'ok'}); }
  //  });
  //};

  //var putContainer = function(out, user, containerJson, systemId) {
  //  api.putContainer(user, systemId, containerJson, function(err) {
  //    logger.info('rsp: put container');
  //    if (err) { out.response({result: 'err', err: err}); }
  //    else { out.response({result: 'ok'}); }
  //  });
  //};

  //var deleteContainer = function(out, user, systemId, containerId) {
  //  api.deleteContainer(user, systemId, containerId, function(err) {
  //    logger.info('rsp: delete container');
  //    if (err) { out.response({result: 'err', err: err}); }
  //    else { out.response({result: 'ok'}); }
  //  });
  //};

  var buildContainer = function(out, systemId, containerId, cb) {
    api.buildContainer(out.connection.user, systemId, containerId, out, function(err, result) {
      logger.info('rsp: build container ' + systemId);
      if (err) {
        return cb(err);
      }
      out.response(result);
      cb();
    });
  };

  var deploySystem = function(out, systemId, revisionId, cb) {
    var user = out.connection.user;
    api.deploySystem(user, systemId, revisionId, 'live', out, function(err, result) {
      logger.info('rsp: deploy system ' + user + ' ' + systemId + ' ' + revisionId);
      if (err) {
        return cb(err);
      }
      out.response(result);
      cb();
    });
  };

  var analyzeSystem = function(out, systemId, cb) {
    var user = out.connection.user;
    api.analyzeSystem(user, systemId, out, function(err, result) {
      logger.info('rsp: analyze system ' + user + ' ' + systemId);
      if (err) {
        return cb(err);
      }
      out.response(result);
      cb();
    });
  };

  var checkSystem = function(out, systemId, cb) {
    var user = out.connection.user;
    api.checkSystem(user, systemId, function(err, result) {
      logger.info('rsp: check system ' + user + ' ' + systemId);
      if (err) {
        return cb(err);
      }
      out.response(result);
      cb();
    });
  };

  var markRevision = function(out, systemId, revisionId, cb) {
    var user = out.connection.user;
    api.markRevision(user, systemId, revisionId, function(err, result) {
      logger.info('rsp: mark revision ' + user + ' ' + systemId + ' ' + revisionId);
      if (err) {
        return cb(err);
      }
      out.response(result);
      cb();
    });
  };

  var previewSystemDeploy = function(out, systemId, revisionId, cb) {
    var user = out.connection.user;
    api.previewSystemDeploy(user, systemId, revisionId, out, function(err, result) {
      logger.info('rsp: deploy system ' + user + ' ' + systemId + ' ' + revisionId);
      if (err) {
        return cb(err);
      }
      out.response(result);
      cb();
    });
  };

  var listRevisions = function(out, systemId, cb) {
    var user = out.connection.user;
    api.listRevisions(systemId, function(err, result) {
      logger.info('rsp: list revisions ' + systemId);
      if (err) {
        return cb(err);
      }
      out.response(result);
      cb();
    });
  };

  var getRevision = function(out, systemId, revisionId, cb) {
    var user = out.connection.user;
    api.getRevision(systemId, revisionId, function(err, result) {
      logger.info('rsp: get revision ' + systemId);
      if (err) {
        return cb(err);
      }
      out.response(result);
      cb();
    });
  };

  var timeline = function(out, systemId, cb) {
    var user = out.connection.user;
    api.timeline(systemId, function(err, result) {
      logger.info('rsp: timeline');
      if (err) {
        return cb(err);
      }
      out.response(result);
      cb();
    });
  };

  var quitConnection = function(out, cb) {
    logger.info('rsp: quit');
    out.response({bye: 'bye!'}, function() {
      out.connection.end();
      cb();
    });
  };

  var handlers = {
    revision: {
      list: listRevisions,
      get: getRevision,
      mark: markRevision,
      preview: previewSystemDeploy
    },

    system: {
      list: listSystems,
      get: getSystem,
      create: createSystem,
      deployed: getDeployed,
      deploy: deploySystem,
      analyze: analyzeSystem,
      check: checkSystem,
      sync: syncSystem,
      clone: cloneSystem,
      //disabled by @mcollina
      //delete: deleteSystem
    },

    container: {
      list: listContainers,
      //delete: deleteContainer,
      build: buildContainer
    },

    timeline: {
      list: timeline
    },

    remote: {
      add: addRemote
    }
  };

  function forEachHandler(current, base, callback) {
    if (typeof current === 'function') {
      callback = current;
      current = handlers;
      base = "";
    }
    Object.keys(current).forEach(function(key) {
      var newBase = base + key + ' '
      if (typeof current[key] === 'function') {
        callback(newBase.trim(), current[key])
      } else {
        forEachHandler(current[key], newBase, callback)
      }
    })
  }

  var _server = new bcksrv();

  forEachHandler(function(command, func) {
    _server.register(command, function(args, stream, cb) {
      //var req = (command + ' ' + args.join(' ')).trim();
      var req = command;
      var out = netOut(stream, req, logger)
      var authorizedUser = authorized(stream, out);
      if (!authorizedUser) {return;}
      logger.info('rcv: ' + req);

      args.unshift(out);
      args.push(cb);
      func.apply(null, args);
    })
  });

  var handlersUnauthorized = {
    login: login,
    githubLogin: githubLogin,
    token: token,
    quit: quitConnection
  };

  Object.keys(handlersUnauthorized).forEach(function(cmd) {
    _server.register(cmd, function(args, stream, cb) {
      var req = cmd;
      var out = netOut(stream, req, logger)
      logger.info('rcv: ' + req);

      args.unshift(out);
      args.push(cb);
      handlersUnauthorized[cmd].apply(null, args);
    });
  });

  var handlersMultiline = {
    'system put': putSystem,
    //'container add': addContainer,
    //'container put': putContainer
  };

  Object.keys(handlersMultiline).forEach(function(cmd) {
    _server.register(cmd, { multiline: 'END' }, function(args, stream, multiline, cb) {
      //var req = cmd + ' ' + args.join(' ');
      var req = cmd;
      var out = netOut(stream, req, logger)
      var authorizedUser = authorized(stream, out);
      if (!authorizedUser) {return;}
      logger.info('rcv: ' + req);

      args.unshift(out);
      args.push(multiline);
      args.push(cb);
      handlersMultiline[cmd].apply(null, args);
    });
  })

  return {
    stream: function() {

      var stream = _server.stream();

      stream.on('commandError', function(cmd, args, err) {
        logger.error(err);
        args[0].response({result: 'err', err: err});
        stream.end();
      });

      return stream;
    },

    start: function(opts) {
      opts = opts || {}

      opts.port = opts.port || 3223;
      var that = this;

      var server = net.createServer(function(conn) {
        conn.pipe(that.stream()).pipe(conn);
      });

      server.listen(opts.port);

      return server;
    }
  };
};

<commit_msg>Quick login fix.<commit_after>/*
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * ndf command protocol
 *
 * list systems
 * list container systemid
 *
 *
 */

'use strict';

var bcksrv = require('bcksrv');
var netOut = require('./networkOut');
var net = require('net');

module.exports = function(api, auth, logger) {

  var login = function(out, username, password, cb) {
    auth.login(username, password, function(err, result) {
      if (err) {
        return cb(err)
      }
      if (result.user) {
        out.connection.user = result.user;
      }
      out.response(result);
      cb();
    });
  };

  var token = function(out, token, cb) {
    auth.userInfo(token, function(err, user) {
      if (err) { return cb(err); }
      out.connection.user = user;
      out.response(user);
      cb();
    });
  };

  var authorized = function(connection, out) {
    if (!connection.user) {
      out.response({ok:false, err:'Unauthorized'});
    }
    return connection.user;
  };

  var githubLogin = function(out, accessToken, cb) {
    auth.githubLogin(accessToken, function(err, result) {
      if (err) { return cb(err); }
      if (result.user) {
        out.connection.user = result.user;
      }
      out.response(result);
      cb();
    });
  };

  var listSystems = function(out, cb) {
    api.listSystems(function(err, systems) {
      if (err) { return cb(err); }

      logger.info('rsp: list systems');
      out.response(systems);
      cb();
    });
  };

  var createSystem = function(out, name, namespace, cb) {
    api.createSystem(out.connection.user, name, namespace, function(err, system) {
      if (err) {
        return cb(err);
      }
      logger.info('rsp: create system');
      out.response(system);
      cb();
    });
  };

  var getSystem = function(out, systemId, cb) {
    api.getHeadSystem(systemId, function(err, system) {
      logger.info('rsp: get system ' + systemId);
      if (err) {
        return cb(err);
      }
      out.response(system);
      cb();
    });
  };

  var getDeployed = function(out, systemId, cb) {
    api.getDeployedSystem(systemId, function(err, system) {
      if (err) {
        return cb(err);
      }
      logger.info('rsp: get deployed ' + systemId);
      out.response(system);
      cb();
    });
  };

  var putSystem = function(out, systemJson, cb) {
    api.putSystem(out.connection.user, systemJson, function(err) {
      logger.info('rsp: put system');
      if (err) {
        return cb(err);
      }
      out.response({result: 'ok'});
      cb();
    });
  };

  // disabled by @mcollina
  //var deleteSystem = function(out, user, systemId) {
  //  api.deleteSystem(user, systemId, function(err) {
  //    logger.info('rsp: delete system');
  //    if (err) { out.response({result: 'err', err: err}); }
  //    else { out.response({result: 'ok'}); }
  //  });
  //};

  var cloneSystem = function(out, url, cb) {
    api.cloneSystem(out.connection.user, url, function(err) {
      logger.info('rsp: clone system');
      if (err) {
        return cb(err);
      }
      out.response({result: 'ok'});
      cb();
    });
  };

  var syncSystem = function(out, systemId, cb) {
    api.syncSystem(out.connection.user, systemId, function(err) {
      logger.info('rsp: sync system');
      if (err) {
        return cb(err);
      }
      out.response({result: 'ok'});
      cb()
    });
  };

  var addRemote = function(out, systemId, url, cb) {
    api.addRemote(out.connection.user, systemId, url, function(err) {
      logger.info('rsp: add remote');
      if (err) {
        return cb(err);
      }
      out.response({result: 'ok'});
      cb();
    });
  };

  var listContainers = function(out, systemId, cb) {
    api.listContainers(systemId, function(err, containers) {
      logger.info('rsp: list containers ' + systemId);
      if (err) {
        return cb(err);
      }
      out.response(containers);
      cb();
    });
  };

  //var addContainer = function(out, user, containerJson, systemId) {
  //  api.addContainer(user, systemId, containerJson, function(err) {
  //    logger.info('rsp: add container');
  //    if (err) { out.response({result: 'err', err: err}); }
  //    else { out.response({result: 'ok'}); }
  //  });
  //};

  //var putContainer = function(out, user, containerJson, systemId) {
  //  api.putContainer(user, systemId, containerJson, function(err) {
  //    logger.info('rsp: put container');
  //    if (err) { out.response({result: 'err', err: err}); }
  //    else { out.response({result: 'ok'}); }
  //  });
  //};

  //var deleteContainer = function(out, user, systemId, containerId) {
  //  api.deleteContainer(user, systemId, containerId, function(err) {
  //    logger.info('rsp: delete container');
  //    if (err) { out.response({result: 'err', err: err}); }
  //    else { out.response({result: 'ok'}); }
  //  });
  //};

  var buildContainer = function(out, systemId, containerId, cb) {
    api.buildContainer(out.connection.user, systemId, containerId, out, function(err, result) {
      logger.info('rsp: build container ' + systemId);
      if (err) {
        return cb(err);
      }
      out.response(result);
      cb();
    });
  };

  var deploySystem = function(out, systemId, revisionId, cb) {
    var user = out.connection.user;
    api.deploySystem(user, systemId, revisionId, 'live', out, function(err, result) {
      logger.info('rsp: deploy system ' + user + ' ' + systemId + ' ' + revisionId);
      if (err) {
        return cb(err);
      }
      out.response(result);
      cb();
    });
  };

  var analyzeSystem = function(out, systemId, cb) {
    var user = out.connection.user;
    api.analyzeSystem(user, systemId, out, function(err, result) {
      logger.info('rsp: analyze system ' + user + ' ' + systemId);
      if (err) {
        return cb(err);
      }
      out.response(result);
      cb();
    });
  };

  var checkSystem = function(out, systemId, cb) {
    var user = out.connection.user;
    api.checkSystem(user, systemId, function(err, result) {
      logger.info('rsp: check system ' + user + ' ' + systemId);
      if (err) {
        return cb(err);
      }
      out.response(result);
      cb();
    });
  };

  var markRevision = function(out, systemId, revisionId, cb) {
    var user = out.connection.user;
    api.markRevision(user, systemId, revisionId, function(err, result) {
      logger.info('rsp: mark revision ' + user + ' ' + systemId + ' ' + revisionId);
      if (err) {
        return cb(err);
      }
      out.response(result);
      cb();
    });
  };

  var previewSystemDeploy = function(out, systemId, revisionId, cb) {
    var user = out.connection.user;
    api.previewSystemDeploy(user, systemId, revisionId, out, function(err, result) {
      logger.info('rsp: deploy system ' + user + ' ' + systemId + ' ' + revisionId);
      if (err) {
        return cb(err);
      }
      out.response(result);
      cb();
    });
  };

  var listRevisions = function(out, systemId, cb) {
    var user = out.connection.user;
    api.listRevisions(systemId, function(err, result) {
      logger.info('rsp: list revisions ' + systemId);
      if (err) {
        return cb(err);
      }
      out.response(result);
      cb();
    });
  };

  var getRevision = function(out, systemId, revisionId, cb) {
    var user = out.connection.user;
    api.getRevision(systemId, revisionId, function(err, result) {
      logger.info('rsp: get revision ' + systemId);
      if (err) {
        return cb(err);
      }
      out.response(result);
      cb();
    });
  };

  var timeline = function(out, systemId, cb) {
    var user = out.connection.user;
    api.timeline(systemId, function(err, result) {
      logger.info('rsp: timeline');
      if (err) {
        return cb(err);
      }
      out.response(result);
      cb();
    });
  };

  var quitConnection = function(out, cb) {
    logger.info('rsp: quit');
    out.response({bye: 'bye!'}, function() {
      out.connection.end();
      cb();
    });
  };

  var handlers = {
    revision: {
      list: listRevisions,
      get: getRevision,
      mark: markRevision,
      preview: previewSystemDeploy
    },

    system: {
      list: listSystems,
      get: getSystem,
      create: createSystem,
      deployed: getDeployed,
      deploy: deploySystem,
      analyze: analyzeSystem,
      check: checkSystem,
      sync: syncSystem,
      clone: cloneSystem,
      //disabled by @mcollina
      //delete: deleteSystem
    },

    container: {
      list: listContainers,
      //delete: deleteContainer,
      build: buildContainer
    },

    timeline: {
      list: timeline
    },

    remote: {
      add: addRemote
    }
  };

  function forEachHandler(current, base, callback) {
    if (typeof current === 'function') {
      callback = current;
      current = handlers;
      base = "";
    }
    Object.keys(current).forEach(function(key) {
      var newBase = base + key + ' '
      if (typeof current[key] === 'function') {
        callback(newBase.trim(), current[key])
      } else {
        forEachHandler(current[key], newBase, callback)
      }
    })
  }

  var _server = new bcksrv();

  forEachHandler(function(command, func) {
    _server.register(command, function(args, stream, cb) {
      //var req = (command + ' ' + args.join(' ')).trim();
      var req = command;
      var out = netOut(stream, req, logger)
      var authorizedUser = authorized(stream, out);
      if (!authorizedUser) {return;}
      logger.info('rcv: ' + req);

      args.unshift(out);
      args.push(cb);
      func.apply(null, args);
    })
  });

  var handlersUnauthorized = {
    login: login,
    githubLogin: githubLogin,
    token: token,
    quit: quitConnection
  };

  Object.keys(handlersUnauthorized).forEach(function(cmd) {
    _server.register(cmd, function(args, stream, cb) {
      var req = cmd;
      var out = netOut(stream, req, logger)
      logger.info('rcv: ' + req);

      args.unshift(out);
      args.push(cb);
      handlersUnauthorized[cmd].apply(null, args);
    });
  });

  var handlersMultiline = {
    'system put': putSystem,
    //'container add': addContainer,
    //'container put': putContainer
  };

  Object.keys(handlersMultiline).forEach(function(cmd) {
    _server.register(cmd, { multiline: 'END' }, function(args, stream, multiline, cb) {
      //var req = cmd + ' ' + args.join(' ');
      var req = cmd;
      var out = netOut(stream, req, logger)
      var authorizedUser = authorized(stream, out);
      if (!authorizedUser) {return;}
      logger.info('rcv: ' + req);

      args.unshift(out);
      args.push(multiline);
      args.push(cb);
      handlersMultiline[cmd].apply(null, args);
    });
  })

  return {
    stream: function() {

      var stream = _server.stream();

      stream.on('commandError', function(cmd, args, err) {
        logger.error(err);
        args[0].response({result: 'err', err: err});
        stream.end();
      });

      return stream;
    },

    start: function(opts) {
      opts = opts || {}

      opts.port = opts.port || 3223;
      var that = this;

      var server = net.createServer(function(conn) {
        conn.pipe(that.stream()).pipe(conn);
      });

      server.listen(opts.port);

      return server;
    }
  };
};

<|endoftext|>


<commit_before>var clipboard = require("clipboard"),
    contextMenu = require("context-menu"),
    tabs = require("tabs"),
    xhr = require("xhr");
var selectors = 'link[rev=canonical],link[rel=shorturl],link[rel=shortlink]';

/** Find short URL in the page */
function findShortUrl(ctx) {
    let doc = ctx.document,
        short = doc.querySelector(selectors),
        link;
    if (short && (link = short.href))
        return link;
    return false;
}

/** Create a short URL from tinyurl.com */
function createShortUrl(ctx) {
    let req = new xhr.XMLHttpRequest(),
        url, canonical;
    // use canonical URL if it exists, current URL otherwise.
    canonical = ctx.document.querySelector('link[rel=canonical]');
    if (!(canonical && (url = canonical.href)))
        url = ctx.document.URL;

    req.open("GET", "http://tinyurl.com/api-create.php?url="
             +encodeURIComponent(url), false);
    req.send(null);
    if (req.status == 200) {
        console.log(url + ' --> ' + req.responseText);
        return req.responseText;
    } else {
        console.warning('ZOMG, could not create short URL.');
        return false;
    }
}

exports.main = function() {
    var item = contextMenu.Item({
        label: 'Copy ShortURL',
        onClick: function(ctx, item) {
            var url = findShortUrl(ctx);
            if (!url) {
                url = createShortUrl(ctx);
            }
            if (url) clipboard.set(url);
        }
    });
    contextMenu.add(item);
}
<commit_msg>Use notifications API to tell the user what has (or has not) happened. Closes #2.<commit_after>var clipboard = require("clipboard"),
    contextMenu = require("context-menu"),
    notifications = require("notifications"),
    tabs = require("tabs"),
    xhr = require("xhr");
var selectors = 'link[rev=canonical],link[rel=shorturl],link[rel=shortlink]';

/** Find short URL in the page */
function findShortUrl(ctx) {
    let doc = ctx.document,
        short = doc.querySelector(selectors),
        link;
    if (short && (link = short.href)) {
        notify("Short URL found:\n" + link);
        return link;
    }
    return false;
}

/** Create a short URL from tinyurl.com */
function createShortUrl(ctx) {
    let req = new xhr.XMLHttpRequest(),
        url, canonical;
    // use canonical URL if it exists, current URL otherwise.
    canonical = ctx.document.querySelector('link[rel=canonical]');
    if (!(canonical && (url = canonical.href)))
        url = ctx.document.URL;

    req.open("GET", "http://tinyurl.com/api-create.php?url="
             +encodeURIComponent(url), false);
    req.send(null);
    if (req.status == 200) {
        notify("No short URL found. Created alternative URL instead:\n" +
               url + ' --> ' + req.responseText);
        return req.responseText;
    } else {
        notify('ZOMG, error creating short URL.');
        return false;
    }
}

function notify(txt) {
    notifications.notify({text: txt});
}

exports.main = function() {
    var item = contextMenu.Item({
        label: 'Copy ShortURL',
        onClick: function(ctx, item) {
            var url = findShortUrl(ctx);
            if (!url) {
                url = createShortUrl(ctx);
            }
            if (url) clipboard.set(url);
        }
    });
    contextMenu.add(item);
}
<|endoftext|>


<commit_before>'use strict';

var https = require('https');
var querystring = require('querystring');

function setup_response_handler(req, callback) {
  if (typeof callback !== 'function') {
    //console.log('missing callback');
    return;
  }
  req.on('response',
    function(res) {
      var response = '';
      res.setEncoding('utf8');
      res.on('data',
        function(chunk) {
          response += chunk;
      });
      res.on('end',
        function() {
          var err = null;
          try {
            response = JSON.parse(response);
            if(200 != res.statusCode) {
              err = new Error(response.error.message);
              err.name = response.error.type;
              err.code = response.error.code;
              err.param = response.error.param;
              response = null;
            }
          }
          catch(e) {
            err = new Error('Invalid JSON from stripe.com');
            response = null;
          }
          callback(err, response);
      });
    });
  req.on('error', function(error){
    callback(error);
  });
}

var stripe = function()

module.exports = function (api_key, options) {
  var defaults = options || {};

  var auth = 'Basic ' + new Buffer(api_key + ':').toString('base64');

  function _request(method, path, data, callback) {

    //console.log('data', typeof data, data);

    // convert first level of deep data structures to foo[bar]=baz syntax
    Object.keys(data).forEach(function(key) {
      if (typeof data[key] === 'object' && data[key] !== null) {
        var o = data[key];
        delete data[key];
        Object.keys(o).forEach(function(k) {
          var new_key = key + '[' + k + ']';
          data[new_key] = o[k];
        });
      }
    });

    var request_data = querystring.stringify(data);

    //console.log(method, 'request for', path);
    //console.log('http request', request_data);

    var request_options = {
        host: 'api.stripe.com',
        port: '443',
        path: path,
        method: method,
        headers: {
          'Authorization': auth,
          'Accept': 'application/json',
          'Content-Type': 'application/x-www-form-urlencoded',
          'Content-Length': request_data.length
        }
      };

    var req = https.request(request_options);
    setup_response_handler(req, callback);
    req.write(request_data);
    req.end();
  }

  function post(path, data, callback) {
    _request('POST', path, data, callback);
  }

  function get(path, data, callback) {
    _request('GET', path, data, callback);
  }

  function del(path, data, callback) {
    _request('DELETE', path, data, callback);
  }

  function normalizeArguments() {
    var args = arguments[0];
    if(typeof args[0] == 'object' && typeof args[1] == 'function' && !args[2])
      return { count: args[0].count, offset: args[0].offset, cb: args[1] };
    else
      return { count: args[0], offset: args[1], cb: args[2] };
  }

  return {
    charges: {
      capture: function (charge_id, data, cb) {
        if (typeof data === 'function') {
          cb = data;
          data = {};
        }
        post('/v1/charges/' + charge_id + '/capture', data, cb);
      },
      create: function (data, cb) {
        post('/v1/charges', data, cb);
      },
      retrieve: function(charge_id, cb) {
        if(!(charge_id && typeof charge_id === 'string')) {
          cb('charge_id required');
        }
        get('/v1/charges/' + charge_id, {}, cb);
      },
      refund: function(charge_id, amount, cb) {
        var requestParams = {};
        if(!(charge_id && typeof charge_id === 'string')) {
          cb('charge_id required');
        }
        if (typeof amount === 'function') {
          cb = amount;
          amount = null;
        }
        if (amount) {
          requestParams.amount = amount;
        }
        post('/v1/charges/' + charge_id + '/refund', requestParams, cb);
      },
      list: function(data, cb) {
        get('/v1/charges', data, cb);
      },
    },
    customers: {
      create: function (data, cb) {
        post('/v1/customers', data, cb);
      },
      retrieve: function(customer_id, cb) {
        if (!(customer_id && typeof customer_id === 'string')) {
          return cb('customer_id required');
        }
        get('/v1/customers/' + customer_id, {}, cb);
      },
      update: function(customer_id, data, cb) {
        post('/v1/customers/' + customer_id, data, cb);
      },
      del: function(customer_id, cb) {
        del('/v1/customers/' + customer_id, {}, cb);
      },
      list: function(count, offset, cb) {
        var nArgs = normalizeArguments(arguments);
        get('/v1/customers', { count: nArgs.count, offset: nArgs.offset }, nArgs.cb);
      },
      update_subscription: function(customer_id, data, cb) {
        post('/v1/customers/' + customer_id + '/subscription', data, cb);
      },
      cancel_subscription: function(customer_id, at_period_end, cb) {
        del('/v1/customers/' + customer_id + '/subscription', { at_period_end: at_period_end }, cb);
      }
    },
    plans: {
      create: function (data, cb) {
        post('/v1/plans', data, cb);
      },
      retrieve: function(plan_id, cb) {
        if (!(plan_id && typeof plan_id === 'string')) {
          return cb('plan_id required');
        }
        get('/v1/plans/' + plan_id, {}, cb);
      },
      del: function(plan_id, cb) {
        del('/v1/plans/' + plan_id, {}, cb);
      },
      list: function(count, offset, cb) {
        var nArgs = normalizeArguments(arguments);
        get('/v1/plans', { count: nArgs.count, offset: nArgs.offset }, nArgs.cb);
      },
      update: function (plan_id, data, cb) {
        post('/v1/plans/' + plan_id, data, cb);
      }
    },
    invoices: {
      retrieve: function(invoice_id, cb) {
        get('/v1/invoices/' + invoice_id, {}, cb);
      },
      list: function(data, cb) {
        get('/v1/invoices', data, cb);
      },
      upcoming: function(customer_id, cb) {
        get('/v1/invoices/upcoming', { customer: customer_id }, cb);
      },
      create: function(customer_id, cb) {
        post('/v1/invoices', { customer: customer_id }, cb);
      },
      pay: function(invoice_id, cb) {
        post('/v1/invoices/'+invoice_id+'/pay', {}, cb);
      }
    },
    invoice_items: {
      create: function(data, cb) {
        post('/v1/invoiceitems', data, cb);
      },
      retrieve: function(invoice_item_id, cb) {
        if (!(invoice_item_id && typeof invoice_item_id === 'string')) {
          return cb('invoice_item_id required');
        }
        get('/v1/invoiceitems/' + invoice_item_id, {}, cb);
      },
      update: function(invoice_item_id, data, cb) {
        post('/v1/invoiceitems/' + invoice_item_id, data, cb);
      },
      del: function(invoice_item_id, cb) {
        del('/v1/invoiceitems/' + invoice_item_id, {}, cb);
      },
      list: function(customer_id, count, offset, cb) {
        var nArgs = normalizeArguments({count: count, offset: offset }, cb);
        get('/v1/invoiceitems', { customer: customer_id, count: count, offset: offset}, cb );
      }
    },
    coupons: {
      create: function (data, cb) {
        post('/v1/coupons', data, cb);
      },
      retrieve: function(coupon_id, cb) {
        if (!(coupon_id && typeof coupon_id === 'string')) {
          cb('coupon_id required');
        }
        get('/v1/coupons/' + coupon_id, {}, cb);
      },
      del: function(coupon_id, cb) {
        del('/v1/coupons/' + coupon_id, {}, cb);
      },
      list: function(count, offset, cb) {
        var nArgs = normalizeArguments(arguments);
        get('/v1/coupons', { count: nArgs.count, offset: nArgs.offset}, nArgs.cb );
      }
    },
    token: {
      create: function (data, cb) {
        post('/v1/tokens', data, cb)
      },
      retrieve: function (token_id, cb) {
        get('/v1/tokens/' + token_id, {}, cb)
      }
    },
    account: {
      retrieve: function (cb) {
        get('/v1/account', {}, cb)
      }
    },
    events: {
      retrieve: function (token_id, cb) {
        get('/v1/events/' + token_id, {}, cb)
      },
      list: function (cb) {
        get('/v1/events/', {}, cb)
      }
    },
    recipients: {
      create: function(data, cb) {
        post('/v1/recipients', data, cb);
      },
      retrieve: function(recipient_id, cb) {
        get('/v1/recipients/' + recipient_id, {}, cb);
      },
      update: function(recipient_id, data, cb) {
        post('/v1/recipients/' + recipient_id, data, cb);
      },
      del: function(recipient_id, cb) {
        del('/v1/recipients/' + recipient_id, {}, cb);
      },
      list: function(count, offset, cb) {
        var nArgs = normalizeArguments(arguments);
        get('/v1/recipients', { count: nArgs.count, offset: nArgs.offset }, nArgs.cb);
      }
    },
    transfers: {
      create: function(data, cb) {
        post('/v1/transfers', data, cb);
      },
      retrieve: function(transfer_id, cb) {
        get('/v1/transfers/' + transfer_id, {}, cb);
      },
      cancel: function(transfer_id, cb) {
        post('/v1/transfers/' + transfer_id + '/cancel', {}, cb);
      },
      list: function(count, offset, cb) {
        var nArgs = normalizeArguments(arguments);
        get('/v1/transfers', { count: nArgs.count, offset: nArgs.offset }, nArgs.cb);
      }
    },
    balance: {
      retrieve: function(cb) {
        get('/v1/balance', {}, cb);
      },
      list: function(count, offset, cb) {
        var nArgs = normalizeArguments(arguments);
        get('/v1/balance/history', { count: nArgs.count, offset: nArgs.offset }, nArgs.cb);
      }
    }
  };
}
<commit_msg>Partial not-working refactor<commit_after>'use strict';

var https = require('https');
var querystring = require('querystring');

var stripeOptions = {
  host: 'api.stripe.com',
  port: '443'
};

function Stripe(api_key) {
  this.auth = 'Basic ' + new Buffer(api_key + ':').toString('base64');

  this.charges._stripe = this;
  this.customers._stripe = this;
}

Stripe.prototype.charges = {
  capture: function (charge_id, data, cb) {
    if (data.constructor === Function) {
      cb = data;
      data = {};
    }
    post('/v1/charges/' + charge_id + '/capture', data, cb, this._stripe);
  },
  create: function (data, cb) {
    post('/v1/charges', data, cb, this._stripe);
  },
  retrieve: function(charge_id, cb) {
    if (!charge_id || charge_id.constructor !== String)) {
      cb('charge_id required.');
    }
    get('/v1/charges/' + charge_id, {}, cb, this._stripe);
  },
  refund: function(charge_id, amount, cb) {
    var requestParams = {};
    if(!(charge_id && typeof charge_id === 'string')) {
      cb('charge_id required');
    }
    if (typeof amount === 'function') {
      cb = amount;
      amount = null;
    }
    if (amount) {
      requestParams.amount = amount;
    }
    post('/v1/charges/' + charge_id + '/refund', requestParams, cb, this._stripe);
  },
  list: function(data, cb) {
    get('/v1/charges', data, cb, this._stripe);
  }
}

// TODO(michelle): some args make no sense and also multiple cards!
Stripe.prototype.customers = {
  create: function (data, cb) {
    post('/v1/customers', data, cb, this._stripe);
  },
  retrieve: function(customer_id, cb) {
    if (!customer_id || customer_id.constructor !== String) {
      return cb('customer_id required.');
    }
    get('/v1/customers/' + customer_id, {}, cb, this._stripe);
  },
  update: function(customer_id, data, cb) {
    post('/v1/customers/' + customer_id, data, cb, this._stripe);
  },
  remove: function(customer_id, cb) {
    remove('/v1/customers/' + customer_id, {}, cb, this._stripe);
  },
  list: function(count, offset, cb) {
    var nArgs = normalizeArguments(arguments);
    get('/v1/customers', {count: nArgs.count, offset: nArgs.offset}, nArgs.cb, this._stripe);
  },
  update_subscription: function(customer_id, data, cb) {
    post('/v1/customers/' + customer_id + '/subscription', data, cb, this._stripe);
  },
  cancel_subscription: function(customer_id, at_period_end, cb) {
    remove('/v1/customers/' + customer_id + '/subscription', {at_period_end: at_period_end}, cb, this._stripe);
  }
}

Stripe.prototype.plans = {
  create: function (data, cb) {
    post('/v1/plans', data, cb, this._stripe);
  },
  retrieve: function(plan_id, cb) {
    if (!(plan_id && typeof plan_id === 'string')) {
      return cb('plan_id required');
    }
    get('/v1/plans/' + plan_id, {}, cb);
  },
  remove: function(plan_id, cb) {
    remove('/v1/plans/' + plan_id, {}, cb);
  },
  list: function(count, offset, cb) {
    var nArgs = normalizeArguments(arguments);
    get('/v1/plans', { count: nArgs.count, offset: nArgs.offset }, nArgs.cb);
  },
  update: function(plan_id, data, cb) {
    post('/v1/plans/' + plan_id, data, cb);
  }
}

    invoices: {
      retrieve: function(invoice_id, cb) {
        get('/v1/invoices/' + invoice_id, {}, cb);
      },
      list: function(data, cb) {
        get('/v1/invoices', data, cb);
      },
      upcoming: function(customer_id, cb) {
        get('/v1/invoices/upcoming', { customer: customer_id }, cb);
      },
      create: function(customer_id, cb) {
        post('/v1/invoices', { customer: customer_id }, cb);
      },
      pay: function(invoice_id, cb) {
        post('/v1/invoices/'+invoice_id+'/pay', {}, cb);
      }
    },

    invoice_items: {
      create: function(data, cb) {
        post('/v1/invoiceitems', data, cb);
      },
      retrieve: function(invoice_item_id, cb) {
        if (!(invoice_item_id && typeof invoice_item_id === 'string')) {
          return cb('invoice_item_id required');
        }
        get('/v1/invoiceitems/' + invoice_item_id, {}, cb);
      },
      update: function(invoice_item_id, data, cb) {
        post('/v1/invoiceitems/' + invoice_item_id, data, cb);
      },
      remove: function(invoice_item_id, cb) {
        remove('/v1/invoiceitems/' + invoice_item_id, {}, cb);
      },
      list: function(customer_id, count, offset, cb) {
        var nArgs = normalizeArguments({count: count, offset: offset }, cb);
        get('/v1/invoiceitems', { customer: customer_id, count: count, offset: offset}, cb );
      }
    },

    coupons: {
      create: function (data, cb) {
        post('/v1/coupons', data, cb);
      },
      retrieve: function(coupon_id, cb) {
        if (!(coupon_id && typeof coupon_id === 'string')) {
          cb('coupon_id required');
        }
        get('/v1/coupons/' + coupon_id, {}, cb);
      },
      remove: function(coupon_id, cb) {
        remove('/v1/coupons/' + coupon_id, {}, cb);
      },
      list: function(count, offset, cb) {
        var nArgs = normalizeArguments(arguments);
        get('/v1/coupons', { count: nArgs.count, offset: nArgs.offset}, nArgs.cb );
      }
    },

    token: {
      create: function (data, cb) {
        post('/v1/tokens', data, cb)
      },
      retrieve: function (token_id, cb) {
        get('/v1/tokens/' + token_id, {}, cb)
      }
    },

    account: {
      retrieve: function (cb) {
        get('/v1/account', {}, cb)
      }
    },

    events: {
      retrieve: function (token_id, cb) {
        get('/v1/events/' + token_id, {}, cb)
      },
      list: function (cb) {
        get('/v1/events/', {}, cb)
      }
    },

    recipients: {
      create: function(data, cb) {
        post('/v1/recipients', data, cb);
      },
      retrieve: function(recipient_id, cb) {
        get('/v1/recipients/' + recipient_id, {}, cb);
      },
      update: function(recipient_id, data, cb) {
        post('/v1/recipients/' + recipient_id, data, cb);
      },
      remove: function(recipient_id, cb) {
        remove('/v1/recipients/' + recipient_id, {}, cb);
      },
      list: function(count, offset, cb) {
        var nArgs = normalizeArguments(arguments);
        get('/v1/recipients', { count: nArgs.count, offset: nArgs.offset }, nArgs.cb);
      }
    },

}

Stripe.prototype,transfers = {
  create: function(data, cb) {
    this._stripe._post('/v1/transfers', data, cb);
  },
  retrieve: function(transfer_id, cb) {
    this._stripe._get('/v1/transfers/' + transfer_id, {}, cb);
  },
  cancel: function(transfer_id, cb) {
    this._stripe._post('/v1/transfers/' + transfer_id + '/cancel', {}, cb);
  },
  list: function(count, offset, cb) {
    var nArgs = normalizeArguments(arguments);
    this._stripe._get('/v1/transfers', { count: nArgs.count, offset: nArgs.offset }, nArgs.cb);
  }
}

Stripe.prototype.balance = {
  retrieve: function(cb) {
    get('/v1/balance', {}, cb);
  },
  list: function(count, offset, cb) {
    var nArgs = normalizeArguments(arguments);
    get('/v1/balance/history', { count: nArgs.count, offset: nArgs.offset }, nArgs.cb);
  }
}

Stripe.prototype._request = function(method, path, data, callback) {
  // Convert first level of nexted data structures to `foo[bar]=baz` syntax.
  var keys = Object.keys(data);
  for (var i = 0, ii = keys.length; i < ii; i += 1) {
    var key = keys[i];
    if (data[key] !== null && data[key].constructor === Object) {
      var nested = data[key];
      var nestedKeys = Object.keys(nested);
      delete data[key];

      for (var j = nestedKeys, jj = nestedKeys.length; j < jj; j += 1) {
        var nestedKey = nestedKeys[j];
        data[key + '[' + k + ']'] = nested[nestedKey];
      }
    }
  }

  var requestData = querystring.stringify(data);
  var requestOptions = {
    host: stripeOptions.host,
    port: stripeOptions.port,
    path: path,
    method: method,
    headers: {
      'Authorization': this.auth,
      'Accept': 'application/json',
      'Content-Type': 'application/x-www-form-urlencoded',
      'Content-Length': requestData.length
    }
  };

  var req = https.request(requestOptions);
  setupResponseHandler(req, callback);
  req.write(requestData);
  req.end();
}

Stripe.prototype._post = function(path, data, callback) {
  this._request('POST', path, data, callback);
}

Stripe.prototype._get = function(path, data, callback) {
  this._request('GET', path, data, callback);
}

Stripe.prototype._remove = function(path, data, callback) {
  this._request('DELETE', path, data, callback);
}

/** Set up HTTPS response and error handlers. */
function setupResponseHandler(req, callback) {
  if (typeof callback !== 'function') {
    throw new Error("You didn't pass in a callback. See https://stripe.com/docs/api/node for code examples.");
    return;
  }
  req.on('response', function(res) {
    var response = '';

    res.setEncoding('utf8');
    res.on('data', function(chunk) {
      response += chunk;
    });
    res.on('end', function() {
      var err = null;
      try {
        response = JSON.parse(response);
        if(200 != res.statusCode) {
          err = new Error(response.error.message);
          err.name = response.error.type;
          err.code = response.error.code;
          err.param = response.error.param;
          response = null;
        }
      } catch(e) {
        err = new Error('Invalid JSON from stripe.com');
        response = null;
      }
      callback(err, response);
    });
  });

  req.on('error', function(error) {
    callback(error);
  });
}

// TODO(michelle): this still needed?
function normalizeArguments() {
  var args = arguments[0];
  if (typeof args[0] == 'object' && typeof args[1] == 'function' && !args[2]) {
    return {count: args[0].count, offset: args[0].offset, cb: args[1]};
  } else {
    return {count: args[0], offset: args[1], cb: args[2]};
  }
}

module.exports = Stripe;
<|endoftext|>


<commit_before>/*
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * ndf command protocol
 *
 * list systems
 * list container systemid
 *
 *
 */

'use strict';

var bcksrv = require('bcksrv');
var netOut = require('./networkOut');

module.exports = function(api, auth, logger) {

  var login = function(out, username, password, cb) {
    auth.login(username, password, function(err, result) {
      if (err) {
        return cb(err)
      }
      if (result.user) {
        out.connection.user = result.user;
      }
      out.response(result);
    });
  };

  var token = function(out, token, cb) {
    auth.userInfo(token, function(err, user) {
      if (err) { return cb(err); }
      out.connection.user = user;
      out.response(user);
      cb();
    });
  };

  var authorized = function(connection, out) {
    if (!connection.user) {
      out.response({ok:false, err:'Unauthorized'});
    }
    return connection.user;
  };

  var githubLogin = function(out, accessToken, cb) {
    auth.githubLogin(accessToken, function(err, result) {
      if (err) {logger.error(err); return out.stderr(err);}
      if (result.user) {
        out.connection.user = result.user;
      }
      out.response(result);
    });
  };

  var listSystems = function(out, cb) {
    api.listSystems(function(err, systems) {
      if (err) { return cb(err); }

      logger.info('rsp: list systems');
      out.response(systems);
      cb();
    });
  };

  var createSystem = function(out, name, namespace, cb) {
    api.createSystem(out.connection.user, name, namespace, function(err, system) {
      if (err) {
        return cb(err);
      }
      logger.info('rsp: create system');
      out.response(system);
      cb();
    });
  };

  var getSystem = function(out, systemId, cb) {
    api.getHeadSystem(systemId, function(err, system) {
      logger.info('rsp: get system ' + systemId);
      if (err) {
        return cb(err);
      }
      out.response(system);
      cb();
    });
  };

  var getDeployed = function(out, systemId, cb) {
    api.getDeployedSystem(systemId, function(err, system) {
      if (err) {
        return cb(err);
      }
      logger.info('rsp: get deployed ' + systemId);
      out.response(system);
      cb();
    });
  };

  var putSystem = function(out, systemJson, cb) {
    api.putSystem(out.connection.user, systemJson, function(err) {
      logger.info('rsp: put system');
      if (err) {
        return cb(err);
      }
      out.response({result: 'ok'});
      cb();
    });
  };

  // disabled by @mcollina
  //var deleteSystem = function(out, user, systemId) {
  //  api.deleteSystem(user, systemId, function(err) {
  //    logger.info('rsp: delete system');
  //    if (err) { out.response({result: 'err', err: err}); }
  //    else { out.response({result: 'ok'}); }
  //  });
  //};

  var cloneSystem = function(out, url, cb) {
    api.cloneSystem(out.connection.user, url, function(err) {
      logger.info('rsp: clone system');
      if (err) {
        return cb(err);
      }
      out.response({result: 'ok'});
      cb();
    });
  };

  var syncSystem = function(out, systemId, cb) {
    api.syncSystem(out.connection.user, systemId, function(err) {
      logger.info('rsp: sync system');
      if (err) {
        return cb(err);
      }
      out.response({result: 'ok'});
      cb()
    });
  };

  var addRemote = function(out, systemId, url, cb) {
    api.addRemote(out.connection.user, systemId, url, function(err) {
      logger.info('rsp: add remote');
      if (err) {
        return cb(err);
      }
      out.response({result: 'ok'});
      cb();
    });
  };

  var listContainers = function(out, systemId, cb) {
    api.listContainers(systemId, function(err, containers) {
      logger.info('rsp: list containers ' + systemId);
      if (err) {
        return cb(err);
      }
      out.response(containers);
      cb();
    });
  };

  //var addContainer = function(out, user, containerJson, systemId) {
  //  api.addContainer(user, systemId, containerJson, function(err) {
  //    logger.info('rsp: add container');
  //    if (err) { out.response({result: 'err', err: err}); }
  //    else { out.response({result: 'ok'}); }
  //  });
  //};

  //var putContainer = function(out, user, containerJson, systemId) {
  //  api.putContainer(user, systemId, containerJson, function(err) {
  //    logger.info('rsp: put container');
  //    if (err) { out.response({result: 'err', err: err}); }
  //    else { out.response({result: 'ok'}); }
  //  });
  //};

  //var deleteContainer = function(out, user, systemId, containerId) {
  //  api.deleteContainer(user, systemId, containerId, function(err) {
  //    logger.info('rsp: delete container');
  //    if (err) { out.response({result: 'err', err: err}); }
  //    else { out.response({result: 'ok'}); }
  //  });
  //};

  var buildContainer = function(out, systemId, containerId, cb) {
    api.buildContainer(out.connection.user, systemId, containerId, out, function(err, result) {
      logger.info('rsp: build container ' + systemId);
      if (err) {
        return cb(err);
      }
      out.response(result);
      cb();
    });
  };

  var deploySystem = function(out, systemId, revisionId, cb) {
    var user = out.connection.user;
    api.deploySystem(user, systemId, revisionId, 'live', out, function(err, result) {
      logger.info('rsp: deploy system ' + user + ' ' + systemId + ' ' + revisionId);
      if (err) {
        return cb(err);
      }
      out.response(result);
      cb();
    });
  };

  var analyzeSystem = function(out, user, systemId) {
    api.analyzeSystem(user, systemId, out, function(err, result) {
      logger.info('rsp: analyze system ' + user + ' ' + systemId);
      out.response(result);
    });
  };

  var checkSystem = function(out, user, systemId) {
    api.checkSystem(user, systemId, function(err, result) {
      logger.info('rsp: check system ' + user + ' ' + systemId);
      out.response(result);
    });
  };

  var markRevision = function(out, user, systemId, revisionId) {
    api.markRevision(user, systemId, revisionId, function(err, result) {
      logger.info('rsp: mark revision ' + user + ' ' + systemId + ' ' + revisionId);
      out.response(result);
    });
  };

  var previewSystemDeploy = function(out, user, systemId, revisionId) {
    api.previewSystemDeploy(user, systemId, revisionId, out, function(err, result) {
      logger.info('rsp: deploy system ' + user + ' ' + systemId + ' ' + revisionId);
      out.response(result);
    });
  };

  var listRevisions = function(out, user, systemId) {
    api.listRevisions(systemId, function(err, result) {
      logger.info('rsp: list revisions ' + systemId);
      out.response(result);
    });
  };

  var getRevision = function(out, user, systemId, revisionId) {
    api.getRevision(systemId, revisionId, function(err, result) {
      logger.info('rsp: get revision ' + systemId);
      out.response(result);
    });
  };

  var timeline = function(out, user, systemId) {
    api.timeline(systemId, function(err, result) {
      logger.info('rsp: timeline');
      out.response(result);
    });
  };

  var quitConnection = function(out, cb) {
    logger.info('rsp: quit');
    out.response({bye: 'bye!'}, function() {
      out.connection.end();
      cb();
    });
  };

  var handlers = {
    revision: {
      list: listRevisions,
      get: getRevision,
      mark: markRevision,
      preview: previewSystemDeploy
    },

    system: {
      list: listSystems,
      get: getSystem,
      create: createSystem,
      deployed: getDeployed,
      deploy: deploySystem,
      analyze: analyzeSystem,
      check: checkSystem,
      sync: syncSystem,
      clone: cloneSystem,
      //disabled by @mcollina
      //delete: deleteSystem
    },

    container: {
      list: listContainers,
      //delete: deleteContainer,
      build: buildContainer
    },

    timeline: {
      list: timeline
    },

    remote: {
      add: addRemote
    }
  };

  function forEachHandler(current, base, callback) {
    if (typeof current === 'function') {
      callback = current;
      current = handlers;
      base = "";
    }
    Object.keys(current).forEach(function(key) {
      var newBase = base + key + ' '
      if (typeof current[key] === 'function') {
        callback(newBase.trim(), current[key])
      } else {
        forEachHandler(current[key], newBase, callback)
      }
    })
  }

  var _server = new bcksrv();

  forEachHandler(function(command, func) {
    _server.register(command, function(args, stream, cb) {
      //var req = (command + ' ' + args.join(' ')).trim();
      var req = command;
      var out = netOut(stream, req, logger)
      var authorizedUser = authorized(stream, out);
      if (!authorizedUser) {return;}
      logger.info('rcv: ' + req);

      args.unshift(out);
      args.push(cb);
      func.apply(null, args);
    })
  });

  var handlersUnauthorized = {
    login: login,
    githubLogin: githubLogin,
    token: token,
    quit: quitConnection
  };

  Object.keys(handlersUnauthorized).forEach(function(cmd) {
    _server.register(cmd, function(args, stream, cb) {
      var req = cmd;
      var out = netOut(stream, req, logger)
      logger.info('rcv: ' + req);

      args.unshift(out);
      args.push(cb);
      handlersUnauthorized[cmd].apply(null, args);
    });
  });

  var handlersMultiline = {
    'system put': putSystem,
    //'container add': addContainer,
    //'container put': putContainer
  };

  Object.keys(handlersMultiline).forEach(function(cmd) {
    _server.register(cmd, { multiline: 'END' }, function(args, stream, multiline, cb) {
      //var req = cmd + ' ' + args.join(' ');
      var req = cmd;
      var out = netOut(stream, req, logger)
      var authorizedUser = authorized(stream, out);
      if (!authorizedUser) {return;}
      logger.info('rcv: ' + req);

      args.unshift(out);
      args.push(multiline);
      args.push(cb);
      handlersMultiline[cmd].apply(null, args);
    });
  })

  return {
    stream: function() {

      var stream = _server.stream();

      stream.on('commandError', function(cmd, args, err) {
        logger.error(err);
        args[0].response({result: 'err', err: err});
        stream.end();
      });

      return stream;
    }
  };
};

<commit_msg>githubLogin.<commit_after>/*
 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

/*
 * ndf command protocol
 *
 * list systems
 * list container systemid
 *
 *
 */

'use strict';

var bcksrv = require('bcksrv');
var netOut = require('./networkOut');

module.exports = function(api, auth, logger) {

  var login = function(out, username, password, cb) {
    auth.login(username, password, function(err, result) {
      if (err) {
        return cb(err)
      }
      if (result.user) {
        out.connection.user = result.user;
      }
      out.response(result);
    });
  };

  var token = function(out, token, cb) {
    auth.userInfo(token, function(err, user) {
      if (err) { return cb(err); }
      out.connection.user = user;
      out.response(user);
      cb();
    });
  };

  var authorized = function(connection, out) {
    if (!connection.user) {
      out.response({ok:false, err:'Unauthorized'});
    }
    return connection.user;
  };

  var githubLogin = function(out, accessToken, cb) {
    auth.githubLogin(accessToken, function(err, result) {
      if (err) { return cb(err); }
      if (result.user) {
        out.connection.user = result.user;
      }
      out.response(result);
      cb();
    });
  };

  var listSystems = function(out, cb) {
    api.listSystems(function(err, systems) {
      if (err) { return cb(err); }

      logger.info('rsp: list systems');
      out.response(systems);
      cb();
    });
  };

  var createSystem = function(out, name, namespace, cb) {
    api.createSystem(out.connection.user, name, namespace, function(err, system) {
      if (err) {
        return cb(err);
      }
      logger.info('rsp: create system');
      out.response(system);
      cb();
    });
  };

  var getSystem = function(out, systemId, cb) {
    api.getHeadSystem(systemId, function(err, system) {
      logger.info('rsp: get system ' + systemId);
      if (err) {
        return cb(err);
      }
      out.response(system);
      cb();
    });
  };

  var getDeployed = function(out, systemId, cb) {
    api.getDeployedSystem(systemId, function(err, system) {
      if (err) {
        return cb(err);
      }
      logger.info('rsp: get deployed ' + systemId);
      out.response(system);
      cb();
    });
  };

  var putSystem = function(out, systemJson, cb) {
    api.putSystem(out.connection.user, systemJson, function(err) {
      logger.info('rsp: put system');
      if (err) {
        return cb(err);
      }
      out.response({result: 'ok'});
      cb();
    });
  };

  // disabled by @mcollina
  //var deleteSystem = function(out, user, systemId) {
  //  api.deleteSystem(user, systemId, function(err) {
  //    logger.info('rsp: delete system');
  //    if (err) { out.response({result: 'err', err: err}); }
  //    else { out.response({result: 'ok'}); }
  //  });
  //};

  var cloneSystem = function(out, url, cb) {
    api.cloneSystem(out.connection.user, url, function(err) {
      logger.info('rsp: clone system');
      if (err) {
        return cb(err);
      }
      out.response({result: 'ok'});
      cb();
    });
  };

  var syncSystem = function(out, systemId, cb) {
    api.syncSystem(out.connection.user, systemId, function(err) {
      logger.info('rsp: sync system');
      if (err) {
        return cb(err);
      }
      out.response({result: 'ok'});
      cb()
    });
  };

  var addRemote = function(out, systemId, url, cb) {
    api.addRemote(out.connection.user, systemId, url, function(err) {
      logger.info('rsp: add remote');
      if (err) {
        return cb(err);
      }
      out.response({result: 'ok'});
      cb();
    });
  };

  var listContainers = function(out, systemId, cb) {
    api.listContainers(systemId, function(err, containers) {
      logger.info('rsp: list containers ' + systemId);
      if (err) {
        return cb(err);
      }
      out.response(containers);
      cb();
    });
  };

  //var addContainer = function(out, user, containerJson, systemId) {
  //  api.addContainer(user, systemId, containerJson, function(err) {
  //    logger.info('rsp: add container');
  //    if (err) { out.response({result: 'err', err: err}); }
  //    else { out.response({result: 'ok'}); }
  //  });
  //};

  //var putContainer = function(out, user, containerJson, systemId) {
  //  api.putContainer(user, systemId, containerJson, function(err) {
  //    logger.info('rsp: put container');
  //    if (err) { out.response({result: 'err', err: err}); }
  //    else { out.response({result: 'ok'}); }
  //  });
  //};

  //var deleteContainer = function(out, user, systemId, containerId) {
  //  api.deleteContainer(user, systemId, containerId, function(err) {
  //    logger.info('rsp: delete container');
  //    if (err) { out.response({result: 'err', err: err}); }
  //    else { out.response({result: 'ok'}); }
  //  });
  //};

  var buildContainer = function(out, systemId, containerId, cb) {
    api.buildContainer(out.connection.user, systemId, containerId, out, function(err, result) {
      logger.info('rsp: build container ' + systemId);
      if (err) {
        return cb(err);
      }
      out.response(result);
      cb();
    });
  };

  var deploySystem = function(out, systemId, revisionId, cb) {
    var user = out.connection.user;
    api.deploySystem(user, systemId, revisionId, 'live', out, function(err, result) {
      logger.info('rsp: deploy system ' + user + ' ' + systemId + ' ' + revisionId);
      if (err) {
        return cb(err);
      }
      out.response(result);
      cb();
    });
  };

  var analyzeSystem = function(out, user, systemId) {
    api.analyzeSystem(user, systemId, out, function(err, result) {
      logger.info('rsp: analyze system ' + user + ' ' + systemId);
      out.response(result);
    });
  };

  var checkSystem = function(out, user, systemId) {
    api.checkSystem(user, systemId, function(err, result) {
      logger.info('rsp: check system ' + user + ' ' + systemId);
      out.response(result);
    });
  };

  var markRevision = function(out, user, systemId, revisionId) {
    api.markRevision(user, systemId, revisionId, function(err, result) {
      logger.info('rsp: mark revision ' + user + ' ' + systemId + ' ' + revisionId);
      out.response(result);
    });
  };

  var previewSystemDeploy = function(out, user, systemId, revisionId) {
    api.previewSystemDeploy(user, systemId, revisionId, out, function(err, result) {
      logger.info('rsp: deploy system ' + user + ' ' + systemId + ' ' + revisionId);
      out.response(result);
    });
  };

  var listRevisions = function(out, user, systemId) {
    api.listRevisions(systemId, function(err, result) {
      logger.info('rsp: list revisions ' + systemId);
      out.response(result);
    });
  };

  var getRevision = function(out, user, systemId, revisionId) {
    api.getRevision(systemId, revisionId, function(err, result) {
      logger.info('rsp: get revision ' + systemId);
      out.response(result);
    });
  };

  var timeline = function(out, user, systemId) {
    api.timeline(systemId, function(err, result) {
      logger.info('rsp: timeline');
      out.response(result);
    });
  };

  var quitConnection = function(out, cb) {
    logger.info('rsp: quit');
    out.response({bye: 'bye!'}, function() {
      out.connection.end();
      cb();
    });
  };

  var handlers = {
    revision: {
      list: listRevisions,
      get: getRevision,
      mark: markRevision,
      preview: previewSystemDeploy
    },

    system: {
      list: listSystems,
      get: getSystem,
      create: createSystem,
      deployed: getDeployed,
      deploy: deploySystem,
      analyze: analyzeSystem,
      check: checkSystem,
      sync: syncSystem,
      clone: cloneSystem,
      //disabled by @mcollina
      //delete: deleteSystem
    },

    container: {
      list: listContainers,
      //delete: deleteContainer,
      build: buildContainer
    },

    timeline: {
      list: timeline
    },

    remote: {
      add: addRemote
    }
  };

  function forEachHandler(current, base, callback) {
    if (typeof current === 'function') {
      callback = current;
      current = handlers;
      base = "";
    }
    Object.keys(current).forEach(function(key) {
      var newBase = base + key + ' '
      if (typeof current[key] === 'function') {
        callback(newBase.trim(), current[key])
      } else {
        forEachHandler(current[key], newBase, callback)
      }
    })
  }

  var _server = new bcksrv();

  forEachHandler(function(command, func) {
    _server.register(command, function(args, stream, cb) {
      //var req = (command + ' ' + args.join(' ')).trim();
      var req = command;
      var out = netOut(stream, req, logger)
      var authorizedUser = authorized(stream, out);
      if (!authorizedUser) {return;}
      logger.info('rcv: ' + req);

      args.unshift(out);
      args.push(cb);
      func.apply(null, args);
    })
  });

  var handlersUnauthorized = {
    login: login,
    githubLogin: githubLogin,
    token: token,
    quit: quitConnection
  };

  Object.keys(handlersUnauthorized).forEach(function(cmd) {
    _server.register(cmd, function(args, stream, cb) {
      var req = cmd;
      var out = netOut(stream, req, logger)
      logger.info('rcv: ' + req);

      args.unshift(out);
      args.push(cb);
      handlersUnauthorized[cmd].apply(null, args);
    });
  });

  var handlersMultiline = {
    'system put': putSystem,
    //'container add': addContainer,
    //'container put': putContainer
  };

  Object.keys(handlersMultiline).forEach(function(cmd) {
    _server.register(cmd, { multiline: 'END' }, function(args, stream, multiline, cb) {
      //var req = cmd + ' ' + args.join(' ');
      var req = cmd;
      var out = netOut(stream, req, logger)
      var authorizedUser = authorized(stream, out);
      if (!authorizedUser) {return;}
      logger.info('rcv: ' + req);

      args.unshift(out);
      args.push(multiline);
      args.push(cb);
      handlersMultiline[cmd].apply(null, args);
    });
  })

  return {
    stream: function() {

      var stream = _server.stream();

      stream.on('commandError', function(cmd, args, err) {
        logger.error(err);
        args[0].response({result: 'err', err: err});
        stream.end();
      });

      return stream;
    }
  };
};

<|endoftext|>


<commit_before>
const colourise = {
	red: function (x) {return x}
}

const fromStream = ( function () {

	var self = {}

	/*
		-------------------------------- Generators --------------------------------

	*/

	// -------------------------------- numeric --------------------------------

	self.number = function (len) {
		// uniform random number of a given order 'len'.

		const sign  = Math.random() > 0.5? +1: -1
		return sign * Math.random() * Math.pow(10, len)
	}
	self.integer = function (len) {
		// uniform random integer of a given order 'len'.

		return Math.round(self.number(len))
	}

	self.nan    = function (len) {
		return NaN
	}

	// -------------------------------- character --------------------------------

	self.alphabetical = (function () {
		// uppercase and lowecase letters in a string of length 'len'.

		const charset =
			'abcdefghijklmnopqrstuvwxyz' +
			'ABCDEFGHIJKLMNOPQRSTUVWXYZ'

		return function (len) {

			var out = ''

			for (var ith = 0; ith < len; ith++) {
				out += charset.charAt(Math.random * charset.length)
			}

			return out
		}

	})()

	/*
		-------------------------------- Sampler --------------------------------

	*/

	return function (len) {
		// return a random generator.

		const generators     = Object.keys(self)
		const whichGenerator = generators[Math.floor(Math.random() * generators.length)]

		return self[whichGenerator](len)
	}

} )()

console.log(fromStream(3))

const runTest = function () {

}

/*

*/

const yieldCase = function (params) {

	return params.map(function (param) {
		return fromStream()
	})

}

const throwPropertyError = function (testData, state) {

}

const messageSuccess = function (states, info) {

}

const whenTest = function (prop, testcase) {
	// simply call the predicate with the testcase.

	return prop.apply(null, testcase)
}

const validateTest = function (test) {
	/*
		ensure that the test being passed to run
		can be executed properly.
	*/

	// throw an error if any fields are missing.
	;['info', 'params', 'time'].forEach(function (key) {

		if (!test.hasOwnProperty(key)) {
			var message =
				"the property '" + key + "' was missing from the test object."

			throw colourise.red(message)
		}
	})

	// time mustn't be NaN
	if (test.time !== test.time) {

		var message =
			'time must not be NaN.'

		throw colourise.red(message)
	}

	// time definitely mustn't be Infinite
	if (!isFinite(test.time)) {

		var message =
			'time must not be infinite.'

		throw colourise.red(message)
	}

	// time must be positive
	if (test.time < 0) {
		var message =
			'time must be positive.'

		throw colourise.red(message)
	}

	return true
}

const executeTest = function (test) {

	validateTest(test)

}

/*
	-------------------------------- Grammar --------------------------------

	describe(string)            add a description to a property group. Concatanative property.

	over([string])              the parametres to bind random variables to.
	                            Overriding property.

	over_(string_)              the parametres to bind random variables to.
	                            Overriding property.

	when(Function, [Function])  when a predicate is true, assert that several other
	                            predicates are also true. Concatanative property.

	when_(Function_)            when a predicate is true, assert that several other
	                            predicates are also true. Concatanative property.

	run(number)                 triggers the start of a test, specifies how long the test runs for.
*/

const describe = function (info) {

	var self  = joinTest(this, {
		info : info,
		type : 'describe'
	})

	return self
}

const over = function (params) {

	var self  = joinTest(this, {
		params 	: params,
		type   	: 'over'
	})

	return self
}

const over_ = function () {

	const args = Array.prototype.slice.call(arguments)

	var self  = joinTest(this, {
		params 	: args,
		type   	: 'over'
	})

	return self
}

const when = function (pred, preds) {

	var self  = joinTest(this, {
		positives : [pred].concat(preds),
		type      : 'when'
	})

	return self
}

const when_ = function () {

	const args = Array.prototype.slice.call(arguments)

	var self  = joinTest(this, {
		positives : args,
		type      : 'when'
	})

	return self
}

const run = function (time) {

	var self  = joinTest(this, {
		time : time,
		type : 'run'
	})

	return self
}

const _forallProto = {
	run      : run,

	over     : over,
	over_    : over_,

	when     : when,
	when_    : when_,

	describe : describe
}

const joinTest = function (acc, left) {

	if (acc.GLOBAL || acc.window) {
		// a heuristic for detecting the global context.
		var acc = Object.create(_forallProto)
	}

	const override = function (key) {
		return function () {

			acc[key] = left[key]
			return acc

		}
	}

	const join = function (key) {
		return function () {

			if (acc[key]) {
				acc[key] = acc[key].concat( [left[key]] )
			} else {
				acc[key] = [left[key]]
			}

			return acc
		}
	}

	const responses = {
		describe : join('info'),
		over     : override('params'),
		when     : join('positives'),
		run      : function () {

			acc.time = left.time

			executeTest(acc)
		}
	}

	for (type in responses) {

		if (left.type === type) {
			return responses[type]()
		}
	}

}

a =
over_('a', 'b')

. describe('this is a string')
. when_(
	function (a, b) {a + b === b + a}
)

. describe('this')
. when_(
	function (a) {a}
)
.run(10)<commit_msg>implemented some of the actual testing functions.<commit_after>
const colourise = {
	red: function (x) {return x}
}

const fromStream = ( function () {

	var self = {}

	/*
		-------------------------------- Generators --------------------------------

	*/

	// -------------------------------- numeric --------------------------------

	self.number = function (len) {
		// uniform random number of a given order 'len'.

		const  sign = Math.random() > 0.5? +1: -1
		return sign * Math.random() * Math.pow(10, len)
	}
	self.integer = function (len) {
		// uniform random integer of a given order 'len'.

		return Math.round(self.number(len))
	}

	self.nan    = function (len) {
		return NaN
	}

	// -------------------------------- character --------------------------------

	self.alphabetical = (function () {
		// uppercase and lowecase letters in a string of length 'len'.

		const charset =
			'abcdefghijklmnopqrstuvwxyz' +
			'ABCDEFGHIJKLMNOPQRSTUVWXYZ'

		return function (len) {

			var out = ''

			for (var ith = 0; ith < len; ith++) {
				out += charset.charAt(Math.random * charset.length)
			}

			return out
		}

	})()

	/*
		-------------------------------- Sampler --------------------------------

	*/

	return function (len) {
		// return a random generator.

		const generators = Object.keys(self)
		const ith        = generators[Math.floor(Math.random() * generators.length)]

		return self[ith](len)
	}

} )()

const runTest = function () {

}

/*

*/

const yieldCase = function (params) {

	return params.map(function (param) {
		return fromStream()
	})

}

const propertyError = function (testData, state) {

}

const exhaustionWarning = function (testData, state, info) {

}

const successMessage = function (states, info) {

}

const whenTest = function (prop, testcase) {
	// simply call the predicate with the testcase.

	return prop.apply(null, testcase)
}

const validateTest = function (test) {
	/*
		ensure that the test being passed to run
		can be executed properly.
	*/

	// throw an error if any fields are missing.
	;['info', 'params', 'time'].forEach(function (key) {

		if (!test.hasOwnProperty(key)) {
			var message =
				"the property '" + key + "' was missing from the test object."

			throw colourise.red(message)
		}
	})

	// time mustn't be NaN
	if (test.time !== test.time) {

		var message =
			'time must not be NaN.'

		throw colourise.red(message)
	}

	// time definitely mustn't be Infinite
	if (!isFinite(test.time)) {

		var message =
			'time must not be infinite.'

		throw colourise.red(message)
	}

	// time must be positive
	if (test.time < 0) {
		var message =
			'time must be positive.'

		throw colourise.red(message)
	}

	return true
}

/*
	The backend wrapper in which the test is executed.
*/

const executeTest = function (test) {

	validateTest(test)

	// attach the test data to the local environment.

	const info         = test.info
	const params       = test.params
	const time         = test.time
	const whenProperty = test.whenProperty

	const initialState = function () {
		return {
			casesExamined : 0
		}
	}

	// each test subtype has its own state, tester and property group.

	var states       = [initialState()]
	const groupTypes = [whenProperty]
	const testers    = [whenTest]

	var timeLeft = stopwatch(time)

	/*
		execute the tests and collect statistics on the failures.
	*/

	while (timeLeft()) {

		var testcase = yieldCase(params)

		for (var ith = 0; ith < states.length; ith++) {

			var test  = testers[ith]
			var group = groupTypes[ith]
			var state = states[ith]

			runTest(test, group, state, testcase, info)
		}

	}

	// additional data needed to report success or failure.

	const testData = {
		info: info,
		time: time
	}

	/*
		Check that the correct number of tests were run, and
		that none of the tests fail.
	*/

	for (var ith = 0; ith < states.length; ith++) {

		var group = groupTypes[ith]
		var state = states[ith]

		if (group.length > 0 && state.testsRun === 0) {
			/*
				No tests were run for a particular test group.
				Warn the user about this fact.
			*/
			exhaustionWarning(testData, state, info)
		}

		if (state.failsFor.length > 0) {
			/*
				Throw errors for this particular group.
			*/

			propertyError
		}

	}

	successMessage(states, info)
}

/*
	-------------------------------- Grammar --------------------------------

	describe(string)            add a description to a property group. Concatanative property.

	over([string])              the parametres to bind random variables to.
	                            Overriding property.

	over_(string_)              the parametres to bind random variables to.
	                            Overriding property.

	when(Function, [Function])  when a predicate is true, assert that several other
	                            predicates are also true. Concatanative property.

	when_(Function_)            when a predicate is true, assert that several other
	                            predicates are also true. Concatanative property.

	run(number)                 triggers the start of a test, specifies how long the test runs for.
*/

const describe = function (info) {

	var self  = joinTest(this, {
		info : info,
		type : 'describe'
	})

	return self
}

const over = function (params) {

	var self  = joinTest(this, {
		params 	: params,
		type   	: 'over'
	})

	return self
}

const over_ = function () {

	const args = Array.prototype.slice.call(arguments)

	var self  = joinTest(this, {
		params 	: args,
		type   	: 'over'
	})

	return self
}

const when = function (pred, preds) {

	var self  = joinTest(this, {
		whenProperty : [pred].concat(preds),
		type         : 'when'
	})

	return self
}

const when_ = function () {

	const args = Array.prototype.slice.call(arguments)

	var self  = joinTest(this, {
		whenProperty : args,
		type         : 'when'
	})

	return self
}

const run = function (time) {

	var self  = joinTest(this, {
		time : time,
		type : 'run'
	})

	return self
}

const _forallProto = {
	run      : run,

	over     : over,
	over_    : over_,

	when     : when,
	when_    : when_,

	describe : describe
}

const joinTest = function (acc, left) {

	if (acc.GLOBAL || acc.window) {
		// a heuristic for detecting the global context.
		var acc = Object.create(_forallProto)
	}

	const override = function (key) {
		return function () {

			acc[key] = left[key]
			return acc

		}
	}

	const join = function (key) {
		return function () {

			if (acc[key]) {
				acc[key] = acc[key].concat( [left[key]] )
			} else {
				acc[key] = [left[key]]
			}

			return acc
		}
	}

	const responses = {
		describe : join('info'),
		over     : override('params'),
		when     : join('whenProperty'),
		run      : function () {

			acc.time = left.time

			executeTest(acc)
		}
	}

	for (type in responses) {

		if (left.type === type) {
			return responses[type]()
		}
	}

}
<|endoftext|>


<commit_before>var tabs		= require("tabs");
var contextMenu = require("context-menu");

var menuItem = contextMenu.Item({
	label: "Create Blockquote",
	context: contextMenu.SelectionContext(),
	contentScript:	'self.on("click", function () {' +
					' var text = window.getSelection().toString();' +
					' self.postMessage(text);' +
					'});',
	onMessage: function (selectionText) {
		let clipboard = require("clipboard");
		var pageLink = tabs.activeTab.url;
		var pageTitle = tabs.activeTab.title;
		var outputText =	'{% blockquote Author ' + pageLink + ' ' + pageTitle + ' %}\r\n' +
							escape(selectionText) + '\r\n' +
							'{% endblockquote %}';
		clipboard.set(unescape(outputText));
	}
});<commit_msg>Changed Author placeholder to Source.<commit_after>var tabs		= require("tabs");
var contextMenu = require("context-menu");

var menuItem = contextMenu.Item({
	label: "Create Blockquote",
	context: contextMenu.SelectionContext(),
	contentScript:	'self.on("click", function () {' +
					' var text = window.getSelection().toString();' +
					' self.postMessage(text);' +
					'});',
	onMessage: function (selectionText) {
		let clipboard = require("clipboard");
		var pageLink = tabs.activeTab.url;
		var pageTitle = tabs.activeTab.title;
		var outputText =	'{% blockquote Source ' + pageLink + ' ' + pageTitle + ' %}\r\n' +
							escape(selectionText) + '\r\n' +
							'{% endblockquote %}';
		clipboard.set(unescape(outputText));
	}
});
<|endoftext|>


<commit_before>'use babel'

import { Point, Range, Disposable, CompositeDisposable } from 'atom'
import * as _ from 'lodash'
import Spell from './spell'

function escapeRegExp (str) {
  return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&')
}

function getScopePath (scopeDescriptor) {
  return _.map(scopeDescriptor.getScopesArray(), scope => scope[0] !== '.' ? '.' + scope : scope).join(' ')
}

const Main = {
  disposables: null,
  linter: null,
  locale: null,
  grammars: null,
  checkers: null,

  getGrammar (scope) {
    for (const grammar of this.grammars.values()) {
      if (_.includes(grammar.grammarScopes, scope)) {
        return grammar
      }
    }
  },

  getChecker (dictionaries) {
    let id = dictionaries.join()
    if (!this.checkers[id]) {
      let checker = new Spell(dictionaries)
      this.disposables.add(checker)
      this.checkers[id] = checker
    }

    return this.checkers[id]
  },

  activate () {
    this.disposables = new CompositeDisposable()
    this.locale = 'en_US'
    require('os-locale')((err, locale) => {
      if (!err) {
        this.locale = locale || this.locale
      }
    })
    this.grammars = new Set()
    this.ignoredScopes = {}
    this.checkers = {}
    require('atom-package-deps').install('linter-spell')
      .then(() => {
        console.log('All dependencies installed, good to go')
      })
  },

  deactivate () {
    this.disposables.dispose()
  },

  provideGrammar () {
    return [{
      grammarScopes: [
        'source.asciidoc',
        'text.git-commit',
        'text.plain',
        'text.plain.null-grammar'],
      ignoredScopes: []
    }, {
      grammarScopes: ['source.gfm'],
      ignoredScopes: [
        '.link .markup.underline.link.gfm',
        '.markup.raw.gfm',
        'constant.character.entity.gfm'
      ]
    }]
  },

  consumeGrammar (grammars) {
    grammars = _.castArray(grammars)
    for (const grammar of grammars) {
      this.grammars.add(grammar)
      if (grammar.ignoredScopes) {
        grammar._ignoredPattern =
          new RegExp(
            '(?:^| )(?:' +
            _.map(grammar.ignoredScopes, escapeRegExp).join('|') +
            ')(?:$| )')
        console.log(grammar._ignoredPattern)
      }
    }
    return new Disposable(() => {
      for (const grammar of grammars) {
        this.grammars.delete(grammar)
      }
    })
  },

  consumeLinter (linter) {
    this.linter = linter
    return new Disposable(() => this.linter = null)
  },

  provideIntentions () {
    return {
      grammarScopes: ['*'],
      getIntentions: ({textEditor, bufferPosition}) => {
        if (this.linter) {
          const editorLinter = this.linter.getEditorLinter(textEditor)
          if (editorLinter) {
            for (const message of editorLinter.getMessages()) {
              if (message.linter === 'spell' && message.range && message.range.containsPoint(bufferPosition)) {
                return message.intentions
              }
            }
          }
        }
        return []
      }
    }
  },

  provideLinter () {
    return {
      name: 'spell',
      grammarScopes: ['*'],
      scope: 'file',
      lintOnFly: false,
      lint: async (textEditor, scopeName) => {
        let messages = []
        const grammar = this.getGrammar(textEditor.getGrammar().scopeName)
        if (grammar) {
          const filePath = textEditor.getPath()

          const dictionaries = _.find([
            grammar.getDictionaries ? grammar.getDictionaries(textEditor) : [],
            atom.config.get('linter-spell.defaultDictionaries'),
            [this.locale]
          ], d => d.length > 0)

          const checker = this.getChecker(dictionaries)

          let ranges = [textEditor.getBuffer().getRange()]
          if (grammar._ignoredPattern !== null) {
            let current = Point.fromObject(ranges[ranges.length - 1].start, true)
            while (ranges[ranges.length - 1].containsPoint(current)) {
              let next = Point.fromObject(current, true)
              let path = getScopePath(textEditor.scopeDescriptorForBufferPosition(current))
              do {
                if (textEditor.getBuffer().lineLengthForRow(next.row) === next.column) {
                  next.row++
                  next.column = 0
                } else {
                  next.column++
                }
              } while (ranges[ranges.length - 1].containsPoint(next) && path === getScopePath(textEditor.scopeDescriptorForBufferPosition(next)))
              console.log(path)
              if (grammar._ignoredPattern.test(path)) {
                if (current === ranges[ranges.length - 1].start) {
                  ranges[ranges.length - 1].start = next
                } else {
                  let r = new Range(next, ranges[ranges.length - 1].end)
                  ranges[ranges.length - 1].end = current
//                  console.log(ranges[ranges.length - 1].isEmpty())
                  ranges.push(r)
                }
              }
              current = next
            }
          }

          _.remove(ranges, range => range.isEmpty())

          if (ranges.length > 0 && grammar.getRamges) {
            let {ranges, ignoredRanges} = grammar.getRanges(textEditor, ranges)

            for (const ignoredRange of ignoredRanges) {
              ranges = _.flatMap(ranges, range => {
                if (range.intersectsWith(ignoredRange)) {
                  let r = []
                  if (range.start.isLessThan(ignoredRange.start)) {
                    r.push(new Range(range.start, ignoredRange.start))
                  }
                  if (ignoredRange.end.isLessThan(range.end)) {
                    r.push(new Range(ignoredRange.end, range.end))
                  }
                  return r
                } else {
                  return range
                }
              })
            }
          }

          console.log(ranges)

          for (let checkRange of ranges) {
            for (const { text, range, suggestions } of await checker.getMisspellings(textEditor, checkRange)) {
              const intentions = _.concat(_.map(suggestions,
                (suggestion, index) => {
                  return {
                    priority: -index,
                    icon: 'light-bulb',
                    title: `Change to "${suggestion}"`,
                    selected: () => textEditor.setTextInBufferRange(range, suggestion)
                  }
                }), {
                  priority: -100,
                  icon: 'check',
                  title: 'Add word',
                  selected: () => checker.addWord(text)
                }, {
                  priority: -101,
                  icon: 'check',
                  title: 'Add word (case insensitive)',
                  selected: () => checker.addWordCaseInsensitive(text)
                }, {
                  priority: -102,
                  icon: 'circle-slash',
                  title: 'Ignore word',
                  selected: () => checker.ignoreWord(text)
                }, {
                  priority: -103,
                  icon: 'circle-slash',
                  title: 'Ignore word (case insensitive)',
                  selected: () => checker.ignoreWordCaseInsensitive(text)
                })
              messages.push({
                type: 'Warning',
                text: `${text}: ${suggestions.join(', ')}`,
                range: range,
                intentions: intentions,
                filePath: filePath
              })
            }
          }
        }
        return _.sortBy(messages, 'range')
      }
    }
  }
}

export default Main
<commit_msg>Small tweaks<commit_after>'use babel'

import { Point, Range, Disposable, CompositeDisposable } from 'atom'
import * as _ from 'lodash'
import Spell from './spell'

function escapeRegExp (str) {
  return str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&')
}

function getScopePath (scopeDescriptor) {
  return _.map(scopeDescriptor.getScopesArray(), scope => scope[0] !== '.' ? '.' + scope : scope).join(' ')
}

const Main = {
  disposables: null,
  linter: null,
  locale: null,
  grammars: null,
  checkers: null,

  getGrammar (scope) {
    for (const grammar of this.grammars.values()) {
      if (_.includes(grammar.grammarScopes, scope)) {
        return grammar
      }
    }
  },

  getChecker (dictionaries) {
    let id = dictionaries.join()
    if (!this.checkers[id]) {
      let checker = new Spell(dictionaries)
      this.disposables.add(checker)
      this.checkers[id] = checker
    }

    return this.checkers[id]
  },

  activate () {
    this.disposables = new CompositeDisposable()
    this.locale = 'en_US'
    require('os-locale')((err, locale) => {
      if (!err) {
        this.locale = locale || this.locale
      }
    })
    this.grammars = new Set()
    this.ignoredScopes = {}
    this.checkers = {}
    require('atom-package-deps').install('linter-spell')
      .then(() => {
        console.log('All dependencies installed, good to go')
      })
  },

  deactivate () {
    this.disposables.dispose()
  },

  provideGrammar () {
    return [{
      grammarScopes: [
        'source.asciidoc',
        'text.git-commit',
        'text.plain',
        'text.plain.null-grammar'],
      ignoredScopes: []
    }, {
      grammarScopes: ['source.gfm'],
      ignoredScopes: [
        '.link .markup.underline.link.gfm',
        '.markup.raw.gfm',
        'constant.character.entity.gfm'
      ]
    }]
  },

  consumeGrammar (grammars) {
    grammars = _.castArray(grammars)
    for (const grammar of grammars) {
      this.grammars.add(grammar)
      if (grammar.ignoredScopes) {
        grammar._ignoredPattern =
          new RegExp(
            '(?:^| )(?:' +
            _.map(grammar.ignoredScopes, escapeRegExp).join('|') +
            ')(?:$| )')
//        console.log(grammar._ignoredPattern)
      }
    }
    return new Disposable(() => {
      for (const grammar of grammars) {
        this.grammars.delete(grammar)
      }
    })
  },

  consumeLinter (linter) {
    this.linter = linter
    return new Disposable(() => this.linter = null)
  },

  provideIntentions () {
    return {
      grammarScopes: ['*'],
      getIntentions: ({textEditor, bufferPosition}) => {
        if (this.linter) {
          const editorLinter = this.linter.getEditorLinter(textEditor)
          if (editorLinter) {
            for (const message of editorLinter.getMessages()) {
              if (message.linter === 'spell' && message.range && message.range.containsPoint(bufferPosition)) {
                return message.intentions
              }
            }
          }
        }
        return []
      }
    }
  },

  provideLinter () {
    return {
      name: 'spell',
      grammarScopes: ['*'],
      scope: 'file',
      lintOnFly: false,
      lint: async (textEditor, scopeName) => {
        let messages = []
        const grammar = this.getGrammar(textEditor.getGrammar().scopeName)
        if (grammar) {
          const filePath = textEditor.getPath()

          const dictionaries = _.find([
            grammar.getDictionaries ? grammar.getDictionaries(textEditor) : [],
            atom.config.get('linter-spell.defaultDictionaries'),
            [this.locale]
          ], d => d.length > 0)

          const checker = this.getChecker(dictionaries)

          let ranges = [textEditor.getBuffer().getRange()]
          if (grammar._ignoredPattern !== null) {
            let current = Point.fromObject(ranges[ranges.length - 1].start, true)
            while (ranges[ranges.length - 1].containsPoint(current)) {
              let next = Point.fromObject(current, true)
              let path = getScopePath(textEditor.scopeDescriptorForBufferPosition(current))
              do {
                if (textEditor.getBuffer().lineLengthForRow(next.row) === next.column) {
                  next.row++
                  next.column = 0
                } else {
                  next.column++
                }
              } while (ranges[ranges.length - 1].containsPoint(next) && path === getScopePath(textEditor.scopeDescriptorForBufferPosition(next)))
//              console.log(path)
              if (grammar._ignoredPattern.test(path)) {
                if (current === ranges[ranges.length - 1].start) {
                  ranges[ranges.length - 1].start = next
                } else {
                  let r = new Range(next, ranges[ranges.length - 1].end)
                  ranges[ranges.length - 1].end = current
//                  console.log(ranges[ranges.length - 1].isEmpty())
                  ranges.push(r)
                }
              }
              current = next
            }
          }

          _.remove(ranges, range => range.isEmpty())

          if (ranges.length > 0 && grammar.getRamges) {
            let {ranges, ignoredRanges} = grammar.getRanges(textEditor, ranges)

            for (const ignoredRange of ignoredRanges) {
              ranges = _.flatMap(ranges, range => {
                if (range.intersectsWith(ignoredRange)) {
                  let r = []
                  if (range.start.isLessThan(ignoredRange.start)) {
                    r.push(new Range(range.start, ignoredRange.start))
                  }
                  if (ignoredRange.end.isLessThan(range.end)) {
                    r.push(new Range(ignoredRange.end, range.end))
                  }
                  return r
                } else {
                  return range
                }
              })
            }
          }

//          console.log(ranges)

          for (let checkRange of ranges) {
            for (const { text, range, suggestions } of await checker.getMisspellings(textEditor, checkRange)) {
              const intentions = _.concat(_.map(suggestions,
                (suggestion, index) => {
                  return {
                    priority: -index,
                    icon: 'light-bulb',
                    title: `Change to "${suggestion}"`,
                    selected: () => textEditor.setTextInBufferRange(range, suggestion)
                  }
                }), {
                  priority: -100,
                  icon: 'check',
                  title: 'Add word',
                  selected: () => checker.addWord(text)
                }, {
                  priority: -101,
                  icon: 'check',
                  title: 'Add word (case insensitive)',
                  selected: () => checker.addWordCaseInsensitive(text)
                }, {
                  priority: -102,
                  icon: 'circle-slash',
                  title: 'Ignore word',
                  selected: () => checker.ignoreWord(text)
                }, {
                  priority: -103,
                  icon: 'circle-slash',
                  title: 'Ignore word (case insensitive)',
                  selected: () => checker.ignoreWordCaseInsensitive(text)
                })
              messages.push({
                type: 'Warning',
                text: `${text}: ${suggestions.join(', ')}`,
                range: range,
                intentions: intentions,
                filePath: filePath
              })
            }
          }
        }
        return _.sortBy(messages, 'range')
      }
    }
  }
}

export default Main
<|endoftext|>