<commit_before>var path = require('path');
var fs = require('fs');
var _ = require('underscore');
var Dependencies = require('./dependencies/dependencies');
var Config = require('./config');
var Meteor = require('./meteor');
var Command = require('./command');
var wrench = require('wrench');
var exec = require('child_process').exec;

// The project is the current directory's personal version of meteor,
// complete with it's own set of packages.
// it installs into ./meteor/meteorite

Project = function(root, meteorArgs) {

  // Figure out all the paths we'll need to know
  this.root = root;
  this.meteorArgs = meteorArgs;
  this.smartJsonPath = path.join(this.root, 'smart.json');
  this.smartLockPath = path.join(this.root, 'smart.lock');
  this.meteorRoot = path.join(this.root, '.meteor');
  this.installRoot = path.join(this.meteorRoot, 'meteorite');
  this.packagesRoot = path.join(this.installRoot, 'packages');

  // set a base meteor if it's specified in the args (or a default one if not)
  this.meteor = new Meteor(meteorArgs);
};

// read the config from smart.lock if it exists
Project.prototype.initFromLock = function() {

  if (fs.existsSync(this.smartLockPath)) {
    var data = fs.readFileSync(this.smartLockPath).toString();
    var lockData = JSON.parse(data);

    this.meteor = new Meteor(lockData.meteor);
    this.dependencies = Dependencies.newFromLockJson(this, lockData.dependencies);
  }
};

// have a look in smart.json, see if it's different to what we have from smart.lock
Project.prototype.checkSmartJson = function(forceUpdate) {

  // this is the config specified in smart.json
  var config = new Config(this.root);

  var newMeteor = new Meteor(config.meteor);
  var newDeps =  new Dependencies(this.root, config.packages);

  if (forceUpdate || !this.meteor.equals(newMeteor) || !this.dependencies || !this.dependencies.equalBase(newDeps)) {

    if (!forceUpdate && this.dependencies)
      console.log('smart.json changed.. installing from smart.json...');

    this.lockChanged = true;
    this.meteor = newMeteor;
    this.dependencies = newDeps;
  }
};

// FIXME - this doesn't actually fetch the packages.
// we only fetch them when we are about to install them, or we need to
// take a look inside them. I think this is reasonable.
Project.prototype.fetch = function(fn, forceUpdate) {
  var self = this;

  // prepare dependencies and meteor
  self.initFromLock();
  self.checkSmartJson(forceUpdate);

  // Ensure the right version of meteor has been fetched
  self.meteor.prepare(function() {

    // resolving dependencies fetches them. We need to check otherwise
    if (!self.dependencies.resolved()) {

      console.log('Resolving dependencies..');

      self.dependencies.resolve(self.meteorArgs.force, function(err, problems) {

        _.each(problems, function(problem, name) {
          console.log('Problem installing ' + name);
          console.log('    x ' + problem);
        });

        // FIXME -- we should use the same callback style everywhere
        if (err)
          throw err;

        fn();
      });
    } else {
      fn();
    }
  });
};

Project.prototype.uninstall = function() {
  var self = this;

  // Kill ./.meteor/meteorite
  console.log('Uninstalling custom meteor build...');
  self.meteor.uninstallFrom(self);
};

// either install from smart.lock or prepare smart.lock and do so
Project.prototype.install = function(fn, forceUpdate) {
  var self = this;

  // Fetch everything the project needs
  self.fetch(function() {
    // FIXME -- write smart lock here --> however this won't matter with PACKAGE_DIRS
    if (!self.needsToInstall())
      return fn();

    // Add meteorite to gitignore
    self._addToGitIgnore();

    // Install meteor there
    self.meteor.installInto(self, function(meteorInstalled) {

      // Add each package to newly installed meteor
      self.dependencies.installInto(self, function(packagesInstalled) {

        (meteorInstalled || packagesInstalled) && console.log('Meteor installed');

        // install the smart.lock file
        if (fs.existsSync(self.smartJsonPath) && (self.lockChanged || !fs.existsSync(self.smartLockPath)))
          self.writeLockFile();

        fn();
      });
    });
  }, forceUpdate);
};

// if there's no dependencies we don't have to install
Project.prototype.needsToInstall = function() {
  return !this.dependencies.isEmpty();
}

Project.prototype.isMeteorInstalled = function(fn) {

  var meteorPath = path.join(this.installRoot, 'meteor');
  if (!fs.existsSync(meteorPath))
    fn(false);
  else
    this.meteor.source.installedInto(this.installRoot, fn);
};

// prepare a new smart.lock, then install
Project.prototype.update = function(fn) {

  this.install(fn, true);
};

Project.prototype.execute = function(args, fn) {
  var self = this;

  // TODO -- what do we do here if not installed? I'm not sure we just go ahead
  //   and install, we should probably abort and tell them
  self.install(function() {
    if (self.needsToInstall()) {
      Command.execute(path.join(self.installRoot, 'meteor'), args, fn);
    } else {
      self.meteor.execute(args, fn);
    }
  });
};

Project.prototype._addToGitIgnore = function() {

  if (!fs.existsSync(gitignorePath))
    return;

  var gitignorePath = path.join(this.meteorRoot, '.gitignore');
  var gitignoreContent = fs.readFileSync(gitignorePath, 'utf8');

  // Add ./.meteor/meteorite to ./.meteor/.gitignore
  // but only if it's not aleady in there
  if (!/meteorite/.test(gitignoreContent)) {
    console.log('Adding meteorite to .meteor/gitignore ...');
    fs.writeFileSync(gitignorePath, gitignoreContent + "meteorite\n");
  }

};

// ensure a named package is installed
//
// NOTE: Right now, if the package is already available (included in meteor, already in smart.json)
// we ignore the version, and just stick with what we have
//
// TODO: In the future a version # would override anything in meteor + rewrite smart.json
// but right now it's TBH to overwrite meteor's packages.
Project.prototype.installPackage = function(pkgName, version, fn) {
  var self = this;

  // first ensure we are fetched, so we know _all_ the packages that are available
  self.fetch(function() {

    // now, check if we have the package already
    if (self.hasPackage(pkgName))
      return fn();

    // better check that the package exists on atmosphere
    Atmosphere.package(pkgName, function(atmosphere_defn) {

      if (!atmosphere_defn)
        throw "Package named " + pkgName + " doesn't exist in your meteor installation, smart.json, or on atmosphere";

      // ok, it's not installed. So we need to add it (permanently) to the smart.json
      // and clear our dependencies
      var smartJson = self.readSmartJson();
      var defn = {}
      if (version)
        defn.version = version;
      smartJson.packages = smartJson.packages || {};
      smartJson.packages[pkgName] = defn;
      self.writeSmartJson(smartJson);

      // maybe a hack to read it back out from disk, but not a big deal I don't think
      self.checkSmartJson(true);

      fn();
    });
  });
}

// Is the package part of the meteor install, or is it a dependency?
//
// NOTE: assumes we have fetched. FIXME: figure out a better / systematic way
// to write code that has this sort of assumption
Project.prototype.hasPackage = function(pkgName) {

  return this.meteor.hasPackage(pkgName) || this.dependencies.packages[pkgName];
};

// very simple version of what config does
Project.prototype.readSmartJson = function() {

  try {
    var rawConfig = fs.readFileSync(path.join(this.root, 'smart.json')).toString();
    return JSON.parse(rawConfig);

  } catch (err) {
    return {};
  }
};

Project.prototype.smartJson = function() {
  var data = {};

  if (!this.meteor.defaultMeteor)
    data.meteor = this.meteor.toJson();

  if (this.dependencies)
    data.packages = this.dependencies.toJson().basePackages;
  else
    data.packages = {};

  return data;
};

Project.prototype.writeSmartJson = function(json) {
  json = json || this.smartJson();

  // Make a nicely formated default json string
  var smartJsonString = JSON.stringify(json, null, 2) + "\n";

  // Write to disk
  if (fs.existsSync(this.root))
    fs.writeFileSync(this.smartJsonPath, smartJsonString);
};

Project.prototype.lockJson = function() {

  return {
    meteor: this.meteor.toJson(true),
    dependencies: this.dependencies.toJson(true)
  };
};

// write out into smart.lock
Project.prototype.writeLockFile = function() {

  var smartJsonString = JSON.stringify(this.lockJson(), null, 2) + "\n";
  fs.writeFileSync(this.smartLockPath, smartJsonString);
};

module.exports = Project;
<commit_msg>rename problem to conflict<commit_after>var path = require('path');
var fs = require('fs');
var _ = require('underscore');
var Dependencies = require('./dependencies/dependencies');
var Config = require('./config');
var Meteor = require('./meteor');
var Command = require('./command');
var wrench = require('wrench');
var exec = require('child_process').exec;

// The project is the current directory's personal version of meteor,
// complete with it's own set of packages.
// it installs into ./meteor/meteorite

Project = function(root, meteorArgs) {

  // Figure out all the paths we'll need to know
  this.root = root;
  this.meteorArgs = meteorArgs;
  this.smartJsonPath = path.join(this.root, 'smart.json');
  this.smartLockPath = path.join(this.root, 'smart.lock');
  this.meteorRoot = path.join(this.root, '.meteor');
  this.installRoot = path.join(this.meteorRoot, 'meteorite');
  this.packagesRoot = path.join(this.installRoot, 'packages');

  // set a base meteor if it's specified in the args (or a default one if not)
  this.meteor = new Meteor(meteorArgs);
};

// read the config from smart.lock if it exists
Project.prototype.initFromLock = function() {

  if (fs.existsSync(this.smartLockPath)) {
    var data = fs.readFileSync(this.smartLockPath).toString();
    var lockData = JSON.parse(data);

    this.meteor = new Meteor(lockData.meteor);
    this.dependencies = Dependencies.newFromLockJson(this, lockData.dependencies);
  }
};

// have a look in smart.json, see if it's different to what we have from smart.lock
Project.prototype.checkSmartJson = function(forceUpdate) {

  // this is the config specified in smart.json
  var config = new Config(this.root);

  var newMeteor = new Meteor(config.meteor);
  var newDeps =  new Dependencies(this.root, config.packages);

  if (forceUpdate || !this.meteor.equals(newMeteor) || !this.dependencies || !this.dependencies.equalBase(newDeps)) {

    if (!forceUpdate && this.dependencies)
      console.log('smart.json changed.. installing from smart.json...');

    this.lockChanged = true;
    this.meteor = newMeteor;
    this.dependencies = newDeps;
  }
};

// FIXME - this doesn't actually fetch the packages.
// we only fetch them when we are about to install them, or we need to
// take a look inside them. I think this is reasonable.
Project.prototype.fetch = function(fn, forceUpdate) {
  var self = this;

  // prepare dependencies and meteor
  self.initFromLock();
  self.checkSmartJson(forceUpdate);

  // Ensure the right version of meteor has been fetched
  self.meteor.prepare(function() {

    // resolving dependencies fetches them. We need to check otherwise
    if (!self.dependencies.resolved()) {

      console.log('Resolving dependencies..');

      self.dependencies.resolve(self.meteorArgs.force, function(err, conflicts) {

        _.each(conflicts, function(conflict, name) {
          console.log('Problem installing ' + name);
          console.log('    x ' + conflict);
        });

        // FIXME -- we should use the same callback style everywhere
        if (err)
          throw err;

        fn();
      });
    } else {
      fn();
    }
  });
};

Project.prototype.uninstall = function() {
  var self = this;

  // Kill ./.meteor/meteorite
  console.log('Uninstalling custom meteor build...');
  self.meteor.uninstallFrom(self);
};

// either install from smart.lock or prepare smart.lock and do so
Project.prototype.install = function(fn, forceUpdate) {
  var self = this;

  // Fetch everything the project needs
  self.fetch(function() {
    // FIXME -- write smart lock here --> however this won't matter with PACKAGE_DIRS
    if (!self.needsToInstall())
      return fn();

    // Add meteorite to gitignore
    self._addToGitIgnore();

    // Install meteor there
    self.meteor.installInto(self, function(meteorInstalled) {

      // Add each package to newly installed meteor
      self.dependencies.installInto(self, function(packagesInstalled) {

        (meteorInstalled || packagesInstalled) && console.log('Meteor installed');

        // install the smart.lock file
        if (fs.existsSync(self.smartJsonPath) && (self.lockChanged || !fs.existsSync(self.smartLockPath)))
          self.writeLockFile();

        fn();
      });
    });
  }, forceUpdate);
};

// if there's no dependencies we don't have to install
Project.prototype.needsToInstall = function() {
  return !this.dependencies.isEmpty();
}

Project.prototype.isMeteorInstalled = function(fn) {

  var meteorPath = path.join(this.installRoot, 'meteor');
  if (!fs.existsSync(meteorPath))
    fn(false);
  else
    this.meteor.source.installedInto(this.installRoot, fn);
};

// prepare a new smart.lock, then install
Project.prototype.update = function(fn) {

  this.install(fn, true);
};

Project.prototype.execute = function(args, fn) {
  var self = this;

  // TODO -- what do we do here if not installed? I'm not sure we just go ahead
  //   and install, we should probably abort and tell them
  self.install(function() {
    if (self.needsToInstall()) {
      Command.execute(path.join(self.installRoot, 'meteor'), args, fn);
    } else {
      self.meteor.execute(args, fn);
    }
  });
};

Project.prototype._addToGitIgnore = function() {

  if (!fs.existsSync(gitignorePath))
    return;

  var gitignorePath = path.join(this.meteorRoot, '.gitignore');
  var gitignoreContent = fs.readFileSync(gitignorePath, 'utf8');

  // Add ./.meteor/meteorite to ./.meteor/.gitignore
  // but only if it's not aleady in there
  if (!/meteorite/.test(gitignoreContent)) {
    console.log('Adding meteorite to .meteor/gitignore ...');
    fs.writeFileSync(gitignorePath, gitignoreContent + "meteorite\n");
  }

};

// ensure a named package is installed
//
// NOTE: Right now, if the package is already available (included in meteor, already in smart.json)
// we ignore the version, and just stick with what we have
//
// TODO: In the future a version # would override anything in meteor + rewrite smart.json
// but right now it's TBH to overwrite meteor's packages.
Project.prototype.installPackage = function(pkgName, version, fn) {
  var self = this;

  // first ensure we are fetched, so we know _all_ the packages that are available
  self.fetch(function() {

    // now, check if we have the package already
    if (self.hasPackage(pkgName))
      return fn();

    // better check that the package exists on atmosphere
    Atmosphere.package(pkgName, function(atmosphere_defn) {

      if (!atmosphere_defn)
        throw "Package named " + pkgName + " doesn't exist in your meteor installation, smart.json, or on atmosphere";

      // ok, it's not installed. So we need to add it (permanently) to the smart.json
      // and clear our dependencies
      var smartJson = self.readSmartJson();
      var defn = {}
      if (version)
        defn.version = version;
      smartJson.packages = smartJson.packages || {};
      smartJson.packages[pkgName] = defn;
      self.writeSmartJson(smartJson);

      // maybe a hack to read it back out from disk, but not a big deal I don't think
      self.checkSmartJson(true);

      fn();
    });
  });
}

// Is the package part of the meteor install, or is it a dependency?
//
// NOTE: assumes we have fetched. FIXME: figure out a better / systematic way
// to write code that has this sort of assumption
Project.prototype.hasPackage = function(pkgName) {

  return this.meteor.hasPackage(pkgName) || this.dependencies.packages[pkgName];
};

// very simple version of what config does
Project.prototype.readSmartJson = function() {

  try {
    var rawConfig = fs.readFileSync(path.join(this.root, 'smart.json')).toString();
    return JSON.parse(rawConfig);

  } catch (err) {
    return {};
  }
};

Project.prototype.smartJson = function() {
  var data = {};

  if (!this.meteor.defaultMeteor)
    data.meteor = this.meteor.toJson();

  if (this.dependencies)
    data.packages = this.dependencies.toJson().basePackages;
  else
    data.packages = {};

  return data;
};

Project.prototype.writeSmartJson = function(json) {
  json = json || this.smartJson();

  // Make a nicely formated default json string
  var smartJsonString = JSON.stringify(json, null, 2) + "\n";

  // Write to disk
  if (fs.existsSync(this.root))
    fs.writeFileSync(this.smartJsonPath, smartJsonString);
};

Project.prototype.lockJson = function() {

  return {
    meteor: this.meteor.toJson(true),
    dependencies: this.dependencies.toJson(true)
  };
};

// write out into smart.lock
Project.prototype.writeLockFile = function() {

  var smartJsonString = JSON.stringify(this.lockJson(), null, 2) + "\n";
  fs.writeFileSync(this.smartLockPath, smartJsonString);
};

module.exports = Project;
<|endoftext|>


<commit_before>/**
 * AuO.js
 *
 * Main entry point for the AuO library. Create a new instance of AuO by calling new AuO(). Calling
 * launch() adds the instance to the DOM tree, and calling suspend() removes the instance from the
 * DOM tree.
 *
 * @constructor
 */
const AuO = function () {
    ////////////////////////////////////////////////////////////////////////////////////////////////
    //
    // Functions in the AuO interface.
    //
    ////////////////////////////////////////////////////////////////////////////////////////////////

    /**
     * Launches this instance of AuO. Application becomes visible to the user. Will automatically
     * set the z-index so that the launched instance has higher z-index than all other elements on
     * the page.
     */
    this.launch = function () {
        const allElements = document.getElementsByTagName("*");
        const allElementsZindex = Array.from(allElements).map(function (element) {
            return element.style.zIndex;
        });
        const maxZindex = Math.max.apply(null, allElementsZindex);
        container.style("z-index", maxZindex + 1);
        document.body.appendChild(container.element());
        initiate();
    };

    /**
     * Suspends using this instance of AuO. Removes the application from the DOM tree and sets
     * the z-index to -Infinity. The interface is only hidden from view, however. To stop all
     * services, the instance itself must be deleted.
     */
    this.suspend = function () {
        suspendInstance();
    };

    ////////////////////////////////////////////////////////////////////////////////////////////////
    //
    // Runtime code.
    //
    ////////////////////////////////////////////////////////////////////////////////////////////////

    var initiated = false;
    /**
     * Initiates runtime procedures for this instance of AuO. Will only run once throughout the
     * lifetime of an instance. Called by this.launch().
     */
    const initiate = function () {
        // Prevent multiple initiations.
        if (initiated) {
            return;
        }
        initiated = true;

        runtimeAtInitiation();
    };

    /**
     * Suspends this AuO instance.
     */
    const suspendInstance = function () {
        container.detach().style("z-index", -Infinity);
    };

    /**
     * Code run at the end of constructing a new AuO instance.
     */
    const runtimeAtConstruction = function () {
    };

    /**
     * Code run at initiate step of an AuO instance.
     */
    const runtimeAtInitiation = function() {
    };

    ////////////////////////////////////////////////////////////////////////////////////////////////
    //
    // Helper functions for the entire library.
    //
    ////////////////////////////////////////////////////////////////////////////////////////////////

    /**
     * Determines whether the value is a nil-value. A nil value is an undefined or a null.
     */
    const isNil = function (value) {
        return (undefined === value) || (null === value);
    };

    ////////////////////////////////////////////////////////////////////////////////////////////////
    //
    // Helper class FunctionalElement for functional language-style HTML DOM manipulations.
    //
    ////////////////////////////////////////////////////////////////////////////////////////////////

    /**
     * A functional, stripped-down wrapper around HTML DOM elements.
     *
     * Invariant: the encapsulated element can never be undefined or null.
     *
     * Functions:
     *     element -- accessor for the encapsulated element.
     *     get(attribute) -- wrapper for getAttribute(attribute).
     *     set(attribute, value) -- wrapper for setAttribute(attribute, value) and
     *         removeAttribute("attribute). The latter is called if the value is undefined or null,
     *         otherwise the former is called. For the innerHTML attribute, will treat undefined
     *         and null as empty strings.
     *     style -- wrapper for style.setProperty(property, value).
     *     append -- wrapper for appendChild(child).
     *     remove -- wrapper for removeChild(child).
     *     attach -- appends the element to the specified parent.
     *     detach -- removes the element as a child of its parent.
     *     listen -- wrapper for addEventListener(event, callback).
     *
     * @constructor
     */
    const FunctionalElement = function (tagname) {
        const element = document.createElement(tagname);
        this.element = function() {
            return element;
        };
        this.get = function (attribute) {
            element.getAttribute(attribute);
            return this;
        };
        this.set = function (attribute, value) {
            if ("innerHTML" === attribute) {
                element.innerHTML = isNil(value) ? "" : value;
            } else {
                if (isNil(value)) {
                    element.removeAttribute(attribute);
                } else {
                    element.setAttribute(attribute, value);
                }
            }
            return this;
        };
        this.style = function (property, value) {
            element.style.setProperty(property, value);
            return this;
        };
        this.append = function (child) {
            element.appendChild(child.element());
            return this;
        };
        this.remove = function (child) {
            element.removechild(child.element());
            return this;
        };
        this.attach = function (parent) {
            isNil(parent) || parent.element.appendChild(element);
            return this;
        };
        this.detach = function () {
            isNil(element.parentNode) || element.parentNode.removeChild(element);
            return this;
        };
        this.listen = function (event, callback) {
            element.addEventListener(event, callback);
            return this;
        };
    };

    ////////////////////////////////////////////////////////////////////////////////////////////////
    //
    // Create the DOM elements we want to work with.
    //
    ////////////////////////////////////////////////////////////////////////////////////////////////

    // Highest-level container for the interface, also responsible for the faded screen background.
    const container = new FunctionalElement("div");

    // Element to enable vertical centering of the interface.
    const verticalMiddleButtress = new FunctionalElement("div");

    // Element to enable horizontal centering of the interface.
    const horizontalCenterContainer = new FunctionalElement("div");

    // Container for the main UI.
    const mainUI = new FunctionalElement("div");

    // Title bar for the UI.
    const titleBar = new FunctionalElement("div");
    const title = new FunctionalElement("div");
    const titleClose = new FunctionalElement("div");

    // Container for the controls UI.
    const controlsUI = new FunctionalElement("div");

    // Buttons for controlling recording and playback.
    const buttonRecord = new FunctionalElement("button");
    const buttonPlay = new FunctionalElement("button");
    const buttonStop = new FunctionalElement("button");

    // Container for the zoom UI.
    const zoomUI = new FunctionalElement("div");

    // Buttons for zooming.
    const buttonZoomIn = new FunctionalElement("button");
    const buttonZoomOut = new FunctionalElement("button");

    // Display for the zoom value for the zoom UI.
    const zoomDisplay = new FunctionalElement("div");

    // Container for the audio UI.
    const audioUI = new FunctionalElement("div");

    // Display for the visualizer of the audio.
    const audioDisplay = new FunctionalElement("canvas");

    // Red bar for indicating the current time frame on the display.
    const audioCurrent = new FunctionalElement("div");

    ////////////////////////////////////////////////////////////////////////////////////////////////
    //
    // Hook up the appropriate listeners.
    //
    ////////////////////////////////////////////////////////////////////////////////////////////////

    // Prevent events from propagating to elements underneath the AuO instance.
    container.listen("click", function (event) {
        event.stopPropagation();
    });

    // Closing via crosshairs is equivalent to suspending the instance.
    titleClose.listen("click", function (event) {
        suspendInstance();
    });

    ////////////////////////////////////////////////////////////////////////////////////////////////
    //
    // Build the DOM tree.
    //
    ////////////////////////////////////////////////////////////////////////////////////////////////

    container
        .append(verticalMiddleButtress)
        .append(horizontalCenterContainer
            .append(mainUI
                .append(titleBar
                    .append(title)
                    .append(titleClose)
                ).append(controlsUI
                    .append(buttonRecord)
                    .append(buttonPlay)
                    .append(buttonStop)
                ).append(audioUI
                    .append(audioDisplay)
                    .append(audioCurrent)
                ).append(zoomUI
                    .append(buttonZoomIn)
                    .append(zoomDisplay)
                    .append(buttonZoomOut)
                )
            )
        )
    ;

    ////////////////////////////////////////////////////////////////////////////////////////////////
    //
    // Style the DOM elements. Styles are sorted lexically. Styles come before sets.
    //
    ////////////////////////////////////////////////////////////////////////////////////////////////

    container
        .style("background-color", "rgba(0, 0, 0, 0.4)")
        .style("display", "block")
        .style("height", "100vh")
        .style("left", "0px")
        .style("position", "fixed")
        .style("text-align", "center")
        .style("top", "0px")
        .style("vertical-align", "middle")
        .style("width", "100%");

    verticalMiddleButtress
        .style("display", "inline-block")
        .style("height", "100%")
        .style("vertical-align", "middle")
        .style("width", "0px");

    horizontalCenterContainer
        .style("display", "inline-block")
        .style("text-align", "center")
        .style("vertical-align", "middle")
        .style("width", "100%");

    mainUI
        .style("background-color", "#FFF")
        .style("border-radius", "10px")
        .style("box-shadow", "10px 10px 5px rgba(0, 0, 0, 0.4)")
        .style("display", "block")
        .style("margin", "auto")
        .style("padding", "10px")
        .style("position", "relative")
        .style("text-align", "justify")
        .style("white-space", "nowrap")
        .style("width", "80vw");

    titleBar
        .style("backgroud-color", "#DDD")
        .style("display", "block")
        .style("font-size", "12pt")
        .style("font-weight", "bold")
        .style("padding", "5px")
        .style("white-space", "nowrap")
        .style("width", "auto");

    title
        .style("display", "inline-block")
        .style("width", "calc(100% - 120pt)")
        .style("text-align", "left")
        .set("innerHTML", "Record custom sound");

    titleClose
        .style("display", "inline-block")
        .style("font-size", "14pt")
        .style("text-align", "right")
        .style("width", "120pt")
        .set("innerHTML", "[Close] ⨂");

    controlsUI
        .style("display", "block")
        .style("margin", "5px")
        .style("vertical-align", "top")
        .style("white-space", "normal")
        .style("width", "auto");

    buttonRecord
        .style("width", "100px")
        .set("innerHTML", "Record");

    buttonPlay
        .style("margin-left", "5px")
        .style("width", "100px")
        .set("innerHTML", "Play");

    buttonStop
        .style("margin-left", "5px")
        .style("width", "100px")
        .set("innerHTML", "Stop");

    audioUI
        .style("display", "block")
        .style("overflow-x", "scroll")
        .style("margin", "5px")
        .style("position", "relative")
        .style("white-space", "normal")
        .style("width", "auto");

    audioDisplay
        .style("border-left", "1px solid blue")
        .style("height", "100px")
        .style("width", "100%")
        .set("height", "100%");

    audioCurrent
        .style("background-color", "red")
        .style("display", "none")
        .style("height", "100%")
        .style("left", "0px")
        .style("position", "absolute")
        .style("top", "0px")
        .style("width", "1px");

    zoomUI
        .style("display", "block")
        .style("margin-bottom", "5px")
        .style("margin-top", "5px")
        .style("text-align", "center")
        .style("width", "auto");

    buttonZoomIn
        .style("width", "100px")
        .set("innerHTML", "Zoom in");

    buttonZoomOut
        .style("width", "100px")
        .set("innerHTML", "Zoom out");

    zoomDisplay
        .style("display", "inline-block")
        .style("text-align", "center")
        .style("width", "300px");

    ////////////////////////////////////////////////////////////////////////////////////////////////
    //
    // Complete runtime evaluations at the end of construction.
    //
    ////////////////////////////////////////////////////////////////////////////////////////////////

    runtimeAtConstruction();
};
<commit_msg>Added CSS class functionality into FunctionalElement and rewrote the docs a little.<commit_after>/**
 * AuO.js
 *
 * Main entry point for the AuO library. Create a new instance of AuO by calling new AuO(). Calling
 * launch() adds the instance to the DOM tree, and calling suspend() removes the instance from the
 * DOM tree.
 *
 * @constructor
 */
const AuO = function () {
    ////////////////////////////////////////////////////////////////////////////////////////////////
    //
    // Functions in the AuO interface.
    //
    ////////////////////////////////////////////////////////////////////////////////////////////////

    /**
     * Launches this instance of AuO. Application becomes visible to the user. Will automatically
     * set the z-index so that the launched instance has higher z-index than all other elements on
     * the page.
     */
    this.launch = function () {
        const allElements = document.getElementsByTagName("*");
        const allElementsZindex = Array.from(allElements).map(function (element) {
            return element.style.zIndex;
        });
        const maxZindex = Math.max.apply(null, allElementsZindex);
        container.style("z-index", maxZindex + 1);
        document.body.appendChild(container.element());
        initiate();
    };

    /**
     * Suspends using this instance of AuO. Removes the application from the DOM tree and sets
     * the z-index to -Infinity. The interface is only hidden from view, however. To stop all
     * services, the instance itself must be deleted.
     */
    this.suspend = function () {
        suspendInstance();
    };

    ////////////////////////////////////////////////////////////////////////////////////////////////
    //
    // Runtime code.
    //
    ////////////////////////////////////////////////////////////////////////////////////////////////

    var initiated = false;
    /**
     * Initiates runtime procedures for this instance of AuO. Will only run once throughout the
     * lifetime of an instance. Called by this.launch().
     */
    const initiate = function () {
        // Prevent multiple initiations.
        if (initiated) {
            return;
        }
        initiated = true;

        runtimeAtInitiation();
    };

    /**
     * Suspends this AuO instance.
     */
    const suspendInstance = function () {
        container.detach().style("z-index", -Infinity);
    };

    /**
     * Code run at the end of constructing a new AuO instance.
     */
    const runtimeAtConstruction = function () {
    };

    /**
     * Code run at initiate step of an AuO instance.
     */
    const runtimeAtInitiation = function() {
    };

    ////////////////////////////////////////////////////////////////////////////////////////////////
    //
    // Helper functions for the entire library.
    //
    ////////////////////////////////////////////////////////////////////////////////////////////////

    /**
     * Determines whether the value is a nil-value. A nil value is an undefined or a null.
     */
    const isNil = function (value) {
        return (undefined === value) || (null === value);
    };

    ////////////////////////////////////////////////////////////////////////////////////////////////
    //
    // Helper class FunctionalElement for functional language-style HTML DOM manipulations.
    //
    ////////////////////////////////////////////////////////////////////////////////////////////////

    /**
     * A functional, stripped-down wrapper around HTML DOM elements.
     *
     * Invariant: the encapsulated element can never be undefined or null.
     *
     * Functions:
     *     element -- accessor for the encapsulated element.
     *     get(attribute) -- wrapper for getAttribute(attribute).
     *     set(attribute, value) -- wrapper for setAttribute(attribute, value) and
     *         removeAttribute("attribute). The latter is called if the value is undefined or null,
     *         otherwise the former is called. For the innerHTML attribute, will treat undefined
     *         and null as empty strings.
     *     class(classname, add) -- forcibly add or remove the class from the element.
     *     style(property, value) -- wrapper for style.setProperty(property, value).
     *     append(child) -- wrapper for appendChild(child).
     *     remove(child) -- wrapper for removeChild(child).
     *     attach(parent) -- appends the element to the specified parent.
     *     detach() -- removes the element as a child of its parent.
     *     listen(event, callback) -- wrapper for addEventListener(event, callback).
     *
     * @constructor
     */
    const FunctionalElement = function (tagname) {
        const element = document.createElement(tagname);
        this.element = function() {
            return element;
        };
        this.get = function (attribute) {
            element.getAttribute(attribute);
            return this;
        };
        this.set = function (attribute, value) {
            if ("innerHTML" === attribute) {
                element.innerHTML = isNil(value) ? "" : value;
            } else {
                if (isNil(value)) {
                    element.removeAttribute(attribute);
                } else {
                    element.setAttribute(attribute, value);
                }
            }
            return this;
        };
        this.class = function (classname, add = true) {
            element.classList.toggle(classname, add);
            return this;
        };
        this.style = function (property, value) {
            element.style.setProperty(property, value);
            return this;
        };
        this.append = function (child) {
            element.appendChild(child.element());
            return this;
        };
        this.remove = function (child) {
            element.removechild(child.element());
            return this;
        };
        this.attach = function (parent) {
            isNil(parent) || parent.element.appendChild(element);
            return this;
        };
        this.detach = function () {
            isNil(element.parentNode) || element.parentNode.removeChild(element);
            return this;
        };
        this.listen = function (event, callback) {
            element.addEventListener(event, callback);
            return this;
        };
    };

    ////////////////////////////////////////////////////////////////////////////////////////////////
    //
    // Create the DOM elements we want to work with.
    //
    ////////////////////////////////////////////////////////////////////////////////////////////////

    // Highest-level container for the interface, also responsible for the faded screen background.
    const container = new FunctionalElement("div");

    // Element to enable vertical centering of the interface.
    const verticalMiddleButtress = new FunctionalElement("div");

    // Element to enable horizontal centering of the interface.
    const horizontalCenterContainer = new FunctionalElement("div");

    // Container for the main UI.
    const mainUI = new FunctionalElement("div");

    // Title bar for the UI.
    const titleBar = new FunctionalElement("div");
    const title = new FunctionalElement("div");
    const titleClose = new FunctionalElement("div");

    // Container for the controls UI.
    const controlsUI = new FunctionalElement("div");

    // Buttons for controlling recording and playback.
    const buttonRecord = new FunctionalElement("button");
    const buttonPlay = new FunctionalElement("button");
    const buttonStop = new FunctionalElement("button");

    // Container for the zoom UI.
    const zoomUI = new FunctionalElement("div");

    // Buttons for zooming.
    const buttonZoomIn = new FunctionalElement("button");
    const buttonZoomOut = new FunctionalElement("button");

    // Display for the zoom value for the zoom UI.
    const zoomDisplay = new FunctionalElement("div");

    // Container for the audio UI.
    const audioUI = new FunctionalElement("div");

    // Display for the visualizer of the audio.
    const audioDisplay = new FunctionalElement("canvas");

    // Red bar for indicating the current time frame on the display.
    const audioCurrent = new FunctionalElement("div");

    ////////////////////////////////////////////////////////////////////////////////////////////////
    //
    // Hook up the appropriate listeners.
    //
    ////////////////////////////////////////////////////////////////////////////////////////////////

    // Prevent events from propagating to elements underneath the AuO instance.
    container.listen("click", function (event) {
        event.stopPropagation();
    });

    // Closing via crosshairs is equivalent to suspending the instance.
    titleClose.listen("click", function (event) {
        suspendInstance();
    });

    ////////////////////////////////////////////////////////////////////////////////////////////////
    //
    // Build the DOM tree.
    //
    ////////////////////////////////////////////////////////////////////////////////////////////////

    container
        .append(verticalMiddleButtress)
        .append(horizontalCenterContainer
            .append(mainUI
                .append(titleBar
                    .append(title)
                    .append(titleClose)
                ).append(controlsUI
                    .append(buttonRecord)
                    .append(buttonPlay)
                    .append(buttonStop)
                ).append(audioUI
                    .append(audioDisplay)
                    .append(audioCurrent)
                ).append(zoomUI
                    .append(buttonZoomIn)
                    .append(zoomDisplay)
                    .append(buttonZoomOut)
                )
            )
        )
    ;

    ////////////////////////////////////////////////////////////////////////////////////////////////
    //
    // Style the DOM elements. Styles are sorted lexically. Styles come before sets.
    //
    ////////////////////////////////////////////////////////////////////////////////////////////////

    container
        .style("background-color", "rgba(0, 0, 0, 0.4)")
        .style("display", "block")
        .style("height", "100vh")
        .style("left", "0px")
        .style("position", "fixed")
        .style("text-align", "center")
        .style("top", "0px")
        .style("vertical-align", "middle")
        .style("width", "100%");

    verticalMiddleButtress
        .style("display", "inline-block")
        .style("height", "100%")
        .style("vertical-align", "middle")
        .style("width", "0px");

    horizontalCenterContainer
        .style("display", "inline-block")
        .style("text-align", "center")
        .style("vertical-align", "middle")
        .style("width", "100%");

    mainUI
        .style("background-color", "#FFF")
        .style("border-radius", "10px")
        .style("box-shadow", "10px 10px 5px rgba(0, 0, 0, 0.4)")
        .style("display", "block")
        .style("margin", "auto")
        .style("overflow", "auto")
        .style("padding", "10px")
        .style("position", "relative")
        .style("text-align", "justify")
        .style("white-space", "nowrap")
        .style("width", "80vw");

    titleBar
        .style("backgroud-color", "#DDD")
        .style("display", "block")
        .style("font-size", "12pt")
        .style("font-weight", "bold")
        .style("padding", "5px")
        .style("white-space", "nowrap")
        .style("width", "auto");

    title
        .style("display", "inline-block")
        .style("width", "calc(100% - 120pt)")
        .style("text-align", "left")
        .set("innerHTML", "Record custom sound");

    titleClose
        .style("display", "inline-block")
        .style("font-size", "14pt")
        .style("text-align", "right")
        .style("width", "120pt")
        .set("innerHTML", "[Close] ⨂");

    controlsUI
        .style("display", "block")
        .style("margin", "5px")
        .style("vertical-align", "top")
        .style("white-space", "normal")
        .style("width", "auto");

    buttonRecord
        .style("width", "100px")
        .set("innerHTML", "Record");

    buttonPlay
        .style("margin-left", "5px")
        .style("width", "100px")
        .set("innerHTML", "Play");

    buttonStop
        .style("margin-left", "5px")
        .style("width", "100px")
        .set("innerHTML", "Stop");

    audioUI
        .style("display", "block")
        .style("overflow-x", "scroll")
        .style("margin", "5px")
        .style("position", "relative")
        .style("white-space", "normal")
        .style("width", "auto");

    audioDisplay
        .style("border-left", "1px solid blue")
        .style("height", "100px")
        .style("width", "100%")
        .set("height", "100%");

    audioCurrent
        .style("background-color", "red")
        .style("display", "none")
        .style("height", "100%")
        .style("left", "0px")
        .style("position", "absolute")
        .style("top", "0px")
        .style("width", "1px");

    zoomUI
        .style("display", "block")
        .style("margin-bottom", "5px")
        .style("margin-top", "5px")
        .style("text-align", "center")
        .style("width", "auto");

    buttonZoomIn
        .style("width", "100px")
        .set("innerHTML", "Zoom in");

    buttonZoomOut
        .style("width", "100px")
        .set("innerHTML", "Zoom out");

    zoomDisplay
        .style("display", "inline-block")
        .style("text-align", "center")
        .style("width", "300px");

    ////////////////////////////////////////////////////////////////////////////////////////////////
    //
    // Complete runtime evaluations at the end of construction.
    //
    ////////////////////////////////////////////////////////////////////////////////////////////////

    runtimeAtConstruction();
};
<|endoftext|>


<commit_before>'use strict';

var $ = require('gulp-load-plugins')();
var wiredep = require('wiredep');
var concat = require('concat-stream');
var _ = require('lodash');
var chalk = require('chalk');

module.exports = function(options) {
  var gulp  = require(options.modulesData['gulp'].uses);
  var karma = require(options.modulesData['karma'].uses);

  function listFiles(callback) {

    var wiredepOptions = _.extend({}, options.wiredep, {
      dependencies: true,
      devDependencies: true,
      stream: null
    });

    var bowerDeps = wiredep(wiredepOptions);

    var additionalDeps = options.modulesData['unitTests'].addDeps || [];

    var specFiles = options.specFiles || [];

    var htmlFiles = [
      options.src + '/**/*.html'
    ];

    var srcFiles = [
      options.tmp + '/serve/app/**/*.js'
    ].concat(specFiles.map(function(file) {
      return '!' + file;
    }));

    gulp.src(srcFiles)
      .pipe($.angularFilesort()).on('error', options.errorHandler('AngularFilesort'))
      .pipe(concat(function(files) {
        callback(bowerDeps.js
          .concat(additionalDeps)
          .concat(_.pluck(files, 'path'))
          .concat(htmlFiles)
          .concat(specFiles));
      }));
  }

  function runTests (testOptions, options) {
    listFiles(function(files) {

      var karmaModuleData   = options.modulesData['karma'];
      var karmaConfFileName = process.cwd() + '/' + karmaModuleData.configFile;
      var server            = null;
      var karmaOptions      = {
        configFile:  karmaConfFileName,
        files: files,
        singleRun: testOptions.singleRun,
        autoWatch: !testOptions.singleRun,
        browsers : testOptions.browsers,
        basePath : process.cwd()
      }

      if(typeof karma.Server !== 'function'){
        chalk.red('Please update karma to v0.13 to continue...');
        process.exit(1);
      }

      server = new karma.Server(karmaOptions, function(){ testOptions.done() });
      server.start();
    });
  }

  gulp.task('test', ['scripts'], function(done) {
    var testConfig = _.extend(options.modulesData['unitTests'].testConfig, {done : done});
    runTests(testConfig, options);
  });

  gulp.task('test:auto', ['watchTests'], function(done) {
    var testAutoConfig = _.extend(options.modulesData['unitTests'].testAutoConfig, {done : done});
    runTests(testAutoConfig, options);
  });

};
<commit_msg>Fix console message for old versions of karma<commit_after>'use strict';

var $ = require('gulp-load-plugins')();
var wiredep = require('wiredep');
var concat = require('concat-stream');
var _ = require('lodash');
var chalk = require('chalk');

module.exports = function(options) {
  var gulp  = require(options.modulesData['gulp'].uses);
  var karma = require(options.modulesData['karma'].uses);
  var baseBuildUtils = require(options.modulesData['utils'].uses)(options);

  function listFiles(callback) {

    var wiredepOptions = _.extend({}, options.wiredep, {
      dependencies: true,
      devDependencies: true,
      stream: null
    });

    var bowerDeps = wiredep(wiredepOptions);

    var additionalDeps = options.modulesData['unitTests'].addDeps || [];

    var specFiles = options.specFiles || [];

    var htmlFiles = [
      options.src + '/**/*.html'
    ];

    var srcFiles = [
      options.tmp + '/serve/app/**/*.js'
    ].concat(specFiles.map(function(file) {
      return '!' + file;
    }));

    gulp.src(srcFiles)
      .pipe($.angularFilesort()).on('error', options.errorHandler('AngularFilesort'))
      .pipe(concat(function(files) {
        callback(bowerDeps.js
          .concat(additionalDeps)
          .concat(_.pluck(files, 'path'))
          .concat(htmlFiles)
          .concat(specFiles));
      }));
  }

  function runTests (testOptions, options) {
    listFiles(function(files) {

      var karmaModuleData   = options.modulesData['karma'];
      var karmaConfFileName = process.cwd() + '/' + karmaModuleData.configFile;
      var server            = null;
      var karmaOptions      = {
        configFile:  karmaConfFileName,
        files: files,
        singleRun: testOptions.singleRun,
        autoWatch: !testOptions.singleRun,
        browsers : testOptions.browsers,
        basePath : process.cwd()
      }

      if(typeof karma.Server !== 'function'){
        console.log(baseBuildUtils.getBaseBuildName() + chalk.red('Please update karma to v0.13 to continue...'));
        process.exit(1);
      }

      server = new karma.Server(karmaOptions, function(){ testOptions.done() });
      server.start();
    });
  }

  gulp.task('test', ['scripts'], function(done) {
    var testConfig = _.extend(options.modulesData['unitTests'].testConfig, {done : done});
    runTests(testConfig, options);
  });

  gulp.task('test:auto', ['watchTests'], function(done) {
    var testAutoConfig = _.extend(options.modulesData['unitTests'].testAutoConfig, {done : done});
    runTests(testAutoConfig, options);
  });

};
<|endoftext|>


<commit_before>/**
 * @license
 * Copyright 2016 Google Inc. All Rights Reserved.
 * Copyright 2018 The FOAM 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.
 */

foam.CLASS({
  package: 'foam.dao',
  name: 'ContextualizingDAO',
  extends: 'foam.dao.ProxyDAO',

  documentation: function() {/*
    ContextualizingDAO recreates objects returned by find()/put(), giving them
    access to the exports that this ContextualizingDAO has access to.

    If using a foam.dao.EasyDAO, set contextualize:true to automatically
    contextualize objects returned by find().
  */},

  methods: [
    /** Found objects are cloned into the same context as this DAO */
    {
      name: 'find_',
      code: function(x, id) {
        var self = this;
        return self.delegate.find_(x, id).then(function(obj) {
          return self.maybeContextualize_(x, obj);
        });
      },
      javaCode: 'return maybeContextualize_(x, super.find_(x, id));'
    },
    {
      name: 'put_',
      code: function(x, o) {
        var self = this;
        return self.delegate.put_(x, o).then(function(o) {
          return self.maybeContextualize_(x, o);
        });
      },
      javaCode: 'return maybeContextualize_(x, super.put_(x, obj));'
    },
    {
      name: 'maybeContextualize_',
      returns: 'foam.core.FObject',
      javaReturns: 'foam.core.FObject',
      args: [ { name: 'x', of: 'foam.core.X' },
              { name: 'obj', of: 'foam.core.FObject' } ],
      code: function(obj) {
        return obj && obj.clone(this);
      },
      javaCode: `if ( obj != null ) {
  obj = obj.fclone();
  obj.setX(x);
}
return obj;`
    }
  ]
});
<commit_msg>Actually fix contextualizingDAO...<commit_after>/**
 * @license
 * Copyright 2016 Google Inc. All Rights Reserved.
 * Copyright 2018 The FOAM 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.
 */

foam.CLASS({
  package: 'foam.dao',
  name: 'ContextualizingDAO',
  extends: 'foam.dao.ProxyDAO',

  documentation: function() {/*
    ContextualizingDAO recreates objects returned by find()/put(), giving them
    access to the exports that this ContextualizingDAO has access to.

    If using a foam.dao.EasyDAO, set contextualize:true to automatically
    contextualize objects returned by find().
  */},

  methods: [
    /** Found objects are cloned into the same context as this DAO */
    {
      name: 'find_',
      code: function(x, id) {
        var self = this;
        return self.delegate.find_(x, id).then(function(obj) {
          return self.maybeContextualize_(x, obj);
        });
      },
      javaCode: 'return maybeContextualize_(x, super.find_(x, id));'
    },
    {
      name: 'put_',
      code: function(x, o) {
        var self = this;
        return self.delegate.put_(x, o).then(function(o) {
          return self.maybeContextualize_(x, o);
        });
      },
      javaCode: 'return maybeContextualize_(x, super.put_(x, obj));'
    },
    {
      name: 'maybeContextualize_',
      returns: 'foam.core.FObject',
      javaReturns: 'foam.core.FObject',
      args: [ { name: 'x', of: 'foam.core.X' },
              { name: 'obj', of: 'foam.core.FObject' } ],
      code: function(x, obj) {
        return obj && obj.clone(this);
      },
      javaCode: `if ( obj != null ) {
  obj = obj.fclone();
  obj.setX(x);
}
return obj;`
    }
  ]
});
<|endoftext|>


<commit_before>var express = require('express');
var bodyParser = require('body-parser');
var path = require('path');
var async = require('async');
var mongoose = require('mongoose');

var DatabaseModule = require('./modules/dbModule');
var TwitterModule = require('./modules/twModule');
var FacebookModule = require('./modules/fbModule');

var app = express();

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.static(__dirname + '/public'));

app.post('/message',function(req,res){
	var msg = req.body.message;
	console.log('message',msg);

	console.log('PROGRAM START');

	async.waterfall([
		// Create Twitter message
		function ( next ){
			console.log( "(App Mex) message by Twitter" );
			TwitterModule.post( msg, function twitterCallback( resultData ){
				if ( resultData.success === false ){
					next( true, resultData.error );
					return;
				}
				var twitterId = resultData.data ? resultData.data.id_str : null;
				next( null, resultData.data );
			});
		},
		// Create Facebook message
		function ( twitterId, next){
			if( !twitterId ){
				next( true,"(App Mex) Error retrieving twitter data...");
				return;
			}

			FacebookModule.post( msg, function facebookCallback( resultData ){
				if(resultData.success === false){
					next( true, resultData.error);
					return;
				}
				var facebookResult = resultData.data;
				var facebookId = resultData.data ? resultData.data.id : null;
				next(null, twitterId, facebookId);
			});
		},
		function (twitterId, facebookId, next){
			if( !twitterId || !facebookId) {
				next( true,"(App Mex) Error retrieving facebook data..");
				return;
			}

			var dataToSave = {
				message: msg,
				tweet_id: twitterId,
				fb_id: facebookId
			};

			DatabaseModule(dataToSave, function databaseCallback( resultData){
				if(resultData.success === false){
					next( true, resultData.error);
					return;
				}
				var databaseResult = resultData.data;
				next( null, databaseResult);
			});
		}
		], function(err,result){
				if(err){
					res.json({'error':result});
				}else{
					console.log('Main callback: '+ result);
			 		res.json(result);
				}
			}
	);
	console.log('END PROGRAM');
});

app.get('/message/:message_id',function(req,res){
	var messageId = req.params.message_id;
	console.log('PROGRAM START');

	async.waterfall([
		function(next){
			// Database call
			console.log("(AppMex) Fetching a database record by ID");
			DatabaseModule.get(messageId, function databaseCallback( resultData ){
				if ( resultData.success === false){
					// Error calling the database
					next( true, resultData.error );
					return;
				};

				next(null, resultData.data); // <- Result from the database "resultData.data"
			});
		},
		function(databaseResult, next){
			// Twitter call
			if ( !databaseResult || !databaseResult.tweet_id ){
				next(true, "(App Mex) Error retrieving the tweet_id from the database...");
				return;
			}

			var tweet_id = databaseResult.tweet_id;
			TwitterModule.get(tweet_id, function twitterCallback( resultData ){
				if ( resultData.success === false){ // Error retrieving the tweet from Twitter
					// Error calling the database
					next( true, resultData.error );
					return;
				};

				var twitterResult = resultData.data;
				next(null, databaseResult, twitterResult);
			});
		},
		function(databaseResult, twitterResult, next){
			/// TODO: Facebook call
			if ( !databaseResult || !databaseResult.fb_id ){
				next( true, "(App Mex) Error retrieving the fb_id from the database...");
				return;
			}

			var fb_id = databaseResult.fb_id;
			FacebookModule.get(fb_id, function facebookCallback( resultData ){
				if( resultData.success === false){ //Error retrieving the tweet from Facebook
					// Error calling the database
					next( true, resultData.error);
					return;
				}

				var facebookResult = resultData.data;
				next(null,databaseResult, twitterResult, facebookResult);
			});
		},
		function(databaseResult, twitterResult, facebookResult, next){
			var finalResult = {
				db: databaseResult,
				twitter: twitterResult,
				facebook: facebookResult
			}
			next(null, finalResult);
		}],
		function(err,result){ //<- Final function. It will return the result to the client
			if(err){
				res.json(err);
				return;
			}

			res.json(result);
		}
	);
	console.log('END PROGRAM');
});

var server = app.listen(3000, function () {
  var host = server.address().address;
  var port = server.address().port;

  console.log('Example app listening at http://%s:%s', host, port);
});<commit_msg>facebookId undefined<commit_after>var express = require('express');
var bodyParser = require('body-parser');
var path = require('path');
var async = require('async');
var mongoose = require('mongoose');

var DatabaseModule = require('./modules/dbModule');
var TwitterModule = require('./modules/twModule');
var FacebookModule = require('./modules/fbModule');

var app = express();

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(express.static(__dirname + '/public'));

app.post('/message',function(req,res){
	var msg = req.body.message;
	console.log('message',msg);

	console.log('PROGRAM START');

	async.waterfall([
		// Create Twitter message
		function ( next ){
			console.log( "(App Mex) message by Twitter" );
			TwitterModule.post( msg, function twitterCallback( resultData ){
				if ( resultData.success === false ){
					next( true, resultData.error );
					return;
				}
				var twitterId = resultData.data ? resultData.data.id_str : null;
				next( null, resultData.data );
			});
		},
		// Create Facebook message
		function ( twitterId, next){
			if( !twitterId ){
				next( true,"(App Mex) Error retrieving twitter data...");
				return;
			}

			FacebookModule.post( msg, function facebookCallback( resultData ){
				if(resultData.success === false){
					next( true, resultData.error);
					return;
				}

				var facebookResult = resultData.data;
				var facebookId = resultData.data ? resultData.data.id : null;
				console.log('FacebbokID = ....'+facebookId);

				next(null, twitterId, facebookId);
			});
		},
		function (twitterId, facebookId, next){
			if( !twitterId || !facebookId) {
				next( true,"(App Mex) Error retrieving facebook data..");
				return;
			}

			var dataToSave = {
				message: msg,
				tweet_id: twitterId,
				fb_id: facebookId
			};

			DatabaseModule(dataToSave, function databaseCallback( resultData){
				if(resultData.success === false){
					next( true, resultData.error);
					return;
				}
				var databaseResult = resultData.data;
				next( null, databaseResult);
			});
		}
		], function(err,result){
				if(err){
					res.json({'error':result});
				}else{
					console.log('Main callback: '+ result);
			 		res.json(result);
				}
			}
	);
	console.log('END PROGRAM');
});

app.get('/message/:message_id',function(req,res){
	var messageId = req.params.message_id;
	console.log('PROGRAM START');

	async.waterfall([
		function(next){
			// Database call
			console.log("(AppMex) Fetching a database record by ID");
			DatabaseModule.get(messageId, function databaseCallback( resultData ){
				if ( resultData.success === false){
					// Error calling the database
					next( true, resultData.error );
					return;
				};

				next(null, resultData.data); // <- Result from the database "resultData.data"
			});
		},
		function(databaseResult, next){
			// Twitter call
			if ( !databaseResult || !databaseResult.tweet_id ){
				next(true, "(App Mex) Error retrieving the tweet_id from the database...");
				return;
			}

			var tweet_id = databaseResult.tweet_id;
			TwitterModule.get(tweet_id, function twitterCallback( resultData ){
				if ( resultData.success === false){ // Error retrieving the tweet from Twitter
					// Error calling the database
					next( true, resultData.error );
					return;
				};

				var twitterResult = resultData.data;
				next(null, databaseResult, twitterResult);
			});
		},
		function(databaseResult, twitterResult, next){
			/// TODO: Facebook call
			if ( !databaseResult || !databaseResult.fb_id ){
				next( true, "(App Mex) Error retrieving the fb_id from the database...");
				return;
			}

			var fb_id = databaseResult.fb_id;
			FacebookModule.get(fb_id, function facebookCallback( resultData ){
				if( resultData.success === false){ //Error retrieving the tweet from Facebook
					// Error calling the database
					next( true, resultData.error);
					return;
				}

				var facebookResult = resultData.data;
				next(null,databaseResult, twitterResult, facebookResult);
			});
		},
		function(databaseResult, twitterResult, facebookResult, next){
			var finalResult = {
				db: databaseResult,
				twitter: twitterResult,
				facebook: facebookResult
			}
			next(null, finalResult);
		}],
		function(err,result){ //<- Final function. It will return the result to the client
			if(err){
				res.json(err);
				return;
			}

			res.json(result);
		}
	);
	console.log('END PROGRAM');
});

var server = app.listen(3000, function () {
  var host = server.address().address;
  var port = server.address().port;

  console.log('Example app listening at http://%s:%s', host, port);
});<|endoftext|>


<commit_before>

    "use strict";

    var express = require("express");
    var bodyParser = require('body-parser');
    var winston = require('winston');

    var authorize = require('./services/authorize');
    var authenticate = require('./services/authenticate');

    function server(){

        winston.profile('server');

        console.log("STARTING HEROKU MICROSERVICES");

        var app = express();
        app.use(bodyParser.urlencoded({ extended: false }));
        app.use(bodyParser.json());
        app.use( function( req, res, next ){
            winston.info("REQUEST FROM APPNAME %s", req.body.appname );
            if ( !req.body.appname ){
                res.status(400).json({});
            } else {
                next();
            }
        });

        app.use( function( req, res, next ){
            if ( req.body.token ){
                authorize.func2(...arguments).then( function(){
                    next();
                }).catch( function(){
                    res.status(403).json({});
                });
            } else {
                var safeurls = ["/check/username",  "/register","/authenticate"];
                if  ( safeurls.indexOf( req.url ) !== -1) {
                    next();
                } else {
                    res.status(403).json({});
                }
            }
        });

        var server = app.listen( process.env.PORT, function () {
            winston.log( "info", "STARTED HEROKU MICROSERVICES ON PORT ", process.env.PORT );
        });

        winston.profile('server');

        return app;
    }

    module.exports = server;<commit_msg>filter by appname<commit_after>

    "use strict";

    var express = require("express");
    var bodyParser = require('body-parser');
    var winston = require('winston');

    var authorize = require('./services/authorize');
    var authenticate = require('./services/authenticate');

    function server(){

        winston.profile('server');

        console.log("STARTING HEROKU MICROSERVICES");

        function filterByAppname( req, res, next ){
            winston.info("REQUEST FROM APPNAME %s", req.body.appname );
            if ( !req.body.appname ){
                res.status(400).json({});
            } else {
                next();
            }
        }
        var app = express();
        app.use(bodyParser.urlencoded({ extended: false }));
        app.use(bodyParser.json());
        app.use( filterByAppname);

        app.use( function( req, res, next ){
            if ( req.body.token ){
                authorize.func2(...arguments).then( function(){
                    next();
                }).catch( function(){
                    res.status(403).json({});
                });
            } else {
                var safeurls = ["/check/username",  "/register","/authenticate"];
                if  ( safeurls.indexOf( req.url ) !== -1) {
                    next();
                } else {
                    res.status(403).json({});
                }
            }
        });

        var server = app.listen( process.env.PORT, function () {
            winston.log( "info", "STARTED HEROKU MICROSERVICES ON PORT ", process.env.PORT );
        });

        winston.profile('server');

        return app;
    }

    module.exports = server;<|endoftext|>


<commit_before>/*jshint bitwise:false*/
/*global unescape*/

(function (factory) {
    if (typeof exports === 'object') {
        // Node/CommonJS
        module.exports = factory();
    } else if (typeof define === 'function' && define.amd) {
        // AMD
        define(factory);
    } else {
        // Browser globals (with support for web workers)
        var glob;
        try {
            glob = window;
        } catch (e) {
            glob = self;
        }

        glob.SparkMD5 = factory();
    }
}(function (undefined) {

    'use strict';

    ////////////////////////////////////////////////////////////////////////////

    /*
     * Fastest md5 implementation around (JKM md5)
     * Credits: Joseph Myers
     *
     * @see http://www.myersdaily.org/joseph/javascript/md5-text.html
     * @see http://jsperf.com/md5-shootout/7
     */

    /* this function is much faster,
      so if possible we use it. Some IEs
      are the only ones I know of that
      need the idiotic second function,
      generated by an if clause.  */
    var add32 = function (a, b) {
        return (a + b) & 0xFFFFFFFF;
    },

    cmn = function (q, a, b, x, s, t) {
        a = add32(add32(a, q), add32(x, t));
        return add32((a << s) | (a >>> (32 - s)), b);
    },

    ff = function (a, b, c, d, x, s, t) {
        return cmn((b & c) | ((~b) & d), a, b, x, s, t);
    },

    gg = function (a, b, c, d, x, s, t) {
        return cmn((b & d) | (c & (~d)), a, b, x, s, t);
    },

    hh = function (a, b, c, d, x, s, t) {
        return cmn(b ^ c ^ d, a, b, x, s, t);
    },

    ii = function (a, b, c, d, x, s, t) {
        return cmn(c ^ (b | (~d)), a, b, x, s, t);
    },

    md5cycle = function (x, k) {
        var a = x[0],
            b = x[1],
            c = x[2],
            d = x[3];

        a = ff(a, b, c, d, k[0], 7, -680876936);
        d = ff(d, a, b, c, k[1], 12, -389564586);
        c = ff(c, d, a, b, k[2], 17, 606105819);
        b = ff(b, c, d, a, k[3], 22, -1044525330);
        a = ff(a, b, c, d, k[4], 7, -176418897);
        d = ff(d, a, b, c, k[5], 12, 1200080426);
        c = ff(c, d, a, b, k[6], 17, -1473231341);
        b = ff(b, c, d, a, k[7], 22, -45705983);
        a = ff(a, b, c, d, k[8], 7, 1770035416);
        d = ff(d, a, b, c, k[9], 12, -1958414417);
        c = ff(c, d, a, b, k[10], 17, -42063);
        b = ff(b, c, d, a, k[11], 22, -1990404162);
        a = ff(a, b, c, d, k[12], 7, 1804603682);
        d = ff(d, a, b, c, k[13], 12, -40341101);
        c = ff(c, d, a, b, k[14], 17, -1502002290);
        b = ff(b, c, d, a, k[15], 22, 1236535329);

        a = gg(a, b, c, d, k[1], 5, -165796510);
        d = gg(d, a, b, c, k[6], 9, -1069501632);
        c = gg(c, d, a, b, k[11], 14, 643717713);
        b = gg(b, c, d, a, k[0], 20, -373897302);
        a = gg(a, b, c, d, k[5], 5, -701558691);
        d = gg(d, a, b, c, k[10], 9, 38016083);
        c = gg(c, d, a, b, k[15], 14, -660478335);
        b = gg(b, c, d, a, k[4], 20, -405537848);
        a = gg(a, b, c, d, k[9], 5, 568446438);
        d = gg(d, a, b, c, k[14], 9, -1019803690);
        c = gg(c, d, a, b, k[3], 14, -187363961);
        b = gg(b, c, d, a, k[8], 20, 1163531501);
        a = gg(a, b, c, d, k[13], 5, -1444681467);
        d = gg(d, a, b, c, k[2], 9, -51403784);
        c = gg(c, d, a, b, k[7], 14, 1735328473);
        b = gg(b, c, d, a, k[12], 20, -1926607734);

        a = hh(a, b, c, d, k[5], 4, -378558);
        d = hh(d, a, b, c, k[8], 11, -2022574463);
        c = hh(c, d, a, b, k[11], 16, 1839030562);
        b = hh(b, c, d, a, k[14], 23, -35309556);
        a = hh(a, b, c, d, k[1], 4, -1530992060);
        d = hh(d, a, b, c, k[4], 11, 1272893353);
        c = hh(c, d, a, b, k[7], 16, -155497632);
        b = hh(b, c, d, a, k[10], 23, -1094730640);
        a = hh(a, b, c, d, k[13], 4, 681279174);
        d = hh(d, a, b, c, k[0], 11, -358537222);
        c = hh(c, d, a, b, k[3], 16, -722521979);
        b = hh(b, c, d, a, k[6], 23, 76029189);
        a = hh(a, b, c, d, k[9], 4, -640364487);
        d = hh(d, a, b, c, k[12], 11, -421815835);
        c = hh(c, d, a, b, k[15], 16, 530742520);
        b = hh(b, c, d, a, k[2], 23, -995338651);

        a = ii(a, b, c, d, k[0], 6, -198630844);
        d = ii(d, a, b, c, k[7], 10, 1126891415);
        c = ii(c, d, a, b, k[14], 15, -1416354905);
        b = ii(b, c, d, a, k[5], 21, -57434055);
        a = ii(a, b, c, d, k[12], 6, 1700485571);
        d = ii(d, a, b, c, k[3], 10, -1894986606);
        c = ii(c, d, a, b, k[10], 15, -1051523);
        b = ii(b, c, d, a, k[1], 21, -2054922799);
        a = ii(a, b, c, d, k[8], 6, 1873313359);
        d = ii(d, a, b, c, k[15], 10, -30611744);
        c = ii(c, d, a, b, k[6], 15, -1560198380);
        b = ii(b, c, d, a, k[13], 21, 1309151649);
        a = ii(a, b, c, d, k[4], 6, -145523070);
        d = ii(d, a, b, c, k[11], 10, -1120210379);
        c = ii(c, d, a, b, k[2], 15, 718787259);
        b = ii(b, c, d, a, k[9], 21, -343485551);

        x[0] = add32(a, x[0]);
        x[1] = add32(b, x[1]);
        x[2] = add32(c, x[2]);
        x[3] = add32(d, x[3]);
    },

    /* there needs to be support for Unicode here,
       * unless we pretend that we can redefine the MD-5
       * algorithm for multi-byte characters (perhaps
       * by adding every four 16-bit characters and
       * shortening the sum to 32 bits). Otherwise
       * I suggest performing MD-5 as if every character
       * was two bytes--e.g., 0040 0025 = @%--but then
       * how will an ordinary MD-5 sum be matched?
       * There is no way to standardize text to something
       * like UTF-8 before transformation; speed cost is
       * utterly prohibitive. The JavaScript standard
       * itself needs to look at this: it should start
       * providing access to strings as preformed UTF-8
       * 8-bit unsigned value arrays.
       */
    md5blk = function (s) {
        var md5blks = [],
            i; /* Andy King said do it this way. */

        for (i = 0; i < 64; i += 4) {
            md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24);
        }
        return md5blks;
    },

    md5blk_array = function (a) {
        var md5blks = [],
            i; /* Andy King said do it this way. */

        for (i = 0; i < 64; i += 4) {
            md5blks[i >> 2] = a[i] + (a[i + 1] << 8) + (a[i + 2] << 16) + (a[i + 3] << 24);
        }
        return md5blks;
    },

    md51 = function (s) {
        var n = s.length,
            state = [1732584193, -271733879, -1732584194, 271733878],
            i,
            length,
            tail,
            tmp,
            lo,
            hi;

        for (i = 64; i <= n; i += 64) {
            md5cycle(state, md5blk(s.substring(i - 64, i)));
        }
        s = s.substring(i - 64);
        length = s.length;
        tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
        for (i = 0; i < length; i += 1) {
            tail[i >> 2] |= s.charCodeAt(i) << ((i % 4) << 3);
        }
        tail[i >> 2] |= 0x80 << ((i % 4) << 3);
        if (i > 55) {
            md5cycle(state, tail);
            for (i = 0; i < 16; i += 1) {
                tail[i] = 0;
            }
        }

        // Beware that the final length might not fit in 32 bits so we take care of that
        tmp = n * 8;
        tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);
        lo = parseInt(tmp[2], 16);
        hi = parseInt(tmp[1], 16) || 0;

        tail[14] = lo;
        tail[15] = hi;

        md5cycle(state, tail);
        return state;
    },

    md51_array = function (a) {
        var n = a.length,
            state = [1732584193, -271733879, -1732584194, 271733878],
            i,
            length,
            tail,
            tmp,
            lo,
            hi;

        for (i = 64; i <= n; i += 64) {
            md5cycle(state, md5blk_array(a.subarray(i - 64, i)));
        }

        // Not sure if it is a bug, however IE10 will always produce a sub array of length 1
        // containing the last element of the parent array if the sub array specified starts
        // beyond the length of the parent array - weird.
        // https://connect.microsoft.com/IE/feedback/details/771452/typed-array-subarray-issue
        a = (i - 64) < n ? a.subarray(i - 64) : new Uint8Array(0);

        length = a.length;
        tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
        for (i = 0; i < length; i += 1) {
            tail[i >> 2] |= a[i] << ((i % 4) << 3);
        }

        tail[i >> 2] |= 0x80 << ((i % 4) << 3);
        if (i > 55) {
            md5cycle(state, tail);
            for (i = 0; i < 16; i += 1) {
                tail[i] = 0;
            }
        }

        // Beware that the final length might not fit in 32 bits so we take care of that
        tmp = n * 8;
        tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);
        lo = parseInt(tmp[2], 16);
        hi = parseInt(tmp[1], 16) || 0;

        tail[14] = lo;
        tail[15] = hi;

        md5cycle(state, tail);

        return state;
    },

    hex_chr = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'],

    rhex = function (n) {
        var s = '',
            j;
        for (j = 0; j < 4; j += 1) {
            s += hex_chr[(n >> (j * 8 + 4)) & 0x0F] + hex_chr[(n >> (j * 8)) & 0x0F];
        }
        return s;
    },

    hex = function (x) {
        var i;
        for (i = 0; i < x.length; i += 1) {
            x[i] = rhex(x[i]);
        }
        return x.join('');
    },

    md5 = function (s) {
        return hex(md51(s));
    },

    ////////////////////////////////////////////////////////////////////////////

    /**
     * SparkMD5 OOP implementation.
     *
     * Use this class to perform an incremental md5, otherwise use the
     * static methods instead.
     */
    SparkMD5 = function () {
        // call reset to init the instance
        this.reset();
    };

    // In some cases the fast add32 function cannot be used..
    if (md5('hello') !== '5d41402abc4b2a76b9719d911017c592') {
        add32 = function (x, y) {
            var lsw = (x & 0xFFFF) + (y & 0xFFFF),
                msw = (x >> 16) + (y >> 16) + (lsw >> 16);
            return (msw << 16) | (lsw & 0xFFFF);
        };
    }

    /**
     * Appends a string.
     * A conversion will be applied if an utf8 string is detected.
     *
     * @param {String} str The string to be appended
     *
     * @return {SparkMD5} The instance itself
     */
    SparkMD5.prototype.append = function (str) {
        // converts the string to utf8 bytes if necessary
        if (/[\u0080-\uFFFF]/.test(str)) {
            str = unescape(encodeURIComponent(str));
        }

        // then append as binary
        this.appendBinary(str);

        return this;
    };

    /**
     * Appends a binary string.
     *
     * @param {String} contents The binary string to be appended
     *
     * @return {SparkMD5} The instance itself
     */
    SparkMD5.prototype.appendBinary = function (contents) {
        this._buff += contents;
        this._length += contents.length;

        var length = this._buff.length,
            i;

        for (i = 64; i <= length; i += 64) {
            md5cycle(this._state, md5blk(this._buff.substring(i - 64, i)));
        }

        this._buff = this._buff.substr(i - 64);

        return this;
    };

    /**
     * Finishes the incremental computation, reseting the internal state and
     * returning the result.
     * Use the raw parameter to obtain the raw result instead of the hex one.
     *
     * @param {Boolean} raw True to get the raw result, false to get the hex result
     *
     * @return {String|Array} The result
     */
    SparkMD5.prototype.end = function (raw) {
        var buff = this._buff,
            length = buff.length,
            i,
            tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            ret;

        for (i = 0; i < length; i += 1) {
            tail[i >> 2] |= buff.charCodeAt(i) << ((i % 4) << 3);
        }

        this._finish(tail, length);
        ret = !!raw ? this._state : hex(this._state);

        this.reset();

        return ret;
    };

    /**
     * Finish the final calculation based on the tail.
     *
     * @param {Array}  tail   The tail (will be modified)
     * @param {Number} length The length of the remaining buffer
     */
    SparkMD5.prototype._finish = function (tail, length) {
        var i = length,
            tmp,
            lo,
            hi;

        tail[i >> 2] |= 0x80 << ((i % 4) << 3);
        if (i > 55) {
            md5cycle(this._state, tail);
            for (i = 0; i < 16; i += 1) {
                tail[i] = 0;
            }
        }

        // Do the final computation based on the tail and length
        // Beware that the final length may not fit in 32 bits so we take care of that
        tmp = this._length * 8;
        tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);
        lo = parseInt(tmp[2], 16);
        hi = parseInt(tmp[1], 16) || 0;

        tail[14] = lo;
        tail[15] = hi;
        md5cycle(this._state, tail);
    };

    /**
     * Resets the internal state of the computation.
     *
     * @return {SparkMD5} The instance itself
     */
    SparkMD5.prototype.reset = function () {
        this._buff = "";
        this._length = 0;
        this._state = [1732584193, -271733879, -1732584194, 271733878];

        return this;
    };

    /**
     * Releases memory used by the incremental buffer and other aditional
     * resources. If you plan to use the instance again, use reset instead.
     */
    SparkMD5.prototype.destroy = function () {
        delete this._state;
        delete this._buff;
        delete this._length;
    };

    /**
     * Performs the md5 hash on a string.
     * A conversion will be applied if utf8 string is detected.
     *
     * @param {String}  str The string
     * @param {Boolean} raw True to get the raw result, false to get the hex result
     *
     * @return {String|Array} The result
     */
    SparkMD5.hash = function (str, raw) {
        // converts the string to utf8 bytes if necessary
        if (/[\u0080-\uFFFF]/.test(str)) {
            str = unescape(encodeURIComponent(str));
        }

        var hash = md51(str);

        return !!raw ? hash : hex(hash);
    };

    /**
     * Performs the md5 hash on a binary string.
     *
     * @param {String}  content The binary string
     * @param {Boolean} raw     True to get the raw result, false to get the hex result
     *
     * @return {String|Array} The result
     */
    SparkMD5.hashBinary = function (content, raw) {
        var hash = md51(content);

        return !!raw ? hash : hex(hash);
    };

    /**
     * SparkMD5 OOP implementation for array buffers.
     *
     * Use this class to perform an incremental md5 ONLY for array buffers.
     */
    SparkMD5.ArrayBuffer = function () {
        // call reset to init the instance
        this.reset();
    };

    ////////////////////////////////////////////////////////////////////////////

    /**
     * Appends an array buffer.
     *
     * @param {ArrayBuffer} arr The array to be appended
     *
     * @return {SparkMD5.ArrayBuffer} The instance itself
     */
    SparkMD5.ArrayBuffer.prototype.append = function (arr) {
        // TODO: we could avoid the concatenation here but the algorithm would be more complex
        //       if you find yourself needing extra performance, please make a PR.
        var buff = this._concatArrayBuffer(this._buff, arr),
            length = buff.length,
            i;

        this._length += arr.byteLength;

        for (i = 64; i <= length; i += 64) {
            md5cycle(this._state, md5blk_array(buff.subarray(i - 64, i)));
        }

        // Avoids IE10 weirdness (documented above)
        this._buff = (i - 64) < length ? buff.subarray(i - 64) : new Uint8Array(0);

        return this;
    };

    /**
     * Finishes the incremental computation, reseting the internal state and
     * returning the result.
     * Use the raw parameter to obtain the raw result instead of the hex one.
     *
     * @param {Boolean} raw True to get the raw result, false to get the hex result
     *
     * @return {String|Array} The result
     */
    SparkMD5.ArrayBuffer.prototype.end = function (raw) {
        var buff = this._buff,
            length = buff.length,
            tail = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
            i,
            ret;

        for (i = 0; i < length; i += 1) {
            tail[i >> 2] |= buff[i] << ((i % 4) << 3);
        }

        this._finish(tail, length);
        ret = !!raw ? this._state : hex(this._state);

        this.reset();

        return ret;
    };

    SparkMD5.ArrayBuffer.prototype._finish = SparkMD5.prototype._finish;

    /**
     * Resets the internal state of the computation.
     *
     * @return {SparkMD5.ArrayBuffer} The instance itself
     */
    SparkMD5.ArrayBuffer.prototype.reset = function () {
        this._buff = new Uint8Array(0);
        this._length = 0;
        this._state = [1732584193, -271733879, -1732584194, 271733878];

        return this;
    };

    /**
     * Releases memory used by the incremental buffer and other aditional
     * resources. If you plan to use the instance again, use reset instead.
     */
    SparkMD5.ArrayBuffer.prototype.destroy = SparkMD5.prototype.destroy;

    /**
     * Concats two array buffers, returning a new one.
     *
     * @param  {ArrayBuffer} first  The first array buffer
     * @param  {ArrayBuffer} second The second array buffer
     *
     * @return {ArrayBuffer} The new array buffer
     */
    SparkMD5.ArrayBuffer.prototype._concatArrayBuffer = function (first, second) {
        var firstLength = first.length,
            result = new Uint8Array(firstLength + second.byteLength);

        result.set(first);
        result.set(new Uint8Array(second), firstLength);

        return result;
    };

    /**
     * Performs the md5 hash on an array buffer.
     *
     * @param {ArrayBuffer} arr The array buffer
     * @param {Boolean}     raw True to get the raw result, false to get the hex result
     *
     * @return {String|Array} The result
     */
    SparkMD5.ArrayBuffer.hash = function (arr, raw) {
        var hash = md51_array(new Uint8Array(arr));

        return !!raw ? hash : hex(hash);
    };

    return SparkMD5;
}));
<commit_msg>Delete spark-md5.js<commit_after><|endoftext|>