<commit_before>'use strict'

var fs = require('fs')
var path = require('path')
var afterAll = require('after-all-results')
var errorCallsites = require('error-callsites')
var debug = require('debug')('stackman')

var isAbsolute = path.isAbsolute || require('path-is-absolute')

var cache = require('async-cache')({
  max: 500,
  load: function (file, cb) {
    debug('reading %s', file)
    fs.readFile(file, {encoding: 'utf8'}, cb)
  }
})

var LINES_OF_CONTEXT = 7
var ESCAPED_REGEX_PATH_SEP = path.sep === '/' ? '/' : '\\\\'
var MODULE_FOLDER_REGEX = new RegExp('.*node_modules' + ESCAPED_REGEX_PATH_SEP + '([^' + ESCAPED_REGEX_PATH_SEP + ']*)')

exports.callsites = callsites
exports.properties = properties
exports.sourceContexts = sourceContexts

function callsites (err, opts, cb) {
  if (typeof opts === 'function') return callsites(err, null, opts)
  if (!opts) opts = {}
  if (!('sourcemap' in opts)) opts.sourcemap = true

  var stack = errorCallsites(err)

  if (!validStack(stack)) {
    process.nextTick(function () {
      cb(new Error('Could not process callsites'))
    })
    return
  }

  stack.forEach(function (callsite) {
    Object.defineProperties(callsite, {
      getRelativeFileName: {
        writable: false,
        value: getRelativeFileName
      },
      getTypeNameSafely: {
        writable: false,
        value: getTypeNameSafely
      },
      getFunctionNameSanitized: {
        writable: false,
        value: getFunctionNameSanitized
      },
      getModuleName: {
        writable: false,
        value: getModuleName
      },
      isApp: {
        writable: false,
        value: isApp
      },
      isModule: {
        writable: false,
        value: isModule
      },
      isNode: {
        writable: false,
        value: isNode
      },
      sourceContext: {
        writable: false,
        value: sourceContext
      }
    })
  })

  // TODO: Load sourcemap if `opts.sourcemap === true`
  process.nextTick(function () {
    cb(null, stack)
  })
}

function properties (err) {
  var properties = {}
  Object.keys(err).forEach(function (key) {
    if (key === 'stack') return // 'stack' seems to be enumerable in Node 0.11
    var val = err[key]
    if (val === null) return // null is typeof object and well break the switch below
    switch (typeof val) {
      case 'function':
        return
      case 'object':
        // ignore all objects except Dates
        if (typeof val.toISOString !== 'function') return
        val = val.toISOString()
    }
    properties[key] = val
  })
  return properties
}

function sourceContexts (callsites, opts, cb) {
  if (typeof opts === 'function') return sourceContexts(callsites, null, opts)
  if (!opts) opts = {}

  var next = afterAll(cb)

  callsites.forEach(function (callsite) {
    if (callsite.isNode()) {
      next()(null, null)
    } else {
      callsite.sourceContext(opts, next())
    }
  })
}

function validStack (stack) {
  return Array.isArray(stack) &&
         typeof stack[0] === 'object' &&
         typeof stack[0].getFileName === 'function'
}

function getRelativeFileName () {
  var filename = this.getFileName()
  if (!filename) return
  var root = process.cwd()
  if (root[root.length - 1] !== path.sep) root += path.sep
  return !~filename.indexOf(root) ? filename : filename.substr(root.length)
}

function getTypeNameSafely () {
  try {
    return this.getTypeName()
  } catch (e) {
    // This seems to happen sometimes when using 'use strict',
    // stemming from `getTypeName`.
    // [TypeError: Cannot read property 'constructor' of undefined]
    return null
  }
}

function getFunctionNameSanitized () {
  var fnName = this.getFunctionName()
  if (fnName) return fnName
  var typeName = this.getTypeNameSafely()
  if (typeName) return typeName + '.' + (this.getMethodName() || '<anonymous>')
  return '<anonymous>'
}

function getModuleName () {
  var filename = this.getFileName() || ''
  var match = filename.match(MODULE_FOLDER_REGEX)
  return match ? match[1] : null
}

function isApp () {
  return !this.isNode() && !~(this.getFileName() || '').indexOf('node_modules' + path.sep)
}

function isModule () {
  return !!~(this.getFileName() || '').indexOf('node_modules' + path.sep)
}

function isNode () {
  if (this.isNative()) return true
  var filename = this.getFileName() || ''
  return (!isAbsolute(filename) && filename[0] !== '.')
}

function sourceContext (opts, cb) {
  if (this.isNode()) {
    return process.nextTick(cb, new Error('Can\'t get source context of a Node core callsite'))
  }
  if (typeof opts === 'function') {
    cb = opts
    opts = {}
  }

  var callsite = this
  var filename = this.getFileName() || ''

  cache.get(filename, function (err, data) {
    if (err) {
      debug('error reading %s: %s', filename, err.message)
      cb(err)
    } else {
      data = data.split(/\r?\n/)
      cb(null, parseLines(data, callsite, opts))
    }
  })
}

function parseLines (lines, callsite, opts) {
  var linesOfContext = opts.lines || LINES_OF_CONTEXT
  var lineno = callsite.getLineNumber()
  return {
    pre: lines.slice(Math.max(0, lineno - (linesOfContext + 1)), lineno - 1),
    line: lines[lineno - 1],
    post: lines.slice(lineno, lineno + linesOfContext)
  }
}
<commit_msg>Code cleanup<commit_after>'use strict'

var fs = require('fs')
var path = require('path')
var afterAll = require('after-all-results')
var errorCallsites = require('error-callsites')
var debug = require('debug')('stackman')

var isAbsolute = path.isAbsolute || require('path-is-absolute')

var cache = require('async-cache')({
  max: 500,
  load: function (file, cb) {
    debug('reading %s', file)
    fs.readFile(file, {encoding: 'utf8'}, cb)
  }
})

var LINES_OF_CONTEXT = 7
var ESCAPED_REGEX_PATH_SEP = path.sep === '/' ? '/' : '\\\\'
var MODULE_FOLDER_REGEX = new RegExp('.*node_modules' + ESCAPED_REGEX_PATH_SEP + '([^' + ESCAPED_REGEX_PATH_SEP + ']*)')

exports.callsites = callsites
exports.properties = properties
exports.sourceContexts = sourceContexts

function callsites (err, opts, cb) {
  if (typeof opts === 'function') return callsites(err, null, opts)
  if (!opts) opts = {}
  if (!('sourcemap' in opts)) opts.sourcemap = true

  var _callsites = errorCallsites(err)

  if (!validStack(_callsites)) {
    process.nextTick(function () {
      cb(new Error('Could not process callsites'))
    })
    return
  }

  _callsites.forEach(function (callsite) {
    Object.defineProperties(callsite, {
      getRelativeFileName: {
        writable: false,
        value: getRelativeFileName
      },
      getTypeNameSafely: {
        writable: false,
        value: getTypeNameSafely
      },
      getFunctionNameSanitized: {
        writable: false,
        value: getFunctionNameSanitized
      },
      getModuleName: {
        writable: false,
        value: getModuleName
      },
      isApp: {
        writable: false,
        value: isApp
      },
      isModule: {
        writable: false,
        value: isModule
      },
      isNode: {
        writable: false,
        value: isNode
      },
      sourceContext: {
        writable: false,
        value: sourceContext
      }
    })
  })

  // TODO: Load sourcemap if `opts.sourcemap === true`
  process.nextTick(function () {
    cb(null, _callsites)
  })
}

function properties (err) {
  var properties = {}
  Object.keys(err).forEach(function (key) {
    if (key === 'stack') return // 'stack' seems to be enumerable in Node 0.11
    var val = err[key]
    if (val === null) return // null is typeof object and well break the switch below
    switch (typeof val) {
      case 'function':
        return
      case 'object':
        // ignore all objects except Dates
        if (typeof val.toISOString !== 'function') return
        val = val.toISOString()
    }
    properties[key] = val
  })
  return properties
}

function sourceContexts (callsites, opts, cb) {
  if (typeof opts === 'function') return sourceContexts(callsites, null, opts)
  if (!opts) opts = {}

  var next = afterAll(cb)

  callsites.forEach(function (callsite) {
    if (callsite.isNode()) {
      next()(null, null)
    } else {
      callsite.sourceContext(opts, next())
    }
  })
}

function validStack (callsites) {
  return Array.isArray(callsites) &&
         typeof callsites[0] === 'object' &&
         typeof callsites[0].getFileName === 'function'
}

function getRelativeFileName () {
  var filename = this.getFileName()
  if (!filename) return
  var root = process.cwd()
  if (root[root.length - 1] !== path.sep) root += path.sep
  return !~filename.indexOf(root) ? filename : filename.substr(root.length)
}

function getTypeNameSafely () {
  try {
    return this.getTypeName()
  } catch (e) {
    // This seems to happen sometimes when using 'use strict',
    // stemming from `getTypeName`.
    // [TypeError: Cannot read property 'constructor' of undefined]
    return null
  }
}

function getFunctionNameSanitized () {
  var fnName = this.getFunctionName()
  if (fnName) return fnName
  var typeName = this.getTypeNameSafely()
  if (typeName) return typeName + '.' + (this.getMethodName() || '<anonymous>')
  return '<anonymous>'
}

function getModuleName () {
  var filename = this.getFileName() || ''
  var match = filename.match(MODULE_FOLDER_REGEX)
  return match ? match[1] : null
}

function isApp () {
  return !this.isNode() && !~(this.getFileName() || '').indexOf('node_modules' + path.sep)
}

function isModule () {
  return !!~(this.getFileName() || '').indexOf('node_modules' + path.sep)
}

function isNode () {
  if (this.isNative()) return true
  var filename = this.getFileName() || ''
  return (!isAbsolute(filename) && filename[0] !== '.')
}

function sourceContext (opts, cb) {
  if (this.isNode()) {
    return process.nextTick(cb, new Error('Can\'t get source context of a Node core callsite'))
  }
  if (typeof opts === 'function') {
    cb = opts
    opts = {}
  }

  var callsite = this
  var filename = this.getFileName() || ''

  cache.get(filename, function (err, data) {
    if (err) {
      debug('error reading %s: %s', filename, err.message)
      cb(err)
    } else {
      data = data.split(/\r?\n/)
      cb(null, parseLines(data, callsite, opts))
    }
  })
}

function parseLines (lines, callsite, opts) {
  var linesOfContext = opts.lines || LINES_OF_CONTEXT
  var lineno = callsite.getLineNumber()
  return {
    pre: lines.slice(Math.max(0, lineno - (linesOfContext + 1)), lineno - 1),
    line: lines[lineno - 1],
    post: lines.slice(lineno, lineno + linesOfContext)
  }
}
<|endoftext|>


<commit_before>var common = require('./common')
var download = require('electron-download')
var extract = require('extract-zip')
var fs = require('fs-extra')
var getPackageInfo = require('get-package-info')
var os = require('os')
var path = require('path')
var resolve = require('resolve')
var series = require('run-series')

var supportedArchs = common.archs.reduce(function (result, arch) {
  result[arch] = 1
  return result
}, {})

var supportedPlatforms = {
  // Maps to module ID for each platform (lazy-required if used)
  darwin: './mac',
  linux: './linux',
  mas: './mac', // map to darwin
  win32: './win32'
}

function validateList (list, supported, name) {
  // Validates list of architectures or platforms.
  // Returns a normalized array if successful, or an error message string otherwise.

  if (!list) return `Must specify ${name}`
  if (list === 'all') return Object.keys(supported)

  if (!Array.isArray(list)) list = list.split(',')
  for (var i = list.length; i--;) {
    if (!supported[list[i]]) {
      return `Unsupported ${name} ${list[i]}; must be one of: ${Object.keys(supported).join(', ')}`
    }
  }

  return list
}

function getNameAndVersion (opts, dir, cb) {
  var props = []
  if (!opts.name) props.push(['productName', 'name'])
  if (!opts.version) props.push(['dependencies.electron-prebuilt', 'devDependencies.electron-prebuilt'])

  // Name and version provided, no need to infer
  if (props.length === 0) return cb(null)

  // Search package.json files to infer name and version from
  getPackageInfo(props, dir, function (err, result) {
    if (err) return cb(err)
    if (result.values.productName) opts.name = result.values.productName
    if (result.values['dependencies.electron-prebuilt']) {
      resolve('electron-prebuilt', {
        basedir: path.dirname(result.source['dependencies.electron-prebuilt'].src)
      }, function (err, res, pkg) {
        if (err) return cb(err)
        opts.version = pkg.version
        return cb(null)
      })
    } else {
      return cb(null)
    }
  })
}

function createSeries (opts, archs, platforms) {
  var tempBase = path.join(opts.tmpdir || os.tmpdir(), 'electron-packager')

  function testSymlink (cb) {
    var testPath = path.join(tempBase, 'symlink-test')
    var testFile = path.join(testPath, 'test')
    var testLink = path.join(testPath, 'testlink')
    series([
      function (cb) {
        fs.outputFile(testFile, '', cb)
      },
      function (cb) {
        fs.symlink(testFile, testLink, cb)
      }
    ], function (err) {
      var result = !err
      fs.remove(testPath, function () {
        cb(result) // ignore errors on cleanup
      })
    })
  }

  var combinations = []
  archs.forEach(function (arch) {
    platforms.forEach(function (platform) {
      // Electron does not have 32-bit releases for Mac OS X, so skip that combination
      if (common.isPlatformMac(platform) && arch === 'ia32') return
      combinations.push(common.createDownloadOpts(opts, platform, arch))
    })
  })

  var tasks = []
  var useTempDir = opts.tmpdir !== false
  if (useTempDir) {
    tasks.push(function (cb) {
      fs.remove(tempBase, cb)
    })
  }
  return tasks.concat(combinations.map(function (combination) {
    var arch = combination.arch
    var platform = combination.platform
    var version = combination.version

    return function (callback) {
      download(combination, function (err, zipPath) {
        if (err) return callback(err)

        function createApp (comboOpts) {
          var buildParentDir
          if (useTempDir) {
            buildParentDir = tempBase
          } else {
            buildParentDir = opts.out || process.cwd()
          }
          var buildDir = path.join(buildParentDir, `${platform}-${arch}-template`)
          console.error(`Packaging app for platform ${platform} ${arch} using electron v${version}`)
          series([
            function (cb) {
              fs.mkdirs(buildDir, cb)
            },
            function (cb) {
              extract(zipPath, {dir: buildDir}, cb)
            }
          ], function () {
            require(supportedPlatforms[platform]).createApp(comboOpts, buildDir, callback)
          })
        }

        // Create delegated options object with specific platform and arch, for output directory naming
        var comboOpts = Object.create(opts)
        comboOpts.arch = arch
        comboOpts.platform = platform

        if (!useTempDir) {
          createApp(comboOpts)
          return
        }

        function checkOverwrite () {
          var finalPath = common.generateFinalPath(comboOpts)
          fs.exists(finalPath, function (exists) {
            if (exists) {
              if (opts.overwrite) {
                fs.remove(finalPath, function () {
                  createApp(comboOpts)
                })
              } else {
                console.error(`Skipping ${platform} ${arch} (output dir already exists, use --overwrite to force)`)
                callback()
              }
            } else {
              createApp(comboOpts)
            }
          })
        }

        if (common.isPlatformMac(combination.platform)) {
          testSymlink(function (result) {
            if (result) return checkOverwrite()

            console.error(`Cannot create symlinks; skipping ${combination.platform} platform`)
            callback()
          })
        } else {
          checkOverwrite()
        }
      })
    }
  }))
}

module.exports = function packager (opts, cb) {
  var archs = validateList(opts.all ? 'all' : opts.arch, supportedArchs, 'arch')
  var platforms = validateList(opts.all ? 'all' : opts.platform, supportedPlatforms, 'platform')
  if (!Array.isArray(archs)) return cb(new Error(archs))
  if (!Array.isArray(platforms)) return cb(new Error(platforms))

  getNameAndVersion(opts, opts.dir || process.cwd(), function (err) {
    if (err) {
      err.message = 'Unable to infer name or version. Please specify a name and version.\n' + err.message
      return cb(err)
    }

    // Ignore this and related modules by default
    var defaultIgnores = ['/node_modules/electron-prebuilt($|/)', '/node_modules/electron-packager($|/)', '/\.git($|/)', '/node_modules/\\.bin($|/)']

    if (typeof (opts.ignore) !== 'function') {
      if (opts.ignore && !Array.isArray(opts.ignore)) opts.ignore = [opts.ignore]
      opts.ignore = (opts.ignore) ? opts.ignore.concat(defaultIgnores) : defaultIgnores
    }

    series(createSeries(opts, archs, platforms), function (err, appPaths) {
      if (err) return cb(err)

      cb(null, appPaths.filter(function (appPath) {
        // Remove falsy entries (e.g. skipped platforms)
        return appPath
      }))
    })
  })
}
<commit_msg>Escape dot in ".git" correctly<commit_after>var common = require('./common')
var download = require('electron-download')
var extract = require('extract-zip')
var fs = require('fs-extra')
var getPackageInfo = require('get-package-info')
var os = require('os')
var path = require('path')
var resolve = require('resolve')
var series = require('run-series')

var supportedArchs = common.archs.reduce(function (result, arch) {
  result[arch] = 1
  return result
}, {})

var supportedPlatforms = {
  // Maps to module ID for each platform (lazy-required if used)
  darwin: './mac',
  linux: './linux',
  mas: './mac', // map to darwin
  win32: './win32'
}

function validateList (list, supported, name) {
  // Validates list of architectures or platforms.
  // Returns a normalized array if successful, or an error message string otherwise.

  if (!list) return `Must specify ${name}`
  if (list === 'all') return Object.keys(supported)

  if (!Array.isArray(list)) list = list.split(',')
  for (var i = list.length; i--;) {
    if (!supported[list[i]]) {
      return `Unsupported ${name} ${list[i]}; must be one of: ${Object.keys(supported).join(', ')}`
    }
  }

  return list
}

function getNameAndVersion (opts, dir, cb) {
  var props = []
  if (!opts.name) props.push(['productName', 'name'])
  if (!opts.version) props.push(['dependencies.electron-prebuilt', 'devDependencies.electron-prebuilt'])

  // Name and version provided, no need to infer
  if (props.length === 0) return cb(null)

  // Search package.json files to infer name and version from
  getPackageInfo(props, dir, function (err, result) {
    if (err) return cb(err)
    if (result.values.productName) opts.name = result.values.productName
    if (result.values['dependencies.electron-prebuilt']) {
      resolve('electron-prebuilt', {
        basedir: path.dirname(result.source['dependencies.electron-prebuilt'].src)
      }, function (err, res, pkg) {
        if (err) return cb(err)
        opts.version = pkg.version
        return cb(null)
      })
    } else {
      return cb(null)
    }
  })
}

function createSeries (opts, archs, platforms) {
  var tempBase = path.join(opts.tmpdir || os.tmpdir(), 'electron-packager')

  function testSymlink (cb) {
    var testPath = path.join(tempBase, 'symlink-test')
    var testFile = path.join(testPath, 'test')
    var testLink = path.join(testPath, 'testlink')
    series([
      function (cb) {
        fs.outputFile(testFile, '', cb)
      },
      function (cb) {
        fs.symlink(testFile, testLink, cb)
      }
    ], function (err) {
      var result = !err
      fs.remove(testPath, function () {
        cb(result) // ignore errors on cleanup
      })
    })
  }

  var combinations = []
  archs.forEach(function (arch) {
    platforms.forEach(function (platform) {
      // Electron does not have 32-bit releases for Mac OS X, so skip that combination
      if (common.isPlatformMac(platform) && arch === 'ia32') return
      combinations.push(common.createDownloadOpts(opts, platform, arch))
    })
  })

  var tasks = []
  var useTempDir = opts.tmpdir !== false
  if (useTempDir) {
    tasks.push(function (cb) {
      fs.remove(tempBase, cb)
    })
  }
  return tasks.concat(combinations.map(function (combination) {
    var arch = combination.arch
    var platform = combination.platform
    var version = combination.version

    return function (callback) {
      download(combination, function (err, zipPath) {
        if (err) return callback(err)

        function createApp (comboOpts) {
          var buildParentDir
          if (useTempDir) {
            buildParentDir = tempBase
          } else {
            buildParentDir = opts.out || process.cwd()
          }
          var buildDir = path.join(buildParentDir, `${platform}-${arch}-template`)
          console.error(`Packaging app for platform ${platform} ${arch} using electron v${version}`)
          series([
            function (cb) {
              fs.mkdirs(buildDir, cb)
            },
            function (cb) {
              extract(zipPath, {dir: buildDir}, cb)
            }
          ], function () {
            require(supportedPlatforms[platform]).createApp(comboOpts, buildDir, callback)
          })
        }

        // Create delegated options object with specific platform and arch, for output directory naming
        var comboOpts = Object.create(opts)
        comboOpts.arch = arch
        comboOpts.platform = platform

        if (!useTempDir) {
          createApp(comboOpts)
          return
        }

        function checkOverwrite () {
          var finalPath = common.generateFinalPath(comboOpts)
          fs.exists(finalPath, function (exists) {
            if (exists) {
              if (opts.overwrite) {
                fs.remove(finalPath, function () {
                  createApp(comboOpts)
                })
              } else {
                console.error(`Skipping ${platform} ${arch} (output dir already exists, use --overwrite to force)`)
                callback()
              }
            } else {
              createApp(comboOpts)
            }
          })
        }

        if (common.isPlatformMac(combination.platform)) {
          testSymlink(function (result) {
            if (result) return checkOverwrite()

            console.error(`Cannot create symlinks; skipping ${combination.platform} platform`)
            callback()
          })
        } else {
          checkOverwrite()
        }
      })
    }
  }))
}

module.exports = function packager (opts, cb) {
  var archs = validateList(opts.all ? 'all' : opts.arch, supportedArchs, 'arch')
  var platforms = validateList(opts.all ? 'all' : opts.platform, supportedPlatforms, 'platform')
  if (!Array.isArray(archs)) return cb(new Error(archs))
  if (!Array.isArray(platforms)) return cb(new Error(platforms))

  getNameAndVersion(opts, opts.dir || process.cwd(), function (err) {
    if (err) {
      err.message = 'Unable to infer name or version. Please specify a name and version.\n' + err.message
      return cb(err)
    }

    // Ignore this and related modules by default
    var defaultIgnores = ['/node_modules/electron-prebuilt($|/)', '/node_modules/electron-packager($|/)', '/\\.git($|/)', '/node_modules/\\.bin($|/)']

    if (typeof (opts.ignore) !== 'function') {
      if (opts.ignore && !Array.isArray(opts.ignore)) opts.ignore = [opts.ignore]
      opts.ignore = (opts.ignore) ? opts.ignore.concat(defaultIgnores) : defaultIgnores
    }

    series(createSeries(opts, archs, platforms), function (err, appPaths) {
      if (err) return cb(err)

      cb(null, appPaths.filter(function (appPath) {
        // Remove falsy entries (e.g. skipped platforms)
        return appPath
      }))
    })
  })
}
<|endoftext|>


<commit_before>var _ = require("lodash");

var settings = {
	fullDomain : false,
	ignoreDomains : [],
	reverse : true
}
var escapeRegexpString = function(str){
	//escapes regex literals in a string.
	return String(str).replace(/([.*+?=^!:${}()|[\]\/\\])/g, '\\$1');
};

var setup = function(config){
	settings  = _.merge(settings,config);
	settings.ignoreDomains = settings.ignoreDomains.map(function(item){
		item = escapeStringRegexp(item);
		item = new RegExp(item+"$");
		return item;
	});
	if(!settings.fullDomain){
		settings.ignoreDomains.push(/.*?\..*$/);
	}
};

var converter = function(req,res,next){
	var subs;
	//saving original path
	req.originalUrl = req.url;
	//remove the port if present.
	subs = req.headers.host.replace(/:.*$/,"");
	//removing the ignored domain;
	settings.ignoreDomains.every(function(domain){
		//using every this way it will only replace the first domain found and be false after the first replace.
		return subs === (subs = subs.replace(domain,""));
	});

	//removing the trailing `.`
	subs = subs.replace(/\.$/,"");

	//turn it to a path str.
	subs = subs.split(".");
	if(settings.reverse){
		subs = subs.reverse()
	}
	subs = subs.join("/");

	//assigning to req.url (replacing first `/` from the old url)
	req.url = "/" + subs + req.url.replace(/^\//,"");
	next();
}

module.exports = function(config){
	setup(config);
	return {
		converter : converter
	};
}<commit_msg>originalUrl has a use already<commit_after>var _ = require("lodash");

var settings = {
	fullDomain : false,
	ignoreDomains : [],
	reverse : true
}
var escapeRegexpString = function(str){
	//escapes regex literals in a string.
	return String(str).replace(/([.*+?=^!:${}()|[\]\/\\])/g, '\\$1');
};

var setup = function(config){
	settings  = _.merge(settings,config);
	settings.ignoreDomains = settings.ignoreDomains.map(function(item){
		item = escapeStringRegexp(item);
		item = new RegExp(item+"$");
		return item;
	});
	if(!settings.fullDomain){
		settings.ignoreDomains.push(/.*?\..*$/);
	}
};

var converter = function(req,res,next){
	var subs;
	//saving original path
	req.trueUrl = req.url;
	//remove the port if present.
	subs = req.headers.host.replace(/:.*$/,"");
	//removing the ignored domain;
	settings.ignoreDomains.every(function(domain){
		//using every this way it will only replace the first domain found and be false after the first replace.
		return subs === (subs = subs.replace(domain,""));
	});

	//removing the trailing `.`
	subs = subs.replace(/\.$/,"");

	//turn it to a path str.
	subs = subs.split(".");
	if(settings.reverse){
		subs = subs.reverse()
	}
	subs = subs.join("/");

	//assigning to req.url (replacing first `/` from the old url)
	req.url = "/" + subs + req.url.replace(/^\//,"");
	next();
}

module.exports = function(config){
	setup(config);
	return {
		converter : converter
	};
}<|endoftext|>


<commit_before>/* eslint-env browser */
/* global _gaq, ga */
import { on, find, ready, closest } from 'domassist';
import aug from 'aug';

const GATrack = {
  sendEvent(category, action, label) {
    if (GATrack.prefix) {
      category = `${GATrack.prefix}-${category}`;
    }

    GATrack.log(category, action, label);

    if (typeof window._gaq === 'undefined' && typeof window.ga === 'undefined') { // eslint-disable-line no-underscore-dangle
      return GATrack;
    }

    if (typeof window._gaq !== 'undefined') { // eslint-disable-line no-underscore-dangle
      _gaq.push(['_trackEvent', category, action, label, null, false]);
    } else {
      ga('send', 'event', category, action, label, { transport: 'beacon' });
    }
  },

  getData(element, options = {}) {
    const href = element.dataset.gaTrackHref || element.getAttribute('href');
    const category = element.dataset.gaTrack || options.category || 'ga-track';
    const label = element.dataset.gaTrackLabel || options.label || href;
    const action = element.dataset.gaTrackAction || options.action || element.textContent.trim();

    return { href, category, label, action };
  },

  track(element, options = {}) {
    if (Array.isArray(element)) {
      element.forEach(data => {
        find(data.element).forEach(el => {
          GATrack.track(el, data);
        });
      });

      return;
    }

    if (typeof element.dataset.gaTrackInitialised !== 'undefined') {
      return;
    }

    element.dataset.gaTrackInitialised = 'true';

    options = aug({}, GATrack.defaults, options);

    this.log('tracking', element, options);
    on(element, 'click', event => {
      GATrack.onTrackedClick(element, event, options);
    });
  },

  onTrackedClick(element, event, options) {
    const data = GATrack.getData(element, options);
    const target = element.getAttribute('target');

    GATrack.sendEvent(data.category, data.action, data.label);

    if (element.dataset.gaTrackHref === 'false') {
      event.preventDefault();
    } else if (data.href && !event.metaKey && event.which === 1 && target !== '_blank') {
      event.preventDefault();
      setTimeout(() => { window.location = data.href; }, options.delay);
    }
  },

  autotrack() {
    if (GATrack.autotracking === true) {
      return;
    }

    GATrack.autotracking = true;
    const selector = '[data-ga-track]';

    on(document.body, 'click', e => {
      let element = e.target;

      if (!element.matches(selector)) {
        element = closest(element, selector);
      }

      if (element) {
        GATrack.onTrackedClick(element, event, GATrack.defaults);
      }
    });
  },

  log(...args) {
    if (GATrack.debug) {
      console.log('GATRACK', ...args); //eslint-disable-line no-console
    }
  },

  debug: (typeof window.localStorage === 'object' && window.localStorage.getItem('GATrackDebug')),
  prefix: null,
  defaults: {
    delay: 200
  }
};

const outlineTracked = () => find('[data-ga-track-initialised], [data-ga-track]').map(el => {
  el.style.outline = 'red dotted 1px';
  return el;
});

GATrack.debug = window.localStorage.getItem('GATrackDebug');
const outline = window.localStorage.getItem('GATrackOutline');

window.GAOutlineTracked = outlineTracked;

ready(() => {
  GATrack.autotrack();

  if (outline) {
    outlineTracked();
  }
});

export default GATrack;
<commit_msg>Using more reliable hitCallback<commit_after>/* eslint-env browser */
/* global _gaq, ga */
import { on, find, ready, closest } from 'domassist';
import aug from 'aug';

const GATrack = {
  sendEvent(category, action, label, callback = null, delay = 1000) {
    if (GATrack.prefix) {
      category = `${GATrack.prefix}-${category}`;
    }

    GATrack.log(category, action, label);

    if (typeof window._gaq === 'undefined' && typeof window.ga === 'undefined') { // eslint-disable-line no-underscore-dangle
      return GATrack;
    }

    if (typeof window._gaq !== 'undefined') { // eslint-disable-line no-underscore-dangle
      _gaq.push(['_trackEvent', category, action, label, null, false]);
    } else {
      const options = {
        transport: 'beacon'
      };

      if (typeof callback === 'function') {
        options.hitCallback = callback;
        setTimeout(callback, delay);
      }

      ga('send', 'event', category, action, label, options);
    }
  },

  getData(element, options = {}) {
    const href = element.dataset.gaTrackHref || element.getAttribute('href');
    const category = element.dataset.gaTrack || options.category || 'ga-track';
    const label = element.dataset.gaTrackLabel || options.label || href;
    const action = element.dataset.gaTrackAction || options.action || element.textContent.trim();

    return { href, category, label, action };
  },

  track(element, options = {}) {
    if (Array.isArray(element)) {
      element.forEach(data => {
        find(data.element).forEach(el => {
          GATrack.track(el, data);
        });
      });

      return;
    }

    if (typeof element.dataset.gaTrackInitialised !== 'undefined') {
      return;
    }

    element.dataset.gaTrackInitialised = 'true';

    options = aug({}, GATrack.defaults, options);

    this.log('tracking', element, options);
    on(element, 'click', event => {
      GATrack.onTrackedClick(element, event, options);
    });
  },

  onTrackedClick(element, event, options) {
    const data = GATrack.getData(element, options);
    const target = element.getAttribute('target');
    let callback = null;

    if (element.dataset.gaTrackHref === 'false') {
      event.preventDefault();
    } else if (data.href && !event.metaKey && event.which === 1 && target !== '_blank') {
      event.preventDefault();
      callback = () => {
        window.location = data.href;
      };
    }

    GATrack.sendEvent(data.category, data.action, data.label, callback, options.delay);
  },

  autotrack() {
    if (GATrack.autotracking === true) {
      return;
    }

    GATrack.autotracking = true;
    const selector = '[data-ga-track]';

    on(document.body, 'click', e => {
      let element = e.target;

      if (!element.matches(selector)) {
        element = closest(element, selector);
      }

      if (element) {
        GATrack.onTrackedClick(element, event, GATrack.defaults);
      }
    });
  },

  log(...args) {
    if (GATrack.debug) {
      console.log('GATRACK', ...args); //eslint-disable-line no-console
    }
  },

  debug: (typeof window.localStorage === 'object' && window.localStorage.getItem('GATrackDebug')),
  prefix: null,
  defaults: {
    delay: 1000
  }
};

const outlineTracked = () => find('[data-ga-track-initialised], [data-ga-track]').map(el => {
  el.style.outline = 'red dotted 1px';
  return el;
});

GATrack.debug = window.localStorage.getItem('GATrackDebug');
const outline = window.localStorage.getItem('GATrackOutline');

window.GAOutlineTracked = outlineTracked;

ready(() => {
  GATrack.autotrack();

  if (outline) {
    outlineTracked();
  }
});

export default GATrack;
<|endoftext|>


<commit_before>var {Cc, Ci} = require("chrome");

var gcSvc = Cc["@mozilla.org/grammarcheck;1"].
				getService(Ci.nsIEditorGrammarCheck);

function handleWord(word)
{
	var startPos = [0,4];
	var endPos = [2,9];

	gcSvc.errorsFound(startPos, endPos, startPos.length);
	gcSvc.addSuggestionForError(0, "[this will be replaced]");
	gcSvc.addSuggestionForError(1, "[another suggestion]");
}

gcSvc.registerAddon(handleWord);
<commit_msg>add untested code to use remote server<commit_after>var {Cc, Ci} = require("chrome");

var gcSvc = Cc["@mozilla.org/grammarcheck;1"].
				getService(Ci.nsIEditorGrammarCheck);

var xmlhttp = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].createInstance(Ci.nsIXMLHttpRequest);

function handleWord(word)
{
	var oReq = xmlhttp;
	oReq.addEventListener("load", function(result) {
		console.log("LOAD!!");
		console.log(result);
		console.log(oReq.responseXML);
		var xml = oReq.responseXML;
		var errors = xml.getElementsByTagName("error");
		var startPositions = [];
		var endPositions = [];
		for (var i = 0; i < errors.length; i++) {
			console.log("ERROR: " + errors[i].getAttribute("offset") + ", len: " + errors[i].getAttribute("errorlength"));
			var startPos = parseInt(errors[i].getAttribute("offset"));
			var endPos = startPos + parseInt(errors[i].getAttribute("errorlength"));
			startPositions.push(startPos);
			endPositions.push(endPos);
			// msg, replacements (#)
		}
		//gcSvc.errorsFound(startPositions, endPositions, startPositions.length);
		for (var j = 0; j < errors.length; j++) {
			//gcSvc.addSuggestionForError(0, "[this will be replaced]");

		}
		console.log("START: " + startPositions);
		console.log("END: " + endPositions);
	});
	oReq.open("POST", "https://languagetool.org:8081/", true);
	oReq.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
	var data = "language=en&text=this is an test";
	oReq.send(data);
	console.log("POSTED");

	var startPos = [0,4];
	var endPos = [2,9];

	gcSvc.errorsFound(startPos, endPos, startPos.length);
	gcSvc.addSuggestionForError(0, "[this will be replaced]");
	gcSvc.addSuggestionForError(1, "[another suggestion]");
}

gcSvc.registerAddon(handleWord);
<|endoftext|>


<commit_before>var http = require('http')
	, fs = require('fs')
	, path = require('path')
	, request = require('request')
	, routeConfig = require(process.argv.pop())
	, PORT = 4040;

var routeConfigLen = routeConfig.proxies.length;

process.on('uncaughtException', function (err) {
  console.log('Caught exception: ' + err);
});

function cannedResponseHandler(req, res) {
    if (!routeConfig.canned || !routeConfig.canned[req.url])
		return false;

	var file = path.join(__dirname, routeConfig.canned[req.url]);
	console.log("Shipping canned response %s", req.url);
	fs.stat(file, function(err, stat) {
		res.writeHead(200, {
			'Content-Type': 'application/json',
			'Content-Length': stat.size,
			'Access-Control-Allow-Origin': '*',
			'Access-Control-Allow-Headers': 'X-Requested-With'
		});

		fs.createReadStream(file).pipe(res);
	});

	return true;
}

var host;

http.createServer(function(req, res) {
	res.setHeader("Access-Control-Allow-Origin", req.headers.origin);
	res.setHeader("Access-Control-Allow-Headers", "X-Requested-With, X-Proxy-Host");
	res.setHeader("Access-Control-Allow-Credentials", "true");

	if (cannedResponseHandler(req, res))
		return;

	var splitReq = req.url.split('/');
	if (splitReq.length <= 1)
		return;

	if (req.headers['x-proxy-host']) {
		host = req.headers['x-proxy-host'];
	} else {
		for (var i = 0; i < routeConfigLen; i++) {
			if (req.url.indexOf(routeConfig.proxies[i].proxyURL) === 0) {
				host = routeConfig.proxies[i].host + '/';
				req.url = req.url.substr(routeConfig.proxies[i].proxyURL.length);
				break;
			}
		}
	}

	var formattedUrl = host + req.url;
	var options = {
		url: formattedUrl,
		headers: {
			  Authorization: req.headers.authorization
			, 'User-Agent': req.headers['user-agent']
			, Connection: req.headers.connection
			, cookie: req.headers.cookie
		}
	};

	console.log("Proxying", options.url);

	request(options, function(err, response, body) {
		res.setHeader('content-type', response.headers['content-type']);
		res.end(body);
	});

}).listen(PORT);

console.log("server pid %s listening on port %s", process.pid, PORT);
<commit_msg>support sending data in body, e.g. POST data<commit_after>var http = require('http')
	, fs = require('fs')
	, path = require('path')
	, request = require('request')
	, routeConfig = require(process.argv.pop())
	, PORT = 4040;

var routeConfigLen = routeConfig.proxies.length;

process.on('uncaughtException', function (err) {
  console.log('Caught exception: ' + err);
});

function cannedResponseHandler(req, res) {
    if (!routeConfig.canned || !routeConfig.canned[req.url])
		return false;

	var file = path.join(__dirname, routeConfig.canned[req.url]);
	console.log("Shipping canned response %s", req.url);
	fs.stat(file, function(err, stat) {
		res.writeHead(200, {
			'Content-Type': 'application/json',
			'Content-Length': stat.size,
			'Access-Control-Allow-Origin': '*',
			'Access-Control-Allow-Headers': 'X-Requested-With'
		});

		fs.createReadStream(file).pipe(res);
	});

	return true;
}

var host;

http.createServer(function(req, res) {
	res.setHeader("Access-Control-Allow-Origin", req.headers.origin);
	res.setHeader("Access-Control-Allow-Headers", "Content-Type, X-Requested-With, X-Proxy-Host");
	res.setHeader("Access-Control-Allow-Credentials", "true");

	if (cannedResponseHandler(req, res))
		return;

	var splitReq = req.url.split('/');
	if (splitReq.length <= 1)
		return;

	if (req.headers['x-proxy-host']) {
		host = req.headers['x-proxy-host'];
	} else {
		for (var i = 0; i < routeConfigLen; i++) {
			if (req.url.indexOf(routeConfig.proxies[i].proxyURL) === 0) {
				host = routeConfig.proxies[i].host + '/';
				req.url = req.url.substr(routeConfig.proxies[i].proxyURL.length);
				break;
			}
		}
	}

	var formattedUrl = host + req.url;
	var options = {
		url: formattedUrl,
		headers: {
			  Authorization: req.headers.authorization
			, 'User-Agent': req.headers['user-agent']
			, Connection: req.headers.connection
			, cookie: req.headers.cookie
		}
	};

	console.log("Proxying", options.url);

	var body = "";
	req.on('data', function (data) {
			body += data;
	});
	req.on('end', function () {
		request(options, function(err, response, body) {
			res.setHeader('content-type', response.headers['content-type']);
			res.end(body);
		});
	});

}).listen(PORT);

console.log("server pid %s listening on port %s", process.pid, PORT);
<|endoftext|>


<commit_before>'use strict';

var skynet = require('skynet');
var util = require('util');
var _ = require('lodash');
var EventEmitter = require('events').EventEmitter;
var DeviceManager = require('./device-manager');

var Gatenu = function(config) {
  var self = this;
  var skynetConnection = skynet.createConnection({ uuid: config.uuid, token: config.token, server: config.server, port: config.port });
  var deviceManager = new DeviceManager({
    uuid: config.uuid,
    token: config.token,
    devicePath: config.devicePath,
    tmpPath: config.tmpPath,
    nodePath: config.nodePath,
    server:  config.server,
    port:    config.port
  });

  var refreshDevices = function(callback) {
    self.emit('refresh');
    skynetConnection.whoami({}, function(data){
      deviceManager.refreshDevices(data.devices, callback);
    });
  };

  var updateType = function(){
	console.log('updating type');
    skynetConnection.update({uuid: config.uuid, type: 'device:gateblu'});
		console.log('updated type');
  };

  deviceManager.on('start', function(device){
    self.emit('device:start', device);
  });

  skynetConnection.on('notReady', function(data) {
    console.error('notReady', data);
    if (!config.uuid) {
      skynetConnection.register({}, function(data){
        skynetConnection.identify({uuid: data.uuid, token: data.token});
      });
    }
  });

  skynetConnection.on('ready', function(data){
    config.uuid  = data.uuid;
    config.token = data.token;
		console.log('connected!', data);
    self.emit('config', config);
    updateType();
    refreshDevices(function(error){
      if (error) {
        self.emit('error', error);
      }
    });
  });

  skynetConnection.on('message', function(message){
    if (message.topic === 'refresh') {
      refreshDevices();
    }
    if( deviceManager[message.topic] ) {
      deviceManager[message.topic](message.payload);
    }
  });

  var cleanup = _.once(function() {
    process.stdin.resume();

    deviceManager.stopDevices(function(error, uuids){
      process.exit();
    });
  });

  process.on('exit', cleanup);
  process.on('SIGINT', cleanup);
  process.on('uncaughtException', cleanup);

};

util.inherits(Gatenu, EventEmitter);
module.exports = Gatenu;
<commit_msg>removed console.logs<commit_after>'use strict';

var skynet = require('skynet');
var util = require('util');
var _ = require('lodash');
var EventEmitter = require('events').EventEmitter;
var DeviceManager = require('./device-manager');

var Gatenu = function(config) {
  var self = this;
  var skynetConnection = skynet.createConnection({ uuid: config.uuid, token: config.token, server: config.server, port: config.port });
  var deviceManager = new DeviceManager({
    uuid: config.uuid,
    token: config.token,
    devicePath: config.devicePath,
    tmpPath: config.tmpPath,
    nodePath: config.nodePath,
    server:  config.server,
    port:    config.port
  });

  var refreshDevices = function(callback) {
    self.emit('refresh');
    skynetConnection.whoami({}, function(data){
      deviceManager.refreshDevices(data.devices, callback);
    });
  };

  var updateType = function(){
    skynetConnection.update({uuid: config.uuid, type: 'device:gateblu'});
  };

  deviceManager.on('start', function(device){
    self.emit('device:start', device);
  });

  skynetConnection.on('notReady', function(data) {
    console.error('notReady', data);
    if (!config.uuid) {
      skynetConnection.register({}, function(data){
        skynetConnection.identify({uuid: data.uuid, token: data.token});
      });
    }
  });

  skynetConnection.on('ready', function(data){
    config.uuid  = data.uuid;
    config.token = data.token;
    self.emit('config', config);
    updateType();
    refreshDevices(function(error){
      if (error) {
        self.emit('error', error);
      }
    });
  });

  skynetConnection.on('message', function(message){
    if (message.topic === 'refresh') {
      refreshDevices();
    }
    if( deviceManager[message.topic] ) {
      deviceManager[message.topic](message.payload);
    }
  });

  var cleanup = _.once(function() {
    process.stdin.resume();

    deviceManager.stopDevices(function(error, uuids){
      process.exit();
    });
  });

  process.on('exit', cleanup);
  process.on('SIGINT', cleanup);
  process.on('uncaughtException', cleanup);

};

util.inherits(Gatenu, EventEmitter);
module.exports = Gatenu;
<|endoftext|>


<commit_before>const fs = require('fs')
const path = require('path')

function fileExists (filepath, options, done) {
  if (typeof options === 'function') {
    done = options
    options = {}
  }

  if (!done) {
    return new Promise(resolve => {
      fs.stat(fullPath(filepath, options), (err, stats) => {
        if (err) {
          return resolve(err.code === 'ENOENT' ? false : err)
        }
        resolve(stats.isFile())
      })
    })
  }

  fs.stat(fullPath(filepath, options), (err, stats) => {
    if (err) {
      return err.code === 'ENOENT'
        ? done(null, false)
        : done(err)
    }

    done(null, stats.isFile())
  })
}

fileExists.sync = function fileExistsSync (filepath = '', options = {}) {
  try {
    return fs.statSync(fullPath(filepath, options)).isFile()
  }
  catch (e) {
    // Check exception. If ENOENT - no such file or directory ok, file doesn't exist.
    // Otherwise something else went wrong, we don't have rights to access the file, ...
    if (e.code != 'ENOENT') {
      throw e
    }

    return false
  }
}

function fullPath (filepath, options = {}) {
  const root = options.root
  return (root) ? path.join(root, filepath) : filepath
}

module.exports = fileExists
<commit_msg>Fix Promise error reporting<commit_after>const fs = require('fs')
const path = require('path')

function fileExists (filepath, options, done) {
  if (typeof options === 'function') {
    done = options
    options = {}
  }

  if (!done) {
    return new Promise((resolve, reject) => {
      fs.stat(fullPath(filepath, options), (err, stats) => {
        if (err) {
          return err.code === 'ENOENT'
            ? resolve(false)
            : reject(err)
        }
        resolve(stats.isFile())
      })
    })
  }

  fs.stat(fullPath(filepath, options), (err, stats) => {
    if (err) {
      return err.code === 'ENOENT'
        ? done(null, false)
        : done(err)
    }

    done(null, stats.isFile())
  })
}

fileExists.sync = function fileExistsSync (filepath = '', options = {}) {
  try {
    return fs.statSync(fullPath(filepath, options)).isFile()
  }
  catch (e) {
    // Check exception. If ENOENT - no such file or directory ok, file doesn't exist.
    // Otherwise something else went wrong, we don't have rights to access the file, ...
    if (e.code != 'ENOENT') {
      throw e
    }

    return false
  }
}

function fullPath (filepath, options = {}) {
  const root = options.root
  return (root) ? path.join(root, filepath) : filepath
}

module.exports = fileExists
<|endoftext|>


<commit_before>
/**
 * slice() reference.
 */

var slice = Array.prototype.slice;

/**
 * Expose `co`.
 */

module.exports = co;

/**
 * Wrap the given generator `fn` and
 * return a thunk.
 *
 * @param {Function} fn
 * @return {Function}
 * @api public
 */

function co(fn) {
  var isGenFun = isGeneratorFunction(fn);

  return function (done) {
    var ctx = this;

    // in toThunk() below we invoke co()
    // with a generator, so optimize for
    // this case
    var gen = fn;

    // we only need to parse the arguments
    // if gen is a generator function.
    if (isGenFun) {
      var args = slice.call(arguments), len = args.length;
      var hasCallback = len && 'function' == typeof args[len - 1];
      done = hasCallback ? args.pop() : error;
      gen = fn.apply(this, args);
    } else {
      done = done || error;
    }

    next();

    // #92
    // wrap the callback in a setImmediate
    // so that any of its errors aren't caught by `co`
    function exit(err, res) {
      setImmediate(done.bind(ctx, err, res));
    }

    function next(err, res) {
      var ret;

      // multiple args
      if (arguments.length > 2) res = slice.call(arguments, 1);

      // error
      if (err) {
        try {
          ret = gen.throw(err);
        } catch (e) {
          return exit(e);
        }
      }

      // ok
      if (!err) {
        try {
          ret = gen.next(res);
        } catch (e) {
          return exit(e);
        }
      }

      // done
      if (ret.done) return exit(null, ret.value);

      // normalize
      ret.value = toThunk(ret.value, ctx);

      // run
      if ('function' == typeof ret.value) {
        var called = false;
        try {
          ret.value.call(ctx, function(){
            if (called) return;
            called = true;
            next.apply(ctx, arguments);
          });
        } catch (e) {
          setImmediate(function(){
            if (called) return;
            called = true;
            next(e);
          });
        }
        return;
      }

      // invalid
      next(new Error('yield a function, promise, generator, array, or object'));
    }
  }
}

/**
 * Convert `obj` into a normalized thunk.
 *
 * @param {Mixed} obj
 * @param {Mixed} ctx
 * @return {Function}
 * @api private
 */

function toThunk(obj, ctx) {

  if (isGeneratorFunction(obj)) {
    return co(obj.call(ctx));
  }

  if (isGenerator(obj)) {
    return co(obj);
  }

  if (isPromise(obj)) {
    return promiseToThunk(obj);
  }

  if ('function' == typeof obj) {
    return obj;
  }

  if (isObject(obj) || Array.isArray(obj)) {
    return objectToThunk.call(ctx, obj);
  }

  return obj;
}

/**
 * Convert an object of yieldables to a thunk.
 *
 * @param {Object} obj
 * @return {Function}
 * @api private
 */

function objectToThunk(obj){
  var ctx = this;

  return function(done){
    var keys = Object.keys(obj);
    var pending = keys.length;
    var results = new obj.constructor();
    var finished;

    if (!pending) {
      setImmediate(function(){
        done(null, results)
      });
      return;
    }

    for (var i = 0; i < keys.length; i++) {
      run(obj[keys[i]], keys[i]);
    }

    function run(fn, key) {
      if (finished) return;
      try {
        fn = toThunk(fn, ctx);

        if ('function' != typeof fn) {
          results[key] = fn;
          return --pending || done(null, results);
        }

        fn.call(ctx, function(err, res){
          if (finished) return;

          if (err) {
            finished = true;
            return done(err);
          }

          results[key] = res;
          --pending || done(null, results);
        });
      } catch (err) {
        finished = true;
        done(err);
      }
    }
  }
}

/**
 * Convert `promise` to a thunk.
 *
 * @param {Object} promise
 * @return {Function}
 * @api private
 */

function promiseToThunk(promise) {
  return function(fn){
    promise.then(function(res) {
      fn(null, res);
    }, fn);
  }
}

/**
 * Check if `obj` is a promise.
 *
 * @param {Object} obj
 * @return {Boolean}
 * @api private
 */

function isPromise(obj) {
  return obj && 'function' == typeof obj.then;
}

/**
 * Check if `obj` is a generator.
 *
 * @param {Mixed} obj
 * @return {Boolean}
 * @api private
 */

function isGenerator(obj) {
  return obj && 'function' == typeof obj.next && 'function' == typeof obj.throw;
}

/**
 * Check if `obj` is a generator function.
 *
 * @param {Mixed} obj
 * @return {Boolean}
 * @api private
 */

function isGeneratorFunction(obj) {
  return obj && obj.constructor && 'GeneratorFunction' == obj.constructor.name;
}

/**
 * Check for plain object.
 *
 * @param {Mixed} val
 * @return {Boolean}
 * @api private
 */

function isObject(val) {
  return val && Object == val.constructor;
}

/**
 * Throw `err` in a new stack.
 *
 * This is used when co() is invoked
 * without supplying a callback, which
 * should only be for demonstrational
 * purposes.
 *
 * @param {Error} err
 * @api private
 */

function error(err) {
  if (!err) return;
  setImmediate(function(){
    throw err;
  });
}
<commit_msg>use a closure instead of .bind()<commit_after>
/**
 * slice() reference.
 */

var slice = Array.prototype.slice;

/**
 * Expose `co`.
 */

module.exports = co;

/**
 * Wrap the given generator `fn` and
 * return a thunk.
 *
 * @param {Function} fn
 * @return {Function}
 * @api public
 */

function co(fn) {
  var isGenFun = isGeneratorFunction(fn);

  return function (done) {
    var ctx = this;

    // in toThunk() below we invoke co()
    // with a generator, so optimize for
    // this case
    var gen = fn;

    // we only need to parse the arguments
    // if gen is a generator function.
    if (isGenFun) {
      var args = slice.call(arguments), len = args.length;
      var hasCallback = len && 'function' == typeof args[len - 1];
      done = hasCallback ? args.pop() : error;
      gen = fn.apply(this, args);
    } else {
      done = done || error;
    }

    next();

    // #92
    // wrap the callback in a setImmediate
    // so that any of its errors aren't caught by `co`
    function exit(err, res) {
      setImmediate(function(){
        done.call(ctx, err, res);
      });
    }

    function next(err, res) {
      var ret;

      // multiple args
      if (arguments.length > 2) res = slice.call(arguments, 1);

      // error
      if (err) {
        try {
          ret = gen.throw(err);
        } catch (e) {
          return exit(e);
        }
      }

      // ok
      if (!err) {
        try {
          ret = gen.next(res);
        } catch (e) {
          return exit(e);
        }
      }

      // done
      if (ret.done) return exit(null, ret.value);

      // normalize
      ret.value = toThunk(ret.value, ctx);

      // run
      if ('function' == typeof ret.value) {
        var called = false;
        try {
          ret.value.call(ctx, function(){
            if (called) return;
            called = true;
            next.apply(ctx, arguments);
          });
        } catch (e) {
          setImmediate(function(){
            if (called) return;
            called = true;
            next(e);
          });
        }
        return;
      }

      // invalid
      next(new Error('yield a function, promise, generator, array, or object'));
    }
  }
}

/**
 * Convert `obj` into a normalized thunk.
 *
 * @param {Mixed} obj
 * @param {Mixed} ctx
 * @return {Function}
 * @api private
 */

function toThunk(obj, ctx) {

  if (isGeneratorFunction(obj)) {
    return co(obj.call(ctx));
  }

  if (isGenerator(obj)) {
    return co(obj);
  }

  if (isPromise(obj)) {
    return promiseToThunk(obj);
  }

  if ('function' == typeof obj) {
    return obj;
  }

  if (isObject(obj) || Array.isArray(obj)) {
    return objectToThunk.call(ctx, obj);
  }

  return obj;
}

/**
 * Convert an object of yieldables to a thunk.
 *
 * @param {Object} obj
 * @return {Function}
 * @api private
 */

function objectToThunk(obj){
  var ctx = this;

  return function(done){
    var keys = Object.keys(obj);
    var pending = keys.length;
    var results = new obj.constructor();
    var finished;

    if (!pending) {
      setImmediate(function(){
        done(null, results)
      });
      return;
    }

    for (var i = 0; i < keys.length; i++) {
      run(obj[keys[i]], keys[i]);
    }

    function run(fn, key) {
      if (finished) return;
      try {
        fn = toThunk(fn, ctx);

        if ('function' != typeof fn) {
          results[key] = fn;
          return --pending || done(null, results);
        }

        fn.call(ctx, function(err, res){
          if (finished) return;

          if (err) {
            finished = true;
            return done(err);
          }

          results[key] = res;
          --pending || done(null, results);
        });
      } catch (err) {
        finished = true;
        done(err);
      }
    }
  }
}

/**
 * Convert `promise` to a thunk.
 *
 * @param {Object} promise
 * @return {Function}
 * @api private
 */

function promiseToThunk(promise) {
  return function(fn){
    promise.then(function(res) {
      fn(null, res);
    }, fn);
  }
}

/**
 * Check if `obj` is a promise.
 *
 * @param {Object} obj
 * @return {Boolean}
 * @api private
 */

function isPromise(obj) {
  return obj && 'function' == typeof obj.then;
}

/**
 * Check if `obj` is a generator.
 *
 * @param {Mixed} obj
 * @return {Boolean}
 * @api private
 */

function isGenerator(obj) {
  return obj && 'function' == typeof obj.next && 'function' == typeof obj.throw;
}

/**
 * Check if `obj` is a generator function.
 *
 * @param {Mixed} obj
 * @return {Boolean}
 * @api private
 */

function isGeneratorFunction(obj) {
  return obj && obj.constructor && 'GeneratorFunction' == obj.constructor.name;
}

/**
 * Check for plain object.
 *
 * @param {Mixed} val
 * @return {Boolean}
 * @api private
 */

function isObject(val) {
  return val && Object == val.constructor;
}

/**
 * Throw `err` in a new stack.
 *
 * This is used when co() is invoked
 * without supplying a callback, which
 * should only be for demonstrational
 * purposes.
 *
 * @param {Error} err
 * @api private
 */

function error(err) {
  if (!err) return;
  setImmediate(function(){
    throw err;
  });
}
<|endoftext|>


<commit_before>// Dependency modules
var events        = require('events');

// Local modules
var baClient      = require('./lib/bacnet-client');
var baEnum        = require('./lib/bacnet-enum');

// Public enums
module.exports.enum = baEnum;

/**
 * To be able to communicate to BACNET devices, you have to initialize a new bacstack instance.
 * @class bacstack
 * @param {object=} settings - The options object used for parameterising the bacstack.
 * @param {number=} [settings.port=47808] - BACNET communication port for listening and sending.
 * @param {string=} settings.interface - Specific BACNET communication interface if different from primary one.
 * @param {string=} [settings.broadcastAddress=255.255.255.255] - The address used for broadcast messages.
 * @param {number=} [settings.adpuTimeout=3000] - The timeout in milliseconds until a transaction should be interpreted as error.
 * @example
 * var bacnet = require('bacstack');
 *
 * var client = new bacnet({
 *   port: 47809,                          // Use BAC1 as communication port
 *   interface: '192.168.251.10',          // Listen on a specific interface
 *   broadcastAddress: '192.168.251.255',  // Use the subnet broadcast address
 *   adpuTimeout: 6000                     // Wait twice as long for response
 * });
 */
module.exports = function(settings) {
  var self = new events.EventEmitter();

  settings = settings || {};
  var options = {
    port: settings.port || 47808,
    interface: settings.interface,
    transport: settings.transport,
    broadcastAddress: settings.broadcastAddress || '255.255.255.255',
    adpuTimeout: settings.adpuTimeout || 3000
  };

  var client = new baClient(options);

  client.events.on('iAm', function(address, deviceId, maxAdpu, segmentation, vendorId) {

    /**
     * @event bacstack.iAm
     * @param {string} address - The IP address of the detected device.
     * @param {number} deviceId - The BACNET device-id of the detected device.
     * @param {number} maxAdpu - The max ADPU size the detected device is supporting.
     * @param {number} segmentation - The type of segmentation the detected device is supporting.
     * @param {number} vendorId - The BACNET vendor-id of the detected device.
     * @example
     * client.on('iAm', function(address, deviceId, maxAdpu, segmentation, vendorId) {
     *   console.log('address: ', address, ' - deviceId: ', deviceId, ' - maxAdpu: ', maxAdpu, ' - segmentation: ', segmentation, ' - vendorId: ', vendorId);
     * });
     */
    self.emit('iAm', address, deviceId, maxAdpu, segmentation, vendorId);
  });

  client.events.on('error', function(err) {

    /**
     * @event bacstack.error
     * @param {error} err - The IP address of the detected device.
     * @example
     * client.on('error', function(err) {
     *   console.log('Error occurred: ', err);
     *   client.close();
     * });
     */
    self.emit('error', err);
  });

  /**
   * The whoIs command discovers all BACNET devices in a network.
   * @function bacstack.whoIs
   * @param {number=} lowLimit - Minimal device instance number to search for.
   * @param {number=} highLimit - Maximal device instance number to search for.
   * @param {string=} address - Unicast address if command should device directly.
   * @fires bacstack.iAm
   * @example
   * client.whoIs();
   */
  self.whoIs = function(lowLimit, highLimit, address) {
    client.whoIs(lowLimit, highLimit, address);
  };

  /**
   * The readProperty command reads a single property of an object from a device.
   * @function bacstack.readProperty
   * @param {string} address - IP address of the target device.
   * @param {number} objectType - The BACNET object type to read.
   * @param {number} objectInstance - The BACNET object instance to read.
   * @param {number} propertyId - The BACNET property id in the specified object to read.
   * @param {number=} arrayIndex - The array index of the property to be read.
   * @param {function} next - The callback containing an error, in case of a failure and value object in case of success.
   * @example
   * client.readProperty('192.168.1.43', 8, 44301, 28, null, function(err, value) {
   *   console.log('value: ', value);
   * });
   */
  self.readProperty = function(address, objectType, objectInstance, propertyId, arrayIndex, next) {
    client.readProperty(address, objectType, objectInstance, propertyId, arrayIndex, next);
  };

  /**
   * The writeProperty command writes a single property of an object to a device.
   * @function bacstack.writeProperty
   * @param {string} address - IP address of the target device.
   * @param {number} objectType - The BACNET object type to write.
   * @param {number} objectInstance - The BACNET object instance to write.
   * @param {number} propertyId - The BACNET property id in the specified object to write.
   * @param {number} priority - The priority to be used for writing to the property.
   * @param {object[]} valueList - A list of values to be written to the speicifed property.
   * @param {number} valueList.Tag - The data-type of the value to be written. Has to be a BacnetApplicationTags declaration as specified in lib/bacnet-enum.js.
   * @param {number} valueList.Value - The actual value to be written.
   * @param {function} next - The callback containing an error, in case of a failure and value object in case of success.
   * @example
   * client.writeProperty('192.168.1.43', 8, 44301, 28, 12, [{Tag: 4, Value: 100}], function(err, value) {
   *   console.log('value: ', value);
   * });
   */
  self.writeProperty = function(address, objectType, objectInstance, propertyId, priority, valueList, next) {
    client.writeProperty(address, objectType, objectInstance, propertyId, priority, valueList, next);
  };

  /**
   * The readPropertyMultiple command reads multiple properties in multiple objects from a device.
   * @function bacstack.readPropertyMultiple
   * @param {string} address - IP address of the target device.
   * @param {object[]} propertyIdAndArrayIndex - List of object and property specifications to be read.
   * @param {object} propertyIdAndArrayIndex.objectIdentifier - Specifies which object to read.
   * @param {number} propertyIdAndArrayIndex.objectIdentifier.type - The BACNET object type to read.
   * @param {number} propertyIdAndArrayIndex.objectIdentifier.instance - The BACNET object instance to read.
   * @param {object[]} propertyIdAndArrayIndex.propertyReferences - List of properties to be read.
   * @param {number} propertyIdAndArrayIndex.propertyReferences.propertyIdentifier - The BACNET property id in the specified object to read. Also supports 8 for all properties.
   * @param {function} next - The callback containing an error, in case of a failure and value object in case of success.
   * @example
   * var requestArray = [
   *   {objectIdentifier: {type: 8, instance: 4194303}, propertyReferences: [{propertyIdentifier: 8}]}
   * ];
   * client.readPropertyMultiple('192.168.1.43', requestArray, function(err, value) {
   *   console.log('value: ', value);
   * });
   */
  self.readPropertyMultiple = function(address, propertyIdAndArrayIndex, next) {
    client.readPropertyMultiple(address, propertyIdAndArrayIndex, next);
  };

  /**
   * Unloads the current BACstack instance and closes the underlying UDP socket.
   * @function bacstack.close
   * @example
   * var client = new bacnet();
   * client.close();
   */
  self.close = function() {
    client.close();
  };

  return self;
};
<commit_msg>fix(ba-enums): make sure the exported enums are not overridden<commit_after>// Dependency modules
var events        = require('events');

// Local modules
var baClient      = require('./lib/bacnet-client');
var baEnum        = require('./lib/bacnet-enum');

/**
 * To be able to communicate to BACNET devices, you have to initialize a new bacstack instance.
 * @class bacstack
 * @param {object=} settings - The options object used for parameterising the bacstack.
 * @param {number=} [settings.port=47808] - BACNET communication port for listening and sending.
 * @param {string=} settings.interface - Specific BACNET communication interface if different from primary one.
 * @param {string=} [settings.broadcastAddress=255.255.255.255] - The address used for broadcast messages.
 * @param {number=} [settings.adpuTimeout=3000] - The timeout in milliseconds until a transaction should be interpreted as error.
 * @example
 * var bacnet = require('bacstack');
 *
 * var client = new bacnet({
 *   port: 47809,                          // Use BAC1 as communication port
 *   interface: '192.168.251.10',          // Listen on a specific interface
 *   broadcastAddress: '192.168.251.255',  // Use the subnet broadcast address
 *   adpuTimeout: 6000                     // Wait twice as long for response
 * });
 */
module.exports = function(settings) {
  var self = new events.EventEmitter();

  settings = settings || {};
  var options = {
    port: settings.port || 47808,
    interface: settings.interface,
    transport: settings.transport,
    broadcastAddress: settings.broadcastAddress || '255.255.255.255',
    adpuTimeout: settings.adpuTimeout || 3000
  };

  var client = new baClient(options);

  client.events.on('iAm', function(address, deviceId, maxAdpu, segmentation, vendorId) {

    /**
     * @event bacstack.iAm
     * @param {string} address - The IP address of the detected device.
     * @param {number} deviceId - The BACNET device-id of the detected device.
     * @param {number} maxAdpu - The max ADPU size the detected device is supporting.
     * @param {number} segmentation - The type of segmentation the detected device is supporting.
     * @param {number} vendorId - The BACNET vendor-id of the detected device.
     * @example
     * client.on('iAm', function(address, deviceId, maxAdpu, segmentation, vendorId) {
     *   console.log('address: ', address, ' - deviceId: ', deviceId, ' - maxAdpu: ', maxAdpu, ' - segmentation: ', segmentation, ' - vendorId: ', vendorId);
     * });
     */
    self.emit('iAm', address, deviceId, maxAdpu, segmentation, vendorId);
  });

  client.events.on('error', function(err) {

    /**
     * @event bacstack.error
     * @param {error} err - The IP address of the detected device.
     * @example
     * client.on('error', function(err) {
     *   console.log('Error occurred: ', err);
     *   client.close();
     * });
     */
    self.emit('error', err);
  });

  /**
   * The whoIs command discovers all BACNET devices in a network.
   * @function bacstack.whoIs
   * @param {number=} lowLimit - Minimal device instance number to search for.
   * @param {number=} highLimit - Maximal device instance number to search for.
   * @param {string=} address - Unicast address if command should device directly.
   * @fires bacstack.iAm
   * @example
   * client.whoIs();
   */
  self.whoIs = function(lowLimit, highLimit, address) {
    client.whoIs(lowLimit, highLimit, address);
  };

  /**
   * The readProperty command reads a single property of an object from a device.
   * @function bacstack.readProperty
   * @param {string} address - IP address of the target device.
   * @param {number} objectType - The BACNET object type to read.
   * @param {number} objectInstance - The BACNET object instance to read.
   * @param {number} propertyId - The BACNET property id in the specified object to read.
   * @param {number=} arrayIndex - The array index of the property to be read.
   * @param {function} next - The callback containing an error, in case of a failure and value object in case of success.
   * @example
   * client.readProperty('192.168.1.43', 8, 44301, 28, null, function(err, value) {
   *   console.log('value: ', value);
   * });
   */
  self.readProperty = function(address, objectType, objectInstance, propertyId, arrayIndex, next) {
    client.readProperty(address, objectType, objectInstance, propertyId, arrayIndex, next);
  };

  /**
   * The writeProperty command writes a single property of an object to a device.
   * @function bacstack.writeProperty
   * @param {string} address - IP address of the target device.
   * @param {number} objectType - The BACNET object type to write.
   * @param {number} objectInstance - The BACNET object instance to write.
   * @param {number} propertyId - The BACNET property id in the specified object to write.
   * @param {number} priority - The priority to be used for writing to the property.
   * @param {object[]} valueList - A list of values to be written to the speicifed property.
   * @param {number} valueList.Tag - The data-type of the value to be written. Has to be a BacnetApplicationTags declaration as specified in lib/bacnet-enum.js.
   * @param {number} valueList.Value - The actual value to be written.
   * @param {function} next - The callback containing an error, in case of a failure and value object in case of success.
   * @example
   * client.writeProperty('192.168.1.43', 8, 44301, 28, 12, [{Tag: 4, Value: 100}], function(err, value) {
   *   console.log('value: ', value);
   * });
   */
  self.writeProperty = function(address, objectType, objectInstance, propertyId, priority, valueList, next) {
    client.writeProperty(address, objectType, objectInstance, propertyId, priority, valueList, next);
  };

  /**
   * The readPropertyMultiple command reads multiple properties in multiple objects from a device.
   * @function bacstack.readPropertyMultiple
   * @param {string} address - IP address of the target device.
   * @param {object[]} propertyIdAndArrayIndex - List of object and property specifications to be read.
   * @param {object} propertyIdAndArrayIndex.objectIdentifier - Specifies which object to read.
   * @param {number} propertyIdAndArrayIndex.objectIdentifier.type - The BACNET object type to read.
   * @param {number} propertyIdAndArrayIndex.objectIdentifier.instance - The BACNET object instance to read.
   * @param {object[]} propertyIdAndArrayIndex.propertyReferences - List of properties to be read.
   * @param {number} propertyIdAndArrayIndex.propertyReferences.propertyIdentifier - The BACNET property id in the specified object to read. Also supports 8 for all properties.
   * @param {function} next - The callback containing an error, in case of a failure and value object in case of success.
   * @example
   * var requestArray = [
   *   {objectIdentifier: {type: 8, instance: 4194303}, propertyReferences: [{propertyIdentifier: 8}]}
   * ];
   * client.readPropertyMultiple('192.168.1.43', requestArray, function(err, value) {
   *   console.log('value: ', value);
   * });
   */
  self.readPropertyMultiple = function(address, propertyIdAndArrayIndex, next) {
    client.readPropertyMultiple(address, propertyIdAndArrayIndex, next);
  };

  /**
   * Unloads the current BACstack instance and closes the underlying UDP socket.
   * @function bacstack.close
   * @example
   * var client = new bacnet();
   * client.close();
   */
  self.close = function() {
    client.close();
  };

  return self;
};

// Public enums
module.exports.enum = baEnum;
<|endoftext|>


<commit_before>
module.exports = {
    master: {
        Product: require('./src/master/product'),
        Fabric: require('./src/master/fabric'),
        Buyer: require('./src/master/buyer'),
        Supplier: require('./src/master/supplier'),
        Uom: require('./src/master/uom'),
        Unit: require('./src/master/unit'),
        Category: require('./src/master/category'),
    },
    purchasing: {
        PurchaseOrderItem: require('./src/purchasing/purchase-order-item'),
        PurchaseOrder: require('./src/purchasing/purchase-order'),
        PurchaseOrderExternal: require('./src/purchasing/purchase-order-external'),
        QualityStandard: require('./src/purchasing/quality-standard'),
        DeliveryOrder:require('./src/purchasing/delivery-order')
    },
    map: require('./src/map'),
    validator: require('./src/validator')
}
<commit_msg>update model<commit_after>
module.exports = {
    master: {
        Product: require('./src/master/product'),
        Buyer: require('./src/master/buyer'),
        Supplier: require('./src/master/supplier'),
        Uom: require('./src/master/uom'),
        Unit: require('./src/master/unit'),
        Category: require('./src/master/category'),
    },
    purchasing: {
        PurchaseOrderItem: require('./src/purchasing/purchase-order-item'),
        PurchaseOrder: require('./src/purchasing/purchase-order'),
        PurchaseOrderExternal: require('./src/purchasing/purchase-order-external'),
        QualityStandard: require('./src/purchasing/quality-standard'),
        DeliveryOrder:require('./src/purchasing/delivery-order')
    },
    map: require('./src/map'),
    validator: require('./src/validator')
}
<|endoftext|>


<commit_before>var crypto = require('crypto')

function Merkle (depth) {
  this.hash = null //hash
  this.tree = []
  this.pre = null
  this.length = 0
  this.depth = depth || 0
  this._digest = false
  this.leaf = false
  //this.target = null
  this.sync = false
  //this._onSync = null
}

Merkle.tree = function (a) {
  var m = new Merkle(0)
  a.forEach(function (h) {
    m.update(h)
  })
  return m
}

var proto = Merkle.prototype

function intAt(hash, depth) {

  //parse 'a' as 10
  var i = hash.charCodeAt(depth) - 87

  //but if it was a number, make it count from 0
  return (i < 0) ? i + 39 : i
}

proto.update = function (hash) {

  if(0 === this.length) {
    this.leaf = true
    this._digest = true
    this.pre = hash.substring(0, this.depth)
    this.hash = hash
    this.length = 1

//    if(this.target && this.target == this.digest()) {
//      this.target = null
//      this.sync = true
//      this._onSync(this.pre, this.digest())
//    }

    return this
  }
  var _hash = this.hash

  if(this.leaf) {
    if(hash === this.hash)
      return this
    this.tree[intAt(_hash, this.depth)] = new Merkle(this.depth + 1).update(_hash)
    this.leaf = false
  }

  this._digest = false
  this.hash = null

  var i = intAt(hash, this.depth)
  var t = this.tree[i]

  if(!t) {
    this.tree[i] = new Merkle(this.depth + 1).update(hash)
    this.length ++
  } else {
    this.tree[i].update(hash)
  }

//  if(this.target && this.target == this.digest()) {
//    this.target = null
//    this.sync = true
//    this._onSync(this.pre, this.digest())
//  }

  return this
}

proto.matchesPrefix = function (hash) {
  var d = this.depth
  while(d--)
    if(this.hash[d] !== hash[d])
      return false
  return true
}

proto.digest = function () {
  if(this._digest)
    return this.hash

  var h = crypto.createHash('sha1')

  for(var i = 0; i < 16; i ++) {
    var t = this.tree[i]
    if(t) h.update(t.digest(), 'hex')
  }

  this._digest = true
  return this.hash = h.digest('hex')
}

proto.prefix = function () {
  return this.pre
  //this.firstHash.substring(0, this.depth)
}

proto.toJSON = function () {
  if(this.leaf)
    return this.hash
  return {
    pre: this.prefix(),
    hash: this.digest(),
    tree: this.tree.filter(Boolean).map(function (e) {
      return 'string' === typeof e ? e : e.toJSON()
    })
  }
}

//recreate the array used to create the tree.
proto.leaves = function (a) {
  a = a || []
  if(this.leaf)
    return [this.hash]
  this.tree.forEach(function (o) {
    if(o.leaf) a.push(o.hash)
    else       o.leaves(a)
  })
  return a
}

//iterate down the tree, and find the branch that matches this tree.
proto.subtree = function (prefix) {
  if(this.depth == prefix.length && prefix == this.pre)
    return this

  var i = intAt(prefix, this.depth)
  if(this.tree[i])
    return this.tree[i].subtree(prefix)

  return null
}

proto.has = function (hash) {
  if(this.leaf)
    return this.digest() === hash
  var i = this._at(hash)
  var t = this.tree[i]
  if(!t)
    return false
  return t.has(hash)
}

proto._at = function (hash) {
  var i = hash.charCodeAt(this.depth) - 87

  //but if it was a number, make it count from 0
  return (i < 0) ? i + 39 : i
}

proto.get = function (hash) {
  if(this.leaf)
    return this.digest() === hash ? this : null
  var i = this._at(hash), t = this.tree[i]
  if(!t)
    return null
  return t.get(hash)
}

proto.expand = function () {
  var a = {}
  var d = this.depth
  this.tree.forEach(function (hash) {
    if(hash.leaf)
      a[hash.pre] = hash.digest()
    else
      a[hash.pre] = {hash: hash.digest()/*, depth: ? */}
  })
  return a
}

module.exports = Merkle

if(!module.parent) {
  var table = require('./util').table

  var a = table(4)
  var m = Merkle.tree(a)
  console.log(JSON.stringify(m, null, 2))
}
<commit_msg>count the number of objects with a given prefix<commit_after>var crypto = require('crypto')

function Merkle (depth) {
  this.hash = null //hash
  this.tree = []
  this.pre = null
  this.length = 0
  this.count = 0
  this.depth = depth || 0
  this._digest = false
  this.leaf = false
  this.sync = false
}

Merkle.tree = function (a) {
  var m = new Merkle(0)
  a.forEach(function (h) {
    m.update(h)
  })
  return m
}

var proto = Merkle.prototype

function intAt(hash, depth) {

  //parse 'a' as 10
  var i = hash.charCodeAt(depth) - 87

  //but if it was a number, make it count from 0
  return (i < 0) ? i + 39 : i
}

proto.update = function (hash) {

  if(0 === this.length) {
    this.leaf = true
    this._digest = true
    this.pre = hash.substring(0, this.depth)
    this.hash = hash
    this.length = 1
    this.count = 1
    return true
  }
  var _hash = this.hash

  if(this.leaf) {
    if(hash === this.hash)
      return false
    var u = this.tree[intAt(_hash, this.depth)] = new Merkle(this.depth + 1)
    u.update(_hash)
    this.leaf = false
  }

  this._digest = false
  this.hash = null

  var i = intAt(hash, this.depth)
  var t = this.tree[i]

  if(!t) {
    t = this.tree[i] = new Merkle(this.depth + 1)
    this.length ++
    this.count ++
    t.update(hash)
    return true
  }

  if(t.update(hash)) {
    this.count ++
    return true
  } else
    return false
}

proto.matchesPrefix = function (hash) {
  var d = this.depth
  while(d--)
    if(this.hash[d] !== hash[d])
      return false
  return true
}

proto.digest = function () {
  if(this._digest)
    return this.hash

  var h = crypto.createHash('sha1')

  for(var i = 0; i < 16; i ++) {
    var t = this.tree[i]
    if(t) h.update(t.digest(), 'hex')
  }

  this._digest = true
  return this.hash = h.digest('hex')
}

proto.prefix = function () {
  return this.pre
  //this.firstHash.substring(0, this.depth)
}

proto.toJSON = function () {
  if(this.leaf)
    return this.hash
  return {
    pre: this.prefix(),
    hash: this.digest(),
    tree: this.tree.filter(Boolean).map(function (e) {
      return 'string' === typeof e ? e : e.toJSON()
    })
  }
}

//recreate the array used to create the tree.
proto.leaves = function (a) {
  a = a || []
  if(this.leaf)
    return [this.hash]
  this.tree.forEach(function (o) {
    if(o.leaf) a.push(o.hash)
    else       o.leaves(a)
  })
  return a
}

//iterate down the tree, and find the branch that matches this tree.
proto.subtree = function (prefix) {
  if(this.depth == prefix.length && prefix == this.pre)
    return this

  var i = intAt(prefix, this.depth)
  if(this.tree[i])
    return this.tree[i].subtree(prefix)

  return null
}

proto.has = function (hash) {
  if(this.leaf)
    return this.digest() === hash
  var i = this._at(hash)
  var t = this.tree[i]
  if(!t)
    return false
  return t.has(hash)
}

proto._at = function (hash) {
  var i = hash.charCodeAt(this.depth) - 87

  //but if it was a number, make it count from 0
  return (i < 0) ? i + 39 : i
}

proto.get = function (hash) {
  if(this.leaf)
    return this.digest() === hash ? this : null
  var i = this._at(hash), t = this.tree[i]
  if(!t)
    return null
  return t.get(hash)
}

proto.expand = function () {
  var a = {}
  var d = this.depth
  this.tree.forEach(function (e) {
    if(e.leaf)
      a[e.pre] = {hash: e.digest(), count: 1}
    else
      a[e.pre] = {hash: e.digest(), count: e.count}
  })
  return a
}

module.exports = Merkle

if(!module.parent) {
  var table = require('./util').table

  var a = table(4)
  var m = Merkle.tree(a)
  console.log(JSON.stringify(m, null, 2))
}
<|endoftext|>


<commit_before>// The callback function passed to handlers when the other side doesn't
// expect a reply to the message.
function noReplyCallback(err, obj, cb) {
    if (cb)
        cb(new Error("No reply expected"), null, noReplyCallback);
}

// Error serialization matching bunyan. (Both MIT)
// https://github.com/trentm/node-bunyan/blob/e43a1a405f379c37d59c4227168dca0e8f41d052/lib/bunyan.js#L968-L1002
function getFullErrorStack(ex)
{
    var ret = ex.stack || ex.toString();
    if (typeof(ex.cause) === 'function') {
        var cex = ex.cause();
        if (cex)
            ret += '\nCaused by: ' + getFullErrorStack(cex);
    }
    return ret;
}

var errorSerializer = function(v) {
    if (v && v.stack) {
        v = {
            message: v.message,
            name: v.name,
            stack: getFullErrorStack(v),
            code: v.code,
            signal: v.signal
        };
    }
    return v;
};

function Jmsg(writeFn, handlers) {
    this.handlers = handlers || {};
    this.timeout = 60000;

    this._seq = 1;
    this._callbacks = Object.create(null);
    this._writeFn = writeFn;
}

// Send a JSON message.
Jmsg.prototype.send = function(a, b, c, d) {
    // type, value, [cb], [handle]
    if (typeof(b) !== 'function')
        this._sendRaw({ t: a, v: b }, c, d);
    // type, [cb], [handle]
    else
        this._sendRaw({ t: a }, b, d);
};

Jmsg.prototype._sendRaw = function(msg, cb, handle) {
    if (typeof(cb) === 'function') {
        var handlers = this._handlers;
        var callbacks = this._callbacks;
        var seq = msg.s = this._seq++;
        callbacks[seq] = {
            fn: cb,
            timeout: setTimeout(function() {
                delete callbacks[seq];
                cb.call(handlers, new Error("Timeout"), null, noReplyCallback);
            }, this.timeout)
        };
    }
    this._writeFn(msg, handle);
};

// Dispatch a JSON message.
Jmsg.prototype.dispatch = function(msg, handle) {
    var self = this;

    var seq = msg.s;
    var callback = seq ? function(err, val, cb, handle) {
        self._sendRaw({ r: seq, e: errorSerializer(err), v: val }, cb, handle);
    } : noReplyCallback;

    var fn, tmp;
    var handlers = self.handlers;
    if ((tmp = msg.r)) {
        var callbacks = self._callbacks;
        fn = callbacks[tmp];
        if (fn) {
            delete callback[tmp];
            clearTimeout(fn.timeout);
            fn.fn.call(handlers, msg.e, msg.v, callback, handle);
        }
        else if (seq) {
            callback(new Error("Unknown sequence number"));
        }
    }
    else if ((tmp = msg.t)) {
        fn = handlers.hasOwnProperty(tmp) && handlers[tmp];
        if (fn)
            fn.call(handlers, msg.v, callback, handle);
        else if (seq)
            callback(new Error("No such action"));
    }
};

// Close the instance, finishing all callbacks.
Jmsg.prototype.close = function(err) {
    var handlers = this._handlers;
    var callbacks = this._callbacks;
    this._callbacks = Object.create(null);
    Object.keys(callbacks).forEach(function(key) {
        if (!err) err = new Error("Connection closed");
        callbacks[key].fn.call(handlers, err, null, noReplyCallback, null);
    });
};

// Main export.
exports = module.exports = function(writeFn, handlers) {
    return new Jmsg(writeFn, handlers);
};

// Process on a duplex stream.
exports.stream = function(stream, handlers) {
    var handle = exports(function(msg) {
        s.write(JSON.stringify(msg) + "\n");
    }, handlers);

    var carry = require('carrier').carry(stream);

    carry.on('line', function(msg) {
        try { msg = JSON.parse(msg); }
        catch (err) {}

        if (typeof(msg) === 'object' && msg !== null)
            handle.dispatch(msg);
    });

    carry.on('end', function() {
        handle.close();
    });

    return handle;
};

// Process cluster messages.
exports.cluster = function(a, b) {
    // worker, [handlers]
    if (process.send) {
        channel = process;
        handlers = a;
    }
    // [handlers]
    else {
        channel = a;
        handlers = b;
    }

    var handle = exports(channel.send.bind(channel), handlers);

    channel.on('message', handle.dispatch.bind(handle));

    channel.on('exit', function() {
        handle.close();
    });

    return handle;
};
<commit_msg>Fix bug in stream handling.<commit_after>// The callback function passed to handlers when the other side doesn't
// expect a reply to the message.
function noReplyCallback(err, obj, cb) {
    if (cb)
        cb(new Error("No reply expected"), null, noReplyCallback);
}

// Error serialization matching bunyan. (Both MIT)
// https://github.com/trentm/node-bunyan/blob/e43a1a405f379c37d59c4227168dca0e8f41d052/lib/bunyan.js#L968-L1002
function getFullErrorStack(ex)
{
    var ret = ex.stack || ex.toString();
    if (typeof(ex.cause) === 'function') {
        var cex = ex.cause();
        if (cex)
            ret += '\nCaused by: ' + getFullErrorStack(cex);
    }
    return ret;
}

var errorSerializer = function(v) {
    if (v && v.stack) {
        v = {
            message: v.message,
            name: v.name,
            stack: getFullErrorStack(v),
            code: v.code,
            signal: v.signal
        };
    }
    return v;
};

function Jmsg(writeFn, handlers) {
    this.handlers = handlers || {};
    this.timeout = 60000;

    this._seq = 1;
    this._callbacks = Object.create(null);
    this._writeFn = writeFn;
}

// Send a JSON message.
Jmsg.prototype.send = function(a, b, c, d) {
    // type, value, [cb], [handle]
    if (typeof(b) !== 'function')
        this._sendRaw({ t: a, v: b }, c, d);
    // type, [cb], [handle]
    else
        this._sendRaw({ t: a }, b, d);
};

Jmsg.prototype._sendRaw = function(msg, cb, handle) {
    if (typeof(cb) === 'function') {
        var handlers = this._handlers;
        var callbacks = this._callbacks;
        var seq = msg.s = this._seq++;
        callbacks[seq] = {
            fn: cb,
            timeout: setTimeout(function() {
                delete callbacks[seq];
                cb.call(handlers, new Error("Timeout"), null, noReplyCallback);
            }, this.timeout)
        };
    }
    this._writeFn(msg, handle);
};

// Dispatch a JSON message.
Jmsg.prototype.dispatch = function(msg, handle) {
    var self = this;

    var seq = msg.s;
    var callback = seq ? function(err, val, cb, handle) {
        self._sendRaw({ r: seq, e: errorSerializer(err), v: val }, cb, handle);
    } : noReplyCallback;

    var fn, tmp;
    var handlers = self.handlers;
    if ((tmp = msg.r)) {
        var callbacks = self._callbacks;
        fn = callbacks[tmp];
        if (fn) {
            delete callback[tmp];
            clearTimeout(fn.timeout);
            fn.fn.call(handlers, msg.e, msg.v, callback, handle);
        }
        else if (seq) {
            callback(new Error("Unknown sequence number"));
        }
    }
    else if ((tmp = msg.t)) {
        fn = handlers.hasOwnProperty(tmp) && handlers[tmp];
        if (fn)
            fn.call(handlers, msg.v, callback, handle);
        else if (seq)
            callback(new Error("No such action"));
    }
};

// Close the instance, finishing all callbacks.
Jmsg.prototype.close = function(err) {
    var handlers = this._handlers;
    var callbacks = this._callbacks;
    this._callbacks = Object.create(null);
    Object.keys(callbacks).forEach(function(key) {
        if (!err) err = new Error("Connection closed");
        callbacks[key].fn.call(handlers, err, null, noReplyCallback, null);
    });
};

// Main export.
exports = module.exports = function(writeFn, handlers) {
    return new Jmsg(writeFn, handlers);
};

// Process on a duplex stream.
exports.stream = function(stream, handlers) {
    var handle = exports(function(msg) {
        stream.write(JSON.stringify(msg) + "\n");
    }, handlers);

    var carry = require('carrier').carry(stream);

    carry.on('line', function(msg) {
        try { msg = JSON.parse(msg); }
        catch (err) {}

        if (typeof(msg) === 'object' && msg !== null)
            handle.dispatch(msg);
    });

    carry.on('end', function() {
        handle.close();
    });

    return handle;
};

// Process cluster messages.
exports.cluster = function(a, b) {
    // worker, [handlers]
    if (process.send) {
        channel = process;
        handlers = a;
    }
    // [handlers]
    else {
        channel = a;
        handlers = b;
    }

    var handle = exports(channel.send.bind(channel), handlers);

    channel.on('message', handle.dispatch.bind(handle));

    channel.on('exit', function() {
        handle.close();
    });

    return handle;
};
<|endoftext|>