<commit_before>var cont     = require('cont')
var pull     = require('pull-stream')
var defer    = require('pull-defer')
var path     = require('path')
var explain  = require('explain-error')
var mkdirp   = require('mkdirp')
var rimraf   = require('rimraf')
var fs       = require('fs')
var glob     = require('pull-glob')
var paramap  = require('pull-paramap')
var cat      = require('pull-cat')
var Notify   = require('pull-notify')
var Live     = require('pull-live')
var Write    = require('pull-write-file')
var Read     = require('pull-file')
var Catch    = require('pull-catch')

var u = require('./util')
var createHash = u.createHash

function write (filename, cb) {
  return WriteFile(filename, cb)
}

function readFile (...args) {
  return pull(
    Read(...args),
    Catch(err => {
      err.message = 'could not get blob'

      // delete sensitive metadata
      err.path = null
      err.dest = null

      return false // pass along error
    })
  )
};

function toArray (h) {
  return Array.isArray(h) ? h : [h]
}

function single (fn) {
  var waiting = {}
  function async (key, cb) {
    if(!waiting[key]) {
      waiting[key] = [cb]
      var cbs = waiting[key]
      fn(key, function done (err, result) {
        if(cbs.length)
        delete waiting[key]
        while(cbs.length) cbs.shift()(err, result)
      })
    }
    else
      waiting[key].push(cb)
  }

  //dump all the things that have been done already,
  //when something has been added?
  async.done = function (key, err, value) {
    if(!waiting[key]) return
    var cbs = waiting[key]
    delete waiting[key]
    while(cbs.length) cbs.shift()(err, result)
  }

  return async
}

var Blobs = module.exports = function (config) {
  var dir
  if('string' === typeof config)
    dir = config, config = {dir: dir}

  var encode = config.encode || u.encode
  var decode = config.decode || u.decode
  var isHash = config.isHash || u.isHash

  function toPath (dir, string) {
    if(!string || !isHash(string)) return false
    var d = decode(string)
    var h = d.hash.toString('hex')
    return path.join(dir, d.alg, h.substring(0,2), h.substring(2))
  }

  function toHash(filename) {
    var parts = path.relative(dir, filename).split(path.sep)
    var alg = parts.shift()
    return encode(new Buffer(parts.join(''), 'hex'), alg)
  }

  var newBlob = Notify()

  config = config || {}
  var alg = config.hash = config.hash || config.alg || 'blake2s'

  var empty = u.encode(u.algs[alg]().digest(), alg)

  function isEmptyHash(hash) {
    return empty === hash
  }

  dir = config.dir

  var n = 0
  var waiting = [], tmp = false, clean = false

  function init (cb) {
    if(tmp) return cb()
    else waiting.push(cb)
  }

  var stat = single(fs.stat)

  var tmpdir = path.join(dir, 'tmp')

  rimraf(tmpdir, function () {
    mkdirp(tmpdir, function () {
      tmp = true; while(waiting.length) waiting.shift()()
    })
  })

  function toMeta(hash, stat) {
    if(!stat) return null
    return {id: hash, size: stat.size, ts: +stat.ctime}
  }

  function has (hash) {
    return function (cb) {
      if(isEmptyHash(hash)) return cb(null, true)
      var p = toPath(dir, hash)
      if(!p) return cb(new Error('not a valid blob hash:'+hash))
      stat(p, function (err, stat) {
        cb(null, !!stat)
      })
    }
  }

  function size (hash) {
    return function (cb) {
      if(isEmptyHash(hash)) return cb(null, 0)
      var p = toPath(dir, hash)
      if(!p) return cb(new Error('not a valid blob hash:'+hash))
      stat(p, function (err, stat) {
        cb(null, stat ? stat.size : null)
      })
    }
  }

  var meta = function (hash, cb) {
    if(isEmptyHash(hash)) return cb(null, {id: hash, size: 0, ts: 0})
    stat(toPath(dir, hash), function (err, stat) {
      cb(err, toMeta(hash, stat))
    })
  }

  function createTester (test) {
    return function (hashes, cb) {
      var n = !Array.isArray(hashes)
      //check if any hashes are invalid.
      var invalid
      if(n ? !isHash(hashes) : !hashes.every(function (h) {
        if(!isHash(h)) invalid = h
        else return true
      }))
        return cb(new Error('not a valid hash:'+invalid))

      cont.para(toArray(hashes).map(test)) (function (err, ary) {
        //will give an error if any hash was invalid.
        if(err) cb(err)
        // This will only error if the hash is not present,
        // so never callback an error.
        // PS. if you have a situation where you never error
        // add a comment like this one to explain why.
        else if(n) cb(null, ary[0])
        else       cb(null, ary)
      })
      return cb
    }
  }

  var listeners = []

  function getSlice(opts) {
    if(isEmptyHash(opts.hash)) return pull.empty()

    var stream = defer.source()
    stat(toPath(dir, opts.hash), function (err, stat) {
      if(err)
        stream.abort(explain(err, 'stat failed'))

      else if(opts.size != null && opts.size !== stat.size)
        stream.abort(new Error('incorrect file length,'
          + ' requested:' + opts.size + ' file was:' + stat.size
          + ' for file:' + opts.hash
        ))

      else if(opts.max != null && opts.max < stat.size)
        stream.abort(new Error('incorrect file length,'
          + ' requested:' + opts.size + ' file was:' + stat.size
          + ' for file:' + opts.hash
        ))

      else
        stream.resolve(readFile(toPath(dir, opts.hash), {
          start: opts.start,
          end: opts.end
        }))
    })

    return stream
  }

  return {
    get: function (opts) {
      if(isHash(opts)) {
        if(isEmptyHash(hash)) return pull.empty()
        return readFile(toPath(dir, opts))
      }
      var hash = opts.key || opts.hash
      if(!isHash(hash))
        return pull.error(new Error(
          'multiblob.get: {hash} is mandatory'
        ))

      return getSlice({hash: hash, size: opts.size, max: opts.max})
    },
    isEmptyHash: isEmptyHash,

    getSlice: function (opts) {
      if(!isHash(opts.hash))
        return pull.error(new Error(
          'multiblob.getSlice: {hash} is mandatory'
        ))

      if(isNaN(opts.start))
        return pull.error(new Error(
          'multiblob.getSlice: {start} must be a number'
        ))

      if(isNaN(opts.end))
        return pull.error(new Error(
          'multiblob.getSlice: {end} must be a number'
        ))

      return getSlice(opts)
    },

    size: createTester(size),

    has: createTester(has),
    meta: meta,

    add: function (hash, cb) {
      if('function' === typeof hash) cb = hash, hash = null

      if(!cb) cb = function (err) {
        if(err) throw explain(err, 'no callback provided')
      }

      if(hash && !isHash(hash)) {
        //abort input stream and callback once source is aborted.
        var err = new Error('not a valid hash:'+hash)
        return function (read) {
          read(err, cb)
        }
      }

      var deferred = defer.sink()
      init(function () {
        var tmpfile = path.join(dir, 'tmp', Date.now() + '-' + n++)
        var hasher = createHash(alg, true)
        var size = 0

        deferred.resolve(pull(
          hasher,
          pull.map(function (data) {
            if('string' === typeof data) data = new Buffer(data, 'utf8')
            size += data.length
            return data
          }),
          Write(tmpfile, function (err) {
            if(err) return cb(explain(err, 'could not write to tmpfile'))

            var _hash = encode(hasher.digest, alg)

            if(hash && hash !== _hash)
              return cb(new Error('actual hash:'+ _hash
                + ' did not match expected hash:'+hash), _hash)

            var p = toPath(dir, hash || _hash)

            mkdirp(path.dirname(p), function () {
              fs.rename(tmpfile, p, function (err) {
                if(err) cb(explain(err, 'could not move file'))
                else    newBlob({id:toHash(p), size: size, ts: Date.now()}), cb(null, _hash)
              })
            })
          })
        ))
      })

      return deferred
    },

    ls: Live(function old (opts) {
      var long = (opts.size || opts.long || opts.meta)
      return pull(
        glob(path.join(dir, '*', '*', '*')),
        long ? paramap(function (filename, cb) {
          stat(filename, function (err, stat) {
            cb(err, toMeta(toHash(filename), stat))
          })
        }, 32) : pull.map(toHash)
      )
    }, function live (opts) {
      var long = (opts.size || opts.long || opts.meta)
      return long
          ? newBlob.listen()
          : pull(newBlob.listen(), pull.map(function (e) { return e.id }))
    }),

    rm: function (hash, cb) {
      if(!isHash(hash)) cb(new Error('not valid hash:'+hash))
      else              fs.unlink(toPath(dir, hash), cb)
    },

    resolve: function (hash) {
      if(!isHash(hash)) throw new Error('not valid hash:'+hash)
      return toPath(dir, hash)
    }
  }
}

<commit_msg>Log file read errors except ENOENT<commit_after>var cont     = require('cont')
var pull     = require('pull-stream')
var defer    = require('pull-defer')
var path     = require('path')
var explain  = require('explain-error')
var mkdirp   = require('mkdirp')
var rimraf   = require('rimraf')
var fs       = require('fs')
var glob     = require('pull-glob')
var paramap  = require('pull-paramap')
var cat      = require('pull-cat')
var Notify   = require('pull-notify')
var Live     = require('pull-live')
var Write    = require('pull-write-file')
var Read     = require('pull-file')
var Catch    = require('pull-catch')

var u = require('./util')
var createHash = u.createHash

function write (filename, cb) {
  return WriteFile(filename, cb)
}

function readFile (...args) {
  return pull(
    Read(...args),
    Catch(err => {
      if (err.code !== 'ENOENT') {
        console.error(new Error(err))
      }

      err.message = 'could not get blob'

      // delete sensitive metadata
      err.path = null
      err.dest = null

      return false // pass along error
    })
  )
};

function toArray (h) {
  return Array.isArray(h) ? h : [h]
}

function single (fn) {
  var waiting = {}
  function async (key, cb) {
    if(!waiting[key]) {
      waiting[key] = [cb]
      var cbs = waiting[key]
      fn(key, function done (err, result) {
        if(cbs.length)
        delete waiting[key]
        while(cbs.length) cbs.shift()(err, result)
      })
    }
    else
      waiting[key].push(cb)
  }

  //dump all the things that have been done already,
  //when something has been added?
  async.done = function (key, err, value) {
    if(!waiting[key]) return
    var cbs = waiting[key]
    delete waiting[key]
    while(cbs.length) cbs.shift()(err, result)
  }

  return async
}

var Blobs = module.exports = function (config) {
  var dir
  if('string' === typeof config)
    dir = config, config = {dir: dir}

  var encode = config.encode || u.encode
  var decode = config.decode || u.decode
  var isHash = config.isHash || u.isHash

  function toPath (dir, string) {
    if(!string || !isHash(string)) return false
    var d = decode(string)
    var h = d.hash.toString('hex')
    return path.join(dir, d.alg, h.substring(0,2), h.substring(2))
  }

  function toHash(filename) {
    var parts = path.relative(dir, filename).split(path.sep)
    var alg = parts.shift()
    return encode(new Buffer(parts.join(''), 'hex'), alg)
  }

  var newBlob = Notify()

  config = config || {}
  var alg = config.hash = config.hash || config.alg || 'blake2s'

  var empty = u.encode(u.algs[alg]().digest(), alg)

  function isEmptyHash(hash) {
    return empty === hash
  }

  dir = config.dir

  var n = 0
  var waiting = [], tmp = false, clean = false

  function init (cb) {
    if(tmp) return cb()
    else waiting.push(cb)
  }

  var stat = single(fs.stat)

  var tmpdir = path.join(dir, 'tmp')

  rimraf(tmpdir, function () {
    mkdirp(tmpdir, function () {
      tmp = true; while(waiting.length) waiting.shift()()
    })
  })

  function toMeta(hash, stat) {
    if(!stat) return null
    return {id: hash, size: stat.size, ts: +stat.ctime}
  }

  function has (hash) {
    return function (cb) {
      if(isEmptyHash(hash)) return cb(null, true)
      var p = toPath(dir, hash)
      if(!p) return cb(new Error('not a valid blob hash:'+hash))
      stat(p, function (err, stat) {
        cb(null, !!stat)
      })
    }
  }

  function size (hash) {
    return function (cb) {
      if(isEmptyHash(hash)) return cb(null, 0)
      var p = toPath(dir, hash)
      if(!p) return cb(new Error('not a valid blob hash:'+hash))
      stat(p, function (err, stat) {
        cb(null, stat ? stat.size : null)
      })
    }
  }

  var meta = function (hash, cb) {
    if(isEmptyHash(hash)) return cb(null, {id: hash, size: 0, ts: 0})
    stat(toPath(dir, hash), function (err, stat) {
      cb(err, toMeta(hash, stat))
    })
  }

  function createTester (test) {
    return function (hashes, cb) {
      var n = !Array.isArray(hashes)
      //check if any hashes are invalid.
      var invalid
      if(n ? !isHash(hashes) : !hashes.every(function (h) {
        if(!isHash(h)) invalid = h
        else return true
      }))
        return cb(new Error('not a valid hash:'+invalid))

      cont.para(toArray(hashes).map(test)) (function (err, ary) {
        //will give an error if any hash was invalid.
        if(err) cb(err)
        // This will only error if the hash is not present,
        // so never callback an error.
        // PS. if you have a situation where you never error
        // add a comment like this one to explain why.
        else if(n) cb(null, ary[0])
        else       cb(null, ary)
      })
      return cb
    }
  }

  var listeners = []

  function getSlice(opts) {
    if(isEmptyHash(opts.hash)) return pull.empty()

    var stream = defer.source()
    stat(toPath(dir, opts.hash), function (err, stat) {
      if(err)
        stream.abort(explain(err, 'stat failed'))

      else if(opts.size != null && opts.size !== stat.size)
        stream.abort(new Error('incorrect file length,'
          + ' requested:' + opts.size + ' file was:' + stat.size
          + ' for file:' + opts.hash
        ))

      else if(opts.max != null && opts.max < stat.size)
        stream.abort(new Error('incorrect file length,'
          + ' requested:' + opts.size + ' file was:' + stat.size
          + ' for file:' + opts.hash
        ))

      else
        stream.resolve(readFile(toPath(dir, opts.hash), {
          start: opts.start,
          end: opts.end
        }))
    })

    return stream
  }

  return {
    get: function (opts) {
      if(isHash(opts)) {
        if(isEmptyHash(hash)) return pull.empty()
        return readFile(toPath(dir, opts))
      }
      var hash = opts.key || opts.hash
      if(!isHash(hash))
        return pull.error(new Error(
          'multiblob.get: {hash} is mandatory'
        ))

      return getSlice({hash: hash, size: opts.size, max: opts.max})
    },
    isEmptyHash: isEmptyHash,

    getSlice: function (opts) {
      if(!isHash(opts.hash))
        return pull.error(new Error(
          'multiblob.getSlice: {hash} is mandatory'
        ))

      if(isNaN(opts.start))
        return pull.error(new Error(
          'multiblob.getSlice: {start} must be a number'
        ))

      if(isNaN(opts.end))
        return pull.error(new Error(
          'multiblob.getSlice: {end} must be a number'
        ))

      return getSlice(opts)
    },

    size: createTester(size),

    has: createTester(has),
    meta: meta,

    add: function (hash, cb) {
      if('function' === typeof hash) cb = hash, hash = null

      if(!cb) cb = function (err) {
        if(err) throw explain(err, 'no callback provided')
      }

      if(hash && !isHash(hash)) {
        //abort input stream and callback once source is aborted.
        var err = new Error('not a valid hash:'+hash)
        return function (read) {
          read(err, cb)
        }
      }

      var deferred = defer.sink()
      init(function () {
        var tmpfile = path.join(dir, 'tmp', Date.now() + '-' + n++)
        var hasher = createHash(alg, true)
        var size = 0

        deferred.resolve(pull(
          hasher,
          pull.map(function (data) {
            if('string' === typeof data) data = new Buffer(data, 'utf8')
            size += data.length
            return data
          }),
          Write(tmpfile, function (err) {
            if(err) return cb(explain(err, 'could not write to tmpfile'))

            var _hash = encode(hasher.digest, alg)

            if(hash && hash !== _hash)
              return cb(new Error('actual hash:'+ _hash
                + ' did not match expected hash:'+hash), _hash)

            var p = toPath(dir, hash || _hash)

            mkdirp(path.dirname(p), function () {
              fs.rename(tmpfile, p, function (err) {
                if(err) cb(explain(err, 'could not move file'))
                else    newBlob({id:toHash(p), size: size, ts: Date.now()}), cb(null, _hash)
              })
            })
          })
        ))
      })

      return deferred
    },

    ls: Live(function old (opts) {
      var long = (opts.size || opts.long || opts.meta)
      return pull(
        glob(path.join(dir, '*', '*', '*')),
        long ? paramap(function (filename, cb) {
          stat(filename, function (err, stat) {
            cb(err, toMeta(toHash(filename), stat))
          })
        }, 32) : pull.map(toHash)
      )
    }, function live (opts) {
      var long = (opts.size || opts.long || opts.meta)
      return long
          ? newBlob.listen()
          : pull(newBlob.listen(), pull.map(function (e) { return e.id }))
    }),

    rm: function (hash, cb) {
      if(!isHash(hash)) cb(new Error('not valid hash:'+hash))
      else              fs.unlink(toPath(dir, hash), cb)
    },

    resolve: function (hash) {
      if(!isHash(hash)) throw new Error('not valid hash:'+hash)
      return toPath(dir, hash)
    }
  }
}

<|endoftext|>


<commit_before>var server = require('http').createServer()
var wr = require('./water_rower.js')({ debug: false} );
var ws = require('ws');
var url = require('url')
var WebSocketServer = ws.Server
var wsServer = new WebSocketServer({ server: server });

var parseArgs = require('minimist');
var argv = parseArgs( process.argv , {
  number: [ 'port' ],
  string: [ 'comport' ],
  boolean: [ 'debug']
});

var port = argv.port || 'NULL';
var debug = argv.debug || false;
var comport = argv.comport;

var rower = new wr.WaterRower({ port: comport });

var express = require('express');
var app = express();
app.get('/', function(req, res) {
  res.status(200).send('Hello, world!');
});

wsServer.on('connection', function connection(sock) {
  var location = url.parse(ws.upgradeReq.url, true);
  var updateListener = function(msg) {
    sock.send( JSON.stringify(msg) );
  };

  rower.on('readings', updateListener);

  sock.on('disconnect', function() {
    rower.removeListener(updateListener);
    console.log("Socket disconnect.");
  });

  console.log("Socket connect.");
});

console.log('Starting water rower.');
server.on('request', app);
server.listen(port, function () {
  console.log('Listening on ' + server.address().port)
});
<commit_msg>Fix last bad ref to ws.<commit_after>var server = require('http').createServer()
var wr = require('./water_rower.js')({ debug: false} );
var ws = require('ws');
var url = require('url')
var WebSocketServer = ws.Server
var wsServer = new WebSocketServer({ server: server });

var parseArgs = require('minimist');
var argv = parseArgs( process.argv , {
  number: [ 'port' ],
  string: [ 'comport' ],
  boolean: [ 'debug']
});

var port = argv.port || 'NULL';
var debug = argv.debug || false;
var comport = argv.comport;

var rower = new wr.WaterRower({ port: comport });

var express = require('express');
var app = express();
app.get('/', function(req, res) {
  res.status(200).send('Hello, world!');
});

wsServer.on('connection', function connection(sock) {
  var location = url.parse(sock.upgradeReq.url, true);
  var updateListener = function(msg) {
    sock.send( JSON.stringify(msg) );
  };

  rower.on('readings', updateListener);

  sock.on('disconnect', function() {
    rower.removeListener(updateListener);
    console.log("Socket disconnect.");
  });

  console.log("Socket connect.");
});

console.log('Starting water rower.');
server.on('request', app);
server.listen(port, function () {
  console.log('Listening on ' + server.address().port)
});
<|endoftext|>


<commit_before>'use strict'

const suffixes = new Map()
suffixes.set(3, 'K')
suffixes.set(6, 'M')
suffixes.set(9, 'B')
suffixes.set(12, 'T')

// Figure out the appropriate scale for the number
const scale = (num) => {
  let zeroes
  for (let z of suffixes.keys()) if (num > z) zeroes = z
  return { suffix: suffixes.get(zeroes), zeroes }
}

// Figure out how many digits in the integer
const digits = (num => Math.floor(Math.log10(Math.abs(num))) + 1)

// Make sure value is a number
const validate = (num => {
  num = parseFloat(num)
  if (isNaN(num)) throw new Error('Not a number')
  else return num
})

module.exports = (ugly, decimal) => {

  ugly = validate(ugly)

  const d = digits(ugly), s = scale(d)
  const pretty = ugly/Math.pow(10, s.zeroes)

  decimal = (pretty % 1 === 0) ? 1 : (decimal + 1) || 2

  if (ugly < 1000) return ugly
  else return `${parseFloat(pretty.toPrecision(decimal))}${s.suffix}`
}
<commit_msg>Makes sure decimal value supplied is at least 1<commit_after>'use strict'

const suffixes = new Map()
suffixes.set(3, 'K')
suffixes.set(6, 'M')
suffixes.set(9, 'B')
suffixes.set(12, 'T')

// Figure out the appropriate scale for the number
const scale = (num) => {
  let zeroes
  for (let z of suffixes.keys()) if (num > z) zeroes = z
  return { suffix: suffixes.get(zeroes), zeroes }
}

// Figure out how many digits in the integer
const digits = (num => Math.floor(Math.log10(Math.abs(num))) + 1)

// Make sure value is a number
const validate = (num => {
  num = parseFloat(num)
  if (isNaN(num)) throw new Error('Not a number')
  else return num
})

module.exports = (ugly, decimal) => {

  ugly = validate(ugly)

  const d = digits(ugly), s = scale(d)
  const pretty = ugly/Math.pow(10, s.zeroes)

  decimal = (pretty % 1 === 0) ? 1 : Math.max(1, (decimal + 1)) || 2

  if (ugly < 1000) return ugly
  else return `${parseFloat(pretty.toPrecision(decimal))}${s.suffix}`
}
<|endoftext|>


<commit_before>/* jshint node: true */
'use strict';

module.exports = {
  name: 'ember-django-adapter',

  included: function(app) {
    this._super.included(app);

    app.import('vendor/ember-django-adapter/register-version.js');
  }
};
<commit_msg>Add possibility to use this addon inside addon #163<commit_after>/* jshint node: true */
'use strict';

module.exports = {
  name: 'ember-django-adapter',

  included: function(app) {
    this._super.included.apply(this, arguments);

    // see: https://github.com/ember-cli/ember-cli/issues/3718
    if (typeof app.import !== 'function' && app.app) {
      app = app.app;
    }

    app.import('vendor/ember-django-adapter/register-version.js');
  }
};
<|endoftext|>


<commit_before>#!/usr/bin/env /usr/local/bin/node

// <bitbar.title>BitBus</bitbar.title>
// <bitbar.version>v1.0</bitbar.version>
// <bitbar.author>Robert Benjamin</bitbar.author>
// <bitbar.author.github>robertbenjamin</bitbar.author.github>
// <bitbar.desc>A BitBar menubar app for seeing when the next bus arrives at my work.</bitbar.desc>
// <bitbar.image>http://i.imgur.com/zjuQRQF.png</bitbar.image>
// <bitbar.dependencies>node,superagent,momentjs</bitbar.dependencies>
// <bitbar.abouturl>https://github.com/robertbenjamin/bit-bus</bitbar.abouturl>

const bitbar = require('bitbar');
const request = require('superagent');
const moment = require('moment');
const busAPIKey = require('./src/API_KEY.js') || 'TEST';

var busStop = 18610;
var busAPI = `http://api.pugetsound.onebusaway.org/api/where/arrivals-and-departures-for-stop/1_${busStop}.json?key=${busAPIKey}&minutesAfter=70`;
var menuColor = bitbar.darkMode ? 'white' : 'black';
var warningColor = '#ff4136';

request
.get(busAPI)
.end(function(err, res) {
  if (err || !res.ok) {
    bitbar([{
      text: ':bus: no internet :(',
      color: menuColor
    }]);
    return;
  }

  var response = JSON.parse(res.text);

  var trips = response.data.entry.arrivalsAndDepartures
    .filter(function(trip) {
      return trip.routeShortName == '32';
    })
    .map(function(trip) {
      var newTrip = {};

      newTrip.scheduledArrival = moment(trip.scheduledArrivalTime).fromNow();
      if (trip.predictedArrivalTime) {
        newTrip.predictedArrival = moment(trip.predictedArrivalTime).fromNow();
      }

      return newTrip;
    });

  var menu = [];
  menu.push({
    text: ':bus: ' + (trips[0].predictedArrival || trips[0].scheduledArrival),
    color: trips[0].predictedArrival ? menuColor : warningColor
  });

  menu.push(bitbar.sep);

  trips.slice(1).forEach(function(trip) {
    menu.push({
      text: ':point_right: ' + (trip.predictedArrival || trip.scheduledArrival),
      color: trip.predictedArrival ? menuColor : warningColor
    })
  });

  bitbar(menu);

});<commit_msg>ES6ify and change error text color<commit_after>#!/usr/bin/env /usr/local/bin/node

// <bitbar.title>BitBus</bitbar.title>
// <bitbar.version>v1.0</bitbar.version>
// <bitbar.author>Robert Benjamin</bitbar.author>
// <bitbar.author.github>robertbenjamin</bitbar.author.github>
// <bitbar.desc>A BitBar menubar app for seeing when the next bus arrives at my work.</bitbar.desc>
// <bitbar.image>http://i.imgur.com/zjuQRQF.png</bitbar.image>
// <bitbar.dependencies>node,superagent,momentjs</bitbar.dependencies>
// <bitbar.abouturl>https://github.com/robertbenjamin/bit-bus</bitbar.abouturl>

const bitbar = require('bitbar');
const request = require('superagent');
const moment = require('moment');
const busAPIKey = require('./src/API_KEY.js') || 'TEST';

let busStop = 18610;
let busAPI = `http://api.pugetsound.onebusaway.org/api/where/arrivals-and-departures-for-stop/1_${busStop}.json?key=${busAPIKey}&minutesAfter=70`;
let menuColor = bitbar.darkMode ? 'white' : 'black';
let warningColor = '#ff4136';

request
.get(busAPI)
.end((err, res) => {
  if (err || !res.ok) {
    bitbar([{
      text: ':bus: no internet :(',
      color: warningColor
    }]);
    return;
  }

  let response = JSON.parse(res.text);

  let trips = response.data.entry.arrivalsAndDepartures
    .filter((trip) => trip.routeShortName === '32')
    .map((trip) => {
      let newTrip = {};

      newTrip.scheduledArrival = moment(trip.scheduledArrivalTime).fromNow();
      if (trip.predictedArrivalTime) newTrip.predictedArrival = moment(trip.predictedArrivalTime).fromNow();

      return newTrip;
    });

  let menu = [];
  menu.push({
    text: `:bus: ${trips[0].predictedArrival || trips[0].scheduledArrival}`,
    color: trips[0].predictedArrival ? menuColor : warningColor
  });

  menu.push(bitbar.sep);

  trips.slice(1).forEach((trip) => {
    menu.push({
      text: `:point_right: ${trip.predictedArrival || trip.scheduledArrival}`,
      color: trip.predictedArrival ? menuColor : warningColor
    })
  });

  bitbar(menu);

});<|endoftext|>


<commit_before>// HackerNews API - https://github.com/HackerNews/API

// https://github.com/stefanpenner/es6-promise#auto-polyfill
require('es6-promise').polyfill();
// https://github.com/matthew-andrews/isomorphic-fetch#usage,
require('isomorphic-fetch');
const bestStories = [];
const rating = 700;
let i;

// setInterval(function testing() {
//   console.log(bestStories);
// }, 0);

function jsonFetch(url) {
  const opts = {
    method: 'get',
    // mode: 'cors',
    // credentials: 'include',
    headers: {
      Accept: 'application/json',
      'Content-Type': 'application/json',
    },
  };

  return fetch(url, opts)
    .then((response) => {
      const { status } = response;
      if (status >= 400) {
        throw new Error(`Bad response from server with status ${status}`);
      }
      return response.json();
    });
}

const urlHN = 'https://hacker-news.firebaseio.com/v0/topstories.json?print=pretty';
jsonFetch(urlHN)
  .then((stories) => {
    for (i = 0; i < stories.length; i++) {
      const storyId = stories[i];
      const storyUrl = `https://hacker-news.firebaseio.com/v0/item/${storyId}.json?print=pretty`;
      console.log(`Now i -> ${i};
        stories[i] -> ${stories[i]}
        stryUrl -> ${storyUrl}`);
      jsonFetch(storyUrl)
        .then((storyObj) => {
          console.log(`StoryObj -> ${storyObj.score}`);
          if (storyObj.score > rating) {
            bestStories.push(storyObj);
          }
        });
    }
    // console.log(bestStories);
  })
  .catch((e) => console.error(e));
// TODO: - save news on a json file
// TODO: save info from that json to mongo
// TODO: play with mongo li
// TODO: add comments link - you can use https://news.ycombinator.com/item?id=12061453 where
//       id is equal to storyId
<commit_msg>working with debug<commit_after>// HackerNews API - https://github.com/HackerNews/API

// https://github.com/stefanpenner/es6-promise#auto-polyfill
require('es6-promise').polyfill();
// https://github.com/matthew-andrews/isomorphic-fetch#usage,
require('isomorphic-fetch');
const bestStories = [];
const rating = 50;
let i;

// setInterval(function testing() {
//   console.log(bestStories);
// }, 1000);

function jsonFetch(url) {
  const opts = {
    method: 'get',
    // mode: 'cors',
    // credentials: 'include',
    headers: {
      Accept: 'application/json',
      'Content-Type': 'application/json',
    },
  };

  return fetch(url, opts)
    .then((response) => {
      const { status } = response;
      if (status >= 400) {
        throw new Error(`Bad response from server with status ${status}`);
      }
      return response.json();
    });
}

const urlHN = 'https://hacker-news.firebaseio.com/v0/topstories.json?print=pretty';
jsonFetch(urlHN)
  .then((stories) => {
    let j = 0;
    for (i = 0; i < stories.length; i++) {
      const storyId = stories[i];
      const storyUrl = `https://hacker-news.firebaseio.com/v0/item/${storyId}.json?print=pretty`;
      // console.log(`Now i -> ${i};
      //   stories[i] -> ${stories[i]}
      //   stryUrl -> ${storyUrl}`);
      jsonFetch(storyUrl)
        .then((storyObj) => {
          j++;
          // console.log(`StoryObj -> ${storyObj.score}
          //   j -> ${j}`);
          if (storyObj.score > rating) {
            bestStories.push(storyObj);
          }
          if (j === stories.length) {
            console.log(JSON.stringify(bestStories));
          }
        })
        .catch((e) => console.error(e));
    }
    // console.log(bestStories);
  })
  .catch((e) => console.error(e));

// TODO: - save news on a json file
// TODO: save info from that json to mongo
// TODO: play with mongo li
// TODO: add comments link - you can use https://news.ycombinator.com/item?id=12061453 where
//       id is equal to storyId
<|endoftext|>


<commit_before>var url = require('url');
var path = require('path');
var zlib = require('zlib');
var crypto = require('crypto');
var mapnik = require('mapnik');
var fs = require('fs');
var qs = require('querystring');
var sm = new (require('sphericalmercator'))();
var immediate = global.setImmediate || process.nextTick;

// Register datasource plugins
mapnik.register_default_input_plugins();

var mapnikPool = require('mapnik-pool')(mapnik);

module.exports = Bridge;

function Bridge(uri, callback) {
    var source = this;

    if (typeof uri === 'string' || (uri.protocol && !uri.xml)) {
        uri = typeof uri === 'string' ? url.parse(uri) : uri;
        uri.query = typeof uri.query === 'string' ? qs.parse(uri.query) : (uri.query || {});
        var filepath = path.resolve(uri.pathname);
        fs.readFile(filepath, 'utf8', function(err, xml) {
            if (err) return callback(err);
            var opts = Object.keys(uri.query).reduce(function(memo, key) {
                memo[key] = !!parseInt(uri.query[key], 10);
                return memo;
            }, {xml:xml, base:path.dirname(filepath)});
            init(opts);
        });
        return source;
    } else {
        init(uri);
        return source;
    }

    function init(uri) {
        if (!uri.xml) return callback && callback(new Error('No xml'));

        source._uri = uri;
        source._base = path.resolve(uri.base || __dirname);

        // 'blank' option forces all solid tiles to be interpreted as blank.
        source._blank = typeof uri.blank === 'boolean' ? uri.blank : false;

        if (callback) source.once('open', callback);

        source.update(uri, function(err) {
            source.emit('open', err, source);
        });
    }
}
require('util').inherits(Bridge, require('events').EventEmitter);

Bridge.registerProtocols = function(tilelive) {
    tilelive.protocols['bridge:'] = Bridge;
};

// Helper for callers to ensure source is open. This is not built directly
// into the constructor because there is no good auto cache-keying system
// for these tile sources (ie. sharing/caching is best left to the caller).
Bridge.prototype.open = function(callback) {
    if (this._map) return callback(null, this);
    this.once('open', callback);
};

// Allows in-place update of XML/backends.
Bridge.prototype.update = function(opts, callback) {
    // Unset maxzoom. Will be re-set on first getTile.
    this._maxzoom = undefined;
    // Unset type. Will be re-set on first getTile.
    this._type = undefined;
    this._xml = opts.xml;
    this._map = mapnikPool.fromString(this._xml,
        { size: 256, bufferSize: 256 },
        { strict: false, base: this._base + '/' });
    // If no nextTick the stale pool can be used to acquire new maps.
    return immediate(function() {
        this._map.destroyAllNow(callback);
    }.bind(this));
};

Bridge.prototype.close = function(callback) {
    var _map = this._map;

    if (!_map) return callback();

    _map.drain(function() {
        _map.destroyAllNow(callback);
    });

};

Bridge.prototype.getTile = function(z, x, y, callback) {
    if (!this._map) return callback(new Error('Tilesource not loaded'));

    var source = this;
    source._map.acquire(function(err, map) {
        if (err) return callback(err);

        // set source _maxzoom cache to prevent repeat calls to map.parameters
        if (source._maxzoom === undefined) {
            source._maxzoom = map.parameters.maxzoom ? parseInt(map.parameters.maxzoom, 10) : 14;
        }

        // set source _type cache to prevent repeat calls to map layers
        if (source._type === undefined) {
            var layers = map.layers();
            if (layers.length && layers.some(function(l) { return l.datasource.type === 'raster' })) {
                source._type = 'raster';
            } else {
                source._type = 'vector';
            }
        }

        if (source._type === 'raster') {
            Bridge.getRaster(source, map, z, x, y, callback);
        } else {
            Bridge.getVector(source, map, z, x, y, callback);
        }
    });
};

Bridge.getRaster = function(source, map, z, x, y, callback) {
    map.resize(512,512);
    map.extent = sm.bbox(+x,+y,+z, false, '900913');
    map.render(new mapnik.Image(512,512), function(err, image) {
        immediate(function() { source._map.release(map); });
        if (err) return callback(err);
        var view = image.view(0,0,512,512);
        view.isSolid(function(err, solid, pixel) {
            if (err) return callback(err);

            // If source is in blank mode any solid tile is empty.
            if (solid && source._blank) return callback(new Error('Tile does not exist'));

            var pixel_key = '';
            if (solid) {
                var a = (pixel>>>24) & 0xff;
                var r = pixel & 0xff;
                var g = (pixel>>>8) & 0xff;
                var b = (pixel>>>16) & 0xff;
                pixel_key = r +','+ g + ',' + b + ',' + a;
            }

            view.encode('webp', {}, function(err, buffer) {
                if (err) return callback(err);
                buffer.solid = pixel_key;
                return callback(err, buffer, {'Content-Type':'image/webp'});
            });
        });
    });
};

Bridge.getVector = function(source, map, z, x, y, callback) {
    var opts = {};
    // use tolerance of 8 for zoom levels below max
    opts.tolerance = z < source._maxzoom ? 0 : 0;

    var headers = {};
    headers['Content-Type'] = 'application/x-protobuf';

    map.resize(256, 256);
    map.extent = sm.bbox(+x,+y,+z, false, '900913');

    var simplify_distance = 1 / 256 / (map.extent[2] - map.extent[0]);
    opts.simplify_distance = z < source._maxzoom ? simplify_distance : 0;

    // also pass buffer_size in options to be forward compatible with recent node-mapnik
    // https://github.com/mapnik/node-mapnik/issues/175
    opts.buffer_size = map.bufferSize;
    map.render(new mapnik.VectorTile(+z,+x,+y), opts, function(err, image) {
        immediate(function() { source._map.release(map); });

        if (err) return callback(err);
        // Fake empty RGBA to the rest of the tilelive API for now.
        image.isSolid(function(err, solid, key) {
            if (err) return callback(err);

            var buffer = image.getData();
            zlib.gzip(buffer, function(err, pbfz) {
                if (err) return callback(err);

                headers['Content-Encoding'] = 'gzip';

                // Solid handling.
                if (solid === false) return callback(err, pbfz, headers);

                // Empty tiles are equivalent to no tile.
                if (source._blank || !key) return callback(new Error('Tile does not exist'));

                // Fake a hex code by md5ing the buffer. The key generated by
                // node-mapnik for vector tiles is not reliably different for
                // "solid" tiles with different contents.
                var mockrgb = crypto.createHash('md5').update(buffer).digest('hex').substr(0,6);
                pbfz.solid = [
                    parseInt(mockrgb.substr(0,2),16),
                    parseInt(mockrgb.substr(2,2),16),
                    parseInt(mockrgb.substr(4,2),16),
                    1
                ].join(',');

                return callback(err, pbfz, headers);
            });
        });
    });
};

Bridge.prototype.getInfo = function(callback) {
    if (!this._map) return callback(new Error('Tilesource not loaded'));

    this._map.acquire(function(err, map) {
        if (err) return callback(err);

        var params = map.parameters;
        var info = Object.keys(params).reduce(function(memo, key) {
            switch (key) {
            // The special "json" key/value pair allows JSON to be serialized
            // and merged into the metadata of a mapnik XML based source. This
            // enables nested properties and non-string datatypes to be
            // captured by mapnik XML.
            case 'json':
                try {
                    var jsondata = JSON.parse(params[key]);
                    Object.keys(jsondata).reduce(function(memo, key) {
                        memo[key] = memo[key] || jsondata[key];
                        return memo;
                    }, memo);
                }
                catch (err) { return callback(err); }
                break;
            case 'bounds':
            case 'center':
                memo[key] = params[key].split(',').map(function(v) { return parseFloat(v) });
                break;
            default:
                memo[key] = params[key];
                break;
            }
            return memo;
        }, {});

        // Set an intelligent default for geocoder_shardlevel if not set.
        if (info.geocoder_layer && !('geocoder_shardlevel' in info)) {
            if (info.maxzoom > 12) {
                info.geocoder_shardlevel = 3;
            } else if (info.maxzoom > 8) {
                info.geocoder_shardlevel = 2;
            } else if (info.maxzoom > 6) {
                info.geocoder_shardlevel = 1;
            } else {
                info.geocoder_shardlevel = 0;
            }
        }

        immediate(function() { this._map.release(map); }.bind(this));
        return callback(null, info);
    }.bind(this));
};

Bridge.prototype.getIndexableDocs = function(pointer, callback) {
    if (!this._map) return callback(new Error('Tilesource not loaded'));

    pointer = pointer || {};
    pointer.limit = pointer.limit || 10000;

    var source = this;
    var knownsrs = {
        '+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over': '+init=epsg:3857',
        '+proj=merc +lon_0=0 +lat_ts=0 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m +no_defs': '+init=epsg:3857',
        '+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs': '+init=epsg:4326'
    };

    source.getInfo(function(err, info) {
        if (err) return callback(err);
        source._map.acquire(function(err, map) {
            if (err) return callback(err);
            immediate(function() { source._map.release(map); });

            var name = (map.parameters.geocoder_layer||'').split('.').shift() || '';
            var field = (map.parameters.geocoder_layer||'').split('.').pop() || '_text';
            var zoom = info.maxzoom + parseInt(map.parameters.geocoder_resolution||0, 10);
            var layer = name ?
                map.layers().filter(function(l) { return l.name === name })[0] :
                map.layers()[0];

            if (!zoom) return callback(new Error('No geocoding zoom defined'));
            if (!layer) return callback(new Error('No geocoding layer found'));
            if (!knownsrs[layer.srs]) return callback(new Error('Unknown layer SRS'));

            var srs = knownsrs[layer.srs];
            if (!pointer.featureset) pointer.featureset = layer.datasource.featureset();
            var featureset = pointer.featureset;
            var params = layer.datasource.parameters();
            var docs = [];
            var cache = {};
            var i = 0;

            function feature() {
                if (i === pointer.limit) {
                    return callback(null, docs, pointer);
                }

                var f = featureset.next();

                if (!f) {
                    return callback(null, docs, pointer);
                }

                var doc = f.attributes();
                if (!doc[field]) return ++i && immediate(feature);
                doc._id = f.id();
                doc._text = doc[field];
                if (typeof doc._bbox === 'string') {
                    doc._bbox = doc._bbox.split(',');
                    doc._bbox[0] = parseFloat(doc._bbox[0]);
                    doc._bbox[1] = parseFloat(doc._bbox[1]);
                    doc._bbox[2] = parseFloat(doc._bbox[2]);
                    doc._bbox[3] = parseFloat(doc._bbox[3]);
                } else {
                    doc._bbox = doc._bbox || (srs === '+init=epsg:4326' ? f.extent() : sm.convert(f.extent(), 'WGS84'));
                }

                if (typeof doc._lfromhn === 'string') doc._lfromhn = doc._lfromhn.split(',');
                if (typeof doc._ltohn === 'string') doc._ltohn = doc._ltohn.split(',');
                if (typeof doc._rfromhn === 'string') doc._rfromhn = doc._rfromhn.split(',');
                if (typeof doc._rtohn === 'string') doc._rtohn = doc._rtohn.split(',');
                if (typeof doc._parityr === 'string') doc._parityr = doc._parityr.split(',');
                if (typeof doc._parityl === 'string') doc._parityl = doc._parityl.split(',');

                if (typeof doc._center === 'string') {
                    doc._center = doc._center.split(',');
                    doc._center[0] = parseFloat(doc._center[0]);
                    doc._center[1] = parseFloat(doc._center[1]);
                } else {
                    doc._center = [
                        doc._bbox[0] + (doc._bbox[2]-doc._bbox[0])*0.5,
                        doc._bbox[1] + (doc._bbox[3]-doc._bbox[1])*0.5
                    ];
                }
                if (doc._bbox[0] === doc._bbox[2]) delete doc._bbox;

                var geom = f.geometry();
                if (srs == "+init=epsg:4326") {
                    geom.toJSON(function(err,json_string) {
                        doc._geometry = JSON.parse(json_string);
                        docs.push(doc);
                        i++;
                        immediate(feature);
                    });
                } else {
                    var from = new mapnik.Projection(srs);
                    var to = new mapnik.Projection("+init=epsg:4326");
                    var tr = new mapnik.ProjTransform(from,to);
                    geom.toJSON({transform:tr},function(err,json_string) {
                        doc._geometry = JSON.parse(json_string);
                        docs.push(doc);
                        i++;
                        immediate(feature);
                    });
                }
            }

            feature();
        });
    });
};
<commit_msg>latest tilelive.js api no longer needs unique solid key for non-solid tiles<commit_after>var url = require('url');
var path = require('path');
var zlib = require('zlib');
var mapnik = require('mapnik');
var fs = require('fs');
var qs = require('querystring');
var sm = new (require('sphericalmercator'))();
var immediate = global.setImmediate || process.nextTick;

// Register datasource plugins
mapnik.register_default_input_plugins();

var mapnikPool = require('mapnik-pool')(mapnik);

module.exports = Bridge;

function Bridge(uri, callback) {
    var source = this;

    if (typeof uri === 'string' || (uri.protocol && !uri.xml)) {
        uri = typeof uri === 'string' ? url.parse(uri) : uri;
        uri.query = typeof uri.query === 'string' ? qs.parse(uri.query) : (uri.query || {});
        var filepath = path.resolve(uri.pathname);
        fs.readFile(filepath, 'utf8', function(err, xml) {
            if (err) return callback(err);
            var opts = Object.keys(uri.query).reduce(function(memo, key) {
                memo[key] = !!parseInt(uri.query[key], 10);
                return memo;
            }, {xml:xml, base:path.dirname(filepath)});
            init(opts);
        });
        return source;
    } else {
        init(uri);
        return source;
    }

    function init(uri) {
        if (!uri.xml) return callback && callback(new Error('No xml'));

        source._uri = uri;
        source._base = path.resolve(uri.base || __dirname);

        // 'blank' option forces all solid tiles to be interpreted as blank.
        source._blank = typeof uri.blank === 'boolean' ? uri.blank : false;

        if (callback) source.once('open', callback);

        source.update(uri, function(err) {
            source.emit('open', err, source);
        });
    }
}
require('util').inherits(Bridge, require('events').EventEmitter);

Bridge.registerProtocols = function(tilelive) {
    tilelive.protocols['bridge:'] = Bridge;
};

// Helper for callers to ensure source is open. This is not built directly
// into the constructor because there is no good auto cache-keying system
// for these tile sources (ie. sharing/caching is best left to the caller).
Bridge.prototype.open = function(callback) {
    if (this._map) return callback(null, this);
    this.once('open', callback);
};

// Allows in-place update of XML/backends.
Bridge.prototype.update = function(opts, callback) {
    // Unset maxzoom. Will be re-set on first getTile.
    this._maxzoom = undefined;
    // Unset type. Will be re-set on first getTile.
    this._type = undefined;
    this._xml = opts.xml;
    this._map = mapnikPool.fromString(this._xml,
        { size: 256, bufferSize: 256 },
        { strict: false, base: this._base + '/' });
    // If no nextTick the stale pool can be used to acquire new maps.
    return immediate(function() {
        this._map.destroyAllNow(callback);
    }.bind(this));
};

Bridge.prototype.close = function(callback) {
    var _map = this._map;

    if (!_map) return callback();

    _map.drain(function() {
        _map.destroyAllNow(callback);
    });

};

Bridge.prototype.getTile = function(z, x, y, callback) {
    if (!this._map) return callback(new Error('Tilesource not loaded'));

    var source = this;
    source._map.acquire(function(err, map) {
        if (err) return callback(err);

        // set source _maxzoom cache to prevent repeat calls to map.parameters
        if (source._maxzoom === undefined) {
            source._maxzoom = map.parameters.maxzoom ? parseInt(map.parameters.maxzoom, 10) : 14;
        }

        // set source _type cache to prevent repeat calls to map layers
        if (source._type === undefined) {
            var layers = map.layers();
            if (layers.length && layers.some(function(l) { return l.datasource.type === 'raster' })) {
                source._type = 'raster';
            } else {
                source._type = 'vector';
            }
        }

        if (source._type === 'raster') {
            Bridge.getRaster(source, map, z, x, y, callback);
        } else {
            Bridge.getVector(source, map, z, x, y, callback);
        }
    });
};

Bridge.getRaster = function(source, map, z, x, y, callback) {
    map.resize(512,512);
    map.extent = sm.bbox(+x,+y,+z, false, '900913');
    map.render(new mapnik.Image(512,512), function(err, image) {
        immediate(function() { source._map.release(map); });
        if (err) return callback(err);
        var view = image.view(0,0,512,512);
        view.isSolid(function(err, solid, pixel) {
            if (err) return callback(err);

            // If source is in blank mode any solid tile is empty.
            if (solid && source._blank) return callback(new Error('Tile does not exist'));

            var pixel_key = '';
            if (solid) {
                var a = (pixel>>>24) & 0xff;
                var r = pixel & 0xff;
                var g = (pixel>>>8) & 0xff;
                var b = (pixel>>>16) & 0xff;
                pixel_key = r +','+ g + ',' + b + ',' + a;
            }

            view.encode('webp', {}, function(err, buffer) {
                if (err) return callback(err);
                buffer.solid = pixel_key;
                return callback(err, buffer, {'Content-Type':'image/webp'});
            });
        });
    });
};

Bridge.getVector = function(source, map, z, x, y, callback) {
    var opts = {};
    // use tolerance of 8 for zoom levels below max
    opts.tolerance = z < source._maxzoom ? 0 : 0;

    var headers = {};
    headers['Content-Type'] = 'application/x-protobuf';

    map.resize(256, 256);
    map.extent = sm.bbox(+x,+y,+z, false, '900913');

    var simplify_distance = 1 / 256 / (map.extent[2] - map.extent[0]);
    opts.simplify_distance = z < source._maxzoom ? simplify_distance : 0;

    // also pass buffer_size in options to be forward compatible with recent node-mapnik
    // https://github.com/mapnik/node-mapnik/issues/175
    opts.buffer_size = map.bufferSize;
    map.render(new mapnik.VectorTile(+z,+x,+y), opts, function(err, image) {
        immediate(function() { source._map.release(map); });
        if (err) return callback(err);
        image.isSolid(function(err, solid, key) {
            if (err) return callback(err);

            var buffer = image.getData();
            zlib.gzip(buffer, function(err, pbfz) {
                if (err) return callback(err);

                headers['Content-Encoding'] = 'gzip';

                // Solid handling.
                if (solid === false) return callback(err, pbfz, headers);

                // Empty tiles are equivalent to no tile.
                if (source._blank || !key) return callback(new Error('Tile does not exist'));

                return callback(err, pbfz, headers);
            });
        });
    });
};

Bridge.prototype.getInfo = function(callback) {
    if (!this._map) return callback(new Error('Tilesource not loaded'));

    this._map.acquire(function(err, map) {
        if (err) return callback(err);

        var params = map.parameters;
        var info = Object.keys(params).reduce(function(memo, key) {
            switch (key) {
            // The special "json" key/value pair allows JSON to be serialized
            // and merged into the metadata of a mapnik XML based source. This
            // enables nested properties and non-string datatypes to be
            // captured by mapnik XML.
            case 'json':
                try {
                    var jsondata = JSON.parse(params[key]);
                    Object.keys(jsondata).reduce(function(memo, key) {
                        memo[key] = memo[key] || jsondata[key];
                        return memo;
                    }, memo);
                }
                catch (err) { return callback(err); }
                break;
            case 'bounds':
            case 'center':
                memo[key] = params[key].split(',').map(function(v) { return parseFloat(v) });
                break;
            default:
                memo[key] = params[key];
                break;
            }
            return memo;
        }, {});

        // Set an intelligent default for geocoder_shardlevel if not set.
        if (info.geocoder_layer && !('geocoder_shardlevel' in info)) {
            if (info.maxzoom > 12) {
                info.geocoder_shardlevel = 3;
            } else if (info.maxzoom > 8) {
                info.geocoder_shardlevel = 2;
            } else if (info.maxzoom > 6) {
                info.geocoder_shardlevel = 1;
            } else {
                info.geocoder_shardlevel = 0;
            }
        }

        immediate(function() { this._map.release(map); }.bind(this));
        return callback(null, info);
    }.bind(this));
};

Bridge.prototype.getIndexableDocs = function(pointer, callback) {
    if (!this._map) return callback(new Error('Tilesource not loaded'));

    pointer = pointer || {};
    pointer.limit = pointer.limit || 10000;

    var source = this;
    var knownsrs = {
        '+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over': '+init=epsg:3857',
        '+proj=merc +lon_0=0 +lat_ts=0 +x_0=0 +y_0=0 +ellps=WGS84 +datum=WGS84 +units=m +no_defs': '+init=epsg:3857',
        '+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs': '+init=epsg:4326'
    };

    source.getInfo(function(err, info) {
        if (err) return callback(err);
        source._map.acquire(function(err, map) {
            if (err) return callback(err);
            immediate(function() { source._map.release(map); });

            var name = (map.parameters.geocoder_layer||'').split('.').shift() || '';
            var field = (map.parameters.geocoder_layer||'').split('.').pop() || '_text';
            var zoom = info.maxzoom + parseInt(map.parameters.geocoder_resolution||0, 10);
            var layer = name ?
                map.layers().filter(function(l) { return l.name === name })[0] :
                map.layers()[0];

            if (!zoom) return callback(new Error('No geocoding zoom defined'));
            if (!layer) return callback(new Error('No geocoding layer found'));
            if (!knownsrs[layer.srs]) return callback(new Error('Unknown layer SRS'));

            var srs = knownsrs[layer.srs];
            if (!pointer.featureset) pointer.featureset = layer.datasource.featureset();
            var featureset = pointer.featureset;
            var params = layer.datasource.parameters();
            var docs = [];
            var cache = {};
            var i = 0;

            function feature() {
                if (i === pointer.limit) {
                    return callback(null, docs, pointer);
                }

                var f = featureset.next();

                if (!f) {
                    return callback(null, docs, pointer);
                }

                var doc = f.attributes();
                if (!doc[field]) return ++i && immediate(feature);
                doc._id = f.id();
                doc._text = doc[field];
                if (typeof doc._bbox === 'string') {
                    doc._bbox = doc._bbox.split(',');
                    doc._bbox[0] = parseFloat(doc._bbox[0]);
                    doc._bbox[1] = parseFloat(doc._bbox[1]);
                    doc._bbox[2] = parseFloat(doc._bbox[2]);
                    doc._bbox[3] = parseFloat(doc._bbox[3]);
                } else {
                    doc._bbox = doc._bbox || (srs === '+init=epsg:4326' ? f.extent() : sm.convert(f.extent(), 'WGS84'));
                }

                if (typeof doc._lfromhn === 'string') doc._lfromhn = doc._lfromhn.split(',');
                if (typeof doc._ltohn === 'string') doc._ltohn = doc._ltohn.split(',');
                if (typeof doc._rfromhn === 'string') doc._rfromhn = doc._rfromhn.split(',');
                if (typeof doc._rtohn === 'string') doc._rtohn = doc._rtohn.split(',');
                if (typeof doc._parityr === 'string') doc._parityr = doc._parityr.split(',');
                if (typeof doc._parityl === 'string') doc._parityl = doc._parityl.split(',');

                if (typeof doc._center === 'string') {
                    doc._center = doc._center.split(',');
                    doc._center[0] = parseFloat(doc._center[0]);
                    doc._center[1] = parseFloat(doc._center[1]);
                } else {
                    doc._center = [
                        doc._bbox[0] + (doc._bbox[2]-doc._bbox[0])*0.5,
                        doc._bbox[1] + (doc._bbox[3]-doc._bbox[1])*0.5
                    ];
                }
                if (doc._bbox[0] === doc._bbox[2]) delete doc._bbox;

                var geom = f.geometry();
                if (srs == "+init=epsg:4326") {
                    geom.toJSON(function(err,json_string) {
                        doc._geometry = JSON.parse(json_string);
                        docs.push(doc);
                        i++;
                        immediate(feature);
                    });
                } else {
                    var from = new mapnik.Projection(srs);
                    var to = new mapnik.Projection("+init=epsg:4326");
                    var tr = new mapnik.ProjTransform(from,to);
                    geom.toJSON({transform:tr},function(err,json_string) {
                        doc._geometry = JSON.parse(json_string);
                        docs.push(doc);
                        i++;
                        immediate(feature);
                    });
                }
            }

            feature();
        });
    });
};
<|endoftext|>


<commit_before>require('dotenv').load()

let debug = require('debug')('index')
let local = require('./local')
let parallel = require('run-parallel')
let rpc = require('./rpc')
let zmq = require('./zmq')

// recursively calls connectBlock(id) until `bitcoind[id].next` is falsy
function connectBlock (id, height, callback) {
  debug(`Connecting ${id} @${height}`)

  rpc('getblockheader', [id], (err, header) => {
    if (err) return callback(err)
    if (header.height !== height) return callback(new Error('Height mismatch'))

    local.connect(id, (err) => {
      if (err) return callback(err)

      debug(`Connected ${id} @${height}`)
      if (!header.nextblockhash) return callback()

      // recurse until next is falsy
      connectBlock(header.nextblockhash, height + 1, callback)
    })
  })
}

function disconnectBlock (id, callback) {
  debug(`Disconnecting ${id}`)

  local.disconnect(id, (err) => {
    if (err) return callback(err)

    debug(`Disconnected ${id}`)
    callback()
  })
}

function sync (err, callback) {
  if (err) return callback(err)

  debug('Checking bitcoind/local chains')
  parallel({
    bitcoind: (f) => rpc('getbestblockhash', [], f),
    local: (f) => local.tip(f)
  }, (err, tips) => {
    if (err) return callback(err)

    // Step 0, genesis?
    if (!tips.local) {
      debug('genesis')
      return rpc('getblockhash', [0], (err, genesisId) => {
        if (err) return callback(err)

        connectBlock(genesisId, 0, callback)
      })
    }

    // Step 1, equal?
    debug('tips', tips)
    if (tips.bitcoind === tips.local) return callback()

    // else, Step 2, is local behind? [bitcoind has local tip]
    rpc('getblockheader', [tips.local], (err, common) => {
      // not in bitcoind chain? [forked]
      if (
        (err && err.message === 'Block not found') ||
        (!err && common.confirmations === -1)
      ) {
        debug('local is forked')
        return disconnectBlock(tips.local, sync)
      }
      if (err) return callback(err)

      // behind
      debug('bitcoind is ahead')
      connectBlock(common.nextblockhash, common.height + 1, callback)
    })
  })
}

zmq.on('hashblock', () => sync())
zmq.on('hashtx', (txId) => () => {
  debug(`Seen ${txId} ${Date.now()}`)
  local.see(txId)
})

sync(null, (err) => {
  if (err) throw err
})
<commit_msg>index: avoid disconnectBlock recursion issues<commit_after>require('dotenv').load()

let debug = require('debug')('index')
let local = require('./local')
let parallel = require('run-parallel')
let rpc = require('./rpc')
let zmq = require('./zmq')

// recursively calls connectBlock(id) until `bitcoind[id].next` is falsy
function connectBlock (id, height, callback) {
  debug(`Connecting ${id} @${height}`)

  rpc('getblockheader', [id], (err, header) => {
    if (err) return callback(err)
    if (header.height !== height) return callback(new Error('Height mismatch'))

    local.connect(id, (err) => {
      if (err) return callback(err)

      debug(`Connected ${id} @${height}`)
      if (!header.nextblockhash) return callback()

      // recurse until next is falsy
      connectBlock(header.nextblockhash, height + 1, callback)
    })
  })
}

function disconnectBlock (id, callback) {
  debug(`Disconnecting ${id}`)

  local.disconnect(id, (err) => {
    if (err) return callback(err)

    debug(`Disconnected ${id}`)
    callback()
  })
}

function sync (callback) {
  debug('Checking bitcoind/local chains')

  parallel({
    bitcoind: (f) => rpc('getbestblockhash', [], f),
    local: (f) => local.tip(f)
  }, (err, tips) => {
    if (err) return callback(err)

    // Step 0, genesis?
    if (!tips.local) {
      debug('genesis')
      return rpc('getblockhash', [0], (err, genesisId) => {
        if (err) return callback(err)

        connectBlock(genesisId, 0, callback)
      })
    }

    // Step 1, equal?
    debug('tips', tips)
    if (tips.bitcoind === tips.local) return callback()

    // else, Step 2, is local behind? [bitcoind has local tip]
    rpc('getblockheader', [tips.local], (err, common) => {
      // not in bitcoind chain? [forked]
      if (
        (err && err.message === 'Block not found') ||
        (!err && common.confirmations === -1)
      ) {
        debug('local is forked')
        return disconnectBlock(tips.local, (err) => {
          if (err) return callback(err)

          sync(null, callback)
        })
      }
      if (err) return callback(err)

      // behind
      debug('bitcoind is ahead')
      connectBlock(common.nextblockhash, common.height + 1, callback)
    })
  })
}

function debugIfErr (err) {
  if (err) debug(err)
}

zmq.on('hashblock', () => sync(debugIfErr))
zmq.on('hashtx', (txId) => () => {
  debug(`Seen ${txId} ${Date.now()}`)
  local.see(txId)
})

sync(debugIfErr)
<|endoftext|>


<commit_before>var path = require('path')
var jstransformer = require('jstransformer')
var toTransformer = require('inputformat-to-jstransformer')
var extend = require('extend')
var async = require('async')
var clone = require('clone')
var minimatch = require('minimatch')

var transformers = {}

/**
* Get the transformer from the given name.
*
* @return The JSTransformer; null if it doesn't exist.
*/
function getTransformer(name) {
  if (name in transformers) {
    return transformers[name]
  }
  var transformer = toTransformer(name)
  transformers[name] = transformer ? jstransformer(transformer) : false
  return transformers[name]
}

module.exports = function (opts) {
  // Prepare the options.
  opts = opts || {}
  opts.layoutPattern = opts.layoutPattern || 'layouts/**'
  opts.pattern = opts.pattern || '**'
  opts.engineLocals = opts.engineLocals || {}
  opts.engineOptions = opts.engineOptions || {}
  var defaultLayout = opts.defaultLayout

  // Execute the plugin.
  return function (files, metalsmith, done) {
    // Retrieve all layouts.
    var templates = {}
    var filesKeys = Object.keys(files)
    var layouts = minimatch.match(filesKeys, opts.layoutPattern, {matchBase: true})

    /**
     * Compile the given layout and store it in templates.
     */
    function compileLayout(layout, done) {
      // Find which JSTransformer to compile with.
      var transform = path.extname(layout).substring(1)
      transform = getTransformer(transform)
      if (transform) {
        // Retrieve the options for the JSTransformer.
        var thefilename = path.join(metalsmith._directory, metalsmith._source, layout)
        var options = extend({}, opts.engineOptions[transform.name], files[layout], {
          filename: thefilename,
          root: metalsmith.source()
        })

        // Compile the content.
        var content = files[layout].contents.toString()
        transform.compileAsync(content, options).then(function (results) {
          // Wire up the template for the layout.
          templates[layout] = results
          templates[layout].transformName = transform.name

          // Set the layout as the default layout, if desired.
          if (files[layout].defaultLayout) {
            defaultLayout = layout
          }

          // Finished compiling the layout into a template.
          done()
        }, function (err) {
          done(err)
        })
      } else {
        done('The layout ' + layout + ' has an unsupported transform of ' + transform + '.')
      }
    }

    /**
     * Delete the given file from the files array.
     */
    function deleteFile(file, done) {
      if (file in files) {
        delete files[file]
      }
      done()
    }

    /**
     * Render the given file in its layout templates.
     */
    function renderContent(file, done) {
      // Only render content, skip rendering layouts.
      if (!(file in layouts)) {
        var layoutName = files[file].layout || defaultLayout
        while (layoutName && templates[layoutName]) {
          // Build the options/locals.
          var thefilename = path.join(metalsmith._directory, metalsmith._source, layoutName)
          var transformName = templates[layoutName].transformName
          var locals = extend({}, metalsmith.metadata(), opts.engineLocals[transformName], files[layoutName], files[file], {
            contents: files[file].contents.toString(),
            filename: thefilename,
            root: metalsmith.source()
          })

          // Render the content using the template function and options.
          try {
            files[file].contents = templates[layoutName].fn(locals)
          } catch (err) {
            return done(err)
          }

          // Allow for recursive explicit layouts.
          layoutName = files[layoutName].layout
        }
      }
      done()
    }

    /**
     * Process the given file. Call done() when done processing.
     */
    function processFile(file, done) {
      /**
       * Process the given extension on the file.
       */
      function processExtension(extension, done) {
        // Retrieve the transformer.
        var transformer = getTransformer(extension)

        // Process the extension until the transformation is done.
        if (transformer && !files[file].jstransformerDone) {
          // Construct the options.
          var engineOpts = opts.engineOptions[transformer.name]
          var options = extend({}, metalsmith.metadata(), engineOpts, files[file], {
            filename: metalsmith.source() + '/' + file,
            root: metalsmith.source()
          })
          // Construct the locals.
          var engineLocals = opts.engineLocals[transformer.name]
          var locals = extend({}, metalsmith.metadata(), engineLocals, files[file], {
            filename: metalsmith.source() + '/' + file,
            root: metalsmith.source()
          })

          // Get the transformer to render the contents.
          transformer.renderAsync(files[file].contents.toString(), options, locals).then(function (result) {
            // Allow providing the default output format.
            files[file].jstransformerOutputFormat = transformer.outputFormat
            // Remove an extension from the end.
            files[file].jstransformerFilePath.pop()
            files[file].contents = new Buffer(result.body)
            done()
          }, function (err) {
            files[file].jstransformerDone = true
            done(err)
          })
        } else {
          // The transformer isn't supported, skip the rest.
          files[file].jstransformerDone = true
          done()
        }
      }

      // Prepare the extension processing.
      var extensions = file.split('.')
      files[file].jstransformerFilePath = clone(extensions)
      extensions.reverse().pop()
      // Loop through the transformer series.
      async.mapSeries(extensions, processExtension, done)
    }

    /**
     * Rename the given file to its desired new name.
     */
    function renameFile(file, done) {
      var filename = file
      // Check if there is a potential filepath change.
      if (files[file].jstransformerFilePath) {
        // See if we should add the default output format.
        if (files[file].jstransformerFilePath.length === 1 && files[file].jstransformerOutputFormat) {
          files[file].jstransformerFilePath.push(files[file].jstransformerOutputFormat)
        }
        filename = files[file].jstransformerFilePath.join('.')
      }

      // See if we are to now rename the file.
      if (filename !== file) {
        var newFile = clone(files[file])
        delete files[file]
        files[filename] = newFile
      }

      done()
    }

    // TODO: Clean up async function chain tree.
    // Compile all layouts.
    async.map(layouts, compileLayout, function (err) {
      if (err) {
        done(err)
      } else {
        // Render all individual content.
        var contentFiles = minimatch.match(filesKeys, opts.pattern, {matchBase: true})
        async.map(contentFiles, processFile, function (err) {
          if (err) {
            done(err)
          } else {
            // Render the content within the layouts.
            async.map(contentFiles, renderContent, function (err) {
              if (err) {
                done(err)
              } else {
                // Delete the layout data.
                async.map(layouts, deleteFile, function (err) {
                  if (err) {
                    done(err)
                  } else {
                    // Now rename all the files.
                    async.map(Object.keys(files), renameFile, done)
                  }
                })
              }
            })
          }
        })
      }
    })
  }
}
<commit_msg>Delete plugin auxiliary metadata from files<commit_after>var path = require('path')
var jstransformer = require('jstransformer')
var toTransformer = require('inputformat-to-jstransformer')
var extend = require('extend')
var async = require('async')
var clone = require('clone')
var minimatch = require('minimatch')

var transformers = {}

/**
* Get the transformer from the given name.
*
* @return The JSTransformer; null if it doesn't exist.
*/
function getTransformer(name) {
  if (name in transformers) {
    return transformers[name]
  }
  var transformer = toTransformer(name)
  transformers[name] = transformer ? jstransformer(transformer) : false
  return transformers[name]
}

module.exports = function (opts) {
  // Prepare the options.
  opts = opts || {}
  opts.layoutPattern = opts.layoutPattern || 'layouts/**'
  opts.pattern = opts.pattern || '**'
  opts.engineLocals = opts.engineLocals || {}
  opts.engineOptions = opts.engineOptions || {}
  var defaultLayout = opts.defaultLayout

  // Execute the plugin.
  return function (files, metalsmith, done) {
    // Retrieve all layouts.
    var templates = {}
    var filesKeys = Object.keys(files)
    var layouts = minimatch.match(filesKeys, opts.layoutPattern, {matchBase: true})

    /**
     * Compile the given layout and store it in templates.
     */
    function compileLayout(layout, done) {
      // Find which JSTransformer to compile with.
      var transform = path.extname(layout).substring(1)
      transform = getTransformer(transform)
      if (transform) {
        // Retrieve the options for the JSTransformer.
        var thefilename = path.join(metalsmith._directory, metalsmith._source, layout)
        var options = extend({}, opts.engineOptions[transform.name], files[layout], {
          filename: thefilename,
          root: metalsmith.source()
        })

        // Compile the content.
        var content = files[layout].contents.toString()
        transform.compileAsync(content, options).then(function (results) {
          // Wire up the template for the layout.
          templates[layout] = results
          templates[layout].transformName = transform.name

          // Set the layout as the default layout, if desired.
          if (files[layout].defaultLayout) {
            defaultLayout = layout
          }

          // Finished compiling the layout into a template.
          done()
        }, function (err) {
          done(err)
        })
      } else {
        done('The layout ' + layout + ' has an unsupported transform of ' + transform + '.')
      }
    }

    /**
     * Delete the given file from the files array.
     */
    function deleteFile(file, done) {
      if (file in files) {
        delete files[file]
      }
      done()
    }

    /**
     * Render the given file in its layout templates.
     */
    function renderContent(file, done) {
      // Only render content, skip rendering layouts.
      if (!(file in layouts)) {
        var layoutName = files[file].layout || defaultLayout
        while (layoutName && templates[layoutName]) {
          // Build the options/locals.
          var thefilename = path.join(metalsmith._directory, metalsmith._source, layoutName)
          var transformName = templates[layoutName].transformName
          var locals = extend({}, metalsmith.metadata(), opts.engineLocals[transformName], files[layoutName], files[file], {
            contents: files[file].contents.toString(),
            filename: thefilename,
            root: metalsmith.source()
          })

          // Render the content using the template function and options.
          try {
            files[file].contents = templates[layoutName].fn(locals)
          } catch (err) {
            return done(err)
          }

          // Allow for recursive explicit layouts.
          layoutName = files[layoutName].layout
        }
      }
      done()
    }

    /**
     * Process the given file. Call done() when done processing.
     */
    function processFile(file, done) {
      /**
       * Process the given extension on the file.
       */
      function processExtension(extension, done) {
        // Retrieve the transformer.
        var transformer = getTransformer(extension)

        // Process the extension until the transformation is done.
        if (transformer && !files[file].jstransformerDone) {
          // Construct the options.
          var engineOpts = opts.engineOptions[transformer.name]
          var options = extend({}, metalsmith.metadata(), engineOpts, files[file], {
            filename: metalsmith.source() + '/' + file,
            root: metalsmith.source()
          })
          // Construct the locals.
          var engineLocals = opts.engineLocals[transformer.name]
          var locals = extend({}, metalsmith.metadata(), engineLocals, files[file], {
            filename: metalsmith.source() + '/' + file,
            root: metalsmith.source()
          })

          // Get the transformer to render the contents.
          transformer.renderAsync(files[file].contents.toString(), options, locals).then(function (result) {
            // Allow providing the default output format.
            files[file].jstransformerOutputFormat = transformer.outputFormat
            // Remove an extension from the end.
            files[file].jstransformerFilePath.pop()
            files[file].contents = new Buffer(result.body)
            done()
          }, function (err) {
            files[file].jstransformerDone = true
            done(err)
          })
        } else {
          // The transformer isn't supported, skip the rest.
          files[file].jstransformerDone = true
          done()
        }
      }

      // Prepare the extension processing.
      var extensions = file.split('.')
      files[file].jstransformerFilePath = clone(extensions)
      extensions.reverse().pop()
      // Loop through the transformer series.
      async.mapSeries(extensions, processExtension, done)
    }

    /**
     * Rename the given file to its desired new name.
     */
    function renameFile(file, done) {
      var filename = file
      // Check if there is a potential filepath change.
      if (files[file].jstransformerFilePath) {
        // See if we should add the default output format.
        if (files[file].jstransformerFilePath.length === 1 && files[file].jstransformerOutputFormat) {
          files[file].jstransformerFilePath.push(files[file].jstransformerOutputFormat)
        }
        filename = files[file].jstransformerFilePath.join('.')
      }

      // See if we are to now rename the file.
      if (filename !== file) {
        var newFile = clone(files[file])
        delete files[file]
        files[filename] = newFile
      }

      done()
    }

    /**
     * Delete auxiliary metadata from the given file if exist.
     */
    function deleteAuxiliaryMetadata(file, done) {
      delete files[file].jstransformerOutputFormat
      delete files[file].jstransformerFilePath
      delete files[file].jstransformerDone
      done()
    }

    // TODO: Clean up async function chain tree.
    // Compile all layouts.
    async.map(layouts, compileLayout, function (err) {
      if (err) {
        done(err)
      } else {
        // Render all individual content.
        var contentFiles = minimatch.match(filesKeys, opts.pattern, {matchBase: true})
        async.map(contentFiles, processFile, function (err) {
          if (err) {
            done(err)
          } else {
            // Render the content within the layouts.
            async.map(contentFiles, renderContent, function (err) {
              if (err) {
                done(err)
              } else {
                // Delete the layout data.
                async.map(layouts, deleteFile, function (err) {
                  if (err) {
                    done(err)
                  } else {
                    // Now rename all the files.
                    async.map(Object.keys(files), renameFile, function (err) {
                      if (err) {
                        done(err)
                      } else {
                        // Now delete auxiliary metadata from files.
                        async.map(Object.keys(files), deleteAuxiliaryMetadata, done)
                      }
                    })
                  }
                })
              }
            })
          }
        })
      }
    })
  }
}
<|endoftext|>


<commit_before>var path = require('path')
var readPackage = require('read-closest-package')
var fork = require('child_process').fork

module.exports = tooler
function tooler (cb) {
  readPackage(function (err, data, file) {
    if (err) return cb(err)
    if (!data || !data.tooler || typeof data.tooler !== 'string') {
      return cb('Must specify a "tooler" config in your package.json.')
    }

    var pkgPath = path.dirname(file)
    var script = path.resolve(pkgPath, data.tooler)
    fork(script, process.argv.slice(2), {
      cwd: process.cwd(),
      stdio: 'inherit'
    })
    cb(null)
  })
}
<commit_msg>Return the same exit code<commit_after>var path = require('path')
var readPackage = require('read-closest-package')
var fork = require('child_process').fork

module.exports = tooler
function tooler (cb) {
  readPackage(function (err, data, file) {
    if (err) return cb(err)
    if (!data || !data.tooler || typeof data.tooler !== 'string') {
      return cb('Must specify a "tooler" config in your package.json.')
    }

    var pkgPath = path.dirname(file)
    var script = path.resolve(pkgPath, data.tooler)
    var child = fork(script, process.argv.slice(2), {
      cwd: process.cwd(),
      stdio: 'inherit'
    })
    child.on('close', function (code) {
      process.exit(code);
    })
    cb(null)
  })
}
<|endoftext|>


<commit_before>module.exports = {
    extends: [
        'eslint-config-airbnb-base',
    ],
    rules: {
        'arrow-body-style': ['error', 'as-needed'],
        'arrow-parens': ['error', 'always'],
        curly: ['error', 'all'],
        indent: ['error', 4],
    },
};
<commit_msg>relax parameter parens<commit_after>module.exports = {
    extends: [
        'eslint-config-airbnb-base',
    ],
    rules: {
        'arrow-body-style': ['error', 'as-needed'],
        'arrow-parens': ['error', 'as-needed'],
        curly: ['error', 'all'],
        indent: ['error', 4],
    },
};
<|endoftext|>


<commit_before>module.exports = {
    "rules": {
        "indent": [
            2,
            3
        ],
        "quotes": [
            2,
            "single"
        ],
        "linebreak-style": 0,
        "semi": [
            2,
            "always"
        ],
        "comma-dangle": [
            2,
            "always-multiline"
        ],
        "strict": [
            2,
            "global"
        ],
        "no-cond-assign": [
            2,
            "always"
        ],
        "no-console": 1,
        "no-constant-condition": 2,
        "no-control-regex": 2,
        "no-debugger": 2,
        "no-dupe-keys": 2,
        "no-duplicate-case": 2,
        "no-empty-character-class": 2,
        "no-empty": 2,
        "no-ex-assign": 2,
        "no-extra-boolean-cast": 1,
        "no-extra-parens": 0,
        "no-extra-semi": 2,
        "no-func-assign": 2,
        "no-inner-declarations": 2,
        "no-invalid-regexp": 2,
        "no-irregular-whitespace": 2,
        "no-negated-in-lhs": 2,
        "no-obj-calls": 2,
        "no-regex-spaces": 2,
        "no-sparse-arrays": 1,
        "no-unexpected-multiline": 1,
        "no-unreachable": 2,
        "use-isnan": 2,
        "valid-jsdoc": 1,
        "valid-typeof": 2
    },
    "env": {
        "es6": true,
        "node": true,
        "mocha": true
    },
    "extends": "eslint:recommended"
}<commit_msg>added brace styles to style guide<commit_after>module.exports = {
    "rules": {
        //Space, Indentation and Formatting Style Guide
        "indent": [
            2,
            3
        ],
        "brace-style": [
            2,
            "1tbs",
            { "allowSingleLine": true }
        ],
        "quotes": [
            2,
            "single"
        ],
        "linebreak-style": 0,
        "semi": [
            2,
            "always"
        ],
        "comma-dangle": [
            2,
            "always-multiline"
        ],
        "strict": [
            2,
            "global"
        ],
        "no-cond-assign": [
            2,
            "always"
        ],
        "no-console": 0,
        "no-constant-condition": 2,
        "no-control-regex": 2,
        "no-debugger": 2,
        "no-dupe-keys": 2,
        "no-duplicate-case": 2,
        "no-empty-character-class": 2,
        "no-empty": 2,
        "no-ex-assign": 2,
        "no-extra-boolean-cast": 1,
        "no-extra-parens": 0,
        "no-extra-semi": 2,
        "no-func-assign": 2,
        "no-inner-declarations": 2,
        "no-invalid-regexp": 2,
        "no-irregular-whitespace": 2,
        "no-negated-in-lhs": 2,
        "no-obj-calls": 2,
        "no-regex-spaces": 2,
        "no-sparse-arrays": 1,
        "no-unexpected-multiline": 1,
        "no-unreachable": 2,
        "use-isnan": 2,
        "valid-jsdoc": 1,
        "valid-typeof": 2
    },
    "env": {
        "es6": true,
        "node": true,
        "mocha": true
    },
    "extends": "eslint:recommended"
}<|endoftext|>


<commit_before>'use strict';

var React = require('react-native');

var {
  Component,
  PropTypes,
  View,
  Easing,
  StyleSheet,
  Animated,
  } = React;

export default class FlipView extends Component {
  static propTypes = {
    style: View.propTypes.style,
    flipDuration: PropTypes.number,
    flipEasing: PropTypes.func,
    flipAxis: PropTypes.oneOf(['x', 'y']),
    front: PropTypes.object,
    back: PropTypes.object,
    perspective: PropTypes.number,
    onFlip: PropTypes.func,
    onFlipped: PropTypes.func,
    isFlipped: PropTypes.bool,
  };

  static defaultProps = {
    style: {},
    flipDuration: 500,
    flipEasing: Easing.out(Easing.ease),
    flipAxis: 'y',
    perspective: 1000,
    onFlip: () => {},
    onFlipped: () => {},
    isFlipped: false,
  };

  constructor(props) {
    super(props);

    var targetRenderState = this._getTargetRenderStateFromFlippedValue(props.isFlipped);

    var frontRotationAnimatedValue = new Animated.Value(targetRenderState.frontRotation);
    var backRotationAnimatedValue = new Animated.Value(targetRenderState.backRotation);

    var interpolationConfig = {inputRange: [0, 1], outputRange: ["0deg", "360deg"]};
    var frontRotation = frontRotationAnimatedValue.interpolate(interpolationConfig);
    var backRotation = backRotationAnimatedValue.interpolate(interpolationConfig);

    this.state = {
      frontRotationAnimatedValue,
      backRotationAnimatedValue,
      frontRotation,
      backRotation,
      isFlipped: false,
    };
  }

  componentWillReceiveProps = (nextProps) => {
    if (nextProps.isFlipped !== this.props.isFlipped) {
      this.flip();
    }
  };

  _getTargetRenderStateFromFlippedValue = (isFlipped) => {
    return {
      frontRotation: isFlipped ? 0.5 : 0,
      backRotation: isFlipped ? 1 : 0.5
    };
  };

  render = () => {
    var rotateProperty = this.props.flipAxis === 'y' ? 'rotateY' : 'rotateX';

    return (
      <View {...this.props}>
        <Animated.View
          pointerEvents={this.state.isFlipped ? 'none' : 'auto'}
          style={[styles.flippableView, {transform: [{perspective: this.props.perspective}, {[rotateProperty]: this.state.frontRotation}]}]}>
          {this.props.front}
        </Animated.View>
        <Animated.View
          pointerEvents={this.state.isFlipped ? 'auto' : 'none'}
          style={[styles.flippableView, {transform: [{perspective: this.props.perspective}, {[rotateProperty]: this.state.backRotation}]}]}>
          {this.props.back}
        </Animated.View>
      </View>
    );
  };

  flip = () => {
    this.props.onFlip();

    var nextIsFlipped = !this.state.isFlipped;

    var {frontRotation, backRotation} = this._getTargetRenderStateFromFlippedValue(nextIsFlipped);

    Animated.parallel([this._animateValue(this.state.frontRotationAnimatedValue, frontRotation, this.props.flipEasing),
      this._animateValue(this.state.backRotationAnimatedValue, backRotation, this.props.flipEasing)]
    ).start(k => {
      if (!k.finished) {
        return;
      }
      this.setState({isFlipped: nextIsFlipped});
      this.props.onFlipped(nextIsFlipped);
    });
  };

  _animateValue = (animatedValue, toValue, easing) => {
    return Animated.timing(
      animatedValue,
      {
        toValue: toValue,
        duration: this.props.flipDuration,
        easing: easing
      }
    );
  };

  _stepFunctionEasing = (t) => {
    return Math.round(this.props.flipEasing(t));
  };
}

var styles = StyleSheet.create({
  flippableView: {
    position: 'absolute',
    left: 0,
    top: 0,
    right: 0,
    bottom: 0,
    backfaceVisibility: 'hidden',
  }
});<commit_msg>Removed unused stepFunctionEasing function<commit_after>'use strict';

var React = require('react-native');

var {
  Component,
  PropTypes,
  View,
  Easing,
  StyleSheet,
  Animated,
  } = React;

export default class FlipView extends Component {
  static propTypes = {
    style: View.propTypes.style,
    flipDuration: PropTypes.number,
    flipEasing: PropTypes.func,
    flipAxis: PropTypes.oneOf(['x', 'y']),
    front: PropTypes.object,
    back: PropTypes.object,
    perspective: PropTypes.number,
    onFlip: PropTypes.func,
    onFlipped: PropTypes.func,
    isFlipped: PropTypes.bool,
  };

  static defaultProps = {
    style: {},
    flipDuration: 500,
    flipEasing: Easing.out(Easing.ease),
    flipAxis: 'y',
    perspective: 1000,
    onFlip: () => {},
    onFlipped: () => {},
    isFlipped: false,
  };

  constructor(props) {
    super(props);

    var targetRenderState = this._getTargetRenderStateFromFlippedValue(props.isFlipped);

    var frontRotationAnimatedValue = new Animated.Value(targetRenderState.frontRotation);
    var backRotationAnimatedValue = new Animated.Value(targetRenderState.backRotation);

    var interpolationConfig = {inputRange: [0, 1], outputRange: ["0deg", "360deg"]};
    var frontRotation = frontRotationAnimatedValue.interpolate(interpolationConfig);
    var backRotation = backRotationAnimatedValue.interpolate(interpolationConfig);

    this.state = {
      frontRotationAnimatedValue,
      backRotationAnimatedValue,
      frontRotation,
      backRotation,
      isFlipped: false,
    };
  }

  componentWillReceiveProps = (nextProps) => {
    if (nextProps.isFlipped !== this.props.isFlipped) {
      this.flip();
    }
  };

  _getTargetRenderStateFromFlippedValue = (isFlipped) => {
    return {
      frontRotation: isFlipped ? 0.5 : 0,
      backRotation: isFlipped ? 1 : 0.5
    };
  };

  render = () => {
    var rotateProperty = this.props.flipAxis === 'y' ? 'rotateY' : 'rotateX';

    return (
      <View {...this.props}>
        <Animated.View
          pointerEvents={this.state.isFlipped ? 'none' : 'auto'}
          style={[styles.flippableView, {transform: [{perspective: this.props.perspective}, {[rotateProperty]: this.state.frontRotation}]}]}>
          {this.props.front}
        </Animated.View>
        <Animated.View
          pointerEvents={this.state.isFlipped ? 'auto' : 'none'}
          style={[styles.flippableView, {transform: [{perspective: this.props.perspective}, {[rotateProperty]: this.state.backRotation}]}]}>
          {this.props.back}
        </Animated.View>
      </View>
    );
  };

  flip = () => {
    this.props.onFlip();

    var nextIsFlipped = !this.state.isFlipped;

    var {frontRotation, backRotation} = this._getTargetRenderStateFromFlippedValue(nextIsFlipped);

    Animated.parallel([this._animateValue(this.state.frontRotationAnimatedValue, frontRotation, this.props.flipEasing),
      this._animateValue(this.state.backRotationAnimatedValue, backRotation, this.props.flipEasing)]
    ).start(k => {
      if (!k.finished) {
        return;
      }
      this.setState({isFlipped: nextIsFlipped});
      this.props.onFlipped(nextIsFlipped);
    });
  };

  _animateValue = (animatedValue, toValue, easing) => {
    return Animated.timing(
      animatedValue,
      {
        toValue: toValue,
        duration: this.props.flipDuration,
        easing: easing
      }
    );
  };
}

var styles = StyleSheet.create({
  flippableView: {
    position: 'absolute',
    left: 0,
    top: 0,
    right: 0,
    bottom: 0,
    backfaceVisibility: 'hidden',
  }
});<|endoftext|>