<commit_before>var LidarAnimation = require('../animations/lidar'),
    fs = require('fs'),
    Path = require('path'),
    helper = require('./shared');

var LidarHelper = function(where) {
    this.animation = new LidarAnimation(where);
    this.settings = null;
    this.readSettings();
    this.readings = [];
    this.enabled = false;
    return this;
}

LidarHelper.prototype = {
    setEnabled: function(status) {
        this.animation.setEnabled(status);
        this.enabled = status;
        this.downLevel = 0;
        this.readings = [];
        return this;
    },
    receiveValues: function(upward, downward) {
        helper.logger.debug(`LidarHelper: Received Values: ${upward}, ${downward}`);
        if(!this.enabled) {
            helper.logger.debug('LidarHelper: Disabled. Ignoring.');
            return;
        }
        this.readings.push(upward);
        if(this.readings.length < 2) {
            helper.logger.debug('LidarHelper: Not enough data. Ignoring.');
            return;
        }
        while(this.readings.length > 2) {
            helper.logger.debug('LidarHelper: Shifting');
            this.readings.shift();
        }
        helper.logger.debug(`LidarHelper: data: ${this.readings.join(', ')}`);
        var avg = this.readings.reduce((a, b) => a + b, 0) / this.readings.length;
        console.log(avg);
        if(avg <= 0.03) {
            helper.logger.debug('LidarHelper: Average is too low. Dropping.');
            this.animation.drop();
        }

        if(upward > 0.03) {
            this.downLevel++;
            this.readings = [];
            helper.logger.debug('LidarHelper: downLevel increased to ' + this.downLevel);
            if(this.downLevel < 4) {
                this.animation.openLevel(this.downLevel);
            }
        }
    },
    readSettings: function() {
        try {
            var path = Path.resolve(__dirname, '../settings.json');
            this.settings = JSON.parse(fs.readFileSync(path));
        } catch(ex) {
            helper.logger.error('LidarHelper: Error reading settings:');
            helper.logger.error(ex);
        }
    }
};

module.exports = LidarHelper;
<commit_msg>Fixup 1<commit_after>var LidarAnimation = require('../animations/lidar'),
    fs = require('fs'),
    Path = require('path'),
    helper = require('./shared');

var LidarHelper = function(where) {
    this.animation = new LidarAnimation(where);
    this.settings = null;
    this.readSettings();
    this.readings = [];
    this.enabled = false;
    return this;
}

LidarHelper.prototype = {
    setEnabled: function(status) {
        this.animation.setEnabled(status);
        this.enabled = status;
        this.downLevel = 0;
        this.readings = [];
        return this;
    },
    receiveValues: function(upward, downward) {
        helper.logger.debug(`LidarHelper: Received Values: ${upward}, ${downward}`);
        if(!this.enabled) {
            helper.logger.debug('LidarHelper: Disabled. Ignoring.');
            return;
        }
        this.readings.push(upward);
        while(this.readings.length > 2) {
            helper.logger.debug('LidarHelper: Shifting');
            this.readings.shift();
        }
        if(this.readings.length >= 2)
            helper.logger.debug(`LidarHelper: data: ${this.readings.join(', ')}`);
            var avg = this.readings.reduce((a, b) => a + b, 0) / this.readings.length;
            console.log(avg);
            if(avg <= 0.03) {
                helper.logger.debug('LidarHelper: Average is too low. Dropping.');
                this.animation.drop();
            }
        }

        if(upward > 0.03) {
            this.downLevel++;
            this.readings = [];
            helper.logger.debug('LidarHelper: downLevel increased to ' + this.downLevel);
            if(this.downLevel < 4) {
                this.animation.openLevel(this.downLevel);
            }
        }
    },
    readSettings: function() {
        try {
            var path = Path.resolve(__dirname, '../settings.json');
            this.settings = JSON.parse(fs.readFileSync(path));
        } catch(ex) {
            helper.logger.error('LidarHelper: Error reading settings:');
            helper.logger.error(ex);
        }
    }
};

module.exports = LidarHelper;
<|endoftext|>


<commit_before>import { homedir } from 'os';
import { join as pathJoin } from 'path';
import fs from 'fs-promise';
import fetch from 'node-fetch';
import { stringify as stringifyQuery } from 'querystring';

const stdin = process.openStdin();

function readEmail () {
  return new Promise((resolve, reject) => {
    process.stdout.write('> Enter your email address: ');
    stdin.on('data', (d) => {
      stdin.destroy();
      resolve(d.toString().trim());
    });
  });
}

async function getVerificationToken (email) {
  const data = JSON.stringify({ email });
  const res = await fetch('http://localhost:3001/', {
    method: 'POST',
    mode: 'cors',
    headers: {
      'Content-Type': 'application/json',
      'Content-Length': data.length
    },
    body: data
  });

  if (200 !== res.status) {
    throw new Error('Verification error');
  }

  const body = await res.json();
  return body.token;
}

async function verify (email, verificationToken) {
  const query = {
    email,
    token: verificationToken
  };

  const res = await fetch('http://localhost:3001/verify?' + stringifyQuery(query));

  const body = await res.json();
  return body.token;
}

function sleep (ms) {
  return new Promise((resolve, reject) => {
    setTimeout(resolve, ms);
  });
}

async function register () {
  const email = await readEmail();
  const verificationToken = await getVerificationToken(email);

  console.log('> Please follow the link in your email to log in.');

  let final;
  do {
    await sleep(5000);
    try {
      final = await verify(email, verificationToken);
    } catch (e) {}
  } while (!final);

  return { email, token: final };
}

export default function () {
  return register().then((loginData) => {
    return fs.writeFile(pathJoin(homedir(), '.now.json'), JSON.stringify(loginData));
  });
}
<commit_msg>login: a little more explicit<commit_after>import { homedir } from 'os';
import { join as pathJoin } from 'path';
import fs from 'fs-promise';
import fetch from 'node-fetch';
import { stringify as stringifyQuery } from 'querystring';

const stdin = process.openStdin();

function readEmail () {
  return new Promise((resolve, reject) => {
    process.stdout.write('> Enter your email address: ');
    stdin.on('data', (d) => {
      stdin.destroy();
      resolve(d.toString().trim());
    });
  });
}

async function getVerificationToken (email) {
  const data = JSON.stringify({ email });
  const res = await fetch('http://localhost:3001/', {
    method: 'POST',
    mode: 'cors',
    headers: {
      'Content-Type': 'application/json',
      'Content-Length': data.length
    },
    body: data
  });

  if (200 !== res.status) {
    throw new Error('Verification error');
  }

  const body = await res.json();
  return body.token;
}

async function verify (email, verificationToken) {
  const query = {
    email,
    token: verificationToken
  };

  const res = await fetch('http://localhost:3001/verify?' + stringifyQuery(query));

  const body = await res.json();
  return body.token;
}

function sleep (ms) {
  return new Promise((resolve, reject) => {
    setTimeout(resolve, ms);
  });
}

async function register () {
  const email = await readEmail();
  const verificationToken = await getVerificationToken(email);

  console.log('> Please follow the link in your email to log in.');
  console.log('> Waiting for confirmation…');

  let final;
  do {
    await sleep(5000);
    try {
      final = await verify(email, verificationToken);
    } catch (e) {}
  } while (!final);

  return { email, token: final };
}

export default function () {
  return register().then((loginData) => {
    return fs.writeFile(pathJoin(homedir(), '.now.json'), JSON.stringify(loginData));
  });
}
<|endoftext|>


<commit_before>import { homedir } from 'os';
import { join as pathJoin } from 'path';
import fs from 'fs-promise';
import fetch from 'node-fetch';
import { stringify as stringifyQuery } from 'querystring';

const stdin = process.openStdin();

function readEmail () {
  return new Promise((resolve, reject) => {
    process.stdout.write('> Enter your email address: ');
    stdin.on('data', (d) => {
      stdin.destroy();
      resolve(d.toString().trim());
    });
  });
}

async function getVerificationToken (email) {
  const data = JSON.stringify({ email });
  const res = await fetch('http://localhost:3001/', {
    method: 'POST',
    mode: 'cors',
    headers: {
      'Content-Type': 'application/json',
      'Content-Length': data.length
    },
    body: data
  });

  if (200 !== res.status) {
    throw new Error('Verification error');
  }

  const body = await res.json();
  return body.token;
}

async function verify (email, verificationToken) {
  const query = {
    email,
    token: verificationToken
  };

  const res = await fetch('http://localhost:3001/verify?' + stringifyQuery(query));

  const body = await res.json();
  return body.token;
}

function sleep (ms) {
  return new Promise((resolve, reject) => {
    setTimeout(resolve, ms);
  });
}

async function register () {
  const email = await readEmail();
  const verificationToken = await getVerificationToken(email);

  console.log('> Please follow the link in your email to log in.');
  console.log('> Waiting for confirmation…');

  let final;
  do {
    await sleep(5000);
    try {
      final = await verify(email, verificationToken);
    } catch (e) {}
  } while (!final);

  return { email, token: final };
}

export default function () {
  return register().then((loginData) => {
    return fs.writeFile(pathJoin(homedir(), '.now.json'), JSON.stringify(loginData));
  });
}
<commit_msg>improved login output<commit_after>import { homedir } from 'os';
import { join as pathJoin } from 'path';
import fs from 'fs-promise';
import fetch from 'node-fetch';
import { stringify as stringifyQuery } from 'querystring';
import chalk from 'chalk';

const stdin = process.openStdin();

function readEmail () {
  return new Promise((resolve, reject) => {
    process.stdout.write('> Enter your email address: ');
    stdin.on('data', (d) => {
      stdin.destroy();
      resolve(d.toString().trim());
    });
  });
}

async function getVerificationToken (email) {
  const data = JSON.stringify({ email });
  const res = await fetch('http://localhost:3001/', {
    method: 'POST',
    mode: 'cors',
    headers: {
      'Content-Type': 'application/json',
      'Content-Length': data.length
    },
    body: data
  });

  if (200 !== res.status) {
    throw new Error('Verification error');
  }

  const body = await res.json();
  return body.token;
}

async function verify (email, verificationToken) {
  const query = {
    email,
    token: verificationToken
  };

  const res = await fetch('http://localhost:3001/verify?' + stringifyQuery(query));

  const body = await res.json();
  return body.token;
}

function sleep (ms) {
  return new Promise((resolve, reject) => {
    setTimeout(resolve, ms);
  });
}

async function register () {
  const email = await readEmail();
  const verificationToken = await getVerificationToken(email);

  console.log(`> Please follow the link sent to ${chalk.bold(email)} to log in.`);
  process.stdout.write('> Waiting for confirmation..');

  let final;
  do {
    await sleep(2500);
    try {
      final = await verify(email, verificationToken);
    } catch (e) {}
    process.stdout.write('.');
  } while (!final);

  process.stdout.write('\n');

  return { email, token: final };
}

export default function () {
  return register().then((loginData) => {
    return fs.writeFile(pathJoin(homedir(), '.now.json'), JSON.stringify(loginData));
  });
}
<|endoftext|>


<commit_before>/*jslint node: true*/
"use strict";

var webid = require('webid');
var debug = require('./logging').login;

function loginHandler(req, res, next) {
    var ldp = req.app.locals.ldp;
    if (!ldp.webid) {
        setEmptySession(req);
        return next();
    }
    if (req.session.userId && req.session.identified) {
        debug("User: " + req.session.userId);
        res.set('User', req.session.userId);
        return next();
    } else {
        var certificate = req.connection.getPeerCertificate();
        if (!(certificate === null || Object.keys(certificate).length === 0))  {
            var verifAgent = new webid.VerificationAgent(certificate);
            verifAgent.verify(function(err, result) {
                if (err) {
                    debug("Error processing certificate: " + err);
                    setEmptySession(req);
                    var authError = new Error();
                    authError.status = 403;
                    authError.message = err;
                    return next(authError);
                } else {
                    req.session.userId = result;
                    req.session.identified = true;
                    debug("Identified user: " + req.session.userId);
                    res.set('User', req.session.userId);
                    return next();
                }
            });
        } else {
            debug("No client certificate found in the request. Did the user click on a cert?");
            setEmptySession(req);
            next();
        }
    }

    function setEmptySession(req) {
        req.session.userId = "";
        req.session.identified = false;
    }
}

exports.loginHandler = loginHandler;
<commit_msg>cleaning login handler code<commit_after>/*jslint node: true*/
"use strict";

var webid = require('webid');
var debug = require('./logging').login;

function loginHandler(req, res, next) {
    var ldp = req.app.locals.ldp;

    // No webid required? skip
    if (!ldp.webid) {
        setEmptySession(req);
        return next();
    }

    // User already logged in? skip
    if (req.session.userId && req.session.identified) {
        debug("User: " + req.session.userId);
        res.set('User', req.session.userId);
        return next();
    }

    var certificate = req.connection.getPeerCertificate();
    // Certificate is empty? skip
    if (certificate === null || Object.keys(certificate).length === 0)  {
        debug("No client certificate found in the request. Did the user click on a cert?");
        setEmptySession(req);
        return next();
    }
    var verifAgent = new webid.VerificationAgent(certificate);

    // Verify webid
    verifAgent.verify(function(err, result) {
        if (err) {
            debug("Error processing certificate: " + err);
            setEmptySession(req);
            var authError = new Error();
            authError.status = 403;
            authError.message = err;
            return next(authError);
        }
        req.session.userId = result;
        req.session.identified = true;
        debug("Identified user: " + req.session.userId);
        res.set('User', req.session.userId);
        return next();
    });
}

function setEmptySession(req) {
    req.session.userId = "";
    req.session.identified = false;
}

exports.loginHandler = loginHandler;
<|endoftext|>


<commit_before>"use strict";

var Client = require("./client");
var fs = require("fs");
var errors = require("./errors");
var MEDIA_PATH = "media";

function sendFile(request, file, mediaType, callback) {
	var stream = null;
	request.buffer().type(mediaType || "application/octet-stream");
	if (typeof file === "string") {
		stream = fs.createReadStream(file);
	}
	else if (Buffer.isBuffer(file)) {
		request.write(file);
		request.end(callback);
		return;
	}
	else if (typeof file.pipe === "function" && typeof file.read === "function" && typeof file.on === "function") {
		stream = file;
	}

	if (stream) {
		request.on("response", callback);
		stream.pipe(request);
		return;
	}

	callback({ statusCode : 400, text : "Invalid data to send", body : { message : "Invalid data to send" } });
}

module.exports = {
	/**
	 * Get a list of your media files
	 * @param client Client instance
	 * @param query query parameters
	 * @param callback callback function
	 * @example
	 * bandwidth.Media.list(client, function(err, list){});
	 */
	list : function (client, query, callback) {
		if (arguments.length === 1) {
			callback = client;
			client = new Client();
		}
		else if (arguments.length === 2) {
			callback = query;
			if (client instanceof Client) {
				query = {};
			}
			else {
				query = client;
				client = new Client();
			}
		}

		client.makeRequest("get", client.concatUserPath(MEDIA_PATH), query, callback);
	},

	/**
	 * Uploads a media file (or stream, or buffer) to the name you choose
	 * @param client Client instance
	 * @param name file name
	 * @param mediaTypr media type of file
	 * @param callback callback function
	 * @example
	 * bandwidth.Media.upload(client, "file.pdf", stream, "application/pdf", function(err){});
	 */
	upload : function (client, name, data, mediaType, callback) {
		if (arguments.length === 3) {
			callback = data;
			data = name;
			name = client;
			client = new Client();
			mediaType = null;
		}
		else if (arguments.length === 4) {
			callback = mediaType;
			if (client instanceof Client) {
				mediaType = null;
			}
			else {
				mediaType = data;
				data = name;
				name = client;
				client = new Client();
			}
		}

		var request = client.createRequest("put", client.concatUserPath(MEDIA_PATH) + "/" + encodeURIComponent(name));
		sendFile(request, data, mediaType, function (res) {
			client.checkResponse(res, callback);
		});
	},

	/**
	 * Downloads a media file you uploaded to given destination(file or stream)
	 * @param client Client instance
	 * @param name file name
	 * @param destination file name or stream to write downloaded file
	 * @returns request object
	 * @example
	 * bandwidth.Media.download(client, "file1.pdf", "/tmp/file1.pdf").end(function(err, res){});
	 */
	download : function (client, name, destination) {
		if (arguments.length <= 2) {
			if (client instanceof Client) {
				destination = null;
			}
			else {
				destination = name;
				name = client;
				client = new Client();
			}
		}

		var request = client.createRequest("get", client.concatUserPath(MEDIA_PATH) + "/" + encodeURIComponent(name));
		if (destination) {
			var stream = null;
			if (typeof destination === "string") {
				stream = fs.createWriteStream(destination);
			}
			else if (typeof destination.write === "function") {
				stream = destination;
			}

			if (stream) {
				return request.pipe(stream);
			}
		}

		return request;
	},

	/**
	 * Permanently deletes a media file you uploaded
	 * @param client Client instance
	 * @param name file name
	 * @param callback callback function
	 * @example
	 * bandwidth.delete(client, "file1.pdf", function(err){});
	 */
	delete : function (client, name, callback) {
		if (arguments.length === 2) {
			callback = name;
			name = client;
			client = new Client();
		}

		client.makeRequest("del", client.concatUserPath(MEDIA_PATH) + "/" + encodeURIComponent(name), callback);
	},

	/**
	 * Get information about a media file
	 * @param client Client instance
	 * @param name file name
	 * @param callback
	 * @example
	 * bandwidth.Media.getInfo(client, "file1.wav", function(err, res){});
	 */
	getInfo : function (client, name, callback) {
		if (arguments.length === 2) {
			callback = name;
			name = client;
			client = new Client();
		}

		var request = client.createRequest("head", client.concatUserPath(MEDIA_PATH) + "/" + encodeURIComponent(name));
		request.end(function (err, res) {
			if (res.ok) {
				return callback(null,
					{
						contentType   : res.type,
						contentLength : res.header["content-length"]
					});
			}

			return callback(new errors.BandwidthError("Http code " + res.status, res.status));
		});
	},

	/**
	 * Get a media file binary contents
	 * @param client Client instance
	 * @param name file name
	 * @param callback
	 * @example
	 * bandwidth.Media.getContents(client, "file1.wav", function(err, res){});
	 */
	getContents : function (client, name, callback) {
		if (arguments.length === 2) {
			callback = name;
			name = client;
			client = new Client();
		}

		var request = client.createRequest("get", client.concatUserPath(MEDIA_PATH) + "/" + encodeURIComponent(name));

		request.end(function (err, res) {
			// Receive chunks of data into an array of Buffers
			var buf = [];
			res.on("data", function(chunk) {
				buf.push(chunk);
			});
			// Response end
			res.on("end", function(){
				if (res.ok) {
					return callback(null,
						{
							contentType   : res.type,
							contentLength : res.header["content-length"],
							contentBody   : Buffer.concat(buf)
						});
				}
				// Not OK
				return callback(new errors.BandwidthError("Http code " + res.status, res.status));
			});
		});
	}
};
<commit_msg>Code style fixes<commit_after>"use strict";

var Client = require("./client");
var fs = require("fs");
var errors = require("./errors");
var MEDIA_PATH = "media";

function sendFile(request, file, mediaType, callback) {
	var stream = null;
	request.buffer().type(mediaType || "application/octet-stream");
	if (typeof file === "string") {
		stream = fs.createReadStream(file);
	}
	else if (Buffer.isBuffer(file)) {
		request.write(file);
		request.end(callback);
		return;
	}
	else if (typeof file.pipe === "function" && typeof file.read === "function" && typeof file.on === "function") {
		stream = file;
	}

	if (stream) {
		request.on("response", callback);
		stream.pipe(request);
		return;
	}

	callback({ statusCode : 400, text : "Invalid data to send", body : { message : "Invalid data to send" } });
}

module.exports = {
	/**
	 * Get a list of your media files
	 * @param client Client instance
	 * @param query query parameters
	 * @param callback callback function
	 * @example
	 * bandwidth.Media.list(client, function(err, list){});
	 */
	list : function (client, query, callback) {
		if (arguments.length === 1) {
			callback = client;
			client = new Client();
		}
		else if (arguments.length === 2) {
			callback = query;
			if (client instanceof Client) {
				query = {};
			}
			else {
				query = client;
				client = new Client();
			}
		}

		client.makeRequest("get", client.concatUserPath(MEDIA_PATH), query, callback);
	},

	/**
	 * Uploads a media file (or stream, or buffer) to the name you choose
	 * @param client Client instance
	 * @param name file name
	 * @param mediaTypr media type of file
	 * @param callback callback function
	 * @example
	 * bandwidth.Media.upload(client, "file.pdf", stream, "application/pdf", function(err){});
	 */
	upload : function (client, name, data, mediaType, callback) {
		if (arguments.length === 3) {
			callback = data;
			data = name;
			name = client;
			client = new Client();
			mediaType = null;
		}
		else if (arguments.length === 4) {
			callback = mediaType;
			if (client instanceof Client) {
				mediaType = null;
			}
			else {
				mediaType = data;
				data = name;
				name = client;
				client = new Client();
			}
		}

		var request = client.createRequest("put", client.concatUserPath(MEDIA_PATH) + "/" + encodeURIComponent(name));
		sendFile(request, data, mediaType, function (res) {
			client.checkResponse(res, callback);
		});
	},

	/**
	 * Downloads a media file you uploaded to given destination(file or stream)
	 * @param client Client instance
	 * @param name file name
	 * @param destination file name or stream to write downloaded file
	 * @returns request object
	 * @example
	 * bandwidth.Media.download(client, "file1.pdf", "/tmp/file1.pdf").end(function(err, res){});
	 */
	download : function (client, name, destination) {
		if (arguments.length <= 2) {
			if (client instanceof Client) {
				destination = null;
			}
			else {
				destination = name;
				name = client;
				client = new Client();
			}
		}

		var request = client.createRequest("get", client.concatUserPath(MEDIA_PATH) + "/" + encodeURIComponent(name));
		if (destination) {
			var stream = null;
			if (typeof destination === "string") {
				stream = fs.createWriteStream(destination);
			}
			else if (typeof destination.write === "function") {
				stream = destination;
			}

			if (stream) {
				return request.pipe(stream);
			}
		}

		return request;
	},

	/**
	 * Permanently deletes a media file you uploaded
	 * @param client Client instance
	 * @param name file name
	 * @param callback callback function
	 * @example
	 * bandwidth.delete(client, "file1.pdf", function(err){});
	 */
	delete : function (client, name, callback) {
		if (arguments.length === 2) {
			callback = name;
			name = client;
			client = new Client();
		}

		client.makeRequest("del", client.concatUserPath(MEDIA_PATH) + "/" + encodeURIComponent(name), callback);
	},

	/**
	 * Get information about a media file
	 * @param client Client instance
	 * @param name file name
	 * @param callback
	 * @example
	 * bandwidth.Media.getInfo(client, "file1.wav", function(err, res){});
	 */
	getInfo : function (client, name, callback) {
		if (arguments.length === 2) {
			callback = name;
			name = client;
			client = new Client();
		}

		var request = client.createRequest("head", client.concatUserPath(MEDIA_PATH) + "/" + encodeURIComponent(name));
		request.end(function (err, res) {
			if (res.ok) {
				return callback(null,
					{
						contentType   : res.type,
						contentLength : res.header["content-length"]
					});
			}

			return callback(new errors.BandwidthError("Http code " + res.status, res.status));
		});
	},

	/**
	 * Get a media file binary contents
	 * @param client Client instance
	 * @param name file name
	 * @param callback
	 * @example
	 * bandwidth.Media.getContents(client, "file1.wav", function(err, res){});
	 */
	getContents : function (client, name, callback) {
		if (arguments.length === 2) {
			callback = name;
			name = client;
			client = new Client();
		}

		var request = client.createRequest("get", client.concatUserPath(MEDIA_PATH) + "/" + encodeURIComponent(name));

		request.end(function (err, res) {
			// Receive chunks of data into an array of Buffers
			var buf = [];
			res.on("data", function (chunk) {
				buf.push(chunk);
			});
			// Response end
			res.on("end", function () {
				if (res.ok) {
					return callback(null,
						{
							contentType   : res.type,
							contentLength : res.header["content-length"],
							contentBody   : Buffer.concat(buf)
						});
				}
				// Not OK
				return callback(new errors.BandwidthError("Http code " + res.status, res.status));
			});
		});
	}
};
<|endoftext|>


<commit_before>"use strict";

var _require = require("./util");

const assertOk = _require.assertOk;

function mergeOptions(model, options) {
	model.name = options.name;
	Object.assign(model.fields, options.fields);
	Object.assign(model.computed, options.computed);
	Object.assign(model.methods, options.methods);
}

class Model {
	constructor(options) {
		options.fields = options.fields || {};
		options.computed = options.computed || {};
		options.methods = options.methods || {};

		this.$options = options;
		this.fields = {};
		this.computed = {};
		this.methods = {};

		if (this.$options.mixins) {
			this.$options.mixins.forEach(mixin => mergeOptions(this, mixin));
		}
		mergeOptions(this, options);
	}

	call(methodName, params = {}, context = {}) {
		assertOk(this.methods[methodName], "no-method: " + methodName, 404);
		return this.methods[methodName].apply(this, [params, context]);
	}

	get(value, fieldName, params = {}, context = {}) {
		if (this.computed[fieldName]) {
			return this.computed[fieldName].apply(this, [value, params, context]);
		}

		if (this.fields[fieldName]) {
			return value[fieldName];
		}
	}
}

class AnonymousModel {
	constructor(fields) {
		this.fields = fields;
		this.computed = {};
	}

	get(value, fieldName) {
		assertOk(this.fields[fieldName] != undefined, "no-field: " + fieldName, 400);
		return value[fieldName];
	}
}

module.exports = {
	Model,
	AnonymousModel
};<commit_msg>handle sync execption<commit_after>"use strict";

var _require = require("./util");

const assertOk = _require.assertOk;

function mergeOptions(model, options) {
	model.name = options.name;
	Object.assign(model.fields, options.fields);
	Object.assign(model.computed, options.computed);
	Object.assign(model.methods, options.methods);
}

class Model {
	constructor(options) {
		options.fields = options.fields || {};
		options.computed = options.computed || {};
		options.methods = options.methods || {};

		this.$options = options;
		this.fields = {};
		this.computed = {};
		this.methods = {};

		if (this.$options.mixins) {
			this.$options.mixins.forEach(mixin => mergeOptions(this, mixin));
		}
		mergeOptions(this, options);
	}

	call(methodName, params = {}, context = {}) {
		try {
			assertOk(this.methods[methodName], "no-method: " + methodName, 404);
			return this.methods[methodName].apply(this, [params, context]);
		} catch (e) {
			return Promise.reject(e);
		}
	}

	get(value, fieldName, params = {}, context = {}) {
		try {
			if (this.computed[fieldName]) {
				return this.computed[fieldName].apply(this, [value, params, context]);
			}

			if (this.fields[fieldName]) {
				return value[fieldName];
			}
		} catch (e) {
			return Promise.reject(e);
		}
	}
}

class AnonymousModel {
	constructor(fields) {
		this.fields = fields;
		this.computed = {};
	}

	get(value, fieldName) {
		assertOk(this.fields[fieldName] != undefined, "no-field: " + fieldName, 400);
		return value[fieldName];
	}
}

module.exports = {
	Model,
	AnonymousModel
};<|endoftext|>


<commit_before>'use strict';

const Objection = require('objection');

const internals = {};

module.exports = class SchwiftyModel extends Objection.Model {

    static get joiSchema() {}

    // Caches schema, with and without optional keys
    // Will create _schemaMemo and _optionalSchemaMemo properties
    static getJoiSchema(patch) {

        const schema = this._schemaMemo = this._schemaMemo || this.joiSchema;

        if (patch) {
            const patchSchema = this._patchSchemaMemo = this._patchSchemaMemo || internals.patchSchema(schema);
            return patchSchema;
        }

        return schema;
    }

    // Will create _jsonAttributesMemo properties
    static get jsonAttributes() {

        if (this._jsonAttributesMemo) {
            return this._jsonAttributesMemo;
        }

        const joiSchema = this.getJoiSchema();

        if (!joiSchema) {
            return null;
        }

        const schemaKeyDescs = joiSchema.describe().children || {};

        // Setting this._jsonAttributesMemo here.
        this.jsonAttributes = Object.keys(schemaKeyDescs).filter((field) => {

            const type = schemaKeyDescs[field].type;

            // These are the joi types we want to be parsed/serialized as json
            return (type === 'array') || (type === 'object');
        });

        return jsonAttributes;
    }

    /*
    This is here as a necessity because classes can't have
    a getter without the setter for a prop. Schwifty's Model
    classes don't implement a setter for jsonAttributes.

    behold. */
    static set jsonAttributes(value) {

        this._jsonAttributesMemo = value || [];
    }

    static parseJoiValidationError(validation) {

        return validation.error.details;
    }

    $validate(json, options) { // Note, in objection v0.7.x there is a new Validator interface

        json = json || this.$parseJson(this.$toJson(true));
        options = options || {};

        let joiSchema = this.constructor.getJoiSchema(options.patch);

        if (!joiSchema || options.skipValidation) {
            return json;
        }

        // Allow modification of schema, setting of options, etc.
        joiSchema = this.$beforeValidate(joiSchema, json, options);

        const validation = joiSchema.validate(json);

        if (validation.error) {
            const errors = SchwiftyModel.parseJoiValidationError(validation);
            throw new Objection.ValidationError(errors);
        }

        json = validation.value;

        this.$afterValidate(json, options);

        return json;
    }
};

internals.patchSchema = (schema) => {

    if (!schema) {
        return;
    }

    const keys = Object.keys(schema.describe().children || {});

    // Make all keys optional, do not enforce defaults

    if (keys.length) {
        schema = schema.optionalKeys(keys);
    }

    return schema.options({ noDefaults: true });
};
<commit_msg>Fix model :wrench:<commit_after>'use strict';

const Objection = require('objection');

const internals = {};

module.exports = class SchwiftyModel extends Objection.Model {

    static get joiSchema() {}

    // Caches schema, with and without optional keys
    // Will create _schemaMemo and _optionalSchemaMemo properties
    static getJoiSchema(patch) {

        const schema = this._schemaMemo = this._schemaMemo || this.joiSchema;

        if (patch) {
            const patchSchema = this._patchSchemaMemo = this._patchSchemaMemo || internals.patchSchema(schema);
            return patchSchema;
        }

        return schema;
    }

    // Will create _jsonAttributesMemo properties
    static get jsonAttributes() {

        if (this._jsonAttributesMemo) {
            return this._jsonAttributesMemo;
        }

        const joiSchema = this.getJoiSchema();

        if (!joiSchema) {
            return null;
        }

        const schemaKeyDescs = joiSchema.describe().children || {};

        // Setting this._jsonAttributesMemo here.
        this.jsonAttributes = Object.keys(schemaKeyDescs).filter((field) => {

            const type = schemaKeyDescs[field].type;

            // These are the joi types we want to be parsed/serialized as json
            return (type === 'array') || (type === 'object');
        });

        return this.jsonAttributes;
    }

    /*
    This is here as a necessity because classes can't have
    a getter without the setter for a prop. Schwifty's Model
    classes don't implement a setter for jsonAttributes.

    behold. */
    static set jsonAttributes(value) {

        this._jsonAttributesMemo = value || [];
    }

    static parseJoiValidationError(validation) {

        return validation.error.details;
    }

    $validate(json, options) { // Note, in objection v0.7.x there is a new Validator interface

        json = json || this.$parseJson(this.$toJson(true));
        options = options || {};

        let joiSchema = this.constructor.getJoiSchema(options.patch);

        if (!joiSchema || options.skipValidation) {
            return json;
        }

        // Allow modification of schema, setting of options, etc.
        joiSchema = this.$beforeValidate(joiSchema, json, options);

        const validation = joiSchema.validate(json);

        if (validation.error) {
            const errors = SchwiftyModel.parseJoiValidationError(validation);
            throw new Objection.ValidationError(errors);
        }

        json = validation.value;

        this.$afterValidate(json, options);

        return json;
    }
};

internals.patchSchema = (schema) => {

    if (!schema) {
        return;
    }

    const keys = Object.keys(schema.describe().children || {});

    // Make all keys optional, do not enforce defaults

    if (keys.length) {
        schema = schema.optionalKeys(keys);
    }

    return schema.options({ noDefaults: true });
};
<|endoftext|>


<commit_before>var q = require('q');
var assign = require('object-assign');
var bson = require('bson');
var joi = require('joi');
var etag = require('etag');
var debug = require('debug')('dozer:model');
var objectPath = require('object-path');
var dozer = require('dozer-client')
var defaults = require('defaults');
var clone = require('clone');
var util = require('util');
var EJSON = require('mongodb-extended-json');
var Immutable = require('./immutable');
Immutable.use(require('./defined-object'));
Immutable.use('array', require('./array'));
Immutable.use(Date, require('./date'));
Immutable.use(bson.ObjectId, require('./bson-objectId'));
Immutable.use(require('./object'));

function define (definition) {

  definition = defaults(definition, {
    properties: {},
    methods: {},
    virtuals:{}
  });

  if (!definition.collectionUri && !definition.abstract) {
    throw new Error('A model must have a collectionUri unless defined as abstract');
  }

  definition.properties._id = {
    type: 'objectid'
  };

  definition.properties._etag = {
    type: 'string'
  };

  definition.properties.__modified = {
    type: 'array',
    enumerable: false,
    default: []
  };

  definition._schema = _buildSchema(definition);

  return {

    create: function (data) {
      return _create(data, definition);
    },

    extend: function (superDef) {
      return _extend(definition, superDef);
    },

    isA: function (obj) {
      return Immutable.isImmutableType(obj, definition.name || 'object');
    },

    count: function (query, options) {
      query = assign({}, query, definition.where);
      options = options || {};
      options.count = true;
      options.query = query;
      var uri = definition.collectionUri;
      debug('counting ' + JSON.stringify(query) + ' in ' + uri);
      return dozer.get(uri, options)
        .then(function (result) {
          return result.count;
        }.bind(this));
    },

    find: function (query, options) {
      query = assign({}, query, definition.where);
      options = options || {};
      options.query = query;
      var uri = definition.collectionUri;
      debug('finding ' + JSON.stringify(query) + ' in ' + uri);
      return dozer.get(uri, options)
        .then(function (result) {
          return result.map(function (item) {
            return _create(item, definition);
          });
        }.bind(this));
    },

    findOne: function (query, options) {
      query = assign({}, query, definition.where);
      options = options || {};
      options.query = query;
      options.one = true;
      var uri = definition.collectionUri;
      debug('finding one' + JSON.stringify(query) + ' in ' + uri);
      return dozer.get(uri, options)
        .then(function (result) {
          if (!result) {
            return null;
          } else {
            return !result ? null : _create(result, definition);
          }
        }.bind(this));
    },

    update: function (query, update, options) {
      query = assign({}, query, definition.where);
      options = defaults(options, { autoSet: true });
      options.query = query;
      var uri = definition.collectionUri;
      if (options.autoSet) {
        update = { $set: update };
      }
      delete options.autoSet;
      debug('updating ' + JSON.stringify(query) + ' from ' + uri);
      return dozer.put(uri, update, options);
    },

    remove: function (query, options) {
      query = assign({}, query, definition.where);
      options = options || {};
      options.query = query;
      var uri = definition.collectionUri;
      debug('removing ' + JSON.stringify(query) + ' from ' + uri);
      return dozer.del(uri, options);
    },

    distinct: function (key, query, options) {
      query = assign({}, query, definition.where);
      options = options || {};
      var uri = definition.collectionUri;
      debug('finding distinct "' + key + '" ' + JSON.stringify(query) + ' from ' + uri);
      return dozer.distinct(uri, key, query, options);
    },

    aggregate: function (pipeline, options) {
      var uri = definition.collectionUri;
      debug('aggregating ' + JSON.stringify(pipeline) + ' from ' + uri);
      return dozer.aggregate(uri, pipeline, options);
    }

  };

};

function _create (data, definition) {

  var _markAsModified = function (obj, path) {
    if (Array.isArray(path)) {
      path = path.join('.');
    }
    var shouldAdd = true;
    obj.__modified = obj.__modified.filter(function (value) {
      shouldAdd = shouldAdd && !(path.indexOf(value + '.', 0) === 0);
      return !(value.indexOf(path + '.', 0) === 0);
    });
    if (shouldAdd) {
      obj.__modified.push(path);
    }
  };

  definition.methods.is = function (obj) {
    if (this === obj) { return true; }
    if ('undefined' === typeof obj || obj === null) { return false; }
    if (this.__type !== obj.__type) { return false; }
    if (!this._id || !obj._id) { return false; }
    return this._id.toObject().toHexString() === this._id.toObject().toHexString();
  };

  definition.methods.equals = function (obj) {
    if (this === obj) { return true; }
    return this.is(obj) && this._etag === obj._etag && !this.isModified() && !obj.isModified();
  };

  definition.methods.isNew = function () {
    return 'undefined' === typeof this._id;
  };

  definition.methods.isModified = function (path) {
    if (path) {
      if (Array.isArray(path)) {
        path = path.join('.');
      }
      for (var i = 0, l = this.__modified.length; i < l; i++) {
        var value = this.__modified[i];
        if (value === path || value.indexOf(path + '.', 0) === 0) {
          return true;
        }
      }
      return false;
    } else {
      return this.__modified.length > 0;
    }
  };

  definition.methods.getModifiedPaths = util.deprecate(function () {
    return this.__modified.toObject();
  }, 'Model.getModifiedPaths will be removed in a future release');

  definition.methods.get = function (path) {
    return objectPath.get(this, path);
  };

  definition.methods.set = function (pathOrObj, value) {
    return this.mutate(function () {
      if ('undefined' === typeof value) {
        assign(this, pathOrObj);
        Object.keys(pathOrObj).forEach(function (item) {
          _markAsModified(this, item);
        }.bind(this));
      } else {
        objectPath.set(this, pathOrObj, value);
        _markAsModified(this, pathOrObj);
      }
    });
  };

  definition.methods.del = function (path) {
    return this.mutate(function () {
      objectPath.del(this, path);
      _markAsModified(this, path);
    });
  };

  definition.methods.has = function (path) {
    return objectPath.has(this, path);
  };

  definition.methods.toJSON = function (options) {
    options = defaults(options, {
      virtuals: true,
      extended: true
    });
    function addVirtuals (def, obj) {
      if (def.virtuals) {
        Object.keys(def.virtuals).forEach(function (name) {
          obj[name] = def.virtuals[name].call(obj);
        }.bind(this));
      }
      if (def.properties) {
        Object.keys(obj).forEach(function (name) {
          if (!def.properties[name]) { return; }
          addVirtuals(def.properties[name], obj[name]);
        });
      }
    }
    var json = clone(data);
    if (options.virtuals) {
      addVirtuals(definition, json);
    }
    return options.extended ? EJSON.inflate(json) : json;
  };

  definition.methods.validate = function (options) {
    var deferred = q.defer();
    options = defaults(options, {
      abortEarly: false,
      convert: false,
      allowUnknown: false,
      skipFunctions: true,
      stripUnknown: false,
    });
    joi.validate(this.toObject(), definition._schema, options, function (err, value) {
      if (err) { return deferred.reject(err); }
      deferred.resolve(value);
    });
    return deferred.promise;
  };

  definition.methods.save = function (options) {
    if (!this.isNew() && !this.isModified()) {
      return q.resolve(this);
    }
    return this.validate(options)
      .then(function (value) {
        var obj = this.toObject();
        var newEtag = etag(JSON.stringify(obj));
        if (!this.isNew()) {
          var query = { _etag: this._etag };
          var set = { _etag: newEtag };
          this.__modified.forEach(function (path) {
            set[path] = obj[path];
          });
          var update = { $set: set };
          var uri = definition.collectionUri + '/' + this._id.toString();
          debug('updating ' + uri + ': ' + JSON.stringify(update));
          return dozer.put(uri, update, { query: query })
            .then(function (result) {
              debug('update into ' + definition.collectionUri + ' successful', result);
              return this.set({
                _etag: newEtag,
                __modified: []
              });
            }.bind(this));
        } else {
          var uri = definition.collectionUri;
          obj._etag = newEtag;
          debug('inserting into ' + uri + ': ' + JSON.stringify(obj));
          return dozer.post(uri, obj)
            .then(function (result) {
              debug('insert into ' + definition.collectionUri + ' successful', result);
              var obj = Array.isArray(result.ops) ? result.ops[0] : result.ops;
              obj.__modified = [];
              return _create(obj, definition);
            }.bind(this));
        }
      }.bind(this));
  };

  definition.methods.remove = function (options) {
    var uri = definition.collectionUri;
    var query = { _id: this._id, _etag: this._etag };
    debug('removing ' + JSON.stringify(query) + ' in ' + uri);
    return dozer.del(uri, { query: query })
      .then(function (result) {
        debug('remove from ' + uri + ' successful');
        return result;
      }.bind(this));
  };

  return Immutable.create(data, { definition: definition });
};

function _extend (definition, superDef) {
  var newDef = clone(definition);
  newDef.properties = defaults(newDef.properties, superDef.properties || {});
  newDef.methods = defaults(newDef.methods, superDef.methods || {});
  newDef.virtuals = defaults(newDef.virtuals, superDef.virtuals || {});
  return define(newDef);
};

module.exports = {
  define: define
};

function _buildSchema (definition) {
  var schema = {};
  for (var p in definition.properties) {
    var propertyDef = definition.properties[p];
    if (propertyDef.type !== 'virtual') {
      schema[p] = _buildPropertySchema(p, propertyDef);
    }
  }
  return schema;
}

function _buildPropertySchema (name, propertyDef) {
  var schema = null;
  switch (propertyDef.type.trim().toLowerCase()) {
    case 'array':
      schema = joi.array();
      if ('undefined' !== typeof propertyDef.items) {
        schema = schema.items(_buildPropertySchema(name + '.items', propertyDef.items));
      }
      if ('undefined' !== typeof propertyDef.sparse) { schema = schema.sparse(propertyDef.sparse); }
      if (propertyDef.unique) { schema = schema.unique(); }
      break;
    case 'binary':
      schema = joi.binary();
      if ('undefined' !== typeof propertyDef.encoding) { schema = schema.encoding(propertyDef.encoding); }
      break;
    case 'boolean':
      schema = joi.boolean();
      break;
    case 'date':
      schema = joi.date();
      if (propertyDef.iso) { schema = schema.iso(); }
      if ('undefined' !== typeof propertyDef.format) { schema = schema.format(propertyDef.format); }
      break;
    case 'number':
      schema = joi.number();
      if ('undefined' !== typeof propertyDef.greater) { schema = schema.greater(propertyDef.greater); }
      if ('undefined' !== typeof propertyDef.less) { schema = schema.less(propertyDef.less); }
      if ('undefined' !== typeof propertyDef.integer) { schema = schema.integer(propertyDef.integer); }
      if ('undefined' !== typeof propertyDef.precision) { schema = schema.precision(propertyDef.precision); }
      if ('undefined' !== typeof propertyDef.multiple) { schema = schema.multiple(propertyDef.multiple); }
      if (propertyDef.negative) { schema = schema.negative(); }
      if (propertyDef.positive) { schema = schema.positive(); }
      break;
    case 'object':
      schema = joi.object();
      if ('undefined' !== typeof propertyDef.constr) {
        schema = schema.type(propertyDef.constr);
      }
      if ('undefined' !== typeof propertyDef.properties) {
        var keys = {};
        for (var p in propertyDef.properties) {
          if (propertyDef.properties[p].type !== 'virtual') {
            keys[p] = _buildPropertySchema(name + '.' + p, propertyDef.properties[p]);
          }
        }
        schema = schema.keys(keys);
      }
      if ('undefined' !== typeof propertyDef.unknown) { schema = schema.unknown(propertyDef.unknown); }
      if ('undefined' !== typeof propertyDef.rename) { schema = schema.rename(propertyDef.rename); }
      if ('undefined' !== typeof propertyDef.requiredKeys) { schema = schema.requiredKeys(propertyDef.requiredKeys); }
      break;
    case 'string':
      schema = joi.string();
      if (propertyDef.insensitive) { schema = schema.insensitive(); }
      if (propertyDef.creditCard) { schema = schema.creditCard(); }
      if ('undefined' !== typeof propertyDef.regex) { schema = schema.regex(propertyDef.regex); }
      if (propertyDef.alphanum) { schema = schema.alphanum(); }
      if (propertyDef.token) { schema = schema.token(); }
      if (propertyDef.email) { schema = schema.email(); }
      if (propertyDef.guid) { schema = schema.guid(); }
      if (propertyDef.hostname) { schema = schema.hostname(); }
      if (propertyDef.lowercase) { schema = schema.lowercase(); }
      if (propertyDef.uppercase) { schema = schema.uppercase(); }
      if (propertyDef.trim) { schema = schema.trim(); }
      break;
    case 'objectid':
      schema = joi.object().type(bson.ObjectId);
    case 'any':
    case '*':
      schema = joi.any();
      break;
    default:
      throw new Error('Invalid type (' + propertyDef.type + ') for property ' + name);
  }
  if ('undefined' !== typeof propertyDef.min) { schema = schema.min(propertyDef.min); }
  if ('undefined' !== typeof propertyDef.max) { schema = schema.max(propertyDef.max); }
  if ('undefined' !== typeof propertyDef.length) { schema = schema.length(propertyDef.length); }
  if ('undefined' !== typeof propertyDef.allow) { schema = schema.allow(propertyDef.allow); }
  if ('undefined' !== typeof propertyDef.valid) { schema = schema.valid(propertyDef.valid); }
  if ('undefined' !== typeof propertyDef.invalid) { schema = schema.invalid(propertyDef.invalid); }
  if (propertyDef.forbidden) { schema = schema.forbidden(); }
  if (propertyDef.strip) { schema = schema.strip(); }
  if (propertyDef.required) { schema = schema.required(); }
  if ('undefined' !== typeof propertyDef.strict) { schema = schema.strict(propertyDef.strict); }
  if ('undefined' !== typeof propertyDef.label) { schema = schema.label(propertyDef.label); }
  if (propertyDef.raw) { schema = schema.raw(); }
  if ('undefined' !== typeof propertyDef.default) { schema = schema.default(propertyDef.default, 'default'); }
  return schema;

}
<commit_msg>fixes mode.extend bug<commit_after>var q = require('q');
var assign = require('object-assign');
var bson = require('bson');
var joi = require('joi');
var etag = require('etag');
var debug = require('debug')('dozer:model');
var objectPath = require('object-path');
var dozer = require('dozer-client')
var defaults = require('defaults');
var clone = require('clone');
var util = require('util');
var EJSON = require('mongodb-extended-json');
var Immutable = require('./immutable');
Immutable.use(require('./defined-object'));
Immutable.use('array', require('./array'));
Immutable.use(Date, require('./date'));
Immutable.use(bson.ObjectId, require('./bson-objectId'));
Immutable.use(require('./object'));

function define (definition) {

  definition = defaults(definition, {
    properties: {},
    methods: {},
    virtuals:{}
  });

  if (!definition.collectionUri && !definition.abstract) {
    throw new Error('A model must have a collectionUri unless defined as abstract');
  }

  definition.properties._id = {
    type: 'objectid'
  };

  definition.properties._etag = {
    type: 'string'
  };

  definition.properties.__modified = {
    type: 'array',
    enumerable: false,
    default: []
  };

  definition._schema = _buildSchema(definition);

  return {

    create: function (data) {
      return _create(data, definition);
    },

    extend: function (subDefinition) {
      return _extend(subDefinition, definition);
    },

    isA: function (obj) {
      return Immutable.isImmutableType(obj, definition.name || 'object');
    },

    count: function (query, options) {
      query = assign({}, query, definition.where);
      options = options || {};
      options.count = true;
      options.query = query;
      var uri = definition.collectionUri;
      debug('counting ' + JSON.stringify(query) + ' in ' + uri);
      return dozer.get(uri, options)
        .then(function (result) {
          return result.count;
        }.bind(this));
    },

    find: function (query, options) {
      query = assign({}, query, definition.where);
      options = options || {};
      options.query = query;
      var uri = definition.collectionUri;
      debug('finding ' + JSON.stringify(query) + ' in ' + uri);
      return dozer.get(uri, options)
        .then(function (result) {
          return result.map(function (item) {
            return _create(item, definition);
          });
        }.bind(this));
    },

    findOne: function (query, options) {
      query = assign({}, query, definition.where);
      options = options || {};
      options.query = query;
      options.one = true;
      var uri = definition.collectionUri;
      debug('finding one' + JSON.stringify(query) + ' in ' + uri);
      return dozer.get(uri, options)
        .then(function (result) {
          if (!result) {
            return null;
          } else {
            return !result ? null : _create(result, definition);
          }
        }.bind(this));
    },

    update: function (query, update, options) {
      query = assign({}, query, definition.where);
      options = defaults(options, { autoSet: true });
      options.query = query;
      var uri = definition.collectionUri;
      if (options.autoSet) {
        update = { $set: update };
      }
      delete options.autoSet;
      debug('updating ' + JSON.stringify(query) + ' from ' + uri);
      return dozer.put(uri, update, options);
    },

    remove: function (query, options) {
      query = assign({}, query, definition.where);
      options = options || {};
      options.query = query;
      var uri = definition.collectionUri;
      debug('removing ' + JSON.stringify(query) + ' from ' + uri);
      return dozer.del(uri, options);
    },

    distinct: function (key, query, options) {
      query = assign({}, query, definition.where);
      options = options || {};
      var uri = definition.collectionUri;
      debug('finding distinct "' + key + '" ' + JSON.stringify(query) + ' from ' + uri);
      return dozer.distinct(uri, key, query, options);
    },

    aggregate: function (pipeline, options) {
      var uri = definition.collectionUri;
      debug('aggregating ' + JSON.stringify(pipeline) + ' from ' + uri);
      return dozer.aggregate(uri, pipeline, options);
    }

  };

};

function _create (data, definition) {

  var _markAsModified = function (obj, path) {
    if (Array.isArray(path)) {
      path = path.join('.');
    }
    var shouldAdd = true;
    obj.__modified = obj.__modified.filter(function (value) {
      shouldAdd = shouldAdd && !(path.indexOf(value + '.', 0) === 0);
      return !(value.indexOf(path + '.', 0) === 0);
    });
    if (shouldAdd) {
      obj.__modified.push(path);
    }
  };

  definition.methods.is = function (obj) {
    if (this === obj) { return true; }
    if ('undefined' === typeof obj || obj === null) { return false; }
    if (this.__type !== obj.__type) { return false; }
    if (!this._id || !obj._id) { return false; }
    return this._id.toObject().toHexString() === this._id.toObject().toHexString();
  };

  definition.methods.equals = function (obj) {
    if (this === obj) { return true; }
    return this.is(obj) && this._etag === obj._etag && !this.isModified() && !obj.isModified();
  };

  definition.methods.isNew = function () {
    return 'undefined' === typeof this._id;
  };

  definition.methods.isModified = function (path) {
    if (path) {
      if (Array.isArray(path)) {
        path = path.join('.');
      }
      for (var i = 0, l = this.__modified.length; i < l; i++) {
        var value = this.__modified[i];
        if (value === path || value.indexOf(path + '.', 0) === 0) {
          return true;
        }
      }
      return false;
    } else {
      return this.__modified.length > 0;
    }
  };

  definition.methods.getModifiedPaths = util.deprecate(function () {
    return this.__modified.toObject();
  }, 'Model.getModifiedPaths will be removed in a future release');

  definition.methods.get = function (path) {
    return objectPath.get(this, path);
  };

  definition.methods.set = function (pathOrObj, value) {
    return this.mutate(function () {
      if ('undefined' === typeof value) {
        assign(this, pathOrObj);
        Object.keys(pathOrObj).forEach(function (item) {
          _markAsModified(this, item);
        }.bind(this));
      } else {
        objectPath.set(this, pathOrObj, value);
        _markAsModified(this, pathOrObj);
      }
    });
  };

  definition.methods.del = function (path) {
    return this.mutate(function () {
      objectPath.del(this, path);
      _markAsModified(this, path);
    });
  };

  definition.methods.has = function (path) {
    return objectPath.has(this, path);
  };

  definition.methods.toJSON = function (options) {
    options = defaults(options, {
      virtuals: true,
      extended: true
    });
    function addVirtuals (def, obj) {
      if (def.virtuals) {
        Object.keys(def.virtuals).forEach(function (name) {
          obj[name] = def.virtuals[name].call(obj);
        }.bind(this));
      }
      if (def.properties) {
        Object.keys(obj).forEach(function (name) {
          if (!def.properties[name]) { return; }
          addVirtuals(def.properties[name], obj[name]);
        });
      }
    }
    var json = clone(data);
    if (options.virtuals) {
      addVirtuals(definition, json);
    }
    return options.extended ? EJSON.inflate(json) : json;
  };

  definition.methods.validate = function (options) {
    var deferred = q.defer();
    options = defaults(options, {
      abortEarly: false,
      convert: false,
      allowUnknown: false,
      skipFunctions: true,
      stripUnknown: false,
    });
    joi.validate(this.toObject(), definition._schema, options, function (err, value) {
      if (err) { return deferred.reject(err); }
      deferred.resolve(value);
    });
    return deferred.promise;
  };

  definition.methods.save = function (options) {
    if (!this.isNew() && !this.isModified()) {
      return q.resolve(this);
    }
    return this.validate(options)
      .then(function (value) {
        var obj = this.toObject();
        var newEtag = etag(JSON.stringify(obj));
        if (!this.isNew()) {
          var query = { _etag: this._etag };
          var set = { _etag: newEtag };
          this.__modified.forEach(function (path) {
            set[path] = obj[path];
          });
          var update = { $set: set };
          var uri = definition.collectionUri + '/' + this._id.toString();
          debug('updating ' + uri + ': ' + JSON.stringify(update));
          return dozer.put(uri, update, { query: query })
            .then(function (result) {
              debug('update into ' + definition.collectionUri + ' successful', result);
              return this.set({
                _etag: newEtag,
                __modified: []
              });
            }.bind(this));
        } else {
          var uri = definition.collectionUri;
          obj._etag = newEtag;
          debug('inserting into ' + uri + ': ' + JSON.stringify(obj));
          return dozer.post(uri, obj)
            .then(function (result) {
              debug('insert into ' + definition.collectionUri + ' successful', result);
              var obj = Array.isArray(result.ops) ? result.ops[0] : result.ops;
              obj.__modified = [];
              return _create(obj, definition);
            }.bind(this));
        }
      }.bind(this));
  };

  definition.methods.remove = function (options) {
    var uri = definition.collectionUri;
    var query = { _id: this._id, _etag: this._etag };
    debug('removing ' + JSON.stringify(query) + ' in ' + uri);
    return dozer.del(uri, { query: query })
      .then(function (result) {
        debug('remove from ' + uri + ' successful');
        return result;
      }.bind(this));
  };

  return Immutable.create(data, { definition: definition });
};

function _extend (definition, superDef) {
  var newDef = clone(definition);
  if (!newDef.collectionUri) {
    newDef.collectionUri = superDef.collectionUri;
  }
  newDef.properties = defaults(newDef.properties, superDef.properties || {});
  newDef.methods = defaults(newDef.methods, superDef.methods || {});
  newDef.virtuals = defaults(newDef.virtuals, superDef.virtuals || {});
  return define(newDef);
};

module.exports = {
  define: define
};

function _buildSchema (definition) {
  var schema = {};
  for (var p in definition.properties) {
    var propertyDef = definition.properties[p];
    if (propertyDef.type !== 'virtual') {
      schema[p] = _buildPropertySchema(p, propertyDef);
    }
  }
  return schema;
}

function _buildPropertySchema (name, propertyDef) {
  var schema = null;
  switch (propertyDef.type.trim().toLowerCase()) {
    case 'array':
      schema = joi.array();
      if ('undefined' !== typeof propertyDef.items) {
        schema = schema.items(_buildPropertySchema(name + '.items', propertyDef.items));
      }
      if ('undefined' !== typeof propertyDef.sparse) { schema = schema.sparse(propertyDef.sparse); }
      if (propertyDef.unique) { schema = schema.unique(); }
      break;
    case 'binary':
      schema = joi.binary();
      if ('undefined' !== typeof propertyDef.encoding) { schema = schema.encoding(propertyDef.encoding); }
      break;
    case 'boolean':
      schema = joi.boolean();
      break;
    case 'date':
      schema = joi.date();
      if (propertyDef.iso) { schema = schema.iso(); }
      if ('undefined' !== typeof propertyDef.format) { schema = schema.format(propertyDef.format); }
      break;
    case 'number':
      schema = joi.number();
      if ('undefined' !== typeof propertyDef.greater) { schema = schema.greater(propertyDef.greater); }
      if ('undefined' !== typeof propertyDef.less) { schema = schema.less(propertyDef.less); }
      if ('undefined' !== typeof propertyDef.integer) { schema = schema.integer(propertyDef.integer); }
      if ('undefined' !== typeof propertyDef.precision) { schema = schema.precision(propertyDef.precision); }
      if ('undefined' !== typeof propertyDef.multiple) { schema = schema.multiple(propertyDef.multiple); }
      if (propertyDef.negative) { schema = schema.negative(); }
      if (propertyDef.positive) { schema = schema.positive(); }
      break;
    case 'object':
      schema = joi.object();
      if ('undefined' !== typeof propertyDef.constr) {
        schema = schema.type(propertyDef.constr);
      }
      if ('undefined' !== typeof propertyDef.properties) {
        var keys = {};
        for (var p in propertyDef.properties) {
          if (propertyDef.properties[p].type !== 'virtual') {
            keys[p] = _buildPropertySchema(name + '.' + p, propertyDef.properties[p]);
          }
        }
        schema = schema.keys(keys);
      }
      if ('undefined' !== typeof propertyDef.unknown) { schema = schema.unknown(propertyDef.unknown); }
      if ('undefined' !== typeof propertyDef.rename) { schema = schema.rename(propertyDef.rename); }
      if ('undefined' !== typeof propertyDef.requiredKeys) { schema = schema.requiredKeys(propertyDef.requiredKeys); }
      break;
    case 'string':
      schema = joi.string();
      if (propertyDef.insensitive) { schema = schema.insensitive(); }
      if (propertyDef.creditCard) { schema = schema.creditCard(); }
      if ('undefined' !== typeof propertyDef.regex) { schema = schema.regex(propertyDef.regex); }
      if (propertyDef.alphanum) { schema = schema.alphanum(); }
      if (propertyDef.token) { schema = schema.token(); }
      if (propertyDef.email) { schema = schema.email(); }
      if (propertyDef.guid) { schema = schema.guid(); }
      if (propertyDef.hostname) { schema = schema.hostname(); }
      if (propertyDef.lowercase) { schema = schema.lowercase(); }
      if (propertyDef.uppercase) { schema = schema.uppercase(); }
      if (propertyDef.trim) { schema = schema.trim(); }
      break;
    case 'objectid':
      schema = joi.object().type(bson.ObjectId);
    case 'any':
    case '*':
      schema = joi.any();
      break;
    default:
      throw new Error('Invalid type (' + propertyDef.type + ') for property ' + name);
  }
  if ('undefined' !== typeof propertyDef.min) { schema = schema.min(propertyDef.min); }
  if ('undefined' !== typeof propertyDef.max) { schema = schema.max(propertyDef.max); }
  if ('undefined' !== typeof propertyDef.length) { schema = schema.length(propertyDef.length); }
  if ('undefined' !== typeof propertyDef.allow) { schema = schema.allow(propertyDef.allow); }
  if ('undefined' !== typeof propertyDef.valid) { schema = schema.valid(propertyDef.valid); }
  if ('undefined' !== typeof propertyDef.invalid) { schema = schema.invalid(propertyDef.invalid); }
  if (propertyDef.forbidden) { schema = schema.forbidden(); }
  if (propertyDef.strip) { schema = schema.strip(); }
  if (propertyDef.required) { schema = schema.required(); }
  if ('undefined' !== typeof propertyDef.strict) { schema = schema.strict(propertyDef.strict); }
  if ('undefined' !== typeof propertyDef.label) { schema = schema.label(propertyDef.label); }
  if (propertyDef.raw) { schema = schema.raw(); }
  if ('undefined' !== typeof propertyDef.default) { schema = schema.default(propertyDef.default, 'default'); }
  return schema;

}
<|endoftext|>


<commit_before>var util = require('util');
var async = require('async');
var _ = require('underscore');
var modelIndex = 'nodes';

function Model(seraphDb, type) {
  this.type = type;
  this.db = seraphDb;
  this.fields = [];
  this.events = {
    validate: [],
    beforeSave: [],
    afterSave: [],
    prepare: [],
    index: []
  };

  var self = this;
  this.on('prepare', function whitelist(obj, callback) {
    if (!Array.isArray(self.fields) || !self.fields.length) {
      callback(null, obj);
    } else {
      callback(null, _.pick(obj, self.fields.concat([self.db.options.id])));
    }
  });

  this.on('index', function(object, callback) {
    self.db.index(modelIndex, object, 'type', self.type, function(err) {
      if (err) return callback(err);
      callback(null, object);
    });
  });
}

Model.prototype.save = function(object, callback) {
  var self = this;
  async.waterfall([
    this.triggerTransformEvent.bind(this, 'prepare', object),
    this.triggerEvent.bind(this, 'validate'),
    this.triggerTransformEvent.bind(this, 'beforeSave'),
    this.db.save.bind(this.db),
    this.triggerEvent.bind(this, 'index'),
    this.triggerEvent.bind(this, 'afterSave')
  ], callback);
}

Model.prototype.prepare = function(obj, cb) {
  this.triggerTransformEvent('prepare', obj, cb);
};

Model.prototype.validate = function(obj, cb) {
  this.triggerEvent('validate', obj, cb);
};

Model.prototype.index = function(obj, cb) {
  this.triggerEvent('index', obj, cb);
};

Model.prototype.on = function(event, action) {
  if (!this.events[event]) throw new Error("No such event - " + event);
  this.events[event].push(action);
};

Model.prototype.triggerEvent = function(event, object, callback) {
  if (!this.events[event].length) {
    callback(null, object);
  } else {
    async.forEach(this.events.validate, function(validator, callback) {
      validator(object, callback);
    }, function(err) {
      callback(err, object);
    });
  }
}

Model.prototype.triggerTransformEvent = function(event, object, callback) {
  if (!this.events[event].length) {
    callback(null, object);
  } else {
    var seed = function(cb) {
      cb(null, _.clone(object));
    };
    async.waterfall([seed].concat(this.events[event]), callback);
  }
}

Model.prototype.findAll = function(callback) {
  this.db.index.read(modelIndex, 'type', this.type, callback);
}

Model.prototype.where = function(predicate, any, callback) {
  if (typeof any === 'function') {
    callback = any;
    any = false;
  }

  this.db.find(predicate, any, this.cypherStart(), callback);
}

Model.prototype.cypherStart = function() {
  return 'node:' + modelIndex + '(type = "' + this.type + '")';
}

module.exports = function createSeraphModel(db, type) {
  return new Model(db, type);
};
<commit_msg>Took away callbacks for afterSave and beforeSave events. Closes #12<commit_after>var util = require('util');
var async = require('async');
var _ = require('underscore');
var modelIndex = 'nodes';

function Model(seraphDb, type) {
  this.type = type;
  this.db = seraphDb;
  this.fields = [];
  this.events = {
    validate: [],
    beforeSave: [],
    afterSave: [],
    prepare: [],
    index: []
  };

  var self = this;
  this.on('prepare', function whitelist(obj, callback) {
    if (!Array.isArray(self.fields) || !self.fields.length) {
      callback(null, obj);
    } else {
      callback(null, _.pick(obj, self.fields.concat([self.db.options.id])));
    }
  });

  this.on('index', function(object, callback) {
    self.db.index(modelIndex, object, 'type', self.type, function(err) {
      if (err) return callback(err);
      callback(null, object);
    });
  });
}

Model.prototype.save = function(object, callback) {
  var self = this;
  async.waterfall([
    this.triggerTransformEvent.bind(this, 'prepare', object),
    this.triggerProgressionEvent.bind(this, 'validate'),
    this.triggerEvent.bind(this, 'beforeSave'),
    this.db.save.bind(this.db),
    this.triggerProgressionEvent.bind(this, 'index'),
    this.triggerEvent.bind(this, 'afterSave')
  ], callback);
}

Model.prototype.prepare = function(obj, cb) {
  this.triggerTransformEvent('prepare', obj, cb);
};

Model.prototype.validate = function(obj, cb) {
  this.triggerProgressionEvent('validate', obj, cb);
};

Model.prototype.index = function(obj, cb) {
  this.triggerProgressionEvent('index', obj, cb);
};

Model.prototype.on = function(event, action) {
  if (!this.events[event]) throw new Error("No such event - " + event);
  this.events[event].push(action);
};

Model.prototype.triggerEvent = function(event, object, callback) {
  if (this.events[event].length) {
    this.events[event].forEach(function(listener) {
      listener(object);
    });
  }
  callback(null, object);
};

Model.prototype.triggerProgressionEvent = function(event, object, callback) {
  if (!this.events[event].length) {
    callback(null, object);
  } else {
    async.forEach(this.events[event], function(listener, callback) {
      listener(object, callback);
    }, function(err) {
      callback(err, object);
    });
  }
}

Model.prototype.triggerTransformEvent = function(event, object, callback) {
  if (!this.events[event].length) {
    callback(null, object);
  } else {
    var seed = function(cb) {
      cb(null, _.clone(object));
    };
    async.waterfall([seed].concat(this.events[event]), callback);
  }
}

Model.prototype.findAll = function(callback) {
  this.db.index.read(modelIndex, 'type', this.type, callback);
}

Model.prototype.where = function(predicate, any, callback) {
  if (typeof any === 'function') {
    callback = any;
    any = false;
  }

  this.db.find(predicate, any, this.cypherStart(), callback);
}

Model.prototype.cypherStart = function() {
  return 'node:' + modelIndex + '(type = "' + this.type + '")';
}

module.exports = function createSeraphModel(db, type) {
  return new Model(db, type);
};
<|endoftext|>


<commit_before><commit_msg>enhance(task): add support for namespaces in core media transformation<commit_after><|endoftext|>


<commit_before>"use strict";

console.log('month file is running');

let currentMonth = function () {
    var date = new Date();
    console.log('date', date);

    //Month
    var month = new Array();
    month[0] = 'January';
    var currentMonth = month[date.getMonth()];

    //Year
    var currentYear = date.getFullYear();

    //calendar spaces
    var headSpaces;

    //Output
    var output = "    " + currentMonth + " " + currentYear + "\n" +
      "Su Mo Tu We Th Fr Sa\n";
    console.log(output);
}

module.exports = {
  currentMonth: currentMonth
}
<commit_msg>added function that gets total of days of current month<commit_after>"use strict";

console.log('month file is running');

var daysString;

//Getting the number of days in current month
let daysInMonth = function (month, year) {
    var totalDays = new Date(year, month, 0).getDate();
    var days = [];

    for (var i = 1; i <= totalDays; i++) {
      days.push(i);
     }
    daysString = days.toString().replace(/,/g, " ");
    console.log('daysString', daysString);

    return daysString;
}

let currentMonth = function () {
    var date = new Date();
    console.log('date', date);

    //Month
    var month = new Array();
    month[1] = 'January';
    var currentMonth = month[date.getMonth()+1];

    //Year
    var currentYear = date.getFullYear();

    //days
    var monthNumb = date.getMonth()+1;
    daysInMonth(monthNumb, currentYear);

    //Output
    console.log('******THIS IS MY CONSOLE.LOG******');
    var output = "    " + currentMonth + " " + currentYear + "\n" +
      "Su Mo Tu We Th Fr Sa\n" + daysString;
    console.log(output);

}

module.exports = {
  currentMonth: currentMonth
}
<|endoftext|>


<commit_before>"use strict";

console.log("is the month file firing?");
<commit_msg>I can create the header, but I hate using a switch<commit_after>"use strict";

function createMonthHeader (year, month) {
  switch (month) {
    case 3:
        return `          March ${year}\n`;
        break;
    case 4:
        return `          April ${year}\n`;
        break;
    case 5:
        return `          May ${year}\n`;
        break;
    case 6:
        return `          June ${year}\n`;
        break;
    case 7:
        return `          July ${year}\n`;
        break;
    case 8:
        return `          August ${year}\n`;
        break;
    case 9:
        return `          September ${year}\n`;
        break;
    case 10:
        return `          October ${year}\n`;
        break;
    case 11:
        return `          November ${year}\n`;
        break;
    case 12:
        return `          December ${year}\n`;
        break;
    case 13:
        return `          January ${year}\n`;
        break;
    case 14:
        return `          February ${year}\n`;
        break;
    default:
        return "Error";
  }
}

console.log(createMonthHeader(2016, 14));

module.exports = {
  createMonthHeader: createMonthHeader
}
<|endoftext|>


<commit_before>var _ = require('lodash');
var Pty = require('node-pty');
var Fs = require('fs');
var Path = require('path');
var Utility = require('./utility.js');
var ShellQuote = require('shell-quote');
var StripAnsi = require('strip-ansi');

class Motel {
  constructor({
    state,
    env,
    onStateChange
  }) {
    this._env = env;
    this._state = state;
    this._sessions = [];
    this._onStateChange = onStateChange;
    this._applicationLocks = {};
    this._terminals = {};

    if (!this._state.applications) {
      this._state.applications = [];
      this._onStateChange();
      this._broadcastStates();
    }
  }

  _lockApplication(application, callback) {
    var callbackError;
    return Promise.resolve()
      .then(() => Utility.whilePromise(() => this._applicationLocks[application.name]))
      .then(() => this._applicationLocks[application.name] = true)
      .then(() => this._broadcastStates())
      .then(() => Promise.resolve()
        .then(() => callback())
        .catch(error => callbackError = error)
      )
      .then(() => this._applicationLocks[application.name] = false)
      .then(() => this._broadcastStates())
      .then(() => callbackError && Promise.reject(callbackError));
  }

  getApplicationPort(hostname) {
    var application = _.find(this._state.applications, a =>
      hostname == `${a.name}.dev` ||
      _.endsWith(hostname, `.${a.name}.dev`)
    );
    return Promise.resolve()
      .then(() =>
        application && this._ensureApplicationUp(application)
        .then(() => application.port)
      );
  }

  _doActionResizeTerminal(parameters, session) {
    session.terminalCols = parameters.cols;
    session.terminalRows = parameters.rows;

    var terminal = this._terminals[parameters.applicationName];

    if (!terminal) return;
    terminal.pty.resize(
      _.min(this._sessions.map(s => s.terminalCols)),
      _.min(this._sessions.map(s => s.terminalRows))
    );
  }

  _doActionInputTerminal(parameters) {
    var terminal = this._terminals[parameters.applicationName];

    if (!terminal) return;
    terminal.pty.write(parameters.dataString);
  }

  _doActionStartApplication(parameters) {
    var application = _.find(this._state.applications, a => a.name == parameters.applicationName);
    if (!application) return;

    return Promise.resolve()
      .then(() => this._ensureApplicationUp(application))
      .catch(error => this._broadcastMessage('danger', error.message));
  }

  _doActionStopApplication(parameters) {
    var application = _.find(this._state.applications, a => a.name == parameters.applicationName);
    if (!application) return;

    return Promise.resolve()
      .then(() => this._ensureApplicationDown(application))
      .then(error => this._broadcastMessage('success', 'Application stopped.'))
      .catch(error => this._broadcastMessage('danger', error.message));
  }

  _doActionRestartApplication(parameters) {
    var application = _.find(this._state.applications, a => a.name == parameters.applicationName);
    if (!application) return;

    return Promise.resolve()
      .then(() => this._ensureApplicationDown(application))
      .then(() => this._ensureApplicationUp(application))
      .then(error => this._broadcastMessage('success', 'Application restarted.'))
      .catch(error => this._broadcastMessage('danger', error.message));
  }

  _doActionCreateApplication(parameters, session) {
    var application = _.find(this._state.applications, a => a.name == parameters.application.name);

    return Promise.resolve()
      .then(() => application && this._ensureApplicationDown(application))
      .then(() => !application && this._state.applications.push(application = {}))
      .then(() => _.assign(application, parameters.application))
      .then(() => this._onStateChange())
      .then(() => this._broadcastStates())
      .then(() => session.setState({
        activeApplicationIndex: this._state.applications.indexOf(application)
      }))
      .then(error => this._broadcastMessage('success', 'Application saved.'))
      .catch(error => this._broadcastMessage('danger', error.message));
  }

  _doActionDeleteApplication(parameters) {
    var application = _.find(this._state.applications, a => a.name == parameters.applicationName);
    if (!application) return;
    return this._ensureApplicationDown(application)
      .then(() => _.pull(this._state.applications, application))
      .then(() => this._onStateChange())
      .then(() => this._broadcastStates())
      .then(error => this._broadcastMessage('success', 'Application deleted.'))
      .catch(error => this._broadcastMessage('danger', error.message));
  }

  _ensureApplicationUp(application) {
    return this._lockApplication(application, () => {
      var terminal = this._terminals[application.name];
      if (terminal) return;
      var env = _.defaults({}, application.env, {
        'PORT': application.port
      });
      var xs = ShellQuote.parse(application.command, env);
      terminal = this._terminals[application.name] = {
        pty: Pty.spawn(xs[0], xs.slice(1), {
          name: 'xterm-color',
          cols: _.min([80, ...this._sessions.map(s => s.terminalCols)]),
          rows: _.min([24, ...this._sessions.map(s => s.terminalRows)]),
          cwd: application.dir,
          env: env
        })
      };

      if (application.out) {
        var outPath = Path.join(application.dir, application.out);
        Utility.mkdirp(Path.dirname(outPath))
          .then(Utility.openFile(
            outPath,
            'a'
          ))
          .then(file => terminal.outFd = file)
          .catch(error => console.error(error.stack));
      }

      terminal.pty.on('data', data => {
        if (terminal.outFd) Fs.writeSync(terminal.outFd, Buffer(StripAnsi(data)));
        for (var session of this._sessions) {
          session.socket.send(JSON.stringify({
            terminalOutput: {
              applicationName: application.name,
              dataString: data
            }
          }));
        }
      });

      terminal.pty.on('exit', code => {
        if (terminal.outFd) Fs.closeSync(terminal.outFd);
        delete this._terminals[application.name];
        this._broadcastStates();
      });

      this._broadcastStates();

      var startTime = Date.now();
      return Utility.whilePromise(() => {
          var terminal = this._terminals[application.name];
          if (!terminal) return;
          if (Date.now() - startTime > 5000) return;

          return Utility.checkPortListening(application.port)
            .then(listening => !listening);
        })
        .then(() => Utility.delay(500));
    });
  }

  _ensureApplicationDown(application) {
    return this._lockApplication(application, () => {
      var applicationDown = false;
      var terminal = this._terminals[application.name];
      if (terminal) {
        terminal.pty.kill();
        Utility.delay(10000)
          .then(() => {
            if (applicationDown) return;
            terminal.pty.kill('KILL');
          })
          .catch(error => console.error(error.stack));
      }
      return Utility.whilePromise(() => this._terminals[application.name])
        .then(() => applicationDown = true);
    });
  }

  ensureDown() {
    return Promise.all(this._state.applications.map(application =>
      this._ensureApplicationDown(application)
    ));
  }

  _broadcastStates() {
    for (var session of this._sessions) {
      session.socket.send(JSON.stringify({
        state: {
          env: this._env,
          applications: this._state.applications.map(application =>
            _.merge({}, application, {
              locked: !!this._applicationLocks[application.name],
              running: !!this._terminals[application.name]
            })
          )
        }
      }));
    }
  }

  _broadcastMessage(type, message) {
    for (var session of this._sessions) {
      session.socket.send(JSON.stringify({
        message: {
          type,
          message
        }
      }));
    }
  }

  handleWebsocket(socket) {
    var session = {
      socket,
      setState: (state) => {
        socket.send(JSON.stringify({
          state
        }));
      }
    };

    this._sessions.push(session);
    this._broadcastStates();

    session.setState({
      caCertificate: this._state.caCertificate
    });

    socket.on('message', (data) => {
      if (session.onMessage) return session.onMessage(data);
      var action = JSON.parse(data);
      var actionFuncion = this['_doAction' + action.name];
      if (!actionFuncion) return this._broadcastMessage('danger', action.name + ' doesn\'t exist.');
      Promise.resolve()
        .then(() => actionFuncion.call(this, action.parameters, session))
        .catch(error => this._broadcastMessage('danger', error.message));
    });

    socket.on('close', () => {
      _.pull(this._sessions, session);
      this._broadcastStates();
    });

  }
}

module.exports = Motel;
<commit_msg>Use SIGINT instead of SIGTERM, fix SIGKILL<commit_after>var _ = require('lodash');
var Pty = require('node-pty');
var Fs = require('fs');
var Path = require('path');
var Utility = require('./utility.js');
var ShellQuote = require('shell-quote');
var StripAnsi = require('strip-ansi');

class Motel {
  constructor({
    state,
    env,
    onStateChange
  }) {
    this._env = env;
    this._state = state;
    this._sessions = [];
    this._onStateChange = onStateChange;
    this._applicationLocks = {};
    this._terminals = {};

    if (!this._state.applications) {
      this._state.applications = [];
      this._onStateChange();
      this._broadcastStates();
    }
  }

  _lockApplication(application, callback) {
    var callbackError;
    return Promise.resolve()
      .then(() => Utility.whilePromise(() => this._applicationLocks[application.name]))
      .then(() => this._applicationLocks[application.name] = true)
      .then(() => this._broadcastStates())
      .then(() => Promise.resolve()
        .then(() => callback())
        .catch(error => callbackError = error)
      )
      .then(() => this._applicationLocks[application.name] = false)
      .then(() => this._broadcastStates())
      .then(() => callbackError && Promise.reject(callbackError));
  }

  getApplicationPort(hostname) {
    var application = _.find(this._state.applications, a =>
      hostname == `${a.name}.dev` ||
      _.endsWith(hostname, `.${a.name}.dev`)
    );
    return Promise.resolve()
      .then(() =>
        application && this._ensureApplicationUp(application)
        .then(() => application.port)
      );
  }

  _doActionResizeTerminal(parameters, session) {
    session.terminalCols = parameters.cols;
    session.terminalRows = parameters.rows;

    var terminal = this._terminals[parameters.applicationName];

    if (!terminal) return;
    terminal.pty.resize(
      _.min(this._sessions.map(s => s.terminalCols)),
      _.min(this._sessions.map(s => s.terminalRows))
    );
  }

  _doActionInputTerminal(parameters) {
    var terminal = this._terminals[parameters.applicationName];

    if (!terminal) return;
    terminal.pty.write(parameters.dataString);
  }

  _doActionStartApplication(parameters) {
    var application = _.find(this._state.applications, a => a.name == parameters.applicationName);
    if (!application) return;

    return Promise.resolve()
      .then(() => this._ensureApplicationUp(application))
      .catch(error => this._broadcastMessage('danger', error.message));
  }

  _doActionStopApplication(parameters) {
    var application = _.find(this._state.applications, a => a.name == parameters.applicationName);
    if (!application) return;

    return Promise.resolve()
      .then(() => this._ensureApplicationDown(application))
      .then(error => this._broadcastMessage('success', 'Application stopped.'))
      .catch(error => this._broadcastMessage('danger', error.message));
  }

  _doActionRestartApplication(parameters) {
    var application = _.find(this._state.applications, a => a.name == parameters.applicationName);
    if (!application) return;

    return Promise.resolve()
      .then(() => this._ensureApplicationDown(application))
      .then(() => this._ensureApplicationUp(application))
      .then(error => this._broadcastMessage('success', 'Application restarted.'))
      .catch(error => this._broadcastMessage('danger', error.message));
  }

  _doActionCreateApplication(parameters, session) {
    var application = _.find(this._state.applications, a => a.name == parameters.application.name);

    return Promise.resolve()
      .then(() => application && this._ensureApplicationDown(application))
      .then(() => !application && this._state.applications.push(application = {}))
      .then(() => _.assign(application, parameters.application))
      .then(() => this._onStateChange())
      .then(() => this._broadcastStates())
      .then(() => session.setState({
        activeApplicationIndex: this._state.applications.indexOf(application)
      }))
      .then(error => this._broadcastMessage('success', 'Application saved.'))
      .catch(error => this._broadcastMessage('danger', error.message));
  }

  _doActionDeleteApplication(parameters) {
    var application = _.find(this._state.applications, a => a.name == parameters.applicationName);
    if (!application) return;
    return this._ensureApplicationDown(application)
      .then(() => _.pull(this._state.applications, application))
      .then(() => this._onStateChange())
      .then(() => this._broadcastStates())
      .then(error => this._broadcastMessage('success', 'Application deleted.'))
      .catch(error => this._broadcastMessage('danger', error.message));
  }

  _ensureApplicationUp(application) {
    return this._lockApplication(application, () => {
      var terminal = this._terminals[application.name];
      if (terminal) return;
      var env = _.defaults({}, application.env, {
        'PORT': application.port
      });
      var xs = ShellQuote.parse(application.command, env);
      terminal = this._terminals[application.name] = {
        pty: Pty.spawn(xs[0], xs.slice(1), {
          name: 'xterm-color',
          cols: _.min([80, ...this._sessions.map(s => s.terminalCols)]),
          rows: _.min([24, ...this._sessions.map(s => s.terminalRows)]),
          cwd: application.dir,
          env: env
        })
      };

      if (application.out) {
        var outPath = Path.join(application.dir, application.out);
        Utility.mkdirp(Path.dirname(outPath))
          .then(Utility.openFile(
            outPath,
            'a'
          ))
          .then(file => terminal.outFd = file)
          .catch(error => console.error(error.stack));
      }

      terminal.pty.on('data', data => {
        if (terminal.outFd) Fs.writeSync(terminal.outFd, Buffer(StripAnsi(data)));
        for (var session of this._sessions) {
          session.socket.send(JSON.stringify({
            terminalOutput: {
              applicationName: application.name,
              dataString: data
            }
          }));
        }
      });

      terminal.pty.on('exit', code => {
        if (terminal.outFd) Fs.closeSync(terminal.outFd);
        delete this._terminals[application.name];
        this._broadcastStates();
      });

      this._broadcastStates();

      var startTime = Date.now();
      return Utility.whilePromise(() => {
          var terminal = this._terminals[application.name];
          if (!terminal) return;
          if (Date.now() - startTime > 5000) return;

          return Utility.checkPortListening(application.port)
            .then(listening => !listening);
        })
        .then(() => Utility.delay(500));
    });
  }

  _ensureApplicationDown(application) {
    return this._lockApplication(application, () => {
      var applicationDown = false;
      var terminal = this._terminals[application.name];
      if (terminal) {
        terminal.pty.kill('SIGINT');
        Utility.delay(10000)
          .then(() => {
            if (applicationDown) return;
            terminal.pty.kill('SIGKILL');
          })
          .catch(error => console.error(error.stack));
      }
      return Utility.whilePromise(() => this._terminals[application.name])
        .then(() => applicationDown = true);
    });
  }

  ensureDown() {
    return Promise.all(this._state.applications.map(application =>
      this._ensureApplicationDown(application)
    ));
  }

  _broadcastStates() {
    for (var session of this._sessions) {
      session.socket.send(JSON.stringify({
        state: {
          env: this._env,
          applications: this._state.applications.map(application =>
            _.merge({}, application, {
              locked: !!this._applicationLocks[application.name],
              running: !!this._terminals[application.name]
            })
          )
        }
      }));
    }
  }

  _broadcastMessage(type, message) {
    for (var session of this._sessions) {
      session.socket.send(JSON.stringify({
        message: {
          type,
          message
        }
      }));
    }
  }

  handleWebsocket(socket) {
    var session = {
      socket,
      setState: (state) => {
        socket.send(JSON.stringify({
          state
        }));
      }
    };

    this._sessions.push(session);
    this._broadcastStates();

    session.setState({
      caCertificate: this._state.caCertificate
    });

    socket.on('message', (data) => {
      if (session.onMessage) return session.onMessage(data);
      var action = JSON.parse(data);
      var actionFuncion = this['_doAction' + action.name];
      if (!actionFuncion) return this._broadcastMessage('danger', action.name + ' doesn\'t exist.');
      Promise.resolve()
        .then(() => actionFuncion.call(this, action.parameters, session))
        .catch(error => this._broadcastMessage('danger', error.message));
    });

    socket.on('close', () => {
      _.pull(this._sessions, session);
      this._broadcastStates();
    });

  }
}

module.exports = Motel;
<|endoftext|>