var command = process.argv[2]
var target = process.argv[3]

var concerns = require('cfg/concerns.json')
var types = require('cfg/types.json')

var tasks = {
  new: {
    runner: require('tasks/new'),
    help: "new"
  },
  install: {
    runner: require('tasks/install'),
    help: "install"
  },
  search: {
    runner: require('tasks/search'),
    help: "search"
  },
  help: {
    runner: require('tasks/help'),
    help: "help"
  }
}

if (tasks[command])
  tasks[command].runner(target)
else
	console.log("No task was found for command [" + command + "] and target [" + target + "]!")

var command = process.argv[2]
var target = process.argv[3]

var concerns = require('./cfg/concerns.json')
var types = require('./cfg/types.json')

var tasks = {
  new: {
    runner: require('tasks/new'),
    help: "new"
  },
  install: {
    runner: require('tasks/install'),
    help: "install"
  },
  search: {
    runner: require('tasks/search'),
    help: "search"
  },
  help: {
    runner: require('tasks/help'),
    help: "help"
  }
}

if (tasks[command])
  tasks[command].runner(target)
else
	console.log("No task was found for command [" + command + "] and target [" + target + "]!")

Fix require calls with leading .


'use strict';
var gutil = require('gulp-util');
var through = require('through2');
var applySourceMap = require('vinyl-sourcemaps-apply');
var objectAssign = require('object-assign');
var to5 = require('6to5');

module.exports = function (opts) {
	opts = opts || {};

	return through.obj(function (file, enc, cb) {
		if (file.isNull()) {
			cb(null, file);
			return;
		}

		if (file.isStream()) {
			cb(new gutil.PluginError('gulp-6to5', 'Streaming not supported'));
			return;
		}

		try {
			var fileOpts = objectAssign({}, opts, {
				filename: file.path,
				sourceMap: !!file.sourceMap
			});

			var res = to5.transform(file.contents.toString(), fileOpts);

			if (file.sourceMap && res.map) {
				applySourceMap(file, res.map);
			}

			file.contents = new Buffer(res.code);
			this.push(file);
		} catch (err) {
			this.emit('error', new gutil.PluginError('gulp-6to5', err, {fileName: file.path}));
		}

		cb();
	});
};

'use strict';
var gutil = require('gulp-util');
var through = require('through2');
var applySourceMap = require('vinyl-sourcemaps-apply');
var objectAssign = require('object-assign');
var to5 = require('6to5');

module.exports = function (opts) {
	opts = opts || {};

	return through.obj(function (file, enc, cb) {
		if (file.isNull()) {
			cb(null, file);
			return;
		}

		if (file.isStream()) {
			cb(new gutil.PluginError('gulp-6to5', 'Streaming not supported'));
			return;
		}

		try {
			var fileOpts = objectAssign({}, opts, {
				filename: file.path,
				filenameRelative: file.relative,
				sourceMap: !!file.sourceMap
			});

			var res = to5.transform(file.contents.toString(), fileOpts);

			if (file.sourceMap && res.map) {
				applySourceMap(file, res.map);
			}

			file.contents = new Buffer(res.code);
			this.push(file);
		} catch (err) {
			this.emit('error', new gutil.PluginError('gulp-6to5', err, {fileName: file.path}));
		}

		cb();
	});
};

Add filenameRelative to opts to support AMD module names


'use strict';

const defaults = {
  currency: '€',
  currencyPosition: 'after',
  decimals: 2,
  decimalSeparator: ',',
  orderSeparator: '.',
  zeroDecimals: '',
  space: ' '
};

module.exports = (value, options) => {
  const config = Object.assign({}, defaults, options);

  if (isNaN(value) || value === null) {
    return '';
  }
  value = Number(value);
  value = value.toFixed(~~config.decimals);

  const parts = value.split('.');
  const fnums = parts[0];
  let dec = parts[1] ? config.decimalSeparator + parts[1] : '';

  let curr = '';
  if (config.currency) {
    curr = config.currencyPosition === 'before' ?
      config.currency + config.space :
      config.space + config.currency;
  }

  // Do something with zero-valued decimals
  if (
    (config.zeroDecimals !== null || config.zeroDecimals !== undefined) &&
    parseInt(parts[1], 10) === 0
  ) {
    if (config.zeroDecimals === '') {
      // Strip away zero-valued decimals
      dec = '';
    } else {
      // Add custom string
      dec = config.decimalSeparator + config.zeroDecimals;
    }
  }

  const formattedValue =
    fnums.replace(/(\d)(?=(?:\d{3})+$)/g, '$1' + config.orderSeparator) + dec;
  return config.currencyPosition === 'before' ?
    // As in '$ 123'
    curr + formattedValue :
    // As in '123 €'
    formattedValue + curr;
};

'use strict';

const defaults = {
  currency: '€',
  currencyPosition: 'after',
  decimals: 2,
  decimalSeparator: ',',
  orderSeparator: '.',
  zeroDecimals: '',
  space: ' '
};

module.exports = (value, options) => {
  const config = Object.assign({}, defaults, options);

  if (isNaN(value) || value === null) {
    return '';
  }
  value = Number(value);
  value = value.toFixed(~~config.decimals);

  const parts = value.split('.');
  const fnums = parts[0];
  let dec = parts[1] ? config.decimalSeparator + parts[1] : '';

  let curr = '';
  if (config.currency) {
    curr = config.currencyPosition === 'before' ?
      config.currency + config.space :
      config.space + config.currency;
  }

  // Do something with zero-valued decimals
  if (typeof config.zeroDecimals === 'string' && parseInt(parts[1], 10) === 0) {
    if (config.zeroDecimals === '') {
      // Strip away zero-valued decimals
      dec = '';
    } else {
      // Add custom string
      dec = config.decimalSeparator + config.zeroDecimals;
    }
  }

  const formattedValue =
    fnums.replace(/(\d)(?=(?:\d{3})+$)/g, '$1' + config.orderSeparator) + dec;
  return config.currencyPosition === 'before' ?
    // As in '$ 123'
    curr + formattedValue :
    // As in '123 €'
    formattedValue + curr;
};

Fix a bug with non-string zero decimals.


var fs = require('fs');
var chalk = require('chalk');
var partiesAbbreviation = require('./util/parties-abbreviations.js');

module.exports = function splitResults(json, directory) {

	var electionDate = json.electionDate;

	// save each json.races item as a separate file
	json.races.forEach(function(race, index, array) {

		// create file name
		var state = race.reportingUnits[0].statePostal;
		var party = race.party;
		var raceType = race.raceType;
		var filename = directory + '/' + [state, party, raceType].join('-') + '.json';

		// add election date to race
		race.electionDate = electionDate;

		// add party name to race
		race.partyName = partiesAbbreviation[race.party];

		fs.writeFileSync(filename, JSON.stringify(race, null, 2));
		console.log(chalk.green('Writing ' + filename));

	});

}

var fs = require('fs');
var chalk = require('chalk');

module.exports = function splitResults(json, directory) {

	var electionDate = json.electionDate;

	// save each json.races item as a separate file
	json.races.forEach(function(race, index, array) {

		// create file name
		var state = race.reportingUnits[0].statePostal;
		var party = race.party;
		var raceType = race.raceType;
		var filename = directory + '/' + [state, party, raceType].join('-') + '.json';

		// add election date to race
		race.electionDate = electionDate;

		fs.writeFileSync(filename, JSON.stringify(race, null, 2));
		console.log(chalk.green('Writing ' + filename));

	});

}

Revert "Add party name to race"


'use strict';
const xRegExp = require('xregexp');

module.exports = (text, separator) => {
	if (typeof text !== 'string') {
		throw new TypeError('Expected a string');
	}

	separator = typeof separator === 'undefined' ? '_' : separator;

	const regex1 = xRegExp('([\\p{Ll}\\d])(\\p{Lu})', 'g');
	const regex2 = xRegExp('(\\p{Lu}+)(\\p{Lu}[\\p{Ll}\\d]+)', 'g');

	return text
		.replace(regex1, `$1${separator}$2`)
		.replace(regex2, `$1${separator}$2`)
		.toLowerCase();
};

'use strict';
const xRegExp = require('xregexp');

module.exports = (text, separator) => {
	if (typeof text !== 'string') {
		throw new TypeError('Expected a string');
	}

	separator = typeof separator === 'undefined' ? '_' : separator;

	const regex1 = xRegExp('([\\p{Ll}\\d])(\\p{Lu})', 'g');
	const regex2 = xRegExp('(\\p{Lu}+)(\\p{Lu}[\\p{Ll}\\d]+)', 'g');

	return text
		// TODO: Use this instead of `xregexp` when targeting Node.js 10:
		// .replace(/([\p{Lowercase_Letter}\d])(\p{Uppercase_Letter})/gu, `$1${separator}$2`)
		// .replace(/(\p{Lowercase_Letter}+)(\p{Uppercase_Letter}[\p{Lowercase_Letter}\d]+)/gu, `$1${separator}$2`)
		.replace(regex1, `$1${separator}$2`)
		.replace(regex2, `$1${separator}$2`)
		.toLowerCase();
};

Add comment about future regex


module.exports = {
	devices: require("./src/lib/devices"),
	drivers: require("./src/lib/drivers"),
	events: require("./src/lib/events"),
	maps: require("./src/lib/maps")
};

module.exports = {
	devices: require("./src/lib/devices"),
	drivers: require("./src/lib/drivers"),
	events: require("./src/lib/events")
};

Remove problematic maps from export


var Disclosure = function(el) {
  var self = this;
  self.el = el;
  self.isActive = false;
  self.details = el.querySelectorAll('[data-details]');
  el.addEventListener('click', function(e) { self.toggle(e) });
  self.hide();
};

Disclosure.prototype.hide = function() {
  for (var i = 0; i < this.details.length; i++) {
    this.details[i].style.display = 'none';
  }
};

Disclosure.prototype.show = function() {
  for (var i = 0; i < el.details.length; i++) {
    this.details[i].style.display = 'block';
  }
};

Disclosure.prototype.toggle = function(e) {
  e.stopPropagation();
  this.isActive = !this.isActive;
  if (this.isActive) { this.show() } else { this.hide() }
};

module.exports = function(el) {
  return new Disclosure(el);
};

var Disclosure = function(el) {
  var self = this;
  self.el = el;
  self.isActive = false;
  self.details = el.querySelectorAll('[data-details]');
  el.addEventListener('click', function(e) { self.toggle(e) });
  self.hide();
};

Disclosure.prototype.hide = function() {
  for (var i = 0; i < this.details.length; i++) {
    this.details[i].style.display = 'none';
  }
};

Disclosure.prototype.show = function() {
  for (var i = 0; i < el.details.length; i++) {
    this.details[i].style.display = 'block';
  }
};

Disclosure.prototype.toggle = function(e) {
  e.stopPropagation();
  this.isActive = !this.isActive;
  if (this.isActive) { this.show() } else { this.hide() }
};

module.exports = {
  create: function(el) {
    return new Disclosure(el);
  },
  all: function() {
    var els = document.querySelectorAll("[data-disclose]");
    for (var i = 0; i < els.length; i++) {
      new Disclosure(els[i]);
    }
  }
};

Expand the api to have an all()


'use strict';

// Load the http module to create an http server.
var http = require('http');

var listenPort = process.env.VCAP_APP_PORT || 8000;

// Configure our HTTP server to respond with Hello World to all requests.
var server = http.createServer(function (request, response) {
  response.writeHead(200, {'Content-Type': 'text/plain'});
  response.end('Hello World\n');
  console.log('Another happy world served!');
});

// Listen on port 8000, IP defaults to 127.0.0.1
server.listen(listenPort);

// Put a friendly message on the terminal
console.log('Server running on port ' + listenPort);

'use strict';

// Load the http module to create an http server.
var http = require('http');

var listenPort = process.env.VCAP_APP_PORT || 8000;

// Configure our HTTP server to respond with Hello World to all requests.
var server = http.createServer(function (request, response) {
  response.writeHead(200, {'Content-Type': 'text/plain'});
  response.end('Hello World\n');
  response.write(process.env.VCAP_SERVICES);
  console.log('Another happy world served!');
});

// Listen on port 8000, IP defaults to 127.0.0.1
server.listen(listenPort);

// Put a friendly message on the terminal
console.log('Server running on port ' + listenPort);

Add a line to inspect VCAP_SERVICES


'use strict';

var getArrowFunctions = function getArrowFunctions() {
    return [
		Function('return (a, b) => a * b;')(),
		Function('return () => 42;')(),
		Function('return () => function () {};')(),
		Function('return () => x => x * x;')(),
		Function('return x => x * x;')()
	];
};
var arrowFuncs = [];
try { arrowFuncs = getArrowFunctions(); } catch (e) {/**/}

module.exports = function makeArrowFunction() {
	return arrowFuncs[0];
};
module.exports.list = function makeArrowFunctions() {
	return arrowFuncs.slice();
};

'use strict';

var getArrowFunctions = function getArrowFunctions() {
    return [
		Function('return (a, b) => a * b;')(),
		Function('return () => 42;')(),
		Function('return () => function () {};')(),
		Function('return () => x => x * x;')(),
		Function('return x => x * x;')(),
		Function('return x => { return x * x; }')(),
		Function('return (x, y) => { return x + x; }')()
	];
};
var arrowFuncs = [];
try { arrowFuncs = getArrowFunctions(); } catch (e) {/**/}

module.exports = function makeArrowFunction() {
	return arrowFuncs[0];
};
module.exports.list = function makeArrowFunctions() {
	return arrowFuncs.slice();
};

Add arrow functions with explicit block bodies.


module.exports = semanticEditionParse

var digit = '[1-9][0-9]*'

var EUCD = new RegExp(
  '^' +
  '(' + digit + ')e' +
  '(?:' +
    '(' + digit + ')u' +
    '(?:' +
      '(' + digit + ')c' + ')?' + ')?' +
  '(?:' +
    '(' + digit + ')d' + ')?' +
  '$')

var components = [ 'edition', 'update', 'correction', 'draft' ]

function semanticEditionParse(argument) {
  var parsed = EUCD.exec(argument)
  var returned = { }
  components.forEach(function(component, index) {
    var group = ( index + 1 )
    var value = parsed[group]
    if (value !== undefined) {
      returned[component] = parseInt(value) } })
  return returned }

module.exports = semanticEditionParse

var captureDigit = '([1-9][0-9]*)'

var EUCD = new RegExp(
  '^' +
  captureDigit + 'e' +
  '(?:' +
    captureDigit + 'u' +
    '(?:' +
      captureDigit + 'c' + ')?' + ')?' +
  '(?:' +
    captureDigit + 'd' + ')?' +
  '$')

var components = [ 'edition', 'update', 'correction', 'draft' ]

function semanticEditionParse(argument) {
  var parsed = EUCD.exec(argument)
  var returned = { }
  components.forEach(function(component, index) {
    var group = ( index + 1 )
    var value = parsed[group]
    if (value !== undefined) {
      returned[component] = parseInt(value) } })
  return returned }

Refactor regular expression digit pattern


'use strict';

var eco = require('eco');

exports.name = 'eco';
exports.outputFormat = 'html';
exports.render = function (str, options) {
  return eco.render(str, options);
};

'use strict';

var eco = require('eco');

exports.name = 'eco';
exports.outputFormat = 'xml';
exports.render = function (str, options) {
  return eco.render(str, options);
};

Use XML as output format


var through = require('through-gulp')
var gutil = require('gulp-util')
var rext = require('replace-ext')
var preprocessor = require('sourdough-preprocessor')
var PluginError = gutil.PluginError

var PLUGIN_NAME = 'gulp-sourdough'

function sourdough(options) {
    options = options || {}
    return through(function (file, enc, cb) {
        if (file.isStream()) {
            return cb(new PluginError(PLUGIN_NAME, 'Streaming not supported'))
        }
        if (file.isBuffer()) {
            try {
                file.path = rext(file.path, '.css')
                file.contents = new Buffer(preprocessor(String(file.contents), options))
            } catch (e) {
                return cb(new PluginError(PLUGIN_NAME, e))
            }
        }
        this.push(file)
        cb()
    }, function (cb) {
        cb()
    });
}

module.exports = sourdough

var through = require('through-gulp')
var gutil = require('gulp-util')
var rext = require('replace-ext')
var preprocessor = require('sourdough-preprocessor')
var PluginError = gutil.PluginError

var PLUGIN_NAME = 'gulp-sourdough'

function sourdough(options) {
    options = options || {}
    return through(function (file, enc, cb) {

        if (options.from === undefined) {
          options.from = file.path
        }

        if (file.isStream()) {
            return cb(new PluginError(PLUGIN_NAME, 'Streaming not supported'))
        }
        if (file.isBuffer()) {
            try {
                file.path = rext(file.path, '.css')
                file.contents = new Buffer(preprocessor(String(file.contents), options))
            } catch (e) {
                return cb(new PluginError(PLUGIN_NAME, e))
            }
        }
        this.push(file)
        cb()
    }, function (cb) {
        cb()
    });
}

module.exports = sourdough

Add from prop to fix imports


#!/usr/bin/env node

module.exports = (function() {
    var turboLogo = require('turbo-logo'),
        colors = require('colors/safe');

    return {
        print: finalPrint
    };

    /////////

    function getText() {
        return 'Burger JS';
    }

    function getBurgerAscii() {
        return '      _..----.._      \r\n    .\'     o    \'.    \r\n   \/   o       o  \\\r\n  |o        o     o|\r\n  \/\'-.._o     __.-\'\\\r\n  \\      `````     \/\r\n  |``--........--\'`|\r\n   \\ \/\r\n     `\'----------\'`';
    }

    function finalPrint(options) {
        var burger = getBurgerAscii(),
            text = getText(),
            color = options && options.color || 'rainbow';

        console.log(colors[color](burger));
        turboLogo(text, color);
    }
})();

#!/usr/bin/env node

module.exports = (function() {
    'use strict';

    var turboLogo = require('turbo-logo'),
        colors = require('colors/safe');

    return {
        print: finalPrint
    };

    /////////

    function getText() {
        return 'Burger JS';
    }

    function getBurgerAscii() {
        return '      _..----.._      \r\n    .\'     o    \'.    \r\n   \/   o       o  \\\r\n  |o        o     o|\r\n  \/\'-.._o     __.-\'\\\r\n  \\      `````     \/\r\n  |``--........--\'`|\r\n   \\ \/\r\n     `\'----------\'`';
    }

    function finalPrint(options) {
        var burger = getBurgerAscii(),
            text = getText(),
            color = options && options.color || 'rainbow';

        console.log(colors[color](burger));
        turboLogo(text, color);
    }
})();

Add 'use-strict' just to trigger the build


'use strict';

module.exports = makeError;
function makeError(code, message, options) {
  var line = options.line;
  var column = options.column;
  var filename = options.filename;
  var src = options.src;
  var fullMessage;
  var location = line + (column ? ':' + column : '');
  if (src) {
    var lines = src.split('\n');
    var start = Math.max(line - 3, 0);
    var end = Math.min(lines.length, line + 3);
    // Error context
    var context = lines.slice(start, end).map(function(text, i){
      var curr = i + start + 1;
      return (curr == line ? '  > ' : '    ')
        + curr
        + '| '
        + text;
    }).join('\n');
    fullMessage = (filename || 'Jade') + ':' + location + '\n' + context + '\n\n' + message;
  } else {
    fullMessage = (filename || 'Jade') + ':' + location + '\n\n' + message;
  }
  var err = new Error(fullMessage);
  err.code = 'JADE:' + code;
  err.msg = message;
  err.line = line;
  err.column = column;
  err.filename = filename;
  err.src = src;
  return err;
}

'use strict';

module.exports = makeError;
function makeError(code, message, options) {
  var line = options.line;
  var column = options.column;
  var filename = options.filename;
  var src = options.src;
  var fullMessage;
  var location = line + (column ? ':' + column : '');
  if (src) {
    var lines = src.split('\n');
    var start = Math.max(line - 3, 0);
    var end = Math.min(lines.length, line + 3);
    // Error context
    var context = lines.slice(start, end).map(function(text, i){
      var curr = i + start + 1;
      return (curr == line ? '  > ' : '    ')
        + curr
        + '| '
        + text;
    }).join('\n');
    fullMessage = (filename || 'Jade') + ':' + location + '\n' + context + '\n\n' + message;
  } else {
    fullMessage = (filename || 'Jade') + ':' + location + '\n\n' + message;
  }
  var err = new Error(fullMessage);
  err.code = 'JADE:' + code;
  err.msg = message;
  err.line = line;
  err.column = column;
  err.filename = filename;
  err.src = src;
  err.toJSON = function () {
    return {
      code: this.code,
      msg: this.msg,
      line: this.line,
      column: this.column,
      filename: this.filename
    };
  };
  return err;
}

Add a toJSON method to the error object


const fs = require('fs');
const Fuze = require('fuse.js');
const mustache = require('mustache');

const template = fs.readFileSync('./template.md', {encoding: 'utf-8'});

module.exports = robot => {
  robot.on('issues.opened', async (event, context) => {
    const github = await robot.auth(event.payload.installation.id);

    // Get all issues that aren't the new issue
    const allIssues = await github.issues.getForRepo(context.repo());
    const otherIssues = allIssues.filter(issue => issue.number !== context.issue().number);
    const theIssue = allIssues.find(issue => issue.number === context.issue().number);

    const fuse = new Fuze(otherIssues, {
      shouldSort: true,
      threshold: 0.2,
      keys: [{
        name: 'title',
        weight: 0.8
      }, {
        name: 'body',
        weight: 0.2
      }]
    });

    const results = fuse.search(theIssue.title);
    if (results.length > 0) {
      const commentBody = mustache.render(template, {
        payload: event.payload,
        issues: otherIssues.slice(0, 3)
      });

      await github.issues.createComment(context.issue({body: commentBody}));
    }
  });
};

const fs = require('fs');
const Fuze = require('fuse.js');
const mustache = require('mustache');

const defaultTemplate = fs.readFileSync('./template.md', {encoding: 'utf-8'});

module.exports = robot => {
  robot.on('issues.opened', async (event, context) => {
    const github = await robot.auth(event.payload.installation.id);

    // Get all issues that aren't the new issue
    const allIssues = await github.issues.getForRepo(context.repo());
    const otherIssues = allIssues.filter(issue => issue.number !== context.issue().number);
    const theIssue = allIssues.find(issue => issue.number === context.issue().number);

    const fuse = new Fuze(otherIssues, {
      shouldSort: true,
      threshold: 0.2,
      keys: [{
        name: 'title',
        weight: 0.8
      }, {
        name: 'body',
        weight: 0.2
      }]
    });

    const results = fuse.search(theIssue.title);

    if (results.length > 0) {
      let template;

      try {
        // Try to get issue template from the repository
        const params = context.repo({path: '.github/DUPLICATE_ISSUE_TEMPLATE.md'});
        const data = await github.repos.getContent(params);
        template = new Buffer(data.content, 'base64').toString();
      } catch (err) {
        // It doesn't have one, so let's use the default
        template = defaultTemplate;
      }

      const commentBody = mustache.render(template, {
        payload: event.payload,
        issues: otherIssues.slice(0, 3)
      });

      await github.issues.createComment(context.issue({body: commentBody}));
    }
  });
};

Use `.github/DUPLICATE_ISSUE_TEMPLATE.md` if it exists


'use strict'

var State = require('dover')
var Observ = require('observ')
var emailRegex = require('email-regex')({exact: true})
var isEmail = emailRegex.test.bind(emailRegex)
var h = require('virtual-dom/h')
var changeEvent = require('value-event/change')

module.exports = EmailInput

function EmailInput (data) {
  data = data || {}

  var state = State({
    value: Observ(data.value || ''),
    valid: Observ(isEmail(data.value) || false),
    placeholder: Observ(data.placeholder || ''),
    channels: {
      change: change
    }
  })

  state.value(function (email) {
    state.valid.set(isEmail(email))
  })

  return state
}

function change (state, data) {
  state.value.set(data.email)
}

EmailInput.render = function render (state) {
  return h('input', {
    type: 'email',
    value: state.value,
    name: 'email',
    'ev-event': changeEvent(state.channels.change),
    placeholder: state.placeholder
  })
}

'use strict'

var State = require('dover')
var Observ = require('observ')
var emailRegex = require('email-regex')({exact: true})
var isEmail = emailRegex.test.bind(emailRegex)
var h = require('virtual-dom/h')
var changeEvent = require('value-event/change')

module.exports = EmailInput

function EmailInput (data) {
  data = data || {}

  var state = State({
    value: Observ(data.value || ''),
    valid: Observ(isEmail(data.value) || false),
    channels: {
      change: change
    }
  })

  state.value(function (email) {
    state.valid.set(isEmail(email))
  })

  return state
}

function change (state, data) {
  state.value.set(data.email)
}

EmailInput.render = function render (state) {
  return h('input', {
    type: 'email',
    value: state.value,
    name: 'email',
    'ev-event': changeEvent(state.channels.change)
  })
}

Remove placeholder from state atom


// Avoid `console` errors in browsers that lack a console.
(function() {
    var noop = function noop() {};
    var methods = [
        'assert', 'clear', 'count', 'debug', 'dir', 'dirxml', 'error',
        'exception', 'group', 'groupCollapsed', 'groupEnd', 'info', 'log',
        'markTimeline', 'profile', 'profileEnd', 'table', 'time', 'timeEnd',
        'timeStamp', 'trace', 'warn'
    ];
    var length = methods.length;
    var console = window.console || {};

    while (length--) {
        // Only stub undefined methods.
        console[methods[length]] = console[methods[length]] || noop;
    }
}());

// Place any jQuery/helper plugins in here.

// Avoid `console` errors in browsers that lack a console.
(function() {
    var noop = function noop() {};
    var methods = [
        'assert', 'clear', 'count', 'debug', 'dir', 'dirxml', 'error',
        'exception', 'group', 'groupCollapsed', 'groupEnd', 'info', 'log',
        'markTimeline', 'profile', 'profileEnd', 'table', 'time', 'timeEnd',
        'timeStamp', 'trace', 'warn'
    ];
    var length = methods.length;
    var console = (window.console = window.console || {});

    while (length--) {
        // Only stub undefined methods.
        console[methods[length]] = console[methods[length]] || noop;
    }
}());

// Place any jQuery/helper plugins in here.

Fix `console` stubbing method in oldIE


document.getElementById("ayuda").setAttribute("aria-current", "page");
var aside = document.getElementById("complementario");
var button = document.createElement("BUTTON");
var text = document.createTextNode("Prueba");
button.appendChild(text);
aside.appendChild(button);
button.addEventListener("click", prueba, true);

function prueba() {
	var xhttp = new XMLHttpRequest();
	xhttp.onreadystatechange = function() {
		if (this.readyState == 4 && this.status == 200) {
			var div = document.createElement("DIV");
			div.innerHTML(this.responseText);
			aside.appendChild(div);
		}
	};
	xhttp.open("GET", "../userGuide.html", true);
	xhttp.send();
}

document.getElementById("ayuda").setAttribute("aria-current", "page");
var aside = document.getElementById("complementario");
var button = document.createElement("BUTTON");
var text = document.createTextNode("Prueba");
button.appendChild(text);
aside.appendChild(button);
button.addEventListener("click", prueba, true);

function prueba() {
	var xhttp = new XMLHttpRequest();
	alert("prueba");
	xhttp.onreadystatechange = function() {
		if (this.readyState == 4 && this.status == 200) {
			var div = document.createElement("DIV");
			div.innerHTML(this.responseText);
			aside.appendChild(div);
		}
	};
	xhttp.open("GET", "../userGuide.html", true);
	xhttp.send();
}

Add alert to test AJAX


//@TODO: This is not yet working in Safari. Test and fix.

function scrollTo(e) {
    var distanceToTop = function (el) {
            try {
                return Math.floor(el.getBoundingClientRect().top);
            } catch (err) {
                console.log(err);
            }
        },
        targetID = this.getAttribute("href"),
        targetAnchor = document.querySelector(targetID),
        originalTop = distanceToTop(targetAnchor),
        offset = document.querySelector('.l-nav-primary-desktop').offsetHeight;

    e.preventDefault();

    if (!targetAnchor) {
        return;
    }

    window.scrollBy({ top: originalTop - offset, left: 0, behavior: "smooth" });

}

// grab links
var linksToAnchors = document.querySelectorAll('a.page-scroll');
// Event handler for clicking on links
linksToAnchors.forEach(function (each) {
    each.onclick = scrollTo;
});

Add @TODO as a reminder to fix the fact that the scrollTo is not working with Safari yet.


Bureaucracy.start.cols = [
	{
		_id: 'name',
		name: "Name",
		type: String
	},
	{
		_id: 'date',
		name: "Travel Date",
		type: Date
	},
	{
		_id: 'age',
		name: "Age",
		type: Number
	},
	{
		_id: 'things',
		name: "Things",
		type: Array,
		value: function(xs) {
			return xs.length;
		}
	},
	{
		_id: 'location',
		name: "Location",
		type: Location
	}
];

Bureaucracy.start.rows = [
	{
		_id: 'edgar',
		name: "Edgar",
		age: 77,
		things: ["filing-cabinet"],
		location: "DC",
		date: "2015-02-01"
	},
	{
		_id: 'dale',
		name: "Dale",
		age: 55,
		things: ["microcassette recorder"],
		location: "WA",
		date: "2015-02-11"
	},
	{
		_id: 'clarice',
		name: "Clarice",
		age: 52,
		things: ["dresser", "cabinet"],
		location: "OH",
		date: "2015-01-30"
	}
];

Bureaucracy.start.cols = [
	{
		_id: 'name',
		name: "Name",
		type: String
	},
	{
		_id: 'date',
		name: "Travel Date",
		type: Date
	},
	{
		_id: 'age',
		name: "Age",
		type: Number
	},
	{
		_id: 'things',
		name: "Things",
		type: Array,
		value: function(row, col) {
			var xs = row[col._id];
			return xs.length;
		}
	},
	{
		_id: 'location',
		name: "Location",
		type: Location
	}
];

Bureaucracy.start.rows = [
	{
		_id: 'edgar',
		name: "Edgar",
		age: 77,
		things: ["filing-cabinet"],
		location: "DC",
		date: "2015-02-01"
	},
	{
		_id: 'dale',
		name: "Dale",
		age: 55,
		things: ["microcassette recorder"],
		location: "WA",
		date: "2015-02-11"
	},
	{
		_id: 'clarice',
		name: "Clarice",
		age: 52,
		things: ["dresser", "cabinet"],
		location: "OH",
		date: "2015-01-30"
	}
];

Fix computed value in demo


// Include The 'require.async' Module
require("require.async")(require);

/**
 * Tokenizes an input string.
 *
 * @param {String} Input
 *
 * @return {Array}
 */
function tokenize (input) {
    return input
            .replace(/[^a-zA-Z ]+/g, "")
            .replace("/ {2,}/", " ")
            .toLowerCase()
            .split(" ");
}

/**
 * Performs sentiment analysis on the provided input "term".
 *
 * @param {String} Input term
 *
 * @return {Object}
 */
module.exports = function (term, callback) {

	// Include the AFINN Dictionary JSON asynchronously
	require.async("./AFINN.json", function(afinn) {

        // Split line term to letters only words array
        var words = tokenize(term || "");
        var score = 0;
        var rate;
        var i = 0;

        function calculate(word) {
            // Get the word rate from the AFINN dictionary
            rate = afinn[word];
            if (rate) {
                // Add current word rate to the final calculated sentiment score
                score += rate;
            }

            // Defer next turn execution (Etheration)
            setImmediate(function() {
                // Use callback for completion
                if (i === (words.length - 1)) {
                    callback(null, score);
                }
                else {
                    // Invoke next turn
                    calculate(words[++i]);
                }
            });
        }

        // Start calculating
        calculate(i);
	});
};

// Include The 'require.async' Module
require("require.async")(require);

/**
 * Tokenizes an input string.
 *
 * @param {String} Input
 *
 * @return {Array}
 */
function tokenize (input) {
    return input
            .replace(/[^a-zA-Z ]+/g, "")
            .replace("/ {2,}/", " ")
            .toLowerCase()
            .split(" ");
}

/**
 * Performs sentiment analysis on the provided input "term".
 *
 * @param {String} Input term
 *
 * @return {Object}
 */
module.exports = function (term, callback) {

	// Include the AFINN Dictionary JSON asynchronously
	require.async("./AFINN.json", function(afinn) {

        // Split line term to letters only words array
        var words = tokenize(term || "");
        var score = 0;
        var rate;
        var i = 0;

        function calculate(word) {
            // Get the word rate from the AFINN dictionary
            rate = afinn[word];
            if (rate) {
                // Add current word rate to the final calculated sentiment score
                score += rate;
            }

            // Defer next turn execution (Etheration)
            setImmediate(function() {
                // Use callback for completion
                if (i === (words.length - 1)) {
                    callback(null, score);
                }
                else {
                    // Invoke next turn
                    calculate(words[++i]);
                }
            });
        }

        // Start calculating
        calculate(words[i]);
	});
};

Fix bug in sentiment calculation


var redis = require('redis'),
  redisCon = module.exports = {};

redisCon.subClient = redis.createClient();
redisCon.pubClient = redis.createClient();

redisCon.subClient.psubscribe('__keyevent@0__:expired');

redisCon.register = function(input){
  redisCon.pubClient.set(input, 'randomestring', 'EX', 900, redis.print);
  analytics.track({
    userId: 'null',
    containerId: input,
    event: 'start',
    time: new Date()
  });
  console.log('redis register');
};

redisCon.stopCallback = function(cb){
  redisCon.subClient.on('pmessage', function(pattern, channel, expiredKey){
    console.log('key expired: ', expiredKey);
    analytics.track({
      userId: 'null',
      containerId: expiredKey,
      event: 'stop',
      time: new Date()
    });
    console.log('redis stop');
    cb(expiredKey);
  });
};

var redis = require('redis'),
  redisCon = module.exports = {};

// redisCon.subClient = redis.createClient();
// redisCon.pubClient = redis.createClient();

redisCon.subClient = redis.createClient(10310,
  "pub-redis-10310.us-east-1-4.1.ec2.garantiadata.com");
redisCon.subClient.auth("8BnAVVcUwskP", function(){
  console.log("subClient Connected!");
});

redisCon.pubClient = redis.createClient(10310,
  "pub-redis-10310.us-east-1-4.1.ec2.garantiadata.com");
redisCon.pubClient.auth("8BnAVVcUwskP", function(){
  console.log("pubClient Connected!");
});

redisCon.subClient.psubscribe('__keyevent@0__:expired');

redisCon.register = function(input){
  redisCon.pubClient.set(input, 'randomestring', 'EX', 900, redis.print);
  analytics.track({
    userId: 'null',
    containerId: input,
    event: 'start',
    time: new Date()
  });
  console.log('redis register');
};

redisCon.stopCallback = function(cb){
  redisCon.subClient.on('pmessage', function(pattern, channel, expiredKey){
    console.log('key expired: ', expiredKey);
    analytics.track({
      userId: 'null',
      containerId: expiredKey,
      event: 'stop',
      time: new Date()
    });
    console.log('redis stop');
    cb(expiredKey);
  });
};

Add redis cloud, will it work?


/* eslint-env node */
const path = require('path');
var browsers = ['Chrome'];

if (process.env.NODE_ENV === 'test') {
  browsers = ['PhantomJS'];
}

module.exports = (config) => {
  config.set({
    basePath: '.',
    frameworks: ['mocha', 'chai', 'phantomjs-shim', 'es6-shim'],
    files: [
      './tests/index.js'
    ],
    preprocessors: {
      './tests/index.js': ['webpack', 'sourcemap']
    },
    webpack: {
      resolve: {
        alias: {
          'react-easy-chart': path.join(__dirname, 'modules')
        }
      },
      module: {
        loaders: [
          { test: /\.js$/, loader: 'babel', exclude: /node_modules/ }
        ]
      },
      devtool: 'inline-source-map'
    },
    webpackServer: {
      noInfo: true
    },
    browsers: browsers,
    singleRun: true,
    reporters: ['progress'],
    plugins: [
      require('karma-mocha'),
      require('karma-chai'),
      require('karma-webpack'),
      require('karma-sourcemap-loader'),
      require('karma-chrome-launcher'),
      require('karma-phantomjs-launcher'),
      require('karma-phantomjs-shim'),
      require('karma-es6-shim')
    ]
  });
};

/* eslint-env node */
const path = require('path');
var browsers = ['Chrome'];

if (process.env.NODE_ENV === 'test') {
  browsers = ['PhantomJS'];
}

module.exports = (config) => {
  config.set({
    basePath: '.',
    frameworks: ['mocha', 'chai', 'es6-shim'],
    files: [
      './tests/index.js'
    ],
    preprocessors: {
      './tests/index.js': ['webpack', 'sourcemap']
    },
    webpack: {
      resolve: {
        alias: {
          'react-easy-chart': path.join(__dirname, 'modules')
        }
      },
      module: {
        loaders: [
          { test: /\.js$/, loader: 'babel', exclude: /node_modules/ }
        ]
      },
      devtool: 'inline-source-map'
    },
    webpackServer: {
      noInfo: true
    },
    browsers: browsers,
    singleRun: true,
    reporters: ['progress'],
    plugins: [
      require('karma-mocha'),
      require('karma-chai'),
      require('karma-webpack'),
      require('karma-sourcemap-loader'),
      require('karma-chrome-launcher'),
      require('karma-phantomjs-launcher'),
      require('karma-es6-shim')
    ]
  });
};

Replace phantomjs shim with es6-shim


"use strict";

var port = process.env.PORT || 8080;
var file = require("fs").readFileSync;
var glob = require("glob");
var path = require("path");

var rested = require("rested");

var routes = glob.sync("routes/*.js").map(function (e, i, a) {
	return require(path.join(__dirname, e));
});

var server = rested.createServer({
	"crt": file(path.join(__dirname, "files/api.munapps.ca.crt")),
	"key": file(path.join(__dirname, "files/api.munapps.ca.key")),
	"secure": true,
	"routes": routes
});

server.listen(port, function () {
	console.log("Server listening on port " + port);
});

"use strict";

var port = process.env.PORT || 8080;
var file = require("fs").readFileSync;
var glob = require("glob");
var path = require("path");

var rested = require("rested");

var routes = glob.sync("routes/*.js").map(function (e, i, a) {
	return require(path.join(__dirname, e));
});

var server = rested.createServer({
	"crt": file(path.join(__dirname, "files/api.munapps.ca.crt")),
	"key": file(path.join(__dirname, "files/api.munapps.ca.key")),
	"secure": true,
	"routes": routes
});

server.eachRequest(function (request, response) {
	response.setHeader("X-Powered-By", "Coffee");
	response.setHeader("X-Shenanigans", "none");
	response.setHeader("X-GitHub", "http://git.io/3K55mA");
});

server.listen(port, function () {
	console.log("Server listening on port " + port);
});

Add headers common to each request


'use strict';

const Hapi = require('hapi');

const server = new Hapi.Server();
const port = process.env.PORT || 3000;
const verifyToken = process.env.VERIFY_TOKEN || '';
server.connection({port: port});

server.start((err) => {
  if (err) {
    throw err;
  }
  console.log('Server running at:', server.info.uri);
});

server.route({
  method: 'GET',
  path: '/webhook',
  handler: function (request, reply) {
    if (req.query['hub.verify_token'] === verifyToken) {
      res.send(req.query['hub.challenge']);
    }
    res.send('Error, wrong validation token');
  }
});

'use strict';

const Hapi = require('hapi');

const server = new Hapi.Server();
const port = process.env.PORT || 3000;
const verifyToken = process.env.VERIFY_TOKEN || '';
server.connection({port: port});

server.start((err) => {
  if (err) {
    throw err;
  }
  console.log('Server running at:', server.info.uri);
});

server.route({
  method: 'GET',
  path: '/webhook',
  handler: function (req, reply) {
    if (req.query['hub.verify_token'] === verifyToken) {
      reply(req.query['hub.challenge']);
    }
    reply('Error, wrong validation token');
  }
});

Change to hapi.js code instead of express


#! /usr/bin/env ./node_modules/.bin/babel-node

import prompt from 'prompt';
import {parse} from 'nomnom';

const schema = {
  properties: {
    name: {
      description: 'Package name: ',
      pattern: /^[a-z]+[a-z\-_]+$/,
      message: 'Name must be only letters, numbers, dashes and underscores',
      required: true
    }
  }
};

prompt.message = '>'.green;
prompt.delimiter = ' ';
prompt.colors = false;
prompt.start();

const scaffold = () => {
  prompt.get(schema, (err, {name}) =>
    console.log(`Scaffolding ${name}...`));
};

// Check if script is run directly
if (require.main === module) {
  scaffold(parse());
}

export default scaffold;

#! /usr/bin/env ./node_modules/.bin/babel-node

import prompt from 'prompt';
import {parse} from 'nomnom';

const schema = {
  properties: {
    name: {
      description: 'Package name: ',
      pattern: /^[a-z]+[a-z\-_]+$/,
      message: 'Name must be only letters, numbers, dashes and underscores',
      required: true
    }
  }
};

Object.assign(prompt, {
  message: '>'.green,
  delimiter: ' ',
  colors: false
});
prompt.start();

const scaffold = () => {
  prompt.get(schema, (err, {name}) =>
    console.log(`Scaffolding ${name}...`));
};

// Check if script is run directly
if (require.main === module) {
  scaffold(parse());
}

export default scaffold;

Use Object.assign for prompt confg


// @flow
module.exports = {
  extends: [
    'plugin:flowtype/recommended',
    'plugin:react/recommended',
    'plugin:jest/recommended',
    './rules/imports.js',
    // This comes last so that prettier-config can turn off appropriate rules given the order of precedence by eslint 'extends'
    require.resolve('eslint-config-uber-universal-stage-3'),
  ],

  plugins: [
    'eslint-plugin-flowtype',
    'eslint-plugin-react',
    'eslint-plugin-react-hooks',
  ],
  rules: {
    // Enforce flow file declarations
    'flowtype/require-valid-file-annotation': ['error', 'always'],

    // We should be using flow rather than propTypes
    'react/prop-types': 'off',

    // Enforces consistent spacing within generic type annotation parameters.
    // https://github.com/gajus/eslint-plugin-flowtype/blob/master/.README/rules/generic-spacing.md
    'flowtype/generic-spacing': 'off',

    // Enforce hook rules
    // https://reactjs.org/docs/hooks-faq.html#what-exactly-do-the-lint-rules-enforce
    'react-hooks/rules-of-hooks': 'error',
    // https://github.com/facebook/react/issues/14920
    'react-hooks/exhaustive-deps': 'warn',
  },
  settings: {
    react: {
      version: 'detect',
    },
  },
};

// @flow
module.exports = {
  extends: [
    'plugin:flowtype/recommended',
    'plugin:react/recommended',
    'plugin:jest/recommended',
    './rules/imports.js',
    // This comes last so that prettier-config can turn off appropriate rules given the order of precedence by eslint 'extends'
    require.resolve('eslint-config-uber-universal-stage-3'),
  ],

  plugins: [
    'eslint-plugin-flowtype',
    'eslint-plugin-react',
    'eslint-plugin-react-hooks',
  ],
  rules: {
    // Enforce flow file declarations
    'flowtype/require-valid-file-annotation': ['error', 'always'],

    // We should be using flow rather than propTypes
    'react/prop-types': 'off',

    // Enforces consistent spacing within generic type annotation parameters.
    // https://github.com/gajus/eslint-plugin-flowtype/blob/master/.README/rules/generic-spacing.md
    'flowtype/generic-spacing': 'off',

    // Enforce hook rules
    // https://reactjs.org/docs/hooks-faq.html#what-exactly-do-the-lint-rules-enforce
    'react-hooks/rules-of-hooks': 'error',
    // https://github.com/facebook/react/issues/14920
    'react-hooks/exhaustive-deps': 'warn',
  },
  settings: {
    react: {
      version: 'latest',
    },
  },
};

Fix version warning when react isn't installed


'use strict';

const compiler = require('vueify').compiler;
const fs = require('fs');

class VueBrunch {

  constructor(config) {
    this.config = config && config.plugins && config.plugins.vue || {};
    this.styles = {};
  }

  compile(file) {

    if (this.config) {
      compiler.applyConfig(this.config);
    }

    compiler.on('style', args => {
      this.styles[args.file] = args.style;
    });

    return new Promise((resolve, reject) => {
      compiler.compile(file.data, file.path, (error, result) => {

        if (error) {
          reject(error);
        }

        resolve(result);
      });
    });
  }

  onCompile() {
    if (this.config.extractCSS) {
      this.extractCSS();
    }
  }

  extractCSS() {
    var outPath = this.config.out || this.config.o || 'bundle.css';
    var css = Object.keys(this.styles || [])
      .map(file => this.styles[file])
      .join('\n');

    if (typeof outPath === 'object' && outPath.write) {
      outPath.write(css);
      outPath.end();
    } else if (typeof outPath === 'string') {
      fs.writeFileSync(outPath, css);
    }
  }
}

VueBrunch.prototype.brunchPlugin = true;
VueBrunch.prototype.type = 'template';
VueBrunch.prototype.extension = 'vue';

module.exports = VueBrunch;

'use strict';

const compiler = require('vueify').compiler;
const fs = require('fs');

class VueBrunch {

  constructor(config) {
    this.config = config && config.plugins && config.plugins.vue || {};
    this.styles = {};
  }

  compile(file) {

    if (this.config) {
      compiler.applyConfig(this.config);
    }

    compiler.on('style', args => {
      this.styles[args.file] = args.style;
    });

    return new Promise((resolve, reject) => {
      compiler.compile(file.data, file.path, (error, result) => {

        if (error) {
          reject(error);
        }

        resolve(result);
      });
    });
  }

  onCompile() {
    if (this.config.extractCSS) {
      this.extractCSS();
    }
  }

  extractCSS() {
    var outPath = this.config.out || this.config.o || 'bundle.css';
    var css = Object.keys(this.styles || [])
      .map(file => this.styles[file])
      .join('\n');

    if (typeof outPath === 'object' && outPath.write) {
      outPath.write(css);
      outPath.end();
    } else if (typeof outPath === 'string') {
      fs.writeFileSync(outPath, css);
    }
  }
}

VueBrunch.prototype.brunchPlugin = true;
VueBrunch.prototype.type = 'javascript';
VueBrunch.prototype.extension = 'vue';

module.exports = VueBrunch;

Set type to javascript to force JS compilation


/* jshint node: true */
'use strict';

module.exports = {
  name: 'ember-power-select',

  included: function(appOrAddon) {
    var app = appOrAddon.app || appOrAddon;
    if (!app.__emberPowerSelectIncludedInvoked) {
      app.__emberPowerSelectIncludedInvoked = true;
      this._super.included.apply(this, arguments);
      // Don't include the precompiled css file if the user uses ember-cli-sass
      if (!app.registry.availablePlugins['ember-cli-sass']) {
        var addonConfig = app.options['ember-power-select'];

        if (!addonConfig || !addonConfig.theme) {
          app.import('vendor/ember-power-select.css');
        } else {
          app.import('vendor/ember-power-select-'+addonConfig.theme+'.css');
        }
      }
    }
  },

  contentFor: function(type, config) {
    var emberBasicDropdown = this.addons.filter(function(addon) {
      return addon.name === 'ember-basic-dropdown';
    })[0]
    return emberBasicDropdown.contentFor(type, config);
  }
};

/* jshint node: true */
'use strict';

module.exports = {
  name: 'ember-power-select',

  included: function(appOrAddon) {
    var app = appOrAddon.app || appOrAddon;
    if (!app.__emberPowerSelectIncludedInvoked) {
      app.__emberPowerSelectIncludedInvoked = true;

      // Since ember-power-select styles already `@import` styles of ember-basic-dropdown,
      // this flag tells to ember-basic-dropdown to skip importing its styles.
      app.__skipEmberBasicDropdownStyles = true;

      this._super.included.apply(this, arguments);
      // Don't include the precompiled css file if the user uses ember-cli-sass
      if (!app.registry.availablePlugins['ember-cli-sass']) {
        var addonConfig = app.options['ember-power-select'];

        if (!addonConfig || !addonConfig.theme) {
          app.import('vendor/ember-power-select.css');
        } else {
          app.import('vendor/ember-power-select-'+addonConfig.theme+'.css');
        }
      }
    }
  },

  contentFor: function(type, config) {
    var emberBasicDropdown = this.addons.filter(function(addon) {
      return addon.name === 'ember-basic-dropdown';
    })[0]
    return emberBasicDropdown.contentFor(type, config);
  }
};

Enable flag in first invocation to ensure ember-basic-dropdown doesn't include its styles


var Sandbox = require('sandbox');

module.exports = exports = function(json, callback) {
	// run the code in a sandbox to thwart evil people
	var s = new Sandbox();

	// in a self executing function set json equal to a variable and stringify the result
	json = "(function() { var j ="+json+"; return JSON.stringify(j); })()";

	s.run(json, function(output) {

		//chop off the extra quotes
		var out = output.result;
		out = out.substring(1, out.length-1);

		if (output.result[1] == '{') {
			callback(null, out)
		} else {
			callback(out, null)
		}

	});
}

var Sandbox = require('sandbox');

module.exports = exports = function(json, callback) {
	// run the code in a sandbox to thwart evil people
	var s = new Sandbox();

	// in a self executing function set json equal to a variable and stringify the result
	json = "(function() { var j ="+json+"; return JSON.stringify(j); })()";

	s.run(json, function(output) {

		//chop off the extra quotes
		var out = output.result;
		out = out.substring(1, out.length-1);

		if (output.result[1] == '{') {
			callback(null, out) //no error as valid responses will start with a {
		} else {
			callback(out, null) //error
		}

	});
};

Add better documentation to library


import postcss from 'postcss';

const postcssFlexibility = postcss.plugin('postcss-flexibility', () => css => {
	css.walkRules(rule => {
		const isDisabled = rule.some(({prop, text}) =>
			prop === '-js-display' || text === 'flexibility-disable'
		);

		if (!isDisabled) {
			rule.walkDecls('display', decl => {
				const {value} = decl;
				if (value === 'flex') {
					decl.cloneBefore({prop: '-js-display'});
				}
			});
		}
	});
});

export default postcssFlexibility;

import postcss from 'postcss';

const postcssFlexibility = postcss.plugin('postcss-flexibility', () => css => {
	css.walkRules(rule => {
		const isDisabled = rule.some(({prop, text}) =>
			prop === '-js-display' || text === 'flexibility-disable' || text === '! flexibility-disable'
		);

		if (!isDisabled) {
			rule.walkDecls('display', decl => {
				const {value} = decl;
				if (value === 'flex') {
					decl.cloneBefore({prop: '-js-display'});
				}
			});
		}
	});
});

export default postcssFlexibility;

Add support for loud comments


module.exports = function (promise, timeout, opts) {
    var Promise     = promise.constructor;
    var rejectWith  = opts && opts.rejectWith;
    var resolveWith = opts && opts.resolveWith;
    var timer;

    var timeoutPromise = new Promise(function (resolve, reject) {
        timer = setTimeout(function () {
            if (rejectWith !== void 0)
                reject(rejectWith);
            else
                resolve(resolveWith);
        }, timeout);
    });

    return Promise.race([timeoutPromise, promise])
        .then(function (value) {
            if (timer.unref) timer.unref();
            return value;
        }, function (error) {
            if (timer.unref) timer.unref();
            throw error;
        });
};

module.exports = function (promise, timeout, opts) {
    var Promise     = promise.constructor;
    var rejectWith  = opts && opts.rejectWith;
    var resolveWith = opts && opts.resolveWith;
    var timer;

    var timeoutPromise = new Promise(function (resolve, reject) {
        timer = setTimeout(function () {
            if (rejectWith !== void 0)
                reject(rejectWith);
            else
                resolve(resolveWith);
        }, timeout);
    });

    return Promise.race([timeoutPromise, promise])
        .then(function (value) {
            // For browser support: timer.unref is only available in Node.
            if (timer.unref) timer.unref();
            return value;
        }, function (error) {
            // For browser support: timer.unref is only available in Node.
            if (timer.unref) timer.unref();
            throw error;
        });
};

Add comment for timer.unref check


var exec = require('child_process').exec;
var _ = require('lodash');
var Q = require('q');

function UrlToImage() {
    var api = {};

    api.render = function(url, file, opts) {
        var def = Q.defer();

        var args = [
            __dirname + 'url-to-image.js',
            url,
            file,
            opts.width,
            opts.height
        ];

        var execOpts = {
            maxBuffer: Infinity
        };

        exec('phantomjs ' + args.join(' '), execOpts, function(err, stdout) {
            def.resolve(err);
        });

        return def;
    };

    return api;
}

module.exports = UrlToImage;

var path = require('path');
var exec = require('child_process').exec;
var _ = require('lodash');
var Q = require('q');

function UrlToImage() {
    var api = {};

    api.render = function(url, file, opts) {
        var def = Q.defer();

        var args = [
            path.join(__dirname, 'url-to-image.js'),
            url,
            file,
            opts.width,
            opts.height
        ];

        var execOpts = {
            maxBuffer: Infinity
        };

        exec('phantomjs ' + args.join(' '), execOpts, function(err, stdout) {
            def.resolve(err);
        });

        return def;
    };

    return api;
}

module.exports = UrlToImage;

Fix to use node path module to join path


!function(mocha) {
  'use strict';

  //mocha.checkLeaks();
  mocha.options.ignoreLeaks = true;
  mocha.globals(['chai', 'BatchGl', 'mocha', 'BatchGlMocks']);
  mocha.run();
}(mocha);

!function(mocha) {
  'use strict';

  mocha.checkLeaks();
  mocha.globals(['chai', 'BatchGl', 'mocha', 'BatchGlMocks']);
  mocha.run();
}(mocha);

Make Mocha check for leaks.


var gulp = require('gulp'),
    react = require('gulp-react'),
    gulpIf = require('gulp-if'),
    uglify = require('gulp-uglify'),
    _ = require('underscore'),
    elixir = require('laravel-elixir'),
    utilities = require('laravel-elixir/ingredients/commands/Utilities'),
    notification = require('laravel-elixir/ingredients/commands/Notification');

elixir.extend('react', function (src, options) {

    var config = this,
        defaultOptions = {
            debug:         ! config.production,
            srcDir:        config.assetsDir + 'js',
            output:        config.jsOutput
        };

    options = _.extend(defaultOptions, options);
    src = "./" + utilities.buildGulpSrc(src, options.srcDir);

    options = _.extend(defaultOptions, options);

    gulp.task('react', function () {

        var onError = function(e) {
            new notification().error(e, 'React Compilation Failed!');
            this.emit('end');
        };

        return gulp.src(src)
            .pipe(react(options)).on('error', onError)
            .pipe(gulpIf(! options.debug, uglify()))
            .pipe(gulp.dest(options.output))
            .pipe(new notification().message('React Compiled!'));
    });

    this.registerWatcher('react', options.srcDir + '/**/*.js');

    return this.queueTask('react');
});

var gulp = require('gulp'),
    react = require('gulp-react'),
    gulpIf = require('gulp-if'),
    uglify = require('gulp-uglify'),
    _ = require('underscore'),
    elixir = require('laravel-elixir'),
    utilities = require('laravel-elixir/ingredients/commands/Utilities'),
    notification = require('laravel-elixir/ingredients/commands/Notification');

elixir.extend('react', function (src, options) {

    var config = this,
        defaultOptions = {
            debug:         ! config.production,
            srcDir:        config.assetsDir + 'js',
            output:        config.jsOutput
        };

    options = _.extend(defaultOptions, options);
    src = "./" + utilities.buildGulpSrc(src, options.srcDir);

    options = _.extend(defaultOptions, options);

    gulp.task('react', function () {

        var onError = function(e) {
            new notification().error(e, 'React Compilation Failed!');
            this.emit('end');
        };

        return gulp.src(src)
            .pipe(react(options)).on('error', onError)
            .pipe(gulpIf(! options.debug, uglify()))
            .pipe(gulp.dest(options.output))
            .pipe(new notification().message('React Compiled!'));
    });

    this.registerWatcher('react', options.srcDir + '/**/*.js');
    this.registerWatcher('react', options.srcDir + '/**/*.jsx');

    return this.queueTask('react');
});

Add watcher for jsx files.


'use strict';
const chalk = require('chalk');
const isRoot = require('is-root');
const isDocker = require('is-docker');

module.exports = message => {
	const defaultMessage = chalk`
{red.bold You are not allowed to run this app with root permissions.}
If running without {bold sudo} doesn't work, you can either fix your permission problems or change where npm stores global packages by putting {bold ~/npm/bin} in your PATH and running:
{blue npm config set prefix ~/npm}

See: {underline https://github.com/sindresorhus/guides/blob/master/npm-global-without-sudo.md}`;

	if (isRoot() && !isDocker()) {
		console.error(message || defaultMessage);
		process.exit(77); // eslint-disable-line unicorn/no-process-exit
	}
};

'use strict';
const chalk = require('chalk');
const isRoot = require('is-root');
const isDocker = require('is-docker');

module.exports = message => {
	const defaultMessage = chalk`
{red.bold You are not allowed to run this app with root permissions.}
If running without {bold sudo} doesn't work, you can either fix your permission problems or change where npm stores global packages by putting {bold ~/npm/bin} in your PATH and running:
{blue npm config set prefix ~/npm}

See: {underline https://github.com/sindresorhus/guides/blob/main/npm-global-without-sudo.md}`;

	if (isRoot() && !isDocker()) {
		console.error(message || defaultMessage);
		process.exit(77); // eslint-disable-line unicorn/no-process-exit
	}
};

Rename `master` branch to `main`


'use strict';

module.exports = class TCache {
    constructor(tag) {
        this.tag = tag;

        this._tasks = [];
        this._fetching = false;
    }

    _run() {
        this._fetching = true;

        let firstTask = this._tasks[0];
        firstTask[0](...firstTask.slice(1,-1), (err, result) => {
            let curTask;
            while (curTask = this._tasks.shift()) {
                setImmediate(curTask.slice(-1)[0], err, result);
            }

            this._fetching = false;
        });
    }

    push(func, ...args) {
        if (typeof func !== 'function' ||
            typeof args.slice(-1)[0] !== 'function') {
            return false;
        }

        this._tasks.push([func, ...args]);
        if (!this._fetching) this._run();
        return true;
    }
}

'use strict';

module.exports = class TCache {
    constructor(tag) {
        this.tag = tag;

        this._tasks = [];
        this._fetching = false;
    }

    get size() {
        return this._tasks.length;
    }

    _run() {
        this._fetching = true;

        let firstTask = this._tasks[0];
        firstTask[0](...firstTask.slice(1,-1), (err, result) => {
            let curTask;
            while (curTask = this._tasks.shift()) {
                setImmediate(curTask.slice(-1)[0], err, result);
            }

            this._fetching = false;
        });
    }

    push(func, ...args) {
        if (typeof func !== 'function' ||
            typeof args.slice(-1)[0] !== 'function') {
            return false;
        }

        this._tasks.push([func, ...args]);
        if (!this._fetching) this._run();
        return true;
    }
}

Add getter of the size of total tasks.


var cookie = require('cookie');

var _cookies = cookie.parse((document && document.cookie) ? document.cookie : '');

for (var key in _cookies) {
  try {
    _cookies[key] = JSON.parse(_cookies[key]);
  } catch(e) {
    // Not serialized object
  }
}

function load(name) {
  return _cookies[name];
}

function save(name, val, opt) {
  // Cookies only work in the browser
  if (!document || !document.cookie) return;

  _cookies[name] = val;
  document.cookie = cookie.serialize(name, val, opt);
}

var reactCookie = {
  load: load,
  save: save
};

if (typeof module !== 'undefined') {
  module.exports = reactCookie
}

if (typeof window !== 'undefined') {
  window['reactCookie'] = reactCookie;
}

var cookie = require('cookie');

var _cookies = cookie.parse((typeof document !== 'undefined') ? document.cookie : '');

for (var key in _cookies) {
  try {
    _cookies[key] = JSON.parse(_cookies[key]);
  } catch(e) {
    // Not serialized object
  }
}

function load(name) {
  return _cookies[name];
}

function save(name, val, opt) {
  _cookies[name] = val;

  // Cookies only work in the browser
  if (typeof document === 'undefined') return;

  document.cookie = cookie.serialize(name, val, opt);
}

var reactCookie = {
  load: load,
  save: save
};

if (typeof module !== 'undefined') {
  module.exports = reactCookie
}

if (typeof window !== 'undefined') {
  window['reactCookie'] = reactCookie;
}

Fix the document undefined check


/**
 * Remove node_modules/hydro/ entries from the
 * error stacks.
 *
 * @param {Object} hydro
 * @api public
 */

module.exports = function(hydro) {
  if (!hydro.get('cleanStacks')) return;

  hydro.on('post:test', function(test) {
    if (test.status !== 'failed') return;
    var stack = test.error.stack.split('\n').filter(function(line) {
      return line.indexOf('node_modules/hydro') === -1;
    });
    test.error.stack = stack.join('\n');
  });
};

/**
 * CLI flags.
 */

module.exports.flags = {
  '--clean-stacks': 'remove hydro entries from error stacks'
};

/**
 * Remove node_modules/hydro/ entries from the
 * error stacks.
 *
 * @param {Object} hydro
 * @api public
 */

module.exports = function(hydro) {
  if (!hydro.get('cleanStacks')) return;

  hydro.on('post:test', function(test) {
    if (test.status !== 'failed') return;
    if (!test.error.stack) return;
    var stack = test.error.stack.split('\n').filter(function(line) {
      return line.indexOf('node_modules/hydro') === -1;
    });
    test.error.stack = stack.join('\n');
  });
};

/**
 * CLI flags.
 */

module.exports.flags = {
  '--clean-stacks': 'remove hydro entries from error stacks'
};

Handle errors without a stack


var hyperglue = require('hyperglue');

module.exports = function (html, data, scope) {
    var keys = Object.keys(data),
        _data = {},
        _key = typeof scope !== 'undefined' ? scope + ' ' : '',
        k;

    for (k in keys) {
        _key += '[data-bind=' + keys[k] + ']';
        _data[_key] = data[keys[k]];
    }

    return hyperglue(html, _data);
};

var hyperglue = require('hyperglue');

module.exports = function (html, data, scope) {
    var keys = Object.keys(data),
        _data = {},
        _key = typeof scope !== 'undefined' ? scope + ' ' : '',
        selector,
        k;

    for (k in keys) {
        selector = _key + '[data-bind=' + keys[k] + ']';
        _data[selector] = data[keys[k]];
    }

    return hyperglue(html, _data);
};

Fix issue w/ building hyperglue selector data-bind selector


// Karma configuration file, see link for more information
// https://karma-runner.github.io/0.13/config/configuration-file.html

module.exports = function (config) {
  config.set({
    basePath: '',
    frameworks: ['jasmine', '@angular/cli'],
    plugins: [
      require('karma-jasmine'),
      require('karma-chrome-launcher'),
      require('karma-jasmine-html-reporter'),
      require('karma-coverage-istanbul-reporter'),
      require('@angular/cli/plugins/karma')
    ],
    client:{
      clearContext: false // leave Jasmine Spec Runner output visible in browser
    },
    files: [
      { pattern: './src/test.ts', watched: false }
    ],
    preprocessors: {
      './src/test.ts': ['@angular/cli']
    },
    mime: {
      'text/x-typescript': ['ts','tsx']
    },
    coverageIstanbulReporter: {
      reports: [ config.watch ? 'html' : 'text-summary', 'lcovonly' ],
      fixWebpackSourcePaths: true
    },
    angularCli: {
      environment: 'dev'
    },
    reporters: config.angularCli && config.angularCli.codeCoverage
              ? ['progress', 'coverage-istanbul']
              : ['progress', 'kjhtml'],
    port: 8081,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: true,
    browsers: ['ChromeNoSandbox'],
    customLaunchers: {
      ChromeNoSandbox: {
        base: 'Chrome',
        flags: ['--no-sandbox'],
      },
    },
    singleRun: false
  });
};

// Karma configuration file, see link for more information
// https://karma-runner.github.io/0.13/config/configuration-file.html

module.exports = function (config) {
  config.set({
    basePath: '',
    frameworks: ['jasmine', '@angular/cli'],
    plugins: [
      require('karma-jasmine'),
      require('karma-chrome-launcher'),
      require('karma-jasmine-html-reporter'),
      require('karma-coverage-istanbul-reporter'),
      require('@angular/cli/plugins/karma')
    ],
    client:{
      clearContext: false // leave Jasmine Spec Runner output visible in browser
    },
    files: [
      { pattern: './src/test.ts', watched: false }
    ],
    preprocessors: {
      './src/test.ts': ['@angular/cli']
    },
    mime: {
      'text/x-typescript': ['ts','tsx']
    },
    coverageIstanbulReporter: {
      reports: [ config.watch ? 'html' : 'text-summary', 'lcovonly' ],
      fixWebpackSourcePaths: true
    },
    angularCli: {
      environment: 'dev'
    },
    reporters: config.angularCli && config.angularCli.codeCoverage
              ? ['progress', 'coverage-istanbul']
              : ['progress', 'kjhtml'],
    port: 8081,
    colors: true,
    logLevel: config.LOG_INFO,
    autoWatch: true,
    browsers: ['ChromeHeadless'],
    customLaunchers: {
      ChromeNoSandbox: {
        base: 'Chrome',
        flags: ['--headless'],
      },
    },
    singleRun: false
  });
};

Use Chrome in headless mode


'use strict'

var childProcess = require('child_process')

childProcess.exec('./index.js', function onBoot (err) {
  if (err) {
    throw err
  }
})

'use strict'

var childProcess = require('child_process')
var path = require('path')
var assert = require('chai').assert

var TREAD = path.join(process.cwd(), 'index.js')

var proc = childProcess.fork(TREAD, ['-h'])

proc.on('error', function onError (error) {
  assert.fail(error)
})

proc.on('exit', function onExit (code, signal) {
  assert.equal(code, 0, 'should exit 0')
  assert.isNull(signal, 'should not have exit signal')
})

Add assertions to integration tests


var DS = require('dslink');

var Increment = DS.createNode({
  onInvoke: function(columns) {
    // TODO: Support for columns.amount, requires bugfix.
    var previous = link.getNode('/counter').lastValueUpdate.value;
    link.getNode('/counter').updateValue(previous + 1);
  }
});

// Process the arguments and initializes the default nodes.
var link = new DS.LinkProvider(process.argv.slice(2), 'javascript-template-', {
  defaultNodes: {
    counter: {
      $type: 'int',
      '?value': 0
    },
    increment: {
      // references the increment profile, which makes this node an instance of
      // our Increment class
      $is: 'increment',
      $invokable: 'write',
      $columns: [
        {
          name: 'amount',
          type: 'int',
          default: 1
        }
      ]
    }
  },
  profiles: {
    increment: function(path) {
      return new Increment(path);
    }
  }
});

// Connect to the broker.
// link.connect() returns a Promise.
link.connect().catch(function(e) {
  console.log(e.stack);
});

var DS = require('dslink');

// creates a node with an action on it
var Increment = DS.createNode({
  onInvoke: function(columns) {
    // get current value of the link
    var previous = link.getNode('/counter').lastValueUpdate.value;

    // set new value by adding an amount to the previous amount
    link.getNode('/counter').updateValue(previous + parseInt(columns.amount));
  }
});

// Process the arguments and initializes the default nodes.
var link = new DS.LinkProvider(process.argv.slice(2), 'javascript-template-', {
  defaultNodes: {
    // counter is a value node, it holds the value of our counter
    counter: {
      $type: 'int',
      '?value': 0
    },
    // increment is an action node, it will increment /counter
    // by the specified amount
    increment: {
      // references the increment profile, which makes this node an instance of
      // our Increment class
      $is: 'increment',
      $invokable: 'write',
      // $params is the parameters that are passed to onInvoke
      $params: [
        {
          name: 'amount',
          type: 'int',
          default: 1
        }
      ]
    }
  },
  // register our custom node here as a profile
  // when we use $is with increment, it
  // creates our Increment node
  profiles: {
    increment: function(path) {
      return new Increment(path);
    }
  }
});

// Connect to the broker.
// link.connect() returns a Promise.
link.connect().catch(function(e) {
  console.log(e.stack);
});

Update template, add more examples.


var uuid = require('uuid')

var blessThisCode = function(){
    var blessingId = uuid.v4()
    var blessing = `Blessing ID #${blessingId}: Our blessings are with you.`
    return blessing
}

exports.blessThisCode = blessThisCode

var uuid = require('uuid')

var blessThisCode = function(){
    var blessingId = uuid.v4()
    var blessing = `Blessing ID #${blessingId}: Our blessings are with you.`
    return blessing
}

var isCodeBlessed = function(){
    return true
}

exports.blessThisCode = blessThisCode
exports.isCodeBlessed = isCodeBlessed

Add method to return current code blessing status


var expect = require('chai').expect;
var count = require('count-substring');
var htmlToText = require('html-to-text');

module.exports = function (browser) {
    describe("The tests written in Elm", function () {
        it('should pass', function () {
            return browser
                .url('http://localhost:8080/elm.html')
                .waitUntil(function () {
                    return this.getHTML("#results").then(function (html) {
                        var passedCount = count(html, "All tests passed");
                        var failedCount = count(html, "FAILED");

                        if (passedCount > 0) {
                            return true;
                        }

                        if (failedCount > 0) {
                            console.log("Failed!\n");
                            console.log(htmlToText.fromString(html));

                            throw "Failed tests written in Elm";
                        }

                        return false;
                    });
                }, 10000, 500);
        });
    });
};

var expect = require('chai').expect;
var count = require('count-substring');

module.exports = function (browser) {
    describe("The tests written in Elm", function () {
        it('should pass', function () {
            return browser
                .url('http://localhost:8080/elm.html')
                .waitUntil(function () {
                    return this.getText("#results").then(function (text) {
                        return text.indexOf("suites run") > 0;
                    });
                }, 10000, 500)
                .getText("#results")
                .then(function (text) {
                    var failedCount = count(text, "FAILED");
                    if (failedCount != 0) console.log(text);
                    expect(failedCount).to.equal(0);
                });
        });
    });
};

Simplify checking to see if Elm tests have passed.


import raven from "raven"
import { assign } from "lodash"

const blacklistHttpStatuses = [401, 403, 404]

export const shouldLogError = originalError => {
  if (originalError && originalError.statusCode) {
    return (
      originalError.statusCode < 500 &&
      !blacklistHttpStatuses.includes(originalError.statusCode)
    )
  }
  return true
}

export default function graphqlErrorHandler(
  req,
  { isProduction, enableSentry }
) {
  return error => {
    if (enableSentry) {
      if (shouldLogError(error.originalError)) {
        raven.captureException(
          error,
          assign(
            {},
            {
              tags: { graphql: "exec_error" },
              extra: {
                source: error.source && error.source.body,
                positions: error.positions,
                path: error.path,
              },
            },
            raven.parsers.parseRequest(req)
          )
        )
      }
    }
    return {
      message: error.message,
      locations: error.locations,
      stack: isProduction ? null : error.stack,
    }
  }
}

import raven from "raven"
import { assign } from "lodash"

const blacklistHttpStatuses = [401, 403, 404]

export const shouldLogError = originalError => {
  if (originalError && originalError.statusCode) {
    return (
      originalError.statusCode < 500 &&
      !blacklistHttpStatuses.includes(originalError.statusCode)
    )
  }
  return true
}

export default function graphqlErrorHandler(
  req,
  { isProduction, enableSentry }
) {
  return error => {
    if (enableSentry) {
      if (shouldLogError(error.originalError)) {
        raven.captureException(
          error,
          assign(
            {},
            {
              tags: { graphql: "exec_error" },
              extra: {
                source: error.source && error.source.body,
                positions: error.positions,
                path: error.path,
              },
            },
            raven.parsers.parseRequest(req)
          )
        )
      }
    }
    return {
      message: error.message,
      locations: error.locations,
      path: isProduction ? null : error.path,
      stack: isProduction ? null : error.stack,
    }
  }
}

Include resolver path to error report in dev mode.


import koaRouter from 'koa-router';
import fs from 'fs';
import path from 'path'
import readline from 'readline';

const router = koaRouter();

function lineReaderThunk(lineReader) {
    return function(done) {
        lineReader.on('line', function (line) {
            done(null, line);
        });
    }
}

router.get('/posts', function*(next) {
    const postsBaseDir = path.resolve(__dirname, '../../../posts');
    const posts = fs.readdirSync(postsBaseDir);

    var postData = {};
    for (let i = 0, len = posts.length; i < len; i++) {
        let postFilename = posts[i];
        const postFilePath = path.resolve(postsBaseDir, postFilename);

        var lineReader = readline.createInterface({
            input: fs.createReadStream(postFilePath)
        });

        postData[postFilename] = [];

        var line = yield lineReaderThunk(lineReader);
        postData[postFilename].push(line);
    }

    this.body = postData;
});

export default router.middleware();

import koaRouter from 'koa-router';
import fs from 'fs';
import path from 'path'
import readline from 'readline';

const router = koaRouter();

function readPostFile(postFilePath) {
    return function(done) {
        var lines = [];

        var lineReader = readline.createInterface({
            input: fs.createReadStream(postFilePath)
        });

        lineReader.on('line', function(line){
            lines.push(line);
        });

        lineReader.on('close', function(){
            done(null, lines);
        });
    }
}

router.get('/posts', function*(next) {
    const postsBaseDir = path.resolve(__dirname, '../../../posts');
    const posts = fs.readdirSync(postsBaseDir);
    var postData = {};

    for (let i = 0, len = posts.length; i < len; i++) {
        let postFilename = posts[i];
        const postFilePath = path.resolve(postsBaseDir, postFilename);

        postData[postFilename] = yield readPostFile(postFilePath);
    }

    this.body = postData;
});

export default router.middleware();

Read all the lines of the md files and return them in the response


const ZoomdataSDK = require('zoomdata-client/distribute/sdk/zoomdata-client.node');

async function run() {
    const application = {
        secure: true,
        host: 'developer.zoomdata.com',
        port: 443,
        path: '/zoomdata-2.6'
    };

    const credentials = {
        key: 'KVKWiD8kUl'
    };

    const client = await ZoomdataSDK.createClient({ application, credentials });

    console.log('Client ready');

    const queryConfig = {
        filters: [],
        groups: [{
            name: 'position',
            limit: 10,
            sort: { dir: 'asc', name: 'position' }
        }],
        metrics: [
            { name: 'satisfaction', func: 'sum' }
        ]
    };

    try {
        const data = await fetchData(client, 'Impala', queryConfig);
        console.log('Received data:', data);
    } finally {
        client.close();
    }
}

async function fetchData(client, name, queryConfig) {
    const query = await client.createQuery({ name }, queryConfig);

    console.log('Query created');

    return new Promise((resolve, reject) => {
        console.log('Running query...');
        client.runQuery(query, resolve, reject);
    });
}

run().catch(console.error);

const ZoomdataSDK = require('zoomdata-client/distribute/sdk/zoomdata-client.node');

async function run() {
    const application = {
        secure: true,
        host: 'developer.zoomdata.com',
        port: 443,
        path: '/zoomdata-2.6'
    };

    const credentials = {
        key: 'KVKWiD8kUl'
    };

    const client = await ZoomdataSDK.createClient({ application, credentials });

    console.log('Client ready');

    const queryConfig = {
        filters: [],
        groups: [{
            name: 'gender',
            limit: 10,
            sort: { dir: 'asc', name: 'gender' }
        }],
        metrics: [
            { name: 'satisfaction', func: 'sum' }
        ]
    };

    try {
        const data = await fetchData(client, 'My IMPALA Source', queryConfig);
        console.log('Received data:', data);
    } finally {
        client.close();
    }
}

async function fetchData(client, name, queryConfig) {
    const query = await client.createQuery({ name }, queryConfig);

    console.log('Query created');

    return new Promise((resolve, reject) => {
        console.log('Running query...');
        client.runQuery(query, resolve, reject);
    });
}

run().catch(console.error);

Update query configuration and source name


const express = require('express');
const path = require('path');
const app = express();

app.use(express.static('./build'));

app.get('/', function (req, res) {
    res.sendFile(path.join(__dirname, './build', 'index.html'));
});

app.get('/infrastucture', function(req, res)  {
    res.send(200, {
        regions : [
            {   name : "east-1",
                environments : [
                    {
                        status : 'green',
                        instanceCount : 12,
                        trafficWeight: 0.3
                    }
                ]
            }
        ]
    })
});

app.get('/load', function(req, res)  {
    res.send(200, {
        regions : [
            {   name : "east-1",
                environments : [
                    {
                        errRate : 0.1,
                        replicationLag : 0.7
                    }
                ]
            }
        ]
    })
});

app.listen(9000);

const express = require('express');
const path = require('path');
const app = express();

app.use(express.static('./build'));

app.get('/', function (req, res) {
    res.sendFile(path.join(__dirname, './build', 'index.html'));
});

app.get('/infrastructure', function(req, res)  {
    res.status(200).send({
        regions : [
            {   name : "east-1",
                environments : [
                    {
                        status : 'green',
                        instanceCount : 12,
                        trafficWeight: 0.3
                    }
                ]
            }
        ]
    })
});

app.get('/load', function(req, res)  {
    res.status(200).send({
        regions : [
            {   name : "east-1",
                environments : [
                    {
                        errRate : 0.1,
                        replicationLag : 0.7
                    }
                ]
            }
        ]
    })
});

app.listen(9000);

Fix infrastructure spelling and clean up deprecated code


module.exports = {
    parser: 'babel-eslint',
    extends: [
        'airbnb',
        'plugin:ava/recommended',
    ],
    plugins: [
        'import',
        'ava',
    ],
    rules: {
        indent: ['error', 4, {
            SwitchCase: 1,
            MemberExpression: 1,
            VariableDeclarator: 1,
            outerIIFEBody: 1,
            FunctionDeclaration: {
                parameters: 1,
                body: 1,
            },
            FunctionExpression: {
                parameters: 1,
                body: 1,
            },
        }],
        'valid-jsdoc': 'error',
        strict: 'error',
        'no-sync': 'error',
        'no-inline-comments': 'error',
        'no-use-before-define': ['error', 'nofunc'],
        'no-restricted-syntax': ['error', 'ForInStatement', 'LabeledStatement', 'WithStatement'],
        'max-len': ['error', 150, 4, {
            ignoreUrls: true,
            ignoreComments: false,
            ignoreRegExpLiterals: true,
            ignoreStrings: true,
            ignoreTemplateLiterals: true,
        }],
    },
};

module.exports = {
    parser: 'babel-eslint',
    extends: [
        'airbnb',
        'plugin:ava/recommended',
    ],
    plugins: [
        'import',
        'ava',
    ],
    rules: {
        indent: ['error', 4, {
            SwitchCase: 1,
            MemberExpression: 1,
            VariableDeclarator: 1,
            outerIIFEBody: 1,
            FunctionDeclaration: {
                parameters: 1,
                body: 1,
            },
            FunctionExpression: {
                parameters: 1,
                body: 1,
            },
        }],
        'valid-jsdoc': 'error',
        strict: 'error',
        'no-sync': 'error',
        'no-inline-comments': 'error',
        'no-use-before-define': ['error', 'nofunc'],
        'no-restricted-syntax': ['error', 'ForInStatement', 'LabeledStatement', 'WithStatement'],
        'max-len': ['error', 150, 4, {
            ignoreUrls: true,
            ignoreComments: false,
            ignoreRegExpLiterals: true,
            ignoreStrings: true,
            ignoreTemplateLiterals: true,
        }],
        'react/jsx-filename-extension': ['error', { extensions: ['.js', '.jsx'] }],
    },
};

Allow .js extension for JSX files


var gulp = require('gulp'),
    react = require('gulp-react'),
    gulpIf = require('gulp-if'),
    uglify = require('gulp-uglify'),
    _ = require('underscore'),
    elixir = require('laravel-elixir'),
    utilities = require('laravel-elixir/ingredients/commands/Utilities'),
    notification = require('laravel-elixir/ingredients/commands/Notification');

elixir.extend('react', function (src, options) {
    var config = this;

    options = _.extend({
        debug:  ! config.production,
        srcDir: config.assetsDir + 'js',
        output: config.jsOutput
    }, options);

    src = "./" + utilities.buildGulpSrc(src, options.srcDir);

    gulp.task('react', function () {
        var onError = function(e) {
            new notification().error(e, 'React Compilation Failed!');
            this.emit('end');
        };

        return gulp.src(src)
            .pipe(react(options)).on('error', onError)
            .pipe(gulpIf(! options.debug, uglify()))
            .pipe(gulp.dest(options.output))
            .pipe(new notification().message('React Compiled!'));
    });

    this.registerWatcher('react', options.srcDir + '/**/*.+(js|jsx)');

    return this.queueTask('react');
});

var gulp = require('gulp'),
    react = require('gulp-react'),
    gulpIf = require('gulp-if'),
    uglify = require('gulp-uglify'),
    _ = require('underscore'),
    elixir = require('laravel-elixir'),
    utilities = require('laravel-elixir/ingredients/commands/Utilities'),
    notification = require('laravel-elixir/ingredients/commands/Notification');

elixir.extend('react', function (src, options) {
    var config = this;

    options = _.extend({
        debug:  ! config.production,
        srcDir: config.assetsDir + 'js',
        output: config.jsOutput
    }, options);

    src = "./" + utilities.buildGulpSrc(src, options.srcDir, "");

    gulp.task('react', function () {
        var onError = function(e) {
            new notification().error(e, 'React Compilation Failed!');
            this.emit('end');
        };

        return gulp.src(src)
            .pipe(react(options)).on('error', onError)
            .pipe(gulpIf(! options.debug, uglify()))
            .pipe(gulp.dest(options.output))
            .pipe(new notification().message('React Compiled!'));
    });

    this.registerWatcher('react', options.srcDir + '/**/*.+(js|jsx)');

    return this.queueTask('react');
});

Fix filepath to source directory when srcDir is specified and the first argument is blank


var nunjucks = require("nunjucks");

module.exports = function(env, callback) {
  var NunjucksTemplate = function(template) {
    this.template = template;
  };

  NunjucksTemplate.prototype.render = function render(locals, callback) {
    try {
      callback(null, new Buffer(this.template.render(locals)));
    } catch (error) {
      callback(error);
    }
  };

  NunjucksTemplate.fromFile = function fromFile(filepath, callback) {
    var nenv = new nunjucks.Environment(new nunjucks.FileSystemLoader(env.templatesPath));
    callback(null, new NunjucksTemplate(nenv.getTemplate(filepath.relative)));
  };

  env.registerTemplatePlugin("**/*.*(html)", NunjucksTemplate);

  callback();
};

var nunjucks = require("nunjucks");

module.exports = function(env, callback) {
  var NunjucksTemplate = function(template) {
    this.template = template;
  };

  NunjucksTemplate.prototype.render = function render(locals, callback) {
    try {
      callback(null, new Buffer(this.template.render(locals)));
    } catch (error) {
      callback(error);
    }
  };

  NunjucksTemplate.fromFile = function fromFile(filepath, callback) {
    var nenv = new nunjucks.Environment(new nunjucks.FileSystemLoader(env.templatesPath));
    callback(null, new NunjucksTemplate(nenv.getTemplate(filepath.relative)));
  };

  env.registerTemplatePlugin("**/*.*(html|nunjucks)", NunjucksTemplate);

  callback();
};

Add support for templates named *.nunjucks


/* globals module */

'use strict'

module.exports = {
  name: 'ember-frost-bunsen',

  included: function (app) {
    this._super.included(app)
    app.import('bower_components/z-schema/dist/ZSchema-browser.js')
  },

  init: function (app) {
    this.options = this.options || {}
    this.options.babel = this.options.babel || {}
    this.options.babel.optional = this.options.babel.optional || []

    if (this.options.babel.optional.indexOf('es7.decorators') === -1) {
      this.options.babel.optional.push('es7.decorators')
    }
    this._super.init && this._super.init.apply(this, arguments)
  }
}

/* globals module */

'use strict'

module.exports = {
  name: 'ember-frost-bunsen',

  included: function (app) {
    this._super.included(app)
    this.app.import('bower_components/z-schema/dist/ZSchema-browser.js')
  },

  init: function (app) {
    this.options = this.options || {}
    this.options.babel = this.options.babel || {}
    this.options.babel.optional = this.options.babel.optional || []

    if (this.options.babel.optional.indexOf('es7.decorators') === -1) {
      this.options.babel.optional.push('es7.decorators')
    }
    this._super.init && this._super.init.apply(this, arguments)
  }
}

Revert "incorrect call to this.app.import(). causing issues in consuming app"


#!/usr/bin/env node

var path = require('path');
var fs = require('fs');
var colors = require('colors');
var shell = require('./lib/shell');
var subtree = require('./lib/subtree');

var cwd = process.cwd();
var gitroot = path.join(cwd, ".git")

try {
    fs.readdirSync(gitroot);
} catch (error) {
    console.error('Run this script from the root of the repository.'.red);
    process.exit(1);
}

subtree.run(process.argv.slice(2), function(err, result) {
    if (err) {
        console.error(('ERROR: ' + err).red);
        process.exit(1);
    }
});

#!/usr/bin/env node

var path = require('path');
var fs = require('fs');
var colors = require('colors');
var shell = require('./lib/shell');
var subtree = require('./lib/subtree');

var args = process.argv.slice(2);

if (args.length > 0) {

    // Check if it's project root
    try {
        var gitroot = path.join(process.cwd(), ".git")
        fs.readdirSync(gitroot);
    } catch (error) {
        console.error('Run this script from the root of the repository.'.red);
        process.exit(1);
    }

    // Check if config file exists
    try {
        var subtrees = path.join(process.cwd(), "subtrees.json")
        fs.readFileSync(subtrees);
    } catch (error) {
        console.error('Missing subtrees.json configuration file'.red);
        process.exit(1);
    }

    subtree.run(args, function(err, result) {
        if (err) {
            console.error(('ERROR: ' + err).red);
            process.exit(1);
        }
    });
} else {
    console.log('usage: git-subtree <command>\n');
    console.log('Commands:');
    console.log('init\tInitialize project subtrees');
    console.log('add\tCreate remote, fetch and add subtree folder');
    console.log('pull\tPull changes from subtree');
    console.log('push\tPush changes to subtree');
    console.log('commit\tCommit subtree folder changes');
}

Print help if no args, and add check for subtrees.json file presence.


'use strict';

module.exports = function(config) {

    config.set({

        autoWatch: true,

        browsers: [
            'PhantomJS'
        ],

        colors: true,

        coverageReporter: {
            dir: 'coverage',
            instrumenterOptions: {
                istanbul: {
                    noCompact: true
                }
            },
            reporters: [{
                type: 'html',
                subdir: 'report-html'
            }, {
                type: 'lcov',
                subdir: 'report-lcov'
            }, {
                type: 'cobertura',
                subdir: '.',
                file: 'cobertura.txt'
            }, {
                type: 'lcovonly',
                subdir: '.',
                file: 'report-lcovonly.txt'
            }, {
                type: 'teamcity',
                subdir: '.',
                file: 'teamcity.txt'
            }, {
                type: 'text',
                subdir: '.',
                file: 'text.txt'
            }, {
                type: 'text-summary',
                subdir: '.',
                file: 'text-summary.txt'
            }]
        },

        files: [
            'dist/jasmine-matchers.js',
            'dist/jasmine-matchers.spec.js'
        ],

        frameworks: [
            'jasmine'
        ],

        preprocessors: {
            '**/dist/*.js': [
                'coverage'
            ]
        },

        reporters: [
            'nested',
            'coverage'
        ],

        thresholdReporter: {
            statements: 95,
            branches: 95,
            functions: 95,
            lines: 95
        }

    });

};

'use strict';

module.exports = function(config) {

    config.set({

        autoWatch: true,

        browsers: [
            'PhantomJS'
        ],

        colors: true,

        coverageReporter: {
            dir: 'coverage',
            instrumenterOptions: {
                istanbul: {
                    noCompact: true
                }
            },
            reporters: [{
                type: 'html',
                subdir: 'report-html'
            }, {
                type: 'lcov',
                subdir: 'report-lcov'
            }, {
                type: 'cobertura',
                subdir: '.',
                file: 'cobertura.txt'
            }, {
                type: 'lcovonly',
                subdir: '.',
                file: 'report-lcovonly.txt'
            }, {
                type: 'teamcity',
                subdir: '.',
                file: 'teamcity.txt'
            }, {
                type: 'text',
                subdir: '.',
                file: 'text.txt'
            }, {
                type: 'text-summary',
                subdir: '.',
                file: 'text-summary.txt'
            }]
        },

        files: [
            'dist/jasmine-matchers.js',
            'dist/jasmine-matchers.spec.js'
        ],

        frameworks: [
            'jasmine'
        ],

        preprocessors: {
            '**/dist/jasmine-matchers.js': [
                'coverage'
            ]
        },

        reporters: [
            'nested',
            'coverage'
        ],

        thresholdReporter: {
            statements: 95,
            branches: 95,
            functions: 95,
            lines: 95
        }

    });

};

Exclude spec from coverage reporting.


'use strict';
var execFile = require('child_process').execFile;
var toDecimal = require('to-decimal');

module.exports = function (cb) {
	if (process.platform !== 'win32') {
		throw new TypeError('Only Windows systems are supported');
	}

	var cmd = 'WMIC';
	var args = ['Path', 'Win32_Battery', 'Get', 'EstimatedChargeRemaining'];

	execFile(cmd, args, function (err, stdout) {
		if (err) {
			cb(err);
			return;
		}

		if (!stdout) {
			cb(new Error('No battery could be found'));
		}

		cb(null, toDecimal(parseFloat(stdout.trim().split('\n')[1])));
	});
};

'use strict';
var execFile = require('child_process').execFile;
var toDecimal = require('to-decimal');

module.exports = function (cb) {
	if (process.platform !== 'win32') {
		throw new TypeError('Only Windows systems are supported');
	}

	var cmd = 'WMIC';
	var args = ['Path', 'Win32_Battery', 'Get', 'EstimatedChargeRemaining'];

	execFile(cmd, args, function (err, stdout) {
		if (err) {
			cb(err);
			return;
		}

		if (!stdout) {
			cb(new Error('No battery could be found'));
		}

		stdout = parseFloat(stdout.trim().split('\n')[1]);
		cb(null, toDecimal(stdout > 1 ? 1 : stdout));
	});
};

Set to `1` if higher


// Requires
var Q = require('q');
var _ = require('underscore');

var qClass = require('qpatch').qClass;

// Etcd client
var Etcd = qClass(require('node-etcd'), ['watcher']);

// Since etcd create the dir keys automatically
// transform the tree of keys
// to contain only a flat array of leaves
function cleanDump(obj) {
    // Is a leaf
    if(!_.has(obj, 'kvs')) {
        // We don't want the modifiedIndex attr in our dumps/restores
        return _.pick(obj, 'key', 'value');
    }
    return _.flatten(_.map(obj.kvs, cleanDump));
}

function Dumper(etcd) {
    // ETCD client
    this.store = new Etcd();

    _.bindAll(this);
}

// Get a JS object of the DB
Dumper.prototype.dump = function() {
    return this.store.get('', {
        recusrive: true
    })
    .then(cleanDump);
};

// Restore a list of keys
Dumper.prototype.restore = function(entries) {
    var self = this;

    return Q.all(_.map(entries, function(entry) {
        return this.store.set(entry.key, entry.value);
    }));
};

// Restore the database from input data
function createDumper() {
    return new Dumper();
}

// Exports
module.exports = createDumper;

// Requires
var Q = require('q');
var _ = require('underscore');

var qClass = require('qpatch').qClass;

// Etcd client
var Etcd = qClass(require('node-etcd'), ['watcher']);

// Since etcd create the dir keys automatically
// transform the tree of keys
// to contain only a flat array of leaves
function cleanDump(obj) {
    // Is a leaf
    if(!_.has(obj, 'kvs')) {
        // We don't want the modifiedIndex attr in our dumps/restores
        return _.pick(obj, 'key', 'value');
    }
    return _.flatten(_.map(obj.kvs, cleanDump));
}

function Dumper(etcd) {
    // ETCD client
    this.store = new Etcd();

    _.bindAll(this);
}

// Get a JS object of the DB
Dumper.prototype.dump = function() {
    return this.store.get('', {
        recursive: true
    })
    .then(cleanDump);
};

// Restore a list of keys
Dumper.prototype.restore = function(entries) {
    var self = this;

    return Q.all(_.map(entries, function(entry) {
        return this.store.set(entry.key, entry.value);
    }));
};

// Restore the database from input data
function createDumper() {
    return new Dumper();
}

// Exports
module.exports = createDumper;

Fix silly typo "recusrive" => "recursive"


module.exports = require("./moment-timezone");
module.exports.tz.add(require('./data/packed/latest.json'));

var moment = module.exports = require("./moment-timezone");
moment.tz.load(require('./data/packed/latest.json'));

Use `moment.tz.load` instead of `moment.tz.add` to import initial data in Node.


var pegjs = require('pegjs');
var loaderUtils = require('loader-utils');

module.exports = function(source) {
  this.cacheable && this.cacheable();
  var query = loaderUtils.parseQuery(this.query);
  var pegOptions = { output: 'source' };
  var parser = 'module.exports = ' + pegjs.buildParser(source, pegOptions) + ';';
  this.callback(null, parser, null);
};

var pegjs = require('pegjs');
var loaderUtils = require('loader-utils');

module.exports = function(source) {
  this.cacheable && this.cacheable();
  var query = loaderUtils.parseQuery(this.query);
  var cacheParserResults = !!query.cache;
  // Description of PEG.js options: https://github.com/pegjs/pegjs#javascript-api
  var pegOptions = { output: 'source', cache: cacheParserResults };
  return 'module.exports = ' + pegjs.buildParser(source, pegOptions) + ';';
};

Add option to build parser with enabled cache


'use strict';

var util = require('util');
var wrapi = require('wrapi');

var endpoints = require('./api/slack.json');

function slackWrapi(token) {

  var opts = {
    qs: {
      token: token
    },
    headers: {
      'User-Agent': 'slack-wrapi'
    }
  };

  slackWrapi.super_.call(this,
            'https://slack.com/api/',
            endpoints,
            opts);
};

util.inherits(slackWrapi, wrapi);
module.exports = slackWrapi;

'use strict';

var util = require('util');
var wrapi = require('wrapi');

var endpoints = require('./api/slack.json');

function slackWrapi(token) {

  var opts = {
    headers: {
      'User-Agent': 'slack-wrapi',
      'Authorization': 'Bearer ' + token,
    }
  };

  slackWrapi.super_.call(this,
            'https://slack.com/api/',
            endpoints,
            opts);
};

util.inherits(slackWrapi, wrapi);
module.exports = slackWrapi;

Add authorization header to api calls