<commit_before>// Copyright (c) 2015 Uber Technologies, Inc.

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

var async = require('async');
var metrics = require("metrics");
var parseArgs = require('minimist');

var TChannel = require("../channel");
var base2 = require('../test/lib/base2');
var LCGStream = require('../test/lib/rng_stream');

// TODO: disentangle the global closure of numClients and numRequestss and move
// these after the harness class declaration
var argv = parseArgs(process.argv.slice(2), {
    alias: {
        m: 'multiplicity',
        c: 'numClients',
        r: 'numRequests',
        p: 'pipeline',
        s: 'sizes'
    },
    default: {
        multiplicity: 2,
        numClients: 5,
        numRequests: 20000,
        pipeline: '10,100,1000',
        sizes: '4,4096'
    }
});
var multiplicity = parseInt(argv.multiplicity, 10);
var numClients = parseInt(argv.numClients, 10);
var numRequests = parseInt(argv.numRequests, 10);
argv.pipeline = parseIntList(argv.pipeline);
argv.sizes = parseIntList(argv.sizes);

// -- test harness

function Test(args) {
    this.args = args;

    this.arg1 = new Buffer(args.command);
    this.arg2 = args.arg2 || null;
    this.arg3 = args.arg3 || null;

    this.callback = null;
    this.clients = [];
    this.clientsReady = 0;
    this.commandsSent = 0;
    this.commandsCompleted = 0;
    this.maxPipeline = this.args.pipeline || numRequests;
    this.clientOptions = args.clientOptions || {
        returnBuffers: false
    };

    this.connectLatency = new metrics.Histogram();
    this.readyLatency = new metrics.Histogram();
    this.commandLatency = new metrics.Histogram();
}

Test.prototype.copy = function () {
    return new Test(this.args);
};

Test.prototype.run = function (callback) {
    var self = this;
    var i;

    this.callback = callback;

    var ids = [];
    for (i = 0; i < numClients ; i++) ids.push(i);
    async.each(ids, function each(i, done) {
        self.newClient(i, done);
    }, function(err) {
        if (err) {
            console.error('failed to setup clients', err);
        } else {
            self.start();
        }
    });
};

Test.prototype.newClient = function (id, callback) {
    var self = this;
    var port = 4041 + id;
    var newClient = new TChannel();
    newClient.createTime = Date.now();
    newClient.listen(port, "127.0.0.1", function (err) {
        if (err) return callback(err);
        self.clients[id] = newClient;
        // sending a ping to pre-connect the socket
        newClient
            .request({host: '127.0.0.1:4040'})
            .send('ping', null, null, function(err) {
                if (err) return callback(err);
                self.connectLatency.update(Date.now() - newClient.createTime);
                self.readyLatency.update(Date.now() - newClient.createTime);
                callback();
            });
    });
};

Test.prototype.start = function () {
    this.testStart = Date.now();
    this.fillPipeline();
};

Test.prototype.fillPipeline = function () {
    var pipeline = this.commandsSent - this.commandsCompleted;

    while (this.commandsSent < numRequests && pipeline < this.maxPipeline) {
        this.commandsSent++;
        pipeline++;
        this.sendNext();
    }

    if (this.commandsCompleted === numRequests) {
        this.printStats();
        this.stopClients();
    }
};

Test.prototype.stopClients = function () {
    var self = this;

    this.clients.forEach(function (client, pos) {
        if (pos === self.clients.length - 1) {
            client.quit(function () {
                self.callback();
            });
        } else {
            client.quit();
        }
    });
};

Test.prototype.sendNext = function () {
    var self = this;
    var curClient = this.commandsSent % this.clients.length;
    var start = Date.now();

    this.clients[curClient]
        .request({
            host: '127.0.0.1:4040',
            timeout: 10000,
            service: 'benchmark',
            headers: {
                benchHeader1: 'bench value one',
                benchHeader2: 'bench value two',
                benchHeader3: 'bench value three'
            }
        })
        .send(this.arg1, this.arg2, this.arg3, done);

    function done(err) {
        if (err) {
            throw err;
        }
        self.commandsCompleted++;
        self.commandLatency.update(Date.now() - start);
        self.fillPipeline();
    }
};

Test.prototype.getStats = function () {
    var obj = this.commandLatency.printObj();
    obj.descr = this.args.descr;
    obj.pipeline = this.args.pipeline;
    obj.numClients = this.clientsReady;
    obj.elapsed = Date.now() - this.testStart;
    obj.rate = numRequests / (obj.elapsed / 1000);
    return obj;
};

Test.prototype.printStats = function () {
    var obj = this.getStats();
    process.stdout.write(JSON.stringify(obj) + "\n");
};

// -- define tests

var tests = [];

argv.pipeline.forEach(function each(pipeline) {
    tests.push(new Test({descr: "PING", command: "ping", args: null, pipeline: pipeline}));
});

var randBytes = new LCGStream({
    seed: 1234,
    limit: Infinity
});

argv.sizes.forEach(function each(size) {
    var sizeDesc = base2.pretty(size, 'B');
    var key = 'foo_rand000000000000';
    var buf = randBytes.read(Math.ceil(size / 4 * 3)); // 4 base64 encoded bytes per 3 raw bytes
    if (!buf) {
        throw new Error("can't have size " + sizeDesc);
    }
    var str = buf.toString('base64').slice(0, size); // chop off any "==" trailer
    argv.pipeline.forEach(function each(pipeline) {
        tests.push(new Test({
            descr: "SET " + sizeDesc,
            command: "set",
            arg2: key,
            arg3: str,
            pipeline: pipeline
        }));
        tests.push(new Test({
            descr: "GET " + sizeDesc,
            command: "get",
            arg2: key,
            pipeline: pipeline
        }));
    });
});

function next(i, j, done) {
    if (i >= tests.length) return done();
    if (j >= multiplicity) return next(i+1, 0, done);
    var test = tests[i].copy();
    test.run(function () {
        next(i, j+1, done);
    });
}

next(0, 0, function() {
    process.exit(0);
});

function parseIntList(str) {
    if (typeof str === 'number') {
        return [str];
    }
    return str
        .split(/\s*,\s*/)
        .map(function each(part) {
            return parseInt(part, 10);
        });
}
<commit_msg>Add back full saturated pipeline to default bench<commit_after>// Copyright (c) 2015 Uber Technologies, Inc.

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.

var async = require('async');
var metrics = require("metrics");
var parseArgs = require('minimist');

var TChannel = require("../channel");
var base2 = require('../test/lib/base2');
var LCGStream = require('../test/lib/rng_stream');

// TODO: disentangle the global closure of numClients and numRequestss and move
// these after the harness class declaration
var argv = parseArgs(process.argv.slice(2), {
    alias: {
        m: 'multiplicity',
        c: 'numClients',
        r: 'numRequests',
        p: 'pipeline',
        s: 'sizes'
    },
    default: {
        multiplicity: 2,
        numClients: 5,
        numRequests: 20000,
        pipeline: '10,100,1000,20000',
        sizes: '4,4096'
    }
});
var multiplicity = parseInt(argv.multiplicity, 10);
var numClients = parseInt(argv.numClients, 10);
var numRequests = parseInt(argv.numRequests, 10);
argv.pipeline = parseIntList(argv.pipeline);
argv.sizes = parseIntList(argv.sizes);

// -- test harness

function Test(args) {
    this.args = args;

    this.arg1 = new Buffer(args.command);
    this.arg2 = args.arg2 || null;
    this.arg3 = args.arg3 || null;

    this.callback = null;
    this.clients = [];
    this.clientsReady = 0;
    this.commandsSent = 0;
    this.commandsCompleted = 0;
    this.maxPipeline = this.args.pipeline || numRequests;
    this.clientOptions = args.clientOptions || {
        returnBuffers: false
    };

    this.connectLatency = new metrics.Histogram();
    this.readyLatency = new metrics.Histogram();
    this.commandLatency = new metrics.Histogram();
}

Test.prototype.copy = function () {
    return new Test(this.args);
};

Test.prototype.run = function (callback) {
    var self = this;
    var i;

    this.callback = callback;

    var ids = [];
    for (i = 0; i < numClients ; i++) ids.push(i);
    async.each(ids, function each(i, done) {
        self.newClient(i, done);
    }, function(err) {
        if (err) {
            console.error('failed to setup clients', err);
        } else {
            self.start();
        }
    });
};

Test.prototype.newClient = function (id, callback) {
    var self = this;
    var port = 4041 + id;
    var newClient = new TChannel();
    newClient.createTime = Date.now();
    newClient.listen(port, "127.0.0.1", function (err) {
        if (err) return callback(err);
        self.clients[id] = newClient;
        // sending a ping to pre-connect the socket
        newClient
            .request({host: '127.0.0.1:4040'})
            .send('ping', null, null, function(err) {
                if (err) return callback(err);
                self.connectLatency.update(Date.now() - newClient.createTime);
                self.readyLatency.update(Date.now() - newClient.createTime);
                callback();
            });
    });
};

Test.prototype.start = function () {
    this.testStart = Date.now();
    this.fillPipeline();
};

Test.prototype.fillPipeline = function () {
    var pipeline = this.commandsSent - this.commandsCompleted;

    while (this.commandsSent < numRequests && pipeline < this.maxPipeline) {
        this.commandsSent++;
        pipeline++;
        this.sendNext();
    }

    if (this.commandsCompleted === numRequests) {
        this.printStats();
        this.stopClients();
    }
};

Test.prototype.stopClients = function () {
    var self = this;

    this.clients.forEach(function (client, pos) {
        if (pos === self.clients.length - 1) {
            client.quit(function () {
                self.callback();
            });
        } else {
            client.quit();
        }
    });
};

Test.prototype.sendNext = function () {
    var self = this;
    var curClient = this.commandsSent % this.clients.length;
    var start = Date.now();

    this.clients[curClient]
        .request({
            host: '127.0.0.1:4040',
            timeout: 10000,
            service: 'benchmark',
            headers: {
                benchHeader1: 'bench value one',
                benchHeader2: 'bench value two',
                benchHeader3: 'bench value three'
            }
        })
        .send(this.arg1, this.arg2, this.arg3, done);

    function done(err) {
        if (err) {
            throw err;
        }
        self.commandsCompleted++;
        self.commandLatency.update(Date.now() - start);
        self.fillPipeline();
    }
};

Test.prototype.getStats = function () {
    var obj = this.commandLatency.printObj();
    obj.descr = this.args.descr;
    obj.pipeline = this.args.pipeline;
    obj.numClients = this.clientsReady;
    obj.elapsed = Date.now() - this.testStart;
    obj.rate = numRequests / (obj.elapsed / 1000);
    return obj;
};

Test.prototype.printStats = function () {
    var obj = this.getStats();
    process.stdout.write(JSON.stringify(obj) + "\n");
};

// -- define tests

var tests = [];

argv.pipeline.forEach(function each(pipeline) {
    tests.push(new Test({descr: "PING", command: "ping", args: null, pipeline: pipeline}));
});

var randBytes = new LCGStream({
    seed: 1234,
    limit: Infinity
});

argv.sizes.forEach(function each(size) {
    var sizeDesc = base2.pretty(size, 'B');
    var key = 'foo_rand000000000000';
    var buf = randBytes.read(Math.ceil(size / 4 * 3)); // 4 base64 encoded bytes per 3 raw bytes
    if (!buf) {
        throw new Error("can't have size " + sizeDesc);
    }
    var str = buf.toString('base64').slice(0, size); // chop off any "==" trailer
    argv.pipeline.forEach(function each(pipeline) {
        tests.push(new Test({
            descr: "SET " + sizeDesc,
            command: "set",
            arg2: key,
            arg3: str,
            pipeline: pipeline
        }));
        tests.push(new Test({
            descr: "GET " + sizeDesc,
            command: "get",
            arg2: key,
            pipeline: pipeline
        }));
    });
});

function next(i, j, done) {
    if (i >= tests.length) return done();
    if (j >= multiplicity) return next(i+1, 0, done);
    var test = tests[i].copy();
    test.run(function () {
        next(i, j+1, done);
    });
}

next(0, 0, function() {
    process.exit(0);
});

function parseIntList(str) {
    if (typeof str === 'number') {
        return [str];
    }
    return str
        .split(/\s*,\s*/)
        .map(function each(part) {
            return parseInt(part, 10);
        });
}
<|endoftext|>


<commit_before>'use strict';

const EventEmitter = require('events');
const Getopt = require('node-getopt/lib/getopt.js');
const CliError = require('./CliError');

const Options = require('./Options');
const Runner = require('./Runner');

class Cli extends EventEmitter
{
	constructor(argv, stdin, stdout, stderr)
	{
		super();

		this.options = new Options(argv[0]);
		this.argv = argv;
		this.stdin = stdin;
		this.stdout = stdout;
		this.stderr = stderr;

		this.getopt = new Getopt([
			['h', 'help', 'show this help'],
			['I', 'ignore-json-error', 'ignore broken JSON'],
			['v', 'verbose', 'display additional information'],
			['S', 'sort-external-buffer-size=SIZE', 'use SIZE bytes for `sort` memory buffer'],
			['B', 'sort-in-memory-buffer-length=ROWS', 'save up to ROWS rows for in-memory sort'],
			['T', 'temporary-directory=DIR', 'use DIR for temporaries, not $TMPDIR or /tmp'],
			['b', 'bind=BIND=VALUE+', 'bind valiable'],
			['', 'version', 'show version information']
		]);

		this.getopt.setHelp(
			'Usage: jl-sql [OPTIONS] SQL\n'
			+ 'OPTIONS:\n'
			+ '[[OPTIONS]]\n'
			+ '\n'
			+ 'Version: ' + this.versionString() + '\n\n'
			+ 'See full documentation at https://github.com/avz/jl-sql\n'
		);

		this.getopt.error(this.onArgumentError.bind(this));

		this.options = this.parseOptions();
	}

	parseOptions()
	{
		const getopt = this.getopt.parse(this.argv.slice(1));

		if (getopt.options.help) {
			this.throwUsage();
		}

		if (getopt.options.version) {
			this.throwVersion();
		}

		if (!getopt.argv.length) {
			this.throwArgumentError('SQL expected');
		}

		if (getopt.argv.length > 1) {
			this.throwArgumentError('too many arguments');
		}

		const options = new Options(getopt.argv[0]);

		if (getopt.options['ignore-json-error']) {
			options.ignoreJsonErrors = true;
		}

		if (getopt.options.verbose) {
			options.verbose = true;
		}

		if (getopt.options['temporary-directory']) {
			options.tmpDir = getopt.options['temporary-directory'];
		}

		options.sortOptions = {

		};

		if (getopt.options['sort-external-buffer-size']) {
			options.sortOptions.bufferSize = parseInt(getopt.options['sort-external-buffer-size']);
		}

		if (getopt.options['sort-in-memory-buffer-length']) {
			options.sortOptions.inMemoryBufferSize = parseInt(getopt.options['sort-in-memory-buffer-length']);
		} else {
			options.sortOptions.inMemoryBufferSize = 10000;
		}

		if (getopt.options.bind) {
			options.binds = this.parseBinds(getopt.options.bind);
		}

		return options;
	}

	parseBinds(binds)
	{
		const map = {};

		for (const def of binds) {
			const m = def.match(/^(::?)(.*?)=(.*)$/);

			if (!m) {
				this.throwArgumentError('wrong bind definition: ' + def);
			}

			const name = m[2];
			const value = m[3];
			const isArray = m[1] === '::';

			if (isArray) {
				if (name in map) {
					if (!(map[name] instanceof Array)) {
						this.throwArgumentError('bind name ::' + name + ' must not be mixed with :' + name);
					}

					map[name].push(value);
				} else {
					map[name] = [value];
				}
			} else {
				if (name in map) {
					if (map[name] instanceof Array) {
						this.throwArgumentError('bind name ::' + name + ' must not be mixed with :' + name);
					}

					this.throwArgumentError('bind name :' + name + ' redefinition');
				}

				map[name] = value;
			}
		}

		return map;
	}

	run()
	{
		const runner = new Runner(this.options);

		runner.on('error', (err) => {
			this.emit('error', err);
		});

		runner.on('warning', (warn) => {
			this.emit('warning', warn);
		});

		runner.run(this.stdin, this.stdout, this.stderr);
	}

	throwUsage(code = 255)
	{
		this.throwArgumentError(null);
	}

	versionString()
	{
		const myVersion = require('../package').version;
		const apiVersion = require('jl-sql-api').version || 'X.X.X';

		return 'jl-sql v' + myVersion + ' (jl-sql-api v' + apiVersion + ')';
	}

	throwVersion()
	{
		throw new CliError(this.versionString() + '\n', 0);
	}

	getUsage()
	{
		return this.getopt.getHelp();
	}

	throwArgumentError(message = null)
	{
		let m = '';

		if (message !== null) {
			m += 'ERROR: ' + message + '\n\n';
		}

		m += this.getUsage();

		throw new CliError(m, 255);
	}

	throwRuntimeError(message)
	{
		throw new CliError(message, 1);
	}

	onArgumentError(err)
	{
		this.throwArgumentError(err.message);
	}
}

module.exports = Cli;
<commit_msg>Removed extra newline in output of --version and --help<commit_after>'use strict';

const EventEmitter = require('events');
const Getopt = require('node-getopt/lib/getopt.js');
const CliError = require('./CliError');

const Options = require('./Options');
const Runner = require('./Runner');

class Cli extends EventEmitter
{
	constructor(argv, stdin, stdout, stderr)
	{
		super();

		this.options = new Options(argv[0]);
		this.argv = argv;
		this.stdin = stdin;
		this.stdout = stdout;
		this.stderr = stderr;

		this.getopt = new Getopt([
			['h', 'help', 'show this help'],
			['I', 'ignore-json-error', 'ignore broken JSON'],
			['v', 'verbose', 'display additional information'],
			['S', 'sort-external-buffer-size=SIZE', 'use SIZE bytes for `sort` memory buffer'],
			['B', 'sort-in-memory-buffer-length=ROWS', 'save up to ROWS rows for in-memory sort'],
			['T', 'temporary-directory=DIR', 'use DIR for temporaries, not $TMPDIR or /tmp'],
			['b', 'bind=BIND=VALUE+', 'bind valiable'],
			['', 'version', 'show version information']
		]);

		this.getopt.setHelp(
			'Usage: jl-sql [OPTIONS] SQL\n'
			+ 'OPTIONS:\n'
			+ '[[OPTIONS]]\n'
			+ '\n'
			+ 'Version: ' + this.versionString() + '\n\n'
			+ 'See full documentation at https://github.com/avz/jl-sql\n'
		);

		this.getopt.error(this.onArgumentError.bind(this));

		this.options = this.parseOptions();
	}

	parseOptions()
	{
		const getopt = this.getopt.parse(this.argv.slice(1));

		if (getopt.options.help) {
			this.throwUsage();
		}

		if (getopt.options.version) {
			this.throwVersion();
		}

		if (!getopt.argv.length) {
			this.throwArgumentError('SQL expected');
		}

		if (getopt.argv.length > 1) {
			this.throwArgumentError('too many arguments');
		}

		const options = new Options(getopt.argv[0]);

		if (getopt.options['ignore-json-error']) {
			options.ignoreJsonErrors = true;
		}

		if (getopt.options.verbose) {
			options.verbose = true;
		}

		if (getopt.options['temporary-directory']) {
			options.tmpDir = getopt.options['temporary-directory'];
		}

		options.sortOptions = {

		};

		if (getopt.options['sort-external-buffer-size']) {
			options.sortOptions.bufferSize = parseInt(getopt.options['sort-external-buffer-size']);
		}

		if (getopt.options['sort-in-memory-buffer-length']) {
			options.sortOptions.inMemoryBufferSize = parseInt(getopt.options['sort-in-memory-buffer-length']);
		} else {
			options.sortOptions.inMemoryBufferSize = 10000;
		}

		if (getopt.options.bind) {
			options.binds = this.parseBinds(getopt.options.bind);
		}

		return options;
	}

	parseBinds(binds)
	{
		const map = {};

		for (const def of binds) {
			const m = def.match(/^(::?)(.*?)=(.*)$/);

			if (!m) {
				this.throwArgumentError('wrong bind definition: ' + def);
			}

			const name = m[2];
			const value = m[3];
			const isArray = m[1] === '::';

			if (isArray) {
				if (name in map) {
					if (!(map[name] instanceof Array)) {
						this.throwArgumentError('bind name ::' + name + ' must not be mixed with :' + name);
					}

					map[name].push(value);
				} else {
					map[name] = [value];
				}
			} else {
				if (name in map) {
					if (map[name] instanceof Array) {
						this.throwArgumentError('bind name ::' + name + ' must not be mixed with :' + name);
					}

					this.throwArgumentError('bind name :' + name + ' redefinition');
				}

				map[name] = value;
			}
		}

		return map;
	}

	run()
	{
		const runner = new Runner(this.options);

		runner.on('error', (err) => {
			this.emit('error', err);
		});

		runner.on('warning', (warn) => {
			this.emit('warning', warn);
		});

		runner.run(this.stdin, this.stdout, this.stderr);
	}

	throwUsage(code = 255)
	{
		this.throwArgumentError(null);
	}

	versionString()
	{
		const myVersion = require('../package').version;
		const apiVersion = require('jl-sql-api').version || 'X.X.X';

		return 'jl-sql v' + myVersion + ' (jl-sql-api v' + apiVersion + ')';
	}

	throwVersion()
	{
		throw new CliError(this.versionString(), 0);
	}

	getUsage()
	{
		return this.getopt.getHelp().replace(/\s+$/, '');
	}

	throwArgumentError(message = null)
	{
		let m = '';

		if (message !== null) {
			m += 'ERROR: ' + message + '\n\n';
		}

		m += this.getUsage();

		throw new CliError(m, 255);
	}

	throwRuntimeError(message)
	{
		throw new CliError(message, 1);
	}

	onArgumentError(err)
	{
		this.throwArgumentError(err.message);
	}
}

module.exports = Cli;
<|endoftext|>


<commit_before>var async  = require('async')
  , fs    = require('fs')
  , debug = false // disabled access control
  , server
  , db;

var endpoints = {};

exports.init = function (_server, _cb)
{
  server = _server;
  db = server.db;

  fs.readdir('./src/api', function (err, files)
  {
    if(err)
    {
      console.error("Could not load api: " + err);
      cb();
      return;
    }

    console.debug("Found " + files.length + " apiendpoints!");
    async.eachSeries(files,
      function (file, cb)
      {
        var endpoint = require('./api/' + file);

        console.debug("Initiating endpoint: " + endpoint.name + "...");
        endpoints[endpoint.name] = endpoint;
        endpoints[endpoint.name].init(db, server, cb);
      }, _cb);
  });
}

exports.handleRequest = function (req, res)
{
  var method = req.method
    , params = req.params
    , query  = req.query;

  var user = res.locals.user;

  console.log("[API] REQUEST " + method + " " + req.url);

  if(!debug && (!user || !user.hasRole("admin")))
  {
    answerRequest(res, 401, "Unauthorized", null);
    return;
  }

  var endpoint = endpoints[params.endpoint];

  if(!endpoint)
  {
    answerRequest(res, 400, "Endpoint does not exist.", null);
    return;
  }

  if(method == "GET")
  {
    var isMany = !params.entity;

    if(isMany)
      endpoint.getMany(res, params, query, answerRequest);
    else
      endpoint.getOne(res, params, query, answerRequest);
  }
  else if(method == "POST")
  {
    if(query.datatables)
      endpoint.setOneDT(req.body, res, params, query, answerRequest);
    else
      endpoint.createOne(req.body, res, params, query, answerRequest);
  }
}

function answerRequest(res, statusCode, msg, data)
{
  console.log("[API] RESPONSE " + statusCode + ": " + msg);

  var response =
    {
      status: statusCode,
      message: msg,
      data: data
    };

  res.statusCode = statusCode;
  res.end(JSON.stringify(response));
}
<commit_msg>Explicitly log API-Requets into the info-channel<commit_after>var async  = require('async')
  , fs    = require('fs')
  , debug = false // disabled access control
  , server
  , db;

var endpoints = {};

exports.init = function (_server, _cb)
{
  server = _server;
  db = server.db;

  fs.readdir('./src/api', function (err, files)
  {
    if(err)
    {
      console.error("Could not load api: " + err);
      cb();
      return;
    }

    console.debug("Found " + files.length + " apiendpoints!");
    async.eachSeries(files,
      function (file, cb)
      {
        var endpoint = require('./api/' + file);

        console.debug("Initiating endpoint: " + endpoint.name + "...");
        endpoints[endpoint.name] = endpoint;
        endpoints[endpoint.name].init(db, server, cb);
      }, _cb);
  });
}

exports.handleRequest = function (req, res)
{
  var method = req.method
    , params = req.params
    , query  = req.query;

  var user = res.locals.user;

  console.info("[API] REQUEST " + method + " " + req.url);

  if(!debug && (!user || !user.hasRole("admin")))
  {
    answerRequest(res, 401, "Unauthorized", null);
    return;
  }

  var endpoint = endpoints[params.endpoint];

  if(!endpoint)
  {
    answerRequest(res, 400, "Endpoint does not exist.", null);
    return;
  }

  if(method == "GET")
  {
    var isMany = !params.entity;

    if(isMany)
      endpoint.getMany(res, params, query, answerRequest);
    else
      endpoint.getOne(res, params, query, answerRequest);
  }
  else if(method == "POST")
  {
    if(query.datatables)
      endpoint.setOneDT(req.body, res, params, query, answerRequest);
    else
      endpoint.createOne(req.body, res, params, query, answerRequest);
  }
}

function answerRequest(res, statusCode, msg, data)
{
  console.info("[API] RESPONSE " + statusCode + ": " + msg);

  var response =
    {
      status: statusCode,
      message: msg,
      data: data
    };

  res.statusCode = statusCode;
  res.end(JSON.stringify(response));
}
<|endoftext|>


<commit_before>'use strict';

const _ = require('lodash');
const AbstractConnectionManager = require('../abstract/connection-manager');
const Utils = require('../../utils');
const debug = Utils.getLogger().debugContext('connection:pg');
const Promise = require('../../promise');
const sequelizeErrors = require('../../errors');
const semver = require('semver');
const dataTypes = require('../../data-types');
const moment = require('moment-timezone');

class ConnectionManager extends AbstractConnectionManager {
  constructor(dialect, sequelize) {
    super(dialect, sequelize);

    this.sequelize = sequelize;
    this.sequelize.config.port = this.sequelize.config.port || 5432;
    try {
      let pgLib;
      if (sequelize.config.dialectModulePath) {
        pgLib = require(sequelize.config.dialectModulePath);
      } else {
        pgLib = require('pg');
      }
      this.lib = sequelize.config.native ? pgLib.native : pgLib;
    } catch (err) {
      if (err.code === 'MODULE_NOT_FOUND') {
        throw new Error('Please install \'' + (sequelize.config.dialectModulePath || 'pg') + '\' module manually');
      }
      throw err;
    }

    this.refreshTypeParser(dataTypes.postgres);
  }

  // Expose this as a method so that the parsing may be updated when the user has added additional, custom types
  _refreshTypeParser(dataType) {
    if (dataType.types.postgres.oids) {
      for (const oid of dataType.types.postgres.oids) {
        this.lib.types.setTypeParser(oid, value => dataType.parse(value, oid, this.lib.types.getTypeParser));
      }
    }

    if (dataType.types.postgres.array_oids) {
      for (const oid of dataType.types.postgres.array_oids) {
        this.lib.types.setTypeParser(oid, value =>
          this.lib.types.arrayParser.create(value, v =>
            dataType.parse(v, oid, this.lib.types.getTypeParser)
          ).parse()
        );
      }
    }
  }

  connect(config) {
    config.user = config.username;
    const connectionConfig = _.pick(config, [
      'user', 'password', 'host', 'database', 'port'
    ]);

    if (config.dialectOptions) {
      _.merge(connectionConfig,
        _.pick(config.dialectOptions, [
        // see [http://www.postgresql.org/docs/9.3/static/runtime-config-logging.html#GUC-APPLICATION-NAME]
          'application_name',
          // choose the SSL mode with the PGSSLMODE environment variable
          // object format: [https://github.com/brianc/node-postgres/blob/master/lib/connection.js#L79]
          // see also [http://www.postgresql.org/docs/9.3/static/libpq-ssl.html]
          'ssl',
          // In addition to the values accepted by the corresponding server,
          // you can use "auto" to determine the right encoding from the
          // current locale in the client (LC_CTYPE environment variable on Unix systems)
          'client_encoding',
          // !! DONT SET THIS TO TRUE !!
          // (unless you know what you're doing)
          // see [http://www.postgresql.org/message-id/flat/bc9549a50706040852u27633f41ib1e6b09f8339d845@mail.gmail.com#bc9549a50706040852u27633f41ib1e6b09f8339d845@mail.gmail.com]
          'binary',
          // This should help with backends incorrectly considering idle clients to be dead and prematurely disconnecting them.
          // this feature has been added in pg module v6.0.0, check pg/CHANGELOG.md
          'keepAlive',
          // Times out queries after a set time in milliseconds. Added in pg v7.3
          'statement_timeout'
        ]));
    }

    return new Promise((resolve, reject) => {
      const connection = new this.lib.Client(connectionConfig);
      let responded = false;

      connection.connect(err => {
        if (err) {
          if (err.code) {
            switch (err.code) {
              case 'ECONNREFUSED':
                reject(new sequelizeErrors.ConnectionRefusedError(err));
                break;
              case 'ENOTFOUND':
                reject(new sequelizeErrors.HostNotFoundError(err));
                break;
              case 'EHOSTUNREACH':
                reject(new sequelizeErrors.HostNotReachableError(err));
                break;
              case 'EINVAL':
                reject(new sequelizeErrors.InvalidConnectionError(err));
                break;
              default:
                reject(new sequelizeErrors.ConnectionError(err));
                break;
            }
          } else {
            reject(new sequelizeErrors.ConnectionError(err));
          }
          return;
        }
        responded = true;
        debug('connection acquired');
        resolve(connection);
      });

      // If we didn't ever hear from the client.connect() callback the connection timeout, node-postgres does not treat this as an error since no active query was ever emitted
      connection.on('end', () => {
        debug('connection timeout');
        if (!responded) {
          reject(new sequelizeErrors.ConnectionTimedOutError(new Error('Connection timed out')));
        }
      });

      // Don't let a Postgres restart (or error) to take down the whole app
      connection.on('error', err => {
        debug(`connection error ${err.code}`);
        connection._invalid = true;
      });
    }).tap(connection => {
      // Disable escape characters in strings, see https://github.com/sequelize/sequelize/issues/3545
      let query = '';

      if (this.sequelize.options.databaseVersion !== 0 && semver.gte(this.sequelize.options.databaseVersion, '8.2.0')) {
        query += 'SET standard_conforming_strings=on;';
      }

      if (!this.sequelize.config.keepDefaultTimezone) {
        const isZone = !!moment.tz.zone(this.sequelize.options.timezone);
        if (isZone) {
          query += 'SET client_min_messages TO warning; SET TIME ZONE \'' + this.sequelize.options.timezone + '\';';
        } else {
          query += 'SET client_min_messages TO warning; SET TIME ZONE INTERVAL \'' + this.sequelize.options.timezone + '\' HOUR TO MINUTE;';
        }
      }

      //Setting parameter for forcing error messages languages in English as Sequelize treats them in English
      query += "SET lc_messages TO 'en_US.UTF-8';";

      if (query) {
        return connection.query(query);
      }
    }).tap(connection => {
      if (
        dataTypes.GEOGRAPHY.types.postgres.oids.length === 0 &&
        dataTypes.GEOMETRY.types.postgres.oids.length === 0 &&
        dataTypes.HSTORE.types.postgres.oids.length === 0 &&
        dataTypes.ENUM.types.postgres.oids.length === 0
      ) {
        return this._refreshDynamicOIDs(connection);
      }
    });
  }

  disconnect(connection) {
    return new Promise(resolve => {
      connection.end();
      resolve();
    });
  }

  validate(connection) {
    return connection._invalid === undefined;
  }

  _refreshDynamicOIDs(connection) {
    const databaseVersion = this.sequelize.options.databaseVersion;
    const supportedVersion = '8.3.0';

    // Check for supported version
    if ( (databaseVersion && semver.gte(databaseVersion, supportedVersion)) === false) {
      return Promise.resolve();
    }

    // Refresh dynamic OIDs for some types
    // These include, Geometry / HStore / Enum
    return (connection || this.sequelize).query(
      "SELECT typname, typtype, oid, typarray FROM pg_type WHERE (typtype = 'b' AND typname IN ('hstore', 'geometry', 'geography')) OR (typtype = 'e')"
    ).then(results => {
      const result = Array.isArray(results) ? results.pop() : results;

      // Reset OID mapping for dynamic type
      [
        dataTypes.postgres.GEOMETRY,
        dataTypes.postgres.HSTORE,
        dataTypes.postgres.GEOGRAPHY,
        dataTypes.postgres.ENUM
      ].forEach(type => {
        type.types.postgres.oids = [];
        type.types.postgres.array_oids = [];
      });

      for (const row of result.rows) {
        let type;

        if (row.typname === 'geometry') {
          type = dataTypes.postgres.GEOMETRY;
        } else if (row.typname === 'hstore') {
          type = dataTypes.postgres.HSTORE;
        } else if (row.typname === 'geography') {
          type = dataTypes.postgres.GEOGRAPHY;
        } else if (row.typtype === 'e') {
          type = dataTypes.postgres.ENUM;
        }

        type.types.postgres.oids.push(row.oid);
        type.types.postgres.array_oids.push(row.typarray);

        this._refreshTypeParser(type);
      }
    });
  }
}

_.extend(ConnectionManager.prototype, AbstractConnectionManager.prototype);

module.exports = ConnectionManager;
module.exports.ConnectionManager = ConnectionManager;
module.exports.default = ConnectionManager;
<commit_msg>feat(connection-manager): we can set to parse BIGINT into number instead of strings.<commit_after>'use strict';

const _ = require('lodash');
const AbstractConnectionManager = require('../abstract/connection-manager');
const Utils = require('../../utils');
const debug = Utils.getLogger().debugContext('connection:pg');
const Promise = require('../../promise');
const sequelizeErrors = require('../../errors');
const semver = require('semver');
const dataTypes = require('../../data-types');
const moment = require('moment-timezone');

class ConnectionManager extends AbstractConnectionManager {
  constructor(dialect, sequelize) {
    super(dialect, sequelize);

    this.sequelize = sequelize;
    this.sequelize.config.port = this.sequelize.config.port || 5432;
    try {
      let pgLib;
      if (sequelize.config.dialectModulePath) {
        pgLib = require(sequelize.config.dialectModulePath);
      } else {
        pgLib = require('pg');
      }
      //We can set to parse BIGINT into number instead of getting strings
      pgLib.defaults.parseInt8 = sequelize.options.parseInt8 || false;
      this.lib = sequelize.config.native ? pgLib.native : pgLib;
    } catch (err) {
      if (err.code === 'MODULE_NOT_FOUND') {
        throw new Error('Please install \'' + (sequelize.config.dialectModulePath || 'pg') + '\' module manually');
      }
      throw err;
    }

    this.refreshTypeParser(dataTypes.postgres);
  }

  // Expose this as a method so that the parsing may be updated when the user has added additional, custom types
  _refreshTypeParser(dataType) {
    if (dataType.types.postgres.oids) {
      for (const oid of dataType.types.postgres.oids) {
        this.lib.types.setTypeParser(oid, value => dataType.parse(value, oid, this.lib.types.getTypeParser));
      }
    }

    if (dataType.types.postgres.array_oids) {
      for (const oid of dataType.types.postgres.array_oids) {
        this.lib.types.setTypeParser(oid, value =>
          this.lib.types.arrayParser.create(value, v =>
            dataType.parse(v, oid, this.lib.types.getTypeParser)
          ).parse()
        );
      }
    }
  }

  connect(config) {
    config.user = config.username;
    const connectionConfig = _.pick(config, [
      'user', 'password', 'host', 'database', 'port'
    ]);

    if (config.dialectOptions) {
      _.merge(connectionConfig,
        _.pick(config.dialectOptions, [
        // see [http://www.postgresql.org/docs/9.3/static/runtime-config-logging.html#GUC-APPLICATION-NAME]
          'application_name',
          // choose the SSL mode with the PGSSLMODE environment variable
          // object format: [https://github.com/brianc/node-postgres/blob/master/lib/connection.js#L79]
          // see also [http://www.postgresql.org/docs/9.3/static/libpq-ssl.html]
          'ssl',
          // In addition to the values accepted by the corresponding server,
          // you can use "auto" to determine the right encoding from the
          // current locale in the client (LC_CTYPE environment variable on Unix systems)
          'client_encoding',
          // !! DONT SET THIS TO TRUE !!
          // (unless you know what you're doing)
          // see [http://www.postgresql.org/message-id/flat/bc9549a50706040852u27633f41ib1e6b09f8339d845@mail.gmail.com#bc9549a50706040852u27633f41ib1e6b09f8339d845@mail.gmail.com]
          'binary',
          // This should help with backends incorrectly considering idle clients to be dead and prematurely disconnecting them.
          // this feature has been added in pg module v6.0.0, check pg/CHANGELOG.md
          'keepAlive',
          // Times out queries after a set time in milliseconds. Added in pg v7.3
          'statement_timeout'
        ]));
    }

    return new Promise((resolve, reject) => {
      const connection = new this.lib.Client(connectionConfig);
      let responded = false;

      connection.connect(err => {
        if (err) {
          if (err.code) {
            switch (err.code) {
              case 'ECONNREFUSED':
                reject(new sequelizeErrors.ConnectionRefusedError(err));
                break;
              case 'ENOTFOUND':
                reject(new sequelizeErrors.HostNotFoundError(err));
                break;
              case 'EHOSTUNREACH':
                reject(new sequelizeErrors.HostNotReachableError(err));
                break;
              case 'EINVAL':
                reject(new sequelizeErrors.InvalidConnectionError(err));
                break;
              default:
                reject(new sequelizeErrors.ConnectionError(err));
                break;
            }
          } else {
            reject(new sequelizeErrors.ConnectionError(err));
          }
          return;
        }
        responded = true;
        debug('connection acquired');
        resolve(connection);
      });

      // If we didn't ever hear from the client.connect() callback the connection timeout, node-postgres does not treat this as an error since no active query was ever emitted
      connection.on('end', () => {
        debug('connection timeout');
        if (!responded) {
          reject(new sequelizeErrors.ConnectionTimedOutError(new Error('Connection timed out')));
        }
      });

      // Don't let a Postgres restart (or error) to take down the whole app
      connection.on('error', err => {
        debug(`connection error ${err.code}`);
        connection._invalid = true;
      });
    }).tap(connection => {
      // Disable escape characters in strings, see https://github.com/sequelize/sequelize/issues/3545
      let query = '';

      if (this.sequelize.options.databaseVersion !== 0 && semver.gte(this.sequelize.options.databaseVersion, '8.2.0')) {
        query += 'SET standard_conforming_strings=on;';
      }

      if (!this.sequelize.config.keepDefaultTimezone) {
        const isZone = !!moment.tz.zone(this.sequelize.options.timezone);
        if (isZone) {
          query += 'SET client_min_messages TO warning; SET TIME ZONE \'' + this.sequelize.options.timezone + '\';';
        } else {
          query += 'SET client_min_messages TO warning; SET TIME ZONE INTERVAL \'' + this.sequelize.options.timezone + '\' HOUR TO MINUTE;';
        }
      }

      //Setting parameter for forcing error messages languages in English as Sequelize treats them in English
      query += "SET lc_messages TO 'en_US.UTF-8';";

      if (query) {
        return connection.query(query);
      }
    }).tap(connection => {
      if (
        dataTypes.GEOGRAPHY.types.postgres.oids.length === 0 &&
        dataTypes.GEOMETRY.types.postgres.oids.length === 0 &&
        dataTypes.HSTORE.types.postgres.oids.length === 0 &&
        dataTypes.ENUM.types.postgres.oids.length === 0
      ) {
        return this._refreshDynamicOIDs(connection);
      }
    });
  }

  disconnect(connection) {
    return new Promise(resolve => {
      connection.end();
      resolve();
    });
  }

  validate(connection) {
    return connection._invalid === undefined;
  }

  _refreshDynamicOIDs(connection) {
    const databaseVersion = this.sequelize.options.databaseVersion;
    const supportedVersion = '8.3.0';

    // Check for supported version
    if ( (databaseVersion && semver.gte(databaseVersion, supportedVersion)) === false) {
      return Promise.resolve();
    }

    // Refresh dynamic OIDs for some types
    // These include, Geometry / HStore / Enum
    return (connection || this.sequelize).query(
      "SELECT typname, typtype, oid, typarray FROM pg_type WHERE (typtype = 'b' AND typname IN ('hstore', 'geometry', 'geography')) OR (typtype = 'e')"
    ).then(results => {
      const result = Array.isArray(results) ? results.pop() : results;

      // Reset OID mapping for dynamic type
      [
        dataTypes.postgres.GEOMETRY,
        dataTypes.postgres.HSTORE,
        dataTypes.postgres.GEOGRAPHY,
        dataTypes.postgres.ENUM
      ].forEach(type => {
        type.types.postgres.oids = [];
        type.types.postgres.array_oids = [];
      });

      for (const row of result.rows) {
        let type;

        if (row.typname === 'geometry') {
          type = dataTypes.postgres.GEOMETRY;
        } else if (row.typname === 'hstore') {
          type = dataTypes.postgres.HSTORE;
        } else if (row.typname === 'geography') {
          type = dataTypes.postgres.GEOGRAPHY;
        } else if (row.typtype === 'e') {
          type = dataTypes.postgres.ENUM;
        }

        type.types.postgres.oids.push(row.oid);
        type.types.postgres.array_oids.push(row.typarray);

        this._refreshTypeParser(type);
      }
    });
  }
}

_.extend(ConnectionManager.prototype, AbstractConnectionManager.prototype);

module.exports = ConnectionManager;
module.exports.ConnectionManager = ConnectionManager;
module.exports.default = ConnectionManager;
<|endoftext|>


<commit_before>// Schema for Projects collection
ProjectsSchema = new SimpleSchema({
  "name": {
    type: String,
    label: "Project Name"
  },
  "description": {
    type: String,
    label: "Project Description (maximum 500 characters)",
    max: 500
  },
  "shortDescription": {
    type: String,
    label: "Project Short (maximum 140 characters)",
    max: 140
  },

  "problemCategories": {
  type: [String],
  label: "Problem Categories",
  allowedValues: ['social', 'bureaucracy', 'housing', 'education',
                  'language', 'employment', 'coordination'],
  autoform: {
    options: [
      {label: "Social", value: "social"},
      {label: "Bureaucracy", value: "bureaucracy"},
      {label: "Housing", value: "housing"},
      {label: "Education", value: "education"},
      {label: "Language", value: "language"},
      {label: "Employment", value: "employment"},
      {label: "Coordination", value: "coordination"}
    ]
  }
},

  // TODO: auto-associate user ID that created project
  // "contactPersonId": {
  //   type: String,
  //   label: "Contact Person ID",
  //   regEx: SimpleSchema.RegEx.Id,
  //   optional: true
  // },
  // TODO: Add 'Problems' feature
  // "problemDescription": {
  //   type: String,
  //   label: "Problem Description"
  // },
  // "problemCategories": {
  //   type: [String],
  //   label: "Problem Categories"
  // },

  "tags": {
    type: [String],
    label: "Tags"
  },

  "currentStage": {
     type: String,
     allowedValues: [
        'initiation',
        'planning',
        'implementationExecution',
        'operationMonitoring',
        'closing'
     ],
     optional: true,
     label: "Select current project stage",
     autoform: {
        options: [
           {label: "Initiation", value: "initiation"},
           {label: "Planning", value: "planning"},
           {label: "Implementation / Execution", value: "implementationExecution"},
           {label: "Operation / Monitoring", value: "operationMonitoring"},
           {label: "Closing", value: "closing"}
       ]
     }
   },

  // TODO: add Teams feature
  // "teamIds": {
  //   type: [String],
  //   label: "Team IDs",
  //   regEx: SimpleSchema.RegEx.Id,
  //   optional: true
  // },
  // "teamDescription": {
  //   type: String,
  //   label: "Team Description"
  // },
  // "currentStage": {
  //   type: String,
  //   label: "Current Stage"
  // },
  // "startupDate": {
  //   type: Date,
  //   label: "Startup Date"
  // },
  // TODO: Add "Target Groups" feature
  // "targetGroups": {
  //   type: [String],
  //   label: "Target Groups"
  // },
  // "targetLocations": {
  //   type: [String],
  //   label: "Target Locations"
  // },
  "targetPlatforms": {
    type: [String],
    label: "Target Platforms",
    allowedValues: ['web', 'ios', 'android', 'windows-phone'],
    autoform: {
      options: [
        {label: "Web", value: "web"},
        {label: "iOS", value: "ios"},
        {label: "Android", value: "android"},
        {label: "Windows Phone", value: "windows-phone"}
      ]
    }
  },
  "postalAddress": {
    type: Object,
    label: "Postal Address"
  },
 "postalAddress.city":{
    type:String,
    label:"City"
 },
  "postalAddress.country":{
    type:String,
    label:"Country"
  },

  "links": {
     type: [Object],
     label: "Links"
  },
  "links.$.name":{
    type: String,
    label: "Name"
  },
  "links.$.uri":{
    type: String,
    label: "URI",
    regex: SimpleSchema.Regex.Url
  },
  // TODO: Add 'Requests' feature
  // "requestIds": {
  //   type: [String],
  //   label: "Request IDs",
  //   regEx: SimpleSchema.RegEx.Id,
  //   optional: true
  // }
  "dateListed": {
    type: Date,
    label: "Date Listed",
    autoValue: function () {
      if (this.isInsert) {
        return new Date();
      } else if (this.isUpsert) {
        return {$setOnInsert: new Date()};
      } else {
        this.unset();  // Prevent user from supplying their own value
      }
    }
  },
});

Projects.attachSchema(ProjectsSchema);
<commit_msg>Added socialMedia to projectschema. Includes twitter, facebook, linkedin, instagram and google+ at the moment<commit_after>// Schema for Projects collection
ProjectsSchema = new SimpleSchema({
  "name": {
    type: String,
    label: "Project Name"
  },
  "description": {
    type: String,
    label: "Project Description (maximum 500 characters)",
    max: 500
  },
  "shortDescription": {
    type: String,
    label: "Project Short (maximum 140 characters)",
    max: 140
  },

  "problemCategories": {
  type: [String],
  label: "Problem Categories",
  allowedValues: ['social', 'bureaucracy', 'housing', 'education',
                  'language', 'employment', 'coordination'],
  autoform: {
    options: [
      {label: "Social", value: "social"},
      {label: "Bureaucracy", value: "bureaucracy"},
      {label: "Housing", value: "housing"},
      {label: "Education", value: "education"},
      {label: "Language", value: "language"},
      {label: "Employment", value: "employment"},
      {label: "Coordination", value: "coordination"}
    ]
  }
},

  // TODO: auto-associate user ID that created project
  // "contactPersonId": {
  //   type: String,
  //   label: "Contact Person ID",
  //   regEx: SimpleSchema.RegEx.Id,
  //   optional: true
  // },
  // TODO: Add 'Problems' feature
  // "problemDescription": {
  //   type: String,
  //   label: "Problem Description"
  // },
  // "problemCategories": {
  //   type: [String],
  //   label: "Problem Categories"
  // },

  "tags": {
    type: [String],
    label: "Tags"
  },

  "currentStage": {
     type: String,
     allowedValues: [
        'initiation',
        'planning',
        'implementationExecution',
        'operationMonitoring',
        'closing'
     ],
     optional: true,
     label: "Select current project stage",
     autoform: {
        options: [
           {label: "Initiation", value: "initiation"},
           {label: "Planning", value: "planning"},
           {label: "Implementation / Execution", value: "implementationExecution"},
           {label: "Operation / Monitoring", value: "operationMonitoring"},
           {label: "Closing", value: "closing"}
       ]
     }
   },

  // TODO: add Teams feature
  // "teamIds": {
  //   type: [String],
  //   label: "Team IDs",
  //   regEx: SimpleSchema.RegEx.Id,
  //   optional: true
  // },
  // "teamDescription": {
  //   type: String,
  //   label: "Team Description"
  // },
  // "currentStage": {
  //   type: String,
  //   label: "Current Stage"
  // },
  // "startupDate": {
  //   type: Date,
  //   label: "Startup Date"
  // },
  // TODO: Add "Target Groups" feature
  // "targetGroups": {
  //   type: [String],
  //   label: "Target Groups"
  // },
  // "targetLocations": {
  //   type: [String],
  //   label: "Target Locations"
  // },
  "targetPlatforms": {
    type: [String],
    label: "Target Platforms",
    allowedValues: ['web', 'ios', 'android', 'windows-phone'],
    autoform: {
      options: [
        {label: "Web", value: "web"},
        {label: "iOS", value: "ios"},
        {label: "Android", value: "android"},
        {label: "Windows Phone", value: "windows-phone"}
      ]
    }
  },
  "postalAddress": {
    type: Object,
    label: "Postal Address"
  },
 "postalAddress.city":{
    type:String,
    label:"City"
 },
  "postalAddress.country":{
    type:String,
    label:"Country"
  },

  "links": {
     type: [Object],
     label: "Links"
  },
  "links.$.name":{
    type: String,
    label: "Name"
  },
  "links.$.uri":{
    type: String,
    label: "URI",
    regex: SimpleSchema.Regex.Url
  },
  "socialMedia": {
    type:Object,
    label: "Social Media"
  },
  "socialMedia.facebook": {
    type:String,
    label: "Facebook",
    regex: SimpleSchema.Regex.Url
  },
  "socialMedia.linkedin": {
    type:String,
    label: "Linkedin",
    regex: SimpleSchema.Regex.Url
  },
  "socialMedia.twitter": {
    type:String,
    label: "Twitter",
    regex: SimpleSchema.Regex.Url
  },
  "socialMedia.instagram": {
    type:String,
    label: "Instagram",
    regex: SimpleSchema.Regex.Url
  },
  "socialMedia.googleplus": {
    type:String,
    label: "Google+",
    regex: SimpleSchema.Regex.Url
  },
  // TODO: Add 'Requests' feature
  // "requestIds": {
  //   type: [String],
  //   label: "Request IDs",
  //   regEx: SimpleSchema.RegEx.Id,
  //   optional: true
  // }
  "dateListed": {
    type: Date,
    label: "Date Listed",
    autoValue: function () {
      if (this.isInsert) {
        return new Date();
      } else if (this.isUpsert) {
        return {$setOnInsert: new Date()};
      } else {
        this.unset();  // Prevent user from supplying their own value
      }
    }
  },
});

Projects.attachSchema(ProjectsSchema);
<|endoftext|>


<commit_before>'use strict';

var _ = require('lodash');
var utils = require('formio-utils');

module.exports = [
  function() {
    return {
      restrict: 'E',
      scope: true,
      template: '' +
        '<uib-accordion>' +
          '
' +
            'This component should Display:' +
            '<select class="form-control input-md" ng-model="component.conditional.show">' +
            '<option ng-repeat="item in _booleans track by $index" value="{{item}}">{{item.toString()}}</option>' +
            '</select>' +
            '
When the form component:' +
            '<select class="form-control input-md" ng-model="component.conditional.when">' +
            '<option ng-repeat="item in _components track by $index" value="{{item.key}}">{{item.label}}</option>' +
            '</select>' +
            '
Has the value:' +
            '<input type="text" class="form-control input-md" ng-model="component.conditional.eq">' +
          '
' +
          '
' +
            '<textarea class="form-control" rows="5" id="custom" name="custom" ng-model="component.customConditional" placeholder="/*** Example Code ***/\nshow = (data[\'mykey\'] > 1);">{{ component.validate.custom }}</textarea>' +
            '' +
            '
Enter custom conditional code.
' +
            '
You must assign the show variable as either true or false.
' +
            '
The global variable data is provided, and allows you to access the data of any form component, by using its API key.
' +
            '
Note: Advanced Conditional logic will only work, if the Simple Conditional logic is not defined.
' +
            '' +
          '
' +
        '</uib-accordion>',
      controller: [
        '$scope',
        function(
          $scope) {
          // Default the current components conditional logic.
          $scope.component = $scope.component || {};
          $scope.component.conditional = $scope.component.conditional || {};

          // The available logic functions.
          $scope._booleans = ['', 'true', 'false'];

          // Filter the list of available form components for conditional logic.
          $scope._components = _.get($scope, 'form.components') || [];
          $scope._components = utils.flattenComponents($scope._components);
          // Remove non-input/button fields because they don't make sense.
          // FA-890 - Dont allow the current component to be a conditional trigger.
          $scope._components = _.reject($scope._components, function(c) {
            return !c.input || (c.type === 'button') || (c.key === $scope.component.key);
          });

          // Add default item to the components list.
          $scope._components.unshift('');

          // Default and watch the show logic.
          $scope.component.conditional.show = $scope.component.conditional.show || '';
          // Coerce show var to supported value.
          var _booleanMap = {
            '': '',
            'true': 'true',
            'false': 'false'
          };
          $scope.component.conditional.show = _booleanMap.hasOwnProperty($scope.component.conditional.show)
            ? _booleanMap[$scope.component.conditional.show]
            : '';

          // Default and watch the when logic.
          $scope.component.conditional.when = $scope.component.conditional.when || null;

          // Default and watch the search logic.
          $scope.component.conditional.eq = $scope.component.conditional.eq || '';

          // Track the status of the accordion panels open state.
          $scope.status = {
            simple: !$scope.component.customConditional,
            advanced: !!$scope.component.customConditional
          };
        }
      ]
    };
  }
];
<commit_msg>Updating simple field conditional form to show the component api key when there is no label.<commit_after>'use strict';

var _ = require('lodash');
var utils = require('formio-utils');

module.exports = [
  function() {
    return {
      restrict: 'E',
      scope: true,
      template: '' +
        '<uib-accordion>' +
          '
' +
            'This component should Display:' +
            '<select class="form-control input-md" ng-model="component.conditional.show">' +
            '<option ng-repeat="item in _booleans track by $index" value="{{item}}">{{item.toString()}}</option>' +
            '</select>' +
            '
When the form component:' +
            '<select class="form-control input-md" ng-model="component.conditional.when">' +
            '<option ng-repeat="item in _components track by $index" value="{{item.key}}">{{item !== "" ? item.label + " (" + item.key + ")" : ""}}</option>' +
            '</select>' +
            '
Has the value:' +
            '<input type="text" class="form-control input-md" ng-model="component.conditional.eq">' +
          '
' +
          '
' +
            '<textarea class="form-control" rows="5" id="custom" name="custom" ng-model="component.customConditional" placeholder="/*** Example Code ***/\nshow = (data[\'mykey\'] > 1);">{{ component.validate.custom }}</textarea>' +
            '' +
            '
Enter custom conditional code.
' +
            '
You must assign the show variable as either true or false.
' +
            '
The global variable data is provided, and allows you to access the data of any form component, by using its API key.
' +
            '
Note: Advanced Conditional logic will only work, if the Simple Conditional logic is not defined.
' +
            '' +
          '
' +
        '</uib-accordion>',
      controller: [
        '$scope',
        function(
          $scope) {
          // Default the current components conditional logic.
          $scope.component = $scope.component || {};
          $scope.component.conditional = $scope.component.conditional || {};

          // The available logic functions.
          $scope._booleans = ['', 'true', 'false'];

          // Filter the list of available form components for conditional logic.
          $scope._components = _.get($scope, 'form.components') || [];
          $scope._components = utils.flattenComponents($scope._components);
          // Remove non-input/button fields because they don't make sense.
          // FA-890 - Dont allow the current component to be a conditional trigger.
          $scope._components = _.reject($scope._components, function(c) {
            return !c.input || (c.type === 'button') || (c.key === $scope.component.key) || (!c.label && !c.key);
          });

          // Add default item to the components list.
          $scope._components.unshift('');

          // Default and watch the show logic.
          $scope.component.conditional.show = $scope.component.conditional.show || '';
          // Coerce show var to supported value.
          var _booleanMap = {
            '': '',
            'true': 'true',
            'false': 'false'
          };
          $scope.component.conditional.show = _booleanMap.hasOwnProperty($scope.component.conditional.show)
            ? _booleanMap[$scope.component.conditional.show]
            : '';

          // Default and watch the when logic.
          $scope.component.conditional.when = $scope.component.conditional.when || null;

          // Default and watch the search logic.
          $scope.component.conditional.eq = $scope.component.conditional.eq || '';

          // Track the status of the accordion panels open state.
          $scope.status = {
            simple: !$scope.component.customConditional,
            advanced: !!$scope.component.customConditional
          };
        }
      ]
    };
  }
];
<|endoftext|>


<commit_before>var fw = require('knockout/build/output/knockout-latest');
var _ = require('footwork-lodash');

var util = require('../misc/util');
var isPath = util.isPath;
var privateDataSymbol = util.getSymbol('footwork');

/**
 * The component resource loader tells footwork where to load the components assets from. It uses the supplied configuration to use AMD to download
 * them (the viewModel/template) if possible. After downloading these resources its template is then wrapped by the component lifecycle
 * loader and then bootstrapped.
 */
fw.components.loaders.push(fw.components.componentResourceLoader = {
  getConfig: function (componentName, callback) {
    var configOptions = null;
    var componentLocation;

    if (_.isFunction(window.require) && (componentLocation = fw.components.getLocation(componentName))) {
      var folderOffset = componentLocation.folderOffset || '';

      if (folderOffset !== '') {
        folderOffset = componentName + '/';
      }

      if (_.isString(componentLocation.combined)) {
        // combined viewModel + component module
        var combinedPath = componentLocation.combined;

        if (isPath(combinedPath)) {
          combinedPath = combinedPath + folderOffset + fw.components.getFileName(componentName, 'combined');
        }

        configOptions = {
          require: window.require.toUrl(combinedPath)
        };
      } else {
        var viewModelConfig;

        if (!_.isString(componentLocation.viewModel)) {
          // template-only component, substitute with 'blank' viewModel
          viewModelConfig = fw[privateDataSymbol].ViewModel;
        } else {
          // user has supplied the location of the viewModel, specify require config to download
          var viewModelPath = componentLocation.viewModel;

          if (isPath(viewModelPath)) {
            viewModelPath = viewModelPath + folderOffset + fw.components.getFileName(componentName, 'viewModel');
          }

          viewModelConfig = { require: window.require.toUrl(viewModelPath) };
        }

        var templatePath = componentLocation.template;
        if (isPath(templatePath)) {
          templatePath = templatePath + folderOffset + fw.components.getFileName(componentName, 'template');
        }

        templatePath = 'text!' + window.require.toUrl(templatePath);

        configOptions = {
          viewModel: viewModelConfig,
          template: { require: templatePath }
        };
      }
    }

    callback(configOptions);
  }
});
<commit_msg>changed name of component resource loader [skip ci]<commit_after>var fw = require('knockout/build/output/knockout-latest');
var _ = require('footwork-lodash');

var util = require('../misc/util');
var isPath = util.isPath;
var privateDataSymbol = util.getSymbol('footwork');

/**
 * The component resource loader tells footwork where to load the components assets from. It uses the supplied configuration to use AMD to download
 * them (the viewModel/template) if possible. After downloading these resources its template is then wrapped by the component lifecycle
 * loader and then bootstrapped.
 */
fw.components.loaders.push(fw.components.locationLoader = {
  getConfig: function (componentName, callback) {
    var configOptions = null;
    var componentLocation;

    if (_.isFunction(window.require) && (componentLocation = fw.components.getLocation(componentName))) {
      var folderOffset = componentLocation.folderOffset || '';

      if (folderOffset !== '') {
        folderOffset = componentName + '/';
      }

      if (_.isString(componentLocation.combined)) {
        // combined viewModel + component module
        var combinedPath = componentLocation.combined;

        if (isPath(combinedPath)) {
          combinedPath = combinedPath + folderOffset + fw.components.getFileName(componentName, 'combined');
        }

        configOptions = {
          require: window.require.toUrl(combinedPath)
        };
      } else {
        var viewModelConfig;

        if (!_.isString(componentLocation.viewModel)) {
          // template-only component, substitute with 'blank' viewModel
          viewModelConfig = fw[privateDataSymbol].ViewModel;
        } else {
          // user has supplied the location of the viewModel, specify require config to download
          var viewModelPath = componentLocation.viewModel;

          if (isPath(viewModelPath)) {
            viewModelPath = viewModelPath + folderOffset + fw.components.getFileName(componentName, 'viewModel');
          }

          viewModelConfig = { require: window.require.toUrl(viewModelPath) };
        }

        var templatePath = componentLocation.template;
        if (isPath(templatePath)) {
          templatePath = templatePath + folderOffset + fw.components.getFileName(componentName, 'template');
        }

        templatePath = 'text!' + window.require.toUrl(templatePath);

        configOptions = {
          viewModel: viewModelConfig,
          template: { require: templatePath }
        };
      }
    }

    callback(configOptions);
  }
});
<|endoftext|>


<commit_before>(function($,rangy){
	rootNS = this;
	TextSelector = function(){
		var self = this;
		this._color = "#666666";
		this._selections = [];
	}
	TextSelector.constructor = TextSelector;
	TextSelector.prototype = {};
	$.extend(TextSelector.prototype, {

		getSelectedText:function(){
				var self = this;
				var selObj = new Array();

				//var range = rangy.createRange();
				var sel = rangy.getSelection();
				var startChildren = self._getChildNumber(sel.anchorNode);
				var endChildren = self._getChildNumber(sel.focusNode);

				selObj = {
					'id': "uniqueId", // replace me
					'StartParent' : $(sel.anchorNode.parentNode).getPath(),
					//.parentNode.id,
					'StartOffset' : sel.anchorOffset,
					'StartChild' : startChildren,
					'EndParent' : $(sel.focusNode.parentNode).getPath(),
					'EndOffset' : sel.focusOffset,
					'EndChild' : endChildren,
					'color': this._color
				}

				// Returns selection object
				// of the following type:
				// {
				//  "id": unique
				//	"StartParent": "Id of anchor parent",
				//   "StartOffset": "anchor offset"
				//   "StartChild": "child in anchorNode",
				//	 "EndParent": "Id of focus parent",
				//   "EndOffset": "focus offset",
				//   "EndChild": "child in focus Node"

				return selObj;

		},
		_getIndexOfId: function(selId){
			for (var i=0;i<this._selections.length;i++){
				if (this._selections[i].id=selId){
					return i;
				}
			}
			return null;
		},

		_getPathToNode: function(node){
			path = "";

			if (node.id){
				return "#"+node.id;
			}
			else{
				var childNo=this._getChildNumber(node,node.nodeName);

				path=">*:eq("+childNo+")";
				while(node.parentNode){
					node = node.parentNode;
					if (node.id){
						return "#"+node.id+path;
					}
					else{
						var childNo=this._getChildNumber(node,node.nodeName);

						if (childNo) {
							path = ">*:eq(" + childNo + ")" + path;
						}
						else{
							return node.nodeName+path;
						}
					}
				}
				return node.nodeName+":"+path;
			}

		},

		_getChildNumber: function(obj){
		          if (obj.parentNode) {
				  	var children = obj.parentNode.childNodes;
				  	var num;
				  	for (var i = 0; i < children.length; i++) {
				  		if (children[i].isSameNode(obj)) {

				  			return i;
				  		}
				  	}
				  }

					return null;
                	/*$.each(children, function(index, value) {

                		if(children.eq(index)[0].isSameNode(obj)) {
							alert("gotcha "+index);
                			return index;
                		}
                	});
                	return null;
                }
                return null;	*/
		},
		changeSelectionColor:function(selId,color){
			// get selection object from this._selections
			// by selId.  For now, I've created a fake one.

		},
		changePenColor:function(color){
			// From now on, highlight in Color
			this._color = color;
		},

		addSelection: function(selObj){
			// adds a selection object to this._selections
			// and adds highlight span (each with a class
  			// name unique to this selection).  CSS should
			// turn the background-color of this class to
			// this._color
		},
		removeSelection: function(selId){
			// removes selection object from array
			// and drops all highlight spans
		},
		exportSelections: function(){
			// returns JSON object of this._selections
		},
		importSelections: function(JSONobj){
			/* assigns a JSON object of selections (like that
			   returned by exportSelections) to this._selections
			   Then add colors to each */
		},
		clearSelections: function(){
			/*  empties this._selections
			 *  and removes all highlight markers
			 */
			this._selections = [];
			this.removeHighlightMarkers();
			return true;
		},
		removeHighlightMarkers: function(){
			/*
			 *  removes all highlight markers
			 *  but keeps this._selections unchanged
			 *
			 */
		},
		addHighlightMarkers: function(){
			/*
			 * adds highlight markers for all selections in
			 * this._selections
			 */
		}
	});
	rootNS.TextSelector = TextSelector;
})(jQuery,rangy)
<commit_msg>JGD<commit_after>(function($,rangy){
	rootNS = this;
	// Tim Bowman wrote this
	TextSelector = function(){
		var self = this;
		this._color = "#666666";
		this._selections = [];
	}
	TextSelector.constructor = TextSelector;
	TextSelector.prototype = {};
	$.extend(TextSelector.prototype, {

		getSelectedText:function(){
				var self = this;
				var selObj = new Array();

				//var range = rangy.createRange();
				var sel = rangy.getSelection();
				var startChildren = self._getChildNumber(sel.anchorNode);
				var endChildren = self._getChildNumber(sel.focusNode);

				selObj = {
					'id': "uniqueId", // replace me
					'StartParent' : $(sel.anchorNode.parentNode).getPath(),
					//.parentNode.id,
					'StartOffset' : sel.anchorOffset,
					'StartChild' : startChildren,
					'EndParent' : $(sel.focusNode.parentNode).getPath(),
					'EndOffset' : sel.focusOffset,
					'EndChild' : endChildren,
					'color': this._color
				}

				// Returns selection object
				// of the following type:
				// {
				//  "id": unique
				//	"StartParent": "Id of anchor parent",
				//   "StartOffset": "anchor offset"
				//   "StartChild": "child in anchorNode",
				//	 "EndParent": "Id of focus parent",
				//   "EndOffset": "focus offset",
				//   "EndChild": "child in focus Node"

				return selObj;

		},
		_getIndexOfId: function(selId){
			for (var i=0;i<this._selections.length;i++){
				if (this._selections[i].id=selId){
					return i;
				}
			}
			return null;
		},

		_getPathToNode: function(node){
			path = "";

			if (node.id){
				return "#"+node.id;
			}
			else{
				var childNo=this._getChildNumber(node,node.nodeName);

				path=">*:eq("+childNo+")";
				while(node.parentNode){
					node = node.parentNode;
					if (node.id){
						return "#"+node.id+path;
					}
					else{
						var childNo=this._getChildNumber(node,node.nodeName);

						if (childNo) {
							path = ">*:eq(" + childNo + ")" + path;
						}
						else{
							return node.nodeName+path;
						}
					}
				}
				return node.nodeName+":"+path;
			}

		},

		_getChildNumber: function(obj){
		          if (obj.parentNode) {
				  	var children = obj.parentNode.childNodes;
				  	var num;
				  	for (var i = 0; i < children.length; i++) {
				  		if (children[i].isSameNode(obj)) {

				  			return i;
				  		}
				  	}
				  }

					return null;
                	/*$.each(children, function(index, value) {

                		if(children.eq(index)[0].isSameNode(obj)) {
							alert("gotcha "+index);
                			return index;
                		}
                	});
                	return null;
                }
                return null;	*/
		},
		changeSelectionColor:function(selId,color){
			// get selection object from this._selections
			// by selId.  For now, I've created a fake one.

		},
		changePenColor:function(color){
			// From now on, highlight in Color
			this._color = color;
		},

		addSelection: function(selObj){
			// adds a selection object to this._selections
			// and adds highlight span (each with a class
  			// name unique to this selection).  CSS should
			// turn the background-color of this class to
			// this._color
		},
		removeSelection: function(selId){
			// removes selection object from array
			// and drops all highlight spans
		},
		exportSelections: function(){
			// returns JSON object of this._selections
		},
		importSelections: function(JSONobj){
			/* assigns a JSON object of selections (like that
			   returned by exportSelections) to this._selections
			   Then add colors to each */
		},
		clearSelections: function(){
			/*  empties this._selections
			 *  and removes all highlight markers
			 */
			this._selections = [];
			this.removeHighlightMarkers();
			return true;
		},
		removeHighlightMarkers: function(){
			/*
			 *  removes all highlight markers
			 *  but keeps this._selections unchanged
			 *
			 */
		},
		addHighlightMarkers: function(){
			/*
			 * adds highlight markers for all selections in
			 * this._selections
			 */
		}
	});
	rootNS.TextSelector = TextSelector;
})(jQuery,rangy)
<|endoftext|>


<commit_before>//* @public
/**
	_moon.Panel_ is the default kind for controls created inside a
	moon.Panels container.  Typically, a _moon.Panels_
	will contain several instances of _moon.Panel_.

	The built-in features of _moon.Panel_ include a header and a FittableRows
	layout for the main body content.
*/

enyo.kind({
	name : "moon.Panel",
	published: {
		//* Facade for the header's _title_ property
		title: "",
		//* Facade for the header's _titleAbove_ property
		titleAbove: "",
		//* Facade for the header's _titleBelow_ property
		titleBelow: "",
		//* If true, the header's _titleAbove_ property is automatically populated
		//* with the panel number
		autoNumber: true
    },
	events : {
		//* Fires when this panel has completed its pre-arrangement transition.
		onPreTransitionComplete: "",
		//* Fires when this panel has completed its post-arrangement transition.
		onPostTransitionComplete: ""
	},

	//* @protected

	spotlight: "container",
	fit : true,
	classes: "moon-panel",
	layoutKind: "FittableRowsLayout",
	panelTools : [
		{name: "header", kind: "moon.Header"},
		{name: "panelBody", fit: true, classes: "moon-panel-body"},
		{name: "animator", kind: "StyleAnimator", onComplete: "animationComplete"}
	],
	headerComponents: [],
	isBreadcrumb: false,

	create: function() {
		this.inherited(arguments);
		this.$.header.createComponents(this.headerComponents);
		this.autoNumberChanged();
		this.titleChanged();
		this.titleAboveChanged();
		this.titleBelowChanged();
	},
	initComponents: function() {
		this.createTools();
		this.controlParentName = "panelBody";
		this.discoverControlParent();
		this.inherited(arguments);
	},
	createTools: function() {
		this.createComponents(this.panelTools);
	},
	//* Force layout kind changes to apply to _this.$.panelBody_
	layoutKindChanged: function() {
		this.$.panelBody.setLayoutKind(this.getLayoutKind());
		this.layoutKind = "FittableRowsLayout";
		this.inherited(arguments);
	},

	//* @public

	autoNumberChanged: function() {
		if (this.getAutoNumber() == true && this.container) {
			this.setTitleAbove(this.clientIndexInContainer() + 1);
		}
	},
	//* Updates _this.header_ when _title_ changes.
	titleChanged: function() {
		this.$.header.setTitle(this.getTitle());
	},
	//* Updates _this.header_ when _titleAbove_ changes.
	titleAboveChanged: function() {
		this.$.header.setTitleAbove(this.getTitleAbove());
	},
	//* Updates _this.header_ when _titleBelow_ changes.
	titleBelowChanged: function() {
		this.$.header.setTitleBelow(this.getTitleBelow());
	},
	shrinkPanel: function() {
		this.$.animator.newAnimation({
			name: "preTransition",
			duration: 800,
			timingFunction: "cubic-bezier(.42, 0, .16, 1.1)",
			keyframes: {
				0: [{
					control: this.$.panelBody,
					properties: {
						"height" : "current"
					}
				}],
				25: [{
					control: this.$.panelBody,
					properties: {
						"opacity" : "1"
					}
				}],
				50: [{
					control: this.$.panelBody,
					properties: {
						"height"  : "0px",
						"opacity" : "0"
					}
				},
				{
					control: this,
					properties: {
						"width" : "current"
					}
				}],
				100: [{
					control: this,
					properties: {
						"width" : "200px"
					}
				}]
			}
		});

		this.$.header.animateCollapse();
		this.$.animator.play("preTransition");
	},
	growPanel: function() {
		this.$.animator.newAnimation({
			name: "postTransition",
			duration: 800,
			timingFunction: "cubic-bezier(.42, 0, .16, 1.1)",
			keyframes: {
				0: [{
					control: this,
					properties: {
						"width" : "current"
					}
				}],
				25: [{
					control: this,
					properties: {
						"width" : this.actualWidth+"px"
					}
				},
				{
					control: this.$.panelBody,
					properties: {
						"height"  : "current",
						"opacity" : "current"
					}
				}],
				75: [{
					control: this.$.panelBody,
					properties: {
						"opacity" : "1"
					}
				}],
				100: [
				{
					control: this.$.panelBody,
					properties: {
						"height" : "auto"
					}
				}]
			}
		});

		this.$.header.animateExpand();
		this.$.animator.play("postTransition");
	},

	//* @protected

	preTransitionComplete: function() {
		this.isBreadcrumb = true;
		this.doPreTransitionComplete();
	},
	postTransitionComplete: function() {
		this.isBreadcrumb = false;
		this.doPostTransitionComplete();
	},
	preTransition: function(inFromIndex, inToIndex) {
		if (this.container && !this.isBreadcrumb && this.container.layout.isBreadcrumb(this.clientIndexInContainer(), inToIndex)) {
			this.shrinkPanel();
			return true;
		}
		return false;
	},
	postTransition: function(inFromIndex, inToIndex) {
		if (this.container && this.isBreadcrumb && !this.container.layout.isBreadcrumb(this.clientIndexInContainer(), inToIndex)) {
			this.growPanel();
			return true;
		}
		return false;
	},
	animationComplete: function(inSender, inEvent) {
		switch (inEvent.animation.name) {
			case "preTransition":
				this.preTransitionComplete();
				break;
			case "postTransition":
				this.postTransitionComplete();
				break;
		}
	}
});<commit_msg>GF-4074: Implemenet getHeader method()<commit_after>//* @public
/**
	_moon.Panel_ is the default kind for controls created inside a
	moon.Panels container.  Typically, a _moon.Panels_
	will contain several instances of _moon.Panel_.

	The built-in features of _moon.Panel_ include a header and a FittableRows
	layout for the main body content.
*/

enyo.kind({
	name : "moon.Panel",
	published: {
		//* Facade for the header's _title_ property
		title: "",
		//* Facade for the header's _titleAbove_ property
		titleAbove: "",
		//* Facade for the header's _titleBelow_ property
		titleBelow: "",
		//* If true, the header's _titleAbove_ property is automatically populated
		//* with the panel number
		autoNumber: true
    },
	events : {
		//* Fires when this panel has completed its pre-arrangement transition.
		onPreTransitionComplete: "",
		//* Fires when this panel has completed its post-arrangement transition.
		onPostTransitionComplete: ""
	},

	//* @protected

	spotlight: "container",
	fit : true,
	classes: "moon-panel",
	layoutKind: "FittableRowsLayout",
	panelTools : [
		{name: "header", kind: "moon.Header"},
		{name: "panelBody", fit: true, classes: "moon-panel-body"},
		{name: "animator", kind: "StyleAnimator", onComplete: "animationComplete"}
	],
	headerComponents: [],
	isBreadcrumb: false,

	create: function() {
		this.inherited(arguments);
		this.$.header.createComponents(this.headerComponents);
		this.autoNumberChanged();
		this.titleChanged();
		this.titleAboveChanged();
		this.titleBelowChanged();
	},
	initComponents: function() {
		this.createTools();
		this.controlParentName = "panelBody";
		this.discoverControlParent();
		this.inherited(arguments);
	},
	createTools: function() {
		this.createComponents(this.panelTools);
	},
	//* Force layout kind changes to apply to _this.$.panelBody_
	layoutKindChanged: function() {
		this.$.panelBody.setLayoutKind(this.getLayoutKind());
		this.layoutKind = "FittableRowsLayout";
		this.inherited(arguments);
	},

	//* @public

	autoNumberChanged: function() {
		if (this.getAutoNumber() == true && this.container) {
			this.setTitleAbove(this.clientIndexInContainer() + 1);
		}
	},
	//* Updates _this.header_ when _title_ changes.
	titleChanged: function() {
		this.$.header.setTitle(this.getTitle());
	},
	//* Updates _this.header_ when _titleAbove_ changes.
	titleAboveChanged: function() {
		this.$.header.setTitleAbove(this.getTitleAbove());
	},
	//* Updates _this.header_ when _titleBelow_ changes.
	titleBelowChanged: function() {
		this.$.header.setTitleBelow(this.getTitleBelow());
	},
	//* Get _this.header_ to update panel header dynamically.
	getHeader: function() {
		return this.$.header;
	},
	shrinkPanel: function() {
		this.$.animator.newAnimation({
			name: "preTransition",
			duration: 800,
			timingFunction: "cubic-bezier(.42, 0, .16, 1.1)",
			keyframes: {
				0: [{
					control: this.$.panelBody,
					properties: {
						"height" : "current"
					}
				}],
				25: [{
					control: this.$.panelBody,
					properties: {
						"opacity" : "1"
					}
				}],
				50: [{
					control: this.$.panelBody,
					properties: {
						"height"  : "0px",
						"opacity" : "0"
					}
				},
				{
					control: this,
					properties: {
						"width" : "current"
					}
				}],
				100: [{
					control: this,
					properties: {
						"width" : "200px"
					}
				}]
			}
		});

		this.$.header.animateCollapse();
		this.$.animator.play("preTransition");
	},
	growPanel: function() {
		this.$.animator.newAnimation({
			name: "postTransition",
			duration: 800,
			timingFunction: "cubic-bezier(.42, 0, .16, 1.1)",
			keyframes: {
				0: [{
					control: this,
					properties: {
						"width" : "current"
					}
				}],
				25: [{
					control: this,
					properties: {
						"width" : this.actualWidth+"px"
					}
				},
				{
					control: this.$.panelBody,
					properties: {
						"height"  : "current",
						"opacity" : "current"
					}
				}],
				75: [{
					control: this.$.panelBody,
					properties: {
						"opacity" : "1"
					}
				}],
				100: [
				{
					control: this.$.panelBody,
					properties: {
						"height" : "auto"
					}
				}]
			}
		});

		this.$.header.animateExpand();
		this.$.animator.play("postTransition");
	},

	//* @protected

	preTransitionComplete: function() {
		this.isBreadcrumb = true;
		this.doPreTransitionComplete();
	},
	postTransitionComplete: function() {
		this.isBreadcrumb = false;
		this.doPostTransitionComplete();
	},
	preTransition: function(inFromIndex, inToIndex) {
		if (this.container && !this.isBreadcrumb && this.container.layout.isBreadcrumb(this.clientIndexInContainer(), inToIndex)) {
			this.shrinkPanel();
			return true;
		}
		return false;
	},
	postTransition: function(inFromIndex, inToIndex) {
		if (this.container && this.isBreadcrumb && !this.container.layout.isBreadcrumb(this.clientIndexInContainer(), inToIndex)) {
			this.growPanel();
			return true;
		}
		return false;
	},
	animationComplete: function(inSender, inEvent) {
		switch (inEvent.animation.name) {
			case "preTransition":
				this.preTransitionComplete();
				break;
			case "postTransition":
				this.postTransitionComplete();
				break;
		}
	}
});<|endoftext|>


<commit_before>var states = {
  resting: "resting",
  inFlight: "inFlight"
};

class Ship {
  constructor(options) {
    this.mesh = options.mesh;
    this.mesh.scale.set(options.scale, options.scale, options.scale);
    this.mesh.rotateY(options.rotateY);
    this.homePosition = options.position.clone();
    this.mesh.position.copy(this.homePosition.clone());
    this.mesh.children.forEach((child) => {
      child.castShadow = true;
    });

    this.restingPosition();

    this.startTime = Date.now() + (Math.random() * 2000);
  }

  restingPosition() {
    this.state = states.resting;
  }

  hover() {
    var delta = (Date.now() - this.startTime) / 1000;

    var t = Math.sin(delta).toFixed(3);

    this.mesh.position.set(
      this.mesh.position.x,
      this.mesh.position.y,
      // Move between range [-5, 5]
      (t * 10) - 5
    );
  }

  moveToPlanet(offset) {
    this.mesh.position.copy(offset);
  }

  moveToHomePosition() {
    this.mesh.position.copy(this.homePosition);
  }

  update() {
    if (this.state === states.resting) {
      this.hover();
    }
  }
}

module.exports = Ship;
<commit_msg>update phong material settings for ship meshes<commit_after>var states = {
  resting: "resting",
  inFlight: "inFlight"
};

class Ship {
  constructor(options) {
    this.mesh = options.mesh;
    this.mesh.scale.set(options.scale, options.scale, options.scale);
    this.mesh.rotateY(options.rotateY);
    this.homePosition = options.position.clone();
    this.mesh.position.copy(this.homePosition.clone());
    this.mesh.children.forEach((child) => {
      child.castShadow = true;
      //child.material.color.setHex(0x555555);
      child.material.emissive.setHex(0x111111);
      child.material.specular.setHex(0xffffff);
      child.material.shininess = 10;
    });

    this.restingPosition();

    this.startTime = Date.now() + (Math.random() * 2000);
  }

  restingPosition() {
    this.state = states.resting;
  }

  hover() {
    var delta = (Date.now() - this.startTime) / 1000;

    var t = Math.sin(delta).toFixed(3);

    this.mesh.position.set(
      this.mesh.position.x,
      this.mesh.position.y,
      // Move between range [-5, 5]
      (t * 10) - 5
    );
  }

  moveToPlanet(offset) {
    this.mesh.position.copy(offset);
  }

  moveToHomePosition() {
    this.mesh.position.copy(this.homePosition);
  }

  update() {
    if (this.state === states.resting) {
      this.hover();
    }
  }
}

module.exports = Ship;
<|endoftext|>


<commit_before>// // Create an array that contains the words in the sentence
// const sentence = ["The", "walrus", "danced", "through", "the", "trees", "in", "the", "light", "of", "the", "moon"];

// /*
//     The addExcitement function should be an impure function, and accept
//     the array as the sole argument. It should iterate over the array
//     and output the words to the browser console.
// */
// function addExcitement (theWordArray) {
//   let sentence = ""
//   for (let i = 0; i < theWordArray.length; i++) {
//     let currentWord = theWordArray[i]
//     sentence += currentWord + " "
//     console.log(sentence)
//   }
// }

// // Invoke the function and pass in the array
// addExcitement(sentence);

// Create an array that contains the words in the sentence
// const sentence = ["The", "walrus", "danced", "through", "the", "trees", "in", "the", "light", "of", "the", "moon"];
// const exclamation = "!"

// /*
//     The addExcitement function should be an impure function, and accept
//     the array as the sole argument. It should iterate over the array
//     and output the words to the browser console.
// */
// function addExcitement (theWordArray) {
//   let sentence = ""
//   for (let i = 0; i < theWordArray.length; i++) {
//     let currentWord = theWordArray[i]
//     if (i % 3 === 2) {
//       currentWord += exclamation + " "
//     } else {
//       currentWord += " "
//     }
//     sentence += currentWord + " "
//     console.log(sentence)
//   }
// }

// // Invoke the function and pass in the array
// addExcitement(sentence);

// // Create an array that contains the words in the sentence
// const sentence = ["The", "walrus", "danced", "through", "the", "trees", "in", "the", "light", "of", "the", "moon"];
// let exclamation = "!"

// /*
//     The addExcitement function should be an impure function, and accept
//     the array as the sole argument. It should iterate over the array
//     and output the words to the browser console.
// */
// function addExcitement (theWordArray) {
//   let sentence = ""
//   for (let i = 0; i < theWordArray.length; i++) {
//     let currentWord = theWordArray[i]
//     if (i % 3 === 2) {
//       currentWord += exclamation + " "
//       exclamation += "!"
//     } else {
//       currentWord += " "
//     }
//     sentence += currentWord + " "
//     console.log(sentence)
//   }
// }

// // Invoke the function and pass in the array
// addExcitement(sentence);

// Create an array that contains the words in the sentence
const sentence = ["The", "walrus", "danced", "through", "the", "trees", "in", "the", "light", "of", "the", "moon"];

/*
    The addExcitement function should be an impure function, and accept
    the array as the sole argument. It should iterate over the array
    and output the words to the browser console.
*/
let addExcitement = (theWordArray, character) => {
  let sentence = ""
  let characterList = character
  for (let i = 0; i < theWordArray.length; i++) {
    let currentWord = theWordArray[i]
    if (i % 3 === 2) {
      currentWord += characterList + " "
      characterList += character
    } else {
      currentWord += " "
    }
    sentence += currentWord + " "
    console.log(sentence)
  }
}

// Invoke the function and pass in the array
addExcitement(sentence, "?");<commit_msg>fixed the modulus to something that actually makes sense<commit_after>// Create an array that contains the words in the sentence
// let sentence = ["The", "walrus", "danced", "through", "the", "trees", "in", "the", "light", "of", "the", "moon"];

// /*
//     The addExcitement function should be an impure function, and accept
//     the array as the sole argument. It should iterate over the array
//     and output the words to the browser console.
// */
// function addExcitement (theWordArray) {
//   let sentenceToWrite = ""
//   for (let i = 0; i < theWordArray.length; i++) {
//     let currentWord = theWordArray[i]
//     sentenceToWrite += currentWord + " "
//     console.log(sentence)
//   }
// }

// for
// // Invoke the function and pass in the array
// addExcitement(sentence);

// Create an array that contains the words in the sentence
// const sentence = ["The", "walrus", "danced", "through", "the", "trees", "in", "the", "light", "of", "the", "moon"];
// const exclamation = "!"

// /*
//     The addExcitement function should be an impure function, and accept
//     the array as the sole argument. It should iterate over the array
//     and output the words to the browser console.
// */
// function addExcitement (theWordArray) {
//   let sentenceToWrite = ""
//   for (let i = 0; i < theWordArray.length; i++) {
//     let currentWord = theWordArray[i]
//     let counter = i + 1
//     if (counter % 3 === 0) {
//       currentWord += exclamation + " "
//     } else {
//       currentWord += " "
//     }
//     sentenceToWrite += currentWord + " "
//     console.log(sentenceToWrite)
//   }
// }

// // Invoke the function and pass in the array
// addExcitement(sentence);

// // Create an array that contains the words in the sentence
// const sentence = ["The", "walrus", "danced", "through", "the", "trees", "in", "the", "light", "of", "the", "moon"];
// let exclamation = "!"

// /*
//     The addExcitement function should be an impure function, and accept
//     the array as the sole argument. It should iterate over the array
//     and output the words to the browser console.
// */
// function addExcitement (theWordArray) {
//   let sentence = ""
//   for (let i = 0; i < theWordArray.length; i++) {
//     let currentWord = theWordArray[i]
//     let counter = i + 1
//     if (counter % 3 === 0) {
//       currentWord += exclamation + " "
//       exclamation += "!"
//     } else {
//       currentWord += " "
//     }
//     sentence += currentWord + " "
//     console.log(sentence)
//   }
// }

// // Invoke the function and pass in the array
// addExcitement(sentence);

// Create an array that contains the words in the sentence
const sentence = ["The", "walrus", "danced", "through", "the", "trees", "in", "the", "light", "of", "the", "moon"];

/*
    The addExcitement function should be an impure function, and accept
    the array as the sole argument. It should iterate over the array
    and output the words to the browser console.
*/
let addExcitement = (theWordArray, character) => {
  let sentence = ""
  let characterList = character
  for (let i = 0; i < theWordArray.length; i++) {
    let currentWord = theWordArray[i]
    let counter = i + 1
   if (counter % 3 === 0) {
      currentWord += characterList + " "
      characterList += character
    } else {
      currentWord += " "
    }
     sentence += currentWord + " "
     console.log(sentence)
   }
 }

// // Invoke the function and pass in the array
 addExcitement(sentence, "?");
//  addExcitement(sentence, "*")
//  addExcitement(sentence, "@")<|endoftext|>


<commit_before>function Editor() {
    function init() {
        this.Inputs = new InputManager();
        this.mainLoop();
    }

    function mainLoop() {
        var now = Date.now();
        var dt = (now - this.lastTime) / 1000.0;

        this.Inputs.processKeyboard();
        // update entities, animations, and such, with dt
        this.update(dt);
        render();

        this.lastTime = now;
        requestAnimFrame(this.mainLoop);
    }

    function update(dt) {
        this.stateMap[this.currentState].update(dt);
    }

    this.stateMap = {
        "CELL_PLACEMENT": {
            update: updateNothing,
            mouse: handleCameraMouse,
            keyboard: handleCameraKeyboard
        }
    }

    this.currentState = "CELL_PLACEMENT";
    this.lastTime = 0;
    this.init = init;
    this.mainLoop = mainLoop.bind(this);
}

function updateNothing(dt) {
    // the editor doesn't animate right now, or need any notion of time,
    // so this function is a nop
}<commit_msg>update has to actually be defined, dummy<commit_after>function Editor() {
    function init() {
        this.Inputs = new InputManager();
        this.mainLoop();
    }

    function mainLoop() {
        var now = Date.now();
        var dt = (now - this.lastTime) / 1000.0;

        this.Inputs.processKeyboard();
        // update entities, animations, and such, with dt
        this.update(dt);
        render();

        this.lastTime = now;
        requestAnimFrame(this.mainLoop);
    }

    function update(dt) {
        this.stateMap[this.currentState].update(dt);
    }

    this.stateMap = {
        "CELL_PLACEMENT": {
            update: updateNothing,
            mouse: handleCameraMouse,
            keyboard: handleCameraKeyboard
        }
    }

    this.currentState = "CELL_PLACEMENT";
    this.lastTime = 0;
    this.init = init;
    this.mainLoop = mainLoop.bind(this);
    this.update = update;
}

function updateNothing(dt) {
    // the editor doesn't animate right now, or need any notion of time,
    // so this function is a nop
}<|endoftext|>