<commit_before>'use strict';

/**
 * @file Helper for image file processing
 * For more information about Convert :
 * See http://www.imagemagick.org/script/convert.php
 */

var shellExec = require('child_process').exec;
var async = require('async');
var config = require('../config/configuration.js');

var hydrationError = require('anyfetch-file-hydrater').hydrationError;

/**
 * Generate base64 encoding of path resized to thumbnail size
 */
var generateThumb = function(path, thumbSize, cb) {
  // Initial command is:
  //convert original.png -auto-orient -thumbnail 350x250 thumb.png
  // -auto-orient use EXIF information for orientation,
  // -thumbnail strips metadata and use a quick algorithm for generation in the given size
  // -strip strips EXIF informations and ImageMagick metadata
  // see http://www.imagemagick.org/Usage/thumbnails/
  // For images smaller than final thumbnail size, we don't want to resize:
  //convert original.png -auto-orient -thumbnail 350x250\> thumb.png
  // To retrieve data in stdout, we have to export onto fd:1 as png, so:
  //convert original.png -auto-orient -thumbnail 350x250 png:fd:1
  // Finally, to convert this raw data to base64 we use -i (ignore garbage) and -w 0 to disable linebreaks.
  shellExec('convert -limit memory 100MiB -limit map 30MiB -limit area 10Mib ' + path + " -auto-orient -thumbnail " + thumbSize + "\\> -strip png:fd:1 | base64 -i -w 0", {maxBuffer: 20480 * 1024, timeout: 60000}, cb);
};

/**
 * Generate base64 encoding of path resized to display size
 */
var generateDisplay = function(path, displaySize, cb) {
  // Initial command is:
  //convert original.png -auto-orient -resize 750x750 image.png
  // We want to keep origin extension, so just fd:1
  shellExec('convert -limit memory 100MiB -limit map 30MiB -limit area 10Mib ' + path + " -auto-orient -resize " + displaySize + "\\> -quality 80 jpg:fd:1 | base64 -i -w 0", {maxBuffer: 20480 * 1024, timeout: 60000}, cb);
};

/**
 * Extract the content of the specified file
 *
 * @param {string} path Path of the specified file
 * @param {function} cb Callback, first parameter, is the error if any, then the processed data
 */
module.exports = function(path, document, changes, finalCb) {
  // Skip PSD
  if (document.metadata && document.metadata.path && (document.metadata.path.indexOf('.psd') !== -1 || document.metadata.path.indexOf('.PSD') !== -1)) {
    return finalCb(null, changes);
  }

  async.series({
    generateThumb: function(cb) {
      // Skip if already provided
      if(document.data && document.data.thumb) {
        return cb();
      }

      generateThumb(path, config.thumb_size, function(err, thumbnail) {
        if(err) {
          return cb(new hydrationError(err));
        }

        if(!thumbnail) {
          return cb(new hydrationError("Unable to hydrate image and create thumbnail"));
        }

        changes.data.thumb = "data:image/png;base64," + thumbnail;
        cb();
      });
    },
    generateDisplay: function(cb) {
      // Skip if already provided
      if(document.data && document.data.display) {
        return cb();
      }

      generateDisplay(path, config.display_size, function(err, display) {
        if(err) {
          return cb(new hydrationError(err), changes);
        }

        if(!display) {
          return cb(new hydrationError("Unable to hydrate image and create display"));
        }

        changes.data.display = "data:image/jpeg;base64," + display;
        cb();
      });
    },
  }, function(err) {
    changes.document_type = "image";
    finalCb(err, changes);
  });
};
<commit_msg>remove psd check<commit_after>'use strict';

/**
 * @file Helper for image file processing
 * For more information about Convert :
 * See http://www.imagemagick.org/script/convert.php
 */

var shellExec = require('child_process').exec;
var async = require('async');
var config = require('../config/configuration.js');

var hydrationError = require('anyfetch-file-hydrater').hydrationError;

/**
 * Generate base64 encoding of path resized to thumbnail size
 */
var generateThumb = function(path, thumbSize, cb) {
  // Initial command is:
  //convert original.png -auto-orient -thumbnail 350x250 thumb.png
  // -auto-orient use EXIF information for orientation,
  // -thumbnail strips metadata and use a quick algorithm for generation in the given size
  // -strip strips EXIF informations and ImageMagick metadata
  // see http://www.imagemagick.org/Usage/thumbnails/
  // For images smaller than final thumbnail size, we don't want to resize:
  //convert original.png -auto-orient -thumbnail 350x250\> thumb.png
  // To retrieve data in stdout, we have to export onto fd:1 as png, so:
  //convert original.png -auto-orient -thumbnail 350x250 png:fd:1
  // Finally, to convert this raw data to base64 we use -i (ignore garbage) and -w 0 to disable linebreaks.
  shellExec('convert -limit memory 100MiB -limit map 30MiB -limit area 10Mib ' + path + " -auto-orient -thumbnail " + thumbSize + "\\> -strip png:fd:1 | base64 -i -w 0", {maxBuffer: 20480 * 1024, timeout: 60000}, cb);
};

/**
 * Generate base64 encoding of path resized to display size
 */
var generateDisplay = function(path, displaySize, cb) {
  // Initial command is:
  //convert original.png -auto-orient -resize 750x750 image.png
  // We want to keep origin extension, so just fd:1
  shellExec('convert -limit memory 100MiB -limit map 30MiB -limit area 10Mib ' + path + " -auto-orient -resize " + displaySize + "\\> -quality 80 jpg:fd:1 | base64 -i -w 0", {maxBuffer: 20480 * 1024, timeout: 60000}, cb);
};

/**
 * Extract the content of the specified file
 *
 * @param {string} path Path of the specified file
 * @param {function} cb Callback, first parameter, is the error if any, then the processed data
 */
module.exports = function(path, document, changes, finalCb) {

  async.series({
    generateThumb: function(cb) {
      // Skip if already provided
      if(document.data && document.data.thumb) {
        return cb();
      }

      generateThumb(path, config.thumb_size, function(err, thumbnail) {
        if(err) {
          return cb(new hydrationError(err));
        }

        if(!thumbnail) {
          return cb(new hydrationError("Unable to hydrate image and create thumbnail"));
        }

        changes.data.thumb = "data:image/png;base64," + thumbnail;
        cb();
      });
    },
    generateDisplay: function(cb) {
      // Skip if already provided
      if(document.data && document.data.display) {
        return cb();
      }

      generateDisplay(path, config.display_size, function(err, display) {
        if(err) {
          return cb(new hydrationError(err), changes);
        }

        if(!display) {
          return cb(new hydrationError("Unable to hydrate image and create display"));
        }

        changes.data.display = "data:image/jpeg;base64," + display;
        cb();
      });
    },
  }, function(err) {
    changes.document_type = "image";
    finalCb(err, changes);
  });
};
<|endoftext|>


<commit_before>var path = require('path')
var ecstatic = require('ecstatic')
var osmserver = require('osm-p2p-server')
var http = require('http')
var hyperlog = require('hyperlog')
var level = require('level')
var sneakernet = require('hyperlog-sneakernet-replicator')

var body = require('body/any')
var qs = require('querystring')
var exportGeoJson = require('osm-p2p-geojson')
var importGeo = require('./lib/import-geo.js')
var pump = require('pump')
var shp = require('shpjs')
var tmpdir = require('os').tmpdir()
var concat = require('concat-stream')
var wsock = require('websocket-stream')
var eos = require('end-of-stream')
var randombytes = require('randombytes')

var userConfig = require('./lib/user-config')
var metadata = userConfig.getSettings('metadata')

module.exports = function (osm) {
  var osmrouter = osmserver(osm)
  var replicating = false

  var server = http.createServer(function (req, res) {
    console.log(req.method, req.url)
    if (osmrouter.handle(req, res)) {
    } else if (req.method === 'POST' && req.url === '/replicate') {
      if (replicating) return error(400, res, 'Replication in progress.\n')
      body(req, res, function (err, params) {
        if (err) return error(400, res, err)
        replicate(params.source)
        res.end('replication started\n')
      })
    } else if (req.url.split('?')[0] === '/export.geojson') {
      var params = qs.parse(req.url.replace(/^[^\?]*?/, ''))
      var bbox = [[params.minlat,params.maxlat],[params.minlon,params.maxlon]]
        .map(function (pt) {
          if (pt[0] === undefined) pt[0] = -Infinity
          if (pt[1] === undefined) pt[1] = Infinity
          return pt
        })
      res.setHeader('content-type', 'text/json')
      pump(exportGeoJson(osm, {bbox: bbox}), res)
    } else if (req.url === '/import.shp' && /^(PUT|POST)/.test(req.method)) {
      req.pipe(concat(function (buf) {
        errb(shp(buf), function (err, geojsons) {
          if (err) return error(400, res, err)
          if (!(geojsons instanceof Array)) {
            geojsons = [geojsons]
          }
          var errors = [], pending = 1
          geojsons.forEach(function (geo) {
            importGeo(osm, geo, function (err) {
              if (err) errors.push(String(err.message || err))
              if (--pending === 0) done()
            })
          })
          if (--pending === 0) done()
          function done () {
            res.end(JSON.stringify({
              errors: errors
            }, null, 2))
          }
        })
      }))
    } else error(404, res, 'Not Found')
  })

  var streams = {}
  wsock.createServer({ server: server }, function (stream) {
    var id = randombytes(8).toString('hex')
    streams[id] = stream
    eos(stream, function () { delete streams[id] })
  })
  return server

  function replicate (sourceFile) {
    console.log('replicating to', sourceFile)
    sneakernet(osm.log, { safetyFile: true }, sourceFile, onend)
    replicating = true

    function onend (err) {
      if (err) return syncErr(err)
      replicating = false
      send('replication-data-complete')
      setTimeout(function () {
        osm.ready(function () {
          console.log('COMPLETE')
          send('replication-complete')
        })
      }, 5000) // HACK, figure out how to not do this in the future
    }
    function syncErr (err) {
      replicating = false
      send('replication-error', err.message)
    }
  }
  function send (topic, msg) {
    var str = JSON.stringify({ topic: topic, message: msg || {} }) + '\n'
    Object.keys(streams).forEach(function (id) {
      streams[id].write(str)
    })
  }
}

function error (code, res, err) {
  res.statusCode = code
  res.end((err.message || err) + '\n')
}

function errb (promise, cb) {
  promise.then(cb.bind(null, null))
  promise.catch(cb)
}
<commit_msg>Linting.<commit_after>var osmserver = require('osm-p2p-server')
var http = require('http')
var sneakernet = require('hyperlog-sneakernet-replicator')

var body = require('body/any')
var qs = require('querystring')
var exportGeoJson = require('osm-p2p-geojson')
var importGeo = require('./lib/import-geo.js')
var pump = require('pump')
var shp = require('shpjs')
var concat = require('concat-stream')
var wsock = require('websocket-stream')
var eos = require('end-of-stream')
var randombytes = require('randombytes')

module.exports = function (osm) {
  var osmrouter = osmserver(osm)
  var replicating = false

  var server = http.createServer(function (req, res) {
    console.log(req.method, req.url)
    if (osmrouter.handle(req, res)) {
    } else if (req.method === 'POST' && req.url === '/replicate') {
      if (replicating) return error(400, res, 'Replication in progress.\n')
      body(req, res, function (err, params) {
        if (err) return error(400, res, err)
        replicate(params.source)
        res.end('replication started\n')
      })
    } else if (req.url.split('?')[0] === '/export.geojson') {
      var params = qs.parse(req.url.replace(/^[^\?]*?/, ''))
      var bbox = [
        [params.minlat, params.maxlat],
        [params.minlon, params.maxlon]
      ].map(function (pt) {
        if (pt[0] === undefined) pt[0] = -Infinity
        if (pt[1] === undefined) pt[1] = Infinity
        return pt
      })
      res.setHeader('content-type', 'text/json')
      pump(exportGeoJson(osm, {bbox: bbox}), res)
    } else if (req.url === '/import.shp' && /^(PUT|POST)/.test(req.method)) {
      req.pipe(concat(function (buf) {
        errb(shp(buf), function (err, geojsons) {
          if (err) return error(400, res, err)
          if (!(geojsons instanceof Array)) {
            geojsons = [geojsons]
          }
          var errors = []
          var pending = 1
          geojsons.forEach(function (geo) {
            importGeo(osm, geo, function (err) {
              if (err) errors.push(String(err.message || err))
              if (--pending === 0) done()
            })
          })
          if (--pending === 0) { done() }
          function done () {
            res.end(JSON.stringify({
              errors: errors
            }, null, 2))
          }
        })
      }))
    } else error(404, res, 'Not Found')
  })

  var streams = {}
  wsock.createServer({ server: server }, function (stream) {
    var id = randombytes(8).toString('hex')
    streams[id] = stream
    eos(stream, function () { delete streams[id] })
  })
  return server

  function replicate (sourceFile) {
    console.log('replicating to', sourceFile)
    sneakernet(osm.log, { safetyFile: true }, sourceFile, onend)
    replicating = true

    function onend (err) {
      if (err) return syncErr(err)
      replicating = false
      send('replication-data-complete')
      setTimeout(function () {
        osm.ready(function () {
          console.log('COMPLETE')
          send('replication-complete')
        })
      }, 5000) // HACK, figure out how to not do this in the future
    }
    function syncErr (err) {
      replicating = false
      send('replication-error', err.message)
    }
  }
  function send (topic, msg) {
    var str = JSON.stringify({ topic: topic, message: msg || {} }) + '\n'
    Object.keys(streams).forEach(function (id) {
      streams[id].write(str)
    })
  }
}

function error (code, res, err) {
  res.statusCode = code
  res.end((err.message || err) + '\n')
}

function errb (promise, cb) {
  promise.then(cb.bind(null, null))
  promise.catch(cb)
}
<|endoftext|>


<commit_before>'use strict';
const {EventEmitter} = require('events');
const WebSocket = require('ws');
// temporary: RangeSet will be moved to api/common soon
const RangeSet = require('./rangeset').RangeSet;
const {RippledError, DisconnectedError, NotConnectedError,
  TimeoutError, UnexpectedError} = require('./errors');

function isStreamMessageType(type) {
  return type === 'ledgerClosed' ||
         type === 'transaction' ||
         type === 'path_find';
}

class Connection extends EventEmitter {
  constructor(url, options = {}) {
    super();
    this._url = url;
    this._timeout = options.timeout || (20 * 1000);
    this._isReady = false;
    this._ws = null;
    this._ledgerVersion = null;
    this._availableLedgerVersions = new RangeSet();
    this._nextRequestID = 1;
  }

  // return value is array of arguments to Connection.emit
  _parseMessage(message) {
    const data = JSON.parse(message);
    if (data.type === 'response') {
      if (!(Number.isInteger(data.id) && data.id >= 0)) {
        throw new UnexpectedError('valid id not found in response');
      }
      return [data.id.toString(), data];
    } else if (isStreamMessageType(data.type)) {
      if (data.type === 'ledgerClosed') {
        this._ledgerVersion = Number(data.ledger_index);
        this._availableLedgerVersions.reset();
        this._availableLedgerVersions.parseAndAddRanges(
          data.validated_ledgers);
      }
      return [data.type, data];
    } else if (data.type === undefined && data.error) {
      return ['error', data.error, data.error_message];  // e.g. slowDown
    }
    throw new UnexpectedError('unrecognized message type: ' + data.type);
  }

  _onMessage(message) {
    let parameters;
    try {
      parameters = this._parseMessage(message);
    } catch (error) {
      this.emit('error', 'badMessage', message);
      return;
    }
    // we don't want this inside the try/catch or exceptions in listener
    // will be caught
    this.emit.apply(this, parameters);
  }

  get state() {
    return this._ws ? this._ws.readyState : WebSocket.CLOSED;
  }

  get _shouldBeConnected() {
    return this._ws !== null;
  }

  isConnected() {
    return this.state === WebSocket.OPEN && this._isReady;
  }

  _onUnexpectedClose() {
    this._isReady = false;
    this.connect().then();
  }

  _onOpen() {
    const request = {
      command: 'subscribe',
      streams: ['ledger']
    };
    return this.request(request).then(response => {
      this._ledgerVersion = Number(response.ledger_index);
      this._availableLedgerVersions.parseAndAddRanges(
        response.validated_ledgers);
      this._isReady = true;
      this.emit('connected');
    });
  }

  connect() {
    return new Promise((resolve, reject) => {
      if (this.state === WebSocket.OPEN) {
        resolve();
      } else if (this.state === WebSocket.CONNECTING) {
        this._ws.once('open', resolve);
      } else {
        this._ws = new WebSocket(this._url);
        this._ws.on('message', this._onMessage.bind(this));
        this._ws.once('close', () => this._onUnexpectedClose);
        this._ws.once('open', () => this._onOpen().then(resolve, reject));
      }
    });
  }

  disconnect() {
    return new Promise(resolve => {
      if (this.state === WebSocket.CLOSED) {
        resolve();
      } else if (this.state === WebSocket.CLOSING) {
        this._ws.once('close', resolve);
      } else {
        this._ws.removeListener('close', this._onUnexpectedClose);
        this._ws.once('close', () => {
          this._ws = null;
          this._isReady = false;
          resolve();
        });
        this._ws.close();
      }
    });
  }

  reconnect() {
    return this.disconnect().then(() => this.connect());
  }

  _whenReady(promise) {
    return new Promise((resolve, reject) => {
      if (!this._shouldBeConnected) {
        reject(new NotConnectedError());
      } else if (this.state === WebSocket.OPEN && this._isReady) {
        promise.then(resolve, reject);
      } else {
        this.once('connected', () => promise.then(resolve, reject));
      }
    });
  }

  getLedgerVersion() {
    return this._whenReady(Promise.resolve(this._ledgerVersion));
  }

  hasLedgerVersions(lowLedgerVersion, highLedgerVersion) {
    return this._whenReady(Promise.resolve(
      this._availableLedgerVersions.containsRange(
        lowLedgerVersion, highLedgerVersion || this._ledgerVersion)));
  }

  hasLedgerVersion(ledgerVersion) {
    return this.hasLedgerVersions(ledgerVersion, ledgerVersion);
  }

  _send(message) {
    return new Promise((resolve, reject) => {
      this._ws.send(message, undefined, (error, result) => {
        if (error) {
          reject(new DisconnectedError(error.message));
        } else {
          resolve(result);
        }
      });
    });
  }

  request(request, timeout) {
    return new Promise((resolve, reject) => {
      if (!this._shouldBeConnected) {
        reject(new NotConnectedError());
      }

      let timer = null;
      const self = this;
      const id = this._nextRequestID;
      this._nextRequestID += 1;
      const eventName = id.toString();

      function onDisconnect() {
        clearTimeout(timer);
        self.removeAllListeners(eventName);
        reject(new DisconnectedError());
      }

      function cleanup() {
        clearTimeout(timer);
        self.removeAllListeners(eventName);
        if (self._ws !== null) {
          self._ws.removeListener('close', onDisconnect);
        }
      }

      function _resolve(response) {
        cleanup();
        resolve(response);
      }

      function _reject(error) {
        cleanup();
        reject(error);
      }

      this.once(eventName, response => {
        if (response.status === 'error') {
          _reject(new RippledError(response.error));
        } else if (response.status === 'success') {
          _resolve(response.result);
        } else {
          _reject(new UnexpectedError(
            'unrecognized status: ' + response.status));
        }
      });

      this._ws.once('close', onDisconnect);

      // JSON.stringify automatically removes keys with value of 'undefined'
      const message = JSON.stringify(Object.assign({}, request, {id}));

      this._whenReady(this._send(message)).then(() => {
        const delay = timeout || this._timeout;
        timer = setTimeout(() => _reject(new TimeoutError()), delay);
      }).catch(_reject);
    });
  }
}

module.exports = Connection;
<commit_msg>Use Promise.resolve<commit_after>'use strict';
const {EventEmitter} = require('events');
const WebSocket = require('ws');
// temporary: RangeSet will be moved to api/common soon
const RangeSet = require('./rangeset').RangeSet;
const {RippledError, DisconnectedError, NotConnectedError,
  TimeoutError, UnexpectedError} = require('./errors');

function isStreamMessageType(type) {
  return type === 'ledgerClosed' ||
         type === 'transaction' ||
         type === 'path_find';
}

class Connection extends EventEmitter {
  constructor(url, options = {}) {
    super();
    this._url = url;
    this._timeout = options.timeout || (20 * 1000);
    this._isReady = false;
    this._ws = null;
    this._ledgerVersion = null;
    this._availableLedgerVersions = new RangeSet();
    this._nextRequestID = 1;
  }

  // return value is array of arguments to Connection.emit
  _parseMessage(message) {
    const data = JSON.parse(message);
    if (data.type === 'response') {
      if (!(Number.isInteger(data.id) && data.id >= 0)) {
        throw new UnexpectedError('valid id not found in response');
      }
      return [data.id.toString(), data];
    } else if (isStreamMessageType(data.type)) {
      if (data.type === 'ledgerClosed') {
        this._ledgerVersion = Number(data.ledger_index);
        this._availableLedgerVersions.reset();
        this._availableLedgerVersions.parseAndAddRanges(
          data.validated_ledgers);
      }
      return [data.type, data];
    } else if (data.type === undefined && data.error) {
      return ['error', data.error, data.error_message];  // e.g. slowDown
    }
    throw new UnexpectedError('unrecognized message type: ' + data.type);
  }

  _onMessage(message) {
    let parameters;
    try {
      parameters = this._parseMessage(message);
    } catch (error) {
      this.emit('error', 'badMessage', message);
      return;
    }
    // we don't want this inside the try/catch or exceptions in listener
    // will be caught
    this.emit.apply(this, parameters);
  }

  get _state() {
    return this._ws ? this._ws.readyState : WebSocket.CLOSED;
  }

  get _shouldBeConnected() {
    return this._ws !== null;
  }

  isConnected() {
    return this._state === WebSocket.OPEN && this._isReady;
  }

  _onUnexpectedClose() {
    this._isReady = false;
    this.connect().then();
  }

  _onOpen() {
    const request = {
      command: 'subscribe',
      streams: ['ledger']
    };
    return this.request(request).then(response => {
      this._ledgerVersion = Number(response.ledger_index);
      this._availableLedgerVersions.parseAndAddRanges(
        response.validated_ledgers);
      this._isReady = true;
      this.emit('connected');
    });
  }

  connect() {
    return new Promise((resolve, reject) => {
      if (this._state === WebSocket.OPEN) {
        resolve();
      } else if (this._state === WebSocket.CONNECTING) {
        this._ws.once('open', resolve);
      } else {
        this._ws = new WebSocket(this._url);
        this._ws.on('message', this._onMessage.bind(this));
        this._ws.once('close', () => this._onUnexpectedClose);
        this._ws.once('open', () => this._onOpen().then(resolve, reject));
      }
    });
  }

  disconnect() {
    return new Promise(resolve => {
      if (this._state === WebSocket.CLOSED) {
        resolve();
      } else if (this._state === WebSocket.CLOSING) {
        this._ws.once('close', resolve);
      } else {
        this._ws.removeListener('close', this._onUnexpectedClose);
        this._ws.once('close', () => {
          this._ws = null;
          this._isReady = false;
          resolve();
        });
        this._ws.close();
      }
    });
  }

  reconnect() {
    return this.disconnect().then(() => this.connect());
  }

  _whenReady(promise) {
    return new Promise((resolve, reject) => {
      if (!this._shouldBeConnected) {
        reject(new NotConnectedError());
      } else if (this._state === WebSocket.OPEN && this._isReady) {
        promise.then(resolve, reject);
      } else {
        this.once('connected', () => promise.then(resolve, reject));
      }
    });
  }

  getLedgerVersion() {
    return this._whenReady(Promise.resolve(this._ledgerVersion));
  }

  hasLedgerVersions(lowLedgerVersion, highLedgerVersion) {
    return this._whenReady(Promise.resolve(
      this._availableLedgerVersions.containsRange(
        lowLedgerVersion, highLedgerVersion || this._ledgerVersion)));
  }

  hasLedgerVersion(ledgerVersion) {
    return this.hasLedgerVersions(ledgerVersion, ledgerVersion);
  }

  _send(message) {
    return new Promise((resolve, reject) => {
      this._ws.send(message, undefined, (error, result) => {
        if (error) {
          reject(new DisconnectedError(error.message));
        } else {
          resolve(result);
        }
      });
    });
  }

  request(request, timeout) {
    return new Promise((resolve, reject) => {
      if (!this._shouldBeConnected) {
        reject(new NotConnectedError());
      }

      let timer = null;
      const self = this;
      const id = this._nextRequestID;
      this._nextRequestID += 1;
      const eventName = id.toString();

      function onDisconnect() {
        clearTimeout(timer);
        self.removeAllListeners(eventName);
        reject(new DisconnectedError());
      }

      function cleanup() {
        clearTimeout(timer);
        self.removeAllListeners(eventName);
        if (self._ws !== null) {
          self._ws.removeListener('close', onDisconnect);
        }
      }

      function _resolve(response) {
        cleanup();
        resolve(response);
      }

      function _reject(error) {
        cleanup();
        reject(error);
      }

      this.once(eventName, response => {
        if (response.status === 'error') {
          _reject(new RippledError(response.error));
        } else if (response.status === 'success') {
          _resolve(response.result);
        } else {
          _reject(new UnexpectedError(
            'unrecognized status: ' + response.status));
        }
      });

      this._ws.once('close', onDisconnect);

      // JSON.stringify automatically removes keys with value of 'undefined'
      const message = JSON.stringify(Object.assign({}, request, {id}));

      this._whenReady(this._send(message)).then(() => {
        const delay = timeout || this._timeout;
        timer = setTimeout(() => _reject(new TimeoutError()), delay);
      }).catch(_reject);
    });
  }
}

module.exports = Connection;
<|endoftext|>


<commit_before>/**
 * @fileOverview Prepopulation unit tests.
 */
var Promise = require('bluebird');
var chai = require('chai');
var sinon = require('sinon');
var floordate = require('floordate');
var assert = chai.assert;

var Prepopulate = require('../../lib/db/populate.db');
var fixtures = require('../lib/fixtures');

suite('Prepopulation of usage keys', function() {
  this.timeout(4000);
  var fix;

  fixtures.setupCase(function(res) {
    fix = res;
  });

  suite('Skip one month ahead', function() {
    var clock;
    setup(function() {
      var floored = floordate(Date.now(), 'month');
      var moveFwd = 40 * 24 * 3600 * 1000;
      clock = sinon.useFakeTimers(floored.getTime() + moveFwd);
    });
    teardown(function() {
      clock.restore();
    });

    test('check prepopulation works', function(done) {
      var pre = new Prepopulate(fix.client, {prefix: 'test'});
      pre.prepopulate().then(function() {
        var keys = fix.tokenModel.getKeys(fix.tokenItem);
        var keysTwo = fix.tokenModel.getKeys(fix.tokenItemTwo);
        var pget = Promise.promisify(fix.client.get, fix.client);
        return Promise.all([
          pget(keys.usage),
          pget(keys.usageFuture),
          pget(keysTwo.usage),
          pget(keysTwo.usageFuture),
        ]).then(function(result) {
          assert.equal(result[0], 10, 'usage one');
          assert.equal(result[1], 10, 'usage one future');
          assert.equal(result[2], 10, 'usage two');
          assert.equal(result[3], 10, 'usage two future');
        });
        // you are here
      }).then(done, done);
    });
  });
});
<commit_msg>debug travis<commit_after>/**
 * @fileOverview Prepopulation unit tests.
 */
var Promise = require('bluebird');
var chai = require('chai');
var sinon = require('sinon');
var floordate = require('floordate');
var assert = chai.assert;

var Prepopulate = require('../../lib/db/populate.db');
var fixtures = require('../lib/fixtures');

suite('Prepopulation of usage keys', function() {
  this.timeout(4000);
  var fix;

  fixtures.setupCase(function(res) {
    fix = res;
  });

  suite('Skip one month ahead', function() {
    var clock;
    setup(function() {
      var floored = floordate(Date.now(), 'month');
      var moveFwd = 40 * 24 * 3600 * 1000;
      clock = sinon.useFakeTimers(floored.getTime() + moveFwd);
    });
    teardown(function() {
      clock.restore();
    });

    test('check prepopulation works', function(done) {
      var pre = new Prepopulate(fix.client, {prefix: 'test'});
      pre.prepopulate().then(function() {
        console.log('prepopulation done!');
        var keys = fix.tokenModel.getKeys(fix.tokenItem);
        var keysTwo = fix.tokenModel.getKeys(fix.tokenItemTwo);
        var pget = Promise.promisify(fix.client.get, fix.client);
        return Promise.all([
          pget(keys.usage),
          pget(keys.usageFuture),
          pget(keysTwo.usage),
          pget(keysTwo.usageFuture),
        ]).then(function(result) {
          console.log('...and got all results!', result);

          assert.equal(result[0], 10, 'usage one');
          assert.equal(result[1], 10, 'usage one future');
          assert.equal(result[2], 10, 'usage two');
          assert.equal(result[3], 10, 'usage two future');
        });
        // you are here
      }).then(done, done);
    });
  });
});
<|endoftext|>


<commit_before>"use strict";

// Usage: (secure-<func>.js)
// const shim = require('openwhisk-shim');
// main = shim.makeShim(true);

const {NodeVM} = require("vm2");
const fs = require("fs");
const {PartialOrder} = require("po-utils");
const {TotalOrder} = require("to-utils");
const {auth} = require("auth");
const {SecureKV_PO} = require("secure-kv-po");
const {SecureKV_TO} = require("secure-kv-to");
const child_process = require( 'child_process' );
const aws = require( 'aws-sdk' );
const https = require( 'https' );

const rmFilesInDir = function (dirPath) {
    try {
        const files = fs.readdirSync(dirPath);

        if (files.length > 0)
            for (let i = 0; i < files.length; i++) {
                const filePath = dirPath + '/' + files[i];
                if (fs.statSync(filePath).isFile())
                    fs.unlinkSync(filePath);
                else
                    rmFilesInDir(filePath);
            }
    }
    catch(e) { }
};

const notEmptyDir = function (dirPath) {
    try {
        const files = fs.readdirSync(dirPath);
        return files.length > 0;
    }
    catch(e) { return true; }
};

const conf = JSON.parse(fs.readFileSync(__dirname.split('node_modules')[0] + 'conf.json', 'utf8'));
const unsecuredLambda = fs.readFileSync(__dirname.split('node_modules')[0] + conf.unsecLambda, 'utf8');

const labelOrdering = conf.usingPO ? new PartialOrder(conf.labels) : new TotalOrder(conf.min, conf.max);

module.exports.makeShim = function (allowExtReq) {
    return function (params) {

        let label;

        let reqUser;
        let reqPass;

        if (conf.runFromGET) { // Run http GET request on behalf of invoking user.
            reqUser = params.queryStringParameters.user;
            reqPass = params.queryStringParameters.pass;
            if (conf.userPassForIFCOnly) {
                delete params.queryStringParameters.user;
                delete params.queryStringParameters.pass;
            }
        } else { // Run http POST request on behalf of invoking user.
            let reqBody;
            if ((typeof params.body) === "string") {
                reqBody = JSON.parse(params.body);
            } else {
                reqBody = params.body;
            }
            reqUser = reqBody.user;
            reqPass = reqBody.pass;

        }

        const p = auth(reqUser, reqPass);

        const processEnv = {};

        for (let envVar of conf.processEnv) {
            processEnv[envVar] = process.env[envVar];
        }

        let executionEnv = {
            console: 'inherit',
            sandbox: {
                process: {
                    env: processEnv,
                },
                externalParams: params,
                bumpLabelTo:
                    function (newLabel) {
                        if (labelOrdering.lte(label, newLabel)) {
                            label = newLabel;
                            return true;
                        } else {
                            return false;
                        }
                    },
                bumpLabelToTop:
                    function () {
                        label = labelOrdering.getTop();
                    }
            },
            require: {
                external: allowExtReq,
                builtin: ['fs', 'url', 'path'],
                root: "./",
                mock: {
                    'kv-store': {
                        KV_Store: function (h, u, pwd, tableName) {
                            const skv = conf.usingPO ?
                                new SecureKV_PO(h, u, pwd, labelOrdering, tableName) :
                                new SecureKV_TO(h, u, pwd, tableName);

                            return {
                                init: () => skv.init(),
                                close: () => skv.close(),
                                put: (k, v) => skv.put(k, v, label),
                                get: (k) => {
                                    return skv.get(k, label)
                                        .then((res) => {
                                            if (res.length > 0) {
                                                return res[0].rowvalues;
                                            } else {
                                                return res;
                                            }
                                        }); // Arbitrary choice (?)
                                },
                                del: (k) => skv.del(k, label),
                                keys: () => skv.keys(label),
                                entries: () => skv.entries(label),
                            }
                        }
                    },
                    'child_process' : {

                        execSync: (command, options) => {
                            // Check that the command actually runs the correct file

                            if (command.split(' ')[0].split('/').slice(-1)[0] === 'gg-execute-static') {
                                return child_process.execSync(command,options);
                            } else {
                                throw "Trying to run an unexpected executable."
                            }

                        }
                    },
                    'aws-sdk' : {
                        config: aws.config,
                        S3: () => {
                            const s3 = new aws.S3();

                            return {
                                upload : (data, callback) => {
                                    if (labelOrdering.lte(label, conf.securityBound)) {
                                        return s3.upload(data, callback);
                                    } else {
                                        throw ("Attempting store a file in an S3 bucket, in violation of security policy");
                                    }

                                }
                            }
                        }
                    },
                    'https' : {
                        get : (url, callback)  => {
                            if (labelOrdering.lte(label, conf.securityBound)) {
                                return https.get(url, callback);
                            } else {
                                throw ("Attempting to access a url in violation of security policy");
                            }

                        }

                    }

                }
            }
        };

        // Need to understand exactly how the filesystem retains information between executions and
        // make sure that it is handled.
        // if (notEmptyDir('/tmp/')) {
        //     console.log("WARNING : /tmp/ dir not empty on fresh invocation of lambda. Might lead to data leak.")
        // }

        return p.then((l) => {
            if (l === undefined) {
                // In case getting the label failed, run on behalf of 'bottom' (completely unprivileged).
                label = labelOrdering.getBottom();
            } else {
                label = l;
            }

            const vm = new NodeVM(executionEnv);

            console.log(`
//  ***********************************
//  ** Original Lambda Code:
${unsecuredLambda}
//  ** End of Original Lambda Code:
//  ***********************************

module.exports = module.exports.main(externalParams);

        `);

            return vm.run(`
//  ***********************************
//  ** Original Lambda Code:
${unsecuredLambda}
//  ** End of Original Lambda Code:
//  ***********************************

module.exports = module.exports.main(externalParams);
        `, __dirname + "/" + conf.secLambda);
        })
            .then((executionResult) => {
                if (conf.declassifier &&
                    labelOrdering.lte(label, conf.declassifier.maxLabel) &&
                    labelOrdering.lte(conf.declassifier.minLabel, conf.securityBound)) {
                    const declf = require("../../decl");
                    declf.declassifier(err, value, callback);
                } else {
                    if (labelOrdering.lte(label, conf.securityBound)) {
                        return executionResult;
                    } else {
                        return Promise.reject("Attempting to return a dict/promise in violation with security policy");
                    }
                }
            })
    };
};<commit_msg>Set security bound to the label in case no security bound was hardcoded.<commit_after>"use strict";

// Usage: (secure-<func>.js)
// const shim = require('openwhisk-shim');
// main = shim.makeShim(true);

const {NodeVM} = require("vm2");
const fs = require("fs");
const {PartialOrder} = require("po-utils");
const {TotalOrder} = require("to-utils");
const {auth} = require("auth");
const {SecureKV_PO} = require("secure-kv-po");
const {SecureKV_TO} = require("secure-kv-to");
const child_process = require( 'child_process' );
const aws = require( 'aws-sdk' );
const https = require( 'https' );

const rmFilesInDir = function (dirPath) {
    try {
        const files = fs.readdirSync(dirPath);

        if (files.length > 0)
            for (let i = 0; i < files.length; i++) {
                const filePath = dirPath + '/' + files[i];
                if (fs.statSync(filePath).isFile())
                    fs.unlinkSync(filePath);
                else
                    rmFilesInDir(filePath);
            }
    }
    catch(e) { }
};

const notEmptyDir = function (dirPath) {
    try {
        const files = fs.readdirSync(dirPath);
        return files.length > 0;
    }
    catch(e) { return true; }
};

const conf = JSON.parse(fs.readFileSync(__dirname.split('node_modules')[0] + 'conf.json', 'utf8'));
const unsecuredLambda = fs.readFileSync(__dirname.split('node_modules')[0] + conf.unsecLambda, 'utf8');

const labelOrdering = conf.usingPO ? new PartialOrder(conf.labels) : new TotalOrder(conf.min, conf.max);

module.exports.makeShim = function (allowExtReq) {
    return function (params) {

        let label;
        let securityBound;

        let reqUser;
        let reqPass;

        if (conf.runFromGET) { // Run http GET request on behalf of invoking user.
            reqUser = params.queryStringParameters.user;
            reqPass = params.queryStringParameters.pass;
            if (conf.userPassForIFCOnly) {
                delete params.queryStringParameters.user;
                delete params.queryStringParameters.pass;
            }
        } else { // Run http POST request on behalf of invoking user.
            let reqBody;
            if ((typeof params.body) === "string") {
                reqBody = JSON.parse(params.body);
            } else {
                reqBody = params.body;
            }
            reqUser = reqBody.user;
            reqPass = reqBody.pass;

        }

        const p = auth(reqUser, reqPass);

        const processEnv = {};

        for (let envVar of conf.processEnv) {
            processEnv[envVar] = process.env[envVar];
        }

        let executionEnv = {
            console: 'inherit',
            sandbox: {
                process: {
                    env: processEnv,
                },
                externalParams: params,
                bumpLabelTo:
                    function (newLabel) {
                        if (labelOrdering.lte(label, newLabel)) {
                            label = newLabel;
                            return true;
                        } else {
                            return false;
                        }
                    },
                bumpLabelToTop:
                    function () {
                        label = labelOrdering.getTop();
                    }
            },
            require: {
                external: allowExtReq,
                builtin: ['fs', 'url', 'path'],
                root: "./",
                mock: {
                    'kv-store': {
                        KV_Store: function (h, u, pwd, tableName) {
                            const skv = conf.usingPO ?
                                new SecureKV_PO(h, u, pwd, labelOrdering, tableName) :
                                new SecureKV_TO(h, u, pwd, tableName);

                            return {
                                init: () => skv.init(),
                                close: () => skv.close(),
                                put: (k, v) => skv.put(k, v, label),
                                get: (k) => {
                                    return skv.get(k, label)
                                        .then((res) => {
                                            if (res.length > 0) {
                                                return res[0].rowvalues;
                                            } else {
                                                return res;
                                            }
                                        }); // Arbitrary choice (?)
                                },
                                del: (k) => skv.del(k, label),
                                keys: () => skv.keys(label),
                                entries: () => skv.entries(label),
                            }
                        }
                    },
                    'child_process' : {

                        execSync: (command, options) => {
                            // Check that the command actually runs the correct file

                            if (command.split(' ')[0].split('/').slice(-1)[0] === 'gg-execute-static') {
                                return child_process.execSync(command,options);
                            } else {
                                throw "Trying to run an unexpected executable."
                            }

                        }
                    },
                    'aws-sdk' : {
                        config: aws.config,
                        S3: () => {
                            const s3 = new aws.S3();

                            return {
                                upload : (data, callback) => {
                                    if (labelOrdering.lte(label, securityBound)) {
                                        return s3.upload(data, callback);
                                    } else {
                                        throw ("Attempting store a file in an S3 bucket, in violation of security policy");
                                    }

                                }
                            }
                        }
                    },
                    'https' : {
                        get : (url, callback)  => {
                            if (labelOrdering.lte(label, securityBound)) {
                                return https.get(url, callback);
                            } else {
                                throw ("Attempting to access a url in violation of security policy");
                            }

                        }

                    }

                }
            }
        };

        // Need to understand exactly how the filesystem retains information between executions and
        // make sure that it is handled.
        // if (notEmptyDir('/tmp/')) {
        //     console.log("WARNING : /tmp/ dir not empty on fresh invocation of lambda. Might lead to data leak.")
        // }

        return p.then((l) => {
            if (l === undefined) {
                // In case getting the label failed, run on behalf of 'bottom' (completely unprivileged).
                label = labelOrdering.getBottom();
            } else {
                label = l;
            }
            if (conf.securityBound) {
                securityBound = conf.securityBound;
            } else {
                securityBound = l;
            }
            const vm = new NodeVM(executionEnv);

            console.log(`
//  ***********************************
//  ** Original Lambda Code:
${unsecuredLambda}
//  ** End of Original Lambda Code:
//  ***********************************

module.exports = module.exports.main(externalParams);

        `);

            return vm.run(`
//  ***********************************
//  ** Original Lambda Code:
${unsecuredLambda}
//  ** End of Original Lambda Code:
//  ***********************************

module.exports = module.exports.main(externalParams);
        `, __dirname + "/" + conf.secLambda);
        })
            .then((executionResult) => {
                if (conf.declassifier &&
                    labelOrdering.lte(label, conf.declassifier.maxLabel) &&
                    labelOrdering.lte(conf.declassifier.minLabel, securityBound)) {
                    const declf = require("../../decl");
                    declf.declassifier(err, value, callback);
                } else {
                    if (labelOrdering.lte(label, securityBound)) {
                        return executionResult;
                    } else {
                        return Promise.reject("Attempting to return a dict/promise in violation with security policy");
                    }
                }
            })
    };
};<|endoftext|>


<commit_before>/* Port of strftime(). Compatibility notes:
 *
 * %c - formatted string is slightly different
 * %D - not implemented (use "%m/%d/%y" or "%d/%m/%y")
 * %e - space is not added
 * %E - not implemented
 * %h - not implemented (use "%b")
 * %k - space is not added
 * %n - not implemented (use "\n")
 * %O - not implemented
 * %r - not implemented (use "%I:%M:%S %p")
 * %R - not implemented (use "%H:%M")
 * %t - not implemented (use "\t")
 * %T - not implemented (use "%H:%M:%S")
 * %U - not implemented
 * %W - not implemented
 * %+ - not implemented
 * %% - not implemented (use "%")
 *
 * strftime() reference:
 * http://man7.org/linux/man-pages/man3/strftime.3.html
 *
 * Day of year (%j) code based on Joe Orost's answer:
 * http://stackoverflow.com/questions/8619879/javascript-calculate-the-day-of-the-year-1-366
 *
 * Week number (%V) code based on Taco van den Broek's prototype:
 * http://techblog.procurios.nl/k/news/view/33796/14863/calculate-iso-8601-week-and-year-in-javascript.html
 */
function strftime(sFormat, date) {
  if (!(date instanceof Date)) date = new Date();
  var nDay = date.getDay(),
    nDate = date.getDate(),
    nMonth = date.getMonth(),
    nYear = date.getFullYear(),
    nHour = date.getHours(),
    aDays = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
    aMonths = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
    aDayCount = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334],
    isLeapYear = function() {
      if (nYear&3!==0) return false;
      return nYear%100!==0 || nYear%400===0;
    },
    getThursday = function() {
      var target = new Date(date);
      target.setDate(nDate - ((nDay+6)%7) + 3);
      return target;
    },
    zeroPad = function(nNum, nPad) {
      return ('' + (Math.pow(10, nPad) + nNum)).slice(1);
    };
  return sFormat.replace(/%[a-z]/gi, function(sMatch) {
    return {
      '%a': aDays[nDay].slice(0,3),
      '%A': aDays[nDay],
      '%b': aMonths[nMonth].slice(0,3),
      '%B': aMonths[nMonth],
      '%c': date.toUTCString(),
      '%C': Math.floor(nYear/100),
      '%d': zeroPad(nDate, 2),
      '%e': nDate,
      '%F': date.toISOString().slice(0,10),
      '%G': getThursday().getFullYear(),
      '%g': ('' + getThursday().getFullYear()).slice(2),
      '%H': zeroPad(nHour, 2),
      '%I': zeroPad((nHour+11)%12 + 1, 2),
      '%j': zeroPad(aDayCount[nMonth] + nDate + ((nMonth>1 && isLeapYear()) ? 1 : 0), 3),
      '%k': '' + nHour,
      '%l': (nHour+11)%12 + 1,
      '%m': zeroPad(nMonth + 1, 2),
      '%M': zeroPad(date.getMinutes(), 2),
      '%p': (nHour<12) ? 'AM' : 'PM',
      '%P': (nHour<12) ? 'am' : 'pm',
      '%s': Math.round(date.getTime()/1000),
      '%S': zeroPad(date.getSeconds(), 2),
      '%u': nDay || 7,
      '%V': (function() {
              var target = getThursday(),
                n1stThu = target.valueOf();
              target.setMonth(0, 1);
              var nJan1 = target.getDay();
              if (nJan1!==4) target.setMonth(0, 1 + ((4-nJan1)+7)%7);
              return zeroPad(1 + Math.ceil((n1stThu-target)/604800000), 2);
            })(),
      '%w': '' + nDay,
      '%x': date.toLocaleDateString(),
      '%X': date.toLocaleTimeString(),
      '%y': ('' + nYear).slice(2),
      '%Y': nYear,
      '%z': date.toTimeString().replace(/.+GMT([+-]\d+).+/, '$1'),
      '%Z': date.toTimeString().replace(/.+\((.+?)\)$/, '$1')
    }[sMatch] || sMatch;
  });
}
<commit_msg>Explicit parens to make sure comparison is proper<commit_after>/* Port of strftime(). Compatibility notes:
 *
 * %c - formatted string is slightly different
 * %D - not implemented (use "%m/%d/%y" or "%d/%m/%y")
 * %e - space is not added
 * %E - not implemented
 * %h - not implemented (use "%b")
 * %k - space is not added
 * %n - not implemented (use "\n")
 * %O - not implemented
 * %r - not implemented (use "%I:%M:%S %p")
 * %R - not implemented (use "%H:%M")
 * %t - not implemented (use "\t")
 * %T - not implemented (use "%H:%M:%S")
 * %U - not implemented
 * %W - not implemented
 * %+ - not implemented
 * %% - not implemented (use "%")
 *
 * strftime() reference:
 * http://man7.org/linux/man-pages/man3/strftime.3.html
 *
 * Day of year (%j) code based on Joe Orost's answer:
 * http://stackoverflow.com/questions/8619879/javascript-calculate-the-day-of-the-year-1-366
 *
 * Week number (%V) code based on Taco van den Broek's prototype:
 * http://techblog.procurios.nl/k/news/view/33796/14863/calculate-iso-8601-week-and-year-in-javascript.html
 */
function strftime(sFormat, date) {
  if (!(date instanceof Date)) date = new Date();
  var nDay = date.getDay(),
    nDate = date.getDate(),
    nMonth = date.getMonth(),
    nYear = date.getFullYear(),
    nHour = date.getHours(),
    aDays = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
    aMonths = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
    aDayCount = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334],
    isLeapYear = function() {
      if ((nYear&3)!==0) return false;
      return nYear%100!==0 || nYear%400===0;
    },
    getThursday = function() {
      var target = new Date(date);
      target.setDate(nDate - ((nDay+6)%7) + 3);
      return target;
    },
    zeroPad = function(nNum, nPad) {
      return ('' + (Math.pow(10, nPad) + nNum)).slice(1);
    };
  return sFormat.replace(/%[a-z]/gi, function(sMatch) {
    return {
      '%a': aDays[nDay].slice(0,3),
      '%A': aDays[nDay],
      '%b': aMonths[nMonth].slice(0,3),
      '%B': aMonths[nMonth],
      '%c': date.toUTCString(),
      '%C': Math.floor(nYear/100),
      '%d': zeroPad(nDate, 2),
      '%e': nDate,
      '%F': date.toISOString().slice(0,10),
      '%G': getThursday().getFullYear(),
      '%g': ('' + getThursday().getFullYear()).slice(2),
      '%H': zeroPad(nHour, 2),
      '%I': zeroPad((nHour+11)%12 + 1, 2),
      '%j': zeroPad(aDayCount[nMonth] + nDate + ((nMonth>1 && isLeapYear()) ? 1 : 0), 3),
      '%k': '' + nHour,
      '%l': (nHour+11)%12 + 1,
      '%m': zeroPad(nMonth + 1, 2),
      '%M': zeroPad(date.getMinutes(), 2),
      '%p': (nHour<12) ? 'AM' : 'PM',
      '%P': (nHour<12) ? 'am' : 'pm',
      '%s': Math.round(date.getTime()/1000),
      '%S': zeroPad(date.getSeconds(), 2),
      '%u': nDay || 7,
      '%V': (function() {
              var target = getThursday(),
                n1stThu = target.valueOf();
              target.setMonth(0, 1);
              var nJan1 = target.getDay();
              if (nJan1!==4) target.setMonth(0, 1 + ((4-nJan1)+7)%7);
              return zeroPad(1 + Math.ceil((n1stThu-target)/604800000), 2);
            })(),
      '%w': '' + nDay,
      '%x': date.toLocaleDateString(),
      '%X': date.toLocaleTimeString(),
      '%y': ('' + nYear).slice(2),
      '%Y': nYear,
      '%z': date.toTimeString().replace(/.+GMT([+-]\d+).+/, '$1'),
      '%Z': date.toTimeString().replace(/.+\((.+?)\)$/, '$1')
    }[sMatch] || sMatch;
  });
}
<|endoftext|>


<commit_before>/**
 * A generic Schedule Limiter for NodeJS.
 *
 * USAGE:
 *   let ScheduleLimiter = require('schedule-limiter');
 *   let limiter = new ScheduleLimiter({
 *       database: {
 *           type: 'Redis',
 *           options: {
 *               host: 'localhost',
 *               port: 6379
 *           }
 *       }
 *   });
 *   let id = 1; // e.g. userId
 *   limiter.setLimit(id,100); // Set Limit as 100
 *   limiter.createSchedule(id, {'2015': {'Dec': 50}, '2016': {'Jan': 60}})
 *     .then(function(usage) {
 *         callMyRequestSendingFunction(...);
 *     }).catch(function(error) {
 *         console.log(error.message);
 *         // Handle error and notify user
 *     });
 *   limiter.getUsage(id, {'2015': ['Dec'], '2016': ['Jan', 'Feb'] })
 *     .then(function(usage) {
 *         console.log(usage);
 *         // {'2015': {'12': 50}, '2016': {'1': 60, '2': 0}}
 *     });
 *   limiter.cancelSchedule(id, {'2015': {'Dec': 50}, '2016': {'Jan': 60}})
 *     .then(function(usage) {
 *         callMyFunction(...);
 *     }).catch(function(error) {
 *         console.log(error.message);
 *         // Handle error and notify user
 *     });
 */

'use strict';

let Adapter = require('./Adapter');
let debug = require('debug')('ScheduleLimiter:lib:ScheduleLimiter');

module.exports = class ScheduleLimiter {
    constructor(opts) {
        this.adapter = new Adapter(opts);
        this.scheduleUpto = 12; // (months) Able to schedule up to one year
        const monthMapping = {
            'jan': 1,
            'feb': 2,
            'mar': 3,
            'apr': 4,
            'may': 5,
            'jun': 6,
            'jul': 7,
            'aug': 8,
            'sep': 9,
            'oct': 10,
            'nov': 11,
            'dec': 12
        };
        this.monthMap = new Map();
        for (let month of Object.keys(monthMapping)) {
            this.monthMap.set(month, monthMapping[month]);
        }
    }

    /**
     * Set the limit against particular id. Then this limit will consider as
     * limit for every month
     * @param id {Integer/String} ID (appId or userId) which want to limit
     * @param limit {Integer} Limit value
     */
    setLimit(id, limit) {
        return this.adapter.setLimit(id, limit);
    }

    /**
     * Get the stored limit against particular ID
     * @param id {Integer/String} ID (appId or userId) which want to limit
     * @return {Integer} Limit value
     */
    getLimit(id) {
        return this.adapter.getLimit(id);
    }

    /**
     * Set the limit against particular id. Then this limit will consider as
     * limit for every month
     * @param limit {Array} Array of limit Objects s.t.
     * [{'userId': 1000}, {'userId2: 500}, ...]
     */
    setLimits(limits) {

    }

    /**
     * Get the current usage (used tokens) against a particular id.
     * @param id {Integer/String} ID (appId or userId) which want to limit
     * @param months {Object} Object which contains Months Array s.t.
     * {'2015': ['Jan', 'feb', 3, '4']}
     * @param includeLimit {Boolean} Whether include current limit (Optional) Default `false`
     * @return {Object} Remaining limits for each month s.t.
     * {'2015': {'1': 10, '2': 15, '3': 20, '4': 30}}
     */
    getUsage(id, months, includeLimit) {
        this.adapter.getUsage(id, months, includeLimit);
    }

    /**
     * Increase the usage value of given set of months against particular ID.
     * If successfully increase the values, return values after increment.
     * Otherwise rollback to previous state and return an error.
     * @param id {Integer/String} ID (appId or userId) which want to limit
     * @param tokens {Object} Number of tokens which want to use s.t.
     * {'2015': {'Jan': 10, 'feb': 15, 3: 20, '4': 30}, '2016': {'1': 40}}
     * @return {Object} Remaining limits for each month s.t.
     * {'2015': {'1': 10, '2': 15, '3': 20, '4': 30}, '2016': {'1': 40}}
     */
    createSchedule(id, tokens, force) {
        debug(`CreateSchedule ${id} tokens: `, tokens);
        if (!isNaN(tokens)) { // if a number, then create an Obj for current month
            const month = new Date().getMonth() + 1;
            tokens = [{
                month: tokens
            }];
        }
        // Set force default value as 'false'
        force = force || false;

        /**
         * Reference: http://redis.io/commands/incr#pattern-rate-limiter
         *
         * There are two approach to check the limit and set the values
         * 1. Increase the usage with given token values, then compare return
         *    values (new usage) with limit whether it exceeds
         *    -> If exceeds > rollback
         *    -> Otherwise > do nothing
         * E.g. In Redis, one database call (when exceeds, two database calls)
         * 2. Get the usage according to given tokens, then compare with limit
         *    by considering if it increase the token value, then exceeds the
         *    limit
         *    -> If exceeds > do nothing
         *    -> Otherwise  > increase the usage
         * E.g. In Redis, two database call (when exceeds, one database calls)
         *
         * Both options have a race condition, which can be neglectable.
         */

        // TODO: 1nd option implementation (should be able to one of them)

        // 2nd option implementation
        const formattedTokens = this._formatMonths(tokens);
        let months = {};
        for (let year of Object.keys(formattedTokens)) {
            months[year] = Object.keys(formattedTokens[year]);
        }

        return new Promise((resolve, reject) => {
            this.adapter.getUsage(id, months, true).then(usage => {
                const limit = usage.limit;
                // Delete `limit` field
                delete usage.limit;
                const isExceed = this._isExceed(limit, usage, formattedTokens);
                if (isExceed.state) {
                    this.adapter.increaseValues(id, isExceed.tokens).
                    then(usage => {
                        resolve(usage);
                    }).catch(err => {
                        reject(err);
                    });
                } else {
                    reject(new Error(isExceed.message));
                }
            }).catch(err => {
                reject(err);
            });
        }); // END - 2nd Option
    }

    /**
     * Cancel previously schedule by decrease the usage value of given set of
     * months against particular ID.
     * If successfully decrease the values, return values after decrement.
     * Otherwise rollback to previous state and return an error.
     * @param id {Integer/String} ID (appId or userId) which want to limit
     * @param tokens {Object} Number of tokens which want to use s.t.
     * {'2015': {'Jan' 10, 'feb': 15, 3: 20}, '2016': {'4': 30}}
     * @return {Object} Remaining limits for each month s.t.
     * {'2015': {'1': 10, '2': 15, '3': 20}, '2016': {'4': 30}}
     */
    cancelSchedule(id, tokens, force) {
        debug(`CancelSchedule ${id} tokens: `, tokens);

        if (!isNaN(tokens)) { //if a number,then create an Obj for current month
            const month = new Date().getMonth() + 1;
            tokens = {
                month: tokens
            };
        }
        force = force || false;

        // 2nd Option implementation (reverse)
        const formattedTokens = this._formatMonths(tokens);
        let months = {};
        for (let year of Object.keys(formattedTokens)) {
            months[year] = Object.keys(formattedTokens[year]);
        }

        return new Promise((resolve, reject) => {
            this.adapter.getUsage(id, months).then(usage => {
                const isNegative = this._isNegative(usage, formattedTokens);
                if (isNegative.state) {
                    this.adapter.decreaseValues(id, isNegative.tokens).
                        then(usage => {
                            resolve(usage);
                        }).catch(err => {
                            reject(err);
                        });
                } else {
                    reject(new Error(isNegative.message));
                }
            }).catch(err => {
                reject(err);
            });
        }); // END - 2nd Option
    }

    /**
     * Format mixed month keys into Number format
     * @param tokens {Object} Number of tokens which want to use s.t.
     * {'2015': {'Jan' 10, 'feb': 15, 3: 20}, '2016': {'4': 30}}
     * @return {Object} Formatted token keys for each month s.t.
     * {'2015': {'1': 10, '2': 15, '3': 20}, '2016': {'4': 30}}
     */
    _formatMonths(tokens) {
        debug('_formatMonths tokens: ', tokens);

        let formattedTokens = {};
        for (let year of Object.keys(tokens)) {
            formattedTokens[year] = {};
            for (let month of Object.keys(tokens[year])) {
                let monthNumber = (isNaN(month)) ?
                    this.monthMap.get(month.toLowerCase()) : month;
                formattedTokens[year][monthNumber] = tokens[year][month];
            }
        }

        return formattedTokens;
    }

    _isExceed(limit, usage, tokens) {
        debug('_isExceed args : ', limit, usage, tokens);
        // If force enabled, possible removable token size get changed
        let newTokens = tokens;

        for (let year of Object.keys(usage)) {
            for (let month of Object.keys(usage[year])) {
                if (usage[year][month] + tokens[year][month] > limit) {
                    return {
                        state: false,
                        message: `Required amount of ${usage[year][month]} ` +
                          `exceeds the limit ${limit} in ${year}-${month} by ` +
                          `${usage[year][month]+tokens[year][month] - limit).` +
                          ` Remained amount is ${limit - usage[year][month]}`
                    };
                }
            }
        }
        return {
            state: true,
            tokens: newTokens
        };
    }

    _isNegative(usage, tokens) {
        // If force enabled, possible removable token size get changed
        let newTokens = tokens;

        for (let year of Object.keys(usage)) {
            for (let month of Object.keys(usage[year])) {
                if ((usage[year][month] - tokens[year][month]) < 0) {
                    return {
                        state: false,
                        message: `Usage ${usage[year][month]} can't less than 0 in ${year}-${month}`
                    };
                }
            }
        }
        return {
            state: true,
            tokens: newTokens
        };
    }

};

// export default ScheduleLimiter;
<commit_msg>Fixed: Systax error in not closing paranthesis<commit_after>/**
 * A generic Schedule Limiter for NodeJS.
 *
 * USAGE:
 *   let ScheduleLimiter = require('schedule-limiter');
 *   let limiter = new ScheduleLimiter({
 *       database: {
 *           type: 'Redis',
 *           options: {
 *               host: 'localhost',
 *               port: 6379
 *           }
 *       }
 *   });
 *   let id = 1; // e.g. userId
 *   limiter.setLimit(id,100); // Set Limit as 100
 *   limiter.createSchedule(id, {'2015': {'Dec': 50}, '2016': {'Jan': 60}})
 *     .then(function(usage) {
 *         callMyRequestSendingFunction(...);
 *     }).catch(function(error) {
 *         console.log(error.message);
 *         // Handle error and notify user
 *     });
 *   limiter.getUsage(id, {'2015': ['Dec'], '2016': ['Jan', 'Feb'] })
 *     .then(function(usage) {
 *         console.log(usage);
 *         // {'2015': {'12': 50}, '2016': {'1': 60, '2': 0}}
 *     });
 *   limiter.cancelSchedule(id, {'2015': {'Dec': 50}, '2016': {'Jan': 60}})
 *     .then(function(usage) {
 *         callMyFunction(...);
 *     }).catch(function(error) {
 *         console.log(error.message);
 *         // Handle error and notify user
 *     });
 */

'use strict';

let Adapter = require('./Adapter');
let debug = require('debug')('ScheduleLimiter:lib:ScheduleLimiter');

module.exports = class ScheduleLimiter {
    constructor(opts) {
        this.adapter = new Adapter(opts);
        this.scheduleUpto = 12; // (months) Able to schedule up to one year
        const monthMapping = {
            'jan': 1,
            'feb': 2,
            'mar': 3,
            'apr': 4,
            'may': 5,
            'jun': 6,
            'jul': 7,
            'aug': 8,
            'sep': 9,
            'oct': 10,
            'nov': 11,
            'dec': 12
        };
        this.monthMap = new Map();
        for (let month of Object.keys(monthMapping)) {
            this.monthMap.set(month, monthMapping[month]);
        }
    }

    /**
     * Set the limit against particular id. Then this limit will consider as
     * limit for every month
     * @param id {Integer/String} ID (appId or userId) which want to limit
     * @param limit {Integer} Limit value
     */
    setLimit(id, limit) {
        return this.adapter.setLimit(id, limit);
    }

    /**
     * Get the stored limit against particular ID
     * @param id {Integer/String} ID (appId or userId) which want to limit
     * @return {Integer} Limit value
     */
    getLimit(id) {
        return this.adapter.getLimit(id);
    }

    /**
     * Set the limit against particular id. Then this limit will consider as
     * limit for every month
     * @param limit {Array} Array of limit Objects s.t.
     * [{'userId': 1000}, {'userId2: 500}, ...]
     */
    setLimits(limits) {

    }

    /**
     * Get the current usage (used tokens) against a particular id.
     * @param id {Integer/String} ID (appId or userId) which want to limit
     * @param months {Object} Object which contains Months Array s.t.
     * {'2015': ['Jan', 'feb', 3, '4']}
     * @param includeLimit {Boolean} Whether include current limit (Optional) Default `false`
     * @return {Object} Remaining limits for each month s.t.
     * {'2015': {'1': 10, '2': 15, '3': 20, '4': 30}}
     */
    getUsage(id, months, includeLimit) {
        this.adapter.getUsage(id, months, includeLimit);
    }

    /**
     * Increase the usage value of given set of months against particular ID.
     * If successfully increase the values, return values after increment.
     * Otherwise rollback to previous state and return an error.
     * @param id {Integer/String} ID (appId or userId) which want to limit
     * @param tokens {Object} Number of tokens which want to use s.t.
     * {'2015': {'Jan': 10, 'feb': 15, 3: 20, '4': 30}, '2016': {'1': 40}}
     * @return {Object} Remaining limits for each month s.t.
     * {'2015': {'1': 10, '2': 15, '3': 20, '4': 30}, '2016': {'1': 40}}
     */
    createSchedule(id, tokens, force) {
        debug(`CreateSchedule ${id} tokens: `, tokens);
        if (!isNaN(tokens)) { // if a number, then create an Obj for current month
            const month = new Date().getMonth() + 1;
            tokens = [{
                month: tokens
            }];
        }
        // Set force default value as 'false'
        force = force || false;

        /**
         * Reference: http://redis.io/commands/incr#pattern-rate-limiter
         *
         * There are two approach to check the limit and set the values
         * 1. Increase the usage with given token values, then compare return
         *    values (new usage) with limit whether it exceeds
         *    -> If exceeds > rollback
         *    -> Otherwise > do nothing
         * E.g. In Redis, one database call (when exceeds, two database calls)
         * 2. Get the usage according to given tokens, then compare with limit
         *    by considering if it increase the token value, then exceeds the
         *    limit
         *    -> If exceeds > do nothing
         *    -> Otherwise  > increase the usage
         * E.g. In Redis, two database call (when exceeds, one database calls)
         *
         * Both options have a race condition, which can be neglectable.
         */

        // TODO: 1nd option implementation (should be able to one of them)

        // 2nd option implementation
        const formattedTokens = this._formatMonths(tokens);
        let months = {};
        for (let year of Object.keys(formattedTokens)) {
            months[year] = Object.keys(formattedTokens[year]);
        }

        return new Promise((resolve, reject) => {
            this.adapter.getUsage(id, months, true).then(usage => {
                const limit = usage.limit;
                // Delete `limit` field
                delete usage.limit;
                const isExceed = this._isExceed(limit, usage, formattedTokens);
                if (isExceed.state) {
                    this.adapter.increaseValues(id, isExceed.tokens).
                    then(usage => {
                        resolve(usage);
                    }).catch(err => {
                        reject(err);
                    });
                } else {
                    reject(new Error(isExceed.message));
                }
            }).catch(err => {
                reject(err);
            });
        }); // END - 2nd Option
    }

    /**
     * Cancel previously schedule by decrease the usage value of given set of
     * months against particular ID.
     * If successfully decrease the values, return values after decrement.
     * Otherwise rollback to previous state and return an error.
     * @param id {Integer/String} ID (appId or userId) which want to limit
     * @param tokens {Object} Number of tokens which want to use s.t.
     * {'2015': {'Jan' 10, 'feb': 15, 3: 20}, '2016': {'4': 30}}
     * @return {Object} Remaining limits for each month s.t.
     * {'2015': {'1': 10, '2': 15, '3': 20}, '2016': {'4': 30}}
     */
    cancelSchedule(id, tokens, force) {
        debug(`CancelSchedule ${id} tokens: `, tokens);

        if (!isNaN(tokens)) { //if a number,then create an Obj for current month
            const month = new Date().getMonth() + 1;
            tokens = {
                month: tokens
            };
        }
        force = force || false;

        // 2nd Option implementation (reverse)
        const formattedTokens = this._formatMonths(tokens);
        let months = {};
        for (let year of Object.keys(formattedTokens)) {
            months[year] = Object.keys(formattedTokens[year]);
        }

        return new Promise((resolve, reject) => {
            this.adapter.getUsage(id, months).then(usage => {
                const isNegative = this._isNegative(usage, formattedTokens);
                if (isNegative.state) {
                    this.adapter.decreaseValues(id, isNegative.tokens).
                        then(usage => {
                            resolve(usage);
                        }).catch(err => {
                            reject(err);
                        });
                } else {
                    reject(new Error(isNegative.message));
                }
            }).catch(err => {
                reject(err);
            });
        }); // END - 2nd Option
    }

    /**
     * Format mixed month keys into Number format
     * @param tokens {Object} Number of tokens which want to use s.t.
     * {'2015': {'Jan' 10, 'feb': 15, 3: 20}, '2016': {'4': 30}}
     * @return {Object} Formatted token keys for each month s.t.
     * {'2015': {'1': 10, '2': 15, '3': 20}, '2016': {'4': 30}}
     */
    _formatMonths(tokens) {
        debug('_formatMonths tokens: ', tokens);

        let formattedTokens = {};
        for (let year of Object.keys(tokens)) {
            formattedTokens[year] = {};
            for (let month of Object.keys(tokens[year])) {
                let monthNumber = (isNaN(month)) ?
                    this.monthMap.get(month.toLowerCase()) : month;
                formattedTokens[year][monthNumber] = tokens[year][month];
            }
        }

        return formattedTokens;
    }

    _isExceed(limit, usage, tokens) {
        debug('_isExceed args : ', limit, usage, tokens);
        // If force enabled, possible removable token size get changed
        let newTokens = tokens;

        for (let year of Object.keys(usage)) {
            for (let month of Object.keys(usage[year])) {
                if (usage[year][month] + tokens[year][month] > limit) {
                    return {
                        state: false,
                        message: `Required amount of ${usage[year][month]} ` +
                          `exceeds the limit ${limit} in ${year}-${month} by ` +
                          `${usage[year][month]+tokens[year][month] - limit)}.` +
                          ` Remained amount is ${limit - usage[year][month]}`
                    };
                }
            }
        }
        return {
            state: true,
            tokens: newTokens
        };
    }

    _isNegative(usage, tokens) {
        // If force enabled, possible removable token size get changed
        let newTokens = tokens;

        for (let year of Object.keys(usage)) {
            for (let month of Object.keys(usage[year])) {
                if ((usage[year][month] - tokens[year][month]) < 0) {
                    return {
                        state: false,
                        message: `Usage ${usage[year][month]} can't less than 0 in ${year}-${month}`
                    };
                }
            }
        }
        return {
            state: true,
            tokens: newTokens
        };
    }

};

// export default ScheduleLimiter;
<|endoftext|>


<commit_before>/**
 *
 *  Web Starter Kit
 *  Copyright 2015 Google Inc. All rights reserved.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License
 *
 */

'use strict';

// Include gulp & tools we'll use
var gulp = require('gulp');
var $ = require('gulp-load-plugins')();
var del = require('del');
var runSequence = require('run-sequence');
var browserSync = require('browser-sync');
var pagespeed = require('psi');
var reload = browserSync.reload;
var swPrecache = require('sw-precache');
var fs = require('fs');
var path = require('path');
var packageJson = require('./package.json');

// Lint JavaScript
gulp.task('jshint', function () {
  return gulp.src(['app/scripts/**/*.js','!app/scripts/vendor/**/*'])
    .pipe(reload({stream: true, once: true}))
    .pipe($.jshint())
    .pipe($.jshint.reporter('jshint-stylish'))
    .pipe($.if(!browserSync.active, $.jshint.reporter('fail')));
});

// Optimize images
gulp.task('images', function () {
  return gulp.src('app/images/**/*')
    .pipe($.cache($.imagemin({
      progressive: true,
      interlaced: true
    })))
    .pipe(gulp.dest('dist/images'))
    .pipe($.size({title: 'images'}));
});

// Copy all files at the root level (app)
gulp.task('copy', function () {
  return gulp.src([
    'app/*',
    '!app/*.html',
    'node_modules/apache-server-configs/dist/.htaccess'
  ], {
    dot: true
  }).pipe(gulp.dest('dist'))
    .pipe($.size({title: 'copy'}));
});

// Copy web fonts to dist
gulp.task('fonts', function () {
  return gulp.src(['app/fonts/**'])
    .pipe(gulp.dest('dist/fonts'))
    .pipe($.size({title: 'fonts'}));
});

// Compile and automatically prefix stylesheets
gulp.task('styles', function () {

  var AUTOPREFIXER_BROWSERS = [
    'ie >= 10',
    'ie_mob >= 10',
    'ff >= 30',
    'chrome >= 34',
    'safari >= 7',
    'opera >= 23',
    'ios >= 7',
    'android >= 4.4',
    'bb >= 10'
  ];

  // For best performance, don't add Sass partials to `gulp.src`
  return gulp.src([
    'app/**/*.scss',
    'app/styles/**/*.css'
  ])
    .pipe($.changed('.tmp/styles', {extension: '.css'}))
    .pipe($.sourcemaps.init())
    .pipe($.sass({
      precision: 10
    }).on('error', $.sass.logError))
    .pipe($.autoprefixer(AUTOPREFIXER_BROWSERS))
    .pipe(gulp.dest('.tmp'))
    // Concatenate and minify styles
    .pipe($.if('*.css', $.csso()))
    .pipe($.sourcemaps.write())
    .pipe(gulp.dest('dist'))
    .pipe($.size({title: 'styles'}));
});

// Concatenate and minify JavaScript
gulp.task('scripts', function () {
  var sources = ['./app/scripts/main.js'];
  return gulp.src(sources)
    .pipe($.concat('main.min.js'))
    .pipe($.uglify({preserveComments: 'some'}))
    // Output files
    .pipe(gulp.dest('dist/scripts'))
    .pipe($.size({title: 'scripts'}));
});

// Concatenate and vendor JavaScript
gulp.task('scripts:vendor', function () {
  var sources = [
    './app/scripts/vendor/jquery/dist/jquery.min.js',
    './app/scripts/vendor/knockout/dist/knockout.js'
  ];
  return gulp.src(sources)
    .pipe($.concat('vendor.min.js'))
    .pipe($.uglify())
    .pipe(gulp.dest('dist/scripts'))
    .pipe($.size({title: 'scripts:vendor'}));
});

// Scan your HTML for assets & optimize them
gulp.task('html', function () {
  var assets = $.useref.assets({searchPath: '{.tmp,app}'});

  return gulp.src('app/**/**/*.html')
    .pipe(assets)
    // Remove any unused CSS
    .pipe($.if('*.css', $.uncss({
      html: [
        'app/index.html'
      ],
      // CSS Selectors for UnCSS to ignore
      ignore: [
        /.navdrawer-container.open/,
        /.app-bar.open/
      ]
    })))

    // Concatenate and minify styles
    // In case you are still using useref build blocks
    .pipe($.if('*.css', $.csso()))
    .pipe(assets.restore())
    .pipe($.useref())

    // Minify any HTML
    .pipe($.if('*.html', $.minifyHtml()))
    // Output files
    .pipe(gulp.dest('dist'))
    .pipe($.size({title: 'html'}));
});

// Clean output directory
gulp.task('clean', del.bind(null, ['.tmp', 'dist/*', '!dist/.git'], {dot: true}));

// Watch files for changes & reload
gulp.task('serve', ['styles'], function () {
  browserSync({
    notify: false,
    // Customize the BrowserSync console logging prefix
    logPrefix: 'WSK',
    server: ['.tmp', 'app']
  });

  gulp.watch(['app/**/*.html'], reload);
  gulp.watch(['app/styles/**/*.{scss,css}'], ['styles', reload]);
  gulp.watch(['app/scripts/**/*.js'], ['jshint']);
  gulp.watch(['app/images/**/*'], reload);
});

// Build and serve the output from the dist build
gulp.task('serve:dist', ['default'], function () {
  browserSync({
    notify: false,
    logPrefix: 'WSK',
    server: 'dist',
    baseDir: 'dist'
  });
});

// Build production files, the default task
gulp.task('default', ['clean'], function (cb) {
  runSequence(
    'styles',
    ['jshint', 'html', 'scripts', 'scripts:vendor', 'images', 'fonts', 'copy'],
    cb);
});

// Load custom tasks from the `tasks` directory
// try { require('require-dir')('tasks'); } catch (err) { console.error(err); }
<commit_msg>update vendor scripts sources<commit_after>/**
 *
 *  Web Starter Kit
 *  Copyright 2015 Google Inc. All rights reserved.
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *      https://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License
 *
 */

'use strict';

// Include gulp & tools we'll use
var gulp = require('gulp');
var $ = require('gulp-load-plugins')();
var del = require('del');
var runSequence = require('run-sequence');
var browserSync = require('browser-sync');
var pagespeed = require('psi');
var reload = browserSync.reload;
var swPrecache = require('sw-precache');
var fs = require('fs');
var path = require('path');
var packageJson = require('./package.json');

// Lint JavaScript
gulp.task('jshint', function () {
  return gulp.src(['app/scripts/**/*.js','!app/scripts/vendor/**/*'])
    .pipe(reload({stream: true, once: true}))
    .pipe($.jshint())
    .pipe($.jshint.reporter('jshint-stylish'))
    .pipe($.if(!browserSync.active, $.jshint.reporter('fail')));
});

// Optimize images
gulp.task('images', function () {
  return gulp.src('app/images/**/*')
    .pipe($.cache($.imagemin({
      progressive: true,
      interlaced: true
    })))
    .pipe(gulp.dest('dist/images'))
    .pipe($.size({title: 'images'}));
});

// Copy all files at the root level (app)
gulp.task('copy', function () {
  return gulp.src([
    'app/*',
    '!app/*.html',
    'node_modules/apache-server-configs/dist/.htaccess'
  ], {
    dot: true
  }).pipe(gulp.dest('dist'))
    .pipe($.size({title: 'copy'}));
});

// Copy web fonts to dist
gulp.task('fonts', function () {
  return gulp.src(['app/fonts/**'])
    .pipe(gulp.dest('dist/fonts'))
    .pipe($.size({title: 'fonts'}));
});

// Compile and automatically prefix stylesheets
gulp.task('styles', function () {

  var AUTOPREFIXER_BROWSERS = [
    'ie >= 10',
    'ie_mob >= 10',
    'ff >= 30',
    'chrome >= 34',
    'safari >= 7',
    'opera >= 23',
    'ios >= 7',
    'android >= 4.4',
    'bb >= 10'
  ];

  // For best performance, don't add Sass partials to `gulp.src`
  return gulp.src([
    'app/**/*.scss',
    'app/styles/**/*.css'
  ])
    .pipe($.changed('.tmp/styles', {extension: '.css'}))
    .pipe($.sourcemaps.init())
    .pipe($.sass({
      precision: 10
    }).on('error', $.sass.logError))
    .pipe($.autoprefixer(AUTOPREFIXER_BROWSERS))
    .pipe(gulp.dest('.tmp'))
    // Concatenate and minify styles
    .pipe($.if('*.css', $.csso()))
    .pipe($.sourcemaps.write())
    .pipe(gulp.dest('dist'))
    .pipe($.size({title: 'styles'}));
});

// Concatenate and minify JavaScript
gulp.task('scripts', function () {
  var sources = ['./app/scripts/main.js'];
  return gulp.src(sources)
    .pipe($.concat('main.min.js'))
    .pipe($.uglify({preserveComments: 'some'}))
    // Output files
    .pipe(gulp.dest('dist/scripts'))
    .pipe($.size({title: 'scripts'}));
});

// Concatenate and vendor JavaScript
gulp.task('scripts:vendor', function () {
  var sources = ['./app/scripts/vendor/**/*.js'];
  return gulp.src(sources)
    .pipe($.concat('vendor.min.js'))
    .pipe($.uglify())
    .pipe(gulp.dest('dist/scripts'))
    .pipe($.size({title: 'scripts:vendor'}));
});

// Scan your HTML for assets & optimize them
gulp.task('html', function () {
  var assets = $.useref.assets({searchPath: '{.tmp,app}'});

  return gulp.src('app/**/**/*.html')
    .pipe(assets)
    // Remove any unused CSS
    .pipe($.if('*.css', $.uncss({
      html: [
        'app/index.html'
      ],
      // CSS Selectors for UnCSS to ignore
      ignore: [
        /.navdrawer-container.open/,
        /.app-bar.open/
      ]
    })))

    // Concatenate and minify styles
    // In case you are still using useref build blocks
    .pipe($.if('*.css', $.csso()))
    .pipe(assets.restore())
    .pipe($.useref())

    // Minify any HTML
    .pipe($.if('*.html', $.minifyHtml()))
    // Output files
    .pipe(gulp.dest('dist'))
    .pipe($.size({title: 'html'}));
});

// Clean output directory
gulp.task('clean', del.bind(null, ['.tmp', 'dist/*', '!dist/.git'], {dot: true}));

// Watch files for changes & reload
gulp.task('serve', ['styles'], function () {
  browserSync({
    notify: false,
    // Customize the BrowserSync console logging prefix
    logPrefix: 'WSK',
    server: ['.tmp', 'app']
  });

  gulp.watch(['app/**/*.html'], reload);
  gulp.watch(['app/styles/**/*.{scss,css}'], ['styles', reload]);
  gulp.watch(['app/scripts/**/*.js'], ['jshint']);
  gulp.watch(['app/images/**/*'], reload);
});

// Build and serve the output from the dist build
gulp.task('serve:dist', ['default'], function () {
  browserSync({
    notify: false,
    logPrefix: 'WSK',
    server: 'dist',
    baseDir: 'dist'
  });
});

// Build production files, the default task
gulp.task('default', ['clean'], function (cb) {
  runSequence(
    'styles',
    ['jshint', 'html', 'scripts', 'scripts:vendor', 'images', 'fonts', 'copy'],
    cb);
});

// Load custom tasks from the `tasks` directory
// try { require('require-dir')('tasks'); } catch (err) { console.error(err); }
<|endoftext|>


<commit_before>/**
* Copyright 2012-2016, Plotly, Inc.
* All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

'use strict';

var Plotly = require('./core');

Plotly.register([
    require('./bar'),
    require('./box'),
    require('./heatmap'),
    require('./histogram'),
    require('./histogram2d'),
    require('./histogram2dcontour'),
    require('./pie'),
    require('./contour'),
    require('./scatter3d'),
    require('./surface'),
    require('./mesh3d'),
    require('./scattergeo'),
    require('./choropleth'),
    require('./scattergl'),
    require('./scatterternary')
]);

module.exports = Plotly;
<commit_msg>add 'scattermapbox' to main plotly.js bundle<commit_after>/**
* Copyright 2012-2016, Plotly, Inc.
* All rights reserved.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*/

'use strict';

var Plotly = require('./core');

Plotly.register([
    require('./bar'),
    require('./box'),
    require('./heatmap'),
    require('./histogram'),
    require('./histogram2d'),
    require('./histogram2dcontour'),
    require('./pie'),
    require('./contour'),
    require('./scatter3d'),
    require('./surface'),
    require('./mesh3d'),
    require('./scattergeo'),
    require('./choropleth'),
    require('./scattergl'),
    require('./scatterternary'),
    require('./scattermapbox')
]);

module.exports = Plotly;
<|endoftext|>


<commit_before>var express = require('express');
var app = express();
var port = 3000;

app.set('views', __dirname + '/templates');
app.set('view engine', "jade");
app.engine('jade', require('jade').__express); // 'splain this

app.get('/', function(req, res) {
  res.render('chat');
});

app.use(express.static(__dirname + '/public'));

//app.listen(port);
var io = require('socket.io').listen(app.listen(port));
console.log('Listening on port ' + port);

io.sockets.on('connection', function (socket) {

  socket.emit('message', { message: 'welcome to the chat', timestamp: new Date().getTime() });

  socket.on('send', function (data) {
    data.timestamp = new Date().getTime();
    io.sockets.emit('message', data);
  });

  socket.on('typing', function(data) {
    io.sockets.emit('typing', data);
  });

  socket.on('stopped typing', function(data) {
    io.sockets.emit('stopped typing', data);
  });

});
<commit_msg>change port<commit_after>var express = require('express');
var app = express();
var port = process.env.PORT || 8000;

app.set('views', __dirname + '/templates');
app.set('view engine', "jade");
app.engine('jade', require('jade').__express); // 'splain this

app.get('/', function(req, res) {
  res.render('chat');
});

app.use(express.static(__dirname + '/public'));

//app.listen(port);
var io = require('socket.io').listen(app.listen(port));
console.log('Listening on port ' + port);

io.sockets.on('connection', function (socket) {

  socket.emit('message', { message: 'welcome to the chat', timestamp: new Date().getTime() });

  socket.on('send', function (data) {
    data.timestamp = new Date().getTime();
    io.sockets.emit('message', data);
  });

  socket.on('typing', function(data) {
    io.sockets.emit('typing', data);
  });

  socket.on('stopped typing', function(data) {
    io.sockets.emit('stopped typing', data);
  });

});
<|endoftext|>