<commit_before>var vecs = require("vecs");

module.exports = function (svgRoot) {
  var root = vecs.SVGRoot.instanceFromRawElement(svgRoot);
  root.setViewBox("0 0 1000 1000");
  root.setPreserveAspectRatio("xMinYMin");

  var cp = new CrepuscularRays(root);
  cp.draw();

  var ms = new MountainSilhouette(root);
  ms.draw();

  var cactus = new Saguaro(root);
  cactus.draw();
};

var Saguaro = function (svgRoot) {
  this._svgRoot = svgRoot;

  this._xPos = 750;
  this._yPos = 350;
  this._armOffsetFromTop = 300;
  this._trunkWidth = 60;
  this._color = "#758A65";
};

Saguaro.prototype.draw = function () {
  var trunkRadius = this._trunkWidth / 2;

  var trunkCap = new vecs.SVGCircle(trunkRadius);
  trunkCap.setFillColor(this._color);
  this._svgRoot.addAt(trunkCap, this._xPos, this._yPos);

  var trunk = new vecs.SVGRect(this._trunkWidth, 1000);
  trunk.setFillColor(this._color);
  this._svgRoot.addAt(trunk, this._xPos - trunkRadius, this._yPos);

  var leftArm = this._createArm(false);
  var armYOffset = this._yPos + this._armOffsetFromTop;
  this._svgRoot.addAt(leftArm, this._xPos, armYOffset);

  var rightArm = this._createArm(true);
  this._svgRoot.addAt(rightArm, this._xPos, armYOffset + 50);
};

Saguaro.prototype._createArm = function (flip) {
  var trunkRadius = this._trunkWidth / 2;
  var flipTrigger = flip ? -1 : 1;

  var armHeight = 200;
  var arm = new vecs.SVGPath();
  arm.addQuadraticBezierCurve(
    trunkRadius*flipTrigger - 150*flipTrigger, 70,
    trunkRadius*flipTrigger - 150*flipTrigger, 0 - armHeight
  );
  arm.addLineSegment(0, -30);
  arm.setFillColor("transparent");
  arm.setStrokeWidth(this._trunkWidth);
  arm.setStrokeColor(this._color);
  arm.setStrokeLinecap("round");
  arm.preventClose();

  return arm;
};

var MountainSilhouette = function (svgRoot) {
  this._svgRoot = svgRoot;

  this._peaks = 3;
  this._peakMax = 560;
  this._valleyMin = 640;
  this._color = "#222222";
};

MountainSilhouette.prototype.draw = function () {
  var ridges = new vecs.SVGPolygon();

  var peaksAndValleysCount = this._peaks * 2;
  for (var i = 0; i <= peaksAndValleysCount; i++) {
    var peak = i % 2 === 0;
    var x = 1000 * i / peaksAndValleysCount;
    var y = peak ? this._peakMax : this._valleyMin;
    ridges.addPoint(x, y);
  }
  ridges.addPoint(1001, 1001);
  ridges.addPoint(-1, 1001);

  ridges.setStrokeWidth(1);
  ridges.setStrokeColor(this._color);
  ridges.setFillColor(this._color);
  this._svgRoot.addAt(ridges, 0, 300);
};

var CrepuscularRays = function (svg) {
  this._svgRoot = svg;
  // this._svgRoot.observeTouchGesture(this._updateCenterPointFromEvent.bind(this));

  this._rayOriginationPoint = this._svgRoot.createPoint(500, 1000);
  this._colors = ["red", "yellow"];
  this._rayCount = 26;
  this._rayElements = [];
  this._needsRedraw = true;
};

CrepuscularRays.prototype._updateCenterPointFromEvent = function (e) {
  this.setRayOriginationPoint(e.positionRelativeToViewport());
};

CrepuscularRays.prototype.svgRoot = function () {
  return this._svgRoot;
};

CrepuscularRays.prototype.setRayOriginationPoint = function (point) {
  this._rayOriginationPoint = point;
  this._needsRedraw = true;
  this.draw();
};

CrepuscularRays.prototype.setColors = function (colors) {
  this._colors = colors.slice(0);
  this._needsRedraw = true;
};

CrepuscularRays.prototype.setRayCount = function (count) {
  this._rayCount = count;
  this._needsRedraw = true;
};

CrepuscularRays.prototype.draw = function () {
  if (!this._needsRedraw) return;

  // Clean up our children elements
  this._rayElements.forEach(function (element) {
    element.removeFromDocument();
  });
  this._rayElements = [];

  // Create new children elements
  for (var i = 0; i < this._rayCount; i++) {
    var triangle = new vecs.SVGPolygon();
    this._rayElements.push(triangle);
    this._svgRoot.addAt(triangle, i * 50, i * 50);

    var viewportDimensions = this._svgRoot.viewportDimensions()
      , radius = (Math.max(viewportDimensions.width, viewportDimensions.height) + 2)
      , radians1 = 2 * Math.PI * i / this._rayCount
      , x1 = (viewportDimensions.width  / 2) + (radius * Math.cos(radians1))
      , y1 = (viewportDimensions.height / 2) + (radius * Math.sin(radians1))
      , radians2 = 2 * Math.PI  * (i + 1) / this._rayCount
      , x2 = (viewportDimensions.width  / 2) + (radius * Math.cos(radians2))
      , y2 = (viewportDimensions.height / 2) + (radius * Math.sin(radians2));

    triangle.addPoint(this._rayOriginationPoint.x, this._rayOriginationPoint.y);
    triangle.addPoint(x1, y1);
    triangle.addPoint(x2, y2);

    var color = this._colors[i % this._colors.length];
    triangle.setFillColor(color);
  }

  this._needsRedraw = false;
};<commit_msg>TucsonJS logo text (Relay Condensed Bold)<commit_after>var vecs = require("vecs");

module.exports = function (svgRoot) {
  var root = vecs.SVGRoot.instanceFromRawElement(svgRoot);
  root.setViewBox("0 0 1000 1000");
  root.setPreserveAspectRatio("xMinYMin");

  var cp = new CrepuscularRays(root);
  cp.draw();

  var ms = new MountainSilhouette(root);
  ms.draw();

  var cactus = new Saguaro(root);
  cactus.draw();
};

var Saguaro = function (svgRoot) {
  this._svgRoot = svgRoot;

  this._xPos = 750;
  this._yPos = 350;
  this._armOffsetFromTop = 300;
  this._trunkWidth = 60;
  this._color = "#758A65";
};

Saguaro.prototype.draw = function () {
  var trunkRadius = this._trunkWidth / 2;

  var trunkCap = new vecs.SVGCircle(trunkRadius);
  trunkCap.setFillColor(this._color);
  this._svgRoot.addAt(trunkCap, this._xPos, this._yPos);

  var trunk = new vecs.SVGRect(this._trunkWidth, 1000);
  trunk.setFillColor(this._color);
  this._svgRoot.addAt(trunk, this._xPos - trunkRadius, this._yPos);

  var leftArm = this._createArm(false);
  var armYOffset = this._yPos + this._armOffsetFromTop;
  this._svgRoot.addAt(leftArm, this._xPos, armYOffset);

  var rightArm = this._createArm(true);
  this._svgRoot.addAt(rightArm, this._xPos, armYOffset + 50);
};

Saguaro.prototype._createArm = function (flip) {
  var trunkRadius = this._trunkWidth / 2;
  var flipTrigger = flip ? -1 : 1;

  var armHeight = 200;
  var arm = new vecs.SVGPath();
  arm.addQuadraticBezierCurve(
    trunkRadius*flipTrigger - 150*flipTrigger, 70,
    trunkRadius*flipTrigger - 150*flipTrigger, 0 - armHeight
  );
  arm.addLineSegment(0, -30);
  arm.setFillColor("transparent");
  arm.setStrokeWidth(this._trunkWidth);
  arm.setStrokeColor(this._color);
  arm.setStrokeLinecap("round");
  arm.preventClose();

  return arm;
};

var MountainSilhouette = function (svgRoot) {
  this._svgRoot = svgRoot;

  this._peaks = 3;
  this._peakMax = 560;
  this._valleyMin = 640;
  this._color = "#222222";
};

MountainSilhouette.prototype.draw = function () {
  var ridges = new vecs.SVGPolygon();

  var peaksAndValleysCount = this._peaks * 2;
  for (var i = 0; i <= peaksAndValleysCount; i++) {
    var peak = i % 2 === 0;
    var x = 1000 * i / peaksAndValleysCount;
    var y = peak ? this._peakMax : this._valleyMin;
    ridges.addPoint(x, y);
  }
  ridges.addPoint(1001, 1001);
  ridges.addPoint(-1, 1001);

  ridges.setStrokeWidth(1);
  ridges.setStrokeColor(this._color);
  ridges.setFillColor(this._color);
  this._svgRoot.addAt(ridges, 0, 300);
};

var CrepuscularRays = function (svg) {
  this._svgRoot = svg;
  // this._svgRoot.observeTouchGesture(this._updateCenterPointFromEvent.bind(this));

  this._rayOriginationPoint = this._svgRoot.createPoint(500, 1000);
  this._colors = ["red", "yellow"];
  this._rayCount = 26;
  this._rayElements = [];
  this._needsRedraw = true;
};

CrepuscularRays.prototype._updateCenterPointFromEvent = function (e) {
  this.setRayOriginationPoint(e.positionRelativeToViewport());
};

CrepuscularRays.prototype.svgRoot = function () {
  return this._svgRoot;
};

CrepuscularRays.prototype.setRayOriginationPoint = function (point) {
  this._rayOriginationPoint = point;
  this._needsRedraw = true;
  this.draw();
};

CrepuscularRays.prototype.setColors = function (colors) {
  this._colors = colors.slice(0);
  this._needsRedraw = true;
};

CrepuscularRays.prototype.setRayCount = function (count) {
  this._rayCount = count;
  this._needsRedraw = true;
};

CrepuscularRays.prototype.draw = function () {
  if (!this._needsRedraw) return;

  // Clean up our children elements
  this._rayElements.forEach(function (element) {
    element.removeFromDocument();
  });
  this._rayElements = [];

  // Create new children elements
  for (var i = 0; i < this._rayCount; i++) {
    var triangle = new vecs.SVGPolygon();
    this._rayElements.push(triangle);
    this._svgRoot.addAt(triangle, i * 50, i * 50);

    var viewportDimensions = this._svgRoot.viewportDimensions()
      , radius = (Math.max(viewportDimensions.width, viewportDimensions.height) + 2)
      , radians1 = 2 * Math.PI * i / this._rayCount
      , x1 = (viewportDimensions.width  / 2) + (radius * Math.cos(radians1))
      , y1 = (viewportDimensions.height / 2) + (radius * Math.sin(radians1))
      , radians2 = 2 * Math.PI  * (i + 1) / this._rayCount
      , x2 = (viewportDimensions.width  / 2) + (radius * Math.cos(radians2))
      , y2 = (viewportDimensions.height / 2) + (radius * Math.sin(radians2));

    triangle.addPoint(this._rayOriginationPoint.x, this._rayOriginationPoint.y);
    triangle.addPoint(x1, y1);
    triangle.addPoint(x2, y2);

    var color = this._colors[i % this._colors.length];
    triangle.setFillColor(color);
  }

  this._needsRedraw = false;
};

var TucsonJSText = function (svg, color) {
  this._svgRoot = svg;
  this._color = color;
  this._path = "M 23.2 22.8 L 23.2 142.2 L 46.2 142.2 L 46.2 22.8 L 69.2 22.8 L 69.2 1.2 L 0.0 1.2 L 0.0 22.8 Z M 115.8 144.6 C 142.6 144.6 151.4 128.0 151.4 89.6 L 151.4 1.2 L 129.4 1.2 L 129.4 91.6 C 129.4 113.6 127.4 123.6 116.0 123.6 C 104.8 123.6 102.8 113.6 102.8 91.6 L 102.8 1.2 L 80.2 1.2 L 80.2 89.6 C 80.2 128.4 88.6 144.6 115.8 144.6 Z M 163.6 71.6 C 163.6 126.0 191.6 143.0 215.2 143.0 C 218.4 143.0 221.6 142.6 224.4 141.8 L 221.8 120.4 C 219.8 120.8 218.0 120.8 216.4 120.8 C 197.0 120.8 186.2 101.0 186.2 72.0 C 186.2 42.6 197.0 23.4 216.4 23.4 C 218.2 23.4 220.0 23.6 221.8 23.8 L 224.4 1.6 C 221.6 1.0 218.4 0.6 215.0 0.6 C 191.6 0.6 163.6 17.2 163.6 71.6 Z M 259.4 143.2 C 281.2 143.2 295.4 132.4 295.4 110.4 C 295.4 79.8 255.6 51.0 255.6 32.6 C 255.6 25.2 260.4 21.8 267.4 21.8 C 272.4 21.8 278.6 23.2 283.2 25.0 L 290.0 5.0 C 286.2 3.0 277.0 0.0 266.6 0.0 C 250.4 0.0 233.0 7.4 233.0 32.6 C 233.0 63.2 272.6 90.8 272.6 110.4 C 272.6 117.8 268.0 122.6 259.0 122.6 C 250.8 122.6 241.4 119.2 236.8 116.8 L 229.4 135.8 C 236.4 139.6 247.2 143.2 259.4 143.2 Z M 343.6 143.4 C 367.0 143.4 382.6 121.8 382.6 71.8 C 382.6 21.4 367.0 0.0 343.6 0.0 C 320.0 0.0 304.2 21.6 304.2 71.8 C 304.2 122.0 320.0 143.4 343.6 143.4 Z M 343.6 122.0 C 331.2 122.0 327.0 99.4 327.0 72.0 C 327.0 44.4 331.2 22.6 343.6 22.6 C 356.0 22.6 360.0 44.4 360.0 72.0 C 360.0 99.6 356.0 122.0 343.6 122.0 Z M 459.4 142.4 L 468.8 142.4 L 468.8 1.2 L 448.4 1.2 L 448.4 75.6 L 408.4 1.0 L 397.2 1.0 L 397.2 142.2 L 417.4 142.2 L 417.4 62.2 Z M 495.6 143.4 C 510.2 143.4 526.6 139.6 526.6 107.8 L 526.6 1.2 L 504.0 1.2 L 504.0 105.0 C 504.0 118.2 501.2 121.2 492.4 121.2 C 489.8 121.2 486.4 120.8 482.4 120.0 L 479.8 141.2 C 484.4 142.4 490.4 143.4 495.6 143.4 Z M 566.6 143.2 C 588.4 143.2 602.6 132.4 602.6 110.4 C 602.6 79.8 562.8 51.0 562.8 32.6 C 562.8 25.2 567.6 21.8 574.6 21.8 C 579.6 21.8 585.8 23.2 590.4 25.0 L 597.2 5.0 C 593.4 3.0 584.2 0.0 573.8 0.0 C 557.6 0.0 540.2 7.4 540.2 32.6 C 540.2 63.2 579.8 90.8 579.8 110.4 C 579.8 117.8 575.2 122.6 566.2 122.6 C 558.0 122.6 548.6 119.2 544.0 116.8 L 536.6 135.8 C 543.6 139.6 554.4 143.2 566.6 143.2 Z";
};

TucsonJSText.prototype.draw = function () {
  var container = new vecs.SVGRoot(1000, 1000);
  var textPath = new vecs.SVGPath();
  textPath.addRawCommandString(this._path);
  textPath.setFillColor(this._color);
  container.addAt(textPath, 0, 0);
  this._svgRoot.addAt(container, 375, 830);
};
<|endoftext|>


<commit_before>/* jshint node: true */

'use strict';
var path = require('path');
var fs = require('fs');

//
var JSONReporter = function (baseReporterDecorator, config, helper, logger) {

  var log = logger.create('karma-json-reporter');
  baseReporterDecorator(this);

  var history = {
    browsers : {},
    result : {},
    summary : {}
  };

  var reporterConfig = config.jsonReporter || {};
  var stdout = typeof reporterConfig.stdout !== 'undefined' ? reporterConfig.stdout : true;
  var outputFile = (reporterConfig.outputFile) ? helper.normalizeWinPath(path.resolve(config.basePath, reporterConfig.outputFile )) : null;

  this.onSpecComplete = function(browser, result) {
    history.result[browser.id] = history.result[browser.id] || [];
    history.result[browser.id].push(result);

    history.browsers[browser.id] = history.browsers[browser.id] || browser;
  };

  this.onRunComplete = function(browser, result) {
    history.summary = result;
    if(stdout) process.stdout.write(JSON.stringify(history));
    if(outputFile) {
      helper.mkdirIfNotExists(path.dirname(outputFile), function() {
      fs.writeFile(outputFile, JSON.stringify(history), function(err) {
        if (err) {
          log.warn('Cannot write JSON\n\t' + err.message);
        } else {
          log.debug('JSON written to "%s".', outputFile);
        }
      });
    });
    }
    history.result = {};
  };
};

JSONReporter.$inject = ['baseReporterDecorator','config','helper','logger'];

// PUBLISH DI MODULE
module.exports = {
  'reporter:json': ['type', JSONReporter]
};
<commit_msg>Clearing history.result only after the output file has been written. (#14)<commit_after>/* jshint node: true */

'use strict';
var path = require('path');
var fs = require('fs');

//
var JSONReporter = function (baseReporterDecorator, config, helper, logger) {

  var log = logger.create('karma-json-reporter');
  baseReporterDecorator(this);

  var history = {
    browsers : {},
    result : {},
    summary : {}
  };

  var reporterConfig = config.jsonReporter || {};
  var stdout = typeof reporterConfig.stdout !== 'undefined' ? reporterConfig.stdout : true;
  var outputFile = (reporterConfig.outputFile) ? helper.normalizeWinPath(path.resolve(config.basePath, reporterConfig.outputFile )) : null;

  this.onSpecComplete = function(browser, result) {
    history.result[browser.id] = history.result[browser.id] || [];
    history.result[browser.id].push(result);

    history.browsers[browser.id] = history.browsers[browser.id] || browser;
  };

  this.onRunComplete = function(browser, result) {
    history.summary = result;
    if(stdout) process.stdout.write(JSON.stringify(history));
    if(outputFile) {
      helper.mkdirIfNotExists(path.dirname(outputFile), function() {
      fs.writeFile(outputFile, JSON.stringify(history), function(err) {
        if (err) {
          log.warn('Cannot write JSON\n\t' + err.message);
        } else {
          log.debug('JSON written to "%s".', outputFile);
        }
        history.result = {};
      });
    });
    }else {
      history.result = {};
    }

  };
};

JSONReporter.$inject = ['baseReporterDecorator','config','helper','logger'];

// PUBLISH DI MODULE
module.exports = {
  'reporter:json': ['type', JSONReporter]
};
<|endoftext|>


<commit_before>var fs = require('fs');
var appinfo = require('./package.json');

/**
 * Exported function.
 * @param  {object} Vapor Vapor instance.
 */
module.exports = function(Vapor) {
    var client = Vapor.client;
    var Steam = Vapor.Steam;
    var config = Vapor.config.pluginOptions[appinfo.name];

    var friendsList = {};
    var FRIENDSLIST_PATH = Vapor.api.getPluginFolderPath(appinfo.name) + '/friendslist.json';

    if(config === undefined)
        throw new Error('Missing config options for plugin ' + appinfo.name);

    function loadFriendsList(path) {
        if(fs.existsSync(path))
            return JSON.parse(fs.readFileSync(path));

        return {};
    }

    function saveFriendsList(path, friendsList) {
        fs.writeFileSync(path, JSON.stringify(friendsList));
    }

    function getOldestActive(friendsList) {
        var id;
        var lowest = Number.MAX_VALUE;

        for(var steamID in friendsList) {
            if(friendsList[steamID] < lowest) {
                lowest = friendsList[steamID];
                id = steamID;
            }
        }

        return steamID;
    }

    function addToFriendsList(friendsList, steamID) {
        friendsList[steamID] = getTimeStamp();
    }

    function removeFromFriendsList(friendsList, steamID) {
        delete friendsList[steamID];
    }

    function countFriendsList(friendsList) {
        return Object.keys(friendsList).length;
    }

    function addFriend(client, user, friendsList) {
        if(countFriendsList(friendsList) === config.limit) {
            var friend = getOldestActive(friendsList);
            client.removeFriend(friend);
            removeFromFriendsList(friendsList, friend);
        }

        client.addFriend(user);
        addToFriendsList(friendsList, user);

        if(config.welcomeMessage &&
           typeof config.welcomeMessage == 'string' &&
           config.welcomeMessage !== '') {
            client.sendMessage(user, config.welcomeMessage);
        }
    }

    function getTimeStamp() {
        return Math.floor(new Date() / 1000);
    }

    /**
     * Main entry point
     */
    friendsList = loadFriendsList(FRIENDSLIST_PATH);

    // Handle 'friend' event
    Vapor.api.registerHandler('steam', 'friend', function(user, type) {
        if(type === Steam.EFriendRelationship.RequestRecipient) {
            addFriend(client, user, friendsList);
        } else if(type === Steam.EFriendRelationship.None) {
            removeFromFriendsList(friendsList, user);
        }

        saveFriendsList(FRIENDSLIST_PATH, friendsList);
    });

    // Handle 'relationships' event
    Vapor.api.registerHandler('steam', 'relationships', function() {
        for(var user in client.friends) {
            if(client.friends[user] === Steam.EFriendRelationship.Friend) {
                if(!friendsList.hasOwnProperty(user)) {
                    addToFriendsList(friendsList, user);
                }
            } else if(client.friends[user] === Steam.EFriendRelationship.RequestRecipient) {
                addFriend(client, user, friendsList);
            }
        }

        saveFriendsList(FRIENDSLIST_PATH, friendsList);
    });
};
<commit_msg>Adopted the new API system.<commit_after>var fs = require('fs');
var appinfo = require('./package.json');

/**
 * Exported function.
 * @param  {object} VaporAPI VaporAPI instance.
 */
module.exports = function(VaporAPI) {
    var client = VaporAPI.getClient();
    var Steam = VaporAPI.getSteam();
    var config = VaporAPI.getConfig(appinfo.name);

    var friendsList = {};
    var FRIENDSLIST_PATH = VaporAPI.getPluginFolderPath(appinfo.name) + '/friendslist.json';

    if(config === undefined)
        throw new Error('Missing config options for plugin ' + appinfo.name);

    function loadFriendsList(path) {
        if(fs.existsSync(path))
            return JSON.parse(fs.readFileSync(path));

        return {};
    }

    function saveFriendsList(path, friendsList) {
        fs.writeFileSync(path, JSON.stringify(friendsList));
    }

    function getOldestActive(friendsList) {
        var id;
        var lowest = Number.MAX_VALUE;

        for(var steamID in friendsList) {
            if(friendsList[steamID] < lowest) {
                lowest = friendsList[steamID];
                id = steamID;
            }
        }

        return steamID;
    }

    function addToFriendsList(friendsList, steamID) {
        friendsList[steamID] = getTimeStamp();
    }

    function removeFromFriendsList(friendsList, steamID) {
        delete friendsList[steamID];
    }

    function countFriendsList(friendsList) {
        return Object.keys(friendsList).length;
    }

    function addFriend(client, user, friendsList) {
        if(countFriendsList(friendsList) === config.limit) {
            var friend = getOldestActive(friendsList);
            client.removeFriend(friend);
            removeFromFriendsList(friendsList, friend);
        }

        client.addFriend(user);
        addToFriendsList(friendsList, user);

        if(config.welcomeMessage &&
           typeof config.welcomeMessage == 'string' &&
           config.welcomeMessage !== '') {
            client.sendMessage(user, config.welcomeMessage);
        }
    }

    function getTimeStamp() {
        return Math.floor(new Date() / 1000);
    }

    /**
     * Main entry point
     */
    friendsList = loadFriendsList(FRIENDSLIST_PATH);

    // Handle 'friend' event
    VaporAPI.registerHandler('steam', 'friend', function(user, type) {
        if(type === Steam.EFriendRelationship.RequestRecipient) {
            addFriend(client, user, friendsList);
        } else if(type === Steam.EFriendRelationship.None) {
            removeFromFriendsList(friendsList, user);
        }

        saveFriendsList(FRIENDSLIST_PATH, friendsList);
    });

    // Handle 'relationships' event
    VaporAPI.registerHandler('steam', 'relationships', function() {
        for(var user in client.friends) {
            if(client.friends[user] === Steam.EFriendRelationship.Friend) {
                if(!friendsList.hasOwnProperty(user)) {
                    addToFriendsList(friendsList, user);
                }
            } else if(client.friends[user] === Steam.EFriendRelationship.RequestRecipient) {
                addFriend(client, user, friendsList);
            }
        }

        saveFriendsList(FRIENDSLIST_PATH, friendsList);
    });
};
<|endoftext|>


<commit_before>'use strict';

var contpara  = require('cont').para
var pull      = require('pull-stream')
var pl        = require('pull-level')
var paramap   = require('pull-paramap')
var timestamp = require('monotonic-timestamp')
var assert    = require('assert')
var ltgt      = require('ltgt')
var mlib      = require('ssb-msgs')
var explain   = require('explain-error')
var pdotjson  = require('./package.json')
var createFeed = require('ssb-feed')
var cat       = require('pull-cat')
var ref       = require('ssb-ref')
var ssbKeys   = require('ssb-keys')
var Live      = require('pull-live')
var Notify    = require('pull-notify')
var compare   = require('typewiselite')
var peek      = require('level-peek')
var Validator = require('ssb-feed/validator')

var isFeedId = ref.isFeedId
var isMsgId  = ref.isMsgId
var isBlobId = ref.isBlobId

var u         = require('./util')
var stdopts   = u.options
var msgFmt    = u.format

//53 bit integer
var MAX_INT  = 0x1fffffffffffff

function isNumber (n) {
  return typeof n === 'number'
}

function isString (s) {
  return 'string' === typeof s
}

var isArray = Array.isArray

function isObject (o) {
  return o && 'object' === typeof o && !Array.isArray(o)
}

function all (stream) {
  return function (cb) {
    pull(stream, pull.collect(cb))
  }
}

function getVMajor () {
  var version = require('./package.json').version
  return (version.split('.')[0])|0
}

module.exports = function (db, opts, keys, path) {

  var sysDB   = db.sublevel('sys')
  var logDB   = db.sublevel('log')
  var feedDB  = require('./indexes/feed')(db)
  var clockDB = require('./indexes/clock')(db)
  var lastDB  = require('./indexes/last')(db)
  var indexDB = require('./indexes/links')(db, keys)
  var appsDB  = db.sublevel('app')

  function get (db, key) {
    return function (cb) { db.get(key, cb) }
  }

  db.opts = opts

  db.add = Validator(db)

  var realtime = Notify()

  var await = u.await()
  var set = await.set
  await.set = null
  var waiting = []
  db.seen = await
  db.post(function (op) {
    set(Math.max(op.ts || op.timestamp, await.get()||0))
  })

  peek.last(logDB, {keys: true}, function (err, key) {
    set(Math.max(key || 0, await.get()||0))
  })

  db.pre(function (op, _add, _batch) {
    var msg = op.value
    var id = op.key
    // index by sequence number

    function add (kv) {
      _add(kv);
      kv._value = op.value
      realtime(kv)
    }

    var localtime = op.timestamp = timestamp()

    add({
      key: localtime, value: id,
      type: 'put', prefix: logDB
    })

  })

  db.needsRebuild = function (cb) {
    sysDB.get('vmajor', function (err, dbvmajor) {
      dbvmajor = (dbvmajor|0) || 0
      cb(null, dbvmajor < getVMajor())
    })
  }

  db.rebuildIndex = function (cb) {
    var n = 4, m = 4, ended
    feedDB.rebuild(next)
    clockDB.rebuild(next)
    lastDB.rebuild(next)
    indexDB.rebuild(next)

    function next (err) {
      if(err && !ended) cb(ended = err)
    }

    var m = 4
    feedDB.await(next2)
    clockDB.await(next2)
    lastDB.await(next2)
    indexDB.await(next2)

    function next2 () {
      if(ended) return
      if(--m) return
      ended = true
      sysDB.put('vmajor', getVMajor(), cb)
    }
  }

  function Limit (fn) {
    return function (opts) {
      if(opts && opts.limit && opts.limit > 0) {
        var limit = opts.limit
        var read = fn(opts)
        return function (abort, cb) {
          if(limit--) return read(abort, function (err, data) {
            if(data && data.sync) limit ++
            cb(err, data)
          })
          else read(true, cb)
        }
      }
      else
        return fn(opts)
    }
  }

  //TODO: eventually, this should filter out authors you do not follow.
  db.createFeedStream = Limit(feedDB.createFeedStream)
  //latest was stored as author: seq
  //but for the purposes of replication back pressure
  //we need to know when we last replicated with someone.
  //instead store as: {sequence: seq, ts: localtime}
  //then, peers can request a max number of posts per feed.

  function toSeq (latest) {
    return isNumber(latest) ? latest : latest.sequence
  }

  function lookup(keys, values) {
    return paramap(function (key, cb) {
      if(key.sync) return cb(null, key)
      if(!values) return cb(null, key)
      db.get(key, function (err, msg) {
        if (err) cb(err)
        else {
          cb(null, u.format(keys, values, { key: key, value: msg }))
        }
      })
    })
  }

  db.lookup = lookup

  db.createHistoryStream = Limit(clockDB.createHistoryStream)

  db.createUserStream = Limit(clockDB.createUserStream)

  //writeStream - used in replication.
  db.createWriteStream = function (cb) {
    return pull(
      paramap(function (data, cb) {
        db.add(data, function (err, msg) {
          db.emit('invalid', err, msg)
          cb()
        })
      }),
      pull.drain(null, cb)
    )
  }

  db.createFeed = function (keys) {
    if(!keys)
      keys = opts.keys.generate()
    return createFeed(db, keys, opts)
  }

  db.latest = Limit(lastDB.latest)

  db.latestSequence = function (id, cb) {
    lastDB.get(id, cb)
  }

  db.getLatest = function (id, cb) {
    lastDB.get(id, function (err, v) {
      if(err) return cb()
      //callback null there is no latest
      clockDB.get([id, toSeq(v)], function (err, hash) {
        if(err) return cb()
        db.get(hash, function (err, msg) {
          if(err) cb()
          else cb(null, {key: hash, value: msg})
        })
      })
    })
  }

  db.createLogStream = Limit(Live(function (opts) {
    opts = stdopts(opts)
    var keys = opts.keys; delete opts.keys
    var values = opts.values; delete opts.values
    return pull(
      pl.old(logDB, stdopts(opts)),
      //lookup2(keys, values, 'timestamp')
      paramap(function (data, cb) {
        var key = data.value
        var seq = data.key
        db.get(key, function (err, value) {
          if (err) cb(err)
          else cb(null, msgFmt(keys, values, {key: key, value: value, timestamp: seq}))
        })
      })
    )
  }, function (opts) {
    return pl.live(db, stdopts(opts))
  }))

  var HI = undefined, LO = null

  db.messagesByType = Limit(indexDB.messagesByType)

  db.links = Limit(indexDB.links)

  //get all messages that link to a given message.
  db.relatedMessages = function (opts, cb) {
    if(isString(opts)) opts = {key: opts}
    if(!opts) throw new Error('opts *must* be object')
    var key = opts.id || opts.key
    var depth = opts.depth || Infinity
    var seen = {}

    //filter a list of rel, used to avoid 'branch' rel in patchwork,
    //which causes messages to be queried twice.
    var n = 1
    var msgs = {key: key, value: null}
    db.get(key, function (err, msg) {
      msgs.value = msg
      if (err && err.notFound)
        err = null // ignore not found
      done(err)
    })

    related(msgs, depth)

    function related (msg, depth) {
      if(depth <= 0) return
      if (n<0) return
      n++
      all(db.links({dest: msg.key, rel: opts.rel, keys: true, values:true, meta: false, type:'msg'}))
      (function (err, ary) {
        if(ary && ary.length) {
          msg.related = ary = ary.sort(function (a, b) {
            return compare(a.value.timestamp, b.value.timestamp) || compare(a.key, b.key)
          }).filter(function (msg) {
            if(seen[msg.key]) return
            return seen[msg.key] = true
          })
          ary.forEach(function (msg) { related (msg, depth - 1) })
        }
        done(err)
      })
    }

    function count (msg) {
      if(!msg.related)
        return msg
      var c = 0
      msg.related.forEach(function (_msg) {
        if(opts.parent) _msg.parent = msg.key
        c += 1 + (count(_msg).count || 0)
      })
      if(opts.count) msg.count = c
      return msg
    }

    function done (err) {
      if(err && n > 0) {
        n = -1
        return cb(err)
      }
      if(--n) return
      cb(null, count(msgs))
    }
  }

  var _close = db.close

  db.close = function (cb) {
    var n = 5
    clockDB.close(next)
    feedDB.close(next)
    lastDB.close(next)
    indexDB.close(next)
    _close.call(db, next)
    function next (err) {
      if(n < 0) return
      if(err) return n = -1, cb(err)
      if(--n) return
      db && cb()
    }
  }

  return db
}

<commit_msg>pass options (and thus caps) to ssb-feed<commit_after>'use strict';

var contpara  = require('cont').para
var pull      = require('pull-stream')
var pl        = require('pull-level')
var paramap   = require('pull-paramap')
var timestamp = require('monotonic-timestamp')
var assert    = require('assert')
var ltgt      = require('ltgt')
var mlib      = require('ssb-msgs')
var explain   = require('explain-error')
var pdotjson  = require('./package.json')
var createFeed = require('ssb-feed')
var cat       = require('pull-cat')
var ref       = require('ssb-ref')
var ssbKeys   = require('ssb-keys')
var Live      = require('pull-live')
var Notify    = require('pull-notify')
var compare   = require('typewiselite')
var peek      = require('level-peek')
var Validator = require('ssb-feed/validator')

var isFeedId = ref.isFeedId
var isMsgId  = ref.isMsgId
var isBlobId = ref.isBlobId

var u         = require('./util')
var stdopts   = u.options
var msgFmt    = u.format

//53 bit integer
var MAX_INT  = 0x1fffffffffffff

function isNumber (n) {
  return typeof n === 'number'
}

function isString (s) {
  return 'string' === typeof s
}

var isArray = Array.isArray

function isObject (o) {
  return o && 'object' === typeof o && !Array.isArray(o)
}

function all (stream) {
  return function (cb) {
    pull(stream, pull.collect(cb))
  }
}

function getVMajor () {
  var version = require('./package.json').version
  return (version.split('.')[0])|0
}

module.exports = function (db, opts, keys, path) {
  var sysDB   = db.sublevel('sys')
  var logDB   = db.sublevel('log')
  var feedDB  = require('./indexes/feed')(db)
  var clockDB = require('./indexes/clock')(db)
  var lastDB  = require('./indexes/last')(db)
  var indexDB = require('./indexes/links')(db, keys)
  var appsDB  = db.sublevel('app')

  function get (db, key) {
    return function (cb) { db.get(key, cb) }
  }

  db.opts = opts

  db.add = Validator(db, opts)

  var realtime = Notify()

  var await = u.await()
  var set = await.set
  await.set = null
  var waiting = []
  db.seen = await
  db.post(function (op) {
    set(Math.max(op.ts || op.timestamp, await.get()||0))
  })

  peek.last(logDB, {keys: true}, function (err, key) {
    set(Math.max(key || 0, await.get()||0))
  })

  db.pre(function (op, _add, _batch) {
    var msg = op.value
    var id = op.key
    // index by sequence number

    function add (kv) {
      _add(kv);
      kv._value = op.value
      realtime(kv)
    }

    var localtime = op.timestamp = timestamp()

    add({
      key: localtime, value: id,
      type: 'put', prefix: logDB
    })

  })

  db.needsRebuild = function (cb) {
    sysDB.get('vmajor', function (err, dbvmajor) {
      dbvmajor = (dbvmajor|0) || 0
      cb(null, dbvmajor < getVMajor())
    })
  }

  db.rebuildIndex = function (cb) {
    var n = 4, m = 4, ended
    feedDB.rebuild(next)
    clockDB.rebuild(next)
    lastDB.rebuild(next)
    indexDB.rebuild(next)

    function next (err) {
      if(err && !ended) cb(ended = err)
    }

    var m = 4
    feedDB.await(next2)
    clockDB.await(next2)
    lastDB.await(next2)
    indexDB.await(next2)

    function next2 () {
      if(ended) return
      if(--m) return
      ended = true
      sysDB.put('vmajor', getVMajor(), cb)
    }
  }

  function Limit (fn) {
    return function (opts) {
      if(opts && opts.limit && opts.limit > 0) {
        var limit = opts.limit
        var read = fn(opts)
        return function (abort, cb) {
          if(limit--) return read(abort, function (err, data) {
            if(data && data.sync) limit ++
            cb(err, data)
          })
          else read(true, cb)
        }
      }
      else
        return fn(opts)
    }
  }

  //TODO: eventually, this should filter out authors you do not follow.
  db.createFeedStream = Limit(feedDB.createFeedStream)
  //latest was stored as author: seq
  //but for the purposes of replication back pressure
  //we need to know when we last replicated with someone.
  //instead store as: {sequence: seq, ts: localtime}
  //then, peers can request a max number of posts per feed.

  function toSeq (latest) {
    return isNumber(latest) ? latest : latest.sequence
  }

  function lookup(keys, values) {
    return paramap(function (key, cb) {
      if(key.sync) return cb(null, key)
      if(!values) return cb(null, key)
      db.get(key, function (err, msg) {
        if (err) cb(err)
        else {
          cb(null, u.format(keys, values, { key: key, value: msg }))
        }
      })
    })
  }

  db.lookup = lookup

  db.createHistoryStream = Limit(clockDB.createHistoryStream)

  db.createUserStream = Limit(clockDB.createUserStream)

  //writeStream - used in replication.
  db.createWriteStream = function (cb) {
    return pull(
      paramap(function (data, cb) {
        db.add(data, function (err, msg) {
          if(err)
            db.emit('invalid', err, msg)
          cb()
        })
      }),
      pull.drain(null, cb)
    )
  }

  db.createFeed = function (keys) {
    if(!keys) keys = ssbKeys.generate()
    return createFeed(db, keys, opts)
  }

  db.latest = Limit(lastDB.latest)

  db.latestSequence = function (id, cb) {
    lastDB.get(id, cb)
  }

  db.getLatest = function (id, cb) {
    lastDB.get(id, function (err, v) {
      if(err) return cb()
      //callback null there is no latest
      clockDB.get([id, toSeq(v)], function (err, hash) {
        if(err) return cb()
        db.get(hash, function (err, msg) {
          if(err) cb()
          else cb(null, {key: hash, value: msg})
        })
      })
    })
  }

  db.createLogStream = Limit(Live(function (opts) {
    opts = stdopts(opts)
    var keys = opts.keys; delete opts.keys
    var values = opts.values; delete opts.values
    return pull(
      pl.old(logDB, stdopts(opts)),
      //lookup2(keys, values, 'timestamp')
      paramap(function (data, cb) {
        var key = data.value
        var seq = data.key
        db.get(key, function (err, value) {
          if (err) cb(err)
          else cb(null, msgFmt(keys, values, {key: key, value: value, timestamp: seq}))
        })
      })
    )
  }, function (opts) {
    return pl.live(db, stdopts(opts))
  }))

  var HI = undefined, LO = null

  db.messagesByType = Limit(indexDB.messagesByType)

  db.links = Limit(indexDB.links)

  //get all messages that link to a given message.
  db.relatedMessages = function (opts, cb) {
    if(isString(opts)) opts = {key: opts}
    if(!opts) throw new Error('opts *must* be object')
    var key = opts.id || opts.key
    var depth = opts.depth || Infinity
    var seen = {}

    //filter a list of rel, used to avoid 'branch' rel in patchwork,
    //which causes messages to be queried twice.
    var n = 1
    var msgs = {key: key, value: null}
    db.get(key, function (err, msg) {
      msgs.value = msg
      if (err && err.notFound)
        err = null // ignore not found
      done(err)
    })

    related(msgs, depth)

    function related (msg, depth) {
      if(depth <= 0) return
      if (n<0) return
      n++
      all(db.links({dest: msg.key, rel: opts.rel, keys: true, values:true, meta: false, type:'msg'}))
      (function (err, ary) {
        if(ary && ary.length) {
          msg.related = ary = ary.sort(function (a, b) {
            return compare(a.value.timestamp, b.value.timestamp) || compare(a.key, b.key)
          }).filter(function (msg) {
            if(seen[msg.key]) return
            return seen[msg.key] = true
          })
          ary.forEach(function (msg) { related (msg, depth - 1) })
        }
        done(err)
      })
    }

    function count (msg) {
      if(!msg.related)
        return msg
      var c = 0
      msg.related.forEach(function (_msg) {
        if(opts.parent) _msg.parent = msg.key
        c += 1 + (count(_msg).count || 0)
      })
      if(opts.count) msg.count = c
      return msg
    }

    function done (err) {
      if(err && n > 0) {
        n = -1
        return cb(err)
      }
      if(--n) return
      cb(null, count(msgs))
    }
  }

  var _close = db.close

  db.close = function (cb) {
    var n = 5
    clockDB.close(next)
    feedDB.close(next)
    lastDB.close(next)
    indexDB.close(next)
    _close.call(db, next)
    function next (err) {
      if(n < 0) return
      if(err) return n = -1, cb(err)
      if(--n) return
      db && cb()
    }
  }

  return db
}

<|endoftext|>


<commit_before>'use strict';

var _ = require('underscore');
var mysql = require('mysql');
var path = require('path');
var util = require('util');

var debug = {
	log: require('debug')('express-mysql-session:log'),
	error: require('debug')('express-mysql-session:error')
};

module.exports = function(session) {

	var constructorArgs;

	if (_.isUndefined(session.Store)) {
		session = require('express-session');
		constructorArgs = Array.prototype.slice.call(arguments);
	}

	var Store = session.Store;

	var MySQLStore = function(options, connection, cb) {

		debug.log('Creating session store');

		if (_.isFunction(connection)) {
			cb = connection;
			connection = null;
		}

		this.connection = connection;
		this.setOptions(options);

		if (!this.connection) {
			this.connection = mysql.createPool(this.options);
		}

		var done = function() {

			if (this.options.clearExpired) {
				this.setExpirationInterval();
			}

			if (cb) {
				cb.apply(undefined, arguments);
			}

		}.bind(this);

		if (this.options.createDatabaseTable) {
			this.createDatabaseTable(done);
		} else {
			_.defer(done);
		}
	};

	util.inherits(MySQLStore, Store);

	MySQLStore.prototype.defaultOptions = {
		// Whether or not to automatically check for and clear expired sessions:
		clearExpired: true,
		// How frequently expired sessions will be cleared; milliseconds:
		checkExpirationInterval: 900000,
		// The maximum age of a valid session; milliseconds:
		expiration: 86400000,
		// Whether or not to create the sessions database table, if one does not already exist:
		createDatabaseTable: true,
		// Number of connections when creating a connection pool:
		connectionLimit: 1,
		// Whether or not to end the database connection when the store is closed:
		endConnectionOnClose: true,
		charset: 'utf8mb4_bin',
		schema: {
			tableName: 'sessions',
			columnNames: {
				session_id: 'session_id',
				expires: 'expires',
				data: 'data'
			}
		}
	};

	MySQLStore.prototype.setOptions = function(options) {

		this.options = _.defaults({}, options || {}, {
			// The default value of this option depends on whether or not a connection was passed to the constructor.
			endConnectionOnClose: !this.connection,
		}, this.defaultOptions);

		this.options.schema = _.defaults({}, this.options.schema || {}, this.defaultOptions.schema);
		this.options.schema.columnNames = _.defaults({}, this.options.schema.columnNames || {}, this.defaultOptions.schema.columnNames);
		this.validateOptions(this.options);
	};

	MySQLStore.prototype.validateOptions = function(options) {

		var allowedColumnNames = _.keys(this.defaultOptions.schema.columnNames);
		var userDefinedColumnNames = _.keys(options.schema.columnNames);
		_.each(userDefinedColumnNames, function(userDefinedColumnName) {
			if (!_.contains(allowedColumnNames, userDefinedColumnName)) {
				throw new Error('Unknown column specified ("' + userDefinedColumnName + '"). Only the following columns are configurable: "session_id", "expires", "data". Please review the documentation to understand how to correctly use this option.');
			}
		});
	};

	MySQLStore.prototype.createDatabaseTable = function(cb) {

		debug.log('Creating sessions database table');

		var fs = require('fs');
		var schemaFilePath = path.join(__dirname, 'schema.sql');

		fs.readFile(schemaFilePath, 'utf-8', function(error, sql) {

			if (error) {
				debug.error('Failed to read schema file.');
				return cb && cb(error);
			}

			sql = sql.replace(/`[^`]+`/g, '??');

			var params = [
				this.options.schema.tableName,
				this.options.schema.columnNames.session_id,
				this.options.schema.columnNames.expires,
				this.options.schema.columnNames.data,
				this.options.schema.columnNames.session_id
			];

			this.query(sql, params, function(error) {

				if (error) {
					debug.error('Failed to create sessions database table.');
					debug.error(error);
					return cb && cb(error);
				}

				cb && cb();
			});

		}.bind(this));
	};

	MySQLStore.prototype.get = function(session_id, cb) {

		debug.log('Getting session:', session_id);

		// LIMIT not needed here because the WHERE clause is searching by the table's primary key.
		var sql = 'SELECT ?? AS data FROM ?? WHERE ?? = ?';

		var params = [
			this.options.schema.columnNames.data,
			this.options.schema.tableName,
			this.options.schema.columnNames.session_id,
			session_id
		];

		this.query(sql, params, function(error, rows) {

			if (error) {
				debug.error('Failed to get session:', session_id);
				debug.error(error);
				return cb(error, null);
			}

			try {
				var session = rows[0] ? JSON.parse(rows[0].data) : null;
			} catch (error) {
				debug.error(error);
				return cb(new Error('Failed to parse data for session:', session_id));
			}

			cb(null, session);
		});
	};

	MySQLStore.prototype.set = function(session_id, data, cb) {

		debug.log('Setting session:', session_id);

		var expires;

		if (data.cookie) {
			if (data.cookie.expires) {
				expires = data.cookie.expires;
			} else if (data.cookie._expires) {
				expires = data.cookie._expires;
			}
		}

		if (!expires) {
			expires = Date.now() + this.options.expiration;
		}

		if (!(expires instanceof Date)) {
			expires = new Date(expires);
		}

		// Use whole seconds here; not milliseconds.
		expires = Math.round(expires.getTime() / 1000);

		data = JSON.stringify(data);

		var sql = 'INSERT INTO ?? (??, ??, ??) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE ?? = VALUES(??), ?? = VALUES(??)';

		var params = [
			this.options.schema.tableName,
			this.options.schema.columnNames.session_id,
			this.options.schema.columnNames.expires,
			this.options.schema.columnNames.data,
			session_id,
			expires,
			data,
			this.options.schema.columnNames.expires,
			this.options.schema.columnNames.expires,
			this.options.schema.columnNames.data,
			this.options.schema.columnNames.data
		];

		this.query(sql, params, function(error) {

			if (error) {
				debug.error('Failed to insert session data.');
				debug.error(error);
				return cb && cb(error);
			}

			cb && cb();
		});
	};

	MySQLStore.prototype.touch = function(session_id, data, cb) {

		debug.log('Touching session:', session_id);

		var expires;

		if (data.cookie) {
			if (data.cookie.expires) {
				expires = data.cookie.expires;
			} else if (data.cookie._expires) {
				expires = data.cookie._expires;
			}
		}

		if (!expires) {
			expires = Date.now() + this.options.expiration;
		}

		if (!(expires instanceof Date)) {
			expires = new Date(expires);
		}

		// Use whole seconds here; not milliseconds.
		expires = Math.round(expires.getTime() / 1000);

		// LIMIT not needed here because the WHERE clause is searching by the table's primary key.
		var sql = 'UPDATE ?? SET ?? = ? WHERE ?? = ?';

		var params = [
			this.options.schema.tableName,
			this.options.schema.columnNames.expires,
			expires,
			this.options.schema.columnNames.session_id,
			session_id
		];

		this.query(sql, params, function(error) {

			if (error) {
				debug.error('Failed to touch session:', session_id);
				debug.error(error);
				return cb && cb(error);
			}

			return cb && cb();
		});
	};

	MySQLStore.prototype.destroy = function(session_id, cb) {

		debug.log('Destroying session:', session_id);

		// LIMIT not needed here because the WHERE clause is searching by the table's primary key.
		var sql = 'DELETE FROM ?? WHERE ?? = ?';

		var params = [
			this.options.schema.tableName,
			this.options.schema.columnNames.session_id,
			session_id
		];

		this.query(sql, params, function(error) {

			if (error) {
				debug.error('Failed to destroy session:', session_id);
				debug.error(error);
				return cb && cb(error);
			}

			cb && cb();
		});
	};

	MySQLStore.prototype.length = function(cb) {

		debug.log('Getting number of sessions');

		var sql = 'SELECT COUNT(*) FROM ??';

		var params = [
			this.options.schema.tableName
		];

		this.query(sql, params, function(error, rows) {

			if (error) {
				debug.error('Failed to get number of sessions.');
				debug.error(error);
				return cb && cb(error);
			}

			var count = rows[0] ? rows[0]['COUNT(*)'] : 0;

			cb(null, count);
		});
	};

	MySQLStore.prototype.all = function(cb) {

		debug.log('Getting all sessions');

		var sql = 'SELECT * FROM ??';

		var params = [
			this.options.schema.tableName
		];

		this.query(sql, params, function(error, rows) {

			if (error) {
				debug.error('Failed to get all sessions.');
				debug.error(error);
				return cb && cb(error);
			}

			var sessions = _.chain(rows).map(function(row) {
				try {
					var data = JSON.parse(row.data);
				} catch (error) {
					debug.error('Failed to parse data for session: ' + row.session_id);
					debug.error(error);
					return null;
				}
				return [row.session_id, data];
			}).compact().object().value();

			cb && cb(null, sessions);
		});
	};

	MySQLStore.prototype.clear = function(cb) {

		debug.log('Clearing all sessions');

		var sql = 'DELETE FROM ??';

		var params = [
			this.options.schema.tableName
		];

		this.query(sql, params, function(error) {

			if (error) {
				debug.error('Failed to clear all sessions.');
				debug.error(error);
				return cb && cb(error);
			}

			cb && cb();
		});
	};

	MySQLStore.prototype.clearExpiredSessions = function(cb) {

		debug.log('Clearing expired sessions');

		var sql = 'DELETE FROM ?? WHERE ?? < ?';

		var params = [
			this.options.schema.tableName,
			this.options.schema.columnNames.expires,
			Math.round(Date.now() / 1000)
		];

		this.query(sql, params, function(error) {

			if (error) {
				debug.error('Failed to clear expired sessions.');
				debug.error(error);
				return cb && cb(error);
			}

			cb && cb();
		});
	};

	MySQLStore.prototype.query = function(sql, params, cb) {

		var done = _.once(cb);
		var promise = this.connection.query(sql, params, done);

		if (promise && _.isFunction(promise.then) && _.isFunction(promise.catch)) {
			// Probably a promise.
			promise.then(function(result) {
				var rows = result[0];
				var fields = result[1];
				done(null, rows, fields);
			}).catch(function(error) {
				done(error);
			});
		}
	};

	MySQLStore.prototype.setExpirationInterval = function(interval) {

		interval || (interval = this.options.checkExpirationInterval);

		debug.log('Setting expiration interval to', interval + 'ms');

		this.clearExpirationInterval();
		this._expirationInterval = setInterval(this.clearExpiredSessions.bind(this), interval);
	};

	MySQLStore.prototype.clearExpirationInterval = function() {

		debug.log('Clearing expiration interval');

		clearInterval(this._expirationInterval);
		this._expirationInterval = null;
	};

	MySQLStore.prototype.close = function(cb) {

		debug.log('Closing session store');

		this.clearExpirationInterval();

		if (this.connection && this.options.endConnectionOnClose) {
			this.connection.end(cb);
		} else {
			cb && cb(null);
		}
	};

	if (constructorArgs) {
		// For backwards compatibility.
		// Immediately call as a constructor.
		return new (MySQLStore.bind.apply(MySQLStore, [undefined/* context */].concat(constructorArgs)))();
	}

	return MySQLStore;
};
<commit_msg>Consistent error handling<commit_after>'use strict';

var _ = require('underscore');
var mysql = require('mysql');
var path = require('path');
var util = require('util');

var debug = {
	log: require('debug')('express-mysql-session:log'),
	error: require('debug')('express-mysql-session:error')
};

module.exports = function(session) {

	var constructorArgs;

	if (_.isUndefined(session.Store)) {
		session = require('express-session');
		constructorArgs = Array.prototype.slice.call(arguments);
	}

	var Store = session.Store;

	var MySQLStore = function(options, connection, cb) {

		debug.log('Creating session store');

		if (_.isFunction(connection)) {
			cb = connection;
			connection = null;
		}

		this.connection = connection;
		this.setOptions(options);

		if (!this.connection) {
			this.connection = mysql.createPool(this.options);
		}

		var done = function() {

			if (this.options.clearExpired) {
				this.setExpirationInterval();
			}

			if (cb) {
				cb.apply(undefined, arguments);
			}

		}.bind(this);

		if (this.options.createDatabaseTable) {
			this.createDatabaseTable(done);
		} else {
			_.defer(done);
		}
	};

	util.inherits(MySQLStore, Store);

	MySQLStore.prototype.defaultOptions = {
		// Whether or not to automatically check for and clear expired sessions:
		clearExpired: true,
		// How frequently expired sessions will be cleared; milliseconds:
		checkExpirationInterval: 900000,
		// The maximum age of a valid session; milliseconds:
		expiration: 86400000,
		// Whether or not to create the sessions database table, if one does not already exist:
		createDatabaseTable: true,
		// Number of connections when creating a connection pool:
		connectionLimit: 1,
		// Whether or not to end the database connection when the store is closed:
		endConnectionOnClose: true,
		charset: 'utf8mb4_bin',
		schema: {
			tableName: 'sessions',
			columnNames: {
				session_id: 'session_id',
				expires: 'expires',
				data: 'data'
			}
		}
	};

	MySQLStore.prototype.setOptions = function(options) {

		this.options = _.defaults({}, options || {}, {
			// The default value of this option depends on whether or not a connection was passed to the constructor.
			endConnectionOnClose: !this.connection,
		}, this.defaultOptions);

		this.options.schema = _.defaults({}, this.options.schema || {}, this.defaultOptions.schema);
		this.options.schema.columnNames = _.defaults({}, this.options.schema.columnNames || {}, this.defaultOptions.schema.columnNames);
		this.validateOptions(this.options);
	};

	MySQLStore.prototype.validateOptions = function(options) {

		var allowedColumnNames = _.keys(this.defaultOptions.schema.columnNames);
		var userDefinedColumnNames = _.keys(options.schema.columnNames);
		_.each(userDefinedColumnNames, function(userDefinedColumnName) {
			if (!_.contains(allowedColumnNames, userDefinedColumnName)) {
				throw new Error('Unknown column specified ("' + userDefinedColumnName + '"). Only the following columns are configurable: "session_id", "expires", "data". Please review the documentation to understand how to correctly use this option.');
			}
		});
	};

	MySQLStore.prototype.createDatabaseTable = function(cb) {

		debug.log('Creating sessions database table');

		var fs = require('fs');
		var schemaFilePath = path.join(__dirname, 'schema.sql');

		fs.readFile(schemaFilePath, 'utf-8', function(error, sql) {

			if (error) {
				debug.error('Failed to read schema file.');
				debug.error(error);
				return cb && cb(error);
			}

			sql = sql.replace(/`[^`]+`/g, '??');

			var params = [
				this.options.schema.tableName,
				this.options.schema.columnNames.session_id,
				this.options.schema.columnNames.expires,
				this.options.schema.columnNames.data,
				this.options.schema.columnNames.session_id
			];

			this.query(sql, params, function(error) {

				if (error) {
					debug.error('Failed to create sessions database table.');
					debug.error(error);
					return cb && cb(error);
				}

				cb && cb();
			});

		}.bind(this));
	};

	MySQLStore.prototype.get = function(session_id, cb) {

		debug.log('Getting session:', session_id);

		// LIMIT not needed here because the WHERE clause is searching by the table's primary key.
		var sql = 'SELECT ?? AS data FROM ?? WHERE ?? = ?';

		var params = [
			this.options.schema.columnNames.data,
			this.options.schema.tableName,
			this.options.schema.columnNames.session_id,
			session_id
		];

		this.query(sql, params, function(error, rows) {

			if (error) {
				debug.error('Failed to get session:', session_id);
				debug.error(error);
				return cb(error, null);
			}

			try {
				var session = rows[0] ? JSON.parse(rows[0].data) : null;
			} catch (error) {
				debug.error('Failed to parse data for session (' + session_id + ')');
				debug.error(error);
				return cb(error);
			}

			cb(null, session);
		});
	};

	MySQLStore.prototype.set = function(session_id, data, cb) {

		debug.log('Setting session:', session_id);

		var expires;

		if (data.cookie) {
			if (data.cookie.expires) {
				expires = data.cookie.expires;
			} else if (data.cookie._expires) {
				expires = data.cookie._expires;
			}
		}

		if (!expires) {
			expires = Date.now() + this.options.expiration;
		}

		if (!(expires instanceof Date)) {
			expires = new Date(expires);
		}

		// Use whole seconds here; not milliseconds.
		expires = Math.round(expires.getTime() / 1000);

		data = JSON.stringify(data);

		var sql = 'INSERT INTO ?? (??, ??, ??) VALUES (?, ?, ?) ON DUPLICATE KEY UPDATE ?? = VALUES(??), ?? = VALUES(??)';

		var params = [
			this.options.schema.tableName,
			this.options.schema.columnNames.session_id,
			this.options.schema.columnNames.expires,
			this.options.schema.columnNames.data,
			session_id,
			expires,
			data,
			this.options.schema.columnNames.expires,
			this.options.schema.columnNames.expires,
			this.options.schema.columnNames.data,
			this.options.schema.columnNames.data
		];

		this.query(sql, params, function(error) {

			if (error) {
				debug.error('Failed to insert session data.');
				debug.error(error);
				return cb && cb(error);
			}

			cb && cb();
		});
	};

	MySQLStore.prototype.touch = function(session_id, data, cb) {

		debug.log('Touching session:', session_id);

		var expires;

		if (data.cookie) {
			if (data.cookie.expires) {
				expires = data.cookie.expires;
			} else if (data.cookie._expires) {
				expires = data.cookie._expires;
			}
		}

		if (!expires) {
			expires = Date.now() + this.options.expiration;
		}

		if (!(expires instanceof Date)) {
			expires = new Date(expires);
		}

		// Use whole seconds here; not milliseconds.
		expires = Math.round(expires.getTime() / 1000);

		// LIMIT not needed here because the WHERE clause is searching by the table's primary key.
		var sql = 'UPDATE ?? SET ?? = ? WHERE ?? = ?';

		var params = [
			this.options.schema.tableName,
			this.options.schema.columnNames.expires,
			expires,
			this.options.schema.columnNames.session_id,
			session_id
		];

		this.query(sql, params, function(error) {

			if (error) {
				debug.error('Failed to touch session (' + session_id + ')');
				debug.error(error);
				return cb && cb(error);
			}

			return cb && cb();
		});
	};

	MySQLStore.prototype.destroy = function(session_id, cb) {

		debug.log('Destroying session:', session_id);

		// LIMIT not needed here because the WHERE clause is searching by the table's primary key.
		var sql = 'DELETE FROM ?? WHERE ?? = ?';

		var params = [
			this.options.schema.tableName,
			this.options.schema.columnNames.session_id,
			session_id
		];

		this.query(sql, params, function(error) {

			if (error) {
				debug.error('Failed to destroy session (' + session_id + ')');
				debug.error(error);
				return cb && cb(error);
			}

			cb && cb();
		});
	};

	MySQLStore.prototype.length = function(cb) {

		debug.log('Getting number of sessions');

		var sql = 'SELECT COUNT(*) FROM ??';

		var params = [
			this.options.schema.tableName
		];

		this.query(sql, params, function(error, rows) {

			if (error) {
				debug.error('Failed to get number of sessions.');
				debug.error(error);
				return cb && cb(error);
			}

			var count = rows[0] ? rows[0]['COUNT(*)'] : 0;

			cb(null, count);
		});
	};

	MySQLStore.prototype.all = function(cb) {

		debug.log('Getting all sessions');

		var sql = 'SELECT * FROM ??';

		var params = [
			this.options.schema.tableName
		];

		this.query(sql, params, function(error, rows) {

			if (error) {
				debug.error('Failed to get all sessions.');
				debug.error(error);
				return cb && cb(error);
			}

			var sessions = _.chain(rows).map(function(row) {
				try {
					var data = JSON.parse(row.data);
				} catch (error) {
					debug.error('Failed to parse data for session (' + row.session_id + ')');
					debug.error(error);
					return null;
				}
				return [row.session_id, data];
			}).compact().object().value();

			cb && cb(null, sessions);
		});
	};

	MySQLStore.prototype.clear = function(cb) {

		debug.log('Clearing all sessions');

		var sql = 'DELETE FROM ??';

		var params = [
			this.options.schema.tableName
		];

		this.query(sql, params, function(error) {

			if (error) {
				debug.error('Failed to clear all sessions.');
				debug.error(error);
				return cb && cb(error);
			}

			cb && cb();
		});
	};

	MySQLStore.prototype.clearExpiredSessions = function(cb) {

		debug.log('Clearing expired sessions');

		var sql = 'DELETE FROM ?? WHERE ?? < ?';

		var params = [
			this.options.schema.tableName,
			this.options.schema.columnNames.expires,
			Math.round(Date.now() / 1000)
		];

		this.query(sql, params, function(error) {

			if (error) {
				debug.error('Failed to clear expired sessions.');
				debug.error(error);
				return cb && cb(error);
			}

			cb && cb();
		});
	};

	MySQLStore.prototype.query = function(sql, params, cb) {

		var done = _.once(cb);
		var promise = this.connection.query(sql, params, done);

		if (promise && _.isFunction(promise.then) && _.isFunction(promise.catch)) {
			// Probably a promise.
			promise.then(function(result) {
				var rows = result[0];
				var fields = result[1];
				done(null, rows, fields);
			}).catch(function(error) {
				done(error);
			});
		}
	};

	MySQLStore.prototype.setExpirationInterval = function(interval) {

		interval || (interval = this.options.checkExpirationInterval);

		debug.log('Setting expiration interval to', interval + 'ms');

		this.clearExpirationInterval();
		this._expirationInterval = setInterval(this.clearExpiredSessions.bind(this), interval);
	};

	MySQLStore.prototype.clearExpirationInterval = function() {

		debug.log('Clearing expiration interval');

		clearInterval(this._expirationInterval);
		this._expirationInterval = null;
	};

	MySQLStore.prototype.close = function(cb) {

		debug.log('Closing session store');

		this.clearExpirationInterval();

		if (this.connection && this.options.endConnectionOnClose) {
			this.connection.end(cb);
		} else {
			cb && cb(null);
		}
	};

	if (constructorArgs) {
		// For backwards compatibility.
		// Immediately call as a constructor.
		return new (MySQLStore.bind.apply(MySQLStore, [undefined/* context */].concat(constructorArgs)))();
	}

	return MySQLStore;
};
<|endoftext|>


<commit_before>'use strict'

const express = require('express')
const bodyParser = require('body-parser')
const request = require('request')
const app = express()

app.set('port', (process.env.PORT || 5000))

// Process application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({extended: false}))

// Process application/json
app.use(bodyParser.json())

// Index route
app.get('/', function (req, res) {
    res.send('loblaws-webhook')
})

// for Facebook verification
app.get('/webhook/', function (req, res) {
    if (req.query['hub.verify_token'] === 'loblaws-webhook') {
        res.send(req.query['hub.challenge'])
    }
    res.send('Error, wrong token')
})

// Spin up the server
app.listen(app.get('port'), function() {
    console.log('running on port', app.get('port'))
})

app.post('/webhook', function (req, res) {
    var events = req.body.entry[0].messaging;
    for (i = 0; i < events.length; i++) {
        var event = events[i];
        if (event.message && event.message.text) {
            sendMessage(event.sender.id, {text: "Echo: " + event.message.text});
        }
        sendMessage(event.sender.id, {text: "Response"});
    }
    res.sendStatus(200);
});

function sendMessage(recipientId, message) {
    request({
        url: 'https://graph.facebook.com/v2.6/me/messages',
        qs: {access_token: process.env.PAGE_ACCESS_TOKEN},
        method: 'POST',
        json: {
            recipient: {id: recipientId},
            message: message,
        }
    }, function(error, response, body) {
        if (error) {
            console.log('Error sending message: ', error);
        } else if (response.body.error) {
            console.log('Error: ', response.body.error);
        }
    });
};<commit_msg>Messenger echo<commit_after>'use strict'

const express = require('express')
const bodyParser = require('body-parser')
const request = require('request')
const app = express()

app.set('port', (process.env.PORT || 5000))

// Process application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({extended: false}))

// Process application/json
app.use(bodyParser.json())

// Index route
app.get('/', function (req, res) {
    res.send('loblaws-webhook')
})

// for Facebook verification
app.get('/webhook', function (req, res) {
    if (req.query['hub.verify_token'] === 'loblaws-webhook') {
        res.send(req.query['hub.challenge']);
    } else {
        res.send('Invalid verify token');
    }
});

// Spin up the server
app.listen(app.get('port'), function() {
    console.log('running on port', app.get('port'))
})

app.post('/webhook', function (req, res) {
    var events = req.body.entry[0].messaging;
    for (i = 0; i < events.length; i++) {
        var event = events[i];
        if (event.message && event.message.text) {
            sendMessage(event.sender.id, {text: "Echo: " + event.message.text});
        }
        sendMessage(event.sender.id, {text: "Response"});
    }
    res.sendStatus(200);
});

function sendMessage(recipientId, message) {
    request({
        url: 'https://graph.facebook.com/v2.6/me/messages',
        qs: {access_token: process.env.PAGE_ACCESS_TOKEN},
        method: 'POST',
        json: {
            recipient: {id: recipientId},
            message: message,
        }
    }, function(error, response, body) {
        if (error) {
            console.log('Error sending message: ', error);
        } else if (response.body.error) {
            console.log('Error: ', response.body.error);
        }
    });
};<|endoftext|>


<commit_before>import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { ActivityIndicator, Image, StyleSheet, View } from 'react-native';

const styles = StyleSheet.create({
  centered: {
    ...StyleSheet.absoluteFillObject,
    alignItems: 'center',
    justifyContent: 'center',
  },
});

const DefaultIndicator = ActivityIndicator;

const getSourceKey = source => (source && source.uri) || String(source);

export const createImageProgress = ImageComponent =>
  class ImageProgress extends Component {
    static propTypes = {
      children: PropTypes.node,
      errorContainerStyle: PropTypes.any,
      indicator: PropTypes.func,
      indicatorContainerStyle: PropTypes.any,
      indicatorProps: PropTypes.object,
      renderIndicator: PropTypes.func,
      renderError: PropTypes.func,
      source: PropTypes.any,
      style: PropTypes.any,
      imageStyle: PropTypes.object,
      threshold: PropTypes.number,
    };

    static defaultProps = {
      indicatorContainerStyle: styles.centered,
      errorContainerStyle: styles.centered,
      threshold: 50,
    };

    static prefetch = Image.prefetch;
    static getSize = Image.getSize;

    static getDerivedStateFromProps(props, state) {
      const sourceKey = getSourceKey(props.source);
      if (sourceKey !== state.sourceKey) {
        return {
          sourceKey,
          error: null,
          loading: false,
          progress: 0,
        };
      }
      return null;
    }

    constructor(props) {
      super(props);

      this.state = {
        sourceKey: getSourceKey(props.source),
        error: null,
        loading: false,
        progress: 0,
        thresholdReached: !props.threshold,
      };
    }

    componentDidMount() {
      if (this.props.threshold) {
        this.thresholdTimer = setTimeout(() => {
          this.setState({ thresholdReached: true });
          this.thresholdTimer = null;
        }, this.props.threshold);
      }
    }

    componentWillUnmount() {
      if (this.thresholdTimer) {
        clearTimeout(this.thresholdTimer);
      }
    }

    setNativeProps(nativeProps) {
      if (this.ref) {
        this.ref.setNativeProps(nativeProps);
      }
    }

    measure(cb) {
      if (this.ref) {
        this.ref.measure(cb);
      }
    }

    ref = null;
    handleRef = ref => {
      this.ref = ref;
    };

    bubbleEvent(propertyName, event) {
      if (typeof this.props[propertyName] === 'function') {
        this.props[propertyName](event);
      }
    }

    handleLoadStart = () => {
      if (!this.state.loading && this.state.progress !== 1) {
        this.setState({
          error: null,
          loading: true,
          progress: 0,
        });
      }
      this.bubbleEvent('onLoadStart');
    };

    handleProgress = event => {
      const progress = event.nativeEvent.loaded / event.nativeEvent.total;
      // RN is a bit buggy with these events, sometimes a loaded event and then a few
      // 100% progress – sometimes in an infinite loop. So we just assume 100% progress
      // actually means the image is no longer loading
      if (progress !== this.state.progress && this.state.progress !== 1) {
        this.setState({
          loading: progress < 1,
          progress,
        });
      }
      this.bubbleEvent('onProgress', event);
    };

    handleError = event => {
      this.setState({
        loading: false,
        error: event.nativeEvent,
      });
      this.bubbleEvent('onError', event);
    };

    handleLoad = event => {
      if (this.state.progress !== 1) {
        this.setState({
          error: null,
          loading: false,
          progress: 1,
        });
      }
      this.bubbleEvent('onLoad', event);
    };

    handleLoadEnd = event => {
      this.setState({
        loading: false,
        progress: 1,
      });
      this.bubbleEvent('onLoadEnd', event);
    };

    render() {
      const {
        children,
        errorContainerStyle,
        indicator,
        indicatorContainerStyle,
        indicatorProps,
        renderError,
        renderIndicator,
        source,
        style,
        threshold,
        imageStyle,
        ...props
      } = this.props;

      if (!source || !source.uri) {
        // This is not a networked asset so fallback to regular image
        return (
          <View style={style} ref={this.handleRef}>
            <ImageComponent
              {...props}
              source={source}
              style={[StyleSheet.absoluteFill, imageStyle]}
            />
            {children}
          </View>
        );
      }
      const {
        progress,
        sourceKey,
        thresholdReached,
        loading,
        error,
      } = this.state;

      let indicatorElement;

      if (error) {
        if (renderError) {
          indicatorElement = (
            <View style={errorContainerStyle}>{renderError(error)}</View>
          );
        }
      } else if ((loading || progress < 1) && thresholdReached) {
        if (renderIndicator) {
          indicatorElement = renderIndicator(progress, !loading || !progress);
        } else {
          const IndicatorComponent =
            typeof indicator === 'function' ? indicator : DefaultIndicator;
          indicatorElement = (
            <IndicatorComponent
              progress={progress}
              indeterminate={!loading || !progress}
              {...indicatorProps}
            />
          );
        }
        indicatorElement = (
          <View style={indicatorContainerStyle}>{indicatorElement}</View>
        );
      }

      return (
        <View style={style} ref={this.handleRef}>
          <ImageComponent
            {...props}
            key={sourceKey}
            onLoadStart={this.handleLoadStart}
            onProgress={this.handleProgress}
            onError={this.handleError}
            onLoad={this.handleLoad}
            onLoadEnd={this.handleLoadEnd}
            source={source}
            style={[StyleSheet.absoluteFill, imageStyle]}
          />
          {indicatorElement}
          {children}
        </View>
      );
    }
  };

export default createImageProgress(Image);
<commit_msg>Fix imageStyle prop type #79<commit_after>import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { ActivityIndicator, Image, StyleSheet, View } from 'react-native';

const styles = StyleSheet.create({
  centered: {
    ...StyleSheet.absoluteFillObject,
    alignItems: 'center',
    justifyContent: 'center',
  },
});

const DefaultIndicator = ActivityIndicator;

const getSourceKey = source => (source && source.uri) || String(source);

export const createImageProgress = ImageComponent =>
  class ImageProgress extends Component {
    static propTypes = {
      children: PropTypes.node,
      errorContainerStyle: PropTypes.any,
      indicator: PropTypes.func,
      indicatorContainerStyle: PropTypes.any,
      indicatorProps: PropTypes.object,
      renderIndicator: PropTypes.func,
      renderError: PropTypes.func,
      source: PropTypes.any,
      style: PropTypes.any,
      imageStyle: PropTypes.any,
      threshold: PropTypes.number,
    };

    static defaultProps = {
      indicatorContainerStyle: styles.centered,
      errorContainerStyle: styles.centered,
      threshold: 50,
    };

    static prefetch = Image.prefetch;
    static getSize = Image.getSize;

    static getDerivedStateFromProps(props, state) {
      const sourceKey = getSourceKey(props.source);
      if (sourceKey !== state.sourceKey) {
        return {
          sourceKey,
          error: null,
          loading: false,
          progress: 0,
        };
      }
      return null;
    }

    constructor(props) {
      super(props);

      this.state = {
        sourceKey: getSourceKey(props.source),
        error: null,
        loading: false,
        progress: 0,
        thresholdReached: !props.threshold,
      };
    }

    componentDidMount() {
      if (this.props.threshold) {
        this.thresholdTimer = setTimeout(() => {
          this.setState({ thresholdReached: true });
          this.thresholdTimer = null;
        }, this.props.threshold);
      }
    }

    componentWillUnmount() {
      if (this.thresholdTimer) {
        clearTimeout(this.thresholdTimer);
      }
    }

    setNativeProps(nativeProps) {
      if (this.ref) {
        this.ref.setNativeProps(nativeProps);
      }
    }

    measure(cb) {
      if (this.ref) {
        this.ref.measure(cb);
      }
    }

    ref = null;
    handleRef = ref => {
      this.ref = ref;
    };

    bubbleEvent(propertyName, event) {
      if (typeof this.props[propertyName] === 'function') {
        this.props[propertyName](event);
      }
    }

    handleLoadStart = () => {
      if (!this.state.loading && this.state.progress !== 1) {
        this.setState({
          error: null,
          loading: true,
          progress: 0,
        });
      }
      this.bubbleEvent('onLoadStart');
    };

    handleProgress = event => {
      const progress = event.nativeEvent.loaded / event.nativeEvent.total;
      // RN is a bit buggy with these events, sometimes a loaded event and then a few
      // 100% progress – sometimes in an infinite loop. So we just assume 100% progress
      // actually means the image is no longer loading
      if (progress !== this.state.progress && this.state.progress !== 1) {
        this.setState({
          loading: progress < 1,
          progress,
        });
      }
      this.bubbleEvent('onProgress', event);
    };

    handleError = event => {
      this.setState({
        loading: false,
        error: event.nativeEvent,
      });
      this.bubbleEvent('onError', event);
    };

    handleLoad = event => {
      if (this.state.progress !== 1) {
        this.setState({
          error: null,
          loading: false,
          progress: 1,
        });
      }
      this.bubbleEvent('onLoad', event);
    };

    handleLoadEnd = event => {
      this.setState({
        loading: false,
        progress: 1,
      });
      this.bubbleEvent('onLoadEnd', event);
    };

    render() {
      const {
        children,
        errorContainerStyle,
        indicator,
        indicatorContainerStyle,
        indicatorProps,
        renderError,
        renderIndicator,
        source,
        style,
        threshold,
        imageStyle,
        ...props
      } = this.props;

      if (!source || !source.uri) {
        // This is not a networked asset so fallback to regular image
        return (
          <View style={style} ref={this.handleRef}>
            <ImageComponent
              {...props}
              source={source}
              style={[StyleSheet.absoluteFill, imageStyle]}
            />
            {children}
          </View>
        );
      }
      const {
        progress,
        sourceKey,
        thresholdReached,
        loading,
        error,
      } = this.state;

      let indicatorElement;

      if (error) {
        if (renderError) {
          indicatorElement = (
            <View style={errorContainerStyle}>{renderError(error)}</View>
          );
        }
      } else if ((loading || progress < 1) && thresholdReached) {
        if (renderIndicator) {
          indicatorElement = renderIndicator(progress, !loading || !progress);
        } else {
          const IndicatorComponent =
            typeof indicator === 'function' ? indicator : DefaultIndicator;
          indicatorElement = (
            <IndicatorComponent
              progress={progress}
              indeterminate={!loading || !progress}
              {...indicatorProps}
            />
          );
        }
        indicatorElement = (
          <View style={indicatorContainerStyle}>{indicatorElement}</View>
        );
      }

      return (
        <View style={style} ref={this.handleRef}>
          <ImageComponent
            {...props}
            key={sourceKey}
            onLoadStart={this.handleLoadStart}
            onProgress={this.handleProgress}
            onError={this.handleError}
            onLoad={this.handleLoad}
            onLoadEnd={this.handleLoadEnd}
            source={source}
            style={[StyleSheet.absoluteFill, imageStyle]}
          />
          {indicatorElement}
          {children}
        </View>
      );
    }
  };

export default createImageProgress(Image);
<|endoftext|>


<commit_before>var http = require('http');

http.createServer(function(req, res) {
  res.writeHead(200, {'Content-Type' : 'text/plain'});
  res.end('OK\n');
}).listen(80, '127.0.0.1');
<commit_msg>Taking port from env<commit_after>var http = require('http');

var port = process.env.PORT || 3000;

http.createServer(function(req, res) {
  res.writeHead(200, {'Content-Type' : 'text/plain'});
  res.end('OK\n');
}).listen(port, '127.0.0.1');
<|endoftext|>


<commit_before>/**
 * Module dependencies.
 */

var Meta = require('./lib/meta');
var Wrap = require('super-wrap');

/**
 * Module exports
 */

exports = module.exports = Mixin;

/**
 * Expose `Meta`
 */

exports.Meta = Meta;

/**
 * Create
 */

exports.create = function() {
  var C = new Mixin();
  C.addMixins(Array.prototype.slice.call(arguments));
  return C;
};

/**
 * Mixin constructor
 */

function Mixin() {
  this.mixins = [];
}

/**
 * AddMixins
 */

Mixin.prototype.addMixins = function(mixins) {
  for (var i = 0; i < mixins.length; i++) {
    this.mixins.push(mixins[i]);
  }
};

/**
 * Reopen
 */

Mixin.prototype.reopen = function() {
  this.addMixins(Array.prototype.slice.call(arguments));
  return this;
};

/**
 * Apply
 */

Mixin.prototype.apply = function(obj) {
  if ('object' === typeof obj && !(obj instanceof Array)) {
    return this.applyObject(obj);
  }

  throw new Error("Argument passed to Mixin.apply has to be a mixin instance or an object.");
};

/**
 * Searching
 */

function findNextParent(obj, callback) {

  function nextParent(object) {
    if (object.parent) {
      var ret = callback(object);
      if (ret) {
        return nextParent(object.parent);
      }
    }
  }

  return nextParent(obj);
}

function findChild(obj) {
  if (obj.child) {
    return findChild(obj.child);
  }
  return obj;
}

/**
 * ApplyObject
 */

Mixin.prototype.applyObject = function(object) {
  var source = this;
  var target = object;
  var fns = {};

  for (var i = 0; i < this.mixins.length; i++) {
    var mixin = this.mixins[i];
    for (var key in mixin) {
      var val = mixin[key];
      if ('function' === typeof val) {
        if (!fns[key]) {
          fns[key] = {
            val: val,
            child: null,
            parent: null
          };
        } else {
          var obj = findChild(fns[key]);
          obj.child = {
            val: val,
            child: null,
            parent: obj
          };
        }
      } else {
        target[key] = val;
      }
    }
  }

  this.handleFunctions(fns, target);

  return target;
};

/**
 * HandleFunctions
 *
 * This will setup the _super chain. The smallest indexes will be the latest
 * Mixins. Thus, the smaller indexes will be the children.
 */

Mixin.prototype.handleFunctions = function(fns, target) {

  for (var key in fns) {
    var parent = fns[key];
    var child = findChild(parent);

    function next(object, parent) {
      object.val = Wrap(object.val, parent && parent.val);

      if (object.child) {
        return next(object.child, object);
      }
    }

    next(parent);
    target[key] = child.val;
  }

};<commit_msg>tests pass<commit_after>/**
 * Module dependencies.
 */

var Meta = require('./lib/meta');
var Wrap = require('super-wrap');

/**
 * Module exports
 */

exports = module.exports = Mixin;

/**
 * Expose `Meta`
 */

exports.Meta = Meta;

/**
 * Create
 */

exports.create = function() {
  var C = new Mixin();
  C.initMixin(Array.prototype.slice.call(arguments));
  return C;
};

/**
 * Mixin Class.
 *
 * Each mixin will hold it's mixins, and it's properties.
 *
 */

function Mixin() {
  this.mixins = [];
  this.properties = {};
}

/**
 * Init Mixins
 */

Mixin.prototype.initMixin = function(args) {

  for (var i = 0; i < args.length; i++) {
    var arg = args[i];

    if (arg instanceof Mixin) {
      this.mixins.push(arg);
      continue;
    }

    var mixin = new Mixin();
    mixin.properties = arg;
    this.mixins.push(mixin);
  }

  return this;
};

/**
 * toString
 */

Mixin.toString = function() {
  return '<Mixin>';
}

/**
 * AddMixins
 */

Mixin.prototype.addMixins = function(mixins) {
  for (var i = 0; i < mixins.length; i++) {
    var mixin = mixins[i];
    if (mixin instanceof Mixin) {
      this.mixins.push(mixin);
    } else if ('object' === typeof mixin && !(mixin instanceof Array)) {
      var M = new Mixin();
      M.properties = mixin;
      this.mixins.push(M);
    }
  }
};

/**
 * Reopen
 */

Mixin.prototype.reopen = function() {
  this.addMixins(Array.prototype.slice.call(arguments));
  return this;
};

/**
 * Apply
 */

Mixin.prototype.apply = function(obj) {
  if (('object' === typeof obj || 'function' === typeof obj) && !(obj instanceof Array)) {
    return this.applyObject(obj);
  }

  throw new Error("Argument passed to Mixin.apply has to be a mixin instance or an object.");
};

/**
 * Expose `apply`
 */

exports.apply = Mixin.prototype.apply;

/**
 * Expose `reopen`
 */

exports.reopen = Mixin.prototype.reopen;

/**
 * findNextParent
 */

function findNextParent(obj, callback) {

  function nextParent(object) {
    if (object.parent) {
      var ret = callback(object);
      if (ret) {
        return nextParent(object.parent);
      }
    }
  }

  return nextParent(obj);
}

/**
 * findChild
 */

function findChild(obj) {
  if (obj.child) {
    return findChild(obj.child);
  }
  return obj;
}

/**
 * ApplyObject
 */

Mixin.prototype.applyObject = function(object) {
  var target = object;
  var fns = {};
  var values = {};

  for (var i = 0; i < this.mixins.length; i++) {
    var mixin = this.mixins[i];
    var props = mixin.properties;

    for (var key in props) {
      var val = props[key];

      if ('function' === typeof val) {

        if (values[key]) {
          // The object already has the key. We'll need to setup a
          // prototype around it.
          var parent = values[key];
          values[key] = Wrap(val, parent);

        } else {
          // If the target (base class/object) doesn't have the key
          // then we'll just take it.
          values[key] = val;
        }

      } else {
        values[key] = val;
      }

    }

  }

  for (var key in values) {
    var val = values[key];
    if (target[key] && 'function' === typeof target[key]
        && 'function' === typeof val) {
      target[key] = Wrap(target[key], val);
    } else {
      target[key] = val;
    }
  }

  return target;
};

/**
 * HandleFunctions
 *
 * This will setup the _super chain. The smallest indexes will be the latest
 * Mixins. Thus, the smaller indexes will be the children.
 */

Mixin.prototype.handleFunctions = function(fns, target) {

  for (var key in fns) {
    var parent = fns[key];
    var child = findChild(parent);

    function next(object, parent) {
      object.val = Wrap(object.val, parent && parent.val);

      if (object.child) {
        return next(object.child, object);
      }
    }

    next(parent);
    target[key] = child.val;
  }

};<|endoftext|>


<commit_before>var strftime = require('prettydate').strftime;

module.exports = function generateCommonLog(request, response)
{
    var protocol = 'HTTP/' + request.httpVersion;
    var payload_len = response._data ? response._data.length : '-';
    var UA = request.headers['user-agent'] || '-';
    var referer = request.headers['referer'] || '-';
    var tstamp = response._time ? new Date(response._time) : new Date();
    var remote = (request.socket ? request.socket.remoteAddress : '') || '';
    var accepts = request.headers['accept'] || '-';
    var elapsed = response._time ? (Date.now() - response._time) + ' ms' : '';

    var fields = [
        remote.replace('::ffff:', ''), // client ip
        '-',  // RFC 1413, never used
        '-',   // userid as determined by http auth
        '[' + strftime(tstamp, '%d/%b/%Y:%H:%M:%S %z') + ']', // time
        '"' + [request.method, request.url, protocol].join(' ') + '"',
        response.statusCode,
        payload_len,
        '"' + referer + '"',
        '"' + UA + '"',
        '"' + accepts + '"',
        elapsed,
    ];

    return fields.join(' ');
};
<commit_msg>adds options object for configuring ipHeader<commit_after>var strftime = require('prettydate').strftime;

module.exports = function generateCommonLog(request, response, options)
{
    var protocol = 'HTTP/' + request.httpVersion;
    var payload_len = response._data ? response._data.length : '-';
    var UA = request.headers['user-agent'] || '-';
    var referer = request.headers['referer'] || '-';
    var tstamp = response._time ? new Date(response._time) : new Date();
    var remote = (options && options.ipHeader ? request.headers[options.ipHeader] : '') ||
                 (request.socket ? request.socket.remoteAddress : '') || '';
    var accepts = request.headers['accept'] || '-';
    var elapsed = response._time ? (Date.now() - response._time) + ' ms' : '';

    var fields = [
        remote.replace('::ffff:', ''), // client ip
        '-',  // RFC 1413, never used
        '-',   // userid as determined by http auth
        '[' + strftime(tstamp, '%d/%b/%Y:%H:%M:%S %z') + ']', // time
        '"' + [request.method, request.url, protocol].join(' ') + '"',
        response.statusCode,
        payload_len,
        '"' + referer + '"',
        '"' + UA + '"',
        '"' + accepts + '"',
        elapsed,
    ];

    return fields.join(' ');
};<|endoftext|>


<commit_before>'use strict'

/**
 * un-escape special characters in the given string of html.
 *
 * @param  {String} html
 * @return {String}
 */

module.exports = function (html) {
  return String(html)
    .replace(/"/g, '"')
    .replace(/'/g, '\'')
    .replace(/</g, '<')
    .replace(/>/g, '>')
    .replace(/&/g, '&')
}<commit_msg>Support `:` escaping<commit_after>'use strict'

/**
 * un-escape special characters in the given string of html.
 *
 * @param  {String} html
 * @return {String}
 */

module.exports = function (html) {
  return String(html)
    .replace(/"/g, '"')
    .replace(/'/g, '\'')
    .replace(/:/g, ':')
    .replace(/</g, '<')
    .replace(/>/g, '>')
    .replace(/&/g, '&')
}
<|endoftext|>


<commit_before>/* jshint node:true, undef:true, unused:true */

var ModuleContainer = require('es6-module-transpiler').Container;
var FileResolver = require('es6-module-transpiler').FileResolver;
var formatters = require('es6-module-transpiler').formatters;

var path = require('path');
var mergeTrees = require('broccoli-merge-trees');
var helpers = require('broccoli-kitchen-sink-helpers');
var Writer = require('broccoli-writer');

/**
 * Returns a broccoli tree generator based on the given input tree and options.
 *
 * @param inputTree
 * @param options
 * @returns {CompileModules}
 */
function compileModules(inputTree, options) {
  return new CompileModules(inputTree, options);
}

CompileModules.prototype = Object.create(Writer.prototype);
CompileModules.prototype.constructor = CompileModules;

/**
 * Creates a new compiled modules writer.
 *
 * @param inputTree
 * @param options
 * @extends {Writer}
 * @constructor
 */
function CompileModules(inputTree, options) {
  this.setInputTree(inputTree);
  this.setInputFiles(options.inputFiles);
  this.setOutput(options.output);
  this.setFormatter(options.formatter);
}

/**
 * Sets the input tree to read files from.
 *
 * @param inputTree
 */
CompileModules.prototype.setInputTree = function(inputTree) {
  if (inputTree === undefined || inputTree === null) {
    throw new Error('Expected input tree object, got: ' + inputTree);
  }

  this.inputTree = inputTree;
};

/**
 * Sets the input files list of globs.
 *
 * @param {[string]} inputFiles
 */
CompileModules.prototype.setInputFiles = function(inputFiles) {
  if (!Array.isArray(inputFiles)) {
    throw new Error('Expected an array of input file globs, got: ' + inputFiles);
  }
  this.inputFiles = inputFiles;
};

/**
 * Sets the output directory or file.
 *
 * @param {string} output
 */
CompileModules.prototype.setOutput = function(output) {
  helpers.assertAbsolutePaths([output]);
  this.output = output;
};

/**
 * Sets the current formatter.
 *
 * @param formatter
 */
CompileModules.prototype.setFormatter = function(formatter) {
  if (!formatter) {
    formatter = formatters.DEFAULT;
  }

  if (typeof formatter === 'string') {
    var formatterName = formatter;
    formatter = formatters[formatter];
    if (typeof formatter !== 'function') {
      throw new Error(
        'No built-in module output formatter named `' +
        formatterName + '`, choose one of ' +
        Object.keys(formatters).filter(function(key) {
          return key !== 'DEFAULT';
        }).join(', ')
      );
    }
    formatter = new formatter();
  }

  if (typeof formatter !== 'object') {
    throw new Error(
      'Expected module output formatter object, got: ' + formatter
    );
  }

  this.formatter = formatter;
};

/**
 * Writes modules to the given destination directory.
 *
 * @param readTree
 * @param {string} destDir
 * @returns {Promise}
 */
CompileModules.prototype.write = function(readTree, destDir) {
  return readTree(this.inputTree).then(function(srcDir) {
    var container = new ModuleContainer({
      formatter: this.formatter,
      resolvers: [new FileResolver([srcDir])]
    });

    var inputFiles = helpers.multiGlob(this.inputFiles, {cwd: srcDir});
    for (var i = 0; i < inputFiles.length; i++) {
      container.getModule(inputFiles[i]);
    }

    container.write(path.join(destDir, this.output));
  }.bind(this));
};

module.exports = compileModules;
<commit_msg>improve slow-tree output<commit_after>/* jshint node:true, undef:true, unused:true */

var ModuleContainer = require('es6-module-transpiler').Container;
var FileResolver = require('es6-module-transpiler').FileResolver;
var formatters = require('es6-module-transpiler').formatters;

var path = require('path');
var mergeTrees = require('broccoli-merge-trees');
var helpers = require('broccoli-kitchen-sink-helpers');
var Writer = require('broccoli-writer');

/**
 * Returns a broccoli tree generator based on the given input tree and options.
 *
 * @param inputTree
 * @param options
 * @returns {CompileModules}
 */
function compileModules(inputTree, options) {
  return new CompileModules(inputTree, options);
}

CompileModules.prototype = Object.create(Writer.prototype);
CompileModules.prototype.constructor = CompileModules;

/**
 * Creates a new compiled modules writer.
 *
 * @param inputTree
 * @param options
 * @extends {Writer}
 * @constructor
 */
function CompileModules(inputTree, options) {
  this.setInputTree(inputTree);
  this.setInputFiles(options.inputFiles);
  this.setOutput(options.output);
  this.setFormatter(options.formatter);

  if (options.output) {
    this.description = 'CompileModules (' + options.output + ')';
  }
}

/**
 * Sets the input tree to read files from.
 *
 * @param inputTree
 */
CompileModules.prototype.setInputTree = function(inputTree) {
  if (inputTree === undefined || inputTree === null) {
    throw new Error('Expected input tree object, got: ' + inputTree);
  }

  this.inputTree = inputTree;
};

/**
 * Sets the input files list of globs.
 *
 * @param {[string]} inputFiles
 */
CompileModules.prototype.setInputFiles = function(inputFiles) {
  if (!Array.isArray(inputFiles)) {
    throw new Error('Expected an array of input file globs, got: ' + inputFiles);
  }
  this.inputFiles = inputFiles;
};

/**
 * Sets the output directory or file.
 *
 * @param {string} output
 */
CompileModules.prototype.setOutput = function(output) {
  helpers.assertAbsolutePaths([output]);
  this.output = output;
};

/**
 * Sets the current formatter.
 *
 * @param formatter
 */
CompileModules.prototype.setFormatter = function(formatter) {
  if (!formatter) {
    formatter = formatters.DEFAULT;
  }

  if (typeof formatter === 'string') {
    var formatterName = formatter;
    formatter = formatters[formatter];
    if (typeof formatter !== 'function') {
      throw new Error(
        'No built-in module output formatter named `' +
        formatterName + '`, choose one of ' +
        Object.keys(formatters).filter(function(key) {
          return key !== 'DEFAULT';
        }).join(', ')
      );
    }
    formatter = new formatter();
  }

  if (typeof formatter !== 'object') {
    throw new Error(
      'Expected module output formatter object, got: ' + formatter
    );
  }

  this.formatter = formatter;
};

/**
 * Writes modules to the given destination directory.
 *
 * @param readTree
 * @param {string} destDir
 * @returns {Promise}
 */
CompileModules.prototype.write = function(readTree, destDir) {
  return readTree(this.inputTree).then(function(srcDir) {
    var container = new ModuleContainer({
      formatter: this.formatter,
      resolvers: [new FileResolver([srcDir])]
    });

    var inputFiles = helpers.multiGlob(this.inputFiles, {cwd: srcDir});
    for (var i = 0; i < inputFiles.length; i++) {
      container.getModule(inputFiles[i]);
    }

    container.write(path.join(destDir, this.output));
  }.bind(this));
};

module.exports = compileModules;
<|endoftext|>