<commit_before>var assert = require("assert");
var path = require("path");
var fs = require("fs");

var mkdirp = require("mkdirp");
var temp = require("temp");

var licenseSniffer = require("../");

describe("license-sniffer.sniff", function() {
    it("detects itself as BSD", function(done) {
        licenseSniffer.sniff(path.join(__dirname, ".."), function(err, license) {
            assert.ifError(err);
            assert.deepEqual(license.names, ["BSD"]);
            done();
        });
    });

    it("errors if package.json doesn't exist", function(done) {
        licenseSniffer.sniff(__dirname, function(err, license) {
            assert.ok(err);
            done();
        });
    });

    it("detects BSD license using LICENSE file if present", function(done) {
        withTemporaryModule("test-module", function(moduleDirPath) {
            var bsdLicenseText = licenseText("bsd-2-clause");
            fs.writeFileSync(path.join(moduleDirPath, "LICENSE"), bsdLicenseText);
            licenseSniffer.sniff(moduleDirPath, function(err, license) {
                assert.ifError(err);
                assert.deepEqual(license.names, ["BSD 2-Clause"]);
                done();
            });
        });
    });

    it("detects MIT license using LICENSE file if present", function(done) {
        withTemporaryModule("test-module", function(moduleDirPath) {
            var mitLicenseText = licenseText("mit");
            fs.writeFileSync(path.join(moduleDirPath, "LICENSE"), mitLicenseText);
            licenseSniffer.sniff(moduleDirPath, function(err, license) {
                assert.ifError(err);
                assert.deepEqual(license.names, ["MIT"]);
                done();
            });
        });
    });

    it("detects unlicense using UNLICENSE file if present", function(done) {
        withTemporaryModule("test-module", function(moduleDirPath) {
            var unlicenseText = licenseText("unlicense");
            fs.writeFile(path.join(moduleDirPath, "UNLICENSE"), unlicenseText);
            licenseSniffer.sniff(moduleDirPath, function(err, license) {
                assert.ifError(err);
                assert.deepEqual(license.names, ["Public domain"]);
                done();
            });
        });
    });

    it("detects no license if LICENSE is not similar to any known license", function(done) {
        withTemporaryModule("test-module", function(moduleDirPath) {
            fs.writeFile(path.join(moduleDirPath, "LICENSE"), "Been Listening");
            licenseSniffer.sniff(moduleDirPath, function(err, license) {
                assert.ifError(err);
                assert.deepEqual(license.names, []);
                done();
            });
        });
    });

    it("detects itself as BSD", function(done) {
        licenseSniffer.sniff(path.join(__dirname, ".."), function(err, license) {
            assert.ifError(err);
            assert.deepEqual(license.names, ["BSD"]);
            done();
        });
    });
});

function licenseText(name) {
    return fs.readFileSync(path.join(__dirname, "../licenses/" + name), "utf8");
}

function withTemporaryModule(moduleName, callback) {
    var moduleDirPath = temp.mkdirSync();
    fs.writeFileSync(
        path.join(moduleDirPath, "package.json"),
        JSON.stringify({"name": moduleName})
    );
    callback(moduleDirPath);
}

describe("license-sniffer.sniffPackageJson", function() {
    it("reads license names as empty list if package.json is empty", function(done) {
        licenseSniffer.sniffPackageJson({}, function(err, license) {
            assert.ifError(err);
            assert.deepEqual(license.names, []);
            done();
        });
    });

    it("reads license field", function(done) {
        licenseSniffer.sniffPackageJson({license: "BSD"}, function(err, license) {
            assert.ifError(err);
            assert.deepEqual(license.names, ["BSD"]);
            done();
        });
    });

    it("packageJson is parsed to JSON object if its a string", function(done) {
        licenseSniffer.sniffPackageJson('{"license": "BSD"}', function(err, license) {
            assert.ifError(err);
            assert.deepEqual(license.names, ["BSD"]);
            done();
        });
    });

    it("passes error to callback if JSON is badly formed", function(done) {
        licenseSniffer.sniffPackageJson('{license: "BSD"}', function(err, license) {
            assert.ok(err);
            done();
        });
    });

    it("reads licenses field if license field is not present", function(done) {
        var packageJson = {
            licenses: [
                {
                    type: "BSD",
                    url: "http://opensource.org/licenses/BSD-2-Clause"
                }
            ]
        };
        licenseSniffer.sniffPackageJson(packageJson, function(err, license) {
            assert.ifError(err);
            assert.deepEqual(license.names, ["BSD"]);
            done();
        });
    });

    it("reads multiple licenses if licenses has many elements", function(done) {
        var packageJson = {
            licenses: [{type: "BSD"}, {type: "MIT"}]
        };
        licenseSniffer.sniffPackageJson(packageJson, function(err, license) {
            assert.ifError(err);
            assert.deepEqual(license.names, ["BSD", "MIT"]);
            done();
        });
    });
});

describe("license-sniffer.sniffRecursive", function() {
    it("sniffs licenses of modules in node_modules", function(done) {
        withTemporaryModule("test-module", function(modulePath) {
            writeFileSync(
                path.join(modulePath, "package.json"),
                JSON.stringify({license: "BSD"})
            );
            writeFileSync(
                path.join(modulePath, "node_modules/one/package.json"),
                JSON.stringify({license: "MIT"})
            );
            writeFileSync(
                path.join(modulePath, "node_modules/one/node_modules/one-one/package.json"),
                JSON.stringify({license: "Apache"})
            );
            licenseSniffer.sniffRecursive(modulePath, function(err, result) {
                assert.ifError(err);
                assert.deepEqual(
                    result,
                    [
                        {modulePath: modulePath, names: ["BSD"]},
                        {modulePath: path.join(modulePath, "node_modules/one"), names: ["MIT"]},
                        {modulePath: path.join(modulePath, "node_modules/one/node_modules/one-one"), names: ["Apache"]}
                    ]
                );
                done();
            });
        });
    });
});

function writeFileSync(filePath, contents) {
    mkdirp.sync(path.dirname(filePath));
    fs.writeFileSync(filePath, contents);
}
<commit_msg>Remove duplicate test<commit_after>var assert = require("assert");
var path = require("path");
var fs = require("fs");

var mkdirp = require("mkdirp");
var temp = require("temp");

var licenseSniffer = require("../");

describe("license-sniffer.sniff", function() {
    it("detects itself as BSD", function(done) {
        licenseSniffer.sniff(path.join(__dirname, ".."), function(err, license) {
            assert.ifError(err);
            assert.deepEqual(license.names, ["BSD"]);
            done();
        });
    });

    it("errors if package.json doesn't exist", function(done) {
        licenseSniffer.sniff(__dirname, function(err, license) {
            assert.ok(err);
            done();
        });
    });

    it("detects BSD license using LICENSE file if present", function(done) {
        withTemporaryModule("test-module", function(moduleDirPath) {
            var bsdLicenseText = licenseText("bsd-2-clause");
            fs.writeFileSync(path.join(moduleDirPath, "LICENSE"), bsdLicenseText);
            licenseSniffer.sniff(moduleDirPath, function(err, license) {
                assert.ifError(err);
                assert.deepEqual(license.names, ["BSD 2-Clause"]);
                done();
            });
        });
    });

    it("detects MIT license using LICENSE file if present", function(done) {
        withTemporaryModule("test-module", function(moduleDirPath) {
            var mitLicenseText = licenseText("mit");
            fs.writeFileSync(path.join(moduleDirPath, "LICENSE"), mitLicenseText);
            licenseSniffer.sniff(moduleDirPath, function(err, license) {
                assert.ifError(err);
                assert.deepEqual(license.names, ["MIT"]);
                done();
            });
        });
    });

    it("detects unlicense using UNLICENSE file if present", function(done) {
        withTemporaryModule("test-module", function(moduleDirPath) {
            var unlicenseText = licenseText("unlicense");
            fs.writeFile(path.join(moduleDirPath, "UNLICENSE"), unlicenseText);
            licenseSniffer.sniff(moduleDirPath, function(err, license) {
                assert.ifError(err);
                assert.deepEqual(license.names, ["Public domain"]);
                done();
            });
        });
    });

    it("detects no license if LICENSE is not similar to any known license", function(done) {
        withTemporaryModule("test-module", function(moduleDirPath) {
            fs.writeFile(path.join(moduleDirPath, "LICENSE"), "Been Listening");
            licenseSniffer.sniff(moduleDirPath, function(err, license) {
                assert.ifError(err);
                assert.deepEqual(license.names, []);
                done();
            });
        });
    });
});

function licenseText(name) {
    return fs.readFileSync(path.join(__dirname, "../licenses/" + name), "utf8");
}

function withTemporaryModule(moduleName, callback) {
    var moduleDirPath = temp.mkdirSync();
    fs.writeFileSync(
        path.join(moduleDirPath, "package.json"),
        JSON.stringify({"name": moduleName})
    );
    callback(moduleDirPath);
}

describe("license-sniffer.sniffPackageJson", function() {
    it("reads license names as empty list if package.json is empty", function(done) {
        licenseSniffer.sniffPackageJson({}, function(err, license) {
            assert.ifError(err);
            assert.deepEqual(license.names, []);
            done();
        });
    });

    it("reads license field", function(done) {
        licenseSniffer.sniffPackageJson({license: "BSD"}, function(err, license) {
            assert.ifError(err);
            assert.deepEqual(license.names, ["BSD"]);
            done();
        });
    });

    it("packageJson is parsed to JSON object if its a string", function(done) {
        licenseSniffer.sniffPackageJson('{"license": "BSD"}', function(err, license) {
            assert.ifError(err);
            assert.deepEqual(license.names, ["BSD"]);
            done();
        });
    });

    it("passes error to callback if JSON is badly formed", function(done) {
        licenseSniffer.sniffPackageJson('{license: "BSD"}', function(err, license) {
            assert.ok(err);
            done();
        });
    });

    it("reads licenses field if license field is not present", function(done) {
        var packageJson = {
            licenses: [
                {
                    type: "BSD",
                    url: "http://opensource.org/licenses/BSD-2-Clause"
                }
            ]
        };
        licenseSniffer.sniffPackageJson(packageJson, function(err, license) {
            assert.ifError(err);
            assert.deepEqual(license.names, ["BSD"]);
            done();
        });
    });

    it("reads multiple licenses if licenses has many elements", function(done) {
        var packageJson = {
            licenses: [{type: "BSD"}, {type: "MIT"}]
        };
        licenseSniffer.sniffPackageJson(packageJson, function(err, license) {
            assert.ifError(err);
            assert.deepEqual(license.names, ["BSD", "MIT"]);
            done();
        });
    });
});

describe("license-sniffer.sniffRecursive", function() {
    it("sniffs licenses of modules in node_modules", function(done) {
        withTemporaryModule("test-module", function(modulePath) {
            writeFileSync(
                path.join(modulePath, "package.json"),
                JSON.stringify({license: "BSD"})
            );
            writeFileSync(
                path.join(modulePath, "node_modules/one/package.json"),
                JSON.stringify({license: "MIT"})
            );
            writeFileSync(
                path.join(modulePath, "node_modules/one/node_modules/one-one/package.json"),
                JSON.stringify({license: "Apache"})
            );
            licenseSniffer.sniffRecursive(modulePath, function(err, result) {
                assert.ifError(err);
                assert.deepEqual(
                    result,
                    [
                        {modulePath: modulePath, names: ["BSD"]},
                        {modulePath: path.join(modulePath, "node_modules/one"), names: ["MIT"]},
                        {modulePath: path.join(modulePath, "node_modules/one/node_modules/one-one"), names: ["Apache"]}
                    ]
                );
                done();
            });
        });
    });
});

function writeFileSync(filePath, contents) {
    mkdirp.sync(path.dirname(filePath));
    fs.writeFileSync(filePath, contents);
}
<|endoftext|>


<commit_before>module.exports = {
  servers: {
    one: {
      host: 'coauthor.csail.mit.edu',
      username: 'ubuntu',
      pem: "/afs/csail/u/e/edemaine/.ssh/private/id_rsa"
      // pem:
      // password:
      // or leave blank for authenticate from ssh-agent
    }
  },

  // Meteor server
  meteor: {
    name: 'coauthor',
    path: '/afs/csail/u/e/edemaine/Projects/coauthor',
    servers: {
      one: {}
    },
    docker: {
      image: 'abernix/meteord:node-12-base',
      stopAppDuringPrepareBundle: false
    },
    buildOptions: {
      serverOnly: true,
      buildLocation: '/scratch/coauthor-build'
    },
    env: {
      // Comment this out to upgrade the database (for Coauthor upgrades).
      // This can take a while on startup, so be sure to also increase
      // deployCheckWaitTime below.
      COAUTHOR_SKIP_UPGRADE_DB: '1',
      // Set to your public-facing URL
      ROOT_URL: 'https://coauthor.csail.mit.edu',
      // Set to your SMTP server, to enable Coauthor email notifications.
      // Comment out this line to turn off email notifications.
      MAIL_URL: 'smtp://coauthor.csail.mit.edu:25?ignoreTLS=true',
      // Default From address for mail notifications is
      // coauthor@deployed-host-name; set this to override:
      //MAIL_FROM: 'coauthor@coauthor.csail.mit.edu',
      // If you don't use MUP's MongoDB server, set this to your server:
      MONGO_URL: 'mongodb://mongodb/meteor',
      // You shouldn't need to change this:
      MONGO_OPLOG_URL: 'mongodb://mongodb/local',
      // Set to fill available RAM:
      NODE_OPTIONS: '--trace-warnings --max-old-space-size=8192'
    },
    // If you're upgrading the database, you probably need to increase this:
    deployCheckWaitTime: 200,
    //deployCheckWaitTime: 2000,
    /* Old mup-frontend-server configuration:
    ssl: {
      // pem: '../coauthor_csail_mit_edu.ssl/coauthor_csail_mit_edu.pem'
      crt: '../../coauthor_csail_mit_edu.ssl/coauthor_csail_mit_edu.pem',
      key: '../../coauthor_csail_mit_edu.ssl/coauthor_csail_mit_edu.key',
      port: 443
    },
    nginx: {
      clientUploadLimit: '0', // disable upload limit
    },
    */
  },

  // Mongo server
  mongo: {
    version: '4.4.4',
    oplog: true,
    port: 27017,
    servers: {
      one: {},
    },
  },

  // Reverse proxy for SSL
  proxy: {
    domains: 'coauthor.csail.mit.edu',
    ssl: {
      // pem: '../coauthor_csail_mit_edu.ssl/coauthor_csail_mit_edu.pem'
      crt: '../../coauthor_csail_mit_edu.ssl/coauthor_csail_mit_edu.pem',
      key: '../../coauthor_csail_mit_edu.ssl/coauthor_csail_mit_edu.key',
      forceSSL: true,
    },
    clientUploadLimit: '0', // disable upload limit
    nginxServerConfig: '../.proxy.config',
  },

  // Run 'npm install' before deploying, to ensure packages are up-to-date
  hooks: {
    'pre.deploy': {
      localCommand: 'npm install'
    }
  },
};
<commit_msg>Comment about MongoDB versions<commit_after>module.exports = {
  servers: {
    one: {
      host: 'coauthor.csail.mit.edu',
      username: 'ubuntu',
      pem: "/afs/csail/u/e/edemaine/.ssh/private/id_rsa"
      // pem:
      // password:
      // or leave blank for authenticate from ssh-agent
    }
  },

  // Meteor server
  meteor: {
    name: 'coauthor',
    path: '/afs/csail/u/e/edemaine/Projects/coauthor',
    servers: {
      one: {}
    },
    docker: {
      image: 'abernix/meteord:node-12-base',
      stopAppDuringPrepareBundle: false
    },
    buildOptions: {
      serverOnly: true,
      buildLocation: '/scratch/coauthor-build'
    },
    env: {
      // Comment this out to upgrade the database (for Coauthor upgrades).
      // This can take a while on startup, so be sure to also increase
      // deployCheckWaitTime below.
      COAUTHOR_SKIP_UPGRADE_DB: '1',
      // Set to your public-facing URL
      ROOT_URL: 'https://coauthor.csail.mit.edu',
      // Set to your SMTP server, to enable Coauthor email notifications.
      // Comment out this line to turn off email notifications.
      MAIL_URL: 'smtp://coauthor.csail.mit.edu:25?ignoreTLS=true',
      // Default From address for mail notifications is
      // coauthor@deployed-host-name; set this to override:
      //MAIL_FROM: 'coauthor@coauthor.csail.mit.edu',
      // If you don't use MUP's MongoDB server, set this to your server:
      MONGO_URL: 'mongodb://mongodb/meteor',
      // You shouldn't need to change this:
      MONGO_OPLOG_URL: 'mongodb://mongodb/local',
      // Set to fill available RAM:
      NODE_OPTIONS: '--trace-warnings --max-old-space-size=8192'
    },
    // If you're upgrading the database, you probably need to increase this:
    deployCheckWaitTime: 200,
    //deployCheckWaitTime: 2000,
    /* Old mup-frontend-server configuration:
    ssl: {
      // pem: '../coauthor_csail_mit_edu.ssl/coauthor_csail_mit_edu.pem'
      crt: '../../coauthor_csail_mit_edu.ssl/coauthor_csail_mit_edu.pem',
      key: '../../coauthor_csail_mit_edu.ssl/coauthor_csail_mit_edu.key',
      port: 443
    },
    nginx: {
      clientUploadLimit: '0', // disable upload limit
    },
    */
  },

  // Mongo server
  mongo: {
    // Mongo 4 has the advantage of free cloud monitoring
    // [https://docs.mongodb.com/manual/administration/monitoring/].
    // But you can also run an old version such as the default '3.4.1'.
    version: '4.4.4',
    oplog: true,
    port: 27017,
    servers: {
      one: {},
    },
  },

  // Reverse proxy for SSL
  proxy: {
    domains: 'coauthor.csail.mit.edu',
    ssl: {
      // pem: '../coauthor_csail_mit_edu.ssl/coauthor_csail_mit_edu.pem'
      crt: '../../coauthor_csail_mit_edu.ssl/coauthor_csail_mit_edu.pem',
      key: '../../coauthor_csail_mit_edu.ssl/coauthor_csail_mit_edu.key',
      forceSSL: true,
    },
    clientUploadLimit: '0', // disable upload limit
    nginxServerConfig: '../.proxy.config',
  },

  // Run 'npm install' before deploying, to ensure packages are up-to-date
  hooks: {
    'pre.deploy': {
      localCommand: 'npm install'
    }
  },
};
<|endoftext|>


<commit_before>/**
 * LineReader
 *
 * Reads a file one line at a time. This is especially useful for large files
 * since it only stores small chunks of the file in memory.
 *
 * @param {File} file -- The file object to read
 */
var LineReader = function ( file ) {
  if ( !(this instanceof LineReader) ) {
    return new LineReader( file );
  }

  var internals = this._internals = {};
  var self = this;

  internals.events = {};
  internals.reader = new FileReader();
  internals.canRead = true;

  internals.file = file;
  internals.fileLength = file.size;

  internals.readPos = 0;
  internals.chunkSize = 1024;
  internals.chunk = '';
  internals.lines = [];

  internals.reader.onload = function ( e ) {
    internals.chunk += e.target.result;
    if ( /\n/.test( internals.chunk ) ) {
      internals.lines = internals.chunk.split('\n');
      if ( self._hasMoreData ) {
        internals.chunk = internals.lines.pop();
      }
      self._step();
    }
  };
};

/**
 * LineReader#on
 *
 * Binds events
 *
 * @param {String} eventName -- the name of the event to bind to
 * @param {Function} cb -- the function to execute when the event is triggered
 */
LineReader.prototype.on = function ( eventName, cb ) {
  var internals = this._internals;

  internals.events[ eventName ] = cb;
};

/**
 * LineReader#read
 *
 * Starts the read process
 */
LineReader.prototype.read = function () {
  var internals = this._internals;
  var blob = internals.file.slice( internals.readPos, internals.readPos + internals.chunkSize );

  internals.readPos += internals.chunkSize;

  internals.reader.readAsBinaryString( blob );
};

/**
 * LineReader#stop
 *
 * Stops the read process
 */
LineReader.prototype.stop = function () {
  this._internals.canRead = false;
};

/**
 * LineReader#_step
 *
 * Internal: gets the next line and emits it as a `line` event
 */
LineReader.prototype._step = function () {
  var internals = this._internals;

  if ( internals.lines.length === 0 ) {
    return this.read();
  }

  if ( typeof internals.events.line === 'function' && internals.canRead ) {
    internals.events.line( internals.lines.shift(), this._step.bind(this) );
  }
};

/**
 * LineReader#_hasMoreData
 *
 * Internal: determines if there is still more data to read.
 */
LineReader.prototype._hasMoreData = function () {
  var internals = this._internals;
  return internals.readPos < internals.fileLength;
};
<commit_msg>Adds license to LineReader.js<commit_after>/**
 * LineReader
 * https://github.com/mgmeyers/LineReader
 *
 * Copyright 2014 Matthew Meyers <hello@matthewmeye.rs>
 * Released under the MIT license:
 * http://www.opensource.org/licenses/mit-license.php
 *
 * Reads a file one line at a time. This is especially useful for large files
 * since it only stores small chunks of the file in memory.
 *
 * @param {File} file -- The file object to read
 */
var LineReader = function ( file ) {
  if ( !(this instanceof LineReader) ) {
    return new LineReader( file );
  }

  var internals = this._internals = {};
  var self = this;

  internals.events = {};
  internals.reader = new FileReader();
  internals.canRead = true;

  internals.file = file;
  internals.fileLength = file.size;

  internals.readPos = 0;
  internals.chunkSize = 1024;
  internals.chunk = '';
  internals.lines = [];

  internals.reader.onload = function ( e ) {
    internals.chunk += e.target.result;
    if ( /\n/.test( internals.chunk ) ) {
      internals.lines = internals.chunk.split('\n');
      if ( self._hasMoreData ) {
        internals.chunk = internals.lines.pop();
      }
      self._step();
    }
  };
};

/**
 * LineReader#on
 *
 * Binds events
 *
 * @param {String} eventName -- the name of the event to bind to
 * @param {Function} cb -- the function to execute when the event is triggered
 */
LineReader.prototype.on = function ( eventName, cb ) {
  var internals = this._internals;

  internals.events[ eventName ] = cb;
};

/**
 * LineReader#read
 *
 * Starts the read process
 */
LineReader.prototype.read = function () {
  var internals = this._internals;
  var blob = internals.file.slice( internals.readPos, internals.readPos + internals.chunkSize );

  internals.readPos += internals.chunkSize;

  internals.reader.readAsBinaryString( blob );
};

/**
 * LineReader#stop
 *
 * Stops the read process
 */
LineReader.prototype.stop = function () {
  this._internals.canRead = false;
};

/**
 * LineReader#_step
 *
 * Internal: gets the next line and emits it as a `line` event
 */
LineReader.prototype._step = function () {
  var internals = this._internals;

  if ( internals.lines.length === 0 ) {
    return this.read();
  }

  if ( typeof internals.events.line === 'function' && internals.canRead ) {
    internals.events.line( internals.lines.shift(), this._step.bind(this) );
  }
};

/**
 * LineReader#_hasMoreData
 *
 * Internal: determines if there is still more data to read.
 */
LineReader.prototype._hasMoreData = function () {
  var internals = this._internals;
  return internals.readPos < internals.fileLength;
};
<|endoftext|>


<commit_before>class KasenIterator {
  constructor(iter, func) {
    this.iter = iter;
    this.func = func;
  }

  // eslint-disable-next-line class-methods-use-this
  next() {
    throw new Error("not implemented");
  }

  // eslint-disable-next-line class-methods-use-this
  prev() {
    throw new Error("not implemented");
  }
}

export class MapIterator extends KasenIterator {
  __base(direction) {
    const result = this.iter[direction]();
    if (!result.done) {
      result.value = this.func(result.value, result.key);
    }
    return result;
  }

  next() {
    return this.__base("next");
  }

  prev() {
    return this.__base("prev");
  }
}

export class FilterIterator extends KasenIterator {
  __base(direction) {
    let result;
    // eslint-disable-next-line no-cond-assign
    while (!(result = this.iter[direction]()).done) {
      if (this.func(result.value, result.key)) {
        // TODO: Shrink "key" if Array
        break;
      }
    }
    return result;
  }

  next() {
    return this.__base("next");
  }

  prev() {
    return this.__base("prev");
  }
}

export class ReverseIterator extends KasenIterator {
  next() {
    return this.iter.prev();
  }

  prev() {
    return this.iter.next();
  }
}
<commit_msg>Implement default next() and prev()<commit_after>class KasenIterator {
  constructor(iter, func) {
    this.iter = iter;
    this.func = func;
  }

  // eslint-disable-next-line class-methods-use-this, no-unused-vars
  __base(_direction) {
    throw new Error("not implemented");
  }

  next() {
    return this.__base("next");
  }

  prev() {
    return this.__base("prev");
  }
}

export class MapIterator extends KasenIterator {
  __base(direction) {
    const result = this.iter[direction]();
    if (!result.done) {
      result.value = this.func(result.value, result.key);
    }
    return result;
  }
}

export class FilterIterator extends KasenIterator {
  __base(direction) {
    let result;
    // eslint-disable-next-line no-cond-assign
    while (!(result = this.iter[direction]()).done) {
      if (this.func(result.value, result.key)) {
        // TODO: Shrink "key" if Array
        break;
      }
    }
    return result;
  }
}

export class ReverseIterator extends KasenIterator {
  next() {
    return this.iter.prev();
  }

  prev() {
    return this.iter.next();
  }
}
<|endoftext|>


<commit_before>// StyleDocco documentation code/preview rendering and handling
// ===================================================================
// Takes the HTML code from preview textareas and renders iframes with
// the specified preview CSS and JavaScript applied.

(function() {

'use strict';

// Abort if rendering a preview page (to avoid recursive iframe loading).
// This can happen in WebKit where we set the iframe src to `location.href`.
if (location.hash === '#__preview__' || location.protocol === 'data:') return;

// Helper functions. Using `Array.prototype` to make them work on NodeLists.
var forEach = function(arr, it) {
  return Array.prototype.forEach.call(arr, it);
};
var invoke = function(obj, fn) {
  var args = Array.prototype.slice.call(arguments, 2);
  return map(obj, function(value) {
    return (isFunction(fn) ? fn || value : value[fn]).apply(value, args);
  });
};
var isFunction = function(obj) {
  return Object.prototype.toString.call(obj) === '[object Function]';
};
var map = function(arr, it) {
  return Array.prototype.map.call(arr, it);
};
var pluck = function(arr, prop) {
  return map(arr, function(item) { return item[prop]; } );
};

// Parse `key=value; key=value` strings (for cookies).
var keyvalParse = function(str) {
  var obj = {};
  var pairs = str.split(';');
  for (var i = 0; pairs.length > i; i++) {
    var kvs = pairs[i].trim().split('=');
    obj[kvs[0]] = kvs[1];
  }
  return obj;
};
var removeClass = function(els, className) {
  return invoke(pluck(els, 'classList'), 'remove', className);
};

var postMessage = function(target, msg) {
  target.contentDocument.defaultView.postMessage(msg, '*');
};

var headEl = document.getElementsByTagName('head')[0];
var bodyEl = document.getElementsByTagName('body')[0];

// Get preview styles intended for preview iframes.
var styles = pluck(
  headEl.querySelectorAll('style[type="text/preview"]'),
  'innerHTML').join('');
// Get preview scripts intended for preview iframes.
var scripts = pluck(
  headEl.querySelectorAll('script[type="text/preview"]'),
  'innerHTML').join('');

var previewUrl = location.href.split('#')[0] + '#__preview__';

// Check if browser treats data uris as same origin.
var iframeEl = document.createElement('iframe');
iframeEl.src = 'data:text/html,';
bodyEl.appendChild(iframeEl);
iframeEl.addEventListener('load', function() {
  var support = { sameOriginDataUri: false };
  if (this.contentDocument) support.sameOriginDataUri = true;
  this.parentNode.removeChild(this);
  // Loop through code textareas and render the code in iframes.
  forEach(bodyEl.getElementsByTagName('textarea'), function(codeEl, idx) {
    addIframe(codeEl, support, idx);
    resizeableButtons();
    autoResizeTextArea(codeEl);
  });
});

var addIframe = function(codeEl, support, iframeId) {
  var previewEl, resizeableEl, iframeEl;
  previewEl = document.createElement('div');
  previewEl.appendChild(resizeableEl = document.createElement('div'));
  previewEl.className = 'preview';
  resizeableEl.appendChild(iframeEl = document.createElement('iframe'));
  resizeableEl.className = 'resizeable';
  iframeEl.setAttribute('scrolling', 'no');
  iframeEl.name = 'iframe' + iframeId++;
  iframeEl.addEventListener('load', function() {
    var htmlEl, bodyEl, scriptEl, styleEl, headEl, oldHeadEl, doc;
    doc = this.contentDocument;
    // Abort if we're loading a data uri in a browser without same
    // origin data uri support.
    if (!support.sameOriginDataUri && this.src !== previewUrl) {
      return;
    // Otherwise replace iframe content with the preview code.
    } else if (this.src === previewUrl) {
      htmlEl = doc.createElement('html');
      htmlEl.appendChild(doc.createElement('head'));
      htmlEl.appendChild(bodyEl = doc.createElement('body'));
      bodyEl.innerHTML = codeEl.textContent;
      doc.replaceChild(htmlEl, doc.documentElement);
    }
    // Add scripts and styles.
    headEl = doc.createElement('head');
    headEl.appendChild(styleEl = doc.createElement('style'));
    headEl.appendChild(scriptEl = doc.createElement('script'));
    scriptEl.textContent = scripts;
    styleEl.textContent = styles;
    oldHeadEl = doc.getElementsByTagName('head')[0];
    oldHeadEl.parentNode.replaceChild(headEl, oldHeadEl);
    postMessage(this, 'getHeight');
  });
  var iframeSrc;
  if (!support.sameOriginDataUri) {
    iframeSrc = previewUrl;
  } else {
    iframeSrc = 'data:text/html;charset=utf-8,' +
      encodeURIComponent('<!doctype html>' +
        codeEl.textContent);
  }
  iframeEl.setAttribute('src', iframeSrc);
  var codeDidChange = function() {
    iframeEl.contentDocument.body.innerHTML = this.value;
    postMessage(iframeEl, 'getHeight');
  };
  codeEl.addEventListener('keypress', codeDidChange);
  codeEl.addEventListener('keyup', codeDidChange);
  codeEl.parentNode.insertBefore(previewEl, codeEl);
};

// Add an element with the same styles and content as the textarea to
// calculate the height of the textarea content.
var autoResizeTextArea = function(el) {
  var mirrorEl = document.createElement('div');
  mirrorEl.className = 'preview-code';
  mirrorEl.style.position = 'absolute';
  mirrorEl.style.left = '-9999px';
  bodyEl.appendChild(mirrorEl);
  var maxHeight = parseInt(
    window.getComputedStyle(el).getPropertyValue('max-height'),
    10);
  var codeDidChange = function(ev) {
    mirrorEl.textContent = this.value + '\n';
    var height = mirrorEl.offsetHeight + 2; // Account for borders.
    if (height >= maxHeight) {
      this.style.overflow = 'auto';
    } else {
      this.style.overflow = 'hidden';
    }
    this.style.height = (mirrorEl.offsetHeight + 2) + 'px';
  };
  el.addEventListener('keypress', codeDidChange);
  el.addEventListener('keyup', codeDidChange);
  codeDidChange.call(el);
};

var resizeableButtons = function() {
  var settingsEl = bodyEl.getElementsByClassName('settings')[0];
  var resizeableEls = bodyEl.getElementsByClassName('resizeable');
  var resizeableElOffset = 30; // `.resizeable` padding
  var resizePreviews = function(width) {
    document.cookie = 'preview-width=' + width;
    forEach(resizeableEls, function(el) {
      if (width === 'auto') width = el.parentNode.offsetWidth;
      el.style.width = width + 'px';
      // TODO: Add CSS transitions and update height after `transitionend` event
      postMessage(el.getElementsByTagName('iframe')[0], 'getHeight');
    });
  };

  // Resize previews to the cookie value.
  var previewWidth = keyvalParse(document.cookie)['preview-width'];
  if (previewWidth) {
    resizePreviews(previewWidth);
    removeClass(settingsEl.getElementsByClassName('is-active'), 'is-active');
    var btn = settingsEl.querySelector('button[data-width="' + previewWidth + '"]');
    if (btn) { btn.classList.add('is-active'); }
  }

  window.addEventListener('message', function (ev) {
    if (ev.data == null || !ev.source) return;
    var data = ev.data;
    var sourceFrameEl = document.getElementsByName(ev.source.name)[0];
    // Set iframe height
    if (data.height != null && sourceFrameEl) {
      sourceFrameEl.parentNode.style.height = (data.height + resizeableElOffset) + 'px';
    }
  }, false);

  // Resizing buttons
  if (settingsEl && resizeableEls.length > 0) {
    settingsEl.hidden = false;
    settingsEl.addEventListener('click', function(event) {
      var tagName = event.target.tagName.toLowerCase();
      var btn;
      if (tagName === 'button') btn = event.target;
      else if (tagName === 'svg') btn = event.target.parentNode;
      else return;
      event.preventDefault();
      removeClass(settingsEl.getElementsByClassName('is-active'), 'is-active');
      btn.classList.add('is-active');
      var width = btn.dataset.width;
      resizePreviews(width);
    });
  }
};

})();
<commit_msg>Correctly render iframes. Closes #100.<commit_after>// StyleDocco documentation code/preview rendering and handling
// ===================================================================
// Takes the HTML code from preview textareas and renders iframes with
// the specified preview CSS and JavaScript applied.

(function() {

'use strict';

// Abort if rendering a preview page (to avoid recursive iframe loading).
// This can happen in WebKit where we set the iframe src to `location.href`.
if (location.hash === '#__preview__' || location.protocol === 'data:') return;

// Helper functions. Using `Array.prototype` to make them work on NodeLists.
var forEach = function(arr, it) {
  return Array.prototype.forEach.call(arr, it);
};
var invoke = function(obj, fn) {
  var args = Array.prototype.slice.call(arguments, 2);
  return map(obj, function(value) {
    return (isFunction(fn) ? fn || value : value[fn]).apply(value, args);
  });
};
var isFunction = function(obj) {
  return Object.prototype.toString.call(obj) === '[object Function]';
};
var map = function(arr, it) {
  return Array.prototype.map.call(arr, it);
};
var pluck = function(arr, prop) {
  return map(arr, function(item) { return item[prop]; } );
};

// Parse `key=value; key=value` strings (for cookies).
var keyvalParse = function(str) {
  var obj = {};
  var pairs = str.split(';');
  for (var i = 0; pairs.length > i; i++) {
    var kvs = pairs[i].trim().split('=');
    obj[kvs[0]] = kvs[1];
  }
  return obj;
};
var removeClass = function(els, className) {
  return invoke(pluck(els, 'classList'), 'remove', className);
};

var postMessage = function(target, msg) {
  target.contentDocument.defaultView.postMessage(msg, '*');
};

var headEl = document.getElementsByTagName('head')[0];
var bodyEl = document.getElementsByTagName('body')[0];

// Get preview styles intended for preview iframes.
var styles = pluck(
  headEl.querySelectorAll('style[type="text/preview"]'),
  'innerHTML').join('');
// Get preview scripts intended for preview iframes.
var scripts = pluck(
  headEl.querySelectorAll('script[type="text/preview"]'),
  'innerHTML').join('');

var previewUrl = location.href.split('#')[0] + '#__preview__';

// Check if browser treats data uris as same origin.
var iframeEl = document.createElement('iframe');
iframeEl.src = 'data:text/html,';
bodyEl.appendChild(iframeEl);
iframeEl.addEventListener('load', function() {
  var support = { sameOriginDataUri: true };
  try {
    this.contentDocument;
    if (!this.contentDocument) support.sameOriginDataUri = false;
  } catch (e) {
    support.sameOriginDataUri = false;
  }
  this.parentNode.removeChild(this);
  // Loop through code textareas and render the code in iframes.
  forEach(bodyEl.getElementsByTagName('textarea'), function(codeEl, idx) {
    addIframe(codeEl, support, idx);
    resizeableButtons();
    autoResizeTextArea(codeEl);
  });
});

var addIframe = function(codeEl, support, iframeId) {
  var previewEl, resizeableEl, iframeEl;
  previewEl = document.createElement('div');
  previewEl.appendChild(resizeableEl = document.createElement('div'));
  previewEl.className = 'preview';
  resizeableEl.appendChild(iframeEl = document.createElement('iframe'));
  resizeableEl.className = 'resizeable';
  iframeEl.setAttribute('scrolling', 'no');
  iframeEl.name = 'iframe' + iframeId++;
  iframeEl.addEventListener('load', function() {
    var htmlEl, bodyEl, scriptEl, styleEl, headEl, oldHeadEl, doc;
    doc = this.contentDocument;
    // Abort if we're loading a data uri in a browser without same
    // origin data uri support.
    if (!support.sameOriginDataUri && this.src !== previewUrl) {
      return;
    // Otherwise replace iframe content with the preview code.
    } else if (this.src === previewUrl) {
      htmlEl = doc.createElement('html');
      htmlEl.appendChild(doc.createElement('head'));
      htmlEl.appendChild(bodyEl = doc.createElement('body'));
      bodyEl.innerHTML = codeEl.textContent;
      doc.replaceChild(htmlEl, doc.documentElement);
    }
    // Add scripts and styles.
    headEl = doc.createElement('head');
    headEl.appendChild(styleEl = doc.createElement('style'));
    headEl.appendChild(scriptEl = doc.createElement('script'));
    scriptEl.textContent = scripts;
    styleEl.textContent = styles;
    oldHeadEl = doc.getElementsByTagName('head')[0];
    oldHeadEl.parentNode.replaceChild(headEl, oldHeadEl);
    postMessage(this, 'getHeight');
  });
  var iframeSrc;
  if (!support.sameOriginDataUri) {
    iframeSrc = previewUrl;
  } else {
    iframeSrc = 'data:text/html;charset=utf-8,' +
      encodeURIComponent('<!doctype html>' +
        codeEl.textContent);
  }
  iframeEl.setAttribute('src', iframeSrc);
  var codeDidChange = function() {
    iframeEl.contentDocument.body.innerHTML = this.value;
    postMessage(iframeEl, 'getHeight');
  };
  codeEl.addEventListener('keypress', codeDidChange);
  codeEl.addEventListener('keyup', codeDidChange);
  codeEl.parentNode.insertBefore(previewEl, codeEl);
};

// Add an element with the same styles and content as the textarea to
// calculate the height of the textarea content.
var autoResizeTextArea = function(el) {
  var mirrorEl = document.createElement('div');
  mirrorEl.className = 'preview-code';
  mirrorEl.style.position = 'absolute';
  mirrorEl.style.left = '-9999px';
  bodyEl.appendChild(mirrorEl);
  var maxHeight = parseInt(
    window.getComputedStyle(el).getPropertyValue('max-height'),
    10);
  var codeDidChange = function(ev) {
    mirrorEl.textContent = this.value + '\n';
    var height = mirrorEl.offsetHeight + 2; // Account for borders.
    if (height >= maxHeight) {
      this.style.overflow = 'auto';
    } else {
      this.style.overflow = 'hidden';
    }
    this.style.height = (mirrorEl.offsetHeight + 2) + 'px';
  };
  el.addEventListener('keypress', codeDidChange);
  el.addEventListener('keyup', codeDidChange);
  codeDidChange.call(el);
};

var resizeableButtons = function() {
  var settingsEl = bodyEl.getElementsByClassName('settings')[0];
  var resizeableEls = bodyEl.getElementsByClassName('resizeable');
  var resizeableElOffset = 30; // `.resizeable` padding
  var resizePreviews = function(width) {
    document.cookie = 'preview-width=' + width;
    forEach(resizeableEls, function(el) {
      if (width === 'auto') width = el.parentNode.offsetWidth;
      el.style.width = width + 'px';
      // TODO: Add CSS transitions and update height after `transitionend` event
      postMessage(el.getElementsByTagName('iframe')[0], 'getHeight');
    });
  };

  // Resize previews to the cookie value.
  var previewWidth = keyvalParse(document.cookie)['preview-width'];
  if (previewWidth) {
    resizePreviews(previewWidth);
    removeClass(settingsEl.getElementsByClassName('is-active'), 'is-active');
    var btn = settingsEl.querySelector('button[data-width="' + previewWidth + '"]');
    if (btn) { btn.classList.add('is-active'); }
  }

  window.addEventListener('message', function (ev) {
    if (ev.data == null || !ev.source) return;
    var data = ev.data;
    var sourceFrameEl = document.getElementsByName(ev.source.name)[0];
    // Set iframe height
    if (data.height != null && sourceFrameEl) {
      sourceFrameEl.parentNode.style.height = (data.height + resizeableElOffset) + 'px';
    }
  }, false);

  // Resizing buttons
  if (settingsEl && resizeableEls.length > 0) {
    settingsEl.hidden = false;
    settingsEl.addEventListener('click', function(event) {
      var tagName = event.target.tagName.toLowerCase();
      var btn;
      if (tagName === 'button') btn = event.target;
      else if (tagName === 'svg') btn = event.target.parentNode;
      else return;
      event.preventDefault();
      removeClass(settingsEl.getElementsByClassName('is-active'), 'is-active');
      btn.classList.add('is-active');
      var width = btn.dataset.width;
      resizePreviews(width);
    });
  }
};

})();
<|endoftext|>


<commit_before>CT.data = {
	map: {},

	// data comparison
	"sameList": function(list1, list2) {
	    if (list1.length != list2.length)
	        return false;
	    for (var i = 0; i < list1.length; i++) {
	        if (list1[i] != list2[i])
	            return false;
	    }
	    return true;
	},
	"copyList": function(oldlist) {
	    var newlist = [];
	    for (var i = 0; i < oldlist.length; i++)
	        newlist.push(oldlist[i]);
	    return newlist;
	},
	"diff": function(dold, dnew, required, compdicts, submap, complists) {
	    var ddiff = required || {};
	    compdicts = compdicts || [];
	    complists = complists || [];
	    submap = submap || {};
	    for (var k in dnew) {
	        if (compdicts.indexOf(k) != -1) {
	            for (var j in dnew[k]) {
	                if (dnew[k][j] != dold[k][j]) {
	                    ddiff[k] = dnew[k];
	                    break;
	                }
	            }
	        }
	        else if (complists.indexOf(k) != -1) {
	            if (!sameList(dnew[k], dold[k]))
	                ddiff[k] = dnew[k];
	        }
	        else if (k in submap) {
	            if (dnew[k] != dold[k][submap[k]])
	                ddiff[k] = dnew[k];
	        }
	        else if (dnew[k] != dold[k])
	            ddiff[k] = dnew[k];
	    }
	    return ddiff;
	},

	// cache
	"get": function(key) {
		return CT.data.map[key];
	},
	"add": function(d) {
	    if (CT.data.map[d.key]) {
	        for (var k in d)
	            CT.data.map[d.key][k] = d[k];
	    }
	    else
	        CT.data.map[d.key] = d;
	},
	"addSet": function(dlist) {
	    for (var i = 0; i < dlist.length; i++)
	        CT.data.add(dlist[i]);
	},
	"uniquify": function(items, exceptions) {
	    exceptions = exceptions || [];
	    items.sort();
	    var newitems = [];
	    var latestitem = "";
	    for (var i = 0; i < items.length; i++) {
	        if (items[i] != latestitem && exceptions.indexOf(items[i]) == -1) {
	            latestitem = items[i];
	            newitems.push(latestitem);
	        }
	    }
	    return newitems;
	},

	// data acquisition functions -- require backend integration
	"checkAndDo": function(keys, cb, nlcb, eb, req, getpath, getparams) {
	    var needed = [];
	    keys = CT.data.uniquify(keys);
	    for (var i = 0; i < keys.length; i++) {
	        if (CT.data.map[keys[i]] == null || req && CT.data.map[keys[i]][req] == null)
	            needed.push(keys[i]);
	    }
	    if (needed.length == 0)
	        return cb();
	    getparams = getparams || {"gtype": "data"};
	    getparams.keys = needed;
	    CT.net.post(getpath || "/get", getparams,
	    "error retrieving data", function(rawdata) {
	        CT.data.addSet(rawdata);
	        if (nlcb) nlcb(needed);
	        cb();
	    }, eb);
	},
	"requirePrep": function() {}, // override!
	"itemReady": function(key, plist) {
	    var isready = key in CT.data.map;
	    plist && plist.forEach(function(p) {
	    	isready = isready && p in CT.data.map[key];
	    });
	    return isready;
	},
	"require": function(key, cb, plist, getpath, getparams) {
		CT.data.requirePrep(key);
	    if (CT.data.itemReady(key, plist))
	        cb(CT.data.map[key]);
	    else {
	    	getparams = getparams || {"gtype": "user", "chat": 1};
	    	getparams.uid = key;
	        CT.net.post(getpath || "/get", getparams,
	            "error retrieving data", function(rawdata) {
	                CT.data.new(rawdata);
	                cb(CT.data.map[key]);
	            });
	    }
	},
	"requireAll": function(keys, cb, uid, plist, getpath, getparams) {
		keys.forEach(CT.data.requirePrep);
	    var needed = [];
	    for (var i = 0; i < keys.length; i++) {
	    	if (!CT.data.itemReady(keys[i], plist))
	            needed.push(keys[i]);
	    }
	    if (needed.length == 0)
	        cb(keys);
	    else {
	    	getparams = getparams || {"gtype": "user", "chat": 1};
	    	getparams.uids = needed;
	        CT.net.post("/get", getparams,
	            "error retrieving data", function(rawdata) {
	                for (var i = 0; i < rawdata.length; i++)
	                    CT.data.new(rawdata[i]);
	                cb(keys);
	            });
	    }
	}
};<commit_msg>fixed misreferences in CT.data<commit_after>CT.data = {
	map: {},

	// data comparison
	"sameList": function(list1, list2) {
	    if (list1.length != list2.length)
	        return false;
	    for (var i = 0; i < list1.length; i++) {
	        if (list1[i] != list2[i])
	            return false;
	    }
	    return true;
	},
	"copyList": function(oldlist) {
	    var newlist = [];
	    for (var i = 0; i < oldlist.length; i++)
	        newlist.push(oldlist[i]);
	    return newlist;
	},
	"diff": function(dold, dnew, required, compdicts, submap, complists) {
	    var ddiff = required || {};
	    compdicts = compdicts || [];
	    complists = complists || [];
	    submap = submap || {};
	    for (var k in dnew) {
	        if (compdicts.indexOf(k) != -1) {
	            for (var j in dnew[k]) {
	                if (dnew[k][j] != dold[k][j]) {
	                    ddiff[k] = dnew[k];
	                    break;
	                }
	            }
	        }
	        else if (complists.indexOf(k) != -1) {
	            if (!sameList(dnew[k], dold[k]))
	                ddiff[k] = dnew[k];
	        }
	        else if (k in submap) {
	            if (dnew[k] != dold[k][submap[k]])
	                ddiff[k] = dnew[k];
	        }
	        else if (dnew[k] != dold[k])
	            ddiff[k] = dnew[k];
	    }
	    return ddiff;
	},

	// cache
	"get": function(key) {
		return CT.data.map[key];
	},
	"add": function(d) {
	    if (CT.data.map[d.key]) {
	        for (var k in d)
	            CT.data.map[d.key][k] = d[k];
	    }
	    else
	        CT.data.map[d.key] = d;
	},
	"addSet": function(dlist) {
	    for (var i = 0; i < dlist.length; i++)
	        CT.data.add(dlist[i]);
	},
	"uniquify": function(items, exceptions) {
	    exceptions = exceptions || [];
	    items.sort();
	    var newitems = [];
	    var latestitem = "";
	    for (var i = 0; i < items.length; i++) {
	        if (items[i] != latestitem && exceptions.indexOf(items[i]) == -1) {
	            latestitem = items[i];
	            newitems.push(latestitem);
	        }
	    }
	    return newitems;
	},

	// data acquisition functions -- require backend integration
	"checkAndDo": function(keys, cb, nlcb, eb, req, getpath, getparams) {
	    var needed = [];
	    keys = CT.data.uniquify(keys);
	    for (var i = 0; i < keys.length; i++) {
	        if (CT.data.map[keys[i]] == null || req && CT.data.map[keys[i]][req] == null)
	            needed.push(keys[i]);
	    }
	    if (needed.length == 0)
	        return cb();
	    getparams = getparams || {"gtype": "data"};
	    getparams.keys = needed;
	    CT.net.post(getpath || "/get", getparams,
	    "error retrieving data", function(rawdata) {
	        CT.data.addSet(rawdata);
	        if (nlcb) nlcb(needed);
	        cb();
	    }, eb);
	},
	"requirePrep": function() {}, // override!
	"itemReady": function(key, plist) {
	    var isready = key in CT.data.map;
	    plist && plist.forEach(function(p) {
	    	isready = isready && p in CT.data.map[key];
	    });
	    return isready;
	},
	"require": function(key, cb, plist, getpath, getparams) {
		CT.data.requirePrep(key);
	    if (CT.data.itemReady(key, plist))
	        cb(CT.data.map[key]);
	    else {
	    	getparams = getparams || {"gtype": "user", "chat": 1};
	    	getparams.uid = key;
	        CT.net.post(getpath || "/get", getparams,
	            "error retrieving data", function(rawdata) {
	                CT.data.add(rawdata);
	                cb(CT.data.map[key]);
	            });
	    }
	},
	"requireAll": function(keys, cb, uid, plist, getpath, getparams) {
		keys.forEach(CT.data.requirePrep);
	    var needed = [];
	    for (var i = 0; i < keys.length; i++) {
	    	if (!CT.data.itemReady(keys[i], plist))
	            needed.push(keys[i]);
	    }
	    if (needed.length == 0)
	        cb(keys);
	    else {
	    	getparams = getparams || {"gtype": "user", "chat": 1};
	    	getparams.uids = needed;
	        CT.net.post("/get", getparams,
	            "error retrieving data", function(rawdata) {
	            	CT.data.addSet(rawdata);
	                cb(keys);
	            });
	    }
	}
};<|endoftext|>


<commit_before>const {unreadApiUrl, apiUrl} = require('../config');
const messagesParser = require('./xml/messages');
const foldersParser = require('./xml/folders');

function logError(status, res) {
    var error = new Error(status);

    error.response = res;

    console.error(error);
}

function request(url) {
    return new Promise((resolve, reject) => {
        const xhr = new XMLHttpRequest();

        xhr.onload = function() {
            if (this.status >= 200 && this.status < 300) {
                resolve(this.responseXML);
            } else {
                logError(this.statusText, this.response);
                reject();
            }
        };

        xhr.onerror = function () {
            logError(this.statusText, this.response);
            reject();
        };

        xhr.open('GET', url, true);
        xhr.send();
    });
}

var api = {
    loadMessages() {
        return Promise.all([
            request(apiUrl + 'mailbox_list'),
            request(apiUrl + 'folder_list')
        ]).then(([messages, folders]) => {
            return {
                messages: messagesParser.parse(messages),
                folders: foldersParser.parse(folders)
            };
        });
    }
};

//function userData() {
//    Request({
//        url: API_URL + 'settings_setup',
//        onComplete(res) {
//            if (res.status >= 200 && res.status < 300) {
//                onSuccess(res.json.counters.unread);
//            }
//            else {
//                onError();
//            }
//        }
//    }).get();
//}

module.exports = api;
<commit_msg>remove additional request for getting folders<commit_after>const {API_URL, IGNORED_FOLDERS} = require('../config');
const userParser = require('./utils/xml/user');
const messagesParser = require('./utils/xml/messages');

function logError(status, res) {
    var error = new Error(status);

    error.response = res;

    console.error(error);
}

function request(url) {
    return new Promise((resolve, reject) => {
        const xhr = new XMLHttpRequest();

        xhr.onload = function() {
            if (this.status >= 200 && this.status < 300) {
                resolve(this.responseXML);
            } else {
                logError(this.statusText, this.response);
                reject();
            }
        };

        xhr.onerror = function () {
            logError(this.statusText, this.response);
            reject();
        };

        xhr.open('GET', url, true);
        xhr.send();
    });
}

function loadData() {
    return Promise.all([
        request(`${API_URL}settings_setup`),
        request(`${API_URL}mailbox_list?first=0&last=100&extra_cond=only_new&goto=all`)
    ]).then(([userXml, messagesXml]) => {
        const user = userParser(userXml);
        const {messages, unreadCount} = messagesParser(messagesXml);

        return {
            user,
            unreadCount,
            messages
        };
    });
}

module.exports = {
    loadData
};
<|endoftext|>


<commit_before>var bot = require('./bot');
var interval = require('interval');
var config = require('./config');
var stringify = require('json-stable-stringify');
var PouchDB = require('pouchdb');
var dbremote = new PouchDB("https://" + config.couch.user + ":" + config.couch.pw + "@" + config.couch.server + "/" + config.couch.db);
var db = new PouchDB('./local');
var sync = db.sync(dbremote);
sync.on('change', function (ch) {
  console.log(JSON.stringify(ch, false, 4));
});
sync.on('complete', function () {
  db.replicate.to(dbremote, {live: true});
  console.log('starting');
  setInterval(interfunc, interval({seconds: 10}));
  interfunc();
});
sync.on('error', function (e) {
  console.log(e);
  process.exit(5);
});

var i = 0;
function interfunc() {
  //console.log('run number #', ++i);
  bot();
}
process.on('exit', function (e) {
  console.log('exiting', e);
});
<commit_msg>less verbose replication<commit_after>var bot = require('./bot');
var interval = require('interval');
var config = require('./config');
var stringify = require('json-stable-stringify');
var PouchDB = require('pouchdb');
var dbremote = new PouchDB("https://" + config.couch.user + ":" + config.couch.pw + "@" + config.couch.server + "/" + config.couch.db);
var db = new PouchDB('./local');
var sync = db.sync(dbremote);
sync.on('change', function (ch) {
  console.log('syncing');
});
sync.on('complete', function () {
  db.replicate.to(dbremote, {live: true});
  console.log('starting');
  setInterval(interfunc, interval({seconds: 10}));
  interfunc();
});
sync.on('error', function (e) {
  console.log(e);
  process.exit(5);
});

var i = 0;
function interfunc() {
  //console.log('run number #', ++i);
  bot();
}
process.on('exit', function (e) {
  console.log('exiting', e);
});
<|endoftext|>


<commit_before>/*!
 * Copyright 2014 Apereo Foundation (AF) Licensed under the
 * Educational Community License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License. You may
 * obtain a copy of the License at
 *
 *     http://opensource.org/licenses/ECL-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an "AS IS"
 * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */

var _ = require('underscore');

var OAE = require('oae-util/lib/oae');
var PreviewProcessorAPI = require('oae-preview-processor');
var Util = require('oae-util/lib/util');

var DiscussionsAPI = require('oae-discussions');
var DiscussionsConstants = require('oae-discussions/lib/constants').DiscussionsConstants;

//////////////////////////////
// CREATE / GET DISCUSSIONS //
//////////////////////////////

/**
 * @REST postDiscussionCreate
 *
 * Create a new discussion
 *
 * @Server      tenant
 * @Method      POST
 * @Path        /discussion/create
 * @BodyParam   {NewDiscussion}         body                Information about discussion to create
 * @Return      {Discussion}                                Returns an object representing the discussion
 */
OAE.tenantRouter.on('post', '/api/discussion/create', function(req, res) {

    var members = {};
    if (_.isArray(req.body.managers)) {
        _.each(req.body.managers, function(manager) {
            members[manager] = DiscussionsConstants.roles.MANAGER;
        });
    } else if (_.isString(req.body.managers)) {
        members[req.body.managers] = DiscussionsConstants.roles.MANAGER;
    }

    if (_.isArray(req.body.members)) {
        _.each(req.body.members, function(member) {
            members[member] = DiscussionsConstants.roles.MEMBER;
        });
    } else if (_.isString(req.body.members)) {
        members[req.body.members] = DiscussionsConstants.roles.MEMBER;
    }

    DiscussionsAPI.Discussions.createDiscussion(req.ctx, req.body.displayName, req.body.description, req.body.visibility, members, null, function(err, discussion) {
        if (err) {
            return res.send(err.code, err.msg);
        }

        res.send(200, discussion);
    });
});

/**
 * @REST postDiscussionDiscussionId
 *
 * Update a discussion
 *
 * @Server      tenant
 * @Method      POST
 * @Path        /discussion/{discussionId}
 * @BodyParam   {UpdatedDiscussion}     body                Updated information for discussion
 * @Return      {Discussion}                                Returns an object representing the discussion
 */
OAE.tenantRouter.on('post', '/api/discussion/:discussionId', function(req, res) {
    DiscussionsAPI.Discussions.updateDiscussion(req.ctx, req.params.discussionId, req.body, function(err, discussion) {
        if (err) {
            return res.send(err.code, err.msg);
        }

        res.send(200, discussion);
    });
});

/**
 * @REST deleteDiscussionDiscussionId
 *
 * Delete a discussion
 *
 * @Server      tenant
 * @Method      DELETE
 * @Path        /discussion/{discussionId}
 * @PathParam   {string}                discussionId        Unique identifier for discusion to update
 */
OAE.tenantRouter.on('delete', '/api/discussion/:discussionId', function(req, res) {
    DiscussionsAPI.Discussions.deleteDiscussion(req.ctx, req.params.discussionId, function(err, message) {
        if (err) {
            return res.send(err.code, err.msg);
        }

        res.send(200, message);
    });
});

/**
 * @REST getDiscussionLibraryPrincipalId
 *
 * Get a user or group's discussions library
 *
 * @Server      tenant
 * @Method      GET
 * @Path        /discussion/library/{principalId}
 * @PathParam   {string}                principalId         Unique identifier for user or group whose discussions are requested
 * @QueryParam  {number}                [limit]             Maximum number of discussions to return (defaults to 12, limited to between 1 and 25)
 * @QueryParam  {string}                [start]             Marker for continuing search (starts at beginning by default)
 * @Return      {DiscussionsLibrary}                        Returns an object containing followers of user
 */
OAE.tenantRouter.on('get', '/api/discussion/library/:principalId', function(req, res) {
    var limit = Util.getNumberParam(req.query.limit, 12, 1, 25);
    DiscussionsAPI.Discussions.getDiscussionsLibrary(req.ctx, req.params.principalId, req.query.start, limit, function(err, discussions, nextToken) {
        if (err) {
            return res.send(err.code, err.msg);
        }

        res.send(200, {'results': discussions, 'nextToken': nextToken});
    });
});

/**
 * @REST deleteDiscussionLibraryPrincipalIdDiscussionId
 *
 * Delete a discussion from a user or group library
 *
 * @Server      tenant
 * @Method      DELETE
 * @Path        /discussion/library/{principalId}/{discussionId}
 * @PathParam   {string}                discussionId        Unique identifier for discusion to remove
 * @PathParam   {string}                principalId         Unique identifier for user or group whose library is affected
 */
OAE.tenantRouter.on('delete', '/api/discussion/library/:principalId/:discussionId', function(req, res) {
    DiscussionsAPI.Discussions.removeDiscussionFromLibrary(req.ctx, req.params.principalId, req.params.discussionId, function(err) {
        if (err) {
            return res.send(err.code, err.msg);
        }

        res.send(200);
    });
});

/**
 * @REST getDiscussionDiscussionId
 *
 * Get a full discussion profile
 *
 * @Server      tenant
 * @Method      GET
 * @Path        /discussion/{discussionId}
 * @PathParam   {string}                discussionId        Unique identifier for discusion to retrieve
 * @Return      {DiscussionDetails}                         Returns an object containing the detailed discussion profile
 */
OAE.tenantRouter.on('get', '/api/discussion/:discussionId', function(req, res) {
    DiscussionsAPI.Discussions.getFullDiscussionProfile(req.ctx, req.params.discussionId, function(err, discussion) {
        if (err) {
            return res.send(err.code, err.msg);
        }

        res.send(200, discussion);
    });
});

//////////////////////////////////////
// UPDATE / GET DISCUSSIONS MEMBERS //
//////////////////////////////////////

/**
 * @REST postDiscussionDiscussionIdShare
 *
 * Share a discussion
 *
 * @Server      tenant
 * @Method      POST
 * @Path        /discussion/{discussionId}/share
 * @PathParam   {string}                discussionId        Unique identifier for discusion to share
 * @BodyParam   {MemberList}            body                Unique identifiers(s) for participant(s) in the discussion
 * @Return      {void}
 */
OAE.tenantRouter.on('post', '/api/discussion/:discussionId/share', function(req, res) {

    var members = (_.isArray(req.body.members)) ? req.body.members : [req.body.members];
    members = _.compact(members);

    DiscussionsAPI.Discussions.shareDiscussion(req.ctx, req.params.discussionId, members, function(err) {
        if (err) {
            return res.send(err.code, err.msg);
        }
        res.send(200);
    });
});

/**
 * @REST postDiscussionDiscussionIdMembers
 *
 * Set discussion permissions
 *
 * @Server      tenant
 * @Method      POST
 * @Path        /discussion/{discussionId}/members
 * @PathParam   {string}                discussionId        Unique identifier for discusion to share
 * @BodyParam   {MemberList}            body                Unique identifiers(s) for participant(s) in the discussion
 * @Return      {void}
 */
OAE.tenantRouter.on('post', '/api/discussion/:discussionId/members', function(req, res) {

    // Parse the incoming false values
    var permissionUpdates = {};
    _.each(req.body, function(value, key) {
        permissionUpdates[key] = Util.castToBoolean(value);
    });

    DiscussionsAPI.Discussions.setDiscussionPermissions(req.ctx, req.params.discussionId, permissionUpdates, function(err) {
        if (err) {
            return res.send(err.code, err.msg);
        }
        res.send(200);
    });
});

/**
 * @REST getDiscussionDiscussionIdMembers
 *
 * Get discussion members
 *
 * @Server      tenant
 * @Method      GET
 * @Path        /discussion/{discussionId}/members
 * @PathParam   {string}                discussionId        Unique identifier for discusion to share
 * @QueryParam  {number}                [limit]             Maximum number of users to return (defaults to 10, limited to between 1 and 25)
 * @QueryParam  {string}                [start]             Marker for continuing search (starts at beginning by default)
 * @Return      {MembersResponse}                           Returns an object containing members of discussion
 */
OAE.tenantRouter.on('get', '/api/discussion/:discussionId/members', function(req, res) {
    var limit = Util.getNumberParam(req.query.limit, 10, 1, 25);
    DiscussionsAPI.Discussions.getDiscussionMembers(req.ctx, req.params.discussionId, req.query.start, limit, function(err, members, nextToken) {
        if (err) {
            return res.send(err.code, err.msg);
        }

        res.send(200, {'results': members, 'nextToken': nextToken});
    });
});

//////////////////////////////////////
// CREATE / GET DISCUSSION MESSAGES //
//////////////////////////////////////

/**
 * @REST getDiscussionDiscussionIdMessages
 *
 * Get a list of messages from the discussion
 *
 * @Server      tenant
 * @Method      GET
 * @Path        /discussion/{discussionId}/messages
 * @PathParam   {string}                discussionId        Unique identifier for discusion to share
 * @QueryParam  {number}                [limit]             Maximum number of messages to return (defaults to 10, limited to between 1 and 25)
 * @QueryParam  {string}                [start]             Marker for continuing search (starts at beginning by default)
 * @Return      {MessagesResponse}                          Returns an object containing messages of discussion
 */
OAE.tenantRouter.on('get', '/api/discussion/:discussionId/messages', function(req, res) {
    var limit = Util.getNumberParam(req.query.limit, 10, 1, 25);
    DiscussionsAPI.Discussions.getMessages(req.ctx, req.params.discussionId, req.query.start, limit, function(err, messages, nextToken) {
        if (err) {
            return res.send(err.code, err.msg);
        }

        res.send(200, {'results': messages, 'nextToken': nextToken});
    });
});

/**
 * @REST postDiscussionDiscussionIdMessages
 *
 * Create a new message in a discussion
 *
 * @Server      tenant
 * @Method      POST
 * @Path        /discussion/{discussionId}/messages
 * @PathParam   {string}                discussionId        Unique identifier for discusion for new message
 * @BodyParam   {NewMessage}            body                Content of new message
 * @Return      {Message}                                   Returns an object representing the new message
 */
OAE.tenantRouter.on('post', '/api/discussion/:discussionId/messages', function(req, res) {
    DiscussionsAPI.Discussions.createMessage(req.ctx, req.params.discussionId, req.body.body, req.body.replyTo, function(err, message) {
        if (err) {
            return res.send(err.code, err.msg);
        }

        res.send(200, message);
    });
});

/**
 * @REST deleteDiscussionDiscussionIdMessagesCreated
 *
 * Delete a message in a discussion
 *
 * @Server      tenant
 * @Method      DELETE
 * @Path        /discussion/{discussionId}/messages/{created}
 * @PathParam   {string}                created             Creation time of message to delete
 * @PathParam   {string}                discussionId        Unique identifier for discusion containing message
 * @Return      {Message}                                   Returns an object representing the deleted message
 */
OAE.tenantRouter.on('delete', '/api/discussion/:discussionId/messages/:created', function(req, res) {
    DiscussionsAPI.Discussions.deleteMessage(req.ctx, req.params.discussionId, req.params.created, function(err, message) {
        if (err) {
            return res.send(err.code, err.msg);
        }

        res.send(200, message);
    });
});
<commit_msg>convert body parameters to form parameters<commit_after>/*!
 * Copyright 2014 Apereo Foundation (AF) Licensed under the
 * Educational Community License, Version 2.0 (the "License"); you may
 * not use this file except in compliance with the License. You may
 * obtain a copy of the License at
 *
 *     http://opensource.org/licenses/ECL-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an "AS IS"
 * BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
 * or implied. See the License for the specific language governing
 * permissions and limitations under the License.
 */

var _ = require('underscore');

var OAE = require('oae-util/lib/oae');
var PreviewProcessorAPI = require('oae-preview-processor');
var Util = require('oae-util/lib/util');

var DiscussionsAPI = require('oae-discussions');
var DiscussionsConstants = require('oae-discussions/lib/constants').DiscussionsConstants;

//////////////////////////////
// CREATE / GET DISCUSSIONS //
//////////////////////////////

/**
 * @REST postDiscussionCreate
 *
 * Create a new discussion
 *
 * @Server      tenant
 * @Method      POST
 * @Path        /discussion/create
 * @BodyParam   {NewDiscussion}         body                Information about discussion to create
 * @Return      {Discussion}                                Returns an object representing the discussion
 */
OAE.tenantRouter.on('post', '/api/discussion/create', function(req, res) {

    var members = {};
    if (_.isArray(req.body.managers)) {
        _.each(req.body.managers, function(manager) {
            members[manager] = DiscussionsConstants.roles.MANAGER;
        });
    } else if (_.isString(req.body.managers)) {
        members[req.body.managers] = DiscussionsConstants.roles.MANAGER;
    }

    if (_.isArray(req.body.members)) {
        _.each(req.body.members, function(member) {
            members[member] = DiscussionsConstants.roles.MEMBER;
        });
    } else if (_.isString(req.body.members)) {
        members[req.body.members] = DiscussionsConstants.roles.MEMBER;
    }

    DiscussionsAPI.Discussions.createDiscussion(req.ctx, req.body.displayName, req.body.description, req.body.visibility, members, null, function(err, discussion) {
        if (err) {
            return res.send(err.code, err.msg);
        }

        res.send(200, discussion);
    });
});

/**
 * @REST postDiscussionDiscussionId
 *
 * Update a discussion
 *
 * @Server      tenant
 * @Method      POST
 * @Path        /discussion/{discussionId}
 * @FormParam   {string}        discussionId        Unique identifier for discusion to update
 * @FormParam   {string}        [description]       Description of discussion
 * @FormParam   {string}        [displayName]       Name to display for discussion
 * @FormParam   {string}        [visibility]        Visibility for discussion           [loggedin,private,public]
 * @Return      {Discussion}                        Returns an object representing the discussion
 */
OAE.tenantRouter.on('post', '/api/discussion/:discussionId', function(req, res) {
    DiscussionsAPI.Discussions.updateDiscussion(req.ctx, req.params.discussionId, req.body, function(err, discussion) {
        if (err) {
            return res.send(err.code, err.msg);
        }

        res.send(200, discussion);
    });
});

/**
 * @REST deleteDiscussionDiscussionId
 *
 * Delete a discussion
 *
 * @Server      tenant
 * @Method      DELETE
 * @Path        /discussion/{discussionId}
 * @PathParam   {string}                discussionId        Unique identifier for discusion to update
 */
OAE.tenantRouter.on('delete', '/api/discussion/:discussionId', function(req, res) {
    DiscussionsAPI.Discussions.deleteDiscussion(req.ctx, req.params.discussionId, function(err, message) {
        if (err) {
            return res.send(err.code, err.msg);
        }

        res.send(200, message);
    });
});

/**
 * @REST getDiscussionLibraryPrincipalId
 *
 * Get a user or group's discussions library
 *
 * @Server      tenant
 * @Method      GET
 * @Path        /discussion/library/{principalId}
 * @PathParam   {string}                principalId         Unique identifier for user or group whose discussions are requested
 * @QueryParam  {number}                [limit]             Maximum number of discussions to return (defaults to 12, limited to between 1 and 25)
 * @QueryParam  {string}                [start]             Marker for continuing search (starts at beginning by default)
 * @Return      {DiscussionsLibrary}                        Returns an object containing followers of user
 */
OAE.tenantRouter.on('get', '/api/discussion/library/:principalId', function(req, res) {
    var limit = Util.getNumberParam(req.query.limit, 12, 1, 25);
    DiscussionsAPI.Discussions.getDiscussionsLibrary(req.ctx, req.params.principalId, req.query.start, limit, function(err, discussions, nextToken) {
        if (err) {
            return res.send(err.code, err.msg);
        }

        res.send(200, {'results': discussions, 'nextToken': nextToken});
    });
});

/**
 * @REST deleteDiscussionLibraryPrincipalIdDiscussionId
 *
 * Delete a discussion from a user or group library
 *
 * @Server      tenant
 * @Method      DELETE
 * @Path        /discussion/library/{principalId}/{discussionId}
 * @PathParam   {string}                discussionId        Unique identifier for discusion to remove
 * @PathParam   {string}                principalId         Unique identifier for user or group whose library is affected
 */
OAE.tenantRouter.on('delete', '/api/discussion/library/:principalId/:discussionId', function(req, res) {
    DiscussionsAPI.Discussions.removeDiscussionFromLibrary(req.ctx, req.params.principalId, req.params.discussionId, function(err) {
        if (err) {
            return res.send(err.code, err.msg);
        }

        res.send(200);
    });
});

/**
 * @REST getDiscussionDiscussionId
 *
 * Get a full discussion profile
 *
 * @Server      tenant
 * @Method      GET
 * @Path        /discussion/{discussionId}
 * @PathParam   {string}                discussionId        Unique identifier for discusion to retrieve
 * @Return      {DiscussionDetails}                         Returns an object containing the detailed discussion profile
 */
OAE.tenantRouter.on('get', '/api/discussion/:discussionId', function(req, res) {
    DiscussionsAPI.Discussions.getFullDiscussionProfile(req.ctx, req.params.discussionId, function(err, discussion) {
        if (err) {
            return res.send(err.code, err.msg);
        }

        res.send(200, discussion);
    });
});

//////////////////////////////////////
// UPDATE / GET DISCUSSIONS MEMBERS //
//////////////////////////////////////

/**
 * @REST postDiscussionDiscussionIdShare
 *
 * Share a discussion
 *
 * @Server      tenant
 * @Method      POST
 * @Path        /discussion/{discussionId}/share
 * @PathParam   {string}                discussionId        Unique identifier for discusion to share
 * @BodyParam   {MemberList}            body                Unique identifiers(s) for participant(s) in the discussion
 * @Return      {void}
 */
OAE.tenantRouter.on('post', '/api/discussion/:discussionId/share', function(req, res) {

    var members = (_.isArray(req.body.members)) ? req.body.members : [req.body.members];
    members = _.compact(members);

    DiscussionsAPI.Discussions.shareDiscussion(req.ctx, req.params.discussionId, members, function(err) {
        if (err) {
            return res.send(err.code, err.msg);
        }
        res.send(200);
    });
});

/**
 * @REST postDiscussionDiscussionIdMembers
 *
 * Set discussion permissions
 *
 * @Server      tenant
 * @Method      POST
 * @Path        /discussion/{discussionId}/members
 * @PathParam   {string}                discussionId        Unique identifier for discusion to share
 * @BodyParam   {MemberList}            body                Unique identifiers(s) for participant(s) in the discussion
 * @Return      {void}
 */
OAE.tenantRouter.on('post', '/api/discussion/:discussionId/members', function(req, res) {

    // Parse the incoming false values
    var permissionUpdates = {};
    _.each(req.body, function(value, key) {
        permissionUpdates[key] = Util.castToBoolean(value);
    });

    DiscussionsAPI.Discussions.setDiscussionPermissions(req.ctx, req.params.discussionId, permissionUpdates, function(err) {
        if (err) {
            return res.send(err.code, err.msg);
        }
        res.send(200);
    });
});

/**
 * @REST getDiscussionDiscussionIdMembers
 *
 * Get discussion members
 *
 * @Server      tenant
 * @Method      GET
 * @Path        /discussion/{discussionId}/members
 * @PathParam   {string}                discussionId        Unique identifier for discusion to share
 * @QueryParam  {number}                [limit]             Maximum number of users to return (defaults to 10, limited to between 1 and 25)
 * @QueryParam  {string}                [start]             Marker for continuing search (starts at beginning by default)
 * @Return      {MembersResponse}                           Returns an object containing members of discussion
 */
OAE.tenantRouter.on('get', '/api/discussion/:discussionId/members', function(req, res) {
    var limit = Util.getNumberParam(req.query.limit, 10, 1, 25);
    DiscussionsAPI.Discussions.getDiscussionMembers(req.ctx, req.params.discussionId, req.query.start, limit, function(err, members, nextToken) {
        if (err) {
            return res.send(err.code, err.msg);
        }

        res.send(200, {'results': members, 'nextToken': nextToken});
    });
});

//////////////////////////////////////
// CREATE / GET DISCUSSION MESSAGES //
//////////////////////////////////////

/**
 * @REST getDiscussionDiscussionIdMessages
 *
 * Get a list of messages from the discussion
 *
 * @Server      tenant
 * @Method      GET
 * @Path        /discussion/{discussionId}/messages
 * @PathParam   {string}                discussionId        Unique identifier for discusion to share
 * @QueryParam  {number}                [limit]             Maximum number of messages to return (defaults to 10, limited to between 1 and 25)
 * @QueryParam  {string}                [start]             Marker for continuing search (starts at beginning by default)
 * @Return      {MessagesResponse}                          Returns an object containing messages of discussion
 */
OAE.tenantRouter.on('get', '/api/discussion/:discussionId/messages', function(req, res) {
    var limit = Util.getNumberParam(req.query.limit, 10, 1, 25);
    DiscussionsAPI.Discussions.getMessages(req.ctx, req.params.discussionId, req.query.start, limit, function(err, messages, nextToken) {
        if (err) {
            return res.send(err.code, err.msg);
        }

        res.send(200, {'results': messages, 'nextToken': nextToken});
    });
});

/**
 * @REST postDiscussionDiscussionIdMessages
 *
 * Create a new message in a discussion
 *
 * @Server      tenant
 * @Method      POST
 * @Path        /discussion/{discussionId}/messages
 * @PathParam   {string}        discussionId        Unique identifier for discusion for new message
 * @FormParam   {string}        [body]              Content of new message
 * @FormParam   {string}        [replyTo]           Created time for message to which the new message is a reply
 * @Return      {Message}                           Returns an object representing the new message
 */
OAE.tenantRouter.on('post', '/api/discussion/:discussionId/messages', function(req, res) {
    DiscussionsAPI.Discussions.createMessage(req.ctx, req.params.discussionId, req.body.body, req.body.replyTo, function(err, message) {
        if (err) {
            return res.send(err.code, err.msg);
        }

        res.send(200, message);
    });
});

/**
 * @REST deleteDiscussionDiscussionIdMessagesCreated
 *
 * Delete a message in a discussion
 *
 * @Server      tenant
 * @Method      DELETE
 * @Path        /discussion/{discussionId}/messages/{created}
 * @PathParam   {string}                created             Creation time of message to delete
 * @PathParam   {string}                discussionId        Unique identifier for discusion containing message
 * @Return      {Message}                                   Returns an object representing the deleted message
 */
OAE.tenantRouter.on('delete', '/api/discussion/:discussionId/messages/:created', function(req, res) {
    DiscussionsAPI.Discussions.deleteMessage(req.ctx, req.params.discussionId, req.params.created, function(err, message) {
        if (err) {
            return res.send(err.code, err.msg);
        }

        res.send(200, message);
    });
});
<|endoftext|>


<commit_before>/**
 *
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

require.config({
    baseUrl: '/src/main/webapp/app/js/',
    paths: {
        'test': '/src/test/javascript/test/',
        'text': '../lib/require/text',
        'lib/d3': '../lib/d3/d3.v2.min',
        'lib/less': '../lib/less/less-1.3.0.min',
        'lib/jquery': '../lib/jquery/jquery-1.7.2.min',
        'lib/bootstrap': '../lib/bootstrap/2.1.1/js/bootstrap.min',
        'lib/handlebars': '../lib/handlebars/handlebars-1.0.rc.1'
    },
    shim: {
        'lib/bootstrap': {
            deps: ['lib/jquery']
        }
    }
});

(function () {
    var REQUIREMENTS = (function () {
        // We should list all our modules...
        var app = ['ApplicationChannel', 'ApplicationController', 'ApplicationModel', 'ApplicationTemplates',
            'util/DelayedTask', 'util/I18N', 'util/Log', 'util/Obj', 'util/Sequence',
            'view/ApplicationView', 'view/GrowlNotification'];

        // ... and libraries dependencies.
        var lib = ['lib/less', 'lib/jquery', 'lib/bootstrap', 'lib/handlebars'];

        // These are the test files under the "photodb/photodb-web/src/test/javascript/test" directory.
        var tests = [
            'test/I18N',
            'test/DelayedTask',
            'test/Obj',
            'test/Sequence',
            'test/ApplicationChannel',
            'test/ApplicationController'
        ];

        return app.concat(lib).concat(tests);
    })();

    /**
     * Load all the modules before starting.
     */
    require(REQUIREMENTS, function () {
        $(document).ready(function () {
            jasmine.getEnv().addReporter(
                new jasmine.HtmlReporter()
            );
            jasmine.getEnv().execute();
        });
    });
})();
<commit_msg>-fixing the start.js test file<commit_after>/**
 *
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

require.config({
    baseUrl: '/src/main/webapp/app/js/',
    paths: {
        'test': '/src/test/javascript/test/',
        'text': '../lib/require/text',
        'lib/d3': '../lib/d3/d3.v2.min',
        'lib/less': '../lib/less/less-1.3.0.min',
        'lib/jquery': '../lib/jquery/jquery-1.7.2.min',
        'lib/bootstrap': '../lib/bootstrap/2.1.1/js/bootstrap.min',
        'lib/handlebars': '../lib/handlebars/handlebars-1.0.rc.1'
    },
    shim: {
        'lib/bootstrap': {
            deps: ['lib/jquery']
        }
    }
});

(function () {
    var tests = [
        'test/I18N',
        'test/DelayedTask',
        'test/Obj',
        'test/Sequence',
        'test/ApplicationChannel',
        'test/ApplicationController',
        'test/ApplicationModel'
    ];

    /**
     * Load all the modules before starting.
     */
    require(tests, function () {
        $(document).ready(function () {
            jasmine.getEnv().addReporter(
                new jasmine.HtmlReporter()
            );
            jasmine.getEnv().execute();
        });
    });
})();
<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2015 The Lovefield Project Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
goog.setTestOnly();
goog.require('goog.testing.AsyncTestCase');
goog.require('goog.testing.jsunit');
goog.require('lf.Capability');
goog.require('lf.schema.DataStoreType');
goog.require('lf.testing.hrSchema.MockDataGenerator');
goog.require('lf.testing.hrSchema.getSchemaBuilder');
goog.require('lf.testing.util');

/** @type {!goog.testing.AsyncTestCase} */
var asyncTestCase = goog.testing.AsyncTestCase.createAndInstall(
    'ImportTaskTest');

/** @type {number} */
asyncTestCase.stepTimeout = 30 * 1000;  // 30 seconds.

/** @type {!lf.Capability} */
var capability;

function setUpPage() {
  capability = lf.Capability.get();
}

/**
 * @param {!lf.schema.ConnectOptions} options Connect options.
 * @return {!IThenable}
 */
function runTestImport(options) {
  var builder1 = lf.testing.hrSchema.getSchemaBuilder();
  var builder2 = lf.testing.hrSchema.getSchemaBuilder();
  var dataGen = new lf.testing.hrSchema.MockDataGenerator(builder1.getSchema());
  dataGen.generate(
      /* jobCount */ 100, /* employeeCount */ 1000, /* departmentCount */ 10);

  var db, db2;
  var data;
  return builder1.connect(options).then(function(dbInstance) {
    db = dbInstance;
    var d = db.getSchema().table('Department');
    var l = db.getSchema().table('Location');
    var c = db.getSchema().table('Country');
    var r = db.getSchema().table('Region');
    var j = db.getSchema().table('Job');
    var e = db.getSchema().table('Employee');

    var tx = db.createTransaction();
    return tx.exec([
      db.insert().into(r).values(dataGen.sampleRegions),
      db.insert().into(c).values(dataGen.sampleCountries),
      db.insert().into(l).values(dataGen.sampleLocations),
      db.insert().into(d).values(dataGen.sampleDepartments),
      db.insert().into(j).values(dataGen.sampleJobs),
      db.insert().into(e).values(dataGen.sampleEmployees)
    ]);
  }).then(function() {
    return db.export();
  }).then(function(exportedData) {
    data = exportedData;
    db.close();
    return builder2.connect(options);
  }).then(function(dbInstance) {
    db2 = dbInstance;
    data['name'] = builder2.getSchema().name();
    return db2.import(data);
  }).then(function() {
    return db2.export();
  }).then(function(exportedData) {
    assertEquals(builder2.getSchema().name(), exportedData['name']);
    assertEquals(builder2.getSchema().version(), exportedData['version']);
    assertObjectEquals(data, exportedData);
  });
}

function testImport_MemDB() {
  asyncTestCase.waitForAsync('testImport_MemDB');
  runTestImport({storeType: lf.schema.DataStoreType.MEMORY}).then(
      asyncTestCase.continueTesting.bind(asyncTestCase), fail);
}

function testImport_IndexedDB() {
  if (!capability.indexedDb) {
    return;
  }

  asyncTestCase.waitForAsync('testImport_IndexedDB');
  runTestImport({storeType: lf.schema.DataStoreType.INDEXED_DB}).then(
      asyncTestCase.continueTesting.bind(asyncTestCase), fail);
}

function testImport_WebSql() {
  if (!capability.webSql) {
    return;
  }

  asyncTestCase.waitForAsync('testImport_WebSql');
  runTestImport({storeType: lf.schema.DataStoreType.WEB_SQL}).then(
      asyncTestCase.continueTesting.bind(asyncTestCase), fail);
}

function disabledTestBenchmark() {
  var ROW_COUNT = 62500;
  var LOOP_COUNT = 30;

  var jobs = new Array(ROW_COUNT);
  for (var i = 0; i < ROW_COUNT; ++i) {
    jobs[i] = {
      id: 'jobId' + i.toString(),
      title: 'Job ' + i.toString(),
      minSalary: 10000 + i,
      maxSalary: 20000 + i
    };
  }

  var start;
  var results;
  var runImport = function() {
    var builder = lf.testing.hrSchema.getSchemaBuilder();
    var data = {
      'name': builder.getSchema().name(),
      'version': builder.getSchema().version(),
      'tables': {
        'Job': jobs
      }
    };

    return builder.connect({
      storeType: lf.schema.DataStoreType.MEMORY
    }).then(function(db) {
      start = goog.global.performance.now();
      return db.import(data);
    }).then(function() {
      var end = goog.global.performance.now();
      results.push(end - start);
    });
  };

  var runInsert = function() {
    var builder = lf.testing.hrSchema.getSchemaBuilder();
    return builder.connect({
      storeType: lf.schema.DataStoreType.MEMORY
    }).then(function(db) {
      var j = db.getSchema().table('Job');
      start = goog.global.performance.now();
      var rows = jobs.map(function(data) {
        return j.createRow(data);
      });
      return db.insert().into(j).values(rows).exec();
    }).then(function() {
      var end = goog.global.performance.now();
      results.push(end - start);
    });
  };

  var compute = function() {
    var base = results.sort(function(a, b) {
      return (a < b) ? -1 : ((a > b) ? 1 : 0);
    });
    var average = base.reduce(function(p, c) {
      return p + c;
    }, 0) / LOOP_COUNT;
    console['log'](average);
  };

  var fill = function(target) {
    results = [];
    var funcs = new Array(LOOP_COUNT);
    for (var i = 0; i < LOOP_COUNT; ++i) {
      funcs[i] = target;
    }
    return funcs;
  };

  asyncTestCase.waitForAsync('testBenchmark');
  lf.testing.util.sequentiallyRun(fill(runImport)).then(function() {
    compute();
    return lf.testing.util.sequentiallyRun(fill(runInsert));
  }).then(function() {
    compute();
    asyncTestCase.continueTesting();
  });
}
<commit_msg>Fixing import_task_testjs testImport_WebSql flaky test. ------------- Created by MOE: https://github.com/google/moe MOE_MIGRATED_REVID=103800696<commit_after>/**
 * @license
 * Copyright 2015 The Lovefield Project Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
goog.setTestOnly();
goog.require('goog.testing.AsyncTestCase');
goog.require('goog.testing.jsunit');
goog.require('lf.Capability');
goog.require('lf.schema.DataStoreType');
goog.require('lf.testing.hrSchema.MockDataGenerator');
goog.require('lf.testing.hrSchema.getSchemaBuilder');
goog.require('lf.testing.util');

/** @type {!goog.testing.AsyncTestCase} */
var asyncTestCase = goog.testing.AsyncTestCase.createAndInstall(
    'ImportTaskTest');

/** @type {number} */
asyncTestCase.stepTimeout = 30 * 1000;  // 30 seconds.

/** @type {!lf.Capability} */
var capability;

function setUpPage() {
  capability = lf.Capability.get();
}

/**
 * @param {!lf.schema.ConnectOptions} options Connect options.
 * @return {!IThenable}
 */
function runTestImport(options) {
  // Need to guarantee that the two DBs have different names.
  var builder1 = lf.testing.hrSchema.getSchemaBuilder(
      'hr1_' + new Date().getTime());
  var builder2 = lf.testing.hrSchema.getSchemaBuilder(
      'hr2_' + new Date().getTime());
  var dataGen = new lf.testing.hrSchema.MockDataGenerator(builder1.getSchema());
  dataGen.generate(
      /* jobCount */ 100, /* employeeCount */ 1000, /* departmentCount */ 10);

  var db, db2;
  var data;
  return builder1.connect(options).then(function(dbInstance) {
    db = dbInstance;
    var d = db.getSchema().table('Department');
    var l = db.getSchema().table('Location');
    var c = db.getSchema().table('Country');
    var r = db.getSchema().table('Region');
    var j = db.getSchema().table('Job');
    var e = db.getSchema().table('Employee');

    var tx = db.createTransaction();
    return tx.exec([
      db.insert().into(r).values(dataGen.sampleRegions),
      db.insert().into(c).values(dataGen.sampleCountries),
      db.insert().into(l).values(dataGen.sampleLocations),
      db.insert().into(d).values(dataGen.sampleDepartments),
      db.insert().into(j).values(dataGen.sampleJobs),
      db.insert().into(e).values(dataGen.sampleEmployees)
    ]);
  }).then(function() {
    return db.export();
  }).then(function(exportedData) {
    data = exportedData;
    db.close();
    return builder2.connect(options);
  }).then(function(dbInstance) {
    db2 = dbInstance;
    data['name'] = builder2.getSchema().name();
    return db2.import(data);
  }).then(function() {
    return db2.export();
  }).then(function(exportedData) {
    assertEquals(builder2.getSchema().name(), exportedData['name']);
    assertEquals(builder2.getSchema().version(), exportedData['version']);
    assertObjectEquals(data, exportedData);
  });
}

function testImport_MemDB() {
  asyncTestCase.waitForAsync('testImport_MemDB');
  runTestImport({storeType: lf.schema.DataStoreType.MEMORY}).then(
      asyncTestCase.continueTesting.bind(asyncTestCase), fail);
}

function testImport_IndexedDB() {
  if (!capability.indexedDb) {
    return;
  }

  asyncTestCase.waitForAsync('testImport_IndexedDB');
  runTestImport({storeType: lf.schema.DataStoreType.INDEXED_DB}).then(
      asyncTestCase.continueTesting.bind(asyncTestCase), fail);
}

function testImport_WebSql() {
  if (!capability.webSql) {
    return;
  }

  asyncTestCase.waitForAsync('testImport_WebSql');
  runTestImport({storeType: lf.schema.DataStoreType.WEB_SQL}).then(
      asyncTestCase.continueTesting.bind(asyncTestCase), fail);
}

function disabledTestBenchmark() {
  var ROW_COUNT = 62500;
  var LOOP_COUNT = 30;

  var jobs = new Array(ROW_COUNT);
  for (var i = 0; i < ROW_COUNT; ++i) {
    jobs[i] = {
      id: 'jobId' + i.toString(),
      title: 'Job ' + i.toString(),
      minSalary: 10000 + i,
      maxSalary: 20000 + i
    };
  }

  var start;
  var results;
  var runImport = function() {
    var builder = lf.testing.hrSchema.getSchemaBuilder();
    var data = {
      'name': builder.getSchema().name(),
      'version': builder.getSchema().version(),
      'tables': {
        'Job': jobs
      }
    };

    return builder.connect({
      storeType: lf.schema.DataStoreType.MEMORY
    }).then(function(db) {
      start = goog.global.performance.now();
      return db.import(data);
    }).then(function() {
      var end = goog.global.performance.now();
      results.push(end - start);
    });
  };

  var runInsert = function() {
    var builder = lf.testing.hrSchema.getSchemaBuilder();
    return builder.connect({
      storeType: lf.schema.DataStoreType.MEMORY
    }).then(function(db) {
      var j = db.getSchema().table('Job');
      start = goog.global.performance.now();
      var rows = jobs.map(function(data) {
        return j.createRow(data);
      });
      return db.insert().into(j).values(rows).exec();
    }).then(function() {
      var end = goog.global.performance.now();
      results.push(end - start);
    });
  };

  var compute = function() {
    var base = results.sort(function(a, b) {
      return (a < b) ? -1 : ((a > b) ? 1 : 0);
    });
    var average = base.reduce(function(p, c) {
      return p + c;
    }, 0) / LOOP_COUNT;
    console['log'](average);
  };

  var fill = function(target) {
    results = [];
    var funcs = new Array(LOOP_COUNT);
    for (var i = 0; i < LOOP_COUNT; ++i) {
      funcs[i] = target;
    }
    return funcs;
  };

  asyncTestCase.waitForAsync('testBenchmark');
  lf.testing.util.sequentiallyRun(fill(runImport)).then(function() {
    compute();
    return lf.testing.util.sequentiallyRun(fill(runInsert));
  }).then(function() {
    compute();
    asyncTestCase.continueTesting();
  });
}
<|endoftext|>