<commit_before>const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const fs = require('fs');
app.use(bodyParser.urlencoded({ extended: true }));
const HashMap = require('hashmap');
const dirname = fs.realpathSync('./');

var teams = new HashMap();
var ingredients = JSON.parse(fs.readFileSync(__dirname + '/data/ingredients.json', 'utf8'));
var team_suggestions = new HashMap();

// DUMMI DATA
let i1 = {
    id: 0,
    ingredients: ['Salami', 'Schinken'],
    vote: 20
};
let i2 = {
    id: 1,
    ingredients: ['Oliven', 'Schinken'],
    vote: 2
};
let i3 = {
    id: 2,
    ingredients: ['Salami', 'Pilze', 'Oliven'],
    vote: 0
};
let i4 = {
    id: 3,
    ingredients: ['Salami', 'Feta', 'Maultaschen', 'Speck'],
    vote: 7
};
team_suggestions.set('team', [i1, i2, i3, i4]);
// END DUMMI DATA

// build api endpoint for getting js files
fs.readdirSync(dirname + '/src/js').forEach(file => {
    app.get('/js/' + file, function (req, res) {
        res.status(200).sendFile(dirname + '/src/js/' + file);
    });
});

// build api endpoint for getting bootstrap files
fs.readdirSync(dirname + '/node_modules/bootstrap/dist/css').forEach(file => {
    app.get('/css/' + file, function (req, res) {
        res.status(200).sendFile(dirname + '/node_modules/bootstrap/dist/css/' + file);
    });
});

app.get('/', function (req, res) {
    res.status(200).sendFile(__dirname + "/index.htm");
});

app.get('/teams', function (req, res) {
    res.status(200).sendFile(__dirname + "/teamPage.html");
});

app.get('/pizzas/amount', function (req, res) {
    let teamname = req.query.teamname;
    if (teamname != undefined && teams.has(teamname)) {
        let amount = {
            amount: teams.get(teamname).pizza_count
        };
        res.status(200).end(JSON.stringify(amount));
    } else {
        res.sendStatus(400);
    }
});

app.get('/pizzas/ingredients', function (req, res) {
    if (ingredients.length > 0) {
        res.status(200).end(JSON.stringify(ingredients));
    } else {
        res.sendStatus(404);
    }
});

app.get('/pizzas/suggestions', function (req, res) {
    let teamname = req.query.teamname;
    if (teamname != undefined && team_suggestions.has(teamname)) {
        let suggestions = team_suggestions.get(teamname);
        res.status(200).end(JSON.stringify(suggestions));
    } else {
        res.sendStatus(400);
    }
});

app.get('/pizzas/suggest', function (req, res) {
    res.status(200).sendFile(__dirname + '/proposer.html');
});

// TODO in swagger eintragen
app.get('/teamdata', function (req, res) {
    let teamname = req.query.teamname;
    if (teamname != undefined && teams.has(teamname)) {
        res.end(JSON.stringify(teams.get(teamname)));
    } else {
        res.sendStatus(400);
    }
})

app.post('/sessioncreate/', function (req, res) {
    let teamname = req.body.teamname;
    if (teamname != undefined && !teams.has(teamname) && !team_suggestions.has(teamname)) {
        console.log('Creating team ' + teamname);
        let data = {
            teamsize: {
                number: 0,
                type: 'Not defined'
            },
            pizza_count: 0
        };
        teams.set(teamname, data);
        team_suggestions.set(teamname, []);
        res.status(200).sendFile(__dirname + '/js/teamPage.js');
        res.redirect(302, '/teams/?teamname=' + teamname);
        res.status(200).end(JSON.stringify({ teamname: teamname }));
    } else {
        console.log('Creating Team: Failure because of undefined teamname!');
        res.sendStatus(400);
    }
});

app.post('/teams/teamsize/', function (req, res) {
    let count = parseInt(req.body.count);
    let type = req.body.type;
    let teamname = req.body.teamname;
    if (count != NaN && type != undefined && teamname != undefined) {
        console.log('Update team size for team ' + teamname);
        let pizza_count = computeNumberOfPizzas(count, type);
        let data = {
            teamsize: {
                number: count,
                type: type
            },
            pizza_count: pizza_count
        };
        console.log(data);
        teams.set(teamname, data);
        res.redirect(302, '/teams/?teamname=' + teamname);
        res.status(200).end(JSON.stringify({ teamname: teamname, data: data }));
    } else {
        console.log('Update team size failed');
        res.sendStatus(400);
    }
});

app.post('/pizzas/suggestions', function (req, res) {
    let teamname = req.body.teamname;
    let ingredients = req.body.ingredients;
    if (teamname != undefined && ingredients.length > 0 && team_suggestions.has(teamname)) {
        console.log('Add suggestion for team ' + teamname);
        let suggestion = {
            id: team_suggestions.get(teamname).length,
            ingredients: ingredients,
            vote: 1
        };
        team_suggestions.get(teamname).push(suggestion);
        res.end(JSON.stringify(suggestion));
    } else {
        console.log('Failed to add suggestion');
        res.sendStatus(400);
    }
});

app.post('/pizzas/suggestions/vote', function (req, res) {
    let teamname = req.body.teamname;
    let suggestion_id = parseInt(req.body.id);
    let vote = parseInt(req.body.vote);
    if (teamname != undefined && suggestion_id != NaN && vote != NaN && team_suggestions.has(teamname)) {
        console.log('Update vote vor suggestion');
        vote = Math.sign(vote);
        team_suggestions.get(teamname)[suggestion_id].vote += vote;
        res.sendStatus(200);
    } else {
        console.log('Update voting failed');
        res.sendStatus(400);
    }
});

function computeNumberOfPizzas(count, type) {
    if (type == 'Personen') {
        let number = count * 4;
        return Math.ceil(number / 16);
    } else if (type == 'Pizzastuecke') {
        return Math.ceil(count / 16);
    } else {
        return 0;
    }
};

function saveToFile(data, filename = "tfmap.log", exitOnWrite = false) {
    let folderName = "results";
    if (!fs.existsSync(folderName)) {
        fs.mkdirSync(folderName);
    }
    fs.writeFileSync('results/' + filename, data);
    console.log("The file was saved!");
    if (exitOnWrite) {
        process.exit(0);
    }
}

var server = app.listen(8081, function () {
    var host = server.address().address;
    var port = server.address().port;
    console.log("REST server listening at http://%s:%s", host, port);
});<commit_msg>teamsize type is now null, if type is not set<commit_after>const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const fs = require('fs');
app.use(bodyParser.urlencoded({ extended: true }));
const HashMap = require('hashmap');
const dirname = fs.realpathSync('./');

var teams = new HashMap();
var ingredients = JSON.parse(fs.readFileSync(__dirname + '/data/ingredients.json', 'utf8'));
var team_suggestions = new HashMap();

// DUMMI DATA
let i1 = {
    id: 0,
    ingredients: ['Salami', 'Schinken'],
    vote: 20
};
let i2 = {
    id: 1,
    ingredients: ['Oliven', 'Schinken'],
    vote: 2
};
let i3 = {
    id: 2,
    ingredients: ['Salami', 'Pilze', 'Oliven'],
    vote: 0
};
let i4 = {
    id: 3,
    ingredients: ['Salami', 'Feta', 'Maultaschen', 'Speck'],
    vote: 7
};
team_suggestions.set('team', [i1, i2, i3, i4]);
// END DUMMI DATA

// build api endpoint for getting js files
fs.readdirSync(dirname + '/src/js').forEach(file => {
    app.get('/js/' + file, function (req, res) {
        res.status(200).sendFile(dirname + '/src/js/' + file);
    });
});

// build api endpoint for getting bootstrap files
fs.readdirSync(dirname + '/node_modules/bootstrap/dist/css').forEach(file => {
    app.get('/css/' + file, function (req, res) {
        res.status(200).sendFile(dirname + '/node_modules/bootstrap/dist/css/' + file);
    });
});

app.get('/', function (req, res) {
    res.status(200).sendFile(__dirname + "/index.htm");
});

app.get('/teams', function (req, res) {
    res.status(200).sendFile(__dirname + "/teamPage.html");
});

app.get('/pizzas/amount', function (req, res) {
    let teamname = req.query.teamname;
    if (teamname != undefined && teams.has(teamname)) {
        let amount = {
            amount: teams.get(teamname).pizza_count
        };
        res.status(200).end(JSON.stringify(amount));
    } else {
        res.sendStatus(400);
    }
});

app.get('/pizzas/ingredients', function (req, res) {
    if (ingredients.length > 0) {
        res.status(200).end(JSON.stringify(ingredients));
    } else {
        res.sendStatus(404);
    }
});

app.get('/pizzas/suggestions', function (req, res) {
    let teamname = req.query.teamname;
    if (teamname != undefined && team_suggestions.has(teamname)) {
        let suggestions = team_suggestions.get(teamname);
        res.status(200).end(JSON.stringify(suggestions));
    } else {
        res.sendStatus(400);
    }
});

app.get('/pizzas/suggest', function (req, res) {
    res.status(200).sendFile(__dirname + '/proposer.html');
});

// TODO in swagger eintragen
app.get('/teamdata', function (req, res) {
    let teamname = req.query.teamname;
    if (teamname != undefined && teams.has(teamname)) {
        res.end(JSON.stringify(teams.get(teamname)));
    } else {
        res.sendStatus(400);
    }
})

app.post('/sessioncreate/', function (req, res) {
    let teamname = req.body.teamname;
    if (teamname != undefined && !teams.has(teamname) && !team_suggestions.has(teamname)) {
        console.log('Creating team ' + teamname);
        let data = {
            teamsize: {
                number: 0,
                type: null
            },
            pizza_count: 0
        };
        teams.set(teamname, data);
        team_suggestions.set(teamname, []);
        res.status(200).sendFile(__dirname + '/js/teamPage.js');
        res.redirect(302, '/teams/?teamname=' + teamname);
        res.status(200).end(JSON.stringify({ teamname: teamname }));
    } else {
        console.log('Creating Team: Failure because of undefined teamname!');
        res.sendStatus(400);
    }
});

app.post('/teams/teamsize/', function (req, res) {
    let count = parseInt(req.body.count);
    let type = req.body.type;
    let teamname = req.body.teamname;
    if (count != NaN && type != undefined && teamname != undefined) {
        console.log('Update team size for team ' + teamname);
        let pizza_count = computeNumberOfPizzas(count, type);
        let data = {
            teamsize: {
                number: count,
                type: type
            },
            pizza_count: pizza_count
        };
        console.log(data);
        teams.set(teamname, data);
        res.redirect(302, '/teams/?teamname=' + teamname);
        res.status(200).end(JSON.stringify({ teamname: teamname, data: data }));
    } else {
        console.log('Update team size failed');
        res.sendStatus(400);
    }
});

app.post('/pizzas/suggestions', function (req, res) {
    let teamname = req.body.teamname;
    let ingredients = req.body.ingredients;
    if (teamname != undefined && ingredients.length > 0 && team_suggestions.has(teamname)) {
        console.log('Add suggestion for team ' + teamname);
        let suggestion = {
            id: team_suggestions.get(teamname).length,
            ingredients: ingredients,
            vote: 1
        };
        team_suggestions.get(teamname).push(suggestion);
        res.end(JSON.stringify(suggestion));
    } else {
        console.log('Failed to add suggestion');
        res.sendStatus(400);
    }
});

app.post('/pizzas/suggestions/vote', function (req, res) {
    let teamname = req.body.teamname;
    let suggestion_id = parseInt(req.body.id);
    let vote = parseInt(req.body.vote);
    if (teamname != undefined && suggestion_id != NaN && vote != NaN && team_suggestions.has(teamname)) {
        console.log('Update vote vor suggestion');
        vote = Math.sign(vote);
        team_suggestions.get(teamname)[suggestion_id].vote += vote;
        res.sendStatus(200);
    } else {
        console.log('Update voting failed');
        res.sendStatus(400);
    }
});

function computeNumberOfPizzas(count, type) {
    if (type == 'Personen') {
        let number = count * 4;
        return Math.ceil(number / 16);
    } else if (type == 'Pizzastuecke') {
        return Math.ceil(count / 16);
    } else {
        return 0;
    }
};

function saveToFile(data, filename = "tfmap.log", exitOnWrite = false) {
    let folderName = "results";
    if (!fs.existsSync(folderName)) {
        fs.mkdirSync(folderName);
    }
    fs.writeFileSync('results/' + filename, data);
    console.log("The file was saved!");
    if (exitOnWrite) {
        process.exit(0);
    }
}

var server = app.listen(8081, function () {
    var host = server.address().address;
    var port = server.address().port;
    console.log("REST server listening at http://%s:%s", host, port);
});<|endoftext|>


<commit_before>import dotenv from 'dotenv-defaults'
import fs from 'fs'
import { DefinePlugin } from 'webpack'

// Mostly taken from here: https://github.com/motdotla/dotenv-expand/blob/master/lib/main.js#L4
const interpolate = (env, vars) => {
  const matches = env.match(/\$([a-zA-Z0-9_]+)|\${([a-zA-Z0-9_]+)}/g) || []

  matches.forEach((match) => {
    const key = match.replace(/\$|{|}/g, '')
    let variable = vars[key] || ''
    variable = interpolate(variable, vars)
    env = env.replace(match, variable)
  })

  return env
}

class Dotenv {
  /**
   * The dotenv-webpack plugin.
   * @param {Object} options - The parameters.
   * @param {String} [options.path=./.env] - The location of the environment variable.
   * @param {Boolean|String} [options.safe=false] - If false ignore safe-mode, if true load `'./.env.example'`, if a string load that file as the sample.
   * @param {Boolean} [options.systemvars=false] - If true, load system environment variables.
   * @param {Boolean} [options.silent=false] - If true, suppress warnings, if false, display warnings.
   * @returns {webpack.DefinePlugin}
   */
  constructor (config = {}) {
    this.config = Object.assign({}, {
      path: './.env'
    }, config)

    this.checkDeprecation()

    return new DefinePlugin(this.formatData(this.gatherVariables()))
  }

  checkDeprecation () {
    const { sample, safe, silent } = this.config
    // Catch older packages, but hold their hand (just for a bit)
    if (sample) {
      if (safe) {
        this.config.safe = sample
      }
      this.warn('dotenv-webpack: "options.sample" is a deprecated property. Please update your configuration to use "options.safe" instead.', silent)
    }
  }

  gatherVariables () {
    const { safe } = this.config
    let vars = this.initializeVars()

    const { env, blueprint } = this.getEnvs()

    Object.keys(blueprint).map(key => {
      const value = vars.hasOwnProperty(key) ? vars[key] : env[key]
      if (!value && safe) {
        throw new Error(`Missing environment variable: ${key}`)
      } else {
        vars[key] = value
      }
    })

    // add the leftovers
    if (safe) {
      Object.assign(vars, env)
    }

    return vars
  }

  initializeVars () {
    return (this.config.systemvars) ? Object.assign({}, process.env) : {}
  }

  getEnvs () {
    const { path, defaults, silent, safe } = this.config
    let def = ''
    if (defaults) {
      def = this.loadFile({
        file: defaults === true ? './.env.defaults' : defaults,
        silent
      })
    }

    const env = dotenv.parse(this.loadFile({
      file: path,
      silent
    }), def)

    let blueprint = env
    if (safe) {
      let file = './.env.example'
      if (safe !== true) {
        file = safe
      }
      blueprint = dotenv.parse(this.loadFile({
        file,
        silent
      }))
    }

    return {
      env,
      blueprint
    }
  }

  formatData (vars = {}) {
    const { expand } = this.config
    return Object.keys(vars).reduce((obj, key) => {
      const v = vars[key]
      const vKey = `process.env.${key}`
      let vValue
      if (expand) {
        if (v.substring(0, 2) === '\\$') {
          vValue = v.substring(1)
        } else if (v.indexOf('\\$') > 0) {
          vValue = v.replace(/\\\$/g, '$')
        } else {
          vValue = interpolate(v, vars)
        }
      } else {
        vValue = v
      }

      obj[vKey] = JSON.stringify(vValue)

      return obj
    }, {})
  }

  /**
   * Load a file.
   * @param {String} config.file - The file to load.
   * @param {String} config.def - The defaults.
   * @param {Boolean} config.silent - If true, suppress warnings, if false, display warnings.
   * @returns {Object}
   */
  loadFile ({ file, silent }) {
    try {
      return fs.readFileSync(file, 'utf8')
    } catch (err) {
      this.warn(`Failed to load ${file}.`, silent)
      return {}
    }
  }

  /**
   * Displays a console message if 'silent' is falsey
   * @param {String} msg - The message.
   * @param {Boolean} silent - If true, display the message, if false, suppress the message.
   */
  warn (msg, silent) {
    !silent && console.warn(msg)
  }
}

export default Dotenv
<commit_msg>chore: this is endless...<commit_after>import dotenv from 'dotenv-defaults'
import fs from 'fs'
import { DefinePlugin } from 'webpack'

// Mostly taken from here: https://github.com/motdotla/dotenv-expand/blob/master/lib/main.js#L4
const interpolate = (env, vars) => {
  const matches = env.match(/\$([a-zA-Z0-9_]+)|\${([a-zA-Z0-9_]+)}/g) || []

  matches.forEach((match) => {
    const key = match.replace(/\$|{|}/g, '')
    let variable = vars[key] || ''
    variable = interpolate(variable, vars)
    env = env.replace(match, variable)
  })

  return env
}

class Dotenv {
  /**
   * The dotenv-webpack plugin.
   * @param {Object} options - The parameters.
   * @param {String} [options.path=./.env] - The location of the environment variable.
   * @param {Boolean|String} [options.safe=false] - If false ignore safe-mode, if true load `'./.env.example'`, if a string load that file as the sample.
   * @param {Boolean} [options.systemvars=false] - If true, load system environment variables.
   * @param {Boolean} [options.silent=false] - If true, suppress warnings, if false, display warnings.
   * @returns {webpack.DefinePlugin}
   */
  constructor (config = {}) {
    this.config = Object.assign({}, {
      path: './.env'
    }, config)

    this.checkDeprecation()

    return new DefinePlugin(this.formatData(this.gatherVariables()))
  }

  checkDeprecation () {
    const { sample, safe, silent } = this.config
    // Catch older packages, but hold their hand (just for a bit)
    if (sample) {
      if (safe) {
        this.config.safe = sample
      }
      this.warn('dotenv-webpack: "options.sample" is a deprecated property. Please update your configuration to use "options.safe" instead.', silent)
    }
  }

  gatherVariables () {
    const { safe } = this.config
    let vars = this.initializeVars()

    const { env, blueprint } = this.getEnvs()

    Object.keys(blueprint).map(key => {
      const value = vars.hasOwnProperty(key) ? vars[key] : env[key]
      if (!value && safe) {
        throw new Error(`Missing environment variable: ${key}`)
      } else {
        vars[key] = value
      }
    })

    // add the leftovers
    if (safe) {
      Object.assign(vars, env)
    }

    return vars
  }

  initializeVars () {
    return (this.config.systemvars) ? Object.assign({}, process.env) : {}
  }

  getEnvs () {
    const { path, silent, safe } = this.config

    const env = dotenv.parse(this.loadFile({
      file: path,
      silent
    }), this.getDefaults())

    let blueprint = env
    if (safe) {
      let file = './.env.example'
      if (safe !== true) {
        file = safe
      }
      blueprint = dotenv.parse(this.loadFile({
        file,
        silent
      }))
    }

    return {
      env,
      blueprint
    }
  }

  getDefaults () {
    const { silent, defaults } = this.config

    if (defaults) {
      return this.loadFile({
        file: defaults === true ? './.env.defaults' : defaults,
        silent
      })
    }

    return ''
  }

  formatData (vars = {}) {
    const { expand } = this.config
    return Object.keys(vars).reduce((obj, key) => {
      const v = vars[key]
      const vKey = `process.env.${key}`
      let vValue
      if (expand) {
        if (v.substring(0, 2) === '\\$') {
          vValue = v.substring(1)
        } else if (v.indexOf('\\$') > 0) {
          vValue = v.replace(/\\\$/g, '$')
        } else {
          vValue = interpolate(v, vars)
        }
      } else {
        vValue = v
      }

      obj[vKey] = JSON.stringify(vValue)

      return obj
    }, {})
  }

  /**
   * Load a file.
   * @param {String} config.file - The file to load.
   * @param {Boolean} config.silent - If true, suppress warnings, if false, display warnings.
   * @returns {Object}
   */
  loadFile ({ file, silent }) {
    try {
      return fs.readFileSync(file, 'utf8')
    } catch (err) {
      this.warn(`Failed to load ${file}.`, silent)
      return {}
    }
  }

  /**
   * Displays a console message if 'silent' is falsey
   * @param {String} msg - The message.
   * @param {Boolean} silent - If true, display the message, if false, suppress the message.
   */
  warn (msg, silent) {
    !silent && console.warn(msg)
  }
}

export default Dotenv
<|endoftext|>


<commit_before>'use strict';
var Alexa = require("alexa-sdk");
var request = require("request");

exports.handler = function(event, context, callback) {
    var alexa = Alexa.handler(event, context);
    alexa.registerHandlers(handlers);
    alexa.execute();
};

var handlers = {
    'LaunchRequest': function () {
        this.emit('SayHello');
    },
    'HelloWorldIntent': function () {
        this.emit('SayHello');
    },
    'SayHello': function () {
        request('http://www.chapin.edu/data/calendar/rsscache/calendar_282.rss', function (error, response, body) {
            if (!error && response.statusCode == 200) {
                //console.log(body);
                //console.log(response.statusCode);

                var parseString = require('xml2js').parseString;
                var dataXML = body;
                parseString(dataXML, function (err, result) {
                    var dataJSON = result;
                    console.log(dataJSON);
                    this.emit(':tell', dataJSON);

                });

            }
            else
            {
                console.log('Error with request');
                this.emit('Oops.');
            }

        });
    }
};
<commit_msg>Update index.js<commit_after>'use strict';
var Alexa = require("alexa-sdk");
var request = require("request");

exports.handler = function(event, context, callback) {
    var alexa = Alexa.handler(event, context);
    alexa.registerHandlers(handlers);
    alexa.execute();
};

var handlers = {
    'LaunchRequest': function () {
        this.emit('SayHello');
    },
    'HelloWorldIntent': function () {
        this.emit('SayHello');
    },
    'SayHello': function () {
        request('http://www.chapin.edu/data/calendar/rsscache/calendar_282.rss', function (error, response, body) {
            if (!error && response.statusCode == 200) {
                //console.log(body);
                //console.log(response.statusCode);

                var parseString = require('xml2js').parseString;
                var dataXML = body;
                parseString(dataXML, function (err, result) {
                    var dataJSON = result;
                    console.dir(dataJSON);
                    this.emit(':tell', JSON.stringify(dataJSON));

                });

            }
            else
            {
                console.log('Error with request');
                this.emit('Oops.');
            }

        });
    }
};
<|endoftext|>


<commit_before>import React, {PropTypes} from 'react';
import Spinner from 'spin.js';

export default class ReactSpinner extends React.Component {
  static propTypes = {
    // This object is passed in wholesale as the spinner config
    config: PropTypes.object,
    // This is a quick way to overwrite just the color on the config
    color: PropTypes.string.isRequired,
  }
  static defaultProps = {
    config: {},
    color: 'black',
  }
  componentDidMount() {
    const {color, config} = this.props;
    const spinConfig = {
      // a few sensible defaults
      width: 2,
      radius: 10,
      length: 7,
      // color should not overwrite config
      color,
      // config will overwrite anything else
      ...config,
    };

    this.spinner = new Spinner(spinConfig);
    this.spinner.spin(this.refs.container);
  }
  componentWillUnmount() {
    this.spinner.stop();
  }
  render() {
    return ()
  }
}
<commit_msg>small style change<commit_after>import React, {PropTypes} from 'react';
import Spinner from 'spin.js';

export default class ReactSpinner extends React.Component {
  static propTypes = {
    // This object is passed in wholesale as the spinner config
    config: PropTypes.object,
    // This is a quick way to overwrite just the color on the config
    color: PropTypes.string.isRequired,
  }
  static defaultProps = {
    config: {},
    color: 'black',
  }
  componentDidMount() {
    const {color, config} = this.props;
    const spinConfig = {
      // a few sensible defaults
      width: 2,
      radius: 10,
      length: 7,
      // color should not overwrite config
      color,
      // config will overwrite anything else
      ...config,
    };

    this.spinner = new Spinner(spinConfig);
    this.spinner.spin(this.refs.container);
  }
  componentWillUnmount() {
    this.spinner.stop();
  }
  render() {
    return ;
  }
}
<|endoftext|>


<commit_before>import {cloneElement, Children} from 'react'
import {findPathValue} from './utils'
import {warnNotFound} from './debug'

export {genLocation, loc, isPath, findPath, findPathValue} from './utils'

export function Router({
  location,
  options,
  children,
}) {
  if (location == null) return null

  const routes = addRoutes(children, {})
  return renderMatch(routes, location, options)
}

function addRoutes(elements, routes, parent) {
  Children.forEach(elements, element => {
    const route = createRoute(element, parent)
    routes[route.path] = route

    const {children} = element.props
    addRoutes(children, routes, route)
  })

  return routes
}

function createRoute(element, parent) {
  const path = fullPath(element.props.path, parent)
    .replace(/\/$/, '') // remove trailing slash

  return {path, parent, element}
}

function fullPath(path, parent) {
  if (!path) return parent ? parent.path : '' // index route
  if (!parent || path[0] === '/') return path // root or absolute
  return parent.path + '/' + path
}

function renderMatch(routes, location, options) {
  const result = findPathValue(routes, location, options)
  if (result) return render(result.value, result.params)

  warnNotFound(routes, location)
  return null
}

function render(route, params, children) {
  const {element, parent} = route
  const node = cloneElement(element, params, children)

  return parent ? render(parent, params, node) : node
}
<commit_msg>comment about == null<commit_after>import {cloneElement, Children} from 'react'
import {findPathValue} from './utils'
import {warnNotFound} from './debug'

export {genLocation, loc, isPath, findPath, findPathValue} from './utils'

export function Router({
  location,
  options,
  children,
}) {
  // null or undefined
  if (location == null) return null

  const routes = addRoutes(children, {})
  return renderMatch(routes, location, options)
}

function addRoutes(elements, routes, parent) {
  Children.forEach(elements, element => {
    const route = createRoute(element, parent)
    routes[route.path] = route

    const {children} = element.props
    addRoutes(children, routes, route)
  })

  return routes
}

function createRoute(element, parent) {
  const path = fullPath(element.props.path, parent)
    .replace(/\/$/, '') // remove trailing slash

  return {path, parent, element}
}

function fullPath(path, parent) {
  if (!path) return parent ? parent.path : '' // index route
  if (!parent || path[0] === '/') return path // root or absolute
  return parent.path + '/' + path
}

function renderMatch(routes, location, options) {
  const result = findPathValue(routes, location, options)
  if (result) return render(result.value, result.params)

  warnNotFound(routes, location)
  return null
}

function render(route, params, children) {
  const {element, parent} = route
  const node = cloneElement(element, params, children)

  return parent ? render(parent, params, node) : node
}
<|endoftext|>


<commit_before>const discord = require('discord.js');

module.exports = {
	Client: require('./client'),
	Command: require('./command'),
	CommandArgument: require('./command-argument'),
	CommandGroup: require('./command-group'),
	CommandMessage: require('./command-message'),
	FriendlyError: require('./errors/friendly'),
	CommandFormatError: require('./errors/command-format'),

	util: require('./util'),
	version: require('../package').version
};

require('./extensions/guild').applyToClass(discord.Guild);

/**
 * @external ClientOptions
 * @see {@link http://hydrabolt.github.io/discord.js/#!/docs/tag/indev/typedef/ClientOptions}
 */
/**
 * @external User
 * @see {@link http://hydrabolt.github.io/discord.js/#!/docs/tag/indev/class/User}
 */
/**
 * @external Guild
 * @see {@link http://hydrabolt.github.io/discord.js/#!/docs/tag/indev/class/Guild}
 */
/**
 * @external GuildResolvable
 * @see {@link http://hydrabolt.github.io/discord.js/#!/docs/tag/indev/typedef/GuildResolvable}
 */
/**
 * @external GuildMember
 * @see {@link http://hydrabolt.github.io/discord.js/#!/docs/tag/indev/class/GuildMember}
 */
/**
 * @external Channel
 * @see {@link http://hydrabolt.github.io/discord.js/#!/docs/tag/indev/class/Channel}
 */
/**
 * @external Message
 * @see {@link http://hydrabolt.github.io/discord.js/#!/docs/tag/indev/class/Message}
 */
/**
 * @external StringResolvable
 * @see {@link http://hydrabolt.github.io/discord.js/#!/docs/tag/indev/typedef/StringResolvable}
 */
<commit_msg>Updated d.js docs links<commit_after>const discord = require('discord.js');

module.exports = {
	Client: require('./client'),
	Command: require('./command'),
	CommandArgument: require('./command-argument'),
	CommandGroup: require('./command-group'),
	CommandMessage: require('./command-message'),
	FriendlyError: require('./errors/friendly'),
	CommandFormatError: require('./errors/command-format'),

	util: require('./util'),
	version: require('../package').version
};

require('./extensions/guild').applyToClass(discord.Guild);

/**
 * @external ClientOptions
 * @see {@link http://hydrabolt.github.io/discord.js/#!/docs/tag/master/typedef/ClientOptions}
 */
/**
 * @external User
 * @see {@link http://hydrabolt.github.io/discord.js/#!/docs/tag/master/class/User}
 */
/**
 * @external Guild
 * @see {@link http://hydrabolt.github.io/discord.js/#!/docs/tag/master/class/Guild}
 */
/**
 * @external GuildResolvable
 * @see {@link http://hydrabolt.github.io/discord.js/#!/docs/tag/master/typedef/GuildResolvable}
 */
/**
 * @external GuildMember
 * @see {@link http://hydrabolt.github.io/discord.js/#!/docs/tag/master/class/GuildMember}
 */
/**
 * @external Role
 * @see {@link http://hydrabolt.github.io/discord.js/#!/docs/tag/master/class/Role}
 */
/**
 * @external Channel
 * @see {@link http://hydrabolt.github.io/discord.js/#!/docs/tag/master/class/Channel}
 */
/**
 * @external Message
 * @see {@link http://hydrabolt.github.io/discord.js/#!/docs/tag/master/class/Message}
 */
/**
 * @external StringResolvable
 * @see {@link http://hydrabolt.github.io/discord.js/#!/docs/tag/master/typedef/StringResolvable}
 */
<|endoftext|>


<commit_before>import fs from 'fs';
import path from 'path';
import homeOrTmp from 'home-or-tmp';
import tar from 'tar';
import EventEmitter from 'events';
import chalk from 'chalk';
import { rimrafSync } from 'sander';
import {
	DegitError,
	exec,
	fetch,
	mkdirp,
	tryRequire,
	stashFiles,
	unstashFiles,
	degitConfigName,
} from './utils';

const base = path.join(homeOrTmp, '.degit');

export default function degit(src, opts) {
	return new Degit(src, opts);
}

class Degit extends EventEmitter {
	constructor(src, opts = {}) {
		super();

		this.src = src;
		this.cache = opts.cache;
		this.force = opts.force;
		this.verbose = opts.verbose;

		this.repo = parse(src);

		this._hasStashed = false;

		this.directiveActions = {
			clone: async (dir, dest, action) => {
				if (this._hasStashed === false) {
					stashFiles(dir, dest);
					this._hasStashed = true;
				}
				const opts = Object.assign(
					{ force: true },
					{ cache: action.cache, verbose: action.verbose }
				);
				const d = degit(action.src, opts);

				d.on('info', event => {
					console.error(
						chalk.cyan(`> ${event.message.replace('options.', '--')}`)
					);
				});

				d.on('warn', event => {
					console.error(
						chalk.magenta(`! ${event.message.replace('options.', '--')}`)
					);
				});

				await d.clone(dest).catch(err => {
					console.error(chalk.red(`! ${err.message}`));
					process.exit(1);
				});
			},
			remove: this.remove.bind(this),
		};
	}

	_getDirectives(dest) {
		const directivesPath = path.resolve(dest, degitConfigName);
		const directives =
			tryRequire(directivesPath, { clearCache: true }) || false;
		if (directives) {
			fs.unlinkSync(directivesPath);
		}

		return directives;
	}

	async clone(dest) {
		this._checkDirIsEmpty(dest);

		const repo = this.repo;

		const dir = path.join(base, repo.site, repo.user, repo.name);
		const cached = tryRequire(path.join(dir, 'map.json')) || {};

		const hash = this.cache
			? this._getHashFromCache(repo, cached)
			: await this._getHash(repo, cached);

		if (!hash) {
			// TODO 'did you mean...?'
			throw new DegitError(`could not find commit hash for ${repo.ref}`, {
				code: 'MISSING_REF',
				ref: repo.ref,
			});
		}

		const file = `${dir}/${hash}.tar.gz`;
		const url =
			repo.site === 'gitlab'
				? `${repo.url}/repository/archive.tar.gz?ref=${hash}`
				: repo.site === 'bitbucket'
				? `${repo.url}/get/${hash}.tar.gz`
				: `${repo.url}/archive/${hash}.tar.gz`;

		try {
			if (!this.cache) {
				try {
					fs.statSync(file);
					this._verbose({
						code: 'FILE_EXISTS',
						message: `${file} already exists locally`,
					});
				} catch (err) {
					mkdirp(path.dirname(file));
					this._verbose({
						code: 'DOWNLOADING',
						message: `downloading ${url} to ${file}`,
					});

					await fetch(url, file);
				}
			}
		} catch (err) {
			throw new DegitError(`could not download ${url}`, {
				code: 'COULD_NOT_DOWNLOAD',
				url,
				original: err,
			});
		}

		updateCache(dir, repo, hash, cached);

		this._verbose({
			code: 'EXTRACTING',
			message: `extracting ${file} to ${dest}`,
		});

		mkdirp(dest);
		await untar(file, dest);

		this._info({
			code: 'SUCCESS',
			message: `cloned ${chalk.bold(repo.user + '/' + repo.name)}#${chalk.bold(
				repo.ref
			)}${dest !== '.' ? ` to ${dest}` : ''}`,
			repo,
			dest,
		});

		const directives = this._getDirectives(dest);
		if (directives) {
			for (const d of directives) {
				// TODO, can this be a loop with an index to pass for better error messages?
				await this.directiveActions[d.action](dir, dest, d);
			}
			if (this._hasStashed === true) {
				unstashFiles(dir, dest);
			}
		}
	}

	remove(dir, dest, action) {
		let files = action.files;
		if (!Array.isArray(files)) {
			files = [files];
		}
		const removedFiles = files
			.map(file => {
				const filePath = path.resolve(dest, file);
				if (fs.existsSync(filePath)) {
					const isDir = fs.lstatSync(filePath).isDirectory();
					if (isDir) {
						rimrafSync(filePath);
						return file + '/';
					} else {
						fs.unlinkSync(filePath);
						return file;
					}
				} else {
					this._warn({
						code: 'FILE_DOES_NOT_EXIST',
						message: `action wants to remove ${chalk.bold(
							file
						)} but it does not exist`,
					});
					return null;
				}
			})
			.filter(d => d);

		if (removedFiles.length > 0) {
			this._info({
				code: 'REMOVED',
				message: `removed: ${chalk.bold(
					removedFiles.map(d => chalk.bold(d)).join(', ')
				)}`,
			});
		}
	}

	_checkDirIsEmpty(dir) {
		try {
			const files = fs.readdirSync(dir);
			if (files.length > 0) {
				if (this.force) {
					this._info({
						code: 'DEST_NOT_EMPTY',
						message: `destination directory is not empty. Using options.force, continuing`,
					});
				} else {
					throw new DegitError(
						`destination directory is not empty, aborting. Use options.force to override`,
						{
							code: 'DEST_NOT_EMPTY',
						}
					);
				}
			} else {
				this._verbose({
					code: 'DEST_IS_EMPTY',
					message: `destination directory is empty`,
				});
			}
		} catch (err) {
			if (err.code !== 'ENOENT') throw err;
		}
	}

	_info(info) {
		this.emit('info', info);
	}

	_warn(info) {
		this.emit('warn', info);
	}

	_verbose(info) {
		if (this.verbose) this._info(info);
	}

	async _getHash(repo, cached) {
		try {
			const refs = await fetchRefs(repo);
			return this._selectRef(refs, repo.ref);
		} catch (err) {
			this._warn(err);
			this._verbose(err.original);

			return this._getHashFromCache(repo, cached);
		}
	}

	_getHashFromCache(repo, cached) {
		if (repo.ref in cached) {
			const hash = cached[repo.ref];
			this._info({
				code: 'USING_CACHE',
				message: `using cached commit hash ${hash}`,
			});
			return hash;
		}
	}

	_selectRef(refs, selector) {
		for (const ref of refs) {
			if (ref.name === selector) {
				this._verbose({
					code: 'FOUND_MATCH',
					message: `found matching commit hash: ${ref.hash}`,
				});
				return ref.hash;
			}
		}

		if (selector.length < 8) return null;

		for (const ref of refs) {
			if (ref.hash.startsWith(selector)) return ref.hash;
		}
	}
}

const supported = new Set(['github', 'gitlab', 'bitbucket', 'git.sr.ht']);

function parse(src) {
	const match = /^(?:https:\/\/([^/]+)\/|git@([^/]+)[:/]|([^/]+)[:/])?([^/\s]+)\/([^/\s#]+)(?:#(.+))?/.exec(
		src
	);
	if (!match) {
		throw new DegitError(`could not parse ${src}`, {
			code: 'BAD_SRC',
		});
	}

	const site = (match[1] || match[2] || match[3] || 'github').replace(
		/\.(com|org)$/,
		''
	);
	if (!supported.has(site)) {
		throw new DegitError(
			`degit supports GitHub, GitLab, Sourcehut and BitBucket`,
			{
				code: 'UNSUPPORTED_HOST',
			}
		);
	}

	const user = match[4];
	const name = match[5].replace(/\.git$/, '');
	const ref = match[6] || 'master';

	const url = `https://${site}.${
		site === 'bitbucket' ? 'org' : site === 'git.sr.ht' ? '' : 'com'
	}/${user}/${name}`;

	return { site, user, name, ref, url };
}

async function untar(file, dest) {
	return tar.extract({
		file,
		strip: 1,
		C: dest,
	});
}

async function fetchRefs(repo) {
	try {
		const { stdout } = await exec(`git ls-remote ${repo.url}`);
	} catch (error) {
		throw new DegitError(`could not fetch remote ${repo.url}`, {
			code: 'COULD_NOT_FETCH',
			url: repo.url,
			original: err,
		});
	}

	return stdout
		.split('\n')
		.filter(Boolean)
		.map(row => {
			const [hash, ref] = row.split('\t');

			if (ref === 'HEAD') {
				return {
					type: 'HEAD',
					hash,
				};
			}

			const match = /refs\/(\w+)\/(.+)/.exec(ref);
			if (!match)
				throw new DegitError(`could not parse ${ref}`, {
					code: 'BAD_REF',
				});

			return {
				type:
					match[1] === 'heads'
						? 'branch'
						: match[1] === 'refs'
						? 'ref'
						: match[1],
				name: match[2],
				hash,
			};
		});
}

function updateCache(dir, repo, hash, cached) {
	if (cached[repo.ref] === hash) return;

	const oldHash = cached[repo.ref];
	if (oldHash) {
		let used = false;
		for (const key in cached) {
			if (cached[key] === hash) {
				used = true;
				break;
			}
		}

		if (!used) {
			// we no longer need this tar file
			try {
				fs.unlinkSync(path.join(dir, `${oldHash}.tar.gz`));
			} catch (err) {
				// ignore
			}
		}
	}

	cached[repo.ref] = hash;
	fs.writeFileSync(
		path.join(dir, 'map.json'),
		JSON.stringify(cached, null, '  ')
	);
}<commit_msg>Fix lint issues<commit_after>import fs from 'fs';
import path from 'path';
import homeOrTmp from 'home-or-tmp';
import tar from 'tar';
import EventEmitter from 'events';
import chalk from 'chalk';
import { rimrafSync } from 'sander';
import {
	DegitError,
	exec,
	fetch,
	mkdirp,
	tryRequire,
	stashFiles,
	unstashFiles,
	degitConfigName,
} from './utils';

const base = path.join(homeOrTmp, '.degit');

export default function degit(src, opts) {
	return new Degit(src, opts);
}

class Degit extends EventEmitter {
	constructor(src, opts = {}) {
		super();

		this.src = src;
		this.cache = opts.cache;
		this.force = opts.force;
		this.verbose = opts.verbose;

		this.repo = parse(src);

		this._hasStashed = false;

		this.directiveActions = {
			clone: async (dir, dest, action) => {
				if (this._hasStashed === false) {
					stashFiles(dir, dest);
					this._hasStashed = true;
				}
				const opts = Object.assign(
					{ force: true },
					{ cache: action.cache, verbose: action.verbose }
				);
				const d = degit(action.src, opts);

				d.on('info', event => {
					console.error(
						chalk.cyan(`> ${event.message.replace('options.', '--')}`)
					);
				});

				d.on('warn', event => {
					console.error(
						chalk.magenta(`! ${event.message.replace('options.', '--')}`)
					);
				});

				await d.clone(dest).catch(err => {
					console.error(chalk.red(`! ${err.message}`));
					process.exit(1);
				});
			},
			remove: this.remove.bind(this),
		};
	}

	_getDirectives(dest) {
		const directivesPath = path.resolve(dest, degitConfigName);
		const directives =
			tryRequire(directivesPath, { clearCache: true }) || false;
		if (directives) {
			fs.unlinkSync(directivesPath);
		}

		return directives;
	}

	async clone(dest) {
		this._checkDirIsEmpty(dest);

		const repo = this.repo;

		const dir = path.join(base, repo.site, repo.user, repo.name);
		const cached = tryRequire(path.join(dir, 'map.json')) || {};

		const hash = this.cache
			? this._getHashFromCache(repo, cached)
			: await this._getHash(repo, cached);

		if (!hash) {
			// TODO 'did you mean...?'
			throw new DegitError(`could not find commit hash for ${repo.ref}`, {
				code: 'MISSING_REF',
				ref: repo.ref,
			});
		}

		const file = `${dir}/${hash}.tar.gz`;
		const url =
			repo.site === 'gitlab'
				? `${repo.url}/repository/archive.tar.gz?ref=${hash}`
				: repo.site === 'bitbucket'
				? `${repo.url}/get/${hash}.tar.gz`
				: `${repo.url}/archive/${hash}.tar.gz`;

		try {
			if (!this.cache) {
				try {
					fs.statSync(file);
					this._verbose({
						code: 'FILE_EXISTS',
						message: `${file} already exists locally`,
					});
				} catch (err) {
					mkdirp(path.dirname(file));
					this._verbose({
						code: 'DOWNLOADING',
						message: `downloading ${url} to ${file}`,
					});

					await fetch(url, file);
				}
			}
		} catch (err) {
			throw new DegitError(`could not download ${url}`, {
				code: 'COULD_NOT_DOWNLOAD',
				url,
				original: err,
			});
		}

		updateCache(dir, repo, hash, cached);

		this._verbose({
			code: 'EXTRACTING',
			message: `extracting ${file} to ${dest}`,
		});

		mkdirp(dest);
		await untar(file, dest);

		this._info({
			code: 'SUCCESS',
			message: `cloned ${chalk.bold(repo.user + '/' + repo.name)}#${chalk.bold(
				repo.ref
			)}${dest !== '.' ? ` to ${dest}` : ''}`,
			repo,
			dest,
		});

		const directives = this._getDirectives(dest);
		if (directives) {
			for (const d of directives) {
				// TODO, can this be a loop with an index to pass for better error messages?
				await this.directiveActions[d.action](dir, dest, d);
			}
			if (this._hasStashed === true) {
				unstashFiles(dir, dest);
			}
		}
	}

	remove(dir, dest, action) {
		let files = action.files;
		if (!Array.isArray(files)) {
			files = [files];
		}
		const removedFiles = files
			.map(file => {
				const filePath = path.resolve(dest, file);
				if (fs.existsSync(filePath)) {
					const isDir = fs.lstatSync(filePath).isDirectory();
					if (isDir) {
						rimrafSync(filePath);
						return file + '/';
					} else {
						fs.unlinkSync(filePath);
						return file;
					}
				} else {
					this._warn({
						code: 'FILE_DOES_NOT_EXIST',
						message: `action wants to remove ${chalk.bold(
							file
						)} but it does not exist`,
					});
					return null;
				}
			})
			.filter(d => d);

		if (removedFiles.length > 0) {
			this._info({
				code: 'REMOVED',
				message: `removed: ${chalk.bold(
					removedFiles.map(d => chalk.bold(d)).join(', ')
				)}`,
			});
		}
	}

	_checkDirIsEmpty(dir) {
		try {
			const files = fs.readdirSync(dir);
			if (files.length > 0) {
				if (this.force) {
					this._info({
						code: 'DEST_NOT_EMPTY',
						message: `destination directory is not empty. Using options.force, continuing`,
					});
				} else {
					throw new DegitError(
						`destination directory is not empty, aborting. Use options.force to override`,
						{
							code: 'DEST_NOT_EMPTY',
						}
					);
				}
			} else {
				this._verbose({
					code: 'DEST_IS_EMPTY',
					message: `destination directory is empty`,
				});
			}
		} catch (err) {
			if (err.code !== 'ENOENT') throw err;
		}
	}

	_info(info) {
		this.emit('info', info);
	}

	_warn(info) {
		this.emit('warn', info);
	}

	_verbose(info) {
		if (this.verbose) this._info(info);
	}

	async _getHash(repo, cached) {
		try {
			const refs = await fetchRefs(repo);
			return this._selectRef(refs, repo.ref);
		} catch (err) {
			this._warn(err);
			this._verbose(err.original);

			return this._getHashFromCache(repo, cached);
		}
	}

	_getHashFromCache(repo, cached) {
		if (repo.ref in cached) {
			const hash = cached[repo.ref];
			this._info({
				code: 'USING_CACHE',
				message: `using cached commit hash ${hash}`,
			});
			return hash;
		}
	}

	_selectRef(refs, selector) {
		for (const ref of refs) {
			if (ref.name === selector) {
				this._verbose({
					code: 'FOUND_MATCH',
					message: `found matching commit hash: ${ref.hash}`,
				});
				return ref.hash;
			}
		}

		if (selector.length < 8) return null;

		for (const ref of refs) {
			if (ref.hash.startsWith(selector)) return ref.hash;
		}
	}
}

const supported = new Set(['github', 'gitlab', 'bitbucket', 'git.sr.ht']);

function parse(src) {
	const match = /^(?:https:\/\/([^/]+)\/|git@([^/]+)[:/]|([^/]+)[:/])?([^/\s]+)\/([^/\s#]+)(?:#(.+))?/.exec(
		src
	);
	if (!match) {
		throw new DegitError(`could not parse ${src}`, {
			code: 'BAD_SRC',
		});
	}

	const site = (match[1] || match[2] || match[3] || 'github').replace(
		/\.(com|org)$/,
		''
	);
	if (!supported.has(site)) {
		throw new DegitError(
			`degit supports GitHub, GitLab, Sourcehut and BitBucket`,
			{
				code: 'UNSUPPORTED_HOST',
			}
		);
	}

	const user = match[4];
	const name = match[5].replace(/\.git$/, '');
	const ref = match[6] || 'master';

	const url = `https://${site}.${
		site === 'bitbucket' ? 'org' : site === 'git.sr.ht' ? '' : 'com'
	}/${user}/${name}`;

	return { site, user, name, ref, url };
}

async function untar(file, dest) {
	return tar.extract({
		file,
		strip: 1,
		C: dest,
	});
}

async function fetchRefs(repo) {
	try {
		const { stdout } = await exec(`git ls-remote ${repo.url}`);

		return stdout
			.split('\n')
			.filter(Boolean)
			.map(row => {
				const [hash, ref] = row.split('\t');

				if (ref === 'HEAD') {
					return {
						type: 'HEAD',
						hash,
					};
				}

				const match = /refs\/(\w+)\/(.+)/.exec(ref);
				if (!match)
					throw new DegitError(`could not parse ${ref}`, {
						code: 'BAD_REF',
					});

				return {
					type:
						match[1] === 'heads'
							? 'branch'
							: match[1] === 'refs'
							? 'ref'
							: match[1],
					name: match[2],
					hash,
				};
			});
	} catch (error) {
		throw new DegitError(`could not fetch remote ${repo.url}`, {
			code: 'COULD_NOT_FETCH',
			url: repo.url,
			original: error,
		});
	}
}

function updateCache(dir, repo, hash, cached) {
	if (cached[repo.ref] === hash) return;

	const oldHash = cached[repo.ref];
	if (oldHash) {
		let used = false;
		for (const key in cached) {
			if (cached[key] === hash) {
				used = true;
				break;
			}
		}

		if (!used) {
			// we no longer need this tar file
			try {
				fs.unlinkSync(path.join(dir, `${oldHash}.tar.gz`));
			} catch (err) {
				// ignore
			}
		}
	}

	cached[repo.ref] = hash;
	fs.writeFileSync(
		path.join(dir, 'map.json'),
		JSON.stringify(cached, null, '  ')
	);
}
<|endoftext|>


<commit_before>/**
 * @license MIT
 * taksim.io/emitter // @echo VERSION
 * https://github.com/taksim-io/emitter
 * Copyright (c) 2015 taksim.io
*/

;(function(root, factory) {
  if (typeof define === 'function' && define.amd) {
    define(factory);
  } else if (typeof exports === 'object') {
    module.exports = factory(root);
  } else {
    var Emitter = factory(root);
    root.Emitter || (root.Emitter = Emitter);
    root.taksim || (root.taksim = {});
    root.taksim.Emitter = Emitter;
  }
})(this, function() {

  'use strict';

  var uniqueId = 1;
  var namespace = 'emitter';
  var proto = TaksimEmitter.prototype;

  function TaksimEmitter(obj) {
    if (obj) {
      return mixin(obj, proto);
    }
  }

  proto.emit = function() {
    var on = _t(this).listeners;
    var args = Array.prototype.slice.call(arguments);
    var event = args.shift();
    var result;
    if (on && on[event]) {
      var callbacks = on[event];
      if (typeof callbacks === 'function') {
        result = callbacks.apply(this, args);
      }
      else {
        var len = callbacks.length;
        callbacks = callbacks.slice();
        for (var i = 0; i < len; i++) {
          result = callbacks[i].apply(this, args);
          if (result === false) {
            break;
          }
        }
      }
    }
    return result;
  };

  proto.on = function(event, callback) {
    if (typeof event === 'object') {
      eachEvent(this, 'on', event);
    }
    else if (typeof callback === 'function') {
      var events = event.split(' ');
      var i = events.length;
      var t = _t(this);
      var on = t.listeners;
      on || (on = t.listeners = {});
      while (i--) {
        event = events[i];
        if (typeof on[event] !== 'function') {
          on[event] || (on[event] = []);
          on[event].push(callback);
        }
      }
    }
    return this;
  };

  proto.once = function(event, callback) {
    if (typeof event === 'object') {
      eachEvent(this, 'once', event);
    }
    else if (typeof callback === 'function') {
      var events = event.split(' ');
      var i = events.length;
      while (i--) {
        this.on(event, once(this, events[i], callback));
      }
    }
    return this;
  };

  function once(ctx, event, callback) {
    return function before() {
      ctx.off(event, before);
      callback.apply(ctx, arguments);
    };
  }

  proto.only = function(event, callback) {
    if (typeof event === 'object') {
      eachEvent(this, 'only', event);
    }
    else if (typeof callback === 'function') {
      var events = event.split(' ');
      var i = events.length;
      var t = _t(this);
      var on = t.listeners;
      on || (on = t.listeners = {});
      while (i--) {
        var e = events[i];
        if (typeof on[e] !== 'function') {
          on[e] = callback;
        }
      }
    }
    return this;
  };

  proto.off = function(event, callback) {
    var argsLen = arguments.length;
    var t = _t(this);
    var on = t.listeners;
    if (!on) {
      return this;
    }
    if (argsLen === 0) {
      t.listeners = null;
    }
    else if (!on[event]) {
      var events = event.split(' ');
      var j = events.length;
      if (j > 1) {
        while (j--) {
          this.off(events[j], callback);
        }
      }
    }
    else if (argsLen === 1 || !callback || typeof on[event] === 'function') {
      on[event] = null;
    }
    else {
      var callbacks = on[event];
      var len = callbacks.length;
      for (var i = 0; i < len; i++) {
        var strCallback = String(callbacks[i]);
        if (strCallback === String(callback) ||
            strCallback === String(once(this, event, callback))) {
          callbacks.splice(i, 1);
          break;
        }
      }
    }
    return this;
  };

  proto.offence = function(event, callback) {
    var argsLen = arguments.length;
    var t = _t(this);
    var on = t.listeners;
    var callbacks;
    if (!on) {
      return this;
    }
    if (argsLen === 0) {
      for (var key in on) {
        if (on.hasOwnProperty(key)) {
          this.offence(key);
        }
      }
    }
    else if (!on[event]) {
      var events = event.split(' ');
      var j = events.length;
      if (j > 1) {
        while (j--) {
          this.offence(events[j], callback);
        }
      }
    }
    else if (argsLen === 1 || !callback || typeof callbacks === 'function') {
      callbacks = on[event];
      if (String(callbacks) !== 'function() {on[event] = callbacks;}') {
        on[event] = function() {on[event] = callbacks;};
      }
    }
    else if (callback) {
      callbacks = on[event];
      var len = callbacks.length;
      for (var i = 0; i < len; i++) {
        var strCallback = String(callbacks[i]);
        if (strCallback === String(callback) ||
            strCallback === String(once(this, event, callback))) {
          offence(callbacks, i, callbacks[i]);
          break;
        }
      }
    }
    return this;
  };

  proto.getListeners = function(event) {
    return (_t(this).listeners || {})[event] || [];
  };

  proto.hasListeners = function(event) {
    return !!this.getListeners(event).length;
  };

  function offence(callbacks, i, callback) {
    callbacks[i] = function() {
      callbacks[i] = callback;
    };
  }

  function eachEvent(ctx, method, obj) {
    for (var key in obj) {
      if (obj.hasOwnProperty(key)) {
        ctx[method](key, obj[key]);
      }
    }
  }

  function _t(ctx) {
    ctx._t || (ctx._t = {});
    ctx._t.id || (ctx._t.id = uniqueId++);
    return ctx._t[namespace] || (ctx._t[namespace] = {});
  }

  function mixin(base) {
    var len = arguments.length;
    base || (base = {});
    for (var i = 1; i < len; i++) {
      var source = arguments[i];
      if (source) {
        for (var prop in source) {
          if (source.hasOwnProperty(prop)) {
            base[prop] = source[prop];
          }
        }
      }
    }
    return base;
  }

  function inherits(child, parent) {
    var childProto = child.prototype;
    var Mirror = function() {
      this.constructor = child;
    };
    Mirror.prototype = parent.prototype;
    child.prototype = new Mirror();
    child.__super__ = parent.prototype;
    mixin(child.prototype, childProto);
  }

  TaksimEmitter.mixin = mixin;
  TaksimEmitter.extend = function(ctor, extender) {
    if (typeof ctor !== 'function') {
      extender = ctor;
      ctor = null;
    }
    var parent = this;
    var child;

    if (ctor) {
      child = ctor;
    }
    else {
      child = function() {
        return parent.apply(this, arguments);
      };
    }

    inherits(child, parent);
    mixin(child, parent);
    mixin(child.prototype, extender);

    return child;
  };

  return TaksimEmitter;
});
<commit_msg>Moved unique id generation to  "_tid" method<commit_after>/**
 * @license MIT
 * taksim.io/emitter // @echo VERSION
 * https://github.com/taksim-io/emitter
 * Copyright (c) 2015 taksim.io
*/

;(function(root, factory) {
  if (typeof define === 'function' && define.amd) {
    define(factory);
  } else if (typeof exports === 'object') {
    module.exports = factory(root);
  } else {
    var Emitter = factory(root);
    root.Emitter || (root.Emitter = Emitter);
    root.taksim || (root.taksim = {});
    root.taksim.Emitter = Emitter;
  }
})(this, function() {

  'use strict';

  var uniqueId = 1;
  var namespace = 'emitter';
  var proto = TaksimEmitter.prototype;

  function TaksimEmitter(obj) {
    if (obj) {
      return mixin(obj, proto);
    }
  }

  proto.emit = function() {
    var on = _t(this).listeners;
    var args = Array.prototype.slice.call(arguments);
    var event = args.shift();
    var result;
    if (on && on[event]) {
      var callbacks = on[event];
      if (typeof callbacks === 'function') {
        result = callbacks.apply(this, args);
      }
      else {
        var len = callbacks.length;
        callbacks = callbacks.slice();
        for (var i = 0; i < len; i++) {
          result = callbacks[i].apply(this, args);
          if (result === false) {
            break;
          }
        }
      }
    }
    return result;
  };

  proto.on = function(event, callback) {
    if (typeof event === 'object') {
      eachEvent(this, 'on', event);
    }
    else if (typeof callback === 'function') {
      var events = event.split(' ');
      var i = events.length;
      var t = _t(this);
      var on = t.listeners;
      on || (on = t.listeners = {});
      while (i--) {
        event = events[i];
        if (typeof on[event] !== 'function') {
          on[event] || (on[event] = []);
          on[event].push(callback);
        }
      }
    }
    return this;
  };

  proto.once = function(event, callback) {
    if (typeof event === 'object') {
      eachEvent(this, 'once', event);
    }
    else if (typeof callback === 'function') {
      var events = event.split(' ');
      var i = events.length;
      while (i--) {
        this.on(event, once(this, events[i], callback));
      }
    }
    return this;
  };

  function once(ctx, event, callback) {
    return function before() {
      ctx.off(event, before);
      callback.apply(ctx, arguments);
    };
  }

  proto.only = function(event, callback) {
    if (typeof event === 'object') {
      eachEvent(this, 'only', event);
    }
    else if (typeof callback === 'function') {
      var events = event.split(' ');
      var i = events.length;
      var t = _t(this);
      var on = t.listeners;
      on || (on = t.listeners = {});
      while (i--) {
        var e = events[i];
        if (typeof on[e] !== 'function') {
          on[e] = callback;
        }
      }
    }
    return this;
  };

  proto.off = function(event, callback) {
    var argsLen = arguments.length;
    var t = _t(this);
    var on = t.listeners;
    if (!on) {
      return this;
    }
    if (argsLen === 0) {
      t.listeners = null;
    }
    else if (!on[event]) {
      var events = event.split(' ');
      var j = events.length;
      if (j > 1) {
        while (j--) {
          this.off(events[j], callback);
        }
      }
    }
    else if (argsLen === 1 || !callback || typeof on[event] === 'function') {
      on[event] = null;
    }
    else {
      var callbacks = on[event];
      var len = callbacks.length;
      for (var i = 0; i < len; i++) {
        var strCallback = String(callbacks[i]);
        if (strCallback === String(callback) ||
            strCallback === String(once(this, event, callback))) {
          callbacks.splice(i, 1);
          break;
        }
      }
    }
    return this;
  };

  proto.offence = function(event, callback) {
    var argsLen = arguments.length;
    var t = _t(this);
    var on = t.listeners;
    var callbacks;
    if (!on) {
      return this;
    }
    if (argsLen === 0) {
      for (var key in on) {
        if (on.hasOwnProperty(key)) {
          this.offence(key);
        }
      }
    }
    else if (!on[event]) {
      var events = event.split(' ');
      var j = events.length;
      if (j > 1) {
        while (j--) {
          this.offence(events[j], callback);
        }
      }
    }
    else if (argsLen === 1 || !callback || typeof callbacks === 'function') {
      callbacks = on[event];
      if (String(callbacks) !== 'function() {on[event] = callbacks;}') {
        on[event] = function() {on[event] = callbacks;};
      }
    }
    else if (callback) {
      callbacks = on[event];
      var len = callbacks.length;
      for (var i = 0; i < len; i++) {
        var strCallback = String(callbacks[i]);
        if (strCallback === String(callback) ||
            strCallback === String(once(this, event, callback))) {
          offence(callbacks, i, callbacks[i]);
          break;
        }
      }
    }
    return this;
  };

  proto.getListeners = function(event) {
    return (_t(this).listeners || {})[event] || [];
  };

  proto.hasListeners = function(event) {
    return !!this.getListeners(event).length;
  };

  proto._tid = function() {
    var ctx = this;
    ctx._t || (ctx._t = {});
    return ctx._t.tid || (ctx._t.tid = uniqueId++);
  };

  function offence(callbacks, i, callback) {
    callbacks[i] = function() {
      callbacks[i] = callback;
    };
  }

  function eachEvent(ctx, method, obj) {
    for (var key in obj) {
      if (obj.hasOwnProperty(key)) {
        ctx[method](key, obj[key]);
      }
    }
  }

  function _t(ctx) {
    ctx._t || (ctx._t = {});
    return ctx._t[namespace] || (ctx._t[namespace] = {});
  }

  function mixin(base) {
    var len = arguments.length;
    base || (base = {});
    for (var i = 1; i < len; i++) {
      var source = arguments[i];
      if (source) {
        for (var prop in source) {
          if (source.hasOwnProperty(prop)) {
            base[prop] = source[prop];
          }
        }
      }
    }
    return base;
  }

  function inherits(child, parent) {
    var childProto = child.prototype;
    var Mirror = function() {
      this.constructor = child;
    };
    Mirror.prototype = parent.prototype;
    child.prototype = new Mirror();
    child.__super__ = parent.prototype;
    mixin(child.prototype, childProto);
  }

  TaksimEmitter.mixin = mixin;
  TaksimEmitter.extend = function(ctor, extender) {
    if (typeof ctor !== 'function') {
      extender = ctor;
      ctor = null;
    }
    var parent = this;
    var child;

    if (ctor) {
      child = ctor;
    }
    else {
      child = function() {
        return parent.apply(this, arguments);
      };
    }

    inherits(child, parent);
    mixin(child, parent);
    mixin(child.prototype, extender);

    return child;
  };

  return TaksimEmitter;
});
<|endoftext|>


<commit_before>import {DOM, FEATURE} from 'aurelia-pal';

let hasSetImmediate = typeof setImmediate === 'function';

function makeRequestFlushFromMutationObserver(flush) {
  let toggle = 1;
  let observer = DOM.createMutationObserver(flush);
  let node = DOM.createTextNode('');
  observer.observe(node, {characterData: true});
  return function requestFlush() {
    toggle = -toggle;
    node.data = toggle;
  };
}

function makeRequestFlushFromTimer(flush) {
  return function requestFlush() {
    // We dispatch a timeout with a specified delay of 0 for engines that
    // can reliably accommodate that request. This will usually be snapped
    // to a 4 milisecond delay, but once we're flushing, there's no delay
    // between events.
    let timeoutHandle = setTimeout(handleFlushTimer, 0);
    // However, since this timer gets frequently dropped in Firefox
    // workers, we enlist an interval handle that will try to fire
    // an event 20 times per second until it succeeds.
    let intervalHandle = setInterval(handleFlushTimer, 50);
    function handleFlushTimer() {
      // Whichever timer succeeds will cancel both timers and request the
      // flush.
      clearTimeout(timeoutHandle);
      clearInterval(intervalHandle);
      flush();
    }
  };
}

function onError(error, task) {
  if ('onError' in task) {
    task.onError(error);
  } else if (hasSetImmediate) {
    setImmediate(() => { throw error; });
  } else {
    setTimeout(() => { throw error; }, 0);
  }
}

/**
* Something that is callable. Either a Function or a class with a call method.
*/
interface Callable {
  /**
  * Call it.
  */
  call(): void;
}

/**
* Implements an asynchronous task queue.
*/
export class TaskQueue {
  /**
  * Creates an instance of TaskQueue.
  */
  constructor() {
    this.microTaskQueue = [];
    this.microTaskQueueCapacity = 1024;
    this.taskQueue = [];

    if (FEATURE.mutationObserver) {
      this.requestFlushMicroTaskQueue = makeRequestFlushFromMutationObserver(() => this.flushMicroTaskQueue());
    } else {
      this.requestFlushMicroTaskQueue = makeRequestFlushFromTimer(() => this.flushMicroTaskQueue());
    }

    this.requestFlushTaskQueue = makeRequestFlushFromTimer(() => this.flushTaskQueue());
  }

  /**
  * Queues a task on the micro task queue for ASAP execution.
  * @param task The task to queue up for ASAP execution.
  */
  queueMicroTask(task: Callable | Function): void {
    if (this.microTaskQueue.length < 1) {
      this.requestFlushMicroTaskQueue();
    }

    this.microTaskQueue.push(task);
  }

  /**
  * Queues a task on the macro task queue for turn-based execution.
  * @param task The task to queue up for turn-based execution.
  */
  queueTask(task: Callable | Function): void {
    if (this.taskQueue.length < 1) {
      this.requestFlushTaskQueue();
    }

    this.taskQueue.push(task);
  }

  /**
  * Immediately flushes the task queue.
  */
  flushTaskQueue(): void {
    let queue = this.taskQueue;
    let index = 0;
    let task;

    this.taskQueue = []; //recursive calls to queueTask should be scheduled after the next cycle

    try {
      while (index < queue.length) {
        task = queue[index];
        task.call();
        index++;
      }
    } catch (error) {
      onError(error, task);
    }
  }

  /**
  * Immediately flushes the micro task queue.
  */
  flushMicroTaskQueue(): void {
    let queue = this.microTaskQueue;
    let capacity = this.microTaskQueueCapacity;
    let index = 0;
    let task;

    try {
      while (index < queue.length) {
        task = queue[index];
        task.call();
        index++;

        // Prevent leaking memory for long chains of recursive calls to `queueMicroTask`.
        // If we call `queueMicroTask` within a MicroTask scheduled by `queueMicroTask`, the queue will
        // grow, but to avoid an O(n) walk for every MicroTask we execute, we don't
        // shift MicroTasks off the queue after they have been executed.
        // Instead, we periodically shift 1024 MicroTasks off the queue.
        if (index > capacity) {
          // Manually shift all values starting at the index back to the
          // beginning of the queue.
          for (let scan = 0, newLength = queue.length - index; scan < newLength; scan++) {
            queue[scan] = queue[scan + index];
          }

          queue.length -= index;
          index = 0;
        }
      }
    } catch (error) {
      onError(error, task);
    }

    queue.length = 0;
  }
}
<commit_msg>fix(index): rename Callable to Task<commit_after>import {DOM, FEATURE} from 'aurelia-pal';

let hasSetImmediate = typeof setImmediate === 'function';

function makeRequestFlushFromMutationObserver(flush) {
  let toggle = 1;
  let observer = DOM.createMutationObserver(flush);
  let node = DOM.createTextNode('');
  observer.observe(node, {characterData: true});
  return function requestFlush() {
    toggle = -toggle;
    node.data = toggle;
  };
}

function makeRequestFlushFromTimer(flush) {
  return function requestFlush() {
    // We dispatch a timeout with a specified delay of 0 for engines that
    // can reliably accommodate that request. This will usually be snapped
    // to a 4 milisecond delay, but once we're flushing, there's no delay
    // between events.
    let timeoutHandle = setTimeout(handleFlushTimer, 0);
    // However, since this timer gets frequently dropped in Firefox
    // workers, we enlist an interval handle that will try to fire
    // an event 20 times per second until it succeeds.
    let intervalHandle = setInterval(handleFlushTimer, 50);
    function handleFlushTimer() {
      // Whichever timer succeeds will cancel both timers and request the
      // flush.
      clearTimeout(timeoutHandle);
      clearInterval(intervalHandle);
      flush();
    }
  };
}

function onError(error, task) {
  if ('onError' in task) {
    task.onError(error);
  } else if (hasSetImmediate) {
    setImmediate(() => { throw error; });
  } else {
    setTimeout(() => { throw error; }, 0);
  }
}

/**
* Either a Function or a class with a call method that will do work when dequeued.
*/
interface Task {
  /**
  * Call it.
  */
  call(): void;
}

/**
* Implements an asynchronous task queue.
*/
export class TaskQueue {
  /**
  * Creates an instance of TaskQueue.
  */
  constructor() {
    this.microTaskQueue = [];
    this.microTaskQueueCapacity = 1024;
    this.taskQueue = [];

    if (FEATURE.mutationObserver) {
      this.requestFlushMicroTaskQueue = makeRequestFlushFromMutationObserver(() => this.flushMicroTaskQueue());
    } else {
      this.requestFlushMicroTaskQueue = makeRequestFlushFromTimer(() => this.flushMicroTaskQueue());
    }

    this.requestFlushTaskQueue = makeRequestFlushFromTimer(() => this.flushTaskQueue());
  }

  /**
  * Queues a task on the micro task queue for ASAP execution.
  * @param task The task to queue up for ASAP execution.
  */
  queueMicroTask(task: Task | Function): void {
    if (this.microTaskQueue.length < 1) {
      this.requestFlushMicroTaskQueue();
    }

    this.microTaskQueue.push(task);
  }

  /**
  * Queues a task on the macro task queue for turn-based execution.
  * @param task The task to queue up for turn-based execution.
  */
  queueTask(task: Task | Function): void {
    if (this.taskQueue.length < 1) {
      this.requestFlushTaskQueue();
    }

    this.taskQueue.push(task);
  }

  /**
  * Immediately flushes the task queue.
  */
  flushTaskQueue(): void {
    let queue = this.taskQueue;
    let index = 0;
    let task;

    this.taskQueue = []; //recursive calls to queueTask should be scheduled after the next cycle

    try {
      while (index < queue.length) {
        task = queue[index];
        task.call();
        index++;
      }
    } catch (error) {
      onError(error, task);
    }
  }

  /**
  * Immediately flushes the micro task queue.
  */
  flushMicroTaskQueue(): void {
    let queue = this.microTaskQueue;
    let capacity = this.microTaskQueueCapacity;
    let index = 0;
    let task;

    try {
      while (index < queue.length) {
        task = queue[index];
        task.call();
        index++;

        // Prevent leaking memory for long chains of recursive calls to `queueMicroTask`.
        // If we call `queueMicroTask` within a MicroTask scheduled by `queueMicroTask`, the queue will
        // grow, but to avoid an O(n) walk for every MicroTask we execute, we don't
        // shift MicroTasks off the queue after they have been executed.
        // Instead, we periodically shift 1024 MicroTasks off the queue.
        if (index > capacity) {
          // Manually shift all values starting at the index back to the
          // beginning of the queue.
          for (let scan = 0, newLength = queue.length - index; scan < newLength; scan++) {
            queue[scan] = queue[scan + index];
          }

          queue.length -= index;
          index = 0;
        }
      }
    } catch (error) {
      onError(error, task);
    }

    queue.length = 0;
  }
}
<|endoftext|>


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

'use strict';

const yargs = require('yargs');
const fs = require('fs');
const path = require('path');
const AWS = require('aws-sdk');

const logger = require('log4js').getLogger();

const argv = yargs
	.alias('s', 'server').describe('server', 'The address and port of the Kubernetes API server')
	.alias('cacert', 'certificate-authority').describe('certificate-authority', 'Path to a cert. file for the certificate authority')
	.alias('cert', 'client-certificate').describe('client-certificate', 'Path to a client certificate file for TLS')
	.alias('key', 'client-key').describe('client-key', 'Path to a client key file for TLS')
	.boolean('insecure-skip-tls-verify').describe('insecure-skip-tls-verify', 'If true, the server\'s certificate will not be checked for validity. This will make your HTTPS connections insecure')
	.describe('token', 'Bearer token for authentication to the API server')
	.describe('namespace', 'The namespace to watch')
	.help()
	.argv;

/** The basic configuration for accessing the API server */
let k8sConfig;
if (argv.server) {
	const fs = require('fs');

	k8sConfig = {
		url: argv.server,
		insecureSkipTlsVerify: argv.insecureSkipTlsVerify
	};
	if (argv.certificateAuthority) {
		k8sConfig.ca = fs.readFileSync(argv.certificateAuthority, 'utf8');
	}
	if (argv.token) {
		k8sConfig.auth = { bearer: argv.token };
	} else if (argv.username && argv.password) {
		k8sConfig.auth = { user: argv.username, pass: argv.password };
	} else if (argv.clientCertificate && argv.clientKey) {
		k8sConfig.cert = fs.readFileSync(argv.clientCertificate, 'utf8');
		k8sConfig.key = fs.readFileSync(argv.clientKey, 'utf8');
	}
} else if (process.env.KUBERNETES_SERVICE_HOST) {
	const credentialsPath = '/var/run/secrets/kubernetes.io/serviceaccount/';
	k8sConfig = {
		url: `https://${process.env.KUBERNETES_SERVICE_HOST}:${process.env.KUBERNETES_SERVICE_PORT}`,
		ca: fs.readFileSync(path.resolve(credentialsPath, 'ca.crt'), 'utf8'),
		auth: { bearer: fs.readFileSync(path.resolve(credentialsPath, 'token'), 'utf8') }
	}
} else {
	logger.error('Unknown Kubernetes API server');
	process.exit(1);
}

const k8s = require('auto-kubernetes-client');
const sqs = new AWS.SQS({
	endpoint: process.env.AWS_SQS_ENDPOINT_URL_OVERRIDE,
	region: process.env.AWS_REGION,
});

if (!argv.namespace) {
	// FIXME: How to do watching without namespace (i.e. "all namespaces")
	logger.error('Must provide a namespace using --namespace');
	process.exit(1);
}

k8s(k8sConfig).then(function(k8sClient) {
	/**
	 * Convert the queue.spec parts from camelCase to AWS CapitalCase.
	 *
	 * @param {Object} queue a queue definition
	 * @param {String} [queueArn] the ARN of the queue
	 * @return {Object} the queue attributes
	 */
	function translateQueueAttributes(queue, queueArn) {
		function capitalize(s) {
			return s[0].toUpperCase() + s.substring(1);
		}

		return Object.keys(queue.spec || {}).reduce((result, key) => {
			const value = queue.spec[key];
			let resultValue;
			switch (key) {
			case 'redrivePolicy':
				resultValue = JSON.stringify(value);
				break;
			case 'policy':
				// Inject the queue ARN as 'Resource' into all statements of the policy
				let policy;
				if (queueArn) {
					logger.debug(`[${queue.metadata.name}]: Injecting resource ARN ${queueArn} into policy document`)
					policy = Object.assign({}, value, { Statement: (value.Statement || []).map(statement => Object.assign({Resource: queueArn}, statement)) });
				} else {
					policy = value;
				}

				resultValue = JSON.stringify(policy);
				break;
			default:
				// Convert to string
				resultValue = `${value}`;
				break;
			}
			logger.debug(`[${queue.metadata.name}]: Attribute ${key} = ${resultValue}`);

			result[capitalize(key)] = resultValue;
			return result;
		}, {});
	}

	/**
	 *
	 * @param {AWSError|Error} err
	 */
	function isTransientNetworkError(err) {
		return err.code === 'NetworkingError' && (err.errno === 'EHOSTUNREACH' || err.errno === 'ECONNREFUSED');
	}

	/**
	 * Resolve a promise using the given `resolve` after the `timeout` has passed by retrying `operation` on `queue`.
	 *
	 * @param {Function} resolve
	 * @param {Function} operation
	 * @param {Number} after
	 * @param {Queue} queue
	 */
	function resolveRetry(resolve, operation, after, queue, cause) {
		logger.warn(`[${queue.metadata.name}]: ${cause}, retrying in ${after/1000}s`);
		return setTimeout(function() {
			return resolve(operation(queue));
		}, after);
	}

	function createQueue(queue) {
		return new Promise(function(resolve, reject) {
			const attributes = translateQueueAttributes(queue);
			return sqs.createQueue({ QueueName: queue.metadata.name, Attributes: attributes }, function(err, data) {
				if (err) {
					if (err.name === 'AWS.SimpleQueueService.QueueDeletedRecently') {
						return resolveRetry(resolve, createQueue, 10000, queue, 'queue recently deleted');
					} else if (isTransientNetworkError(err)) {
						return resolveRetry(resolve, createQueue, 30000, queue, `transient ${err.code} ${err.errno}`);
					}

					logger.warn(`[${queue.metadata.name}]: Cannot create queue: ${err.message}`);
					return reject(err);
				}

				return resolve(data);
			});
		});
	}

	function updateQueue(queue) {
		return new Promise(function(resolve, reject) {
			return sqs.getQueueUrl({ QueueName: queue.metadata.name }, function(err, data) {
				if (err) {
					if (err.name === 'AWS.SimpleQueueService.NonExistentQueue') {
						// Queue doesn't exist: this means kubernetes saw an update, but in fact the queue was never created,
						// or has been deleted in the meantime. Create it again.
						logger.info(`[${queue.metadata.name}]: Queue does not/no longer exist, re-creating it`);
						return resolve(createQueue(queue));
					} else if (isTransientNetworkError(err)) {
						return resolveRetry(resolve, updateQueue, 30000, queue, `transient ${err.code} ${err.errno}`);
					}

					logger.warn(`[${queue.metadata.name}]: Cannot determine queue URL: ${err.message}`);
					return reject(err);
				}

				const queueUrl = data.QueueUrl;
				return sqs.getQueueAttributes({ QueueUrl: queueUrl, AttributeNames: [ 'QueueArn' ] }, function(err, data) {
					if (err) {
						if (isTransientNetworkError(err)) {
							return resolveRetry(resolve, updateQueue, 30000, queue, `transient ${err.code} ${err.errno}`);
						}

						logger.warn(`[${queue.metadata.name}]: Cannot determine queue ARN: ${err.message}`);
						return reject(err);
					}

					const attributes = translateQueueAttributes(queue, data.Attributes.QueueArn);
					if (Object.keys(attributes).length === 0) {
						// The API requires that we provide attributes when trying to update attributes.
						// If the caller intended to set values to their defaults, then they must be explicit and
						// provide these values. In other words: AWS SQS copies the defaults at creation time, and
						// afterwards there is no such thing as a "default" anymore.
						// From our side though this is not an error, but we merely ignore the request.
						// See also a similar change in Apache Camel: https://issues.apache.org/jira/browse/CAMEL-5782
						logger.warn(`[${queue.metadata.name}]: Ignoring update without attributes`);
						return resolve();
					}

					return sqs.setQueueAttributes({ QueueUrl: queueUrl, Attributes: attributes }, function(err, data) {
						if (err) {
							if (isTransientNetworkError(err)) {
								return resolveRetry(resolve, updateQueue, 30000, queue, `transient ${err.code} ${err.errno}`);
							}

							logger.warn(`[${queue.metadata.name}]: Cannot update queue attributes: ${err.message}`);
							return reject(err);
						}

						return resolve(data);
					});
				});
			});
		});
	}

	function deleteQueue(queue) {
		return new Promise(function(resolve, reject) {
			return sqs.getQueueUrl({ QueueName: queue.metadata.name }, function(err, data) {
				if (err) {
					if (isTransientNetworkError(err)) {
						return resolveRetry(resolve, deleteQueue, 30000, queue, `transient ${err.code} ${err.errno}`);
					}

					logger.warn(`[${queue.metadata.name}]: Cannot determine queue URL: ${err.message}`);
					return reject(err);
				}

				return sqs.deleteQueue({ QueueUrl: data.QueueUrl }, function(err, data) {
					if (err) {
						if (isTransientNetworkError(err)) {
							return resolveRetry(resolve, deleteQueue, 30000, queue, `transient ${err.code} ${err.errno}`);
						}

						logger.warn(`[${queue.metadata.name}]: Cannot delete queue: ${err.message}`);
						return reject(err);
					}

					return resolve(data);
				});
			});
		});
	}

	const queues = k8sClient.group('aws.k8s.collaborne.com', 'v1').ns(argv.namespace).queues;
	// Known promises for queues, used to synchronize requests and avoid races between delayed creations and modifications.
	const queuePromises = {};

	function enqueue(name, next) {
		// Enqueue the request to happen when the previous request is done.
		const previousPromise = queuePromises[name] || Promise.resolve();

		return queuePromises[name] = previousPromise.then(next);
	}

	/**
	 * Main loop
	 */
	function mainLoop() {
		// List all known queues
		queues.list().then(list => {
			const resourceVersion = list.metadata.resourceVersion;

			// Treat all queues we see as "update", which will trigger a creation/update of attributes accordingly.
			for (const queue of list.items) {
				const name = queue.metadata.name;
				enqueue(name, function() {
					logger.info(`[${name}]: Syncing`);
					return updateQueue(queue);
				}).then(function(data) {
					logger.info(`[${name}]: ${JSON.stringify(data)}`);
				}, function(err) {
					logger.error(`[${name}]: ${err.message} (${err.code})`);
				});
			}

			// Start watching the queues from that version on
			logger.info(`Watching queues at ${resourceVersion}...`);
			queues.watch(resourceVersion)
				.on('data', function(item) {
					const queue = item.object;
					const name = queue.metadata.name;

					let next;

					switch (item.type) {
					case 'ADDED':
						next = function() {
							logger.info(`[${name}]: Creating queue`);
							return createQueue(queue);
						};
						break;
					case 'MODIFIED':
						next = function() {
							logger.info(`[${name}]: Updating queue attributes`);
							return updateQueue(queue);
						};
						break;
					case 'DELETED':
						next = function() {
							logger.info(`[${name}]: Deleting queue`);
							return deleteQueue(queue);
						};
						break;
					case 'ERROR':
						// Log the message, and continue: usually the stream would end now, but there might be more events
						// in it that we do want to consume.
						logger.warn(`Error while watching: ${item.object.message}, ignoring`);
						return;
					default:
						logger.warn(`Unkown watch event type ${item.type}, ignoring`);
						return;
					}

					// Note that we retain the 'rejected' state here: an existing queue that ended in a rejection
					// will effectively stay rejected.
					const result = enqueue(name, next).then(function(data) {
						logger.info(`[${name}]: ${JSON.stringify(data)}`);
					}, function(err) {
						logger.error(`[${name}]: ${err.message} (${err.code})`);
					});

					return result;
				})
				.on('end', function() {
					// Restart the watch from the last known version.
					logger.info('Watch ended, restarting');
					return mainLoop();
				});
		});
	}

	// Start!
	mainLoop();
}).catch(function(err) {
	logger.error(`Uncaught error, aborting: ${err.message}`);
	process.exit(1);
});
<commit_msg>Refactor: extract creation of Kubernetes client config<commit_after>#!/usr/bin/env node

'use strict';

const yargs = require('yargs');
const fs = require('fs');
const path = require('path');
const AWS = require('aws-sdk');

const k8s = require('auto-kubernetes-client');

const logger = require('log4js').getLogger();

const argv = yargs
	.alias('s', 'server').describe('server', 'The address and port of the Kubernetes API server')
	.alias('cacert', 'certificate-authority').describe('certificate-authority', 'Path to a cert. file for the certificate authority')
	.alias('cert', 'client-certificate').describe('client-certificate', 'Path to a client certificate file for TLS')
	.alias('key', 'client-key').describe('client-key', 'Path to a client key file for TLS')
	.boolean('insecure-skip-tls-verify').describe('insecure-skip-tls-verify', 'If true, the server\'s certificate will not be checked for validity. This will make your HTTPS connections insecure')
	.describe('token', 'Bearer token for authentication to the API server')
	.describe('namespace', 'The namespace to watch').demandOption('namespace')
	.help()
	.argv;

/**
 * Creates basic configuration for accessing the Kubernetes API server
 *
 * @param {Object} argv Command line arguments
 * @returns {Object} Kubernetes client configuration
 */
function createK8sConfig(argv) {
	let k8sConfig;
	if (argv.server) {
		// For local development
		k8sConfig = {
			url: argv.server,
			insecureSkipTlsVerify: argv.insecureSkipTlsVerify
		};
		if (argv.certificateAuthority) {
			k8sConfig.ca = fs.readFileSync(argv.certificateAuthority, 'utf8');
		}
		if (argv.token) {
			k8sConfig.auth = { bearer: argv.token };
		} else if (argv.username && argv.password) {
			k8sConfig.auth = { user: argv.username, pass: argv.password };
		} else if (argv.clientCertificate && argv.clientKey) {
			k8sConfig.cert = fs.readFileSync(argv.clientCertificate, 'utf8');
			k8sConfig.key = fs.readFileSync(argv.clientKey, 'utf8');
		}
	} else if (process.env.KUBERNETES_SERVICE_HOST) {
		// Runs in Kubernetes
		const credentialsPath = '/var/run/secrets/kubernetes.io/serviceaccount/';
		k8sConfig = {
			url: `https://${process.env.KUBERNETES_SERVICE_HOST}:${process.env.KUBERNETES_SERVICE_PORT}`,
			ca: fs.readFileSync(path.resolve(credentialsPath, 'ca.crt'), 'utf8'),
			auth: { bearer: fs.readFileSync(path.resolve(credentialsPath, 'token'), 'utf8') }
		}
	} else {
		throw new Error('Unknown Kubernetes API server');
	}

	return k8sConfig;
}

// TODO: Move into Plugin
const sqs = new AWS.SQS({
	endpoint: process.env.AWS_SQS_ENDPOINT_URL_OVERRIDE,
	region: process.env.AWS_REGION,
});

const k8sConfig = createK8sConfig(argv);
k8s(k8sConfig).then(function(k8sClient) {
	/**
	 * Convert the queue.spec parts from camelCase to AWS CapitalCase.
	 *
	 * @param {Object} queue a queue definition
	 * @param {String} [queueArn] the ARN of the queue
	 * @return {Object} the queue attributes
	 */
	function translateQueueAttributes(queue, queueArn) {
		function capitalize(s) {
			return s[0].toUpperCase() + s.substring(1);
		}

		return Object.keys(queue.spec || {}).reduce((result, key) => {
			const value = queue.spec[key];
			let resultValue;
			switch (key) {
			case 'redrivePolicy':
				resultValue = JSON.stringify(value);
				break;
			case 'policy':
				// Inject the queue ARN as 'Resource' into all statements of the policy
				let policy;
				if (queueArn) {
					logger.debug(`[${queue.metadata.name}]: Injecting resource ARN ${queueArn} into policy document`)
					policy = Object.assign({}, value, { Statement: (value.Statement || []).map(statement => Object.assign({Resource: queueArn}, statement)) });
				} else {
					policy = value;
				}

				resultValue = JSON.stringify(policy);
				break;
			default:
				// Convert to string
				resultValue = `${value}`;
				break;
			}
			logger.debug(`[${queue.metadata.name}]: Attribute ${key} = ${resultValue}`);

			result[capitalize(key)] = resultValue;
			return result;
		}, {});
	}

	/**
	 *
	 * @param {AWSError|Error} err
	 */
	function isTransientNetworkError(err) {
		return err.code === 'NetworkingError' && (err.errno === 'EHOSTUNREACH' || err.errno === 'ECONNREFUSED');
	}

	/**
	 * Resolve a promise using the given `resolve` after the `timeout` has passed by retrying `operation` on `queue`.
	 *
	 * @param {Function} resolve
	 * @param {Function} operation
	 * @param {Number} after
	 * @param {Queue} queue
	 */
	function resolveRetry(resolve, operation, after, queue, cause) {
		logger.warn(`[${queue.metadata.name}]: ${cause}, retrying in ${after/1000}s`);
		return setTimeout(function() {
			return resolve(operation(queue));
		}, after);
	}

	function createQueue(queue) {
		return new Promise(function(resolve, reject) {
			const attributes = translateQueueAttributes(queue);
			return sqs.createQueue({ QueueName: queue.metadata.name, Attributes: attributes }, function(err, data) {
				if (err) {
					if (err.name === 'AWS.SimpleQueueService.QueueDeletedRecently') {
						return resolveRetry(resolve, createQueue, 10000, queue, 'queue recently deleted');
					} else if (isTransientNetworkError(err)) {
						return resolveRetry(resolve, createQueue, 30000, queue, `transient ${err.code} ${err.errno}`);
					}

					logger.warn(`[${queue.metadata.name}]: Cannot create queue: ${err.message}`);
					return reject(err);
				}

				return resolve(data);
			});
		});
	}

	function updateQueue(queue) {
		return new Promise(function(resolve, reject) {
			return sqs.getQueueUrl({ QueueName: queue.metadata.name }, function(err, data) {
				if (err) {
					if (err.name === 'AWS.SimpleQueueService.NonExistentQueue') {
						// Queue doesn't exist: this means kubernetes saw an update, but in fact the queue was never created,
						// or has been deleted in the meantime. Create it again.
						logger.info(`[${queue.metadata.name}]: Queue does not/no longer exist, re-creating it`);
						return resolve(createQueue(queue));
					} else if (isTransientNetworkError(err)) {
						return resolveRetry(resolve, updateQueue, 30000, queue, `transient ${err.code} ${err.errno}`);
					}

					logger.warn(`[${queue.metadata.name}]: Cannot determine queue URL: ${err.message}`);
					return reject(err);
				}

				const queueUrl = data.QueueUrl;
				return sqs.getQueueAttributes({ QueueUrl: queueUrl, AttributeNames: [ 'QueueArn' ] }, function(err, data) {
					if (err) {
						if (isTransientNetworkError(err)) {
							return resolveRetry(resolve, updateQueue, 30000, queue, `transient ${err.code} ${err.errno}`);
						}

						logger.warn(`[${queue.metadata.name}]: Cannot determine queue ARN: ${err.message}`);
						return reject(err);
					}

					const attributes = translateQueueAttributes(queue, data.Attributes.QueueArn);
					if (Object.keys(attributes).length === 0) {
						// The API requires that we provide attributes when trying to update attributes.
						// If the caller intended to set values to their defaults, then they must be explicit and
						// provide these values. In other words: AWS SQS copies the defaults at creation time, and
						// afterwards there is no such thing as a "default" anymore.
						// From our side though this is not an error, but we merely ignore the request.
						// See also a similar change in Apache Camel: https://issues.apache.org/jira/browse/CAMEL-5782
						logger.warn(`[${queue.metadata.name}]: Ignoring update without attributes`);
						return resolve();
					}

					return sqs.setQueueAttributes({ QueueUrl: queueUrl, Attributes: attributes }, function(err, data) {
						if (err) {
							if (isTransientNetworkError(err)) {
								return resolveRetry(resolve, updateQueue, 30000, queue, `transient ${err.code} ${err.errno}`);
							}

							logger.warn(`[${queue.metadata.name}]: Cannot update queue attributes: ${err.message}`);
							return reject(err);
						}

						return resolve(data);
					});
				});
			});
		});
	}

	function deleteQueue(queue) {
		return new Promise(function(resolve, reject) {
			return sqs.getQueueUrl({ QueueName: queue.metadata.name }, function(err, data) {
				if (err) {
					if (isTransientNetworkError(err)) {
						return resolveRetry(resolve, deleteQueue, 30000, queue, `transient ${err.code} ${err.errno}`);
					}

					logger.warn(`[${queue.metadata.name}]: Cannot determine queue URL: ${err.message}`);
					return reject(err);
				}

				return sqs.deleteQueue({ QueueUrl: data.QueueUrl }, function(err, data) {
					if (err) {
						if (isTransientNetworkError(err)) {
							return resolveRetry(resolve, deleteQueue, 30000, queue, `transient ${err.code} ${err.errno}`);
						}

						logger.warn(`[${queue.metadata.name}]: Cannot delete queue: ${err.message}`);
						return reject(err);
					}

					return resolve(data);
				});
			});
		});
	}

	const queues = k8sClient.group('aws.k8s.collaborne.com', 'v1').ns(argv.namespace).queues;
	// Known promises for queues, used to synchronize requests and avoid races between delayed creations and modifications.
	const queuePromises = {};

	function enqueue(name, next) {
		// Enqueue the request to happen when the previous request is done.
		const previousPromise = queuePromises[name] || Promise.resolve();

		return queuePromises[name] = previousPromise.then(next);
	}

	/**
	 * Main loop
	 */
	function mainLoop() {
		// List all known queues
		queues.list().then(list => {
			const resourceVersion = list.metadata.resourceVersion;

			// Treat all queues we see as "update", which will trigger a creation/update of attributes accordingly.
			for (const queue of list.items) {
				const name = queue.metadata.name;
				enqueue(name, function() {
					logger.info(`[${name}]: Syncing`);
					return updateQueue(queue);
				}).then(function(data) {
					logger.info(`[${name}]: ${JSON.stringify(data)}`);
				}, function(err) {
					logger.error(`[${name}]: ${err.message} (${err.code})`);
				});
			}

			// Start watching the queues from that version on
			logger.info(`Watching queues at ${resourceVersion}...`);
			queues.watch(resourceVersion)
				.on('data', function(item) {
					const queue = item.object;
					const name = queue.metadata.name;

					let next;

					switch (item.type) {
					case 'ADDED':
						next = function() {
							logger.info(`[${name}]: Creating queue`);
							return createQueue(queue);
						};
						break;
					case 'MODIFIED':
						next = function() {
							logger.info(`[${name}]: Updating queue attributes`);
							return updateQueue(queue);
						};
						break;
					case 'DELETED':
						next = function() {
							logger.info(`[${name}]: Deleting queue`);
							return deleteQueue(queue);
						};
						break;
					case 'ERROR':
						// Log the message, and continue: usually the stream would end now, but there might be more events
						// in it that we do want to consume.
						logger.warn(`Error while watching: ${item.object.message}, ignoring`);
						return;
					default:
						logger.warn(`Unkown watch event type ${item.type}, ignoring`);
						return;
					}

					// Note that we retain the 'rejected' state here: an existing queue that ended in a rejection
					// will effectively stay rejected.
					const result = enqueue(name, next).then(function(data) {
						logger.info(`[${name}]: ${JSON.stringify(data)}`);
					}, function(err) {
						logger.error(`[${name}]: ${err.message} (${err.code})`);
					});

					return result;
				})
				.on('end', function() {
					// Restart the watch from the last known version.
					logger.info('Watch ended, restarting');
					return mainLoop();
				});
		});
	}

	// Start!
	mainLoop();
}).catch(function(err) {
	logger.error(`Uncaught error, aborting: ${err.message}`);
	process.exit(1);
});
<|endoftext|>


<commit_before>/**
 * Copyright (C) 2016 yanni4night.com
 * index.js
 *
 * changelog
 * 2016-04-29[14:46:40]:revised
 *
 * @author yanni4night@gmail.com
 * @version 1.0.0
 * @since 1.0.0
 */

import isInteger from 'is-integer';

export const pascal = lines => {
    if (!isInteger(lines) || lines < 1) {
        throw new TypeError('"lines" must be a positive integer');
    }

    let triangle = [
        [1]
    ];

    if (1 === lines) {
        return triangle;
    }

    for (let i = 1; i < lines; ++i) {
        let line = [1];
        let preLine = triangle[i - 1];

        if (preLine.length % 2 === 0) {
            for (let j = 1; j < Math.floor((1 + preLine.length) / 2); ++j) {
                line[j] = (preLine[j - 1] | 0) + preLine[j];
            }
            let mid = preLine[preLine.length / 2 - 1] + preLine[preLine.length / 2];
            let lineR = line.slice().reverse();
            line = line.concat([mid]).concat(lineR);
        } else {
            for (let j = 1; j < (1 + preLine.length) / 2; ++j) {
                line[j] = (preLine[j - 1] | 0) + preLine[j];
            }
            let lineR = line.slice().reverse();
            line = line.concat(lineR);
        }

        triangle.push(line);
    }

    return triangle;

};

const repeat = (n, char) => {
    const ret = [];
    for (let i = 0; i < n; ++i) {
        ret.push(char);
    }
    return ret;
};

export const printPascal = lines => {
    const triangle = pascal(lines);
    const lastLine = triangle[triangle.length - 1];
    const postions = lastLine * 2 - 1;
    const ret = [];
    for (let i = 0; i < triangle.length; ++i) {
        let line = repeat(triangle.length - 1 - i, '');
        for (let j = 0; j < triangle[i].length; ++j) {
            line.push(triangle[i][j]);
            if (j !== triangle[i].length - 1) {
                line.push('');
            }
        }
        ret.push(line);
    }
    return ret;
};<commit_msg>remove useless<commit_after>/**
 * Copyright (C) 2016 yanni4night.com
 * index.js
 *
 * changelog
 * 2016-04-29[14:46:40]:revised
 *
 * @author yanni4night@gmail.com
 * @version 1.0.0
 * @since 1.0.0
 */

import isInteger from 'is-integer';

export const pascal = lines => {
    if (!isInteger(lines) || lines < 1) {
        throw new TypeError('"lines" must be a positive integer');
    }

    let triangle = [
        [1]
    ];

    if (1 === lines) {
        return triangle;
    }

    for (let i = 1; i < lines; ++i) {
        let line = [1];
        let preLine = triangle[i - 1];

        if (preLine.length % 2 === 0) {
            for (let j = 1; j < Math.floor((1 + preLine.length) / 2); ++j) {
                line[j] = (preLine[j - 1] | 0) + preLine[j];
            }
            let mid = preLine[preLine.length / 2 - 1] + preLine[preLine.length / 2];
            let lineR = line.slice().reverse();
            line = line.concat([mid]).concat(lineR);
        } else {
            for (let j = 1; j < (1 + preLine.length) / 2; ++j) {
                line[j] = (preLine[j - 1] | 0) + preLine[j];
            }
            let lineR = line.slice().reverse();
            line = line.concat(lineR);
        }

        triangle.push(line);
    }

    return triangle;

};

const repeat = (n, char) => {
    const ret = [];
    for (let i = 0; i < n; ++i) {
        ret.push(char);
    }
    return ret;
};

export const printPascal = lines => {
    const triangle = pascal(lines);
    const ret = [];

    for (let i = 0; i < triangle.length; ++i) {
        let line = repeat(triangle.length - 1 - i, '');
        for (let j = 0; j < triangle[i].length; ++j) {
            line.push(triangle[i][j]);
            if (j !== triangle[i].length - 1) {
                line.push('');
            }
        }
        ret.push(line);
    }
    return ret;
};<|endoftext|>


<commit_before><commit_msg>Env vars output<commit_after>console.log(process.env);
<|endoftext|>


<commit_before><commit_msg>/ ‘src/index.js’<commit_after>console.log('wholl')
<|endoftext|>